2. USB数据传输模型:USB主机控制器与协议栈分层

USB数据传输模型是理解Linux USB设备驱动开发的核心基础。本章深入剖析USB主机控制器(OHCI/UHCI/EHCI/xHCI)、USB设备端控制器以及USB协议栈的分层架构(硬件层、HCD层、USBCore层、设备驱动层),帮助开发者建立从物理信号到驱动接口的完整认知。

2.1 USB主机控制器规范演进

USB主机控制器是系统与USB总线之间的硬件接口,负责执行总线事务、管理传输调度、处理错误恢复。不同USB版本对应不同的主机控制器规范:

规范USB版本传输速率特点
OHCIUSB 1.x1.5 Mbps / 12 Mbps硬件管理事务列表,CPU负载低
UHCIUSB 1.x1.5 Mbps / 12 Mbps软件管理调度,CPU负载高,成本低
EHCIUSB 2.0480 Mbps高速传输,兼容OHCI/UHCI
xHCIUSB 3.x5 Gbps / 10 Gbps统一架构,支持所有速率,可扩展

关键区别:OHCI与UHCI都用于USB 1.x,但OHCI将调度逻辑固化在硬件中,UHCI则依赖软件驱动完成调度。EHCI仅处理高速传输,低速/全速设备通过配套控制器(companion controller)接管。xHCI彻底统一了所有速率等级的传输管理。

2.1.1 OHCI与UHCI对比

  • OHCI(Open Host Controller Interface):由Compaq、Microsoft、National Semiconductor联合制定。硬件维护周期性帧列表(Frame List)和中断列表,软件只需填充端点描述符(Endpoint Descriptor, ED)和传输描述符(Transfer Descriptor, TD)。
  • UHCI(Universal Host Controller Interface):由Intel主导。硬件只提供基本帧定时,软件必须手动构建队列头(Queue Head, QH)和传输描述符(TD),调度逻辑完全在驱动中实现。

开发建议:在嵌入式系统中,OHCI因硬件卸载调度而更受欢迎;UHCI多见于x86平台,因其硬件成本更低。现代系统已全面转向xHCI。

2.1.2 EHCI与xHCI架构

EHCI引入异步列表(Async List)和周期性列表(Periodic List)分离调度,支持高速批量传输和中断传输。xHCI则采用命令环(Command Ring)、事件环(Event Ring)和传输环(Transfer Ring)的环形缓冲区模型,极大简化了驱动开发。

注意:xHCI的环形缓冲区模型与OHCI/UHCI/EHCI的链表模型完全不同,驱动开发时不能复用旧有数据结构。

2.2 USB协议栈分层架构

Linux USB协议栈采用经典的分层设计,从下至上依次为:硬件层、HCD层、USBCore层、设备驱动层。每一层封装下层细节,向上层提供抽象接口。

Linux USB协议栈分层架构 设备驱动层 USB设备驱动(usb_driver / usb_class_driver) USBCore层 USB核心(urb管理、设备枚举、配置解析) HCD层 主机控制器驱动(ohci-hcd / uhci-hcd / ehci-hcd / xhci-hcd) 硬件层 USB主机控制器硬件(OHCI/UHCI/EHCI/xHCI) 数据流方向:设备驱动 → USBCore → HCD → 硬件 → USB总线

2.2.1 硬件层

硬件层包含USB主机控制器芯片及其寄存器接口。主机控制器通过系统总线(PCI、AHB等)与CPU连接,管理USB端口的电气信号、包传输、错误检测和流量控制。硬件层对外暴露MMIO寄存器或I/O端口,供HCD驱动访问。

2.2.2 HCD层(Host Controller Driver)

HCD层是硬件与USBCore之间的桥梁。每个主机控制器规范对应一个HCD驱动:

  • ohci-hcd:实现OHCI规范,管理帧列表和中断列表。
  • uhci-hcd:实现UHCI规范,软件调度队列头和传输描述符。
  • ehci-hcd:实现EHCI规范,管理异步列表和周期性列表。
  • xhci-hcd:实现xHCI规范,管理命令环、事件环和传输环。

