pub use hidapi::{HidApi, HidDevice};
use structopt::StructOpt;
#[derive(Clone, PartialEq, Debug, StructOpt)]
#[structopt(name = "hidpal", about = "USB HID device helper")]
pub struct Filter {
#[structopt(long, default_value="1209", parse(try_from_str=u16_parse_hex), env="USB_VID")]
pub vid: u16,
#[structopt(long, default_value="fff0", parse(try_from_str=u16_parse_hex), env="USB_PID")]
pub pid: u16,
#[structopt(long, env = "USB_SERIAL")]
pub serial: Option<String>,
}
pub fn u16_parse_hex(s: &str) -> Result<u16, std::num::ParseIntError> {
u16::from_str_radix(s, 16)
}
pub fn u8_parse_hex(s: &str) -> Result<u8, std::num::ParseIntError> {
u8::from_str_radix(s, 16)
}
#[derive(Clone, PartialEq, Debug)]
pub struct Info {
manufacturer: Option<String>,
product: Option<String>,
serial: Option<String>,
}
pub trait Device {
fn connect(vid: u16, pid: u16, serial: Option<&str>) -> Result<Self, anyhow::Error> where Self: Sized;
fn info(&mut self) -> Result<Info, anyhow::Error>;
}
impl Device for HidDevice {
fn connect(vid: u16, pid: u16, serial: Option<&str>) -> Result<Self, anyhow::Error> {
let api = HidApi::new()?;
let hid_device = match &serial {
Some(s) => api.open_serial(vid, pid, s),
None => api.open(vid, pid),
}?;
Ok(hid_device)
}
fn info(&mut self) -> Result<Info, anyhow::Error> {
let manufacturer = self.get_manufacturer_string()?;
let product = self.get_product_string()?;
let serial = self.get_serial_number_string()?;
Ok(Info{ manufacturer, product, serial })
}
}