本章主要围绕BLE的HOGH进行说明,网上很多文档讲到HID都要说到USB的HID,让初学者一开始既要看理解蓝牙GATT Service的概念,又要去理解USB的端点概念。实话来说本人刚去学习时也经常需要尝试去理解这两者的关系,很是头大。
针对这一情况,本文主要围绕于蓝牙HOGH来对HID进行说明,让大家对这个东西有个整体认识,具体像report id等USB细节东西给出如何查找USB SPEC的方法。
HID主要完成的工作就是完成:鼠标/键盘等HID和PC/手机等主机的数据通信,数据通信的方向有单向也有双向的。
HID设备通讯协议有两种,分别是HID Boot Protocol和HID Report Protocol。其中HID Boot Protocol是一种通用协议,可用于交换所有HID设备的数据,但是它不支持多个并发数据输入输出;而HID Report Protocol是一种自定义协议,不同的HID设备可以使用不同格式的报告描述符和报告协议来进行数据传输,并支持多个并发数据输入输出。
数据包格式需求-Report Map
要实现HID数据的传输,必须两者协商好一个数据包格式。而HID设备的种类多种多样,所要上报的数据格式/长度各不相同,如只有3个按键的键盘,或者全功能键盘,其所需发送的数据格式是不同的。
HID设备要满足各种稀奇古怪的需求。在HID中是通过report map来定义数据包格式。


一个鼠标的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上报,主机就会按照这个格式解析数据。

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

那按照大家的理解,那不同功能设备发不同数据包不就好了,直接定义多个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的数据包格式各不相同,长度也各不相同。

数据包如何传输-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。

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

在看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个字节,多的字节不管。

具体的格式如Report Map所示(这里后面多的字节不管):
键盘Input格式如下,一共8个字节,多的字节不管。

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

具体的格式如Report Map所示:
模式选择-Protocol Mode(0x2A4E)
通常来讲,设备可能同时支持Report Protocol和Boot Protocol,Report Protocol可能支持更多灵活的功能应用,也可以通过减少包长度来减少功耗。
那么到底什么使用Boot协议呢?当主机设置了Protocol Mode为Boot模式时,只允许发送Boot协议的数据。所有Report协议数据主机都不响应。

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

版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/14222.html