4. Linux USB核心架构:USB核心层(usbcore)、主机控制器驱动层(HCD)、设备驱动层(usb_driver)
Linux USB子系统采用经典的分层架构设计,从上到下依次为:设备驱动层、USB核心层(usbcore)和主机控制器驱动层(HCD)。这种分层结构实现了硬件无关性与驱动可复用性,是理解USB驱动开发的基础。
核心认知:USB核心层是上下两层之间的“交通枢纽”,它向上为设备驱动提供统一的接口,向下通过HCD抽象不同主机控制器的硬件差异。设备驱动无需关心底层是OHCI、UHCI还是EHCI。
4.1 三层架构总览
下图展示了Linux USB子系统的完整分层结构及各层之间的交互关系:
4.2 各层职责与核心数据结构
每一层都有明确的职责边界和核心数据结构,理解这些是编写USB驱动的第一步。
| 层次 | 核心职责 | 关键数据结构 | 主要接口/函数 |
|---|---|---|---|
| 设备驱动层 | 实现具体设备功能(鼠标、键盘、存储等) | struct usb_driverstruct usb_class_driver |
probe() / disconnect()usb_register() |
| USB核心层 | 设备枚举、配置管理、URB调度、电源管理 | struct usb_devicestruct usb_interfacestruct urb |
usb_submit_urb()usb_control_msg() |
| 主机控制器驱动层 | 直接操作硬件寄存器、处理中断、DMA传输 | struct hc_driverstruct usb_hcd |
hcd->driver->start()urb_enqueue() |
4.3 设备驱动层(usb_driver)
设备驱动层是开发者最常接触的层次。每个USB设备驱动通过注册一个struct usb_driver实例来声明自己支持的设备。
/* USB驱动结构体核心成员 */
struct usb_driver {
const char *name; /* 驱动名称 */
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id); /* 设备匹配后调用 */
void (*disconnect) (struct usb_interface *intf); /* 设备拔出时调用 */
const struct usb_device_id *id_table; /* 支持的设备ID列表 */
int (*suspend) (struct usb_interface *intf,
pm_message_t message); /* 电源管理 */
int (*resume) (struct usb_interface *intf);
};
开发要点:设备驱动层不直接操作USB总线事务。当需要与设备通信时,驱动调用usbcore提供的API(如
usb_control_msg())来构造并提交URB,由核心层和HCD层完成实际传输。
4.4 USB核心层(usbcore)
usbcore是USB子系统的中枢,它实现了以下关键功能:
- 设备枚举:检测设备插入/拔出,读取设备描述符、配置描述符、接口描述符和端点描述符。
- 配置管理:为设备选择配置(
struct usb_host_config),分配接口和端点资源。 - URB管理:提供URB(USB Request Block)的创建、提交、取消和完成回调机制。
- 总线调度:管理USB帧/微帧的传输时间片,确保实时性要求。
- 电源管理:处理挂起/唤醒、远程唤醒等电源事件。
usbcore对外暴露的核心API包括:
/* 控制传输(常用于枚举和配置) */
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype,
__u16 value, __u16 index,
void *data, __u16 size, int timeout);
/* 批量传输(常用于存储、网络设备) */
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length,
int timeout);
/* 中断传输(常用于HID设备) */
int usb_interrupt_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length,
int timeout);
/* 异步URB提交(高性能场景) */
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
4.5 主机控制器驱动层(HCD)
HCD层直接与硬件打交道,是USB子系统中唯一与具体主机控制器硬件相关的部分。Linux支持四种主流HCD标准:
| HCD类型 | USB版本 | 传输速率 | 典型硬件 | 驱动文件 |
|---|---|---|---|---|
| OHCI | USB 1.1 | 1.5 Mbps / 12 Mbps | 嵌入式平台、旧式PC | ohci-hcd.c |
| UHCI | USB 1.1 | 1.5 Mbps / 12 Mbps | Intel/VIA芯片组 | uhci-hcd.c |
| EHCI | USB 2.0 | 480 Mbps | 大多数现代PC | ehci-hcd.c |
| XHCI | USB 3.0/3.1 | 5 Gbps / 10 Gbps | 现代PC、服务器 | xhci-hcd.c |
兼容性注意:XHCI控制器可以向下兼容USB 2.0和USB 1.1设备,但需要usbcore在枚举时通过“端口握手”机制将低速/全速/高速设备路由到对应的配套控制器(Companion Controller)。嵌入式开发中,如果使用USB 3.0控制器连接低速HID设备,务必确认XHCI驱动对低速设备的支持情况。
4.6 三层协作流程:以HID设备枚举为例
当一个USB鼠标插入系统时,三层架构的协作流程如下:
- HCD层检测到端口状态变化(中断或轮询),通知usbcore。
- usbcore启动枚举流程:复位设备 → 获取设备描述符 → 分配地址 → 获取配置描述符 → 解析接口和端点。
- usbcore根据
id_table匹配已注册的usb_driver(如usbhid驱动)。 - 设备驱动层的
probe()被调用,驱动解析HID报告描述符,注册输入设备。 - 驱动通过
usb_submit_urb()提交中断URB,usbcore将其传递给HCD层。 - HCD层将URB转换为硬件事务,通过DMA或PIO与设备交换数据。
4.7 关键设计原则
分层隔离原则:
- 设备驱动层 不直接访问 主机控制器寄存器。
- HCD层 不关心 设备的具体功能(鼠标、键盘还是存储)。
- usbcore层 不感知 设备驱动内部状态,只负责传输调度和资源管理。