2. Linux USB 子系统架构:三层划分与数据流
Linux USB 子系统采用经典的三层软件架构设计,从底层的硬件控制到上层的功能抽象,每一层都有明确的职责和接口。理解这三层划分是掌握 USB Host 驱动开发的基础。
2.1 三层架构总览
USB 子系统在逻辑上分为 USB 核心层(USB Core)、主机控制器驱动层(HCD) 和 设备驱动层(Gadget/Function)。核心层作为桥梁,向上为设备驱动提供统一 API,向下抽象不同主机控制器的差异。
2.2 各层职责详解
| 层次 | 核心文件/目录 | 主要职责 | 关键数据结构 |
|---|---|---|---|
| 设备驱动层 | drivers/usb/class/drivers/usb/gadget/ |
实现具体 USB 设备功能(键盘、存储、网卡等);注册为 USB 接口驱动;处理 URB 完成回调 | usb_driverusb_interface |
| USB 核心层 | drivers/usb/core/ |
设备枚举与配置;URB 生命周期管理;总线电源管理;提供 usb_* API 给设备驱动 |
usb_deviceusb_busurb |
| HCD 层 | drivers/usb/host/ |
直接操作主机控制器寄存器;管理传输描述符环(Ring);处理硬件中断;实现 DMA 映射 | usb_hcdxhci_hcdtd |
2.3 核心数据结构关系
三层之间的交互通过几个核心数据结构完成。下图展示了从设备驱动到硬件的关键数据流路径:
2.4 URB:跨层通信的核心载体
URB(USB Request Block) 是 USB 子系统中最核心的跨层通信单元。它类似于网络协议栈中的 sk_buff,承载着从设备驱动到硬件控制器的所有传输请求。
URB 生命周期:
- 创建:设备驱动调用
usb_alloc_urb()分配 URB 结构体 - 填充:设置传输类型(控制/批量/中断/等时)、目标端点、数据缓冲区、回调函数
- 提交:调用
usb_submit_urb()将 URB 交给 USB Core - 路由:USB Core 根据 URB 所属的
usb_device找到对应的 HCD - 硬件化:HCD 将 URB 拆解为硬件传输描述符(如 xHCI 的 TRB)
- 完成回调:硬件传输完成后,HCD 调用 URB 的回调函数通知设备驱动
// URB 结构体核心字段(简化)
struct urb {
struct list_head urb_list; // 链表节点
struct usb_device *dev; // 目标 USB 设备
unsigned int pipe; // 管道(端点方向+类型)
int status; // 传输状态
unsigned int transfer_flags; // 传输标志
void *transfer_buffer; // 数据缓冲区
dma_addr_t transfer_dma; // DMA 地址
int transfer_buffer_length; // 数据长度
int actual_length; // 实际传输长度
unsigned char *setup_packet; // 控制传输设置包
void *context; // 驱动私有数据
usb_complete_t complete; // 完成回调函数
};
2.5 设备驱动层:Gadget 与 Function
USB 子系统不仅支持 Host 模式,还支持 Gadget(设备)模式。在 Gadget 模式下,Linux 设备可以模拟为 USB 外设(如虚拟串口、虚拟网卡、大容量存储设备)。
| 模式 | 驱动层 | 典型场景 | 关键框架 |
|---|---|---|---|
| Host 模式 | 设备驱动层(Device Driver) | PC 连接 USB 鼠标、U 盘 | usb_driver + usb_interface |
| Gadget 模式 | Function 驱动层(Gadget Function) | Android 手机模拟为 MTP 设备 | usb_function + usb_composite_dev |
注意:Gadget 模式下的 Function 驱动与 Host 模式下的设备驱动虽然概念对称,但实现框架完全不同。Function 驱动运行在 drivers/usb/gadget/ 目录下,使用 usb_ep(端点)和 usb_request 接口,而非 URB。
2.6 数据流全景示例
以 USB 大容量存储设备(U 盘)为例,展示一次读请求的完整数据流:
2.7 关键 API 与接口
三层之间的接口定义清晰,下表列出各层之间的核心 API:
| 接口方向 | API 函数 | 说明 |
|---|---|---|
| 设备驱动 → USB Core | usb_submit_urb() |
提交 URB 请求 |
| 设备驱动 → USB Core | usb_control_msg() |
发送控制传输(同步封装) |
| USB Core → HCD | hc_driver->urb_enqueue() |
HCD 接收 URB 并处理 |
| USB Core → HCD | hc_driver->start() |
启动主机控制器 |
| HCD → USB Core | usb_hcd_giveback_urb() |
HCD 将完成的 URB 返回给 Core |
| USB Core → 设备驱动 | urb->complete() |
URB 完成回调函数 |
重要提示:URB 回调函数在中断上下文中执行,不能调用可能导致睡眠的函数(如 kmalloc(GFP_KERNEL)、mutex_lock())。如果需要执行耗时操作,必须使用工作队列(workqueue)或 tasklet 推迟处理。
2.8 本章小结
Linux USB 子系统的三层架构设计体现了软件工程中的分层抽象原则:
- 设备驱动层 关注功能实现,无需关心硬件细节
- USB 核心层 提供通用服务,管理总线生命周期
- HCD 层 封装硬件差异,提供统一接口给上层
URB 作为跨层通信的核心载体,贯穿整个数据流路径。理解这三层划分和 URB 生命周期,是后续深入学习 xHCI 协议和驱动开发的前提。