1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! USB Device (Slave / Peripheral) 模式:DWC2 ForceDevMode 路径下的最小 EP0
//! 状态机 + class 钩子。
//!
//! # 工作模型
//!
//! 本模块**轮询驱动**,没有挂中断。应用流程:
//!
//! 1. 板级 bring-up:`platform::set_dwc2_base_virt()` + 板上 PHY/clock 切到
//! device 模式(VBUS 由 PC 提供,需关板上 VBUS_GPIO)。
//! 2. 调 [`controller::dwc2_device_init`]:复位、Force Device、DCFG=HS、FIFO
//! 划分、EP0 初始化(**保持 `SFTDISCON=1` 不上线**)。
//! 3. 注册一个实现 [`UsbDeviceClass`] 的 class 对象(如 [`class::cdc_acm`])。
//! 4. 调 [`controller::dwc2_device_softconnect`] 上线 D+ 上拉,PC 看到 connect。
//! 5. 主循环里不断调 [`ep0::Ep0Service::service`],它会:
//! - 处理 GINTSTS 的 USBRST / ENUMDONE / SETUP 等事件
//! - 接收 SETUP 包,分发给标准请求 handler 或 [`UsbDeviceClass::class_setup`]
//! - SET_CONFIGURATION 完成后回调 [`UsbDeviceClass::on_configured`]
//! - 然后调用 [`UsbDeviceClass::poll`] 让 class 推动数据 EP
//!
//! # 与 host 模式共存
//!
//! `device-mode` 与 host 路径在源码层共存编译,但**同一时刻只能有一个生效**——
//! 板级 bring-up 决定走哪条。host 端的 [`crate::usb::host`] 与本模块**互不调用**。
//!
//! # SG2002 / CV182x 板级注意事项
//!
//! - PHY ID toggle workaround:vendor host 路径要 device→host;device 路径要 host→device。
//! - VBUS:device 模式下板上的 VBUS_GPIO **必须关掉**,由 PC 通过 USB 线供电;
//! 不然会回灌,PC 拒绝枚举(甚至损坏 USB 端口)。
//! - clock:与 host 模式共用 `clk_axi4_usb / clk_125m_usb / clk_12m_usb`,必须
//! 把 `CLK_BYP_0` bit17/18 清零让其走 fpll,否则 HS chirp 失败。
pub use ;
pub use ;
/// 应用在 [`UsbDeviceClass::on_configured`] 中需要操控的几件事都封装在这。
///
/// 由 [`Ep0Service`] 在每次回调前注入,class 通过 `&Ep0Context` 拿到最新枚举速度,
/// 由此决定 bulk EP MPS(HS=512, FS=64)。
/// EP0 标准请求 + class 请求的统一处理 trait。
///
/// 所有方法都在 main loop 的轮询线程内调用,不要做长阻塞操作;class 只需要把
/// 静态描述符 / 当前应该回的 IN 数据返回即可。