usb协议分析-设备描述符配置包-描述符

/* usb协议分析仅供大家参考---设备描述符配置包,设备描述符, 地址设置, 配置描述符, 字符串描述符 */

/* -1- usb设备描述符配置包 */
typedef struct _USB_SETUP_PACKET
{
    REQUEST_TYPE bmRequestType;
    BYTE         bRequest;
    WORD_BYTE    wValue;
    WORD_BYTE    wIndex;
    WORD         wLength;
} USB_SETUP_PACKET;

1.bmRequestType 是包含有下面几方面的内容:
D7 D6 D5 D4 D3 D2 D1 D0
在这一个字节里,又按位分为:
D7位是表示后面传送数据的方向位。
当D7等于0时,表示后面的数据是从主控器发送到USB设备。在PC里,就是从PC机发送到USB的设备。
当D7等于1时,表示后面的数据是从USB设备发送到主控器。在PC里,就是从USB设备发送到USB设备。
在上次里,我收到并显示出来的数据是80,就表示从USB设备里发送数据给PC。在这里再次给出上一次的包数据:
80 06 00 01 00 00 40 00
这里的80,就是D7位为1。

D6-D5位是请求主分类型
0 是表示标准的请求。
1 是表示类别的请求。
2 是表示厂商的请求。
3 是保留。

D4-D0位是表求接收这个包的接口。
0 是表示USB设备接收。
1 是表示接口接收。
2 是表示端点接收。
3 是表示其它接收,不知道的。
4-31是保留。

2.bRequest 是本描述符的请求类型,也就是后面发送的数据是什么样的东西。
由于USB里有很多配置信息,比如获取设备描述符,又有设置USB地址等等,就是通过这个字节来区分的。
从USB协议里查找表9-4,就可看到如下的编码:
GET_STATUS                  0
CLEAR_FEATURE               1
Reserved for future use     2
SET_FEATURE                 3
Reserved for future use     4
SET_ADDRESS                 5
GET_DESCRIPTOR              6
SET_DESCRIPTOR              7
GET_CONFIGURATION           8
SET_CONFIGURATION           9
GET_INTERFACE               10
SET_INTERFACE               11
SYNCH_FRAME                 12
在上面的数据包里,看到它的内容是06,那么它就是GET_DESCRIPTOR类型。也就是主控器想读取USB设备的描述符,
到这里就已经分析出来的意思,就是主控器想读取USB描述符,但还不知道是什么描述符的内容。

3.wValue是根据不同的请求而设置不同的值。一般就是传送参数给设备标明这是什么请求。在上面GET_DESCRIPTOR获取设备描述符里,它的值是00 01。
在GET_DESCRIPTOR里这个字段的低字节表示描述符的索引,高字节表示描述符的类型。高字节的类型如下:
DEVICE                      1
CONFIGURATION               2
STRING                      3
INTERFACE                   4
ENDPOINT                    5
DEVICE_QUALIFIER            6
OTHER_SPEED_CONFIGURATION   7
INTERFACE_POWER1            8
wValue值在这里的高字节是01,那么它就是设备描述符了。低字节是00,那么它就是表示从偏移地址0开始读取设备描述符。
由于在配置描述符里有很多配置,所以低字节在那里就可以用来识别获取同样类型的描述符不同的配置。

4.wIndex是根据不同的请求而设置不同的值。一般用来说明端点号或者说明接口标识。在获取描述符里,设置为0,或者是语言ID。
在这个发送的描述符里,它是设置为00 00。

5.wLength是根据请求来决定下一阶段发送数据的长度。前面请求第一个字节里,已经说明下一阶段数据传送的方向,
这里说明了传送数据的长度。不管是发送数据,还是接收数据,都不要超过这个数据长度,否则主机会出问题,或者设备有问题。
在这个获取设备描述里,它的长度是40 00,按小端格式去解释,就是64个字节。

到这里,就把主控器发下来的数据解释完成了,知道去做什么的事情和回应。下一次就去分析怎么样返回设备描述符。

/* ------------------------------------------------------------------------------------------------ */

/* -2- 回应设备描述符 */
上一次已经介绍怎么样收到主控器的获取设备描述符的数据,这里就解释怎么样发送回应数据给主控器。
先从USB协议里找到标准设备的定义,我把它用C语言定义如下:
typedef struct _USB_DEVICE_DESCRIPTOR {
BYTE bLength;
BYTE bDescriptorType;
WORD bcdUSB;
BYTE bDeviceClass;
BYTE bDeviceSubClass;
BYTE bDeviceProtocol;
BYTE bMaxPacketSize0;
WORD idVendor;
WORD idProduct;
WORD bcdDevice;
BYTE iManufacturer;
BYTE iProduct;
BYTE iSerialNumber;
BYTE bNumConfigurations;
} USB_DEVICE_DESCRIPTOR;
返回给主控器的数据结构就是上面的内容,只要把上面的结构填写合适的内容,就可以发送回去给主控器。
在我的USB设备里,我把它填写如下的数据:
12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

