日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HID报文讲解

發布時間:2023/12/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HID报文讲解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HID報文講解

1 什么是HID?

HID全稱Human Interface Device,人機接口設備,具體指鍵盤鼠標,藍牙和USB都采用相同的報文協議,https://www.usb.org/sites/default/files/documents/hid1_11.pdf 協議里有詳細描述。

2 什么是HID報文?

HID報文全稱為HID Report Description,是一段用指令和數值來描述通信數據結構的數據組,定義了由設備發給PC或手機的數據包里的數據所表示的意思,比如哪個數據是按鍵,這個是什么按鍵。

3 報文結構

Collection的意思是集合,如上圖,一個Application集用于表示一個虛擬設備,可以包含多個集合和多個報文,一個集合可以包含多個報文,報文描述的是發往PC或手里的數據的意義,也就是描述這個數據表示什么按鍵。

4 指令和數據

集合和報文是通過指令和數據來描述的,指令為一個字節,后面根據bSize跟著數據,指令結構如下:

Tag標簽,Type類型,Size表示數據的個數。

Type值有:

0 = Main

1 = Global

2 = Local

3 = Reserved

根據Type值,在不同的表格里,找Tag的意義

Main類的Tag:

Global類的Tag:

Local類的Tag:

例子:0x05, 0x01

0x09, 0x06

0x05是指令,0x01表示數據

0x05分解開,Tag=0000,Type=01,Size=01

Type=01表示Global類,然后從Global表里找到Tag=0的意思是Usage,即用例,然后在《6 用途表》里找到Global的Usage表,在根據Usage表找到數據值0x01的意思為:Generic Desktop Controls

所以,0x05, 0x01的意思是這是一個普通桌面控制器。

0x09是指令,0x06表示數據

0x09分解開,Tag=0000,Type=10,Size=01

Type=10表示Local類,然后從Local表里找到Tag=0的意思是Usage,即用例然后在《6 用途表》里,去找上面Global指定的子表Generic Desktop,找到數據值0x06的意思為:Keyboard

所以,0x09, 0x06的意思是這是一個鍵盤。

通過上面的例子可以知道,Global即父類,Local為子類,先定義父類表包含了各子類表的名稱,子類表包含了具體的意思。

5 用途表

https://www.usb.org/sites/default/files/hut1_21_0.pdf

HID 報告描述_sK.坤-CSDN博客_hid用途表

6 簡單例子

這是一個只有一個按鍵的例子:

static uint8_t report_map_data[] =

????{

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

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

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

?0x85, 0x01, ??????// id?= 1

????????0x05, 0x07, ??????// Usage Page (Key codes)

????????0x09, 0x29, ??????// Usage Esc

0x15, 0x01, ??????// Logical Minimum (1)

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

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

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

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

????????0xC0 ?????????????// End Collection (Application)

}

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

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

從父類表Usage里找到0x01,表示普通桌面控制器

從子類表Generic Desktop Page里找到0x06,表示鍵盤

0x05和0x09基本是配合使用的,先定位父表,再定位子表。

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

...

0xC0 ?????????????// End Collection (Application)

一個集合的開始和結束

0x85, 0x01, ??????// id?= 1

報文ID=1,當有多個集合時,每個集合需要分配不同的ID

0x05, 0x07, ??????// Usage Page (Key codes)

0x09, 0x29, ??????// Usage Esc

從父類表Usage里找到0x07,表示Keyboard

從子類表Keyboard/Keypad Page里找到0x29,表示鍵盤碼0x29為Esc鍵

這里定義了哪些數據要傳給PC或手機

0x15, 0x01, ??????// Logical Minimum (1)

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

定義傳給PC或手機的數據取值范圍,有兩種取值方式,Array和Variable,比如定義了3個按鍵,如果三個按鍵都要發出去,那么選Variable,Logical Minimum 取0,Logical Maximum 取1,0表示沒按下,1表示按下;如果只發出哪個按鍵按下,可以選Array,Logical Minimum取值1,Logical Maximum取值3,表示3個按鍵索引,發1表示第一個按鍵,發2表示第二個按鍵。

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

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

