零. 概述
本文章主要讲下蓝牙RFCOMM协议(bluetooth rfcomm)的帧格式,包括Address,Control,Length Indicator,Information,FCS等
一. 声明
本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:
第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。
第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等
第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等
第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。
第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)
第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等
第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展
第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。
另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。
-------------------------------------------------------------------------------------------------------------------------
CSDN学院链接(进入选择你想要学习的课程):/lecturer/5352?spm=1002.2001.3001.4144
蓝牙交流扣扣群:970324688
Github代码:/sj15712795029/bluetooth_stack
入手开发板:/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708
蓝牙学习目录:/XiaoXiaoPengBo/article/details/107727900
--------------------------------------------------------------------------------------------------------------------------
二.RFCOMM帧格式
2.1 参数Address:
EA参数:这部分在蓝牙RFCOMM协议中一直为1
C/R参数:此部分是代表RFCOMM的command还是response,官方解释如下:
这个理解起来稍微我有绕,我翻译一下:
C/R(命令/响应)位表示帧是命令还是响应,它的值不仅取决于帧是否携带命令或响应,还有信道的哪一端发送帧。建立连接的设备(通过在DLCI 0上发送SABM命令)称为initiator。响应的设备(通过在DLCI 0上发送UA响应)称为responder。网络上都对这个地方说明的模凌两可,对于上面的这段话其实也说的模棱两可,我来总结下:
1)对于(SABM,UA,DM,DISC)帧,这些统称为命令帧,initiator发送给responder,C/R=1,response相应initiator C/R也为1。
2)对于(SABM,UA,DM,DISC)帧,这些统称为命令帧,response发送给initiator C/R为0,initiator响应给responder,C/R=0.
3)对于UIH帧,这个称为数据帧,initiator发送给responder,C/R=1,response发送给initiator C/R为0.
总结图标如下:
为了便于我上面的总结理解,那么加一个流程图,来加深你们的印象
下面我们用BTsnopp来一一看下以上个3case:
1)对于(SABM,UA,DM,DISC)帧,这些统称为命令帧,initiator发送给responder,C/R=1,response相应initiator C/R也为1。
分别解析如下:
从截图看出是对方来连接我们signaling,所以对方是initiator,所以对方发送SABM种的C/R是1,而我们回复的UA帧中的C/R也为1
以下例子都是以对方为initiator来说明
2)对于(SABM,UA,DM,DISC)帧,这些统称为命令帧,response发送给initiator C/R为0,initiator响应给responder,C/R=0.
从1)中我们可以看到我们是responder,对方是initiator,所以按照我们发送给对方的SABM帧的C/R是0,对方回应我们的也是0
3)对于UIH帧,这个称为数据帧,initiator发送给responder,C/R=1,response发送给initiator C/R为0.
上图解析如下:
可以看到对方给我们的UIH帧C/R为1,我们给对方的UIH帧C/R为0
讲到这里你应该明白了C/R位了吧,我感觉我是全网在这里说明最清晰的。
D参数:这个同样比较绕,我们来看下官方解释
D其实就是DLCI中的direction bit
网上也没有一个特别明确的说明,我自己总结了下,感觉也是比较清晰:
建立连接的设备(通过在DLCI 0上发送SABM命令)称为initiator。响应的设备(通过在DLCI 0上发送UA响应)称为responder,这点在上面我们也已经说明了。initiator自己的D=1,responder自己的D=0,所以如果在DLCI已经建立连接后,后续initiator连接responder某一个profile的时候(比如HFP),那么应该是DCLI=0+ server chanel<<1,如果是responder连接initiator的某一个profile,那么应该是DCLI=1+ server channel<<1
后续交互封包的UIH的DCLI一直不变
举几个例子来说明下这里(remote是initiator,local是responder):
来一个initiator连接responder的btsnoop
可以发现server channel是9,那么按照算法应该是0+9<<1,所以DCLI应该是0x12
来一个responder连接initiator的btsnoop
可以发现server channel是13,那么按照算法应该是1+13<<1,所以DCLI应该是0x1B
Server channel:说白了就是上层profile的rfcomm channel
注册到SDP中,整个流程就是SDP问询对方的RFCOMM channel,然后再发起RFCOMM的连接(比如HFP,HSP,SPP,OPP等),连接完毕交互完参数,就相当于上层profile连接成功
2.2 Control参数
主要是标示RFCOMM frame type是什么,截图如下:
帧分别作用如下:
SABM:异步平衡模式设置指令 SABM 命令可以用在异步平衡模式下,并且它的控制字段只能有一个字节。设备通过首先发送 UA 应答来确认接收到 SABM命令,DLC 发送和接收状态变量都必须设定为 0。用大白话讲就是连接命令
UA:未加编号的确认应答。 UA 应答用在设备对接收到 SABM 和 DISC 后的确认应答
DM:断开连接模式应答。DM 应答是用来报告设备从数据链路逻辑地断开连接这么一种状态的。在断开模式下,不支持任何命令,直到收到了 SABM 命令,然后停止断开模式。在断开模式下,接收到了 DISC 命令,则要向对方发送一个 DM 应答。
DISC:断开连接指令。用 DISC 命令可以用来结束一个正在运行或者刚刚开始的模式。它就是通知一方另一方悬置操作,设备必须假定一个逻辑断开模式。在执行这个命令之前,接收设备要通过发送 UA 应答来确认接受 DISC 命令。在DLCI0 中,DISC 命令的发送也和其他的 DLCI 具有同意的意思。
UIH:带头校验的未编号信息命令和应答用 UIH 命令/应答可以通过不影响V(S)或 V(R)变量来相互发送信息。UIH 是用在传输一些信息的完整性没有它要在正确的 DLCI 上传输重要的情况下的。 FCS 只在地址和控制字段进行计算。 UIH用于对差错码要求不是很高的场合,如语音。
P/F Bit:P/F是Poll/Final位
在Commands中,被称为P(poll)位;而在Responses中则被称为F(final)位,大概用法我自己总结如下:
1)对于(SABM,UA,DM,DISC)帧,这些统称为命令帧,command跟response都设置为1就好。
2)对于UIH帧,除了给对方credit设置为1外,UIH user帧以及UIH多路控制帧都设置为0就好了。
2.3Length Indicator参数
L1 到 L7 位表示数据字段的长度,其默认值为 31 字节。同样,它可以根据 EA位进行扩展。当 EA=0 时,它接下来的字节如下表表示就可以表示 15 个数字。也就是RFCOMM的后续len是32~32767 byte的字节。
2.4Information Field参数
UIH帧数据,只对UIH帧有效,后续再一一介绍下UIH的格式
2.5FCS参数
帧校验序列(FCS)根据不同帧类型在不同域集上进行运算.下面列出需要进行帧运算的字段:
对于 SABM、DISC、UA、DM 帧:在地址、控制和长度标志字段上进行运算;
对于 UIH 帧:在地址和控制字段上进行运算