看到这串数据是不明白是什么东西的,现在就来仔细地分析它的具体定义。下面就按着一个字段一个字段地分析它。
bLength是本结构的数据长度,这样可以方便以后兼容不同的版本协议。因为不同的结构是不同的长度,这样就可以区分不同的协议了。
比如有一天想添加一个字段,那么它的长度就会改变,这时就可以根据不同的长度进行解释不同的协议了。
这次返回的结构长度是0x12,也就是18个字节,它的长度是从bLength长度开始,也就是说是完全整个结构的长度。

bDescriptorType是描述符的类型。它的定义跟主控器发下来描述符的类型是一样的,如下:
DEVICE                      1
CONFIGURATION               2
STRING                      3
INTERFACE                   4
ENDPOINT                    5
DEVICE_QUALIFIER            6
OTHER_SPEED_CONFIGURATION   7
INTERFACE_POWER1            8
由于返回的是设备描述符,所以就选择了1,也就是包里显示的第二个字节01。用这个类型来区分不同的描述符。

bcdUSB是USB发布的协议版本。也就是本设备能适用于那种协议,目前USB主要有两个版本,一个是1.10,一个是2.10版本。
在本设备里,采用了1.10的协议版本。由于这个字段是采用BCD编码,所以1.10的表示为0x0110的格式,按小端格式输出来,就变成10 01的显示了。

bDeviceClass是设备分类。当它的值是0时,表示所有接口在配置描述符里,并且所有接口是独立的。
当它的值是1到FEH时,表示不同的接口关联的。当它的值是FFH时,它是厂商自己定义的。在这个设备里,是定义为0。

bDeviceSubClass是设备子分类码。当前面的bDeviceClass值是0时,这里一定要设置为0。其它就跟据USB-IF组织定义的编码。

bDeviceProtocol是设备使用的协议。如果使用USB-IF组织定义的协议,就需要设置这里的值。如果不使用,就直接设置为0。
如果厂商自己定义的可以设置为FFH。
以上三个值,在本设备里全部设置为0。

bMaxPacketSize0是端点0收发最大的包大小。仅允许设置8,16,32,64中的任何一个大小。在本设备里是设置为64个字节大小。所以看到这个字段是40 的大小。
12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

idVendor是厂商标识。由USB-IF分配的编码。在这里使用0x8000。

idProduct是厂商定义的产品标识。由厂家和产品标识,就可以让操作系统加载不同的驱动程序。如下:
12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

bcdDevice是用BCD表示的设备发布的版本号。这里是1.00。
12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

iManufacturer是厂商字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有厂商字符串。在
这里是0x04,就是从字符串描述符开始位置算起第4个字节位置读取字符串。

iProduct是产品字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有产品字符串。
在这里是0x2C,就是从字符串描述符开始位置算起第2C个字节位置读取字符串。

iSerialNumber是序列号字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有序列号字符串。
在这里是0x4A,就是从字符串描述符开始位置算起第4A个字节位置读取字符串。
所有字符串,都是采有UNICODE编码。

bNumConfigurations是配置描述符的个数。在这里只使用了一个配置,所以设置为1。

/* ------------------------------------------------------------------------------------------------ */

/* -3- 设置USB地址 */
前面已经解释主控器怎么样发送设备描述符下来,然后设备返回相应的设备描述符。下一步主控器的动作是做什么呢?
由于在USB总线上的设备有很多,为了区分不同的设备通讯,就需要给每个设备分配一个地址,这跟网络中的IP地址是一样的,或者跟MAC地址也是一样的。
因而,接着下来就是主控器分配地址给设备,USB的设备地址是从1开始到127。下面就是接收到主控器发下来的数据包:
00 05 01 00 00 00 00 00
由USB_SETUP_PACKET定义具体地分析这个数据,就可以知道应做什么样的响应了。下面就来解释这个操作。
先取得bmRequestType的类型,也就是第一个字节,它是00。从USB协议里查看,它的方向位是主控器发送给设备,
由D6D5位就知道它是USB协议里定义的标准请求,由D4-D0位知道它是USB设备接收这个包数据。
bRequest是05,从前面已经介绍的类型,就知道它是设置地址,如下:
SET_ADDRESS             5
所以这个包需要按设置地址的格式去解释后面的数据。

