2. Linux USB 子系统架构:核心层、主机控制器驱动与设备驱动框架
Linux USB 子系统采用分层的模块化设计,从上到下依次为 设备驱动框架、USB 核心层 (USB Core) 和 主机控制器驱动 (HCD)。这种架构将协议细节、硬件操作与设备逻辑解耦,使得开发者可以专注于各自层次的实现。
2.1 USB 核心层 (USB Core)
USB Core 是子系统的中枢,位于设备驱动与 HCD 之间。它提供与 USB 协议无关的通用服务,包括设备枚举、管道管理、URB 路由、电源管理和带宽计算。
核心职责:
- 设备枚举:处理 Get_Descriptor、Set_Address、Set_Configuration 等标准请求。
- 管道管理:维护每个端点的管道 (pipe) 对象,负责 URB 的提交与完成回调。
- 带宽分配:为等时传输和中断传输预留总线时间片。
- 电源管理:处理挂起/恢复、远程唤醒和选择性挂起。
- 设备模型集成:将 USB 设备注册到 Linux 设备模型,触发驱动匹配。
USB Core 导出的关键数据结构包括 usb_device、usb_interface 和 urb。其中 usb_device 代表一个物理 USB 设备,usb_interface 代表设备中的一个功能接口,urb 是 USB 请求块,用于在驱动与 HCD 之间传递数据。
| 数据结构 | 作用 | 生命周期 |
|---|---|---|
usb_device |
代表一个 USB 设备,包含设备描述符、配置、端点信息 | 从设备插入到拔出 |
usb_interface |
代表设备中的一个功能接口,驱动绑定对象 | 从配置激活到配置切换 |
urb |
USB 请求块,封装传输方向、数据缓冲区、完成回调 | 从提交到完成/取消 |
2.2 主机控制器驱动 (HCD)
HCD 是 USB 子系统的底层软件模块,直接与硬件寄存器交互。它负责将 USB Core 下发的 URB 转换为硬件可执行的传输描述符 (TD),并处理硬件中断、完成传输、管理根集线器。
Linux 内核支持四种主流 HCD 实现,分别对应不同的 USB 规范:
| HCD 驱动 | 对应规范 | 速度支持 | 典型硬件 |
|---|---|---|---|
uhci-hcd |
USB 1.1 UHCI | 低速/全速 | Intel/VIA 南桥 |
ohci-hcd |
USB 1.1 OHCI | 低速/全速 | 非 Intel 平台 (S3C, OMAP) |
ehci-hcd |
USB 2.0 EHCI | 高速 (480 Mbps) | 大多数 x86/ARM 平台 |
xhci-hcd |
USB 3.0/3.1 xHCI | 超高速 (5/10 Gbps) | 现代 x86/ARM 平台 |
调试提示: 在枚举失败时,首先检查 HCD 是否成功注册。使用 lsusb -t 查看设备树,确认 HCD 驱动已加载。若 HCD 未加载,检查内核配置是否启用了对应的 HCD 驱动 (如 CONFIG_USB_EHCI_HCD)。
2.3 设备驱动框架
设备驱动框架位于 USB Core 之上,为具体的 USB 设备或设备类提供编程接口。驱动开发者通过注册 usb_driver 结构体,实现 probe 和 disconnect 回调,即可完成与 USB Core 的绑定。
设备驱动框架分为两类:
- 通用设备驱动:针对特定 VID/PID 的设备,如 USB 转串口芯片 (FTDI、CP210x)。
- 类驱动 (Class Driver):针对 USB 标准设备类,如 HID (人机交互设备)、Mass Storage (大容量存储)、CDC (通信设备类)。类驱动由内核提供,设备厂商只需遵循类规范即可免驱。
常见误区: 初学者常将 usb_driver 与 usb_class_driver 混淆。usb_driver 用于匹配 USB 接口并创建 usb_interface 实例,而 usb_class_driver 用于在 /dev 下创建设备节点,两者通常配合使用。
一个典型的 USB 设备驱动注册流程如下:
/* 定义 usb_device_id 表 */
static const struct usb_device_id my_table[] = {
{ USB_DEVICE(0x1234, 0x5678) },
{ } /* 终止项 */
};
MODULE_DEVICE_TABLE(usb, my_table);
/* 定义 usb_driver 结构体 */
static struct usb_driver my_driver = {
.name = "my_usb_driver",
.probe = my_probe,
.disconnect = my_disconnect,
.id_table = my_table,
};
/* 模块入口注册 */
module_usb_driver(my_driver);
当 USB Core 检测到新设备时,会遍历已注册的 usb_driver 列表,调用 id_table 进行匹配。匹配成功后调用 probe 函数,驱动在此函数中完成初始化、URB 分配和端点配置。
2.4 三层协作:枚举流程中的角色分配
以 USB 设备插入为例,三层架构的协作流程如下:
- HCD 检测到端口状态变化 (DP/DM 电平变化),通知 USB Core。
- USB Core 启动枚举过程:复位设备、分配地址、读取设备描述符、配置描述符。
- USB Core 根据读取的配置信息创建
usb_device和usb_interface实例。 - 设备驱动框架 根据
id_table匹配驱动,调用probe完成初始化。 - 驱动通过 USB Core 提交 URB,USB Core 将 URB 路由到 HCD,最终由硬件执行。
调试切入点: 枚举失败时,通过 dmesg 观察 USB Core 的枚举日志 (如 New USB device found),可以快速定位问题发生在 HCD 层还是驱动匹配层。若没有枚举日志,问题大概率在 HCD 或硬件层。