xref: /aosp_15_r20/external/crosvm/devices/src/serial.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod sys;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::VecDeque;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicU8;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc::channel;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc::Receiver;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc::TryRecvError;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Instant;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
26*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
27*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
28*bb4ee6a4SAndroid Build Coastguard Worker 
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::BusAccessInfo;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::serial_device::SerialInput;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::suspendable::DeviceState;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::suspendable::Suspendable;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker const LOOP_SIZE: usize = 0x40;
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker const DATA: u8 = 0;
40*bb4ee6a4SAndroid Build Coastguard Worker const IER: u8 = 1;
41*bb4ee6a4SAndroid Build Coastguard Worker const IIR: u8 = 2;
42*bb4ee6a4SAndroid Build Coastguard Worker const LCR: u8 = 3;
43*bb4ee6a4SAndroid Build Coastguard Worker const MCR: u8 = 4;
44*bb4ee6a4SAndroid Build Coastguard Worker const LSR: u8 = 5;
45*bb4ee6a4SAndroid Build Coastguard Worker const MSR: u8 = 6;
46*bb4ee6a4SAndroid Build Coastguard Worker const SCR: u8 = 7;
47*bb4ee6a4SAndroid Build Coastguard Worker const DLAB_LOW: u8 = 0;
48*bb4ee6a4SAndroid Build Coastguard Worker const DLAB_HIGH: u8 = 1;
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker const IER_RECV_BIT: u8 = 0x1;
51*bb4ee6a4SAndroid Build Coastguard Worker const IER_THR_BIT: u8 = 0x2;
52*bb4ee6a4SAndroid Build Coastguard Worker const IER_FIFO_BITS: u8 = 0x0f;
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker const IIR_FIFO_BITS: u8 = 0xc0;
55*bb4ee6a4SAndroid Build Coastguard Worker const IIR_NONE_BIT: u8 = 0x1;
56*bb4ee6a4SAndroid Build Coastguard Worker const IIR_THR_BIT: u8 = 0x2;
57*bb4ee6a4SAndroid Build Coastguard Worker const IIR_RECV_BIT: u8 = 0x4;
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker const LSR_DATA_BIT: u8 = 0x1;
60*bb4ee6a4SAndroid Build Coastguard Worker const LSR_EMPTY_BIT: u8 = 0x20;
61*bb4ee6a4SAndroid Build Coastguard Worker const LSR_IDLE_BIT: u8 = 0x40;
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker const MCR_DTR_BIT: u8 = 0x01; // Data Terminal Ready
64*bb4ee6a4SAndroid Build Coastguard Worker const MCR_RTS_BIT: u8 = 0x02; // Request to Send
65*bb4ee6a4SAndroid Build Coastguard Worker const MCR_OUT1_BIT: u8 = 0x04;
66*bb4ee6a4SAndroid Build Coastguard Worker const MCR_OUT2_BIT: u8 = 0x08;
67*bb4ee6a4SAndroid Build Coastguard Worker const MCR_LOOP_BIT: u8 = 0x10;
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker const MSR_CTS_BIT: u8 = 0x10; // Clear to Send
70*bb4ee6a4SAndroid Build Coastguard Worker const MSR_DSR_BIT: u8 = 0x20; // Data Set Ready
71*bb4ee6a4SAndroid Build Coastguard Worker const MSR_RI_BIT: u8 = 0x40; // Ring Indicator
72*bb4ee6a4SAndroid Build Coastguard Worker const MSR_DCD_BIT: u8 = 0x80; // Data Carrier Detect
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_INTERRUPT_IDENTIFICATION: u8 = IIR_NONE_BIT; // no pending interrupt
75*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_LINE_STATUS: u8 = LSR_EMPTY_BIT | LSR_IDLE_BIT; // THR empty and line is idle
76*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_LINE_CONTROL: u8 = 0x3; // 8-bits per character
77*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_MODEM_CONTROL: u8 = MCR_OUT2_BIT;
78*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_MODEM_STATUS: u8 = MSR_DSR_BIT | MSR_CTS_BIT | MSR_DCD_BIT;
79*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps
80*bb4ee6a4SAndroid Build Coastguard Worker 
81*bb4ee6a4SAndroid Build Coastguard Worker const TIMESTAMP_PREFIX_FMT: &str = "[ %F %T%.9f ]: ";
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker /// Emulates serial COM ports commonly seen on x86 I/O ports 0x3f8/0x2f8/0x3e8/0x2e8.
84*bb4ee6a4SAndroid Build Coastguard Worker ///
85*bb4ee6a4SAndroid Build Coastguard Worker /// This can optionally write the guest's output to a Write trait object. To send input to the
86*bb4ee6a4SAndroid Build Coastguard Worker /// guest, use `queue_input_bytes` directly, or give a Read trait object which will be used queue
87*bb4ee6a4SAndroid Build Coastguard Worker /// bytes when `used_command` is called.
88*bb4ee6a4SAndroid Build Coastguard Worker pub struct Serial {
89*bb4ee6a4SAndroid Build Coastguard Worker     // Serial port registers
90*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_enable: Arc<AtomicU8>,
91*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_identification: u8,
92*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_evt: Event,
93*bb4ee6a4SAndroid Build Coastguard Worker     line_control: u8,
94*bb4ee6a4SAndroid Build Coastguard Worker     line_status: u8,
95*bb4ee6a4SAndroid Build Coastguard Worker     modem_control: u8,
96*bb4ee6a4SAndroid Build Coastguard Worker     modem_status: u8,
97*bb4ee6a4SAndroid Build Coastguard Worker     scratch: u8,
98*bb4ee6a4SAndroid Build Coastguard Worker     baud_divisor: u16,
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker     // Host input/output
101*bb4ee6a4SAndroid Build Coastguard Worker     in_buffer: VecDeque<u8>,
102*bb4ee6a4SAndroid Build Coastguard Worker     in_channel: Option<Receiver<u8>>,
103*bb4ee6a4SAndroid Build Coastguard Worker     input: Option<Box<dyn SerialInput>>,
104*bb4ee6a4SAndroid Build Coastguard Worker     out: Option<Box<dyn io::Write + Send>>,
105*bb4ee6a4SAndroid Build Coastguard Worker     out_timestamp: bool,
106*bb4ee6a4SAndroid Build Coastguard Worker     last_write_was_newline: bool,
107*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
108*bb4ee6a4SAndroid Build Coastguard Worker     pub system_params: sys::windows::SystemSerialParams,
109*bb4ee6a4SAndroid Build Coastguard Worker     device_state: DeviceState,
110*bb4ee6a4SAndroid Build Coastguard Worker     worker: Option<WorkerThread<Box<dyn SerialInput>>>,
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker impl Serial {
new_common( interrupt_evt: Event, input: Option<Box<dyn SerialInput>>, out: Option<Box<dyn io::Write + Send>>, out_timestamp: bool, #[cfg(windows)] system_params: sys::windows::SystemSerialParams, ) -> Serial114*bb4ee6a4SAndroid Build Coastguard Worker     fn new_common(
115*bb4ee6a4SAndroid Build Coastguard Worker         interrupt_evt: Event,
116*bb4ee6a4SAndroid Build Coastguard Worker         input: Option<Box<dyn SerialInput>>,
117*bb4ee6a4SAndroid Build Coastguard Worker         out: Option<Box<dyn io::Write + Send>>,
118*bb4ee6a4SAndroid Build Coastguard Worker         out_timestamp: bool,
119*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)] system_params: sys::windows::SystemSerialParams,
120*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Serial {
121*bb4ee6a4SAndroid Build Coastguard Worker         Serial {
122*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_enable: Default::default(),
123*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION,
124*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_evt,
125*bb4ee6a4SAndroid Build Coastguard Worker             line_control: DEFAULT_LINE_CONTROL,
126*bb4ee6a4SAndroid Build Coastguard Worker             line_status: DEFAULT_LINE_STATUS,
127*bb4ee6a4SAndroid Build Coastguard Worker             modem_control: DEFAULT_MODEM_CONTROL,
128*bb4ee6a4SAndroid Build Coastguard Worker             modem_status: DEFAULT_MODEM_STATUS,
129*bb4ee6a4SAndroid Build Coastguard Worker             scratch: 0,
130*bb4ee6a4SAndroid Build Coastguard Worker             baud_divisor: DEFAULT_BAUD_DIVISOR,
131*bb4ee6a4SAndroid Build Coastguard Worker             in_buffer: Default::default(),
132*bb4ee6a4SAndroid Build Coastguard Worker             in_channel: None,
133*bb4ee6a4SAndroid Build Coastguard Worker             input,
134*bb4ee6a4SAndroid Build Coastguard Worker             out,
135*bb4ee6a4SAndroid Build Coastguard Worker             out_timestamp,
136*bb4ee6a4SAndroid Build Coastguard Worker             last_write_was_newline: true,
137*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
138*bb4ee6a4SAndroid Build Coastguard Worker             system_params,
139*bb4ee6a4SAndroid Build Coastguard Worker             device_state: DeviceState::Awake,
140*bb4ee6a4SAndroid Build Coastguard Worker             worker: None,
141*bb4ee6a4SAndroid Build Coastguard Worker         }
142*bb4ee6a4SAndroid Build Coastguard Worker     }
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a unique ID for the serial device.
device_id() -> DeviceId145*bb4ee6a4SAndroid Build Coastguard Worker     pub fn device_id() -> DeviceId {
146*bb4ee6a4SAndroid Build Coastguard Worker         CrosvmDeviceId::Serial.into()
147*bb4ee6a4SAndroid Build Coastguard Worker     }
148*bb4ee6a4SAndroid Build Coastguard Worker 
149*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a debug label for the serial device. Used when setting up `IrqEventSource`.
debug_label() -> String150*bb4ee6a4SAndroid Build Coastguard Worker     pub fn debug_label() -> String {
151*bb4ee6a4SAndroid Build Coastguard Worker         "serial".to_owned()
152*bb4ee6a4SAndroid Build Coastguard Worker     }
153*bb4ee6a4SAndroid Build Coastguard Worker 
154*bb4ee6a4SAndroid Build Coastguard Worker     /// Queues raw bytes for the guest to read and signals the interrupt if the line status would
155*bb4ee6a4SAndroid Build Coastguard Worker     /// change. These bytes will be read by the guest before any bytes from the input stream that
156*bb4ee6a4SAndroid Build Coastguard Worker     /// have not already been queued.
queue_input_bytes(&mut self, c: &[u8]) -> Result<()>157*bb4ee6a4SAndroid Build Coastguard Worker     pub fn queue_input_bytes(&mut self, c: &[u8]) -> Result<()> {
158*bb4ee6a4SAndroid Build Coastguard Worker         if !c.is_empty() && !self.is_loop() {
159*bb4ee6a4SAndroid Build Coastguard Worker             self.in_buffer.extend(c);
160*bb4ee6a4SAndroid Build Coastguard Worker             self.set_data_bit();
161*bb4ee6a4SAndroid Build Coastguard Worker             self.trigger_recv_interrupt()?;
162*bb4ee6a4SAndroid Build Coastguard Worker         }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
165*bb4ee6a4SAndroid Build Coastguard Worker     }
166*bb4ee6a4SAndroid Build Coastguard Worker 
spawn_input_thread(&mut self)167*bb4ee6a4SAndroid Build Coastguard Worker     fn spawn_input_thread(&mut self) {
168*bb4ee6a4SAndroid Build Coastguard Worker         let mut rx = match self.input.take() {
169*bb4ee6a4SAndroid Build Coastguard Worker             Some(input) => input,
170*bb4ee6a4SAndroid Build Coastguard Worker             None => return,
171*bb4ee6a4SAndroid Build Coastguard Worker         };
172*bb4ee6a4SAndroid Build Coastguard Worker 
173*bb4ee6a4SAndroid Build Coastguard Worker         let (send_channel, recv_channel) = channel();
174*bb4ee6a4SAndroid Build Coastguard Worker 
175*bb4ee6a4SAndroid Build Coastguard Worker         // The interrupt enable and interrupt event are used to trigger the guest serial driver to
176*bb4ee6a4SAndroid Build Coastguard Worker         // read the serial device, which will give the VCPU threads time to queue input bytes from
177*bb4ee6a4SAndroid Build Coastguard Worker         // the input thread's buffer, changing the serial device state accordingly.
178*bb4ee6a4SAndroid Build Coastguard Worker         let interrupt_enable = self.interrupt_enable.clone();
179*bb4ee6a4SAndroid Build Coastguard Worker         let interrupt_evt = match self.interrupt_evt.try_clone() {
180*bb4ee6a4SAndroid Build Coastguard Worker             Ok(e) => e,
181*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
182*bb4ee6a4SAndroid Build Coastguard Worker                 error!("failed to clone interrupt event: {}", e);
183*bb4ee6a4SAndroid Build Coastguard Worker                 return;
184*bb4ee6a4SAndroid Build Coastguard Worker             }
185*bb4ee6a4SAndroid Build Coastguard Worker         };
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker         self.worker = Some(WorkerThread::start(
188*bb4ee6a4SAndroid Build Coastguard Worker             format!("{} input thread", self.debug_label()),
189*bb4ee6a4SAndroid Build Coastguard Worker             move |kill_evt| {
190*bb4ee6a4SAndroid Build Coastguard Worker                 let mut rx_buf = [0u8; 1];
191*bb4ee6a4SAndroid Build Coastguard Worker 
192*bb4ee6a4SAndroid Build Coastguard Worker                 #[derive(EventToken)]
193*bb4ee6a4SAndroid Build Coastguard Worker                 enum Token {
194*bb4ee6a4SAndroid Build Coastguard Worker                     Kill,
195*bb4ee6a4SAndroid Build Coastguard Worker                     SerialEvent,
196*bb4ee6a4SAndroid Build Coastguard Worker                 }
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker                 let wait_ctx_res: Result<WaitContext<Token>> = WaitContext::build_with(&[
199*bb4ee6a4SAndroid Build Coastguard Worker                     (&kill_evt, Token::Kill),
200*bb4ee6a4SAndroid Build Coastguard Worker                     (rx.get_read_notifier(), Token::SerialEvent),
201*bb4ee6a4SAndroid Build Coastguard Worker                 ]);
202*bb4ee6a4SAndroid Build Coastguard Worker                 let wait_ctx = match wait_ctx_res {
203*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(wait_context) => wait_context,
204*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => {
205*bb4ee6a4SAndroid Build Coastguard Worker                         error!("Failed to create wait context. {}", e);
206*bb4ee6a4SAndroid Build Coastguard Worker                         return rx;
207*bb4ee6a4SAndroid Build Coastguard Worker                     }
208*bb4ee6a4SAndroid Build Coastguard Worker                 };
209*bb4ee6a4SAndroid Build Coastguard Worker                 let mut kill_timeout = None;
210*bb4ee6a4SAndroid Build Coastguard Worker                 loop {
211*bb4ee6a4SAndroid Build Coastguard Worker                     let events = match wait_ctx.wait() {
212*bb4ee6a4SAndroid Build Coastguard Worker                         Ok(events) => events,
213*bb4ee6a4SAndroid Build Coastguard Worker                         Err(e) => {
214*bb4ee6a4SAndroid Build Coastguard Worker                             error!("Failed to wait for events. {}", e);
215*bb4ee6a4SAndroid Build Coastguard Worker                             return rx;
216*bb4ee6a4SAndroid Build Coastguard Worker                         }
217*bb4ee6a4SAndroid Build Coastguard Worker                     };
218*bb4ee6a4SAndroid Build Coastguard Worker                     for event in events.iter() {
219*bb4ee6a4SAndroid Build Coastguard Worker                         match event.token {
220*bb4ee6a4SAndroid Build Coastguard Worker                             Token::Kill => {
221*bb4ee6a4SAndroid Build Coastguard Worker                                 // Ignore the kill event until there are no other events to process
222*bb4ee6a4SAndroid Build Coastguard Worker                                 // so that we drain `rx` as much as possible. The next
223*bb4ee6a4SAndroid Build Coastguard Worker                                 // `wait_ctx.wait()` call will immediately re-entry this case since
224*bb4ee6a4SAndroid Build Coastguard Worker                                 // we don't call `kill_evt.wait()`.
225*bb4ee6a4SAndroid Build Coastguard Worker                                 if events.iter().all(|e| matches!(e.token, Token::Kill)) {
226*bb4ee6a4SAndroid Build Coastguard Worker                                     return rx;
227*bb4ee6a4SAndroid Build Coastguard Worker                                 }
228*bb4ee6a4SAndroid Build Coastguard Worker                                 const TIMEOUT_DURATION: Duration = Duration::from_millis(500);
229*bb4ee6a4SAndroid Build Coastguard Worker                                 match kill_timeout {
230*bb4ee6a4SAndroid Build Coastguard Worker                                     None => {
231*bb4ee6a4SAndroid Build Coastguard Worker                                         kill_timeout = Some(Instant::now() + TIMEOUT_DURATION);
232*bb4ee6a4SAndroid Build Coastguard Worker                                     }
233*bb4ee6a4SAndroid Build Coastguard Worker                                     Some(t) => {
234*bb4ee6a4SAndroid Build Coastguard Worker                                         if Instant::now() >= t {
235*bb4ee6a4SAndroid Build Coastguard Worker                                             error!(
236*bb4ee6a4SAndroid Build Coastguard Worker                                                 "failed to drain serial input within {:?}, giving up",
237*bb4ee6a4SAndroid Build Coastguard Worker                                                 TIMEOUT_DURATION
238*bb4ee6a4SAndroid Build Coastguard Worker                                             );
239*bb4ee6a4SAndroid Build Coastguard Worker                                             return rx;
240*bb4ee6a4SAndroid Build Coastguard Worker                                         }
241*bb4ee6a4SAndroid Build Coastguard Worker                                     }
242*bb4ee6a4SAndroid Build Coastguard Worker                                 }
243*bb4ee6a4SAndroid Build Coastguard Worker                             }
244*bb4ee6a4SAndroid Build Coastguard Worker                             Token::SerialEvent => {
245*bb4ee6a4SAndroid Build Coastguard Worker                                 // Matches both is_readable and is_hungup.
246*bb4ee6a4SAndroid Build Coastguard Worker                                 // In the case of is_hungup, there might still be data in the
247*bb4ee6a4SAndroid Build Coastguard Worker                                 // buffer, and a regular read would occur. When the buffer is
248*bb4ee6a4SAndroid Build Coastguard Worker                                 // empty, is_hungup would read EOF.
249*bb4ee6a4SAndroid Build Coastguard Worker                                 match rx.read(&mut rx_buf) {
250*bb4ee6a4SAndroid Build Coastguard Worker                                     // Assume the stream of input has ended.
251*bb4ee6a4SAndroid Build Coastguard Worker                                     Ok(0) => {
252*bb4ee6a4SAndroid Build Coastguard Worker                                         return rx;
253*bb4ee6a4SAndroid Build Coastguard Worker                                     }
254*bb4ee6a4SAndroid Build Coastguard Worker                                     Ok(_n) => {
255*bb4ee6a4SAndroid Build Coastguard Worker                                         if send_channel.send(rx_buf[0]).is_err() {
256*bb4ee6a4SAndroid Build Coastguard Worker                                             // The receiver has disconnected.
257*bb4ee6a4SAndroid Build Coastguard Worker                                             return rx;
258*bb4ee6a4SAndroid Build Coastguard Worker                                         }
259*bb4ee6a4SAndroid Build Coastguard Worker                                         if (interrupt_enable.load(Ordering::SeqCst) & IER_RECV_BIT)
260*bb4ee6a4SAndroid Build Coastguard Worker                                             != 0
261*bb4ee6a4SAndroid Build Coastguard Worker                                         {
262*bb4ee6a4SAndroid Build Coastguard Worker                                             interrupt_evt.signal().unwrap();
263*bb4ee6a4SAndroid Build Coastguard Worker                                         }
264*bb4ee6a4SAndroid Build Coastguard Worker                                     }
265*bb4ee6a4SAndroid Build Coastguard Worker                                     Err(e) => {
266*bb4ee6a4SAndroid Build Coastguard Worker                                         // Being interrupted is not an error, but everything else
267*bb4ee6a4SAndroid Build Coastguard Worker                                         // is.
268*bb4ee6a4SAndroid Build Coastguard Worker                                         if e.kind() != io::ErrorKind::Interrupted {
269*bb4ee6a4SAndroid Build Coastguard Worker                                             error!(
270*bb4ee6a4SAndroid Build Coastguard Worker                                                 "failed to read for bytes to queue into serial device: {}",
271*bb4ee6a4SAndroid Build Coastguard Worker                                                 e
272*bb4ee6a4SAndroid Build Coastguard Worker                                             );
273*bb4ee6a4SAndroid Build Coastguard Worker                                             return rx;
274*bb4ee6a4SAndroid Build Coastguard Worker                                         }
275*bb4ee6a4SAndroid Build Coastguard Worker                                     }
276*bb4ee6a4SAndroid Build Coastguard Worker                                 }
277*bb4ee6a4SAndroid Build Coastguard Worker                             }
278*bb4ee6a4SAndroid Build Coastguard Worker                         }
279*bb4ee6a4SAndroid Build Coastguard Worker                     }
280*bb4ee6a4SAndroid Build Coastguard Worker                 }
281*bb4ee6a4SAndroid Build Coastguard Worker             },
282*bb4ee6a4SAndroid Build Coastguard Worker         ));
283*bb4ee6a4SAndroid Build Coastguard Worker         self.in_channel = Some(recv_channel);
284*bb4ee6a4SAndroid Build Coastguard Worker     }
285*bb4ee6a4SAndroid Build Coastguard Worker 
drain_in_channel(&mut self)286*bb4ee6a4SAndroid Build Coastguard Worker     fn drain_in_channel(&mut self) {
287*bb4ee6a4SAndroid Build Coastguard Worker         loop {
288*bb4ee6a4SAndroid Build Coastguard Worker             let in_channel = match self.in_channel.as_ref() {
289*bb4ee6a4SAndroid Build Coastguard Worker                 Some(v) => v,
290*bb4ee6a4SAndroid Build Coastguard Worker                 None => return,
291*bb4ee6a4SAndroid Build Coastguard Worker             };
292*bb4ee6a4SAndroid Build Coastguard Worker             match in_channel.try_recv() {
293*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(byte) => {
294*bb4ee6a4SAndroid Build Coastguard Worker                     self.queue_input_bytes(&[byte]).unwrap();
295*bb4ee6a4SAndroid Build Coastguard Worker                 }
296*bb4ee6a4SAndroid Build Coastguard Worker                 Err(TryRecvError::Empty) => break,
297*bb4ee6a4SAndroid Build Coastguard Worker                 Err(TryRecvError::Disconnected) => {
298*bb4ee6a4SAndroid Build Coastguard Worker                     self.in_channel = None;
299*bb4ee6a4SAndroid Build Coastguard Worker                     return;
300*bb4ee6a4SAndroid Build Coastguard Worker                 }
301*bb4ee6a4SAndroid Build Coastguard Worker             }
302*bb4ee6a4SAndroid Build Coastguard Worker         }
303*bb4ee6a4SAndroid Build Coastguard Worker     }
304*bb4ee6a4SAndroid Build Coastguard Worker 
305*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the interrupt event used to interrupt the driver when it needs to respond to this
306*bb4ee6a4SAndroid Build Coastguard Worker     /// device.
interrupt_event(&self) -> &Event307*bb4ee6a4SAndroid Build Coastguard Worker     pub fn interrupt_event(&self) -> &Event {
308*bb4ee6a4SAndroid Build Coastguard Worker         &self.interrupt_evt
309*bb4ee6a4SAndroid Build Coastguard Worker     }
310*bb4ee6a4SAndroid Build Coastguard Worker 
is_dlab_set(&self) -> bool311*bb4ee6a4SAndroid Build Coastguard Worker     fn is_dlab_set(&self) -> bool {
312*bb4ee6a4SAndroid Build Coastguard Worker         (self.line_control & 0x80) != 0
313*bb4ee6a4SAndroid Build Coastguard Worker     }
314*bb4ee6a4SAndroid Build Coastguard Worker 
is_recv_intr_enabled(&self) -> bool315*bb4ee6a4SAndroid Build Coastguard Worker     fn is_recv_intr_enabled(&self) -> bool {
316*bb4ee6a4SAndroid Build Coastguard Worker         (self.interrupt_enable.load(Ordering::SeqCst) & IER_RECV_BIT) != 0
317*bb4ee6a4SAndroid Build Coastguard Worker     }
318*bb4ee6a4SAndroid Build Coastguard Worker 
is_thr_intr_enabled(&self) -> bool319*bb4ee6a4SAndroid Build Coastguard Worker     fn is_thr_intr_enabled(&self) -> bool {
320*bb4ee6a4SAndroid Build Coastguard Worker         (self.interrupt_enable.load(Ordering::SeqCst) & IER_THR_BIT) != 0
321*bb4ee6a4SAndroid Build Coastguard Worker     }
322*bb4ee6a4SAndroid Build Coastguard Worker 
is_thr_intr_changed(&self, bit: u8) -> bool323*bb4ee6a4SAndroid Build Coastguard Worker     fn is_thr_intr_changed(&self, bit: u8) -> bool {
324*bb4ee6a4SAndroid Build Coastguard Worker         (self.interrupt_enable.load(Ordering::SeqCst) ^ bit) & IER_FIFO_BITS != 0
325*bb4ee6a4SAndroid Build Coastguard Worker     }
326*bb4ee6a4SAndroid Build Coastguard Worker 
is_loop(&self) -> bool327*bb4ee6a4SAndroid Build Coastguard Worker     fn is_loop(&self) -> bool {
328*bb4ee6a4SAndroid Build Coastguard Worker         (self.modem_control & MCR_LOOP_BIT) != 0
329*bb4ee6a4SAndroid Build Coastguard Worker     }
330*bb4ee6a4SAndroid Build Coastguard Worker 
add_intr_bit(&mut self, bit: u8)331*bb4ee6a4SAndroid Build Coastguard Worker     fn add_intr_bit(&mut self, bit: u8) {
332*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_identification &= !IIR_NONE_BIT;
333*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_identification |= bit;
334*bb4ee6a4SAndroid Build Coastguard Worker     }
335*bb4ee6a4SAndroid Build Coastguard Worker 
del_intr_bit(&mut self, bit: u8)336*bb4ee6a4SAndroid Build Coastguard Worker     fn del_intr_bit(&mut self, bit: u8) {
337*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_identification &= !bit;
338*bb4ee6a4SAndroid Build Coastguard Worker         if self.interrupt_identification == 0x0 {
339*bb4ee6a4SAndroid Build Coastguard Worker             self.interrupt_identification = IIR_NONE_BIT;
340*bb4ee6a4SAndroid Build Coastguard Worker         }
341*bb4ee6a4SAndroid Build Coastguard Worker     }
342*bb4ee6a4SAndroid Build Coastguard Worker 
trigger_thr_empty(&mut self) -> Result<()>343*bb4ee6a4SAndroid Build Coastguard Worker     fn trigger_thr_empty(&mut self) -> Result<()> {
344*bb4ee6a4SAndroid Build Coastguard Worker         if self.is_thr_intr_enabled() {
345*bb4ee6a4SAndroid Build Coastguard Worker             self.add_intr_bit(IIR_THR_BIT);
346*bb4ee6a4SAndroid Build Coastguard Worker             self.trigger_interrupt()?
347*bb4ee6a4SAndroid Build Coastguard Worker         }
348*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
349*bb4ee6a4SAndroid Build Coastguard Worker     }
350*bb4ee6a4SAndroid Build Coastguard Worker 
trigger_recv_interrupt(&mut self) -> Result<()>351*bb4ee6a4SAndroid Build Coastguard Worker     fn trigger_recv_interrupt(&mut self) -> Result<()> {
352*bb4ee6a4SAndroid Build Coastguard Worker         if self.is_recv_intr_enabled() {
353*bb4ee6a4SAndroid Build Coastguard Worker             // Only bother triggering the interrupt if the identification bit wasn't set or
354*bb4ee6a4SAndroid Build Coastguard Worker             // acknowledged.
355*bb4ee6a4SAndroid Build Coastguard Worker             if self.interrupt_identification & IIR_RECV_BIT == 0 {
356*bb4ee6a4SAndroid Build Coastguard Worker                 self.add_intr_bit(IIR_RECV_BIT);
357*bb4ee6a4SAndroid Build Coastguard Worker                 self.trigger_interrupt()?
358*bb4ee6a4SAndroid Build Coastguard Worker             }
359*bb4ee6a4SAndroid Build Coastguard Worker         }
360*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
361*bb4ee6a4SAndroid Build Coastguard Worker     }
362*bb4ee6a4SAndroid Build Coastguard Worker 
trigger_interrupt(&mut self) -> Result<()>363*bb4ee6a4SAndroid Build Coastguard Worker     fn trigger_interrupt(&mut self) -> Result<()> {
364*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_evt.signal()
365*bb4ee6a4SAndroid Build Coastguard Worker     }
366*bb4ee6a4SAndroid Build Coastguard Worker 
set_data_bit(&mut self)367*bb4ee6a4SAndroid Build Coastguard Worker     fn set_data_bit(&mut self) {
368*bb4ee6a4SAndroid Build Coastguard Worker         self.line_status |= LSR_DATA_BIT;
369*bb4ee6a4SAndroid Build Coastguard Worker     }
370*bb4ee6a4SAndroid Build Coastguard Worker 
is_data_avaiable(&self) -> bool371*bb4ee6a4SAndroid Build Coastguard Worker     fn is_data_avaiable(&self) -> bool {
372*bb4ee6a4SAndroid Build Coastguard Worker         (self.line_status & LSR_DATA_BIT) != 0
373*bb4ee6a4SAndroid Build Coastguard Worker     }
374*bb4ee6a4SAndroid Build Coastguard Worker 
iir_reset(&mut self)375*bb4ee6a4SAndroid Build Coastguard Worker     fn iir_reset(&mut self) {
376*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_identification = DEFAULT_INTERRUPT_IDENTIFICATION;
377*bb4ee6a4SAndroid Build Coastguard Worker     }
378*bb4ee6a4SAndroid Build Coastguard Worker 
handle_write(&mut self, offset: u8, v: u8) -> Result<()>379*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_write(&mut self, offset: u8, v: u8) -> Result<()> {
380*bb4ee6a4SAndroid Build Coastguard Worker         match offset {
381*bb4ee6a4SAndroid Build Coastguard Worker             DLAB_LOW if self.is_dlab_set() => {
382*bb4ee6a4SAndroid Build Coastguard Worker                 self.baud_divisor = (self.baud_divisor & 0xff00) | v as u16
383*bb4ee6a4SAndroid Build Coastguard Worker             }
384*bb4ee6a4SAndroid Build Coastguard Worker             DLAB_HIGH if self.is_dlab_set() => {
385*bb4ee6a4SAndroid Build Coastguard Worker                 self.baud_divisor = (self.baud_divisor & 0x00ff) | ((v as u16) << 8)
386*bb4ee6a4SAndroid Build Coastguard Worker             }
387*bb4ee6a4SAndroid Build Coastguard Worker             DATA => {
388*bb4ee6a4SAndroid Build Coastguard Worker                 if self.is_loop() {
389*bb4ee6a4SAndroid Build Coastguard Worker                     if self.in_buffer.len() < LOOP_SIZE {
390*bb4ee6a4SAndroid Build Coastguard Worker                         self.in_buffer.push_back(v);
391*bb4ee6a4SAndroid Build Coastguard Worker                         self.set_data_bit();
392*bb4ee6a4SAndroid Build Coastguard Worker                         self.trigger_recv_interrupt()?;
393*bb4ee6a4SAndroid Build Coastguard Worker                     }
394*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
395*bb4ee6a4SAndroid Build Coastguard Worker                     self.handle_write_data(v)?;
396*bb4ee6a4SAndroid Build Coastguard Worker                     self.trigger_thr_empty()?;
397*bb4ee6a4SAndroid Build Coastguard Worker                 }
398*bb4ee6a4SAndroid Build Coastguard Worker             }
399*bb4ee6a4SAndroid Build Coastguard Worker             IER => {
400*bb4ee6a4SAndroid Build Coastguard Worker                 let tx_changed = self.is_thr_intr_changed(v);
401*bb4ee6a4SAndroid Build Coastguard Worker                 self.interrupt_enable
402*bb4ee6a4SAndroid Build Coastguard Worker                     .store(v & IER_FIFO_BITS, Ordering::SeqCst);
403*bb4ee6a4SAndroid Build Coastguard Worker 
404*bb4ee6a4SAndroid Build Coastguard Worker                 if self.is_data_avaiable() {
405*bb4ee6a4SAndroid Build Coastguard Worker                     self.trigger_recv_interrupt()?;
406*bb4ee6a4SAndroid Build Coastguard Worker                 }
407*bb4ee6a4SAndroid Build Coastguard Worker 
408*bb4ee6a4SAndroid Build Coastguard Worker                 if tx_changed {
409*bb4ee6a4SAndroid Build Coastguard Worker                     self.trigger_thr_empty()?;
410*bb4ee6a4SAndroid Build Coastguard Worker                 }
411*bb4ee6a4SAndroid Build Coastguard Worker             }
412*bb4ee6a4SAndroid Build Coastguard Worker             LCR => self.line_control = v,
413*bb4ee6a4SAndroid Build Coastguard Worker             MCR => self.modem_control = v,
414*bb4ee6a4SAndroid Build Coastguard Worker             SCR => self.scratch = v,
415*bb4ee6a4SAndroid Build Coastguard Worker             _ => {}
416*bb4ee6a4SAndroid Build Coastguard Worker         }
417*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
418*bb4ee6a4SAndroid Build Coastguard Worker     }
419*bb4ee6a4SAndroid Build Coastguard Worker 
420*bb4ee6a4SAndroid Build Coastguard Worker     // Write a single byte of data to `self.out`.
handle_write_data(&mut self, v: u8) -> Result<()>421*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_write_data(&mut self, v: u8) -> Result<()> {
422*bb4ee6a4SAndroid Build Coastguard Worker         let out = match self.out.as_mut() {
423*bb4ee6a4SAndroid Build Coastguard Worker             Some(out) => out,
424*bb4ee6a4SAndroid Build Coastguard Worker             None => return Ok(()),
425*bb4ee6a4SAndroid Build Coastguard Worker         };
426*bb4ee6a4SAndroid Build Coastguard Worker 
427*bb4ee6a4SAndroid Build Coastguard Worker         if self.out_timestamp && self.last_write_was_newline {
428*bb4ee6a4SAndroid Build Coastguard Worker             write!(out, "{}", chrono::Utc::now().format(TIMESTAMP_PREFIX_FMT))?;
429*bb4ee6a4SAndroid Build Coastguard Worker         }
430*bb4ee6a4SAndroid Build Coastguard Worker 
431*bb4ee6a4SAndroid Build Coastguard Worker         self.last_write_was_newline = v == b'\n';
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker         out.write_all(&[v])?;
434*bb4ee6a4SAndroid Build Coastguard Worker         out.flush()?;
435*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
436*bb4ee6a4SAndroid Build Coastguard Worker     }
437*bb4ee6a4SAndroid Build Coastguard Worker }
438*bb4ee6a4SAndroid Build Coastguard Worker 
439*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for Serial {
device_id(&self) -> DeviceId440*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
441*bb4ee6a4SAndroid Build Coastguard Worker         CrosvmDeviceId::Serial.into()
442*bb4ee6a4SAndroid Build Coastguard Worker     }
443*bb4ee6a4SAndroid Build Coastguard Worker 
debug_label(&self) -> String444*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
445*bb4ee6a4SAndroid Build Coastguard Worker         "serial".to_owned()
446*bb4ee6a4SAndroid Build Coastguard Worker     }
447*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])448*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
449*bb4ee6a4SAndroid Build Coastguard Worker         if matches!(self.device_state, DeviceState::Sleep) {
450*bb4ee6a4SAndroid Build Coastguard Worker             panic!("Unexpected action: Attempt to write to serial when device is in sleep mode");
451*bb4ee6a4SAndroid Build Coastguard Worker         }
452*bb4ee6a4SAndroid Build Coastguard Worker 
453*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() != 1 {
454*bb4ee6a4SAndroid Build Coastguard Worker             return;
455*bb4ee6a4SAndroid Build Coastguard Worker         }
456*bb4ee6a4SAndroid Build Coastguard Worker 
457*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)]
458*bb4ee6a4SAndroid Build Coastguard Worker         self.handle_sync_thread();
459*bb4ee6a4SAndroid Build Coastguard Worker 
460*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.handle_write(info.offset as u8, data[0]) {
461*bb4ee6a4SAndroid Build Coastguard Worker             error!("serial failed write: {}", e);
462*bb4ee6a4SAndroid Build Coastguard Worker         }
463*bb4ee6a4SAndroid Build Coastguard Worker     }
464*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])465*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
466*bb4ee6a4SAndroid Build Coastguard Worker         if matches!(self.device_state, DeviceState::Sleep) {
467*bb4ee6a4SAndroid Build Coastguard Worker             panic!("Unexpected action: Attempt to write to serial when device is in sleep mode");
468*bb4ee6a4SAndroid Build Coastguard Worker         }
469*bb4ee6a4SAndroid Build Coastguard Worker 
470*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() != 1 {
471*bb4ee6a4SAndroid Build Coastguard Worker             return;
472*bb4ee6a4SAndroid Build Coastguard Worker         }
473*bb4ee6a4SAndroid Build Coastguard Worker 
474*bb4ee6a4SAndroid Build Coastguard Worker         if self.input.is_some() {
475*bb4ee6a4SAndroid Build Coastguard Worker             self.spawn_input_thread();
476*bb4ee6a4SAndroid Build Coastguard Worker         }
477*bb4ee6a4SAndroid Build Coastguard Worker         self.drain_in_channel();
478*bb4ee6a4SAndroid Build Coastguard Worker 
479*bb4ee6a4SAndroid Build Coastguard Worker         data[0] = match info.offset as u8 {
480*bb4ee6a4SAndroid Build Coastguard Worker             DLAB_LOW if self.is_dlab_set() => self.baud_divisor as u8,
481*bb4ee6a4SAndroid Build Coastguard Worker             DLAB_HIGH if self.is_dlab_set() => (self.baud_divisor >> 8) as u8,
482*bb4ee6a4SAndroid Build Coastguard Worker             DATA => {
483*bb4ee6a4SAndroid Build Coastguard Worker                 self.del_intr_bit(IIR_RECV_BIT);
484*bb4ee6a4SAndroid Build Coastguard Worker                 if self.in_buffer.len() <= 1 {
485*bb4ee6a4SAndroid Build Coastguard Worker                     self.line_status &= !LSR_DATA_BIT;
486*bb4ee6a4SAndroid Build Coastguard Worker                 }
487*bb4ee6a4SAndroid Build Coastguard Worker                 self.in_buffer.pop_front().unwrap_or_default()
488*bb4ee6a4SAndroid Build Coastguard Worker             }
489*bb4ee6a4SAndroid Build Coastguard Worker             IER => self.interrupt_enable.load(Ordering::SeqCst),
490*bb4ee6a4SAndroid Build Coastguard Worker             IIR => {
491*bb4ee6a4SAndroid Build Coastguard Worker                 let v = self.interrupt_identification | IIR_FIFO_BITS;
492*bb4ee6a4SAndroid Build Coastguard Worker                 self.iir_reset();
493*bb4ee6a4SAndroid Build Coastguard Worker                 v
494*bb4ee6a4SAndroid Build Coastguard Worker             }
495*bb4ee6a4SAndroid Build Coastguard Worker             LCR => self.line_control,
496*bb4ee6a4SAndroid Build Coastguard Worker             MCR => self.modem_control,
497*bb4ee6a4SAndroid Build Coastguard Worker             LSR => self.line_status,
498*bb4ee6a4SAndroid Build Coastguard Worker             MSR => {
499*bb4ee6a4SAndroid Build Coastguard Worker                 if self.is_loop() {
500*bb4ee6a4SAndroid Build Coastguard Worker                     let mut msr =
501*bb4ee6a4SAndroid Build Coastguard Worker                         self.modem_status & !(MSR_DSR_BIT | MSR_CTS_BIT | MSR_RI_BIT | MSR_DCD_BIT);
502*bb4ee6a4SAndroid Build Coastguard Worker                     if self.modem_control & MCR_DTR_BIT != 0 {
503*bb4ee6a4SAndroid Build Coastguard Worker                         msr |= MSR_DSR_BIT;
504*bb4ee6a4SAndroid Build Coastguard Worker                     }
505*bb4ee6a4SAndroid Build Coastguard Worker                     if self.modem_control & MCR_RTS_BIT != 0 {
506*bb4ee6a4SAndroid Build Coastguard Worker                         msr |= MSR_CTS_BIT;
507*bb4ee6a4SAndroid Build Coastguard Worker                     }
508*bb4ee6a4SAndroid Build Coastguard Worker                     if self.modem_control & MCR_OUT1_BIT != 0 {
509*bb4ee6a4SAndroid Build Coastguard Worker                         msr |= MSR_RI_BIT;
510*bb4ee6a4SAndroid Build Coastguard Worker                     }
511*bb4ee6a4SAndroid Build Coastguard Worker                     if self.modem_control & MCR_OUT2_BIT != 0 {
512*bb4ee6a4SAndroid Build Coastguard Worker                         msr |= MSR_DCD_BIT;
513*bb4ee6a4SAndroid Build Coastguard Worker                     }
514*bb4ee6a4SAndroid Build Coastguard Worker                     msr
515*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
516*bb4ee6a4SAndroid Build Coastguard Worker                     self.modem_status
517*bb4ee6a4SAndroid Build Coastguard Worker                 }
518*bb4ee6a4SAndroid Build Coastguard Worker             }
519*bb4ee6a4SAndroid Build Coastguard Worker             SCR => self.scratch,
520*bb4ee6a4SAndroid Build Coastguard Worker             _ => 0,
521*bb4ee6a4SAndroid Build Coastguard Worker         };
522*bb4ee6a4SAndroid Build Coastguard Worker     }
523*bb4ee6a4SAndroid Build Coastguard Worker }
524*bb4ee6a4SAndroid Build Coastguard Worker 
525*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
526*bb4ee6a4SAndroid Build Coastguard Worker struct SerialSnapshot {
527*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_enable: u8,
528*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_identification: u8,
529*bb4ee6a4SAndroid Build Coastguard Worker     line_control: u8,
530*bb4ee6a4SAndroid Build Coastguard Worker     line_status: u8,
531*bb4ee6a4SAndroid Build Coastguard Worker     modem_control: u8,
532*bb4ee6a4SAndroid Build Coastguard Worker     modem_status: u8,
533*bb4ee6a4SAndroid Build Coastguard Worker     scratch: u8,
534*bb4ee6a4SAndroid Build Coastguard Worker     baud_divisor: u16,
535*bb4ee6a4SAndroid Build Coastguard Worker 
536*bb4ee6a4SAndroid Build Coastguard Worker     in_buffer: VecDeque<u8>,
537*bb4ee6a4SAndroid Build Coastguard Worker 
538*bb4ee6a4SAndroid Build Coastguard Worker     has_input: bool,
539*bb4ee6a4SAndroid Build Coastguard Worker     has_output: bool,
540*bb4ee6a4SAndroid Build Coastguard Worker 
541*bb4ee6a4SAndroid Build Coastguard Worker     last_write_was_newline: bool,
542*bb4ee6a4SAndroid Build Coastguard Worker }
543*bb4ee6a4SAndroid Build Coastguard Worker 
544*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for Serial {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>545*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
546*bb4ee6a4SAndroid Build Coastguard Worker         self.spawn_input_thread();
547*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(worker) = self.worker.take() {
548*bb4ee6a4SAndroid Build Coastguard Worker             self.input = Some(worker.stop());
549*bb4ee6a4SAndroid Build Coastguard Worker         }
550*bb4ee6a4SAndroid Build Coastguard Worker         self.drain_in_channel();
551*bb4ee6a4SAndroid Build Coastguard Worker         let snap = SerialSnapshot {
552*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_enable: self.interrupt_enable.load(Ordering::SeqCst),
553*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_identification: self.interrupt_identification,
554*bb4ee6a4SAndroid Build Coastguard Worker             line_control: self.line_control,
555*bb4ee6a4SAndroid Build Coastguard Worker             line_status: self.line_status,
556*bb4ee6a4SAndroid Build Coastguard Worker             modem_control: self.modem_control,
557*bb4ee6a4SAndroid Build Coastguard Worker             modem_status: self.modem_status,
558*bb4ee6a4SAndroid Build Coastguard Worker             scratch: self.scratch,
559*bb4ee6a4SAndroid Build Coastguard Worker             baud_divisor: self.baud_divisor,
560*bb4ee6a4SAndroid Build Coastguard Worker             in_buffer: self.in_buffer.clone(),
561*bb4ee6a4SAndroid Build Coastguard Worker             has_input: self.input.is_some(),
562*bb4ee6a4SAndroid Build Coastguard Worker             has_output: self.out.is_some(),
563*bb4ee6a4SAndroid Build Coastguard Worker             last_write_was_newline: self.last_write_was_newline,
564*bb4ee6a4SAndroid Build Coastguard Worker         };
565*bb4ee6a4SAndroid Build Coastguard Worker 
566*bb4ee6a4SAndroid Build Coastguard Worker         let serialized = serde_json::to_value(snap).context("error serializing")?;
567*bb4ee6a4SAndroid Build Coastguard Worker         Ok(serialized)
568*bb4ee6a4SAndroid Build Coastguard Worker     }
569*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>570*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
571*bb4ee6a4SAndroid Build Coastguard Worker         let serial_snapshot: SerialSnapshot =
572*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(data).context("error deserializing")?;
573*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_enable = Arc::new(AtomicU8::new(serial_snapshot.interrupt_enable));
574*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_identification = serial_snapshot.interrupt_identification;
575*bb4ee6a4SAndroid Build Coastguard Worker         self.line_control = serial_snapshot.line_control;
576*bb4ee6a4SAndroid Build Coastguard Worker         self.line_status = serial_snapshot.line_status;
577*bb4ee6a4SAndroid Build Coastguard Worker         self.modem_control = serial_snapshot.modem_control;
578*bb4ee6a4SAndroid Build Coastguard Worker         self.modem_status = serial_snapshot.modem_status;
579*bb4ee6a4SAndroid Build Coastguard Worker         self.scratch = serial_snapshot.scratch;
580*bb4ee6a4SAndroid Build Coastguard Worker         self.baud_divisor = serial_snapshot.baud_divisor;
581*bb4ee6a4SAndroid Build Coastguard Worker         self.in_buffer = serial_snapshot.in_buffer;
582*bb4ee6a4SAndroid Build Coastguard Worker         if serial_snapshot.has_input && self.input.is_none() {
583*bb4ee6a4SAndroid Build Coastguard Worker             warn!("Restore serial input missing when restore expected an input");
584*bb4ee6a4SAndroid Build Coastguard Worker         }
585*bb4ee6a4SAndroid Build Coastguard Worker         if serial_snapshot.has_output && self.out.is_none() {
586*bb4ee6a4SAndroid Build Coastguard Worker             warn!("Restore serial out missing when restore expected an out");
587*bb4ee6a4SAndroid Build Coastguard Worker         }
588*bb4ee6a4SAndroid Build Coastguard Worker         self.last_write_was_newline = serial_snapshot.last_write_was_newline;
589*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
590*bb4ee6a4SAndroid Build Coastguard Worker     }
591*bb4ee6a4SAndroid Build Coastguard Worker 
sleep(&mut self) -> anyhow::Result<()>592*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
593*bb4ee6a4SAndroid Build Coastguard Worker         if !matches!(self.device_state, DeviceState::Sleep) {
594*bb4ee6a4SAndroid Build Coastguard Worker             self.device_state = DeviceState::Sleep;
595*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(worker) = self.worker.take() {
596*bb4ee6a4SAndroid Build Coastguard Worker                 self.input = Some(worker.stop());
597*bb4ee6a4SAndroid Build Coastguard Worker             }
598*bb4ee6a4SAndroid Build Coastguard Worker 
599*bb4ee6a4SAndroid Build Coastguard Worker             self.drain_in_channel();
600*bb4ee6a4SAndroid Build Coastguard Worker             self.in_channel = None;
601*bb4ee6a4SAndroid Build Coastguard Worker         }
602*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
603*bb4ee6a4SAndroid Build Coastguard Worker     }
604*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>605*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
606*bb4ee6a4SAndroid Build Coastguard Worker         if !matches!(self.device_state, DeviceState::Awake) {
607*bb4ee6a4SAndroid Build Coastguard Worker             self.device_state = DeviceState::Awake;
608*bb4ee6a4SAndroid Build Coastguard Worker             if self.input.is_some() {
609*bb4ee6a4SAndroid Build Coastguard Worker                 self.spawn_input_thread();
610*bb4ee6a4SAndroid Build Coastguard Worker             }
611*bb4ee6a4SAndroid Build Coastguard Worker         }
612*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
613*bb4ee6a4SAndroid Build Coastguard Worker     }
614*bb4ee6a4SAndroid Build Coastguard Worker }
615*bb4ee6a4SAndroid Build Coastguard Worker 
616*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
617*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
618*bb4ee6a4SAndroid Build Coastguard Worker     use std::io;
619*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::Arc;
620*bb4ee6a4SAndroid Build Coastguard Worker 
621*bb4ee6a4SAndroid Build Coastguard Worker     use hypervisor::ProtectionType;
622*bb4ee6a4SAndroid Build Coastguard Worker     use sync::Mutex;
623*bb4ee6a4SAndroid Build Coastguard Worker 
624*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
625*bb4ee6a4SAndroid Build Coastguard Worker     use crate::serial_device::SerialOptions;
626*bb4ee6a4SAndroid Build Coastguard Worker     use crate::suspendable_tests;
627*bb4ee6a4SAndroid Build Coastguard Worker     pub use crate::sys::serial_device::SerialDevice;
628*bb4ee6a4SAndroid Build Coastguard Worker 
629*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Clone)]
630*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) struct SharedBuffer {
631*bb4ee6a4SAndroid Build Coastguard Worker         pub(super) buf: Arc<Mutex<Vec<u8>>>,
632*bb4ee6a4SAndroid Build Coastguard Worker     }
633*bb4ee6a4SAndroid Build Coastguard Worker 
634*bb4ee6a4SAndroid Build Coastguard Worker     /// Empties the in_buffer.
635*bb4ee6a4SAndroid Build Coastguard Worker     impl Serial {
clear_in_buffer(&mut self)636*bb4ee6a4SAndroid Build Coastguard Worker         pub fn clear_in_buffer(&mut self) {
637*bb4ee6a4SAndroid Build Coastguard Worker             self.in_buffer.clear()
638*bb4ee6a4SAndroid Build Coastguard Worker         }
639*bb4ee6a4SAndroid Build Coastguard Worker     }
640*bb4ee6a4SAndroid Build Coastguard Worker 
641*bb4ee6a4SAndroid Build Coastguard Worker     impl SharedBuffer {
new() -> SharedBuffer642*bb4ee6a4SAndroid Build Coastguard Worker         pub(super) fn new() -> SharedBuffer {
643*bb4ee6a4SAndroid Build Coastguard Worker             SharedBuffer {
644*bb4ee6a4SAndroid Build Coastguard Worker                 buf: Arc::new(Mutex::new(Vec::new())),
645*bb4ee6a4SAndroid Build Coastguard Worker             }
646*bb4ee6a4SAndroid Build Coastguard Worker         }
647*bb4ee6a4SAndroid Build Coastguard Worker     }
648*bb4ee6a4SAndroid Build Coastguard Worker 
649*bb4ee6a4SAndroid Build Coastguard Worker     impl io::Write for SharedBuffer {
write(&mut self, buf: &[u8]) -> io::Result<usize>650*bb4ee6a4SAndroid Build Coastguard Worker         fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
651*bb4ee6a4SAndroid Build Coastguard Worker             self.buf.lock().write(buf)
652*bb4ee6a4SAndroid Build Coastguard Worker         }
flush(&mut self) -> io::Result<()>653*bb4ee6a4SAndroid Build Coastguard Worker         fn flush(&mut self) -> io::Result<()> {
654*bb4ee6a4SAndroid Build Coastguard Worker             self.buf.lock().flush()
655*bb4ee6a4SAndroid Build Coastguard Worker         }
656*bb4ee6a4SAndroid Build Coastguard Worker     }
657*bb4ee6a4SAndroid Build Coastguard Worker 
serial_bus_address(offset: u8) -> BusAccessInfo658*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) fn serial_bus_address(offset: u8) -> BusAccessInfo {
659*bb4ee6a4SAndroid Build Coastguard Worker         // Serial devices only use the offset of the BusAccessInfo
660*bb4ee6a4SAndroid Build Coastguard Worker         BusAccessInfo {
661*bb4ee6a4SAndroid Build Coastguard Worker             offset: offset as u64,
662*bb4ee6a4SAndroid Build Coastguard Worker             address: 0,
663*bb4ee6a4SAndroid Build Coastguard Worker             id: 0,
664*bb4ee6a4SAndroid Build Coastguard Worker         }
665*bb4ee6a4SAndroid Build Coastguard Worker     }
666*bb4ee6a4SAndroid Build Coastguard Worker 
667*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_output()668*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_output() {
669*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
670*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
671*bb4ee6a4SAndroid Build Coastguard Worker 
672*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
673*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
674*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt,
675*bb4ee6a4SAndroid Build Coastguard Worker             None,
676*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out.clone())),
677*bb4ee6a4SAndroid Build Coastguard Worker             None,
678*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
679*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
680*bb4ee6a4SAndroid Build Coastguard Worker         );
681*bb4ee6a4SAndroid Build Coastguard Worker 
682*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"a");
683*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"b");
684*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"c");
685*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(serial_out.buf.lock().as_slice(), b"abc");
686*bb4ee6a4SAndroid Build Coastguard Worker     }
687*bb4ee6a4SAndroid Build Coastguard Worker 
688*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_input()689*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input() {
690*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
691*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
692*bb4ee6a4SAndroid Build Coastguard Worker 
693*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
694*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
695*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
696*bb4ee6a4SAndroid Build Coastguard Worker             None,
697*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
698*bb4ee6a4SAndroid Build Coastguard Worker             None,
699*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
700*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
701*bb4ee6a4SAndroid Build Coastguard Worker         );
702*bb4ee6a4SAndroid Build Coastguard Worker 
703*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
704*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
705*bb4ee6a4SAndroid Build Coastguard Worker 
706*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
707*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
708*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
709*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
710*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
711*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
712*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
713*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
714*bb4ee6a4SAndroid Build Coastguard Worker     }
715*bb4ee6a4SAndroid Build Coastguard Worker 
716*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_input_sleep_snapshot_restore_wake()717*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_sleep_snapshot_restore_wake() {
718*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
719*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
720*bb4ee6a4SAndroid Build Coastguard Worker 
721*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
722*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
723*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
724*bb4ee6a4SAndroid Build Coastguard Worker             None,
725*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
726*bb4ee6a4SAndroid Build Coastguard Worker             None,
727*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
728*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
729*bb4ee6a4SAndroid Build Coastguard Worker         );
730*bb4ee6a4SAndroid Build Coastguard Worker 
731*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
732*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
733*bb4ee6a4SAndroid Build Coastguard Worker 
734*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
735*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
736*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
737*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
738*bb4ee6a4SAndroid Build Coastguard Worker         let sleep_res = serial.sleep();
739*bb4ee6a4SAndroid Build Coastguard Worker         match sleep_res {
740*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
741*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
742*bb4ee6a4SAndroid Build Coastguard Worker         }
743*bb4ee6a4SAndroid Build Coastguard Worker         let snap_res = serial.snapshot();
744*bb4ee6a4SAndroid Build Coastguard Worker         match snap_res {
745*bb4ee6a4SAndroid Build Coastguard Worker             Ok(snap) => {
746*bb4ee6a4SAndroid Build Coastguard Worker                 let restore_res = serial.restore(snap);
747*bb4ee6a4SAndroid Build Coastguard Worker                 match restore_res {
748*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(_rest) => (),
749*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => println!("{}", e),
750*bb4ee6a4SAndroid Build Coastguard Worker                 }
751*bb4ee6a4SAndroid Build Coastguard Worker             }
752*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
753*bb4ee6a4SAndroid Build Coastguard Worker         }
754*bb4ee6a4SAndroid Build Coastguard Worker         let wake_res = serial.wake();
755*bb4ee6a4SAndroid Build Coastguard Worker         match wake_res {
756*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
757*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
758*bb4ee6a4SAndroid Build Coastguard Worker         }
759*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
760*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
761*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
762*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
763*bb4ee6a4SAndroid Build Coastguard Worker     }
764*bb4ee6a4SAndroid Build Coastguard Worker 
765*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_input_snapshot_restore()766*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_snapshot_restore() {
767*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
768*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
769*bb4ee6a4SAndroid Build Coastguard Worker 
770*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
771*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
772*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
773*bb4ee6a4SAndroid Build Coastguard Worker             None,
774*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
775*bb4ee6a4SAndroid Build Coastguard Worker             None,
776*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
777*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
778*bb4ee6a4SAndroid Build Coastguard Worker         );
779*bb4ee6a4SAndroid Build Coastguard Worker 
780*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
781*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
782*bb4ee6a4SAndroid Build Coastguard Worker 
783*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
784*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
785*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
786*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
787*bb4ee6a4SAndroid Build Coastguard Worker         // Take snapshot after reading b'a'. Serial still contains b'b' and b'c'.
788*bb4ee6a4SAndroid Build Coastguard Worker         let snap = serial.snapshot().expect("failed to snapshot serial");
789*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
790*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
791*bb4ee6a4SAndroid Build Coastguard Worker         // Restore snapshot taken after reading b'a'. New reading should give us b'b' since it was
792*bb4ee6a4SAndroid Build Coastguard Worker         // the saved state at the moment of taking a snapshot.
793*bb4ee6a4SAndroid Build Coastguard Worker         let restore_res = serial.restore(snap);
794*bb4ee6a4SAndroid Build Coastguard Worker         match restore_res {
795*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => (),
796*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("Error: {}", e),
797*bb4ee6a4SAndroid Build Coastguard Worker         }
798*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
799*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
800*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
801*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
802*bb4ee6a4SAndroid Build Coastguard Worker     }
803*bb4ee6a4SAndroid Build Coastguard Worker 
804*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_input_snapshot_write_restore()805*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_snapshot_write_restore() {
806*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
807*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
808*bb4ee6a4SAndroid Build Coastguard Worker 
809*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
810*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
811*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
812*bb4ee6a4SAndroid Build Coastguard Worker             None,
813*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
814*bb4ee6a4SAndroid Build Coastguard Worker             None,
815*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
816*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
817*bb4ee6a4SAndroid Build Coastguard Worker         );
818*bb4ee6a4SAndroid Build Coastguard Worker 
819*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
820*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
821*bb4ee6a4SAndroid Build Coastguard Worker 
822*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
823*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
824*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
825*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
826*bb4ee6a4SAndroid Build Coastguard Worker         // Take snapshot after reading b'a'. Serial still contains b'b' and b'c'.
827*bb4ee6a4SAndroid Build Coastguard Worker         let snap = serial.snapshot().expect("failed to snapshot serial");
828*bb4ee6a4SAndroid Build Coastguard Worker         serial.clear_in_buffer();
829*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
830*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
831*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
832*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
833*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
834*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
835*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
836*bb4ee6a4SAndroid Build Coastguard Worker         // Restore snapshot taken after reading b'a'. New reading should give us b'b' since it was
837*bb4ee6a4SAndroid Build Coastguard Worker         // the saved state at the moment of taking a snapshot.
838*bb4ee6a4SAndroid Build Coastguard Worker         let restore_res = serial.restore(snap);
839*bb4ee6a4SAndroid Build Coastguard Worker         match restore_res {
840*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => (),
841*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("Error: {}", e),
842*bb4ee6a4SAndroid Build Coastguard Worker         }
843*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
844*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
845*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
846*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
847*bb4ee6a4SAndroid Build Coastguard Worker     }
848*bb4ee6a4SAndroid Build Coastguard Worker 
849*bb4ee6a4SAndroid Build Coastguard Worker     // Test should panic. Sleep, try to read while sleeping.
850*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
851*bb4ee6a4SAndroid Build Coastguard Worker     #[should_panic]
serial_input_sleep_read_panic()852*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_sleep_read_panic() {
853*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
854*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
855*bb4ee6a4SAndroid Build Coastguard Worker 
856*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
857*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
858*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
859*bb4ee6a4SAndroid Build Coastguard Worker             None,
860*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
861*bb4ee6a4SAndroid Build Coastguard Worker             None,
862*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
863*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
864*bb4ee6a4SAndroid Build Coastguard Worker         );
865*bb4ee6a4SAndroid Build Coastguard Worker 
866*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
867*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
868*bb4ee6a4SAndroid Build Coastguard Worker 
869*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
870*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
871*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
872*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
873*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
874*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
875*bb4ee6a4SAndroid Build Coastguard Worker         let sleep_res = serial.sleep();
876*bb4ee6a4SAndroid Build Coastguard Worker         match sleep_res {
877*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
878*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
879*bb4ee6a4SAndroid Build Coastguard Worker         }
880*bb4ee6a4SAndroid Build Coastguard Worker         // Test should panic when trying to read after sleep.
881*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
882*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
883*bb4ee6a4SAndroid Build Coastguard Worker     }
884*bb4ee6a4SAndroid Build Coastguard Worker 
885*bb4ee6a4SAndroid Build Coastguard Worker     // Test should panic. Sleep, try to read while sleeping.
886*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
887*bb4ee6a4SAndroid Build Coastguard Worker     #[should_panic]
serial_input_sleep_write_panic()888*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_sleep_write_panic() {
889*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
890*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
891*bb4ee6a4SAndroid Build Coastguard Worker 
892*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
893*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
894*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
895*bb4ee6a4SAndroid Build Coastguard Worker             None,
896*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
897*bb4ee6a4SAndroid Build Coastguard Worker             None,
898*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
899*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
900*bb4ee6a4SAndroid Build Coastguard Worker         );
901*bb4ee6a4SAndroid Build Coastguard Worker 
902*bb4ee6a4SAndroid Build Coastguard Worker         let sleep_res = serial.sleep();
903*bb4ee6a4SAndroid Build Coastguard Worker         match sleep_res {
904*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
905*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
906*bb4ee6a4SAndroid Build Coastguard Worker         }
907*bb4ee6a4SAndroid Build Coastguard Worker         // Test should panic when trying to read after sleep.
908*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
909*bb4ee6a4SAndroid Build Coastguard Worker     }
910*bb4ee6a4SAndroid Build Coastguard Worker 
911*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_input_sleep_wake()912*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_input_sleep_wake() {
913*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
914*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
915*bb4ee6a4SAndroid Build Coastguard Worker 
916*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
917*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
918*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt.try_clone().unwrap(),
919*bb4ee6a4SAndroid Build Coastguard Worker             None,
920*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out)),
921*bb4ee6a4SAndroid Build Coastguard Worker             None,
922*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
923*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
924*bb4ee6a4SAndroid Build Coastguard Worker         );
925*bb4ee6a4SAndroid Build Coastguard Worker 
926*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
927*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
928*bb4ee6a4SAndroid Build Coastguard Worker 
929*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(intr_evt.wait(), Ok(()));
930*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = [0u8; 1];
931*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
932*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'a');
933*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
934*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'b');
935*bb4ee6a4SAndroid Build Coastguard Worker         let sleep_res = serial.sleep();
936*bb4ee6a4SAndroid Build Coastguard Worker         match sleep_res {
937*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
938*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
939*bb4ee6a4SAndroid Build Coastguard Worker         }
940*bb4ee6a4SAndroid Build Coastguard Worker         let wake_res = serial.wake();
941*bb4ee6a4SAndroid Build Coastguard Worker         match wake_res {
942*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_res) => (),
943*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => println!("{}", e),
944*bb4ee6a4SAndroid Build Coastguard Worker         }
945*bb4ee6a4SAndroid Build Coastguard Worker         serial.read(serial_bus_address(DATA), &mut data[..]);
946*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], b'c');
947*bb4ee6a4SAndroid Build Coastguard Worker     }
948*bb4ee6a4SAndroid Build Coastguard Worker 
modify_device(serial: &mut Serial)949*bb4ee6a4SAndroid Build Coastguard Worker     fn modify_device(serial: &mut Serial) {
950*bb4ee6a4SAndroid Build Coastguard Worker         serial.clear_in_buffer();
951*bb4ee6a4SAndroid Build Coastguard Worker         serial.queue_input_bytes(b"abc").unwrap();
952*bb4ee6a4SAndroid Build Coastguard Worker     }
953*bb4ee6a4SAndroid Build Coastguard Worker 
954*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
955*bb4ee6a4SAndroid Build Coastguard Worker         serial,
956*bb4ee6a4SAndroid Build Coastguard Worker         Serial::new(
957*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
958*bb4ee6a4SAndroid Build Coastguard Worker             Event::new().unwrap(),
959*bb4ee6a4SAndroid Build Coastguard Worker             None,
960*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(SharedBuffer::new())),
961*bb4ee6a4SAndroid Build Coastguard Worker             None,
962*bb4ee6a4SAndroid Build Coastguard Worker             Default::default(),
963*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
964*bb4ee6a4SAndroid Build Coastguard Worker         ),
965*bb4ee6a4SAndroid Build Coastguard Worker         modify_device
966*bb4ee6a4SAndroid Build Coastguard Worker     );
967*bb4ee6a4SAndroid Build Coastguard Worker 
assert_timestamp_is_present(data: &[u8], serial_message: &str)968*bb4ee6a4SAndroid Build Coastguard Worker     fn assert_timestamp_is_present(data: &[u8], serial_message: &str) {
969*bb4ee6a4SAndroid Build Coastguard Worker         const TIMESTAMP_START: &str = "[";
970*bb4ee6a4SAndroid Build Coastguard Worker         const TIMESTAMP_END: &str = "]: ";
971*bb4ee6a4SAndroid Build Coastguard Worker 
972*bb4ee6a4SAndroid Build Coastguard Worker         let data_str = std::str::from_utf8(data).unwrap();
973*bb4ee6a4SAndroid Build Coastguard Worker         let timestamp_bracket = data_str
974*bb4ee6a4SAndroid Build Coastguard Worker             .find(TIMESTAMP_END)
975*bb4ee6a4SAndroid Build Coastguard Worker             .expect("missing timestamp end bracket");
976*bb4ee6a4SAndroid Build Coastguard Worker         let (timestamp, message) = data_str.split_at(timestamp_bracket + TIMESTAMP_END.len());
977*bb4ee6a4SAndroid Build Coastguard Worker 
978*bb4ee6a4SAndroid Build Coastguard Worker         assert!(timestamp.starts_with(TIMESTAMP_START));
979*bb4ee6a4SAndroid Build Coastguard Worker         assert!(timestamp.ends_with(TIMESTAMP_END));
980*bb4ee6a4SAndroid Build Coastguard Worker 
981*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(message.trim_end(), serial_message);
982*bb4ee6a4SAndroid Build Coastguard Worker     }
983*bb4ee6a4SAndroid Build Coastguard Worker 
984*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serial_output_timestamp()985*bb4ee6a4SAndroid Build Coastguard Worker     fn serial_output_timestamp() {
986*bb4ee6a4SAndroid Build Coastguard Worker         let intr_evt = Event::new().unwrap();
987*bb4ee6a4SAndroid Build Coastguard Worker         let serial_out = SharedBuffer::new();
988*bb4ee6a4SAndroid Build Coastguard Worker 
989*bb4ee6a4SAndroid Build Coastguard Worker         let mut serial = Serial::new(
990*bb4ee6a4SAndroid Build Coastguard Worker             ProtectionType::Unprotected,
991*bb4ee6a4SAndroid Build Coastguard Worker             intr_evt,
992*bb4ee6a4SAndroid Build Coastguard Worker             None,
993*bb4ee6a4SAndroid Build Coastguard Worker             Some(Box::new(serial_out.clone())),
994*bb4ee6a4SAndroid Build Coastguard Worker             None,
995*bb4ee6a4SAndroid Build Coastguard Worker             SerialOptions {
996*bb4ee6a4SAndroid Build Coastguard Worker                 out_timestamp: true,
997*bb4ee6a4SAndroid Build Coastguard Worker                 ..Default::default()
998*bb4ee6a4SAndroid Build Coastguard Worker             },
999*bb4ee6a4SAndroid Build Coastguard Worker             Vec::new(),
1000*bb4ee6a4SAndroid Build Coastguard Worker         );
1001*bb4ee6a4SAndroid Build Coastguard Worker 
1002*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"a");
1003*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"\n");
1004*bb4ee6a4SAndroid Build Coastguard Worker         assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "a");
1005*bb4ee6a4SAndroid Build Coastguard Worker         serial_out.buf.lock().clear();
1006*bb4ee6a4SAndroid Build Coastguard Worker 
1007*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"b");
1008*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"\n");
1009*bb4ee6a4SAndroid Build Coastguard Worker         assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "b");
1010*bb4ee6a4SAndroid Build Coastguard Worker         serial_out.buf.lock().clear();
1011*bb4ee6a4SAndroid Build Coastguard Worker 
1012*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"c");
1013*bb4ee6a4SAndroid Build Coastguard Worker         serial.write(serial_bus_address(DATA), b"\n");
1014*bb4ee6a4SAndroid Build Coastguard Worker         assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "c");
1015*bb4ee6a4SAndroid Build Coastguard Worker         serial_out.buf.lock().clear();
1016*bb4ee6a4SAndroid Build Coastguard Worker     }
1017*bb4ee6a4SAndroid Build Coastguard Worker }
1018