devices/usb/backend/fido_backend/
fido_guest.rs1use std::collections::VecDeque;
6
7use base::error;
8use usb_util::TransferBuffer;
9
10use crate::usb::backend::fido_backend::constants;
11use crate::usb::backend::fido_backend::error::Error;
12use crate::usb::backend::fido_backend::error::Result;
13use crate::usb::backend::fido_backend::poll_thread::PollTimer;
14use crate::usb::backend::fido_backend::transfer::FidoTransfer;
15
16pub struct FidoGuestKey {
20 pub pending_in_packets: VecDeque<[u8; constants::U2FHID_PACKET_SIZE]>,
22 pub idle: u8,
24 pub timer: PollTimer,
26}
27
28impl FidoGuestKey {
29 pub fn new() -> Result<Self> {
30 let timer = PollTimer::new(
31 "guest packet timer".to_string(),
32 std::time::Duration::from_nanos(constants::PACKET_POLL_RATE_NANOS),
33 )?;
34 Ok(FidoGuestKey {
35 pending_in_packets: VecDeque::with_capacity(constants::U2FHID_MAX_IN_PENDING),
36 idle: 1,
37 timer,
38 })
39 }
40
41 pub fn reset(&mut self) {
43 self.pending_in_packets.clear();
44 if let Err(e) = self.timer.clear() {
45 error!("Unable to clear guest key timer, silently failing. {}", e);
46 }
47 }
48
49 pub fn return_data_to_guest(
53 &mut self,
54 transfer_opt: Option<FidoTransfer>,
55 ) -> Result<Option<FidoTransfer>> {
56 let mut transfer = transfer_opt.ok_or(Error::FidoTransferLost)?;
59 match self.pending_in_packets.pop_front() {
60 Some(packet) => {
61 transfer.buffer = TransferBuffer::Vector(packet.to_vec());
62 transfer.actual_length = packet.len();
63 transfer.complete_transfer();
64 Ok(None)
65 }
66 None => {
67 Ok(Some(transfer))
70 }
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77
78 use std::sync::Arc;
79
80 use sync::Mutex;
81 use usb_util::TransferBuffer;
82 use usb_util::TransferStatus;
83
84 use crate::usb::backend::fido_backend::constants::U2FHID_PACKET_SIZE;
85 use crate::usb::backend::fido_backend::fido_guest::FidoGuestKey;
86 use crate::usb::backend::fido_backend::transfer::FidoTransfer;
87 use crate::usb::backend::transfer::BackendTransfer;
88 use crate::usb::backend::transfer::BackendTransferType;
89
90 #[test]
91 fn test_reset() {
92 let mut fido_key = FidoGuestKey::new().unwrap();
93 let fake_packet = [0; U2FHID_PACKET_SIZE];
94
95 fido_key.pending_in_packets.push_back(fake_packet);
96 assert_eq!(fido_key.pending_in_packets.len(), 1);
97 fido_key.reset();
98 assert_eq!(fido_key.pending_in_packets.len(), 0);
99 }
100
101 #[test]
102 fn test_return_data_to_guest_no_packet_retry() {
103 let mut fido_key = FidoGuestKey::new().unwrap();
104 let transfer_buffer = TransferBuffer::Vector(vec![0u8; U2FHID_PACKET_SIZE]);
105 let fake_transfer = FidoTransfer::new(1, transfer_buffer);
106
107 let returned_transfer = fido_key.return_data_to_guest(Some(fake_transfer)).unwrap();
108 assert!(returned_transfer.is_some());
109 }
110
111 #[test]
112 fn test_return_data_to_guest_success() {
113 let mut fido_key = FidoGuestKey::new().unwrap();
114 let fake_packet = [5; U2FHID_PACKET_SIZE];
115 let transfer_buffer = TransferBuffer::Vector(vec![0u8; U2FHID_PACKET_SIZE]);
116 let mut fake_transfer = FidoTransfer::new(1, transfer_buffer);
117
118 let callback_outer = Arc::new(Mutex::new(false));
119 let callback_inner = callback_outer.clone();
120
121 fake_transfer.set_callback(move |t: BackendTransferType| {
122 assert_eq!(t.actual_length(), U2FHID_PACKET_SIZE);
123 assert!(t.status() == TransferStatus::Completed);
124 *callback_inner.lock() = true;
125 });
126 fido_key.pending_in_packets.push_back(fake_packet);
127
128 let returned_transfer = fido_key.return_data_to_guest(Some(fake_transfer)).unwrap();
129 assert!(returned_transfer.is_none());
130 assert!(*callback_outer.lock());
131 }
132}