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