目录
L2CAP协议浅述
L2CAP简介
通用操作
信道标识符
两个设备间操作
层级间操作
信道工作模式
数据包传输格式
面向连接通讯
无连接通讯
在重传、流控、流模式下的面向连接的通讯
在LE credit模式下的面向连接的通讯
信道命令传输格式
信道命令分析
状态机
L2CAP协议数据分析
L2CAP全称为逻辑链路与适配协议,其为高层协议如SDP、RFCOMM的提供了复用接口,并提供数据的分割/重组和高品质服务信息的传输。
下面我将基于远端和协议层级操作、数据包格式、信道命令格式、状态机进行分别说明。
其整体的结果图如下:
L2CAP传输是基于信道的概念,类似于fifo的通信通道,他是一个点对点的通道,每个通道都有一个独立的信道标识符(channel identifier,CID),以下简称CID。学习L2CAP,理解信道是非常重要的,在HCI层的配置信息交互完成之后,信道就会被建立,在ACL链路中通常会建立一个信令信道,如CID号为0x0001,用于发送控制指令。
CID由一个字标识,即两个bytes,其中0x0000不使用,0x0001--0x003f有固定的用途,具体可以去查相关描述的表格,在0x003f之后的可以动态分配,一般做为数据传输的cid,下面给出特定cid的用途:
上面描述的cid命名空间可用于ACL、ASB和AMP链路,下图中的命名空间则用于LE链路:
下图说明了不同设备之间的L2CAP实体间通信的使用方式。
在面向连接的数据信道(如语音通话数据通道)提供了两设备间的连接,而CID则用于标识信道的每一端。无连接信道(如短信)限制数据向单一方向的流动。
有一些信道是作为特殊用途的,如信令信道,固定的CID=0x0001(LE固定为0x0005)。该信道用于创建和建立面向连接的数据信道,并可对这些信道的特性变化进行协商。当两端协商好配置信息之后,会动态分配另一个信道,从上一小节我们可以知道0x0040之后都是为动态分配的信道,这些信道用于上层的数据传输。
层级间用请求-确认、i指示-回复模型通讯,即上层通过向下层发出请求,下层处理完成之后会给出确认;同时下层通过指示的方式通知上层,上层处理完之后会给出回复,其过程如下图所示:
逻辑信道可以工作在5种不同的模式下(可以理解为5种不同的使用场景),最后一种是LE设备特有的:
L2cap协议通讯是建立在信道基础上的数据包,其数据包的类型具体有四种,下面我们将分别做出介绍。
首先我们介绍一下面向连接和无连接通讯的区别:面向连接的服务是按顺序,保证传输质量的,可恢复错误和流量控制的可靠的连接;无连接服务是不按顺序,不保证传输质量的,不可恢复错误不进行流量控制的不可靠连接。举一个简单的例子说明,打电话是面向连接通讯,短消息则是无连接通讯。
面向连接通讯工作在默认模式下,其的数据格式如下图:
Length为数据包的长度,Channel ID(CID)为上文中介绍的通道标示符。
Length为数据包长度,CID固定为0x0002,PSM指明上层协议的类型如RFCOMM、SDP、ATT等。
Length为数据包的长度,Channel ID为通道标示符,L2CAP SDU Length表示数据单元的长度,FCS(Frame Check Sequence)帧校验序列,Control字段根据不同的架构和功能分为三种格式:
1)、Standard Control Field Formats
该格式一般用于重传模式和流控模式,字段描述如下:
2)、Enhanced Control Field Formats
该格式一般用于加强重传模式和流模式,字段描述如下:
3)、Extended Control Field Formats
该格式一般用于加强重传模式和流模式,字段描述如下:
参数类型在上文中已经介绍过了。
命令信道是用于建立连接、配置协商、信道管理等作用的信道,固定ACL链路用CID=0x0001,LE链路用CID=0x0005。当下层连接已建立,且l2cap传输使能这两个信道就能被使用。其通讯机制是request和response的方式,协议包的框架根据上面的描述可以看出,为默认模式C-freme(control frame)框架,如下图所示:
其中荷载的字段通用描述为:
Identifer 标识数据包,用于匹配请求包和回复包,Lenght 数据长度,Data 数据荷载(可选),Code为标识命令的类型,具体描述如下:
下面对信道命令具体的举几个例子进行分析:
1)、Command Reject(在core_v5.0的 Vol 3,Part A ,4.1节)
拒绝指令用于回复指令错误其他原因导致的错误,其荷载具体的格式如下图所示:
其中code、identifier、length我们已在上文中介绍,reason是拒绝原因,描述如下:
Data字段根据reason的不同也会有锁区别,描述如下:
2)、Connection Request(在core_v5.0的 Vol 3,Part A ,4.2节)
此指令用于在两个设备间创建一个l2cap 的channel,其荷载具体的格式如下图所示:
PSM为Protocol/Service Multiplexer,指明上层协议的类型,source CID为请求方的CID。
3)、Connection Response(在core_v5.0的 Vol 3,Part A ,4.3节)
此指令用于对创建一个l2cap 的channel请求的回复,其荷载具体的格式如下图所示:
Result 字段代表请求的结果,其值的描述如下:
Status字段只有在result=0x0001是才有效,描述如下:
由于指令比较多,其他指令这里不在一一叙述,有兴趣可以去看蓝牙核心规范。
L2cap共有12中状态:
CLOSED:channel未连接
WAIT_CONNECT:发出一个连接请求,收到操作被挂起的回复
WAIT_CONNECT_RSP:发出一个连接请求,没有收到回复
CONFIG:配置项正在协商
OPEN:数据可以传输
WAIT_DISCONNECT:发出了一个断开连接请求,但没有收到回复
WAIT_CREATE:发出一个建立通道的请求,收到操作被挂起的回复
WAIT_CREATE_RSP:发出一个建立通道的请求,但没有收到回复
WAIT_MOVE:发出了移除当前通道的请求,收到操作被挂起的回复
WAIT_MOVE_RSP:发出了移除当前通道的请求,但没有收到回复
WAIT_MOVE_CONFIRM:已经对移除通道的请求做了回复,等待对端的确认
WAIT_CONFIRM_RSP:对移除通道回复的确认,等待确认回复
下面是状态机的转换图:
上面就是对l2cap的简单描述,当然核心规范中还有关于分割/重组、重传、流控模式的具体操作流程描述,大家有兴趣的可以去深入了解。下面对抓去的数据进行具体的分析。
分析的log使用手机进行抓取,log会在此文档的附件中。
其中蓝色的部分是hci的数据,上一篇已经说过了,有兴趣可以看我的hci协议分析,红色为具体的l2cap的数据,在这里我举四个例子,附件文档解析到sdp开始建立为止。
1)、Master:signaling,Information request
00000010 00000011 00100000 00001010 00000000 00000110 00000000 00000001 00000000 00001010 00000010 00000010 00000000 00000010 00000000
PDU length:00000110 00000000(0x0006=6,包长度为6,不包括CID)
CID:00000001 00000000(0x0001,signaling)
Code:00001010(0x0a,Information request )
Identifier:00000010(0x02)
Command Length;00000010 00000000(0x0002=2,数据长度为2)
data:00000010 00000000(0x0002,Extended features supported)
2)、Slave:signaling,Information response
00000010 00000011 00100000 00010000 00000000 00001100 00000000 00000001 00000000 00001011 00000010 00001000 00000000 00000010 00000000 00000000 00000000 10000000 00000000 00000000 00000000
PDU length:00001100 00000000(0x000c=12,包长度为12,不包括CID)
CID:00000001 00000000(0x0001,signaling)
Code:00001011(0x0b,Information response)
Identifier:00000010(0x02)
Command Length;00001000 00000000(0x0008=8,数据长度为8)
Info type:00000010 00000000(0x0002,Extended features supported)
Result:00000000 00000000(0x0000,success)
Extended feature mask:10000000 00000000 00000000 00000000(其描述在核心规范L2CAP章节的4.12 EXTENDED FEATURE MASK)
3)、Master:signaling,Information request
00000010 00000011 00100000 00001010 00000000 00000110 00000000 00000001 00000000 00001010 00000011 00000010 00000000 00000011 00000000
PDU length:00000110 00000000(0x0006=6,包长度为6,不包括CID)
CID:00000001 00000000(0x0001,signaling)
Code:00001010(0x0a,Information request )
Identifier:00000011(0x03)
Command Length;00000010 00000000(0x0002=2,数据长度为2)
data:00000011 00000000(0x0003,Fixed Channels supported)
4)、Slave:signaling,Information response
00000010 00000011 00100000 00010100 00000000 00010000 00000000 00000001 00000000 00001011 00000011 00001100 00000000 00000011 00000000 00000000 00000000 00000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000
PDU length:00010000 00000000(0x0010=16,包长度为16,不包括CID)
CID:00000001 00000000(0x0001,signaling)
Code:00001011(0x0b,Information response)
Identifier:00000011(0x03)
Command Length;00001100 00000000(0x000c=12,数据长度为12)
Info type:00000011 00000000(0x0003,Fixed Channels supported)
Result:00000000 00000000(0x0000,success)
Extended feature mask:00000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000(其描述在核心规范L2CAP章节的4.13 FIXED CHANNELS SUPPORTED)
具体的协议的log以及数据分析,以及相关资料,请到我的博客<蓝牙学习笔记(序)>最下面的网盘链接中下载!