0x95和0x75用來表示用到多少字節,Size = 8,即一個鍵值用到8位,用1個字節來存索引,Count = 1,表示只傳一個鍵值,如果想一次傳多個鍵,則Count可以是2,3,4...。

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

0x81, 0x00用來表示數值的意義,根據Main表,0x00,第0位是0對應的是Data,第1位是0?對應的是Array,第二位是0對應的是Absolute,所以它是一個Data、Variable、 Absolute的類型。

Array 表示上報的值是索引,也就是說,報文的數據由1個字節組成,這個字節的值如果是1,即表示Esc鍵按下。

從上面例子可以知道,報文描述的結構是:

定義設備類型

集合{

定義報文ID

報文內容量

報文數據值

報文字節數

數據是Arrary還是Variable

???}

Arrary 表示上報1個或幾個內容,Variable表示字節數與內容量要一致,可以是位或字節量與內容量相等。

7 鍵盤例子

下面是一個鍵盤描述:

static uint8_t report_map_data[] =

????{

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

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

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

?0x85, 0x01, ??????// id

????????0x05, 0x07, ??????// Usage Page (Key Codes)

????????0x19, 0xe0, ??????// Usage Minimum (224)

????????0x29, 0xe7, ??????// Usage Maximum (231)

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

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

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

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

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

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

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

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

????????0x25, 0x65, ??????// Logical Maximum (101)

????????0x05, 0x07, ??????// Usage Page (Key codes)

????????0x19, 0x00, ??????// Usage Minimum (0)

????????0x29, 0x65, ??????// Usage Maximum (101)

????????0x81, 0x00, ??????// Input (Data, Array) Key array(1?byte)

?0xC0

}

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

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

定義設備類型

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

定義設備類型

0x85, 0x01, ??????// id

定義報文ID為1

0x05, 0x07, ??????// Usage Page (Key Codes)

0x19, 0xe0, ??????// Usage Minimum (224)

0x29, 0xe7, ??????// Usage Maximum (231)

用到按鍵碼:224、225、226、227、228、229、230、231,這些按鍵碼對應CTRL,ALT,SHIFT等按鍵

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

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

取值范圍:0和1,0表示未按下,1表示按下

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

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

用1位表示1個按鍵,8位表示上面8個按鍵

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

一個字節表示8個按鍵狀態,即上報全部按鍵,所以選用Variable數據類型。

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

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

用到1個字節

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

0x25, 0x65, ??????// Logical Maximum (101)

取值范圍:0~101

0x05, 0x07, ??????// Usage Page (Key codes)

0x19, 0x00, ??????// Usage Minimum (0)

0x29, 0x65, ??????// Usage Maximum (101)

對應按鍵碼0~101

0x81, 0x00, ??????// Input (Data, Array) Key array(1?byte)

只上報1個按鍵,1個字節表示一個按鍵,0對應0按鍵碼,101對應101按鍵碼。

由上可知,集合里有兩部分,第一部分是CTRL、SHIFT等功能鍵,第二部分是0~101鍵碼等普通鍵,由這兩部分組合成了組合鍵,也就是說,報文是由2個字節構成,第1字節是功能鍵,第2字節是普通鍵。

8 鼠標例子

下面是一個鼠標描述:

static uint8_t report_map_data[] =

????{

0x05, 0x01, // USAGE_PAGE (Generic Desktop)

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

0xa1, 0x01, // COLLECTION (Application)

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

0x09, 0x01, // ??USAGE (Pointer)

0xa1, 0x00, // ??COLLECTION (Physical)

0x05, 0x09, // ????USAGE_PAGE (Button)

0x19, 0x01, // ????USAGE_MINIMUM (Button 1)

0x29, 0x03, // ????USAGE_MAXIMUM (Button 3)

0x15, 0x00, // ????LOGICAL_MINIMUM (0)

0x25, 0x01, // ????LOGICAL_MAXIMUM (1)

0x95, 0x03, // ????REPORT_COUNT (3)

0x75, 0x01, // ????REPORT_SIZE (1)

0x81, 0x02, // ????INPUT (Data,Var,Abs)

0x95, 0x01, // ????REPORT_COUNT (1)

0x75,?0x05, // ????REPORT_SIZE (5)

0x81, 0x03, // ????INPUT (Cnst,Var,Abs)

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,Var,Rel)

