From 5337cb672adad6f76e1f62c9a4ea590ab4fbd8c2 Mon Sep 17 00:00:00 2001 From: Robert Forsman Date: Thu, 9 Dec 2021 14:16:28 -0500 Subject: [PATCH] add maybe_write() for lazy data closures on Endpoint and UsbBus --- src/bus.rs | 23 +++++++++++++++++++++++ src/endpoint.rs | 22 ++++++++++++++++++++++ src/lib.rs | 8 ++++++++ 3 files changed, 53 insertions(+) diff --git a/src/bus.rs b/src/bus.rs index cd176d3..0c9b2bd 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -78,6 +78,29 @@ pub trait UsbBus: Sync + Sized { /// Implementations may also return other errors if applicable. fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> Result; + /// Writes a single packet of data to the specified endpoint and returns number of bytes + /// actually written. + /// If the underlying device [`WouldBlock`](crate::UsbError::WouldBlock) the methods return `None` instead of invoking producer. + /// + /// The only reason for a short write is if the caller passes a slice larger than the amount of + /// memory allocated earlier, and this is generally an error in the class implementation. + /// + /// # Errors + /// + /// * [`InvalidEndpoint`](crate::UsbError::InvalidEndpoint) - The `ep_addr` does not point to a + /// valid endpoint that was previously allocated with [`UsbBus::alloc_ep`]. + /// * [`BufferOverflow`](crate::UsbError::BufferOverflow) - The packet is too long to fit in the + /// transmission buffer. This is generally an error in the class implementation, because the + /// class shouldn't provide more data than the `max_packet_size` it specified when allocating + /// the endpoint. + /// + /// Implementations may also return other errors if applicable. + fn maybe_write<'a>( + &self, + ep_addr: EndpointAddress, + producer: impl FnOnce() -> Result<&'a [u8]>, + ) -> Option>; + /// Reads a single packet of data from the specified endpoint and returns the actual length of /// the packet. /// diff --git a/src/endpoint.rs b/src/endpoint.rs index 520bccb..b605698 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -134,6 +134,28 @@ impl Endpoint<'_, B, In> { pub fn write(&self, data: &[u8]) -> Result { self.bus().write(self.address, data) } + + /// Writes a single packet of data to the specified endpoint and returns number of bytes + /// actually written. The buffer must not be longer than the `max_packet_size` specified when + /// allocating the endpoint. + /// + /// If the underlying device [`WouldBlock`](crate::UsbError::WouldBlock), the underlying + /// methods return `None` instead of invoking `producer`. + /// + /// # Errors + /// + /// Note: USB bus implementation errors are directly passed through, so be prepared to handle + /// other errors as well. + /// + /// * [`BufferOverflow`](crate::UsbError::BufferOverflow) - The data is longer than the + /// `max_packet_size` specified when allocating the endpoint. This is generally an error in + /// the class implementation. + pub fn maybe_write<'a>( + &self, + producer: impl FnOnce() -> Result<&'a [u8]>, + ) -> Option> { + self.bus().maybe_write(self.address, producer) + } } impl Endpoint<'_, B, Out> { diff --git a/src/lib.rs b/src/lib.rs index d7744c9..ac8e574 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -221,6 +221,14 @@ fn _ensure_sync() { Err(UsbError::InvalidEndpoint) } + fn maybe_write<'a>( + &self, + _ep_addr: EndpointAddress, + _producer: impl FnOnce() -> Result<&'a [u8]>, + ) -> Option> { + Some(Err(UsbError::InvalidEndpoint)) + } + fn read(&self, _ep_addr: EndpointAddress, _buf: &mut [u8]) -> Result { Err(UsbError::InvalidEndpoint) }