蜗窝科技

蓝牙协议分析(7)_BLE连接有关的技术分析

wowo · · 蓝牙 · 阅读 93831 · 2016年7月存档

1. 前言

了解蓝牙的人都知道,在经典蓝牙中,保持连接(Connection)是一个相当消耗资源(power和带宽)的过程。特别是当没有数据传输的时候,所消耗的资源完全被浪费了。因而,对很多蓝牙设备来说(特别是功耗敏感的设备),希望在无数可传的时候,能够断开连接。但是,由于跳频(hopping)以及物理通道(Physical Channel)划分的缘故,经典蓝牙连接建立的速度实在难以忍受(要好几秒)。对那些突发的数据传输来说,几秒钟的连接延迟,简直是灾难。

因此,蓝牙SIG制订BLE规范的时候,充分考虑了这方面的需求,极大的简化了连接的建立过程,使连接速度可以达到毫秒级(最快3.75ms就可以搞定)。与此同时,为了节省功耗,也调整了跳频的策略。至此,相比广播通信而言,BLE面向连接的通信,几乎没有额外的代价。

在“蓝牙协议分析(5)_BLE广播通信相关的技术分析”中,我们对BLE的广播通信有了比较全面的了解,本文将接着分析和面向连接的通信有关的技术,包括连接的建立和断开、BLE跳频(Hopping)技术、Link Layer的应答、重传、流控、等等。

2. 怎样才算是建立了连接?

开始之前,我们先回答一个问题,对通信的双方而言,怎样才算建立了连接呢?

从字面上理解,建立了连接,就是指:

二者之间,建立了一条专用的通道,它们可以随时随地的通信。

当然,在蓝牙这种资源有限的通信系统中,通道无法独占,退而求其次,分时也Okay。因此,在BLE中建立了连接,是这样定义的:

在约定的时间段内,双方都到一个指定的物理Channel上通信。

其中,“约定好的时间段”,是时分的概念。而“到指定的物理Channel上”,是跳频的概念。后面的分析,将会围绕这两个概念进行。

另外,和“蓝牙协议分析(5)_BLE广播通信相关的技术分析”类似,我们也将从Link Layer、HCI、GAP三个层次,分别介绍。

3.1 角色的定义

和经典蓝牙一样,协议为处于连接状态的BLE设备,定义了两种Link Layer角色:Master和Slave。Master是连接的发起方(Initiator),可以决定和连接有关的参数(很重要,后面会详细介绍)。Slave是连接的接受方(Advertiser),可以请求(或建议)连接参数,但无法决定。

注1:两个BLE设备之间,只能建立一条连接。

3.2 PDU的定义

和广播通信不同,面向连接的通信使用特定的PDU,称作Data Channel PDU,格式如下(LSB—->MSB):

Header(16 bits)Payload(Variable size)MIC(32 bits)

16bits的Header的格式如下:

LLID(2 bits)NESN (1bit)SN(1 bit)MD(1 bit)RFU(3 bits)Length(8 bits)

Data Channel传输的PDU有两类,一类是数据,称作LL Data PDU,另一类中控制信息,称作LL Control PDU。LLID用于区分PDU的类型,具体可参考后面3.2.1和3.2.2的描述。

NESN(Next Expected Sequence Number)和SN(Sequence Number),用于数据传输过程中的应答(Acknowledgement)和流控(Flow Control),具体可参考后面3.7的介绍。

MD(More Data),用于连接的关闭(或者说保持),具体可参考后面3.5的介绍。

RFU(Reserved for Future Use)。

Length,有效数据的长度(Payload+MIC),只有8-bits,因此Link Layer所能传输的最大数据是255 bytes(有MIC的话是251bytes),如果L2CAP需要传输更多的数据,需要分包之后传输(这也是L2CAP的主要功能之一,具体可参考“蓝牙协议分析(3)_蓝牙低功耗(BLE)协议栈介绍”)。

Payload是有效数据(SDU,L2CAP的PDU),长度由Header中的Length字段觉得,有效范围是0~255。

3.2.1 LL Data PDU

LL Data PDU有两种:

Header中的LLID=01b时,Continuation fragment of an L2CAP message, or an Empty PDU。这种类型的PDU,要么是一个未传输完成L2CAP message(长度超过255,被拆包,此时不是第一个),要么是一个空包(Header中的Length为0)。

Header中的LLID=10b时,Start of an L2CAP message or a complete L2CAP message with no fragmentation。这种类型的PDU,要么是L2CAP message的第一个包,要么是不需要拆包的完整的L2CAP message,无论哪种情况,Header中的Length均不能为0。

3.2.2 LL Control PDU

Header中的LLID=11b时,表示这个数据包是用于控制、管理LL连接的LL control PDU。LL control PDU的payload的格式如下:

Opcode(1 octet)CtrlData(0 ~ 26 octets)

其中Opcode指示控制&管理packet的类型,包括:

LL_CONNECTION_UPDATE_REQ,连接参数的更新;
LL_CHANNEL_MAP_REQ,Channel map的更新;
LL_TERMINATE_IND,连接即将被关闭的通知(可以通知被关闭的原因);
LL_ENC_REQ、LL_ENC_RSP、LL_START_ENC_REQ、LL_START_ENC_RSP,加密有关的请求;等等,具体可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。

3.3 连接的建立

对BLE来说,连接建立的过程很简单,包括:

1)处于connectable状态设备(Advertiser),按照一定的周期广播ADV_IND或者ADV_DIRECT_IND包(可参考“蓝牙协议分析(5)_BLE广播通信相关的技术分析”)。

2)主动连接的设备(Initiator),在收到广播包之后,会回应一个CONNECT_REQ请求,该请求携带了可决定后续“通信时序”的参数,例如双方在哪一个时间点、哪一个Physical Channel收发数据,等等,后面会详细描述。

3)Initiator在发出CONNECT_REQ数据包之后,自动转变为Connection状态,成为Master角色(注意:这是“自动”的,不需要等待另一方的回应)。同样,Advertiser在收到CONNECT_REQ请求之后,也自动转变为Connection状态,成为Slave角色。

4)此后,双方按照CONNECT_REQ参数所给出的约定,定时到切换到某一个Physical Channel上,按照Master->Slave然后Slave->Master的顺序,收发数据,直至连接断开。

master在发出连接请求的时候,需要在CONNECT_REQ PDU的payload中,定义和连接有关的参数。payload的格式如下:

InitA (6 octets)AdvA (6 octets)LL Data (22 octets)

其中InitA和AdvA分别是Master和Slave的蓝牙地址,LL data则包含了所有的连接参数,包括:

AA (4 octets)CRCInit (3 octets)WinSize (1 octet)WinOffset (2 octets)Interval (2 octets)Latency (2 octets)Timeout (2 octets)ChM (5 octets)Hop (5 bits)SCA (3 bits)

AA,LL Connection的Access Address,在不同设备组合之间,需要唯一,并遵守一些原则,具体可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。

CRCInit,用于CRC计算的一个初始值,由Link Layer随机生成。

WinSize和WinOffset,全称是transmitWindowSize和transmitWindowOffset,用于决定连接双方收发数据的时间窗口(第2章提到的时分的概念)。下面3.4小节会详细介绍。

