蓝牙BLE连接技术详解:扫描、广播与空包交互
蓝牙BLE连接技术详解:扫描、广播与空包交互
随着蓝牙BLE设备的普及,蓝牙连接问题一直是蓝牙开发的重要一环。本文将从BLE的开启、扫描、广播类型、连接参数和流程等多个方面进行详细讲解,并结合具体案例和代码示例,帮助读者更好地理解BLE连接过程中的问题和解决方案。
一、BLE的开启
蓝牙service中在开启蓝牙时会读取(Android 12之前在package/app/bluetooth/res/value/config.xml,13在package/modules下)中的协议配置文件,去开启对应的协议service,BLE对应GATT,强制启用,源码流程中配置关闭GATT蓝牙启动不了,开启蓝牙仍然是BTSNOOP中下发一个HCI_RESET。
二、BLE扫描
发起扫描的接口有两个,一个是系统设置中调用的startdiscovery,传统蓝牙和BLE一起扫描,协议栈system/bt/stack/btm/btm_inq.cc可以改掉只扫描传统蓝牙,扫描结果都是从action_found广播发出,另一个就是各种BLE应用调用的GATT startscan,只用来发现外围的BLE设备广播,通过onscanResultBLE回调扫描结果,扫描指令下发前会通过Command: HCI_LE_Set_Scan_Parameters设置窗口、间隔、过滤policy等,这块实际应用遇到问题例如:外围设备广播以20ms间隔广播一次,中心设备设置扫描间隔100ms,扫描窗口为10ms,可能出现扫描设备要很久,或者某一次扫描无法扫到该设备,扫描的窗口碰不上对方设备广播的频率。扫描开启指令则通过Command: HCI_LE_Set_Scan_Enable下发,另外BLE也支持extends类型广播,相比传统BLE广播,支持的数据大小和参数都有变化。
三、BLE广播类型
BLE设备广播地址类型主要就是public address和random private address,由BLE是否支持私有模式决定。BLE广播通过event: HCI_LE_Advertising_Report上报到host,Event_Type标注了广播类型,协议栈也有对应的解析,应用层也可以取到该类型
system\bt\stack\btm\btm_ble_gap.cc
if (legacy_evt_type == 0x00) { // ADV_IND;
event_type = 0x0013;
} else if (legacy_evt_type == 0x01) { // ADV_DIRECT_IND;
event_type = 0x0015;
} else if (legacy_evt_type == 0x02) { // ADV_SCAN_IND;
event_type = 0x0012;
} else if (legacy_evt_type == 0x03) { // ADV_NONCONN_IND;
event_type = 0x0010;
} else if (legacy_evt_type == 0x04) { // SCAN_RSP;
// We can't distinguish between "SCAN_RSP to an ADV_IND", and "SCAN_RSP to
// an ADV_SCAN_IND", so always return "SCAN_RSP to an ADV_IND"
event_type = 0x001B;
- ADV_IND:可连接广播
- ADV_DIRECT_IND :定向广播,直连广播
- ADV_SCAN_IND:扫描请求广播,获取对方更多数据,对应scn rsp
- ADV_NONCONN_IND:不可连接广播,只用来广播一些特定数据
- SCAN_RSP:回应scan req
四、BLE连接参数和流程
选择扫描到的可连接广播,创建连接,蓝牙协议5.4
连接完成事件会在触发创建连接后扫描到对方可连接广播并下发connect_ind,触发双方连接状态
完整连接流程图
五、结合协议具体看一下空包
对方设备发送可连接广播
整个连接包的交互主要为下图:在广播channel上收到可连接广播包,接收到后需在T_IFS(150us)内发出connect_ind连接包,然后在时间transmitWindowDelay+transmitWindowOffset到ransmitWindowDelay+transmitWindowOffset+transmitWindowSize时间内接着发出第一包数据(一般是empty package),对方在T_IFS时间内回复成功,链路连接正式建立完成,并且以第一包为锚点,之后在Connection Interval内进行数据交互。后续进行version、feature exchange,还有加密等不再细讲
发送connect_ind包后,紧接着发送empty package
empty package交互完成,连接建立ok
下图为第一包交互对方不响应会继续发送empty等待对方响应
遇到BLE连接问题可以抓空包分析下连接流程是否正常,经常出现第一包empty package不回包,建立失败,一部分是环境干扰,直接丢包,还有可能对方设备处理异常了,具体问题具体分析。