From 434e61c231e142b6f5f8d81eb25f4ef97686d85a Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Sat, 27 Mar 2021 16:10:53 +0100 Subject: Initial commit --- src/lib.rs | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/lib.rs (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a26f02f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,101 @@ +mod crc32; +mod hid; + +pub mod devices; +pub mod features; + +use std::fmt; + +pub type Error = Box; + +const VID_NITROKEY: u16 = 0x20a0; +const PID_NITROKEY_PRO: u16 = 0x4108; +const PID_NITROKEY_STORAGE: u16 = 0x4109; + +pub fn connect() -> Result { + let manager = Manager::new()?; + if let Some(device) = manager.devices().first() { + device.connect() + } else { + Err("No device connected".into()) + } +} + +pub fn connect_model(model: Model) -> Result { + let manager = Manager::new()?; + if let Some(device) = manager.devices().iter().filter(|i| i.model == model).next() { + device.connect() + } else { + Err(format!("No {:?} device connected", model).into()) + } +} + +pub struct Manager { + hidapi: hidapi::HidApi, +} + +impl Manager { + pub fn new() -> Result { + let hidapi = hidapi::HidApi::new()?; + Ok(Manager { hidapi }) + } + + pub fn devices(&self) -> Vec> { + self.hidapi + .device_list() + .flat_map(|device_info| { + Model::from_vid_pid(device_info.vendor_id(), device_info.product_id()).map( + |model| DeviceInfo { + hidapi: &self.hidapi, + device_info, + model, + }, + ) + }) + .collect() + } +} + +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Model { + Pro, + Storage, +} + +impl Model { + fn from_vid_pid(vid: u16, pid: u16) -> Option { + match vid { + VID_NITROKEY => match pid { + PID_NITROKEY_PRO => Some(Model::Pro), + PID_NITROKEY_STORAGE => Some(Model::Storage), + _ => None, + }, + _ => None, + } + } +} + +pub struct DeviceInfo<'a> { + hidapi: &'a hidapi::HidApi, + device_info: &'a hidapi::DeviceInfo, + model: Model, +} + +impl<'a> DeviceInfo<'a> { + pub fn connect(&self) -> Result { + let hid_device = self.device_info.open_device(self.hidapi)?; + match self.model { + Model::Pro => Ok(devices::Pro::new(hid_device, self).into()), + Model::Storage => unimplemented!(), + } + } +} + +impl<'a> fmt::Debug for DeviceInfo<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DeviceInfo") + .field("model", &self.model) + .field("path", &self.device_info.path()) + .finish() + } +} -- cgit v1.2.1