UDC 核心与 Gadget 设备模型

UDC 核心与 Gadget 设备模型

1. 三类对象

对象 提供者 含义
struct usb_gadget UDC 硬件驱动 一个 Device 模式控制器实例,含ep_listep0、速度能力和状态
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
2
3
4
5
usb_add_gadget()                          udc/core.c:1378
-> device_add(&gadget->dev)
-> 分配 struct usb_udc 并加入 udc_list
-> device_add(&udc->dev) -> /sys/class/udc/<name>
-> usb_gadget_set_state(NOT_ATTACHED)

注销入口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
2
3
4
5
6
7
8
usb_gadget_register_driver_owner()        udc/core.c:1666
-> driver_register(&driver->driver) (gadget bus)
-> 匹配空闲 UDC
-> gadget_bind_driver() udc/core.c:1578
-> udc->driver = driver
-> driver->bind(gadget) = composite/configfs bind
-> usb_gadget_udc_start()
-> usb_gadget_connect() (软连接/pullup)

解绑路径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
2
3
4
5
6
7
8
usb_ep_alloc_request()
-> 填 buf/length/complete/zero/short_not_ok
-> usb_ep_queue()
-> UDC 硬件传输 (DWC3 TRB/DMA)
-> 完成中断
-> req->status/actual 更新
-> req->complete(ep, req)
-> 重新 queue 或 usb_ep_free_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_usb3atmel_usbaaspeed-vhubbdcnet2280等)都不服务 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

文章互动

阅读 --

留言

0 条留言

正在加载留言…