协议架构

HID角色: HID 分为 host/device,游戏主机跟游戏手柄,那么游戏手柄是 hid device 角色,游戏主机是hid host
hid host 角色。
13.1.2 HID
HID report:
蓝牙 HID report 分为三种:
1) Input report:从 hid device 发送给 hid host 的封包
2) Output report:从 hid host 发送给 hid device 的封包
可以看出以上两种封包的 input/output 的方向都是就 hid host 而言的,而且要求低时延
3) Feature report:特性封包,是双向的
HID 逻辑链路:
HID基于L2CAP有两个通道
HID_CONTROL:PSM是0x0011,用来传输控制数据
HID_Interruput:PSM是0x0013,用来传输一些自定义数据
HID 封包格式命令
HID 的封包格式 header field 只有一个 byte,4bit 的 message type,4bit 的 parameter

其中灰色部分为舍弃掉了,以后不再使用
HANDSHAKE 封包
这个消息是只能从 hid device 的 control channel 发出,用于回复以下封包
1) SET_REPORT, SET_IDLE(被舍弃) and SET_PROTOCOL requests
2) GET_REPORT, GET_PROTOCOL and GET_IDLE requests if an error is detected in the parameters of the initial request
3) a request with an unsupported message type

HID_CONTROL 封包
device 和host都可以发

其中 NOP/HARD RESET/SOFT RESET 被舍弃了,不再使用
1) SUSPEND/EXIT SUSPEND
这个是 hid host 发送给 hid device 进入省电模式/退出省电模式的命令,比如 hid host 发送给 hid mouse 发送 SUSPEND 的时候, mouse 关闭 LED 等进入省电模式或者 hid host 发送给 hid keyboard SUSPEND 的时候, keyboard 降低扫描按键的频率
2) VITUAL_CABLE_UNPLUG
这个命令是双向命令, hid host 可以发送给 hid device,同样 hid device 也可以发送给 hid host,收到后断开连线
GET_REPORT 封包
这个封包是 hid host 发送给 hid device 的消息。 hid device 接受到这个封包后,需要在 control 通道上回复包含 requeset 信息的 DATA type 封包


SET_REPORT 封包
hid host 发送给 hid device 的消息

GET_PROTOCOL 封包
host发给Device
用来获取 Bluetooth HID device 的 Protocol Mode,然后 Bluetooth HID device response 一个 DATA payload 说明当前的 Protocol Mode。

SET_PROTOCOL 封包
host发给Device

DATA 封包
可以是host发给Device 也可以是 Device 发给host

HID descriptor
HID协议详解 - Report Descriptor报告描述符构建与解析 这个写的十分详细。
这是一份hid 鼠标的descriptor
c
static uint8_t hid_device_descriptor[] =
{
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)*/
0x19,0x01, /*USAGE_MINIMUM (Button 1)*/
0x29,0x03, /*USAGE_MAXIMUM (Button 3)*/
0x15,0x00, /*LOGICAL_MINIMUM (0)*/
0x25,0x01, /*LOGICAL_MAXIMUM (1)*/
0x95,0x03, /*REPORT_COUNT (3)*/
0x75,0x01, /*REPORT_SIZE (1)*/
0x81,0x02, /*INPUT (Data,Var,Abs)*/
0x95,0x01, /*REPORT_COUNT (1)*/
0x75,0x05, /*REPORT_SIZE (5)*/
0x81,0x03, /*INPUT (Cnst,Var,Abs)*/
0x05, 0x01, /*USAGE_PAGE (Generic Desktop)*/
0x09, 0x30, /*USAGE (X)*/
0x09, 0x31, /*USAGE (Y)*/
0x15, 0x81, /*LOGICAL_MINIMUM (-127)*/
0x25, 0x7f, /*LOGICAL_MAXIMUM (127)*/
0x75, 0x08, /*REPORT_SIZE (8)*/
0x95, 0x02, /*REPORT_COUNT (2)*/
0x81, 0x06, /*INPUT (Data,Var,Rel)*/
0xc0, /*END_COLLECTION*/
0xc0, /*END_COLLECTION*/
};
x05,0x01, /USAGE_PAGE (Generic Desktop) / -》这个就是整个大类,其中 0x05 就是代表USAGE_PAGE,其中 0x01 告知是桌面应用的。
0x09,0x02, /USAGE (Mouse) / ->Mouse 的 USAGE
0xa1,0x01, /COLLECTION (Application) / -> 开始一个 Application 小类
0x09,0x01, /USAGE (Pointer) / ->小类是指针
0xa1,0x00, /COLLECTION (Physical) / ->在开一个小类
0x05,0x09, /USAGE_PAGE (Button) /
0x19,0x01, /USAGE_MINIMUM (Button 1) /
0x29,0x03, /USAGE_MAXIMUM (Button 3) /
0x15,0x00, /LOGICAL_MINIMUM (0) /
0x25,0x01, /LOGICAL_MAXIMUM (1) /
0x95,0x03, /REPORT_COUNT (3) /
0x75,0x01, /REPORT_SIZE (1) /
0x81,0x02, /INPUT (Data,Var,Abs) /
以上是 button,有 3 个,占 3 个 bit,也就是鼠标的左键,中间滚轮,邮件
0x95,0x01, /REPORT_COUNT (1) /
0x75,0x05, /REPORT_SIZE (5) /
0x81,0x03, /INPUT (Cnst,Var,Abs) /
以上是 button,有 1 个,占 5 个 bit,没有实质性作用
0x05, 0x01, /USAGE_PAGE (Generic Desktop) /
0x09, 0x30, /USAGE (X) /
0x09, 0x31, /USAGE (Y) /
0x15, 0x81, /LOGICAL_MINIMUM (-127) /
0x25, 0x7f, /LOGICAL_MAXIMUM (127) /
0x75, 0x08, /REPORT_SIZE (8) /
0x95, 0x02, /REPORT_COUNT (2) /
0x81, 0x06, /INPUT (Data,Var,Rel) /
以上是鼠标 X,Y 坐标,有 2 个 byte,范围是-127~127
0xc0, /END_COLLECTION / ->结束最内层小类
0xc0, /END_COLLECTION/ ->结束外层类




