aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-04-06 03:14:22 +0200
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit22a47aeeb2bc9d459a6e83414632890164a7b448 (patch)
tree294dac5c31fa1e46a88314e95d3dd5feeba4d20e
parentf6d11dfba56b2b04868e87a14d10395e1916306d (diff)
usb: abort control data in/out on reset or when receiving another SETUP.
This removes the horrible timeout hack.
-rw-r--r--embassy-nrf/src/usb.rs71
-rw-r--r--embassy-usb/src/control.rs8
-rw-r--r--embassy-usb/src/driver.rs2
3 files changed, 50 insertions, 31 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index c16e1be00..b5e173078 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -6,7 +6,6 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7use cortex_m::peripheral::NVIC; 7use cortex_m::peripheral::NVIC;
8use embassy::interrupt::InterruptExt; 8use embassy::interrupt::InterruptExt;
9use embassy::time::{with_timeout, Duration};
10use embassy::util::Unborrow; 9use embassy::util::Unborrow;
11use embassy::waitqueue::AtomicWaker; 10use embassy::waitqueue::AtomicWaker;
12use embassy_hal_common::unborrow; 11use embassy_hal_common::unborrow;
@@ -59,6 +58,7 @@ impl<'d, T: Instance> Driver<'d, T> {
59 if regs.events_usbreset.read().bits() != 0 { 58 if regs.events_usbreset.read().bits() != 0 {
60 regs.intenclr.write(|w| w.usbreset().clear()); 59 regs.intenclr.write(|w| w.usbreset().clear());
61 BUS_WAKER.wake(); 60 BUS_WAKER.wake();
61 EP0_WAKER.wake();
62 } 62 }
63 63
64 if regs.events_ep0setup.read().bits() != 0 { 64 if regs.events_ep0setup.read().bits() != 0 {
@@ -585,7 +585,7 @@ pub struct ControlPipe<'d, T: Instance> {
585impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { 585impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
586 type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a; 586 type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a;
587 type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a; 587 type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a;
588 type DataInFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a; 588 type DataInFuture<'a> = impl Future<Output = Result<(), WriteError>> + 'a where Self: 'a;
589 589
590 fn max_packet_size(&self) -> usize { 590 fn max_packet_size(&self) -> usize {
591 usize::from(self.max_packet_size) 591 usize::from(self.max_packet_size)
@@ -596,7 +596,10 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
596 let regs = T::regs(); 596 let regs = T::regs();
597 597
598 // Wait for SETUP packet 598 // Wait for SETUP packet
599 regs.intenset.write(|w| w.ep0setup().set()); 599 regs.intenset.write(|w| {
600 w.ep0setup().set();
601 w.ep0datadone().set()
602 });
600 poll_fn(|cx| { 603 poll_fn(|cx| {
601 EP0_WAKER.register(cx.waker()); 604 EP0_WAKER.register(cx.waker());
602 let regs = T::regs(); 605 let regs = T::regs();
@@ -639,22 +642,27 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
639 let regs = T::regs(); 642 let regs = T::regs();
640 643
641 // Wait until ready 644 // Wait until ready
642 regs.intenset.write(|w| w.ep0datadone().set()); 645 regs.intenset.write(|w| {
646 w.usbreset().set();
647 w.ep0setup().set();
648 w.ep0datadone().set()
649 });
643 poll_fn(|cx| { 650 poll_fn(|cx| {
644 EP0_WAKER.register(cx.waker()); 651 EP0_WAKER.register(cx.waker());
645 let regs = T::regs(); 652 let regs = T::regs();
646 if regs 653 if regs.events_usbreset.read().bits() != 0 {
647 .events_ep0datadone 654 trace!("aborted control data_out: usb reset");
648 .read() 655 Poll::Ready(Err(ReadError::Disabled))
649 .events_ep0datadone() 656 } else if regs.events_ep0setup.read().bits() != 0 {
650 .bit_is_set() 657 trace!("aborted control data_out: received another SETUP");
651 { 658 Poll::Ready(Err(ReadError::Disabled))
652 Poll::Ready(()) 659 } else if regs.events_ep0datadone.read().bits() != 0 {
660 Poll::Ready(Ok(()))
653 } else { 661 } else {
654 Poll::Pending 662 Poll::Pending
655 } 663 }
656 }) 664 })
657 .await; 665 .await?;
658 666
659 unsafe { read_dma::<T>(0, buf) } 667 unsafe { read_dma::<T>(0, buf) }
660 } 668 }
@@ -671,24 +679,29 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
671 regs.shorts 679 regs.shorts
672 .modify(|_, w| w.ep0datadone_ep0status().bit(last_packet)); 680 .modify(|_, w| w.ep0datadone_ep0status().bit(last_packet));
673 681
674 regs.intenset.write(|w| w.ep0datadone().set()); 682 regs.intenset.write(|w| {
675 let res = with_timeout( 683 w.usbreset().set();
676 Duration::from_millis(10), 684 w.ep0setup().set();
677 poll_fn(|cx| { 685 w.ep0datadone().set()
678 EP0_WAKER.register(cx.waker()); 686 });
679 let regs = T::regs();
680 if regs.events_ep0datadone.read().bits() != 0 {
681 Poll::Ready(())
682 } else {
683 Poll::Pending
684 }
685 }),
686 )
687 .await;
688 687
689 if res.is_err() { 688 poll_fn(|cx| {
690 error!("ControlPipe::data_in timed out."); 689 cx.waker().wake_by_ref();
691 } 690 EP0_WAKER.register(cx.waker());
691 let regs = T::regs();
692 if regs.events_usbreset.read().bits() != 0 {
693 trace!("aborted control data_in: usb reset");
694 Poll::Ready(Err(WriteError::Disabled))
695 } else if regs.events_ep0setup.read().bits() != 0 {
696 trace!("aborted control data_in: received another SETUP");
697 Poll::Ready(Err(WriteError::Disabled))
698 } else if regs.events_ep0datadone.read().bits() != 0 {
699 Poll::Ready(Ok(()))
700 } else {
701 Poll::Pending
702 }
703 })
704 .await
692 } 705 }
693 } 706 }
694 707
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index b15ba4463..7c46812bd 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -295,7 +295,13 @@ impl<C: driver::ControlPipe> ControlPipe<C> {
295 .chain(need_zlp.then(|| -> &[u8] { &[] })); 295 .chain(need_zlp.then(|| -> &[u8] { &[] }));
296 296
297 while let Some(chunk) = chunks.next() { 297 while let Some(chunk) = chunks.next() {
298 self.control.data_in(chunk, chunks.size_hint().0 == 0).await; 298 match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
299 Ok(()) => {}
300 Err(e) => {
301 warn!("control accept_in failed: {:?}", e);
302 return;
303 }
304 }
299 } 305 }
300 } 306 }
301 307
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index 6eaa40b0d..d3231cb45 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -147,7 +147,7 @@ pub trait ControlPipe {
147 type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a 147 type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
148 where 148 where
149 Self: 'a; 149 Self: 'a;
150 type DataInFuture<'a>: Future<Output = ()> + 'a 150 type DataInFuture<'a>: Future<Output = Result<(), WriteError>> + 'a
151 where 151 where
152 Self: 'a; 152 Self: 'a;
153 153