usb: abort control data in/out on reset or when receiving another SETUP.

This removes the horrible timeout hack.
This commit is contained in:
Dario Nieuwenhuis 2022-04-06 03:14:22 +02:00
parent f6d11dfba5
commit 22a47aeeb2
3 changed files with 50 additions and 31 deletions

View File

@ -6,7 +6,6 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
use core::task::Poll;
use cortex_m::peripheral::NVIC;
use embassy::interrupt::InterruptExt;
use embassy::time::{with_timeout, Duration};
use embassy::util::Unborrow;
use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::unborrow;
@ -59,6 +58,7 @@ impl<'d, T: Instance> Driver<'d, T> {
if regs.events_usbreset.read().bits() != 0 {
regs.intenclr.write(|w| w.usbreset().clear());
BUS_WAKER.wake();
EP0_WAKER.wake();
}
if regs.events_ep0setup.read().bits() != 0 {
@ -585,7 +585,7 @@ pub struct ControlPipe<'d, T: Instance> {
impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a;
type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a;
type DataInFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
type DataInFuture<'a> = impl Future<Output = Result<(), WriteError>> + 'a where Self: 'a;
fn max_packet_size(&self) -> usize {
usize::from(self.max_packet_size)
@ -596,7 +596,10 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
let regs = T::regs();
// Wait for SETUP packet
regs.intenset.write(|w| w.ep0setup().set());
regs.intenset.write(|w| {
w.ep0setup().set();
w.ep0datadone().set()
});
poll_fn(|cx| {
EP0_WAKER.register(cx.waker());
let regs = T::regs();
@ -639,22 +642,27 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
let regs = T::regs();
// Wait until ready
regs.intenset.write(|w| w.ep0datadone().set());
regs.intenset.write(|w| {
w.usbreset().set();
w.ep0setup().set();
w.ep0datadone().set()
});
poll_fn(|cx| {
EP0_WAKER.register(cx.waker());
let regs = T::regs();
if regs
.events_ep0datadone
.read()
.events_ep0datadone()
.bit_is_set()
{
Poll::Ready(())
if regs.events_usbreset.read().bits() != 0 {
trace!("aborted control data_out: usb reset");
Poll::Ready(Err(ReadError::Disabled))
} else if regs.events_ep0setup.read().bits() != 0 {
trace!("aborted control data_out: received another SETUP");
Poll::Ready(Err(ReadError::Disabled))
} else if regs.events_ep0datadone.read().bits() != 0 {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
})
.await;
.await?;
unsafe { read_dma::<T>(0, buf) }
}
@ -671,24 +679,29 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
regs.shorts
.modify(|_, w| w.ep0datadone_ep0status().bit(last_packet));
regs.intenset.write(|w| w.ep0datadone().set());
let res = with_timeout(
Duration::from_millis(10),
poll_fn(|cx| {
EP0_WAKER.register(cx.waker());
let regs = T::regs();
if regs.events_ep0datadone.read().bits() != 0 {
Poll::Ready(())
} else {
Poll::Pending
}
}),
)
.await;
regs.intenset.write(|w| {
w.usbreset().set();
w.ep0setup().set();
w.ep0datadone().set()
});
if res.is_err() {
error!("ControlPipe::data_in timed out.");
}
poll_fn(|cx| {
cx.waker().wake_by_ref();
EP0_WAKER.register(cx.waker());
let regs = T::regs();
if regs.events_usbreset.read().bits() != 0 {
trace!("aborted control data_in: usb reset");
Poll::Ready(Err(WriteError::Disabled))
} else if regs.events_ep0setup.read().bits() != 0 {
trace!("aborted control data_in: received another SETUP");
Poll::Ready(Err(WriteError::Disabled))
} else if regs.events_ep0datadone.read().bits() != 0 {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
})
.await
}
}

View File

@ -295,7 +295,13 @@ impl<C: driver::ControlPipe> ControlPipe<C> {
.chain(need_zlp.then(|| -> &[u8] { &[] }));
while let Some(chunk) = chunks.next() {
self.control.data_in(chunk, chunks.size_hint().0 == 0).await;
match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
Ok(()) => {}
Err(e) => {
warn!("control accept_in failed: {:?}", e);
return;
}
}
}
}

View File

@ -147,7 +147,7 @@ pub trait ControlPipe {
type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
where
Self: 'a;
type DataInFuture<'a>: Future<Output = ()> + 'a
type DataInFuture<'a>: Future<Output = Result<(), WriteError>> + 'a
where
Self: 'a;