HID 报告描述 2

https://blog.csdn.net/pig10086/article/details/71438990

1,样例解读

下面是一个伪代码描述的样例,其中涉及到的页码可查看第5段用途表:

用法页面(通用桌面),//定位到通用桌面页面,这个相当于指针跳转一样的东西

用法(鼠标),//指定Generic Desktop里的鼠标,表示这是一个鼠标

收集(应用程序),//收集应用程序,是对鼠标的解释

 用法(指针),//表示指针形式

Collection(Physical),// Collection Physical,是对Pointer的解释

  报告ID(0A),//ID为的0x0A的报告

  用法(X),用法(Y),//上报X,Y两个数据

  逻辑最小值(-127),//报告数据值范围为-127

  Logical Maximum(127),// X,Y的取值范围是-127~127

  报告大小(8),报告计数(2),//总共要上报2个字节,即x一个字节,y一个字节

  输入(数据,变量,相对),//将X,Y这两个字节添加到0x0A的报告里,且这两个值是可写并且是相对的

  逻辑最小值(0),

  逻辑最大值(1),//下面按钮的取值范围是0~1

  报告大小(1),报告计数(3),// 3个1位的数据

  用法页面(按钮页面),//是一个按钮

  用法最小值(1),

  用法最大值(3),//共有BUTTON1~BUTTON3,即总共有3个按钮

Input (Data, Variable, Absolute),//将3个分别代表的BUTTON1,BUTTON2,BUTTON3的位添加到0x0A的报告

Report Size (5),

Input (Constant), //增加5个无效的位与上面3位凑成一个字节

End Collection,

End Collection


综上所示,上面样例所表达的意思就是下图所示的:



这里先简单介绍用图表(鼠标):具体看 HID Usage Tables 1.12(用图表).pdf ,或下一章

0x05, 0x01, // Usage Page (Generic Desktop)


0x09, 0x02, // Usage (Mouse)



再 举 一 个 实 际 的 例 子 进 行 解 读 , 下 面 是 摘 自 TI CC2540/CC2541 SDK 里 的BLE-CC254x_v1.4.0\Projects\ble\Profiles\HIDDevKbM\hidkbmservice.c

