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
25pub const LOCK_TIMEOUT_MS: u64 = 5_000;
27pub const SERIAL_TIMEOUT_MS: u64 = 10_000;
29pub const MIN_POLLING_MS: u64 = 500;
31pub const MED_POLLING_MS: u64 = 650;
33#[allow(dead_code)]
35pub const MAX_POLLING_MS: u64 = 1_000;
36pub const QUEUE_TIMEOUT_MS: u64 = 50;
38pub 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
51static RESET_TIME: AtomicU64 = AtomicU64::new(0);
53const 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
72fn polling_inited() -> bool {
74 POLLING_INIT.load(Ordering::Relaxed)
75}
76
77fn 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
110pub fn cashbox_attached() -> bool {
112 CASHBOX_ATTACHED.load(Ordering::Relaxed)
113}
114
115pub 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#[repr(u8)]
174#[derive(Clone, Copy, Debug, PartialEq)]
175pub enum PollMode {
176 Auto,
178 Interactive,
180}
181
182pub struct PushEventReceiver(pub channel::Receiver<ssp::Event>);
213
214impl PushEventReceiver {
215 pub fn new(queue: channel::Receiver<ssp::Event>) -> Self {
217 Self(queue)
218 }
219
220 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
230pub 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 pub fn new(serial_path: &str) -> Result<Self> {
247 let serial_port = Arc::new(Mutex::new(
249 serialport::new(serial_path, BAUD_RATE)
250 .flow_control(serialport::FlowControl::None)
252 .data_bits(serialport::DataBits::Eight)
254 .parity(serialport::Parity::None)
256 .stop_bits(serialport::StopBits::Two)
258 .timeout(time::Duration::from_millis(SERIAL_TIMEOUT_MS))
260 .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 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 pub fn start_background_polling(&self, stop_polling: Arc<AtomicBool>) -> Result<()> {
314 if polling_inited() {
315 Err(ssp::Error::PollingReinit)
316 } else {
317 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 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 set_polling_inited(false);
399
400 Ok(())
401 });
402
403 set_polling_inited(false);
404
405 Ok(())
406 }
407 }
408
409 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_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 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 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 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 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 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 #[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 #[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 #[cfg(feature = "jsonrpc")]
718 pub fn on_enable(&self, stream: &mut UnixStream, event: &ssp::Event) -> Result<()> {
719 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 #[cfg(feature = "jsonrpc")]
738 pub fn on_enable_payout(&self, stream: &mut UnixStream, event: &ssp::Event) -> Result<()> {
739 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 #[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 #[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 #[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 #[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 #[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 pub fn full_reset(&self) -> Result<()> {
865 use serialport::SerialPort;
866
867 self.reset()?;
868
869 let now = time::Instant::now();
870
871 thread::sleep(time::Duration::from_secs(20));
873
874 let mut serial_port = self.serial_port()?;
875 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 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 pub fn dispensing(&self) -> bool {
917 dispensing()
918 }
919
920 #[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 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 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 pub fn new_generator_key(&mut self) {
1002 self.generator = ssp::GeneratorKey::from_entropy();
1003 self.reset_key();
1004 }
1005
1006 pub fn new_modulus_key(&mut self) {
1008 let mut modulus = ssp::ModulusKey::from_entropy();
1009
1010 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 res.response_status().is_ok() {
1536 self.set_key(res.intermediate_key())?;
1537 }
1538
1539 Ok(res)
1540 }
1541
1542 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_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; serial_port.read_exact(buf[index::DATA..remaining].as_mut())?;
1895
1896 log::trace!("Polled response: {:x?}", &buf[..remaining]);
1897
1898 let mut extra = buf[index::DATA..remaining]
1900 .iter()
1901 .filter(|&c| c == &ssp::STX)
1902 .count()
1903 / 2;
1904
1905 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 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 let is_stuffed = wrapped.is_stuffed();
1949
1950 if is_stuffed {
1952 wrapped.unstuff_encrypted_data()?;
1953 }
1954
1955 wrapped.calculate_checksum();
1957
1958 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 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}