use std::time::Duration; use libc::c_int; use sys::*; use error::{self, Error}; /// A device handle. pub struct Handle { ptr: *mut hid_device, } impl Handle { #[doc(hidden)] pub unsafe fn new(ptr: *mut hid_device) -> Self { Handle { ptr: ptr, } } #[doc(hidden)] pub unsafe fn as_ptr(&self) -> *const hid_device { self.ptr as *const _ } #[doc(hidden)] pub unsafe fn as_mut_ptr(&mut self) -> *mut hid_device { self.ptr } } impl Handle { /// Set the handle in blocking or non-blocking mode. pub fn blocking(&mut self, value: bool) -> error::Result<&mut Self> { unsafe { match hid_set_nonblocking(self.as_mut_ptr(), if value { 1 } else { 0 }) { 0 => Ok(self), _ => Err(Error::General) } } } /// The data accessor. pub fn data(&mut self) -> Data { unsafe { Data::new(self) } } /// The feature accessor. pub fn feature(&mut self) -> Feature { unsafe { Feature::new(self) } } } /// The data accessor. pub struct Data<'a> { handle: &'a mut Handle, } impl<'a> Data<'a> { #[doc(hidden)] pub unsafe fn new(handle: &mut Handle) -> Data { Data { handle: handle } } /// Write data to the device. /// /// The first byte must be the report ID. pub fn write>(&mut self, data: T) -> error::Result { let data = data.as_ref(); unsafe { match hid_write(self.handle.as_mut_ptr(), data.as_ptr(), data.len()) { -1 => Err(Error::Write), length => Ok(length as usize) } } } /// Write data to the device with the given report ID. pub fn write_to>(&mut self, id: u8, data: T) -> error::Result { let data = data.as_ref(); let mut buffer = vec![0u8; data.len() + 1]; buffer[0] = id; (&mut buffer[1 ..]).copy_from_slice(data); self.write(&buffer) } /// Read data from the device. /// /// If the device supports reports the first byte will contain the report ID. /// /// Returns the amount of read bytes or `None` if there was a timeout. pub fn read>(&mut self, mut data: T, timeout: Duration) -> error::Result> { let data = data.as_mut(); let result = if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { unsafe { hid_read(self.handle.as_mut_ptr(), data.as_mut_ptr(), data.len()) } } else { unsafe { // Timeout is in milliseconds. hid_read_timeout(self.handle.as_mut_ptr(), data.as_mut_ptr(), data.len(), timeout.as_secs() as c_int * 1_000 + timeout.subsec_nanos() as c_int / 1_000_000) } }; match result { -1 => Err(Error::Read), 0 => Ok(None), v => Ok(Some(v as usize)) } } /// Read data from the device. /// /// Returns the report ID and the amount of read bytes or `None` if there was a timeout. pub fn read_from>(&mut self, mut data: T, timeout: Duration) -> error::Result> { let data = data.as_mut(); let mut buffer = Vec::with_capacity(data.len() + 1); if let Some(length) = self.read(&mut buffer, timeout)? { data[0..length - 1].copy_from_slice(&buffer[1..length]); Ok(Some((buffer[0], length - 1))) } else { Ok(None) } } } /// The feature accessor. pub struct Feature<'a> { handle: &'a mut Handle, } impl<'a> Feature<'a> { #[doc(hidden)] pub unsafe fn new(handle: &mut Handle) -> Feature { Feature { handle: handle } } /// Send a feature request. /// /// The first byte must be the report ID. pub fn send>(&mut self, data: T) -> error::Result { let data = data.as_ref(); unsafe { match hid_send_feature_report(self.handle.as_mut_ptr(), data.as_ptr(), data.len()) { -1 => Err(Error::Write), length => Ok(length as usize) } } } /// Send a feature request to the given report ID. pub fn send_to>(&mut self, id: u8, data: T) -> error::Result { let data = data.as_ref(); let mut buffer = Vec::with_capacity(data.len() + 1); buffer.push(id); buffer.extend(data); self.send(&buffer).map(|v| v - 1) } /// Get a feature request. /// /// The first byte must be the report ID. pub fn get>(&mut self, mut data: T) -> error::Result { let data = data.as_mut(); unsafe { match hid_get_feature_report(self.handle.as_mut_ptr(), data.as_mut_ptr(), data.len()) { -1 => Err(Error::Read), length => Ok(length as usize) } } } /// Get a feature request from the given report ID. pub fn get_from>(&mut self, id: u8, mut data: T) -> error::Result { let data = data.as_mut(); let mut buffer = vec![0u8; data.len() + 1]; buffer[0] = id; let length = self.get(&mut buffer)?; data[0..length - 1].copy_from_slice(&buffer[1..length]); Ok(length - 1) } } impl Drop for Handle { fn drop(&mut self) { unsafe { hid_close(self.as_mut_ptr()); } } }