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

/* -1- usb设备描述符配置包 */
typedef struct _USB_SETUP_PACKET
{
REQUEST_TYPE bmRequestType;
BYTE bRequest;
WORD_BYTE wValue;
WORD_BYTE wIndex;
WORD wLength;
} USB_SETUP_PACKET; .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,就是D7位为1。 D6-D5位是请求主分类型
是表示标准的请求。
是表示类别的请求。
是表示厂商的请求。
是保留。 D4-D0位是表求接收这个包的接口。
是表示USB设备接收。
是表示接口接收。
是表示端点接收。
是表示其它接收,不知道的。
-31是保留。 .bRequest 是本描述符的请求类型,也就是后面发送的数据是什么样的东西。
由于USB里有很多配置信息,比如获取设备描述符,又有设置USB地址等等,就是通过这个字节来区分的。
从USB协议里查找表9-,就可看到如下的编码:
GET_STATUS
CLEAR_FEATURE
Reserved for future use
SET_FEATURE
Reserved for future use
SET_ADDRESS
GET_DESCRIPTOR
SET_DESCRIPTOR
GET_CONFIGURATION
SET_CONFIGURATION
GET_INTERFACE
SET_INTERFACE
SYNCH_FRAME
在上面的数据包里,看到它的内容是06,那么它就是GET_DESCRIPTOR类型。也就是主控器想读取USB设备的描述符,
到这里就已经分析出来的意思,就是主控器想读取USB描述符,但还不知道是什么描述符的内容。 .wValue是根据不同的请求而设置不同的值。一般就是传送参数给设备标明这是什么请求。在上面GET_DESCRIPTOR获取设备描述符里,它的值是00 。
在GET_DESCRIPTOR里这个字段的低字节表示描述符的索引,高字节表示描述符的类型。高字节的类型如下:
DEVICE
CONFIGURATION
STRING
INTERFACE
ENDPOINT
DEVICE_QUALIFIER
OTHER_SPEED_CONFIGURATION
INTERFACE_POWER1
wValue值在这里的高字节是01,那么它就是设备描述符了。低字节是00,那么它就是表示从偏移地址0开始读取设备描述符。
由于在配置描述符里有很多配置,所以低字节在那里就可以用来识别获取同样类型的描述符不同的配置。 .wIndex是根据不同的请求而设置不同的值。一般用来说明端点号或者说明接口标识。在获取描述符里,设置为0,或者是语言ID。
在这个发送的描述符里,它是设置为00 。 .wLength是根据请求来决定下一阶段发送数据的长度。前面请求第一个字节里,已经说明下一阶段数据传送的方向,
这里说明了传送数据的长度。不管是发送数据,还是接收数据,都不要超过这个数据长度,否则主机会出问题,或者设备有问题。
在这个获取设备描述里,它的长度是40 ,按小端格式去解释,就是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设备里,我把它填写如下的数据:
2C 4A 看到这串数据是不明白是什么东西的,现在就来仔细地分析它的具体定义。下面就按着一个字段一个字段地分析它。
bLength是本结构的数据长度,这样可以方便以后兼容不同的版本协议。因为不同的结构是不同的长度,这样就可以区分不同的协议了。
比如有一天想添加一个字段,那么它的长度就会改变,这时就可以根据不同的长度进行解释不同的协议了。
这次返回的结构长度是0x12,也就是18个字节,它的长度是从bLength长度开始,也就是说是完全整个结构的长度。 bDescriptorType是描述符的类型。它的定义跟主控器发下来描述符的类型是一样的,如下:
DEVICE
CONFIGURATION
STRING
INTERFACE
ENDPOINT
DEVICE_QUALIFIER
OTHER_SPEED_CONFIGURATION
INTERFACE_POWER1
由于返回的是设备描述符,所以就选择了1,也就是包里显示的第二个字节01。用这个类型来区分不同的描述符。 bcdUSB是USB发布的协议版本。也就是本设备能适用于那种协议,目前USB主要有两个版本,一个是1.,一个是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,,,64中的任何一个大小。在本设备里是设置为64个字节大小。所以看到这个字段是40 的大小。
2C 4A idVendor是厂商标识。由USB-IF分配的编码。在这里使用0x8000。 idProduct是厂商定义的产品标识。由厂家和产品标识,就可以让操作系统加载不同的驱动程序。如下:
2C 4A bcdDevice是用BCD表示的设备发布的版本号。这里是1.。
2C 4A iManufacturer是厂商字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有厂商字符串。在
这里是0x04,就是从字符串描述符开始位置算起第4个字节位置读取字符串。 iProduct是产品字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有产品字符串。
在这里是0x2C,就是从字符串描述符开始位置算起第2C个字节位置读取字符串。 iSerialNumber是序列号字符串的偏移值。这值主要说明了它在字符串描述符里的偏移位置。如果它设置为0,表示没有序列号字符串。
在这里是0x4A,就是从字符串描述符开始位置算起第4A个字节位置读取字符串。
所有字符串,都是采有UNICODE编码。 bNumConfigurations是配置描述符的个数。在这里只使用了一个配置,所以设置为1。 /* ------------------------------------------------------------------------------------------------ */ /* -3- 设置USB地址 */
前面已经解释主控器怎么样发送设备描述符下来,然后设备返回相应的设备描述符。下一步主控器的动作是做什么呢?
由于在USB总线上的设备有很多,为了区分不同的设备通讯,就需要给每个设备分配一个地址,这跟网络中的IP地址是一样的,或者跟MAC地址也是一样的。
因而,接着下来就是主控器分配地址给设备,USB的设备地址是从1开始到127。下面就是接收到主控器发下来的数据包: 由USB_SETUP_PACKET定义具体地分析这个数据,就可以知道应做什么样的响应了。下面就来解释这个操作。
先取得bmRequestType的类型,也就是第一个字节,它是00。从USB协议里查看,它的方向位是主控器发送给设备,
由D6D5位就知道它是USB协议里定义的标准请求,由D4-D0位知道它是USB设备接收这个包数据。
bRequest是05,从前面已经介绍的类型,就知道它是设置地址,如下:
SET_ADDRESS
所以这个包需要按设置地址的格式去解释后面的数据。 由于USB协议可以知道,USB的设备地址放在字段wValue里,因它的值是01 ,按小端格式解释就是0x0001了。
其它相应的字段wIndex和wLength应都是0,如果是其它非0的数据,是没有定义的。 USB的串行引擎通过这个地址来判断是否接收总线上的数据,如果发送的地址跟它一致,就会接收主控器发过来的数据,
当然从这个设备发送出去的数据也带有这个地址,因此就可以让主控器识别不同的USB设备数据了。 /* ------------------------------------------------------------------------------------------------ */ /* -4- 配置描述符 */
前面已经介绍设置USB的设备地址,接着下来是做什么呢?其实有了设备地址后,主控器还会再次发送获取上面已经读取的设备描述符下来,如下: 然后USB设备也再次回应它,但这次发送的长度是0x0012了,不再是第一次64个字节长度了。
接着USB设备就返回下面的描述符给主控器,也就是第一次已经发送的设备描述符,如下:
2C 4A 这样分配地址之后,再次获取设备描述符成功了,接着下来就是主控器获取配置描述符。下面就是收到的配置描述符数据: 分析上面的数据如下:
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR
wValue是00 。低字节表示偏移地址00,高字节表示描述符的类型。如下:
CONFIGURATION
所以这里的返回的设备描述符是配置描述符。
wIndex是00 。
wLength是09 。它表示返回描述符的长度。这里是9个字节。
接着下来,就是设备返回配置描述符给主控器,发送的数据如下: 发送的数据是按下面的结构来定义,这也是在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 ,也就是0x0022个字节。
bNumInterfaces是接口个数,这里一个。
bConfigurationValue是配置的个数,当设置配置时发送的值。这时设置为1个配置。
iConfiguration是说明配置的字符的偏移值。这里是0。
bmAttributes是配置特性,D7位保留。D6位是说明是否自供电。D5位是否支持远程唤醒。D4—D0是保留,设置为0。
MaxPower是使用的功率,它采用电流来表示。每2mA为单位,比如它的值是50时就表示是100mA的电流消耗。
通过这样说明,主控器就知道这个设备是什么样的设备,有多少功能。 /* ------------------------------------------------------------------------------------------------ */ /* -5- 字符串描述符 */
上一次说到把配置描述符返回给主控器那里了,现在接着下来,就会收到主控器发来字符串描述符。如果在设备描述符那里指定没有字符串描述的话,
在这里是不会收到字符串描述符的。由于我在设备描述符里指定有字符串描述符的偏移地址,因此,就收到主控器发出请求字符串描述符。收到的数据如下:
FF
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR
wValue是00 。低字节表示偏移地址00,高字节表示描述符的类型,如下:
STRING
wIndex是00 。
wLength是FF 。它表示返回描述符的长度。这里是256个字节。
因此,这个获取字符串描述符,就是从字符串描述内存里,0偏移地址开始的位置读取第一个字符串描述符返回给主控器。接着就返回下面的数据给主控器: 上面的数据是按字符串描述符来组织的,它的结构,我定义结构如下:
typedef struct _USB_STRING_DESCRIPTOR {
BYTE bLength;
BYTE bDescriptorType;
WORD bString/*[]*/;
} USB_STRING_DESCRIPTOR; bLength是所有数据的长度。在这里是4。
bDescriptorType是描述类型,这里字符串描述符,所以它是3。
bString是可变的字符数组。不超过254个应都可以的,并且它是使用UNICODE编码的字符串。
在这里是09 ,这是美国英语的标识,0x0409。如果想输入中文的标识,只要改为0x0804就可以了。
通过这个字符串描述符,主控器就知道字符串描述符是使用什么语言说明的了,这样就可以支持全世界的语言标识。

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

  1. STM32 USB设备描述符、配置描述符、端点描述符含义

    查了一整天的资料,自己把不懂的全部试了一遍 一下是程序以及注释 /* USB设备描述符*/ const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ ...

  2. USB协议分析

    一.USB设备描述结构 1.逻辑组织结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口有零或多个端点. 每个USB设备都可以包 ...

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

    USB设备逻辑结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点. USB设备描述符 当我们把USB设备( ...

  4. (转)USB的描述符及各种描述符之间的依赖关系

    全文链接:http://justmei.blog.163.com/blog/static/11609985320102421659260/?latestBlog 1 推荐 [原创] USB入门系列之七 ...

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

    一.web.xml概述 位于每个Web应用的WEB-INF路径下的web.xml文件被称为配置描述符,这个 web.xml文件对于Java Web应用十分重要,每个Java Web应用都必须包含一个w ...

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

    一.数据属性描述符 对象是一个属性集合,对象的基本特征是属性名(name)和属性值(value).ES5 增加了属性描述符,可以更细腻的控制属性的不同操作.属性描述符有 configurable.wr ...

  7. usb驱动开发8之配置描述符

    前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),下面是看配置描述符还是看设备描述符呢??我们知道,设备大于配置,配置大于接口,接口可以有多种设置. 我 ...

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

    USB只是一个总线,只提供一个数据通路而已.USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为.具体的一个设备实现什么功能,要由设备自己来决定.那么,USB主机是如何知道一个设备的功能以及行为 ...

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

    在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID ...

