1. USB驱动基础概念:USB体系结构、主机控制器、设备端、端点类型概述
1.1 USB体系结构概述
USB(Universal Serial Bus)采用主从式星形拓扑,由主机(Host)、集线器(Hub)和设备(Device)三层构成。主机端唯一且负责调度所有事务,设备端只能被动响应主机的请求。
核心要点:USB体系结构是非对称的——主机掌握总线控制权,所有数据传输均由主机发起,设备从不主动发起事务。
开发启示:理解这一主从模型对后续编写URB回调至关重要——设备端的中断端点虽然名为“中断”,实际仍由主机轮询,而非硬件中断。
1.2 主机控制器(Host Controller)
主机控制器是USB体系结构的核心调度器,负责管理总线上的所有事务。Linux内核中通过HCD(Host Controller Driver)层抽象不同硬件实现。
| 主机控制器类型 | 规范版本 | 传输速率 | Linux驱动 |
|---|---|---|---|
| UHCI | USB 1.x | 1.5 Mbps(低速)/ 12 Mbps(全速) | uhci-hcd |
| OHCI | USB 1.x | 1.5 Mbps / 12 Mbps | ohci-hcd |
| EHCI | USB 2.0 | 480 Mbps(高速) | ehci-hcd |
| xHCI | USB 3.x | 5 Gbps(SuperSpeed)及以上 | xhci-hcd |
兼容性注意:xHCI控制器向后兼容USB 2.0/1.x设备,但中断端点的调度策略与EHCI存在差异。在编写跨平台USB驱动时,应避免依赖特定控制器的调度时序。
1.3 设备端(Device Side)
USB设备由设备描述符、配置描述符、接口描述符和端点描述符层级定义。每个设备至少包含一个端点0(默认控制端点),用于枚举和控制传输。
1.4 端点类型概述
USB规范定义了四种传输类型,每种对应不同的端点特性。中断端点是本课程的核心关注点。
| 端点类型 | 传输方向 | 带宽保证 | 错误重试 | 典型应用 |
|---|---|---|---|---|
| 控制端点 (Control) | 双向 | 10% 保留 | 是 | 设备枚举、配置、命令 |
| 批量端点 (Bulk) | 单向 | 无 | 是(硬件重试) | U盘、打印机、大块数据 |
| 中断端点 (Interrupt) | 单向 | 有(bInterval保证) | 是(硬件重试) | 键盘、鼠标、游戏手柄、HID设备 |
| 等时端点 (Isochronous) | 单向 | 有 | 否 | 音频、视频、实时流 |
中断端点的关键特性:
- 轮询机制:主机以固定间隔(bInterval)查询设备是否有数据,并非硬件中断。
- 带宽预留:全速中断端点最大包64字节,高速可达1024字节。
- 错误恢复:硬件自动重试失败事务,URB回调中可通过status字段获知最终结果。
- 低延迟:适用于人机交互设备,典型轮询间隔为1~32ms。
1.5 中断端点与URB的关联
在Linux USB驱动中,URB(USB Request Block)是主机与设备之间数据传输的基本载体。中断端点的数据交换通过中断URB实现,其生命周期如下:
- 分配URB:使用
usb_alloc_urb()分配中断URB实例。 - 初始化URB:调用
usb_fill_int_urb()设置目标设备、端点、回调函数、缓冲区等参数。 - 提交URB:通过
usb_submit_urb()将URB提交给主机控制器。 - 回调执行:数据传输完成后(或发生错误),内核调用注册的回调函数。
- 重新提交:在回调函数中重新提交URB,实现连续中断数据采集。
1.6 中断端点配置的关键参数
在驱动开发中,中断端点的配置参数直接影响系统性能和实时性。以下为中断URB初始化时的核心参数:
/* 中断URB初始化函数原型 */
void usb_fill_int_urb(
struct urb *urb, /* URB指针 */
struct usb_device *dev, /* USB设备结构体 */
unsigned int pipe, /* 管道:usb_rcvintpipe() 或 usb_sndintpipe() */
void *transfer_buffer, /* 数据缓冲区 */
int buffer_length, /* 缓冲区长度 */
usb_complete_t complete_fn, /* 回调函数 */
void *context, /* 回调上下文参数 */
int interval /* 轮询间隔(单位:ms) */
);
| 参数 | 说明 | 注意事项 |
|---|---|---|
pipe |
指定端点方向和编号 | 使用 usb_rcvintpipe(dev, endpoint) 或 usb_sndintpipe(dev, endpoint) |
transfer_buffer |
DMA安全的数据缓冲区 | 必须使用 kmalloc 或 usb_alloc_coherent 分配,不能是栈变量 |
buffer_length |
缓冲区大小 | 应等于或大于端点描述符中的 wMaxPacketSize |
interval |
轮询间隔(毫秒) | 实际值受端点描述符 bInterval 约束,高速设备最小间隔为 125µs(1/8ms) |
开发建议:中断URB的回调函数运行在软中断上下文中,不能调用可能导致睡眠的函数(如
copy_to_user、mutex_lock)。如需将数据传递到用户空间,应使用工作队列或内核线程。
1.7 本章小结
- USB体系结构采用主从式星形拓扑,主机控制器通过集线器管理多个设备。
- Linux通过HCD层抽象不同主机控制器(UHCI/OHCI/EHCI/xHCI)。
- 设备端描述符层级为:设备 → 配置 → 接口 → 端点。
- 四种端点类型中,中断端点提供带宽保证和错误重试,适用于人机交互设备。
- 中断URB的生命周期为:分配 → 初始化 → 提交 → 回调 → 重新提交。
- 回调函数运行在软中断上下文,需注意不能睡眠。