2. Linux USB子系统架构

Linux USB 子系统是操作系统中最复杂的设备驱动框架之一,它同时支持主机侧(Host)和设备侧(Device/Gadget)两种角色。理解其分层架构是编写 USB Gadget 驱动的基石。本章将深入剖析 USB Core、HCD、UDC 与 Gadget API 四个核心层次的职责与交互关系。

2.1 整体分层架构概览

Linux USB 子系统采用典型的层次化设计,从下到上依次为:硬件层、控制器驱动层、核心层以及应用/类驱动层。对于 Gadget 模式,其层次结构对称于主机模式,但方向相反。

核心概念: 主机侧通过 HCD(Host Controller Driver)管理 USB 总线;设备侧通过 UDC(USB Device Controller)实现设备功能。USB Core 作为中间枢纽,提供统一的 API 和数据结构。
Linux USB 子系统分层架构(主机侧 + 设备侧) 主机侧 (Host) 设备侧 (Gadget) USB Host Controller (硬件) EHCI / xHCI / OHCI / UHCI USB Device Controller (硬件) DWC2 / DWC3 / Chipidea / MUSB HCD (主机控制器驱动) ehci-hcd / xhci-hcd / ohci-hcd UDC (设备控制器驱动) dwc2 / dwc3 / chipidea / musb USB Core (核心层) usbcore.ko — 协议抽象、总线管理、设备枚举、URB 传输、Gadget API 注册 USB 主机类驱动 usb-storage / usb-serial / HID Gadget 功能驱动 g_serial / g_ether / g_mass_storage USB Core 同时与 HCD 和 UDC 交互,向上为不同角色提供统一的驱动接口

2.2 各层次职责详解

2.2.1 USB Core(核心层)

USB Core 是 Linux USB 子系统的中枢神经,以内核模块 usbcore.ko 形式存在。它不直接操作硬件,而是提供一套与硬件无关的框架,包括:

  • 总线管理: 维护 USB 总线拓扑,处理设备的热插拔事件。
  • 设备枚举: 解析设备描述符、配置描述符、接口描述符等标准 USB 描述符。
  • URB 传输管理: 提供 URB(USB Request Block)分配、提交、取消和完成回调机制。
  • Gadget API 注册: 提供 usb_gadget_probe_driver() 等接口,供 UDC 驱动和 Gadget 功能驱动注册。
  • 协议抽象: 实现 USB 2.0 / 3.0 协议规范中的标准请求处理。
关键文件: drivers/usb/core/ 目录下的 hub.c、usb.c、urb.c、message.c 等是 USB Core 的核心实现。

2.2.2 HCD(主机控制器驱动)

HCD 位于主机侧,直接与 USB 主机控制器硬件通信。它负责将 USB Core 下发的 URB 转换为硬件可执行的传输描述符(TD),并处理硬件中断。

HCD 类型 对应硬件规范 速度支持 典型驱动
EHCI USB 2.0 高速 (480 Mbps) ehci-hcd
OHCI USB 1.1 全速/低速 (12/1.5 Mbps) ohci-hcd
UHCI USB 1.1 (Intel) 全速/低速 (12/1.5 Mbps) uhci-hcd
xHCI USB 3.0/3.1/3.2 超高速 (5/10/20 Gbps) xhci-hcd

2.2.3 UDC(设备控制器驱动)

UDC 驱动是 Gadget 模式的底层引擎,直接操作 USB 设备控制器寄存器。它负责:

  • 处理设备控制器中断(如连接、断开、复位、挂起)。
  • 管理端点(Endpoint)的配置与数据传输。
  • 通过 Gadget API 向上层报告事件(如 SETUP 请求到达)。
  • 实现 DMA 传输以提升数据吞吐量。
注意: UDC 驱动与 HCD 驱动不能同时加载在同一硬件上,因为 USB 控制器在物理上只能工作于主机模式或设备模式之一(除非是 OTG 控制器)。

2.2.4 Gadget API(设备侧驱动接口)

Gadget API 是 Linux 为设备侧提供的一套标准编程接口,定义在 include/linux/usb/gadget.h 中。它屏蔽了不同 UDC 硬件的差异,使 Gadget 功能驱动可以跨平台运行。

Gadget API 内部结构 Gadget 功能驱动 (g_serial / g_ether / g_mass_storage / 自定义) Gadget API (usb_gadget_driver / usb_gadget / usb_ep / usb_request) include/linux/usb/gadget.h UDC 驱动 (dwc2 / dwc3 / chipidea / musb) Gadget API 是 UDC 硬件无关层,功能驱动只需调用标准 API 即可

2.3 层次间数据流与交互

当 Gadget 功能驱动需要发送数据时,数据流自顶向下传递:

  1. 功能驱动 调用 usb_ep_queue() 提交 usb_request 到指定端点。
  2. Gadget API 将请求转发给 UDC 驱动的 ops->ep_queue() 回调。
  3. UDC 驱动 将请求转换为硬件描述符,写入设备控制器 FIFO 或启动 DMA。
  4. 硬件完成传输后触发中断,UDC 驱动调用 usb_request->complete() 回调通知上层。
关键数据结构:
  • struct usb_gadget — 代表一个 USB 设备控制器实例。
  • struct usb_ep — 代表一个端点,包含端点号、方向、最大包大小等属性。
  • struct usb_request — 代表一次数据传输请求,包含数据缓冲区、长度、完成回调。
  • struct usb_gadget_driver — 代表一个 Gadget 功能驱动,包含 bind()、unbind()、setup() 等回调。

2.4 层次关系对比总结

层次 角色 主要接口/文件 与硬件关系
USB Core 协议抽象与总线管理 drivers/usb/core/ 硬件无关
HCD 主机控制器驱动 drivers/usb/host/ 直接操作主机控制器
UDC 设备控制器驱动 drivers/usb/gadget/udc/ 直接操作设备控制器
Gadget API 设备侧驱动框架 include/linux/usb/gadget.h 硬件无关
工程实践提示: 在开发自定义 Gadget 功能驱动时,通常只需要包含 linux/usb/gadget.h 和 linux/usb/composite.h,无需关心底层 UDC 硬件细节。这种分层设计极大地提高了代码的可移植性。