aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-usb/src')
-rw-r--r--embassy-usb/src/class/cdc_acm.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs
index ea9d9fb7b..732a433f8 100644
--- a/embassy-usb/src/class/cdc_acm.rs
+++ b/embassy-usb/src/class/cdc_acm.rs
@@ -410,6 +410,18 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
410 } 410 }
411} 411}
412 412
413impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for Sender<'d, D> {
414 type Error = EndpointError;
415}
416
417impl<'d, D: Driver<'d>> embedded_io_async::Write for Sender<'d, D> {
418 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
419 let len = core::cmp::min(buf.len(), self.max_packet_size() as usize);
420 self.write_packet(&buf[..len]).await?;
421 Ok(len)
422 }
423}
424
413/// CDC ACM class packet receiver. 425/// CDC ACM class packet receiver.
414/// 426///
415/// You can obtain a `Receiver` with [`CdcAcmClass::split`] 427/// You can obtain a `Receiver` with [`CdcAcmClass::split`]
@@ -451,6 +463,93 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
451 pub async fn wait_connection(&mut self) { 463 pub async fn wait_connection(&mut self) {
452 self.read_ep.wait_enabled().await; 464 self.read_ep.wait_enabled().await;
453 } 465 }
466
467 /// Turn the `Receiver` into a [`BufferedReceiver`].
468 ///
469 /// The supplied buffer must be large enough to hold max_packet_size bytes.
470 pub fn into_buffered(self, buf: &'d mut [u8]) -> BufferedReceiver<'d, D> {
471 BufferedReceiver {
472 receiver: self,
473 buffer: buf,
474 start: 0,
475 end: 0,
476 }
477 }
478}
479
480/// CDC ACM class buffered receiver.
481///
482/// It is a requirement of the [`embedded_io_async::Read`] trait that arbitrarily small lengths of
483/// data can be read from the stream. The [`Receiver`] can only read full packets at a time. The
484/// `BufferedReceiver` instead buffers a single packet if the caller does not read all of the data,
485/// so that the remaining data can be returned in subsequent calls.
486///
487/// If you have no requirement to use the [`embedded_io_async::Read`] trait or to read a data length
488/// less than the packet length, then it is more efficient to use the [`Receiver`] directly.
489///
490/// You can obtain a `BufferedReceiver` with [`Receiver::into_buffered`].
491///
492/// [`embedded_io_async::Read`]: https://docs.rs/embedded-io-async/latest/embedded_io_async/trait.Read.html
493pub struct BufferedReceiver<'d, D: Driver<'d>> {
494 receiver: Receiver<'d, D>,
495 buffer: &'d mut [u8],
496 start: usize,
497 end: usize,
498}
499
500impl<'d, D: Driver<'d>> BufferedReceiver<'d, D> {
501 fn read_from_buffer(&mut self, buf: &mut [u8]) -> usize {
502 let available = &self.buffer[self.start..self.end];
503 let len = core::cmp::min(available.len(), buf.len());
504 buf[..len].copy_from_slice(&self.buffer[..len]);
505 self.start += len;
506 len
507 }
508
509 /// Gets the current line coding. The line coding contains information that's mainly relevant
510 /// for USB to UART serial port emulators, and can be ignored if not relevant.
511 pub fn line_coding(&self) -> LineCoding {
512 self.receiver.line_coding()
513 }
514
515 /// Gets the DTR (data terminal ready) state
516 pub fn dtr(&self) -> bool {
517 self.receiver.dtr()
518 }
519
520 /// Gets the RTS (request to send) state
521 pub fn rts(&self) -> bool {
522 self.receiver.rts()
523 }
524
525 /// Waits for the USB host to enable this interface
526 pub async fn wait_connection(&mut self) {
527 self.receiver.wait_connection().await;
528 }
529}
530
531impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for BufferedReceiver<'d, D> {
532 type Error = EndpointError;
533}
534
535impl<'d, D: Driver<'d>> embedded_io_async::Read for BufferedReceiver<'d, D> {
536 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
537 // If there is a buffered packet, return data from that first
538 if self.start != self.end {
539 return Ok(self.read_from_buffer(buf));
540 }
541
542 // If the caller's buffer is large enough to contain an entire packet, read directly into
543 // that instead of buffering the packet internally.
544 if buf.len() > self.receiver.max_packet_size() as usize {
545 return self.receiver.read_packet(buf).await;
546 }
547
548 // Otherwise read a packet into the internal buffer, and return some of it to the caller
549 self.start = 0;
550 self.end = self.receiver.read_packet(&mut self.buffer).await?;
551 return Ok(self.read_from_buffer(buf));
552 }
454} 553}
455 554
456/// Number of stop bits for LineCoding 555/// Number of stop bits for LineCoding