3. 批量传输端点特性

批量传输(Bulk Transfer)是 USB 协议中为数据完整性设计的传输类型,在 Linux 驱动开发中广泛应用于 U 盘、网卡、打印机等大容量非实时设备。理解批量传输的协议特点、端点描述符结构、最大包大小与带宽预留机制,是编写高性能批量驱动的基础。

3.1 批量传输的协议特点

批量传输在 USB 协议中具有以下核心特征:

  • 数据完整性优先:硬件层自动执行 CRC 校验与重传,保证数据无差错到达。
  • 无固定带宽保证:总线空闲时批量传输可占满带宽,但等时与中断传输优先占用。
  • 流控机制:通过 NYET(Not Yet)握手与数据包 Ping 协议实现端点级流量控制。
  • 单向或双向:每个批量端点仅支持 IN(设备到主机)或 OUT(主机到设备)一个方向。
  • 数据包分帧:批量传输数据被拆分为多个数据包(Data Packet),每个包以 DATA0/DATA1 交替同步。
关键区别:批量传输与中断传输的最大差异在于——批量传输没有轮询间隔约束,主机控制器在每帧(微帧)的剩余时间中调度批量事务;中断传输则保证每 N 个微帧至少有一次服务机会。
驱动开发提示:批量端点常用于块存储与批量数据流场景。在 Linux 内核中,批量 URB 的完成回调(complete callback)可能被延迟调度,驱动不应假设实时响应。
批量传输协议数据流与握手过程 批量传输协议数据流与握手过程 主机 (Host) 设备 (Device) OUT 数据包 (DATA0/DATA1) ACK / NYET 握手 IN 数据包 (DATA0/DATA1) ACK 握手 Ping 协议(高速模式) 主机发送 Ping 令牌包探测设备接收能力 设备回复 ACK(可接收)或 NYET(不可接收)

3.2 批量端点描述符

在 USB 描述符体系中,批量端点通过 端点描述符(Endpoint Descriptor) 中的 bmAttributes 字段标识。Linux 内核通过 struct usb_endpoint_descriptor 访问这些信息。

字段 偏移 大小 说明
bLength 0 1 字节 描述符长度,固定为 7
bDescriptorType 1 1 字节 端点描述符类型,值为 0x05
bEndpointAddress 2 1 字节 端点号(bit 3-0)与方向(bit 7:0=OUT,1=IN)
bmAttributes 3 1 字节 bit 1-0 = 0x02 表示批量传输
wMaxPacketSize 4 2 字节 最大包大小(字节),高速模式含额外事务数位
bInterval 6 1 字节 批量端点忽略此字段(设为 0)
常见误区:批量端点的 bInterval 字段在 USB 2.0 规范中定义为“忽略”,但某些主机控制器会检查该值。驱动开发时建议将其初始化为 0,避免兼容性问题。

Linux 内核中解析批量端点描述符的典型代码片段:

/* 遍历接口的端点描述符,查找批量端点 */
struct usb_host_endpoint *ep;
int i;

for (i = 0; i < udev->actconfig->desc.bNumEndpoints; i++) {
    ep = &udev->actconfig->interface[0]->altsetting[0]->endpoint[i];
    if (usb_endpoint_is_bulk_in(&ep->desc)) {
        bulk_in_pipe = usb_rcvbulkpipe(udev, ep->desc.bEndpointAddress);
        bulk_in_maxp = usb_endpoint_maxp(&ep->desc);
        break;
    }
}
批量端点描述符结构 批量端点描述符结构 bLength=7 bDescType=0x05 bEndpointAddr bmAttributes wMaxPacketSize bInterval=0 批量端点描述符关键字段解析 • bEndpointAddress: bit7=方向(1=IN,0=OUT), bit3-0=端点号 • bmAttributes: bit1-0=0x02 标识批量传输类型 • wMaxPacketSize: 高速模式 bit12-11 表示每微帧额外事务数(0/1/2) • bInterval: 批量端点忽略,驱动应设为 0

3.3 最大包大小与带宽预留

批量传输的最大包大小(MaxPacketSize)由端点描述符的 wMaxPacketSize 字段定义,不同 USB 速度模式下取值不同:

USB 速度 最大包大小 每微帧事务数 理论峰值带宽
低速 (1.5 Mbps) 8 字节 1 8 字节/帧 ≈ 0.8 KB/s
全速 (12 Mbps) 8/16/32/64 字节 1 64 字节/帧 ≈ 64 KB/s
高速 (480 Mbps) 512 字节 1/2/3(微帧) 512×3/125μs ≈ 12.288 MB/s
超高速 (5 Gbps) 1024 字节 1(突发模式) 1024×N/125μs(取决于突发长度)
带宽预留机制:批量传输不预留固定带宽。主机控制器在每帧(或微帧)中,先服务等时传输和中断传输,剩余时间全部用于批量传输。这意味着批量传输的瞬时带宽可以很高,但延迟不可预测。

高速模式下,wMaxPacketSize 的高 2 位(bit 12-11)编码了每微帧的额外事务数:

  • 00:每微帧 1 个事务(基础模式)
  • 01:每微帧 2 个事务
  • 10:每微帧 3 个事务
  • 11:保留

Linux 内核通过 usb_endpoint_maxp() 宏获取最大包大小,通过 usb_endpoint_maxp_mult() 获取额外事务数:

/* 获取批量端点的最大包大小与额外事务数 */
u16 max_packet = usb_endpoint_maxp(&ep->desc);
int extra_txns = usb_endpoint_maxp_mult(&ep->desc);

/* 计算实际每微帧可传输的数据量 */
u32 per_microframe = max_packet * (1 + extra_txns);
pr_info("Bulk EP: maxp=%u, extra_txns=%d, per_microframe=%u\n",
        max_packet, extra_txns, per_microframe);
批量传输带宽预留与调度 批量传输带宽预留与调度(高速模式微帧) 1 微帧 = 125 μs 等时传输 中断 批量传输(剩余带宽) 空闲 / 其他批量 批量传输带宽特性 • 无预留带宽:批量传输使用等时/中断传输后的剩余时间 • 高速模式:每微帧最多可传输 3 个 512 字节数据包 = 1536 字节 • 驱动优化:增大 URB 缓冲区可减少调度开销,提升批量吞吐

3.4 批量传输性能影响因素

在 Linux 驱动中,批量传输的实际性能受以下因素制约:

  • URB 缓冲区大小:较大的 URB 缓冲区(如 64 KB)可减少 URB 提交次数,降低 CPU 开销。
  • 端点最大包大小:全速设备若使用 64 字节最大包,理论吞吐仅为高速 512 字节的 1/8。
  • 主机控制器调度策略:不同 EHCI/xHCI 控制器对批量事务的排队深度不同。
  • 总线竞争:多个批量端点同时传输时,主机控制器按轮询或优先级调度。
  • DMA 对齐:缓冲区未对齐可能导致额外的数据拷贝,降低吞吐。
性能测试建议:在测试批量传输性能时,应使用 usbmon 或 ftrace 跟踪 URB 提交与完成时间,结合 perf 分析 CPU 开销。典型批量驱动吞吐目标:高速 USB 设备应达到 30-40 MB/s 以上。