USB HID描述符【转】
本文转载自:
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描述符【转】的更多相关文章
- (转)USB的描述符及各种描述符之间的依赖关系
全文链接:http://justmei.blog.163.com/blog/static/11609985320102421659260/?latestBlog 1 推荐 [原创] USB入门系列之七 ...
- USB协议-USB的描述符及其之间的关系
USB只是一个总线,只提供一个数据通路而已.USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为.具体的一个设备实现什么功能,要由设备自己来决定.那么,USB主机是如何知道一个设备的功能以及行为 ...
- (八) Usb摄像头描述符解析
目录 Usb摄像头描述符解析 总结 参考资料 打印设备描述符 打印配置描述符 打印接口联合体描述符 打印接口描述符 打印当前设置的额外描述符 代码解析额外的描述符 打印端点描述符 title: Usb ...
- 2.7 usb摄像头之usb摄像头描述符打印
学习目标:参考lsusb源码,打印USB摄像头的设备描述符.配置描述符.接口联合描述符.端点描述符: 一.lsusb命令和源码 使用命令lsusb可以看看设备的id,并执行 # lsusb -v -d ...
- 12.1、USB驱动——描述符、URB、管道
大家常说,一个设备通常有多个配置,配置通常有多个接口,接口通常有多个端点.接口代表逻辑上的设备,比如声卡分为 录音和播放.访问设备时,访问的是某个接口(逻辑设备).除了端点0之外,每个端点只支持一个传 ...
- USB HID报告及报告描述符简介
在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID ...
- USB HID Report Descriptor 报告描述符详解
Report descriptors are composed of pieces of information. Each piece of information is called an Ite ...
- USB学习小记-HID类键盘的报告描述符的理解
前言 断断续续的学习了将近三个月,才把USB的HID类搞明白,速度真是够慢的.利用晚上+周末的时间学习自己的东西确实是必要的,不过效率是有点低,以后要更专注一些才行,希望自己能做到吧. 在学习过程中, ...
- USB HID设备报告描述符详解(转)
转自:http://group.ednchina.com/93/198.aspx. 参考:USB HID usage table 概述: 报告在这里意思是数据传输(data transfer),而 ...
随机推荐
- extjs form.load()加载服务端数据
formPanel.getForm().load({ url: 'getApproveRefundInf?refundIdDetail=${refundIdDetail}', waitMsg: '请稍 ...
- SpringMVC 406 accept请求错误,没有加入将json序列化的包
在spring中使用@responsebody发现请求报406错误 jar包中缺少json序列化的相关的包!
- 选择时区的命令tzselect
选择时区的命令tzselect tzselectPlease identify a location so that time zone rules can be set correctly.Plea ...
- android JSONArray JSONObject 字符串转json数组 遍历json对象
String json = "{''data'':[{''name'':''Wallace''},{''name'':''Grommit''}]}"; StringBuffer m ...
- 密码有效性验证失败。该密码不够复杂,不符合 Windows 策略要求
我在sqlserver2005中建立一个用户的时候,我的用户名和密码是一样的,它不允许我建立报“密码有效性验证失败.该密码不够复杂,不符合 Windows 策略要求”错误,我把密码改成其他一些就可以, ...
- Nginx负载均衡和LVS负载均衡的比较分析
LVS和Nginx都可以用作多机负载的方案,它们各有优缺,在生产环境中需要好好分析实际情况并加以利用. 首先提醒,做技术切不可人云亦云,我云即你云:同时也不可太趋向保守,过于相信旧有方式而等别人来帮你 ...
- Java集合 List,Set,Map
一.List:.有顺序以线性方式存储,可以存放重复对象 线程安全方法:List list = Collections.synchronizedList(new LinkedList(...)); ...
- django 分页(2) 使用类 页码显示
django 分页显示页码 views.py 显示11页码 ) < 起始位置 - 10总页数 else 总页数 > IF 当前页 小于 起始位置 结束页 IF 当前页 大于 IF 如果结束 ...
- Function.prototype.bind接口浅析
本文大部分内容翻译自 MDN内容, 翻译内容经过自己的理解. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Glo ...
- Oracle RAC inventory.xml损坏后如何修复
不建议直接修改该文件 1.从其它节点拷贝一份 2.使用runInstaller工具(这个工具位于<GI_HOME>/oui/bin路径下)重建inventory.xml文件 步骤1:添加G ...