HCD层向上注册struct hc_driver结构体,提供start、stop、urb_enqueue、urb_dequeue等回调函数。

// hc_driver结构体核心回调(简化)
struct hc_driver {
    const char *description;
    int (*start)(struct usb_hcd *hcd);
    void (*stop)(struct usb_hcd *hcd);
    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);
    // ... 其他回调
};

2.2.3 USBCore层

USBCore层是协议栈的中枢,提供以下核心功能:

  • URB管理:分配、提交、取消、完成回调。
  • 设备枚举:检测设备插入/拔出,分配地址,读取描述符。
  • 配置解析:解析设备、配置、接口、端点描述符。
  • 驱动匹配:根据id_table匹配设备和驱动。
  • 电源管理:挂起/恢复、远程唤醒。

USBCore层对外暴露usb_submit_urb、usb_alloc_urb、usb_kill_urb等API,供设备驱动层调用。

2.2.4 设备驱动层

设备驱动层是开发者最常接触的层次。它通过USBCore提供的接口与USB设备通信,实现特定设备的功能。设备驱动层注册struct usb_driver或struct usb_class_driver,处理URB完成回调,解析设备数据。

// USB设备驱动注册示例
static struct usb_driver my_usb_driver = {
    .name = "my_usb_device",
    .probe = my_usb_probe,
    .disconnect = my_usb_disconnect,
    .id_table = my_usb_id_table,
};

module_usb_driver(my_usb_driver);

2.3 USB设备端控制器

USB设备端控制器(Device Controller)位于USB设备侧,负责响应主机控制器的请求。常见的设备端控制器包括:

  • UDC(USB Device Controller):集成在SoC或微控制器中,如Synopsys DesignWare、Chipidea、Freescale USB。
  • Gadget框架:Linux通过Gadget框架将设备端控制器抽象为struct usb_gadget,支持多种功能(串口、存储、网络等)。

主机侧 vs 设备侧:主机侧使用HCD驱动管理主机控制器,设备侧使用UDC驱动管理设备控制器。两者通过USB总线上的包交换实现通信。

2.4 URB传输机制概述

URB(USB Request Block)是Linux USB协议栈中数据传输的基本单元。它封装了一次USB传输的所有信息:目标端点、传输方向、数据缓冲区、传输类型、完成回调等。

URB传输流程 设备驱动 USBCore HCD usb_alloc_urb usb_submit_urb USB主机控制器 硬件传输 完成中断 URB完成回调 URB生命周期:分配 → 填充 → 提交 → 硬件传输 → 完成回调 → 释放

2.5 分层数据流实例

以USB鼠标为例,数据从设备到应用程序的完整路径:

  1. 硬件层:鼠标通过USB线缆发送中断包,主机控制器接收并触发DMA传输。
  2. HCD层:xhci-hcd从事件环中读取完成事件,将数据填入URB缓冲区。
  3. USBCore层:调用URB完成回调,通知HID驱动数据就绪。
  4. 设备驱动层:HID驱动解析报告描述符,将鼠标移动/按键事件上报到输入子系统。

调试技巧:使用usbmon工具可以捕获USB总线上的原始包,帮助定位分层问题。启用CONFIG_USB_MON内核选项后,通过/sys/kernel/debug/usbmon接口读取数据。

2.6 本章小结

层次核心职责关键数据结构/接口
硬件层物理信号收发、包传输MMIO寄存器、DMA引擎
HCD层硬件抽象、传输调度struct hc_driver、struct usb_hcd
USBCore层URB管理、设备枚举、驱动匹配usb_submit_urb、struct usb_device
设备驱动层设备功能实现、数据解析struct usb_driver、struct urb