由于USB协议可以知道,USB的设备地址放在字段wValue里,因它的值是01 00,按小端格式解释就是0x0001了。
其它相应的字段wIndex和wLength应都是0,如果是其它非0的数据,是没有定义的。

USB的串行引擎通过这个地址来判断是否接收总线上的数据,如果发送的地址跟它一致,就会接收主控器发过来的数据,
当然从这个设备发送出去的数据也带有这个地址,因此就可以让主控器识别不同的USB设备数据了。

/* ------------------------------------------------------------------------------------------------ */

/* -4- 配置描述符 */
前面已经介绍设置USB的设备地址,接着下来是做什么呢?其实有了设备地址后,主控器还会再次发送获取上面已经读取的设备描述符下来,如下:
80 06 00 01 00 00 12 00
然后USB设备也再次回应它,但这次发送的长度是0x0012了,不再是第一次64个字节长度了。
接着USB设备就返回下面的描述符给主控器,也就是第一次已经发送的设备描述符,如下:
12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

这样分配地址之后,再次获取设备描述符成功了,接着下来就是主控器获取配置描述符。下面就是收到的配置描述符数据:
80 06 00 02 00 00 09 00
分析上面的数据如下:
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR         6
wValue是00 02。低字节表示偏移地址00,高字节表示描述符的类型。如下:
CONFIGURATION          2
所以这里的返回的设备描述符是配置描述符。
wIndex是00 00。
wLength是09 00。它表示返回描述符的长度。这里是9个字节。
接着下来,就是设备返回配置描述符给主控器,发送的数据如下:
09 02 22 00 01 01 00 01 32
发送的数据是按下面的结构来定义,这也是在USB协议里定义的格式。如下:
typedef struct _USB_CONFIGURATION_DESCRIPTOR {
BYTE bLength;
BYTE bDescriptorType;
WORD wTotalLength;
BYTE bNumInterfaces;
BYTE bConfigurationValue;
BYTE iConfiguration;
BYTE bmAttributes;
BYTE MaxPower;
} USB_CONFIGURATION_DESCRIPTOR;

bLength是配置的长度,也就是配置结构的整个长度。在这里9个字节。
bDescriptorType是描述符的类型,这里配置描述符,所以设置为02。
wTotalLength是所有配置设置的结构长度。包括配置描述符、接口描述符、HID或者其它描述符和端点描述符的长度。这里是22 00,也就是0x0022个字节。
bNumInterfaces是接口个数,这里一个。
bConfigurationValue是配置的个数,当设置配置时发送的值。这时设置为1个配置。
iConfiguration是说明配置的字符的偏移值。这里是0。
bmAttributes是配置特性,D7位保留。D6位是说明是否自供电。D5位是否支持远程唤醒。D4—D0是保留,设置为0。
MaxPower是使用的功率,它采用电流来表示。每2mA为单位,比如它的值是50时就表示是100mA的电流消耗。
通过这样说明,主控器就知道这个设备是什么样的设备,有多少功能。

/* ------------------------------------------------------------------------------------------------ */

/* -5- 字符串描述符 */
上一次说到把配置描述符返回给主控器那里了,现在接着下来,就会收到主控器发来字符串描述符。如果在设备描述符那里指定没有字符串描述的话,
在这里是不会收到字符串描述符的。由于我在设备描述符里指定有字符串描述符的偏移地址,因此,就收到主控器发出请求字符串描述符。收到的数据如下:
80 06 00 03 00 00 FF 00
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR         6
wValue是00 03。低字节表示偏移地址00,高字节表示描述符的类型,如下:
STRING                   3
wIndex是00 00。
wLength是FF 00。它表示返回描述符的长度。这里是256个字节。
因此,这个获取字符串描述符,就是从字符串描述内存里,0偏移地址开始的位置读取第一个字符串描述符返回给主控器。接着就返回下面的数据给主控器:
04 03 09 04
上面的数据是按字符串描述符来组织的,它的结构,我定义结构如下:
typedef struct _USB_STRING_DESCRIPTOR {
BYTE bLength;
BYTE bDescriptorType;
WORD bString/*[]*/;
} USB_STRING_DESCRIPTOR;

