4. 端点类型与传输类型:控制传输、批量传输、中断传输、等时传输特性对比

USB 协议定义了四种传输类型,分别对应不同的端点类型。理解这四种传输类型的特性,是配置端点、编写 URB 提交逻辑的基础。每种传输类型在带宽保证、错误重试、数据大小和延迟方面都有不同的设计目标。

核心概念:端点的类型决定了其支持的传输类型。在 USB 描述符中,bEndpointAddress 的低 4 位与 bmAttributes 字段共同标识端点的方向与传输类型。驱动开发者必须在初始化端点时正确匹配这两者。

4.1 四种传输类型总览

下表从带宽、可靠性、延迟、数据大小和典型应用五个维度,对比四种传输类型。

传输类型 带宽保证 错误重试 延迟 最大数据包大小 (FS/HS/SS) 典型应用
控制传输 固定 10% 保留带宽 硬件自动重试 (3 次) 中等 8 / 64 / 512 字节 设备枚举、配置、命令
批量传输 无保证(利用剩余带宽) 硬件自动重试 (直到成功) 高(非实时) 8 / 64 / 1024 字节 U 盘、打印机、数据采集
中断传输 有保证(轮询间隔) 硬件自动重试 (直到成功) 低(可预测) 8 / 64 / 1024 字节 鼠标、键盘、HID 设备
等时传输 有保证(预留带宽) 无重试(允许丢包) 最低(固定间隔) 1023 / 1023 / 1024 字节 音频、视频、实时流
驱动开发要点:批量传输是 USB 驱动开发中最常用的类型,因为它提供可靠的数据传输且不占用固定带宽。但要注意,批量传输在总线繁忙时可能被延迟,不适合实时性要求高的场景。

4.2 控制传输详解

控制传输是 USB 协议的基础,每个 USB 设备必须至少有一个控制端点(端点 0)。它采用“请求-数据-状态”三阶段模型,用于设备枚举、标准请求和厂商自定义命令。

控制传输三阶段模型 阶段 1:设置阶段 SETUP 令牌 + 8 字节数据 阶段 2:数据阶段 IN/OUT 数据包(可选) 阶段 3:状态阶段 握手包确认 关键说明: • 设置阶段:主机发送 8 字节的 SETUP 数据包,包含请求类型、请求码、值和索引。 • 数据阶段:可选,方向由 SETUP 包中的 bmRequestType 决定。数据长度由 wLength 指定。 • 状态阶段:设备返回握手包(ACK/NAK/STALL),表示传输成功或失败。 • 驱动中通过 usb_control_msg() 或构造 URB 并设置 URB_TYPE 为 URB_CONTROL 来提交。

4.3 批量传输详解

批量传输是 USB 驱动开发中最常用的传输类型。它提供可靠的数据传输,但带宽优先级最低。当总线空闲时,批量传输可以占用全部带宽;当总线繁忙时,它会被其他传输类型抢占。

常见陷阱:批量传输没有固定的带宽保证。在高速 USB 系统中,批量传输的最大数据包大小为 512 字节(HS)或 1024 字节(SS)。如果驱动未正确处理短包(short packet)或 ZLP(零长度包),可能导致数据传输不完整或死锁。

批量传输的 URB 提交流程如下:

  1. 分配 URB:使用 usb_alloc_urb(0, GFP_KERNEL) 分配 URB 结构体。
  2. 填充 URB:设置 urb->dev、urb->pipe(使用 usb_sndbulkpipe() 或 usb_rcvbulkpipe())、urb->transfer_buffer、urb->transfer_buffer_length。
  3. 设置回调:注册 urb->complete 回调函数,处理传输完成或错误。
  4. 提交 URB:调用 usb_submit_urb(urb, GFP_KERNEL) 将 URB 提交到 USB 核心层。
  5. 释放 URB:在回调中或超时后调用 usb_free_urb(urb) 释放资源。
/* 批量传输 URB 提交示例 */
struct urb *bulk_urb;
void *buf;

/* 1. 分配缓冲区 */
buf = kmalloc(512, GFP_KERNEL);
if (!buf)
    return -ENOMEM;

/* 2. 分配 URB */
bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!bulk_urb) {
    kfree(buf);
    return -ENOMEM;
}

/* 3. 填充 URB:批量 OUT 端点 */
usb_fill_bulk_urb(bulk_urb, udev,
                  usb_sndbulkpipe(udev, 0x02),  /* 端点 2 OUT */
                  buf, 512,
                  bulk_write_complete,  /* 回调函数 */
                  NULL);

/* 4. 提交 URB */
ret = usb_submit_urb(bulk_urb, GFP_KERNEL);
if (ret) {
    dev_err(&udev->dev, "批量 URB 提交失败: %d\n", ret);
    usb_free_urb(bulk_urb);
    kfree(buf);
    return ret;
}

4.4 中断传输详解

中断传输并非真正的中断,而是主机以固定间隔轮询设备,检查是否有数据需要传输。它提供低延迟和带宽保证,适用于鼠标、键盘等 HID 设备。

中断传输轮询机制 USB 主机 轮询间隔: 8ms USB 设备 中断端点 轮询时间轴: t=0ms: 主机发送 IN 令牌 → 设备无数据 → 设备返回 NAK t=8ms: 主机再次发送 IN 令牌 → 设备有数据 → 设备返回 DATA + ACK
驱动提示:中断传输的轮询间隔在端点描述符的 bInterval 字段中定义。对于全速设备,单位为毫秒;对于高速设备,单位为 125µs 的倍数。驱动中通过 usb_fill_int_urb() 或手动设置 urb->interval 来配置。

4.5 等时传输详解

等时传输是唯一不保证数据可靠性的传输类型。它没有握手阶段,不进行错误重试,但提供固定的带宽和最低的延迟。等时传输适用于音频、视频等实时流数据,允许偶尔的数据丢失。

特性 等时传输 批量传输 中断传输
错误重试 无 有(直到成功) 有(直到成功)
带宽预留 是(固定) 否 是(按间隔)
数据包大小 最大 1024 字节 最大 1024 字节 最大 1024 字节
URB 类型 URB_ISOCHRONOUS URB_BULK URB_INTERRUPT
典型应用 USB 摄像头、音频设备 存储设备、打印机 HID 设备、游戏手柄
等时传输数据流模型 音频/视频源 实时数据流 等时端点 无重试 主机驱动 处理数据 等时传输特点: • 数据包按固定时间间隔发送,不等待握手确认。 • 驱动需要处理 URB 中的 iso_frame_desc 数组,每个帧描述符包含偏移和长度。

4.6 传输类型选择指南

在实际驱动开发中,选择正确的传输类型至关重要。以下决策流程可以帮助你快速确定合适的传输类型:

  • 是否需要可靠传输?
    • 是 → 继续判断是否需要实时性。
    • 否 → 选择 等时传输(音频/视频流)。
  • 是否需要低延迟和带宽保证?
    • 是 → 选择 中断传输(HID 设备)。
    • 否 → 选择 批量传输(存储设备)。
  • 是否用于设备枚举或标准请求?
    • 是 → 选择 控制传输(端点 0)。
实战建议:在编写 USB 驱动时,优先使用批量传输进行大数据量传输。如果设备是 HID 类,使用中断传输。控制传输仅用于配置和命令。等时传输需要精确的带宽计算,建议在硬件验证阶段再启用。