static CONST uint8 hidReportMap[] =
{

0x05, 0x01, // Usage Page (Generic Desktop)

0x09, 0x02, // Usage (Mouse)

0xA1, 0x01, // Collection (Application)

0x85, 0x01, // Report Id (1)

0x09, 0x01, // Usage (Pointer)

0xA1, 0x00, // Collection (Physical)

0x05, 0x09, // Usage Page (Buttons)

0x19, 0x01, // Usage Minimum (01) - Button 1

0x29, 0x03, // Usage Maximum (03) - Button 3

0x15, 0x00, // Logical Minimum (0)

0x25, 0x01, // Logical Maximum (1)

0x75, 0x01, // Report Size (1)

0x95, 0x03, // Report Count (3)

0x81, 0x02, // Input (Data, Variable,Absolute) - Button states

0x75, 0x05, // Report Size (5)

0x95, 0x01, // Report Count (1)

0x81, 0x01, // Input (Constant) - Padding or Reserved bits

0x05, 0x01, // Usage Page (Generic Desktop)

0x09, 0x30, // Usage (X)

0x09, 0x31, // Usage (Y)

0x09, 0x38, // Usage (Wheel)

0x15, 0x81, // Logical Minimum (-127)

0x25, 0x7F, // Logical Maximum (127)

0x75, 0x08, // Report Size (8)

0x95, 0x03, // Report Count (3)

0x81, 0x06, // Input (Data, Variable, Relative) - X & Y coordinate

0xC0, // End Collection

0xC0, // End Collection


0x05, 0x01, // Usage Pg (Generic Desktop)

0x09, 0x06, // Usage (Keyboard)

0xA1, 0x01, // Collection: (Application)

0x85, 0x02, // Report Id (2)

0x05, 0x07, // Usage Pg (Key Codes)

0x19, 0xE0, // Usage Min (224)

0x29, 0xE7, // Usage Max (231)

0x15, 0x00, // Log Min (0)

0x25, 0x01, // Log Max (1)

// Modifier byte

0x75, 0x01, // Report Size (1)

0x95, 0x08, // Report Count (8)

0x81, 0x02, // Input: (Data, Variable,Absolute)

// Reserved byte

0x95, 0x01, // Report Count (1)

0x75, 0x08, // Report Size (8)

0x81, 0x01, // Input: (Constant)

// LED report

0x95, 0x05, // Report Count (5)

0x75, 0x01, // Report Size (1)

0x05, 0x08, // Usage Pg (LEDs)

0x19, 0x01, // Usage Min (1)

0x29, 0x05, // Usage Max (5)

0x91, 0x02, // Output: (Data, Variable,Absolute)

// LED report padding

0x95, 0x01, // Report Count (1)

0x75, 0x03, // Report Size (3)

0x91, 0x01, // Output: (Constant)

// Key arrays (6 bytes)

0x95, 0x06, // Report Count (6)

0x75, 0x08, // Report Size (8)

0x15, 0x00, // Log Min (0)

0x25, 0x65, // Log Max (101)

0x05, 0x07, // Usage Pg (Key Codes)

0x19, 0x00, // Usage Min (0)

0x29, 0x65, // Usage Max (101)

0x81, 0x00, // Input: (Data, Array)

0xC0, // End Collection


0x05, 0x0C, // Usage Pg (Consumer Devices)

0x09, 0x01, // Usage (Consumer Control)

0xA1, 0x01, // Collection (Application)

0x85, 0x03, // Report Id (3)

0x09, 0x02, // Usage (Numeric Key Pad)

0xA1, 0x02, // Collection (Logical)

0x05, 0x09, // Usage Pg (Button)

0x19, 0x01, // Usage Min (Button 1)

0x29, 0x0A, // Usage Max (Button 10)

0x15, 0x01, // Logical Min (1)

0x25, 0x0A, // Logical Max (10)

0x75, 0x04, // Report Size (4)

0x95, 0x01, // Report Count (1)

0x81, 0x00, // Input (Data,Ary,Abs)

0xC0, // End Collection

0x05, 0x0C, // Usage Pg (Consumer Devices)

0x09, 0x86, // Usage (Channel)

0x15, 0xFF, // Logical Min (-1)

0x25, 0x01, // Logical Max (1)

0x75, 0x02, // Report Size (2)

0x95, 0x01, // Report Count (1)

0x81, 0x46, // Input (Data, Var, Rel, Null)

0x09, 0xE9, // Usage (Volume Up)

0x09, 0xEA, // Usage (Volume Down)

0x15, 0x00, // Logical Min (0)

0x75, 0x01, // Report Size (1)

0x95, 0x02, // Report Count (2)

0x81, 0x02, // Input (Data, Var,Abs)

0x09, 0xE2, // Usage (Mute)

0x09, 0x30, // Usage (Power)

0x09, 0x40, // Usage (Menu)

0x09, 0xB1, // Usage (Pause)

0x09, 0xB2, // Usage (Record)

0x0a, 0x23, 0x02, // Usage (Home)

0x0a, 0x24, 0x02, // Usage (Back)

0x09, 0xB3, // Usage (Fast Forward)

0x09, 0xB4, // Usage (Rewind)

0x09, 0xB5, // Usage (Scan Next)

0x09, 0xB6, // Usage (Scan Prev)

0x09, 0xB7, // Usage (Stop)

0x15, 0x01, // Logical Min (1)

0x25, 0x0C, // Logical Max (12)

0x75, 0x04, // Report Size (4)

0x95, 0x01, // Report Count (1)

0x81, 0x00, // Input (Data, Ary,Abs)

0x09, 0x80, // Usage (Selection)

0xA1, 0x02, // Collection (Logical)

0x05, 0x09, // Usage Pg (Button)

0x19, 0x01, // Usage Min (Button 1)

0x29, 0x03, // Usage Max (Button 3)

0x15, 0x01, // Logical Min (1)

0x25, 0x03, // Logical Max (3)

0x75, 0x02, // Report Size (2)

0x81, 0x00, // Input (Data,Ary,Abs)

0xC0, // End Collection

0x81, 0x03, // Input (Const, Var,Abs)

0xC0 // End Collection
};


