2025年蓝牙HID说明

蓝牙HID说明蓝牙 HID 说明 本章主要围绕 BLE 的 HOGH 进行说明 网上很多文档讲到 HID 都要说到 USB 的 HID 让初学者一开始既要看理解蓝牙 GATT Service 的概念 又要去理解 USB 的端点概念 实话来说本人刚去学习时也经常需要尝试去理解这两者的关系 很是头大 针对这一情况

大家好,我是讯享网,很高兴认识大家。

蓝牙HID说明

本章主要围绕BLE的HOGH进行说明,网上很多文档讲到HID都要说到USB的HID,让初学者一开始既要看理解蓝牙GATT Service的概念,又要去理解USB的端点概念。实话来说本人刚去学习时也经常需要尝试去理解这两者的关系,很是头大。

针对这一情况,本文主要围绕于蓝牙HOGH来对HID进行说明,让大家对这个东西有个整体认识,具体像report id等USB细节东西给出如何查找USB SPEC的方法。

HID主要完成的工作就是完成:鼠标/键盘等HID和PC/手机等主机的数据通信,数据通信的方向有单向也有双向的。

HID设备通讯协议有两种,分别是HID Boot ProtocolHID Report Protocol。其中HID Boot Protocol是一种通用协议,可用于交换所有HID设备的数据,但是它不支持多个并发数据输入输出;而HID Report Protocol是一种自定义协议,不同的HID设备可以使用不同格式的报告描述符和报告协议来进行数据传输,并支持多个并发数据输入输出。

HID Report Protocol

数据包格式需求-Report Map

要实现HID数据的传输,必须两者协商好一个数据包格式。而HID设备的种类多种多样,所要上报的数据格式/长度各不相同,如只有3个按键的键盘,或者全功能键盘,其所需发送的数据格式是不同的。

HID设备要满足各种稀奇古怪的需求。在HID中是通过report map来定义数据包格式。

image-20230914192931449
讯享网

image-20230914193015577

一个鼠标的Report Map长成下面这样。

下面这种Report Map如何看呢,HID Usage Tables 1.4 | USB-IF,其实就是对照这个文档来看。一般我们用工具生成的Report Map都有注释,实话说我到现在还没特别去看里面的数据定义,这个表也是网上随便下载的。

要看懂这个Report Map,不在本文的范围内,可以去看HID 报告描述 2_hid用图表_饭小粒的博客-CSDN博客这个文章,讲得不错。

这里直接给结果,就是上报5个字节的数据,有鼠标的按键(其实用了5bit,Button1-5),还有数据XYZ坐标移动数据和Wheel滚轮数据。在特定的Characteristic上报,主机就会按照这个格式解析数据。

image-20230914203227230

 /* mouse */ 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x05, 0x09, // Usage Page (Button) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x19, 0x01, // Usage Minimum (Button 1) 0x29, 0x05, // Usage Maximum (Button 5) 0x75, 0x01, // Report Size (1) 0x95, 0x05, // Report Count (5) 0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x03, // Report Count (3) 0x81, 0x03, // Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x01, // Usage Page (Generic Desktop) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x75, 0x08, // Report Size (8) 0x95, 0x03, // Report Count (3) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x38, // Usage (Wheel) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0xC0, // End Collection 0xC0, // End Collection 

讯享网

复合设备需求-Report ID

HID设备多种多样,现在的产品已经不像是上述的简单HID设备了,而是类似下图这种复合功能设备。既有基本的鼠标/键盘功能,还有触摸板等功能。也就是表现成多种不同功能的设备。

image-20230914194138471

那按照大家的理解,那不同功能设备发不同数据包不就好了,直接定义多个Report Map不就好了?但是需要注意的是,一个Report Map对应蓝牙的一个Characteristic节点,但是在USB却是对应一个Interface。

蓝牙的Service下的Characteristic的数量其实还好,基本都是软件做的,但是USB设备的Interface/Endpoint基本都是硬件做的,也就是说数量是有限的,如果设备只有1个Endpoint的话,要实现4个功能咋办。

HID在Report Map中引入了Report ID的概念,也就是1个Report Map中可以有多个Report ID,这样只要在每笔包之前加入Report ID,就可以在一个Characteristic/Endpoint中实现多种功能需求。

同样拿上面数据的例子来说,数据格式不变的情况下,只是加了一个Report ID (4),数据包格式如下,只是最开始多了一个字节的Report ID,值为4,其他不变。

同一个Report Map多个Report ID的数据包格式各不相同,长度也各不相同。

image-20230914203612997

讯享网 /* mouse */ 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x85, 0x04, // Report ID (4) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x05, 0x09, // Usage Page (Button) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x19, 0x01, // Usage Minimum (Button 1) 0x29, 0x05, // Usage Maximum (Button 5) 0x75, 0x01, // Report Size (1) 0x95, 0x05, // Report Count (5) 0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x03, // Report Count (3) 0x81, 0x03, // Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x01, // Usage Page (Generic Desktop) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x75, 0x08, // Report Size (8) 0x95, 0x03, // Report Count (3) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x38, // Usage (Wheel) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0xC0, // End Collection 0xC0, // End Collection 

