use std::error::Error; use crate::usb::{ControlIn, ControlOut, ControlType, Device, Interface, Recipient}; pub struct UsbDevice { device_info: nusb::DeviceInfo, device: nusb::Device, } pub struct UsbInterface { interface: nusb::Interface, } pub async fn get_device(vendor_id: u16, product_id: u16) -> Result> { let devices = nusb::list_devices().unwrap(); let mut device_info = None; for device in devices { if device.vendor_id() == vendor_id && device.product_id() == product_id { device_info = Some(device); break; } } let device_info = match device_info { Some(dev) => dev, None => return Err("Device not found".into()), }; let device = device_info.open()?; Ok(UsbDevice { device_info, device, }) } #[derive(PartialEq, Eq, Clone)] pub struct FilterTuple(pub u16, pub u16); pub async fn get_device_filter( device_filter: Vec, ) -> Result> { let devices = nusb::list_devices().unwrap(); let mut device_info = None; for device in devices { match device_filter .iter() .position(|i| i == &FilterTuple(device.vendor_id(), device.product_id())) { Some(_) => { device_info = Some(device); break; } None => device_info = None, } } if device_info.is_none() { return Err("No devices from the list found".into()); } let device_info = match device_info { Some(dev) => dev, None => return Err("Device not found".into()), }; let device = device_info.open()?; Ok(UsbDevice { device_info, device, }) } impl Device for UsbDevice { type UsbDevice = UsbDevice; type UsbInterface = UsbInterface; async fn open_interface(&self, number: u8) -> Result> { let interface = match self.device.claim_interface(number) { Ok(inter) => inter, Err(e) => return Err(e.into()), }; Ok(UsbInterface { interface }) } async fn reset(&self) -> Result<(), Box> { match self.device.reset() { Ok(_) => Ok(()), Err(e) => Err(e.into()), } } async fn vendor_id(&self) -> u16 { self.device_info.vendor_id() } async fn product_id(&self) -> u16 { self.device_info.product_id() } async fn class(&self) -> u8 { self.device_info.class() } async fn subclass(&self) -> u8 { self.device_info.subclass() } async fn manufacturer_string(&self) -> Option { self.device_info.manufacturer_string().map(str::to_string) } async fn product_string(&self) -> Option { self.device_info.product_string().map(str::to_string) } } impl<'a> Interface<'a> for UsbInterface { async fn control_in(&self, data: ControlIn) -> Result, Box> { Ok(self.interface.control_in(data.into()).await.into_result()?) } async fn control_out(&self, data: ControlOut<'a>) -> Result<(), Box> { match self.interface.control_out(data.into()).await.into_result() { Ok(_) => Ok(()), Err(e) => Err(e.into()), } } async fn bulk_in(&self, endpoint: u8, length: usize) -> Result, Box> { let request_buffer = nusb::transfer::RequestBuffer::new(length); Ok(self .interface .bulk_in(endpoint, request_buffer) .await .into_result()?) } async fn bulk_out(&self, endpoint: u8, data: &[u8]) -> Result> { match self .interface .bulk_out(endpoint, data.to_vec()) .await .into_result() { Ok(len) => Ok(len.actual_length()), Err(e) => Err(e.into()), } } } impl From for nusb::transfer::ControlIn { fn from(val: ControlIn) -> Self { nusb::transfer::ControlIn { control_type: val.control_type.into(), recipient: val.recipient.into(), request: val.request, value: val.value, index: val.index, length: val.length, } } } impl<'a> From> for nusb::transfer::ControlOut<'a> { fn from(val: ControlOut<'a>) -> Self { nusb::transfer::ControlOut { control_type: val.control_type.into(), recipient: val.recipient.into(), request: val.request, value: val.value, index: val.index, data: val.data, } } } impl From for nusb::transfer::ControlType { fn from(val: ControlType) -> Self { match val { ControlType::Standard => nusb::transfer::ControlType::Standard, ControlType::Class => nusb::transfer::ControlType::Class, ControlType::Vendor => nusb::transfer::ControlType::Vendor, } } } impl From for nusb::transfer::Recipient { fn from(val: Recipient) -> Self { match val { Recipient::Device => nusb::transfer::Recipient::Device, Recipient::Interface => nusb::transfer::Recipient::Interface, Recipient::Endpoint => nusb::transfer::Recipient::Endpoint, Recipient::Other => nusb::transfer::Recipient::Other, } } }