1. USB驱动基础概念:USB体系结构、主机控制器、设备端、端点类型概述

1.1 USB体系结构概述

USB(Universal Serial Bus)采用主从式星形拓扑,由主机(Host)、集线器(Hub)和设备(Device)三层构成。主机端唯一且负责调度所有事务,设备端只能被动响应主机的请求。

核心要点:USB体系结构是非对称的——主机掌握总线控制权,所有数据传输均由主机发起,设备从不主动发起事务。
开发启示:理解这一主从模型对后续编写URB回调至关重要——设备端的中断端点虽然名为“中断”,实际仍由主机轮询,而非硬件中断。
USB体系结构拓扑图 USB主机控制器 根集线器 集线器1 集线器2 设备1 设备2 设备3 设备4 主机控制器 → 根集线器 → 集线器 → 设备:所有数据传输均由主机发起

1.2 主机控制器(Host Controller)

主机控制器是USB体系结构的核心调度器,负责管理总线上的所有事务。Linux内核中通过HCD(Host Controller Driver)层抽象不同硬件实现。

主机控制器类型 规范版本 传输速率 Linux驱动
UHCI USB 1.x 1.5 Mbps(低速)/ 12 Mbps(全速) uhci-hcd
OHCI USB 1.x 1.5 Mbps / 12 Mbps ohci-hcd
EHCI USB 2.0 480 Mbps(高速) ehci-hcd
xHCI USB 3.x 5 Gbps(SuperSpeed)及以上 xhci-hcd
兼容性注意:xHCI控制器向后兼容USB 2.0/1.x设备,但中断端点的调度策略与EHCI存在差异。在编写跨平台USB驱动时,应避免依赖特定控制器的调度时序。

1.3 设备端(Device Side)

USB设备由设备描述符、配置描述符、接口描述符和端点描述符层级定义。每个设备至少包含一个端点0(默认控制端点),用于枚举和控制传输。

USB设备描述符层级结构 设备描述符 (Device Descriptor) 配置描述符 (Configuration Descriptor) 接口描述符1 (Interface) 接口描述符2 (Interface) 端点描述符 (Endpoint) 端点描述符 (Endpoint) 端点描述符 (Endpoint) ... 每个接口包含多个端点,端点0为默认控制端点,始终存在

1.4 端点类型概述

USB规范定义了四种传输类型,每种对应不同的端点特性。中断端点是本课程的核心关注点。

端点类型 传输方向 带宽保证 错误重试 典型应用
控制端点 (Control) 双向 10% 保留 是 设备枚举、配置、命令
批量端点 (Bulk) 单向 无 是(硬件重试) U盘、打印机、大块数据
中断端点 (Interrupt) 单向 有(bInterval保证) 是(硬件重试) 键盘、鼠标、游戏手柄、HID设备
等时端点 (Isochronous) 单向 有 否 音频、视频、实时流
中断端点的关键特性:
  • 轮询机制:主机以固定间隔(bInterval)查询设备是否有数据,并非硬件中断。
  • 带宽预留:全速中断端点最大包64字节,高速可达1024字节。
  • 错误恢复:硬件自动重试失败事务,URB回调中可通过status字段获知最终结果。
  • 低延迟:适用于人机交互设备,典型轮询间隔为1~32ms。

1.5 中断端点与URB的关联

在Linux USB驱动中,URB(USB Request Block)是主机与设备之间数据传输的基本载体。中断端点的数据交换通过中断URB实现,其生命周期如下:

  1. 分配URB:使用 usb_alloc_urb() 分配中断URB实例。
  2. 初始化URB:调用 usb_fill_int_urb() 设置目标设备、端点、回调函数、缓冲区等参数。
  3. 提交URB:通过 usb_submit_urb() 将URB提交给主机控制器。
  4. 回调执行:数据传输完成后(或发生错误),内核调用注册的回调函数。
  5. 重新提交:在回调函数中重新提交URB,实现连续中断数据采集。
中断URB生命周期流程图 1. usb_alloc_urb() 2. usb_fill_int_urb() 3. usb_submit_urb() 4. 回调函数执行 重新提交 中断URB的典型模式:在回调函数中重新提交URB,实现连续中断数据采集 回调函数中通过 urb->status 判断传输结果,通过 urb->actual_length 获取实际数据长度

1.6 中断端点配置的关键参数

在驱动开发中,中断端点的配置参数直接影响系统性能和实时性。以下为中断URB初始化时的核心参数:

/* 中断URB初始化函数原型 */
void usb_fill_int_urb(
    struct urb *urb,                    /* URB指针 */
    struct usb_device *dev,             /* USB设备结构体 */
    unsigned int pipe,                  /* 管道:usb_rcvintpipe() 或 usb_sndintpipe() */
    void *transfer_buffer,              /* 数据缓冲区 */
    int buffer_length,                  /* 缓冲区长度 */
    usb_complete_t complete_fn,         /* 回调函数 */
    void *context,                      /* 回调上下文参数 */
    int interval                        /* 轮询间隔(单位:ms) */
);
参数 说明 注意事项
pipe 指定端点方向和编号 使用 usb_rcvintpipe(dev, endpoint) 或 usb_sndintpipe(dev, endpoint)
transfer_buffer DMA安全的数据缓冲区 必须使用 kmalloc 或 usb_alloc_coherent 分配,不能是栈变量
buffer_length 缓冲区大小 应等于或大于端点描述符中的 wMaxPacketSize
interval 轮询间隔(毫秒) 实际值受端点描述符 bInterval 约束,高速设备最小间隔为 125µs(1/8ms)
开发建议:中断URB的回调函数运行在软中断上下文中,不能调用可能导致睡眠的函数(如 copy_to_user、mutex_lock)。如需将数据传递到用户空间,应使用工作队列或内核线程。

1.7 本章小结

  • USB体系结构采用主从式星形拓扑,主机控制器通过集线器管理多个设备。
  • Linux通过HCD层抽象不同主机控制器(UHCI/OHCI/EHCI/xHCI)。
  • 设备端描述符层级为:设备 → 配置 → 接口 → 端点。
  • 四种端点类型中,中断端点提供带宽保证和错误重试,适用于人机交互设备。
  • 中断URB的生命周期为:分配 → 初始化 → 提交 → 回调 → 重新提交。
  • 回调函数运行在软中断上下文,需注意不能睡眠。