USB描述符

USB描述符信息存储在USB设备中,在枚举过程中,USB主机会向USB设备发送GetDescriptor请求,USB设备在收到这个请求之后,会将USB描述符信息返回给USB主机,USB主机分析返回来的数据,判断出该设备是哪一种USB设备,建立相应的数据链接通道。那么USB描述符信息到底是一个什么样的数据呢,USB协议中有详细描述。

通用的USB描述符信息包括设备描述符、配置描述符、接口描述符和端点描述符,具体不同的USB设备还包括其它类型的描述符,例如,USB鼠标、键盘还包括HID描述符和报告描述符,还有可能包括字符串描述符,USB协议中对描述符类型定义如下:

所有的描述符信息都是通过发送GetDescriptor请求得到的,但是USB设备也不知道你要获取的是哪种描述符,所以还需要在GetDescriptor请求中指定描述符的类型以及描述符的长度,这样USB设备才能正确的返回描述符信息。

1 设备描述符

Linux中对于设备描述符结构体定义如下:

216 /* USB_DT_DEVICE: Device descriptor */
217 struct usb_device_descriptor {
218         __u8  bLength;
219         __u8  bDescriptorType;
220     
221         __le16 bcdUSB;
222         __u8  bDeviceClass;
223         __u8  bDeviceSubClass;
224         __u8  bDeviceProtocol;
225         __u8  bMaxPacketSize0;
226         __le16 idVendor;
227         __le16 idProduct;
228         __le16 bcdDevice;
229         __u8  iManufacturer;
230         __u8  iProduct;
231         __u8  iSerialNumber;
232         __u8  bNumConfigurations;
233 } __attribute__ ((packed));
234 
235 #define USB_DT_DEVICE_SIZE              18

bLength: 描述符的长度,设备描述符的长度为18个字节。

bDescriptorType: 描述符的类型,设备描述符的类型为0x01。

bcdUSB: USB设备所遵循的协议版本号,例如2.0协议为0x0200。

bDeviceClass: USB设备类代码,由USB-IF分配,如果该字段为0x00,表示由接口描述符来指定(有可能该USB设备是一个复合设备,USB设备的各个接口相互独立,分别属于不同的设备类)。如果是0x01~0xfe,表示为USB-IF定义的设备类,例如0x03为HID设备,0x09为HUB设备。如果是0xff,表示由厂商自定义设备类型。

bDeviceSubClass: USB子类代码,由USB-IF分配,如果bDeviceClass为0x00,那么该字段也必须为 0x00,其它情况可以参考USB关于对于USB Device Class的定义。

bDeviceProtocol: 协议代码,由USB-IF分配,如果bDeviceClass和bDeviceSubClass定义为0x00,那么该字段也必须为0x00。

bMaxPacketSize0: 端点0最大数据包长度,必须为8、16、32和64。

idVendor: 厂商ID,由USB-IF分配,需要向USB-IF组织申请。

idProduct: 产品ID,由厂商指定。

bcdDevice: 设备序列号,由厂商自行设置。

iManufacturer: 用于描述厂商的字符串描述符索引。

iProduct: 用于描述产品的字符串描述符索引。

iSerialNumber: 用于描述产品序列号的字符串描述符索引,注意,所有的字符串描述符是可选的,如果没有字符串描述符,指定这些索引为0x00。

bNumConfigurations:配置描述符数量。

例如,我的USB鼠标设备描述符信息如下:

从中可以看出该USB设备符合USB1.1协议,在设备描述中并没有指定该USB设备类型,端点0最大数据包长度为8个字节,也就是说一次还不能获取完全设备描述符,需要三次才能获取完全。再看bMaxPacketSize0在设备描述符中的偏移,刚好是第8个字节,也就是说传输一次就能知道端点0一次能够传输多长的数据,根据这个值才能判断出是否继续传输,来完整的获取描述符信息。该USB设备的idVendor为0x80ee,idProduct为0x0021,有一个配置等等信息。

2 配置描述符

一个USB设备只有一个USB设备描述符,可以有多个配置描述符,配置描述符定义如下:

265 /* USB_DT_CONFIG: Configuration descriptor information.
266  *
267  * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
268  * descriptor type is different.  Highspeed-capable devices can look
269  * different depending on what speed they're currently running.  Only
270  * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
271  * descriptors.
272  */
273 struct usb_config_descriptor {
274         __u8  bLength;
275         __u8  bDescriptorType;
276 
277         __le16 wTotalLength;
278         __u8  bNumInterfaces;
279         __u8  bConfigurationValue;
280         __u8  iConfiguration;
281         __u8  bmAttributes;
282         __u8  bMaxPower;
283 } __attribute__ ((packed));
284 
285 #define USB_DT_CONFIG_SIZE              9

bLength: 配置描述符长度,配置描述符长度为9字节大小。

bDescriptorType: 描述符类型,配置描述符类型为0x02。

wTotalLength: 配置描述符信息总的大小,包括接口描述符、端点描述符等等。

bNumInterfaces: USB接口数量。

