usb: add first, last params to ControlPipe data_in, data_out.
This commit is contained in:
parent
1ec2e5672f
commit
883e28a0fb
3 changed files with 39 additions and 11 deletions
|
@ -657,7 +657,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a> {
|
||||
fn data_out<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut [u8],
|
||||
_first: bool,
|
||||
_last: bool,
|
||||
) -> Self::DataOutFuture<'a> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
|
||||
|
@ -694,13 +699,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn data_in<'a>(&'a mut self, buf: &'a [u8], last_packet: bool) -> Self::DataInFuture<'a> {
|
||||
fn data_in<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a [u8],
|
||||
_first: bool,
|
||||
last: bool,
|
||||
) -> Self::DataInFuture<'a> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
regs.events_ep0datadone.reset();
|
||||
|
||||
regs.shorts
|
||||
.write(|w| w.ep0datadone_ep0status().bit(last_packet));
|
||||
regs.shorts.write(|w| w.ep0datadone_ep0status().bit(last));
|
||||
|
||||
// This starts a TX on EP0. events_ep0datadone notifies when done.
|
||||
unsafe { write_dma::<T>(0, buf) }
|
||||
|
|
|
@ -155,12 +155,18 @@ pub trait ControlPipe {
|
|||
///
|
||||
/// Must be called after `setup()` for requests with `direction` of `Out`
|
||||
/// and `length` greater than zero.
|
||||
fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a>;
|
||||
fn data_out<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut [u8],
|
||||
first: bool,
|
||||
last: bool,
|
||||
) -> Self::DataOutFuture<'a>;
|
||||
|
||||
/// Sends a DATA IN packet with `data` in response to a control read request.
|
||||
///
|
||||
/// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`.
|
||||
fn data_in<'a>(&'a mut self, data: &'a [u8], last_packet: bool) -> Self::DataInFuture<'a>;
|
||||
fn data_in<'a>(&'a mut self, data: &'a [u8], first: bool, last: bool)
|
||||
-> Self::DataInFuture<'a>;
|
||||
|
||||
/// Accepts a control request.
|
||||
///
|
||||
|
|
|
@ -292,12 +292,12 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
|||
let len = data.len().min(resp_length);
|
||||
let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0;
|
||||
|
||||
let mut chunks = data[0..len]
|
||||
let chunks = data[0..len]
|
||||
.chunks(max_packet_size)
|
||||
.chain(need_zlp.then(|| -> &[u8] { &[] }));
|
||||
|
||||
while let Some(chunk) = chunks.next() {
|
||||
match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
|
||||
for (first, last, chunk) in first_last(chunks) {
|
||||
match self.control.data_in(chunk, first, last).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
warn!("control accept_in failed: {:?}", e);
|
||||
|
@ -315,8 +315,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
|||
let max_packet_size = self.control.max_packet_size();
|
||||
let mut total = 0;
|
||||
|
||||
for chunk in self.control_buf[..req_length].chunks_mut(max_packet_size) {
|
||||
let size = match self.control.data_out(chunk).await {
|
||||
let chunks = self.control_buf[..req_length].chunks_mut(max_packet_size);
|
||||
for (first, last, chunk) in first_last(chunks) {
|
||||
let size = match self.control.data_out(chunk, first, last).await {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
warn!("usb: failed to read CONTROL OUT data stage: {:?}", e);
|
||||
|
@ -668,3 +669,15 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn first_last<T: Iterator>(iter: T) -> impl Iterator<Item = (bool, bool, T::Item)> {
|
||||
let mut iter = iter.peekable();
|
||||
let mut first = true;
|
||||
core::iter::from_fn(move || {
|
||||
let val = iter.next()?;
|
||||
let is_first = first;
|
||||
first = false;
|
||||
let is_last = iter.peek().is_none();
|
||||
Some((is_first, is_last, val))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue