2. Linux USB 子系统架构:核心层、HCD、UDC 与 Gadget 框架
USB 子系统是 Linux 内核中结构最清晰、分层最完善的驱动框架之一。理解其四层架构——USB 核心层、HCD(主机控制器驱动)、UDC(设备控制器驱动)与 Gadget 框架——是进行 USB 驱动移植与设备树配置的基石。本章将从软件架构、数据流、关键数据结构三个维度,拆解每一层的职责与协作关系。
2.1 USB 核心层(USB Core)
USB Core 是 Linux USB 子系统的中枢神经系统,位于用户空间与底层硬件驱动之间。它不直接操作硬件,而是提供一套统一的协议处理、设备管理、驱动匹配与数据路由机制。
- 设备枚举:处理 USB 总线复位、获取设备描述符、分配地址、配置端点。
- 总线管理:维护 USB 总线拓扑结构,管理 Root Hub 与端口状态。
- 驱动匹配:根据
idVendor/idProduct/bInterfaceClass等匹配驱动。 - 数据流路由:将 URBs(USB Request Blocks)从核心层路由到正确的 HCD 或 UDC。
- 电源管理:处理挂起/恢复、远程唤醒等电源事件。
| 数据结构 | 所在文件 | 作用 |
|---|---|---|
struct usb_device |
include/linux/usb.h | 代表一个 USB 设备,包含描述符、配置、端点信息 |
struct usb_interface |
include/linux/usb.h | 代表一个 USB 接口,是驱动绑定的基本单位 |
struct urb |
include/linux/usb.h | USB 请求块,封装一次数据传输的所有信息 |
struct usb_driver |
include/linux/usb.h | USB 设备驱动结构体,定义 probe/disconnect 回调 |
struct usb_host_config |
include/linux/usb.h | 描述设备的某个配置,包含所有接口与端点 |
2.2 HCD(主机控制器驱动)
HCD 是主机侧(Host Side)的底层驱动,直接与 USB 主机控制器硬件通信。Linux 内核支持四种主流主机控制器标准:EHCI(USB 2.0 高速)、OHCI(USB 1.1 全速/低速)、UHCI(Intel 实现的 USB 1.1)以及 xHCI(USB 3.0/3.1/3.2 可扩展主机控制器)。
drivers/usb/host/ 目录下的平台驱动文件(如 ehci-platform.c、xhci-plat.c)。设备树中需要正确配置 compatible 属性、reg(寄存器基址)、interrupts 以及 clocks。
2.3 UDC(设备控制器驱动)
UDC 是设备侧(Device Side / Peripheral Side)的底层驱动,负责管理 USB 设备控制器的硬件寄存器、端点(Endpoint)资源以及中断处理。与 HCD 不同,UDC 不主动发起事务,而是响应主机发起的请求。
| 对比维度 | HCD(主机侧) | UDC(设备侧) |
|---|---|---|
| 角色 | 总线主控,发起所有事务 | 从设备,响应主机请求 |
| 端点方向 | OUT/IN 双向管理 | 通常固定为 IN 或 OUT |
| 数据传输 | 通过 URB 提交 | 通过 Gadget 框架的 request 机制 |
| 电源管理 | 控制总线供电 | 响应远程唤醒与挂起 |
| 设备树匹配 | compatible = "generic-ehci" 等 |
compatible = "snps,dwc3" 等 |
常见的 UDC 控制器包括:DWC2(DesignWare USB 2.0)、DWC3(DesignWare USB 3.0)、FUSB(Freescale USB)、MUSB(Mentor USB)等。每个 UDC 驱动都位于 drivers/usb/gadget/udc/ 目录下。
2.4 Gadget 框架
Gadget 框架是 Linux USB 设备侧驱动的灵魂。它位于 UDC 之上,提供了一套 Function 驱动 抽象层,使得嵌入式设备可以模拟成多种 USB 外设:串口(ACM)、以太网(ECM/RNDIS)、大容量存储(Mass Storage)、音频(UAC)、视频(UVC)等。
2.5 四层协作数据流
当主机向设备发送一个批量 OUT 请求时,数据流经过四层架构的完整路径如下:
- 用户空间:应用程序通过
write()或libusb提交数据。 - USB Core:将数据封装为
struct urb,根据设备地址路由到对应 HCD。 - HCD:将 URB 转换为硬件事务描述符(如 xHCI 的 TRB),写入主机控制器寄存器。
- USB 总线:主机控制器通过差分信号线(D+/D-)发送数据包。
- UDC:设备控制器接收数据,触发中断,UDC 驱动读取 FIFO。
- Gadget 框架:将原始数据传递给对应的 Function 驱动(如 f_serial)。
- Function 驱动:将数据递交给上层的 tty 层或网络协议栈。
usb@fe800000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x10000>;
interrupts = <0 125 4>;
dr_mode = "otg"; /* host / peripheral / otg */
maximum-speed = "super-speed";
phys = <&usb2_phy>, <&usb3_phy>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
};
dr_mode 属性决定了控制器工作在主机模式、设备模式还是 OTG 模式,直接影响内核加载 HCD 还是 UDC+Gadget 驱动栈。
2.6 本章小结
| 层次 | 内核目录 | 核心文件/模块 | 移植关注点 |
|---|---|---|---|
| USB Core | drivers/usb/core/ | usb.c, hub.c, driver.c | 通常无需修改,但需确认 Kconfig 配置 |
| HCD | drivers/usb/host/ | ehci-platform.c, xhci-plat.c | 设备树 reg/interrupts/clocks |
| UDC | drivers/usb/gadget/udc/ | dwc3-udc.c, dwc2_gadget.c | 端点配置、DMA 地址、中断处理 |
| Gadget | drivers/usb/gadget/ | composite.c, configfs.c | Function 驱动选择与绑定 |