diff options
| author | alexmoon <[email protected]> | 2022-03-25 16:46:14 -0400 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-04-06 05:38:11 +0200 |
| commit | bdc6e0481c42d20d5cca19dfc8ec56306e47296e (patch) | |
| tree | 6beb805dd6ffea30877b654aa42e5c83f5a36c0b /embassy-nrf/src | |
| parent | 5c0db627feae071182dd9978ffb56b0524558d93 (diff) | |
Add support for USB classes handling control requests.
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/usb.rs | 424 |
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}; | |||
| 9 | use embassy::util::Unborrow; | 9 | use embassy::util::Unborrow; |
| 10 | use embassy::waitqueue::AtomicWaker; | 10 | use embassy::waitqueue::AtomicWaker; |
| 11 | use embassy_hal_common::unborrow; | 11 | use embassy_hal_common::unborrow; |
| 12 | use embassy_usb::control::Request; | ||
| 12 | use embassy_usb::driver::{self, Event, ReadError, WriteError}; | 13 | use embassy_usb::driver::{self, Event, ReadError, WriteError}; |
| 13 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; | 14 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; |
| 14 | use futures::future::poll_fn; | 15 | use futures::future::poll_fn; |
| @@ -134,6 +135,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 134 | impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { | 135 | impl<'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 | ||
| 362 | unsafe 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 | ®s.epout0, | ||
| 377 | ®s.epout1, | ||
| 378 | ®s.epout2, | ||
| 379 | ®s.epout3, | ||
| 380 | ®s.epout4, | ||
| 381 | ®s.epout5, | ||
| 382 | ®s.epout6, | ||
| 383 | ®s.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 | |||
| 405 | unsafe 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 | ®s.epin0, | ||
| 418 | ®s.epin1, | ||
| 419 | ®s.epin2, | ||
| 420 | ®s.epin3, | ||
| 421 | ®s.epin4, | ||
| 422 | ®s.epin5, | ||
| 423 | ®s.epin6, | ||
| 424 | ®s.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 | |||
| 347 | impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { | 442 | impl<'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 | ®s.epout0, | 463 | READY_ENDPOINTS.fetch_and(!(1 << (i + 16)), Ordering::AcqRel); |
| 413 | ®s.epout1, | ||
| 414 | ®s.epout2, | ||
| 415 | ®s.epout3, | ||
| 416 | ®s.epout4, | ||
| 417 | ®s.epout5, | ||
| 418 | ®s.epout6, | ||
| 419 | ®s.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); | 498 | pub 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 | 504 | impl<'d, T: Instance> ControlPipe<'d, T> { | |
| 480 | let epin = [ | 505 | async fn write(&mut self, buf: &[u8], last_chunk: bool) { |
| 481 | ®s.epin0, | 506 | let regs = T::regs(); |
| 482 | ®s.epin1, | 507 | regs.events_ep0datadone.reset(); |
| 483 | ®s.epin2, | 508 | unsafe { |
| 484 | ®s.epin3, | 509 | write_dma::<T>(0, buf).unwrap(); |
| 485 | ®s.epin4, | 510 | } |
| 486 | ®s.epin5, | 511 | |
| 487 | ®s.epin6, | 512 | regs.shorts |
| 488 | ®s.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 | |||
| 536 | impl<'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 | ||
| 532 | fn dma_start() { | 652 | fn dma_start() { |
