Skip to content

Commit

Permalink
Merge pull request #31 from ssp-rs/feature/enable_payout
Browse files Browse the repository at this point in the history
Feature/enable payout
  • Loading branch information
ssp-rs authored Aug 23, 2023
2 parents ac5df8a + fd27a34 commit 3a0be1a
Show file tree
Hide file tree
Showing 18 changed files with 943 additions and 977 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ssp"
version = "0.5.0"
version = "0.5.1"
edition = "2021"
authors = ["SSP Rust Developers"]
description = "Messages and related types for implementing the SSP/eSSP serial communication protocol"
Expand All @@ -24,6 +24,7 @@ serialport = { version = "4.2", default-features = false, optional = true }
sha2 = "0.10"
zeroize = { version = "1.6", features = ["zeroize_derive"] }
currency-iso4217 = { version = "0.1", features = ["serde"] }
paste = "1.0"

[dependencies.serde]
version = "1.0"
Expand Down
8 changes: 2 additions & 6 deletions src/disable/command.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::{
impl_command_display, impl_command_ops, impl_default, impl_message_from_buf, impl_message_ops,
len::DISABLE_COMMAND, CommandOps, MessageOps, MessageType,
};
use crate::{len::DISABLE_COMMAND, CommandOps, MessageOps, MessageType};

/// Disable - Command (0x09)
///
/// This single byte command disables the unit. This means the unit will enter its disabled state
/// and not execute any further commands or perform any other actions. A poll to the unit
/// while in this state will report disabled (0xE8)
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct DisableCommand {
buf: [u8; DISABLE_COMMAND],
}
Expand All @@ -28,7 +25,6 @@ impl DisableCommand {
}
}

impl_default!(DisableCommand);
impl_command_display!(DisableCommand);
impl_message_from_buf!(DisableCommand);
impl_message_ops!(DisableCommand);
Expand Down
8 changes: 2 additions & 6 deletions src/disable/response.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use crate::{
impl_default, impl_message_from_buf, impl_message_ops, impl_response_display,
impl_response_ops, len::DISABLE_RESPONSE, message::MessageOps, MessageType,
};
use crate::{len::DISABLE_RESPONSE, message::MessageOps, MessageType};

/// Disable - Response (0x09)
///
/// Represents a response to an [DisableCommand](crate::DisableCommand) message.
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct DisableResponse {
buf: [u8; DISABLE_RESPONSE],
}
Expand All @@ -25,7 +22,6 @@ impl DisableResponse {
}
}

impl_default!(DisableResponse);
impl_message_from_buf!(DisableResponse);
impl_message_ops!(DisableResponse, MessageType::Disable);
impl_response_ops!(DisableResponse);
Expand Down
7 changes: 7 additions & 0 deletions src/disable_payout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Message types for disabling a payout device.

mod command;
mod response;

pub use command::*;
pub use response::*;
29 changes: 29 additions & 0 deletions src/disable_payout/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::{len::DISABLE_PAYOUT_COMMAND, CommandOps, MessageOps, MessageType};

/// DisablePayout - Command (0x5B)
///
/// All accepted notes will be routed to the stacker and payout commands will not be accepted.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct DisablePayoutCommand {
buf: [u8; DISABLE_PAYOUT_COMMAND],
}

impl DisablePayoutCommand {
/// Creates a new [DisablePayoutCommand] message.
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; DISABLE_PAYOUT_COMMAND],
};

msg.init();
msg.set_command(MessageType::DisablePayout);

msg
}
}

impl_command_display!(DisablePayoutCommand);
impl_message_from_buf!(DisablePayoutCommand);
impl_message_ops!(DisablePayoutCommand);
impl_command_ops!(DisablePayoutCommand);
28 changes: 28 additions & 0 deletions src/disable_payout/response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::{len::DISABLE_PAYOUT_RESPONSE, message::MessageOps, MessageType};

/// DisablePayout - Response (0x09)
///
/// Represents a response to an [DisablePayoutCommand](crate::DisablePayoutCommand) message.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct DisablePayoutResponse {
buf: [u8; DISABLE_PAYOUT_RESPONSE],
}

impl DisablePayoutResponse {
/// Creates a new [DisablePayoutResponse] message.
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; DISABLE_PAYOUT_RESPONSE],
};

