赞
踩
随着ble设备的普及,众多品牌的手机和车载连接着各式各样的ble外设,接触多的有手环、手表、双模耳机、遥控器、鼠标、键盘或者智能家居设备等等
连接类问题一直是蓝牙开发的重要一环,不懂的人可能只会一个劲的问为什么,开发时遇到实际问题时可能也会苦于日志不全,无法确认问题原因,看完这一篇希望对你们有所帮助
基于android平台讲一下
一、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不回包,建立失败,一部分是环境干扰,直接丢包,还有可能对方设备处理异常了,具体问题具体分析。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。