2. USB硬件拓扑结构:主机控制器(HCD)、根集线器(Root Hub)、USB设备、端点(Endpoint)的物理与逻辑层次

USB 总线采用树形拓扑结构,由主机控制器(Host Controller)作为根节点,通过根集线器(Root Hub)向下扩展,连接至各类 USB 设备。每个 USB 设备内部又包含多个端点(Endpoint),这些端点是 USB 通信的最小逻辑单元。理解这一物理与逻辑层次,是掌握 URB(USB Request Block)通信机制的基础。

核心要点:USB 拓扑是“主机主导、设备响应”的严格主从结构。主机控制器是唯一的通信发起者,所有数据传输都必须经过主机控制器调度。

2.1 物理拓扑层次概览

从物理连接角度看,USB 系统分为四个层级:

  1. 主机控制器(Host Controller):位于主机端,是 USB 总线的“大脑”,负责管理总线事务、调度传输、处理错误。
  2. 根集线器(Root Hub):集成在主机控制器内部或紧邻其旁,提供物理端口,负责检测设备连接/断开、供电管理、总线复位。
  3. USB 设备(USB Device):包括功能设备(如键盘、U盘)和外部集线器(Hub),通过端口接入总线。
  4. 端点(Endpoint):设备内部的通信接口,每个端点对应一个数据缓冲区,是 USB 传输的终点。
USB 物理拓扑结构图 USB 物理拓扑结构图 主机控制器 (HCD) 根集线器 (Root Hub) 端口 1 端口 2 端口 3 端口 4 USB 设备 A USB 设备 B 外部集线器 (Hub) USB 设备 C USB 设备 D 说明:外部集线器可级联,最多支持 7 层深度;每个端口最多连接一个设备。

2.2 主机控制器(HCD)—— 总线的“大脑”

主机控制器驱动(Host Controller Driver, HCD)是 Linux USB 子系统的核心组件之一。它直接与硬件交互,负责:

  • 总线调度:将 URB 转换为 USB 帧/微帧事务,按传输类型(控制、批量、中断、等时)分配带宽。
  • 事务处理:生成 SOF(Start of Frame)包,发起 IN/OUT/SETUP 事务,处理握手包(ACK/NAK/STALL)。
  • 错误恢复:检测总线错误(如 CRC 校验失败、超时),执行重试或报告错误状态。
  • 电源管理:控制端口供电、挂起/唤醒状态。
主流主机控制器规范对比
规范 速度支持 传输方式 Linux 驱动
OHCI (Open HCI) USB 1.1 (低速/全速) 内存映射寄存器 ohci-hcd
UHCI (Universal HCI) USB 1.1 (低速/全速) I/O 端口寄存器 uhci-hcd
EHCI (Enhanced HCI) USB 2.0 (高速) 异步/周期列表调度 ehci-hcd
xHCI (eXtensible HCI) USB 3.x (超高速) 事件环/命令环/传输环 xhci-hcd
开发提示:在 Linux 内核中,HCD 通过 struct usb_hcd 结构体抽象,每个主机控制器对应一个 usb_hcd 实例。驱动开发者通常不需要直接操作 HCD 寄存器,而是通过 USB 核心层提供的 API 提交 URB。

2.3 根集线器(Root Hub)—— 物理连接的起点

根集线器是主机控制器的一部分,在逻辑上被 USB 核心视为一个特殊的 USB 设备。它的主要职责包括:

  • 端口管理:检测设备插入/拔出事件,通过端口状态寄存器报告给 HCD。
  • 供电控制:为每个端口提供 5V 电源(最大 500mA/900mA,取决于 USB 版本)。
  • 总线复位:当新设备连接时,对端口执行复位信号,使设备进入默认地址状态。
  • 速度识别:通过 D+/D- 线路上的上拉电阻检测设备速度(低速/全速/高速/超高速)。

在 Linux 内核中,根集线器被枚举为一个 usb_device 实例,其 devnum 通常为 1。根集线器本身也包含一个默认的控制端点(端点 0),用于主机与根集线器之间的控制传输。

2.4 USB 设备 —— 功能与集线器

USB 设备分为两大类:

  • 功能设备(Function Device):提供特定功能,如 HID(人机接口设备)、大容量存储、音频、视频等。
  • 集线器设备(Hub Device):用于扩展端口数量,允许更多设备接入总线。集线器本身也是一个 USB 设备,拥有自己的端点。

