HID设备类定义文档中明确指出,一个报告描述符必须包含但不仅限于以下数据项:
-
输入(输出或特征)
指明了报告的类型,其中隐含了报告的传输方向以及报告数据所具有的数学特性。 -
用法(也可用“用法最小值与最大值”来定义一连串用法)
-
用法页
用法和用法页一起指明了数据项的用法,每个数据项都必须指明用法,否则主机端不能成功解析报告描述符。用法页是全局的,修饰列于其后的所有数据项,直到出现新的用法页为止;用法则是局部数据项,局部数据项只修饰列于其后的第一个主数据项内的数据项,一旦出现新的主数据项,那么用法必须重新指定。这其中隐含的意思是,每个主数据项前面都必须有修饰它的用法与用法页组合。(“用法”表示的是一个单独的用法,而“用法最小值”和“用法最大值”可以替代“用法”,代表某个范围的用法。) -
逻辑最小值
-
逻辑最大值
逻辑最小值和逻辑最大值指明了报告所使用的数据值的范围,这个数据值是以逻辑单位为基础的,与报告大小有着对应关系。 -
报告大小
报告大小指明数据项的位数。 -
报告计数
报告计数指明有多少个这样的数据项。
例如,定义以下数据项:
逻辑最小值(0)
逻辑最大值(0x7f)
报告大小(8)
那么它的意思就是,此报告中数据字段的大小是8位,本身可以表示0~255之间的任何数,但是逻辑值的范围被定义在0~127之间,所以实际上数据字段的数据不能超过127,否则视为无效报告。
再举一个例子:
逻辑最小值(0)
逻辑最大值(3)
报告大小(2)
这个例子的意思是,此报告中数据字段的大小是2位,逻辑值范围是0~3,那么数据字段的值与逻辑值是一一对应且相等的,即0(00b),1(01b),2(10b),3(11b)。
第三个例子:
再举一个例子:
逻辑最小值(-1)
逻辑最大值(1)
报告大小(2)
这个例子的意思是,此报告中数据字段的大小是2位,逻辑值范围是-1~1,那么数据字段的值与逻辑值是按左对齐的方式部分对应的,即数据字段值0(00b)对应逻辑值-1,数据字段值1(01b)对应逻辑值0,数据字段值2(10b)对应逻辑值1,数据字段值3(11b)无效。
下面举一个HID自定义设备的报告描述符的例子,这个例子比鼠标和键盘更简单。更具体的内容,譬如常用的鼠标和键盘,可以参看官方文档Device Class Definition for Human Interface Devices(HID).pdf 和HID Usage Tables.pdf。
_ReportDescriptor: //报告描述符
.dw 0x06, 0x00, 0xff //用法页,hid设备用途。供应商自定义,修饰其下所有的主项
.dw 0x09, 0x01 //用法(供应商用法1),局部项,只修饰下面的“集合”主项。一个hid设备可以有多个集合。
.dw 0xa1, 0x01 //集合开始,主项
.dw 0x85, 0x01 //报告ID(1),全局项,可以修饰其下所有的主项,但是在这个报告描述中由于后面出现了新的报告ID,所以它只是修饰下面的“输入”主项。
/*********************第一个项目,从用法开始**********************/
.dw 0x9, 0x01 //用法(供应商用法1)
.dw 0x15, 0x00 //逻辑最小值(0),全局项,修饰下面所有的主项
.dw 0x26, 0xff, 0x00 //逻辑最大值(255),全局项,修饰下面所有的主项
.dw 0x75, 0x08 //报告大小(8),全局项,修饰下面所有的主项
.dw 0x95, 0x07 //报告计数(7),全局项,修饰下面所有的主项
.dw 0x81, 0x06 //输入(数据,变量,相对值),主项,说明此报告的属性
/************************第一个报告项目结束*************************/
//下面开始一个新的主项目,前面提到的全局项仍对这个主项目有效,譬如报告大小等
/************************第2个报告项目,从用法开始*****************/
.dw 0x09, 0x01 //用法(供应商用法1) ,局部项,修饰下面的“特征” 主项
.dw 0x85, 0x03 //报告ID(3),全局项,之前的报告ID项失效
.dw 0xb1, 0x06 //特征(数据,变量,相对值)
/************************第2个报告项目结束**************************/
//下面开始一个新的主项目,前面提到的全局项仍对这个主项目有效,譬如报告大小等
/************************第3个报告项目,从用法开始******************/
.dw 0x09, 0x01 //用法(供应商用法1) ,局部项,修饰下面的“特征” 主项
.dw 0x85, 0x02 //报告ID(2),全局项,之前的报告ID项失效
.dw 0xb1, 0x06 //特征(数据,变量,相对值)
/************************第3个报告项目结束***************************/
//下面开始一个新的主项目,前面提到的全局项仍对这个主项目有效,譬如报告大小等
/************************第4个报告项目,从用法开始*******************/
.dw 0x09, 0x01 //用法(供应商用法1) ,局部项,修饰下面的“输出” 主项
.dw 0x85, 0x04 //报告ID(4),全局项,之前的报告ID项失效
.dw 0x91, 0x06 //输出(数据,变量,相对值)
/************************第4个报告项目结束***********************/
.dw 0xc0 //集合结束
_ReportDescriptor_End:
以上描述符定义了4个不同的报告,用报告ID区分。HID设备定义文档上有讲,在一个报告ID之后而在下一个报告ID之前范围内的所有数据项都属于一个报告,发送报告时会把报告ID附在这个报告的前面以区分报告。

.dw 0x06, 0x00, 0xff //用法页,hid设备用途。供应商自定义,修饰其下所有的主项
用法页为什么是0x06开头?可以看上面的表格里,Usage Page为“0000 01nn”,其中nn表示数据长度。这里后面跟的数据是0x00、0xff,长度是2,所应该为0000 0110,对应十六进制0x06。这里只是举例说明,其他格式一致可以自己解析。
以下为hid按键、键盘、鼠标的报告描述符例子。
//---------------------------------------------------------------------
//==========hid_key
static const u8 sHIDReportDesc_hidkey[] = {
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x09, 0xE9, // Usage (Volume Increment)
0x09, 0xEA, // Usage (Volume Decrement)
0x09, 0xCD, // Usage (Play/Pause)
0x09, 0xE2, // Usage (Mute)
0x09, 0xB6, // Usage (Scan Previous Track)
0x09, 0xB5, // Usage (Scan Next Track)
0x09, 0xB3, // Usage (Fast Forward)
0x09, 0xB4, // Usage (Rewind)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x10, // Report Count (16)
0x81, 0x02,<

本文详细解析HID设备报告描述符的组成元素及其含义,包括输入、输出、特征、用法、逻辑最小值与最大值等关键概念,并提供自定义HID设备及常见HID设备如键盘、鼠标的具体描述符实例。

2万+

被折叠的 条评论
为什么被折叠?



