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. 查看apk包名和Activity名

    今天遇到一个bug,比较有意思. 情景: 测试一个钻石提现功能,条件是账户里必须有价值等于或者超过50美元的钻石,才允许提现,否则无法进行下一步. 测试步骤: 提现页面输入一个小于50美元的提现金额, ...

  2. AtCoder Regular Contest 074 瞎打记

    (很长时间没更新了>_<) 由于机房的网总是奥妙重重,开考30多分钟之后我才登进去... 然后发现T1是个简单枚举,1A.T2是个简单优先队列,1A.T3似乎需要一点推导,先看了T4发现是 ...

  3. P1939 【模板】矩阵加速(数列)

    题目描述 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1] (x>3) 求a数列的第n项对1000000007(10^9+7)取余的值. 输入输出格式 输入格式: 第一行一 ...

  4. ans menu list

    ans menu list 1. 系统配置 a) 基本设置 i. NTP ii. 配置模式 iii. 主机信息 b) 高可用性 i. 节点 ii. 路由监视器 iii. 故障转移接口群 c) 设备标识 ...

  5. TortoiseSVN 和 VisualSVN Server 使用教程

    TortoiseSVN 和 VisualSVN Server 使用教程 来源 https://blog.csdn.net/xgf415/article/details/75196360 目录: SVN ...

  6. XML 增加属性

    var resultDoc = new XmlDocument(); resultDoc.LoadXml("<root></root>"); resultD ...

  7. 【洛谷】CYJian的水题大赛【第二弹】解题报告

    点此进入比赛 T1: JerryC Loves Driving 第一题应该就是一道水分题(然而我只水了130分),我的主要做法就是暴力模拟,再做一些小小的优化(蠢得我自己都不想说了). My Code ...

  8. 【BZOJ2138】stone(线段树,Hall定理)

    [BZOJ2138]stone(线段树,Hall定理) 题面 BZOJ 题解 考虑一个暴力. 我们对于每堆石子和每个询问,显然是匹配的操作. 所以可以把石子拆成\(a_i\)个,询问点拆成\(K_i\ ...

  9. CF825F String Compression 解题报告

    CF825F String Compression 题意 给定一个串s,其中重复出现的子串可以压缩成 "数字+重复的子串" 的形式,数字算长度. 只重复一次的串也要压. 求压缩后的 ...

  10. Linux基础-正则表达式整理---------------grep、sed、awk

    目录:    Ⅰ:正则表达式    Ⅱ:作业 Ⅰ:正则表达式 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则. 在lin ...