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 Read for &dyn Uart {
117 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
118 ConsoleExt::read(&**self, buf).map_err(io::Error::other)
119 }
120}
121
122#[derive(Error, Debug, Serialize, Deserialize)]
124pub enum UartError {
125 #[error("Enumerating: {0}")]
126 EnumerationError(String),
127 #[error("Opening: {0}")]
128 OpenError(String),
129 #[error("Invalid option: {0}")]
130 InvalidOption(String),
131 #[error("Invalid speed: {0}")]
132 InvalidSpeed(u32),
133 #[error("Reading: {0}")]
134 ReadError(String),
135 #[error("Writing: {0}")]
136 WriteError(String),
137 #[error("{0}")]
138 GenericError(String),
139}
140impl_serializable_error!(UartError);