USB协议概述:版本演进、物理层、电气特性与传输类型
搞Android驱动的人,天天都要和USB打交道。不管是调试用的ADB,还是外接U盘、鼠标、键盘,底层全是这套协议在跑。我个人习惯把USB协议栈想象成一栋楼——物理层是地基,协议层是框架,驱动层是装修。地基没打好,楼上再漂亮也白搭。
所以第一章,我们先把这个地基摸清楚。别嫌基础,我在项目里见过太多人因为忽略了物理层细节,折腾好几天才发现是D+、D-线序反了,或者VBUS压降太大导致设备枚举失败。嗯,这些都是血泪教训。
1.1 USB版本演进:从1.0到4.0
先看版本演进,这张表基本能说明一切:
| 版本 | 发布年份 | 标称速率 | 编码方式 | 接口形态 |
|---|---|---|---|---|
| USB 1.0/1.1 | 1996/1998 | 1.5 Mbps (Low-Speed) 12 Mbps (Full-Speed) |
NRZI + 位填充 | Type-A/B |
| USB 2.0 | 2000 | 480 Mbps (Hi-Speed) | NRZI + 位填充 | Type-A/B/Micro |
| USB 3.0/3.1 | 2008/2013 | 5 Gbps (SuperSpeed) 10 Gbps (SuperSpeed+) |
8b/10b | Type-A/B/C |
| USB 3.2 | 2017 | 10/20 Gbps (双通道) | 128b/132b (Gen2×2) | Type-C |
| USB4 | 2019 | 40 Gbps | 基于Thunderbolt 3协议 | Type-C |
usb_device_speed 枚举,就是根据版本信息来填充的。我调试过一台机器,插USB 3.0设备却只在2.0模式下跑,查到最后是Type-C接口的CC逻辑没配置对——硬件上走了USB 2.0差分对,根本没连SS引脚。
这里有个容易踩的坑。很多人以为USB 3.0直接把速度提升了10倍那么简单。其实不是。USB 3.0引入了全新的物理层——它增加了一组独立的SSTX/SSRX差分对,和原有的D+/D-完全隔离。也就是说,USB 3.0的线缆里实际上跑着两套总线。
为什么会这样做?兼容性。你插一个USB 3.0 U盘到USB 2.0接口,它能降级用;反过来USB 2.0设备插到3.0接口,也用不了高速。这套机制在Android的OTG驱动里经常要处理,后面章节会细说。
1.2 物理层:信号传输的实物基础
USB的物理层就这么几件事:一对差分信号线(D+/D-)、一根VBUS供电线、一根GND。USB 3.0以上再加一组SuperSpeed差分对。
差分信号为什么好?说白了,抗干扰能力强。D+和D-线上的信号是反相的,外部噪声对两根线的影响差不多,接收端一相减,噪声就被抵消了。我在项目中遇到过焊接D+线虚焊的情况,结果USB设备能检测到插入,但无法完成枚举——因为差分信号幅度不对称,主机端收不到正确的包。
电气特性方面,几个关键参数:
- VBUS电压:标准值5V ±5%。OTG模式下Device可作为Host供电,至少提供5V/500mA。做手机USB充电侦测的时候,VBUS上的电压跳变直接影响状态机,不要只在软件层面想问题。
- 终端电阻:全速/低速设备在D+/D-上分别有1.5kΩ上拉电阻,主机端有15kΩ下拉电阻。这个阻值决定了主机能否检测到设备。我曾经在产线上遇到一批USB鼠标插上没反应,最后发现是上拉电阻焊成了10kΩ——阻值不对,电平判定失败。
- 信号电平:低速/全速下单端信号摆幅0~3.3V,差分信号要求至少0.2V的幅值差异。高速模式下要通过电流驱动,不是电压驱动。
1.3 传输类型:四种数据流动模式
USB协议定义了4种传输类型,每种解决的场景不同。我在Android USB驱动里基本都遇到过,来做一下对比:
| 传输类型 | 特点 | 典型应用 | 带宽保障 | 错误重传 |
|---|---|---|---|---|
| 控制传输 | 双向、可靠、低带宽 | 设备枚举、请求描述符、配置设备 | 10%(保留) | 硬件自动重传 |
| 批量传输 | 可靠、无带宽保证、数据量大 | U盘读写、ADB数据传输 | 尽力而为 | CRC + 自动重传 |
| 中断传输 | 可靠、有延迟保证、数据量小 | 鼠标、键盘、HID设备 | 90%以内可配 | CRC + 自动重传 |
| 实时传输 | 不可靠、有延迟保证、数据量大 | USB摄像头、音频流 | 按带宽预留 | 无重传(数据过期重传无意义) |
你想想看,U盘用批量传输,是因为它能容忍延迟但不能容忍数据错。摄像头用实时传输,是因为丢掉一帧画面还能接受,但如果等重传,画面就会卡住。这个设计理念在系统软件层面也是通用的。
控制传输是特殊的关键。任何USB设备接入后的第一件事,就是通过控制传输完成枚举。在Android中,USB Gadget驱动里处理设备枚举的代码可以说直接影响整个OTG功能的稳定性。
1.4 协议框架概览:一张图理清整体知识脉络
我把前面讲的版本、物理层、传输类型、以及后续会展开的协议层次、驱动栈结构,画成一张框架图。你先对全章的内容有个俯瞰视角:
- USB各版本之间物理层不兼容(2.0 vs 3.0),但协议层面通过枚举协商降级。在Android驱动的PHY配置里,经常需要同时处理这两种模式。
- 差分信号和终端电阻是硬件是否能被正确检测的关键。做OTG调试时,抓USB分析仪优先看D+/D-的电平是否产生正确的SE0和J/K状态。
- 控制传输是USB设备的命门。Android中Gadget驱动的
composite_bind()函数里,控制传输的端点0配置错一个参数,设备就上不了线。
这一章的内容算是开胃菜。你只要把版本差异、物理层参数、传输类型这三点记牢了,后面读USB框架驱动代码会顺畅很多。我在实际的Android OTG调试中,十之八九的问题都可以追溯到本章讲的某个细节——要么是终端电阻配置不对,要么是传输类型选错导致带宽不足。