diff options
Diffstat (limited to 'src/device.rs')
-rw-r--r-- | src/device.rs | 359 |
1 files changed, 155 insertions, 204 deletions
diff --git a/src/device.rs b/src/device.rs index 51551c2..758d4c1 100644 --- a/src/device.rs +++ b/src/device.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: MIT use std::fmt; -use std::marker; use libc; use nitrokey_sys; @@ -54,7 +53,7 @@ impl fmt::Display for VolumeMode { /// A wrapper for a Nitrokey device of unknown type. /// -/// Use the function [`connect`][] to obtain a wrapped instance. The wrapper implements all traits +/// Use the [`connect`][] method to obtain a wrapped instance. The wrapper implements all traits /// that are shared between all Nitrokey devices so that the shared functionality can be used /// without knowing the type of the underlying device. If you want to use functionality that is /// not available for all devices, you have to extract the device. @@ -67,11 +66,12 @@ impl fmt::Display for VolumeMode { /// use nitrokey::{Authenticate, DeviceWrapper, User}; /// # use nitrokey::Error; /// -/// fn perform_user_task(device: &User<DeviceWrapper>) {} +/// fn perform_user_task<'a>(device: &User<'a, DeviceWrapper<'a>>) {} /// fn perform_other_task(device: &DeviceWrapper) {} /// /// # fn try_main() -> Result<(), Error> { -/// let device = nitrokey::connect()?; +/// let mut manager = nitrokey::take()?; +/// let device = manager.connect()?; /// let device = match device.authenticate_user("123456") { /// Ok(user) => { /// perform_user_task(&user); @@ -97,7 +97,8 @@ impl fmt::Display for VolumeMode { /// fn perform_storage_task(device: &Storage) {} /// /// # fn try_main() -> Result<(), Error> { -/// let device = nitrokey::connect()?; +/// let mut manager = nitrokey::take()?; +/// let device = manager.connect()?; /// perform_common_task(&device); /// match device { /// DeviceWrapper::Storage(storage) => perform_storage_task(&storage), @@ -107,21 +108,20 @@ impl fmt::Display for VolumeMode { /// # } /// ``` /// -/// [`connect`]: fn.connect.html +/// [`connect`]: struct.Manager.html#method.connect #[derive(Debug)] -pub enum DeviceWrapper { +pub enum DeviceWrapper<'a> { /// A Nitrokey Storage device. - Storage(Storage), + Storage(Storage<'a>), /// A Nitrokey Pro device. - Pro(Pro), + Pro(Pro<'a>), } /// A Nitrokey Pro device without user or admin authentication. /// -/// Use the global function [`connect`][] to obtain an instance wrapper or the method -/// [`connect`][`Pro::connect`] to directly obtain an instance. If you want to execute a command -/// that requires user or admin authentication, use [`authenticate_admin`][] or -/// [`authenticate_user`][]. +/// Use the [`connect`][] method to obtain an instance wrapper or the [`connect_pro`] method to +/// directly obtain an instance. If you want to execute a command that requires user or admin +/// authentication, use [`authenticate_admin`][] or [`authenticate_user`][]. /// /// # Examples /// @@ -131,11 +131,12 @@ pub enum DeviceWrapper { /// use nitrokey::{Authenticate, User, Pro}; /// # use nitrokey::Error; /// -/// fn perform_user_task(device: &User<Pro>) {} +/// fn perform_user_task<'a>(device: &User<'a, Pro<'a>>) {} /// fn perform_other_task(device: &Pro) {} /// /// # fn try_main() -> Result<(), Error> { -/// let device = nitrokey::Pro::connect()?; +/// let mut manager = nitrokey::take()?; +/// let device = manager.connect_pro()?; /// let device = match device.authenticate_user("123456") { /// Ok(user) => { /// perform_user_task(&user); @@ -153,21 +154,18 @@ pub enum DeviceWrapper { /// /// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin /// [`authenticate_user`]: trait.Authenticate.html#method.authenticate_user -/// [`connect`]: fn.connect.html -/// [`Pro::connect`]: #method.connect +/// [`connect`]: struct.Manager.html#method.connect +/// [`connect_pro`]: struct.Manager.html#method.connect_pro #[derive(Debug)] -pub struct Pro { - // make sure that users cannot directly instantiate this type - #[doc(hidden)] - marker: marker::PhantomData<()>, +pub struct Pro<'a> { + manager: Option<&'a mut crate::Manager>, } /// A Nitrokey Storage device without user or admin authentication. /// -/// Use the global function [`connect`][] to obtain an instance wrapper or the method -/// [`connect`][`Storage::connect`] to directly obtain an instance. If you want to execute a -/// command that requires user or admin authentication, use [`authenticate_admin`][] or -/// [`authenticate_user`][]. +/// Use the [`connect`][] method to obtain an instance wrapper or the [`connect_storage`] method to +/// directly obtain an instance. If you want to execute a command that requires user or admin +/// authentication, use [`authenticate_admin`][] or [`authenticate_user`][]. /// /// # Examples /// @@ -177,11 +175,12 @@ pub struct Pro { /// use nitrokey::{Authenticate, User, Storage}; /// # use nitrokey::Error; /// -/// fn perform_user_task(device: &User<Storage>) {} +/// fn perform_user_task<'a>(device: &User<'a, Storage<'a>>) {} /// fn perform_other_task(device: &Storage) {} /// /// # fn try_main() -> Result<(), Error> { -/// let device = nitrokey::Storage::connect()?; +/// let mut manager = nitrokey::take()?; +/// let device = manager.connect_storage()?; /// let device = match device.authenticate_user("123456") { /// Ok(user) => { /// perform_user_task(&user); @@ -199,13 +198,11 @@ pub struct Pro { /// /// [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin /// [`authenticate_user`]: trait.Authenticate.html#method.authenticate_user -/// [`connect`]: fn.connect.html -/// [`Storage::connect`]: #method.connect +/// [`connect`]: struct.Manager.html#method.connect +/// [`connect_storage`]: struct.Manager.html#method.connect_storage #[derive(Debug)] -pub struct Storage { - // make sure that users cannot directly instantiate this type - #[doc(hidden)] - marker: marker::PhantomData<()>, +pub struct Storage<'a> { + manager: Option<&'a mut crate::Manager>, } /// The status of a volume on a Nitrokey Storage device. @@ -296,7 +293,32 @@ pub struct StorageStatus { /// /// This trait provides the commands that can be executed without authentication and that are /// present on all supported Nitrokey devices. -pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { +pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt::Debug { + /// Returns the [`Manager`][] instance that has been used to connect to this device. + /// + /// # Example + /// + /// ``` + /// use nitrokey::{Device, DeviceWrapper}; + /// + /// fn do_something(device: DeviceWrapper) { + /// // reconnect to any device + /// let manager = device.into_manager(); + /// let device = manager.connect(); + /// // do something with the device + /// // ... + /// } + /// + /// # fn main() -> Result<(), nitrokey::Error> { + /// match nitrokey::take()?.connect() { + /// Ok(device) => do_something(device), + /// Err(err) => println!("Could not connect to a Nitrokey: {}", err), + /// } + /// # Ok(()) + /// # } + /// ``` + fn into_manager(self) -> &'a mut crate::Manager; + /// Returns the model of the connected Nitrokey device. /// /// # Example @@ -306,7 +328,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; /// println!("Connected to a Nitrokey {}", device.get_model()); /// # Ok(()) /// # } @@ -322,7 +345,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; /// match device.get_serial_number() { /// Ok(number) => println!("serial no: {}", number), /// Err(err) => eprintln!("Could not get serial number: {}", err), @@ -344,7 +368,9 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; + /// let count = device.get_user_retry_count(); /// match device.get_user_retry_count() { /// Ok(count) => println!("{} remaining authentication attempts (user)", count), /// Err(err) => eprintln!("Could not get user retry count: {}", err), @@ -366,7 +392,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; /// let count = device.get_admin_retry_count(); /// match device.get_admin_retry_count() { /// Ok(count) => println!("{} remaining authentication attempts (admin)", count), @@ -388,7 +415,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; /// match device.get_firmware_version() { /// Ok(version) => println!("Firmware version: {}", version), /// Err(err) => eprintln!("Could not access firmware version: {}", err), @@ -411,7 +439,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect()?; /// let config = device.get_config()?; /// println!("numlock binding: {:?}", config.numlock); /// println!("capslock binding: {:?}", config.capslock); @@ -445,7 +474,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.change_admin_pin("12345678", "12345679") { /// Ok(()) => println!("Updated admin PIN."), /// Err(err) => eprintln!("Failed to update admin PIN: {}", err), @@ -478,7 +508,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.change_user_pin("123456", "123457") { /// Ok(()) => println!("Updated admin PIN."), /// Err(err) => eprintln!("Failed to update admin PIN: {}", err), @@ -511,7 +542,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.unlock_user_pin("12345678", "123456") { /// Ok(()) => println!("Unlocked user PIN."), /// Err(err) => eprintln!("Failed to unlock user PIN: {}", err), @@ -545,7 +577,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.lock() { /// Ok(()) => println!("Locked the Nitrokey device."), /// Err(err) => eprintln!("Could not lock the Nitrokey device: {}", err), @@ -576,7 +609,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.factory_reset("12345678") { /// Ok(()) => println!("Performed a factory reset."), /// Err(err) => eprintln!("Could not perform a factory reset: {}", err), @@ -610,7 +644,8 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect()?; /// match device.build_aes_key("12345678") { /// Ok(()) => println!("New AES keys have been built."), /// Err(err) => eprintln!("Could not build new AES keys: {}", err), @@ -626,67 +661,6 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug { } } -/// Connects to a Nitrokey device. This method can be used to connect to any connected device, -/// both a Nitrokey Pro and a Nitrokey Storage. -/// -/// # Errors -/// -/// - [`NotConnected`][] if no Nitrokey device is connected -/// -/// # Example -/// -/// ``` -/// use nitrokey::DeviceWrapper; -/// -/// fn do_something(device: DeviceWrapper) {} -/// -/// match nitrokey::connect() { -/// Ok(device) => do_something(device), -/// Err(err) => eprintln!("Could not connect to a Nitrokey: {}", err), -/// } -/// ``` -/// -/// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected -pub fn connect() -> Result<DeviceWrapper, Error> { - if unsafe { nitrokey_sys::NK_login_auto() } == 1 { - match get_connected_device() { - Some(wrapper) => Ok(wrapper), - None => Err(CommunicationError::NotConnected.into()), - } - } else { - Err(CommunicationError::NotConnected.into()) - } -} - -/// Connects to a Nitrokey device of the given model. -/// -/// # Errors -/// -/// - [`NotConnected`][] if no Nitrokey device of the given model is connected -/// -/// # Example -/// -/// ``` -/// use nitrokey::DeviceWrapper; -/// use nitrokey::Model; -/// -/// fn do_something(device: DeviceWrapper) {} -/// -/// match nitrokey::connect_model(Model::Pro) { -/// Ok(device) => do_something(device), -/// Err(err) => eprintln!("Could not connect to a Nitrokey Pro: {}", err), -/// } -/// ``` -/// -/// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected -pub fn connect_model(model: Model) -> Result<DeviceWrapper, Error> { - if connect_enum(model) { - Ok(create_device_wrapper(model)) - } else { - Err(CommunicationError::NotConnected.into()) - } -} - fn get_connected_model() -> Option<Model> { match unsafe { nitrokey_sys::NK_get_device_model() } { nitrokey_sys::NK_device_model_NK_PRO => Some(Model::Pro), @@ -695,18 +669,26 @@ fn get_connected_model() -> Option<Model> { } } -fn create_device_wrapper(model: Model) -> DeviceWrapper { +pub(crate) fn create_device_wrapper( + manager: &mut crate::Manager, + model: Model, +) -> DeviceWrapper<'_> { match model { - Model::Pro => Pro::new().into(), - Model::Storage => Storage::new().into(), + Model::Pro => Pro::new(manager).into(), + Model::Storage => Storage::new(manager).into(), } } -fn get_connected_device() -> Option<DeviceWrapper> { - get_connected_model().map(create_device_wrapper) +pub(crate) fn get_connected_device( + manager: &mut crate::Manager, +) -> Result<DeviceWrapper<'_>, Error> { + match get_connected_model() { + Some(model) => Ok(create_device_wrapper(manager, model)), + None => Err(CommunicationError::NotConnected.into()), + } } -fn connect_enum(model: Model) -> bool { +pub(crate) fn connect_enum(model: Model) -> bool { let model = match model { Model::Storage => nitrokey_sys::NK_device_model_NK_STORAGE, Model::Pro => nitrokey_sys::NK_device_model_NK_PRO, @@ -714,15 +696,15 @@ fn connect_enum(model: Model) -> bool { unsafe { nitrokey_sys::NK_login_enum(model) == 1 } } -impl DeviceWrapper { - fn device(&self) -> &dyn Device { +impl<'a> DeviceWrapper<'a> { + fn device(&self) -> &dyn Device<'a> { match *self { DeviceWrapper::Storage(ref storage) => storage, DeviceWrapper::Pro(ref pro) => pro, } } - fn device_mut(&mut self) -> &mut dyn Device { + fn device_mut(&mut self) -> &mut dyn Device<'a> { match *self { DeviceWrapper::Storage(ref mut storage) => storage, DeviceWrapper::Pro(ref mut pro) => pro, @@ -730,19 +712,19 @@ impl DeviceWrapper { } } -impl From<Pro> for DeviceWrapper { - fn from(device: Pro) -> Self { +impl<'a> From<Pro<'a>> for DeviceWrapper<'a> { + fn from(device: Pro<'a>) -> Self { DeviceWrapper::Pro(device) } } -impl From<Storage> for DeviceWrapper { - fn from(device: Storage) -> Self { +impl<'a> From<Storage<'a>> for DeviceWrapper<'a> { + fn from(device: Storage<'a>) -> Self { DeviceWrapper::Storage(device) } } -impl GenerateOtp for DeviceWrapper { +impl<'a> GenerateOtp for DeviceWrapper<'a> { fn get_hotp_slot_name(&self, slot: u8) -> Result<String, Error> { self.device().get_hotp_slot_name(slot) } @@ -760,7 +742,14 @@ impl GenerateOtp for DeviceWrapper { } } -impl Device for DeviceWrapper { +impl<'a> Device<'a> for DeviceWrapper<'a> { + fn into_manager(self) -> &'a mut crate::Manager { + match self { + DeviceWrapper::Pro(dev) => dev.into_manager(), + DeviceWrapper::Storage(dev) => dev.into_manager(), + } + } + fn get_model(&self) -> Model { match *self { DeviceWrapper::Pro(_) => Model::Pro, @@ -769,44 +758,15 @@ impl Device for DeviceWrapper { } } -impl Pro { - /// Connects to a Nitrokey Pro. - /// - /// # Errors - /// - /// - [`NotConnected`][] if no Nitrokey device of the given model is connected - /// - /// # Example - /// - /// ``` - /// use nitrokey::Pro; - /// - /// fn use_pro(device: Pro) {} - /// - /// match nitrokey::Pro::connect() { - /// Ok(device) => use_pro(device), - /// Err(err) => eprintln!("Could not connect to the Nitrokey Pro: {}", err), - /// } - /// ``` - /// - /// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected - pub fn connect() -> Result<Pro, Error> { - // TODO: maybe Option instead of Result? - if connect_enum(Model::Pro) { - Ok(Pro::new()) - } else { - Err(CommunicationError::NotConnected.into()) - } - } - - fn new() -> Pro { +impl<'a> Pro<'a> { + pub(crate) fn new(manager: &'a mut crate::Manager) -> Pro<'a> { Pro { - marker: marker::PhantomData, + manager: Some(manager), } } } -impl Drop for Pro { +impl<'a> Drop for Pro<'a> { fn drop(&mut self) { unsafe { nitrokey_sys::NK_logout(); @@ -814,47 +774,22 @@ impl Drop for Pro { } } -impl Device for Pro { +impl<'a> Device<'a> for Pro<'a> { + fn into_manager(mut self) -> &'a mut crate::Manager { + self.manager.take().unwrap() + } + fn get_model(&self) -> Model { Model::Pro } } -impl GenerateOtp for Pro {} - -impl Storage { - /// Connects to a Nitrokey Storage. - /// - /// # Errors - /// - /// - [`NotConnected`][] if no Nitrokey device of the given model is connected - /// - /// # Example - /// - /// ``` - /// use nitrokey::Storage; - /// - /// fn use_storage(device: Storage) {} - /// - /// match nitrokey::Storage::connect() { - /// Ok(device) => use_storage(device), - /// Err(err) => eprintln!("Could not connect to the Nitrokey Storage: {}", err), - /// } - /// ``` - /// - /// [`NotConnected`]: enum.CommunicationError.html#variant.NotConnected - pub fn connect() -> Result<Storage, Error> { - // TODO: maybe Option instead of Result? - if connect_enum(Model::Storage) { - Ok(Storage::new()) - } else { - Err(CommunicationError::NotConnected.into()) - } - } +impl<'a> GenerateOtp for Pro<'a> {} - fn new() -> Storage { +impl<'a> Storage<'a> { + pub(crate) fn new(manager: &'a mut crate::Manager) -> Storage<'a> { Storage { - marker: marker::PhantomData, + manager: Some(manager), } } @@ -875,7 +810,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.change_update_pin("12345678", "87654321") { /// Ok(()) => println!("Updated update PIN."), /// Err(err) => eprintln!("Failed to update update PIN: {}", err), @@ -912,7 +848,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.enable_firmware_update("12345678") { /// Ok(()) => println!("Nitrokey entered update mode."), /// Err(err) => eprintln!("Could not enter update mode: {}", err), @@ -946,7 +883,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.enable_encrypted_volume("123456") { /// Ok(()) => println!("Enabled the encrypted volume."), /// Err(err) => eprintln!("Could not enable the encrypted volume: {}", err), @@ -975,7 +913,8 @@ impl Storage { /// fn use_volume() {} /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.enable_encrypted_volume("123456") { /// Ok(()) => { /// println!("Enabled the encrypted volume."); @@ -1021,7 +960,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// device.enable_encrypted_volume("123445")?; /// match device.enable_hidden_volume("hidden-pw") { /// Ok(()) => println!("Enabled a hidden volume."), @@ -1054,7 +994,8 @@ impl Storage { /// fn use_volume() {} /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// device.enable_encrypted_volume("123445")?; /// match device.enable_hidden_volume("hidden-pw") { /// Ok(()) => { @@ -1101,7 +1042,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// device.enable_encrypted_volume("123445")?; /// device.create_hidden_volume(0, 0, 100, "hidden-pw")?; /// # Ok(()) @@ -1141,7 +1083,8 @@ impl Storage { /// use nitrokey::VolumeMode; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.set_unencrypted_volume_mode("12345678", VolumeMode::ReadWrite) { /// Ok(()) => println!("Set the unencrypted volume to read-write mode."), /// Err(err) => eprintln!("Could not set the unencrypted volume to read-write mode: {}", err), @@ -1186,7 +1129,8 @@ impl Storage { /// use nitrokey::VolumeMode; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.set_encrypted_volume_mode("12345678", VolumeMode::ReadWrite) { /// Ok(()) => println!("Set the encrypted volume to read-write mode."), /// Err(err) => eprintln!("Could not set the encrypted volume to read-write mode: {}", err), @@ -1224,7 +1168,8 @@ impl Storage { /// fn use_volume() {} /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect_storage()?; /// match device.get_status() { /// Ok(status) => { /// println!("SD card ID: {:#x}", status.serial_number_sd_card); @@ -1267,7 +1212,8 @@ impl Storage { /// fn use_volume() {} /// /// # fn try_main() -> Result<(), Error> { - /// let device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let device = manager.connect_storage()?; /// match device.get_production_info() { /// Ok(data) => { /// println!("SD card ID: {:#x}", data.sd_card.serial_number); @@ -1315,7 +1261,8 @@ impl Storage { /// # use nitrokey::Error; /// /// # fn try_main() -> Result<(), Error> { - /// let mut device = nitrokey::Storage::connect()?; + /// let mut manager = nitrokey::take()?; + /// let mut device = manager.connect_storage()?; /// match device.clear_new_sd_card_warning("12345678") { /// Ok(()) => println!("Cleared the new SD card warning."), /// Err(err) => eprintln!("Could not set the clear the new SD card warning: {}", err), @@ -1360,7 +1307,7 @@ impl Storage { } } -impl Drop for Storage { +impl<'a> Drop for Storage<'a> { fn drop(&mut self) { unsafe { nitrokey_sys::NK_logout(); @@ -1368,13 +1315,17 @@ impl Drop for Storage { } } -impl Device for Storage { +impl<'a> Device<'a> for Storage<'a> { + fn into_manager(mut self) -> &'a mut crate::Manager { + self.manager.take().unwrap() + } + fn get_model(&self) -> Model { Model::Storage } } -impl GenerateOtp for Storage {} +impl<'a> GenerateOtp for Storage<'a> {} impl From<nitrokey_sys::NK_storage_ProductionTest> for StorageProductionInfo { fn from(data: nitrokey_sys::NK_storage_ProductionTest) -> Self { |