写在前面
本文简单描述从HCI_Reset到完成ACL连接的流程.
流程
重置蓝牙
一切从HCI_Reset开始: 
Android设备重启蓝牙调用该命令.
读取写入配置信息
读取版本信息: 
读取当前设备的地址: 
读取本地设备支持的命令: 
开启简单配对模式: 
有关于Simple Pairing Mode主要有以下关联模型:
- Just Works
- 当两个设备中至少有一个设备即没有显示能力也没有输入能力(即至少一个设备的IO能力是NoInputNoOutput), 使用这个模型, 在配对过程中不需要任何的用户交互(但也是可能会有交互的, 主要还是看上层应用如何实现, 比如在连接前需要用户确认连接). 常见的应用场景就是手机和耳机的连接(手机端可能会提示用户确认连接).
- Numeric Comparison
- 当两个设备都可以显示6位数字且用户可以输入
是或否时(即IO能力都是DisplayYesNo), 使用这种模型, 设备会显示数字代码或者秘钥, 用户需要在两台设备上确认来完成配对. 常见的应用场景就是手机和电脑连接.
- 当两个设备都可以显示6位数字且用户可以输入
- Out of Band (OOB) Pairing
- 使用这种模型, 利用out-of-band(如NFC), 安全地交换配对信息
- Passkey Entry
- 两个设备中有一个设备有输入能力但是没有显示能力, 另一个设备有显示能力(即一个设备IO能力为KeybordOnly, 另一个设备至少有Display能力), 此时使用这种模型, 拥有输入能力的设备需要用户输入另一个设备所显示的passkey. 常见的应用场景是电脑连接键盘.
设置Host支持的事件: 
写入链接策略: 
设置查询结果事件返回格式: 
设置Page Scan类型: 
设置Inquiry Scan类型: 
设置设备类型: 
设置连接超时时间: 
读取本地设备名称, 返回空: 
写入本地设备名: 
配置查询扫描的interval和window大小: 
配置连接扫描的interval和window大小: 
设置当前设备的状态为可查询可连接: 
开启扫描
开启查询扫描: 
取消查询扫描:
通常在进行连接前可以取消查询扫描, 这个操作比较耗时
删除指定设备的link key: 
获取远程设备名:
HCI_Command_Status表示这个命令成功执行.
远程设备通知其所支持的特性: 
远程设备响应获取名称: 
创建连接
接下来开始创建连接: 
创建连接完成, 过程中并未请求认证(认证的请求可以在连接过程中, 也可以在连接后), 响应携带Connection_Handle表示此次连接: 
读取远程设备的版本信息: 
请求认证
发起认证请求: 
Controller请求link key(携带远程设备的BR_ADDR): 
不存在link key: 
请求本地设备的IO能力: 
回复当前设备的IO能力: 
有关IO能力
IO能力用于确定配对过程中使用的身份验证方法. 由设备的输入输出能力组合而成.
输入能力:
- No input: 设备没有能力表示
是或否 - Yes/No: 设备至少有两个按钮可以表示
是或否, 或者有其他机制让用户表示是或否(例如在指定时间内按下按钮表示是, 否则表示否) - Keybord: 设备需要有数字键盘可以输入0-9和确认, 并且至少有两个按钮可以表示
是或否(或者其他机制让用户表示是或否)
输出能力:
- No output: 设备没有能力显示或传递6位十进制数
- Numeric output: 设备有能力显示或传递6位十进制数
根据输入和输出能力组合可以得到IO能力:
- NoInputNoOutput: No input + No output 或 Yes/No + No output
- 设备在配对过程中既不能显示也不能输入
- DisplayOnly: No input + Numeric output
- 设备在配对过程中只能显示数值
- DisplayYesNo: Yes/No + Numeric output
- 设备在配对过程中可以显示数值, 也允许用户确认或拒绝显示的值
- KeyboardOnly: Keybord + No output
- 设备只有输入能力
- KeyboardDisplay: Keybord + Numeric output
- 设备即可输入也有输出, 配对过程中用户可以输入数值进行认证
终于接收到了读取远程设备的版本信息, 可以看到协议栈是5.0: 
请求远程设备支持的特性: 
远程设备IO能力信息,(连接的是耳机): 
远程设备响应了支持的特性: 
发起用户确认请求事件, 携带了数值, Host应该返回HCI_User_Confirmation_Request_Reply或者 HCI_User_Confirmation_Request_Negative_Reply. 如果Host具有输出能力, 应该展示这个数值(DisplayYesNo or KeyboardOnly), 如果Host没有输入输出能力, 那么应该直接返回 HCI_User_Confirmation_Request_Reply: 
用户确认请求, host返回请求确认(我用Android设备连接Airpods pro, 并没有显示数字, 耳机没有输入输出能力, 手机端显示数字也没什么意义): 
完成配对: 
通知为这个连接生成了新的link key: 
最终完成认证: 
开启加密连接: 
断开连接
最后本地主动断开连接: 
zabbits