wasefire_board_api/usb/
serial.rs1use usb_device::UsbError;
18use usb_device::class_prelude::UsbBus;
19use usbd_serial::SerialPort;
20use wasefire_logger as log;
21
22use crate::Error;
23
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[derive(Debug, PartialEq, Eq)]
27pub enum Event {
28 Read,
32
33 Write,
37}
38
39impl<B: crate::Api> From<Event> for crate::Event<B> {
40 fn from(event: Event) -> Self {
41 super::Event::Serial(event).into()
42 }
43}
44
45pub trait Api: Send {
47 fn read(output: &mut [u8]) -> Result<usize, Error>;
51
52 fn write(input: &[u8]) -> Result<usize, Error>;
56
57 fn flush() -> Result<(), Error>;
59
60 fn enable(event: &Event) -> Result<(), Error>;
62
63 fn disable(event: &Event) -> Result<(), Error>;
65}
66
67pub trait HasSerial: Send {
69 type UsbBus: UsbBus;
71
72 fn with_serial<R>(f: impl FnOnce(&mut Serial<Self::UsbBus>) -> R) -> R;
74}
75
76pub struct WithSerial<T: HasSerial> {
78 _never: !,
79 _has_serial: T,
80}
81
82pub struct Serial<'a, T: UsbBus> {
84 port: SerialPort<'a, T>,
85 read_enabled: bool,
86 write_enabled: bool,
87}
88
89impl<'a, T: UsbBus> Serial<'a, T> {
90 pub fn new(port: SerialPort<'a, T>) -> Self {
92 Self { port, read_enabled: false, write_enabled: false }
93 }
94
95 pub fn read(&mut self, output: &mut [u8]) -> Result<usize, Error> {
97 match self.port.read(output) {
98 Ok(len) => {
99 log::trace!("{}{:?} = read({})", len, &output[.. len], output.len());
100 Ok(len)
101 }
102 Err(UsbError::WouldBlock) => Ok(0),
103 Err(e) => {
104 log::debug!("{} = read({})", log::Debug2Format(&e), output.len());
105 Err(Error::world(0))
106 }
107 }
108 }
109
110 pub fn write(&mut self, input: &[u8]) -> Result<usize, Error> {
112 if !self.port.dtr() {
113 return Ok(0);
115 }
116 match self.port.write(input) {
117 Ok(len) => {
118 log::trace!("{} = write({}{:?})", len, input.len(), input);
119 Ok(len)
120 }
121 Err(UsbError::WouldBlock) => Ok(0),
122 Err(e) => {
123 log::debug!("{} = write({}{:?})", log::Debug2Format(&e), input.len(), input);
124 Err(Error::world(0))
125 }
126 }
127 }
128
129 pub fn flush(&mut self) -> Result<(), Error> {
131 loop {
132 match self.port.flush() {
133 Ok(()) => {
134 log::trace!("flush()");
135 break Ok(());
136 }
137 Err(UsbError::WouldBlock) => {
138 log::debug!("flush() didn't flush all data, retrying");
139 continue;
140 }
141 Err(e) => {
142 log::debug!("{} = flush()", log::Debug2Format(&e));
143 break Err(Error::world(0));
144 }
145 }
146 }
147 }
148
149 pub fn enable(&mut self, event: &Event) -> Result<(), Error> {
151 self.set(event, true)
152 }
153
154 pub fn disable(&mut self, event: &Event) -> Result<(), Error> {
156 self.set(event, false)
157 }
158
159 pub fn port(&mut self) -> &mut SerialPort<'a, T> {
161 &mut self.port
162 }
163
164 pub fn tick(&mut self, polled: bool, mut push: impl FnMut(Event)) {
166 if self.read_enabled && polled {
167 push(Event::Read);
168 }
169 if self.write_enabled && self.port.dtr() {
170 push(Event::Write);
171 }
172 }
173
174 fn set(&mut self, event: &Event, enabled: bool) -> Result<(), Error> {
175 match event {
176 Event::Read => self.read_enabled = enabled,
177 Event::Write => self.write_enabled = enabled,
178 }
179 Ok(())
180 }
181}
182
183impl<T: HasSerial> Api for WithSerial<T> {
184 fn read(output: &mut [u8]) -> Result<usize, Error> {
185 T::with_serial(|x| x.read(output))
186 }
187
188 fn write(input: &[u8]) -> Result<usize, Error> {
189 T::with_serial(|x| x.write(input))
190 }
191
192 fn flush() -> Result<(), Error> {
193 T::with_serial(|x| x.flush())
194 }
195
196 fn enable(event: &Event) -> Result<(), Error> {
197 T::with_serial(|x| x.enable(event))
198 }
199
200 fn disable(event: &Event) -> Result<(), Error> {
201 T::with_serial(|x| x.disable(event))
202 }
203}