diff --git a/src/isp.rs b/src/isp.rs index e95865f..6131cb0 100644 --- a/src/isp.rs +++ b/src/isp.rs @@ -7,7 +7,7 @@ use crate::{part::*, util, VerificationError}; extern crate hidapi; -use hidapi::{HidApi, HidDevice, HidError}; +use hidapi::{DeviceInfo, HidApi, HidDevice, HidError}; const MAX_RETRIES: usize = 10; @@ -67,6 +67,18 @@ struct HIDDevices { data: HidDevice, } +pub trait HidApiExtension { + fn sorted_device_list(&self) -> Vec<&DeviceInfo>; +} + +impl HidApiExtension for HidApi { + fn sorted_device_list(self: &HidApi) -> Vec<&DeviceInfo> { + let mut devices: Vec<_> = self.device_list().collect(); + devices.sort_by_key(|d| d.path()); + devices + } +} + impl ISPDevice { pub fn new(part: Part) -> Result { let devices = Self::find_isp_device(part)?; @@ -78,42 +90,6 @@ impl ISPDevice { }) } - /// Prints out all connected HID devices and their paths. - pub fn print_connected_devices() -> Result<(), ISPError> { - let api = ISPDevice::hidapi(); - - info!("Listing all connected HID devices..."); - let mut devices: Vec<_> = api.device_list().collect(); - - devices.sort_by_key(|d| d.path()); - - for d in &devices { - #[cfg(not(target_os = "linux"))] - info!( - "{:}: ID {:04x}:{:04x} manufacturer=\"{:}\" product=\"{:}\" usage_page={:#06x} usage={:#06x}", - d.path().to_str().unwrap(), - d.vendor_id(), - d.product_id(), - d.manufacturer_string().unwrap_or("None"), - d.product_string().unwrap_or("None"), - d.usage_page(), - d.usage() - ); - #[cfg(target_os = "linux")] - info!( - "{:}: ID {:04x}:{:04x} manufacturer=\"{:}\" product=\"{:}\"", - d.path().to_str().unwrap(), - d.vendor_id(), - d.product_id(), - d.manufacturer_string().unwrap_or("None"), - d.product_string().unwrap_or("None") - ); - } - info!("Found {} devices", devices.len()); - - Ok(()) - } - fn hidapi() -> HidApi { let api = HidApi::new().unwrap(); @@ -125,9 +101,9 @@ impl ISPDevice { fn open_isp_devices() -> Result { let api = Self::hidapi(); - - let mut devices: Vec<_> = api - .device_list() + let sorted_devices: Vec<_> = api.sorted_device_list(); + let isp_devices: Vec<_> = sorted_devices + .into_iter() .filter(|d| { #[cfg(not(target_os = "linux"))] return d.vendor_id() == GAMING_KB_VENDOR_ID @@ -148,9 +124,7 @@ impl ISPDevice { }) .collect(); - devices.sort_by_key(|d| d.path()); - - for d in &devices { + for d in &isp_devices { #[cfg(not(target_os = "linux"))] debug!( "Found ISP Device: {:#06x} {:#06x} {:?} {:#06x} {:#06x}", @@ -169,14 +143,14 @@ impl ISPDevice { ); } - let device_count = devices.len(); + let device_count = isp_devices.len(); if device_count == 0 { return Err(ISPError::NotFound); } #[cfg(not(target_os = "windows"))] if device_count == 1 { - let request_device = devices.first().unwrap(); + let request_device = isp_devices.first().unwrap(); debug!("Request device: {:?}", request_device.path()); return Ok(HIDDevices { request: api.open_path(request_device.path()).unwrap(), @@ -189,8 +163,8 @@ impl ISPDevice { if device_count == 1 { return Err(ISPError::IrregularDeviceCount(device_count)); } else if device_count == 2 { - let request_device = devices[0]; - let data_device = devices[1]; + let request_device = isp_devices[0]; + let data_device = isp_devices[1]; debug!("Request device: {:?}", request_device.path()); debug!("Data device: {:?}", data_device.path()); return Ok(HIDDevices { @@ -210,8 +184,9 @@ impl ISPDevice { part.vendor_id, part.product_id ); - let request_device_info = api - .device_list() + let sorted_devices: Vec<_> = api.sorted_device_list(); + let request_device_info = sorted_devices + .into_iter() .filter(|d| { #[cfg(not(target_os = "linux"))] return d.vendor_id() == part.vendor_id @@ -301,6 +276,39 @@ impl ISPDevice { Ok(()) } + /// Prints out all connected HID devices and their paths. + pub fn print_connected_devices() -> Result<(), ISPError> { + info!("Listing all connected HID devices..."); + let api = Self::hidapi(); + let devices: Vec<_> = api.sorted_device_list(); + + for d in &devices { + #[cfg(not(target_os = "linux"))] + info!( + "{:}: ID {:04x}:{:04x} manufacturer=\"{:}\" product=\"{:}\" usage_page={:#06x} usage={:#06x}", + d.path().to_str().unwrap(), + d.vendor_id(), + d.product_id(), + d.manufacturer_string().unwrap_or("None"), + d.product_string().unwrap_or("None"), + d.usage_page(), + d.usage() + ); + #[cfg(target_os = "linux")] + info!( + "{:}: ID {:04x}:{:04x} manufacturer=\"{:}\" product=\"{:}\"", + d.path().to_str().unwrap(), + d.vendor_id(), + d.product_id(), + d.manufacturer_string().unwrap_or("None"), + d.product_string().unwrap_or("None") + ); + } + info!("Found {} devices", devices.len()); + + Ok(()) + } + pub fn read_cycle(&self, read_type: ReadType) -> Result, ISPError> { self.enable_firmware()?;