L2CAP 协议:
L2CAP:全称Logical Link Control and Adaptation Protocol。
核心职责:多路复用(多个上层协议共享一条 ACL 链路)、分段与重组(SAR)、QoS / 流控。
-
ACL(Asynchronous Connectionless):异步、面向数据、支持重传,L2CAP 只跑在 ACL 上。
-
SCO / eSCO((Enhanced) Synchronous Connection-Oriented):同步、面向语音,占用固定时隙,不经过 L2CAP,通常直接承载 HFP 的语音(CVSD / mSBC)。
L2CAP 跑在 ACL 之上:L2CAP 的 CID 划分只跟 ACL 相关;SCO/eSCO 是另一条独立的语音通道。
L2CAP 基本帧格式:

-
Length(2 字节,小端):Information payload 的字节数。
-
CID(2 字节,小端):Channel ID,标识本包发给哪个逻辑信道。
-
L2CAP header 共 4 字节,CID 是对端接收方的 CID(每一方独立分配自己的 CID,是本地概念)。
Signaling 命令格式:

常见 Code:CONNECTION_REQ/RSP、CONFIGURATION_REQ/RSP、DISCONNECTION_REQ/RSP、ECHO_REQ、INFORMATION_REQ。建立一个新 L2CAP 信道就是通过这里的 Connection Request(带上 PSM)完成的。

