2. USB协议基础回顾:USB总线拓扑结构、USB传输类型、USB描述符体系
各位同学,咱们今天聊点基础但极其重要的东西。USB协议,说白了就是一套让设备跟主机“对话”的规矩。我做了这么多年驱动,发现很多问题其实都出在基础没打牢。你想想看,如果连USB怎么连的、数据怎么传的、设备怎么描述自己的都不清楚,那写出来的驱动大概率是跑不起来的。
好,咱们直接进入正题。
2.1 USB总线拓扑结构
USB的拓扑结构,其实就是一个“树形”结构。主机(Host)是根,下面挂Hub,Hub再挂设备或者下一级Hub。我刚开始接触USB时,总觉得这玩意儿跟网络很像,但后来发现区别很大——USB是主从结构,所有通信必须由主机发起。
核心要点:USB系统中只有一个主机,所有设备都是“从机”。设备不能主动发数据,只能等主机来问。
具体来说,拓扑结构分三层:
- 主机(Host):通常是PC、手机或嵌入式主控。它负责调度所有传输。
- Hub(集线器):用来扩展端口。一个USB口最多可以级联7层Hub。
- 设备(Device):就是咱们要驱动的那些玩意儿,比如声卡、麦克风、扬声器。
我记得有一次调试一个USB音频设备,死活枚举不过去。查了半天,发现是Hub级联太多,信号质量不行。嗯,这里要注意:实际项目中,级联超过3层就容易出问题,尤其是高速设备。
2.2 USB传输类型
USB定义了四种传输类型。每种类型都有自己的脾气。咱们做音频驱动,最关心的其实是同步传输和中断传输。但其他两种也得懂,不然枚举阶段就卡住了。
2.2.1 控制传输(Control Transfer)
这是USB的“官话”。所有设备必须支持。枚举阶段全靠它。控制传输的特点是:可靠,但慢。我习惯用它来读取描述符、配置设备。
- 用于:设备枚举、命令下发
- 特点:保证送达,有重试机制
- 带宽占用:最多10%
个人经验:控制传输的包长有限制。全速设备最大64字节,高速设备最大64字节。别想着一次传大数据。
2.2.2 批量传输(Bulk Transfer)
批量传输,说白了就是“尽力而为”。数据量大,但没带宽保证。打印机、U盘喜欢用这个。音频设备一般不用,因为延迟不可控。
- 用于:打印机、存储设备
- 特点:可靠,但延迟不确定
- 带宽:空闲时全占,忙时排队
2.2.3 中断传输(Interrupt Transfer)
名字叫“中断”,其实不是硬件中断。它是主机定期轮询设备,看有没有数据。我做过一个HID音频控制面板,就是用中断传输来传音量旋钮的状态。
- 用于:HID设备、音频控制端点
- 特点:保证延迟,但数据量小
- 轮询间隔:1ms~255ms可配
2.2.4 同步传输(Isochronous Transfer)
重点来了!音频设备的核心传输方式。同步传输不保证数据一定送到,但保证带宽和延迟。你想想看,音频数据晚到几毫秒,声音就卡了。所以USB音频几乎都用同步传输。
避坑指南:我曾经在一个项目里,同步传输的端点描述符配错了,导致音频数据一直有爆音。查了三天才发现是同步类型(Sync Type)设成了异步。记住:音频设备通常用自适应同步或异步同步。
- 用于:音频、视频流
- 特点:带宽保证,无重传
- 带宽:最高90%可用
| 传输类型 | 可靠性 | 带宽保证 | 延迟 | 典型应用 |
|---|---|---|---|---|
| 控制 | 高 | 无 | 高 | 枚举、配置 |
| 批量 | 高 | 无 | 不确定 | U盘、打印机 |
| 中断 | 中 | 有 | 低 | 鼠标、控制面板 |
| 同步 | 低 | 有 | 极低 | 音频、视频 |
2.3 USB描述符体系
描述符是什么?就是设备的“身份证”和“简历”。主机通过读取描述符,才知道你是什么设备、需要多少带宽、用什么协议。我见过不少新手,描述符写错了,设备死活枚举不过。
描述符是层级结构的。从大到小依次是:
- 设备描述符(Device Descriptor):最顶层,描述设备的基本信息,比如VID、PID、USB版本。
- 配置描述符(Configuration Descriptor):一个设备可以有多个配置,但同一时间只能激活一个。每个配置描述符下面挂接口。
- 接口描述符(Interface Descriptor):描述一个功能单元。比如音频设备可能有音频控制接口、音频流接口。
- 端点描述符(Endpoint Descriptor):描述数据传输的端点。音频设备至少有一个同步输出端点或输入端点。
- 字符串描述符(String Descriptor):可选的,提供人类可读的字符串,比如厂商名、产品名。
注意:描述符的顺序不能乱!主机枚举时是按固定顺序读取的。我曾经把接口描述符和端点描述符的顺序搞反了,结果主机直接报“描述符错误”。
咱们做音频驱动,最常打交道的是音频控制接口描述符(AC Interface)和音频流接口描述符(AS Interface)。这些是USB Audio Class标准定义的,后面章节会详细讲。
这里给个简单的设备描述符例子,大家感受一下:
// USB设备描述符示例
const uint8_t device_descriptor[] = {
0x12, // bLength: 18字节
0x01, // bDescriptorType: 设备描述符
0x00, 0x02, // bcdUSB: USB 2.0
0x00, // bDeviceClass: 由接口定义
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
0x40, // bMaxPacketSize0: 64字节
0x34, 0x12, // idVendor: 0x1234
0x56, 0x78, // idProduct: 0x7856
0x00, 0x01, // bcdDevice: 1.00
0x01, // iManufacturer: 字符串索引1
0x02, // iProduct: 字符串索引2
0x00, // iSerialNumber: 无序列号
0x01 // bNumConfigurations: 1个配置
};
我建议:刚开始写描述符时,先用USB分析仪抓一个标准设备的描述符看看。对着抄,再改。比自己从头写靠谱得多。
好了,USB协议基础就回顾到这里。这些内容虽然基础,但后面讲音频类特定描述符、同步传输调度时,全都要用上。下一章咱们直接进入USB Audio Class的核心——音频控制描述符和音频流描述符的详细解析。