本文记录对蓝牙协议栈逻辑链路及自适应协议层的学习还有后面如何在TI的蓝牙芯片上去实现L2CAPCoC的数据透传,为什么用L2CAPCoC进行数据透传呢?因为它每次透传的数据量远远能比GATT大,如果堆够用的话可以传输64KB,而GATT数据透传限于ATT-MTU,最多每次能传输的也就247个字节。
逻辑链路层及自适应协议层
该层属于主机的内容,位于HCI层的上一层,我们可以看下下面这个结构1-1加强一下印象:
1-1BLE协议栈框架
它的作用是为主机的GAP,GATT,SM,Application和链路层之间搭建起通信的桥梁,因此它有不可或缺的协议复用能力。在主机和协议栈数据交换中它还有数据分段和重组的能力。所有从主机或者APP发出的数据都在这一层被封装成L2CAPpacket。L2CAP允许更高层的协议和APP去发送和接收上层datapackets,最多能传输64KB。L2CAP也允许每个通道的流控制和重发机制。
常用的L2CAP术语
L2CAPChannel:L2CAP通道,对端设备两节点之间的逻辑连接,用它们的信道标识符做通道的区分。SDU:服务数据单元,L2CAP与上层交换的数据包,它不包含L2CAP的帧头。PDU:协议数据单元,包括了L2CAP协议信息域、控制信息、上层信息数据,这个数据包就包含了L2CAP的帧头。一个SDU可能被分割成多个PDU进行传输。MTU:最大数据传输单元,上层应用可以接收的payload最大字节数,注意这个跟ATT的MTU是不一样的。MPS:L2CAP可以接收的payload最大字节数。Credit:本蓝牙设备可以接收的LE帧数量。Credits取值范围是1~6553在两个设备之间使用流控制。L2CAPBasicHeader:为每个PDU预先准备的L2CAP协议信息。它包括了CID和长度。PSM:协议服务复用器,占用两个字节,用于定义L2CAP信道数据的解析。有动态的PSM和固定的PSMs。固定的PSMs是由SIG定义的,而动态的PSMs可以由GATT发现。Fragmentation/Reconbination:分包重组,分包是将单个L2CAPPDU分解成更小的数据段以供发送器发送的过程。重组是控制器将片段重新组装成完整的L2CAPPDU的过程。分包重组是由控制器实现的,并且基于LE数据长度扩展特征。Segmentation/Reassembly:分段是将单个L2CAPSDU分解成多个成为SDU段的L2CAP数据包的过程。在接收侧按照与此操作相反的方式进行重新组装。每个段都封装在一个适当的L2CAP报头中。分段和重组都是由L2CAP处理,并且对上下层都是透明的。注:SDU的最大字节数等于协议栈里边定义的L2CAP_SDU_SIZE。代码如下:
L2CAP的工作模式
蓝牙5协议栈L2CAP支持两种不同的工作模式:BasicL2CAPMode和LECreditBasedFlowControlMode。
L2CAP通道
L2CAP由3种通道类型:Connection-Oriented、Connectionlessdata、L2CAPsignaling。L2CAP的每个端点由信道标识符CID引用。Connectionlessdatachannels不适用于蓝牙5协议栈。通道可以划分为固定通道和动态通道。 固定通道执行特殊的L2CAP功能,使用的CIDs范围在0x0001和0x003F之间。每个固定通道的特征都是独立的。 下面罗列了协议栈和应用程序可以使用的CIDs
0x0004 | Attribute Protocol(ATT) | Sending ATT information |
0x0005 | LE Signaling Channel | Sending L2CAP commands |
0x0006 | Security Manager Protocol(SMP) | Sending Pairing/Security Information |
0x0040~0x007F | Dynamically Allocated | LE Credit Based Flow control packets |
比如,GATT层的数据交互使用的通道是0x000SMP使用0x0006通道。应用程序不能直接访问ATT、SMP、信号通道,因为它们已经被相关的HostLayers使用了。上面提到的LEsignalingchannel使用在L2CAP连接参数更新流程、使用在动态通道上建立LECredit基本连接,以及使用在交换Credits上。 动态分配的通道ID用于识别逻辑链路和本地端点。本地端点的取值范围是0x0040到0xFFFF。这个本地端点用于面向连接的L2CAP通道。这些动态分配的通道是可以被应用程序访问和管理的,以便在L2CAP-COC上定义自己的协议。L2CAP通道是双向的,类似于套接字。动态分配一个通道,有以下3个参数:PSM、MTU、CID。前面提到,固定的PSMs是由BLESIG定义的,它们的范围是0x00010x007F。动态的PSMs的范围是0x00800x00FF。PSMs可在GATT服务端设备上保持固定,而GATT客户端可以从GATT服务端中获取PSM。
L2CAP帧类型
在蓝牙协议栈里面有两个L2CAP帧类型。 BasicFrame:基本帧,在基本模式下由固定通道使用 LEinformationFrame:低功耗信息帧,用于LEcredit基本流控制模式下的动态通道。注:L2CAP处理来自主机或者APP的SDU数据帧。下面是不同帧类型的帧头区别:
Basic frame | 4 | Length:2 octets CID: 2 octets |
LE information frame | 6 | Length:2 octets CID: 2 octets SDU length: 2 octets |
从L2CAP的角度来看,所有数据包都作为完整的数据包发送到控制器和从控制器接收。这也意味着分段/重组是由控制器执行的,并且对L2CAP不可见。当使用分段时,较大的数据包将被拆分成多个LL数据包然后在对端设备的LL层进行重组。
当工作在基本模式下,L2CAP不执行分段或者重组。动态通道工作在LECredit基本流控模式下,是有可能发生数据包的分段和重组的。
L2CAPMTU
L2CAPMTU是L2CAP层能够处理的最大数据字节大小。然而,L2CAP使用的MTU是不同的,取决于模式和通道类型。信号通道会使用L2CAP_SIG_MTU_SIZE固定通道数据包的MTU限定最大是MAX_PDU_SIZE-L2CAP_HDR_SIZECOC数据包的最大字节数取决于PSM的MTU,同时被L2CAP_SDU_SIZE限制 当对于固定通道,MTU由更高级别的协议定义。在COC上,MTU受L2CAP_SDU_SIZE和对端设备支持的MTU的最小值约束。
MAX_NUM_PDU定义了一次可以入列到控制器的TX数据包的最大个数。尝试发送更多数据包将导致调用的API接口返回失败,并且数据包也没有真正入列到控制器中。 应用程序可能不清楚在给定时间内有多少个数据包在等着发送,因此我们在写代码调用API的时候最好就是检查API的返回值。还有,一般L2CAP有流控制通知功能,我们可以使用它来提高L2CAP数据通讯的效率。这里那ti的蓝牙芯片来举例,可以使用L2CAP_RegisterFlowCtrlTask这个API使能流控,这样协议栈会有事件L2CAP_NUM_CTRL_DATA_PKT_EVT通知APP可发送的数据包数量,这个事件会在每次有新的缓冲区可用时触发。
总结
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点