diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2019-12-29 12:51:28 +0100 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2020-01-07 11:33:27 +0100 | 
| commit | c74b8b3ea8dc4fe7c6891ae120540f8da5623227 (patch) | |
| tree | 7c66308f30a2a6137339289a55e7ce52f73ae100 /src | |
| parent | bcad061ed3e7777547c1b6fc9223dd65f752d94e (diff) | |
| download | nitrokey-rs-c74b8b3ea8dc4fe7c6891ae120540f8da5623227.tar.gz nitrokey-rs-c74b8b3ea8dc4fe7c6891ae120540f8da5623227.tar.bz2 | |
Add list_devices function
This patch adds support for libnitrokey’s NK_list_devices function by
introducing the top-level list_devices function.  It returns a vector of
DeviceInfo structs with information about all connected Nitrokey
devices.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 68 | 
1 files changed, 68 insertions, 0 deletions
| @@ -109,8 +109,10 @@ mod otp;  mod pws;  mod util; +use std::convert::TryInto as _;  use std::fmt;  use std::marker; +use std::ptr::NonNull;  use std::sync;  use nitrokey_sys; @@ -126,6 +128,8 @@ pub use crate::otp::{ConfigureOtp, GenerateOtp, OtpMode, OtpSlotData};  pub use crate::pws::{GetPasswordSafe, PasswordSafe, SLOT_COUNT};  pub use crate::util::LogLevel; +use crate::util::get_last_result; +  /// The default admin PIN for all Nitrokey devices.  pub const DEFAULT_ADMIN_PIN: &str = "12345678";  /// The default user PIN for all Nitrokey devices. @@ -416,6 +420,70 @@ pub fn force_take() -> Result<sync::MutexGuard<'static, Manager>, Error> {      }  } +/// List all connected Nitrokey devices. +/// +/// This functions returns a vector with [`DeviceInfo`][] structs that contain information about +/// all connected Nitrokey devices.  It will even list unsupported models, although you cannot +/// connect to them. +/// +/// # Errors +/// +/// - [`NotConnected`][] if a Nitrokey device has been disconnected during enumeration +/// - [`Utf8Error`][] if the USB path or the serial number returned by libnitrokey are invalid +///   UTF-8 strings +/// +/// # Example +/// +/// ``` +/// let devices = nitrokey::list_devices()?; +/// if devices.is_empty() { +///     println!("No connected Nitrokey devices found."); +/// } else { +///     println!("model\tpath\tserial number"); +///     for device in devices { +///         match device.model { +///             Some(model) => print!("{}", model), +///             None => print!("unsupported"), +///         } +///         print!("\t{}\t", device.path); +///         match device.serial_number { +///             Some(serial_number) => println!("{}", serial_number), +///             None => println!("unknown"), +///         } +///     } +/// } +/// # Ok::<(), nitrokey::Error>(()) +/// ``` +/// +/// [`DeviceInfo`]: struct.DeviceInfo.html +/// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected +/// [`Utf8Error`]: enum.Error.html#variant.Utf8Error +pub fn list_devices() -> Result<Vec<DeviceInfo>, Error> { +    let ptr = NonNull::new(unsafe { nitrokey_sys::NK_list_devices() }); +    match ptr { +        Some(mut ptr) => { +            let mut vec: Vec<DeviceInfo> = Vec::new(); +            push_device_info(&mut vec, unsafe { ptr.as_ref() })?; +            unsafe { +                nitrokey_sys::NK_free_device_info(ptr.as_mut()); +            } +            Ok(vec) +        } +        None => get_last_result().map(|_| Vec::new()), +    } +} + +fn push_device_info( +    vec: &mut Vec<DeviceInfo>, +    info: &nitrokey_sys::NK_device_info, +) -> Result<(), Error> { +    vec.push(info.try_into()?); +    if let Some(ptr) = NonNull::new(info.next) { +        push_device_info(vec, unsafe { ptr.as_ref() })?; +    } +    Ok(()) +} +  /// Enables or disables debug output.  Calling this method with `true` is equivalent to setting the  /// log level to `Debug`; calling it with `false` is equivalent to the log level `Error` (see  /// [`set_log_level`][]). | 
