1. USB 子系统概述
USB(Universal Serial Bus)自 1996 年问世以来,已成为嵌入式系统与 PC 中最通用的外设连接标准。在 Linux 内核中,USB 子系统是一个高度分层、支持热插拔、即插即用的核心模块。理解 USB 主机控制器、设备、总线拓扑以及内核软件架构,是编写 USB 设备驱动的第一步。
学习目标:掌握 USB 物理拓扑与逻辑拓扑的区别;理解 Linux USB 子系统的 3 层软件栈;为后续 URB 提交与端点配置打下基础。
1.1 USB 主机控制器
USB 主机控制器(Host Controller)是 USB 总线的主控方,负责管理总线上的数据传输、帧调度、错误检测与恢复。Linux 内核支持以下主流主机控制器标准:
| 标准 | 全称 | 速度支持 | 内核驱动 |
|---|---|---|---|
| UHCI | Universal Host Controller Interface | USB 1.1 (Full/Low Speed) | uhci-hcd |
| OHCI | Open Host Controller Interface | USB 1.1 (Full/Low Speed) | ohci-hcd |
| EHCI | Enhanced Host Controller Interface | USB 2.0 (High Speed) | ehci-hcd |
| xHCI | eXtensible Host Controller Interface | USB 3.x (SuperSpeed+) | xhci-hcd |
主机控制器内部维护一个 帧列表(Frame List) 或 事件环(Event Ring),用于调度等时、中断、控制与批量传输。驱动开发者无需直接操作硬件寄存器,而是通过 struct usb_hcd 抽象层与主机控制器交互。
关键点:在嵌入式系统中,xHCI 已成为主流,因为它向后兼容 USB 2.0/1.1 设备,且支持更高效的流式传输(Streams)。
1.2 USB 设备
每个 USB 设备在逻辑上由 配置(Configuration)、接口(Interface) 和 端点(Endpoint) 三层描述符构成。设备驱动通常绑定到一个接口,而不是整个设备。
- 设备描述符:包含 VID/PID、USB 版本、最大包大小等全局信息。
- 配置描述符:描述设备的供电模式、接口数量。一个设备可以有多个配置,但同一时刻只能激活一个。
- 接口描述符:描述功能单元,如 HID 键盘、UVC 摄像头。驱动通过
usb_driver匹配接口。 - 端点描述符:定义数据传输的端点地址、方向、传输类型与最大包长。这是 URB 提交的直接目标。
1.3 USB 总线拓扑结构
USB 采用 树形星型拓扑:主机控制器位于根(Root Hub),通过集线器(Hub)级联扩展,最多支持 7 层(包括根集线器)。每个物理设备对应一个唯一的 总线地址,由主机在枚举时分配。
- 根集线器(Root Hub):集成在主机控制器内部,提供 1~N 个下行端口。
- 外部集线器(External Hub):可级联,每个集线器最多连接 4~7 个下游设备。
- 功能设备(Function Device):终端设备,如鼠标、U 盘、摄像头。
- 复合设备(Composite Device):包含多个接口,每个接口对应一个独立功能。
1.4 Linux USB 子系统软件架构
Linux USB 子系统采用 3 层软件栈,从下到上依次为:主机控制器驱动层(HCD)、核心层(USB Core)、设备驱动层(USB Device Driver)。
| 层次 | 职责 | 关键数据结构 / API |
|---|---|---|
| 主机控制器驱动 (HCD) | 操作硬件寄存器,管理帧调度,处理 DMA | struct usb_hcd, hc_driver |
| USB 核心 (USB Core) | 设备枚举、地址分配、描述符解析、URB 路由、电源管理 | usb_submit_urb(), usb_alloc_dev() |
| USB 设备驱动 | 实现具体设备协议(如 HID、Mass Storage、CDC ACM) | struct usb_driver, probe(), disconnect() |
常见误区:初学者常误以为 USB 设备驱动直接操作主机控制器寄存器。实际上,驱动只与 USB Core 交互,通过
usb_submit_urb() 提交请求,由 Core 层完成底层调度。这种分层设计保证了驱动代码的平台无关性。