opentitanlib/transport/common/
uart.rs1use std::cell::{Cell, RefCell};
6use std::collections::VecDeque;
7use std::io::{ErrorKind, Read, Write};
8use std::os::fd::{AsRawFd, BorrowedFd};
9use std::task::{Context, Poll, Waker, ready};
10use std::time::Duration;
11
12use anyhow::{Context as _, Result};
13use serialport::{ClearBuffer, Parity, SerialPort, TTYPort};
14use tokio::io::unix::AsyncFd;
15
16use crate::io::uart::{FlowControl, Uart, UartError};
18use crate::transport::TransportError;
19use crate::util;
20use crate::util::runtime::MultiWaker;
21
22pub struct SerialPortUart {
24 port_name: String,
25 port: RefCell<AsyncFd<TTYPort>>,
26 pseudo_baud: Cell<u32>,
27 multi_waker: MultiWaker,
28}
29
30impl SerialPortUart {
31 const FOREVER: Duration = Duration::from_secs(100 * 365 * 86400);
37
38 pub fn open(port_name: &str, baud: u32) -> Result<Self> {
40 let port = TTYPort::open(&serialport::new(port_name, baud).preserve_dtr_on_open())
41 .map_err(|e| UartError::OpenError(e.to_string()))?;
42 let _runtime_guard = crate::util::runtime().enter();
43 let port = AsyncFd::new(port)?;
44 flock_serial(port.get_ref(), port_name)?;
45 Ok(SerialPortUart {
46 port_name: port_name.to_string(),
47 port: RefCell::new(port),
48 pseudo_baud: Cell::new(0),
49 multi_waker: MultiWaker::new(),
50 })
51 }
52
53 pub fn open_pseudo(port_name: &str, baud: u32) -> Result<Self> {
55 let port = TTYPort::open(&serialport::new(port_name, baud).preserve_dtr_on_open())
56 .map_err(|e| UartError::OpenError(e.to_string()))?;
57 let _runtime_guard = crate::util::runtime().enter();
58 let port = AsyncFd::new(port)?;
59 flock_serial(port.get_ref(), port_name)?;
60 Ok(SerialPortUart {
61 port_name: port_name.to_string(),
62 port: RefCell::new(port),
63 pseudo_baud: Cell::new(baud),
64 multi_waker: MultiWaker::new(),
65 })
66 }
67}
68
69impl Uart for SerialPortUart {
70 fn get_baudrate(&self) -> Result<u32> {
72 let pseudo = self.pseudo_baud.get();
73 if pseudo == 0 {
74 self.port
75 .borrow()
76 .get_ref()
77 .baud_rate()
78 .context("getting baudrate")
79 } else {
80 Ok(pseudo)
81 }
82 }
83
84 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
86 let pseudo = self.pseudo_baud.get();
87 if pseudo == 0 {
88 self.port
89 .borrow_mut()
90 .get_mut()
91 .set_baud_rate(baudrate)
92 .map_err(|_| UartError::InvalidSpeed(baudrate))?;
93 } else {
94 self.pseudo_baud.set(baudrate);
95 }
96 Ok(())
97 }
98
99 fn get_device_path(&self) -> Result<String> {
100 Ok(self.port_name.clone())
101 }
102
103 fn poll_read(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
104 let mut port = self.port.borrow_mut();
105
106 loop {
107 let mut guard = ready!(
108 self.multi_waker
109 .poll_with(cx, |cx| port.poll_read_ready_mut(cx))
110 )?;
111
112 match guard.try_io(|inner| {
113 inner.get_mut().set_timeout(Duration::ZERO)?;
114 let result = match inner.get_mut().read(buf) {
115 Ok(n) => Ok(n),
116 Err(ioerr) if ioerr.kind() == ErrorKind::TimedOut => {
117 Err(std::io::Error::new(std::io::ErrorKind::WouldBlock, ioerr))
118 }
119 Err(ioerr) => Err(ioerr)?,
120 };
121 inner.get_mut().set_timeout(Self::FOREVER)?;
122 result
123 }) {
124 Ok(result) => return Poll::Ready(Ok(result?)),
125 Err(_would_block) => continue,
126 }
127 }
128 }
129
130 fn write(&self, buf: &[u8]) -> Result<()> {
132 let mut port = self.port.borrow_mut();
135 let mut idx = 0;
136 while idx < buf.len() {
137 match port.get_mut().write(&buf[idx..]) {
138 Ok(n) => idx += n,
139 Err(ioerr) if ioerr.kind() == ErrorKind::TimedOut => {
140 util::file::wait_timeout(
144 unsafe { BorrowedFd::borrow_raw(port.as_raw_fd()) },
146 rustix::event::PollFlags::OUT,
147 Duration::from_secs(5),
148 )?;
149 }
150 Err(ioerr) => return Err(ioerr).context("UART communication error"),
151 }
152 }
153
154 Ok(())
155 }
156
157 fn set_break(&self, enable: bool) -> Result<()> {
158 let mut port = self.port.borrow_mut();
159 if enable {
160 port.get_mut().set_break()?;
161 } else {
162 port.get_mut().clear_break()?;
163 }
164 Ok(())
165 }
166
167 fn set_parity(&self, parity: Parity) -> Result<()> {
168 self.port.borrow_mut().get_mut().set_parity(parity)?;
169 Ok(())
170 }
171
172 fn clear_rx_buffer(&self) -> Result<()> {
174 self.port.borrow_mut().get_mut().clear(ClearBuffer::Input)?;
175
176 const TIMEOUT: Duration = Duration::from_millis(5);
186 let mut buf = [0u8; 256];
187 while self.read_timeout(&mut buf, TIMEOUT)? > 0 {}
188 Ok(())
189 }
190}
191
192pub fn flock_serial(port: &TTYPort, port_name: &str) -> Result<()> {
195 let fd = unsafe { BorrowedFd::borrow_raw(port.as_raw_fd()) };
197 rustix::fs::flock(fd, rustix::fs::FlockOperation::NonBlockingLockExclusive).map_err(|_| {
198 TransportError::OpenError(port_name.to_string(), "Device is locked".to_string())
199 })?;
200 Ok(())
201}
202
203pub struct SoftwareFlowControl<T> {
207 inner: T,
208 flow_control: Cell<FlowControl>,
209 rxbuf: RefCell<VecDeque<u8>>,
210}
211
212impl<T: Uart> SoftwareFlowControl<T> {
213 pub fn new(inner: T) -> Self {
215 SoftwareFlowControl {
216 inner,
217 flow_control: Cell::new(FlowControl::None),
218 rxbuf: RefCell::default(),
219 }
220 }
221
222 fn poll_read_to_buffer(&self, cx: &mut Context<'_>) -> Poll<Result<()>> {
226 let mut buf = [0u8; 256];
227 let len = ready!(self.inner.poll_read(cx, &mut buf)).context("UART read error")?;
228
229 for &ch in &buf[..len] {
230 if self.flow_control.get() != FlowControl::None {
231 if ch == FlowControl::Resume as u8 {
232 log::debug!("Got RESUME");
233 self.flow_control.set(FlowControl::Resume);
234 continue;
235 } else if ch == FlowControl::Pause as u8 {
236 log::debug!("Got PAUSE");
237 self.flow_control.set(FlowControl::Pause);
238 continue;
239 }
240 }
241 self.rxbuf.borrow_mut().push_back(ch);
242 }
243 Poll::Ready(Ok(()))
244 }
245}
246
247impl<T: Uart> Uart for SoftwareFlowControl<T> {
248 fn get_baudrate(&self) -> Result<u32> {
249 self.inner.get_baudrate()
250 }
251
252 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
254 self.inner.set_baudrate(baudrate)
255 }
256
257 fn get_flow_control(&self) -> Result<FlowControl> {
258 Ok(self.flow_control.get())
259 }
260
261 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
262 self.flow_control.set(match flow_control {
263 false => FlowControl::None,
264 true => FlowControl::Resume,
267 });
268 Ok(())
269 }
270
271 fn get_device_path(&self) -> Result<String> {
272 self.inner.get_device_path()
273 }
274
275 fn poll_read(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
276 let mut rxbuf = self.rxbuf.borrow_mut();
277
278 while rxbuf.is_empty() {
279 drop(rxbuf);
280 ready!(self.poll_read_to_buffer(cx))?;
281 rxbuf = self.rxbuf.borrow_mut();
282 }
283
284 let (front, back) = rxbuf.as_slices();
286
287 let front_copy = std::cmp::min(buf.len(), front.len());
288 buf[..front_copy].copy_from_slice(&front[..front_copy]);
289
290 let back_copy = std::cmp::min(buf.len() - front_copy, back.len());
291 buf[front_copy..][..back_copy].copy_from_slice(&back[..back_copy]);
292
293 let copy_len = front_copy + back_copy;
294 rxbuf.drain(..copy_len);
295 Poll::Ready(Ok(copy_len))
296 }
297
298 fn write(&self, buf: &[u8]) -> Result<()> {
300 if self.flow_control.get() == FlowControl::None {
301 return self.inner.write(buf);
302 }
303
304 let pacing = Duration::from_nanos(10 * 1_000_000_000u64 / (self.get_baudrate()? as u64));
306 log::debug!(
307 "flow control: {:?}, pacing = {:?}",
308 self.flow_control.get(),
309 pacing
310 );
311
312 for b in buf.iter() {
313 loop {
316 let _ = self.poll_read_to_buffer(&mut Context::from_waker(Waker::noop()))?;
317 if self.flow_control.get() == FlowControl::Resume {
319 break;
320 }
321 std::thread::sleep(pacing);
323 }
324 self.inner
325 .write(std::slice::from_ref(b))
326 .context("UART write error")?;
327 std::thread::sleep(pacing);
332 }
333 Ok(())
334 }
335
336 fn set_break(&self, enable: bool) -> Result<()> {
337 self.inner.set_break(enable)
338 }
339
340 fn set_parity(&self, parity: Parity) -> Result<()> {
341 self.inner.set_parity(parity)
342 }
343
344 fn clear_rx_buffer(&self) -> Result<()> {
346 self.rxbuf.borrow_mut().clear();
347
348 self.inner.clear_rx_buffer()
350 }
351}