笨叔在最开始学习 l2cap 时,发现l2cap 里面的内容真的有点晦涩难懂,让人痛不欲生,抓耳挠腮,“如坐针毡 如芒刺背 如鲠在喉” 。
本期开始就一起跟着笨叔开始戏耍l2cap,一起战胜恐惧。
L2CAP (Logical Link Control and Adaptation Protocol) 是蓝牙协议栈中的关键层,位于基带层之上,为上层协议提供数据封装和服务。主要功能包括:
-
协议多路复用:允许多个高层协议共享底层链路
-
分段和重组:处理大于基带包大小的数据包
-
服务质量(QoS)管理:支持不同应用的质量需求
-
错误控制和流控制:基本版本提供简单错误检测
我们可以将 l2cap 比喻为 一家 快递分拣中心。
一、L2CAP协议的角色:蓝牙的"快递分拣中心"
想象你开了一家网购平台,L2CAP就像你仓库里的智能分拣系统:
-
多快递公司对接:能同时处理顺丰、京东、邮政(相当于RFCOMM、SDP等不同协议)
-
包裹拆分/合并:大件物品自动拆箱(数据分段),小件合并装箱(数据重组)
-
优先级处理:VIP客户的包裹优先发货(服务质量QoS)
二、核心功能解析
1. 协议多路复用 → 快递柜分格
-
每个快递公司有专属格口(CID信道ID)
-
例如:顺丰用1号格口(RFCOMM用CID 0x0040),京东用2号格口(SDP用CID 0x0001)
2. 分段重组 → 包裹标准化
// 发送大文件时(比如电影)
if(数据 > MTU){ // MTU=最大运输单元(卡车容量)
拆分成多个小包裹; // 分段
}
// 接收时重新拼装
3. 流控制 → 仓库库存管理
-
经典蓝牙:类似"确认收货"机制(每发一包等确认)
-
BLE蓝牙:信用卡模式(对方先给"信用额度",用完要等还款)
三、工作模式对比
模式 | 生活比喻 | 适用场景 |
---|---|---|
基本模式 | 现金交易(一手交钱一手交货) | SDP查询等简单操作 |
重传模式 | 货到付款(可拒收重发) | RFCOMM串口数据传输 |
流控制模式 | 月结账户(有信用额度) | BLE低功耗设备 |
四、CID(Channel ID)分配规则详解
1. CID 的作用
CID(Channel ID)是蓝牙 L2CAP 层的逻辑通道标识符,用于区分同一设备上的不同数据流(类似网络中的端口号)。它的核心特点是:
-
动态分配:每次连接可以分配不同的 CID。
-
本地唯一:仅对当前连接的设备有效。
2. CID 的命名空间(Name Space)
蓝牙规范根据链路类型(ACL-U、LE-U 等)定义了 CID 的取值范围:
(1) ACL-U 逻辑链路(经典蓝牙)
CID 范围 | 用途 |
---|---|
0x0000 | 空标识(禁止使用) |
0x0001 | L2CAP 信令信道(用于连接管理、配置等控制消息) |
0x0002 | 无连接信道(用于广播或组播数据) |
0x0003 | 历史遗留(已废弃) |
0x0007 | BR/EDR 安全管理器(用于传统蓝牙的安全协议) |
0x0040 - 0xFFFF | 动态分配(用于普通数据传输,如 RFCOMM、A2DP 等) |
其他值 | 保留未来使用 |
关键点:
-
0x0001
是固定的信令通道(类似 TCP/IP 的 80 端口)。 -
0x0040
以上可自由分配(类似动态端口号)。
(2) LE-U 逻辑链路(低功耗蓝牙 BLE)
CID 范围 | 用途 |
---|---|
0x0000 | 空标识(禁止使用) |
0x0002 | 无连接信道(用于 BLE 广播数据) |
其他值 | 保留未来使用 |
关键点:
- BLE 的 CID 分配更简单,主要依赖 ATT 协议的
Handle
来区分服务。
3. CID 的动态分配机制
-
分配方式:
-
通过 L2CAP 配置协议(Section 7.1)协商。
-
或通过基于信用的连接机制(Section 4.25)分配。
-
-
唯一性保证:
-
即使多个远端设备使用相同的 CID 值(如
0x0040
),本地设备也能通过逻辑链路区分它们。 -
例如:
- 手机同时连接耳机(CID=0x0040)和手环(CID=0x0040),但数据不会混淆,因为链路不同。
-
4. 实际应用示例
场景:手机同时连接蓝牙耳机和智能手表。
-
耳机连接:
-
分配
CID=0x0040
传输音频(A2DP)。 -
分配
CID=0x0041
传输控制信号(AVRCP)。
-
-
手表连接:
-
分配
CID=0x0040
传输心率数据(GATT)。 -
尽管 CID 值相同,但因链路独立,数据不会冲突。
-
5. 与 PSM 的关系
-
PSM 决定服务类型(如
0x0011
代表 A2DP),而 CID 是实际数据传输的通道。 -
连接流程:
-
设备通过 PSM 找到服务(如
PSM=0x0011
请求音频服务)。 -
协商分配 CID(如
CID=0x0040
)用于传输数据。
-
总结
-
CID 是逻辑通道的“门牌号”,动态分配且链路内唯一。
-
经典蓝牙(ACL-U):
- 固定 CID(如
0x0001
信令) + 动态 CID(0x0040-0xFFFF
)。
- 固定 CID(如
-
低功耗蓝牙(LE-U):
- 主要用
0x0002
和无连接信道,依赖 ATT 协议区分服务。
- 主要用
-
多设备共存:
即使 CID 值相同,不同链路的通道也不会冲突。
五、 SCID DCID PSM 的区别(快递物流系统类比版)
为了更直观地理解这三个概念的区别,我们可以用一个快递物流系统来比喻蓝牙通信:
概念 | 蓝牙术语 | 快递物流比喻 | 作用 | 特点 |
---|---|---|---|---|
PSM | Protocol/Service Multiplexer | 快递公司编号(如顺丰、京东) | 标识服务类型(比如文件传输、音频流) | - 全局统一编号 - 类似“快递公司营业执照” - 例如: - 0x0001 (SDP服务) - 0x0003 (RFCOMM) - 0x0011 (A2DP音频) |
SCID | Source Channel ID | 寄件人专用快递柜编号 | 标识发送方的数据通道 | - 由本地设备分配 - 每次连接可能不同 - 类似“你的专属寄件柜号” |
DCID | Destination Channel ID | 收件人专用快递柜编号 | 标识接收方的数据通道 | - 由对端设备分配 - 每次连接可能不同 - 类似“对方的专属收件柜号” |
详细解释
1. PSM(Protocol/Service Multiplexer)
-
作用:决定使用哪种服务(类似选择快递公司)。
-
特点:
-
全局标准化(比如
0x0001
代表 SDP 服务发现,0x0003
代表 RFCOMM 串口通信)。 -
在建立连接时使用,类似于“你要寄顺丰还是京东?”。
-
-
示例:
-
手机连接耳机时,用
PSM=0x0011
(A2DP 音频服务)。 -
设备发现服务用
PSM=0x0001
(SDP)。
-
2. SCID(Source Channel ID)
-
作用:标识发送方的数据通道(类似“你的快递柜编号”)。
-
特点:
-
由本地设备动态分配(比如手机分配
SCID=0x0040
给音频流)。 -
仅对当前连接有效(断开后可能重新分配)。
-
-
示例:
- 手机发送音频数据时,使用
SCID=0x0040
标识自己的发送通道。
- 手机发送音频数据时,使用
3. DCID(Destination Channel ID)
-
作用:标识接收方的数据通道(类似“对方的快递柜编号”)。
-
特点:
-
由对端设备分配(比如耳机告诉手机:“用
DCID=0x0080
给我发数据”)。 -
仅对当前连接有效。
-
-
示例:
- 手机发送数据时,不仅要指定自己的
SCID
,还要指定对方的DCID
,确保数据送到正确位置。
- 手机发送数据时,不仅要指定自己的
三者的关系(通信流程示例)
场景:手机(A)通过蓝牙发送音频数据给耳机(B)。
-
建立连接:
-
手机发送连接请求:
PSM=0x0011
(A2DP 音频服务)。 -
耳机同意连接,并分配
DCID=0x0080
(告诉手机:“发到这个柜子”)。 -
手机分配
SCID=0x0040
(表示“我用这个柜子发数据”)。
-
-
数据传输:
-
手机发送数据包:
[SCID=0x0040, DCID=0x0080, 音频数据]
。 -
耳机收到后,知道数据来自
SCID=0x0040
,并送到DCID=0x0080
对应的处理模块。
-
-
断开连接:
- 连接关闭后,
SCID
和DCID
失效,下次连接可能分配新的 ID。
- 连接关闭后,
总结
概念 | 作用 | 分配方 | 生命周期 | 类比 |
---|---|---|---|---|
PSM | 决定使用哪种服务 | 蓝牙标准定义 | 长期有效 | 快递公司编号(顺丰、京东) |
SCID | 标识发送方的数据通道 | 本地设备分配 | 仅当前连接有效 | 寄件人专属快递柜 |
DCID | 标识接收方的数据通道 | 对端设备分配 | 仅当前连接有效 | 收件人专属快递柜 |
简单记忆:
-
PSM = 选择服务(选快递公司)。
-
SCID = 你的发货柜号(本地动态分配)。
-
DCID = 对方的收货柜号(对端动态分配)。
这样设计的好处是:
-
灵活性:每次连接可以动态分配通道,避免冲突。
-
多路复用:一台设备可以同时进行多个通信(比如同时传音频和文件)。
-
标准化:PSM 确保不同厂商设备能正确识别服务类型。
六、上层协作案例
案例1:蓝牙耳机听歌
-
手机与耳机"签订合同"(建立L2CAP连接)
-
音乐数据被拆成多个"快递包裹"(分段)
-
耳机实时签收并反馈(流控制)
案例2:查询设备服务(SDP)
-
直接使用"公共快递柜"(固定CID 0x0001)
-
快速存取小件物品(无需建立连接)
-
即用即走(无连接开销)
七、数据格式 讲解
(1)SDU(service data unit),从上层协议或应用传来的数据
(2)PDU(protol data unit),l2cap封装后的数据,PDU的类型有B-frame、I-frame、S-frame、C-frame、G-frame、K-frame
(3)MTU(maximum Transmission Unit), SDU的最大长度(可以支持最大 64KB 的上层应用数据)
(4)MPS(Maximum PDU payload Size),PDU负载的最大长度
(5)CID(channl identifier),l2cap通道id
(6)MaxTransmit,重传模式和增强重传模式中的最大重传次数
SDU 和 PDU 的区别
1. SDU(Service Data Unit,服务数据单元)
-
定义:上层协议交给 L2CAP 的原始数据(比如 RFCOMM 想发送的串口数据、A2DP 的音频数据)。
-
特点:
-
未经加工,就像你要寄的“原始商品”(比如一本书、一件衣服)。
-
不包含 L2CAP 的协议头信息。
-
-
示例:
-
蓝牙键盘发送的按键数据(如
按键A
)。 -
蓝牙耳机接收的音频数据(如
PCM 音频流
)。
-
2. PDU(Protocol Data Unit,协议数据单元)
-
定义:L2CAP 实际发送的数据包(SDU + L2CAP 协议头)。
-
特点:
-
经过封装,就像快递包裹(商品 + 快递单 + 包装盒)。
-
包含 L2CAP 需要的控制信息(如 CID、长度等)。
-
-
示例:
- 键盘数据
按键A
→ 封装成 L2CAP PDU:
- 键盘数据
[L2CAP头 | CID=0x0040 | 长度=1 | 数据=按键A]
关键区别
- | SDU(原始数据) | PDU(传输数据包) |
---|---|---|
内容 | 纯应用数据(如按键、音频) | SDU + L2CAP协议头 |
作用 | 上层协议交给 L2CAP 的数据 | L2CAP 实际发送的数据包 |
类比 | 你要寄的商品(如一本书) | 打包后的快递(书+快递单+盒子) |
数据流动示例(蓝牙键盘发送按键)
-
应用层:键盘检测到
按键A
→ 生成 SDU(0x41
)。 -
L2CAP 层:
-
添加 L2CAP 头(CID=键盘通道,长度=1)→ 生成 PDU:
[CID=0x0040][长度=1][数据=0x41]
-
发送 PDU 给对端设备。
-
-
接收方:
- 拆解 PDU → 提取 SDU(
0x41
)→ 交给上层协议处理。
- 拆解 PDU → 提取 SDU(
为什么需要区分 SDU 和 PDU?
-
分层设计:
-
上层(如 RFCOMM)只关心数据内容(SDU)。
-
L2CAP 负责传输管理(封装成 PDU)。
-
-
灵活性:
- 同一 SDU 可用不同 PDU 格式(如基本模式 vs. 重传模式)。
-
复用能力:
- 多个 SDU 可合并成一个 PDU(如 BLE 分帧)。
总结
-
SDU = 原始数据(你要寄的商品)。
-
PDU = 传输数据包(商品+快递单+包装)。
-
L2CAP 的作用:把 SDU 包装成 PDU,确保数据正确传输。
L2CAP帧(PDU)类型
我们可以把这些帧类型想象成不同功能的"快递包裹":
1. B-frame(基本帧) → 普通快递包裹
-
特点:最简单的包装形式,一包就是一个完整商品
-
场景:就像淘宝普通快递,一箱子装一个完整商品(完整SDU)
-
结构:
[快递单(L2CAP头)] + [完整商品(SDU)]
2. I-frame(信息帧) → 分箱发货的大件
-
特点:大件物品拆分成多个箱子,每个箱子有装箱编号
-
场景:像买家具时的分箱发货(分段SDU),箱子上贴有"1/4、2/4"等标签
-
特殊能力:支持重传(丢箱可补发)、流控制(根据仓库容量发货)
I-frame
3. S-frame(监控帧) → 物流确认单
-
特点:没有实物,只有物流信息
-
常见类型:
-
ACK签收单(确认收到货)
-
NACK拒收单(要求重发)
-
仓库容量通知(流控信用值更新)
-
4. C-frame(控制帧) → 客服沟通信
-
专用通道:只用"客服热线"(CID 0x0001信令信道)
-
处理事项:
-
建立/终止物流合同(连接请求/响应)
-
修改运输条款(配置协商)
-
投诉处理(错误通知)
-
5. G-frame(组播帧) → 小区广播
-
特点:一个包裹,多个收件人
-
两种派送方式:
-
广播模式:小区喇叭喊话(主动广播)
-
组播模式:快递柜自取(无连接通信)
-
-
特殊标记:包裹上注明"物业通知"(PSM字段)
6. K-frame(信用帧) → 高级会员服务
-
创新点:先充值后消费(基于信用值的流控)
-
工作流程:
-
收件人先告知:“我有10个空货架”(发信用值)
-
发货方最多发10箱货
-
每签收1箱,空出1个货架(返还信用)
-
-
优势:避免仓库爆仓(缓冲区溢出)
各帧类型对比表
帧类型 | 类比 | 是否含数据 | 特有功能 | 典型应用场景 |
---|---|---|---|---|
B-frame | 普通快递 | ✔️ | - | 基本模式通信 |
I-frame | 分箱发货 | ✔️ | 分段/重传/流控 | 文件传输 |
S-frame | 物流通知单 | ✖️ | ACK/NACK/流控 | 可靠传输 |
C-frame | 客服工单 | ✖️ | 信令交换 | 连接建立/配置 |
G-frame | 小区广播 | ✔️ | 组播/广播 | 服务发现 |
K-frame | 信用制发货 | ✔️ | LE Credit流控 | BLE低功耗设备 |
为什么需要这么多帧类型?
就像物流系统需要:
-
普通包裹(B-frame)处理日常小件
-
分箱大件(I-frame)处理大文件
-
物流通知(S-frame)确保妥投
-
VIP服务(K-frame)优化资源利用
这种设计使L2CAP能灵活应对从键盘输入(小数据)到音频传输(大数据流)等各种需求。
八、为什么需要L2CAP?
-
统一接口:不同蓝牙设备就像不同快递公司,L2CAP提供统一对接窗口
-
效率提升:大文件自动拆分(避免卡车空载)
-
错峰处理:优先传输音频数据(VIP客户插队)
九、开发者注意事项
-
MTU设置:就像选择卡车尺寸,太大会导致某些小路(设备)无法通行
-
信道选择:
-
固定信道(如SDP)→ 公共储物柜
-
动态信道(如RFCOMM)→ 临时租用仓库
-
-
模式选择:
-
音频传输用流控制(保证实时性)
-
文件传输用重传模式(保证可靠性)
-
总结
通过这个比喻,可以理解L2CAP就像蓝牙世界的物流中枢,默默协调着各种数据的收发工作。