virtio_drivers/device/console/
embedded_io.rs1use super::VirtIOConsole;
4use crate::{Error, Hal, transport::Transport};
5use core::cmp::min;
6use embedded_io::{BufRead, ErrorType, Read, ReadReady, Write};
7
8impl<H: Hal, T: Transport> ErrorType for VirtIOConsole<H, T> {
9 type Error = Error;
10}
11
12impl<H: Hal, T: Transport> Write for VirtIOConsole<H, T> {
13 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
14 if buf.is_empty() {
15 Ok(0)
16 } else {
17 self.send_bytes(buf)?;
18 Ok(buf.len())
19 }
20 }
21
22 fn flush(&mut self) -> Result<(), Self::Error> {
23 Ok(())
25 }
26}
27
28impl<H: Hal, T: Transport> ReadReady for VirtIOConsole<H, T> {
29 fn read_ready(&mut self) -> Result<bool, Self::Error> {
30 self.finish_receive()?;
31 Ok(self.cursor != self.pending_len)
32 }
33}
34
35impl<H: Hal, T: Transport> Read for VirtIOConsole<H, T> {
36 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
37 if buf.is_empty() {
38 Ok(0)
39 } else {
40 self.wait_for_receive()?;
41 let read_length = min(buf.len(), self.pending_len - self.cursor);
42 buf[..read_length]
43 .copy_from_slice(&self.queue_buf_rx[self.cursor..self.cursor + read_length]);
44 self.cursor += read_length;
45 Ok(read_length)
46 }
47 }
48}
49
50impl<H: Hal, T: Transport> BufRead for VirtIOConsole<H, T> {
51 fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
52 self.wait_for_receive()?;
53 Ok(&self.queue_buf_rx[self.cursor..self.pending_len])
54 }
55
56 fn consume(&mut self, amt: usize) {
57 assert!(self.cursor + amt <= self.pending_len);
58 self.cursor += amt;
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use alloc::{sync::Arc, vec};
65 use embedded_io::{BufRead, Read};
66 use std::{sync::Mutex, thread};
67
68 use crate::{
69 config::{ReadOnly, WriteOnly},
70 device::console::{Config, QUEUE_RECEIVEQ_PORT_0, QUEUE_SIZE, VirtIOConsole},
71 hal::fake::FakeHal,
72 transport::{
73 DeviceType,
74 fake::{FakeTransport, QueueStatus, State},
75 },
76 };
77
78 fn setup_test() -> (
79 VirtIOConsole<FakeHal, FakeTransport<Config>>,
80 Arc<Mutex<State<Config>>>,
81 ) {
82 let config_space = Config {
83 cols: ReadOnly::new(80),
84 rows: ReadOnly::new(24),
85 max_nr_ports: ReadOnly::new(4),
86 emerg_wr: WriteOnly::default(),
87 };
88 let state = Arc::new(Mutex::new(State::new(
89 vec![QueueStatus::default(), QueueStatus::default()],
90 config_space,
91 )));
92 let transport = FakeTransport {
93 device_type: DeviceType::Console,
94 max_queue_size: 2,
95 device_features: 0,
96 state: state.clone(),
97 };
98 let console = VirtIOConsole::<FakeHal, FakeTransport<Config>>::new(transport).unwrap();
99 (console, state)
100 }
101
102 #[test]
103 fn read() {
104 let (mut console, state) = setup_test();
105
106 {
107 let mut state = state.lock().unwrap();
108 state.write_to_queue::<QUEUE_SIZE>(QUEUE_RECEIVEQ_PORT_0, &[42, 43, 44, 45, 46, 47]);
109 state.interrupt_pending = true;
110 }
111
112 let mut buf = [0; 3];
113 let n = console.read(&mut buf).unwrap();
114 assert_eq!(n, 3);
115 assert_eq!(&buf, &[42, 43, 44]);
116 let n = console.read(&mut buf).unwrap();
117 assert_eq!(n, 3);
118 assert_eq!(&buf, &[45, 46, 47]);
119 }
120
121 #[test]
122 fn bufread() {
123 let (mut console, state) = setup_test();
124
125 {
126 let mut state = state.lock().unwrap();
127 state.write_to_queue::<QUEUE_SIZE>(QUEUE_RECEIVEQ_PORT_0, &[42, 43, 44, 45, 46, 47]);
128 state.interrupt_pending = true;
129 }
130
131 console.fill_buf().unwrap();
132 console.consume(3);
133 let mut buf = [0; 3];
134 let n = console.read(&mut buf).unwrap();
135 assert_eq!(n, 3);
136 assert_eq!(&buf, &[45, 46, 47]);
137 }
138
139 #[test]
140 fn read_exact() {
141 let (mut console, state) = setup_test();
142
143 let mut recv_buf = [0; 100];
144
145 let data = {
146 let mut data = Vec::new();
147 for i in 0..recv_buf.len() {
148 data.push((42 + i % 256) as u8);
149 }
150 data
151 };
152 let expect = data.clone();
153
154 thread::spawn(move || {
155 for chunk in data.chunks(5) {
157 thread::sleep(std::time::Duration::from_millis(10));
158 let mut state = state.lock().unwrap();
159 state.write_to_queue::<QUEUE_SIZE>(QUEUE_RECEIVEQ_PORT_0, chunk);
160 state.interrupt_pending = true;
161 }
162 });
163
164 console.read_exact(&mut recv_buf).unwrap();
165 assert_eq!(&recv_buf, expect.as_slice());
166 }
167}