diff options
Diffstat (limited to 'embassy-usb/src')
| -rw-r--r-- | embassy-usb/src/class/cdc_acm.rs | 99 |
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 | ||
| 413 | impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for Sender<'d, D> { | ||
| 414 | type Error = EndpointError; | ||
| 415 | } | ||
| 416 | |||
| 417 | impl<'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 | ||
| 493 | pub struct BufferedReceiver<'d, D: Driver<'d>> { | ||
| 494 | receiver: Receiver<'d, D>, | ||
| 495 | buffer: &'d mut [u8], | ||
| 496 | start: usize, | ||
| 497 | end: usize, | ||
| 498 | } | ||
| 499 | |||
| 500 | impl<'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 | |||
| 531 | impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for BufferedReceiver<'d, D> { | ||
| 532 | type Error = EndpointError; | ||
| 533 | } | ||
| 534 | |||
| 535 | impl<'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 |
