feat: add helper to read/write full transfer blocks

instead of always transferring only USB packets, add a provided method
to transmit an entire data block by using a simple loop construct.

Signed-off-by: Felipe Balbi <febalbi@microsoft.com>
This commit is contained in:
Felipe Balbi 2025-08-29 14:32:12 -07:00
parent f86cf87f2f
commit 6dc06d47bf
2 changed files with 32 additions and 0 deletions

View File

@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header --> <!-- next-header -->
## Unreleased - ReleaseDate ## Unreleased - ReleaseDate
- Add `EndpointOut::read_data()` and `EndpointIn::write_data()` provided methods.
## 0.2.0 - 2025-07-16 ## 0.2.0 - 2025-07-16
- Make USB endpoint allocator methods accept an optional `EndpointAddress`. - Make USB endpoint allocator methods accept an optional `EndpointAddress`.

View File

@ -236,6 +236,22 @@ pub trait EndpointOut: Endpoint {
/// ///
/// This should also clear any NAK flags and prepare the endpoint to receive the next packet. /// This should also clear any NAK flags and prepare the endpoint to receive the next packet.
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError>; async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError>;
/// Read until the buffer is full or we receive a short packet from the USB host returning the
/// actual length of the entire data block.
///
/// This should also clear any NAK flags and prepare the endpoint to receive the next packet or
/// data block.
async fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
let mut n = 0;
loop {
let i = self.read(&mut buf[n..]).await?;
n += i;
if i < self.info().max_packet_size as usize {
return Ok(n);
}
}
}
} }
/// USB control pipe trait. /// USB control pipe trait.
@ -349,6 +365,20 @@ pub trait ControlPipe {
pub trait EndpointIn: Endpoint { pub trait EndpointIn: Endpoint {
/// Write a single packet of data to the endpoint. /// Write a single packet of data to the endpoint.
async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError>; async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError>;
/// Write all the data from buf to the endpoint one wMaxPacketSize chunk at a time.
///
/// If the buffer size is evenly divisible by wMaxPacketSize, this will also ensure the
/// terminating zero-length-packet is transmitted.
async fn write_data(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
for chunk in buf.chunks(self.info().max_packet_size as usize) {
self.write(chunk).await?;
}
if buf.len() % self.info().max_packet_size as usize == 0 {
self.write(&[]).await?;
}
Ok(())
}
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]