1use crate::buffer::{Buffer, DefaultBufferStore};
2use crate::cdc_acm::*;
3use core::borrow::BorrowMut;
4use core::slice;
5use usb_device::class_prelude::*;
6use usb_device::descriptor::lang_id::LangID;
7use usb_device::Result;
8
9pub struct SerialPort<'a, B, RS = DefaultBufferStore, WS = DefaultBufferStore>
14where
15 B: UsbBus,
16 RS: BorrowMut<[u8]>,
17 WS: BorrowMut<[u8]>,
18{
19 inner: CdcAcmClass<'a, B>,
20 pub(crate) read_buf: Buffer<RS>,
21 pub(crate) write_buf: Buffer<WS>,
22 write_state: WriteState,
23}
24
25const SHORT_PACKET_INTERVAL: usize = 10;
28
29enum WriteState {
31 Idle,
33
34 Short,
36
37 Full(usize),
42}
43
44impl<'a, B> SerialPort<'a, B>
45where
46 B: UsbBus,
47{
48 pub fn new<'alloc: 'a>(
50 alloc: &'alloc UsbBusAllocator<B>,
51 ) -> SerialPort<'a, B, DefaultBufferStore, DefaultBufferStore> {
52 Self::new_with_interface_names(alloc, None, None)
53 }
54 pub fn new_with_interface_names<'alloc: 'a>(
56 alloc: &'alloc UsbBusAllocator<B>,
57 comm_if_name: Option<&'static str>,
58 data_if_name: Option<&'static str>,
59 ) -> SerialPort<'a, B, DefaultBufferStore, DefaultBufferStore> {
60 SerialPort::new_with_store_and_interface_names(
61 alloc,
62 DefaultBufferStore::default(),
63 DefaultBufferStore::default(),
64 comm_if_name,
65 data_if_name,
66 )
67 }
68}
69
70impl<'a, B, RS, WS> SerialPort<'a, B, RS, WS>
71where
72 B: UsbBus,
73 RS: BorrowMut<[u8]>,
74 WS: BorrowMut<[u8]>,
75{
76 pub fn new_with_store<'alloc: 'a>(
78 alloc: &'alloc UsbBusAllocator<B>,
79 read_store: RS,
80 write_store: WS,
81 ) -> SerialPort<'a, B, RS, WS> {
82 Self::new_with_store_and_interface_names(alloc, read_store, write_store, None, None)
83 }
84
85 pub fn new_with_store_and_interface_names<'alloc: 'a>(
87 alloc: &'alloc UsbBusAllocator<B>,
88 read_store: RS,
89 write_store: WS,
90 comm_if_name: Option<&'static str>,
91 data_if_name: Option<&'static str>,
92 ) -> SerialPort<'a, B, RS, WS> {
93 SerialPort {
94 inner: CdcAcmClass::new_with_interface_names(alloc, 64, comm_if_name, data_if_name),
95 read_buf: Buffer::new(read_store),
96 write_buf: Buffer::new(write_store),
97 write_state: WriteState::Idle,
98 }
99 }
100
101 pub fn line_coding(&self) -> &LineCoding {
103 self.inner.line_coding()
104 }
105
106 pub fn dtr(&self) -> bool {
108 self.inner.dtr()
109 }
110
111 pub fn rts(&self) -> bool {
113 self.inner.rts()
114 }
115
116 pub fn write(&mut self, data: &[u8]) -> Result<usize> {
125 let count = self.write_buf.write(data);
126
127 match self.flush() {
128 Ok(_) | Err(UsbError::WouldBlock) => {}
129 Err(err) => {
130 return Err(err);
131 }
132 };
133
134 if count == 0 {
135 Err(UsbError::WouldBlock)
136 } else {
137 Ok(count)
138 }
139 }
140
141 pub(crate) fn poll(&mut self) -> Result<()> {
143 let Self {
144 inner, read_buf, ..
145 } = self;
146
147 read_buf.write_all(inner.max_packet_size() as usize, |buf_data| {
148 match inner.read_packet(buf_data) {
149 Ok(c) => Ok(c),
150 Err(UsbError::WouldBlock) => Ok(0),
151 Err(err) => Err(err),
152 }
153 })?;
154
155 Ok(())
156 }
157
158 pub fn read(&mut self, data: &mut [u8]) -> Result<usize> {
166 self.poll()?;
169
170 if self.read_buf.available_read() == 0 {
171 return Err(UsbError::WouldBlock);
173 }
174
175 self.read_buf.read(data.len(), |buf_data| {
176 data[..buf_data.len()].copy_from_slice(buf_data);
177
178 Ok(buf_data.len())
179 })
180 }
181
182 pub fn flush(&mut self) -> Result<()> {
187 let buf = &mut self.write_buf;
188 let inner = &mut self.inner;
189 let write_state = &mut self.write_state;
190
191 let full_count = match *write_state {
192 WriteState::Full(c) => c,
193 _ => 0,
194 };
195
196 if buf.available_read() > 0 {
197 let max_write_size = if full_count >= SHORT_PACKET_INTERVAL {
200 inner.max_packet_size() - 1
201 } else {
202 inner.max_packet_size()
203 } as usize;
204
205 buf.read(max_write_size, |buf_data| {
206 inner.write_packet(buf_data)?;
208
209 *write_state = if buf_data.len() == inner.max_packet_size() as usize {
210 WriteState::Full(full_count + 1)
211 } else {
212 WriteState::Short
213 };
214
215 Ok(buf_data.len())
216 })?;
217
218 Err(UsbError::WouldBlock)
219 } else if full_count != 0 {
220 inner.write_packet(&[])?;
223
224 *write_state = WriteState::Short;
225
226 Err(UsbError::WouldBlock)
227 } else {
228 *write_state = WriteState::Idle;
231
232 Ok(())
233 }
234 }
235}
236
237impl<B, RS, WS> UsbClass<B> for SerialPort<'_, B, RS, WS>
238where
239 B: UsbBus,
240 RS: BorrowMut<[u8]>,
241 WS: BorrowMut<[u8]>,
242{
243 fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
244 self.inner.get_configuration_descriptors(writer)
245 }
246
247 fn get_string(&self, index: StringIndex, lang_id: LangID) -> Option<&str> {
248 self.inner.get_string(index, lang_id)
249 }
250
251 fn reset(&mut self) {
252 self.inner.reset();
253 self.read_buf.clear();
254 self.write_buf.clear();
255 self.write_state = WriteState::Idle;
256 }
257
258 fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
259 if addr == self.inner.write_ep().address() {
260 self.flush().ok();
261 }
262 }
263
264 fn control_in(&mut self, xfer: ControlIn<B>) {
265 self.inner.control_in(xfer);
266 }
267
268 fn control_out(&mut self, xfer: ControlOut<B>) {
269 self.inner.control_out(xfer);
270 }
271}
272
273impl<B, RS, WS> embedded_hal::serial::Write<u8> for SerialPort<'_, B, RS, WS>
274where
275 B: UsbBus,
276 RS: BorrowMut<[u8]>,
277 WS: BorrowMut<[u8]>,
278{
279 type Error = UsbError;
280
281 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
282 match <SerialPort<'_, B, RS, WS>>::write(self, slice::from_ref(&word)) {
283 Ok(0) | Err(UsbError::WouldBlock) => Err(nb::Error::WouldBlock),
284 Ok(_) => Ok(()),
285 Err(err) => Err(nb::Error::Other(err)),
286 }
287 }
288
289 fn flush(&mut self) -> nb::Result<(), Self::Error> {
290 match <SerialPort<'_, B, RS, WS>>::flush(self) {
291 Err(UsbError::WouldBlock) => Err(nb::Error::WouldBlock),
292 Ok(_) => Ok(()),
293 Err(err) => Err(nb::Error::Other(err)),
294 }
295 }
296}
297
298impl<B, RS, WS> embedded_hal::serial::Read<u8> for SerialPort<'_, B, RS, WS>
299where
300 B: UsbBus,
301 RS: BorrowMut<[u8]>,
302 WS: BorrowMut<[u8]>,
303{
304 type Error = UsbError;
305
306 fn read(&mut self) -> nb::Result<u8, Self::Error> {
307 let mut buf: u8 = 0;
308
309 match <SerialPort<'_, B, RS, WS>>::read(self, slice::from_mut(&mut buf)) {
310 Ok(0) | Err(UsbError::WouldBlock) => Err(nb::Error::WouldBlock),
311 Ok(_) => Ok(buf),
312 Err(err) => Err(nb::Error::Other(err)),
313 }
314 }
315}