1
2
3pub use hidapi::{HidApi, HidDevice};
4
5use structopt::StructOpt;
6
7#[derive(Clone, PartialEq, Debug, StructOpt)]
8#[structopt(name = "hidpal", about = "USB HID device helper")]
9pub struct Filter {
10 #[structopt(long, default_value="1209", parse(try_from_str=u16_parse_hex), env="USB_VID")]
11 pub vid: u16,
13
14 #[structopt(long, default_value="fff0", parse(try_from_str=u16_parse_hex), env="USB_PID")]
15 pub pid: u16,
17
18 #[structopt(long, env = "USB_SERIAL")]
19 pub serial: Option<String>,
21}
22
23
24pub fn u16_parse_hex(s: &str) -> Result<u16, std::num::ParseIntError> {
25 u16::from_str_radix(s, 16)
26}
27
28pub fn u8_parse_hex(s: &str) -> Result<u8, std::num::ParseIntError> {
29 u8::from_str_radix(s, 16)
30}
31
32#[derive(Clone, PartialEq, Debug)]
33pub struct Info {
34 manufacturer: Option<String>,
35 product: Option<String>,
36 serial: Option<String>,
37}
38
39pub trait Device {
40 fn connect(vid: u16, pid: u16, serial: Option<&str>) -> Result<Self, anyhow::Error> where Self: Sized;
41 fn info(&mut self) -> Result<Info, anyhow::Error>;
42}
43
44impl Device for HidDevice {
45 fn connect(vid: u16, pid: u16, serial: Option<&str>) -> Result<Self, anyhow::Error> {
47 let api = HidApi::new()?;
49
50 let hid_device = match &serial {
52 Some(s) => api.open_serial(vid, pid, s),
53 None => api.open(vid, pid),
54 }?;
55
56 Ok(hid_device)
57 }
58
59 fn info(&mut self) -> Result<Info, anyhow::Error> {
61 let manufacturer = self.get_manufacturer_string()?;
62 let product = self.get_product_string()?;
63 let serial = self.get_serial_number_string()?;
64
65 Ok(Info{ manufacturer, product, serial })
66 }
67}