usb鼠标枚举过程深度解析(上)

转载自:

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

设备枚举过程:

1.         获取设备描述符

2.         复位

3.         设置地址

4.         再次获取设备描述符

5.         获取配置描述符

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

7.         获取字符串描述符

8.         选择设备配置

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

 

usb鼠标枚举过程深度解析(上)_第1张图片

 

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

 

usb鼠标枚举过程深度解析(上)_第2张图片

 

usb鼠标枚举过程深度解析(上)_第3张图片

Transfer0:

 usb鼠标枚举过程深度解析(上)_第4张图片

 

usb鼠标枚举过程深度解析(上)_第5张图片

从图中可以看出,Transfer0由5个Transaction构成。这里所说的USB主机是指USB主控制器。可以看出它是一个控制传输。Transaction0为SETUP Transaction,Transaction1~Transaction3是IN Transaction,Transaction4是OUT Transaction。

Transaction0:

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

struct usb_strlrequest{

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

       _u8 bRequest;        //请求类型

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

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

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

}_attribute_((packed)); 

Transaction1:

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

 usb鼠标枚举过程深度解析(上)_第6张图片

Transaction1~ Transaction3中的Data域得到的正好是这18个字节。Transaction1中的数据域0x12为bLength(描述符的长度),0x01为bDescriptorType(描述符的类型,USB_DT_DEVICE),0x0200为bcdUSB(USB spec的版本号),0x00为bDeviceClass,0x00为bDeviceSubClass,0x00为bDeviceProtocol,0x08为bMaxPacketSize0(端点0一次可以处理的最大字节数)。

Transaction2:

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

Transaction3:

Transaction3的Data域:0x00为iSerialNumber(序列号对应的字符串描述符的索引值),0x01为bNumConfigurations(设备当前速度模式下支持的配置数量)。

Transaction4:

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

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

Transfer1:

 usb鼠标枚举过程深度解析(上)_第7张图片

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

Transfer 2:

 usb鼠标枚举过程深度解析(上)_第8张图片

usb鼠标枚举过程深度解析(上)_第9张图片

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

你可能感兴趣的:(工作,linux,struct,table,产品)