xref: /aosp_15_r20/external/crosvm/arch/src/serial/sys/windows.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #![allow(dead_code)]
6 
7 use std::io::Read;
8 use std::sync::Arc;
9 use std::thread;
10 use std::time::Duration;
11 
12 use base::RawDescriptor;
13 use base::Result;
14 use devices::serial_device::SerialParameters;
15 use devices::serial_device::SerialType;
16 use devices::BusDevice;
17 use devices::Serial;
18 use jail::FakeMinijailStub as Minijail;
19 use sync::Mutex;
20 
21 use crate::DeviceRegistrationError;
22 
23 /// A type for queueing input bytes to a serial device that abstracts if the device is local or part
24 /// of a sandboxed device process.
25 /// TODO(b/160806152) rizhang: Move to different file for readability.
26 pub enum SerialInput {
27     #[doc(hidden)]
28     Local(Arc<Mutex<Serial>>),
29 }
30 
31 impl SerialInput {
32     /// Creates a `SerialInput` that trivially forwards queued bytes to the device in the local
33     /// process.
new_local(serial: Arc<Mutex<Serial>>) -> SerialInput34     pub fn new_local(serial: Arc<Mutex<Serial>>) -> SerialInput {
35         SerialInput::Local(serial)
36     }
37 
38     /// Just like `Serial::queue_input_bytes`, but abstracted over local and sandboxed serial
39     /// devices.
queue_input_bytes(&self, bytes: &[u8]) -> Result<()>40     pub fn queue_input_bytes(&self, bytes: &[u8]) -> Result<()> {
41         match self {
42             SerialInput::Local(device) => device.lock().queue_input_bytes(bytes),
43         }
44     }
45 }
46 
add_serial_device( com: Serial, serial_params: &SerialParameters, serial_jail: Option<Minijail>, _preserved_descriptors: Vec<RawDescriptor>, ) -> std::result::Result<Arc<Mutex<dyn BusDevice>>, DeviceRegistrationError>47 pub fn add_serial_device(
48     com: Serial,
49     serial_params: &SerialParameters,
50     serial_jail: Option<Minijail>,
51     _preserved_descriptors: Vec<RawDescriptor>,
52 ) -> std::result::Result<Arc<Mutex<dyn BusDevice>>, DeviceRegistrationError> {
53     assert!(serial_jail.is_none());
54 
55     let com = Arc::new(Mutex::new(com));
56 
57     if !serial_params.stdin {
58         if let SerialType::SystemSerialType = serial_params.type_ {
59             let mut in_pipe_result = com
60                 .lock()
61                 .system_params
62                 .in_stream
63                 .as_ref()
64                 .unwrap()
65                 .try_clone();
66             let com = com.clone();
67             thread::spawn(move || {
68                 let serial_input = SerialInput::new_local(com);
69                 let in_pipe = in_pipe_result.as_mut().unwrap();
70 
71                 let mut buffer: [u8; 255] = [0; 255];
72                 loop {
73                     // Safe because we are reading bytes.
74                     let bytes = in_pipe.read(&mut buffer).unwrap_or(0);
75                     if bytes > 0 {
76                         serial_input.queue_input_bytes(&buffer[0..bytes]).unwrap();
77                     }
78                     // We can't issue blocking reads here and overlapped I/O is
79                     // incompatible with the call site where writes to this pipe are being
80                     // made, so instead we issue a small wait to prevent us from hogging
81                     // the CPU. This 20ms delay while typing doesn't seem to be noticeable.
82                     thread::sleep(Duration::from_millis(20));
83                 }
84             });
85         }
86     }
87 
88     Ok(com)
89 }
90