aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-29 17:13:49 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commitc06488eb2978d9eaa8dc6a2669a6ce279638f4b2 (patch)
treef501af6dd014597e73a94ec9a1b39eb599aed45d
parentd40ebcccf67c9848d9a22efd02eda9157955a4b4 (diff)
Support multi-frame data phase control requests
-rw-r--r--embassy-nrf/src/usb.rs83
1 files changed, 54 insertions, 29 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index d1c94dbb7..1cd5a9ebb 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -508,6 +508,30 @@ pub struct ControlPipe<'d, T: Instance> {
508} 508}
509 509
510impl<'d, T: Instance> ControlPipe<'d, T> { 510impl<'d, T: Instance> ControlPipe<'d, T> {
511 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> {
512 let regs = T::regs();
513
514 // Wait until ready
515 regs.intenset.write(|w| w.ep0datadone().set());
516 poll_fn(|cx| {
517 EP_OUT_WAKERS[0].register(cx.waker());
518 let regs = T::regs();
519 if regs
520 .events_ep0datadone
521 .read()
522 .events_ep0datadone()
523 .bit_is_set()
524 {
525 Poll::Ready(())
526 } else {
527 Poll::Pending
528 }
529 })
530 .await;
531
532 unsafe { read_dma::<T>(0, buf) }
533 }
534
511 async fn write(&mut self, buf: &[u8], last_chunk: bool) { 535 async fn write(&mut self, buf: &[u8], last_chunk: bool) {
512 let regs = T::regs(); 536 let regs = T::regs();
513 regs.events_ep0datadone.reset(); 537 regs.events_ep0datadone.reset();
@@ -595,29 +619,19 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
595 let req = self.request.unwrap(); 619 let req = self.request.unwrap();
596 assert_eq!(req.direction, UsbDirection::Out); 620 assert_eq!(req.direction, UsbDirection::Out);
597 assert!(req.length > 0); 621 assert!(req.length > 0);
598 assert!(buf.len() >= usize::from(req.length));
599
600 let regs = T::regs();
601 622
602 // Wait until ready 623 let req_length = usize::from(req.length);
603 regs.intenset.write(|w| w.ep0datadone().set()); 624 let max_packet_size = usize::from(self.max_packet_size);
604 poll_fn(|cx| { 625 let mut total = 0;
605 EP_OUT_WAKERS[0].register(cx.waker()); 626 for chunk in buf.chunks_mut(max_packet_size) {
606 let regs = T::regs(); 627 let size = self.read(chunk).await?;
607 if regs 628 total += size;
608 .events_ep0datadone 629 if size < max_packet_size || total == req_length {
609 .read() 630 break;
610 .events_ep0datadone()
611 .bit_is_set()
612 {
613 Poll::Ready(())
614 } else {
615 Poll::Pending
616 } 631 }
617 }) 632 }
618 .await;
619 633
620 unsafe { read_dma::<T>(0, buf) } 634 Ok(total)
621 } 635 }
622 } 636 }
623 637
@@ -697,16 +711,27 @@ impl Allocator {
697 711
698 // Endpoint directions are allocated individually. 712 // Endpoint directions are allocated individually.
699 713
700 let alloc_index = match ep_type { 714 let alloc_index = if let Some(ep_addr) = ep_addr {
701 EndpointType::Isochronous => 8, 715 match (ep_addr.index(), ep_type) {
702 EndpointType::Control => 0, 716 (0, EndpointType::Control) => {}
703 EndpointType::Interrupt | EndpointType::Bulk => { 717 (8, EndpointType::Isochronous) => {}
704 // Find rightmost zero bit in 1..=7 718 (n, EndpointType::Bulk) | (n, EndpointType::Interrupt) if n >= 1 && n <= 7 => {}
705 let ones = (self.used >> 1).trailing_ones() as usize; 719 _ => return Err(driver::EndpointAllocError),
706 if ones >= 7 { 720 }
707 return Err(driver::EndpointAllocError); 721
722 ep_addr.index()
723 } else {
724 match ep_type {
725 EndpointType::Isochronous => 8,
726 EndpointType::Control => 0,
727 EndpointType::Interrupt | EndpointType::Bulk => {
728 // Find rightmost zero bit in 1..=7
729 let ones = (self.used >> 1).trailing_ones() as usize;
730 if ones >= 7 {
731 return Err(driver::EndpointAllocError);
732 }
733 ones + 1
708 } 734 }
709 ones + 1
710 } 735 }
711 }; 736 };
712 737