use libusb::{Device as UsbDevice, DeviceList, DeviceDescriptor};
#[cfg(feature = "structopt")]
use std::num::ParseIntError;
#[cfg(feature = "structopt")]
use structopt::StructOpt;
use crate::{Error};
use crate::device::{VID, PID};
pub struct Manager {
context: libusb::Context,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct Filter {
#[cfg_attr(feature = "structopt", structopt(long, default_value="10c4", parse(try_from_str=parse_hex)))]
pub vid: u16,
#[cfg_attr(feature = "structopt", structopt(long, default_value="87a0", parse(try_from_str=parse_hex)))]
pub pid: u16,
}
#[cfg(feature = "structopt")]
fn parse_hex(src: &str) -> Result<u16, ParseIntError> {
u16::from_str_radix(src, 16)
}
impl Default for Filter {
fn default() -> Self {
Filter{vid: VID, pid: PID}
}
}
impl Manager {
pub fn new() -> Result<Manager, Error> {
let context = match libusb::Context::new() {
Ok(v) => v,
Err(e) => {
error!("Initialising libusb context: {}", e);
return Err(Error::Usb(e))
}
};
Ok(Manager{context})
}
pub fn devices<'b>(&'b mut self) -> Result<DeviceList<'b>, Error> {
let devices = match self.context.devices() {
Ok(v) => v,
Err(e) => {
error!("Fetching devices: {}", e);
return Err(Error::Usb(e))
}
};
Ok(devices)
}
pub fn devices_filtered<'b>(&'b mut self, filter: Filter) -> Result<Vec<(UsbDevice, DeviceDescriptor)>, Error> {
let devices = self.devices()?;
let mut matches = vec![];
for device in devices.iter() {
let device_desc = match device.device_descriptor() {
Ok(d) => d,
Err(_) => continue
};
trace!("Device: {:?}", device_desc);
if device_desc.vendor_id() == filter.vid && device_desc.product_id() == filter.pid {
matches.push((device, device_desc));
}
}
debug!("Found {} matching devices", matches.len());
Ok(matches)
}
}