msg.init();

msg
}
}

impl_message_from_buf!(DisablePayoutResponse);
impl_message_ops!(DisablePayoutResponse, MessageType::DisablePayout);
impl_response_ops!(DisablePayoutResponse);
impl_response_display!(DisablePayoutResponse);
7 changes: 7 additions & 0 deletions src/enable_payout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Messages for enabling devices equipped with a `Smart Payout` module.

mod command;
mod response;

pub use command::*;
pub use response::*;
119 changes: 119 additions & 0 deletions src/enable_payout/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use crate::{len, std::fmt, CommandOps, MessageOps, MessageType};

mod index {
pub const PAYOUT_OPTION: usize = 4;
}

mod bitmask {
pub const OPTION: u8 = 0b11;
}

bitfield! {
/// Option byte for the [EnablePayoutCommand](crate::EnablePayoutCommand) message.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct EnablePayoutOption(u8);
u8;
/// Option bitfield zero, has different meaning based on device type.
///
/// - `nv11`: `GIVE_VALUE_ON_STORED` - set to enable the value of the note stored to be given
/// with the `Note Stored` event.
/// - `smart payout`: `REQUIRE_FULL_STARTUP` - if set, the `Smart Payout` will return busy
/// until it has fully completed the startup procedure.
pub field_0, set_field_0: 0;
/// Option bitfield one, has different meaning based on device type.
///
/// - `nv11`: `NO_HOLD_NOTE_ON_PAYOUT` - set to enable the function of fully rejecting the
/// dispensed banknote rather then holding it in the bezel.
/// - `smart payout`: `OPTIMISE_FOR_PAYIN_SPEED` - if set, the `Smart Payout` will always move
/// towards an empty slot when idle to try and ensure the shortest pay in speed possible.
pub field_1, set_field_1: 1;
}

impl From<u8> for EnablePayoutOption {
fn from(val: u8) -> Self {
Self(val & bitmask::OPTION)
}
}

impl From<&EnablePayoutOption> for u8 {
fn from(val: &EnablePayoutOption) -> Self {
val.0
}
}

impl From<EnablePayoutOption> for u8 {
fn from(val: EnablePayoutOption) -> Self {
(&val).into()
}
}

impl fmt::Display for EnablePayoutOption {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let f0 = self.field_0();
let f1 = self.field_1();

write!(f, r#"{{"field_0": {f0}, "field_1": {f1}}}"#)
}
}

/// EnablePayout - Command (0x5C)
///
/// A command to enable the attached payout device for storing/paying out notes.
///
/// A successful enable will return OK.
///
/// If there is a problem the reply will be generic response `COMMAND_CANNOT_BE_PROCESSED`, followed by an error code.
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct EnablePayoutCommand {
buf: [u8; len::ENABLE_PAYOUT_COMMAND],
}

impl EnablePayoutCommand {
/// Creates a new [EnablePayoutCommand] message.
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; len::ENABLE_PAYOUT_COMMAND],
};

msg.init();
msg.set_command(MessageType::EnablePayout);

msg
}

/// Gets the [EnablePayoutOption].
pub fn option(&self) -> EnablePayoutOption {
self.buf[index::PAYOUT_OPTION].into()
}

/// Sets the [EnablePayoutOption].
pub fn set_option(&mut self, option: EnablePayoutOption) {
self.buf[index::PAYOUT_OPTION] = option.into();
}

/// Builder function that sets the [EnablePayoutOption].
pub fn with_option(mut self, option: EnablePayoutOption) -> Self {
self.set_option(option);
self
}
}

impl_default!(EnablePayoutCommand);
impl_message_from_buf!(EnablePayoutCommand);
impl_message_ops!(EnablePayoutCommand);
impl_command_ops!(EnablePayoutCommand);

