zoukankan      html  css  js  c++  java
  • USB描述符【整理】

    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/

  • 相关阅读:
    AngularJs用户登录的一些处理
    百度地图api-查询周边
    Git常用命令整理
    AngularJs控制器运行前方法,操控导航栏隐藏
    AngularJs中,如何在数据加载完成后,执行Js脚本
    ZZ:Linux的chattr与lsattr命令详解
    ZZ:实战 SSH 端口转发
    Python 删除 恢复 Redshift
    [原创]Python 命令 恢复 删除 RDS
    AWS CLI 命令学习 之 bat 控制EC2 启停
  • 原文地址:https://www.cnblogs.com/Daniel-G/p/3993904.html
Copyright © 2011-2022 走看看