Support multi-frame data phase control requests
This commit is contained in:
parent
d40ebcccf6
commit
c06488eb29
@ -508,6 +508,30 @@ pub struct ControlPipe<'d, T: Instance> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> ControlPipe<'d, T> {
|
impl<'d, T: Instance> ControlPipe<'d, T> {
|
||||||
|
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> {
|
||||||
|
let regs = T::regs();
|
||||||
|
|
||||||
|
// Wait until ready
|
||||||
|
regs.intenset.write(|w| w.ep0datadone().set());
|
||||||
|
poll_fn(|cx| {
|
||||||
|
EP_OUT_WAKERS[0].register(cx.waker());
|
||||||
|
let regs = T::regs();
|
||||||
|
if regs
|
||||||
|
.events_ep0datadone
|
||||||
|
.read()
|
||||||
|
.events_ep0datadone()
|
||||||
|
.bit_is_set()
|
||||||
|
{
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
unsafe { read_dma::<T>(0, buf) }
|
||||||
|
}
|
||||||
|
|
||||||
async fn write(&mut self, buf: &[u8], last_chunk: bool) {
|
async fn write(&mut self, buf: &[u8], last_chunk: bool) {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
regs.events_ep0datadone.reset();
|
regs.events_ep0datadone.reset();
|
||||||
@ -595,29 +619,19 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
|||||||
let req = self.request.unwrap();
|
let req = self.request.unwrap();
|
||||||
assert_eq!(req.direction, UsbDirection::Out);
|
assert_eq!(req.direction, UsbDirection::Out);
|
||||||
assert!(req.length > 0);
|
assert!(req.length > 0);
|
||||||
assert!(buf.len() >= usize::from(req.length));
|
|
||||||
|
|
||||||
let regs = T::regs();
|
let req_length = usize::from(req.length);
|
||||||
|
let max_packet_size = usize::from(self.max_packet_size);
|
||||||
// Wait until ready
|
let mut total = 0;
|
||||||
regs.intenset.write(|w| w.ep0datadone().set());
|
for chunk in buf.chunks_mut(max_packet_size) {
|
||||||
poll_fn(|cx| {
|
let size = self.read(chunk).await?;
|
||||||
EP_OUT_WAKERS[0].register(cx.waker());
|
total += size;
|
||||||
let regs = T::regs();
|
if size < max_packet_size || total == req_length {
|
||||||
if regs
|
break;
|
||||||
.events_ep0datadone
|
|
||||||
.read()
|
|
||||||
.events_ep0datadone()
|
|
||||||
.bit_is_set()
|
|
||||||
{
|
|
||||||
Poll::Ready(())
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.await;
|
|
||||||
|
|
||||||
unsafe { read_dma::<T>(0, buf) }
|
Ok(total)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,16 +711,27 @@ impl Allocator {
|
|||||||
|
|
||||||
// Endpoint directions are allocated individually.
|
// Endpoint directions are allocated individually.
|
||||||
|
|
||||||
let alloc_index = match ep_type {
|
let alloc_index = if let Some(ep_addr) = ep_addr {
|
||||||
EndpointType::Isochronous => 8,
|
match (ep_addr.index(), ep_type) {
|
||||||
EndpointType::Control => 0,
|
(0, EndpointType::Control) => {}
|
||||||
EndpointType::Interrupt | EndpointType::Bulk => {
|
(8, EndpointType::Isochronous) => {}
|
||||||
// Find rightmost zero bit in 1..=7
|
(n, EndpointType::Bulk) | (n, EndpointType::Interrupt) if n >= 1 && n <= 7 => {}
|
||||||
let ones = (self.used >> 1).trailing_ones() as usize;
|
_ => return Err(driver::EndpointAllocError),
|
||||||
if ones >= 7 {
|
}
|
||||||
return Err(driver::EndpointAllocError);
|
|
||||||
|
ep_addr.index()
|
||||||
|
} else {
|
||||||
|
match ep_type {
|
||||||
|
EndpointType::Isochronous => 8,
|
||||||
|
EndpointType::Control => 0,
|
||||||
|
EndpointType::Interrupt | EndpointType::Bulk => {
|
||||||
|
// Find rightmost zero bit in 1..=7
|
||||||
|
let ones = (self.used >> 1).trailing_ones() as usize;
|
||||||
|
if ones >= 7 {
|
||||||
|
return Err(driver::EndpointAllocError);
|
||||||
|
}
|
||||||
|
ones + 1
|
||||||
}
|
}
|
||||||
ones + 1
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user