opentitanlib/io/console/
buf.rs1use std::sync::Mutex;
6use std::task::{Context, Poll, ready};
7
8use anyhow::Result;
9
10use super::ConsoleDevice;
11use crate::io::uart::{FlowControl, Parity, Uart};
12
13pub struct Buffered<T> {
15 inner: T,
16 buffer: Mutex<Inner>,
17}
18
19struct Inner {
20 buffer: Box<[u8; 256]>,
21 len: usize,
22 offset: usize,
23}
24
25impl<T> Buffered<T> {
26 pub fn new(inner: T) -> Self {
27 Self {
28 inner,
29 buffer: Mutex::new(Inner {
30 buffer: vec![0; 256].try_into().unwrap(),
31 len: 0,
32 offset: 0,
33 }),
34 }
35 }
36}
37
38impl<T: ConsoleDevice> ConsoleDevice for Buffered<T> {
39 fn poll_read(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
40 let mut buffer = self.buffer.lock().unwrap();
41
42 loop {
43 if buffer.len != 0 {
44 let copy_len = std::cmp::min(buffer.len, buf.len());
45 buf[..copy_len].copy_from_slice(&buffer.buffer[buffer.offset..][..copy_len]);
46 buffer.offset += copy_len;
47 buffer.len -= copy_len;
48 return Poll::Ready(Ok(copy_len));
49 }
50
51 if buf.len() >= buffer.buffer.len() {
52 return self.inner.poll_read(cx, buf);
53 }
54
55 buffer.len = ready!(self.inner.poll_read(cx, &mut buffer.buffer[..]))?;
56 buffer.offset = 0;
57 }
58 }
59
60 fn write(&self, buf: &[u8]) -> Result<()> {
61 self.inner.write(buf)
62 }
63}
64
65impl<T: Uart> Uart for Buffered<T> {
66 fn get_baudrate(&self) -> Result<u32> {
67 self.inner.get_baudrate()
68 }
69
70 fn set_baudrate(&self, baudrate: u32) -> Result<()> {
71 self.inner.set_baudrate(baudrate)
72 }
73
74 fn get_flow_control(&self) -> Result<FlowControl> {
75 self.inner.get_flow_control()
76 }
77
78 fn set_flow_control(&self, flow_control: bool) -> Result<()> {
79 self.inner.set_flow_control(flow_control)
80 }
81
82 fn get_device_path(&self) -> Result<String> {
83 self.inner.get_device_path()
84 }
85
86 fn clear_rx_buffer(&self) -> Result<()> {
87 let mut buffer = self.buffer.lock().unwrap();
88 buffer.offset = 0;
89 buffer.len = 0;
90
91 self.inner.clear_rx_buffer()?;
92 Ok(())
93 }
94
95 fn set_parity(&self, parity: Parity) -> Result<()> {
96 self.inner.set_parity(parity)
97 }
98
99 fn get_parity(&self) -> Result<Parity> {
100 self.inner.get_parity()
101 }
102
103 fn set_break(&self, enable: bool) -> Result<()> {
104 self.inner.set_break(enable)
105 }
106}