• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::Bus;
17 use devices::Serial;
18 use jail::FakeMinijailStub as Minijail;
19 use sync::Mutex;
20 
21 use crate::serial::SERIAL_ADDR;
22 use crate::DeviceRegistrationError;
23 
24 /// A type for queueing input bytes to a serial device that abstracts if the device is local or part
25 /// of a sandboxed device process.
26 /// TODO(b/160806152) rizhang: Move to different file for readability.
27 pub enum SerialInput {
28     #[doc(hidden)]
29     Local(Arc<Mutex<Serial>>),
30 }
31 
32 impl SerialInput {
33     /// Creates a `SerialInput` that trivially forwards queued bytes to the device in the local
34     /// process.
new_local(serial: Arc<Mutex<Serial>>) -> SerialInput35     pub fn new_local(serial: Arc<Mutex<Serial>>) -> SerialInput {
36         SerialInput::Local(serial)
37     }
38 
39     /// Just like `Serial::queue_input_bytes`, but abstracted over local and sandboxed serial
40     /// devices.
queue_input_bytes(&self, bytes: &[u8]) -> Result<()>41     pub fn queue_input_bytes(&self, bytes: &[u8]) -> Result<()> {
42         match self {
43             SerialInput::Local(device) => device.lock().queue_input_bytes(bytes),
44         }
45     }
46 }
47 
add_serial_device( com_num: usize, com: Serial, serial_params: &SerialParameters, serial_jail: Option<Minijail>, _preserved_descriptors: Vec<RawDescriptor>, io_bus: &Bus, ) -> std::result::Result<(), DeviceRegistrationError>48 pub fn add_serial_device(
49     com_num: usize,
50     com: Serial,
51     serial_params: &SerialParameters,
52     serial_jail: Option<Minijail>,
53     _preserved_descriptors: Vec<RawDescriptor>,
54     io_bus: &Bus,
55 ) -> std::result::Result<(), DeviceRegistrationError> {
56     match serial_jail {
57         Some(_) => (),
58         None => {
59             let com = Arc::new(Mutex::new(com));
60             io_bus
61                 .insert(com.clone(), SERIAL_ADDR[com_num], 0x8)
62                 .unwrap();
63 
64             if !serial_params.stdin {
65                 if let SerialType::SystemSerialType = serial_params.type_ {
66                     let mut in_pipe_result = com
67                         .lock()
68                         .system_params
69                         .in_stream
70                         .as_ref()
71                         .unwrap()
72                         .try_clone();
73                     thread::spawn(move || {
74                         let serial_input = SerialInput::new_local(com);
75                         let in_pipe = in_pipe_result.as_mut().unwrap();
76 
77                         let mut buffer: [u8; 255] = [0; 255];
78                         loop {
79                             // Safe because we are reading bytes.
80                             let bytes = in_pipe.read(&mut buffer).unwrap_or(0);
81                             if bytes > 0 {
82                                 serial_input.queue_input_bytes(&buffer[0..bytes]).unwrap();
83                             }
84                             // We can't issue blocking reads here and overlapped I/O is
85                             // incompatible with the call site where writes to this pipe are being
86                             // made, so instead we issue a small wait to prevent us from hogging
87                             // the CPU. This 20ms delay while typing doesn't seem to be noticeable.
88                             thread::sleep(Duration::from_millis(20));
89                         }
90                     });
91                 }
92             }
93         }
94     }
95     Ok(())
96 }
97