3. Linux USB子系统架构

Linux USB子系统是内核中设计最为清晰的设备模型之一,采用分层、模块化的架构,将主机侧与设备侧的驱动逻辑解耦。本章从整体框架出发,依次剖析USBCore、HCD接口与Gadget框架,帮助开发者建立完整的USB驱动视图。

核心认知:USB子系统分为三层——USB设备驱动层(面向具体设备)、USBCore层(通用协议与资源管理)、HCD层(硬件抽象)。Gadget框架则是设备侧的对等实现。

3.1 Linux USB子系统整体框架

USB子系统在内核中的位置介于硬件控制器与具体设备驱动之间。下图展示了主机侧(Host)与设备侧(Device)的完整分层关系:

Linux USB子系统整体框架 Linux USB子系统整体框架(主机侧 + 设备侧) 主机侧 (Host) 设备侧 (Device) USB设备驱动层 usb_driver / probe() / disconnect() USBCore 层 usb_bus_type / URB / 设备枚举 HCD 层 hcd_operations / ohci-hcd / ehci-hcd / xhci-hcd USB主机控制器硬件 Gadget功能驱动层 gadget_driver / 串口/存储/网络 Gadget API 层 usb_gadget / usb_ep / usb_request UDC 层 usb_udc / 控制器驱动 USB设备控制器硬件 USB 总线 架构要点: • 主机侧:设备驱动 → USBCore → HCD → 硬件,URB是核心通信单元。 • 设备侧:功能驱动 → Gadget API → UDC → 硬件,usb_request是核心通信单元。 • USBCore是主机侧的“交通枢纽”,负责设备枚举、URB路由、驱动匹配。
架构启示:主机侧与设备侧的层次结构高度对称。如果你理解了主机侧的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等回调。
USBCore核心数据结构关系 USBCore核心数据结构关系图 struct usb_device devnum, speed, config ep0, state, bus struct usb_interface altsetting, cur_altsetting dev, usb_dev struct urb pipe, transfer_buffer complete, status, context struct usb_driver id_table, probe, disconnect suspend, resume 包含 提交 绑定
常见误区:很多初学者认为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与USBCore交互流程 HCD与USBCore交互流程 USBCore usb_submit_urb() usb_kill_urb() HCD (hc_driver) urb_enqueue() urb_dequeue() 主机控制器硬件 DMA传输 中断触发 完成回调 (urb->complete)
关键机制: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框架分层与数据流 Gadget框架分层与数据流 Gadget功能驱动 g_serial / g_mass_storage Gadget API usb_gadget / usb_ep / usb_request UDC驱动 dwc3 / mv_udc / atmel_usba Gadget数据流示例(虚拟串口发送数据): 1. 功能驱动调用 usb_ep_queue() 提交 usb_request 2. Gadget API 将请求转发给 UDC 驱动 3. UDC 驱动配置 DMA/寄存器,将数据发送到USB总线
实践建议:在嵌入式开发中,Gadget框架常用于实现USB Device Mode。例如,在树莓派或i.MX平台上,通过配置configfs接口可以动态组合多个功能(如同时模拟串口和U盘)。调试时使用lsusb -v在主机侧查看设备描述符是否正确。

3.5 本章小结

Linux USB子系统架构的核心设计思想是分层抽象:

  • USBCore作为主机侧的中枢,管理设备枚举、URB调度和驱动模型。
  • HCD屏蔽不同主机控制器的硬件差异,提供统一的hc_driver接口。
  • Gadget框架是设备侧的镜像实现,使Linux设备能够充当USB外设。