bConfigurationValue: 当使用SetConfiguration和GetConfiguration请求时所指定的配置索引值。

iConfiguration: 描述配置的字符串描述符索引。

bmAttributes: 供电配置,位详细定义如下:

D7              保留,必须置1

D6              自供电模式

D5              远程唤醒

D4~D0      保留

bMaxPower: 最大功耗,以2mA为单位,例如0x32为50*2=100mA。

我的USB鼠标配置描述符信息如下:

从中可以看出该设备配置信息总大小为0x22=34字节大小,有一个接口,最大功耗为100mA等信息。

3 接口描述符

一个配置中可以有一个或多个接口,一个接口中有0个或多个端点,接口描述符和端点描述符不能直接通过GetDescriptor请求返回,必须连同配置描述符一起返回,Linux中接口描述符定义如下:

309 /* USB_DT_INTERFACE: Interface descriptor */
310 struct usb_interface_descriptor {
311         __u8  bLength;
312         __u8  bDescriptorType;
313 
314         __u8  bInterfaceNumber;
315         __u8  bAlternateSetting;
316         __u8  bNumEndpoints;
317         __u8  bInterfaceClass;
318         __u8  bInterfaceSubClass;
319         __u8  bInterfaceProtocol;
320         __u8  iInterface;
321 } __attribute__ ((packed));
322 
323 #define USB_DT_INTERFACE_SIZE           9

bLength: 描述符长度,接口描述符长度为9个字节。

bDescriptorType: 描述符类型,接口描述符的类型为0x04。

bInterfaceNumber: 该接口编号,接口编号从0开始分配,当一个配置有多个接口时,就用该字段来区分不同的接口。

bAlternateSetting:

bNumEndpoints:  端点数量,不包括端点0。

bInterfaceClass

bInterfaceSubClass

bInterfaceProtocol:  和设备描述符中的bDeviceClass、bDeviceSubClass、bDeviceProtocol类似。

iInterface: 描述该接口的字符串描述符索引。

接口描述符实例如下:

前面9个字节是配置描述符,从中可以看出端点数量为1,bInterfaceClass为0x03,即为HID设备。

4 端点描述符

注意,端点0没有端点描述符,Linux中端点描述符结构定义如下:

327 /* USB_DT_ENDPOINT: Endpoint descriptor */
328 struct usb_endpoint_descriptor {
329         __u8  bLength;
330         __u8  bDescriptorType;
331 
332         __u8  bEndpointAddress;
333         __u8  bmAttributes;
334         __le16 wMaxPacketSize;
335         __u8  bInterval;
336 
337         /* NOTE:  these two are _only_ in audio endpoints. */
338         /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
339         __u8  bRefresh;
340         __u8  bSynchAddress;
341 } __attribute__ ((packed));
342 
343 #define USB_DT_ENDPOINT_SIZE            7
344 #define USB_DT_ENDPOINT_AUDIO_SIZE      9       /* Audio extension */

bLength: 描述符长度,这里有两个值如果是audio设备的端点,那么端点描述符长度就为9个字节,对于其它设备端点,端点描述符长度就为7个字节。

bDescriptorType: 描述符类型,端点描述符类型为0x05。

bEndpointAddress: 端点地址,详细定义如下:

D7 端点方向

0                  OUT端点

1                  IN端点

D6~D4       保留

D3~D0       端点编号

bmAttributes: 端点类型,详细定义如下:

D5~D4 用途

00     数据端点

01     反馈端点

10     隐式反馈数据端点

11     保留

D3~D2 同步类型

00     非同步

01     异步

10     自适应

11     同步

D1~D0 传输类型

00     控制传输

01     同步传输

10     块传输

11     中断传输

如果该端点不是同步端点,D5~D2保留且必须置0。

wMaxPacketSize: 端点所支持最大数据包的长度,详细定义如下:

D10~D0 最大数据包长度

D12~D11

其余位保留且必须置0。

bInterval:端点数据传输的访问时间间隔。对于全速/低速的中断端点,取值范围为 1~255,对于高速中断端点,取值范围为1~16,详细定义可以参考USB协议。

端点描述符实例如下:

因为不能单独的获取接口和端点描述符,所以我将设备配置信息全获取下来了,端点描述符从0x07处开始,0x07为端点描述符长度,该端点是一个IN端点,端点地址为1,该端点是一个中断端点,最大数据包长度为6个字节,时间间隔为10ms。

5 HID描述符

从上图可以看出,除了配置描述符、接口描述符、端点描述符之外、还有一个描述符,它就是HID描述符,HID描述符专用于HID类设备。Linux关于HID描述符结构定义如下:

537 struct hid_class_descriptor {
538         __u8  bDescriptorType;
539         __le16 wDescriptorLength;
540 } __attribute__ ((packed));
541 
542 struct hid_descriptor {
543         __u8  bLength;
544         __u8  bDescriptorType;
545         __le16 bcdHID;
546         __u8  bCountryCode;
547         __u8  bNumDescriptors;
548 
549         struct hid_class_descriptor desc[1];
550 } __attribute__ ((packed));

