今天抽空整理了一下之前学习的USB报告描述符相关的知识点,直接进入正题吧
报告描述符的语法与USB标准描述符不太一样,主要是以项目的形式排列。而项目一般是 前缀 + 数据 的形式。
比如:
0x05, 0x01 // 0x05为前缀 ,0x01为数据
项目一般分为3种,分别是:全局项目,主项目,区域项目,
主项目: 用来定义报告中数据的种类和格式,而说明主项目之意义与用途为全局项目和区域项目。
区域项目:只能适用于列于其下的第一个主项目,不适用于其他主项目,若一个主项目之上有几个不同的卷标的区域性项目,则这些区域 性项目皆适用于描述该主项目。
全局项目:适用于其下方的所有主项目,除非另一个相同卷标的全局性项目出现。
那如何去区分是什么项目呢?这就要看项目的前缀了。
将项目前缀分成3部分,如下:
prefix : bTag(项目目标 4bit) bType(项目的类型 2bit) bSize(项目数据字节数 2bit)
由此可以看出,项目前缀包含3个信息点。所以怎么去区别是什么类型的项目就看前缀了,分别介绍3个信息点对应数值
bType:该部分有2bit 00为主项目 01为全局项目 10为区域项目
bTag: 该部分有4bit ,不同的项目类型,有不同的项目目标,既然有3种类型,我们就分3中来介绍
1、主项目情况下,有5种项目目标:
Input 0x8? // "?"是指后4bit :00(主项目类型)+ xx(数据字节数)
Output 0x9?
Feature 0xb?
collection 0xa1 // 可以看出,该tag指定带1字节数据
End collection 0xc0 // 可以看出,该tag指定带不带数据
2、全局项目情况下,有12种项目目标:
Usage Page 0x0?
Logical Minimum 0x1?
Logical Maximum 0x2?
Maximum Physical 0x3?
Physical Minimum 0x4?
Unit Exponent 0x5?
Unit 0x6?
Report Size 0x7?
Report ID 0x8?
Report Count 0x9?
Push 0xa?
Pop 0xb?
3、区域项目情况下,有3种项目目标:
Usage Page 0x0?
Usage Minumum 0x1?
Usage Maxumum 0x2?
比如上面提到的:
0x05,0x01 // 前缀为 0000 01 01 也就是全局项目里面的 Usage Page。 后面带的1字节数据 0x01 (Generic Desktop Controls, 后面会介绍)
关于这些卷标本文就不再详细介绍,朋友们可以去看看https://blog.csdn.net/dm_man/article/details/5285664,该文章有详细描述。
看到这里,是不是对报告描述符还有点不是很清楚? 别急 举个例子看
这里摘抄一份键盘的报告描述符:
code uint8_t hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x0000 01 01 全局项目 1字节 0000 0001 Generic Desktop Controls
0x09, 0x06, // USAGE (Keyboard) 0x0000 10 01 区域项目 1字节 0000 0110 键盘
0xa1, 0x01, // COLLECTION (Application) 0x1010 00 01 主项目 1字节 0000 0001
0x05, 0x07, // USAGE_PAGE (Keyboard) 0x0000 0101 全局项目 1字节 0000 0111 键盘
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x0001 1001 区域项目 1字节
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x0010 1001 区域项目 1字节
0x15, 0x00, // LOGICAL_MINIMUM (0) 0x0001 0101 全局项目 1字节
0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x0010 0101 全局项目 1字节
0x75, 0x01, // REPORT_SIZE (1) 0x0111 0101 全局项目 1字节
0x95, 0x08, // REPORT_COUNT (8) 0x1001 0101 全局项目 1字节
0x81, 0x02, // INPUT (Data,Var,Abs) 0x1000 0001 主项目 1字节
0x95, 0x01, // REPORT_COUNT (1) 0x1001 0101 全局项目 1字节
0x75, 0x08, // REPORT_SIZE (8) 0x0111 0101 全局项目 1字节
0x81, 0x03, // INPUT (Cnst,Var,Abs) 0x1000 0001 主项目 1字节
0x95, 0x03, // REPORT_COUNT (3) 0x1001 0101 全局项目 1字节
0x75, 0x01, // REPORT_SIZE (1) 0x0111 0101 全局项目 1字节
0x05, 0x08, // USAGE_PAGE (LEDs) 0x0101 0101 全局项目 1字节
0x19, 0x01, // USAGE_MINIMUM (Num Lock) 0x0001 1001 区域项目 1字节
0x29, 0x03, // USAGE_MAXIMUM (Scroll Lock) 0x0001 1001 区域项目 1字节
0x91, 0x02, // OUTPUT (Data,Var,Abs) 0x1000 0001 主项目 1字节
0x95, 0x01, // REPORT_COUNT (1) 0x1001 0101 全局项目 1字节
0x75, 0x05, // REPORT_SIZE (5) 0x0111 0101 全局项目 1字节
0x91, 0x03, // OUTPUT (Cnst,Var,Abs) 0x1000 0001 主项目 1字节
0x95, 0x06, // REPORT_COUNT (6) 0x1001 0101 全局项目 1字节
0x75, 0x08, // REPORT_SIZE (8) 0x0111 0101 全局项目 1字节
0x15, 0x00, // LOGICAL_MINIMUM (0) 0x0001 0101 全局项目 1字节
0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x0010 0101 全局项目 1字节
0x05, 0x07, // USAGE_PAGE (Keyboard) 0x0000 0101 全局项目 1字节
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x0001 1001 区域项目 1字节
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x0001 1001 区域项目 1字节
0x81, 0x00, // INPUT (Data,Ary,Abs) 0x1000 0001 主项目 1字节
0xc0 // END_COLLECTION 0x1100 0000 主项目 0字节
};
Usage Page 后面所带的数据0x01 表示Generic Desktop。
关于这个知识点可以去查看https://wenku.baidu.com/view/7e45326c25c52cc58bd6be3b.html,该文章对于HID Usage Table 有详细介绍。
可以看到,Generic Desktop 大类情况下 Usage 0x06 为键盘,
Report Size 用来设定主项目(Input,Output,Feature)的报告字段大小,它的单位是位。主项目会对每个操作产生一个报告字段,字段大小则由 Report Size 决定。
而Report Count 用来设定主项目之报告字段的数目,其等于操作的数目。
Logical Minimum 和Logical Maximum 在说明每个报告字段的数值范围,这是纯数值所以称为逻辑数值(logical value)。