4. Linux USB 子系统架构:核心层、HCD 层、设备驱动层、Gadget 层
Linux USB 子系统采用分层的模块化架构设计,将复杂的 USB 协议栈划分为四个清晰的层级。这种设计使得上层驱动开发者无需关心底层硬件细节,而底层硬件厂商也只需提供标准化的接口即可融入系统。理解这四层架构是编写 USB Host 驱动、处理热插拔与中断传输的基础。
4.1 USB 核心层(USB Core)
USB Core 是 Linux USB 子系统的中枢神经,位于设备驱动层与 HCD 层之间。它负责实现 USB 协议中与硬件无关的公共逻辑,包括设备枚举、配置管理、urb 分配与路由、电源管理以及热插拔事件分发。
| 功能模块 | 描述 | 关键接口/文件 |
|---|---|---|
| 设备枚举 | 检测设备插入/拔出,分配地址,读取描述符 | hub_port_connect_change() |
| urb 管理 | 分配、提交、取消 urb,协调各层数据传输 | usb_submit_urb() |
| 总线驱动 | 管理 USB 总线拓扑,处理 hub 事件 | drivers/usb/core/hub.c |
| 电源管理 | 挂起/恢复、选择性挂起、远程唤醒 | usb_suspend() |
| 设备模型 | 维护 usb_device、usb_interface 等内核对象 | struct usb_device |
usb_control_msg()、usb_bulk_msg() 和 usb_submit_urb()。USB Core 负责将这些请求转化为 HCD 层可识别的 urb。
4.2 HCD 层(Host Controller Driver)
HCD 层是 Linux USB 子系统中最接近硬件的一层,直接与 USB 主机控制器(如 EHCI、xHCI、OHCI、UHCI)的寄存器交互。它负责将 USB Core 下发的 urb 转换为特定控制器硬件能够执行的传输描述符(TD),并处理硬件中断、完成回调。
4.2.1 主流 HCD 驱动类型
| HCD 驱动 | 对应规范 | 速度支持 | 典型硬件 |
|---|---|---|---|
| ehci-hcd | EHCI 1.0 | High-Speed (480 Mbps) | Intel/PCH 南桥 |
| xhci-hcd | xHCI 1.1/1.2 | SuperSpeed (5/10 Gbps) + 向下兼容 | Intel/AMD 原生 USB 3.x |
| ohci-hcd | OHCI 1.0a | Full/Low-Speed (12/1.5 Mbps) | 非 x86 平台、旧芯片组 |
| uhci-hcd | UHCI 1.1 | Full/Low-Speed (12/1.5 Mbps) | Intel 旧款南桥 |
4.2.2 HCD 与 USB Core 的接口
HCD 通过 struct hc_driver 结构体向 USB Core 注册其能力。该结构体定义了所有必须实现的操作函数指针:
// include/linux/usb/hcd.h
struct hc_driver {
const char *description;
const char *product_desc;
size_t hcd_priv_size;
/* 硬件初始化与关闭 */
int (*start) (struct usb_hcd *hcd);
void (*stop) (struct usb_hcd *hcd);
/* urb 提交与取消 */
int (*urb_enqueue)(struct usb_hcd *hcd,
struct urb *urb, gfp_t mem_flags);
int (*urb_dequeue)(struct usb_hcd *hcd,
struct urb *urb, int status);
/* 中断处理 */
irqreturn_t (*irq)(struct usb_hcd *hcd);
/* 端口状态控制 */
int (*hub_status_data)(struct usb_hcd *hcd, char *buf);
int (*hub_control)(struct usb_hcd *hcd,
u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength);
/* ... 更多回调 */
};
urb_enqueue() 回调运行在中断上下文或持有自旋锁的上下文中。因此,在该回调中不能调用可能导致睡眠的函数(如 kmalloc(GFP_KERNEL)、mutex_lock())。所有内存分配必须使用 GFP_ATOMIC 标志。
4.3 设备驱动层(Device Driver Layer)
设备驱动层是 Linux USB 子系统中最接近应用开发者的层级。它负责与具体的 USB 设备功能进行交互,例如键盘、鼠标、存储设备、串口转换器或自定义 HID 设备。设备驱动通过 USB Core 提供的接口与硬件通信,而无需关心底层主机控制器的差异。
4.3.1 设备驱动注册模型
每个 USB 设备驱动都需要定义一个 struct usb_driver 结构体,并调用 usb_register() 向 USB Core 注册。USB Core 在枚举新设备时,会根据设备的 idVendor、idProduct、bInterfaceClass 等匹配字段,自动调用驱动的 probe() 回调。
// 典型的 USB 设备驱动注册示例
static struct usb_device_id my_device_table[] = {
{ USB_DEVICE(0x1234, 0x5678) }, // VID:PID 匹配
{ USB_DEVICE_INFO(0xFF, 0x00, 0x00) }, // 类匹配
{ } /* 终止项 */
};
MODULE_DEVICE_TABLE(usb, my_device_table);
static int my_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *iface_desc = intf->cur_altsetting;
// 获取端点信息,分配 urb,提交中断传输
return 0;
}
static void my_disconnect(struct usb_interface *intf)
{
// 释放 urb,取消传输,清理资源
}
static struct usb_driver my_driver = {
.name = "my_usb_device",
.id_table = my_device_table,
.probe = my_probe,
.disconnect = my_disconnect,
};
module_usb_driver(my_driver);
4.3.2 设备驱动与中断传输
中断传输(Interrupt Transfer)是 USB 规范中为周期性、低延迟数据交换设计的传输类型,常用于 HID 设备(键盘、鼠标)和部分自定义设备。设备驱动通过 usb_fill_int_urb() 初始化 urb,然后调用 usb_submit_urb() 提交给 USB Core。
| 参数 | 含义 | 典型值 |
|---|---|---|
pipe | 端点管道,由 usb_rcvintpipe() 或 usb_sndintpipe() 构造 | 方向 + 端点号 |
transfer_buffer | 数据缓冲区指针 | kmalloc 分配 |
transfer_buffer_length | 缓冲区大小 | 端点 wMaxPacketSize |
interval | 轮询间隔(单位:帧/微帧) | 1~255(全速:1ms,高速:125μs) |
complete | 传输完成回调函数 | 自定义回调 |
probe() 回调是热插拔检测的终点。当 USB Core 完成设备枚举并找到匹配驱动后,probe() 被调用。驱动在此函数中提交中断 urb,从而开始接收设备上报的数据。当设备拔出时,disconnect() 被调用,驱动必须取消所有未完成的 urb 并释放资源。
4.4 Gadget 层(仅 Device 模式)
Gadget 层是 Linux USB 子系统中用于 Device(设备)模式的部分,与 Host 侧的 HCD 层对称。它允许嵌入式 Linux 设备模拟成 USB 外设(如虚拟串口、U 盘、以太网卡)。虽然本课程聚焦 Host 驱动,但理解 Gadget 层有助于完整把握 USB 子系统的对称设计。
| 对比维度 | Host 侧(HCD + Core) | Device 侧(Gadget) |
|---|---|---|
| 角色 | 总线主控,发起传输 | 外设,响应传输 |
| 核心结构 | struct usb_hcd | struct usb_gadget |
| 驱动注册 | usb_hcd_register() | usb_gadget_probe_driver() |
| 传输接口 | urb | usb_request |
| 典型应用 | PC、嵌入式 Host | 手机、嵌入式 Device |
4.5 层级协作:热插拔事件流
当 USB 设备插入 Host 时,四个层级按以下顺序协作完成热插拔检测与驱动绑定:
- HCD 层:检测到端口状态变化(Port Status Change),触发硬件中断。
- USB Core:Hub 驱动轮询端口状态,调用
hub_port_connect_change(),启动设备枚举流程。 - USB Core:读取设备描述符、配置描述符,分配
struct usb_device,创建usb_interface对象。 - USB Core:遍历已注册的
usb_driver,匹配id_table,调用匹配驱动的probe()回调。 - 设备驱动层:在
probe()中初始化设备,提交中断 urb,开始正常数据传输。
lsusb -t 查看 USB 设备树,usbmon 捕获 USB 总线事务,cat /sys/kernel/debug/usb/devices 查看设备描述符详情。这些工具可以帮助你验证四层架构是否正常工作。