bLength: 描述符长度。

bDescriptorType:描述符类型,HID描述符的类型为0x21。

bcdHID: 所遵循的HID协议版本。

bCountryCode: 国家代码。

bNumDescriptors: 下级描述符数量,通常至少需要一个报告描述符。

bDescriptorType: 下级描述符类型,例如报告描述符。

wDescriptorLength: 下级描述符长度。

从上面USB鼠标配置描述符中可以看出,该鼠标所遵循的HID协议版本为1.1,有一个HIDclass描述符,描述符类型为0x22,即报告描述符,描述符长度为0x46。

原文地址:http://blog.csdn.net/mcgrady_tracy/

USB描述符【整理】的更多相关文章

  1. USB描述符概述

    在USB总线接口协议中,规定了一些标准的USB描述符,如表所示. 对于USB设备来说,有些USB描述符是必需的,例如: 设备描述符 配置描述符 字符串描述符 接口描述符 端点描述符 其余一些描述符并非 ...

  2. USB 描述符

    标准的USB设备有5种USB描述符:设备描述符,配置描述符,字符串描述符,接口描述符,端点描述符. // Standard Device Descriptor typedef struct { u8 ...

  3. USB描述符解析-->枚举.

    枚举可以理解为主机按不定的顺序向USB设备讨要设备信息,好给它分配资源,若枚举不成功,就放弃分配资源,免得浪费资源.一般都是使用中断传输方式通信. 常用的描述符有以下几种:01H.设备描述符  02H ...

  4. usb描述符简述(二)

    title: usb描述符简述 tags: linux date: 2018/12/18/ 18:25:23 toc: true --- usb描述符简述 转载自cnblog 具体描述符 https: ...

  5. USB学习笔记连载(十二):USB描述符

    USB设备是端口,接口,配置的集合,USB协议是以各种USB描述符来表征USB设备的功能.计算机通过这些描述符来获得USB设备的功能. USB描述符包括: USB标准设备描述符,USB集线器描述符.H ...

  6. 2.6 USB摄像头驱动之USB描述符

    学习目标:分析USB摄像头驱动的描述符: 一.USB设备描述符 在usb设备驱动分析那一节,也用到了usb描述符. usb描述符可分为: USB设备描述符(usb_device_descriptor) ...

  7. USB描述符(转)

    //============================================================================// 文件名: USBDESC.C// 用 ...

  8. 自己总结的USB数据结构及其描述符

    背景: USB理论知识光看着空想总觉着丢三落四,好像哪里没法理解到位,自己做个总结. 正文: 1. USB通信的最基本单位是“包”.如果把“包”肢解的话,可以分为各种“域”(7类,即一串二进制数.每类 ...

  9. usb驱动开发7之接口描述符

    前面struct usb_interface里表示接口设置的struct usb_host_interface被有意的飘过了,咱们在这节主要讲讲这个结构体,同样在include/linux/usb.h ...

随机推荐

  1. 第204天:js---重载和多态

    一.根据arguments个数实现重载 js本身不支持重载,所以只能通过其他方式实现,arguments检测传参的个数,然后再执行不同的方式 function add() { var sum = 0 ...

  2. 当我们有多个类 继承同一个父类 这时候使用多态时候 可以使用该父类的类型做引用 不需要将object做引用

    当我们有多个类 继承同一个父类 这时候使用多态时候 可以使用该父类的类型做引用 不需要将object做引用

  3. web框架引入

    1. web请求的本质就是一个socket. 2.http:一次请求,一次响应,断开链接.如下程序:必须先运行服务器端,然后客户端才能去连接.所有web框架的本质就是如下: import socket ...

  4. [COCI2011-2012#5] POPLOCAVANJE 后缀自动机

    题面:洛谷 题解: 其实还可以用AC自动机做,但是没调出来,,,不知道发生了什么... AC自动机做法如下: 观察到如果我们对给定的每个串建AC自动机,那么直接拿大串在上面匹配,如果遇到了一个单词的终 ...

  5. SC命令(windows服务开启/禁用)

    原文链接地址:https://blog.csdn.net/cd520yy/article/details/30976131 sc.exe命令功能列表: 1.更改服务的启动状态(这是比较有用的一个功能) ...

  6. 20135239益西拉姆 Linux内核分析 操作系统是怎样工作的?

    益西拉姆+ 原创作品+ <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 堆栈 堆栈是C语言程序运行时 ...

  7. 传说中的 SonarLint

    Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量 通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy等等二十几种编程语言的 ...

  8. poj1204 Word Puzzles

    Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12090   Accepted: 4547   S ...

  9. Codeforces 526.D Om Nom and Necklace

    D. Om Nom and Necklace time limit per test 1 second memory limit per test 256 megabytes input standa ...

  10. MSA(微服务简介)

    1.为什么要使用微服务? 要说为什么要使用微服务,我们要先说下传统的企业架构模式-垂直架构/单块架构模式,简单点说:我们一般将系统分为三层架构,但是这是逻辑上的三层,而非物理上的三层,这就意味着经过编 ...