1.1 描述符
HID 設備有如下描述符:
- HID
設備的"設備描述符"并無實際意義,沒有使用"設備描述符"來表示自己是 HID 設備。 - HID
設備只有一個配置,所以只有一個配置描述符 - 接口描述符
- 端點描述符:HID
設備有一個控制端點、一個中斷端點
對于鼠標,HOST 可以通過中斷端點讀到數據。
1.2 數據格式
1.2.1 鍵盤
通過中斷傳輸可以讀到鍵盤數據,它是 8 字節的數據,格式如下:
偏移 | 大小 | 描述 |
---|---|---|
0 | 1字節 | "Modifier |
keys status",就是ctrl、alt、shift等按鍵的狀態 | ||
1 | 1字節 | 保留 |
2 | 1字節 | 第1個按鍵的鍵值 |
3 | 1字節 | 第2個按鍵的鍵值 |
4 | 1字節 | 第3個按鍵的鍵值 |
5 | 1字節 | 第4個按鍵的鍵值 |
6 | 1字節 | 第5個按鍵的鍵值 |
7 | 1字節 | 第6個按鍵的鍵值 |
第 0 個字節中每一位都表示一個按鍵的狀態,某位等于 1
時,表示對應的按鍵被按下,格式如下:
位 | 長度 | 描述 |
---|---|---|
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) |
讀到的鍵盤數據里有 6 個按鍵值,每個按鍵值都是 8 位的數據。如果某個按鍵值不等于
0,就表示某個按鍵被按下了。按鍵值跟按鍵的對應關系,請看后面的《1.2.4 掃描碼》。
示例:按鍵"A"、"B"、"C"、"X"的按鍵值分別是 4、5、6、0x1B。
按下了"A",USB 鍵盤上報的數據為:
00 00 04 00 00 00 00 00
松開"A",USB 鍵盤上報的數據為:
00 00 00 00 00 00 00 00
按下"A"、"B",USB 鍵盤上報的數據為:
00 00 04 05 00 00 00 00
保持"A"、"B"不松開,繼續按下"C",USB 鍵盤上報的數據為:
00 00 04 05 06 00 00 00
松開"A",但是保持"B"、"C"不松開,USB 鍵盤上報的數據為:
00 00 05 06 00 00 00 00
USB
鍵盤上報的數據里,哪個按鍵先被按下,就先記錄它的按鍵值。在上面的例子里,"A"松開后只有"B"、"C"這兩個按鍵,"B"、"C"的按鍵值挪到了前面。
按下"Left shift"、并且按下"X",USB 鍵盤上報的數據為:
02 00 1B 00 00 00 00 00
USB
鍵盤只能上報 6 個按鍵值,如果有超過 6 個按鍵被按下,那么它將上報"phantom condition"(6 個按鍵值都是
1),但是"Modifier keys status"還是有效的。比如"Right Shift"被按下,另外超過 6 個的按鍵也被按下時,USB
鍵盤上報的數據為:
20 00 01 01 01 01 01 01
1.2.2 LED
我們還可控制鍵盤的 LED,需要發出一個控制傳輸請求:SetReport ,使用這個請求發送一個字節的數據。
這個字節的數據格式如下,某位為 1 時,會點亮相應的 LED:
位 | 長度 | 描述 |
---|---|---|
0 | 1 | Num |
Lock | ||
1 | 1 | Caps |
Lock | ||
2 | 1 | Scroll |
Lock | ||
3 | 1 | Compose |
4 | 1 | Kana |
5 | 1 | 保留,寫為0 |
發出的 SetReport,是一個控制傳輸的"setup packet",格式如下:
以 libusb 的函數描述它的參數,如下:
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); /* 點亮Caps Lock */
uint16_t wValue = (0x02< < 8)|0; // 0x02: 發給設備, 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
鼠標
通過中斷傳輸可以讀到鼠標數據,它是
8 字節的數據,格式如下:
偏移 | 大小 | 描述 |
---|---|---|
0 | 1字節 | |
1 | 1字節 | 按鍵狀態 |
2 | 2字節 | X |
位移 | ||
4 | 2字節 | Y |
位移 | ||
6 | 1字節或2字節 | 滾輪 |
按鍵狀態里,每一位對應鼠標的一個按鍵,等
1 時表示對應按鍵被點擊了,格式如下:
位 | 長度 | 描述 |
---|---|---|
0 | 1 | 鼠標的左鍵 |
1 | 1 | 鼠標的右鍵 |
2 | 1 | 鼠標的中間鍵 |
3 | 5 | 保留,設備自己定義bit3: |
鼠標的側邊按鍵bit4: |
X
位移、Y 位移都是 8 位的有符號數。對于 X 位移,負數表示鼠標向左移動,正數表示鼠標向右移動,移動的幅度就使用這個 8 位數據表示。對于 Y
位移,負數表示鼠標向上移動,正數表示鼠標向下移動,移動的幅度就使用這個 8 位數據表示。
1.2.4 掃描碼
USB 規范里為每個按鍵定義了 16 位的按鍵值,注意:它是 16 位的,但是 USB 鍵盤只使用 8
位表示按鍵值。所以有些按鍵需要通過"Modifier keys status"來確定。比如"Left Ctrl"的按鍵值是 224,這無法通過 8
位數據來表示,在 USB 鍵盤上報的數據里,使用第 0 字節的 bit4 來表示。
libusb
有同步接口和異步接口,異步接口可以同時支持多個鼠標使用。
-
接口
+關注
關注
33文章
8600瀏覽量
151166 -
usb
+關注
關注
60文章
7945瀏覽量
264687 -
HID
+關注
關注
2文章
130瀏覽量
46612
發布評論請先 登錄
相關推薦
評論