diff options
| author | alexmoon <[email protected]> | 2022-03-29 17:13:49 -0400 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-04-06 05:38:11 +0200 |
| commit | c06488eb2978d9eaa8dc6a2669a6ce279638f4b2 (patch) | |
| tree | f501af6dd014597e73a94ec9a1b39eb599aed45d | |
| parent | d40ebcccf67c9848d9a22efd02eda9157955a4b4 (diff) | |
Support multi-frame data phase control requests
| -rw-r--r-- | embassy-nrf/src/usb.rs | 83 |
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 | ||
| 510 | impl<'d, T: Instance> ControlPipe<'d, T> { | 510 | impl<'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 | ||
