summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs101
1 files changed, 101 insertions, 0 deletions
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<dyn std::error::Error>;
+
+const VID_NITROKEY: u16 = 0x20a0;
+const PID_NITROKEY_PRO: u16 = 0x4108;
+const PID_NITROKEY_STORAGE: u16 = 0x4109;
+
+pub fn connect() -> Result<devices::Device, Error> {
+ 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<devices::Device, Error> {
+ 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<Self, Error> {
+ let hidapi = hidapi::HidApi::new()?;
+ Ok(Manager { hidapi })
+ }
+
+ pub fn devices(&self) -> Vec<DeviceInfo<'_>> {
+ 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<Model> {
+ 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<devices::Device, Error> {
+ 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()
+ }
+}