1. USB子系统概述:USB主机控制器、USB设备、USB协议栈分层结构

USB(Universal Serial Bus)子系统是Linux内核中最为复杂且成熟的子系统之一。理解其整体架构是进行USB驱动开发的基础。本章将从硬件控制器、设备类型以及软件协议栈三个维度,系统性地剖析USB子系统的核心组成。

1.1 USB系统拓扑结构

USB采用树形拓扑,由USB主机控制器、USB Hub和USB功能设备组成。主机控制器位于根节点,负责管理总线上的所有事务。

核心概念:在USB系统中,所有通信必须由主机发起。设备不能主动向主机发送数据,只能响应主机的请求。这种主从模式简化了设备设计,但增加了主机控制器的复杂度。
USB系统拓扑结构 USB主机控制器 根Hub (Root Hub) USB Hub 1 USB Hub 2 USB Hub 3 鼠标 (HID) 键盘 (HID) U盘 (Mass Storage) 摄像头 (Video) 串口 (CDC ACM) 拓扑说明: • 主机控制器是唯一的主节点,管理所有总线事务。 • Hub用于扩展端口,最多支持7层级联(包括根Hub)。 • 每个功能设备通过唯一的设备地址与主机通信。

1.2 USB主机控制器

USB主机控制器(Host Controller)是USB系统的核心硬件,负责实现USB协议的低层传输。Linux内核支持多种主机控制器规范,每种规范对应不同的硬件接口和软件驱动。

规范名称 总线类型 最大速度 Linux驱动 典型硬件
OHCI (Open HCI) USB 1.x 12 Mbps (全速) ohci-hcd 早期嵌入式SoC、部分x86南桥
UHCI (Universal HCI) USB 1.x 12 Mbps (全速) uhci-hcd Intel/VIA x86主板
EHCI (Enhanced HCI) USB 2.0 480 Mbps (高速) ehci-hcd 大多数x86/ARM USB 2.0控制器
xHCI (eXtensible HCI) USB 3.x 5/10/20 Gbps (超高速) xhci-hcd 现代x86/ARM USB 3.x控制器
开发提示:在嵌入式Linux开发中,xHCI已成为主流。xHCI向后兼容USB 2.0/1.1设备,且支持更灵活的端点管理和流式传输。在设备树中,通常通过compatible = "generic-xhci"或厂商特定的兼容字符串来绑定xHCI驱动。

1.3 USB设备分类

USB设备根据功能分为不同的设备类(Device Class)。每个设备类定义了标准的通信协议和描述符格式,使得同一类设备可以使用通用的驱动程序。

  • HID (Human Interface Device):键盘、鼠标、游戏手柄、触摸屏。使用中断传输,低延迟。
  • Mass Storage:U盘、移动硬盘、SD卡读卡器。使用批量传输,大数据量。
  • CDC (Communication Device Class):以太网适配器、串口转换器(如CP2102、CH340)、Modem。
  • Video:摄像头、视频采集卡。使用等时传输,保证带宽。
  • Audio:USB声卡、麦克风、扬声器。使用等时传输,实时性要求高。
  • Hub:USB扩展器。负责端口管理和电源分配。
USB设备类层次 USB设备 HID类 Mass Storage类 CDC类 Video/Audio类 鼠标 键盘 U盘 USB转串口 摄像头 每个设备类定义了一套标准描述符和传输协议。Linux内核通过usb_device_id匹配驱动,支持类驱动和厂商特定驱动。

1.4 USB协议栈分层结构