connInterval,全称是connInterval,连接双方收发数据的周期。由于一个Master可能会和多个Slave建立连接,因此蓝牙的信道资源不能被某一个LL Connection所独占,所以一个收发周期中,可能有多个连接进行收发数据(具体的时间窗口,由transmitWindowOffset决定)。下面3.4小节会详细介绍。

Latency和Timeout,全称是connSlaveLatency和connSupervisionTimeout,和连接超时、自动断开有关,具体可参考3.4小节的描述。

ChM的全称是Channel map,用于标识当前使用和未使用的Physical Channel。Hop的全称是hopIncrement,它和ChM一起决定了数据传输过程中的跳频算法,具体可参考3.6小节的描述。

SCA(sleep clock accuracy),用于定义最差的Master睡眠时钟精度,具体可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”,本文不再详细介绍。

3.4 连接建立后的通信过程

3.3小节提到,当Master发出/Slave收到CONNECT_REQ后,就自动进入连接状态,那双方在收发数据的时间窗口怎么确定呢?可参考下面图片1和图片2:

BLE连接时序—Master视角

图片1 BLE连接时序—Master视角

BLE连接时序—Slave视角

图片2 BLE连接时序—Slave视角

1)从Master的视角看,当它发出CONNECT_REQ后,会在1.25 ms + transmitWindowOffset到1.25ms + transmitWindowOffset + transmitWindowSize之间,发送第一个packet(M->S)。同理,Slave在收到CONNECT_REQ之后,也会在相应的时间区间去接收packet(M->S)。

a)transmitWindowOffset可以控制这个LL Connection使用哪一段时间进行通信,从而保证了同一个Master和多个Slave之间的多个连接,可以互不影响的通信(时分)。transmitWindowOffset的取值范围是:0 ms到connInterval(后面会介绍connInterval)。

b)从Master发出CONNECT_REQ,到Slave接收到CONNECT_REQ,是有一定的时间延迟的,因此需要一定的时间窗口(transmitWindowSize),才能保证第一个packet能否正确的发送并被接收。transmitWindowSize必须是1.25ms的倍数,最小值是1.25 ms,最大值是(connInterval - 1.25 ms),但不能超过10ms。

c)正常情况下,所有“M->S”数据包的发送,不能超过transmitWindowSize,以便留出S->M的时间。但第一个packet例外(参考上面图片1)。

2)Master发出第一个packet之后,将以此为起始点(称作anchor point),以connInterval为周期,接着发送后续的packet(M->S),以及接收Slave的packet(S->M),具体可参考上面图片1。

a)这样以connInterval为周期的发送(M->S)、接收(S->M)组合(可能有多个),称作Connection Event。因此BLE面向连接的通信的基础,就是Connection Event。

b)connInterval的大小,决定了数据传输的周期。对一个连接来说,每个周期只能有一次的收发,因此connInterval的选择,直接决定了数据传输的速度。BLE协议规定,connInterval必须是1.25ms的倍数,范围是7.5ms~4s。

3)Slave如果没有收到第一个packet(M->S),则会以1.25 ms + transmitWindowOffset为起点,等待connInterval之后,再次尝试接收,直到接收到为止。Slave接收到packet之后,则以收到该packet的时间点为起始点(anchor point),以connInterval为周期,接着接收后续的packet(M->S),以及发送packet给Master(S->M),具体可参考上面图片2。

注2,关于数据传输的速率:
由上面的通信过程可知,BLE面向连接的通信速率,是由connInterval以及每个Connection Event中所传输的数据量决定的。
由上面3.2的描述可知,LL Data PDU的有效负荷不能超过255(251)bytes,不过考虑到一次传输的效率、错误处理等因素,具体的Link Layer不会使用这么大的packet。相应地,为了提高传输速度,一般会在一个Connection Event中,传输多个packet。以iOS为例,它可能会在一个Connection Event中,传输6个packets,每个packet的长度是20bytes。
另外,很多平台为了保证自身作为Master的性能,会限制connInterval的最小值,以iOS为例,最小值是30ms。因此,可估算得到相应的传输速率为20B * 6 / 30ms = 32kbps,是相当缓慢的。

注3:BLE的面向连接通信是使用跳频技术的,即每次Connection Event,都会使用不同Physical Channel收发数据,具体的跳频机制,可参考3.6小节的介绍。

3.5 连接的控制与管理

连接建立之后,Master或者Slave可以借助Link Layer Control Protocol (LLCP),通过LL Control PDU,对连接进行管理控制,包括:

Connection Update Procedure,连接参数(包括connInterval,connSlaveLatency,connSupervisionTimeout)更新的通知。只能由Master发起。

Channel Map Update Procedure,更新Channel map。只能由Master发起。

Encryption Procedure,对连接进行加密,可由master或者slave发起。

Termination Procedure,断开连接。

Connection Parameters Request Procedure,请求更新连接参数(connInterval,connSlaveLatency,connSupervisionTimeout),Slave或者Master都可以发起,和Connection Update Procedure不同是,这是一个协商的过程,不是一定能够成功。

LE Ping Procedure,类似于网络协议中ping操作。

等等。不再详细介绍,具体可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。

3.6 连接超时及断开

BLE连接断开的原因有两种:一种是预期内的、主动断开,此时会走3.4小节提到的Termination Procedure过程;第二种是一些非预期的原因导致的超时断开,如距离超出、遭受严重的干扰、突然断电等。

对于第一种,是协议内的正常流程,没有什么好说的。而对于第二种,则需要一些timeout机制,检测这写异常情况,具体如下。

1)Master和Slave的Link Layer,都会启动一个名称为TLLconnSupervision的timer,每接收到一个有效的数据包时,该timer都会重置。

2)连接建立的过程中,如果TLLconnSupervision超过6 * connInterval(没有接收到第一个数据包),则认为连接建立失败。

3)在连接成功之后,如果TLLconnSupervision超过connSupervisionTimeout,则说明link loss,则执行超时断开。connSupervisionTimeout是一个可配置的参数,范围是100ms~32s,并且不能大于(1 + connSlaveLatency) * connInterval * 2。

4)BLE协议允许slave忽略掉“connSlaveLatency”个Connection Event,在被忽略的这段时间内,Slave不需要收发数据包,也不会增加TLLconnSupervision,从而引发超时断开。connSlaveLatency是一个整数,有效范围应该在0到((connSupervisionTimeout / (connInterval*2)) - 1)之间,并且不能大于500。

注4:connSlaveLatency是一个非常有用的参数,它允许Slave在数据通信不频繁的时候,忽略掉一些Connection Event,进而可以睡得更久,更加省电。

3.7 跳频(Hopping)策略

BLE的跳频策略是非常简单的,即:每一个Connection Event,更换一次Physical Channel,当然,master和slave需要按照相同的约定更换,不然就无法通信。这个约定如下:

BLE跳频策略

图片3 BLE跳频策略

1)首先,使用一个Basic的算法,利用lastUnmappedChannel和hopIncrement,计算出unmappedChannel。

a)lastUnmappedChannel在连接建立之初的值是0,每一次Connection Event计算出新的unmappedChannel之后,会更新lastUnmappedChannel。

b)hopIncrement是由Master在连接建立时随机指定的,范围是5到16(可参考3.3中的Hop)。

