本文转载自:

USB是个通用的总线,端口都是统一的。但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的设备的呢?这就要依赖于描述符了。USB的描述符主要有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,HID描述符,报告描述符等等。关于报告描述符,请看我以前写的:《USB HID报告及报告描述符简介 》 http://group.ednchina.com/93/198.aspx一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。 

每种描述符都有自己独立的编号,如下:
#define DEVICE_DESCRIPTOR               0x01  //设备描述符
#define CONFIGURATION_DESCRIPTOR        0x02  //配置描述符
#define STRING_DESCRIPTOR               0x03  //字符串描述符
#define INTERFACE_DESCRIPTOR            0x04  //接口描述符
#define ENDPOINT_DESCRIPTOR             0x05  //端点描述符
    
下面分别详细介绍一下各描述符。

1.设备描述符

//定义标准的设备描述符结构

typedef struct _DEVICE_DCESCRIPTOR_STRUCT
{
 BYTE blength;                               //设备描述符的字节数大小
 BYTE bDescriptorType;                      //设备描述符类型编号
 WORD bcdUSB;                                //USB版本号
 BYTE bDeviceClass;                          //USB分配的设备类代码
 BYTE bDeviceSubClass;                       //USB分配的子类代码
 BYTE bDeviceProtocol;                       //USB分配的设备协议代码
 BYTE bMaxPacketSize0;                       //端点0的最大包大小
 WORD idVendor;                              //厂商编号
 WORD idProduct;                             //产品编号
 WORD bcdDevice;                             //设备出厂编号
 BYTE iManufacturer;                         //设备厂商字符串的索引
 BYTE iProduct;                              //描述产品字符串的索引
 BYTE iSerialNumber;                         //描述设备序列号字符串的索引
 BYTE bNumConfigurations;                    //可能的配置数量
}
DEVICE_DESCRIPTOR_STRUCT, * pDEVICE_DESCRIPTOR_STRUCT;

//实际的设备描述符示例
code DEVICE_DESCRIPTOR_STRUCT device_descriptor=   //设备描述符
{
 sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小,这里是18字节
 DEVICE_DESCRIPTOR,                              //设备描述符类型编号,设备描述符是01
 0x1001,   //USB版本号,这里是USB01.10,即USB1.1。由于51是大端模式,所以高低字节交换
 0x00,                                 //USB分配的设备类代码,0表示类型在接口描述符中定义
 0x00,                                 //USB分配的子类代码,上面一项为0时,本项也要设置为0
 0x00,                                //USB分配的设备协议代码,上面一项为0时,本项也要设置为0
 0x10,                                //端点0的最大包大小,这里为16字节
 0x7104,                             //厂商编号,这个是需要跟USB组织申请的ID号,表示厂商代号。
 0xf0ff,        //该产品的编号,跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序
 0x0100,       //设备出厂编号
 0x01,        //设备厂商字符串的索引,在获取字符串描述符时,使用该索引号来识别不同的字符串
 0x02,        //描述产品字符串的索引,同上
 0x03,         //描述设备序列号字符串的索引,同上
 0x01                        //可能的配置数为1,即该设备只有一个配置
};

2.配置描述符

//定义标准的配置描述符结构

typedef struct _CONFIGURATION_DESCRIPTOR_STRUCT
{
 BYTE bLength;                               //配置描述符的字节数大小
 BYTE bDescriptorType;                       //配置描述符类型编号
 WORD wTotalLength;                          //此配置返回的所有数据大小
 BYTE bNumInterfaces;                        //此配置所支持的接口数量
 BYTE bConfigurationValue;                   //Set_Configuration命令所需要的参数值
 BYTE iConfiguration;                        //描述该配置的字符串的索引值
 BYTE bmAttributes;                          //供电模式的选择
 BYTE MaxPower;                              //设备从总线提取的最大电流
}
CONFIGURATION_DESCRIPTOR_STRUCT, * pCONFIGURATION_DESCRIPTOR_STRUCT;

2.接口描述符

//定义标准的接口描述符结构