Linux USB协议栈采用分层架构,从硬件到用户空间共分为五层。每一层负责不同的抽象级别,层与层之间通过标准接口通信。

  1. 硬件层:物理USB总线、主机控制器寄存器、DMA引擎。
  2. 主机控制器驱动层 (HCD):直接操作硬件寄存器,实现OHCI/UHCI/EHCI/xHCI规范。提供统一的struct hc_driver接口给上层。
  3. USB核心层 (USB Core):管理设备枚举、地址分配、描述符解析、电源管理、URB(USB Request Block)调度。提供usb_submit_urb()等核心API。
  4. 设备驱动层:针对特定设备类或厂商设备实现功能逻辑,如usbhid、usb-storage、cdc_acm。
  5. 用户空间层:通过libusb、/dev/usb/*或sysfs接口与内核交互。
Linux USB协议栈分层架构 用户空间层 libusb / /dev/usb/* / sysfs 设备驱动层 usbhid / usb-storage / cdc_acm / 厂商驱动 USB核心层 (USB Core) 设备枚举 / 地址分配 / 描述符解析 / URB调度 / 电源管理 主机控制器驱动层 (HCD) ohci-hcd / uhci-hcd / ehci-hcd / xhci-hcd 硬件层 USB总线 / 主机控制器寄存器 / DMA引擎 数据流方向:用户空间 → 设备驱动 → USB Core → HCD → 硬件。URB是跨层传递的核心数据结构。

1.5 URB:USB请求块

URB(USB Request Block)是Linux USB协议栈中最核心的数据结构,用于在设备驱动和USB Core之间传递I/O请求。每个URB描述了一次USB传输的所有信息。

struct urb {
    struct list_head urb_list;       /* 链表节点 */
    struct usb_device *dev;          /* 目标USB设备 */
    unsigned int pipe;               /* 管道:端点方向+类型+地址 */
    int status;                      /* 传输状态 */
    unsigned int transfer_flags;     /* 传输标志 */
    void *transfer_buffer;           /* 数据缓冲区 */
    dma_addr_t transfer_dma;         /* DMA地址 */
    int transfer_buffer_length;      /* 缓冲区长度 */
    int actual_length;               /* 实际传输长度 */
    unsigned char *setup_packet;     /* 控制传输设置包 */
    int interval;                    /* 中断/等时传输间隔 */
    usb_complete_t complete;         /* 完成回调函数 */
    void *context;                   /* 回调上下文 */
};
注意事项:URB的生命周期管理是USB驱动开发中的常见错误点。URB必须使用usb_alloc_urb()分配,使用usb_submit_urb()提交,在回调函数中检查urb->status判断传输结果。切勿在中断上下文中调用usb_free_urb()。

1.6 设备枚举流程

当USB设备插入时,主机控制器驱动和USB Core协同完成设备枚举。枚举过程是理解USB协议栈工作的关键。

步骤 动作 描述 涉及层
1 检测连接 Hub检测端口状态变化,报告给主机 HCD + Hub驱动
2 复位设备 主机发送复位信号,设备地址重置为0 HCD
3 分配地址 主机分配唯一地址,设备进入Address状态 USB Core
4 读取描述符 获取设备描述符、配置描述符、接口描述符、端点描述符 USB Core
5 选择配置 主机选择一个配置,设备进入Configured状态 USB Core
6 加载驱动 USB Core根据usb_device_id匹配并绑定设备驱动 USB Core + 设备驱动
USB设备枚举流程 1. 检测连接 Hub报告状态 2. 复位设备 地址=0 3. 分配地址 唯一地址 4. 读取描述符 设备/配置/接口/端点 5. 选择配置 Configured状态 6. 加载驱动 匹配usb_device_id 枚举关键点: • 步骤1-3由HCD和Hub驱动完成,不涉及设备驱动。 • 步骤4中USB Core解析描述符,构建设备拓扑。 • 步骤6中驱动通过probe()回调初始化设备。 • 枚举失败时,设备进入USB_STATE_NOTATTACHED状态。 设备状态机: Attached → Powered → Default (地址0) → Address (分配地址) → Configured (选择配置) → 正常运行

1.7 设备树中的USB绑定

在嵌入式系统中,USB主机控制器通常通过设备树(Device Tree)描述。设备树节点提供控制器基地址、中断号、PHY引用、时钟等信息。

/* 典型的xHCI控制器设备树节点 */
usb@f0930000 {
    compatible = "generic-xhci";
    reg = <0x0 0xf0930000 0x0 0x8000>;
    interrupts = <0 56 4>;
    clocks = <&clock 0x2 0x9>;
    clock-names = "core";
    phys = <&usb_phy0>;
    phy-names = "usb";
    status = "okay";
};
关键字段说明:
  • compatible:驱动匹配字符串,内核通过它找到对应的HCD驱动。
  • reg:控制器寄存器地址范围和大小。
  • interrupts:中断号、触发类型(高电平、上升沿等)。
  • phys / phy-names:引用USB PHY(物理层收发器),用于初始化高速/超高速信号。
  • clocks:控制器工作时钟,通常包括AHB/APB总线时钟和USB参考时钟。

1.8 本章小结

本章从硬件拓扑、主机控制器规范、设备分类、协议栈分层、URB机制、枚举流程到设备树绑定,全面梳理了USB子系统的核心概念。掌握这些基础知识,是后续深入学习USB PHY初始化、设备树定制以及驱动开发实战的前提。