aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2017-04-08 18:23:25 -0700
committerDaniel Mueller <deso@posteo.net>2017-04-08 18:23:25 -0700
commitf1fe434d1487fad624b0574955c3af0cfd75e674 (patch)
treefb15bfc358f17bb018776ace476deafd15ea23e0
parentf571751d203cfcf2456dc0d85b724cbab3d4075a (diff)
downloadnitrocli-f1fe434d1487fad624b0574955c3af0cfd75e674.tar.gz
nitrocli-f1fe434d1487fad624b0574955c3af0cfd75e674.tar.bz2
Introduce transmit function subsuming send and receive
The send a report, wait for some time, and receive a response pattern is used in many places already and more are to come. In fact, no send should ever happen without the wait for a response. To that end, this change introduces a new 'transmit' function that performs the exactly this task: send a report and return the response to it.
-rw-r--r--nitrocli/src/main.rs47
1 files changed, 27 insertions, 20 deletions
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index 6b39ad2..32ecb3a 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -117,6 +117,23 @@ fn receive<P>(handle: &mut libhid::Handle) -> Result<nitrokey::Report<P>>
}
+/// Transmit a HID feature report to the nitrokey and receive a response.
+fn transmit<PS, PR>(handle: &mut libhid::Handle,
+ report: &nitrokey::Report<PS>)
+ -> Result<nitrokey::Report<PR>>
+ where PS: AsRef<[u8]>,
+ PR: AsRef<[u8]> + Default,
+{
+ send(handle, &report)?;
+
+ // We need to give the stick some time to handle the command. If we
+ // don't, we might just receive stale data from before.
+ thread::sleep(time::Duration::from_millis(SEND_RECV_DELAY_MS));
+
+ return receive::<PR>(handle);
+}
+
+
/// Find and open the nitrokey device and execute a function on it.
fn nitrokey_do(function: &NitroFunc) -> Result<()> {
let hid = libhid::init()?;
@@ -138,12 +155,7 @@ fn open() -> Result<()> {
let payload = nitrokey::EnableEncryptedVolumeCommand::new(&passphrase);
let report = nitrokey::Report::from(payload);
- send(handle, &report)?;
- // We need to give the stick some time to handle the command. If we
- // don't, we might just receive stale data from before.
- thread::sleep(time::Duration::from_millis(SEND_RECV_DELAY_MS));
-
- receive::<nitrokey::EmptyPayload>(handle)?;
+ transmit::<_, nitrokey::EmptyPayload>(handle, &report)?;
return Ok(());
});
}
@@ -155,7 +167,7 @@ fn close() -> Result<()> {
let payload = nitrokey::DisableEncryptedVolumeCommand::new();
let report = nitrokey::Report::from(payload);
- send(handle, &report)?;
+ transmit::<_, nitrokey::EmptyPayload>(handle, &report)?;
return Ok(());
});
}
@@ -205,6 +217,8 @@ mod tests {
#[test]
fn wrong_crc() {
+ type Response = nitrokey::Response<nitrokey::DeviceStatusResponse>;
+
nitrokey_do(&|handle| {
let payload = nitrokey::DeviceStatusCommand::new();
let mut report = nitrokey::Report::from(payload);
@@ -213,14 +227,10 @@ mod tests {
// report of the CRC mismatch) repeatedly.
for _ in 0..10 {
report.crc += 1;
- send(handle, &report).unwrap();
- thread::sleep(time::Duration::from_millis(SEND_RECV_DELAY_MS));
- let new_report = receive::<nitrokey::EmptyPayload>(handle).unwrap();
- assert!(new_report.is_valid());
+ let new_report = transmit::<_, nitrokey::EmptyPayload>(handle, &report)?;
+ let response = AsRef::<Response>::as_ref(&new_report.data);
- let response: &nitrokey::Response<nitrokey::DeviceStatusResponse> = new_report.data
- .as_ref();
assert_eq!(response.command, nitrokey::Command::GetDeviceStatus);
assert_eq!(response.command_crc, report.crc);
assert_eq!(response.command_status, nitrokey::CommandStatus::WrongCrc);
@@ -232,17 +242,14 @@ mod tests {
#[test]
fn device_status() {
+ type Response = nitrokey::Response<nitrokey::DeviceStatusResponse>;
+
nitrokey_do(&|handle| {
let payload = nitrokey::DeviceStatusCommand::new();
let report = nitrokey::Report::from(payload);
- send(handle, &report).unwrap();
- thread::sleep(time::Duration::from_millis(SEND_RECV_DELAY_MS));
-
- let new_report = receive::<nitrokey::EmptyPayload>(handle).unwrap();
- assert!(new_report.is_valid());
-
- let response: &nitrokey::Response<nitrokey::DeviceStatusResponse> = new_report.data.as_ref();
+ let report = transmit::<_, nitrokey::EmptyPayload>(handle, &report)?;
+ let response = AsRef::<Response>::as_ref(&report.data);
assert!(response.device_status == nitrokey::StorageStatus::Idle ||
response.device_status == nitrokey::StorageStatus::Okay);