上面用红蓝绿区分出三大应用功能,分别鼠标、键盘和 Consumer,每个应用功能都是用CollectionApplication 括起来的。




我们先来解析鼠标的报告描述:

0x05, 0x01, // Usage Page (Generic Desktop)

0x04 代表是 Global 类的 Usage Page 功能,最位 2 位表示带多少个字节的数据,因为只带1 个数据,所以是 1,跟 0x04 组合起来就是 0x05 了。其他名称的意思都差不多,数值可以参照上一章的Generic Item Format

0x09, 0x02, // Usage (Mouse)

表示这是一个鼠标, Usage 是为了给对方解析数据时有个参照

0xA1, 0x01, // Collection (Application)

0xA1, 0x01 表示 CollectionApplication ; 0xA1, 0x00 表示 Collection Physical.表示下面所包含的是对 Mouse 的解释

0x85, 0x01, // Report Id (1)

该报告对应的 ID 是 1

0x09, 0x01, // Usage (Pointer)

这是个指针形式

0xA1, 0x00, // Collection (Physical)

下面所包含的是对指针的解释

0x05, 0x09, // Usage Page (Buttons)

下面定义的是按键

0x19, 0x01, // Usage Minimum (01) - Button 1

0x29, 0x03, // Usage Maximum (03) - Button 3

总共有 3 个按键

0x15, 0x00, // Logical Minimum (0)

0x25, 0x01, // Logical Maximum (1)

按键的值是 0 和 1,表示放开和按下

0x75, 0x01, // Report Size (1)

0x95, 0x03, // Report Count (3)

有 3 个 1 位,即用 3bits 分别对应三个按键

0x81, 0x02, // Input (Data, Variable,Absolute) - Button states

将这三个位加入本报告的数据中,这三位是可读写的绝对值

0x75, 0x05, // Report Size (5)

0x95, 0x01, // Report Count (1)

定义 1 个 5 位的数据

0x81, 0x01, // Input (Constant) - Padding or Reserved bits

将这个数据添加到本报告的数据中,主要是与前面 3 位组成一个字节,这 5 位是 Constant数据

0x05, 0x01, // Usage Page (Generic Desktop)

0x09, 0x30, // Usage (X)

0x09, 0x31, // Usage (Y)

0x09, 0x38, // Usage (Wheel)

下面定义的是 X,Y,Wheel 三个功能

0x15, 0x81, // Logical Minimum (-127)

0x25, 0x7F, // Logical Maximum (127)

X,Y,Wheel 的取值范围是-127~127

0x75, 0x08, // Report Size (8)

0x95, 0x03, // Report Count (3)

用三个字节来表示 x,y,wheel

0x81, 0x06, // Input (Data, Variable, Relative) - X & Y coordinate

将这三个字节添加到本报告中

0xC0, // End Collection

0xC0, // End Collection


上面解析出来的数据格式如下:


我们来看一下,如果要发一个鼠标的坐标,该如何发:

static void hidEmuKbdSendMouseReport( uint8 buttons )

{

uint8 buf[HID_MOUSE_IN_RPT_LEN];

buf[0] = buttons; // Buttons

buf[1] = 0; // X

buf[2] = 0; // Y

buf[3] = 0; // Wheel

HidDev_Report( HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT,

HID_MOUSE_IN_RPT_LEN, buf );

}

从上面函数可以看到,X,Y 在第 2、3 个字节,结合上面的数据格式图可以看出,正好是对应的。



我们接着解析键盘的报告描述:

0x05, 0x01, // Usage Pg (Generic Desktop)

0x09, 0x06, // Usage (Keyboard)

这是一个键盘

0xA1, 0x01, // Collection: (Application)

0x85, 0x02, // Report Id (2)

本报告的 ID 是 2

0x05, 0x07, // Usage Pg (Key Codes)

下面定义的是按键码

