+1
-1
@@ -45,3 +45,3 @@ // ************************************************************************** | ||
| let avail_backends: [(&'static str, Box<Fn()>); 4] = [ | ||
| let avail_backends: [(&'static str, Box<dyn Fn()>); 4] = [ | ||
| ( | ||
@@ -48,0 +48,0 @@ "LINUX_STATIC_HIDRAW", |
+10
-10
@@ -5,3 +5,3 @@ # This file is automatically @generated by Cargo. | ||
| name = "cc" | ||
| version = "1.0.36" | ||
| version = "1.0.50" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
@@ -11,7 +11,7 @@ | ||
| name = "hidapi" | ||
| version = "1.1.1" | ||
| version = "1.2.0" | ||
| dependencies = [ | ||
| "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||
| ] | ||
@@ -21,3 +21,3 @@ | ||
| name = "libc" | ||
| version = "0.2.54" | ||
| version = "0.2.67" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
@@ -27,8 +27,8 @@ | ||
| name = "pkg-config" | ||
| version = "0.3.14" | ||
| version = "0.3.17" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| [metadata] | ||
| "checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" | ||
| "checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" | ||
| "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" | ||
| "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" | ||
| "checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" | ||
| "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" |
+1
-1
@@ -15,3 +15,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "hidapi" | ||
| version = "1.1.1" | ||
| version = "1.2.0" | ||
| authors = ["Roland Ruckerbauer <roland.rucky@gmail.com>", "Osspial <osspial@gmail.com>", "Artyom Pavlov <newpavlov@gmail.com>", "mberndt123", "niklasad1"] | ||
@@ -18,0 +18,0 @@ build = "build.rs" |
+14
-2
@@ -18,4 +18,16 @@ /**************************************************************************** | ||
| Ok(api) => { | ||
| for device in api.devices() { | ||
| println!("{:#?}", device); | ||
| for device in api.device_list() { | ||
| println!( | ||
| "VID: {:04x}, PID: {:04x}, Serial: {}, Product name: {}", | ||
| device.vendor_id(), | ||
| device.product_id(), | ||
| match device.serial_number() { | ||
| Some(s) => s, | ||
| _ => "<COULD NOT FETCH>", | ||
| }, | ||
| match device.product_string() { | ||
| Some(s) => s, | ||
| _ => "<COULD NOT FETCH>", | ||
| } | ||
| ); | ||
| } | ||
@@ -22,0 +34,0 @@ } |
@@ -19,4 +19,3 @@ /**************************************************************************** | ||
| let device_info = hidapi | ||
| .devices() | ||
| .iter() | ||
| .device_list() | ||
| .next() | ||
@@ -26,3 +25,3 @@ .expect("No devices are available!") | ||
| println!("Opening device:\n {:#?}\n", device_info); | ||
| println!("Opening device:\n VID: {:04x}, PID: {:04x}\n", device_info.vendor_id(), device_info.product_id()); | ||
@@ -29,0 +28,0 @@ let device = device_info.open_device(&hidapi)?; |
@@ -26,12 +26,10 @@ /**************************************************************************** | ||
| let devices = api.devices(); | ||
| let mut devices = api.device_list(); | ||
| let dev_info = devices | ||
| .get(0) | ||
| .nth(0) | ||
| .expect("There is not a single hid device available"); | ||
| println!("{:#?}", dev_info); | ||
| let dev = Rc::new( | ||
| api.open(dev_info.vendor_id, dev_info.product_id) | ||
| api.open(dev_info.vendor_id(), dev_info.product_id()) | ||
| .expect("Can not open device"), | ||
@@ -38,0 +36,0 @@ ); |
+210
-29
@@ -38,2 +38,5 @@ // ************************************************************************** | ||
| // Allow use of deprecated items, we defined ourselfes... | ||
| #![allow(deprecated)] | ||
| extern crate libc; | ||
@@ -94,3 +97,4 @@ | ||
| pub struct HidApi { | ||
| devices: Vec<HidDeviceInfo>, | ||
| devices: Vec<HidDeviceInfo>, /* Deprecated */ | ||
| device_list: Vec<DeviceInfo>, | ||
| _lock: Arc<HidApiLock>, | ||
@@ -108,4 +112,7 @@ } | ||
| let device_list = unsafe { HidApi::get_hid_device_info_vector()? }; | ||
| Ok(HidApi { | ||
| devices: unsafe { HidApi::get_hid_device_info_vector()? }, | ||
| device_list: device_list.clone(), | ||
| devices: device_list.into_iter().map(|d| d.into()).collect(), | ||
| _lock: Arc::new(lock), | ||
@@ -116,9 +123,11 @@ }) | ||
| /// Refresh devices list and information about them (to access them use | ||
| /// `devices()` method) | ||
| /// `device_list()` method) | ||
| pub fn refresh_devices(&mut self) -> HidResult<()> { | ||
| self.devices = unsafe { HidApi::get_hid_device_info_vector()? }; | ||
| let device_list = unsafe { HidApi::get_hid_device_info_vector()? }; | ||
| self.device_list = device_list.clone(); | ||
| self.devices = device_list.into_iter().map(|d| d.into()).collect(); | ||
| Ok(()) | ||
| } | ||
| unsafe fn get_hid_device_info_vector() -> HidResult<Vec<HidDeviceInfo>> { | ||
| unsafe fn get_hid_device_info_vector() -> HidResult<Vec<DeviceInfo>> { | ||
| let mut device_vector = Vec::with_capacity(8); | ||
@@ -143,3 +152,6 @@ | ||
| /// Returns list of objects containing information about connected devices | ||
| /// Returns vec of objects containing information about connected devices | ||
| /// | ||
| /// Deprecated. Use `HidApi::device_list()` instead. | ||
| #[deprecated] | ||
| pub fn devices(&self) -> &Vec<HidDeviceInfo> { | ||
@@ -149,2 +161,7 @@ &self.devices | ||
| /// Returns iterator containing information about attached HID devices. | ||
| pub fn device_list(&self) -> impl Iterator<Item = &DeviceInfo> { | ||
| self.device_list.iter() | ||
| } | ||
| /// Open a HID device using a Vendor ID (VID) and Product ID (PID). | ||
@@ -201,10 +218,12 @@ /// | ||
| /// Converts a pointer to a `wchar_t` to a optional string | ||
| unsafe fn wchar_to_string(wstr: *const wchar_t) -> HidResult<Option<String>> { | ||
| /// Converts a pointer to a `*const wchar_t` to a WcharString. | ||
| unsafe fn wchar_to_string(wstr: *const wchar_t) -> WcharString { | ||
| if wstr.is_null() { | ||
| return Ok(None); | ||
| return WcharString::None; | ||
| } | ||
| let mut char_vector: Vec<char> = Vec::with_capacity(8); | ||
| let mut raw_vector: Vec<wchar_t> = Vec::with_capacity(8); | ||
| let mut index: isize = 0; | ||
| let mut invalid_char = false; | ||
@@ -215,25 +234,33 @@ let o = |i| *wstr.offset(i); | ||
| use std::char; | ||
| char_vector.push(match char::from_u32(o(index) as u32) { | ||
| Some(ch) => ch, | ||
| None => Err(HidError::FromWideCharError { | ||
| wide_char: o(index), | ||
| })?, | ||
| }); | ||
| raw_vector.push(*wstr.offset(index)); | ||
| if !invalid_char { | ||
| if let Some(c) = char::from_u32(o(index) as u32) { | ||
| char_vector.push(c); | ||
| } else { | ||
| invalid_char = true; | ||
| } | ||
| } | ||
| index += 1; | ||
| } | ||
| Ok(Some(char_vector.into_iter().collect())) | ||
| if !invalid_char { | ||
| WcharString::String(char_vector.into_iter().collect()) | ||
| } else { | ||
| WcharString::Raw(raw_vector) | ||
| } | ||
| } | ||
| /// Convert the CFFI `HidDeviceInfo` struct to a native `HidDeviceInfo` struct | ||
| unsafe fn conv_hid_device_info(src: *mut ffi::HidDeviceInfo) -> HidResult<HidDeviceInfo> { | ||
| Ok(HidDeviceInfo { | ||
| unsafe fn conv_hid_device_info(src: *mut ffi::HidDeviceInfo) -> HidResult<DeviceInfo> { | ||
| Ok(DeviceInfo { | ||
| path: CStr::from_ptr((*src).path).to_owned(), | ||
| vendor_id: (*src).vendor_id, | ||
| product_id: (*src).product_id, | ||
| serial_number: wchar_to_string((*src).serial_number)?, | ||
| serial_number: wchar_to_string((*src).serial_number), | ||
| release_number: (*src).release_number, | ||
| manufacturer_string: wchar_to_string((*src).manufacturer_string)?, | ||
| product_string: wchar_to_string((*src).product_string)?, | ||
| manufacturer_string: wchar_to_string((*src).manufacturer_string), | ||
| product_string: wchar_to_string((*src).product_string), | ||
| usage_page: (*src).usage_page, | ||
@@ -245,4 +272,23 @@ usage: (*src).usage, | ||
| #[derive(Clone)] | ||
| enum WcharString { | ||
| String(String), | ||
| Raw(Vec<wchar_t>), | ||
| None, | ||
| } | ||
| impl Into<Option<String>> for WcharString { | ||
| fn into(self) -> Option<String> { | ||
| match self { | ||
| WcharString::String(s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| } | ||
| /// Storage for device related information | ||
| /// | ||
| /// Deprecated. Use `HidApi::device_list()` instead. | ||
| #[derive(Debug, Clone)] | ||
| /// Storage for device related information | ||
| #[deprecated] | ||
| pub struct HidDeviceInfo { | ||
@@ -261,2 +307,136 @@ pub path: CString, | ||
| /// Device information. Use accessors to extract information about Hid devices. | ||
| /// | ||
| /// Note: Methods like `serial_number()` may return None, if the conversion to a | ||
| /// String failed internally. You can however access the raw hid representation of the | ||
| /// string by calling `serial_number_raw()` | ||
| #[derive(Clone)] | ||
| pub struct DeviceInfo { | ||
| path: CString, | ||
| vendor_id: u16, | ||
| product_id: u16, | ||
| serial_number: WcharString, | ||
| release_number: u16, | ||
| manufacturer_string: WcharString, | ||
| product_string: WcharString, | ||
| usage_page: u16, | ||
| usage: u16, | ||
| interface_number: i32, | ||
| } | ||
| impl DeviceInfo { | ||
| pub fn path(&self) -> &CStr { | ||
| &self.path | ||
| } | ||
| pub fn vendor_id(&self) -> u16 { | ||
| self.vendor_id | ||
| } | ||
| pub fn product_id(&self) -> u16 { | ||
| self.product_id | ||
| } | ||
| /// Try to call `serial_number_raw()`, if None is returned. | ||
| pub fn serial_number(&self) -> Option<&str> { | ||
| match self.serial_number { | ||
| WcharString::String(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| pub fn serial_number_raw(&self) -> Option<&[wchar_t]> { | ||
| match self.serial_number { | ||
| WcharString::Raw(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| pub fn release_number(&self) -> u16 { | ||
| self.release_number | ||
| } | ||
| /// Try to call `manufacturer_string_raw()`, if None is returned. | ||
| pub fn manufacturer_string(&self) -> Option<&str> { | ||
| match self.manufacturer_string { | ||
| WcharString::String(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| pub fn manufacturer_string_raw(&self) -> Option<&[wchar_t]> { | ||
| match self.manufacturer_string { | ||
| WcharString::Raw(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| /// Try to call `product_string_raw()`, if None is returned. | ||
| pub fn product_string(&self) -> Option<&str> { | ||
| match self.product_string { | ||
| WcharString::String(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| pub fn product_string_raw(&self) -> Option<&[wchar_t]> { | ||
| match self.product_string { | ||
| WcharString::Raw(ref s) => Some(s), | ||
| _ => None, | ||
| } | ||
| } | ||
| pub fn usage_page(&self) -> u16 { | ||
| self.usage_page | ||
| } | ||
| pub fn usage(&self) -> u16 { | ||
| self.usage | ||
| } | ||
| pub fn interface_number(&self) -> i32 { | ||
| self.interface_number | ||
| } | ||
| /// Use the information contained in `DeviceInfo` to open | ||
| /// and return a handle to a [HidDevice](struct.HidDevice.html). | ||
| /// | ||
| /// By default the device path is used to open the device. | ||
| /// When no path is available, then vid, pid and serial number are used. | ||
| /// If both path and serial number are not available, then this function will | ||
| /// fail with [HidError::OpenHidDeviceWithDeviceInfoError](enum.HidError.html#variant.OpenHidDeviceWithDeviceInfoError). | ||
| /// | ||
| /// Note, that opening a device could still be done using [HidApi::open()](struct.HidApi.html#method.open) directly. | ||
| pub fn open_device(&self, hidapi: &HidApi) -> HidResult<HidDevice> { | ||
| if self.path.as_bytes().len() != 0 { | ||
| hidapi.open_path(self.path.as_c_str()) | ||
| } else if let Some(ref sn) = self.serial_number() { | ||
| hidapi.open_serial(self.vendor_id, self.product_id, sn) | ||
| } else { | ||
| Err(HidError::OpenHidDeviceWithDeviceInfoError { | ||
| device_info: Box::new(self.clone().into()), | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| impl Into<HidDeviceInfo> for DeviceInfo { | ||
| fn into(self) -> HidDeviceInfo { | ||
| HidDeviceInfo { | ||
| path: self.path, | ||
| vendor_id: self.vendor_id, | ||
| product_id: self.product_id, | ||
| serial_number: match self.serial_number { | ||
| WcharString::String(s) => Some(s), | ||
| _ => None, | ||
| }, | ||
| release_number: self.release_number, | ||
| manufacturer_string: match self.manufacturer_string { | ||
| WcharString::String(s) => Some(s), | ||
| _ => None, | ||
| }, | ||
| product_string: match self.product_string { | ||
| WcharString::String(s) => Some(s), | ||
| _ => None, | ||
| }, | ||
| usage_page: self.usage_page, | ||
| usage: self.usage, | ||
| interface_number: self.interface_number, | ||
| } | ||
| } | ||
| } | ||
| impl HidDeviceInfo { | ||
@@ -327,5 +507,6 @@ /// Use the information contained in `HidDeviceInfo` to open | ||
| message: unsafe { | ||
| wchar_to_string(ffi::hid_error(self._hid_device)) | ||
| .map_err(|e| HidError::HidApiErrorEmptyWithCause { cause: Box::new(e) })? | ||
| .ok_or(HidError::HidApiErrorEmpty)? | ||
| match wchar_to_string(ffi::hid_error(self._hid_device)) { | ||
| WcharString::String(s) => s, | ||
| _ => return Err(HidError::HidApiErrorEmpty), | ||
| } | ||
| }, | ||
@@ -450,3 +631,3 @@ }) | ||
| let res = self.check_size(res)?; | ||
| unsafe { wchar_to_string(buf[..res].as_ptr()) } | ||
| unsafe { Ok(wchar_to_string(buf[..res].as_ptr()).into()) } | ||
| } | ||
@@ -465,3 +646,3 @@ | ||
| let res = self.check_size(res)?; | ||
| unsafe { wchar_to_string(buf[..res].as_ptr()) } | ||
| unsafe { Ok(wchar_to_string(buf[..res].as_ptr()).into()) } | ||
| } | ||
@@ -480,3 +661,3 @@ | ||
| let res = self.check_size(res)?; | ||
| unsafe { wchar_to_string(buf[..res].as_ptr()) } | ||
| unsafe { Ok(wchar_to_string(buf[..res].as_ptr()).into()) } | ||
| } | ||
@@ -496,4 +677,4 @@ | ||
| let res = self.check_size(res)?; | ||
| unsafe { wchar_to_string(buf[..res].as_ptr()) } | ||
| unsafe { Ok(wchar_to_string(buf[..res].as_ptr()).into()) } | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet