Support multi-frame data phase control requests
This commit is contained in:
		
				
					committed by
					
						 Dario Nieuwenhuis
						Dario Nieuwenhuis
					
				
			
			
				
	
			
			
			
						parent
						
							d40ebcccf6
						
					
				
				
					commit
					c06488eb29
				
			| @@ -508,6 +508,30 @@ pub struct ControlPipe<'d, T: Instance> { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> ControlPipe<'d, T> { | impl<'d, T: Instance> ControlPipe<'d, T> { | ||||||
|  |     async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> { | ||||||
|  |         let regs = T::regs(); | ||||||
|  |  | ||||||
|  |         // Wait until ready | ||||||
|  |         regs.intenset.write(|w| w.ep0datadone().set()); | ||||||
|  |         poll_fn(|cx| { | ||||||
|  |             EP_OUT_WAKERS[0].register(cx.waker()); | ||||||
|  |             let regs = T::regs(); | ||||||
|  |             if regs | ||||||
|  |                 .events_ep0datadone | ||||||
|  |                 .read() | ||||||
|  |                 .events_ep0datadone() | ||||||
|  |                 .bit_is_set() | ||||||
|  |             { | ||||||
|  |                 Poll::Ready(()) | ||||||
|  |             } else { | ||||||
|  |                 Poll::Pending | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .await; | ||||||
|  |  | ||||||
|  |         unsafe { read_dma::<T>(0, buf) } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async fn write(&mut self, buf: &[u8], last_chunk: bool) { |     async fn write(&mut self, buf: &[u8], last_chunk: bool) { | ||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         regs.events_ep0datadone.reset(); |         regs.events_ep0datadone.reset(); | ||||||
| @@ -595,29 +619,19 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { | |||||||
|             let req = self.request.unwrap(); |             let req = self.request.unwrap(); | ||||||
|             assert_eq!(req.direction, UsbDirection::Out); |             assert_eq!(req.direction, UsbDirection::Out); | ||||||
|             assert!(req.length > 0); |             assert!(req.length > 0); | ||||||
|             assert!(buf.len() >= usize::from(req.length)); |  | ||||||
|  |  | ||||||
|             let regs = T::regs(); |             let req_length = usize::from(req.length); | ||||||
|  |             let max_packet_size = usize::from(self.max_packet_size); | ||||||
|             // Wait until ready |             let mut total = 0; | ||||||
|             regs.intenset.write(|w| w.ep0datadone().set()); |             for chunk in buf.chunks_mut(max_packet_size) { | ||||||
|             poll_fn(|cx| { |                 let size = self.read(chunk).await?; | ||||||
|                 EP_OUT_WAKERS[0].register(cx.waker()); |                 total += size; | ||||||
|                 let regs = T::regs(); |                 if size < max_packet_size || total == req_length { | ||||||
|                 if regs |                     break; | ||||||
|                     .events_ep0datadone |  | ||||||
|                     .read() |  | ||||||
|                     .events_ep0datadone() |  | ||||||
|                     .bit_is_set() |  | ||||||
|                 { |  | ||||||
|                     Poll::Ready(()) |  | ||||||
|                 } else { |  | ||||||
|                     Poll::Pending |  | ||||||
|                 } |                 } | ||||||
|             }) |             } | ||||||
|             .await; |  | ||||||
|  |  | ||||||
|             unsafe { read_dma::<T>(0, buf) } |             Ok(total) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -697,16 +711,27 @@ impl Allocator { | |||||||
|  |  | ||||||
|         // Endpoint directions are allocated individually. |         // Endpoint directions are allocated individually. | ||||||
|  |  | ||||||
|         let alloc_index = match ep_type { |         let alloc_index = if let Some(ep_addr) = ep_addr { | ||||||
|             EndpointType::Isochronous => 8, |             match (ep_addr.index(), ep_type) { | ||||||
|             EndpointType::Control => 0, |                 (0, EndpointType::Control) => {} | ||||||
|             EndpointType::Interrupt | EndpointType::Bulk => { |                 (8, EndpointType::Isochronous) => {} | ||||||
|                 // Find rightmost zero bit in 1..=7 |                 (n, EndpointType::Bulk) | (n, EndpointType::Interrupt) if n >= 1 && n <= 7 => {} | ||||||
|                 let ones = (self.used >> 1).trailing_ones() as usize; |                 _ => return Err(driver::EndpointAllocError), | ||||||
|                 if ones >= 7 { |             } | ||||||
|                     return Err(driver::EndpointAllocError); |  | ||||||
|  |             ep_addr.index() | ||||||
|  |         } else { | ||||||
|  |             match ep_type { | ||||||
|  |                 EndpointType::Isochronous => 8, | ||||||
|  |                 EndpointType::Control => 0, | ||||||
|  |                 EndpointType::Interrupt | EndpointType::Bulk => { | ||||||
|  |                     // Find rightmost zero bit in 1..=7 | ||||||
|  |                     let ones = (self.used >> 1).trailing_ones() as usize; | ||||||
|  |                     if ones >= 7 { | ||||||
|  |                         return Err(driver::EndpointAllocError); | ||||||
|  |                     } | ||||||
|  |                     ones + 1 | ||||||
|                 } |                 } | ||||||
|                 ones + 1 |  | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user