CID 是怎么划分的:
CID 是 16 bit,BR/EDR(经典蓝牙)的划分如下:
| CID 范围 | 用途 |
|---|---|
0x0000 |
Null(保留,禁止使用) |
0x0001 |
Signaling channel(L2CAP 信令,如连接/配置命令) |
0x0002 |
Connectionless channel(无连接数据,广播式) |
0x0003 |
AMP Manager Protocol(早期 AMP 用,现基本废弃) |
0x0004 ~ 0x003F |
Reserved(保留,含 BLE 用的固定信道) |
0x0040 ~ 0xFFFF |
Dynamically allocated(动态分配给面向连接的信道) |
动态 CID 由每一方独立分配:A 建立连接时告诉 B「请把发给我的数据打到 CID=0x0041」,B 也会告诉 A 自己的 CID。所以同一条逻辑连接,两端看到的 CID 通常不一样 ------ 这就是 L2CAP header 里 CID 是「目的方 CID」的原因。
补充:BLE(LE)的固定 CID(对比记忆)
| CID | LE 用途 |
|---|---|
0x0004 |
ATT(属性协议) |
0x0005 |
LE Signaling channel(LE 专用信令) |
0x0006 |
SMP(安全管理协议) |
注意:LE 的信令是 0x0005,而经典蓝牙的信令是 0x0001,这是两套体系。
PSM:
PSM:Protocol/Service Multiplexer,标识不同上层协议(如RFCOMM、AVDTP)。
|--------------------|----------------------------------------------|----------------------|
| PSM 值(Hex) | 协议/服务 | 用途 |
| 0x0001 | SDP | 服务发现(本文档主角) |
| 0x0003 | RFCOMM | 串口仿真(HFP/SPP/OPP 走它) |
| 0x0005 | TCS-BIN | 电话控制 |
| 0x000F | BNEP | 蓝牙网络封装(PAN) |
| 0x0011 | HID_Control | HID 控制通道 |
| 0x0013 | HID_Interrupt | HID 中断通道(键鼠数据) |
| 0x0017 | AVCTP | AVRCP 的底层控制传输 |
| 0x0019 | AVDTP | A2DP 的底层媒体传输 |
| 0x001B | AVCTP_Browsing | AVRCP 浏览通道 |
| 0x001F | ATT (over BR / EDR ) | 经典蓝牙的通道上跑 ATT |
PSM vs CID:
-
PSM(Protocol/Service Multiplexer):标识「服务」,如 SDP=0x0001、RFCOMM=0x0003、AVDTP=0x0019、AVCTP=0x0017。类似 TCP 的「端口号」,建连时用来找服务。
-
CID:连接建立后分配的动态信道标识,之后数据都用 CID 寻址(PSM 只在建连阶段出现)。
类比:PSM 像目标端口,CID 像建好连接后的 socket。
L2CAP Connection:
Destination CID,Source CID的划分,是从发送request的一端的视角确定的。
L2cap Connection request里面的带着本端的cid,叫做source cid。
response里面带着的也是对端的cid,但是它知道它是一个response,所以它回复的目的地cid,叫做source id,本端的CID叫作Destination CID。
L2CAP Connection Request:
-
Command Code: Connection Request (0x02)
-
Command Identifier: 0x03
-
Command Length: 4
-
PSM : SDP (0x0001)
-
Source CID: Dynamically Allocated Channel (0x0108)
L2CAP Connection Response:
-
Command Code: Connection Response (0x03)
-
Command Identifier: 0x03
-
Command Length: 8
-
Destination CID: Dynamically Allocated Channel (0x0040)
-
Source CID: Dynamically Allocated Channel (0x0108)
-
Result: Successful (0x0000)
-
Status: No further information available (0x0000)
L2CAP Configuration:
Configuration Request 描述的是"我这边接收侧的能力",不是发送侧,因此需要双方都发一次request。
Command: Configure Request
-
Command Code: Configure Request (0x04)
-
Command Identifier: 0x04
-
Command Length: 8
-
Destination CID: Dynamically Allocated Channel (0x0108)
-
0000 0000 0000 000. = Reserved: 0x0000
-
.... .... .... ...0 = Continuation Flag: False
-
Option: MTU
-
Type: Maximum Transmission Unit (0x01)
-
Length: 2
-
MTU: 1024
Command: Configure Request
-
Command Code: Configure Request (0x04)
-
Command Identifier: 0x04
-
Command Length: 8
-
Destination CID: Dynamically Allocated Channel (0x0040)
-
0000 0000 0000 000. = Reserved: 0x0000
-
.... .... .... ...0 = Continuation Flag: False
-
Option: MTU
-
Type: Maximum Transmission Unit (0x01)
-
Length: 2
-
MTU: 256
Command: Configure Response
-
Command Code: Configure Response (0x05)
-
Command Identifier: 0x04
-
Command Length: 6
-
Source CID: Dynamically Allocated Channel (0x0108)
-
0000 0000 0000 000. = Reserved: 0x0000
-
.... .... .... ...0 = Continuation Flag: False
-
Result: Success (0x0000)
Command: Configure Response
-
Command Code: Configure Response (0x05)
-
Command Identifier: 0x04
-
Command Length: 10
-
Source CID: Dynamically Allocated Channel (0x0040)
-
0000 0000 0000 000. = Reserved: 0x0000
-
.... .... .... ...0 = Continuation Flag: False
-
Result: Success (0x0000)
-
Option: MTU
-
Type: Maximum Transmission Unit (0x01)
-
Length: 2
-
MTU: 1024
|------|--------------------------------------|------|----------------------------------------------------------------------------------------------------------------------------|
| Type | Option 名称 | 数据长度 | 作用说明 |
| 0x01 | MTU Maximum Transmission Unit | 2B | 本方接收 MTU;告诉对端:发给我的 SDU 不能超过该值;默认 672 字节;SPP/A2DP 必带 |
| 0x02 | Flush Timeout | 2B | 冲刷超时 (ms);ACL 链路超时丢包;0xFFFF = 无限,不 flush;音频流常用 |
| 0x03 | QoS Quality of Service | 11B | QoS 流规格:服务类型、令牌桶、峰值带宽;用于申请链路带宽保障 |
| 0x04 | Retransmission And Flow Control(RFC) | 8B | 模式开关:Basic / Retransmission / Enhanced Retransmission (ERTM) / Streaming;同时配置重传次数、RTO、Monitor 超时、窗口大小;ERTM 可靠通道必带这个 option |
| 0x05 | FCS Frame Check Sequence | 1B | 0 = 关闭 FCS,1 = 开启 16 位 CRC 校验;ERTM/Streaming 模式下使用 |
| 0x06 | Extended Flow Specification | 16B | AMP 高速链路扩展 QoS;普通 BR/EDR 几乎不用 |
| 0x07 | Extended Window Size | 2B | ERTM 模式,扩展滑动窗口最大到 65535;原来 RFC 里窗口只有 0‑63,不够时启用 |