對于 USB 接口的 HID 設(shè)備,有一套協(xié)議。
1.1 描述符
HID 設(shè)備有如下描述符:
- HID
設(shè)備的"設(shè)備描述符"并無實(shí)際意義,沒有使用"設(shè)備描述符"來表示自己是 HID 設(shè)備。 - HID
設(shè)備只有一個配置,所以只有一個配置描述符 - 接口描述符
- bInterfaceClass
為 3,表示它是 HID 設(shè)備 - bInterfaceSubClass
是 0 或 1,1 表示它支持"Boot Interface"(表示 PC 的 BIOS 能識別、使用它),0
表示必須等操作系統(tǒng)啟動后通過驅(qū)動程序來使用它。 - bInterfaceProtocol:0-None,
1-鍵盤, 2-鼠標(biāo)
- bInterfaceClass
- 端點(diǎn)描述符:HID
設(shè)備有一個控制端點(diǎn)、一個中斷端點(diǎn)
對于鼠標(biāo),HOST 可以通過中斷端點(diǎn)讀到數(shù)據(jù)。
1.2 數(shù)據(jù)格式
1.2.1 鍵盤
通過中斷傳輸可以讀到鍵盤數(shù)據(jù),它是 8 字節(jié)的數(shù)據(jù),格式如下:
偏移 | 大小 | 描述 |
---|---|---|
0 | 1字節(jié) | "Modifier |
keys status",就是ctrl、alt、shift等按鍵的狀態(tài) | ||
1 | 1字節(jié) | 保留 |
2 | 1字節(jié) | 第1個按鍵的鍵值 |
3 | 1字節(jié) | 第2個按鍵的鍵值 |
4 | 1字節(jié) | 第3個按鍵的鍵值 |
5 | 1字節(jié) | 第4個按鍵的鍵值 |
6 | 1字節(jié) | 第5個按鍵的鍵值 |
7 | 1字節(jié) | 第6個按鍵的鍵值 |
第 0 個字節(jié)中每一位都表示一個按鍵的狀態(tài),某位等于 1
時,表示對應(yīng)的按鍵被按下,格式如下:
位 | 長度 | 描述 |
---|---|---|
0 | 1 | Left |
Ctrl | ||
1 | 1 | Left |
Shift | ||
2 | 1 | Left |
Alt | ||
3 | 1 | Left |
GUI(Windows/Super key) | ||
4 | 1 | Right |
Ctrl | ||
5 | 1 | Right |
Shift | ||
6 | 1 | Right |
Alt | ||
7 | 1 | Right |
GUI(Windows/Super key) |
讀到的鍵盤數(shù)據(jù)里有 6 個按鍵值,每個按鍵值都是 8 位的數(shù)據(jù)。如果某個按鍵值不等于
0,就表示某個按鍵被按下了。按鍵值跟按鍵的對應(yīng)關(guān)系,請看后面的《1.2.4 掃描碼》。
示例:按鍵"A"、"B"、"C"、"X"的按鍵值分別是 4、5、6、0x1B。
按下了"A",USB 鍵盤上報的數(shù)據(jù)為:
00 00 04 00 00 00 00 00
松開"A",USB 鍵盤上報的數(shù)據(jù)為:
00 00 00 00 00 00 00 00
按下"A"、"B",USB 鍵盤上報的數(shù)據(jù)為:
00 00 04 05 00 00 00 00
保持"A"、"B"不松開,繼續(xù)按下"C",USB 鍵盤上報的數(shù)據(jù)為:
00 00 04 05 06 00 00 00
松開"A",但是保持"B"、"C"不松開,USB 鍵盤上報的數(shù)據(jù)為:
00 00 05 06 00 00 00 00
USB
鍵盤上報的數(shù)據(jù)里,哪個按鍵先被按下,就先記錄它的按鍵值。在上面的例子里,"A"松開后只有"B"、"C"這兩個按鍵,"B"、"C"的按鍵值挪到了前面。
按下"Left shift"、并且按下"X",USB 鍵盤上報的數(shù)據(jù)為:
02 00 1B 00 00 00 00 00
USB
鍵盤只能上報 6 個按鍵值,如果有超過 6 個按鍵被按下,那么它將上報"phantom condition"(6 個按鍵值都是
1),但是"Modifier keys status"還是有效的。比如"Right Shift"被按下,另外超過 6 個的按鍵也被按下時,USB
鍵盤上報的數(shù)據(jù)為:
20 00 01 01 01 01 01 01
1.2.2 LED
我們還可控制鍵盤的 LED,需要發(fā)出一個控制傳輸請求:SetReport ,使用這個請求發(fā)送一個字節(jié)的數(shù)據(jù)。
這個字節(jié)的數(shù)據(jù)格式如下,某位為 1 時,會點(diǎn)亮相應(yīng)的 LED:
位 | 長度 | 描述 |
---|---|---|
0 | 1 | Num |
Lock | ||
1 | 1 | Caps |
Lock | ||
2 | 1 | Scroll |
Lock | ||
3 | 1 | Compose |
4 | 1 | Kana |
5 | 1 | 保留,寫為0 |
發(fā)出的 SetReport,是一個控制傳輸?shù)?setup packet",格式如下:
以 libusb 的函數(shù)描述它的參數(shù),如下:
int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout);
/* 示例代碼 */
unsigned char data = (1< < 1); /* 點(diǎn)亮Caps Lock */
uint16_t wValue = (0x02< < 8)|0; // 0x02: 發(fā)給設(shè)備, 0: report ID
uint16_t wIndex = 0; // 一般是0, the interface number of the USB keyboard
libusb_control_transfer(dev_handle, 0x21, 0x09, wValue, wIndex, &data, 1, timeout);
1.2.3
鼠標(biāo)
通過中斷傳輸可以讀到鼠標(biāo)數(shù)據(jù),它是
8 字節(jié)的數(shù)據(jù),格式如下:
偏移 | 大小 | 描述 |
---|---|---|
0 | 1字節(jié) | |
1 | 1字節(jié) | 按鍵狀態(tài) |
2 | 2字節(jié) | X |
位移 | ||
4 | 2字節(jié) | Y |
位移 | ||
6 | 1字節(jié)或2字節(jié) | 滾輪 |
按鍵狀態(tài)里,每一位對應(yīng)鼠標(biāo)的一個按鍵,等
1 時表示對應(yīng)按鍵被點(diǎn)擊了,格式如下:
位 | 長度 | 描述 |
---|---|---|
0 | 1 | 鼠標(biāo)的左鍵 |
1 | 1 | 鼠標(biāo)的右鍵 |
2 | 1 | 鼠標(biāo)的中間鍵 |
3 | 5 | 保留,設(shè)備自己定義bit3: |
鼠標(biāo)的側(cè)邊按鍵bit4: |
X
位移、Y 位移都是 8 位的有符號數(shù)。對于 X 位移,負(fù)數(shù)表示鼠標(biāo)向左移動,正數(shù)表示鼠標(biāo)向右移動,移動的幅度就使用這個 8 位數(shù)據(jù)表示。對于 Y
位移,負(fù)數(shù)表示鼠標(biāo)向上移動,正數(shù)表示鼠標(biāo)向下移動,移動的幅度就使用這個 8 位數(shù)據(jù)表示。
1.2.4 掃描碼
USB 規(guī)范里為每個按鍵定義了 16 位的按鍵值,注意:它是 16 位的,但是 USB 鍵盤只使用 8
位表示按鍵值。所以有些按鍵需要通過"Modifier keys status"來確定。比如"Left Ctrl"的按鍵值是 224,這無法通過 8
位數(shù)據(jù)來表示,在 USB 鍵盤上報的數(shù)據(jù)里,使用第 0 字節(jié)的 bit4 來表示。
libusb
有同步接口和異步接口,異步接口可以同時支持多個鼠標(biāo)使用。
-
接口
+關(guān)注
關(guān)注
33文章
8575瀏覽量
151014 -
usb
+關(guān)注
關(guān)注
60文章
7936瀏覽量
264463 -
HID
+關(guān)注
關(guān)注
2文章
130瀏覽量
46606
發(fā)布評論請先 登錄
相關(guān)推薦
評論