USB Gadget 关键调用链与函数索引

USB Gadget 关键调用链与函数索引

按当前 RK3588 Linux 6.1 源码整理,行号可能随厂商树变动,以函数名为稳定入口。RK3588 的硬件 UDC 是drivers/usb/dwc3/gadget.c(DWC3 gadget 模式);drivers/usb/gadget/udc/目录下除core.c外的 SoC UDC 驱动均与 RK3588 无关。

1. 分层与文件归属

1
2
3
4
5
6
用户态 ConfigFS (/sys/kernel/config/usb_gadget/)
-> configfs.c 组装 gadget、写 UDC 触发绑定
-> composite.c Chapter 9、config/function 生命周期
-> functions.c Function 注册表(usb_get_function_instance)
-> udc/core.c UDC 类、gadget bus、usb_ep_*/usb_gadget_* API
-> dwc3/gadget.c RK3588 真实 UDC(udc_start/pullup/queue)

2. UDC 上线(boot)

1
2
3
4
5
6
7
8
9
10
11
DTS usbdrd3_0 ("rockchip,rk3588-dwc3","rockchip,rk3399-dwc3")
-> dwc3-of-simple.c 匹配 rk3399-dwc3 fallback
-> of_platform_populate 子节点 "snps,dwc3"
-> dwc3_probe() dwc3/core.c:1976
-> dwc3_core_init_mode() dwc3/core.c:1504
dr_mode=peripheral -> dwc3_gadget_init()
dr_mode=otg -> dwc3_drd_init() 角色切到 DEVICE 后再 gadget_init
-> dwc3_gadget_init() dwc3/gadget.c:4697
-> usb_initialize_gadget() udc/core.c:1355
-> usb_add_gadget() udc/core.c:1378
-> /sys/class/udc/fc000000.usb(取 parent 设备名)

UDC 类初始化:usb_udc_init()udc/core.c,subsys_initcall)创建udc class 和gadget bus。

3. ConfigFS 组装与绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mkdir usb_gadget/g1
mkdir functions/uac2.usb0 -> function_make() configfs.c:623
-> usb_get_function_instance()
mkdir configs/c.1
ln -s functions/... configs/ -> config_usb_cfg_link() configfs.c:448
echo fc000000.usb > UDC -> gadget_dev_desc_UDC_store() configfs.c:293
-> usb_gadget_register_driver_owner() udc/core.c:1666
-> gadget bus match(按 udc_name)
-> gadget_bind_driver() udc/core.c:1578
-> configfs_composite_bind() configfs.c:1319
-> composite_dev_prepare()(分配 ep0 req)
-> 遍历 config 调 usb_add_function() composite.c:314
-> f->bind()(内部 usb_ep_autoconfig 认领端点)
-> usb_gadget_udc_start_locked() -> dwc3_gadget_start() dwc3/gadget.c:3008
-> pullup -> dwc3_gadget_pullup() dwc3/gadget.c:2786

注意:ConfigFS 的usb_composite_driver.bind是空操作,真正绑定逻辑在configfs_composite_bind(作为 gadget_driver.bind,见configfs.c:1718)。启用USB_CONFIGFS_UEVENT时 setup 入口是android_setup()configfs.c:1547),并通过android_usb class 发 CONNECTED/CONFIGURED uevent。

4. 枚举(EP0/Chapter 9)

1
2
3
4
5
6
7
8
Host SETUP -> DWC3 IRQ -> driver->setup
-> composite_setup() composite.c:1745
GET_DESCRIPTOR 填 cdev->req->buf
SET_CONFIGURATION -> set_config() composite.c:915
-> 每个 f->set_alt(f, intf, 0)
SET_INTERFACE -> f->set_alt()
类/厂商请求 -> f->setup()
-> composite_ep0_queue() -> usb_ep_queue(ep0)

状态机:bus reset 时usb_gadget_udc_reset()udc/core.c:1186)置DEFAULT;SET_ADDRESS/SET_CONFIG 在dwc3/ep0.c中推进到ADDRESS/CONFIGURED/sys/class/udc/<name>/state可读当前状态。

5. 数据面

1
2
3
4
5
6
7
8
9
10
11
12
Function set_alt:
config_ep_by_speed() composite.c:292 按速度选描述符
usb_ep_enable()
批量 usb_ep_queue() udc/core.c:288

完成(IRQ):
UDC -> usb_gadget_giveback_request() udc/core.c:989
-> req->complete()(原子上下文,通常立即重新入队)

取消/停流:
usb_ep_dequeue() udc/core.c:326 完成态 -ECONNRESET
usb_ep_disable() udc/core.c:156 未决请求 -ESHUTDOWN

请求分配:usb_ep_alloc_request()u_f.calloc_ep_req()。complete 回调不可睡眠,也不可递归造成入队死锁。

6. 断开与解绑

1
2
3
4
5
6
7
8
9
10
11
12
13
拔线/软断开:
usb_gadget_disconnect() udc/core.c
-> pullup(0)
-> composite_disconnect() composite.c:2204
-> reset_config() -> 每个 f->disable()

echo none > UDC:
unregister_gadget -> gadget_unbind_driver() udc/core.c:1633
-> disconnect -> driver->unbind
-> configfs_composite_unbind() configfs.c:1519
-> purge_configs_funcs()(f->unbind)
-> composite_dev_cleanup()
-> udc_stop

顺序不变量:先 pullup(0)/disable 停流,再 unbind 释放描述符与端点,最后 udc_stop。

7. 关键锁

位置 保护
udc_lock udc/core.c udc_list、driver 绑定
usb_udc.connect_lock udc/core.c started/connected/pullup
cdev->lock(spinlock) composite delayed_status、config 切换
gadget_info.lock/spinlock configfs.c 组装、setup 与 unbind 竞态
UDC 内部 spinlock dwc3 等 端点队列/硬件

8. RK3588 配置速查

三份 Rockchip defconfig 均启用USB_DWC3USB_GADGETUSB_CONFIGFS(+UEVENT)ACM/MASS_STORAGE/F_FS;差异:主配置多F_UVC,cpcem 多F_UAC1/F_UAC2/F_HIDudc/目录 SoC UDC 与USB_DUMMY_HCD均未启用。

DTS 角色:usbdrd_dwc3_0@fc000000默认dr_mode="otg"(gadget 口);usbhost_dwc3_0与 RK3588 完整版的 DRD1 默认 host。OTG 口需 Type-C role-switch 处于 device 角色,/sys/class/udc/下才有可绑定的 UDC。

运维三步:

1
2
3
ls /sys/class/udc/                       # 确认 UDC 名
echo fc000000.usb > $G/UDC # 绑定
cat /sys/class/udc/fc000000.usb/state # 观察枚举状态

文章互动

阅读 --

留言

0 条留言

正在加载留言…