USB鼠标枚举过程深入解析(上)

时间:2024-05-23 18:37:24

努力成为linux kernel hacker的人李万鹏原创作品,转载请标明出处

http://blog.****.net/woshixingaaa/archive/2011/05/02/6384419.aspx

设备枚举过程:

1. 获取设备描述符

2. 复位

3. 设置地址

4. 再次获取设备描述符

5. 获取配置描述符

6. 获取接口,端点描述符

7. 获取字符串描述符

8. 选择设备配置

下图是USB规范中规定的USB6种状态。通过设备枚举过程,USB可以进入Configured状态。

USB鼠标枚举过程深入解析(上)

这个是USB鼠标插入Linux系统的枚举过程的抓包图。

USB鼠标枚举过程深入解析(上)

USB鼠标枚举过程深入解析(上)

Transfer0

USB鼠标枚举过程深入解析(上)

USB鼠标枚举过程深入解析(上)

从图中可以看出,Transfer05Transaction构成。这里所说的USB主机是指USB主控制器。可以看出它是一个控制传输。Transaction0SETUP TransactionTransaction1Transaction3IN TransactionTransaction4OUT Transaction

Transaction0:

Packet 134是由host发向device,指明是SETUP包。SETUP包的作用是指明当前TransactionSETUP类型。Packet 134 ADDR域为0ENDP域为0,说明这次传输是在设备驱动里的缓冲区与地址为0的设备的端点0之间进行的。地址0是在主机给设备分配地址之前使用的默认地址,是不能分配给设备的,端点0是专门用于控制传输的端点,每个设备都必须有的。而且既是IN端点又是OUT端点,使用message管道。记住每个包必须由Sync字段开始。Packet 135是数据包,是从host发向device,现在来分析它的Data域。对应USB spec Table9-280代表请求的数据需要从device发向host06需要查看Table9-4,说明请求的类型是GET_DESCRIPTION01查看Table9-5,说明请求的描述符的类型是DEVICE的。Packet136device发向host的握手包,表示它接受到了这个请求。在Linux中,这个请求使用一个结构体来描述的——usb_ctrlrequest,对应这里的Packet135Data域。

struct usb_strlrequest{

_u8 bRequestType; //辅助的请求类型

_u8 bRequest; //请求类型

_le16 wValue; //请求的辅助数值

_le16 wIndex; //请求的辅助数值,通常用于计算索引或者偏移

_le16 wLength; //如果控制传输有数据阶段,在这里定义数据的大小

}_attribute_((packed));

Transaction1:

Transaction1是一个IN Transaction。首先hostdevice发送令牌包IN包,注意IN包中的ADDR域为0ENDP域为0Packet 138device发向hostDATA包,DATA的类型是DATA1DATA包分两种,DATA0DATA1,在USB的数据传输中,每个Transaction的数据包的类型需要反转data0,data1,data0,data……这样的顺序发送下去,以保证数据的完整性。所以这里是DATA1,上一个是DATA0。查看DATA包的Data域。查看一下这张表:

USB鼠标枚举过程深入解析(上)

Transaction1~ Transaction3中的Data域得到的正好是这18个字节。Transaction1中的数据域0x12bLength(描述符的长度),0x01bDescriptorType(描述符的类型,USB_DT_DEVICE),0x0200bcdUSBUSB spec的版本号),0x00bDeviceClass0x00bDeviceSubClass0x00bDeviceProtocol0x08bMaxPacketSize0(端点0一次可以处理的最大字节数)。

Transaction2:

Transaction2Data域:0x046DidVendor(厂商ID号),0xc018(产品的ID号),0x4301(设备的版本号),iManufacturer(厂商对应的字符串描述符的索引值),iProduct(产品对应的字符串描述符的索引值)。

Transaction3

Transaction3Data域:0x00iSerialNumber(***对应的字符串描述符的索引值),0x01bNumConfigurations(设备当前速度模式下支持的配置数量)。

Transaction4

首先发送一个OUT包,注意令牌包主要是指明传输类型,这里就为OUT类型。然后发一个大小为0DATA包,device回一个ACK握手包。本次传输结束。这是个控制传输过程,在控制传输中有3个阶段:setup阶段,数据阶段和状态阶段。Setup阶段指明了一次主机的请求类型,数据阶段为请求类型所需要传输的数据,最后的状态阶段用于表示一次控制传输的结束。

然后,hostdevice发送了一个Reset信号,由上边的状态图可以看出,USBpowered模式进入了default模式。

Transfer1

USB鼠标枚举过程深入解析(上)

通过bRequest可以看出这是一个SET_ADDRESS的过程,一共包含两个Transaction。注意这里的ADDR域和ENDP域都是0Packet275中的Data域,由于这是一个SETUP Transaction,所以这个域里放的是hostdevice的请求。05表示bRequestSET_ADDRESS,值为03,所以新地址为3。但是不会立即生效,需要等到这个请求的状态阶段完成地址更改才完成。Transaction6首先hostdevice发送一个IN类型令牌包,然后devicehost发送一个字节为0DATA包,host回复一个ACK握手包,这个结束。

Transfer 2

USB鼠标枚举过程深入解析(上)

USB鼠标枚举过程深入解析(上)

Transfer 2完成的是获得设备描述符。与Transaction0的不同是,这次有了明确的地址。第一次获得设备描述符主要为了得到端点0可以发送的数据的大小,所以只要一个Transaction18个字节数据就可。Transfer 2完成了整个设备描述符的读取工作。