ssp_server/
device_handle.rs

1#![allow(dead_code)]
2
3use std::io::{Read, Write};
4#[cfg(feature = "jsonrpc")]
5use std::os::unix::net::UnixStream;
6use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering};
7use std::sync::Arc;
8use std::{thread, time};
9
10use crossbeam::channel;
11use parking_lot::{Mutex, MutexGuard};
12use serialport::TTYPort;
13
14#[cfg(feature = "jsonrpc")]
15use smol_jsonrpc::{Error as RpcError, Request, Response};
16
17#[cfg(feature = "jsonrpc")]
18use ssp::jsonrpc::{jsonrpc_id, set_jsonrpc_id};
19use ssp::{CommandOps, MessageOps, ResponseOps, Result};
20
21use crate::{continue_on_err, encryption_key};
22
23mod inner;
24
25/// Timeout for waiting for lock on a mutex (milliseconds).
26pub const LOCK_TIMEOUT_MS: u64 = 5_000;
27/// Timeout for waiting for serial communication (milliseconds).
28pub const SERIAL_TIMEOUT_MS: u64 = 10_000;
29/// Minimum polling interval between messages (milliseconds).
30pub const MIN_POLLING_MS: u64 = 500;
31/// Medium polling interval between messages (milliseconds).
32pub const MED_POLLING_MS: u64 = 650;
33/// Maximum polling interval between messages (milliseconds).
34#[allow(dead_code)]
35pub const MAX_POLLING_MS: u64 = 1_000;
36/// Timeout for retrieving an event from a queue (milliseconds)
37pub const QUEUE_TIMEOUT_MS: u64 = 50;
38/// Default serial connection BAUD rate (bps).
39pub const BAUD_RATE: u32 = 9_600;
40
41pub(crate) static SEQ_FLAG: AtomicBool = AtomicBool::new(false);
42static POLLING_INIT: AtomicBool = AtomicBool::new(false);
43
44static ESCROWED: AtomicBool = AtomicBool::new(false);
45static ESCROWED_AMOUNT: AtomicU32 = AtomicU32::new(0);
46
47static ENABLED: AtomicBool = AtomicBool::new(false);
48
49static CASHBOX_ATTACHED: AtomicBool = AtomicBool::new(true);
50
51// Time when a device reset was initiated.
52static RESET_TIME: AtomicU64 = AtomicU64::new(0);
53// Timeout for waiting for the device to reset (seconds).
54const RESET_TIMEOUT_SECS: u64 = 60;
55
56static PROTOCOL_VERSION: AtomicU8 = AtomicU8::new(6);
57
58static INTERACTIVE: AtomicBool = AtomicBool::new(false);
59
60static DISPENSING: AtomicBool = AtomicBool::new(false);
61
62static UNSAFE_JAM: AtomicBool = AtomicBool::new(false);
63
64pub(crate) fn sequence_flag() -> ssp::SequenceFlag {
65    SEQ_FLAG.load(Ordering::Relaxed).into()
66}
67
68pub(crate) fn set_sequence_flag(flag: ssp::SequenceFlag) {
69    SEQ_FLAG.store(flag.into(), Ordering::SeqCst);
70}
71
72// Whether the polling routine has started.
73fn polling_inited() -> bool {
74    POLLING_INIT.load(Ordering::Relaxed)
75}
76
77// Sets the flag indicating whether the polling routine started.
78fn set_polling_inited(inited: bool) {
79    POLLING_INIT.store(inited, Ordering::SeqCst);
80}
81
82pub(crate) fn escrowed() -> bool {
83    ESCROWED.load(Ordering::Relaxed)
84}
85
86pub(crate) fn set_escrowed(escrowed: bool) -> bool {
87    let last = ESCROWED.load(Ordering::Relaxed);
88    ESCROWED.store(escrowed, Ordering::SeqCst);
89    last
90}
91
92pub(crate) fn enabled() -> bool {
93    ENABLED.load(Ordering::Relaxed)
94}
95
96pub(crate) fn set_enabled(enabled: bool) {
97    ENABLED.store(enabled, Ordering::SeqCst);
98}
99
100pub(crate) fn escrowed_amount() -> ssp::ChannelValue {
101    ESCROWED_AMOUNT.load(Ordering::Relaxed).into()
102}
103
104pub(crate) fn set_escrowed_amount(amount: ssp::ChannelValue) -> ssp::ChannelValue {
105    let last = ssp::ChannelValue::from(ESCROWED_AMOUNT.load(Ordering::Relaxed));
106    ESCROWED_AMOUNT.store(amount.into(), Ordering::SeqCst);
107    last
108}
109
110/// Gets whether the csahboxed is attached to the device.
111pub fn cashbox_attached() -> bool {
112    CASHBOX_ATTACHED.load(Ordering::Relaxed)
113}
114
115/// Sets whether the csahboxed is attached to the device.
116pub fn set_cashbox_attached(attached: bool) -> bool {
117    let last = cashbox_attached();
118    CASHBOX_ATTACHED.store(attached, Ordering::SeqCst);
119    last
120}
121
122pub(crate) fn resetting() -> bool {
123    reset_time() != 0
124}
125
126pub(crate) fn reset_time() -> u64 {
127    RESET_TIME.load(Ordering::Relaxed)
128}
129
130pub(crate) fn set_reset_time(time: u64) -> u64 {
131    let last = reset_time();
132    RESET_TIME.store(time, Ordering::SeqCst);
133    last
134}
135
136pub(crate) fn protocol_version() -> ssp::ProtocolVersion {
137    PROTOCOL_VERSION.load(Ordering::Relaxed).into()
138}
139
140pub(crate) fn set_protocol_version(protocol: ssp::ProtocolVersion) -> ssp::ProtocolVersion {
141    let last = protocol_version();
142    PROTOCOL_VERSION.store(protocol.into(), Ordering::SeqCst);
143    last
144}
145
146pub(crate) fn interactive() -> bool {
147    INTERACTIVE.load(Ordering::Relaxed)
148}
149
150pub(crate) fn set_interactive(val: bool) -> bool {
151    let last = interactive();
152    INTERACTIVE.store(val, Ordering::SeqCst);
153    last
154}
155
156pub(crate) fn dispensing() -> bool {
157    DISPENSING.load(Ordering::Relaxed)
158}
159
160pub(crate) fn set_dispensing(val: bool) {
161    DISPENSING.store(val, Ordering::SeqCst);
162}
163
164pub(crate) fn unsafe_jam() -> bool {
165    UNSAFE_JAM.load(Ordering::Relaxed)
166}
167
168pub(crate) fn set_unsafe_jam(val: bool) {
169    UNSAFE_JAM.store(val, Ordering::SeqCst)
170}
171
172/// Polling interactivity mode.
173#[repr(u8)]
174#[derive(Clone, Copy, Debug, PartialEq)]
175pub enum PollMode {
176    /// Automically handle polling events.
177    Auto,
178    /// Interactively handle polling events.
179    Interactive,
180}
181
182/// Receiver end of the device-sent event queue.
183///
184/// Owner of the receiver can regularly attempt to pop events from the queue,
185/// and decide how to handle any returned event(s).
186///
187/// Example:
188///
189/// ```rust, no_run
190/// # use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
191/// # fn main() -> ssp::Result<()> {
192/// let stop_polling = Arc::new(AtomicBool::new(false));
193/// let poll_mode = ssp_server::PollMode::Interactive;
194///
195/// let mut handle = ssp_server::DeviceHandle::new("/dev/ttyUSB0")?;
196///
197/// let rx: ssp_server::PushEventReceiver = handle.start_background_polling_with_queue(
198///     Arc::clone(&stop_polling),
199///     poll_mode,
200/// )?;
201///
202/// // Pop events from the queue
203/// loop {
204///     while let Ok(event) = rx.pop_event() {
205///         log::debug!("Received an event: {event}");
206///         // do stuff in response to the event...
207///     }
208/// }
209/// # Ok(())
210/// # }
211/// ```
212pub struct PushEventReceiver(pub channel::Receiver<ssp::Event>);
213
214impl PushEventReceiver {
215    /// Creates a new [PushEventReceiver] from the provided `queue`.
216    pub fn new(queue: channel::Receiver<ssp::Event>) -> Self {
217        Self(queue)
218    }
219
220    /// Attempt to pop an event from the queue.
221    ///
222    /// Returns `Err(_)` if an event could not be retrieved before the timeout.
223    pub fn pop_event(&self) -> Result<ssp::Event> {
224        self.0
225            .recv_timeout(time::Duration::from_millis(QUEUE_TIMEOUT_MS))
226            .map_err(|_| ssp::Error::QueueTimeout)
227    }
228}
229
230/// Handle for communicating with a SSP-enabled device over serial.
231///
232/// ```no_run
233/// let _handle = ssp_server::DeviceHandle::new("/dev/ttyUSB0").unwrap();
234/// ```
235pub struct DeviceHandle {
236    serial_port: Arc<Mutex<TTYPort>>,
237    generator: ssp::GeneratorKey,
238    modulus: ssp::ModulusKey,
239    random: ssp::RandomKey,
240    fixed_key: ssp::FixedKey,
241    key: Arc<Mutex<Option<ssp::AesKey>>>,
242}
243
244impl DeviceHandle {
245    /// Creates a new [DeviceHandle] with a serial connection over the supplied serial device.
246    pub fn new(serial_path: &str) -> Result<Self> {
247        // For details on the following setup, see sections 5.4 & 7 in the SSP implementation guide
248        let serial_port = Arc::new(Mutex::new(
249            serialport::new(serial_path, BAUD_RATE)
250                // disable flow control serial lines
251                .flow_control(serialport::FlowControl::None)
252                // eight-bit data size
253                .data_bits(serialport::DataBits::Eight)
254                // no control bit parity
255                .parity(serialport::Parity::None)
256                // two bit stop
257                .stop_bits(serialport::StopBits::Two)
258                // serial device times out after 10 seconds, so do we
259                .timeout(time::Duration::from_millis(SERIAL_TIMEOUT_MS))
260                // get back a TTY port for POSIX systems, Windows is not supported
261                .open_native()?,
262        ));
263
264        let mut prime_gen = ssp::primes::Generator::from_entropy();
265
266        let mut generator = ssp::GeneratorKey::from_generator(&mut prime_gen);
267        let mut modulus = ssp::ModulusKey::from_generator(&mut prime_gen);
268
269        // Modulus key must be smaller than the Generator key
270        let mod_inner = modulus.as_inner();
271        let gen_inner = generator.as_inner();
272
273        if gen_inner > mod_inner {
274            modulus = gen_inner.into();
275            generator = mod_inner.into();
276        }
277
278        let random = ssp::RandomKey::from_entropy();
279        let fixed_key = ssp::FixedKey::from_inner(ssp::DEFAULT_FIXED_KEY_U64);
280        let key = Arc::new(Mutex::new(None));
281
282        Ok(Self {
283            serial_port,
284            generator,
285            modulus,
286            random,
287            fixed_key,
288            key,
289        })
290    }
291
292    /// Starts background polling routine to regularly send [PollCommand] messages to the device.
293    ///
294    /// **Args**
295    ///
296    /// - `stop_polling`: used to control when the polling routine should stop sending polling messages.
297    ///
298    /// If background polling has already started, the function just returns.
299    ///
300    /// Example:
301    ///
302    /// ```rust, no_run
303    /// # use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
304    /// # fn main() -> ssp::Result<()> {
305    /// let stop_polling = Arc::new(AtomicBool::new(false));
306    ///
307    /// let handle = ssp_server::DeviceHandle::new("/dev/ttyUSB0")?;
308    ///
309    /// handle.start_background_polling(Arc::clone(&stop_polling))?;
310    /// # Ok(())
311    /// # }
312    /// ```
313    pub fn start_background_polling(&self, stop_polling: Arc<AtomicBool>) -> Result<()> {
314        if polling_inited() {
315            Err(ssp::Error::PollingReinit)
316        } else {
317            // Set the global flag to disallow multiple background polling threads.
318            set_polling_inited(true);
319
320            let serial_port = Arc::clone(&self.serial_port);
321            let end_polling = Arc::clone(&stop_polling);
322            let key = Arc::clone(&self.key);
323
324            thread::spawn(move || -> Result<()> {
325                let mut now = time::Instant::now();
326
327                while !end_polling.load(Ordering::Relaxed) {
328                    if now.elapsed().as_millis() > MED_POLLING_MS as u128 {
329                        now = time::Instant::now();
330
331                        if resetting() {
332                            continue;
333                        }
334
335                        if unsafe_jam() {
336                            log::debug!("Unsafe jam detected, resetting device...");
337                            let mut locked_port = continue_on_err!(
338                                Self::lock_serial_port(&serial_port),
339                                "Failed to lock serial port in background polling routine"
340                            );
341                            let mut message = ssp::ResetCommand::new();
342                            continue_on_err!(
343                                Self::poll_message_variant(&mut locked_port, &mut message),
344                                "Failed to reset device"
345                            );
346                            // Wait for device to reset
347                            thread::sleep(time::Duration::from_secs(15));
348                            set_unsafe_jam(false);
349                            continue;
350                        }
351
352                        let mut locked_port = continue_on_err!(
353                            Self::lock_serial_port(&serial_port),
354                            "Failed to lock serial port in background polling routine"
355                        );
356                        let key = continue_on_err!(
357                            Self::lock_encryption_key(&key),
358                            "Failed to lock encryption key in background polling routine"
359                        );
360
361                        let mut message = ssp::PollCommand::new();
362
363                        let res = if let Some(key) = key.as_ref() {
364                            continue_on_err!(
365                                Self::poll_encrypted_message(&mut locked_port, &mut message, key),
366                                "Failed poll command in background polling routine"
367                            )
368                        } else {
369                            continue_on_err!(
370                                Self::poll_message_variant(&mut locked_port, &mut message),
371                                "Failed poll command in background polling routine"
372                            )
373                        };
374
375                        let status = res.as_response().response_status();
376
377                        if status.is_ok() {
378                            let poll_res = continue_on_err!(
379                                res.into_poll_response(),
380                                "Failed to convert poll response in background polling routine"
381                            );
382                            let last_statuses = poll_res.last_response_statuses();
383
384                            log::debug!("Successful poll command, last statuses: {last_statuses}");
385                        } else if status == ssp::ResponseStatus::UnsafeJam {
386                            log::error!("Unsafe Jam detected! Please remove the jam from the device. Attempting an automatic device reset...");
387                            set_unsafe_jam(true);
388                        } else {
389                            log::warn!("Failed poll command, response status: {status}");
390                        }
391                    }
392
393                    thread::sleep(time::Duration::from_millis(MED_POLLING_MS / 3));
394                }
395
396                // Now that polling finished, reset the flag to allow another background routine to
397                // start.
398                set_polling_inited(false);
399
400                Ok(())
401            });
402
403            set_polling_inited(false);
404
405            Ok(())
406        }
407    }
408
409    /// Starts background polling routine to regularly send [PollCommand] messages to the device,
410    /// with an additional event queue for sending push events from the device to the host.
411    ///
412    /// **Args**
413    ///
414    /// - `stop_polling`: used to control when the polling routine should stop sending polling messages.
415    ///
416    /// If background polling has already started, the function just returns.
417    ///
418    /// Returns an event queue receiver that the caller can use to receive device-sent events.
419    ///
420    /// Example:
421    ///
422    /// ```rust, no_run
423    /// # use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
424    /// # fn main() -> ssp::Result<()> {
425    /// let stop_polling = Arc::new(AtomicBool::new(false));
426    /// let poll_mode = ssp_server::PollMode::Interactive;
427    ///
428    /// let handle = ssp_server::DeviceHandle::new("/dev/ttyUSB0")?;
429    ///
430    /// let rx = handle.start_background_polling_with_queue(
431    ///     Arc::clone(&stop_polling),
432    ///     poll_mode,
433    /// )?;
434    ///
435    /// // Pop events from the queue
436    /// loop {
437    ///     while let Ok(event) = rx.pop_event() {
438    ///         log::debug!("Received an event: {event}");
439    ///         // do stuff in response to the event...
440    ///     }
441    /// }
442    /// # Ok(())
443    /// # }
444    /// ```
445    pub fn start_background_polling_with_queue(
446        &self,
447        stop_polling: Arc<AtomicBool>,
448        poll_mode: PollMode,
449    ) -> Result<PushEventReceiver> {
450        if polling_inited() {
451            Err(ssp::Error::PollingReinit)
452        } else {
453            // Set the global flag to disallow multiple background polling threads.
454            set_polling_inited(true);
455
456            if poll_mode == PollMode::Interactive {
457                set_interactive(true);
458            }
459
460            let serial_port = Arc::clone(&self.serial_port);
461            let end_polling = Arc::clone(&stop_polling);
462            let key = Arc::clone(&self.key);
463
464            let (tx, rx) = channel::unbounded();
465
466            thread::spawn(move || -> Result<()> {
467                let mut now = time::Instant::now();
468
469                while !end_polling.load(Ordering::Relaxed) {
470                    if now.elapsed().as_millis() >= MIN_POLLING_MS as u128 {
471                        now = time::Instant::now();
472
473                        if resetting() {
474                            thread::sleep(time::Duration::from_secs(1));
475                            continue;
476                        }
477
478                        if unsafe_jam() {
479                            log::debug!("Unsafe jam detected, resetting device...");
480                            let mut locked_port = continue_on_err!(
481                                Self::lock_serial_port(&serial_port),
482                                "Failed to lock serial port in background polling routine"
483                            );
484                            let mut message = ssp::ResetCommand::new();
485                            continue_on_err!(
486                                Self::poll_message_variant(&mut locked_port, &mut message),
487                                "Failed to reset device"
488                            );
489                            // Wait for device to reset
490                            thread::sleep(time::Duration::from_secs(15));
491                            set_unsafe_jam(false);
492                            continue;
493                        }
494
495                        let mut locked_port = continue_on_err!(
496                            Self::lock_serial_port(&serial_port),
497                            "Failed to lock serial port in background polling routine"
498                        );
499
500                        let key = continue_on_err!(
501                            Self::lock_encryption_key(&key),
502                            "Failed to lock encryption key in background polling routine"
503                        );
504
505                        if escrowed() {
506                            // Do not automatically poll when device has a bill in escrow,
507                            // and the user is in interactive mode.
508                            //
509                            // Sending a poll with bill in escrow stacks the bill.
510                            //
511                            // Sit in a busy loop until the user sends a stack/reject command.
512
513                            // Send hold command to keep note in escrow until `stack` or `reject`
514                            // is sent.
515
516                            let mut message = ssp::HoldCommand::new();
517
518                            continue_on_err!(
519                                Self::poll_message(&mut locked_port, &mut message, key.as_ref()),
520                                "Failed hold command"
521                            );
522
523                            thread::sleep(time::Duration::from_millis(MIN_POLLING_MS));
524
525                            continue;
526                        }
527
528                        if dispensing() {
529                            // Do not automatically poll when device is dispensing notes
530                            thread::sleep(time::Duration::from_millis(MIN_POLLING_MS));
531
532                            continue;
533                        }
534
535                        let mut message = ssp::PollCommand::new();
536
537                        let res = continue_on_err!(
538                            Self::poll_message(&mut locked_port, &mut message, key.as_ref()),
539                            "Failed poll command"
540                        );
541
542                        let status = res.as_response().response_status();
543                        if status.is_ok() {
544                            let poll_res = continue_on_err!(
545                                res.into_poll_response(),
546                                "Failed to convert poll response in background polling routine"
547                            );
548
549                            Self::parse_events(&poll_res, &tx)?;
550                        } else if status.to_u8() == 0 {
551                            log::info!("Device returned a null response: {}", res.as_response());
552                            log::trace!("Response data: {:x?}", res.as_response().buf());
553                        } else if status == ssp::ResponseStatus::UnsafeJam {
554                            log::error!("Unsafe Jam detected! Please remove the jam from the device. Attempting an automatic device reset...");
555                            set_unsafe_jam(true);
556                        } else {
557                            log::warn!("Failed poll command, response status: {status}");
558                        }
559                    }
560
561                    thread::sleep(time::Duration::from_millis(MIN_POLLING_MS));
562                }
563
564                // Now that polling finished, reset the flag to allow another background routine to
565                // start.
566                set_polling_inited(false);
567
568                Ok(())
569            });
570
571            set_polling_inited(false);
572
573            Ok(PushEventReceiver::new(rx))
574        }
575    }
576
577    fn poll_resetting(
578        serial_port: &mut TTYPort,
579        key: Option<&ssp::AesKey>,
580        tx: Option<&channel::Sender<ssp::Event>>,
581    ) -> Result<()> {
582        use std::ops::Sub;
583
584        let reset_time = time::Instant::now().sub(time::Duration::from_secs(reset_time()));
585        let mut message = ssp::PollCommand::new();
586
587        while (1..RESET_TIMEOUT_SECS).contains(&reset_time.elapsed().as_secs()) {
588            let elapsed = reset_time.elapsed().as_secs();
589            let res = continue_on_err!(
590                Self::poll_message(serial_port, &mut message, key),
591                format!("Device is still resetting, elapsed time: {elapsed}")
592            );
593            if res.as_response().response_status().is_ok() {
594                set_reset_time(0);
595
596                if let Some(tx) = tx {
597                    continue_on_err!(
598                        tx.send(ssp::Event::from(ssp::ResetEvent::new())),
599                        "Failed to send Reset event"
600                    );
601                }
602
603                break;
604            }
605        }
606
607        Ok(())
608    }
609
610    #[cfg(feature = "jsonrpc")]
611    pub fn on_message(&mut self, stream: &mut UnixStream) -> Result<ssp::Method> {
612        stream.set_nonblocking(true)?;
613
614        let mut message_buf = vec![0u8; 1024];
615        let mut idx = 0;
616
617        while let Ok(ret) = stream.read(&mut message_buf) {
618            if ret == 0 {
619                // Client hung up the socket, so let the caller know to shutdown the stream
620                return Ok(ssp::Method::Shutdown);
621            }
622
623            if idx >= message_buf.len() {
624                message_buf.resize(2 * message_buf.len(), 0u8);
625            }
626
627            idx += ret;
628
629            if message_buf.contains(&b'\n') {
630                break;
631            }
632        }
633
634        let message_string = std::str::from_utf8(message_buf[..idx].as_ref()).unwrap_or("");
635        if message_string.is_empty() || message_string.contains("ready") {
636            return Ok(ssp::Method::Enable);
637        }
638
639        for message in message_string.split('\n') {
640            if !message.is_empty() {
641                log::debug!("Received message: {message}");
642
643                let message = match serde_json::from_str::<Request>(message) {
644                    Ok(msg) => msg,
645                    Err(err) => {
646                        log::warn!("Expected valid JSON-RPC request, error: {err}");
647                        continue;
648                    }
649                };
650
651                log::debug!("Message: {message:?}");
652                let event = ssp::Event::from(&message);
653                let method = event.method();
654                log::debug!("Message method: {method}");
655
656                let jsonrpc_id = message.id().unwrap_or(jsonrpc_id());
657                set_jsonrpc_id(jsonrpc_id);
658
659                match method {
660                    ssp::Method::Accept => self.on_enable(stream, &event)?,
661                    ssp::Method::Stop => self.on_disable(stream, &event)?,
662                    ssp::Method::Enable => self.on_enable_payout(stream, &event)?,
663                    ssp::Method::Disable => self.on_disable_payout(stream, &event)?,
664                    ssp::Method::Reject => self.on_reject(stream, &event)?,
665                    ssp::Method::Stack => self.on_stack(stream, &event)?,
666                    ssp::Method::StackerFull => self.on_stacker_full(stream, &event)?,
667                    ssp::Method::Status => self.on_status(stream, &event)?,
668                    ssp::Method::Reset => self.on_reset(stream, &event)?,
669                    ssp::Method::Dispense => self.on_dispense(stream, &event)?,
670                    _ => return Err(ssp::Error::JsonRpc("unsupported method".into())),
671                }
672
673                return Ok(method);
674            }
675        }
676
677        Ok(ssp::Method::Disable)
678    }
679
680    /// Message handler for [Disable](ssp::Event::DisableEvent) events.
681    ///
682    /// Exposed to help with creating a custom message handler.
683    #[cfg(feature = "jsonrpc")]
684    pub fn on_disable(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
685        self.disable()?;
686
687        let mut res = Response::from(ssp::Event::from(ssp::DisableEvent::new()));
688        res.set_id(jsonrpc_id());
689
690        let res_str = serde_json::to_string(&res)? + "\n";
691
692        stream.write_all(res_str.as_bytes())?;
693
694        Ok(())
695    }
696
697    /// Message handler for [Disable](ssp::Event::DisableEvent) events.
698    ///
699    /// Exposed to help with creating a custom message handler.
700    #[cfg(feature = "jsonrpc")]
701    pub fn on_disable_payout(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
702        self.disable_payout()?;
703
704        let mut res = Response::from(ssp::Event::from(ssp::DisableEvent::new()));
705        res.set_id(jsonrpc_id());
706
707        let res_str = serde_json::to_string(&res)? + "\n";
708
709        stream.write_all(res_str.as_bytes())?;
710
711        Ok(())
712    }
713
714    /// Message handler for [Enable](ssp::Event::EnableEvent) events.
715    ///
716    /// Exposed to help with creating a custom message handler.
717    #[cfg(feature = "jsonrpc")]
718    pub fn on_enable(&self, stream: &mut UnixStream, event: &ssp::Event) -> Result<()> {
719        // perform full init sequence,
720        // only sending EnableCommand does not bring the device online...
721        let enable_event = ssp::EnableEvent::try_from(event)?;
722        self.enable()?;
723
724        let mut res = Response::from(ssp::Event::from(enable_event));
725        res.set_id(jsonrpc_id());
726
727        let res_str = serde_json::to_string(&res)? + "\n";
728
729        stream.write_all(res_str.as_bytes())?;
730
731        Ok(())
732    }
733
734    /// Message handler for [Enable](ssp::Event::EnableEvent) events.
735    ///
736    /// Exposed to help with creating a custom message handler.
737    #[cfg(feature = "jsonrpc")]
738    pub fn on_enable_payout(&self, stream: &mut UnixStream, event: &ssp::Event) -> Result<()> {
739        // perform full init sequence,
740        // only sending EnableCommand does not bring the device online...
741        let enable_event = ssp::EnableEvent::try_from(event)?;
742        self.enable_payout()?;
743
744        let mut res = Response::from(ssp::Event::from(enable_event));
745        res.set_id(jsonrpc_id());
746
747        let res_str = serde_json::to_string(&res)? + "\n";
748
749        stream.write_all(res_str.as_bytes())?;
750
751        Ok(())
752    }
753
754    /// Message handler for [Reject](ssp::Event::RejectEvent) events.
755    ///
756    /// Exposed to help with creating a custom message handler.
757    #[cfg(feature = "jsonrpc")]
758    pub fn on_reject(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
759        self.reject()?;
760
761        let mut res = Response::from(ssp::Event::from(ssp::RejectEvent::new()));
762        res.set_id(jsonrpc_id());
763
764        let mut res_str = serde_json::to_string(&res)?;
765        res_str += "\n";
766
767        stream.write_all(res_str.as_bytes())?;
768
769        Ok(())
770    }
771
772    /// Message handler for [Stack](ssp::Event::StackEvent) events.
773    ///
774    /// Exposed to help with creating a custom message handler.
775    #[cfg(feature = "jsonrpc")]
776    pub fn on_stack(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
777        let value = self.stack()?;
778
779        let mut res = Response::from(ssp::Event::from(ssp::StackEvent::from(value)));
780        res.set_id(jsonrpc_id());
781
782        let mut res_str = serde_json::to_string(&res)?;
783        res_str += "\n";
784
785        stream.write_all(res_str.as_bytes())?;
786
787        Ok(())
788    }
789
790    /// Message handler for [StackerFull](ssp::Event::StackerFullEvent) events.
791    ///
792    /// Exposed to help with creating a custom message handler.
793    #[cfg(feature = "jsonrpc")]
794    pub fn on_stacker_full(&self, _stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
795        Err(ssp::Error::JsonRpc(
796            "StackerFull handler unimplemented".into(),
797        ))
798    }
799
800    /// Message handler for [Status](ssp::Event::StatusEvent) events.
801    ///
802    /// Exposed to help with creating a custom message handler.
803    #[cfg(feature = "jsonrpc")]
804    pub fn on_status(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
805        let (data, dataset_version) = {
806            let mut serial_port = self.serial_port()?;
807            let key = self.encryption_key()?;
808
809            log::trace!(
810                "full status: {}",
811                self.setup_request_inner(&mut serial_port, key.as_ref())?
812            );
813
814            (
815                self.unit_data_inner(&mut serial_port, key.as_ref())?,
816                Self::dataset_version_inner(&mut serial_port, key.as_ref())?,
817            )
818        };
819
820        let cashbox_attached = cashbox_attached();
821        let status = ssp::DeviceStatus::from(data)
822            .with_dataset_version(dataset_version.dataset_version()?)
823            .with_cashbox_attached(cashbox_attached);
824
825        let event = if cashbox_attached {
826            ssp::StatusEvent::new(status)
827        } else {
828            ssp::StatusEvent::new(status.with_response_status(ssp::ResponseStatus::CashboxRemoved))
829        };
830
831        let mut res = Response::from(ssp::Event::from(event));
832        res.set_id(jsonrpc_id());
833
834        let res_str = serde_json::to_string(&res)? + "\n";
835
836        stream.write_all(res_str.as_bytes())?;
837
838        Ok(())
839    }
840
841    /// Message handler for [Status](ssp::Event::StatusEvent) events.
842    ///
843    /// Exposed to help with creating a custom message handler.
844    #[cfg(feature = "jsonrpc")]
845    pub fn on_reset(&self, stream: &mut UnixStream, _event: &ssp::Event) -> Result<()> {
846        match self.full_reset() {
847            Ok(_) => {
848                let res =
849                    Response::from(ssp::Event::from(ssp::ResetEvent::new())).with_id(jsonrpc_id());
850
851                let res_str = serde_json::to_string(&res)? + "\n";
852
853                log::debug!("Successfully reset device: {res_str}");
854
855                stream.write_all(res_str.as_bytes())?;
856
857                Ok(())
858            }
859            Err(err) => Err(err),
860        }
861    }
862
863    /// Performs the full reset protocol to restart a device.
864    pub fn full_reset(&self) -> Result<()> {
865        use serialport::SerialPort;
866
867        self.reset()?;
868
869        let now = time::Instant::now();
870
871        // Wait a bit for the device to reset, and re-open the port.
872        thread::sleep(time::Duration::from_secs(20));
873
874        let mut serial_port = self.serial_port()?;
875        // Clear the serial port to simulate closing and opening the port
876        serial_port.clear(serialport::ClearBuffer::All)?;
877
878        while now.elapsed().as_secs() < RESET_TIMEOUT_SECS {
879            if let Ok(res) = self.sync_inner(&mut serial_port, None) {
880                if res.response_status().is_ok() {
881                    set_reset_time(0);
882
883                    if let Err(err) =
884                        self.enable_device_inner(&mut serial_port, protocol_version(), None)
885                    {
886                        log::error!("Error enabling device after reset: {err}");
887                    }
888
889                    if interactive() {
890                        // if the server is running in interactive mode, disable until the client
891                        // re-enables the device.
892                        if let Err(err) = self.disable_inner(&mut serial_port, None) {
893                            log::error!("Error disabling device after reset: {err}");
894                        }
895                    }
896
897                    let poll_res = self.poll_inner(&mut serial_port, None)?;
898                    if poll_res.response_status().is_ok() {
899                        log::debug!("Successfully reset device");
900
901                        return Ok(());
902                    } else {
903                        return Err(ssp::Error::InvalidStatus((
904                            poll_res.response_status(),
905                            ssp::ResponseStatus::Ok,
906                        )));
907                    }
908                }
909            }
910        }
911
912        Err(ssp::Error::JsonRpc("failed to reset device".into()))
913    }
914
915    /// Gets whether the device is currently dispensing notes.
916    pub fn dispensing(&self) -> bool {
917        dispensing()
918    }
919
920    /// Message handle for dispense request using a
921    /// [PayoutDenominationList](ssp::PayoutDenominationList).
922    ///
923    /// User is responsible for parsing a request into a valid list.
924    ///
925    /// Exposed to help with creating a custom message handler.
926    #[cfg(feature = "jsonrpc")]
927    pub fn on_dispense(&self, stream: &mut UnixStream, event: &ssp::Event) -> Result<()> {
928        log::trace!("Dispense event: {event:?}");
929
930        let payload = event.payload();
931        log::trace!("PayoutByDenomination payload: {payload}");
932
933        let inner_event = payload.as_dispense_event()?;
934        log::trace!("PayoutByDenomination event: {inner_event}");
935
936        let payout_denom = inner_event.as_inner();
937        log::trace!("PayoutByDenomination request: {payout_denom}");
938
939        let mut serial_port = self.serial_port()?;
940        let key_guard = self.encryption_key()?;
941        let key = key_guard.as_ref();
942
943        self.enable_inner(&mut serial_port, key)?;
944        self.enable_payout_inner(&mut serial_port, key)?;
945
946        set_dispensing(true);
947
948        let mut payout =
949            ssp::PayoutByDenominationCommand::new().with_payout_denominations(payout_denom);
950
951        let res = if let Err(err) =
952            self.payout_by_denomination_inner(&mut serial_port, &mut payout, key)
953        {
954            Response::new()
955                .with_id(jsonrpc_id())
956                .with_error(RpcError::new().with_message(format!("{err}").as_str()))
957        } else {
958            Response::new().with_id(jsonrpc_id())
959        };
960
961        self.disable_payout_inner(&mut serial_port, key)?;
962        self.disable_inner(&mut serial_port, key)?;
963
964        set_dispensing(false);
965
966        let res_str = serde_json::to_string(&res)? + "\n";
967
968        stream.write_all(res_str.as_bytes())?;
969
970        Ok(())
971    }
972
973    /// Acquires a lock on the serial port used for communication with the acceptor device.
974    pub fn serial_port(&self) -> Result<MutexGuard<'_, TTYPort>> {
975        Self::lock_serial_port(&self.serial_port)
976    }
977
978    pub(crate) fn lock_serial_port(
979        serial_port: &Arc<Mutex<TTYPort>>,
980    ) -> Result<MutexGuard<'_, TTYPort>> {
981        serial_port
982            .try_lock_for(time::Duration::from_millis(SERIAL_TIMEOUT_MS))
983            .ok_or(ssp::Error::SerialPort(
984                "timed out locking serial port".into(),
985            ))
986    }
987
988    /// Acquires a lock on the AES encryption key.
989    pub fn encryption_key(&self) -> Result<MutexGuard<'_, Option<ssp::AesKey>>> {
990        Self::lock_encryption_key(&self.key)
991    }
992
993    pub(crate) fn lock_encryption_key(
994        key: &Arc<Mutex<Option<ssp::AesKey>>>,
995    ) -> Result<MutexGuard<'_, Option<ssp::AesKey>>> {
996        key.try_lock_for(time::Duration::from_millis(LOCK_TIMEOUT_MS))
997            .ok_or(ssp::Error::Io("timed out locking encryption key".into()))
998    }
999
1000    /// Creates a new [GeneratorKey](ssp::GeneratorKey) from system entropy.
1001    pub fn new_generator_key(&mut self) {
1002        self.generator = ssp::GeneratorKey::from_entropy();
1003        self.reset_key();
1004    }
1005
1006    /// Creates a new [ModulusKey](ssp::ModulusKey) from system entropy.
1007    pub fn new_modulus_key(&mut self) {
1008        let mut modulus = ssp::ModulusKey::from_entropy();
1009
1010        // Modulus key must be smaller than the Generator key
1011        let gen_inner = self.generator.as_inner();
1012        let mod_inner = modulus.as_inner();
1013
1014        if gen_inner < mod_inner {
1015            self.generator = mod_inner.into();
1016            modulus = gen_inner.into();
1017        }
1018
1019        self.modulus = modulus;
1020
1021        self.reset_key();
1022    }
1023
1024    /// Creates a new [RandomKey](ssp::RandomKey) from system entropy.
1025    pub fn new_random_key(&mut self) {
1026        self.random = ssp::RandomKey::from_entropy();
1027        self.reset_key();
1028    }
1029
1030    fn generator_key(&self) -> &ssp::GeneratorKey {
1031        &self.generator
1032    }
1033
1034    fn modulus_key(&self) -> &ssp::ModulusKey {
1035        &self.modulus
1036    }
1037
1038    fn random_key(&self) -> &ssp::RandomKey {
1039        &self.random
1040    }
1041
1042    fn set_key(&mut self, inter_key: ssp::IntermediateKey) -> Result<()> {
1043        let mut key = self.encryption_key()?;
1044
1045        let mut new_key = ssp::AesKey::from(&self.fixed_key);
1046        let enc_key =
1047            ssp::EncryptionKey::from_keys(&inter_key, self.random_key(), self.modulus_key());
1048
1049        new_key[8..].copy_from_slice(enc_key.as_inner().to_le_bytes().as_ref());
1050
1051        key.replace(new_key);
1052
1053        Ok(())
1054    }
1055
1056    /// Resets the Encryption key to none, requires a new key negotiation before performing eSSP
1057    /// operations.
1058    pub fn reset_key(&mut self) -> Option<ssp::AesKey> {
1059        if let Ok(mut key) = self.encryption_key() {
1060            key.take()
1061        } else {
1062            None
1063        }
1064    }
1065
1066    fn status_res(res: &dyn ssp::ResponseOps) -> Result<()> {
1067        let status = res.response_status();
1068        if status.is_ok() {
1069            Ok(())
1070        } else {
1071            Err(ssp::Error::Status(status))
1072        }
1073    }
1074
1075    /// Performs key negotiation to start a new eSSP session.
1076    ///
1077    /// Uses currently set [GeneratorKey] and [ModulusKey].
1078    pub fn negotiate_key(&mut self) -> Result<()> {
1079        Self::status_res(&self.sync()?)?;
1080        Self::status_res(&self.set_generator()?)?;
1081        Self::status_res(&self.set_modulus()?)?;
1082        Self::status_res(&self.request_key_exchange()?)?;
1083
1084        Ok(())
1085    }
1086
1087    /// Renegotiates the encryption key for a new eSSP session.
1088    pub fn renegotiate_key(&mut self) -> Result<()> {
1089        self.new_generator_key();
1090        self.new_modulus_key();
1091        self.new_random_key();
1092
1093        ssp::reset_sequence_count();
1094
1095        self.negotiate_key()
1096    }
1097
1098    /// Sends a command to stack a bill in escrow.
1099    pub fn stack(&self) -> Result<ssp::ChannelValue> {
1100        let mut serial_port = self.serial_port()?;
1101
1102        let mut message = ssp::PollCommand::new();
1103        let res = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1104
1105        let status = res.as_response().response_status();
1106        if status.is_ok() {
1107            set_escrowed(false);
1108            Ok(set_escrowed_amount(ssp::ChannelValue::default()))
1109        } else {
1110            Err(ssp::Error::InvalidStatus((status, ssp::ResponseStatus::Ok)))
1111        }
1112    }
1113
1114    /// Send a [SetInhibitsCommand](ssp::SetInhibitsCommand) message to the device.
1115    ///
1116    /// No response is returned.
1117    ///
1118    /// The caller should wait a reasonable amount of time for the device
1119    /// to come back online before sending additional messages.
1120    pub fn set_inhibits(
1121        &self,
1122        enable_list: ssp::EnableBitfieldList,
1123    ) -> Result<ssp::SetInhibitsResponse> {
1124        let mut serial_port = self.serial_port()?;
1125        self.set_inhibits_inner(&mut serial_port, enable_list, encryption_key!(self))
1126    }
1127
1128    fn set_inhibits_inner(
1129        &self,
1130        serial_port: &mut TTYPort,
1131        enable_list: ssp::EnableBitfieldList,
1132        key: Option<&ssp::AesKey>,
1133    ) -> Result<ssp::SetInhibitsResponse> {
1134        let mut message = ssp::SetInhibitsCommand::new();
1135        message.set_inhibits(enable_list)?;
1136
1137        let res = Self::poll_message(serial_port, &mut message, key)?;
1138
1139        res.into_set_inhibits_response()
1140    }
1141
1142    /// Send a [ResetCommand](ssp::ResetCommand) message to the device.
1143    ///
1144    /// No response is returned.
1145    ///
1146    /// The caller should wait a reasonable amount of time for the device
1147    /// to come back online before sending additional messages.
1148    pub fn reset(&self) -> Result<()> {
1149        let mut serial_port = self.serial_port()?;
1150
1151        let mut message = ssp::ResetCommand::new();
1152
1153        Self::set_message_sequence_flag(&mut message);
1154
1155        serial_port.write_all(message.as_bytes())?;
1156
1157        set_reset_time(
1158            time::SystemTime::now()
1159                .duration_since(time::UNIX_EPOCH)?
1160                .as_secs(),
1161        );
1162
1163        Ok(())
1164    }
1165
1166    /// Send a [PollCommand](ssp::PollCommand) message to the device.
1167    pub fn poll(&self) -> Result<ssp::PollResponse> {
1168        let mut serial_port = self.serial_port()?;
1169
1170        self.poll_inner(&mut serial_port, encryption_key!(self))
1171    }
1172
1173    fn poll_inner(
1174        &self,
1175        serial_port: &mut TTYPort,
1176        key: Option<&ssp::AesKey>,
1177    ) -> Result<ssp::PollResponse> {
1178        let mut message = ssp::PollCommand::new();
1179
1180        Self::set_message_sequence_flag(&mut message);
1181
1182        let response = Self::poll_message(serial_port, &mut message, key)?;
1183
1184        response.into_poll_response()
1185    }
1186
1187    /// Send a [PollWithAckCommand](ssp::PollWithAckCommand) message to the device.
1188    pub fn poll_with_ack(&self) -> Result<ssp::PollWithAckResponse> {
1189        let mut serial_port = self.serial_port()?;
1190
1191        let mut message = ssp::PollWithAckCommand::new();
1192
1193        Self::set_message_sequence_flag(&mut message);
1194
1195        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1196
1197        response.into_poll_with_ack_response()
1198    }
1199
1200    /// Send a [EventAckCommand](ssp::EventAckCommand) message to the device.
1201    pub fn event_ack(&self) -> Result<ssp::EventAckResponse> {
1202        let mut serial_port = self.serial_port()?;
1203
1204        let mut message = ssp::EventAckCommand::new();
1205
1206        Self::set_message_sequence_flag(&mut message);
1207
1208        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1209
1210        response.into_event_ack_response()
1211    }
1212
1213    /// Send a [RejectCommand](ssp::RejectCommand) message to the device.
1214    pub fn reject(&self) -> Result<ssp::RejectResponse> {
1215        let mut serial_port = self.serial_port()?;
1216
1217        let mut message = ssp::RejectCommand::new();
1218
1219        Self::set_message_sequence_flag(&mut message);
1220
1221        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1222
1223        let res = response.into_reject_response()?;
1224
1225        let status = res.response_status();
1226
1227        if status.is_ok() {
1228            set_escrowed(false);
1229            set_escrowed_amount(ssp::ChannelValue::default());
1230
1231            Ok(res)
1232        } else {
1233            Err(ssp::Error::InvalidStatus((status, ssp::ResponseStatus::Ok)))
1234        }
1235    }
1236
1237    /// Send a [SyncCommand](ssp::SyncCommand) message to the device.
1238    pub fn sync(&self) -> Result<ssp::SyncResponse> {
1239        let mut serial_port = self.serial_port()?;
1240
1241        self.sync_inner(&mut serial_port, encryption_key!(self))
1242    }
1243
1244    fn sync_inner(
1245        &self,
1246        serial_port: &mut TTYPort,
1247        key: Option<&ssp::AesKey>,
1248    ) -> Result<ssp::SyncResponse> {
1249        let mut message = ssp::SyncCommand::new();
1250
1251        set_sequence_flag(ssp::SequenceFlag::from(1));
1252
1253        let response = Self::poll_message(serial_port, &mut message, key)?;
1254
1255        set_sequence_flag(ssp::SequenceFlag::from(0));
1256
1257        response.into_sync_response()
1258    }
1259
1260    /// Starts the device by performing the full initialization sequence.
1261    pub fn enable_device(
1262        &self,
1263        protocol_version: ssp::ProtocolVersion,
1264    ) -> Result<ssp::EnableResponse> {
1265        let mut serial_port = self.serial_port()?;
1266
1267        self.enable_device_inner(&mut serial_port, protocol_version, encryption_key!(self))
1268    }
1269
1270    fn enable_device_inner(
1271        &self,
1272        serial_port: &mut TTYPort,
1273        protocol_version: ssp::ProtocolVersion,
1274        key: Option<&ssp::AesKey>,
1275    ) -> Result<ssp::EnableResponse> {
1276        self.host_protocol_version_inner(serial_port, protocol_version, key)?;
1277        set_protocol_version(protocol_version);
1278
1279        let status = self.setup_request_inner(serial_port, key)?;
1280        log::trace!("Status: {status}");
1281
1282        let serial = self.serial_number_inner(serial_port, key)?;
1283        log::trace!("Serial number: {serial}");
1284
1285        let res = self.enable_inner(serial_port, key)?;
1286
1287        let unit_type = status.unit_type().as_inner();
1288        if (unit_type == 0x06 || unit_type == 0x07) && key.is_some() {
1289            // if encryption mode is enabled, attempt to enable the device with EnablePayout
1290            self.enable_payout_inner(serial_port, key)?;
1291        }
1292
1293        let enable_list = ssp::EnableBitfieldList::from([
1294            ssp::EnableBitfield::from(0xff),
1295            ssp::EnableBitfield::from(0xff),
1296        ]);
1297
1298        self.set_inhibits_inner(serial_port, enable_list, key)?;
1299        self.channel_value_data_inner(serial_port, key)?;
1300
1301        Ok(res)
1302    }
1303
1304    /// Send a [EnableCommand](ssp::EnableCommand) message to the device.
1305    pub fn enable(&self) -> Result<ssp::EnableResponse> {
1306        let mut serial_port = self.serial_port()?;
1307        self.enable_inner(&mut serial_port, encryption_key!(self))
1308    }
1309
1310    fn enable_inner(
1311        &self,
1312        serial_port: &mut TTYPort,
1313        key: Option<&ssp::AesKey>,
1314    ) -> Result<ssp::EnableResponse> {
1315        let mut message = ssp::EnableCommand::new();
1316
1317        let response = Self::poll_message(serial_port, &mut message, key)?;
1318
1319        set_enabled(true);
1320
1321        response.into_enable_response()
1322    }
1323
1324    /// Send a [EnablePayoutCommand](ssp::EnablePayoutCommand) message to the device.
1325    pub fn enable_payout(&self) -> Result<ssp::EnablePayoutResponse> {
1326        let mut serial_port = self.serial_port()?;
1327        self.enable_payout_inner(&mut serial_port, encryption_key!(self))
1328    }
1329
1330    fn enable_payout_inner(
1331        &self,
1332        serial_port: &mut TTYPort,
1333        key: Option<&ssp::AesKey>,
1334    ) -> Result<ssp::EnablePayoutResponse> {
1335        let mut message =
1336            ssp::EnablePayoutCommand::new().with_option(ssp::EnablePayoutOption::from(0b11));
1337
1338        let response = Self::poll_message(serial_port, &mut message, key)?;
1339
1340        set_enabled(true);
1341
1342        response.into_enable_payout_response()
1343    }
1344
1345    /// Send a [DisableCommand](ssp::DisableCommand) message to the device.
1346    pub fn disable(&self) -> Result<ssp::DisableResponse> {
1347        let mut serial_port = self.serial_port()?;
1348        self.disable_inner(&mut serial_port, encryption_key!(self))
1349    }
1350
1351    fn disable_inner(
1352        &self,
1353        serial_port: &mut TTYPort,
1354        key: Option<&ssp::AesKey>,
1355    ) -> Result<ssp::DisableResponse> {
1356        let mut message = ssp::DisableCommand::new();
1357
1358        let response = Self::poll_message(serial_port, &mut message, key)?;
1359
1360        set_enabled(false);
1361
1362        response.into_disable_response()
1363    }
1364
1365    /// Send a [DisablePayoutCommand](ssp::DisablePayoutCommand) message to the device.
1366    pub fn disable_payout(&self) -> Result<ssp::DisablePayoutResponse> {
1367        let mut serial_port = self.serial_port()?;
1368        self.disable_payout_inner(&mut serial_port, encryption_key!(self))
1369    }
1370
1371    fn disable_payout_inner(
1372        &self,
1373        serial_port: &mut TTYPort,
1374        key: Option<&ssp::AesKey>,
1375    ) -> Result<ssp::DisablePayoutResponse> {
1376        let mut message = ssp::DisablePayoutCommand::new();
1377
1378        let response = Self::poll_message(serial_port, &mut message, key)?;
1379
1380        set_enabled(false);
1381
1382        response.into_disable_payout_response()
1383    }
1384
1385    /// Send a [DisplayOffCommand](ssp::DisplayOffCommand) message to the device.
1386    pub fn display_off(&self) -> Result<ssp::DisplayOffResponse> {
1387        let mut serial_port = self.serial_port()?;
1388
1389        let mut message = ssp::DisplayOffCommand::new();
1390
1391        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1392
1393        response.into_display_off_response()
1394    }
1395
1396    /// Send a [DisplayOnCommand](ssp::DisplayOnCommand) message to the device.
1397    pub fn display_on(&self) -> Result<ssp::DisplayOnResponse> {
1398        let mut serial_port = self.serial_port()?;
1399
1400        let mut message = ssp::DisplayOnCommand::new();
1401
1402        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1403
1404        response.into_display_on_response()
1405    }
1406
1407    /// Send an [EmptyCommand](ssp::EmptyCommand) message to the device.
1408    pub fn empty(&self) -> Result<ssp::EmptyResponse> {
1409        let mut serial_port = self.serial_port()?;
1410
1411        let mut message = ssp::EmptyCommand::new();
1412
1413        if let Some(key) = (*self.encryption_key()?).as_ref() {
1414            let res = Self::poll_encrypted_message(&mut serial_port, &mut message, key)?;
1415
1416            res.into_empty_response()
1417        } else {
1418            Err(ssp::Error::Encryption(ssp::ResponseStatus::KeyNotSet))
1419        }
1420    }
1421
1422    /// Send an [SmartEmptyCommand](ssp::SmartEmptyCommand) message to the device.
1423    pub fn smart_empty(&self) -> Result<ssp::SmartEmptyResponse> {
1424        let mut serial_port = self.serial_port()?;
1425
1426        let mut message = ssp::SmartEmptyCommand::new();
1427
1428        if let Some(key) = self.encryption_key()?.as_ref() {
1429            let res = Self::poll_encrypted_message(&mut serial_port, &mut message, key)?;
1430
1431            res.into_smart_empty_response()
1432        } else {
1433            Err(ssp::Error::Encryption(ssp::ResponseStatus::KeyNotSet))
1434        }
1435    }
1436
1437    /// Send an [HostProtocolVersionCommand](ssp::HostProtocolVersionCommand) message to the device.
1438    pub fn host_protocol_version(
1439        &self,
1440        protocol_version: ssp::ProtocolVersion,
1441    ) -> Result<ssp::HostProtocolVersionResponse> {
1442        let mut serial_port = self.serial_port()?;
1443
1444        self.host_protocol_version_inner(&mut serial_port, protocol_version, encryption_key!(self))
1445    }
1446
1447    fn host_protocol_version_inner(
1448        &self,
1449        serial_port: &mut TTYPort,
1450        protocol_version: ssp::ProtocolVersion,
1451        key: Option<&ssp::AesKey>,
1452    ) -> Result<ssp::HostProtocolVersionResponse> {
1453        let mut message = ssp::HostProtocolVersionCommand::new();
1454        message.set_version(protocol_version);
1455
1456        let response = Self::poll_message(serial_port, &mut message, key)?;
1457
1458        response.into_host_protocol_version_response()
1459    }
1460
1461    /// Send a [SerialNumberCommand](ssp::SerialNumberCommand) message to the device.
1462    pub fn serial_number(&self) -> Result<ssp::SerialNumberResponse> {
1463        let mut serial_port = self.serial_port()?;
1464        self.serial_number_inner(&mut serial_port, encryption_key!(self))
1465    }
1466
1467    fn serial_number_inner(
1468        &self,
1469        serial_port: &mut TTYPort,
1470        key: Option<&ssp::AesKey>,
1471    ) -> Result<ssp::SerialNumberResponse> {
1472        let mut message = ssp::SerialNumberCommand::new();
1473
1474        let res = Self::poll_message(serial_port, &mut message, key)?;
1475
1476        res.into_serial_number_response()
1477    }
1478
1479    /// Send a [SetGeneratorCommand](ssp::SetGeneratorCommand) message to the device.
1480    ///
1481    /// If the response is an `Err(_)`, or the response status is not
1482    /// [RsponseStatus::Ok](ssp::ResponseStatus::Ok), the caller should call
1483    /// [new_generator_key](Self::new_generator_key), and try again.
1484    pub fn set_generator(&self) -> Result<ssp::SetGeneratorResponse> {
1485        let mut serial_port = self.serial_port()?;
1486
1487        let mut message = ssp::SetGeneratorCommand::new();
1488        message.set_generator(self.generator_key());
1489
1490        let response = Self::poll_message(&mut serial_port, &mut message, None)?;
1491
1492        response.into_set_generator_response()
1493    }
1494
1495    /// Send a [SetModulusCommand](ssp::SetModulusCommand) message to the device.
1496    ///
1497    /// If the response is an `Err(_)`, or the response status is not
1498    /// [RsponseStatus::Ok](ssp::ResponseStatus::Ok), the caller should call
1499    /// [new_modulus_key](Self::new_modulus_key), and try again.
1500    pub fn set_modulus(&mut self) -> Result<ssp::SetModulusResponse> {
1501        let mut serial_port = self.serial_port()?;
1502
1503        let mut message = ssp::SetModulusCommand::new();
1504        message.set_modulus(self.modulus_key());
1505
1506        let response = Self::poll_message(&mut serial_port, &mut message, None)?;
1507
1508        response.into_set_modulus_response()
1509    }
1510
1511    /// Send a [RequestKeyExchangeCommand](ssp::RequestKeyExchangeCommand) message to the device.
1512    ///
1513    /// If the response is an `Err(_)`, or the response status is not
1514    /// [RsponseStatus::Ok](ssp::ResponseStatus::Ok), the caller should call
1515    /// [new_random_key](Self::new_random_key), and try again.
1516    pub fn request_key_exchange(&mut self) -> Result<ssp::RequestKeyExchangeResponse> {
1517        let res = {
1518            let mut serial_port = self.serial_port()?;
1519
1520            let mut message = ssp::RequestKeyExchangeCommand::new();
1521
1522            let inter_key = ssp::IntermediateKey::from_keys(
1523                self.generator_key(),
1524                self.random_key(),
1525                self.modulus_key(),
1526            );
1527            message.set_intermediate_key(&inter_key);
1528
1529            let response = Self::poll_message(&mut serial_port, &mut message, None)?;
1530
1531            response.into_request_key_exchange_response()?
1532        };
1533
1534        // If the exchange was successful, set the new encryption key.
1535        if res.response_status().is_ok() {
1536            self.set_key(res.intermediate_key())?;
1537        }
1538
1539        Ok(res)
1540    }
1541
1542    /// Send a [SetEncryptionKeyCommand](ssp::SetEncryptionKeyCommand) message to the device.
1543    ///
1544    /// If the response is an `Err(_)`, or the response status is not
1545    /// [RsponseStatus::Ok](ssp::ResponseStatus::Ok), the caller should call
1546    /// [new_modulus_key](Self::new_modulus_key), and try again.
1547    pub fn set_encryption_key(&mut self) -> Result<ssp::SetEncryptionKeyResponse> {
1548        let mut message = ssp::SetEncryptionKeyCommand::new();
1549
1550        let fixed_key = ssp::FixedKey::from_entropy();
1551        message.set_fixed_key(&fixed_key);
1552
1553        let res = if let Some(key) = encryption_key!(self) {
1554            let mut serial_port = self.serial_port()?;
1555            Self::poll_encrypted_message(&mut serial_port, &mut message, key)
1556        } else {
1557            Err(ssp::Error::Encryption(ssp::ResponseStatus::KeyNotSet))
1558        };
1559
1560        match res {
1561            Ok(m) => {
1562                self.fixed_key = fixed_key;
1563                m.into_set_encryption_key_response()
1564            }
1565            Err(err) => Err(err),
1566        }
1567    }
1568
1569    /// Send a [EncryptionResetCommand](ssp::EncryptionResetCommand) message to the device.
1570    pub fn encryption_reset(&mut self) -> Result<ssp::EncryptionResetResponse> {
1571        let mut serial_port = self.serial_port()?;
1572
1573        let mut message = ssp::EncryptionResetCommand::new();
1574
1575        let response = Self::poll_message(&mut serial_port, &mut message, None)?;
1576
1577        if response.as_response().response_status() == ssp::ResponseStatus::CommandCannotBeProcessed
1578        {
1579            Err(ssp::Error::Encryption(
1580                ssp::ResponseStatus::CommandCannotBeProcessed,
1581            ))
1582        } else {
1583            response.into_encryption_reset_response()
1584        }
1585    }
1586
1587    /// Send a [SetupRequestCommand](ssp::SetupRequestCommand) message to the device.
1588    pub fn setup_request(&self) -> Result<ssp::SetupRequestResponse> {
1589        let mut serial_port = self.serial_port()?;
1590        self.setup_request_inner(&mut serial_port, encryption_key!(self))
1591    }
1592
1593    fn setup_request_inner(
1594        &self,
1595        serial_port: &mut TTYPort,
1596        key: Option<&ssp::AesKey>,
1597    ) -> Result<ssp::SetupRequestResponse> {
1598        let mut message = ssp::SetupRequestCommand::new();
1599
1600        let response = Self::poll_message(serial_port, &mut message, key)?;
1601
1602        let res = response.into_setup_request_response()?;
1603
1604        // configure global channel values
1605        let chan_vals = match res.protocol_version()? as u8 {
1606            0..=5 | 0xff => res.channel_values()?,
1607            _ => res.channel_values_long()?,
1608        };
1609
1610        ssp::configure_channels(chan_vals.as_ref())?;
1611
1612        Ok(res)
1613    }
1614
1615    /// Send a [UnitDataCommand](ssp::UnitDataCommand) message to the device.
1616    pub fn unit_data(&self) -> Result<ssp::UnitDataResponse> {
1617        let mut serial_port = self.serial_port()?;
1618
1619        self.unit_data_inner(&mut serial_port, encryption_key!(self))
1620    }
1621
1622    fn unit_data_inner(
1623        &self,
1624        serial_port: &mut TTYPort,
1625        key: Option<&ssp::AesKey>,
1626    ) -> Result<ssp::UnitDataResponse> {
1627        let mut message = ssp::UnitDataCommand::new();
1628
1629        let response = Self::poll_message(serial_port, &mut message, key)?;
1630
1631        response.into_unit_data_response()
1632    }
1633
1634    pub fn dataset_version(&self) -> Result<ssp::DatasetVersionResponse> {
1635        let mut serial_port = self.serial_port()?;
1636
1637        Self::dataset_version_inner(&mut serial_port, encryption_key!(self))
1638    }
1639
1640    pub fn dataset_version_inner(
1641        serial_port: &mut TTYPort,
1642        key: Option<&ssp::AesKey>,
1643    ) -> Result<ssp::DatasetVersionResponse> {
1644        let mut message = ssp::DatasetVersionCommand::new();
1645
1646        let response = Self::poll_message(serial_port, &mut message, key)?;
1647
1648        response.into_dataset_version_response()
1649    }
1650
1651    /// Send a [ChannelValueDataCommand](ssp::ChannelValueDataCommand) message to the device.
1652    pub fn channel_value_data(&self) -> Result<ssp::ChannelValueDataResponse> {
1653        let mut serial_port = self.serial_port()?;
1654
1655        self.channel_value_data_inner(&mut serial_port, encryption_key!(self))
1656    }
1657
1658    fn channel_value_data_inner(
1659        &self,
1660        serial_port: &mut TTYPort,
1661        key: Option<&ssp::AesKey>,
1662    ) -> Result<ssp::ChannelValueDataResponse> {
1663        let mut message = ssp::ChannelValueDataCommand::new();
1664
1665        let response = Self::poll_message(serial_port, &mut message, key)?;
1666
1667        let res = response.into_channel_value_data_response()?;
1668
1669        ssp::configure_channels(res.channel_values()?.as_ref())?;
1670
1671        Ok(res)
1672    }
1673
1674    /// Send a [LastRejectCodeCommand](ssp::LastRejectCodeCommand) message to the device.
1675    pub fn last_reject_code(&self) -> Result<ssp::LastRejectCodeResponse> {
1676        let mut serial_port = self.serial_port()?;
1677
1678        let mut message = ssp::LastRejectCodeCommand::new();
1679
1680        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1681
1682        response.into_last_reject_code_response()
1683    }
1684
1685    /// Send a [HoldCommand](ssp::HoldCommand) message to the device.
1686    pub fn hold(&self) -> Result<ssp::HoldResponse> {
1687        let mut serial_port = self.serial_port()?;
1688
1689        let mut message = ssp::HoldCommand::new();
1690
1691        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1692
1693        response.into_hold_response()
1694    }
1695
1696    /// Send a [GetBarcodeReaderConfigurationCommand](ssp::GetBarcodeReaderConfigurationCommand) message to the device.
1697    pub fn get_barcode_reader_configuration(
1698        &self,
1699    ) -> Result<ssp::GetBarcodeReaderConfigurationResponse> {
1700        let mut serial_port = self.serial_port()?;
1701
1702        let mut message = ssp::GetBarcodeReaderConfigurationCommand::new();
1703
1704        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1705
1706        response.into_get_barcode_reader_configuration_response()
1707    }
1708
1709    /// Gets whether the device has barcode readers present.
1710    pub fn has_barcode_reader(&self) -> Result<bool> {
1711        let mut serial_port = self.serial_port()?;
1712
1713        let mut message = ssp::GetBarcodeReaderConfigurationCommand::new();
1714
1715        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1716
1717        Ok(response
1718            .as_get_barcode_reader_configuration_response()?
1719            .hardware_status()
1720            != ssp::BarcodeHardwareStatus::None)
1721    }
1722
1723    /// Send a [SetBarcodeReaderConfigurationCommand](ssp::SetBarcodeReaderConfigurationCommand) message to the device.
1724    pub fn set_barcode_reader_configuration(
1725        &self,
1726        config: ssp::BarcodeConfiguration,
1727    ) -> Result<ssp::SetBarcodeReaderConfigurationResponse> {
1728        let mut serial_port = self.serial_port()?;
1729
1730        let mut message = ssp::SetBarcodeReaderConfigurationCommand::new();
1731        message.set_configuration(config);
1732
1733        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1734
1735        response.into_set_barcode_reader_configuration_response()
1736    }
1737
1738    /// Send a [GetBarcodeInhibitCommand](ssp::GetBarcodeInhibitCommand) message to the device.
1739    pub fn get_barcode_inhibit(&self) -> Result<ssp::GetBarcodeInhibitResponse> {
1740        let mut serial_port = self.serial_port()?;
1741
1742        let mut message = ssp::GetBarcodeInhibitCommand::new();
1743
1744        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1745
1746        response.into_get_barcode_inhibit_response()
1747    }
1748
1749    /// Send a [SetBarcodeInhibitCommand](ssp::SetBarcodeInhibitCommand) message to the device.
1750    pub fn set_barcode_inhibit(
1751        &self,
1752        inhibit: ssp::BarcodeCurrencyInhibit,
1753    ) -> Result<ssp::SetBarcodeInhibitResponse> {
1754        let mut serial_port = self.serial_port()?;
1755
1756        let mut message = ssp::SetBarcodeInhibitCommand::new();
1757        message.set_inhibit(inhibit);
1758
1759        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1760
1761        response.into_set_barcode_inhibit_response()
1762    }
1763
1764    /// Send a [GetBarcodeDataCommand](ssp::GetBarcodeDataCommand) message to the device.
1765    pub fn get_barcode_data(&self) -> Result<ssp::GetBarcodeDataResponse> {
1766        let mut serial_port = self.serial_port()?;
1767
1768        let mut message = ssp::GetBarcodeDataCommand::new();
1769
1770        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1771
1772        response.into_get_barcode_data_response()
1773    }
1774
1775    /// Send a [ConfigureBezelCommand](ssp::ConfigureBezelCommand) message to the device.
1776    pub fn configure_bezel(
1777        &self,
1778        rgb: ssp::RGB,
1779        storage: ssp::BezelConfigStorage,
1780    ) -> Result<ssp::ConfigureBezelResponse> {
1781        let mut serial_port = self.serial_port()?;
1782
1783        let mut message = ssp::ConfigureBezelCommand::new();
1784        message.set_rgb(rgb);
1785        message.set_config_storage(storage);
1786
1787        let response = Self::poll_message(&mut serial_port, &mut message, encryption_key!(self))?;
1788
1789        response.into_configure_bezel_response()
1790    }
1791
1792    /// Dispenses notes from the device by sending a [PayoutByDenominationCommand] message.
1793    ///
1794    /// **NOTE**: this command requires encryption mode.
1795    ///
1796    /// Parameters:
1797    ///
1798    /// - `list`: list of [`PayoutDenomination`] requests
1799    ///
1800    /// Returns:
1801    ///
1802    /// - `Ok(())`
1803    /// - Err([`Error`](ssp::Error)) if an error occured
1804    pub fn payout_by_denomination(&self, list: &ssp::PayoutDenominationList) -> Result<()> {
1805        let mut serial_port = self.serial_port()?;
1806        let mut message = ssp::PayoutByDenominationCommand::new()
1807            .with_payout_denominations(list)
1808            .with_payout_option(ssp::PayoutOption::PayoutAmount);
1809
1810        self.payout_by_denomination_inner(&mut serial_port, &mut message, encryption_key!(self))
1811    }
1812
1813    pub(crate) fn payout_by_denomination_inner(
1814        &self,
1815        serial_port: &mut TTYPort,
1816        message: &mut ssp::PayoutByDenominationCommand,
1817        key: Option<&ssp::AesKey>,
1818    ) -> Result<()> {
1819        let mut test_cmd = message.with_payout_option(ssp::PayoutOption::TestPayoutAmount);
1820        let test_res = Self::poll_message(serial_port, &mut test_cmd, key)?;
1821
1822        log::trace!("Test payout response: {}", test_res.as_response());
1823        thread::sleep(time::Duration::from_millis(50));
1824
1825        match test_res.as_response().response_status() {
1826            ssp::ResponseStatus::Ok => {
1827                let response = Self::poll_message(serial_port, message, key)?;
1828
1829                log::trace!("Payout response: {}", response.as_response());
1830                match response.as_response().response_status() {
1831                    ssp::ResponseStatus::Ok => Ok(()),
1832                    status => Err(ssp::Error::Status(status)),
1833                }
1834            }
1835            status => Err(ssp::Error::Status(status)),
1836        }
1837    }
1838
1839    fn set_message_sequence_flag(message: &mut dyn CommandOps) {
1840        let mut sequence_id = message.sequence_id();
1841        sequence_id.set_flag(sequence_flag());
1842        message.set_sequence_id(sequence_id);
1843    }
1844
1845    fn poll_message_variant(
1846        serial_port: &mut TTYPort,
1847        message: &mut dyn CommandOps,
1848    ) -> Result<ssp::MessageVariant> {
1849        use ssp::message::index;
1850
1851        Self::set_message_sequence_flag(message);
1852
1853        log::trace!(
1854            "Message type: {}, SEQID: {}",
1855            message.message_type(),
1856            message.sequence_id()
1857        );
1858
1859        log::trace!("Polled message: {:x?}", message.as_bytes());
1860
1861        let mut attempt = 0;
1862        while let Err(_err) = serial_port.write_all(message.as_bytes()) {
1863            attempt += 1;
1864            log::warn!("Failed to send message, attempt #{attempt}");
1865
1866            thread::sleep(time::Duration::from_millis(MIN_POLLING_MS));
1867
1868            message.toggle_sequence_id();
1869        }
1870
1871        // Set the global sequence flag to the opposite value for the next message
1872        set_sequence_flag(!message.sequence_id().flag());
1873
1874        let mut buf = [0u8; ssp::len::MAX_MESSAGE];
1875
1876        serial_port
1877            .read_exact(buf[..index::SEQ_ID].as_mut())
1878            .map_err(|err| {
1879                log::warn!("Error reading initial response bytes: {err}");
1880                err
1881            })?;
1882
1883        let stx = buf[index::STX];
1884        if stx != ssp::STX {
1885            return Err(ssp::Error::InvalidSTX(stx));
1886        }
1887
1888        serial_port.read_exact(buf[index::SEQ_ID..=index::LEN].as_mut())?;
1889
1890        let buf_len = buf[index::LEN] as usize;
1891        let total = buf_len + ssp::len::METADATA;
1892        let mut remaining = index::DATA + buf_len + 2; // data + CRC-16 bytes
1893
1894        serial_port.read_exact(buf[index::DATA..remaining].as_mut())?;
1895
1896        log::trace!("Polled response: {:x?}", &buf[..remaining]);
1897
1898        // check for byte stuffing
1899        let mut extra = buf[index::DATA..remaining]
1900            .iter()
1901            .filter(|&c| c == &ssp::STX)
1902            .count()
1903            / 2;
1904
1905        // read extra bytes off the buffer to account for byte stuffing
1906        while extra != 0 {
1907            log::trace!("Extra bytes: {extra}");
1908            if remaining >= ssp::len::MAX_MESSAGE || remaining + extra >= ssp::len::MAX_MESSAGE {
1909                return Err(ssp::Error::InvalidLength((
1910                    remaining + extra,
1911                    ssp::len::MAX_MESSAGE,
1912                )));
1913            }
1914
1915            serial_port.read_exact(buf[remaining..remaining + extra].as_mut())?;
1916            extra = buf[remaining..remaining + extra]
1917                .iter()
1918                .filter(|&c| c == &ssp::STX)
1919                .count()
1920                / 2;
1921            remaining = remaining.saturating_add(extra);
1922        }
1923
1924        // remove any byte stuffing
1925        if buf[index::DATA..remaining].contains(&ssp::STX) {
1926            log::trace!("Polled response (with stuffing): {:x?}", &buf[..remaining]);
1927            ssp::unstuff(buf[index::DATA..remaining].as_mut(), total - index::DATA)?;
1928        }
1929
1930        ssp::MessageVariant::from_buf(buf[..total].as_ref(), message.message_type())
1931    }
1932
1933    fn poll_encrypted_message(
1934        serial_port: &mut TTYPort,
1935        message: &mut dyn CommandOps,
1936        key: &ssp::AesKey,
1937    ) -> Result<ssp::MessageVariant> {
1938        let mut enc_cmd = ssp::EncryptedCommand::new();
1939        enc_cmd.set_message_data(message)?;
1940
1941        let mut wrapped = enc_cmd.encrypt(key);
1942        Self::set_message_sequence_flag(&mut wrapped);
1943
1944        log::trace!("Encrypted message: {wrapped}");
1945        log::trace!("Encrypted data: {:x?}", wrapped.data());
1946
1947        // recalculate the checksum to include a possible change for the sequence flag
1948        let is_stuffed = wrapped.is_stuffed();
1949
1950        // first, remove any byte stuffing
1951        if is_stuffed {
1952            wrapped.unstuff_encrypted_data()?;
1953        }
1954
1955        // calculate the new checksum
1956        wrapped.calculate_checksum();
1957
1958        // re-add any byte stuffing
1959        if is_stuffed {
1960            wrapped.stuff_encrypted_data()?;
1961        }
1962
1963        let response = Self::poll_message_variant(serial_port, &mut wrapped)?;
1964
1965        if response.as_response().response_status() == ssp::ResponseStatus::KeyNotSet {
1966            return Err(ssp::Error::Encryption(ssp::ResponseStatus::KeyNotSet));
1967        }
1968        log::trace!("Raw response: {:x?}", response.as_response().buf());
1969
1970        let wrapped_res = response.into_wrapped_encrypted_message()?;
1971        log::trace!("Encrypted response: {:x?}", wrapped_res.buf());
1972
1973        // received an encrypted response, decrypt and process
1974        let dec_res = ssp::EncryptedResponse::decrypt(key, wrapped_res);
1975        log::trace!("Decrypted response: {dec_res}");
1976        log::trace!("Decrypted data: {:x?}", dec_res.message_data());
1977
1978        let mut res = ssp::MessageVariant::new(message.command());
1979        res.as_response_mut().set_data(dec_res.message_data())?;
1980        res.as_response_mut().calculate_checksum();
1981
1982        Ok(res)
1983    }
1984
1985    fn poll_message(
1986        serial_port: &mut TTYPort,
1987        message: &mut dyn CommandOps,
1988        key: Option<&ssp::AesKey>,
1989    ) -> Result<ssp::MessageVariant> {
1990        if let Some(key) = key {
1991            log::trace!("Polling encrypted message: {:x?}", message.buf());
1992            Self::poll_encrypted_message(serial_port, message, key)
1993        } else {
1994            log::trace!("Polling clear-text message: {:x?}", message.buf());
1995            Self::poll_message_variant(serial_port, message)
1996        }
1997    }
1998}