aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/auth.rs13
-rw-r--r--src/device.rs117
-rw-r--r--src/lib.rs77
-rw-r--r--src/otp.rs27
-rw-r--r--src/pws.rs24
5 files changed, 178 insertions, 80 deletions
diff --git a/src/auth.rs b/src/auth.rs
index 829d083..0b000f7 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -39,11 +39,12 @@ pub trait Authenticate<'a> {
/// 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);
@@ -85,11 +86,12 @@ pub trait Authenticate<'a> {
/// use nitrokey::{Authenticate, Admin, DeviceWrapper};
/// # use nitrokey::Error;
///
- /// fn perform_admin_task(device: &Admin<DeviceWrapper>) {}
+ /// fn perform_admin_task<'a>(device: &Admin<'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_admin("123456") {
/// Ok(admin) => {
/// perform_admin_task(&admin);
@@ -291,7 +293,8 @@ impl<'a, T: Device<'a>> Admin<'a, T> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// let config = Config::new(None, None, None, false);
/// match device.authenticate_admin("12345678") {
/// Ok(mut admin) => {
diff --git a/src/device.rs b/src/device.rs
index e1a71fa..758d4c1 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -53,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.
@@ -66,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);
@@ -96,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),
@@ -106,7 +108,7 @@ impl fmt::Display for VolumeMode {
/// # }
/// ```
///
-/// [`connect`]: fn.connect.html
+/// [`connect`]: struct.Manager.html#method.connect
#[derive(Debug)]
pub enum DeviceWrapper<'a> {
/// A Nitrokey Storage device.
@@ -117,10 +119,9 @@ pub enum DeviceWrapper<'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
///
@@ -130,11 +131,12 @@ pub enum DeviceWrapper<'a> {
/// 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);
@@ -152,8 +154,8 @@ pub enum DeviceWrapper<'a> {
///
/// [`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<'a> {
manager: Option<&'a mut crate::Manager>,
@@ -161,10 +163,9 @@ pub struct Pro<'a> {
/// 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
///
@@ -174,11 +175,12 @@ pub struct Pro<'a> {
/// 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);
@@ -196,8 +198,8 @@ pub struct Pro<'a> {
///
/// [`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<'a> {
manager: Option<&'a mut crate::Manager>,
@@ -326,7 +328,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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(())
/// # }
@@ -342,7 +345,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -364,7 +368,9 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -386,7 +392,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -408,7 +415,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -431,7 +439,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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);
@@ -465,7 +474,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -498,7 +508,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -531,7 +542,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -565,7 +577,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -596,7 +609,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -630,7 +644,8 @@ pub trait Device<'a>: Authenticate<'a> + GetPasswordSafe<'a> + GenerateOtp + fmt
/// # 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),
@@ -795,7 +810,8 @@ impl<'a> Storage<'a> {
/// # 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),
@@ -832,7 +848,8 @@ impl<'a> Storage<'a> {
/// # 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),
@@ -866,7 +883,8 @@ impl<'a> Storage<'a> {
/// # 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),
@@ -895,7 +913,8 @@ impl<'a> Storage<'a> {
/// 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.");
@@ -941,7 +960,8 @@ impl<'a> Storage<'a> {
/// # 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."),
@@ -974,7 +994,8 @@ impl<'a> Storage<'a> {
/// 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(()) => {
@@ -1021,7 +1042,8 @@ impl<'a> Storage<'a> {
/// # 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(())
@@ -1061,7 +1083,8 @@ impl<'a> Storage<'a> {
/// 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),
@@ -1106,7 +1129,8 @@ impl<'a> Storage<'a> {
/// 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),
@@ -1144,7 +1168,8 @@ impl<'a> Storage<'a> {
/// 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);
@@ -1187,7 +1212,8 @@ impl<'a> Storage<'a> {
/// 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);
@@ -1235,7 +1261,8 @@ impl<'a> Storage<'a> {
/// # 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),
diff --git a/src/lib.rs b/src/lib.rs
index 8b0aae5..36a1dfd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,13 +9,16 @@
//! performed without authentication, some require user access, and some require admin access.
//! This is modelled using the types [`User`][] and [`Admin`][].
//!
-//! Use [`connect`][] to connect to any Nitrokey device. The method will return a
+//! You can only connect to one Nitrokey at a time. Use the global [`take`][] function to obtain
+//! an reference to the [`Manager`][] singleton that keeps track of the connections. Then use the
+//! [`connect`][] method to connect to any Nitrokey device. The method will return a
//! [`DeviceWrapper`][] that abstracts over the supported Nitrokey devices. You can also use
-//! [`Pro::connect`][] or [`Storage::connect`][] to connect to a specific device.
+//! [`connect_model`][], [`connect_pro`][] or [`connect_storage`][] to connect to a specific
+//! device.
//!
-//! You can then use [`authenticate_user`][] or [`authenticate_admin`][] to get an authenticated
-//! device that can perform operations that require authentication. You can use [`device`][] to go
-//! back to the unauthenticated device.
+//! You can call [`authenticate_user`][] or [`authenticate_admin`][] to get an authenticated device
+//! that can perform operations that require authentication. You can use [`device`][] to go back
+//! to the unauthenticated device.
//!
//! This makes sure that you can only execute a command if you have the required access rights.
//! Otherwise, your code will not compile. The only exception are the methods to generate one-time
@@ -31,7 +34,8 @@
//! # use nitrokey::Error;
//!
//! # fn try_main() -> Result<(), Error> {
-//! let device = nitrokey::connect()?;
+//! let mut manager = nitrokey::take()?;
+//! let device = manager.connect()?;
//! println!("{}", device.get_serial_number()?);
//! # Ok(())
//! # }
@@ -44,7 +48,8 @@
//! # use nitrokey::Error;
//!
//! # fn try_main() -> Result<(), Error> {
-//! let device = nitrokey::connect()?;
+//! let mut manager = nitrokey::take()?;
+//! let device = manager.connect()?;
//! let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);
//! match device.authenticate_admin("12345678") {
//! Ok(mut admin) => {
@@ -66,7 +71,8 @@
//! # 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.get_hotp_code(1) {
//! Ok(code) => println!("Generated HOTP code: {}", code),
//! Err(err) => eprintln!("Could not generate HOTP code: {}", err),
@@ -77,9 +83,12 @@
//!
//! [`authenticate_admin`]: trait.Authenticate.html#method.authenticate_admin
//! [`authenticate_user`]: trait.Authenticate.html#method.authenticate_user
-//! [`connect`]: fn.connect.html
-//! [`Pro::connect`]: struct.Pro.html#fn.connect.html
-//! [`Storage::connect`]: struct.Storage.html#fn.connect.html
+//! [`take`]: fn.take.html
+//! [`connect`]: struct.Manager.html#method.connect
+//! [`connect_model`]: struct.Manager.html#method.connect_model
+//! [`connect_pro`]: struct.Manager.html#method.connect_pro
+//! [`connect_storage`]: struct.Manager.html#method.connect_storage
+//! [`manager`]: trait.Device.html#method.manager
//! [`device`]: struct.User.html#method.device
//! [`get_hotp_code`]: trait.GenerateOtp.html#method.get_hotp_code
//! [`get_totp_code`]: trait.GenerateOtp.html#method.get_totp_code
@@ -163,9 +172,50 @@ impl fmt::Display for Version {
/// manager struct makes sure that `nitrokey-rs` does not try to connect to two devices at the same
/// time.
///
-/// To obtain an instance of this manager, use the [`take`][] function.
+/// To obtain a reference to an instance of this manager, use the [`take`][] function. Use one of
+/// the connect methods – [`connect`][], [`connect_model`][], [`connect_pro`][] or
+/// [`connect_storage`][] – to retrieve a [`Device`][] instance.
///
+/// # Examples
+///
+/// Connect to a single device:
+///
+/// ```no_run
+/// use nitrokey::Device;
+/// # use nitrokey::Error;
+///
+/// # fn try_main() -> Result<(), Error> {
+/// let mut manager = nitrokey::take()?;
+/// let device = manager.connect()?;
+/// println!("{}", device.get_serial_number()?);
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Connect to a Pro and a Storage device:
+///
+/// ```no_run
+/// use nitrokey::{Device, Model};
+/// # use nitrokey::Error;
+///
+/// # fn try_main() -> Result<(), Error> {
+/// let mut manager = nitrokey::take()?;
+/// let device = manager.connect_model(Model::Pro)?;
+/// println!("Pro: {}", device.get_serial_number()?);
+/// drop(device);
+/// let device = manager.connect_model(Model::Storage)?;
+/// println!("Storage: {}", device.get_serial_number()?);
+/// # Ok(())
+/// # }
+/// ```
+///
+/// [`connect`]: #method.connect
+/// [`connect_model`]: #method.connect_model
+/// [`connect_pro`]: #method.connect_pro
+/// [`connect_storage`]: #method.connect_storage
+/// [`manager`]: trait.Device.html#method.manager
/// [`take`]: fn.take.html
+/// [`Device`]: trait.Device.html
#[derive(Debug)]
pub struct Manager {
marker: marker::PhantomData<()>,
@@ -195,7 +245,8 @@ impl Manager {
/// fn do_something(device: DeviceWrapper) {}
///
/// # fn main() -> Result<(), nitrokey::Error> {
- /// match nitrokey::take()?.connect() {
+ /// let mut manager = nitrokey::take()?;
+ /// match manager.connect() {
/// Ok(device) => do_something(device),
/// Err(err) => println!("Could not connect to a Nitrokey: {}", err),
/// }
diff --git a/src/otp.rs b/src/otp.rs
index ee142c7..4667aff 100644
--- a/src/otp.rs
+++ b/src/otp.rs
@@ -35,7 +35,8 @@ pub trait ConfigureOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);
/// match device.authenticate_admin("12345678") {
/// Ok(mut admin) => {
@@ -71,7 +72,8 @@ pub trait ConfigureOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::EightDigits);
/// match device.authenticate_admin("12345678") {
/// Ok(mut admin) => {
@@ -104,7 +106,8 @@ pub trait ConfigureOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// match device.authenticate_admin("12345678") {
/// Ok(mut admin) => {
/// match admin.erase_hotp_slot(1) {
@@ -134,7 +137,8 @@ pub trait ConfigureOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// match device.authenticate_admin("12345678") {
/// Ok(mut admin) => {
/// match admin.erase_totp_slot(1) {
@@ -171,7 +175,8 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH);
/// match time {
/// Ok(time) => device.set_time(time.as_secs(), false)?,
@@ -209,7 +214,8 @@ pub trait GenerateOtp {
/// use nitrokey::{CommandError, Error, GenerateOtp};
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// match device.get_hotp_slot_name(1) {
/// Ok(name) => println!("HOTP slot 1: {}", name),
/// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => eprintln!("HOTP slot 1 not programmed"),
@@ -238,7 +244,8 @@ pub trait GenerateOtp {
/// use nitrokey::{CommandError, Error, GenerateOtp};
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let device = manager.connect()?;
/// match device.get_totp_slot_name(1) {
/// Ok(name) => println!("TOTP slot 1: {}", name),
/// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => eprintln!("TOTP slot 1 not programmed"),
@@ -270,7 +277,8 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let code = device.get_hotp_code(1)?;
/// println!("Generated HOTP code on slot 1: {}", code);
/// # Ok(())
@@ -305,7 +313,8 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH);
/// match time {
/// Ok(time) => {
diff --git a/src/pws.rs b/src/pws.rs
index 778765d..3398deb 100644
--- a/src/pws.rs
+++ b/src/pws.rs
@@ -43,7 +43,8 @@ pub const SLOT_COUNT: u8 = 16;
/// }
///
/// # fn try_main() -> Result<(), Error> {
-/// let mut device = nitrokey::connect()?;
+/// let mut manager = nitrokey::take()?;
+/// let mut device = manager.connect()?;
/// let pws = device.get_password_safe("123456")?;
/// use_password_safe(&pws);
/// drop(pws);
@@ -98,7 +99,8 @@ pub trait GetPasswordSafe<'a> {
/// fn use_password_safe(pws: &PasswordSafe) {}
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// match device.get_password_safe("123456") {
/// Ok(pws) => {
/// use_password_safe(&pws);
@@ -149,7 +151,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let pws = device.get_password_safe("123456")?;
/// pws.get_slot_status()?.iter().enumerate().for_each(|(slot, programmed)| {
/// let status = match *programmed {
@@ -194,7 +197,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # 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.get_password_safe("123456") {
/// Ok(pws) => {
/// let name = pws.get_slot_name(0)?;
@@ -231,7 +235,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -264,7 +269,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -295,7 +301,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -341,7 +348,8 @@ impl<'a, 'b> PasswordSafe<'a, 'b> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let mut device = nitrokey::connect()?;
+ /// let mut manager = nitrokey::take()?;
+ /// let mut device = manager.connect()?;
/// let mut pws = device.get_password_safe("123456")?;
/// match pws.erase_slot(0) {
/// Ok(()) => println!("Erased slot 0."),