Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add maybe_write() for lazy data closures on Endpoint and UsbBus #78

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<usize>;

/// 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<Result<usize>>;

/// Reads a single packet of data from the specified endpoint and returns the actual length of
/// the packet.
///
Expand Down
22 changes: 22 additions & 0 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,28 @@ impl<B: UsbBus> Endpoint<'_, B, In> {
pub fn write(&self, data: &[u8]) -> Result<usize> {
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<Result<usize>> {
self.bus().maybe_write(self.address, producer)
}
}

impl<B: UsbBus> Endpoint<'_, B, Out> {
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Result<usize>> {
Some(Err(UsbError::InvalidEndpoint))
}

fn read(&self, _ep_addr: EndpointAddress, _buf: &mut [u8]) -> Result<usize> {
Err(UsbError::InvalidEndpoint)
}
Expand Down