typedef struct _INTERFACE_DESCRIPTOR_STRUCT
{
 BYTE bLength;                               //接口描述符的字节数大小
 BYTE bDescriptorType;                       //接口描述符的类型编号
 BYTE bInterfaceNumber;                      //该接口的编号
 BYTE bAlternateSetting;                     //备用的接口描述符编号
 BYTE bNumEndpoints;                         //该接口使用的端点数,不包括端点0
 BYTE bInterfaceClass;                       //接口类型
 BYTE bInterfaceSubClass;                    //接口子类型
 BYTE bInterfaceProtocol;                    //接口遵循的协议
 BYTE iInterface;                            //描述该接口的字符串索引值
}
INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT;

4.端点描述符

//定义标准的端点描述符结构

typedef struct _ENDPOINT_DESCRIPTOR_STRUCT
{
 BYTE bLegth;                                //端点描述符字节数大小
 BYTE bDescriptorType;                       //端点描述符类型编号
 BYTE bEndpointAddress;                      //端点地址及输入输出属性
 BYTE bmAttributes;                          //端点的传输类型属性
 WORD wMaxPacketSize;                        //端点收、发的最大包大小
 BYTE bInterval;                             //主机查询端点的时间间隔
}
ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT;

下面是一个配置描述符集合的定义
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
 CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
 INTERFACE_DESCRIPTOR_STRUCT  interface_descritor;
 ENDPOINT_DESCRIPTOR_STRUCT  endpoint_descriptor[ENDPOINT_NUMBER];
}CON_INT_ENDP_DESCRIPTOR_STRUCT;