数据包如何传输-Report(0x2A4D)

BLE是通过HID Service来实现数据收发的,蓝牙SPEC包含这两个:Human Interface Device Service | Bluetooth® Technology Website和HID over GATT Profile | Bluetooth® Technology Website,一个是对Service的描述,另外一个是Profile的描述。

数据是通过HID Service中的Report Characteristic来收发的。和USB不同,蓝牙的Characteristic资源充足,所以每个Report ID独有一个。但是同样的,蓝牙没有Interface的概念,只维护了一张Report Map。(如果有多个HID Service会怎么样?)

主要就是一个Report Reference Descriptor(0x2908)节点会声明其Report ID是多少,然后Value节点根据双向传输还是单向传输,定义其属性。

需要注意的是,Report Type定义的方向性一般只定义Input或Output,并不能同时使用。当一个Report ID既支持Input又支持Output时,需要声明2个Report Characteristic,其Report ID相同,而Report Type一个是Input,一个是Output。

image-20230914204935414

Report Map如何传输-Report Map(0x2A4B)

Report Map在蓝牙传输是通过Report Map(0x2A4B) Characteristic来传输的,直接通过其Value节点传输即可。

image-20230914205740320

HID Boot Protocol

在看HID的时候,不可避免就会看到Boot协议的说明,这套机制独立于Report Map机制。这个东西个人感觉就是满足简易Host驱动需要的场景。

什么意思呢,其实看完Report Map后,你会发现这个东西非常灵活啊,对于软件而言,越是灵活的东西其实越难实现。想象一下,你来做PC端的驱动,要识别各种各样的设备,并响应不同设备的传输协议,那这个驱动会写得非常复杂,所需的Code Size和RAM资源会很庞大,而且也容易有bug。

HID引入了Boot模式,在这我称之为简易模式,这个模式只支持满足主机基本操作需要的鼠标和键盘功能设备。其不允许你使用复杂的Report Map来声明你的数据包格式,而且事先约定好一个固定的包格式,设备必须按照这个格式来上报数据。

数据包格式

Boot模式一共提供了3种数据包格式,两个Input,一个Output。详细解析可以看码农的自我修养 - USB键盘和鼠标的数据包格式_键盘协议_夜流冰的博客-CSDN博客和HID设备详解_笔记大全_设计学院 (python100.com)。

鼠标Input格式如下,一共3个字节,多的字节不管。

image-20230915193935516

具体的格式如Report Map所示(这里后面多的字节不管):

 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x05, 0x09, // Usage Page (Button) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x19, 0x01, // Usage Minimum (Button 1) 0x29, 0x05, // Usage Maximum (Button 5) 0x75, 0x01, // Report Size (1) 0x95, 0x05, // Report Count (5) 0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x03, // Report Count (3) 0x81, 0x03, // Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x01, // Usage Page (Generic Desktop) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x75, 0x08, // Report Size (8) 0x95, 0x03, // Report Count (3) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x09, 0x38, // Usage (Wheel) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x81, 0x06, // Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0xC0, // End Collection 0xC0, // End Collection 

键盘Input格式如下,一共8个字节,多的字节不管。

image-20230915193954025

键盘Output格式如下,一共1个字节,主要是灯效信息。

image-20230914212229292

具体的格式如Report Map所示:

讯享网 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0xE0, // Usage Minimum (Keyboard Left Control) 0x29, 0xE7, // Usage Maximum (Keyboard Right GUI) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x81, 0x01, // Input (Cnst,Ary,Abs) 0x19, 0x00, // Usage Minimum (Undefined) 0x2A, 0xFF, 0x00, // Usage Maximum 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8) 0x95, 0x06, // Report Count (6) 0x81, 0x00, // Input (Data,Ary,Abs) /* LED */ 0x05, 0x08, // Usage Page (LEDs) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x05, // Report Count (5) 0x91, 0x02, // Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 0x95, 0x03, // Report Count (3) 0x91, 0x01, // Output (Cnst,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 0xC0, // End Collection 

模式选择-Protocol Mode(0x2A4E)

通常来讲,设备可能同时支持Report Protocol和Boot Protocol,Report Protocol可能支持更多灵活的功能应用,也可以通过减少包长度来减少功耗。

那么到底什么使用Boot协议呢?当主机设置了Protocol Mode为Boot模式时,只允许发送Boot协议的数据。所有Report协议数据主机都不响应。

image-20230914212609128

数据传输

针对上述三种数据包格式,分别在三个Characteristic上发送/接收。分别是:Boot Keyboard Input Report(0x2A22)Boot Keyboard Output Report(0x2A32)Boot Mouse Input Report(0x2A33)

image-20230914213013522

小讯
上一篇 2025-03-01 20:35
下一篇 2025-01-16 20:19

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/126211.html