之前一段时间学习了HOGP profile。Specification写得很简单,主要是说明它的一些基本要求。而在代码方面,它的内容也并不是非常多。正如它的名字一样——HID over GATT Profile,它是利用LE的基本协议GATT(通用属性协议)来实现HID host与Device的交互的。总的来说,工作在LE模式的HID设备从连接建立到通信的过程大致是这样的:
1.在设备发现阶段,HID(以下均指LE的HID设备)device需要在它的advertisement中包含HID的相关信息,如HID service的UUID、设备Appearance、设备Local Name和Class of Device等;这样,HID host在扫描中就可以得知对端为HID设备了;
2.在连接建立阶段,用户通过UI触发连接的建立过程;由于前面检测到对方为HID设备,连接建立会进入到HID的state machine当中,以建立HID连接为最终目标;这一过程又分为下面几个阶段:
1)GATT连接建立阶段;既然是HID over GATT Profile,必须先由GATT来探探对方的虚实,看看它是否符合HOGP的规范。这里会涉及到L2CAP的连接建立与GATT的disovery过程;
2)SMP通道加密阶段;其实这是每对LE设备建立连接的必经之路,好歹得加密防止简单的攻击。由于L2CAP连接建立是由HOGP触发的,因此在这个过程中会有SMP的加密过程。之前一篇博客层介绍过,SMP可以在createBond的过程中触发,实现整个配对、加密过程,但那是在非HID设备的情况下进行的;
3)HID服务搜索阶段与配置;虽然第一阶段中GATT已经完成了service discovery,但是HID还需要将必要的属性从GATT的cache中提取出来,存到自己的database中;此外还有一些额外的属性值(characteristic value)需要读取,如用于解析按键的Report Map;最后,对某些属性的configuration descriptor进行配置,设置如notification、indication等;
4)HID设备注册阶段;这是HID代码向系统注册uhid设备的过程。说实话这一部分我还不是很了解,大概就是注册了一个虚拟设备节点,同时备案了HID的Report Map;以后每次有HID消息过来,只要将它作为Input事件写入这个节点的文件描述符即可,剩下的事件处理kernel会来帮我们完成;
5)HID设备通信阶段;这里将根据之前的第三阶段的配置结果进行。如hid device将事件通过notification的方式发送给hid host,而host根据第三阶段的搜索结果进行相应的处理。
下面,我以一个LE键盘为例,简单介绍下Bluedroid(不是bluez!!!)中HOGP的代码流程。
首先,请允许我放出createBond过程中的一段代码,一切皆是由它引起的