c)确定unmappedChannel的算法为:unmappedChannel = (lastUnmappedChannel + hopIncrement) mod 37,本质上就是每隔“hopIncrement”个Channel取一次,相当直白和简单。

2)计算出unmappedChannel之后,查找当前的Channel map,检查unmappedChannel所代表的Channel是否为used channel。如果是,恭喜,找到了。

Channel map也是由master,在连接建立时,或者后来的Channel map update的时候指定的。

3)如果不是,将所有的used Channel以升序的方式见一个表,表的长度是numUsedChannels,用unmappedChannel和numUsedChannels做模运算,得到一个index,从按照该index,从表中取出对应的channel即可。

3.8 应答(Acknowledgement)和流控(Flow Control)

由3.2小节的描述可知,LL Data PDU的Header中,有NESN(Next Expected Sequence Number)和SN(Sequence Number)两个标记,利用它们,可以很轻松的在Link Layer实现应答、重传、流控等机制。

为了实现这些功能,Link Layer会为每个连接创建两个变量,transmitSeqNum和nextExpectedSeqNum(为了和packet的SN/NESN bit区分,我们将它们简称为sn和nesn),并在连接建立的时候,它们都被初始化为0。

sn用于标识本地设备(Link Layer)发送出去的packets。

nesn是对端设备(Link Layer)用来应答本地设备发送的packet,或者请求本地设备重发packet。

Link Layer在收发packet时,会遵循如下的原则(可结合下面图片4理解):

注5:下面图片4是从“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”中截的一张图,不过spec中画的有问题,我用红色字体改正了。另外,这个图片非常有歧义、难以理解,我会在下面解释。

1)无论是Master还是Slave,发送packet的时候,都会将当前的sn和nesn copy到packet的SN和NESN bit中。

2)无论是Master还是Slave,当接收到一个packet的时候,会将该packet的NESN bit和本地的sn比较:如果相同,说明该packet是对端设备发来的NAK packet(请求重发),则需要将旧的packet重新发送出去;如果不同,说明是对端设备发来的ACK packet(数据被正确接收),则需要将本地的sn加1,接着发送新的packet。

a)以上过程可参考下面图片4中的左边部分。

b)本地的sn,代表本地设备已经发送出去的packet,而packet中的NESN bit,代表对端设备期望本地设备发送的packet。如果二者相同,说明对方期望下次发送的packet,和我们已经发送的packet相同,因此是NAK信号,要求重发。如果二者不同,说明对方设备期望发送一个新的packet,也说明我们上次发送的packet已经成功接收,因此可以将本地的sn加1了。

3)无论是Master还是Slave,当接收到一个packet的时候,会将该packet的SN bit和本地的nesn比较:如果相同,则说明是一个新的packet,接收即可,同时将本地的nesn加1;如果不同,则说明是一个旧的packet,什么都不需要处理。

a)以上过程可参考下面图片4中的右边部分。

b)packet中的SN bit,代表对端设备正在发送的packet,而本地设备的nesn,代表本地设备期望对端设备发送的packet。如果二者相同,则说明是一个期望的packet(新的),就可以收下该packet,并将期望值加1(nesn加1)。如果二者不同,说明不是本地设备期望的packet,什么都不做就可以了。

4)上面2)和3)两个步骤,是相互独立的,因此一个NAK packet,也可能携带新的数据,反之亦然。

5)当一个设备无法接收新的packet的时候(例如RX buffer已满),它可以采取不增加nesn的方式,发送NAK packet。对端设备收到该类型的packet之后,会发送旧的packet(图片4左边部分的“TX old data, sn”分支)。该设备收到这样旧的packet的时候,不会做任何处理(图片4右边部分的“Ignore RX data”分支)。这就是Link Layer的流控机制(Flow control)

BLE应答和流控机制

图片4 BLE应答和流控机制

4. HCI

HCI(Host Control Interface)的功能就简单多了,就是要封装Link Layer所提供的功能,包括两类。

1)连接的建立、关闭、参数设置、管理等,这一类是通过HCI command/event(其格式可参考“蓝牙协议分析(5)_BLE广播通信相关的技术分析”中的介绍)完成的,包括:

LE Create Connection Command,建立连接的命令,需要提供连接有关的参数,包括connInterval(Conn_Interval_Min和Conn_Interval_Max)、connSlaveLatency(Conn_Latency)和connSupervisionTimeout(Supervision_Timeout)。

LE Create Connection Cancel Command,取消或者断开连接。

LE Connection Update Command,更新连接参数,包括connInterval(Conn_Interval_Min和Conn_Interval_Max)、connSlaveLatency(Conn_Latency)和connSupervisionTimeout(Supervision_Timeout)。

LE Set Host Channel Classification Command,配置Channel map。

LE Read Channel Map Command,读取Channel map。

等等。

有关这些命令的具体描述,可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 2, Part E] Host Controller Interface Functional Specification”。

2)对ACL data的封装和转发,不再详细说明。

6. GAP

GAP(Generic Access Profile)的主要功能,是定义BLE设备所具备的能力,以实现互联互通的功能。

对BEL基于连接的通信来说,GAP定义了4种连接有关的模式(不同的产品形态,可以选择是否支持这些模式,具体可参考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] 9.3 CONNECTION MODES AND PROCEDURES”):

Non-connectable mode,不可被连接。

Directed connectable mode,可以被“直连”(在知道对方蓝牙地址的情况下的快速连接)。

Undirected connectable mode,可以被“盲连”(不知道对方蓝牙地址)。

Auto connection establishment procedure,可以被自动连接(不需要host干预)。

相应地,GAP定义了5中和这些模式有关的过程(不同的产品形态,可以选择是否支持这些过程):

General connection establishment procedure,通用的连接建立过程,搜索、发现、连接,都需要Host参与。

Selective connection establishment procedure,有选择的连接建立过程,Host需要告诉Controller,自己只希望于特定的设备建立连接。

Direct Connection Establishment Procedure,直接和某一个已知设备建立连接(对方也知道我们)。

Connection Parameter Update Procedure,连接参数的更新过程。

Terminate Connection Procedure,断开连接。

这些mode和procedure的具体描述,可参考蓝牙spec[1]。

7. 参考文档

[1] Core_v4.2.pdf

原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。

标签:蓝牙BLEconnection跳频流控hoppingflow_control

继续讨论

新讨论请用 GitHub 账号在下方发言——评论会保存在本仓库的 Discussions 里,与站点同寿; 再下方的「历史评论」是原站的只读存档。

评论(129 条,只读存档)

