UDC 核心与 Gadget 设备模型
1. 三类对象
| 对象 | 提供者 | 含义 |
|---|---|---|
struct usb_gadget |
UDC 硬件驱动 | 一个 Device 模式控制器实例,含ep_list、ep0、速度能力和状态 |
struct usb_gadget_driver |
libcomposite/legacy | 上层协议驱动:bind/unbind/setup/disconnect等回调 |
struct usb_udc |
udc/core.c |
把 gadget 发布到/sys/class/udc并与 gadget driver 配对 |
usb_ep表示一个端点,usb_request表示一次异步传输。Gadget API 与 Host 侧 URB 模型对称但方向相反:数据方向以 Host 为参照(IN=设备到主机)。
2. UDC 注册
UDC 硬件驱动(如 DWC3)初始化完成后调用:
1 | usb_add_gadget() udc/core.c:1378 |
注销入口usb_del_gadget()位于udc/core.c:1521。/sys/class/udc/下的名字就是 ConfigFS UDC属性要写入的字符串(RK3588 上通常是fc000000.usb)。
3. Gadget driver 绑定
Linux 6.1 中 gadget driver 已走标准 driver core 匹配:
1 | usb_gadget_register_driver_owner() udc/core.c:1666 |
解绑路径gadget_unbind_driver()位于 1633 行:先usb_gadget_disconnect(),再调用 driver 的unbind,最后udc_stop。
usb_gadget_connect()(743 行)/usb_gadget_disconnect()(805 行)操作 D+ 上拉,对应 ConfigFS 写 UDC 属性后 Host 才看得到设备;soft_connect sysfs 属性也走这两个函数。
4. 端点 API
Function 驱动通过统一 API 操作端点(均在udc/core.c):
| API | 行号 | 语义 |
|---|---|---|
usb_ep_enable() |
113 | 按当前 descriptor 使能端点 |
usb_ep_disable() |
156 | 停用并取消所有在队请求 |
usb_ep_queue() |
288 | 提交usb_request(异步,完成回调) |
usb_ep_dequeue() |
326 | 取消指定请求 |
约束:
enable/disable不可在中断上下文调用,queue/dequeue可以;disable后所有未完成请求以-ESHUTDOWN完成;- completion 回调内可以再次 queue,但要防递归和释放竞争;
- request 的 buf/dma 生命周期由 function 管理,完成前不得释放。
5. usb_request 生命周期
1 | usb_ep_alloc_request() |
status常见值:0 成功、-ECONNRESET被 dequeue、-ESHUTDOWN端点禁用/断开。OUT 方向actual可能小于length(短包),协议层必须处理。
6. 端点自动分配
Function bind 阶段不硬编码端点号,而是用epautoconf.c:
usb_ep_autoconfig():149 行;usb_ep_autoconfig_ss():63 行(带 SuperSpeed companion);usb_ep_autoconfig_release():187 行;usb_ep_autoconfig_reset():203 行(composite unbind 时复位)。
分配器按 descriptor 的类型/方向/包长在gadget->ep_list中挑选可用硬件端点,并回填bEndpointAddress。同一 gadget 中多个 function 竞争有限端点,是组合过多 function 失败(bind 返回-ENODEV)的常见原因。DWC3 的端点能力(数量、类型)决定可组合的 function 上限。
7. 状态机与 sysfs
usb_gadget_set_state()维护USB_STATE_NOT_ATTACHED/ATTACHED/POWERED/DEFAULT/ADDRESS/CONFIGURED等状态,经/sys/class/udc/<name>/state可见。
其它常用属性:
soft_connect:手动 connect/disconnect;current_speed/maximum_speed;function:当前绑定的 gadget driver 名。
8. VBUS 与电源
UDC 可上报 VBUS session(usb_gadget_vbus_connect/disconnect),composite 在 SET_CONFIGURATION 后按配置的MaxPower调用usb_gadget_vbus_draw()。Rockchip 配置USB_GADGET_VBUS_DRAW=500,即默认最大 500mA。挂起时按规范应降到 suspend 电流,composite_suspend()会处理。
9. 本目录 UDC 驱动与 RK3588
udc/下的具体控制器驱动(renesas_usb3、atmel_usba、aspeed-vhub、bdc、net2280等)都不服务 RK3588。RK3588 的 gadget 数据面由drivers/usb/dwc3/gadget.c实现,它同样通过usb_add_gadget()接入本框架,DTS 中dr_mode = "otg"的 DWC3 实例(usb@fc000000)即默认 OTG/Device 口。
dummy_hcd是唯一平台无关的 UDC:它同时注册模拟 HCD 和 UDC,可在无硬件时本机验证 function/composite 逻辑,适合开发自定义 function(如本树f_bytrans)时做回归。
10. 排障入口
| 现象 | 检查 |
|---|---|
/sys/class/udc/为空 |
DWC3 probe、dr_mode、PHY、extcon/role switch |
写 UDC 属性报-ENODEV |
UDC 名拼写、是否已被其它 gadget 占用 |
bind 失败-ENODEV |
端点数量不足(autoconfig 失败) |
| Host 不识别 | pullup 是否执行、EP0 setup 日志、描述符合法性 |
| 传输卡死 | request 队列、completion status、DWC3 event buffer |
正在加载留言…