0x19, 0xE0, // Usage Min (224)

0x29, 0xE7, // Usage Max (231)

按键码分别是 224~231,共总有 8 个按键码

0x15, 0x00, // Log Min (0)

0x25, 0x01, // Log Max (1)

按键码的值是 0 和 1,分别代表放开和按下

// Modifier byte

0x75, 0x01, // Report Size (1)

0x95, 0x08, // Report Count (8)

用 8 个 bit 分别表示 8 个按键的状态

0x81, 0x02, // Input: (Data, Variable,Absolute)

将这 8 个 bit 添加到本报告中

// Reserved byte

0x95, 0x01, // Report Count (1)

0x75, 0x08, // Report Size (8)

0x81, 0x01, // Input: (Constant)

另外再预留 8 个 bit 备用,暂时没用

// LED report

0x95, 0x05, // Report Count (5)

0x75, 0x01, // Report Size (1)

定义 5 个 1bit

0x05, 0x08, // Usage Pg (LEDs)

这是 LED

0x19, 0x01, // Usage Min (1)

0x29, 0x05, // Usage Max (5)

5 个 bit 分别对应 LED1~LED5

0x91, 0x02, // Output: (Data, Variable,Absolute)

将这 5 个 bit 添加到本报告中,LED 需要作为 OUT

// LED report padding

0x95, 0x01, // Report Count (1)

0x75, 0x03, // Report Size (3)

0x91, 0x01, // Output: (Constant)

再增加 3 个 bit,与上面 5 个 bit 组成一个字节

// Key arrays (6 bytes)

0x95, 0x06, // Report Count (6)

0x75, 0x08, // Report Size (8)

定义 6 个字节

0x15, 0x00, // Log Min (0)

0x25, 0x65, // Log Max (101)

每个字节的取值范围是 0~101

0x05, 0x07, // Usage Pg (Key Codes)

这个也是键盘码

0x19, 0x00, // Usage Min (0)

0x29, 0x65, // Usage Max (101)

分别是键盘码 0~键盘码 101

0x81, 0x00, // Input: (Data, Array)

将这 6 个字节添加到本报告中,表示同时可产生 6 个键值。

0xC0, // End Collection

上面解析出来的数据格式如下:


Input 和 Out 是不同的两条通道。现在我们来看一下,如果要发一个按键 K0~K101,需要怎么发,如下:

static void hidEmuKbdSendReport( uint8 keycode )

{

uint8 buf[HID_KEYBOARD_IN_RPT_LEN];

buf[0] = 0; // Modifier keys

buf[1] = 0; // Reserved

buf[2] = keycode; // Keycode 1

buf[3] = 0; // Keycode 2

buf[4] = 0; // Keycode 3

buf[5] = 0; // Keycode 4

buf[6] = 0; // Keycode 5

buf[7] = 0; // Keycode 6

HidDev_Report( HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,

HID_KEYBOARD_IN_RPT_LEN, buf );

}

上面函数可以看到,它是放在第 3 个字节,结合数据格式图可以看出,第 3 个字节开始,刚好是在 K0~K101 的按键区。



我们最后来解析 Consumer 的报告描述:

0x05, 0x0C, // Usage Pg (Consumer Devices)

0x09, 0x01, // Usage (Consumer Control)

这是个 Consumer 控制

0xA1, 0x01, // Collection (Application)

0x85, 0x03, // Report Id (3)

本报告 ID 为 3

0x09, 0x02, // Usage (Numeric Key Pad)

下面定义的是数字键盘

0xA1, 0x02, // Collection (Logical)

0x05, 0x09, // Usage Pg (Button)

下面定义的是按键

0x19, 0x01, // Usage Min (Button 1)

0x29, 0x0A, // Usage Max (Button 10)

分别是 Button1~Button10

0x15, 0x01, // Logical Min (1)

0x25, 0x0A, // Logical Max (10)

每个按键的取值范围为 1~10

0x75, 0x04, // Report Size (4)

0x95, 0x01, // Report Count (1)

1 个 4bit 的值,来表示键值 1~10,这个值是哪个就表示哪个键按下。

