opentitanlib/io/uart/
flow.rs1use std::cell::{Cell, RefCell};
6use std::collections::VecDeque;
7use std::os::fd::BorrowedFd;
8use std::task::{Context, Poll, Waker, ready};
9use std::time::Duration;
10
11use anyhow::{Context as _, Result};
12
13use super::{FlowControl, Parity, Uart};
14use crate::io::console::ConsoleDevice;
15
16pub struct SoftwareFlowControl<T> {
20 inner: T,
21 flow_control: Cell<FlowControl>,
22 rxbuf: RefCell<VecDeque<u8>>,
23}
24
25impl<T: Uart> SoftwareFlowControl<T> {
26 pub fn new(inner: T) -> Self {
28 SoftwareFlowControl {
29 inner,
30 flow_control: Cell::new(FlowControl::None),
31 rxbuf: RefCell::default(),
32 }
33 }
34
35 fn poll_read_to_buffer(&self, cx: &mut Context<'_>) -> Poll<Result<()>> {
39 let mut buf = [0u8; 256];
40 let len = ready!(self.inner.poll_read(cx, &mut buf)).context("UART read error")?;
41
42 for &ch in &buf[..len] {
43 if self.flow_control.get() != FlowControl::None {
44 if ch == FlowControl::Resume as u8 {
45 log::debug!("Got RESUME");
46 self.flow_control.set(FlowControl::Resume);
47 continue;
48 } else if ch == FlowControl::Pause as u8 {
49 log::debug!("Got PAUSE");
50 self.flow_control.set(FlowControl::Pause);
51 continue;
52 }
53 }
54 self.rxbuf.borrow_mut().push_back(ch);
55 }
56 Poll::Ready(Ok(()))
57 }
58}
59
60impl<T: Uart> ConsoleDevice for SoftwareFlowControl<T> {
61 fn poll_read(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
62 let mut rxbuf = self.rxbuf.borrow_mut();
63
64 while rxbuf.is_empty() {
65 drop(rxbuf);
66 ready!(self.poll_read_to_buffer(cx))?;
67 rxbuf = self.rxbuf.borrow_mut();
68 }
69
70 let (front, back) = rxbuf.as_slices();
72
73 let front_copy = std::cmp::min(buf.len(), front.len());
74 buf[..front_copy].copy_from_slice(&front[..front_copy]);
75
76 let back_copy = std::cmp::min(buf.len() - front_copy, back.len());
77 buf[front_copy..][..back_copy].copy_from_slice(&back[..back_copy]);
78
79 let copy_len = front_copy + back_copy;
80 rxbuf.drain(..copy_len);
81 Poll::Ready(Ok(copy_len))
82 }
83
84 fn write(&self, buf: &[u8]) -> Result<()> {
86 if self.flow_control.get() == FlowControl::None {
87 return self.inner.write(buf);
88 }
89
90 let pacing = Duration::from_nanos(10 * 1_000_000_000u64 / (self.get_baudrate()? as u64));
92 log::debug!(
93 "flow control: {:?}, pacing = {:?}",
94 self.flow_control.get(),
95 pacing
96 );
97
98 for b in buf.iter() {
99 loop {
102 let _ = self.poll_read_to_buffer(&mut Context::from_waker(Waker::noop()))?;
103 if self.flow_control.get() == FlowControl::Resume {
105 break;
106 }
107 std::thread::sleep(pacing);
109 }
110 self.inner
111 .write(std::slice::from_ref(b))
112 .context("UART write error")?;
113 std::thread::sleep(pacing);
118 }
119 Ok(())
120 }
121}
122
123impl<T: Uart> Uart for SoftwareFlowControl<T> {
124 fn get_baudrate(&self) -> Result<u32> {
125 self.inner.get_baudrate()
126 }
127
128 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
130 self.inner.set_baudrate(baudrate)
131 }
132
133 fn get_flow_control(&self) -> Result<FlowControl> {
134 Ok(self.flow_control.get())
135 }
136
137 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
138 self.flow_control.set(match flow_control {
139 false => FlowControl::None,
140 true => FlowControl::Resume,
143 });
144 Ok(())
145 }
146
147 fn get_device_path(&self) -> Result<String> {
148 self.inner.get_device_path()
149 }
150
151 fn set_parity(&self, parity: Parity) -> Result<()> {
152 self.inner.set_parity(parity)
153 }
154
155 fn clear_rx_buffer(&self) -> Result<()> {
157 self.rxbuf.borrow_mut().clear();
158
159 self.inner.clear_rx_buffer()
161 }
162
163 fn set_break(&self, enable: bool) -> Result<()> {
164 self.inner.set_break(enable)
165 }
166
167 fn borrow_fd(&self) -> Result<BorrowedFd<'_>> {
168 self.inner.borrow_fd()
169 }
170}