opentitanlib/io/uart/
mod.rs1use std::io::{self, Read};
6use std::os::fd::BorrowedFd;
7use std::rc::Rc;
8use std::time::Duration;
9
10use anyhow::Result;
11use clap::Args;
12use serde::{Deserialize, Serialize};
13pub use serialport::Parity;
14use thiserror::Error;
15
16use crate::app::TransportWrapper;
17use crate::impl_serializable_error;
18use crate::io::console::{ConsoleDevice, ConsoleExt};
19use crate::transport::TransportError;
20
21pub mod flow;
22pub mod serial;
23
24#[derive(Clone, Debug, Default, Args, Serialize, Deserialize)]
25pub struct UartParams {
26 #[arg(long, default_value = "CONSOLE")]
28 uart: String,
29
30 #[arg(long)]
32 baudrate: Option<u32>,
33
34 #[arg(long)]
36 flow_control: bool,
37}
38
39impl UartParams {
40 pub fn create(&self, transport: &TransportWrapper) -> Result<Rc<dyn Uart>> {
41 let uart = transport.uart(&self.uart)?;
42 if let Some(baudrate) = self.baudrate {
43 uart.set_baudrate(baudrate)?;
44 }
45 log::info!("set_flow_control to {}", self.flow_control);
46 uart.set_flow_control(self.flow_control)?;
47 Ok(uart)
48 }
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
52#[repr(u8)]
53pub enum FlowControl {
54 None = 0,
56 Pause = 19,
58 Resume = 17,
60}
61
62pub trait Uart: ConsoleDevice {
64 fn get_baudrate(&self) -> Result<u32>;
66
67 fn set_baudrate(&self, baudrate: u32) -> Result<()>;
69
70 fn get_flow_control(&self) -> Result<FlowControl> {
72 unimplemented!();
73 }
74
75 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
77 if flow_control {
78 unimplemented!();
79 }
80 Ok(())
81 }
82
83 fn get_device_path(&self) -> Result<String> {
86 Err(TransportError::UnsupportedOperation.into())
87 }
88
89 fn clear_rx_buffer(&self) -> Result<()> {
91 const TIMEOUT: Duration = Duration::from_millis(5);
94 let mut buf = [0u8; 256];
95 while self.read_timeout(&mut buf, TIMEOUT)? > 0 {}
96 Ok(())
97 }
98
99 fn set_parity(&self, _parity: Parity) -> Result<()> {
100 Err(TransportError::UnsupportedOperation.into())
101 }
102
103 fn get_parity(&self) -> Result<Parity> {
104 Err(TransportError::UnsupportedOperation.into())
105 }
106
107 fn set_break(&self, _enable: bool) -> Result<()> {
108 Err(TransportError::UnsupportedOperation.into())
109 }
110
111 fn borrow_fd(&self) -> Result<BorrowedFd<'_>> {
112 Err(TransportError::UnsupportedOperation.into())
113 }
114}
115
116impl<T: Uart + ?Sized> Uart for &T {
117 fn get_baudrate(&self) -> Result<u32> {
118 T::get_baudrate(self)
119 }
120
121 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
122 T::set_baudrate(self, baudrate)
123 }
124
125 fn get_flow_control(&self) -> Result<FlowControl> {
126 T::get_flow_control(self)
127 }
128
129 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
130 T::set_flow_control(self, flow_control)
131 }
132
133 fn get_device_path(&self) -> Result<String> {
134 T::get_device_path(self)
135 }
136
137 fn clear_rx_buffer(&self) -> Result<()> {
138 T::clear_rx_buffer(self)
139 }
140
141 fn set_parity(&self, parity: Parity) -> Result<()> {
142 T::set_parity(self, parity)
143 }
144
145 fn get_parity(&self) -> Result<Parity> {
146 T::get_parity(self)
147 }
148
149 fn set_break(&self, enable: bool) -> Result<()> {
150 T::set_break(self, enable)
151 }
152}
153
154impl<T: Uart + ?Sized> Uart for Rc<T> {
155 fn get_baudrate(&self) -> Result<u32> {
156 T::get_baudrate(self)
157 }
158
159 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
160 T::set_baudrate(self, baudrate)
161 }
162
163 fn get_flow_control(&self) -> Result<FlowControl> {
164 T::get_flow_control(self)
165 }
166
167 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
168 T::set_flow_control(self, flow_control)
169 }
170
171 fn get_device_path(&self) -> Result<String> {
172 T::get_device_path(self)
173 }
174
175 fn clear_rx_buffer(&self) -> Result<()> {
176 T::clear_rx_buffer(self)
177 }
178
179 fn set_parity(&self, parity: Parity) -> Result<()> {
180 T::set_parity(self, parity)
181 }
182
183 fn get_parity(&self) -> Result<Parity> {
184 T::get_parity(self)
185 }
186
187 fn set_break(&self, enable: bool) -> Result<()> {
188 T::set_break(self, enable)
189 }
190
191 fn borrow_fd(&self) -> Result<BorrowedFd<'_>> {
192 Err(TransportError::UnsupportedOperation.into())
193 }
194}
195
196impl Read for &dyn Uart {
197 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
198 ConsoleExt::read(&**self, buf).map_err(io::Error::other)
199 }
200}
201
202#[derive(Error, Debug, Serialize, Deserialize)]
204pub enum UartError {
205 #[error("Enumerating: {0}")]
206 EnumerationError(String),
207 #[error("Opening: {0}")]
208 OpenError(String),
209 #[error("Invalid option: {0}")]
210 InvalidOption(String),
211 #[error("Invalid speed: {0}")]
212 InvalidSpeed(u32),
213 #[error("Reading: {0}")]
214 ReadError(String),
215 #[error("Writing: {0}")]
216 WriteError(String),
217 #[error("{0}")]
218 GenericError(String),
219}
220impl_serializable_error!(UartError);