用 wireshark 抓包分析学习 USB 协议
1 框架
上图是使用USB协议通信的两个设备的实现细节。看起来比较复杂,可以看下面的示意图:
整个框架分为三层:Function Layer、USB Device Layer 和 USB Bus Interface Layer;黑色双向箭头代表实际数据通路,浅色箭头代表逻辑连接。
平时我们使用 USB 协议的拓扑结构可能是下面这样的:
也就是一台电脑,挂着几个USB直连设备,比如鼠标键盘;由于USB口不够用,又接了几个 USB HUB,HUB上又挂着其它 USB 设备,比如话筒。
单从通信关系上看,可以理解成下面这样:
就是每一个设备都看作 Endpoint,Host 和 Device 之间的连接视作数据的Pipes,通信数据流通过 Pipes 在 Host 和 Endpoints 之间交换。
这里需要提前说明一下,USB是完全由 Master 主导的。也就是说,无论是从电脑向设备发数据,还是从设备从电脑发数据,都是由电脑控制的。
不过比起拓扑,软件人员可能更关心的是协议的格式,更进一步还想知道,究竟USB连接电脑之后,会发生些什么,这是这篇文章要记叙的主要内容。
2 USB 设备的状态流
这是 USB 设备的状态机。
Attached 指的就是设备已经连接到电脑的 USB 接口上;
设备进入 Powered 状态;
然后 master 让设备 reset,使设备进入 Default 状态;这时候设备使用默认地址
接着 master 会给设备分配一个地址;后续用这个地址和设备通信,也可以理解为换了一个专用的 pipe
master 会读设备的描述符,然后对设备做一些配置,设备进入Configured 状态
总线空闲一定时间之后设备会进入 Suspend 状态,以便省电;这和掉电不一样,设备的地址和配置不会丢失,唤醒之后不用重新分配地址和配置。
3 连接过程
这是 wireshark 工具抓 USB 数据包的界面,绿色框中的是发送数据包的源头,即发出方;红色框中的是数据包的接收方。
上图黄色箭头指向的那一行,是 host 向 设备 1.1.0 发送的一个 GET DESCRIPTOR Request;
上图右下框中绿色高亮的内容就是这个 request 的具体内容,数据格式可以对照下图中的表格:
第一个字节是 bmRequestType,用于描述请求的特性。 值为 0x80,意味着是标准设备,请求 device-to-host,即请求 device 向 host 发送数据
第二个字节是 bRequest,用于指明具体的请求,这里值是 6,对应着获取设备描述符 GET_DESCRIPTOR
因为协议文档是2.0的,和3.2的数据包不能完全对应,后面几个字段先不看了,等看3.2标准文档的时候再说。
紧接着有一个数据包,收发双方呼唤,应该就是 device 应答了 master 的请求。下面打开数据包可以看到回复了一个 device 描述符
避免歧义,这里说明一下,描述符有以下几种类型。Device 是其中的一种。
好,回到数据包的说明。这里有四个和CONFIGURATION相关的数据包。
先是 master 发了一个要求长度为 9 的
device 回了一个长度为 9 的,其中包含了一个长度信息 0x80
然后 master 发了一个要求长度 0x80 的
然后 device 回了一个长度为 0x80 的
最后 用 SET CONFIGURATION request 配置了 device