【Bluedroid】蓝牙启动之 l2c_init 源码解析
蓝牙 L2CAP(逻辑链路控制和适配协议)层是蓝牙协议栈的核心传输层,负责为上层协议(如 ATT、SMP、GATT)提供逻辑通道、服务路由和流量控制等关键功能。本文围绕 L2CAP 层的五大核心数据结构(全局控制块tL2C_CB
、链路控制块tL2C_LCB
、通道控制块tL2C_CCB
、注册控制块tL2C_RCB
及固定通道注册信息tL2CAP_FIXED_CHNL_REG
)展开解析,结合初始化函数l2c_init
的实现,阐述 L2CAP 层如何通过预分配资源池、状态隔离、协议适配和流量控制等机制,支撑蓝牙设备间的可靠数据传输与服务交互。
一、概述
1.1 L2CAP 层的核心架构与数据结构
L2CAP 层的核心功能(如通道管理、服务路由、流量控制)依赖一组高度模块化的数据结构实现,这些结构通过状态隔离、资源预分配和协同工作,确保 L2CAP 层的高效与可靠。以下是核心结构的功能定位与设计逻辑:
1. 全局控制块 tL2C_CB
:L2CAP 的 “大脑”
tL2C_CB
是 L2CAP 层的全局控制块,存储协议栈运行所需的全局状态与配置参数,主要包含:
-
资源池管理:预分配链路控制块(
tL2C_LCB
)、通道控制块(tL2C_CCB
)和注册控制块(tL2C_RCB
)的池化资源,避免动态内存分配的开销; -
流量控制参数:管理经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)的轮询配额(
round_robin_quota
)、未确认包数(round_robin_unacked
),支撑链路级流量调度; -
协议适配配置:包括动态 PSM 分配表(
le_dyn_psm_assigned
)、固定通道掩码(l2c_ble_fixed_chnls_mask
)、控制器能力参数(如num_lm_acl_bufs
),适配不同传输类型(BR/EDR、BLE)的差异化需求; -
兼容性扩展:支持测试模式(
L2CAP_CONFORMANCE_TESTING
)和拥塞回调上下文标记(is_cong_cback_context
),提升调试与异常处理能力。
2. 链路控制块 tL2C_LCB
:单链路的 “微型操作系统”
每条蓝牙链路(由对端设备地址唯一标识)对应一个tL2C_LCB
,负责管理链路的全生命周期状态(连接、空闲、断开),核心功能包括:
-
状态隔离:存储链路角色(
link_role_
)、连接参数(min_interval
/max_interval
)、传输配额(link_xmit_quota
)等独立状态,避免多链路干扰; -
通道管理:通过双向链表(
ccb_queue
)管理该链路下所有活跃通道(tL2C_CCB
),支持通道的快速遍历与操作; -
流量与可靠性:跟踪未确认包数(
sent_not_acked
)、拥塞状态(cong_sent
),结合轮询调度(rr_serv
)和优先级(acl_priority
)优化传输效率; -
协议适配:支持 BLE 的连接参数更新(
conn_update_mask
)、安全检查队列(le_sec_pending_q
)和子速率调整(subrate_req_mask
),满足低功耗场景需求。
3. 通道控制块 tL2C_CCB
:单通道的 “微型控制器”
每个 L2CAP 通道(由本地 / 远程 CID 唯一标识)对应一个tL2C_CCB
,负责通道的状态管理与数据传输,核心设计目标包括:
-
状态与配置:记录通道状态(
chnl_state
)、配置完成标志(config_done
)、MTU 协商结果(max_rx_mtu
),支撑通道的建立、配置与断开流程; -
数据传输与可靠性:通过分段重组(
is_first_seg
/ble_sdu
)、拥塞管理(xmit_hold_q
/buff_quota
)和重传机制(ertm_info
),确保数据可靠传输; -
性能优化:支持通道优先级(
ccb_priority
)、数据速率(tx_data_rate
)和可刷新标记(is_flushable
),适配实时与非实时业务需求; -
协议扩展:兼容 eL2CAP(
ecoc
)和 LE CoC(remote_credit_count
),支撑增强型连接导向通道的动态配置。
4. 注册控制块 tL2C_RCB
:服务路由的 “桥梁”
上层应用(如 GATT 服务器、自定义服务)通过tL2C_RCB
向 L2CAP 注册服务(由 PSM 标识),核心作用包括:
-
服务标识与隔离:存储服务 PSM(
psm
)、实际 PSM(real_psm
)和是否活跃(in_use
),确保不同服务的独立管理; -
参数协商:保存本地 / 对端 MTU(
my_mtu
/required_remote_mtu
)、ERTM 配置(ertm_info
)和 CoC 配置(coc_cfg
),支撑 L2CAP 与对端的连接协商; -
应用交互:通过
api
成员绑定应用回调(如数据接收、连接状态通知),实现 L2CAP 层与上层应用的解耦通信。
5. 固定通道注册信息 tL2CAP_FIXED_CHNL_REG
:标准化协议的 “接口契约”
固定通道(如 ATT、SMP)通过tL2CAP_FIXED_CHNL_REG
注册回调与配置,核心功能包括:
-
事件通知:绑定连接 / 断开回调(
pL2CA_FixedConn_Cb
)、数据接收回调(pL2CA_FixedData_Cb
)和拥塞状态回调(pL2CA_FixedCong_Cb
),上层应用通过回调感知通道状态并处理数据; -
参数配置:设置默认空闲超时(
default_idle_tout
)和发送完成回调(pL2CA_FixedTxComplete_Cb
),优化固定通道的功耗与可靠性。
1.2 初始化函数 l2c_init
:L2CAP 层的启动基础
l2c_init
是 L2CAP 层的初始化入口,主要完成:
-
资源池初始化:通过链表管理空闲
CCB
(p_free_ccb_first
/p_free_ccb_last
),预分配LCB
/RCB
池,确保资源高效复用; -
全局参数配置:初始化动态 PSM 起始值(
le_dyn_psm
)、固定通道掩码(l2c_ble_fixed_chnls_mask
)和空闲超时(idle_timeout
),支撑服务发现与链路管理; -
兼容性初始化:配置测试模式参数(
test_info_resp
)和非可刷新包标志(non_flushable_pbf
),适配控制器能力与调试需求。
二、源码分析
l2c_init
packages/modules/Bluetooth/system/stack/l2cap/l2c_main.cc
/********************************************************************************* Function l2c_init** Description This function is called once at startup to initialize* all the L2CAP structures** Returns void*******************************************************************************/
/******************************************************************************/
/* G L O B A L L 2 C A P D A T A */
/******************************************************************************/
tL2C_CB l2cb;void l2c_init(void) {int16_t xx;// 1. 清空全局控制块memset(&l2cb, 0, sizeof(tL2C_CB));// 2. 初始化动态 LE PSM(协议服务多路复用器)/* the LE PSM is increased by 1 before being used */l2cb.le_dyn_psm = LE_DYNAMIC_PSM_START - 1;// 3. 初始化通道控制块(CCB)空闲队列/* Put all the channel control blocks on the free queue */for (xx = 0; xx < MAX_L2CAP_CHANNELS - 1; xx++) {l2cb.ccb_pool[xx].p_next_ccb = &l2cb.ccb_pool[xx + 1];}// 4. 初始化非可刷新包标志(Non-Flushable Packet Flag)/* it will be set to L2CAP_PKT_START_NON_FLUSHABLE if controller supports */l2cb.non_flushable_pbf = L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT;l2cb.p_free_ccb_first = &l2cb.ccb_pool[0];l2cb.p_free_ccb_last = &l2cb.ccb_pool[MAX_L2CAP_CHANNELS - 1];// 5. 设置空闲超时时间
/* Set the default idle timeout */l2cb.idle_timeout = L2CAP_LINK_INACTIVITY_TOUT;// 6. 一致性测试模式配置(可选)
#if (L2CAP_CONFORMANCE_TESTING == TRUE)/* Conformance testing needs a dynamic response */l2cb.test_info_resp = L2CAP_EXTFEA_SUPPORTED_MASK;
#endif/* Number of ACL buffers to use for high priority channel */// 7. 固定通道掩码初始化(BLE 专用)l2cb.l2c_ble_fixed_chnls_mask = L2CAP_FIXED_CHNL_ATT_BIT |L2CAP_FIXED_CHNL_BLE_SIG_BIT |L2CAP_FIXED_CHNL_SMP_BIT;
}
l2cb
是 L2CAP 层的核心控制块(Control Block),存储了 L2CAP 运行所需的所有状态信息和配置参数。初始化它是 L2CAP 层启动的基础。包括:
-
预分配通道控制块(CCB)并通过链表管理,提升内存效率;
-
初始化动态 PSM 和固定通道掩码,支撑服务发现和数据路由;
-
设置超时参数和包类型标志,保障链路可靠性和功耗优化;
-
兼容测试模式,满足协议一致性验证需求。
tL2C_CB l2cb
packages/modules/Bluetooth/system/stack/l2cap/l2c_int.htypedef uint8_t tL2C_BLE_FIXED_CHNLS_MASK;/* Define the L2CAP control structure
*/
typedef struct {// 控制器允许的最大未确认数据包数(传输窗口),用于流量控制uint16_t controller_xmit_window; /* Total ACL window for all links */// 轮询调度的配额(每个链路在轮询周期内允许发送的最大数据包数)uint16_t round_robin_quota; /* Round-robin link quota */// 当前轮询周期内未确认的数据包数uint16_t round_robin_unacked; /* Round-robin unacked */// 判断当前轮询配额是否可用bool is_classic_round_robin_quota_available() const {return round_robin_unacked < round_robin_quota;}// 更新未确认包数(收到确认后减少计数)void update_outstanding_classic_packets(uint16_t num_packets_acked) {if (round_robin_unacked > num_packets_acked)round_robin_unacked -= num_packets_acked;elseround_robin_unacked = 0;}// 标记是否需要触发轮询检查(如链路状态变化时)bool check_round_robin; /* Do a round robin check */// 标记当前是否处于 “拥塞回调” 上下文。用于防止拥塞处理函数递归调用(如回调中再次触发拥塞)bool is_cong_cback_context;tL2C_LCB lcb_pool[MAX_L2CAP_LINKS]; /* Link Control Block pool */tL2C_CCB ccb_pool[MAX_L2CAP_CHANNELS]; /* Channel Control Block pool */tL2C_RCB rcb_pool[MAX_L2CAP_CLIENTS]; /* Registration info pool */tL2C_CCB* p_free_ccb_first; /* Pointer to first free CCB */tL2C_CCB* p_free_ccb_last; /* Pointer to last free CCB */// 标记是否禁止在连接创建时切换链路类型(如从 BR/EDR 切换到 BLE)bool disallow_switch; /* false, to allow switch at create conn */// 控制器上经典蓝牙 ACL 缓冲区的数量(影响最大并发传输的数据包数)uint16_t num_lm_acl_bufs; /* # of ACL buffers on controller */// 链路空闲超时时间(单位:时钟周期或毫秒)。若链路在此时间内无数据传输,可能触发断开或节能模式uint16_t idle_timeout; /* Idle timeout */// 指向当前处理 HCI传输的链路控制块(用于数据包的发送 / 接收)tL2C_LCB* p_cur_hcit_lcb; /* Current HCI Transport buffer */// 当前活跃的链路控制块数量(即已建立的 L2CAP 链路数)uint16_t num_used_lcbs; /* Number of active link control blocks */uint16_t non_flushable_pbf; /* L2CAP_PKT_START_NON_FLUSHABLE if controllersupports *//* Otherwise, L2CAP_PKT_START */#if (L2CAP_CONFORMANCE_TESTING == TRUE)uint32_t test_info_resp; /* Conformance testing needs a dynamic response */
#endiftL2CAP_FIXED_CHNL_REGfixed_reg[L2CAP_NUM_FIXED_CHNLS]; /* Reg info for fixed channels */// 当前活跃的 BLE 链路数量(用于资源监控)uint16_t num_ble_links_active; /* Number of LE links active */// BLE 控制器的传输窗口(与 controller_xmit_window 类似,但针对 BLE 链路)uint16_t controller_le_xmit_window; /* Total ACL window for all links */// BLE 固定通道的掩码(位掩码),标记哪些通道是预定义的固定通道(如 ATT、SMP)。在 l2c_init 中初始化为 `L2CAP_FIXED_CHNL_ATT_BITtL2C_BLE_FIXED_CHNLS_MASK l2c_ble_fixed_chnls_mask; // LE fixed channels mask// 控制器上 BLE ACL 缓冲区的数量(与 num_lm_acl_bufs 类似,但针对 BLE)uint16_t num_lm_ble_bufs; /* # of ACL buffers on controller */// BLE 轮询调度的配额uint16_t ble_round_robin_quota; /* Round-robin link quota */// BLE 当前轮询周期内的未确认数据包数uint16_t ble_round_robin_unacked; /* Round-robin unacked */// 判断 BLE 轮询配额是否可用bool is_ble_round_robin_quota_available() const {return ble_round_robin_unacked < ble_round_robin_quota;}// 更新 BLE 未确认包数void update_outstanding_le_packets(uint16_t num_packets_acked) {if (ble_round_robin_unacked > num_packets_acked)ble_round_robin_unacked -= num_packets_acked;elseble_round_robin_unacked = 0;}// 标记是否需要触发 BLE 轮询检查bool ble_check_round_robin; /* Do a round robin check */tL2C_RCB ble_rcb_pool[BLE_MAX_L2CAP_CLIENTS]; /* Registration info pool */// 下一个待分配的动态 PSMuint16_t le_dyn_psm; /* Next LE dynamic PSM value to try to assign */// 动态 PSM 分配表(标记哪些 PSM 已被占用),确保每个动态 PSM 唯一bool le_dyn_psm_assigned[LE_DYNAMIC_PSM_RANGE]; /* Table of assigned LE PSM */} tL2C_CB;
tL2C_CB
的设计围绕蓝牙 L2CAP 层的核心功能展开,主要包含以下模块:
-
资源池管理:预分配链路、通道、客户端的控制块(LCB/CCB/RCB),避免动态内存分配的开销;
-
流量控制:管理经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)的轮询配额(Round-Robin Quota)和未确认包数;
-
状态标记:记录链路状态(如是否允许切换、是否处于拥塞回调上下文);
-
协议适配:支持经典蓝牙和 BLE 的差异化配置(如固定通道掩码、动态 PSM 分配);
-
兼容性扩展:包含测试模式(
L2CAP_CONFORMANCE_TESTING
)和控制器能力相关参数。
蓝牙 ACL 链路的数据包分为 “可刷新”(Flushable)和 “非可刷新”(Non-Flushable):
可刷新包:若控制器缓存满,可丢弃(如普通数据);
非可刷新包:必须传输(如语音、视频等实时数据)。
non_flushable_pbf
用于标记 L2CAP 层发送的数据包类型,确保控制器正确处理。
tL2C_LCB
packages/modules/Bluetooth/system/stack/l2cap/l2c_int.h
/* Define a link control block. There is one link control block between* this device and any other device (i.e. BD ADDR).
*/
typedef struct t_l2c_linkcb {bool in_use; /* true when in use, false when not */tL2C_LINK_STATE link_state;// 链路级定时器,用于触发空闲超时(idle_timeout)。若链路在 idle_timeout 时间内无数据传输,可能触发断开或进入低功耗模式alarm_t* l2c_lcb_timer; /* Timer entry for timeout evt */// This tracks if the link has ever either (a)// been used for a dynamic channel (EATT or L2CAP CoC), or (b) has been a// GATT client. If false, the local device is just a GATT server, so for// backwards compatibility we never do a link timeout.bool with_active_local_clients{false};private:uint16_t handle_; /* The handle used with LM */friend void l2cu_set_lcb_handle(struct t_l2c_linkcb& p_lcb, uint16_t handle);void SetHandle(uint16_t handle) { handle_ = handle; }public:uint16_t Handle() const { return handle_; }void InvalidateHandle() { handle_ = HCI_INVALID_HANDLE; }// 通道控制块(CCB)队列,存储该链路下所有活跃通道的 CCBtL2C_CCB_Q ccb_queue; /* Queue of CCBs on this LCB */// 链路断开时待处理的通道 CCB(如未完成的通道释放流程)tL2C_CCB* p_pending_ccb; /* ccb of waiting channel during link disconnect */alarm_t* info_resp_timer; /* Timer entry for info resp timeout evt */RawAddress remote_bd_addr; /* The BD address of the remote */private:tHCI_ROLE link_role_{HCI_ROLE_CENTRAL}; /* Central or peripheral */public:tHCI_ROLE LinkRole() const { return link_role_; }bool IsLinkRoleCentral() const { return link_role_ == HCI_ROLE_CENTRAL; }bool IsLinkRolePeripheral() const {return link_role_ == HCI_ROLE_PERIPHERAL;}void SetLinkRoleAsCentral() { link_role_ = HCI_ROLE_CENTRAL; }void SetLinkRoleAsPeripheral() { link_role_ = HCI_ROLE_PERIPHERAL; }// 信令通道 ID(固定为 0x01),用于标识 L2CAP 信令通道uint8_t signal_id; /* Signalling channel id */// 当前 Echo Request 信令的 ID(用于匹配响应)。Echo 信令用于测试链路连通性uint8_t cur_echo_id; /* Current id value for echo request */uint16_t idle_timeout; /* Idle timeout */private:bool is_bonding_{false}; /* True - link active only for bonding */public:bool IsBonding() const { return is_bonding_; }void SetBonding() { is_bonding_ = true; }void ResetBonding() { is_bonding_ = false; }// 链路允许的最大未确认数据包数(传输配额)。若 link_xmit_quota == 0,表示采用轮询调度(Round-Robin)uint16_t link_xmit_quota; /* Num outstanding pkts allowed */bool is_round_robin_scheduling() const { return link_xmit_quota == 0; }uint16_t sent_not_acked; /* Num packets sent but not acked */void update_outstanding_packets(uint16_t packets_acked) {if (sent_not_acked > packets_acked)sent_not_acked -= packets_acked;elsesent_not_acked = 0;}bool w4_info_rsp; /* true when info request is active */// 对端支持的扩展功能掩码(如流控、大数据包),通过信令协商获取uint32_t peer_ext_fea; /* Peer's extended features mask */list_t* link_xmit_data_q; /* Link transmit data buffer queue */uint8_t peer_chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];tL2CAP_PRIORITY acl_priority;bool is_normal_priority() const {return acl_priority == L2CAP_PRIORITY_NORMAL;}bool is_high_priority() const { return acl_priority == L2CAP_PRIORITY_HIGH; }bool set_priority(tL2CAP_PRIORITY priority) {if (acl_priority != priority) {acl_priority = priority;return true;}return false;}bool use_latency_mode = false;tL2CAP_LATENCY preset_acl_latency = L2CAP_LATENCY_NORMAL;tL2CAP_LATENCY acl_latency = L2CAP_LATENCY_NORMAL;bool is_normal_latency() const { return acl_latency == L2CAP_LATENCY_NORMAL; }bool is_low_latency() const { return acl_latency == L2CAP_LATENCY_LOW; }bool set_latency(tL2CAP_LATENCY latency) {if (acl_latency != latency) {acl_latency = latency;return true;}return false;}tL2C_CCB* p_fixed_ccbs[L2CAP_NUM_FIXED_CHNLS];private:tHCI_REASON disc_reason_{HCI_ERR_UNDEFINED};public:tHCI_REASON DisconnectReason() const { return disc_reason_; }void SetDisconnectReason(tHCI_REASON disc_reason) {disc_reason_ = disc_reason;}tBT_TRANSPORT transport;bool is_transport_br_edr() const { return transport == BT_TRANSPORT_BR_EDR; }bool is_transport_ble() const { return transport == BT_TRANSPORT_LE; }uint16_t tx_data_len; /* tx data length used in data length extension */fixed_queue_t* le_sec_pending_q; /* LE coc channels waiting for security checkcompletion */uint8_t sec_act;// 连接参数更新的掩码(标记哪些参数可更新)uint8_t conn_update_mask;// 标记是否因服务发现(如 GATT 发现)阻塞连接参数更新(避免影响发现过程)bool conn_update_blocked_by_service_discovery;// 标记是否因配置文件连接(如音频流)阻塞参数更新bool conn_update_blocked_by_profile_connection;uint16_t min_interval; /* parameters as requested by peripheral */uint16_t max_interval;uint16_t latency;uint16_t timeout;uint16_t min_ce_len;uint16_t max_ce_len;#define L2C_BLE_SUBRATE_REQ_DISABLE 0x1 // disable subrate req
#define L2C_BLE_NEW_SUBRATE_PARAM 0x2 // new subrate req parameter to be set
#define L2C_BLE_SUBRATE_REQ_PENDING 0x4 // waiting for subrate to be completed/* subrate req params */uint16_t subrate_min;uint16_t subrate_max;uint16_t max_latency;uint16_t cont_num;uint16_t supervision_tout;// 子速率用于调整连接间隔以进一步降低功耗uint8_t subrate_req_mask;/* each priority group is limited burst transmission *//* round robin service for the same priority channels */tL2C_RR_SERV rr_serv[L2CAP_NUM_CHNL_PRIORITY];uint8_t rr_pri; /* current serving priority group *//* Pending ECOC reconfiguration data */tL2CAP_LE_CFG_INFO pending_ecoc_reconfig_cfg;uint8_t pending_ecoc_reconfig_cnt;/* This is to keep list of local cids use in the* credit based connection response.*/uint16_t pending_ecoc_connection_cids[L2CAP_CREDIT_BASED_MAX_CIDS];uint8_t pending_ecoc_conn_cnt;uint16_t pending_lead_cid;uint16_t pending_l2cap_result;unsigned number_of_active_dynamic_channels() const {unsigned cnt = 0;const tL2C_CCB* cur = ccb_queue.p_first_ccb;while (cur != nullptr) {cnt++;cur = cur->p_next_ccb;}return cnt;}
} tL2C_LCB;
tL2C_LCB
是 L2CAP 层管理单条链路的 “微型操作系统”,其设计目标是:
-
状态隔离:每条链路的状态(如角色、超时、流量)独立存储,避免不同链路间的干扰;
-
协议适配:支持经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)的差异化需求(如连接参数、安全检查);
-
实时性:通过预定义成员和高效操作(如队列管理、位掩码),满足蓝牙对低延迟的要求。
tL2C_CCB
packages/modules/Bluetooth/system/stack/l2cap/l2c_int.h
/* Define a channel control block (CCB). There may be many channel control* blocks between the same two Bluetooth devices (i.e. on the same link).* Each CCB has unique local and remote CIDs. All channel control blocks on* the same physical link and are chained together.
*/
typedef struct t_l2c_ccb {bool in_use; /* true when in use, false when not */tL2C_CHNL_STATE chnl_state; /* Channel state */tL2CAP_LE_CFG_INFOlocal_conn_cfg; /* Our config for ble conn oriented channel */tL2CAP_LE_CFG_INFOpeer_conn_cfg; /* Peer device config ble conn oriented channel */bool is_first_seg; /* Dtermine whether the received packet is the firstsegment or not */BT_HDR* ble_sdu; /* Buffer for storing unassembled sdu*/uint16_t ble_sdu_length; /* Length of unassembled sdu length*/struct t_l2c_ccb* p_next_ccb; /* Next CCB in the chain */struct t_l2c_ccb* p_prev_ccb; /* Previous CCB in the chain */struct t_l2c_linkcb* p_lcb; /* Link this CCB is assigned to */uint16_t local_cid; /* Local CID */uint16_t remote_cid; /* Remote CID */alarm_t* l2c_ccb_timer; /* CCB Timer Entry */tL2C_RCB* p_rcb; /* Registration CB for this Channel */#define IB_CFG_DONE 0x01
#define OB_CFG_DONE 0x02
#define RECONFIG_FLAG 0x04 /* True after initial configuration */uint8_t config_done; /* Configuration flag word */uint16_t remote_config_rsp_result; /* The config rsp result from remote */uint8_t local_id; /* Transaction ID for local trans */uint8_t remote_id; /* Transaction ID for local */#define CCB_FLAG_NO_RETRY 0x01 /* no more retry */
#define CCB_FLAG_SENT_PENDING 0x02 /* already sent pending response */uint8_t flags;bool connection_initiator; /* true if we sent ConnectReq */tL2CAP_CFG_INFO our_cfg; /* Our saved configuration options */tL2CAP_CFG_INFO peer_cfg; /* Peer's saved configuration options */// 发送数据暂存队列。当通道拥塞(如对端缓冲区不足)时,暂存待发送的 PDU,待拥塞解除后重新发送fixed_queue_t* xmit_hold_q; /* Transmit data hold queue */// 标记是否已向对端发送 “拥塞状态”(Congestion Status)信令。对端收到后会暂停发送数据,避免进一步拥塞bool cong_sent; /* Set when congested status sent */// 触发拥塞的缓冲区配额(如本地缓冲区剩余空间低于此值时,发送拥塞信令)uint16_t buff_quota; /* Buffer quota before sending congestion */tL2CAP_CHNL_PRIORITY ccb_priority; /* Channel priority */tL2CAP_CHNL_DATA_RATE tx_data_rate; /* Channel Tx data rate */tL2CAP_CHNL_DATA_RATE rx_data_rate; /* Channel Rx data rate *//* Fields used for eL2CAP */// 扩展重传模式(ERTM)信息(如重传次数、超时时间)。ERTM 用于提高数据传输的可靠性(如实时流)tL2CAP_ERTM_INFO ertm_info;// 流控接收块(Flow Control Receive Block),记录接收端的状态(如已接收的 PDU 序号),用于流控和重传tL2C_FCRB fcrb;// 调整后的发送最大协议数据单元大小(Maximum Protocol Data Unit Size)。根据控制器能力动态调整,避免分片uint16_t tx_mps; /* TX MPS adjusted based on current controller */// 最大接收 MTU(Maximum Transmission Unit),由对端协商确定,限制接收的 SDU 大小uint16_t max_rx_mtu;// 流控配置的最大协商次数。若多次协商失败,可能终止通道uint8_t fcr_cfg_tries; /* Max number of negotiation attempts */bool peer_cfg_already_rejected; /* If mode rejected once, set to true */bool out_cfg_fcr_present; /* true if cfg response should include fcr options*/bool is_flushable; /* true if channel is flushable */uint16_t fixed_chnl_idle_tout; /* Idle timeout to use for the fixed channel */uint16_t tx_data_len;/* Number of LE frames that the remote can send to us (credit count in* remote). Valid only for LE CoC */uint16_t remote_credit_count;/* used to indicate that ECOC is used */// 标记是否使用增强连接导向通道(Enhanced CoC,eCoC)。eCoC 支持更高的吞吐量和更灵活的流控bool ecoc{false};// 标记是否已启动通道重新配置(如动态调整 MTU 或流控参数)bool reconfig_started;struct {struct {unsigned bytes{0};unsigned packets{0};void operator()(unsigned bytes) {this->bytes += bytes;this->packets++;}} rx, tx;struct {struct {unsigned bytes{0};unsigned packets{0};void operator()(unsigned bytes) {this->bytes += bytes;this->packets++;}} rx, tx;} dropped;} metrics;} tL2C_CCB;
tL2C_CCB
是 L2CAP 层管理单条通道的 “微型控制器”,其设计目标是:
-
状态隔离:每条通道的状态(如配置完成度、传输状态)独立存储,避免不同通道间的干扰;
-
协议适配:支持经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)的差异化通道类型(如固定通道、动态通道、连接导向通道 CoC);
-
可靠性:通过分段重组、流控、重传等机制,确保数据可靠传输;
-
性能优化:通过优先级、数据速率配置、拥塞管理,提升通道效率。
tL2C_RCB
packages/modules/Bluetooth/system/stack/l2cap/l2c_int.h
typedef struct {bool in_use;bool log_packets;uint16_t psm;uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but *//* this is the real PSM that we need to connect to */tL2CAP_APPL_INFO api;tL2CAP_ERTM_INFO ertm_info;// BLE 连接导向通道(Connection-Oriented Channel, CoC)的配置信息(如最大传输单元 MTU、信用计数)。CoC 是 BLE 中面向连接的传输模式,用于需要可靠传输的场景(如传感器数据)tL2CAP_LE_CFG_INFO coc_cfg;uint16_t my_mtu;// 本地应用要求对端必须支持的最小 MTU。若对端 MTU 小于此值,连接可能被拒绝(确保应用层数据能完整传输)uint16_t required_remote_mtu;
} tL2C_RCB;
在蓝牙协议栈中,L2CAP 层的核心职责之一是服务发现与路由:上层应用(如 GATT 服务器、自定义服务)需要向 L2CAP 注册自己的服务(通过 PSM 标识),当对端设备发起针对该 PSM 的连接请求时,L2CAP 层需将数据路由到对应的应用。tL2C_RCB
正是存储这些注册信息的载体,其设计目标是:
-
服务隔离:每个注册服务的信息独立存储,避免不同服务间的干扰;
-
协议适配:支持经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)的差异化服务类型(如固定 PSM 服务、动态 PSM 服务);
-
连接协商:存储服务的配置参数(如 MTU、ERTM 模式),用于 L2CAP 与对端的连接协商。
通过一个自定义 BLE 服务的注册与数据传输流程,看 tL2C_RCB
的作用:
1. 服务注册:
-
应用层(如自定义传感器服务)调用 L2CAP 接口
L2CA_Register
,传入 PSM(如 0x000F)、my_mtu=256
、required_remote_mtu=128
以及回调函数sensor_data_callback
。 -
L2CAP 层从
tL2C_CB
的rcb_pool
(注册控制块池)中分配一个空闲的tL2C_RCB
,设置in_use=true
、psm=0x000F
、api.p_cback=sensor_data_callback
、my_mtu=256
、required_remote_mtu=128
,完成服务注册。
2. 对端连接请求:
-
对端设备发起针对 PSM=0x000F 的连接请求,L2CAP 层根据 PSM 查找
rcb_pool
,找到对应的tL2C_RCB
。 -
L2CAP 层使用
rcb->coc_cfg
(CoC 配置)和rcb->ertm_info
(ERTM 配置)与对端协商连接参数(如 MTU、流控模式)。
3. 数据传输:
-
对端发送数据到 PSM=0x000F,L2CAP 层根据 PSM 找到
tL2C_RCB
,调用rcb->api.p_cback
将数据传递给应用层的sensor_data_callback
。 -
应用层处理数据后,通过 L2CAP 接口发送响应,L2CAP 层使用
rcb->my_mtu
对数据分片,确保不超过通道 MTU。 -
服务注销:应用层调用
L2CA_Deregister
注销服务,L2CAP 层将rcb->in_use
设为false
,释放tL2C_RCB
回rcb_pool
。
L2CAP 层收到对端发送的数据包后,根据 PSM 查找对应的
tL2C_RCB
,然后通过api.p_cback
调用应用层回调函数,将数据传递给上层应用(如 GATT 服务器处理 ATT 协议数据)。
tL2CAP_FIXED_CHNL_REG
packages/modules/Bluetooth/system/stack/include/l2c_api.h
/********************************************************************************* Fixed Channel callback prototypes*******************************************************************************//* Fixed channel connected and disconnected. Parameters are* channel* BD Address of remote* true if channel is connected, false if disconnected* Reason for connection failure* transport : physical transport, BR/EDR or LE*/
// 通知上层应用固定通道的连接或断开事件
typedef void(tL2CA_FIXED_CHNL_CB)(uint16_t, const RawAddress&, bool, uint16_t,tBT_TRANSPORT);/* Signalling data received. Parameters are* channel* BD Address of remote* Pointer to buffer with data*/
// 将 L2CAP 层收到的固定通道数据传递给上层应用
typedef void(tL2CA_FIXED_DATA_CB)(uint16_t, const RawAddress&, BT_HDR*);/* Congestion status callback protype. This callback is optional. If* an application tries to send data when the transmit queue is full,* the data will anyways be dropped. The parameter is:* remote BD_ADDR* true if congested, false if uncongested*/
// 通知上层应用固定通道的拥塞状态(传输队列是否已满)
typedef void(tL2CA_FIXED_CONGESTION_STATUS_CB)(const RawAddress&, bool);/* Fixed channel registration info (the callback addresses and channel config)*/
typedef struct {// 连接 / 断开事件的回调函数指针。上层应用通过此接口感知通道状态变化tL2CA_FIXED_CHNL_CB* pL2CA_FixedConn_Cb;// 数据接收回调函数指针。上层应用通过此接口获取通道数据tL2CA_FIXED_DATA_CB* pL2CA_FixedData_Cb;// 拥塞状态回调函数指针(可选)。上层应用通过此接口调整发送策略tL2CA_FIXED_CONGESTION_STATUS_CB* pL2CA_FixedCong_Cb;// 通道默认空闲超时时间(单位:毫秒)。若通道在此时间内无数据传输,L2CAP 可能触发断开或进入低功耗模式uint16_t default_idle_tout;// 发送完成回调函数指针(可选)。当 L2CAP 确认数据已成功发送到对端时,调用此回调通知上层应用(如释放发送缓冲区)tL2CA_TX_COMPLETE_CB*pL2CA_FixedTxComplete_Cb; /* fixed channel tx complete callback */
} tL2CAP_FIXED_CHNL_REG;
蓝牙协议中,L2CAP 层通过 通道(Channel)为上层协议(如 ATT、SMP、RFCOMM)提供逻辑传输服务。其中,固定通道是预分配的、PSM(Protocol Service Multiplexer)固定的通道,用于标准化协议(例如:
-
ATT(属性协议)使用 PSM=0x0004;
-
SMP(安全管理协议)使用 PSM=0x0006;
-
BLE 的 GATT 客户端 / 服务器也依赖固定通道。
固定通道的注册需要向上层协议(如 GATT)通知连接状态、传递数据,并处理拥塞等事件。tL2CAP_FIXED_CHNL_REG
正是用于绑定这些交互逻辑的配置结构。
三、L2CAP 初始化流程图
四、动态通道连接时序图
五、固定通道数据流时序图
六、流量控制流程图
七、通道状态转换图
八、内存管理关系图
九、总结
蓝牙 L2CAP 层的核心数据结构(tL2C_CB
/tL2C_LCB
/tL2C_CCB
/tL2C_RCB
/tL2CAP_FIXED_CHNL_REG
)通过状态隔离、资源预分配和协同工作,构建了一个高效、可靠的传输管理体系。这些结构不仅支撑了 L2CAP 层的核心功能(如通道管理、服务路由、流量控制),还通过协议适配(BR/EDR 与 BLE)、扩展支持(eL2CAP/LE CoC)和兼容性设计(测试模式、拥塞处理),满足了蓝牙设备在不同场景(如低功耗、实时传输)下的多样化需求。理解这些数据结构的设计逻辑与交互机制,是掌握蓝牙协议栈开发、调试与优化的关键。