基于snooplog分析蓝牙连接过程,进一步学习蓝牙协议栈
一:什么是BT snoop log
首先问题:
1.为什么远端发来的消息没有收到?
2.为什么搜索不到设备
3.为什么连不上?
4.。。。。。。
总之,研发过程中会遇到很多奇奇怪怪的问题,我们无法通过现象去分析原因,也不可能再过一遍代码吧,这时候需要再某些代码节点设置信息打印(万能的printf),当程序代码走到这一步,要打印个信息出来告知:老子执行到这里了;到我这里执行不下去,出错了。。。
这些就是log,回到正题,除了开发自定义的打印信息,Android蓝牙中有一个很重要的debug方式就是btsnoop.log,这个log是蓝牙协议栈自己生成的,只列出了协议栈收发的消息,如果是其他的原因如丢包,涉及空口,则需要sniff log来分析,具体大家自行看下Ellisys的抓包分析
这个log记录的是host和controller的通信内容,也就是HCI层面(下面再讲)的东西,不涉及到其他层
Host:就相当与上层的应用层,协议栈
Controller:就相当于底层的芯片部分了
所以这部分的log就是类似:上面的APP要做什么事情比如相机要打开摄像头,他要跟底层的通信,告诉下面的硬件,然后硬件答复OK,这时候摄像头就打开了
–Are you OK?
–I’m fine thanks!and you
**
二:怎么抓取snoop log
**
Android手机进入开发者选项,打开蓝牙HCI日志,就会生成log,操作下蓝牙配对连接、放歌通话,log会持续打印,生成一份snooplog,一般mtk芯片的手机都放在根目录下的mtklog文件夹里面,高通的就不太好找,如果都找不到,可以用以下命令
adb shell cat /etc/bluetooth/bt_stack.conf
就能找到btsnoop_hci.log/btsnoop_hci.caf的保存路径
三:分析log
1.工具
(1)Wireshark
下载:https://www.wireshark.org/download.html
(2)Frontline 的Capture File Viewer
下载:https://www.fte.com/products/default.aspx
偏好Frontline
2.导入文件
等待一下加载完成,点击第二给放大镜图标
然后就进入了如图:
左边这部分就是封包的内容信息,右边就是各种包,准确讲应该叫协议帧
工具还区分了各种协议
3.蓝牙协议栈(先看一下图)
4.连接过程
这是大致的连接过程图
(0)初始化信息
Host和Controller两者是相互沟通,一来一回的通信
Host——>Controller:Command,指令,
Controller——>Host:Event,事件,
可以理解为上面领导下达命令,底层打工人响应命令做事情
当我们开启蓝牙,HCI会重置,然后做一些初始化操作,如:
HCI_Read_Buffer_Size读取ACL和SCO链路可传输数据包的大小
Read_Local_Version_Information 读取HCI的版本,制造商
HCI_Read_BD_ADDR 读取mac地址
HCI_Read_Local_Supported_Commands 读取本地设备支持的指令
(1)扫描
两个扫描模式:
Inquiry Scan:让蓝牙芯片进入发现周围蓝牙设备的模式,它的返回值是周围蓝牙设备的信号
Page Scan:让设备进入可被连接的状态,能够响应其他设备的连接请求(这个没有对应的HCI指令,有个page_timeout连接超时)
(2)创建连接
HCI_Connection_Request:创建连接,由Host发给controller,让它连接指定的设备
然后,Controller响应状态:成功/失败;
(3)交换Feature
然后双方的Host要知道对方都支持什么功能,这时候就要交换双方feature信息,获取对方的feature,比如Role switch、Power control、RSSI with Inquiry Results等:
(4)链路创建
交换完成,上层Host的L2CAP已经指定了具体的链路类型,Controller让LMP创建一个链路且后面要维护这个链路,默认初始初始状态是ACL链路,通常用来放音乐的(媒体音频);SCO是用来通话的
然后Baseband基带主要做数模转换(学过数模的大家应该知道这一科很容易挂科)
然后就是RF发射信号了
然后就到远端设备的Controller的RF接收到信号,也是一步步上传,最后同意/拒接/不理睬。。。
回到我方阵容:
当对面同意了,我方收到一个LMP_accepted的包,然后LMP就给到HCI层,发给Host端,Host端决定同意,则连接链路建立
(5)角色转换
如果这个时候对方要从slaver成为master,这个时候双方就要有个角色转换的过程,我方就会收到一个Role_Change,切换主从设备
(6)授权
接下来,就是要不要授权,比如我们看到的有些设备要输入pin码,要双方确认。那么这时候,Controller就会各自的Host请求link key,如果Host回复的是,没有公共的link key,那Controller就只能请求生成私有linkkey,接着就是交换link key,双方保存共有link key,这就是配对过程;
—如果双方已经保存了对方的link key,那么下次连接就不用再配对了,当Controller第一次请求link key,Host就会直接答复共有link key来授权(这里如果出现linkey丢失,就会出现断连,重连时需要重新配对)
授权成功,Master就会发一个加密请求,Slaver同意,那么这个点对点的连接加密成功
最后,双发互发Steup_complete,各自Controller将完成状态发送回上层Host,至此,连接完成,可以开始传输数据
(7)SDP请求支持服务信息
然后,把Profile也加入进来,上面的物理链路建立后,SDP这个东西,他要知道对方有什么服务,SDP就请求L2CAP指定一个针对SDP的Connection,对面回应,她说她可以播放立体音频(a2dp v1.0.0)、可以接听挂断电话(hfp v1.3.0)、可以暂停播放上下曲(avrcp v2.3.0)。。。当然,对方的SDP也会跟我方请求交换服务信息
五、回顾
事实上,两个设备间的通信其实是建立再LMP层面上的通信,因为的双方的通信链路就是通过LMP来建立并管理的(sniff log显示更全面):
六、建立SCO链路
基带规范定义了两种链路类型:面向连接的同步链路(SCO)和面向无连接异步链路(ACL)。SCO链路主要是用来做语音通话用的
1.SCO和上面的默认的ACL有什么区别?
SCO (Synchronous Connection Oriented):
首先解释一下什么是同步面向连接:蓝牙网络中在主站和次站之间建立的一种物理链路,举个栗子,比如A给打B电话,需要进行三次握手:
1.请求(A要向B发送请求)
2.应答(B向A回应例如没问题,你现在可以与我通话)
3.连接(现在正式建立A与B的连接就可以通话了)
面向连接保证了信道的独占,保证了通信的安全与效率,但是也降低了信道的利用率,适合避免时延比数据完整性更为重要的应用,这种类型的通道在每个方向上都以均匀的间隔时间分配固定的时槽
所以,这种链路一般用于实时语音通话
ACL(Asynchronous Connection Less):
同样解释一下什么是异步无连接,就是传输的每个分组数据的处理都独立于其他的分组,大家不会相互阻塞,举个栗子,比如A给B发微信,A不会管B会不会收到,也不会管B会不会应答他,A只管发送
面向无连接可以增强信道的利用效率但是不可靠,一般用于分组数据传输
2.分组数据传输
分组数据传输:蓝牙支持电路和分组交换,数据是以分组的形式在信道中传输,并使用流控制来避免分组丢失和拥塞,以确保分组包数据正确传输,简单的说就是数据是一组一组的传输过去的
电路交换:主要是时分交换,它是将通信的时间划分为许多独立的时间间隙(时隙),每个时隙都对应一个子信道,通过时隙的交换,实现时隙所承载的数据的传输
分组交换:也叫包交换,它将数据划分成多个更小的等长数据段,在每个数据段的前面加上必要的控制信息作为数据段的首部,每个带有首部的数据段就构成了一个分组。首部指明了该分组发送的地址,当交换机收到分组之后,将根据首部中的地址信息将分组转发到目的地
SCO属于电路交换,数据包主要是语音信息,,而ACL属于分组交换,数据包主要是媒体音频数据
ACL的分组包支持重传,而SCO不支持重传,SCO包没有CRC校验码,ACL的方式可以根据丢包信息(分组交换方式)做到数据重传
3.SCO链路建立
回到正题:SCO的建立
跟ACL的差不多,一来一回的沟通形式,只是要注意的是,两者的通信的差异,上面两个栗子,SCO需要应答,而ACL不需要,并且只能在ACL连接建立后才能建立SCO,想一下为什么?
–SCO是的建立是基于HFP的建立而建立的,而HFP本身是ACL链路,SCO依赖与HFP协议中的编解码协商,协商完成双方确认后才能建立SCO通信
–建立sco链路需要的交互的指令是通过acl来完成的,sco链路的参数需要通过acl去跟对方确认
–SCO要对方应答,没应答之前发过去的参数等数据,需要经过acl链路传过去确认
另外,L2CAP规范仅定义ACL链路而不支持 SCO链路。SCO不会经过L2CAP,所以,我们看到的蓝牙协议栈会发现这个:他会直接从基带支持出来,当然,会经过LMP(这个经典图不够完善啊)
七、Profile服务执行过程
最后,顺便将Profile通信也串起来
当我们使用了一个profile的服务,蓝牙是怎么一步一步下发下去,从host的每一个协议,一直到controller,然后再到对端的controller、host
这里,我们就要划分一下Profile,比如HFP、OPP、PBAP这些跟手机语音、network相关的是RFCOMM(串口仿真协议)上的,通信时要经过RFCOMM,而A2DP、AVRCP这些不会走RFCOMM,会直接跟L2CAP通信
所以RFCOMM又是什么鬼?
RFCOMM是为兼容传统的串口应用(服务),同时取代有线的通信方式,蓝牙协议栈需要提供与有线串口一致的通信接口而开发出的协议
例如HFP(Hands-Free Profile),字面意思就是电话免提,设备支持这样的一个服务,HFP是属于RFCOMM上面的一个AT指令协议(实际上他是一个指令类型),通过下发指令来操作。假如我定义三个指令,提示通话AT+CALLCOMING=State,1为有来电,0为没有来电;控制接听挂断AT+CALLCTR=Control,1为接听,0为挂断;确认OK
当手机端来电时,向远端发送:AT+CALLCOMING=1
当远端收到该指示之后,如果接听电话,则发送:AT+CALLCTR=1
当手机端接收控制指令,并回复:OK
HFP定义了两个角色:
音频网关AG (Audio Gate)
免提组件HF (Hands Free)
从字面意思都很好理解,音频网关,就是管语音输入端的,免提就是远端控制咯
从上面的图可以看到,指令下发后会先经过RFCOMM,然后到L2CAP,从log中我们也可以看到,另外,HFP是属于ACL数据包,并不是SCO
基于snooplog分析蓝牙连接过程,进一步学习蓝牙协议栈相关推荐
- websocket / 使用 wireshark 分析 websocket 连接过程
一.连接过程时序图 二.wireshark 分析 上图是一个完整的进行 websocket 连接时产生的数据包. 根据时序图可知,前 3 行是 tcp/ip 握手过程,因为可以通过标志来看到,前 3 ...
- 树莓派学习3-树莓派蓝牙连接手机通信测试(蓝牙连接手机时断时序问题解决)
通过上一篇文章学习,我们可以将树莓派的蓝牙连接到蓝牙音箱,进行语音播放.那么对于蓝牙配置和蓝牙控制软件更新,在此不再赘述. 1.树莓派连接手机蓝牙时断时续问题 原以为手机蓝牙和音箱蓝牙直接可以直接连接 ...
- android mac蓝牙连接不上,Mac蓝牙找不到设备解决方法介绍
很多新手用户不知道怎么在mac系统中连接蓝牙设备,其实方法还是很简单的,当然如果你想要进一步进行了解的话倒是可以跟随小编一起加入这款Mac蓝牙找不到设备解决方法介绍的文章中仔细了解衣服哦,希望小编为你 ...
- android 多个蓝牙连接电脑,Android BLE蓝牙多设备连接
多设备连接的问题很典型,一方面实际应用中存在同时和多个设备通信的场景,另一方面蓝牙连接较耗时,如果能尽可能保持连接,则可省去不少时间,用户体验更好. 然而多设备连接也有一些问题要注意,有以下几点: 一 ...
- android系统 wifi,Android系统wifi分析-手动连接过程
1.已保存显示时间较长 16:59:50~16:59:55 原因是,刚好系统保存热点信息里边没有该热点:没有匹配上: 07-16 16:59:51.017 1318 2154 D WifiServic ...
- android低功耗蓝牙连接失败_低功耗蓝牙 AoA定位系统为室内定位和资产跟踪 提供亚米级精度位置服务...
蓝色创源使用Nordic nRF52833 SoC实现兼容智能手机的低功耗位置服务网络. *定位解决方案提供商蓝色创源(北京)科技有限公司选择使用其nRF52833低功耗蓝牙(Bluetooth® L ...
- android关闭蓝牙连接手机号码,Android BLE蓝牙连接要注意的问题
一.运行时问题 发起请求 手机和蓝牙设备建立连接,不论是在哪个进程,哪个线程发起的请求,最终都要丢到系统蓝牙服务进程中去处理. 看到有的文章说在同一个进程中,发起的连接和读写等请求最好都在UI线程里, ...
- php蓝牙连接不上,Mac蓝牙不可用怎么办?苹果电脑Mac蓝牙连不上i
近日,很多用户在升级Yosemite一段时间后,发现蓝牙不可用了,那么,Mac蓝牙不可用是怎么回事?如何解决?针对此问题,本文就为大家介绍Mac蓝牙连不上iphone现象的解决办法 Mac蓝牙不可用怎 ...
- Wireshark抓包分析TCP连接、发送数据与断开过程
准备工具: 1. 两台连接到同个局域网的电脑,或者虚拟机; 2. 在其中一台电脑安装Wireshark; 3. 在两台电脑上面都有TCP&UDP测试工具软件 TCP连接建立过程(三次握手): ...
最新文章
- 手把手教线性回归分析(附R语言实例)
- CocoaPods一个Objective-C第三方库的管理利器
- 23LC1024四线访问数据
- 物联网网关linux带串口,物联网网关|串口转HTTP GET协议
- java 找不到构造函数_JAVA找不到符号构造函数
- 突然!格力电器向全体股东分红36.1亿元 董明珠得2600万
- 10年年初写的述职报告
- 查看JDK版本和安装路径
- delphi 连接网口打印机 发送指令打印二维码
- 直播APP源码(干货):搭建直播平台的具体方案
- Office 2010 语言包 Office 2010 En english package 包含office professional plus所有组件,还有viso,project!
- 软件架构师必需要了解的 saas 架构设计?
- 无线打印机与手机连接到服务器,图文详解手机通过无线Wifi连接打印机的方法...
- 计算机管理内默认共享,Win10共享默认在哪里关闭 清除默认共享哪种方法比较彻底...
- 移动建站工具(一):分秒钟将Web网站移动化
- GCC 预处理的宏 (predefined macros)
- 万字长文读懂微信“看一看”内容理解与推荐
- 煲汤C语言,煲汤秘诀,附9款排骨汤做法,总有一款适合你!
- 汇编语言(王爽)-实验
- InstallShield打包源码公布