usb: abort control data in/out on reset or when receiving another SETUP.
This removes the horrible timeout hack.
This commit is contained in:
parent
f6d11dfba5
commit
22a47aeeb2
3 changed files with 50 additions and 31 deletions
|
@ -6,7 +6,6 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use cortex_m::peripheral::NVIC;
|
use cortex_m::peripheral::NVIC;
|
||||||
use embassy::interrupt::InterruptExt;
|
use embassy::interrupt::InterruptExt;
|
||||||
use embassy::time::{with_timeout, Duration};
|
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
|
@ -59,6 +58,7 @@ impl<'d, T: Instance> Driver<'d, T> {
|
||||||
if regs.events_usbreset.read().bits() != 0 {
|
if regs.events_usbreset.read().bits() != 0 {
|
||||||
regs.intenclr.write(|w| w.usbreset().clear());
|
regs.intenclr.write(|w| w.usbreset().clear());
|
||||||
BUS_WAKER.wake();
|
BUS_WAKER.wake();
|
||||||
|
EP0_WAKER.wake();
|
||||||
}
|
}
|
||||||
|
|
||||||
if regs.events_ep0setup.read().bits() != 0 {
|
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> {
|
impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||||
type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a;
|
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 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 {
|
fn max_packet_size(&self) -> usize {
|
||||||
usize::from(self.max_packet_size)
|
usize::from(self.max_packet_size)
|
||||||
|
@ -596,7 +596,10 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
// Wait for SETUP packet
|
// Wait for SETUP packet
|
||||||
regs.intenset.write(|w| w.ep0setup().set());
|
regs.intenset.write(|w| {
|
||||||
|
w.ep0setup().set();
|
||||||
|
w.ep0datadone().set()
|
||||||
|
});
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
EP0_WAKER.register(cx.waker());
|
EP0_WAKER.register(cx.waker());
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
@ -639,22 +642,27 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
// Wait until ready
|
// 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| {
|
poll_fn(|cx| {
|
||||||
EP0_WAKER.register(cx.waker());
|
EP0_WAKER.register(cx.waker());
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
if regs
|
if regs.events_usbreset.read().bits() != 0 {
|
||||||
.events_ep0datadone
|
trace!("aborted control data_out: usb reset");
|
||||||
.read()
|
Poll::Ready(Err(ReadError::Disabled))
|
||||||
.events_ep0datadone()
|
} else if regs.events_ep0setup.read().bits() != 0 {
|
||||||
.bit_is_set()
|
trace!("aborted control data_out: received another SETUP");
|
||||||
{
|
Poll::Ready(Err(ReadError::Disabled))
|
||||||
Poll::Ready(())
|
} else if regs.events_ep0datadone.read().bits() != 0 {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
} else {
|
} else {
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await?;
|
||||||
|
|
||||||
unsafe { read_dma::<T>(0, buf) }
|
unsafe { read_dma::<T>(0, buf) }
|
||||||
}
|
}
|
||||||
|
@ -671,24 +679,29 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||||
regs.shorts
|
regs.shorts
|
||||||
.modify(|_, w| w.ep0datadone_ep0status().bit(last_packet));
|
.modify(|_, w| w.ep0datadone_ep0status().bit(last_packet));
|
||||||
|
|
||||||
regs.intenset.write(|w| w.ep0datadone().set());
|
regs.intenset.write(|w| {
|
||||||
let res = with_timeout(
|
w.usbreset().set();
|
||||||
Duration::from_millis(10),
|
w.ep0setup().set();
|
||||||
|
w.ep0datadone().set()
|
||||||
|
});
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
EP0_WAKER.register(cx.waker());
|
EP0_WAKER.register(cx.waker());
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
if regs.events_ep0datadone.read().bits() != 0 {
|
if regs.events_usbreset.read().bits() != 0 {
|
||||||
Poll::Ready(())
|
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 {
|
} else {
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}),
|
})
|
||||||
)
|
.await
|
||||||
.await;
|
|
||||||
|
|
||||||
if res.is_err() {
|
|
||||||
error!("ControlPipe::data_in timed out.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,13 @@ impl<C: driver::ControlPipe> ControlPipe<C> {
|
||||||
.chain(need_zlp.then(|| -> &[u8] { &[] }));
|
.chain(need_zlp.then(|| -> &[u8] { &[] }));
|
||||||
|
|
||||||
while let Some(chunk) = chunks.next() {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ pub trait ControlPipe {
|
||||||
type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
|
type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
type DataInFuture<'a>: Future<Output = ()> + 'a
|
type DataInFuture<'a>: Future<Output = Result<(), WriteError>> + 'a
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue