本文主要是介绍RFCOMM(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
2、Remote Port Negotiation Command (RPN)
这个message用于设置remote port setting(其实就是串口设置),这个命令在DLC open之前可能被使用,另外remote port setting发生变化时要使用这个message。所有参数都有默认值,如果不适用RPN进行协商,则使用默认值。
RPN message格式如下图所示:
(1)Type字段:即上图中的command RPN部分。定义如下图所示:
①EA:固定是1
②C/R:用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0;
(2)length字段:如下图所示,这个message的length只能是1或者8,一个字节就够用,所以E/A=1
(3)DLCI字段:E/A=1,bit2=1,如下图所示:
注意:bit 3应该按照RFCOMM的标准,为D字段
(4)Value octet2 optional至Value octet8 optional,格式如下图所示:
①B1-B8:表示串口波特率,默认值1100 0000 (9600),如下图所示:
②D1-D2:表示数据位,取值如下
③S:表示停止位,S=0表示1个停止位,S=1表示1.5个停止位,默认值S=0
④P:表示校验位:P=0表示无校验位,P=1表示有校验位,默认值P=0
⑤PT1 - PT2:表示校验类型,如下图所示:
⑥FLC1-FLC6: 表示流控,默认值是0,具体含义如下:
⑦XON1-XON8:表示XON characte,默认值是DC1
⑧XOF1-XOF8:表示XOFF character,默认值是DC3
⑨PM1-PM16:即Parameter mask,表示哪些参数是可以协商的,对于command,0表示no change,1表示change;对于response,0表示not accepted proposal,1表示accepted proposal, and the new values are used。具体每个bit表示的含义如下
3、Modem Status Command (MSC)
这个message是用来传输V.24控制信号的,这个message必须在发送数据前交互,这个message包括一个control signal byte和一个可选的break signal byte,如下图所示:
(1)Type字段:即上图中的command部分。定义如下图所示:
①EA:固定是1
②C/R:用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0;
(2)length字段:如下图所示,这个message的length只能是2或者3,一个字节就够用,所以E/A=1
(3)DLCI字段:E/A=1,bit2=1,如下图所示:
注意:bit 3应该按照RFCOMM的标准,为D字段
(4)V.24 signals字段:格式如下图所示
①EA:扩展位,如果没有break signals,则EA=1,如果有break signals,则EA=0;
②FC:即flow control,当设备没有能力接收frame时,这个字段设置为1;
③RTC:即Ready To Communicate,当RTC=1时表示设备准备好通信了;
④RTR:即Ready To Receive,当RTR=1时表示设备准备好接收数据;
⑤IC:即Incoming call indicator,当IC=1时,表示有来电;
⑥DV:即Data Valid,当DV=1时表示正在发送有效数据;
(5)break signal字段:格式如下图所示:(蓝牙应该是没有这个字段)
EA:如果这个字节是最后一个字节,则EA=1,如果不是最后一个字节,则EA=0,所以这个EA应该固定是1.
其他bit为解释如下
举例:
如上图所示:
①Initiator发起的RFCOMM connect,所以DLCI的D字段应该是0
②command type为0xe3,即1110 0011,正好是MSC的message type
③length为0x05,即0000 0101,EA为是1,所以后面跟着2个byte的数据
④DLCI为0xDB,即1101 1011,EA是1,bit2也固定是1,D是0,server channel=1 1011=0x1B=27
⑤v.24 signal为0x8D,即1000 1101,EA=1,FC=0,RTC=1,RTR=1,IC=0,DV=1
4、Test Command (Test)
这个message用来测试两个设备之间的连接,length字段表示后面的value字段的长度,对方收到Test message时,应该回复相同value值
(1)Type字段:即上图中的command部分。定义如下图所示:
①EA:固定是1
②C/R:用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0;
(2)length字段:如下图所示
5、Flow Control On Command (Fcon)
流控开启命令。没有value字段,所以length表示的长度是0个字节
Type如下图所示:
6、Flow Control Off Command (Fcoff)
流控关闭命令,没有value字段,所以length表示的长度是0个字节
Type如下图所示:
7、Remote Line Status (RLS)
这个message用于指示远程线路状态(Remote Line Status),当Remote Line Status发生变化时,就需要发送RLS。格式如下图所示:
(1)type字段:如下图所示:EA=1, C/R用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0;
(2)length字段:后面固定跟2个字节,所以length=EA+ 2<<1=0x05
(3)DLCI字段:
注意:bit 3应该按照RFCOMM的标准,为D字段
(4)Remote Line Status字段:
L1-L4表示Line status,L1=0,表示没有error发生,L1=1表示有error发生,具体的error由L2-L4决定:
8、Non Supported Command Response
当收到不支持的message type时,就用这个message回复,格式如下图所示:
(1)type字段:
①EA:固定是1
②C/R:用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0;
(2)length字段:后面跟一个字节,所以length = EA+ 1<<1=0x3
(3)command type字段:
这里面存放不支持的command的command type,注意:C/R是不支持的那个command的type字段里面的C/R
五、Credit Based Flow Control
1、Credit Based Flow Control是RFCOMM必须要支持的,但是蓝牙V1.0B之前没有。
2、当使用Credit Based Flow Control时,在同一个RFCOMM session的两个设备就会知道对于每个DLC,对方设备还能接收多少个RFCOMM frames(多少个credit)。当credit数量变成0时,发送端就要停止发送frame并等待对方更新credit。
3、不包含user data(length字段中数据长度值为0)的frame,不受credit的限制;
4、DLCI 0上的frame或者非UIH frame也不受Credit Based Flow Control限制
5、在第一个DLC建立之前,要先使用PN command进行协商。后续DLC建立之前,PN command协商是可选的但是最好使用一下,这样可以在DLC的两端初始化credit值。
6、当使用credit based flow control的时候,UIH frame中RFCOMM header里面的control字段的P/F值被重新定义了,定义如下:
当P/F-bit=0,frame的结构如下图所示:
当P/F-bit=1,frame的结构如下图所示:
在length indicator字段和information字段中间加入1byte的credits字段,这个credits字段的含义是:发送端(发送UIH frame中包含credits字段)当前可以接收多少个frame,取值0-255。这个credit是可以累加的,意思是收到一个UIH frame中包含credits字段,那么就可以把这个credits的值加到之前剩余的credit上面。
7、使用Credit Based Flow Control时,FCon和FCoff不能使用。MSC的FC-bit没有含义,应该设置为0
六、举例
如下图这一段RFCOMM frame
1、Frame 161:master设备发送SABM command,建立RFCOMM signal通道,所以master是Initiator,slave是Responder
根据frame的格式:
可以确定:
(1)Address是0x03,即0000 0011,E/A=1,C/R=1,D=0,server channel=0x0。
解释:
①Initiator发起的command,所以C/R=1,所以Frame 163的回复中对应的Address中的C/R也应该为1。
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0x3f,即0011 1111,如下图所示,可以看出这是一个SABM command,P/F=1(因为这个SABM command需要一个response,所以设置为1)
(3)Length Indicator是0x01,即0000 0001,EA=1,后面跟的数据长度为0。
(4)FCS是1C
2、Frame 163:slave设备收到SABM command,所以要回复一个UA response
(1)Address是0x03,即0000 0011,E/A=1,C/R=1,D=0,server channel=0x0。
解释:
①Initiator发起的SABM command里面的C/R=1,这个UA response是对SABM command的回复,所以设置C/R=1
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0x73,即0111 0011,如下图所示,可以看出这是一个UA response,P/F=1(因为这个UA response需要一个SABM command的回复,SABM中P/F设置为1,所以UA response的control中的P/F设置为1)
(3)Length Indicator是0x01,即0000 0001,EA=1,后面跟的数据长度为0。
(4)FCS是0xD7
到这里signal connection就建立完成了。
3、Frame 164:master发起PN message command
(1)Address是0x03,即0000 0011,E/A=1,C/R=1,D=0,server channel=0x0。
解释:
①对于UIH帧,initiator发送给responder,C/R为1,responder发送给initiator C/R为0;这个UIH是initiator发起的,所以设置为1
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0xEF,即1110 1111,如下图所示,可以看出这是一个UIH,P/F=0(UIH的P/F设置为0,Credit Based Flow Control除外)
(3)Length Indicator是0x15,即0001 0101,EA=1,后面跟的数据长度是0x0A
(4)Information是0x83 0x11 0x06 0xf0 0x00 0x00 0x40 0x02 0x00 0x00
解释:
①message type是0x83,即1000 0011,EA=1,C/R=1(用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0)
②message length是0x11,即0001 0001,EA=1,后面跟的数据长度是0x08
③message data是0x06 0xf0 0x00 0x00 0x40 0x02 0x00 0x00
D-bit是0x06,即00 0110,D=0,因为即将建立的连接是initiator发起的,server channel是3;
I-bit为0x0(固定值0x0),CL-bit为0xF,表示支持Credit Based Flow Control
P-bit为0x0,即priority=0
T-bit为0x00(固定值)
N-bit为0x0240=576,即maximum frame size为576 byte
NA-bit为0x00(固定值)
K-bit为0x00,表示credit的初始值是0,即master端最大可以接收0个UIH frame
(5)FCS是0x70
4、Frame 165:slave回复的PN message response
(1)Address是0x01,即0000 0001,E/A=1,C/R=0,D=0,server channel=0x0。
解释:
①对于UIH帧,initiator发送给responder,C/R为1,responder发送给initiator C/R为0;这个UIH是responder发送给initiator的,所以设置为0
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0xEF,即1110 1111,如下图所示,可以看出这是一个UIH,P/F=0(UIH的P/F设置为0,Credit Based Flow Control除外)
(3)Length Indicator是0x15,即0001 0101,EA=1,后面跟的数据长度是0x0A
(4)Information是0x81 0x11 0x06 0xe0 0x00 0x00 0x00 0x01 0x00 0x07
解释:
①message type是0x81,即1000 0001,EA=1,C/R=0(用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0)
②message length是0x11,即0001 0001,EA=1,后面跟的数据长度是0x08
③message data是0x06 0xe0 0x00 0x00 0x00 0x01 0x00 0x07
D-bit是0x06,即00 0110,D=0,因为即将建立的连接是initiator发起的,server channel是3;
I-bit为0x0(固定值0x0),CL-bit为0xe,表示支持Credit Based Flow Control
P-bit为0x0,即priority=0
T-bit为0x00(固定值)
N-bit为0x0100=256,即maximum frame size为256 byte,PN messagerequest中时576byte,所以最终在server channel 3上的maximum frame size是256 byte
NA-bit为0x00(固定值)
K-bit为0x07,表示credit的初始值是7,即salve端最大可以接收7个UIH frame
(5)FCS是0xaa
到这里server channel 3的PN交互就完成了
5、Frame 166:master设备发送SABM command,建立RFCOMM DLC,Initiator发起的连接
(1)Address是0x1b,即0001 1011,E/A=1,C/R=1,D=0,server channel=0x3。
解释:
①Initiator发起的command,所以C/R=1,所以Frame 168的回复中对应的Address中的C/R也应该为1。
②这个DLC是Initiator发起的,所以这个DLC上所有frame的Address字段的D=0。
(2)Control是0x3f,即0011 1111,如下图所示,可以看出这是一个SABM command,P/F=1(因为这个SABM command需要一个response,所以设置为1)
(3)Length Indicator是0x01,即0000 0001,EA=1,后面跟的数据长度为0。
(4)FCS是0xD3
6、Frame 168:slave设备收到SABM command,所以要回复一个UA response
(1)Address是0x1b,即0001 1011,E/A=1,C/R=1,D=0,server channel=0x3。
解释:
①Initiator发起的SABM command里面的C/R=1,这个UA response是对SABM command的回复,所以设置C/R=1
②这个DLC是Initiator发起的,所以这个DLC上所有frame的Address字段的D=0。
(2)Control是0x73,即0111 0011,如下图所示,可以看出这是一个UA response,P/F=1(因为这个UA response需要一个SABM command的回复,SABM中P/F设置为1,所以UA response的control中的P/F设置为1)
(3)Length Indicator是0x01,即0000 0001,EA=1,后面跟的数据长度为0。
(4)FCS是0x18
到这里DLC(server channel=3)就建立完成了。
7、Frame 169:master设备发送的MSC message request(这个message要在数据交互前发送)
(1)Address是0x03,即0000 0011,E/A=1,C/R=1,D=0,server channel=0x0。
解释:
①对于UIH帧,initiator发送给responder,C/R为1,responder发送给initiator C/R为0;这个UIH是initiator发起的,所以设置为1
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0xef,即1110 1111,如下图所示,可以看出这是一个UIH,P/F=0(UIH的P/F设置为0,Credit Based Flow Control除外)
(3)Length Indicator是0x09,即0000 1001,EA=1,后面跟的数据长度为4。
(4)Information是0xe3 0x05 0x1b 0x8d,MSC message格式如下
解释:
①message type为0xe3,即1111 0011,EA=1,CR=1(用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0)
②length为0x05,即0000 0101,EA=1,即后面跟着2个字节
③DLCI为0x1b,即0001 1011,EA=1,C/R=1(固定是1),D=0,server channel=3;注意:其实可以认为server channel 3建立的DLC的DLCI为0x6,message中用到DLCI可以直接设置为0x6
④V.24 signals为0x8d,即1000 1101
(5)FCS是0x70
8、Frame 177:slave设备收到MSC message request,回复MSC message response
(1)Address是0x01,即0000 0001,E/A=1,C/R=0,D=0,server channel=0x0。
解释:
①对于UIH帧,initiator发送给responder,C/R为1,responder发送给initiator C/R为0;所以设置为0
②这个signal connection是Initiator发起的,所以这个signal connection上所有frame的Address字段的D=0。
(2)Control是0xef,即1110 1111,如下图所示,可以看出这是一个UIH,P/F=0(UIH的P/F设置为0,Credit Based Flow Control除外)
(3)Length Indicator是0x09,即0000 1001,EA=1,后面跟的数据长度为4。
(4)Information是0xe1 0x05 0x1b 0x8d,MSC message格式如下
解释:
①message type为0xe1,即1111 0001,EA=1,CR=0(用来区分是command还是response,如果是command,则C/R=1,如果是response,则C/R=0)
②length为0x05,即0000 0101,EA=1,即后面跟着2个字节
③DLCI为0x1b,即0001 1011,EA=1,C/R=1(固定是1),D=0,server channel=3;注意:其实可以认为server channel 3建立的DLC的DLCI为0x6,message中用到DLCI可以直接设置为0x6
④V.24 signals为0x8d,即1000 1101
9、下面就是流控了
(1)frame 170,master发送了一个普通UIH frame,此时slave端的credit应该是变成7-1=6了
(2)frame 171,master发送一个UIH frame(这里面没有information数据),但是有credit,表示master端的credit增加3,即0+3=3
(3)frame 180,slave发送的这个UIH连包含credit和information字段,所以master的credit-1即3-1=2,slave的credit增加4,即6+4 = 10
后续不再介绍。
简单来说:带有credit的的UIH,如果没有information字段,那么只是说明发送端增加多少个credit,如果带有information字段,那么对方的credit-1。
10、DISC、DA、DM
Master的DISC
Slave的DISC
Master的UA response
Slave的DM response
具体含义参考上面的命令分析。
这里有个问题:车机快速断连PBAP,经常会出现PBAP连接不上,稍等一会就可以连接上了
下面是出问题时的air log,可以看到车机去连接RFCOMM的时候,手机断开了,回复DM
后来发现上一次PBAP断开的时候,手机发来的RFCOMM Disconnect,车机没有回应
4、PBAP断开的时候,手机发来的RFCOMM Disconnect,车机回复UA后,录到的btsnoop如下图所示,这样就正常了。
这篇关于RFCOMM(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!