3. USB包结构与传输类型
USB 通信的最小数据单元是 包(Packet),多个包按照特定顺序组合成一次 传输(Transaction),而多个传输再构成更高层级的 传输类型(Transfer Type)。理解包结构与传输类型是分析 USB 枚举过程中复位、地址分配、描述符请求等环节的基础。
3.1 USB 包结构
USB 总线上的所有通信都以包为单位进行。每个包由固定的字段序列组成,并以同步序列(SYNC)开始、包结束(EOP)终止。根据功能不同,USB 包分为三大类:令牌包(Token Packet)、数据包(Data Packet) 和 握手包(Handshake Packet)。
3.1.1 令牌包(Token Packet)
令牌包由主机发出,用于标识一次传输的方向、类型和目标端点。它是每次传输的起始包。令牌包格式如下:
| 字段 | PID(8位) | ADDR(7位) | ENDP(4位) | CRC5(5位) |
|---|---|---|---|---|
| 说明 | 包标识符,指示令牌类型(IN、OUT、SETUP、SOF) | 目标设备地址(0~127) | 目标端点号(0~15) | 对 ADDR+ENDP 的校验 |
· 0x69(IN):主机请求从设备读取数据
· 0xE1(OUT):主机向设备发送数据
· 0x2D(SETUP):主机向设备发送控制请求(仅用于控制传输)
· 0xA5(SOF):帧起始包,用于同步和帧计数
3.1.2 数据包(Data Packet)
数据包紧跟在令牌包之后,承载实际传输的数据。数据包格式如下:
| 字段 | PID(8位) | DATA(0~1023字节) | CRC16(16位) |
|---|---|---|---|
| 说明 | 标识数据包类型(DATA0、DATA1、DATA2、MDATA) | 有效数据负载 | 对 DATA 字段的循环冗余校验 |
3.1.3 握手包(Handshake Packet)
握手包由接收方(设备或主机)发出,用于报告传输状态。握手包仅包含 8 位 PID,无数据字段。
| PID | 名称 | 含义 |
|---|---|---|
| 0x4B | ACK | 数据正确接收,传输成功 |
| 0x5A | NAK | 设备忙,暂时无法处理(非错误) |
| 0x1E | STALL | 端点被暂停或不支持该请求(错误条件) |
| 0x2E | NYET | (高速模式)设备尚未准备好接收下一数据 |
3.1.4 包结构关系图
3.2 USB 传输类型
USB 规范定义了四种传输类型,每种类型对应不同的应用场景和性能要求。在枚举过程中,主要使用控制传输,但理解其他传输类型有助于全面掌握 USB 通信机制。
3.2.1 控制传输(Control Transfer)
控制传输是 USB 枚举的核心传输类型,用于主机与设备之间的配置、状态查询和命令发送。它由两个或三个阶段组成:
- 建立阶段(Setup Stage):主机发送 SETUP 令牌包 + DATA0 数据包(8 字节标准请求),设备必须 ACK。
- 数据阶段(Data Stage):可选,根据请求方向传输数据(IN 或 OUT),使用 DATA0/DATA1 交替。
- 状态阶段(Status Stage):报告整个控制传输的完成状态,方向与数据阶段相反。
| 阶段 | 令牌包 | 数据包 | 握手包 | 说明 |
|---|---|---|---|---|
| 建立 | SETUP | DATA0(8字节) | ACK | 主机发送标准请求(如 Get_Descriptor) |
| 数据(IN) | IN | DATA1/DATA0 | ACK | 设备返回描述符数据 |
| 数据(OUT) | OUT | DATA1/DATA0 | ACK | 主机发送配置数据 |
| 状态 | IN 或 OUT | 无数据(零长度包) | ACK | 确认传输完成 |
3.2.2 批量传输(Bulk Transfer)
批量传输用于传输大量数据,没有带宽保证,但通过 CRC 和重试机制保证数据可靠性。适用于打印机、扫描仪、存储设备等。
- 特点:非实时、高可靠性、带宽占用灵活(空闲时全速传输)
- 包序列:令牌包(IN/OUT) + 数据包(DATA0/DATA1) + 握手包(ACK/NAK/STALL)
- 端点类型:批量端点(Bulk Endpoint)
3.2.3 中断传输(Interrupt Transfer)
中断传输用于传输小量数据,具有保证的轮询间隔(bInterval),适用于人机交互设备(HID)如键盘、鼠标。
- 特点:低延迟、保证轮询频率、数据量小(全速最大 64 字节,高速最大 1024 字节)
- 包序列:与批量传输相同,但主机保证在 bInterval 时间内轮询一次
- 端点类型:中断端点(Interrupt Endpoint)
3.2.4 同步传输(Isochronous Transfer)
同步传输用于传输实时数据流,如音频、视频。它保证带宽和传输时间,但不保证数据可靠性(无重试、无握手包)。
- 特点:实时性优先、固定带宽、无握手/重试、允许少量数据丢失
- 包序列:令牌包(IN/OUT) + 数据包(DATA0/DATA1/DATA2/MDATA) — 无握手包
- 端点类型:同步端点(Isochronous Endpoint)
3.2.5 四种传输类型对比
| 传输类型 | 可靠性 | 带宽保证 | 延迟 | 典型应用 | 枚举中使用 |
|---|---|---|---|---|---|
| 控制传输 | 高(重试+CRC) | 10%(全速) | 中等 | 枚举、配置、命令 | 是(端点0) |
| 批量传输 | 高(重试+CRC) | 无 | 可变 | 存储、打印 | 否 |
| 中断传输 | 高(重试+CRC) | 有(轮询间隔) | 低(保证) | 键盘、鼠标 | 否(枚举后) |
| 同步传输 | 低(无重试) | 有(固定带宽) | 低(固定) | 音频、视频 | 否 |
3.2.6 传输类型与包结构组合图
3.3 包结构与传输类型在枚举中的实际应用
在 USB 枚举过程中,主机和设备通过控制传输在端点 0 上交换数据。以下是一个典型的枚举请求包序列示例(获取设备描述符):
// 主机发送:SETUP 令牌包 + DATA0 数据包(8字节标准请求)
// 令牌包:PID=0x2D (SETUP), ADDR=0x00, ENDP=0x00
// 数据包:PID=0xC3 (DATA0), DATA=80 06 00 01 00 00 12 00
// (bmRequestType=0x80, bRequest=0x06, wValue=0x0100, wIndex=0x0000, wLength=0x0012)
// 设备回复:ACK 握手包
// 主机发送:IN 令牌包
// 令牌包:PID=0x69 (IN), ADDR=0x00, ENDP=0x00
// 设备回复:DATA1 数据包(18字节设备描述符)+ ACK 握手包
// 数据包:PID=0x4B (DATA1), DATA=12 01 00 02 00 00 00 40 ...
// 主机回复:ACK 握手包
// 状态阶段:主机发送 OUT 令牌包 + 零长度数据包
// 令牌包:PID=0xE1 (OUT), ADDR=0x00, ENDP=0x00
// 数据包:PID=0xC3 (DATA0), DATA=空
// 设备回复:ACK 握手包
· 地址 0 是枚举初期的默认地址,设备在收到 Set_Address 请求后才分配到唯一地址。
· DATA0 和 DATA1 交替使用,确保数据包不被重复处理。
· 每个控制传输都以状态阶段结束,用于确认整个传输的完整性。
3.4 本章小结
- USB 包分为令牌包、数据包、握手包三类,分别承担传输启动、数据承载和状态报告功能。
- 控制传输是枚举的核心,由建立、数据(可选)、状态三个阶段组成,使用端点 0。
- 批量传输保证可靠性,中断传输保证低延迟,同步传输保证实时性但不可靠。
- 枚举过程中主机通过控制传输发送标准请求(如 Get_Descriptor、Set_Address),设备通过 DATA0/DATA1 切换和 ACK/NAK/STALL 握手包进行响应。
- 理解包结构和传输类型是分析 USB 总线流量、调试枚举失败问题(如地址分配超时、描述符请求无响应)的基础。