1. USB系统概述
USB(Universal Serial Bus,通用串行总线)自 1996 年问世以来,已成为嵌入式系统和 PC 领域最主流的外设连接标准。本章从总线历史、版本演进、物理拓扑和逻辑拓扑四个维度,建立 USB 系统的完整知识框架,为后续驱动开发和 URB 传输机制打下基础。
1.1 USB 总线历史与版本演进
USB 标准由 Intel、Microsoft、IBM 等公司共同制定,由 USB-IF(USB Implementers Forum)维护。下表梳理了各版本的关键特性与发布时间:
| 版本 | 发布时间 | 理论带宽 | 编码方式 | 关键特性 |
|---|---|---|---|---|
| USB 1.0 | 1996 | 1.5 Mbps(低速)/ 12 Mbps(全速) | NRZI | 取代串口/并口,支持热插拔 |
| USB 1.1 | 1998 | 同上 | NRZI | 修正 1.0 缺陷,广泛商用 |
| USB 2.0 | 2000 | 480 Mbps(高速) | NRZI | 引入微帧、事务分割,兼容 1.x |
| USB 3.0 | 2008 | 5 Gbps(SuperSpeed) | 8b/10b | 双总线架构(USB 2.0 + SS),全双工 |
| USB 3.1 | 2013 | 10 Gbps(SuperSpeed+) | 128b/132b | Type-C 接口引入,PD 供电 |
| USB 3.2 | 2017 | 20 Gbps(双通道) | 128b/132b | 多通道聚合,仅 Type-C |
| USB4 | 2019 | 40 Gbps | 128b/132b | 基于 Thunderbolt 3 协议,隧道传输 |
开发提示: Linux 内核中,USB 子系统通过
usb_device_speed 枚举区分设备速度(USB_SPEED_LOW、USB_SPEED_FULL、USB_SPEED_HIGH、USB_SPEED_SUPER 等)。驱动开发时需根据速度选择适当的传输类型和缓冲区对齐方式。
1.2 USB 物理拓扑结构
USB 采用星形-级联拓扑,由主机(Host)、集线器(Hub)和设备(Device)三层构成。主机控制器位于根节点,Hub 负责端口扩展和速度转换,设备是功能端点。
物理拓扑要点:
- 每个 USB 系统有且仅有一个主机控制器(EHCI / xHCI 等)。
- Hub 深度最多 7 层(含根 Hub),设备总数不超过 127 个(含 Hub)。
- 设备通过上行端口连接 Hub,Hub 通过下行端口连接子设备或下级 Hub。
- Linux 中通过
lsusb -t查看树形拓扑。
1.3 USB 逻辑拓扑
逻辑拓扑描述了 USB 设备在软件层面的组织方式。Linux USB 核心将设备抽象为配置(Configuration)、接口(Interface)、端点(Endpoint)和管道(Pipe)四个层级。
1.3.1 四层逻辑模型
| 逻辑层 | 内核数据结构 | 说明 | 数量限制 |
|---|---|---|---|
| 设备 (Device) | struct usb_device |
代表一个物理 USB 设备,包含设备描述符 | 每设备 1 个 |
| 配置 (Configuration) | struct usb_host_config |
定义设备的功能集合,如供电模式、接口组合 | 最多 255 个,常用 1~2 个 |
| 接口 (Interface) | struct usb_interface |
对应一个功能单元,驱动绑定对象 | 每配置最多 32 个 |
| 端点 (Endpoint) | struct usb_host_endpoint |
数据通信的终点,描述传输方向/类型/带宽 | 每接口最多 16 个(0~15) |
| 管道 (Pipe) | unsigned int (宏编码) |
主机与端点之间的逻辑通信通道 | 每端点 1 个 |
驱动开发关键点: Linux 驱动通过
usb_driver->probe() 回调获得 struct usb_interface * 指针。驱动必须从接口中解析端点描述符,确定端点地址、方向和传输类型,然后通过 usb_rcvbulkpipe() / usb_sndbulkpipe() 等宏构造管道,才能发起 URB 传输。
1.3.2 端点类型与传输方式
USB 规范定义了 4 种端点类型,对应不同的传输方式:
| 端点类型 | 传输方式 | 带宽保证 | 典型应用 | Linux 宏 |
|---|---|---|---|---|
| 控制 (Control) | 双向,主机发起 | 10% 保留 | 设备枚举、配置、命令 | usb_rcvctrlpipe() |
| 批量 (Bulk) | 单向,尽力而为 | 无 | U 盘、打印机、数据采集 | usb_rcvbulkpipe() |
| 中断 (Interrupt) | 单向,轮询 | 有(≤90% 帧时间) | 键盘、鼠标、游戏手柄 | usb_rcvintpipe() |
| 等时 (Isochronous) | 单向,实时 | 有(预分配) | 音频、视频、实时传感器 | usb_rcvisocpipe() |
1.4 设备枚举与描述符
当 USB 设备插入主机时,主机控制器通过枚举(Enumeration)过程获取设备信息。枚举流程如下:
- 复位(Reset):主机检测到设备插入,复位设备,设备地址恢复为 0。
- 获取设备描述符:主机通过控制传输读取前 8 字节(
struct usb_device_descriptor),获取bMaxPacketSize0。 - 分配地址:主机通过
SET_ADDRESS请求分配唯一地址(1~127)。 - 读取完整描述符:主机读取完整的设备描述符、配置描述符、接口描述符、端点描述符。
- 选择配置:主机通过
SET_CONFIGURATION激活某个配置,设备进入就绪状态。 - 驱动绑定:Linux USB 核心根据
idVendor/idProduct或接口类匹配驱动,调用probe()。
内核调试技巧: 使用
usbmon 或 usbhid-dump 可以捕获枚举阶段的 URB 数据包。在驱动开发中,usb_set_interface() 和 usb_clear_halt() 是枚举后常用的辅助函数。