每个 USB 设备在枚举过程中会被分配一个唯一地址(Address),范围 1~127。设备通过配置(Configuration)、接口(Interface)、端点(Endpoint)三级描述符向主机声明自身能力。

USB 设备描述符层次结构 USB 设备描述符层次结构 设备描述符 (Device) 配置描述符 (Configuration) 接口描述符 (Interface) 端点 0 (控制) 端点 1 (批量IN) 端点 2 (中断OUT) 一个设备可以有多个配置,一个配置可以有多个接口,一个接口可以有多个端点(端点0除外)。

2.5 端点(Endpoint)—— 通信的最小逻辑单元

端点是 USB 设备中实际进行数据收发的逻辑实体。每个端点由端点号(Endpoint Number)和方向(Direction)唯一标识。端点 0 是每个设备必须包含的默认控制端点,用于设备枚举和控制传输。

2.5.1 端点类型

USB 端点类型与特性
传输类型 端点类型 典型用途 带宽保证 错误重试
控制传输 控制端点 设备枚举、配置、命令 10% 保留带宽 硬件自动重试
批量传输 批量端点 U盘、打印机、网络 无(空闲时传输) 硬件自动重试
中断传输 中断端点 键盘、鼠标、游戏手柄 保证轮询间隔 硬件自动重试
等时传输 等时端点 音频、视频、摄像头 保证带宽 无重试

2.5.2 端点在 Linux 内核中的表示

在 Linux USB 子系统中,端点通过 struct usb_host_endpoint 结构体描述:

struct usb_host_endpoint {
    struct usb_endpoint_descriptor  desc;       // 端点描述符(硬件信息)
    struct list_head                urb_list;   // 挂载到此端点的 URB 链表
    void                            *hcpriv;    // 主机控制器私有数据
    struct ep_device                ep_dev;     // 端点设备(sysfs 接口)
    unsigned char                   *extra;     // 额外描述符
    int                             extralen;
    int                             enabled;    // 端点是否启用
};

关键字段说明:

  • desc:包含端点地址、方向、类型、最大包大小等硬件属性。
  • urb_list:所有发往该端点的 URB 被挂载到此链表,由 HCD 调度处理。
  • enabled:表示端点是否已启用。未启用的端点不会接收任何 URB。
常见误区:端点号 + 方向组合才是唯一的。例如,端点 1 IN 和端点 1 OUT 是两个不同的端点。在 URB 中通过 pipe 宏(如 usb_rcvbulkpipe、usb_sndbulkpipe)指定端点和方向。

2.6 逻辑层次总结:从 URB 到物理信号

当 USB 设备驱动提交一个 URB 时,数据经历的完整路径如下:

  1. 设备驱动 构造 URB,指定目标端点、数据缓冲区、回调函数。
  2. USB 核心 将 URB 提交到对应 usb_host_endpoint 的 urb_list 中。
  3. HCD 从 urb_list 取出 URB,将其拆分为 USB 事务(Token + Data + Handshake)。
  4. 根集线器 将事务信号通过端口发送到 USB 总线。
  5. USB 设备 的端点硬件接收/发送数据,完成一次通信。
URB 到物理信号的完整路径 URB 到物理信号的完整路径 设备驱动 USB 核心 HCD 根集线器 USB 设备端点 数据流:设备驱动 → USB核心 → HCD → 根集线器 → USB总线 → 设备端点 每个箭头代表一次 URB 提交与事务处理过程

2.7 本章小结

USB 硬件拓扑结构是理解 URB 通信机制的前提。从主机控制器到端点,每一层都有明确的职责和抽象接口:

  • 主机控制器(HCD):总线的调度中心,负责将 URB 转化为总线事务。
  • 根集线器(Root Hub):物理连接的起点,管理端口状态和供电。
  • USB 设备:通过配置、接口、端点三级描述符向主机声明能力。
  • 端点(Endpoint):通信的最小逻辑单元,每种端点类型对应不同的传输特性和带宽策略。
下一阶段准备:在掌握拓扑结构后,第 3 章将深入讲解 URB 的结构体定义、生命周期管理以及如何在驱动中正确提交和回收 URB。