配置描述符集合的示例

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor=  //配置描述符集合
{
//configuration_descriptor                     //配置描述符
{
 sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),      //配置描述符的字节数大小,这里为9
 CONFIGURATION_DESCRIPTOR,                     //配置描述符类型编号,配置描述符为2
 (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+
 sizeof(INTERFACE_DESCRIPTOR_STRUCT)+
 sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+
 (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+
 sizeof(INTERFACE_DESCRIPTOR_STRUCT)+
 sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256,   //配置描述符集合的总大小
 0x01,                                  //只包含一个接口
 0x01,                                  //该配置的编号
 0x00,                                  //iConfiguration字段
 0x80,                                  //采用总线供电,不支持远程唤醒
 0xC8                                   //从总线获取最大电流400mA
},
//interface_descritor                   //接口描述符
{
 sizeof(INTERFACE_DESCRIPTOR_STRUCT),   //接口描述符的字节数大小,这里为9
 INTERFACE_DESCRIPTOR,                  //接口描述符类型编号,接口描述符为3
 0x00,                                  //接口编号为4
 0x00,                                  //该接口描述符的编号为0
 ENDPOINT_NUMBER,                       //非0端点数量为2,只使用端点主端点输入和输出
 0x08,                                  //定义为USB大容量存储设备
 0x06,                                  //使用的子类,为简化块命令
 0x50,                                  //使用的协议,这里使用单批量传输协议
 0x00                                   //接口描述符字符串索引,为0,表示没有字符串
},

//endpoint_descriptor[]
{
 {                                     //主端点输入描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),  //端点描述符的字节数大小,这里为7
  ENDPOINT_DESCRIPTOR,                 //端点描述符类型编号,端点描述符为5
  MAIN_POINT_IN,                       //端点号,主输入端点
  ENDPOINT_TYPE_BULK,                  //使用的传输类型,批量传输
  0x4000,                              //该端点支持的最大包尺寸,64字节
  0x00                                 //中断扫描时间,对批量传输无效
 },
  
 {                                     //主端点输出描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),  //端点描述符的字节数大小,这里为7
  ENDPOINT_DESCRIPTOR,                 //端点描述符类型编号,端点描述符为5
  MAIN_POINT_OUT,                      //端点号,主输出端点
  ENDPOINT_TYPE_BULK,                  //使用的传输类型,批量传输
  0x4000,                              //该端点支持的最大包尺寸,64字节
  0x00                                 //中断扫描时间,对批量传输无效
 }
}
};

其中关于端点的类型定义如下
//定义的端点类型
#define ENDPOINT_TYPE_CONTROL           0x00  //控制传输
#define ENDPOINT_TYPE_ISOCHRONOUS       0x01  //同步传输
#define ENDPOINT_TYPE_BULK              0x02  //批量传输
#define ENDPOINT_TYPE_INTERRUPT         0x03  //中断传输

端点号的定义如下
#define MAIN_POINT_OUT           0x02   //2号输出端点
#define MAIN_POINT_IN            0x82   //2号输入端点

USB HID描述符【转】的更多相关文章

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

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

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

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

  3. (八) Usb摄像头描述符解析

    目录 Usb摄像头描述符解析 总结 参考资料 打印设备描述符 打印配置描述符 打印接口联合体描述符 打印接口描述符 打印当前设置的额外描述符 代码解析额外的描述符 打印端点描述符 title: Usb ...

  4. 2.7 usb摄像头之usb摄像头描述符打印

    学习目标:参考lsusb源码,打印USB摄像头的设备描述符.配置描述符.接口联合描述符.端点描述符: 一.lsusb命令和源码 使用命令lsusb可以看看设备的id,并执行 # lsusb -v -d ...

  5. 12.1、USB驱动——描述符、URB、管道

    大家常说,一个设备通常有多个配置,配置通常有多个接口,接口通常有多个端点.接口代表逻辑上的设备,比如声卡分为 录音和播放.访问设备时,访问的是某个接口(逻辑设备).除了端点0之外,每个端点只支持一个传 ...

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

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

  7. USB HID Report Descriptor 报告描述符详解

    Report descriptors are composed of pieces of information. Each piece of information is called an Ite ...

  8. USB学习小记-HID类键盘的报告描述符的理解

    前言 断断续续的学习了将近三个月,才把USB的HID类搞明白,速度真是够慢的.利用晚上+周末的时间学习自己的东西确实是必要的,不过效率是有点低,以后要更专注一些才行,希望自己能做到吧. 在学习过程中, ...

  9. USB HID设备报告描述符详解(转)

    转自:http://group.ednchina.com/93/198.aspx. 参考:USB HID usage table 概述:   报告在这里意思是数据传输(data transfer),而 ...

随机推荐

  1. 《JAVA NIO》Channel

    3.通道 Channle主要分为两类:File操作对应的FIleChannel和Stream操作对应的socket的3个channe. 1.这3个channel都是抽象类.其具体实现在SPI里面. 2 ...

  2. vertical-align的理解

    vertical-align的理解 定义和用法 vertical-align 属性设置元素的垂直对齐方式 该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐 也就是说 它只是个适用行内元素的属 ...

  3. each的用法

    $(selector).each(function(index,element)) function(index,element) 必需.为每个匹配元素规定运行的函数. index - 选择器的 in ...

  4. 做SSH练习的时候,JUunit运行遇到报错信息

    提示说是applicationcontext文件中的jdbcUrl信息错误,可是xml文件中的url再三确认是没有错的,不知道怎么回事? 最下面贴上applicationContext.xml中的数据 ...

  5. MVC项目实践,在三层架构下实现SportsStore-04,实现分页

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  6. LINQ使用

    基于扩展方法和lamda表达式 1. 查询序列中满足一定条件 Where扩展方法 public interface ISlotPortBinding { byte SlotNumber { get; ...

  7. iOS - (两个APP之间的跳转)

    一个程序若要跳到另一个程序.需要在目标程序的plist文件里面修改: 打开info.plist,添加一项URL types 展开URL types,再展开Item0,将Item0下的URL ident ...

  8. 汉字拼音带声调和发音mp3文件(C#源程序)

    7800多个汉字的拼音带声调以及全部mp3读音文件,附带一个C#实例程序源代码 读音文件按拼音和声调命名,方便调用 获取全部源代码

  9. ThinkPHP分页链接支持数组参数的办法

    这几天在用ThinkPHP做系统,搜索页有个数组参数提交 <input class="params_t" name="t[]" type="ch ...

  10. 解决webApi<Message>An error has occurred.</Message>不能写多个Get方法的问题

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷.     本人最近在研究C#webAPI相关知识,发现webAPI不能够支持 ...