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