0xc0, 0xc0

}

上報4個字節的數據,第1個字節表示鼠標左鍵、右鍵和中鍵。第2個字節鼠標X偏移,第3個字節Y偏移,第4個字節中間滾輪偏移。

9 鍵盤和鼠標合一

鍵盤和鼠標合一有兩種方式,1 是都合到同一個Application集合里,2 分兩個Application集合。

從上面的分析可以知道,一個Application集合對應一個報文ID,相當于一個設備,所以兩個Application集合就是兩個設備,是USB設備的話則對應2個端點,是BLE設備的話,對應兩個特征。

方式1

static uint8_t report_map_data[] =

{

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

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

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

0x85, 0x01, ??????// id

0x05, 0x07, ??????// Usage Page (Key Codes)

0x19, 0xe0, ??????// Usage Minimum (224)

0x29, 0xe7, ??????// Usage Maximum (231)

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

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

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

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

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

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

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

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

0x25, 0x65, ??????// Logical Maximum (101)

0x05, 0x07, ??????// Usage Page (Key codes)

0x19, 0x00, ??????// Usage Minimum (0)

0x29, 0x65, ??????// Usage Maximum (101)

0x81, 0x00, ??????// Input (Data, Array) Key array(1?byte)

0x05, 0x01, // ? USAGE_PAGE (Generic Desktop)

0x09, 0x01, // ? USAGE (Pointer)

0xa1, 0x00, // ? COLLECTION (Physical)

0x05, 0x09, // ????USAGE_PAGE (Button)

0x19, 0x01, // ????USAGE_MINIMUM (Button 1)

0x29, 0x03, // ????USAGE_MAXIMUM (Button 3)

0x15, 0x00, // ????LOGICAL_MINIMUM (0)

0x25, 0x01, // ????LOGICAL_MAXIMUM (1)

0x95, 0x03, // ????REPORT_COUNT (3)

0x75, 0x01, // ????REPORT_SIZE (1)

0x81, 0x02, // ????INPUT (Data,Var,Abs)

0x95, 0x01, // ????REPORT_COUNT (1)

0x75,?0x05, // ????REPORT_SIZE (5)

0x81, 0x03, // ????INPUT (Cnst,Var,Abs)

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,Var,Rel)

0xC0,

0xC0

}

方式2

static uint8_t report_map_data[] =

{

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

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

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

0x85, 0x01, ??????// id

0x05, 0x07, ??????// Usage Page (Key Codes)

0x19, 0xe0, ??????// Usage Minimum (224)

0x29, 0xe7, ??????// Usage Maximum (231)

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

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

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

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

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

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

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

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

0x25, 0x65, ??????// Logical Maximum (101)

0x05, 0x07, ??????// Usage Page (Key codes)

0x19, 0x00, ??????// Usage Minimum (0)

0x29, 0x65, ??????// Usage Maximum (101)

0x81, 0x00, ??????// Input (Data, Array) Key array(1?byte)?

0xC0

0xa1, 0x01, // COLLECTION (Application)

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

0xa1, 0x00, // ??COLLECTION (Physical)

0x05, 0x09, // ????USAGE_PAGE (Button)

0x19, 0x01, // ????USAGE_MINIMUM (Button 1)

0x29, 0x03, // ????USAGE_MAXIMUM (Button 3)

0x15, 0x00, // ????LOGICAL_MINIMUM (0)

0x25, 0x01, // ????LOGICAL_MAXIMUM (1)

0x95, 0x03, // ????REPORT_COUNT (3)

0x75, 0x01, // ????REPORT_SIZE (1)

0x81, 0x02, // ????INPUT (Data,Var,Abs)

0x95, 0x01, // ????REPORT_COUNT (1)

0x75,?0x05, // ????REPORT_SIZE (5)

0x81, 0x03, // ????INPUT (Cnst,Var,Abs)

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,Var,Rel)

0xc0, 0xc0

}

總結

以上是生活随笔為你收集整理的HID报文讲解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。