aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-25 16:46:14 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commitbdc6e0481c42d20d5cca19dfc8ec56306e47296e (patch)
tree6beb805dd6ffea30877b654aa42e5c83f5a36c0b /embassy-nrf/src
parent5c0db627feae071182dd9978ffb56b0524558d93 (diff)
Add support for USB classes handling control requests.
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/usb.rs424
1 files changed, 272 insertions, 152 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 5df5053ac..203f08fc0 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -9,6 +9,7 @@ use embassy::time::{with_timeout, Duration};
9use embassy::util::Unborrow; 9use embassy::util::Unborrow;
10use embassy::waitqueue::AtomicWaker; 10use embassy::waitqueue::AtomicWaker;
11use embassy_hal_common::unborrow; 11use embassy_hal_common::unborrow;
12use embassy_usb::control::Request;
12use embassy_usb::driver::{self, Event, ReadError, WriteError}; 13use embassy_usb::driver::{self, Event, ReadError, WriteError};
13use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 14use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
14use futures::future::poll_fn; 15use futures::future::poll_fn;
@@ -134,6 +135,7 @@ impl<'d, T: Instance> Driver<'d, T> {
134impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { 135impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
135 type EndpointOut = Endpoint<'d, T, Out>; 136 type EndpointOut = Endpoint<'d, T, Out>;
136 type EndpointIn = Endpoint<'d, T, In>; 137 type EndpointIn = Endpoint<'d, T, In>;
138 type ControlPipe = ControlPipe<'d, T>;
137 type Bus = Bus<'d, T>; 139 type Bus = Bus<'d, T>;
138 140
139 fn alloc_endpoint_in( 141 fn alloc_endpoint_in(
@@ -174,6 +176,19 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
174 })) 176 }))
175 } 177 }
176 178
179 fn alloc_control_pipe(
180 &mut self,
181 max_packet_size: u16,
182 ) -> Result<Self::ControlPipe, driver::EndpointAllocError> {
183 self.alloc_endpoint_out(Some(0x00.into()), EndpointType::Control, max_packet_size, 0)?;
184 self.alloc_endpoint_in(Some(0x80.into()), EndpointType::Control, max_packet_size, 0)?;
185 Ok(ControlPipe {
186 _phantom: PhantomData,
187 max_packet_size,
188 request: None,
189 })
190 }
191
177 fn enable(self) -> Self::Bus { 192 fn enable(self) -> Self::Bus {
178 let regs = T::regs(); 193 let regs = T::regs();
179 194
@@ -344,99 +359,110 @@ impl<'d, T: Instance, Dir> driver::Endpoint for Endpoint<'d, T, Dir> {
344 } 359 }
345} 360}
346 361
362unsafe fn read_dma<T: Instance>(i: usize, buf: &mut [u8]) -> Result<usize, ReadError> {
363 let regs = T::regs();
364
365 // Check that the packet fits into the buffer
366 let size = regs.size.epout[0].read().bits() as usize;
367 if size > buf.len() {
368 return Err(ReadError::BufferOverflow);
369 }
370
371 if i == 0 {
372 regs.events_ep0datadone.reset();
373 }
374
375 let epout = [
376 &regs.epout0,
377 &regs.epout1,
378 &regs.epout2,
379 &regs.epout3,
380 &regs.epout4,
381 &regs.epout5,
382 &regs.epout6,
383 &regs.epout7,
384 ];
385 epout[i].ptr.write(|w| w.bits(buf.as_ptr() as u32));
386 // MAXCNT must match SIZE
387 epout[i].maxcnt.write(|w| w.bits(size as u32));
388
389 dma_start();
390 regs.events_endepout[i].reset();
391 regs.tasks_startepout[i].write(|w| w.tasks_startepout().set_bit());
392 while regs.events_endepout[i]
393 .read()
394 .events_endepout()
395 .bit_is_clear()
396 {}
397 regs.events_endepout[i].reset();
398 dma_end();
399
400 regs.size.epout[i].reset();
401
402 Ok(size)
403}
404
405unsafe fn write_dma<T: Instance>(i: usize, buf: &[u8]) -> Result<(), WriteError> {
406 let regs = T::regs();
407 if buf.len() > 64 {
408 return Err(WriteError::BufferOverflow);
409 }
410
411 // EasyDMA can't read FLASH, so we copy through RAM
412 let mut ram_buf: MaybeUninit<[u8; 64]> = MaybeUninit::uninit();
413 let ptr = ram_buf.as_mut_ptr() as *mut u8;
414 core::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
415
416 let epin = [
417 &regs.epin0,
418 &regs.epin1,
419 &regs.epin2,
420 &regs.epin3,
421 &regs.epin4,
422 &regs.epin5,
423 &regs.epin6,
424 &regs.epin7,
425 ];
426
427 // Set the buffer length so the right number of bytes are transmitted.
428 // Safety: `buf.len()` has been checked to be <= the max buffer length.
429 epin[i].ptr.write(|w| w.bits(ptr as u32));
430 epin[i].maxcnt.write(|w| w.maxcnt().bits(buf.len() as u8));
431
432 regs.events_endepin[i].reset();
433
434 dma_start();
435 regs.tasks_startepin[i].write(|w| w.bits(1));
436 while regs.events_endepin[i].read().bits() == 0 {}
437 dma_end();
438
439 Ok(())
440}
441
347impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { 442impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
348 type ReadFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a; 443 type ReadFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a;
349 444
350 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { 445 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
351 async move { 446 async move {
352 let regs = T::regs();
353 let i = self.info.addr.index(); 447 let i = self.info.addr.index();
448 assert!(i != 0);
354 449
355 if i == 0 { 450 // Wait until ready
356 if buf.len() == 0 { 451 poll_fn(|cx| {
357 regs.tasks_ep0status.write(|w| unsafe { w.bits(1) }); 452 EP_OUT_WAKERS[i].register(cx.waker());
358 return Ok(0); 453 let r = READY_ENDPOINTS.load(Ordering::Acquire);
359 } 454 if r & (1 << (i + 16)) != 0 {
360 455 Poll::Ready(())
361 // Wait for SETUP packet 456 } else {
362 regs.events_ep0setup.reset(); 457 Poll::Pending
363 regs.intenset.write(|w| w.ep0setup().set());
364 poll_fn(|cx| {
365 EP_OUT_WAKERS[0].register(cx.waker());
366 let regs = T::regs();
367 if regs.events_ep0setup.read().bits() != 0 {
368 Poll::Ready(())
369 } else {
370 Poll::Pending
371 }
372 })
373 .await;
374
375 if buf.len() < 8 {
376 return Err(ReadError::BufferOverflow);
377 }
378
379 buf[0] = regs.bmrequesttype.read().bits() as u8;
380 buf[1] = regs.brequest.read().brequest().bits();
381 buf[2] = regs.wvaluel.read().wvaluel().bits();
382 buf[3] = regs.wvalueh.read().wvalueh().bits();
383 buf[4] = regs.windexl.read().windexl().bits();
384 buf[5] = regs.windexh.read().windexh().bits();
385 buf[6] = regs.wlengthl.read().wlengthl().bits();
386 buf[7] = regs.wlengthh.read().wlengthh().bits();
387
388 Ok(8)
389 } else {
390 // Wait until ready
391 poll_fn(|cx| {
392 EP_OUT_WAKERS[i].register(cx.waker());
393 let r = READY_ENDPOINTS.load(Ordering::Acquire);
394 if r & (1 << (i + 16)) != 0 {
395 Poll::Ready(())
396 } else {
397 Poll::Pending
398 }
399 })
400 .await;
401
402 // Mark as not ready
403 READY_ENDPOINTS.fetch_and(!(1 << (i + 16)), Ordering::AcqRel);
404
405 // Check that the packet fits into the buffer
406 let size = regs.size.epout[i].read().bits();
407 if size as usize > buf.len() {
408 return Err(ReadError::BufferOverflow);
409 } 458 }
459 })
460 .await;
410 461
411 let epout = [ 462 // Mark as not ready
412 &regs.epout0, 463 READY_ENDPOINTS.fetch_and(!(1 << (i + 16)), Ordering::AcqRel);
413 &regs.epout1,
414 &regs.epout2,
415 &regs.epout3,
416 &regs.epout4,
417 &regs.epout5,
418 &regs.epout6,
419 &regs.epout7,
420 ];
421 epout[i]
422 .ptr
423 .write(|w| unsafe { w.bits(buf.as_ptr() as u32) });
424 // MAXCNT must match SIZE
425 epout[i].maxcnt.write(|w| unsafe { w.bits(size) });
426
427 dma_start();
428 regs.events_endepout[i].reset();
429 regs.tasks_startepout[i].write(|w| w.tasks_startepout().set_bit());
430 while regs.events_endepout[i]
431 .read()
432 .events_endepout()
433 .bit_is_clear()
434 {}
435 regs.events_endepout[i].reset();
436 dma_end();
437 464
438 Ok(size as usize) 465 unsafe { read_dma::<T>(i, buf) }
439 }
440 } 466 }
441 } 467 }
442} 468}
@@ -446,87 +472,181 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
446 472
447 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { 473 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
448 async move { 474 async move {
449 let regs = T::regs();
450 let i = self.info.addr.index(); 475 let i = self.info.addr.index();
476 assert!(i != 0);
451 477
452 // Wait until ready. 478 // Wait until ready.
453 if i != 0 { 479 poll_fn(|cx| {
454 poll_fn(|cx| { 480 EP_IN_WAKERS[i].register(cx.waker());
455 EP_IN_WAKERS[i].register(cx.waker()); 481 let r = READY_ENDPOINTS.load(Ordering::Acquire);
456 let r = READY_ENDPOINTS.load(Ordering::Acquire); 482 if r & (1 << i) != 0 {
457 if r & (1 << i) != 0 { 483 Poll::Ready(())
458 Poll::Ready(()) 484 } else {
459 } else { 485 Poll::Pending
460 Poll::Pending 486 }
461 } 487 })
462 }) 488 .await;
463 .await;
464
465 // Mark as not ready
466 READY_ENDPOINTS.fetch_and(!(1 << i), Ordering::AcqRel);
467 }
468 489
469 if i == 0 { 490 // Mark as not ready
470 regs.events_ep0datadone.reset(); 491 READY_ENDPOINTS.fetch_and(!(1 << i), Ordering::AcqRel);
471 } 492
493 unsafe { write_dma::<T>(i, buf) }
494 }
495 }
496}
472 497
473 assert!(buf.len() <= 64); 498pub struct ControlPipe<'d, T: Instance> {
474 499 _phantom: PhantomData<&'d mut T>,
475 // EasyDMA can't read FLASH, so we copy through RAM 500 max_packet_size: u16,
476 let mut ram_buf: MaybeUninit<[u8; 64]> = MaybeUninit::uninit(); 501 request: Option<Request>,
477 let ptr = ram_buf.as_mut_ptr() as *mut u8; 502}
478 unsafe { core::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len()) }; 503
479 504impl<'d, T: Instance> ControlPipe<'d, T> {
480 let epin = [ 505 async fn write(&mut self, buf: &[u8], last_chunk: bool) {
481 &regs.epin0, 506 let regs = T::regs();
482 &regs.epin1, 507 regs.events_ep0datadone.reset();
483 &regs.epin2, 508 unsafe {
484 &regs.epin3, 509 write_dma::<T>(0, buf).unwrap();
485 &regs.epin4, 510 }
486 &regs.epin5, 511
487 &regs.epin6, 512 regs.shorts
488 &regs.epin7, 513 .modify(|_, w| w.ep0datadone_ep0status().bit(last_chunk));
489 ]; 514
490 515 regs.intenset.write(|w| w.ep0datadone().set());
491 // Set the buffer length so the right number of bytes are transmitted. 516 let res = with_timeout(
492 // Safety: `buf.len()` has been checked to be <= the max buffer length. 517 Duration::from_millis(10),
493 unsafe { 518 poll_fn(|cx| {
494 epin[i].ptr.write(|w| w.bits(ptr as u32)); 519 EP_IN_WAKERS[0].register(cx.waker());
495 epin[i].maxcnt.write(|w| w.maxcnt().bits(buf.len() as u8)); 520 let regs = T::regs();
521 if regs.events_ep0datadone.read().bits() != 0 {
522 Poll::Ready(())
523 } else {
524 Poll::Pending
525 }
526 }),
527 )
528 .await;
529
530 if res.is_err() {
531 error!("ControlPipe::write timed out.");
532 }
533 }
534}
535
536impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
537 type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a;
538 type DataOutFuture<'a> = impl Future<Output = Result<usize, ReadError>> + 'a where Self: 'a;
539 type AcceptInFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
540
541 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a> {
542 async move {
543 assert!(self.request.is_none());
544
545 let regs = T::regs();
546
547 // Wait for SETUP packet
548 regs.intenset.write(|w| w.ep0setup().set());
549 poll_fn(|cx| {
550 EP_OUT_WAKERS[0].register(cx.waker());
551 let regs = T::regs();
552 if regs.events_ep0setup.read().bits() != 0 {
553 Poll::Ready(())
554 } else {
555 Poll::Pending
556 }
557 })
558 .await;
559
560 // Reset shorts
561 regs.shorts
562 .modify(|_, w| w.ep0datadone_ep0status().clear_bit());
563 regs.events_ep0setup.reset();
564
565 let mut buf = [0; 8];
566 buf[0] = regs.bmrequesttype.read().bits() as u8;
567 buf[1] = regs.brequest.read().brequest().bits();
568 buf[2] = regs.wvaluel.read().wvaluel().bits();
569 buf[3] = regs.wvalueh.read().wvalueh().bits();
570 buf[4] = regs.windexl.read().windexl().bits();
571 buf[5] = regs.windexh.read().windexh().bits();
572 buf[6] = regs.wlengthl.read().wlengthl().bits();
573 buf[7] = regs.wlengthh.read().wlengthh().bits();
574
575 let req = Request::parse(&buf);
576
577 if req.direction == UsbDirection::Out {
578 regs.tasks_ep0rcvout
579 .write(|w| w.tasks_ep0rcvout().set_bit());
496 } 580 }
497 581
498 regs.events_endepin[i].reset(); 582 self.request = Some(req);
499 583 req
500 dma_start(); 584 }
501 regs.tasks_startepin[i].write(|w| unsafe { w.bits(1) }); 585 }
502 while regs.events_endepin[i].read().bits() == 0 {} 586
503 dma_end(); 587 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a> {
504 588 async move {
505 if i == 0 { 589 let req = self.request.unwrap();
506 regs.intenset.write(|w| w.ep0datadone().set()); 590 assert_eq!(req.direction, UsbDirection::Out);
507 let res = with_timeout( 591 assert!(req.length > 0);
508 Duration::from_millis(10), 592 assert!(buf.len() >= usize::from(req.length));
509 poll_fn(|cx| { 593
510 EP_IN_WAKERS[0].register(cx.waker()); 594 let regs = T::regs();
511 let regs = T::regs(); 595
512 if regs.events_ep0datadone.read().bits() != 0 { 596 // Wait until ready
513 Poll::Ready(()) 597 regs.intenset.write(|w| w.ep0datadone().set());
514 } else { 598 poll_fn(|cx| {
515 Poll::Pending 599 EP_OUT_WAKERS[0].register(cx.waker());
516 } 600 let regs = T::regs();
517 }), 601 if regs
518 ) 602 .events_ep0datadone
519 .await; 603 .read()
520 604 .events_ep0datadone()
521 if res.is_err() { 605 .bit_is_set()
522 // todo wrong error 606 {
523 return Err(driver::WriteError::BufferOverflow); 607 Poll::Ready(())
608 } else {
609 Poll::Pending
524 } 610 }
611 })
612 .await;
613
614 unsafe { read_dma::<T>(0, buf) }
615 }
616 }
617
618 fn accept(&mut self) {
619 let regs = T::regs();
620 regs.tasks_ep0status
621 .write(|w| w.tasks_ep0status().bit(true));
622 self.request = None;
623 }
624
625 fn accept_in<'a>(&'a mut self, buf: &'a [u8]) -> Self::AcceptInFuture<'a> {
626 async move {
627 info!("control accept {=[u8]:x}", buf);
628 let req = self.request.unwrap();
629 assert_eq!(req.direction, UsbDirection::In);
630
631 let req_len = usize::from(req.length);
632 let len = buf.len().min(req_len);
633 let need_zlp = len != req_len && (len % usize::from(self.max_packet_size)) == 0;
634 let mut chunks = buf[0..len]
635 .chunks(usize::from(self.max_packet_size))
636 .chain(need_zlp.then(|| -> &[u8] { &[] }));
637 while let Some(chunk) = chunks.next() {
638 self.write(chunk, chunks.size_hint().0 == 0).await;
525 } 639 }
526 640
527 Ok(()) 641 self.request = None;
528 } 642 }
529 } 643 }
644
645 fn reject(&mut self) {
646 let regs = T::regs();
647 regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true));
648 self.request = None;
649 }
530} 650}
531 651
532fn dma_start() { 652fn dma_start() {