以下为原站的历史评论(只读存档);继续讨论请用上方的评论区。

  • wuwu

    你真的好厉害啊,好崇拜你
  • 维尼

    BLE让蓝牙起死了,未来很有可能一同智能家居的天下
    • wowo

      @维尼:一统天下估计不可能,这个市场蛋糕太大了…… 蓝牙SIG的估计是这样的:到2020年,全球的IoT设备数量将达到45亿,其中蓝牙设备约为14亿。
  • 老陆

    楼主什么时候写下BLE安全方面的内容?
    • wowo

      @老陆:按照我的思路,连接建立之后,就是安全了。 不过这几天有点忙,没时间写。 PS: BLE安全方面的逻辑,还是很绕的~
      • 老陆

        @wowo:是啊,我反反复复看,还是理解不了。。楼主好厉害,能把知识理得这么清!
      • 老陆

        @wowo:楼主,有两个问题请教下:(1) L2CAP层是利用HCI接口访问LL层吗? (2) GAP/SMP等有没有绕过L2CAP而直接跟controller通讯的部分?
        • wowo

          @老陆:1)蓝牙所有的通信,都绕不开HCI,必须经过HCI。所以L2CAP不能直接访问LL。 2)L2CAP只负责连接有关的数据通信,因此GAP基本上不和L2CAP打交道,一般都是直接和HCI交互。 3)SMP是基于连接的,因此需要一个L2CAP通道传输数据,至于是否有不经过L2CAP的,肯定有,例如连接建立的过程。
          • 老陆

            @wowo:对于HCI,我的理解是,对于单芯片解决方案,它未必是必须的。
            • wowo

              @老陆:一般情况,为了协议栈方便的兼容与统一,单芯片HCI也会存在,只是薄薄的一层。
  • zy

    “经典蓝牙连接建立的速度实在难以忍受(要好几秒)” 这个应该没这么久,standard模式下1.28s会扫一轮A train,interlaced 扫两轮,所以大部分应该在1s内就建立起来了;反倒觉得LE的连接慢了很多。
    • wowo

      @zy:BR/EDR和BLE在连接时间方面,差别还是很大的,可以总结为: BLE的连接时间,优点为:机制简单;消耗少;时间短;时间是确定的(这一点很重要)。它由advInterval决定,Connectable Undirected和Low Duty Cycle Connectable Directed两种Advertising Event不小于20ms,Connectable Directed Event不小于3.75ms。具体可参考“/bluetooth/ble_broadcast.html”。 对应的,BR/EDR的缺点是:机制复杂(不是简单的一两句话能说明白);消耗大;时间长;时间不确定(这一点很重要)。 BR/EDR的连接,类似2个人在操场上跑圈,master跑得快,slave跑得慢,最终总有机会遇到,但遇到的时间,是不确定的。运气好的话,可以立即遇上。运气不好的话,需要1个1.28s,甚至2个1.28s。 前面一直在强调“时间确定”这一点的重要性。试想这样的一种场景:两个设备需要周期性的建立连接,传输一笔实时数据,假设周期是1s(相当宽泛了,跟不用说说毫秒级的了)。BLE毫无压力,保证不辱使命。而BR/EDR就麻烦了,万一抽风了,超过1s才能连接上,怎么办?因此只能选择保持连接(相应的代价,就是维持连接的功耗)。
  • coco

    hi,wowo,这里请教一下阿,如果撇开bluetooth stack这一层进行测试,仅仅是针对bluetooth driver,是不是就只有tx,rx的概念了?
    • wowo

      @coco:是的,一般情况下,TX/RX上面可能会把HCI packet封装一下,0x1标识command、0x04标识event,等等。 因此用这一层测试,就是TX、RX加HCI的格式。
      • coco

        @wowo:这样子说,如果纯粹在drvier这一层去做测试,是无法测试得了如a2dp、opp等等这些profile功能的了吧?
        • wowo

          @coco:是的。
          • coco

            @wowo:哈哈,那有什么开源的针对于蓝牙方面的测试用例吗?
            • wowo

              @coco:你这个问题好大啊:-) 这要看是什么平台,纯linux的话还好一些,不过也不多。 说白了,基于HCI做测试,就是自己写一个协议栈了~~~
              • coco

                @wowo:小弟在android上尝试了直接由stack那一层进去,能做的事情也不多,就是扫描、配对、test mode(tx,rx)等等一些基本的。 请问纯Linux都有哪些呢?急需学习。
  • wowo

    @coco,经典蓝牙的测试确实不多,linux下也差不多是那些。你最好能确定要测什么东西,不同的测试内容,要借助不同的工具。
  • 老陆

    楼主,我现在调试,发现APP(Master)和设备(slaver)连接后,如果没有应用数据传输(更新服务的特征值),则会一直保持连接状态,而一旦有应用数据传输,过一会连接就断开了,且在APP收不到数据几十秒钟后,设备才收到连接断开的事件。我想请教,是不是连接以后,即使没有应用数据传输,也会有连接事件按连接间隔产生,从而维持连接?3.4节连接过后的通信过程中的那些M->S,S->M都是一些什么样的包啊?
    • wowo

      @老陆:链接之后,就算没有数据传输,也会在每个连接事件中传输数据包,只不过是空包而已。 M->S、S->M是表示master给slave,或者slave给master的数据包。
      • 老陆

        @wowo:连接事件如何产生在哪个规范里?连接的控制和管理好理解,是在GAP规范里。M->S,S->M,这些包的具体定义不在LL层,应该是上一层的协议规定的。
        • wowo

          @老陆:连接事件如何产生?你指的是哪个方面呢? 其实在BLE里面,连接事件(Connection Event),是一个虚拟的东西,表示的是一对主/从设备可以进行数据收发的一段时隙。 在BLE连接建立之后,这段时隙就基本确定下来了,主从双方按照一定的节拍(连接参数规定的),定时醒来收发数据即可。 上面的描述,是由LL实现的,至于收发的数据到底是什么,LL不会关心,而是由上层协议一层层传递下来的,如:Profile/Service---->GATT/ATT---->L2CAP----->HCI---->LL
          • 老陆

            @wowo:1. 打个比方,我现在有个GATT Service,其有一个characteristic的Properties为Notify,然后周期性地更新它,那么我感觉在LL,应该只有S->M的包。可上面又说了,在每个连接事件都有M->S和S->M,挺难理解的,是不是在这种情况下,M->S是空包? 2. 您之前说的,连接后,就算没有数据传输,也会在每个连接事件中传输空数据包,给我感觉连接事件是在LL层产生的..... 可能是我理解能力太差了 :(( 楼主对我遇到的,没有应用数据传输,连接正常,有数据传输后反而连接会断开的问题,有没有什么建议? 谢谢了!
            • wowo

              @老陆:我觉得,你之所以觉得理解困难,是因为你把协议的上下层次搅在一起去理解了。 协议的根本点就是,纵向的每个层次互相独立,都可以单独理解。 回到我们这个话题上,先明确一点:从LL看,BLE怎么才算处于连接状态? 答案是,连接双方的LL能正确的按照节拍收发数据,如果miss几次,就可能超时断开了。 所以,无论上层协议有没有实际的数据,LL都要维持这个M->S/S->M的节拍。 因此,如果上层协议有数据传输,LL很乐意的帮它们传输。如果没有怎么办?LL的数据节拍还是要维持,只不过不需要携带有效的用户数据而已(空包)。 “给我感觉连接事件是在LL层产生的”这句表述还是有问题,连接事件不是“产生”的,是连接建立之后的一个固有属性。 连接断开的话,每个BLE设备都会汇报一个断开原因的event,先大致确认一下。 至于断开的原因,很多,总结出来就是M主动断,S主动断,连接超时(距离过大,信号质量不好,某一个设备的LL无法处理了,等等)。
              • 老陆

                @wowo:非常感谢! :))
  • lenli

    窝窝 Length,有效数据的长度(Payload+MIC),只有8-bits,因此Link Layer所能传输的最大数据是255 bytes(有MIC的话是251bytes) 你说的一次最多可以传输251字节,蓝牙手册Vol 6, Part B 2.4小节 说的是最多27+4=31字节。 这个是我没有理解正确,还是你这里说错了
    • wowo

      @lenli:使得,一次传输。 都没有错,255是Data channel上的PDU;31是广播channel的PDU(可参考/bluetooth/ble_broadcast.html)。
  • ybcai

    WOWO,有一点疑问请教您: LL层中,每一个连接事件可以有多组 M->S S->M,这里假设是3组;那么,M->S 和 S->M 的顺序是什么规律: A:M->S S->M M->S S->M M->S S->M B:M->S M->S M->S S->M S->M S->M C:其它 ?
    • wowo

      @ybcai:这个我还真没有留意,从逻辑的角度看,应该是A。有空可以用协议分析仪抓一下包看看。
  • li_inlook

    你好,关于连接事件(Connection Event)时隙的确定的,比如 Connection Interval 50ms ,Latency = 0,那这个时隙是多大了?
    • wowo

      @li_inlook:抱歉,我不是特别明白您的问题,“时隙是多大”指的是什么意思呢?在连接参数里面,最重要的一个就是:我(slave)多久可以传输一次数据,就是connInterval。这个参数决定了数据传输的速率。而一次数据传输可以持续多久,是由master自行决定的。
      • li_inlook

        @wowo:非常感谢您的回复。 因为我看到你说“其实在BLE里面,连接事件(Connection Event),是一个虚拟的东西,表示的是一对主/从设备可以进行数据收发的一段时隙。 在BLE连接建立之后,这段时隙就基本确定下来了” 其实我说的“时隙是多大” 就是当interva 确定后,这个时隙的时长。
        • wowo

          @li_inlook:抱歉,终于明白你的意思了,这个长度是由transmitWindowSize决定的。
          • li_inlook

            @wowo:非常感谢
  • wan

    wowo,请教一下。看到LE Create Connection Command 中需要设置LE_Scan_Interval和LE_Scan_Window ,这里为什么需要扫描相关的参数。看spec不怎么明白。望解答!
    • wowo

      @wan:因为连接的过程包含了scan和connect: 先scan,找到一个符合目标的对象(符合某个规则的ADV包); 然后发连接请求,建立连接。
  • LaoShen

    楼主,有点不明白。是不是因为这个connection interval 和每个connection event能传输的packet数量限制的存在,才导致低速率(比如ios传输速率为20B * 6 / 30ms = 32kbps)。但是iphone也能用蓝牙耳机听歌啊,音乐的传输速率是很高的。一般大于200kbps吧?这个远远大于32kbps的速率是怎么传输的啊?是不是ios支持BLE的同时也支持classic蓝牙。classic蓝牙是不是没有connection interval 和每个connection event能传输的packet数量限制了?
    • wowo

      @LaoShen:是的。classic和ble的原理完全不同。
      • LaoShen

        @wowo:楼主, 是不是有些profile不能运行在BLE上的,比如A2DP? 有没有可能指定HID profile用classic bluetooth而不是BLE? 这样速度能快一点?
        • wowo

          @LaoShen:是的,目前为止BLE不支持A2DP(后面肯定会支持的)。 至于指定profile,技术上肯定没问题。不过考虑到BLE/Classic不能互通,因此需要看对端设备的脸色行事,要强行classic的HID配BLE的HID,就不可能了。
  • yicun

    wowo,请教一下 这个ble从连接建立、再发送一帧数据、再断开,大约需多长时间? 最近公司在用nxp qn9021的芯片,这个时间实测接近于1s,有点太长,目标是50ms 于是方案改成,连接后master搜索从机服务特征值,写入特征值,从机收到后断开,这个时间也要200ms。 可是官方上说可以5ms大概,你说的20ms?,不知道是不是nxp这个芯片的限制,还是?
    • wowo

      @yicun:可以检查一下slave ADV(ADV_IND)的周期,看看是多少,一般连接时间是由这个决定的。如果实在想快,可以试试用ADV_DIRECT_IND。
  • lenli

    问一下窝窝: 应用层为了数据能正确在端到端之间传输,需不需要在实现两个控制传输层,ble本身的L2CAP层有重传机制,能确保数据到达对端吗?如果需要实现,怎么样做比较好?能大致讲一下吗?
    • wowo

      @lenli:首先: 链路层的PDU中,有24-bit的CRC Preamble Access Address PDU CRC (1 octet) (4 octets) (2 to 257 octets) (3 octets) 然后通过链路层的应答和重传机制,基本上保证了基于连接的数据传输是可靠的。 然后: L2CAP也有自己的应答、重传、流控机制(基于i-frame和s-frame)。 因此: 从L2CAP之上的应用程序的角度看,可以认为数据是可靠的,传输过程中的错误,对应用来说,就是无休止的重传和卡顿。
      • lenli

        @wowo:非常感谢窝窝。还想在问一下,LL层机制类似与TCP的传输,但不知道L2CAP如何实现?LL重传有次数的限制,当达到重传次数以后,数据是如何处理的,这部分的工作是L2CAP实现的吗?(i-frame和s-frame)大致的思路是什么样的?能讲一下吗?
      • lenli

        @wowo:我可能没有说清楚,在L2CAP层也还是重传这种思想吗?就你所说:对应用来说,就是无休止的重传和卡顿。假设最坏的情况下次数到了之后咋办?数据丢了还是有其他的办法
        • wowo

          @lenli:我这里只是介绍了简单的机制。其实重传机制,确实可以控制(重传次数等),经典蓝牙经常用。但在ble中,个人觉得没必要这么麻烦。想象一下我们遇到的困惑: BLE使劲的收,但都发生了错误!! BLE的数据一般是小批量的控制数据(不同于经典蓝牙的音乐播放),这样的数据一点都不能错。 因此,这个错误底层协议是清晰的知道的,那怎么办?其实告诉应用程序也没有什么意义,应用也一样干瞪眼。不如尽量重传下去,大不了链路的控制信息也传不下去了,连接就会timeout并断开了
          • lenli

            @wowo:谢谢窝窝的解答,如雷贯耳啊,lolllllll
  • chong

    我想请教一下窝窝: 主机端在同一时刻只能连接一个从机吗,这在哪体现出来的呢,刚开始看蓝牙这块,不是很懂,谢谢啦!
    • wowo

      @chong:不是。对BLE来说,主机可以连接多个从机,从机也可以连接多个主机。
      • chong

        @wowo:谢谢wowo的回复,我看到这样一段话“在任何时刻都只能最多一个设备在尝试建立连接。如果同时对多个蓝牙设备发起建立 Gatt 连接请求。如果前面的设备连接失败了,后面的设备请求会被永远阻塞住,不会有任何连接回调”,这个说法是对的吗?
        • wowo

          @chong:这个协议栈的设计有关,蓝牙协议没有规定这事儿。
          • chong

            @wowo:那我就了解了,真的很感谢wowo☺
            • q576333

              @chong:向wowo請教一下 您說從機也可以連接多個主機 那假設我有多個主機都有各自連接多個不同的從機 而主機間也如果需要互相通訊 那相對的是不是可以把從機當成是主機間通訊的轉寄站呢?
  • q576333

    向wowo請教一下 您說從機也可以連接多個主機 那假設我有多個主機都有各自連接多個不同的從機 而主機間也如果需要互相通訊 那相對的是不是可以把從機當成是主機間通訊的轉寄站呢? (剛剛才發現原來我按錯回復了....)
    • wowo

      @q576333:没关系的,都能看到,只是有点事情,没来得及回复,抱歉! 可以的,这其实就是mesh网络的拓扑了。而且从这个角度看,主或者从的概念,已经不重要了,重要的是传输的效率,只要可以满足应用需求即可。
  • Micah

    3.2.1 LL Data PDU中LLID=0x10是Start of an L2CAP message or no fragmentation吧,你的两个LLID是一样的。刚开始了解蓝牙,看了你之前写的好多的日志,很有收获!
    • wowo

      @Micah:多谢提醒,确实写错了,已改正:-)
  • panda

    一个Connection Event中packet的个数需要master和slave之间协商吗?
  • panda

    WOWO,一个Connection Event中packet的个数需要master和slave协商吗?
    • panda

      @panda:我在spec里找到了答案: The MD bit of the Header of the Data Channel PDU is used to indicate that the device has more data to send. If neither device has set the MD bit in their packets, the packet from the slave closes the connection event.
      • wowo

        @panda:Good job:-)
  • darren

    我想用linux 系统的开发板作为蓝牙server ,让安卓手机作为client, 手机主动发起匹配,连接。成功后,手机端APP端发送数据,开发板接受到数据后,再做相应的动作。 请问这种应用场景用到哪种协议? 没有参看例子? 网上都是开发板自动发起匹配连接的。蛋疼。 谢谢。
  • lpy

    我想问一下,BLE时分过程是怎么时分的?比如两个从设备与主设备通信,同时还有主设备可以作为别的设备的从设备,整个过程怎么理解?望解答
    • wowo

      @lpy:BLE和经典蓝牙不同,时分的概念有点特殊,因为master和slave之间,不会共享physical channel。 也就是说,无论是一个master和多个slave之间,还是一个slave和多个master之间,都是独立的物理channel。 而时分的概念,仅仅是指master可能要在不同的时间段和slave进行数据收发(参考本文3.4小节的连接参数的说明)。
      • lpy

        @wowo:这个我理解,就是master和slave按时到指定信道去收发。有一个问题,如果一个slave和master1通信了,然后这个slave与master2也通信了,那slave怎么协调这个时间?因为通信连接参数都是master下发给slave的,望解答
        • wowo

          @lpy:我们讨论的这些“时间”,例如connection event等,都是链路层(link layer)的概念。它们是怎么对应到物理层的传输上的(是否可以并发,是否可以串行,等等),要看ble controller的设计。 不过,这一块我也不是很熟悉,因此不能立即回答你(抱歉!)。后面有时间我可以看看controller的具体行为,再和你讨论。
          • lpy

            @wowo:你好,我想咨询下,“这样以connInterval为周期的发送(M->S)、接收(S->M)组合(可能有多个)”这句话是在M-S、S-M在一个连接间隔内可以进行多次么?
            • wowo

              @lpy:是的,不过蓝牙spec上的比较模糊,具体要看相应的controller是怎么支持的。有以下的信息可供你参考: 1. 蓝牙spec(这里以Core_v5.0.pdf为例) Figure 1.4: Connection Events 2. Nordic社区中有关的回复 https://devzone.nordicsemi.com/question/3440/how-do-i-calculate-throughput-for-a-ble-link/ Number of packets per event With regard to number of packets per connection event, the nRF8001 will be able to receive 2-3 but can transmit only 1. The nRF51822 on the other hand can both send or transmit up to 6 packets per interval. It seems that most Android devices supports ~4 packets per interval, while most iOS devices supports up to 6 packets. 不过具体是怎么样的行为,我没有实测,所以有可能理解的不对,你可以再帮忙确认一下。
              • lpy

                @wowo:你好,我想问一下,上面提到slave在传输窗口内没有收到包,那会在下一个窗口继续进行接收。那我想问的是如果master在第一个传输窗口发了一个包,slave也收到包了,只是master没有收到slave的发的包,那下一步怎么进行?
              • ljy

                @wowo:可以的,传输声音数据或者快速的OTA 功能时都需要多个数据一个Interval,Android手机实测可达5/interval.
  • wowo

    @lpy ------------------------------------------------------- @wowo:你好,我想问一下,上面提到slave在传输窗口内没有收到包,那会在下一个窗口继续进行接收。那我想问的是如果master在第一个传输窗口发了一个包,slave也收到包了,只是master没有收到slave的发的包,那下一步怎么进行? ------------------------------------------------------- 1. 无论怎么样,master发包的时间点都是固定的(不管slave收到与否)。因此,master有没有收到slave的发包,是一个“无关紧要”的事情。 2. slave之所以要等master的发包,是为了确定收发数据的时间点(这个是master决定的,参考上1的说明)。 3. 最后,master无法收到slave发包,或者slave无法收到master的发包,都会走后续的超时断开流程(connSupervision)。
  • zoe_man

    @wowo请教一下,Master和Slaver建立连接后,由于超出距离而断开连接,从协议栈看此时host发起了LE Create Connection,但是收到Slaver的广播包后,没有立即连接上,过了大概1分钟后才连接成功,而这1分钟时间都在report Slaver的广播包,这是为什么?
    • wowo

      @zoe_man:把这一分钟的包抓一下,看看才能知道怎么回事。
      • zoe_man

        @wowo:@wowo:您好!是怀疑发出的包有问题吗?可以确定Slaver发出的广播包没问题。但有一点异常,发起连接时BD_ADDR是空的,正常情况下BD_ADDR应该存在才对,不知道这是为什么?望解答。 谢谢!
        • wowo

          @zoe_man:BD_ADDR都是空的了,还有什么好说的啊!查这个问题就是了。至于为什么,我还想问你呢(偷笑:-)
          • zoe_man

            @wowo:wowo:我看到btsnoop里是LE_Create_Connection的时候启用了White_list机制,这个机制会对我连接有影响吗?
            • wowo

              @zoe_man:会。你要检查一下白名单是怎么用的,已经被连接的设备是否在你的白名单里面。另外也可以先把白名单禁用看看是否okay。
  • odissey

    你好,请教一个问题: 你的文章里提到“连接建立的过程中,如果TLLconnSupervision超过6 * connInterval(没有接收到第一个数据包),则认为连接建立失败。”请问这个是BLE规范里定义的吗? 1、我使用NXP9021主从机例程测试时,我在主机扫描到从机后,就把从机断电了,然后在主机侧调用GAP_LE_CREATE_CONN_REQ请求,发现过了很长时间,并不会返回任何错误。 2、主机扫描到从机并且和从机成功建立连接后,我迅速将从机断电,过一会(具体时间我没有测试),应该就是过了connSupervisionTimeout,主机会打印连接断开,并且返回断开原因CO_ERROR_CON_TIMEOUT。 我现在的疑问是:是否只有在连接成功建立后,才会有超时机制,而连接建立前没有超时机制,还是说BLE规范里定义了超时机制,只是厂商各自实现不同,比如我自己需要在调用GAP_LE_CREATE_CONN_REQ后,开启定时器去判断连接建立成功没有。 还有一个疑问就是:测试2里,我代码里的connSupervisionTimeout配置为20s,为什么将从机断电后,主机很快,大概不到1s的样子,就返回CO_ERROR_CON_TIMEOUT了。 谢谢。
    • wowo

      @odissey:1. 你去看spec,“Supervision Timeout”说的清清楚楚的,是指在连接建立之后的超时断开。 连接的时候,没有收到连接成功的消息之前,都是不成功,不需要什么定时器。 2. TLLconnSupervision和connSupervisionTimeout不是一回事,时间也不一样。前者监控的是所有的数据包(断电属于这种情况),后者监控的是data pdu。
  • dong

    希望wowo能够写一章描述“一个数据”在协议栈里格式如何变化的帖子,因为作为新手我们本来对每个层的概念就不是很清晰,这样可以通过数据格式的变化来理解它们,而不是反过来通过理解每个层的概念来猜他的PDU格式。 比如说,本来以为理解了HCI层和LL的概念了。可是在看协议BLUETOOTH SPECIFICATION Version 4.0 [Vol 3] L2CAP层的Recombination功能的时候,给出了一幅“一个数据”是怎么从L2CAP->HCI->LL的。但是HCI->LL那个地方并没有说明HCI data packets是怎么变成你这一篇文章所说的data chanel PDU的,瞬间就懵逼了,找协议也没有找到相关的,难受啊。
    • wowo

      @dong:多谢建议,有时间的话我会按照你所困惑的思路整理一下~
  • odng

    wowo好久没来逛了,最近遇到个问题,比较郁闷来请教一下。 我用sniffer进行抓包,主从设备连接之后,一开始双方交换空包(心跳包)是正常的,慢慢的会频繁抓到slave连续发出来的空包,而且每个包的sn和nesn都是一样的,只是每个包发送的channel不一样(sniffer是从3个channel抓到的包),我就感觉很疑惑,为什么会出现这种情况呢?
    • wowo

      @odng:slave没有收到master的包?不过这种情况下channel应该一样才是啊(不应该有跳频发生)。
      • dong

        @wowo:假设slave没有收到master的包,slave为什么还会发包出去呢?先不考虑channel的问题,协议里面不是每次S->M之前,必须要有个M->S吗? 我查阅了一下协议,要让slave发一模一样的sn和nesn,有可能是master那边发过来的包收到了,但是CRC是有问题的,但是这样也是基于M->S的包接收到才行。 我都开始怀疑是不是我的从机硬件有问题,或者是抓包软件漏包了,晕。
        • wowo

          @dong:包里面的SN和NESN,单纯比较是没有意义的,说明不了什么(参考本文的描述,它们要分别和本地的sn和nesn比较才有意义)。 “每个包的sn和nesn都是一样的”,是指每个包一样,还是指sn和nesn一样呢? 如果每个包一样,也就是说每个包的sn和nesn没变化,就是指: master期待slave发送的包没变,slave正在发给master的包也没变。也就是说此时slave一直在重发,并且没有收到master的任何回应。 如果sn和nesn一样,代表slave正在发生的,以及master期待slave发送的,是一样的,没问题啊!!
          • dong

            @wowo:指包里面的sn和nesn数值是一样的。 但是,如果slave没收到master'packet,slave怎么会知道master期望收到什么包呢,协议并没说slave会自发地进行重发啊,只有收到master'packet,并且这个packet的sn和nesn和slave上一个收到的master'packetsn一样的情况下,才会进行重发啊。 如果重发,不就说明slave已经收到master的包了?抓包软件应该显示出来master发出来这个packet才对呀,怎么说也不会连续出现两次一样的slave'packet呀,我是这么考虑的。
            • wowo

              @dong:是的,如果master不发,应该走timeout断开的流程。 “包里面的sn和nesn数值是一样的”,会增加吗?出现这种情况之后会断开吗?如果会增加,又不断开,很有可能是抓包出问题了。 如果不是,很有可能是slave controller有特殊实现,在收不到应答的时候自动重发了。
  • 方言

    Wowo,我感觉核心协议文档里那个图还是对的,可以直接通过包里的SN和NESN来判断包的情况,左边是数据的发送者,右边是数据的接受者,也就是要回复ACK的人。只是文档里的文字写得太晦涩了,和图的关系看起来不那么大。
    • 方言

      @方言:Wowo是对的,协议文档的图竟然是错的。比如接收方应该和上一次发出的NESN来对比,协议图里直接SN = NESN ?会让人误解利用本次接收到的包里的SN和NESN来对比。
      • wowo

        @方言:估计画那个图的家伙对协议太熟悉了,想当然的认为不应该直接比较包里面的内容,因而画图的时候就没有区分。
        • 方言

          @wowo:恩恩~ 是啊 :) 感谢Wowo的文章,让我们可以深入了解协议的内涵。
  • EE

    ------ nesn和sn到底是一个什么变量了??!!如果非二进制,1加1等于2了,如果位变量1加1等于0了,WOWO能否帮说明下下
    • wowo

      @EE:你把这篇文章仔细看看,可以解决你的疑惑的:-)
      • EE

        @wowo:确实是的,已看懂
  • EE

    "1)无论是Master还是Slave,发送packet的时候,都会将当前的sn和nesn copy到packet的SN和NESN bit中。"这句话中理解,“sn和nesn copy到packet的SN和NESN bit中”,那只能说明sn和nesn都是位变量才有意义,不是位变量压根就没有意义,假如发了3个包sn或nesn变成了3,copy给位SN和NESN,SN和NESN怎么的也是1,因为他除了1就是0,你加到30特么的也还是1,这有何意义呢
    • EE

      @EE:所以说sn和nesn只为位变量是否?
      • wowo

        @EE:是的,这篇文章中有说明,这两个sn和nesn都是1 bit,用于应答和重传,足够了。毕竟带宽有限,能省点开销是最好不过的了。
        • EE

          @wowo:恩恩,明白了是1bit
  • EE

    wowo帮忙请问:BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]// 4.5.7 Window Widening//中:If the slave receives a packet from the master regardless of a CRC match, the slave shall update its anchor point.是不是只有建连后的第一个包从机不管CRC是否匹配就算一个有效的包,后续包如果CRC不匹配就不算?如果从机每接收一个CRC不匹配的包也算的话,那很容易受到攻击,比如反正CRC不匹配也算一个包我就发一系列的假包,从机接到后就会创建新的anchor point 从而导致正确的主机包没法接收,是不是这样?
    • wowo

      @EE:第一个收到的包,不管CRC对不对,都会用来更新anchor point。 至于这个包是不是一个有效包,从送给Host,还是依赖CRC的,没毛病:-)
      • EE

        @wowo:恩恩也是的,还有个问题也一并请问下了:建连后当从机成功的接到主机的第一个包然确定了Anchor Point,此刻以后主机和从机都会以相同的connInterval为周期开始同步收发数据,这里就有个问题因为时钟没有绝对的相等,因为起点相同所以肯定会出现抢跑的情况,从而可能导致数据丢失,这个蓝牙是怎么规避的,是不是BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B] //4.5.7 Window Widening//就是说明如果规避的,Window Widening理解想来有点难度,wowwo有空可帮简单的说下吗?!
        • wowo

          @EE:双方的ble controller所维护的clock,基本上是很准确的,时钟的误差(PPM)很小,因此可以不考虑这种情况(或者说当时钟偏差到无法通信的时候,就是断开了)。
          • EE

            @wowo:这样说是有道理
  • EE

    wowo,又来问了喔,BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]//5.1.2 Channel Map Update Procedure// When a slave receives an LL_CHANNEL_MAP_REQ PDU where (Instant –connEventCount ) modulo 65536 is less than 32767 and Instant is not equal to connEventCount , the slave shall listen to all the connection events until it has confirmation that the master has received its acknowledgement of the LL_CHANNEL_MAP_REQ PDU or connEventCount equals Instant. 这原文总是理解不了:LL_CHANNEL_MAP_REQ PDU是单向的不会有回应命令,怎么会有acknowledgement?32767不知怎跑出来的,逻辑上感觉没有可理解性
    • wowo

      @EE:我暂时没有去看spec,姑且认为你这个表述“LL_CHANNEL_MAP_REQ PDU是单向的不会有回应命令”是对的,我的理解是,LL层的传输本身就是有应答的可靠传输。 32767是65536的一半,具体的逻辑,应该是Instant和connEventCount差值最大的时候?
      • EE

        @wowo:哦哦,暂那样理解先了,Instant和connEventCount差值最大32767,估计也是协议硬性规定数值无逻辑可言的,
        • wowo

          @EE:这个值应该有逻辑:Instant和connEventCount都是32bit表示,因此最大是65536,那么它们的差值的最大就32767(因为要取模)。
  • nikoladi

    wowo,看了你一系列文章,受益匪浅。 有没有继续分析ATT协议的打算,自己看core V4.2总是找不到在哪找。 总体还是把握不好
    • wowo

      @nikoladi:这一段暂时没有时间了,太忙了,见谅哈~~
  • EE

    wowo,请问瞬时到来时,从机没有接到主机发过来的包(主机链路丢失)从机该怎么做了?是以新的链接间隔一直进行扫描窗吗,直到超时还是怎样了?
    • EE

      @EE:wowo,我找到答案了,会一直接着发直到超时
  • cici

    您好,在设备支持直连的情况下,不扫描,直接通过mac地址直连的和扫描再连接的区别在哪里呢?会不会成功率不一样?
    • wowo

      @cici:主要是广播间隔不同,速度或者成功率就不同,可参考这篇文章: =========== 1)处于connectable状态设备(Advertiser),按照一定的周期广播ADV_IND或者ADV_DIRECT_IND包(可参考“蓝牙协议分析(5)_BLE广播通信相关的技术分析”)。
      • cici

        @wowo:您好,是这样的,我们目前采用的蓝牙设备,是支持直连的,而且我们也知道设备的mac地址,这种情况才,是否可以跳过接收广播的阶段,从协议上来看,广播阶段是否可以加快连接的速度?
  • 嘟囔

    大神你好,请问如果知道设备的mac地址,scan与否对连接成功率和速度有影响吗
    • wowo

      @嘟囔:scan与否,和连接无关。 如果需要加快连接速度,可以使用ADV_DIRECT_IND,但需要被连接方知道连接方的地址。
  • sdm

    看了蓝牙系列的文章, 受益匪浅, 谢谢
  • KK

    Wowo大 你好 sn和nesn還是不太懂意思 sn和nesn在连接建立的时候,它们都被初始化为0,无论是Master还是Slave,发送packet的时候,都会将当前的sn和nesn copy到packet的SN和NESN bit中。 如果初始化都為0 那發送pacekt時SN&NESN也都為0 那不是永遠都是0?什麼時候才有不同的情況? 謝謝
    • KK

      @KK:如果相同,说明该packet是对端设备发来的NAK packet(请求重发),则需要将旧的packet重新发送出去 舊的packet的SN&NESN還是0吧?
      • wowo

        @KK:你可以看看“图片4 BLE应答和流控机制”中的过程,我回复你也是把那个过程再写一遍~~~
  • 万

    connSupervisionTimeout是一个可配置的参数,范围是100ms~32s,并且不能大于(1 + connSlaveLatency) * connInterval * 2,这句有误,应该将“不能大于”改为“不能小于”。 参考 Core_v4.2.pdf P2620,The connSupervisionTimeout shall be a multiple of 10 ms in the range of 100 ms to 32.0 s and it shall be larger than (1 + connSlaveLatency) * connInterval * 2.
  • StayrealS

    WOWO大您好:拜读了您这个蓝牙协议分析系列受益良多,最近我也在研究BLE,有几个问题请教: 1. 我根据自己的理解大概画了个单master多slave的timeline的示意图: Master1 -TX--RX---TX--RX----Advertising------------ Slave1 -RX--TX-------------------------------------- Slave2 -----------RX--TX--------------------------- BLE4.1提出了一个设备可以既作为master也作为slave进行连接,那么如果上图中Slave1既是Master1的slave也是Slave2的master,timeline会变成怎么样呢? 2. 如果一个master连接了多个(如10个)slave设备,那么它就会一个一个的去进行connInterval的连接和传送吗?这样会不会导致每个slave被连接到的中间间隔很长呢? 3. 我记得在spec中有一个关于T_IFS的限制,就是从收到一个数据帧到自己发送出去需要间隔T_IFS,在您的文章里好像没有体现,是因为这个T_IFS过于细节了吗? 谢谢wowo大!
    • 方言

      @StayrealS:WOWO老大可能太忙,没空回复了,我来回复一下吧,WOWO看到如果不正确请帮忙指正。 T_IFS,这个在Spec的AIR INTERFACE PROTOCOL里一开头就有提到,意思就是同一个信道上连续的传送的包之间有一个时间的间隔,这个间隔叫 Inter Frame Space,即“T_IFS”。这个间隔不管发出者是主还是从,只要包与包之间,都必须有这个间隔。
  • bright

    Hi wowo https://www.codetd.com/article/2274205 裡面有一張關於sn nesn的流程圖。 請教一下 幾個問題 1. 一般情況下,假設本地端傳送資料給對端,那對端收到後一定會馬上回應? 2.假設是的話 connection packet 在傳送的時候 假設一開始是M->S master傳資料給slave sn nesn -> sn nesn 0 0 0 0 0 0 0 1 此時slave的sn與對端的nesn一樣,但是slave並沒有傳東西給master,難道也要理解成master發來的NAK? 這樣會使slave回傳ACK封包(但是內容是什麼?), 之後 0 0 <- 0 1 1 1 0 1 master 收到slave傳來的回傳以後,sn對上slave的nesn可以理解是slave的ack, nesn對上slave的sn,也可以理解,但是承上,slave傳的內容是什麼? 繼續傳未傳完的資料(MD = 1) 1 1 -> 0 1 1 1 1 0 slave收到master的資料,sn對上master的nesn,代表master有收到slave的data,nesn對上master的sn,代表收到的封包序號也是對的。 到這邊我就不理解slave是如何判斷要再度回傳封包給master? 雖然根據你的文章 sn != NESN(ack) 可以傳新的data ,可是slave到底要傳什麼內容給master? Empty PDU嗎?
  • ru-chan

    こんにちは。 パワハラ指切断でおなじみのド屑県香川のド屑企業フジフーヅでございます。 裁判も会社ぐるみで偽証をして無事乗り切ったド屑でございます。 餃子シュウマイなどをスーパーで販売しております。 店頭で見かけましたらそのときはご購入のほどどうかよろしくお願い致します。