1#![cfg_attr(not(test), no_std)]
2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
5
6mod fmt;
8
9use core::cell::UnsafeCell;
10use core::future::poll_fn;
11use core::marker::PhantomData;
12use core::sync::atomic::{AtomicBool, AtomicU16, AtomicU32, Ordering};
13use core::task::Poll;
14
15use embassy_sync::waitqueue::AtomicWaker;
16use embassy_usb_driver::{
17 Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
18 EndpointType, Event, Unsupported,
19};
20
21use crate::fmt::Bytes;
22
23pub mod otg_v1;
24
25use otg_v1::{regs, vals, Otg};
26
27pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(r: Otg, state: &State<MAX_EP_COUNT>, ep_count: usize) {
29 trace!("irq");
30
31 let ints = r.gintsts().read();
32 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
33 r.gintmsk().write(|w| {
35 w.set_iepint(true);
36 w.set_oepint(true);
37 w.set_rxflvlm(true);
38 });
39 state.bus_waker.wake();
40 }
41
42 while r.gintsts().read().rxflvl() {
44 let status = r.grxstsp().read();
45 trace!("=== status {:08x}", status.0);
46 let ep_num = status.epnum() as usize;
47 let len = status.bcnt() as usize;
48
49 assert!(ep_num < ep_count);
50
51 match status.pktstsd() {
52 vals::Pktstsd::SETUP_DATA_RX => {
53 trace!("SETUP_DATA_RX");
54 assert!(len == 8, "invalid SETUP packet length={}", len);
55 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
56
57 if r.dieptsiz(ep_num).read().pktcnt() != 0 {
59 r.grstctl().modify(|w| {
60 w.set_txfnum(ep_num as _);
61 w.set_txfflsh(true);
62 });
63 while r.grstctl().read().txfflsh() {}
64 }
65
66 let data = &state.cp_state.setup_data;
67 data[0].store(r.fifo(0).read().data(), Ordering::Relaxed);
68 data[1].store(r.fifo(0).read().data(), Ordering::Relaxed);
69 }
70 vals::Pktstsd::OUT_DATA_RX => {
71 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
72
73 if state.ep_states[ep_num].out_size.load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
74 let buf =
77 unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) };
78
79 for chunk in buf.chunks_mut(4) {
80 let data = r.fifo(0).read().0;
82 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
83 }
84
85 state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release);
86 state.ep_states[ep_num].out_waker.wake();
87 } else {
88 error!("ep_out buffer overflow index={}", ep_num);
89
90 let len_words = (len + 3) / 4;
92 for _ in 0..len_words {
93 r.fifo(0).read().data();
94 }
95 }
96 }
97 vals::Pktstsd::OUT_DATA_DONE => {
98 trace!("OUT_DATA_DONE ep={}", ep_num);
99 }
100 vals::Pktstsd::SETUP_DATA_DONE => {
101 trace!("SETUP_DATA_DONE ep={}", ep_num);
102 }
103 x => trace!("unknown PKTSTS: {}", x.to_bits()),
104 }
105 }
106
107 if ints.iepint() {
109 let mut ep_mask = r.daint().read().iepint();
110 let mut ep_num = 0;
111
112 while ep_mask != 0 {
114 if ep_mask & 1 != 0 {
115 let ep_ints = r.diepint(ep_num).read();
116
117 r.diepint(ep_num).write_value(ep_ints);
119
120 if ep_ints.txfe() {
122 critical_section::with(|_| {
123 r.diepempmsk().modify(|w| {
124 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
125 });
126 });
127 }
128
129 state.ep_states[ep_num].in_waker.wake();
130 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0);
131 }
132
133 ep_mask >>= 1;
134 ep_num += 1;
135 }
136 }
137
138 if ints.oepint() {
140 trace!("oepint");
141 let mut ep_mask = r.daint().read().oepint();
142 let mut ep_num = 0;
143
144 while ep_mask != 0 {
146 if ep_mask & 1 != 0 {
147 let ep_ints = r.doepint(ep_num).read();
148 r.doepint(ep_num).write_value(ep_ints);
150
151 if ep_ints.stup() {
152 state.cp_state.setup_ready.store(true, Ordering::Release);
153 }
154 state.ep_states[ep_num].out_waker.wake();
155 trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
156 }
157
158 ep_mask >>= 1;
159 ep_num += 1;
160 }
161 }
162}
163
164#[derive(Copy, Clone, Debug, Eq, PartialEq)]
166pub enum PhyType {
167 InternalFullSpeed,
171 InternalHighSpeed,
175 ExternalFullSpeed,
177 ExternalHighSpeed,
179}
180
181impl PhyType {
182 pub fn internal(&self) -> bool {
184 match self {
185 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
186 PhyType::ExternalHighSpeed | PhyType::ExternalFullSpeed => false,
187 }
188 }
189
190 pub fn high_speed(&self) -> bool {
192 match self {
193 PhyType::InternalFullSpeed | PhyType::ExternalFullSpeed => false,
194 PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
195 }
196 }
197
198 fn to_dspd(&self) -> vals::Dspd {
199 match self {
200 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
201 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
202 PhyType::ExternalFullSpeed => vals::Dspd::FULL_SPEED_EXTERNAL,
203 PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
204 }
205 }
206}
207
208const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
210
211struct EpState {
212 in_waker: AtomicWaker,
213 out_waker: AtomicWaker,
214 out_buffer: UnsafeCell<*mut u8>,
217 out_size: AtomicU16,
218}
219
220unsafe impl Send for EpState {}
224unsafe impl Sync for EpState {}
225
226struct ControlPipeSetupState {
227 setup_data: [AtomicU32; 2],
229 setup_ready: AtomicBool,
230}
231
232pub struct State<const EP_COUNT: usize> {
234 cp_state: ControlPipeSetupState,
235 ep_states: [EpState; EP_COUNT],
236 bus_waker: AtomicWaker,
237}
238
239unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
240unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
241
242impl<const EP_COUNT: usize> State<EP_COUNT> {
243 pub const fn new() -> Self {
245 Self {
246 cp_state: ControlPipeSetupState {
247 setup_data: [const { AtomicU32::new(0) }; 2],
248 setup_ready: AtomicBool::new(false),
249 },
250 ep_states: [const {
251 EpState {
252 in_waker: AtomicWaker::new(),
253 out_waker: AtomicWaker::new(),
254 out_buffer: UnsafeCell::new(0 as _),
255 out_size: AtomicU16::new(EP_OUT_BUFFER_EMPTY),
256 }
257 }; EP_COUNT],
258 bus_waker: AtomicWaker::new(),
259 }
260 }
261}
262
263#[derive(Debug, Clone, Copy)]
264struct EndpointData {
265 ep_type: EndpointType,
266 max_packet_size: u16,
267 fifo_size_words: u16,
268}
269
270#[non_exhaustive]
272#[derive(Clone, Copy, PartialEq, Eq, Debug)]
273pub struct Config {
274 pub vbus_detection: bool,
289
290 pub xcvrdly: bool,
297}
298
299impl Default for Config {
300 fn default() -> Self {
301 Self {
302 vbus_detection: false,
303 xcvrdly: false,
304 }
305 }
306}
307
308pub struct Driver<'d, const MAX_EP_COUNT: usize> {
310 config: Config,
311 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
312 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
313 ep_out_buffer: &'d mut [u8],
314 ep_out_buffer_offset: usize,
315 instance: OtgInstance<'d, MAX_EP_COUNT>,
316}
317
318impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
319 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d, MAX_EP_COUNT>, config: Config) -> Self {
329 Self {
330 config,
331 ep_in: [None; MAX_EP_COUNT],
332 ep_out: [None; MAX_EP_COUNT],
333 ep_out_buffer,
334 ep_out_buffer_offset: 0,
335 instance,
336 }
337 }
338
339 fn allocated_fifo_words(&self) -> u16 {
341 self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
342 }
343
344 fn alloc_endpoint<D: Dir>(
346 &mut self,
347 ep_type: EndpointType,
348 ep_addr: Option<EndpointAddress>,
349 max_packet_size: u16,
350 interval_ms: u8,
351 ) -> Result<Endpoint<'d, D>, EndpointAllocError> {
352 trace!(
353 "allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
354 ep_type,
355 max_packet_size,
356 interval_ms,
357 D::dir()
358 );
359
360 if D::dir() == Direction::Out {
361 if self.ep_out_buffer_offset + max_packet_size as usize > self.ep_out_buffer.len() {
362 error!("Not enough endpoint out buffer capacity");
363 return Err(EndpointAllocError);
364 }
365 };
366
367 let fifo_size_words = match D::dir() {
368 Direction::Out => (max_packet_size + 3) / 4,
369 Direction::In => u16::max((max_packet_size + 3) / 4, 16),
371 };
372
373 if fifo_size_words + self.allocated_fifo_words() > self.instance.fifo_depth_words {
374 error!("Not enough FIFO capacity");
375 return Err(EndpointAllocError);
376 }
377
378 let eps = match D::dir() {
379 Direction::Out => &mut self.ep_out[..self.instance.endpoint_count],
380 Direction::In => &mut self.ep_in[..self.instance.endpoint_count],
381 };
382
383 let slot = if let Some(addr) = ep_addr {
385 let requested_index = addr.index();
387 if requested_index >= self.instance.endpoint_count {
388 return Err(EndpointAllocError);
389 }
390 if requested_index == 0 && ep_type != EndpointType::Control {
391 return Err(EndpointAllocError); }
393 if eps[requested_index].is_some() {
394 return Err(EndpointAllocError); }
396 Some((requested_index, &mut eps[requested_index]))
397 } else {
398 eps.iter_mut().enumerate().find(|(i, ep)| {
400 if *i == 0 && ep_type != EndpointType::Control {
401 false
403 } else {
404 ep.is_none()
405 }
406 })
407 };
408
409 let index = match slot {
410 Some((index, ep)) => {
411 *ep = Some(EndpointData {
412 ep_type,
413 max_packet_size,
414 fifo_size_words,
415 });
416 index
417 }
418 None => {
419 error!("No free endpoints available");
420 return Err(EndpointAllocError);
421 }
422 };
423
424 trace!(" index={}", index);
425
426 let state = &self.instance.state.ep_states[index];
427 if D::dir() == Direction::Out {
428 unsafe {
430 *state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
431 }
432 self.ep_out_buffer_offset += max_packet_size as usize;
433 }
434
435 Ok(Endpoint {
436 _phantom: PhantomData,
437 regs: self.instance.regs,
438 state,
439 info: EndpointInfo {
440 addr: EndpointAddress::from_parts(index, D::dir()),
441 ep_type,
442 max_packet_size,
443 interval_ms,
444 },
445 })
446 }
447}
448
449impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d, MAX_EP_COUNT> {
450 type EndpointOut = Endpoint<'d, Out>;
451 type EndpointIn = Endpoint<'d, In>;
452 type ControlPipe = ControlPipe<'d>;
453 type Bus = Bus<'d, MAX_EP_COUNT>;
454
455 fn alloc_endpoint_in(
456 &mut self,
457 ep_type: EndpointType,
458 ep_addr: Option<EndpointAddress>,
459 max_packet_size: u16,
460 interval_ms: u8,
461 ) -> Result<Self::EndpointIn, EndpointAllocError> {
462 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
463 }
464
465 fn alloc_endpoint_out(
466 &mut self,
467 ep_type: EndpointType,
468 ep_addr: Option<EndpointAddress>,
469 max_packet_size: u16,
470 interval_ms: u8,
471 ) -> Result<Self::EndpointOut, EndpointAllocError> {
472 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
473 }
474
475 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
476 let ep_out = self
477 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
478 .unwrap();
479 let ep_in = self
480 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
481 .unwrap();
482 assert_eq!(ep_out.info.addr.index(), 0);
483 assert_eq!(ep_in.info.addr.index(), 0);
484
485 trace!("start");
486
487 let regs = self.instance.regs;
488 let cp_setup_state = &self.instance.state.cp_state;
489 (
490 Bus {
491 config: self.config,
492 ep_in: self.ep_in,
493 ep_out: self.ep_out,
494 inited: false,
495 instance: self.instance,
496 },
497 ControlPipe {
498 max_packet_size: control_max_packet_size,
499 setup_state: cp_setup_state,
500 ep_out,
501 ep_in,
502 regs,
503 },
504 )
505 }
506}
507
508pub struct Bus<'d, const MAX_EP_COUNT: usize> {
510 config: Config,
511 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
512 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
513 instance: OtgInstance<'d, MAX_EP_COUNT>,
514 inited: bool,
515}
516
517impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
518 fn restore_irqs(&mut self) {
519 self.instance.regs.gintmsk().write(|w| {
520 w.set_usbrst(true);
521 w.set_enumdnem(true);
522 w.set_usbsuspm(true);
523 w.set_wuim(true);
524 w.set_iepint(true);
525 w.set_oepint(true);
526 w.set_rxflvlm(true);
527 w.set_srqim(true);
528 w.set_otgint(true);
529 });
530 }
531
532 pub fn phy_type(&self) -> PhyType {
534 self.instance.phy_type
535 }
536
537 pub fn configure_as_device(&mut self) {
539 let r = self.instance.regs;
540 let phy_type = self.instance.phy_type;
541 r.gusbcfg().write(|w| {
542 w.set_fdmod(true);
544 w.set_physel(phy_type.internal() && !phy_type.high_speed());
546 });
547 }
548
549 pub fn config_v1(&mut self) {
552 let r = self.instance.regs;
553 let phy_type = self.instance.phy_type;
554 assert!(phy_type != PhyType::InternalHighSpeed);
555
556 r.gccfg_v1().modify(|w| {
557 w.set_pwrdwn(phy_type.internal());
559 });
560
561 r.gccfg_v1().modify(|w| {
563 w.set_novbussens(!self.config.vbus_detection);
564 w.set_vbusasen(false);
565 w.set_vbusbsen(self.config.vbus_detection);
566 w.set_sofouten(false);
567 });
568 }
569
570 pub fn config_v2v3(&mut self) {
573 let r = self.instance.regs;
574 let phy_type = self.instance.phy_type;
575
576 r.gccfg_v2().modify(|w| {
578 w.set_pwrdwn(phy_type.internal() && !phy_type.high_speed());
580 w.set_phyhsen(phy_type.internal() && phy_type.high_speed());
581 });
582
583 r.gccfg_v2().modify(|w| {
584 w.set_vbden(self.config.vbus_detection);
585 });
586
587 r.gotgctl().modify(|w| {
589 w.set_bvaloen(!self.config.vbus_detection);
590 w.set_bvaloval(true);
591 });
592 }
593
594 pub fn config_v5(&mut self) {
597 let r = self.instance.regs;
598 let phy_type = self.instance.phy_type;
599
600 if phy_type == PhyType::InternalHighSpeed {
601 r.gccfg_v3().modify(|w| {
602 w.set_vbvaloven(!self.config.vbus_detection);
603 w.set_vbvaloval(!self.config.vbus_detection);
604 w.set_vbden(self.config.vbus_detection);
605 });
606 } else {
607 r.gotgctl().modify(|w| {
608 w.set_bvaloen(!self.config.vbus_detection);
609 w.set_bvaloval(!self.config.vbus_detection);
610 });
611 r.gccfg_v3().modify(|w| {
612 w.set_vbden(self.config.vbus_detection);
613 });
614 }
615 }
616
617 fn init(&mut self) {
618 let r = self.instance.regs;
619 let phy_type = self.instance.phy_type;
620
621 r.dctl().write(|w| w.set_sdis(true));
623
624 r.dcfg().write(|w| {
626 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
627 w.set_dspd(phy_type.to_dspd());
628 if self.config.xcvrdly {
629 w.set_xcvrdly(true);
630 }
631 });
632
633 r.diepmsk().write(|w| {
635 w.set_xfrcm(true);
636 });
637
638 r.doepmsk().write(|w| {
640 w.set_stupm(true);
641 });
642
643 self.restore_irqs();
645 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
646
647 r.gahbcfg().write(|w| {
649 w.set_gint(true); });
651
652 r.dctl().write(|w| w.set_sdis(false));
654 }
655
656 fn init_fifo(&mut self) {
657 trace!("init_fifo");
658
659 let regs = self.instance.regs;
660 critical_section::with(|_| {
664 let rx_fifo_size_words = self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out);
666 trace!("configuring rx fifo size={}", rx_fifo_size_words);
667
668 regs.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
669
670 let mut fifo_top = rx_fifo_size_words;
672 for i in 0..self.instance.endpoint_count {
673 if let Some(ep) = self.ep_in[i] {
674 trace!(
675 "configuring tx fifo ep={}, offset={}, size={}",
676 i,
677 fifo_top,
678 ep.fifo_size_words
679 );
680
681 let dieptxf = if i == 0 { regs.dieptxf0() } else { regs.dieptxf(i - 1) };
682
683 dieptxf.write(|w| {
684 w.set_fd(ep.fifo_size_words);
685 w.set_sa(fifo_top);
686 });
687
688 fifo_top += ep.fifo_size_words;
689 }
690 }
691
692 assert!(
693 fifo_top <= self.instance.fifo_depth_words,
694 "FIFO allocations exceeded maximum capacity"
695 );
696
697 regs.grstctl().write(|w| {
699 w.set_rxfflsh(true);
700 w.set_txfflsh(true);
701 w.set_txfnum(0x10);
702 });
703 });
704
705 loop {
706 let x = regs.grstctl().read();
707 if !x.rxfflsh() && !x.txfflsh() {
708 break;
709 }
710 }
711 }
712
713 fn configure_endpoints(&mut self) {
714 trace!("configure_endpoints");
715
716 let regs = self.instance.regs;
717
718 for (index, ep) in self.ep_in.iter().enumerate() {
720 if let Some(ep) = ep {
721 critical_section::with(|_| {
722 regs.diepctl(index).write(|w| {
723 if index == 0 {
724 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
725 } else {
726 w.set_mpsiz(ep.max_packet_size);
727 w.set_eptyp(to_eptyp(ep.ep_type));
728 w.set_sd0pid_sevnfrm(true);
729 w.set_txfnum(index as _);
730 w.set_snak(true);
731 }
732 });
733 });
734 }
735 }
736
737 for (index, ep) in self.ep_out.iter().enumerate() {
739 if let Some(ep) = ep {
740 critical_section::with(|_| {
741 regs.doepctl(index).write(|w| {
742 if index == 0 {
743 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
744 } else {
745 w.set_mpsiz(ep.max_packet_size);
746 w.set_eptyp(to_eptyp(ep.ep_type));
747 w.set_sd0pid_sevnfrm(true);
748 }
749 });
750
751 regs.doeptsiz(index).modify(|w| {
752 w.set_xfrsiz(ep.max_packet_size as _);
753 if index == 0 {
754 w.set_rxdpid_stupcnt(3);
755 } else {
756 w.set_pktcnt(1);
757 }
758 });
759 });
760 }
761 }
762
763 regs.daintmsk().modify(|w| {
765 w.set_iepm(ep_irq_mask(&self.ep_in));
766 w.set_oepm(ep_irq_mask(&self.ep_out));
767 });
768 }
769
770 fn disable_all_endpoints(&mut self) {
771 for i in 0..self.instance.endpoint_count {
772 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
773 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
774 }
775 }
776}
777
778impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Bus for Bus<'d, MAX_EP_COUNT> {
779 async fn poll(&mut self) -> Event {
780 poll_fn(move |cx| {
781 if !self.inited {
782 self.init();
783 self.inited = true;
784
785 if !self.config.vbus_detection {
787 return Poll::Ready(Event::PowerDetected);
788 }
789 }
790
791 let regs = self.instance.regs;
792 self.instance.state.bus_waker.register(cx.waker());
793
794 let ints = regs.gintsts().read();
795
796 if ints.srqint() {
797 trace!("vbus detected");
798
799 regs.gintsts().write(|w| w.set_srqint(true)); self.restore_irqs();
801
802 if self.config.vbus_detection {
803 return Poll::Ready(Event::PowerDetected);
804 }
805 }
806
807 if ints.otgint() {
808 let otgints = regs.gotgint().read();
809 regs.gotgint().write_value(otgints); self.restore_irqs();
811
812 if otgints.sedet() {
813 trace!("vbus removed");
814 if self.config.vbus_detection {
815 self.disable_all_endpoints();
816 return Poll::Ready(Event::PowerRemoved);
817 }
818 }
819 }
820
821 if ints.usbrst() {
822 trace!("reset");
823
824 self.init_fifo();
825 self.configure_endpoints();
826
827 critical_section::with(|_| {
829 regs.dcfg().modify(|w| {
830 w.set_dad(0);
831 });
832 });
833
834 regs.gintsts().write(|w| w.set_usbrst(true)); self.restore_irqs();
836 }
837
838 if ints.enumdne() {
839 trace!("enumdne");
840
841 let speed = regs.dsts().read().enumspd();
842 let trdt = (self.instance.calculate_trdt_fn)(speed);
843 trace!(" speed={} trdt={}", speed.to_bits(), trdt);
844 regs.gusbcfg().modify(|w| w.set_trdt(trdt));
845
846 regs.gintsts().write(|w| w.set_enumdne(true)); self.restore_irqs();
848
849 return Poll::Ready(Event::Reset);
850 }
851
852 if ints.usbsusp() {
853 trace!("suspend");
854 regs.gintsts().write(|w| w.set_usbsusp(true)); self.restore_irqs();
856 return Poll::Ready(Event::Suspend);
857 }
858
859 if ints.wkupint() {
860 trace!("resume");
861 regs.gintsts().write(|w| w.set_wkupint(true)); self.restore_irqs();
863 return Poll::Ready(Event::Resume);
864 }
865
866 Poll::Pending
867 })
868 .await
869 }
870
871 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
872 trace!("endpoint_set_stalled ep={:?} en={}", ep_addr, stalled);
873
874 assert!(
875 ep_addr.index() < self.instance.endpoint_count,
876 "endpoint_set_stalled index {} out of range",
877 ep_addr.index()
878 );
879
880 let regs = self.instance.regs;
881 let state = self.instance.state;
882 match ep_addr.direction() {
883 Direction::Out => {
884 critical_section::with(|_| {
885 regs.doepctl(ep_addr.index()).modify(|w| {
886 w.set_stall(stalled);
887 });
888 });
889
890 state.ep_states[ep_addr.index()].out_waker.wake();
891 }
892 Direction::In => {
893 critical_section::with(|_| {
894 regs.diepctl(ep_addr.index()).modify(|w| {
895 w.set_stall(stalled);
896 });
897 });
898
899 state.ep_states[ep_addr.index()].in_waker.wake();
900 }
901 }
902 }
903
904 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
905 assert!(
906 ep_addr.index() < self.instance.endpoint_count,
907 "endpoint_is_stalled index {} out of range",
908 ep_addr.index()
909 );
910
911 let regs = self.instance.regs;
912 match ep_addr.direction() {
913 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
914 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
915 }
916 }
917
918 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
919 trace!("endpoint_set_enabled ep={:?} en={}", ep_addr, enabled);
920
921 assert!(
922 ep_addr.index() < self.instance.endpoint_count,
923 "endpoint_set_enabled index {} out of range",
924 ep_addr.index()
925 );
926
927 let regs = self.instance.regs;
928 let state = self.instance.state;
929 match ep_addr.direction() {
930 Direction::Out => {
931 critical_section::with(|_| {
932 if !enabled && regs.doepctl(ep_addr.index()).read().epena() {
934 regs.doepctl(ep_addr.index()).modify(|w| {
935 w.set_snak(true);
936 w.set_epdis(true);
937 })
938 }
939
940 regs.doepctl(ep_addr.index()).modify(|w| {
941 w.set_usbaep(enabled);
942 });
943
944 regs.grstctl().write(|w| {
946 w.set_txfflsh(true);
947 w.set_txfnum(ep_addr.index() as _);
948 });
949 loop {
950 let x = regs.grstctl().read();
951 if !x.txfflsh() {
952 break;
953 }
954 }
955 });
956
957 state.ep_states[ep_addr.index()].out_waker.wake();
959 }
960 Direction::In => {
961 critical_section::with(|_| {
962 if !enabled && regs.diepctl(ep_addr.index()).read().epena() {
964 regs.diepctl(ep_addr.index()).modify(|w| {
965 w.set_snak(true); w.set_epdis(true);
967 })
968 }
969
970 regs.diepctl(ep_addr.index()).modify(|w| {
971 w.set_usbaep(enabled);
972 w.set_cnak(enabled); })
974 });
975
976 state.ep_states[ep_addr.index()].in_waker.wake();
978 }
979 }
980 }
981
982 async fn enable(&mut self) {
983 trace!("enable");
984 }
986
987 async fn disable(&mut self) {
988 trace!("disable");
989
990 }
993
994 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
995 Err(Unsupported)
996 }
997}
998
999trait Dir {
1001 fn dir() -> Direction;
1003}
1004
1005pub enum In {}
1007impl Dir for In {
1008 fn dir() -> Direction {
1009 Direction::In
1010 }
1011}
1012
1013pub enum Out {}
1015impl Dir for Out {
1016 fn dir() -> Direction {
1017 Direction::Out
1018 }
1019}
1020
1021pub struct Endpoint<'d, D> {
1023 _phantom: PhantomData<D>,
1024 regs: Otg,
1025 info: EndpointInfo,
1026 state: &'d EpState,
1027}
1028
1029impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
1030 fn info(&self) -> &EndpointInfo {
1031 &self.info
1032 }
1033
1034 async fn wait_enabled(&mut self) {
1035 poll_fn(|cx| {
1036 let ep_index = self.info.addr.index();
1037
1038 self.state.in_waker.register(cx.waker());
1039
1040 if self.regs.diepctl(ep_index).read().usbaep() {
1041 Poll::Ready(())
1042 } else {
1043 Poll::Pending
1044 }
1045 })
1046 .await
1047 }
1048}
1049
1050impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> {
1051 fn info(&self) -> &EndpointInfo {
1052 &self.info
1053 }
1054
1055 async fn wait_enabled(&mut self) {
1056 poll_fn(|cx| {
1057 let ep_index = self.info.addr.index();
1058
1059 self.state.out_waker.register(cx.waker());
1060
1061 if self.regs.doepctl(ep_index).read().usbaep() {
1062 Poll::Ready(())
1063 } else {
1064 Poll::Pending
1065 }
1066 })
1067 .await
1068 }
1069}
1070
1071impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1072 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
1073 trace!("read start len={}", buf.len());
1074
1075 poll_fn(|cx| {
1076 let index = self.info.addr.index();
1077 self.state.out_waker.register(cx.waker());
1078
1079 let doepctl = self.regs.doepctl(index).read();
1080 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
1081 if !doepctl.usbaep() {
1082 trace!("read ep={:?} error disabled", self.info.addr);
1083 return Poll::Ready(Err(EndpointError::Disabled));
1084 }
1085
1086 let len = self.state.out_size.load(Ordering::Relaxed);
1087 if len != EP_OUT_BUFFER_EMPTY {
1088 trace!("read ep={:?} done len={}", self.info.addr, len);
1089
1090 if len as usize > buf.len() {
1091 return Poll::Ready(Err(EndpointError::BufferOverflow));
1092 }
1093
1094 let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) };
1096 buf[..len as usize].copy_from_slice(data);
1097
1098 self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1100
1101 critical_section::with(|_| {
1102 self.regs.doeptsiz(index).modify(|w| {
1104 w.set_xfrsiz(self.info.max_packet_size as _);
1105 w.set_pktcnt(1);
1106 });
1107
1108 if self.info.ep_type == EndpointType::Isochronous {
1109 let frame_number = self.regs.dsts().read().fnsof();
1112 let frame_is_odd = frame_number & 0x01 == 1;
1113
1114 self.regs.doepctl(index).modify(|r| {
1115 if frame_is_odd {
1116 r.set_sd0pid_sevnfrm(true);
1117 } else {
1118 r.set_sd1pid_soddfrm(true);
1119 }
1120 });
1121 }
1122
1123 self.regs.doepctl(index).modify(|w| {
1125 w.set_cnak(true);
1126 });
1127 });
1128
1129 Poll::Ready(Ok(len as usize))
1130 } else {
1131 Poll::Pending
1132 }
1133 })
1134 .await
1135 }
1136}
1137
1138impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1139 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
1140 trace!("write ep={:?} data={:?}", self.info.addr, Bytes(buf));
1141
1142 if buf.len() > self.info.max_packet_size as usize {
1143 return Err(EndpointError::BufferOverflow);
1144 }
1145
1146 let index = self.info.addr.index();
1147 poll_fn(|cx| {
1149 self.state.in_waker.register(cx.waker());
1150
1151 let diepctl = self.regs.diepctl(index).read();
1152 let dtxfsts = self.regs.dtxfsts(index).read();
1153 trace!(
1154 "write ep={:?}: diepctl {:08x} ftxfsts {:08x}",
1155 self.info.addr,
1156 diepctl.0,
1157 dtxfsts.0
1158 );
1159 if !diepctl.usbaep() {
1160 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1161 Poll::Ready(Err(EndpointError::Disabled))
1162 } else if !diepctl.epena() {
1163 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1164 Poll::Ready(Ok(()))
1165 } else {
1166 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1167 Poll::Pending
1168 }
1169 })
1170 .await?;
1171
1172 if buf.len() > 0 {
1173 poll_fn(|cx| {
1174 self.state.in_waker.register(cx.waker());
1175
1176 let size_words = (buf.len() + 3) / 4;
1177
1178 let fifo_space = self.regs.dtxfsts(index).read().ineptfsav() as usize;
1179 if size_words > fifo_space {
1180 critical_section::with(|_| {
1182 self.regs.diepempmsk().modify(|w| {
1183 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1184 });
1185 });
1186
1187 trace!("tx fifo for ep={} full, waiting for txfe", index);
1188
1189 Poll::Pending
1190 } else {
1191 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1192 Poll::Ready(())
1193 }
1194 })
1195 .await
1196 }
1197
1198 critical_section::with(|_| {
1203 self.regs.dieptsiz(index).write(|w| {
1205 w.set_mcnt(1);
1206 w.set_pktcnt(1);
1207 w.set_xfrsiz(buf.len() as _);
1208 });
1209
1210 if self.info.ep_type == EndpointType::Isochronous {
1211 let frame_number = self.regs.dsts().read().fnsof();
1214 let frame_is_odd = frame_number & 0x01 == 1;
1215
1216 self.regs.diepctl(index).modify(|r| {
1217 if frame_is_odd {
1218 r.set_sd0pid_sevnfrm(true);
1219 } else {
1220 r.set_sd1pid_soddfrm(true);
1221 }
1222 });
1223 }
1224
1225 self.regs.diepctl(index).modify(|w| {
1227 w.set_cnak(true);
1228 w.set_epena(true);
1229 });
1230
1231 let chunks = buf.chunks_exact(4);
1233 let rem = chunks.remainder();
1235 let last_chunk = (!rem.is_empty()).then(|| {
1236 let mut tmp = [0u8; 4];
1237 tmp[0..rem.len()].copy_from_slice(rem);
1238 u32::from_ne_bytes(tmp)
1239 });
1240
1241 let fifo = self.regs.fifo(index);
1242 for chunk in chunks {
1243 let val = u32::from_ne_bytes(chunk.try_into().unwrap());
1244 fifo.write_value(regs::Fifo(val));
1245 }
1246 if let Some(val) = last_chunk {
1248 fifo.write_value(regs::Fifo(val));
1249 }
1250 });
1251
1252 trace!("write done ep={:?}", self.info.addr);
1253
1254 Ok(())
1255 }
1256}
1257
1258pub struct ControlPipe<'d> {
1260 max_packet_size: u16,
1261 regs: Otg,
1262 setup_state: &'d ControlPipeSetupState,
1263 ep_in: Endpoint<'d, In>,
1264 ep_out: Endpoint<'d, Out>,
1265}
1266
1267impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1268 fn max_packet_size(&self) -> usize {
1269 usize::from(self.max_packet_size)
1270 }
1271
1272 async fn setup(&mut self) -> [u8; 8] {
1273 poll_fn(|cx| {
1274 self.ep_out.state.out_waker.register(cx.waker());
1275
1276 if self.setup_state.setup_ready.load(Ordering::Relaxed) {
1277 let mut data = [0; 8];
1278 data[0..4].copy_from_slice(&self.setup_state.setup_data[0].load(Ordering::Relaxed).to_ne_bytes());
1279 data[4..8].copy_from_slice(&self.setup_state.setup_data[1].load(Ordering::Relaxed).to_ne_bytes());
1280 self.setup_state.setup_ready.store(false, Ordering::Release);
1281
1282 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1284 w.set_rxdpid_stupcnt(3);
1285 });
1286
1287 self.regs
1289 .doepctl(self.ep_out.info.addr.index())
1290 .modify(|w| w.set_cnak(true));
1291
1292 trace!("SETUP received: {:?}", Bytes(&data));
1293 Poll::Ready(data)
1294 } else {
1295 trace!("SETUP waiting");
1296 Poll::Pending
1297 }
1298 })
1299 .await
1300 }
1301
1302 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
1303 trace!("control: data_out");
1304 let len = self.ep_out.read(buf).await?;
1305 trace!("control: data_out read: {:?}", Bytes(&buf[..len]));
1306 Ok(len)
1307 }
1308
1309 async fn data_in(&mut self, data: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
1310 trace!("control: data_in write: {:?}", Bytes(data));
1311 self.ep_in.write(data).await?;
1312
1313 if last {
1315 trace!("control: data_in waiting for status");
1316 self.ep_out.read(&mut []).await?;
1317 trace!("control: complete");
1318 }
1319
1320 Ok(())
1321 }
1322
1323 async fn accept(&mut self) {
1324 trace!("control: accept");
1325
1326 self.ep_in.write(&[]).await.ok();
1327
1328 trace!("control: accept OK");
1329 }
1330
1331 async fn reject(&mut self) {
1332 trace!("control: reject");
1333
1334 self.regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1336 w.set_stall(true);
1337 });
1338 self.regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1339 w.set_stall(true);
1340 });
1341 }
1342
1343 async fn accept_set_address(&mut self, addr: u8) {
1344 trace!("setting addr: {}", addr);
1345 critical_section::with(|_| {
1346 self.regs.dcfg().modify(|w| {
1347 w.set_dad(addr);
1348 });
1349 });
1350
1351 self.accept().await
1353 }
1354}
1355
1356fn to_eptyp(ep_type: EndpointType) -> vals::Eptyp {
1358 match ep_type {
1359 EndpointType::Control => vals::Eptyp::CONTROL,
1360 EndpointType::Isochronous => vals::Eptyp::ISOCHRONOUS,
1361 EndpointType::Bulk => vals::Eptyp::BULK,
1362 EndpointType::Interrupt => vals::Eptyp::INTERRUPT,
1363 }
1364}
1365
1366fn ep_fifo_size(eps: &[Option<EndpointData>]) -> u16 {
1368 eps.iter().map(|ep| ep.map(|ep| ep.fifo_size_words).unwrap_or(0)).sum()
1369}
1370
1371fn ep_irq_mask(eps: &[Option<EndpointData>]) -> u16 {
1373 eps.iter().enumerate().fold(
1374 0,
1375 |mask, (index, ep)| {
1376 if ep.is_some() {
1377 mask | (1 << index)
1378 } else {
1379 mask
1380 }
1381 },
1382 )
1383}
1384
1385fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1387 match max_packet_size {
1388 8 => 0b11,
1389 16 => 0b10,
1390 32 => 0b01,
1391 64 => 0b00,
1392 other => panic!("Unsupported EP0 size: {}", other),
1393 }
1394}
1395
1396pub struct OtgInstance<'d, const MAX_EP_COUNT: usize> {
1398 pub regs: Otg,
1400 pub state: &'d State<MAX_EP_COUNT>,
1402 pub fifo_depth_words: u16,
1404 pub endpoint_count: usize,
1406 pub phy_type: PhyType,
1408 pub extra_rx_fifo_words: u16,
1410 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8,
1412}