3. USB 传输类型:特性与适用场景
USB 协议定义了四种传输类型,分别针对不同的带宽、延迟和可靠性需求。理解这四种传输类型是编写 USB 设备驱动的核心基础。每种传输类型在 USB 规范中对应特定的端点描述符,驱动开发者必须根据硬件特性选择合适的传输方式。
3.1 控制传输 (Control Transfer)
控制传输是 USB 设备枚举和配置的基础,也是唯一必须被所有 USB 设备支持的传输类型。它用于主机与设备之间的命令/状态交互,例如读取设备描述符、设置配置、发送类特定命令等。
核心特性: 双向、可靠、有保证的传输,但带宽占用较小。控制传输总是由主机发起的 SETUP 阶段开始,随后是可选的数据阶段,最后是状态阶段。
3.1.1 控制传输的四个阶段
- SETUP 阶段: 主机向设备发送 8 字节的 USB 请求块 (USB Request Block, URB),包含请求类型、请求码、参数等信息。
- DATA 阶段(可选): 根据 SETUP 阶段的方向位,主机或设备传输数据。数据长度由 SETUP 阶段指定。
- STATUS 阶段: 用于确认数据阶段是否成功完成。方向与 DATA 阶段相反。
- 完成回调: 当 URB 完成或发生错误时,内核调用注册的回调函数通知驱动。
3.1.2 适用场景
- 设备枚举: 获取设备描述符、配置描述符、接口描述符等。
- 标准请求: 设置地址、设置配置、清除端点暂停等。
- 类特定命令: HID 报告描述符获取、大容量存储设备的 SCSI 命令封装。
- 厂商自定义命令: 固件升级、设备模式切换、寄存器读写。
注意: 控制传输的 DATA 阶段最大数据长度受端点 0 的 wMaxPacketSize 限制(通常为 8、16、32 或 64 字节)。如果需要传输大量数据,应使用批量传输或等时传输。
3.2 批量传输 (Bulk Transfer)
批量传输用于传输大量数据,但不保证固定的延迟。它利用 USB 总线空闲时的带宽,当总线繁忙时可能被延迟。批量传输具有硬件级别的 CRC 校验和重传机制,确保数据完整性。
核心特性: 非周期性、大容量、可靠传输。批量传输只在总线带宽空闲时进行,优先级低于中断传输和等时传输。
3.2.1 批量传输的 URB 编程要点
/* 批量传输 URB 初始化示例 */
struct urb *bulk_urb;
void *bulk_buffer;
dma_addr_t bulk_dma;
/* 1. 分配 URB */
bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!bulk_urb)
return -ENOMEM;
/* 2. 分配 DMA 缓冲区 */
bulk_buffer = usb_alloc_coherent(udev, BULK_BUFFER_SIZE,
GFP_KERNEL, &bulk_dma);
if (!bulk_buffer) {
usb_free_urb(bulk_urb);
return -ENOMEM;
}
/* 3. 填充 URB */
usb_fill_bulk_urb(bulk_urb, udev,
usb_rcvbulkpipe(udev, BULK_IN_EP),
bulk_buffer, BULK_BUFFER_SIZE,
bulk_completion_callback, NULL);
/* 4. 设置 DMA 句柄 */
bulk_urb->transfer_dma = bulk_dma;
bulk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* 5. 提交 URB */
ret = usb_submit_urb(bulk_urb, GFP_KERNEL);
3.2.2 适用场景
| 设备类型 | 典型应用 | 数据特点 |
|---|---|---|
| 大容量存储设备 (U盘、移动硬盘) | 读写数据块 | 数据量大,对延迟不敏感,要求 100% 正确 |
| USB 打印机 | 发送打印作业 | 数据量大,可容忍一定延迟 |
| USB 网络适配器 | 传输网络数据包 | 数据量大,依赖上层协议保证可靠性 |
| 数据采集卡 | 批量上传采样数据 | 数据量大,允许缓冲 |
3.3 中断传输 (Interrupt Transfer)
中断传输用于传输少量、周期性、对延迟敏感的数据。尽管名称包含“中断”,但 USB 中断传输实际上是主机轮询设备的过程,设备不能主动发起传输。主机根据端点描述符中的 bInterval 字段定期轮询设备。
核心特性: 保证最大延迟、有限数据量、可靠传输。中断传输的轮询间隔由端点描述符定义,范围从 1ms 到 255ms(全速/低速)或 125µs 到 4096ms(高速)。
3.3.1 中断传输的轮询机制
/* 中断传输 URB 初始化示例 */
struct urb *intr_urb;
void *intr_buffer;
intr_urb = usb_alloc_urb(0, GFP_KERNEL);
intr_buffer = kmalloc(INT_BUFFER_SIZE, GFP_KERNEL);
/* 填充中断 URB */
usb_fill_int_urb(intr_urb, udev,
usb_rcvintpipe(udev, INT_IN_EP),
intr_buffer, INT_BUFFER_SIZE,
intr_completion_callback, NULL,
interval); /* 轮询间隔,单位:ms (全速) 或 125µs 帧 (高速) */
/* 提交 URB,开始轮询 */
usb_submit_urb(intr_urb, GFP_KERNEL);
3.3.2 适用场景
- HID 设备: 键盘、鼠标、游戏手柄的输入报告。
- 人机交互设备: 触摸屏、手写板、条码扫描器。
- 物理量传感器: 温度传感器、加速度计、陀螺仪的数据读取。
- 设备状态通知: USB 集线器的端口状态变化、打印机状态反馈。
3.4 等时传输 (Isochronous Transfer)
等时传输用于传输实时性要求极高、允许少量数据丢失的流数据。它提供预分配的固定带宽,保证传输速率恒定,但不提供重传机制。等时传输没有握手阶段,数据一旦出错即被丢弃。
关键限制: 等时传输只在高速 USB 设备上广泛支持。低速设备不支持等时传输,全速设备支持但带宽有限。等时端点没有 STALL 和 NAK 机制。
3.4.1 等时传输的 URB 结构
/* 等时传输 URB 初始化示例 */
struct urb *iso_urb;
int packets_per_urb = 8; /* 每个 URB 包含多个等时包 */
iso_urb = usb_alloc_urb(packets_per_urb, GFP_KERNEL);
iso_urb->dev = udev;
iso_urb->pipe = usb_rcvisocpipe(udev, ISO_IN_EP);
iso_urb->transfer_buffer = iso_buffer;
iso_urb->transfer_buffer_length = ISO_BUFFER_SIZE;
iso_urb->complete = iso_completion_callback;
iso_urb->number_of_packets = packets_per_urb;
iso_urb->interval = 1; /* 每个微帧传输一次 */
/* 设置每个等时包的偏移和长度 */
for (i = 0; i < packets_per_urb; i++) {
iso_urb->iso_frame_desc[i].offset = i * ISO_PACKET_SIZE;
iso_urb->iso_frame_desc[i].length = ISO_PACKET_SIZE;
}
usb_submit_urb(iso_urb, GFP_KERNEL);
3.4.2 适用场景
| 设备类型 | 典型应用 | 数据特点 |
|---|---|---|
| USB 音频设备 (声卡、耳机、麦克风) | 音频流播放/录制 | 恒定速率,允许偶尔丢帧,延迟敏感 |
| USB 视频设备 (摄像头、采集卡) | 视频流传输 | 高带宽,恒定帧率,允许丢帧 |
| USB 麦克风阵列 | 多通道音频同步采集 | 多通道同步,严格时序要求 |
| USB 软件无线电 (SDR) | IQ 采样数据传输 | 连续流,高带宽,实时处理 |
3.5 四种传输类型对比总结
| 特性 | 控制传输 | 批量传输 | 中断传输 | 等时传输 |
|---|---|---|---|---|
| 传输方向 | 双向 (SETUP + DATA + STATUS) | 单向 (IN 或 OUT) | 单向 (IN 或 OUT) | 单向 (IN 或 OUT) |
| 数据可靠性 | 高 (CRC + 重传) | 高 (CRC + 重传) | 高 (CRC + 重传) | 低 (CRC 但不重传) |
| 延迟保证 | 无 | 无 | 有 (轮询间隔保证) | 有 (带宽预分配) |
| 带宽占用 | 低 (最多 64 字节/事务) | 高 (最多 512/1024 字节/事务) | 中 (最多 64/1024 字节/事务) | 高 (最多 1024 字节/事务) |
| 端点数量 | 至少 1 个 (端点 0) | 至少 1 个 | 至少 1 个 | 至少 1 个 |
| 硬件握手 | ACK/NAK/STALL | ACK/NAK/STALL | ACK/NAK/STALL | 无握手 |
| 典型用途 | 枚举、配置、命令 | 大容量数据存储 | HID、传感器、状态 | 音频、视频、流媒体 |
驱动开发建议: 在编写 USB 驱动时,首先阅读设备的数据手册,确定每个端点对应的传输类型。错误的传输类型选择会导致 URB 提交失败(错误码 -EINVAL 或 -EPIPE)。对于复合设备(如带音频和 HID 功能的摄像头),不同接口可能使用不同的传输类型,需要分别处理。