HID协议是什么意思

描述

对于 USB 接口的 HID 设备,有一套协议。

1.1 描述符

HID 设备有如下描述符:

接口

  • HID
    设备的"设备描述符"并无实际意义,没有使用"设备描述符"来表示自己是 HID 设备。
  • HID
    设备只有一个配置,所以只有一个配置描述符
  • 接口描述符
    • bInterfaceClass
      为 3,表示它是 HID 设备
    • bInterfaceSubClass
      是 0 或 1,1 表示它支持"Boot Interface"(表示 PC 的 BIOS 能识别、使用它),0
      表示必须等操作系统启动后通过驱动程序来使用它。
    • bInterfaceProtocol:0-None,
      1-键盘, 2-鼠标
  • 端点描述符:HID
    设备有一个控制端点、一个中断端点

接口

对于鼠标,HOST 可以通过中断端点读到数据。

1.2 数据格式

1.2.1 键盘

通过中断传输可以读到键盘数据,它是 8 字节的数据,格式如下:

偏移大小描述
01字节"Modifier
keys status",就是ctrl、alt、shift等按键的状态
11字节保留
21字节第1个按键的键值
31字节第2个按键的键值
41字节第3个按键的键值
51字节第4个按键的键值
61字节第5个按键的键值
71字节第6个按键的键值

第 0 个字节中每一位都表示一个按键的状态,某位等于 1
时,表示对应的按键被按下,格式如下:

长度描述
01Left
Ctrl
11Left
Shift
21Left
Alt
31Left
GUI(Windows/Super key)
41Right
Ctrl
51Right
Shift
61Right
Alt
71Right
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:

长度描述
01Num
Lock
11Caps
Lock
21Scroll
Lock
31Compose
41Kana
51保留,写为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 字节的数据,格式如下:

偏移大小描述
01字节
11字节按键状态
22字节X
位移
42字节Y
位移
61字节或2字节滚轮

按键状态里,每一位对应鼠标的一个按键,等
1 时表示对应按键被点击了,格式如下:

长度描述
01鼠标的左键
11鼠标的右键
21鼠标的中间键
35保留,设备自己定义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
有同步接口和异步接口,异步接口可以同时支持多个鼠标使用。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分