diff options
Diffstat (limited to 'hid/src/device.rs')
-rw-r--r-- | hid/src/device.rs | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/hid/src/device.rs b/hid/src/device.rs new file mode 100644 index 0000000..dc718c7 --- /dev/null +++ b/hid/src/device.rs @@ -0,0 +1,122 @@ +use std::marker::PhantomData; +use std::path::Path; +use std::ffi::CStr; + +use sys::*; +use libc::{size_t, wchar_t, wcstombs}; +use handle::Handle; +use error::{self, Error}; + +/// The HID device. +pub struct Device<'a> { + ptr: *const hid_device_info, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Device<'a> { + #[doc(hidden)] + pub unsafe fn new<'b>(ptr: *const hid_device_info) -> Device<'b> { + Device { + ptr: ptr, + + _marker: PhantomData, + } + } + + /// The path representation. + pub fn path(&self) -> &Path { + unsafe { + Path::new(CStr::from_ptr((*self.ptr).path).to_str().unwrap()) + } + } + + /// The vendor ID. + pub fn vendor_id(&self) -> u16 { + unsafe { + (*self.ptr).vendor_id + } + } + + /// The product ID. + pub fn product_id(&self) -> u16 { + unsafe { + (*self.ptr).product_id + } + } + + /// The serial number. + pub fn serial_number(&self) -> Option<String> { + unsafe { + (*self.ptr).serial_number.as_ref().and_then(|p| to_string(p)) + } + } + + /// The manufacturer string. + pub fn manufacturer_string(&self) -> Option<String> { + unsafe { + (*self.ptr).manufacturer_string.as_ref().and_then(|p| to_string(p)) + } + } + + /// The product string. + pub fn product_string(&self) -> Option<String> { + unsafe { + (*self.ptr).product_string.as_ref().and_then(|p| to_string(p)) + } + } + + /// The release number. + pub fn release_number(&self) -> u16 { + unsafe { + (*self.ptr).release_number + } + } + + /// The usage page. + pub fn usage_page(&self) -> u16 { + unsafe { + (*self.ptr).usage_page + } + } + + /// The usage number. + pub fn usage(&self) -> u16 { + unsafe { + (*self.ptr).usage + } + } + + /// The interface number. + pub fn interface_number(&self) -> isize { + unsafe { + (*self.ptr).interface_number as isize + } + } + + /// Opens the device to use it. + pub fn open(&self) -> error::Result<Handle> { + unsafe { + let handle = hid_open((*self.ptr).vendor_id, (*self.ptr).product_id, (*self.ptr).serial_number); + + if handle.is_null() { + return Err(Error::NotFound); + } + + Ok(Handle::new(handle)) + } + } +} + +#[inline] +unsafe fn to_string(value: *const wchar_t) -> Option<String> { + // USB descriptors are limited to 255 bytes. + let mut buffer = [0u8; 256]; + let length = wcstombs(buffer.as_mut_ptr() as *mut _, value, buffer.len()); + + if length == size_t::max_value() { + return None; + } + + Some(String::from_utf8_lossy(&buffer[0.. length as usize]).into_owned()) +} |