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