RK3588 kernel-6.1 drivers/usb/core 详细分析
1. 范围与源码基准
- 目录:
rk3588/kernel-6.1/drivers/usb/core/ - 产物:与
CONFIG_USB对应的核心模块usbcore(通常模块名为usbcore)。 - Makefile 编译列表(节选):
1 | usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o |
本文按 文件职责、相互关系、典型调用链 说明;更完整的 枚举步骤与 Hub 函数级追踪 可与同目录 rk3588-kernel-6.1-USB总线枚举匹配与数据传输分析.md 对照阅读。
2. 设计目标:usbcore 在内核 USB 主机栈中的位置
usbcore 不是某一种 USB 设备的「功能驱动」,而是 主机侧通用层:
| 层次 | 主要职责 |
|---|---|
接口级驱动(如 usb-storage) |
绑定 usb_interface,完成类协议与上层子系统对接 |
| usbcore(本目录) | 设备模型、URB、同步消息封装、Hub 逻辑、HCD 框架、描述符解析、sysfs/usbfs、电源与异常策略 |
具体 HCD(drivers/usb/host/、dwc3 等) |
寄存器、调度环、DMA、硬件中断 |
分层原则(hcd.c 头部注释概括):错误检查、URB 与设备跟踪、虚拟 Root Hub 的共性逻辑尽量留在 usbcore;只有必须区分硬件的部分才下沉到各 hc_driver。
3. 模块依赖关系(逻辑)
1 | usb_register() / 设备枚举 |
用户态旁路:devio.c 实现 usbfs(历史上 /proc/bus/usb,现为 /dev/bus/usb/BBB/DDD),可在无内核类驱动时直接提交 URB(需权限)。
4. 逐文件说明
4.1 usb.c — 「USB 库」与杂项辅助
文件头明确:不是带回调的驱动,而是一组通用辅助例程。
典型内容包括:
usb_disabled()/nousb:内核命令行或模块参数层面关闭 USB。- 自动挂起默认延时(
CONFIG_PM下usb_autosuspend_delay)。 usb_find_common_endpoints()/_reverse:在给定 altsetting 中查找首个或末个 bulk-in/out、interrupt-in/out,供驱动简化端点发现。- 其它散布的字符串、描述符、电源相关辅助(与
config.c、generic.c协同)。
定位:上层驱动常用的 工具函数集合,减轻重复解析描述符的代码。
4.2 hcd.c — Host Controller Driver 框架与 Root Hub
核心职责:
struct usb_hcd/struct hc_driver生命周期- 典型入口:
usb_add_hcd()/usb_remove_hcd()(HCD 驱动在 probe 中调用)。
- 典型入口:
- 虚拟 Root Hub
- USB2/3/3.1 等 Root Hub 设备描述符静态表;软件模拟 Hub 行为,使上层 hub 驱动 能以统一方式处理根端口与外置 Hub。
- URB 与总线的桥接
- 如
usb_hcd_giveback_urb():HCD 完成传输后将 URB 交回 usbcore(触发完成回调)。 usb_hcd_unmap_urb_for_dma()等与 DMA 映射协作。
- 如
- 端口 resume、RH 状态轮询
- 例如
usb_hcd_poll_rh_status()、usb_hcd_{start,end}_port_resume()。
- 例如
- 总线号管理
usb_bus_idr、全局usb_hcds_loaded位图等。
设计要点:把「所有主机控制器都要做的事」收拢到此文件,减少各 HCD 复制粘贴;硬实时寄存器操作仍在具体 HCD。
4.3 hub.c — Hub 驱动与设备枚举主干
体积最大,承担 USB 即插即用 的核心:
- Hub 作为内核里的
usb_driver:匹配 Hub 接口,管理struct usb_hub。 hub_wq工作队列:hub_event()路径处理端口状态变化、供电、速度协商、TT 等,避免在硬中断里做重逻辑。- 枚举关键步骤(与
usb_device生命周期紧密耦合):端口连接/断开、debounce、分配设备号、复位、读描述符、usb_new_device()一带的设备注册等。 - Hub 特性:MTT、TT buffer、电源管理、大量 quirks(特定厂商 Hub 行为)。
- 导出符号:如
usb_hub_claim_port/usb_hub_release_port、usb_root_hub_lost_power等供电源或其它子系统使用。
原理:无论 Root Hub 还是外置 Hub,端口上的设备发现与状态机都收敛到 Hub 子系统,从而 接口驱动不必关心「设备怎样被挂上总线」。
4.4 urb.c — URB 生命周期与提交入口
- 分配/释放:
usb_alloc_urb()/usb_free_urb(),引用计数kref,可选URB_FREE_BUFFER连带释放传输缓冲。 - 初始化:
usb_init_urb()、各类usb_fill_*_urb()(control/bulk/int/isoc)。 - 锚点:
usb_anchor_*,便于驱动批量跟踪或取消一组 URB。 - 核心入口:
usb_submit_urb()—— 校验设备状态、端点类型、wMaxPacketSize、SuperSpeed isoc 突发等,然后转入 HCD 队列;usb_kill_urb()/usb_unlink_urb()用于同步取消或异步unlink。
原理:URB 是主机侧异步 I/O 原语;usbcore 在此集中做 一致性校验,减轻各 HCD 重复判断。
4.5 message.c — 同步传输与控制路径
usb_start_wait_urb():提交 URB 后用completion阻塞等待(带超时则usb_kill_urb())。usb_control_msg()及一组usb_control_msg_*:封装 SETUP + DATA + STATUS 流程。- 批量/中断等同步读写:基于上述等待模型封装。
- 配置相关:内部
cancel_async_set_config等与usb_set_configuration异步路径协作。 - 字符串描述符:
usb_string()等(依赖 NLS)。
注意:注释强调 usb_control_msg() 不可中断、不适合中断上下文;中断上下文应 usb_submit_urb()。
4.6 driver.c — USB 设备模型与驱动绑定
usb_register()/usb_deregister()(接口驱动)、usb_register_device_driver()等。usb_device_id匹配:静态表 + 动态new_idsysfs(usb_store_new_id())。probe/disconnect/suspend/resume与内核device_driver绑定的封装。- USB device driver(针对 whole device) 与 interface driver 的分支逻辑。
- 与
generic.c、授权(authorize)、forced unbind 等协作(部分符号在usb.h声明)。
原理:USB 设备常含 多接口,默认绝大多数驱动绑定 interface;少数场景使用 device driver。
4.7 config.c — 配置/接口/端点描述符解析
- 从
GET_DESCRIPTOR得到的原始缓冲区walk:解析 configuration → interface → endpoint,处理 IAD、SuperSpeed Endpoint Companion、SSP isoc companion 等扩展描述符。 find_next_descriptor()等跳过未知描述符,保证前向兼容。usb_parse_configuration()、usb_get_configuration()(与 message.c 协作获取完整描述符树)。- 限制:
USB_MAXALTSETTING、USB_MAXCONFIG等硬上限,防止畸形描述符耗尽内核内存。
定位:把 Chapter 9 二进制描述符变成 usb_host_config / usb_host_interface / usb_host_endpoint 等内核结构。
4.8 buffer.c — HCD 级 DMA 一致缓冲
hcd_buffer_create()/destroy():按档位创建dma_pool(默认最大长度档位见pool_max[]),供该总线上驱动共享;初始化阶段usb_init_pool_max()对照ARCH_KMALLOC_MINALIGN。hcd_buffer_alloc()/free():- 若有
localmem_pool(局部内存池),走gen_pool_dma_*; - 若控制器
!hcd_uses_dma,退化为kmalloc/kfree,dma填哨兵值; - 否则优先命中 pool,否则
dma_alloc_coherent。
- 若有
hcd_buffer_alloc_pages()/free_pages():页级大块路径。
原理:小额 DMA 分配高频,用 per-HCD pool 降低 dma_alloc_coherent 碎片与开销;PIO 主机不走 DMA。
4.9 endpoint.c — 端点 sysfs
- 为每个
usb_host_endpoint创建ep_device子设备,导出 地址、类型、方向、wMaxPacketSize、解码后的 interval 等 只读属性。
便于调试与调试策略脚本,不参与传输调度。
4.10 sysfs.c — 设备与接口 sysfs
- usb 设备节点:厂商、产品、序列号、bConfigurationValue 读写(切换配置)、authorized、速度、
quirks、OTG 相关等。 - 接口节点:modalias、driver 绑定链接等。
与 driver.c 的配置切换、quirks.c 标志联动密切。
4.11 devices.c — debugfs /sys/kernel/debug/usb/devices 拓扑文本
- 将 总线—拓扑—带宽—描述符—接口—端点—驱动名 格式化为 人类可读文本(类 UNIX usbfs devices 的现代等价物)。
- poll 支持唤醒监听进程。
适用于 lsusb -v 之外的内核视角快照。
4.12 devio.c — usbfs(/dev/bus/usb/*/*)
struct usb_dev_state:每个打开的文件描述符对应的状态;维护异步 URB 链表、内存映射列表、mmap DMA 等。- ioctl:提交 URB、** reap **、批量释放、disconnect notify 信号、
CAPTURE权限退化等。 USB_SG_SIZE等对大包拆分逻辑。
安全模型:直接对外开放 USB 需要 capability;历史上多起 CVE 与此路径有关,内核在此有大量锁与校验。
4.13 file.c — USB 主设备号与 USB minor 转发
- 注册 USB 主字符设备:open 时根据 minor 查找
usb_minors[]中注册的file_operations(通常由 usb-serial、audio 等 usb_class_driver 注册)。 usb_register_dev()/usb_deregister_dev()的配合实现。
定位:USB 字符设备类驱动 共用的 动态 minor 调度,不是 usbfs。
4.14 generic.c — USB 设备级通用驱动
usb_choose_configuration():无专用 whole-device 驱动时,按供电、接口类(RNDIS、ActiveSync、音频 UAC3 等)启发式挑选配置。usb_generic_driver_*:probe/disconnect/suspend/resume 钩子,让 未绑定专用 device driver 的设备仍能 选配置、绑定接口驱动。
这是 「先看接口驱动,设备侧兜底」 的关键。
4.15 quirks.c — VID/PID 与工作区标志
- 静态表 + 模块参数
quirks动态追加USB_QUIRK_*。 usb_detect_quirks()/usb_detect_interface_quirks():枚举后打上udev->quirks,影响message.c(如延迟控制传输)、hub、HCD 路径。usb_endpoint_is_ignored():极端畸形设备上忽略某端点。
原理:USB 生态有大量固件瑕疵,quirks 是在标准之上的必要补丁层。
4.16 notify.c — USB 通知链
usb_register_notify()/unregister:blocking notifier,事件如USB_DEVICE_ADD/USB_DEVICE_REMOVE/USB_BUS_ADD/USB_BUS_REMOVE。- 典型订阅者:电源管理、桌面会话、调试工具。
4.17 phy.c / phy.h — Root Hub 多 PHY 封装
usb_phy_roothub_alloc():从 DTphys列表devm_of_phy_get_by_index,聚合多条 PHY。usb_phy_roothub_{init,exit,pwr_on,pwr_off,set_mode}:统一遍历调用phy_*,保证 USB2 + USB3 PHY 等同生命周期。
HCD/platform 驱动在 probe 时按需取用,避免散落重复代码。
4.18 port.c — usb_port 设备与端口 sysfs
- Hub 下每个 物理端口 对应
struct usb_port设备(可与 peer、USB4 等概念交互)。 disable、链路伙伴、component master 等与电源、Type‑C 协作的属性(依配置)。
将 端口级策略 从 hub 内部静态结构 抽到 device model,便于 sysfs/udev。
4.19 of.c — 设备树辅助(CONFIG_OF)
usb_of_get_device_node():按 hub 子节点reg == port查找挂接在该端口上的 device node。usb_of_has_combined_node():判断是否 device/interface 共用 DT 节点(单配置单接口等条件)。usb_of_get_interface_node():接口级节点查找。
用于 固件描述固定插入设备(无枚举或枚举后匹配)。
4.20 hcd-pci.c — PCI USB 主机配角协同(CONFIG_USB_PCI)
- Companion controller(同一 PCI slot 上 EHCI + UHCI/OHCI)之间的 handoff:防止 EHCI probe 时抢夺端口导致 companion 状态不一致。
pci_get_drvdata遍历for_each_companion等逻辑。
嵌入式 RK3588 若无非 PCIe USB,此文件可能不参与链接,但属于 usbcore 对 PC 架构历史兼容 的重要部分。
4.21 usb-acpi.c — ACPI glue(CONFIG_ACPI)
usb_acpi_power_manageable():端口是否有 ACPI 电源资源。usb_acpi_port_lpm_incapable():通过 _DSM 判定 USB3 U1/U2 是否应禁用(retimer 等场景)。- 其它 Hub 端口 ACPI handle、功耗辅助。
4.22 usb.h — core 内部 API 头
对本目录各 .c 声明:
- sysfs 创建/删除、端点 enable/disable、
usb_set_configuration、generic driver、hub_wq kick、PM 路径、usb_device_match_id等。 usb_get_max_power():按速度区分 2mA / 8mA 单位。
不对外导出给用户驱动,仅为 drivers/usb/core 内部解耦编译单元。
4.23 hub.h
Hub 驱动与其它 .c(如 port.c、usb-acpi.c)共享的结构体与内联;外部模块一般不直接 include。
4.24 ledtrig-usbport.c(CONFIG_USB_LEDS_TRIGGER_USBPORT)
将 USB 端口活动 映射到 LED trigger,独立目标文件,非 usbcore 本体。
4.25 otg_productlist.h
Hub 等使用的 OTG/HNP 相关产品列表数据(宏展开),供 hub.c include。
5. 关键调用链速查
5.1 异步传输(驱动常见路径)
1 | usb_submit_urb() |
5.2 枚举(简化)
1 | hub_irq → kick hub_wq → hub_event → hub_port_connect_change |
5.3 同步控制传输
1 | usb_control_msg() → usb_internal_control_msg() → usb_start_wait_urb() |
6. 阅读源码的建议顺序
hcd.c头部注释 +usb_add_hcd/giveback_urburb.c:usb_submit_urb校验逻辑driver.c:注册与 matchhub.c:hub_event、hub_port_connect(可配合上文枚举文档)config.c:描述符解析message.c、buffer.c:同步 IO 与 DMA 缓冲策略devio.c(若关心 usbfs 与安全模型)
7. 与仓库内其它文档的关系
| 文档 | 侧重点 |
|---|---|
rk3588-kernel-6.1-drivers-usb目录结构与分层原理.md |
整个 drivers/usb 子目录地图 |
rk3588-kernel-6.1-USB总线枚举匹配与数据传输分析.md |
枚举、匹配、URB、RK3588 DWC3/xHCI 衔接 |
| 本文 | drivers/usb/core 每个编译单元职责与设计取舍 |
基于 rk3588/kernel-6.1/drivers/usb/core 源码阅读整理;内核版本以树内 Makefile / 符号为准。
正在加载留言…