0x81, 0x00, // Input (Data,Ary,Abs)

将这 4bit 添加到本报告中

0xC0, // End Collection

0x05, 0x0C, // Usage Pg (Consumer Devices)

0x09, 0x86, // Usage (Channel)

这里定义的是频道

0x15, 0xFF, // Logical Min (-1)

0x25, 0x01, // Logical Max (1)

频道值范围是-1~1,这里应该只用到-1 和 1,表示频道+和-

0x75, 0x02, // Report Size (2)

0x95, 0x01, // Report Count (1)

用一个 2bit 来表示,第 1 个 bit 表示频道+,第二个表示频道-

0x81, 0x46, // Input (Data, Var, Rel, Null)

将这个 2bit 加到本报告中

0x09, 0xE9, // Usage (Volume Up)

0x09, 0xEA, // Usage (Volume Down)

定义两个按键,音量加和音量减

0x15, 0x00, // Logical Min (0)

按键值为 0~1,这里少了 Logical Max,继承上面的 Logical Max=1

0x75, 0x01, // Report Size (1)

0x95, 0x02, // Report Count (2)

定义 2 个 1bit,每个 bit 代表一个键

0x81, 0x02, // Input (Data, Var,Abs)

将 2 个 1bit 添加到本报告中

0x09, 0xE2, // Usage (Mute)

0x09, 0x30, // Usage (Power)

0x09, 0x40, // Usage (Menu)

0x09, 0xB1, // Usage (Pause)

0x09, 0xB2, // Usage (Record)

0x0a, 0x23, 0x02, // Usage (Home)

0x0a, 0x24, 0x02, // Usage (Back)

0x09, 0xB3, // Usage (Fast Forward)

0x09, 0xB4, // Usage (Rewind)

0x09, 0xB5, // Usage (Scan Next)

0x09, 0xB6, // Usage (Scan Prev)

0x09, 0xB7, // Usage (Stop)

定义 12 个按键

0x15, 0x01, // Logical Min (1)

0x25, 0x0C, // Logical Max (12)

0x75, 0x04, // Report Size (4)

0x95, 0x01, // Report Count (1)

用一个 4 位来存储 1~12,1 表示 Mute … 12 表示 Stop

0x81, 0x00, // Input (Data, Ary,Abs)

将这个 4bit 添加到报告中

0x09, 0x80, // Usage (Selection)

0xA1, 0x02, // Collection (Logical)

0x05, 0x09, // Usage Pg (Button)

这是按键

0x19, 0x01, // Usage Min (Button 1)

0x29, 0x03, // Usage Max (Button 3)

分别是 Button1~Button3

0x15, 0x01, // Logical Min (1)

0x25,0x03,//逻辑最大值(3)

每个按键取值范围是1~3

0x75,0x02,//报告大小(2)

这里缺少了Report Count,继承上面的报告数= 1,也就是用1个2bit来存储1~3

0x81,0x00,//输入(数据,Ary,Abs)

将1个字节添加到本报告中

0xC0,//结束集合

0x81,0x03,//输入(Const,Var,Abs)

再补充2个位将上面的凑成一个字节,报告大小= 2和报告计数= 1继承上面的。

0xC0 //结束集合


修改后,解析出来的数据格式如下:


我们来看一下,如果要发音量+/-键该怎么发:

static void hidCCSendReport(uint8 cmd,bool keyPressed)

{

//只有在报告有意义的内容时才发送报告

uint8 buf [HID_CC_IN_RPT_LEN] = {0,0};

//无需包含报告ID

if(keyPressed)

{

hidCCBuildReport(buf,cmd);

}

HidDev_Report(HID_RPT_ID_CC_IN,HID_REPORT_TYPE_INPUT,

HID_CC_IN_RPT_LEN,buf);

}

在hidCCBuildReport对音量加减解析出来是:

音量加是:buf [0] = 0x40,buf [1] = 0x00

音量减是:buf [0] = 0x80,buf [1] = 0x00

正好与数据格式图中第一个字节的第6位和第7位相对应。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值