2. Linux USB 子系统架构:核心层、HCD、UDC 与 Gadget 框架

USB 子系统是 Linux 内核中结构最清晰、分层最完善的驱动框架之一。理解其四层架构——USB 核心层、HCD(主机控制器驱动)、UDC(设备控制器驱动)与 Gadget 框架——是进行 USB 驱动移植与设备树配置的基石。本章将从软件架构、数据流、关键数据结构三个维度,拆解每一层的职责与协作关系。

Linux USB 子系统四层架构总览 用户空间:应用程序 / libusb / 文件系统接口 USB 核心层 (USB Core) 设备枚举 · 总线管理 · 协议解析 · 驱动匹配 HCD(主机控制器驱动) EHCI / OHCI / UHCI / xHCI 主机侧:管理 Root Hub 与事务 UDC(设备控制器驱动) 底层硬件寄存器操作 设备侧:端点管理与中断处理 USB 主机控制器硬件 USB 设备控制器硬件 Gadget 框架位于 UDC 之上,提供 Function 驱动抽象 主机侧通过 HCD 访问设备;设备侧通过 Gadget 框架模拟外设功能

2.1 USB 核心层(USB Core)

USB Core 是 Linux USB 子系统的中枢神经系统,位于用户空间与底层硬件驱动之间。它不直接操作硬件,而是提供一套统一的协议处理、设备管理、驱动匹配与数据路由机制。

核心职责:
  • 设备枚举:处理 USB 总线复位、获取设备描述符、分配地址、配置端点。
  • 总线管理:维护 USB 总线拓扑结构,管理 Root Hub 与端口状态。
  • 驱动匹配:根据 idVendor / idProduct / bInterfaceClass 等匹配驱动。
  • 数据流路由:将 URBs(USB Request Blocks)从核心层路由到正确的 HCD 或 UDC。
  • 电源管理:处理挂起/恢复、远程唤醒等电源事件。
USB Core 关键数据结构
数据结构 所在文件 作用
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 可扩展主机控制器)。

HCD 内部架构与数据流 USB Core (usb_submit_urb) HCD 通用层 (hcd-pci / hcd-platfrom / hcd-dma) URB 队列管理 · DMA 映射 · 中断处理 · 根 Hub 模拟 ehci-hcd xhci-hcd ohci-hcd / uhci-hcd USB 主机控制器硬件寄存器 / DMA 引擎
移植要点:在嵌入式平台移植 HCD 时,通常需要关注 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 不主动发起事务,而是响应主机发起的请求。

UDC 与 HCD 关键差异对比
对比维度 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)等。

Gadget 框架分层与 Function 驱动 用户空间:configfs / sysfs / 应用程序 Gadget 框架核心 (gadget.ko) gadget_driver · usb_gadget · usb_ep · usb_request f_serial (ACM) USB 串口仿真 f_mass_storage U 盘 / 存储仿真 f_ecm / f_rndis USB 以太网仿真 UDC 驱动 (dwc3-udc / dwc2_gadget / musb_gadget) USB 设备控制器硬件
常见误区:Gadget 框架不等于 UDC。UDC 是硬件驱动层,负责寄存器操作;Gadget 框架是软件抽象层,负责 Function 逻辑。移植时,如果只修改 UDC 驱动而不更新 Gadget 框架的绑定逻辑,设备可能无法被主机正确识别。

2.5 四层协作数据流

当主机向设备发送一个批量 OUT 请求时,数据流经过四层架构的完整路径如下:

  1. 用户空间:应用程序通过 write() 或 libusb 提交数据。
  2. USB Core:将数据封装为 struct urb,根据设备地址路由到对应 HCD。
  3. HCD:将 URB 转换为硬件事务描述符(如 xHCI 的 TRB),写入主机控制器寄存器。
  4. USB 总线:主机控制器通过差分信号线(D+/D-)发送数据包。
  5. UDC:设备控制器接收数据,触发中断,UDC 驱动读取 FIFO。
  6. Gadget 框架:将原始数据传递给对应的 Function 驱动(如 f_serial)。
  7. Function 驱动:将数据递交给上层的 tty 层或网络协议栈。
设备树配置提示:在设备树中,USB 控制器节点通常需要配置以下属性:
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 驱动选择与绑定