aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-29 20:26:30 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit77e0aca03b89ebc5f1e93b6c64b6c91ca10cedd1 (patch)
treeb0b5982f3daddafa7bc36362adcddeae11b07023
parent1672fdc666188454a56b9369150e54420dc67078 (diff)
Move data chunking from the driver to the lib
-rw-r--r--embassy-nrf/src/usb.rs153
-rw-r--r--embassy-usb/src/driver.rs23
-rw-r--r--embassy-usb/src/lib.rs115
3 files changed, 161 insertions, 130 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 1057d880c..570d1c95b 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -186,7 +186,6 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
186 Ok(ControlPipe { 186 Ok(ControlPipe {
187 _phantom: PhantomData, 187 _phantom: PhantomData,
188 max_packet_size, 188 max_packet_size,
189 request: None,
190 }) 189 })
191 } 190 }
192 191
@@ -502,72 +501,19 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
502pub struct ControlPipe<'d, T: Instance> { 501pub struct ControlPipe<'d, T: Instance> {
503 _phantom: PhantomData<&'d mut T>, 502 _phantom: PhantomData<&'d mut T>,
504 max_packet_size: u16, 503 max_packet_size: u16,
505 request: Option<Request>,
506}
507
508impl<'d, T: Instance> ControlPipe<'d, T> {
509 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> {
510 let regs = T::regs();
511
512 // Wait until ready
513 regs.intenset.write(|w| w.ep0datadone().set());
514 poll_fn(|cx| {
515 EP_OUT_WAKERS[0].register(cx.waker());
516 let regs = T::regs();
517 if regs
518 .events_ep0datadone
519 .read()
520 .events_ep0datadone()
521 .bit_is_set()
522 {
523 Poll::Ready(())
524 } else {
525 Poll::Pending
526 }
527 })
528 .await;
529
530 unsafe { read_dma::<T>(0, buf) }
531 }
532
533 async fn write(&mut self, buf: &[u8], last_chunk: bool) {
534 let regs = T::regs();
535 regs.events_ep0datadone.reset();
536 unsafe { write_dma::<T>(0, buf) }
537
538 regs.shorts
539 .modify(|_, w| w.ep0datadone_ep0status().bit(last_chunk));
540
541 regs.intenset.write(|w| w.ep0datadone().set());
542 let res = with_timeout(
543 Duration::from_millis(10),
544 poll_fn(|cx| {
545 EP_IN_WAKERS[0].register(cx.waker());
546 let regs = T::regs();
547 if regs.events_ep0datadone.read().bits() != 0 {
548 Poll::Ready(())
549 } else {
550 Poll::Pending
551 }
552 }),
553 )
554 .await;
555
556 if res.is_err() {
557 error!("ControlPipe::write timed out.");
558 }
559 }
560} 504}
561 505
562impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { 506impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
563 type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a; 507 type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a;
564 type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a; 508 type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a;
565 type AcceptInFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a; 509 type DataInFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
510
511 fn max_packet_size(&self) -> usize {
512 usize::from(self.max_packet_size)
513 }
566 514
567 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a> { 515 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a> {
568 async move { 516 async move {
569 assert!(self.request.is_none());
570
571 let regs = T::regs(); 517 let regs = T::regs();
572 518
573 // Wait for SETUP packet 519 // Wait for SETUP packet
@@ -605,29 +551,65 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
605 .write(|w| w.tasks_ep0rcvout().set_bit()); 551 .write(|w| w.tasks_ep0rcvout().set_bit());
606 } 552 }
607 553
608 self.request = Some(req);
609 req 554 req
610 } 555 }
611 } 556 }
612 557
613 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a> { 558 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a> {
614 async move { 559 async move {
615 let req = unwrap!(self.request); 560 let regs = T::regs();
616 assert!(req.direction == UsbDirection::Out); 561
617 assert!(req.length > 0); 562 // Wait until ready
618 563 regs.intenset.write(|w| w.ep0datadone().set());
619 let req_length = usize::from(req.length); 564 poll_fn(|cx| {
620 let max_packet_size = usize::from(self.max_packet_size); 565 EP_OUT_WAKERS[0].register(cx.waker());
621 let mut total = 0; 566 let regs = T::regs();
622 for chunk in buf.chunks_mut(max_packet_size) { 567 if regs
623 let size = self.read(chunk).await?; 568 .events_ep0datadone
624 total += size; 569 .read()
625 if size < max_packet_size || total == req_length { 570 .events_ep0datadone()
626 break; 571 .bit_is_set()
572 {
573 Poll::Ready(())
574 } else {
575 Poll::Pending
627 } 576 }
577 })
578 .await;
579
580 unsafe { read_dma::<T>(0, buf) }
581 }
582 }
583
584 fn data_in<'a>(&'a mut self, buf: &'a [u8], last_packet: bool) -> Self::DataInFuture<'a> {
585 async move {
586 let regs = T::regs();
587 regs.events_ep0datadone.reset();
588 unsafe {
589 write_dma::<T>(0, buf);
628 } 590 }
629 591
630 Ok(total) 592 regs.shorts
593 .modify(|_, w| w.ep0datadone_ep0status().bit(last_packet));
594
595 regs.intenset.write(|w| w.ep0datadone().set());
596 let res = with_timeout(
597 Duration::from_millis(10),
598 poll_fn(|cx| {
599 EP_IN_WAKERS[0].register(cx.waker());
600 let regs = T::regs();
601 if regs.events_ep0datadone.read().bits() != 0 {
602 Poll::Ready(())
603 } else {
604 Poll::Pending
605 }
606 }),
607 )
608 .await;
609
610 if res.is_err() {
611 error!("ControlPipe::data_in timed out.");
612 }
631 } 613 }
632 } 614 }
633 615
@@ -636,37 +618,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
636 let regs = T::regs(); 618 let regs = T::regs();
637 regs.tasks_ep0status 619 regs.tasks_ep0status
638 .write(|w| w.tasks_ep0status().bit(true)); 620 .write(|w| w.tasks_ep0status().bit(true));
639 self.request = None;
640 }
641
642 fn accept_in<'a>(&'a mut self, buf: &'a [u8]) -> Self::AcceptInFuture<'a> {
643 async move {
644 #[cfg(feature = "defmt")]
645 debug!("control in accept {:x}", buf);
646 #[cfg(not(feature = "defmt"))]
647 debug!("control in accept {:x?}", buf);
648 let req = unwrap!(self.request);
649 assert!(req.direction == UsbDirection::In);
650
651 let req_len = usize::from(req.length);
652 let len = buf.len().min(req_len);
653 let need_zlp = len != req_len && (len % usize::from(self.max_packet_size)) == 0;
654 let mut chunks = buf[0..len]
655 .chunks(usize::from(self.max_packet_size))
656 .chain(need_zlp.then(|| -> &[u8] { &[] }));
657 while let Some(chunk) = chunks.next() {
658 self.write(chunk, chunks.size_hint().0 == 0).await;
659 }
660
661 self.request = None;
662 }
663 } 621 }
664 622
665 fn reject(&mut self) { 623 fn reject(&mut self) {
666 debug!("control reject"); 624 debug!("control reject");
667 let regs = T::regs(); 625 let regs = T::regs();
668 regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true)); 626 regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true));
669 self.request = None;
670 } 627 }
671} 628}
672 629
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index 1c6ba1f52..82b59bd1e 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -137,30 +137,35 @@ pub trait ControlPipe {
137 type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a 137 type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
138 where 138 where
139 Self: 'a; 139 Self: 'a;
140 type AcceptInFuture<'a>: Future<Output = ()> + 'a 140 type DataInFuture<'a>: Future<Output = ()> + 'a
141 where 141 where
142 Self: 'a; 142 Self: 'a;
143 143
144 /// Maximum packet size for the control pipe
145 fn max_packet_size(&self) -> usize;
146
144 /// Reads a single setup packet from the endpoint. 147 /// Reads a single setup packet from the endpoint.
145 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a>; 148 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a>;
146 149
147 /// Reads the data packet of a control write sequence. 150 /// Reads a DATA OUT packet into `buf` in response to a control write request.
148 /// 151 ///
149 /// Must be called after `setup()` for requests with `direction` of `Out` 152 /// Must be called after `setup()` for requests with `direction` of `Out`
150 /// and `length` greater than zero. 153 /// and `length` greater than zero.
151 ///
152 /// `buf.len()` must be greater than or equal to the request's `length`.
153 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a>; 154 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a>;
154 155
155 /// Accepts a control request. 156 /// Sends a DATA IN packet with `data` in response to a control read request.
156 fn accept(&mut self); 157 ///
158 /// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`.
159 fn data_in<'a>(&'a mut self, data: &'a [u8], last_packet: bool) -> Self::DataInFuture<'a>;
157 160
158 /// Accepts a control read request with `data`. 161 /// Accepts a control request.
159 /// 162 ///
160 /// `data.len()` must be less than or equal to the request's `length`. 163 /// Causes the STATUS packet for the current request to be ACKed.
161 fn accept_in<'a>(&'a mut self, data: &'a [u8]) -> Self::AcceptInFuture<'a>; 164 fn accept(&mut self);
162 165
163 /// Rejects a control request. 166 /// Rejects a control request.
167 ///
168 /// Sets a STALL condition on the pipe to indicate an error.
164 fn reject(&mut self); 169 fn reject(&mut self);
165} 170}
166 171
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 32b67a766..77a9c33be 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -55,7 +55,7 @@ pub const MAX_INTERFACE_COUNT: usize = 4;
55 55
56pub struct UsbDevice<'d, D: Driver<'d>> { 56pub struct UsbDevice<'d, D: Driver<'d>> {
57 bus: D::Bus, 57 bus: D::Bus,
58 control: D::ControlPipe, 58 control: ControlPipe<D::ControlPipe>,
59 59
60 config: Config<'d>, 60 config: Config<'d>,
61 device_descriptor: &'d [u8], 61 device_descriptor: &'d [u8],
@@ -92,7 +92,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
92 Self { 92 Self {
93 bus: driver, 93 bus: driver,
94 config, 94 config,
95 control, 95 control: ControlPipe {
96 control,
97 request: None,
98 },
96 device_descriptor, 99 device_descriptor,
97 config_descriptor, 100 config_descriptor,
98 bos_descriptor, 101 bos_descriptor,
@@ -140,32 +143,19 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
140 } 143 }
141 } 144 }
142 145
143 async fn control_in_accept_writer(
144 &mut self,
145 req: Request,
146 f: impl FnOnce(&mut DescriptorWriter),
147 ) {
148 let mut buf = [0; 256];
149 let mut w = DescriptorWriter::new(&mut buf);
150 f(&mut w);
151 let pos = w.position().min(usize::from(req.length));
152 self.control.accept_in(&buf[..pos]).await;
153 }
154
155 async fn handle_control_out(&mut self, req: Request) { 146 async fn handle_control_out(&mut self, req: Request) {
156 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; 147 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
157 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; 148 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
158 149
159 // If the request has a data state, we must read it. 150 // If the request has a data state, we must read it.
160 let data = if req.length > 0 { 151 let data = if req.length > 0 {
161 let size = match self.control.data_out(self.control_buf).await { 152 match self.control.data_out(self.control_buf).await {
162 Ok(size) => size, 153 Ok(data) => data,
163 Err(_) => { 154 Err(_) => {
164 warn!("usb: failed to read CONTROL OUT data stage."); 155 warn!("usb: failed to read CONTROL OUT data stage.");
165 return; 156 return;
166 } 157 }
167 }; 158 }
168 &self.control_buf[0..size]
169 } else { 159 } else {
170 &[] 160 &[]
171 }; 161 };
@@ -315,10 +305,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
315 descriptor_type::CONFIGURATION => self.control.accept_in(self.config_descriptor).await, 305 descriptor_type::CONFIGURATION => self.control.accept_in(self.config_descriptor).await,
316 descriptor_type::STRING => { 306 descriptor_type::STRING => {
317 if index == 0 { 307 if index == 0 {
318 self.control_in_accept_writer(req, |w| { 308 self.control
319 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()) 309 .accept_in_writer(req, |w| {
320 }) 310 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes());
321 .await 311 })
312 .await
322 } else { 313 } else {
323 let s = match index { 314 let s = match index {
324 1 => self.config.manufacturer, 315 1 => self.config.manufacturer,
@@ -333,7 +324,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
333 }; 324 };
334 325
335 if let Some(s) = s { 326 if let Some(s) = s {
336 self.control_in_accept_writer(req, |w| w.string(s)).await; 327 self.control.accept_in_writer(req, |w| w.string(s)).await;
337 } else { 328 } else {
338 self.control.reject() 329 self.control.reject()
339 } 330 }
@@ -343,3 +334,81 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
343 } 334 }
344 } 335 }
345} 336}
337
338struct ControlPipe<C: driver::ControlPipe> {
339 control: C,
340 request: Option<Request>,
341}
342
343impl<C: driver::ControlPipe> ControlPipe<C> {
344 async fn setup(&mut self) -> Request {
345 assert!(self.request.is_none());
346 let req = self.control.setup().await;
347 self.request = Some(req);
348 req
349 }
350
351 async fn data_out<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], ReadError> {
352 let req = self.request.unwrap();
353 assert_eq!(req.direction, UsbDirection::Out);
354 assert!(req.length > 0);
355 let req_length = usize::from(req.length);
356
357 let max_packet_size = self.control.max_packet_size();
358 let mut total = 0;
359
360 for chunk in buf.chunks_mut(max_packet_size) {
361 let size = self.control.data_out(chunk).await?;
362 total += size;
363 if size < max_packet_size || total == req_length {
364 break;
365 }
366 }
367
368 Ok(&buf[0..total])
369 }
370
371 async fn accept_in(&mut self, buf: &[u8]) -> () {
372 #[cfg(feature = "defmt")]
373 debug!("control in accept {:x}", buf);
374 #[cfg(not(feature = "defmt"))]
375 debug!("control in accept {:x?}", buf);
376 let req = unwrap!(self.request);
377 assert!(req.direction == UsbDirection::In);
378
379 let req_len = usize::from(req.length);
380 let len = buf.len().min(req_len);
381 let max_packet_size = self.control.max_packet_size();
382 let need_zlp = len != req_len && (len % usize::from(max_packet_size)) == 0;
383
384 let mut chunks = buf[0..len]
385 .chunks(max_packet_size)
386 .chain(need_zlp.then(|| -> &[u8] { &[] }));
387
388 while let Some(chunk) = chunks.next() {
389 self.control.data_in(chunk, chunks.size_hint().0 == 0).await;
390 }
391
392 self.request = None;
393 }
394
395 async fn accept_in_writer(&mut self, req: Request, f: impl FnOnce(&mut DescriptorWriter)) {
396 let mut buf = [0; 256];
397 let mut w = DescriptorWriter::new(&mut buf);
398 f(&mut w);
399 let pos = w.position().min(usize::from(req.length));
400 self.accept_in(&buf[..pos]).await;
401 }
402
403 fn accept(&mut self) {
404 assert!(self.request.is_some());
405 self.control.accept();
406 self.request = None;
407 }
408
409 fn reject(&mut self) {
410 assert!(self.request.is_some());
411 self.control.reject();
412 self.request = None;
413 }
414}