深入理解经典蓝牙的L2CAP协议

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/RSPCONFIGURATION_REQ/RSPDISCONNECTION_REQ/RSPECHO_REQINFORMATION_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,不够时启用 |

相关推荐
夜月yeyue2 小时前
SOME/IP-SD 服务发现故障
网络·单片机·网络协议·tcp/ip·安全·服务发现
程序员z72 小时前
深入理解 GMP 模型:Go 协程调度器的设计与调度场景全解析
服务器·网络·golang
stolentime2 小时前
OpenClaw 网络数据采集新手入门指南
网络·ai·ai编程
小白说大模型3 小时前
Codex 实战:用 AI 写运维脚本
大数据·运维·网络·人工智能·机器学习·prompt
数字护盾(和中)3 小时前
和中科技剖析 EDR 绕过全链路,AMSI、ETW 规避技术与防御对策
运维·网络·人工智能·科技·安全·web安全
Demons_kirit3 小时前
PortSwigger网络缓存欺骗(1)
网络·缓存
初願致夕霞4 小时前
《为什么公网访问不了内网?正向代理、内网穿透与 NAT 打洞一次说清》
linux·网络·tcp/ip·智能路由器
喜欢吃燃面4 小时前
Linux网络编程深度解析:从Socket API到自定义协议设计
linux·网络·arm开发
xxy222414 小时前
Linux 网络编程入门(一):从 OSI 模型到 TCP Socket 编程
网络·tcp/ip·tcp