随机推荐

  1. Windows窗体应用程序(非Console)使用libuv实现简单的异步WEB服务器

    libuv是一个很强大的异步处理框架(严格意义上不能叫框架,其实就是一组异步函数库,当然框架这东西有各种各样的定义和理解_^...),最初的的目的是用于NODEJS的异步处理,不过因为它是一个独立的项 ...

  2. C/C++求职宝典21个重点笔记

    转:http://blog.csdn.net/lanxuezaipiao/article/details/41557307 char c = '\72'; 中的\72代表一个字符,72是八进制数,代表 ...

  3. Using sql azure for Elmah

    The MSDN docs contain the list of T-SQL that is either partially supported or not supported.  For ex ...

  4. ASP.NET MVC 如何在一个同步方法(非async)方法中等待async方法

    问题 首先,在ASP.NET MVC 环境下对async返回的Task执行Wait()会导致线程死锁.例: public ActionResult Asv2() { //dead lock var t ...

  5. BitMap排序

    问题描述:       BitMap排序思想:             用1bit位标记某个元素对应的值       优点:             效率高,不允许进行比较和移位            ...

  6. Java 查询URL对应IP地址

    /** * @ClassName TestSocket1 * @Version 1.0 * @Date 2014-9-26 上午10:19:36 */ public class TestSocket1 ...

  7. iOS开发之runtime的运用-获取当前网络状态

    之前写过runtime的一些东西,这次通过runtime获取一些苹果官方不想让你拿到的东西,比如,状态栏内部的控件属性.本文将通过runtime带你一步步拿到状态栏中显示网络状态的控件,然后通过监测该 ...

  8. 2014年全球SEO行业调查报告

    前言: 1.该调查报告是MOZ每两年一度针对SEO行业的数据分析报告. 2.随着SEO的进化,该报告已不仅仅是SEO行业,今年的调查数据更多分析网络营销行业,可以称作"网络营销行业调查报告& ...

  9. 科学家有了钱以后,真是挺吓人的——D.E.Shaw的牛逼人生

    科学家有了钱以后,真是挺吓人的——D.E.Shaw的牛逼人生 黑科技,还是要提D.E.Shaw Research这个奇异的存在. 要讲这个黑科技,我们可能要扯远一点,先讲讲D.E. Shaw这个人是怎 ...

  10. 用CSS3制作的旋转六面体动画

    这是用CSS3制作的旋转的六面体 请用火狐或谷歌浏览器预览,有些旋转角度做的不够好,请大神指教 top bottom left right front back