impl fmt::Display for EnablePayoutCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{")?;
write!(f, r#""stx": "0x{:02x}", "#, self.stx())?;
write!(f, r#""sequence_id": {}, "#, self.sequence_id())?;
write!(f, r#""len": "0x{:02x}", "#, self.data_len())?;
write!(f, r#""command": {}, "#, self.command())?;
write!(f, r#""option": {}, "#, self.option())?;
write!(f, r#""checksum": "0x{:04x}""#, self.checksum())?;
write!(f, "}}")
}
}
29 changes: 29 additions & 0 deletions src/enable_payout/response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::{len, MessageOps, MessageType};

/// EnablePayout - Response (0x5C)
///
/// Represents a response to an [EnablePayoutCommand](crate::EnablePayoutCommand) message.
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct EnablePayoutResponse {
buf: [u8; len::ENABLE_PAYOUT_RESPONSE],
}

impl EnablePayoutResponse {
/// Creates a new [EnablePayoutResponse] message.
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; len::ENABLE_PAYOUT_RESPONSE],
};

msg.init();

msg
}
}

impl_default!(EnablePayoutResponse);
impl_message_from_buf!(EnablePayoutResponse);
impl_message_ops!(EnablePayoutResponse, MessageType::EnablePayout);
impl_response_ops!(EnablePayoutResponse);
impl_response_display!(EnablePayoutResponse);
17 changes: 9 additions & 8 deletions src/encrypted/command.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#[cfg(not(test))]
use rand_chacha::rand_core::RngCore;
#[cfg(not(feature = "std"))]
#[cfg(all(not(test), not(feature = "std")))]
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};

#[cfg(not(feature = "std"))]
#[cfg(all(not(test), not(feature = "std")))]
use crate::seed;

use crate::{
Expand Down Expand Up @@ -147,6 +148,7 @@ impl EncryptedCommand {
}

// Less robust than using rand::thread_rng, but still better than PKCS#7 padding...
#[cfg(not(test))]
let mut rng = ChaCha20Rng::from_seed(seed(self.buf(), self.count_buf()));

let start = self.packing_start();
Expand Down Expand Up @@ -249,12 +251,11 @@ impl EncryptedCommand {
log::error!("error stuffing encrypted command message: {err}");
}

log::trace!("encryption sequence count: {}", super::sequence_count());
#[cfg(any(not(test), feature = "test-crypto"))]
log::trace!(
"next encryption sequence count: {}",
super::increment_sequence_count()
);
let count = super::sequence_count();
let next_count = super::increment_sequence_count();

log::trace!("encryption sequence count: {count}");
log::trace!("next encryption sequence count: {next_count}");

enc_msg
}
Expand Down
8 changes: 8 additions & 0 deletions src/len.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ pub const PAYOUT_BY_DENOMINATION_COMMAND: usize = MAX_MESSAGE;
pub const PAYOUT_BY_DENOMINATION_RESPONSE: usize = 6;
/// Length of a serialized [PayoutDenomination](crate::PayoutDenomination).
pub const PAYOUT_BLOCK: usize = 9;
/// EnablePayout Command full message length.
pub const ENABLE_PAYOUT_COMMAND: usize = 7;
/// EnablePayout Response full message length.
pub const ENABLE_PAYOUT_RESPONSE: usize = 6;
/// DisablePayout Command full message length.
pub const DISABLE_PAYOUT_COMMAND: usize = 6;
/// DisablePayout Response full message length.
pub const DISABLE_PAYOUT_RESPONSE: usize = 6;
/// Encrypted Command full message length.
///
/// Because encrypted messages have variable lengths, set the static length to maximum
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use core as std;
#[allow(clippy::single_component_path_imports)]
use std;

#[macro_use]
mod macros;

pub mod aes;
Expand All @@ -35,10 +36,12 @@ pub mod configure_bezel;
pub mod crc;
pub mod dataset_version;
pub mod disable;
pub mod disable_payout;
pub mod display_off;
pub mod display_on;
pub mod empty;
pub mod enable;
pub mod enable_payout;
pub mod encrypted;
pub mod encryption_reset;
pub mod error;
Expand Down Expand Up @@ -80,10 +83,12 @@ pub use channels::*;
pub use configure_bezel::*;
pub use dataset_version::*;
pub use disable::*;
pub use disable_payout::*;
pub use display_off::*;
pub use display_on::*;
pub use empty::*;
pub use enable::*;
pub use enable_payout::*;
pub use encrypted::*;
pub use encryption_reset::*;
pub use error::*;
Expand Down
Loading

0 comments on commit 3a0be1a

Please sign in to comment.