3. Linux USB子系统架构
Linux USB子系统是内核中设计最为清晰的设备模型之一,采用分层、模块化的架构,将主机侧与设备侧的驱动逻辑解耦。本章从整体框架出发,依次剖析USBCore、HCD接口与Gadget框架,帮助开发者建立完整的USB驱动视图。
核心认知:USB子系统分为三层——USB设备驱动层(面向具体设备)、USBCore层(通用协议与资源管理)、HCD层(硬件抽象)。Gadget框架则是设备侧的对等实现。
3.1 Linux USB子系统整体框架
USB子系统在内核中的位置介于硬件控制器与具体设备驱动之间。下图展示了主机侧(Host)与设备侧(Device)的完整分层关系:
架构启示:主机侧与设备侧的层次结构高度对称。如果你理解了主机侧的USBCore + HCD,那么设备侧的Gadget API + UDC几乎可以类比学习。这种对称设计使得Linux既能作为USB Host(如PC),也能作为USB Device(如手机、嵌入式板卡)。
3.2 USBCore模块功能
USBCore是USB子系统的中枢模块,位于drivers/usb/core/目录下。它不直接操作硬件,而是为上层设备驱动和下层HCD提供统一的抽象接口。
| 功能模块 | 核心文件 | 职责描述 |
|---|---|---|
| 设备枚举 | hub.c, driver.c | 检测设备插入/拔出,读取描述符,分配地址,配置设备 |
| URB管理 | urb.c | URB的创建、提交、取消、完成回调处理 |
| 驱动模型 | driver.c, generic.c | usb_driver注册/注销,设备与驱动的匹配(match) |
| 总线管理 | usb.c, bus.c | usb_bus_type初始化,root hub模拟,电源管理 |
| 端点与管道 | endpoint.c, message.c | 端点描述符解析,管道(pipe)构造,控制传输辅助 |
USBCore对外暴露的关键数据结构包括:
- struct usb_device:代表一个USB设备,包含设备地址、速度、配置、接口列表。
- struct usb_interface:代表一个接口(功能单元),设备驱动绑定到接口而非整个设备。
- struct urb:USB请求块,是主机侧所有数据传输的载体。
- struct usb_driver:设备驱动结构体,包含id_table、probe、disconnect等回调。
常见误区:很多初学者认为USB设备驱动直接操作硬件寄存器。实际上,设备驱动只能通过USBCore提供的URB接口与设备通信,绝对不能直接访问主机控制器寄存器。所有硬件操作由HCD层封装。
3.3 HCD(主机控制器驱动)接口
HCD(Host Controller Driver)是USBCore与硬件之间的桥梁。它实现了struct hc_driver结构体中的回调函数,将USBCore下发的URB转换为特定主机控制器(OHCI/EHCI/xHCI)的硬件操作。
Linux内核支持三种主流主机控制器标准:
| 标准 | 速度支持 | 内核驱动 | 寄存器接口 |
|---|---|---|---|
| OHCI | USB 1.1 (Full/Low Speed) | ohci-hcd | 内存映射寄存器,软件调度 |
| EHCI | USB 2.0 (High Speed) | ehci-hcd | 异步列表/周期性列表,硬件调度 |
| xHCI | USB 3.0/3.1/3.2 (SuperSpeed) | xhci-hcd | TRB环,支持所有速度向下兼容 |
HCD层的核心接口定义在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);
/* 端点管理 */
int (*alloc_dev)(struct usb_hcd *hcd, struct usb_device *dev);
void (*free_dev)(struct usb_hcd *hcd, struct usb_device *dev);
/* 根Hub操作 */
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);
};
关键机制:HCD通过中断处理程序检测传输完成,然后调用URB的complete回调函数。这个回调在软中断(softirq)或tasklet上下文中执行,不能睡眠。如果需要在进程上下文处理数据,应在complete回调中使用工作队列(workqueue)延迟处理。
3.4 Gadget框架简介
Gadget框架是Linux USB子系统在设备侧的实现,位于drivers/usb/gadget/目录下。它允许嵌入式设备(如手机、开发板)模拟USB外设功能,例如虚拟串口、U盘、以太网卡等。
Gadget框架的核心层次:
- Gadget功能驱动:实现具体功能,如
g_serial.ko(串口)、g_mass_storage.ko(大容量存储)、g_ether.ko(以太网)。 - Gadget API:提供
struct usb_gadget、struct usb_ep(端点)、struct usb_request(请求)等抽象。 - UDC驱动:UDC(USB Device Controller)驱动,直接操作硬件寄存器,类似于主机侧的HCD。
| 概念 | 主机侧对应 | 设备侧对应 |
|---|---|---|
| 驱动结构 | struct usb_driver | struct usb_gadget_driver |
| 通信单元 | struct urb | struct usb_request |
| 端点抽象 | struct usb_host_endpoint | struct usb_ep |
| 控制器驱动 | HCD (hc_driver) | UDC (usb_udc) |
| 核心层 | USBCore (drivers/usb/core) | Gadget API (drivers/usb/gadget/udc) |
实践建议:在嵌入式开发中,Gadget框架常用于实现USB Device Mode。例如,在树莓派或i.MX平台上,通过配置
configfs接口可以动态组合多个功能(如同时模拟串口和U盘)。调试时使用lsusb -v在主机侧查看设备描述符是否正确。
3.5 本章小结
Linux USB子系统架构的核心设计思想是分层抽象:
- USBCore作为主机侧的中枢,管理设备枚举、URB调度和驱动模型。
- HCD屏蔽不同主机控制器的硬件差异,提供统一的
hc_driver接口。 - Gadget框架是设备侧的镜像实现,使Linux设备能够充当USB外设。