bLength是所有数据的长度。在这里是4。
bDescriptorType是描述类型,这里字符串描述符,所以它是3。
bString是可变的字符数组。不超过254个应都可以的,并且它是使用UNICODE编码的字符串。
在这里是09 04,这是美国英语的标识,0x0409。如果想输入中文的标识,只要改为0x0804就可以了。
通过这个字符串描述符,主控器就知道字符串描述符是使用什么语言说明的了,这样就可以支持全世界的语言标识。
时间: 2024-12-27 15:58:25

usb协议分析-设备描述符配置包-描述符的相关文章

USB协议分析

一.USB设备描述结构 1.逻辑组织结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口有零或多个端点. 每个USB设备都可以包含一个或多个配置,不同的配置使设备表现出不同的功能组合,配置由多个接口组成.在USB协议中,接口代表一个基本的功能,一个功能复杂的USB设备可以具有多个接口,而接口是端点的汇集. 一个USB播放器带有音频,视频功能,还有旋钮和按钮.配置1: 音频(接口)+旋钮(接口)配置2: 视频(接口)+旋钮(接

[国嵌攻略][162][USB协议分析]

USB设备逻辑结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点. USB设备描述符 当我们把USB设备(例如USB鼠标)插到我们的PC时,主机能够自动识别出我们的USB设备类型.在每一个USB设备内部,包含了固定格式的数据,通过这些数据,USB主机就可以获取USB设备的类型.生产厂商等信息.这些固定格式的数据,我们称之为USB描述符.标准设备有5种USB描述符:设备描述符.配置描述符.接口描述符.端点

关于Java Web应用中的配置部署描述符web.xml

一.web.xml概述 位于每个Web应用的WEB-INF路径下的web.xml文件被称为配置描述符,这个 web.xml文件对于Java Web应用十分重要,每个Java Web应用都必须包含一个web.xml文件,且必须放在WEB-INF路径下. 对于Java Web应用而言,WEB-INF是一个特殊的文件夹,Web容器会包含该文件夹下的内容,客户端浏览器无法访问WEB-INF路径下的任何内容.Java Web应用的绝大部分内容都由web.xml文件来配置管理.我们后面介绍的如下内容都要通过

ES5 数据属性描述符和存取描述符

一.数据属性描述符 对象是一个属性集合,对象的基本特征是属性名(name)和属性值(value).ES5 增加了属性描述符,可以更细腻的控制属性的不同操作.属性描述符有 configurable.writable 和 enumerable. 属性描述符通常和 Object.defineProperty/Object.defineProperties 一起使用来定义属性,它也会受到诸如 Object.freeze/Object.seal 等方法改变. 1. configurable 当且仅当 co

USB协议-USB的描述符及其之间的关系

USB只是一个总线,只提供一个数据通路而已.USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为.具体的一个设备实现什么功能,要由设备自己来决定.那么,USB主机是如何知道一个设备的功能以及行为呢?这就要通过描述符来实现了.描述符中记录了设备的类型.厂商ID和产品ID(通常依靠它们来加载对应的驱动程序).端点情况.版本号等众多信息. USB1.1协议定义的标准描述符有设备描述符(Device Descriptor).配置描述符(Configuration Descriptor).接口描述符

USB描述符【转载】

USB描述符 USB描述符信息存储在USB设备中,在枚举过程中,USB主机会向USB设备发送GetDescriptor请求,USB设备在收到这个请求之后,会将USB描述符信息返回给USB主机,USB主机分析返回来的数据,判断出该设备是哪一种USB设备,建立相应的数据链接通道.那么USB描述符信息到底是一个什么样的数据呢,USB协议中有详细描述. 通用的USB描述符信息包括设备描述符.配置描述符.接口描述符和端点描述符,具体不同的USB设备还包括其它类型的描述符,例如,USB鼠标.键盘还包括HID

转 关于USB HID报告描述符

原文地址 USB HID报告及报告描述符简介 在USB中,USBHOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报 告描述符(ReportDescriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符.USBHID设备是通过报告来给传送数据的,报告 有输入报告和输出报告.输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等:输出 报告是主机发送在

USB HID报告及报告描述符简介

在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符.        USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告.输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等:输出报告是主机发送给USB设备的,例如键盘上的数字

usb命令格式、描述符详解

一.USB命令 在USB规范里,对命令一词提供的单词为“Request”,但这里为了更好的理解主机与设备之间的主从关系,将它定义成“命令”. 所有的USB设备都要求对主机发给自己的控制命令作出响应,USB规范定义了11个标准命令,它们分别是:Clear_Feature. Get_Configuration.Get_Descriptor.Get_Interface.Get_Status.Set_Address. Set_Configuration.Set_Descriptor.Set_Interf