【Bluedroid】蓝牙启动之 RFCOMM_Init 流程源码解析
本文围绕蓝牙协议栈中 RFCOMM(无线射频通信)层与 L2CAP(逻辑链路控制和适配协议)层的核心初始化流程及交互机制展开,重点分析了 RFCOMM 模块的初始化函数(
RFCOMM_Init
)、RFCOMM 与 L2CAP 的接口注册函数(rfcomm_l2cap_if_init
),以及 L2CAP 层的服务注册函数(L2CA_Register
)。结合关键数据结构(如tRFC_CB
、tRFC_MCB
、tL2CAP_APPL_INFO
等)的定义与协作关系,阐述了 RFCOMM 如何通过 L2CAP 提供的服务实现连接管理、数据传输及状态同步,揭示了蓝牙协议栈分层架构中上层协议与中间层的高效交互逻辑。
一、概述
1.1 背景:蓝牙协议栈中的 RFCOMM 与 L2CAP
蓝牙协议栈采用分层架构,L2CAP 作为中间层,负责为上层协议(如 RFCOMM、AVCTP)提供面向连接的通道服务,支持数据分片、QoS(服务质量)协商及流量控制。RFCOMM 基于 L2CAP 通道实现串口仿真(如蓝牙串口),需依赖 L2CAP 的连接管理能力。两者的协作是蓝牙数据传输的核心基础。
1.2 RFCOMM 层的初始化:RFCOMM_Init
RFCOMM_Init
是 RFCOMM 层的启动入口,主要完成以下初始化任务:
-
控制块清零:通过
memset
将全局控制块tRFC_CB
(rfc_cb
)的内存置零,确保所有状态变量(如last_mux
、last_port_index
)初始化为默认值。 -
连接映射表清空:清空
rfc_lcid_mcb
(SCI 到连接管理块的映射表),避免残留连接信息干扰后续操作。 -
关键参数初始化:设置
rfc_cb.rfc.last_mux
为MAX_BD_CONNECTIONS
(默认 16),用于后续多路复用器编号的动态分配。 -
L2CAP 接口初始化:调用
rfcomm_l2cap_if_init
,完成 RFCOMM 与 L2CAP 的接口注册。
1.3 RFCOMM 与 L2CAP 的接口注册:rfcomm_l2cap_if_init
该函数的核心是将 RFCOMM 的事件回调函数注册到 L2CAP 层,建立两者的交互通道:
-
回调绑定:将 RFCOMM 的连接、配置、断开、数据接收等事件处理函数(如
RFCOMM_ConnectInd
、RFCOMM_BufDataInd
)绑定到tL2CAP_APPL_INFO
结构体(rfc_cb.rfc.reg_info
),供 L2CAP 调用。 -
L2CAP 注册:调用
L2CA_Register
函数,以BT_PSM_RFCOMM
(0x0003
,RFCOMM 专用 PSM)为标识,向 L2CAP 注册 RFCOMM 服务,并声明本地 MTU(L2CAP_MTU_SIZE
,默认 1691 字节)等参数。
1.4 L2CAP 层的服务注册:L2CA_Register
L2CAP 通过L2CA_Register
管理上层协议的注册,核心逻辑包括:
-
回调有效性校验:强制上层协议提供
pL2CA_ConfigCfm_Cb
(配置确认)、pL2CA_DataInd_Cb
(数据到达)、pL2CA_DisconnectInd_Cb
(断开指示)等核心回调,确保事件能被正确处理。 -
PSM 有效性校验:验证 PSM 是否符合蓝牙规范(如非保留值、奇数规则),避免非法协议注册。
-
虚拟 PSM 分配:针对动态 PSM(
>=0x1001
)的纯客户端场景(无连接请求回调),分配虚拟 PSM(偶数,如0x1002
起),避免与其他服务的 PSM 冲突。 -
注册控制块(RCB)管理:从预分配的 RCB 资源池中获取或创建
tL2C_RCB
,存储上层协议的回调、MTU、PSM 等信息,供 L2CAP 后续事件路由使用。
1.5 关键数据结构的协作
-
tRFC_CB
与tPORT_CB
:RFCOMM 的全局控制块,整合核心状态(tRFCOMM_CB
)与资源池(tPORT_CB
中的端口和连接管理块数组),实现端口与连接的高效管理。 -
tRFC_MCB
:每个物理连接的状态管理块,跟踪多路复用通道的定时器、队列、对端地址等信息,通过port_handles
快速映射逻辑端口(DLCI)。 -
tL2CAP_APPL_INFO
:L2CAP 与上层协议的交互接口,存储回调函数指针,是事件驱动的核心桥梁。
二、源码解析
RFCOMM_Init
packages/modules/Bluetooth/system/stack/rfcomm/port_api.cc
tRFC_CB rfc_cb; // RFCOMM控制块(Control Block),存储模块全局状态
std::unordered_map<uint16_t /* sci */, tRFC_MCB*> rfc_lcid_mcb; // 连接映射表:通过SCI(服务类标识符)映射到连接管理块(MCB)/* The maximum simultaneous links to different devices. */
#ifndef MAX_BD_CONNECTIONS
#define MAX_BD_CONNECTIONS 16
#endif/********************************************************************************* Function RFCOMM_Init** Description This function is called to initialize RFCOMM layer*******************************************************************************/
void RFCOMM_Init(void) {memset(&rfc_cb, 0, sizeof(tRFC_CB)); /* Init RFCOMM control block */rfc_lcid_mcb = {}; /* 清空连接映射表 */rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;rfcomm_l2cap_if_init(); /* 初始化与L2CAP层的接口 */
}
RFCOMM 模块的初始化准备工作。
tRFC_CB
packages/modules/Bluetooth/system/stack/include/l2c_api.h
// 用于 AMP(自适应多路径协议)的扩展流规范,定义了更精细的流量控制参数
/* Define the extended flow specification fields used by AMP */
typedef struct {uint8_t id; // 流标识符(唯一标识一个流)uint8_t stype; // 流类型(如同步流、异步流)uint16_t max_sdu_size; // 最大SDU(服务数据单元)大小(字节)uint32_t sdu_inter_time; // SDU间隔时间(微秒,最小发送间隔)uint32_t access_latency; // 访问延迟(微秒,数据从发送到接收的最大时间)uint32_t flush_timeout; // 刷新超时(微秒,未确认数据的最大保留时间)
} tHCI_EXT_FLOW_SPEC;// 定义 L2CAP 连接的 QoS(服务质量)参数,适用于大多数蓝牙连接场景
typedef struct {uint8_t qos_flags; /* TBD */uint8_t service_type; /* see below */uint32_t token_rate; /* bytes/second */uint32_t token_bucket_size; /* bytes */uint32_t peak_bandwidth; /* bytes/second */uint32_t latency; /* microseconds */uint32_t delay_variation; /* microseconds */
} FLOW_SPEC;// 用于 L2CAP 连接的配置参数协商,支持可选参数(通过布尔字段标记是否存在)
/* Define a structure to hold the configuration parameters. Since the* parameters are optional, for each parameter there is a boolean to* use to signify its presence or absence.*/
typedef struct {uint16_t result; /* Only used in confirm messages */bool mtu_present;uint16_t mtu;bool qos_present;FLOW_SPEC qos;bool flush_to_present;uint16_t flush_to;bool fcr_present;tL2CAP_FCR_OPTS fcr;bool fcs_present; /* Optionally bypasses FCS checks */uint8_t fcs; /* '0' if desire is to bypass FCS, otherwise '1' */bool ext_flow_spec_present;tHCI_EXT_FLOW_SPEC ext_flow_spec;uint16_t flags; /* bit 0: 0-no continuation, 1-continuation */
} tL2CAP_CFG_INFO;// 每个 RFCOMM 多路复用通道(对应一个 L2CAP 通道)的状态管理块,用于跟踪连接状态、定时器和队列
/** RFCOMM multiplexer Control Block
*/
typedef struct {alarm_t* mcb_timer = nullptr; /* MCB timer */fixed_queue_t* cmd_q = nullptr; /* Queue for command messages on this mux */uint8_t port_handles[RFCOMM_MAX_DLCI + 1]; /* Array for quick access to *//* port handles based on dlci */RawAddress bd_addr =RawAddress::kEmpty; /* BD ADDR of the peer if initiator */uint16_t lcid; /* Local cid used for this channel */uint16_t peer_l2cap_mtu; /* Max frame that can be sent to peer L2CAP */uint8_t state; /* Current multiplexer channel state */uint8_t is_initiator; /* true if this side sends SABME (dlci=0) */bool restart_required; /* true if has to restart channel after disc */bool peer_ready; /* True if other side can accept frames */uint8_t flow; /* flow control mechanism for this mux */bool l2cap_congested; /* true if L2CAP is congested */bool is_disc_initiator; /* true if initiated disc of port */uint16_tpending_lcid; /* store LCID for incoming connection while connecting */bool pending_configure_complete; /* true if confiquration of the pendingconnection was completed*/tL2CAP_CFG_INFO pending_cfg_info = {}; /* store configure info for incomingconnection while connecting */
} tRFC_MCB;packages/modules/Bluetooth/system/internal_include/bt_target.h
/******************************************************************************** RFCOMM******************************************************************************//* The maximum number of ports supported. */
#ifndef MAX_RFC_PORTS
#define MAX_RFC_PORTS 30
#endif/* The maximum simultaneous links to different devices. */
#ifndef MAX_BD_CONNECTIONS
#define MAX_BD_CONNECTIONS 16
#endif// RFCOMM 层的全局端口和连接池,管理所有端口实例和多路复用通道
/* Define the PORT/RFCOMM control structure
*/
typedef struct {tPORT port[MAX_RFC_PORTS]; /* Port info pool */tRFC_MCB rfc_mcb[MAX_BD_CONNECTIONS]; /* RFCOMM bd_connections pool */
} tPORT_CB;/* Define the structure that applications use to register with* L2CAP. This structure includes callback functions. All functions* MUST be provided, with the exception of the "connect pending"* callback and "congestion status" callback.*/
typedef struct {tL2CA_CONNECT_IND_CB* pL2CA_ConnectInd_Cb;tL2CA_CONNECT_CFM_CB* pL2CA_ConnectCfm_Cb;tL2CA_CONFIG_IND_CB* pL2CA_ConfigInd_Cb;tL2CA_CONFIG_CFM_CB* pL2CA_ConfigCfm_Cb;tL2CA_DISCONNECT_IND_CB* pL2CA_DisconnectInd_Cb;tL2CA_DISCONNECT_CFM_CB* pL2CA_DisconnectCfm_Cb;tL2CA_DATA_IND_CB* pL2CA_DataInd_Cb;tL2CA_CONGESTION_STATUS_CB* pL2CA_CongestionStatus_Cb;tL2CA_TX_COMPLETE_CB* pL2CA_TxComplete_Cb;tL2CA_ERROR_CB* pL2CA_Error_Cb;tL2CA_CREDIT_BASED_CONNECT_IND_CB* pL2CA_CreditBasedConnectInd_Cb;tL2CA_CREDIT_BASED_CONNECT_CFM_CB* pL2CA_CreditBasedConnectCfm_Cb;tL2CA_CREDIT_BASED_RECONFIG_COMPLETED_CB*pL2CA_CreditBasedReconfigCompleted_Cb;tL2CA_CREDIT_BASED_COLLISION_IND_CB* pL2CA_CreditBasedCollisionInd_Cb;
} tL2CAP_APPL_INFO;packages/modules/Bluetooth/system/stack/rfcomm/rfc_int.h
// RFCOMM 层的核心状态管理结构,包含接收帧、L2CAP 注册信息和关键状态变量
/* Define RFComm control block
*/
typedef struct {MX_FRAME rx_frame; // 接收帧缓冲区(存储从L2CAP层接收的原始数据)tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */bool peer_rx_disabled; /* If true peer sent FCOFF */uint8_t last_mux; /* Last mux allocated */uint8_t last_port_index; // Index of last port allocated in rfc_cb.port
} tRFCOMM_CB;// 整合 RFCOMM 核心控制块和端口控制块,是 RFCOMM 层的全局状态容器
/* Main Control Block for the RFCOMM Layer (PORT and RFC) */
typedef struct {tRFCOMM_CB rfc; // RFCOMM核心状态(接收、L2CAP交互、复用器管理)tPORT_CB port; // 端口和连接池(管理所有端口实例和物理连接)
} tRFC_CB;
蓝牙协议栈中 RFCOMM和 L2CAP层的核心数据结构,用于管理连接、配置参数、服务质量(QoS)和状态信息。
结构体间的协作关系
-
L2CAP 与 RFCOMM 的交互: RFCOMM 通过向 L2CAP 注册回调,当 L2CAP 层收到连接请求、数据或状态变化时,通过这些回调通知 RFCOMM 层(如
pL2CA_DataInd_Cb
处理接收数据)。 -
连接管理: 每个物理连接(到不同蓝牙设备)对应一个
tRFC_MCB
,管理该连接上的所有逻辑端口(通过port_handles
映射 DLCI 到端口句柄)。 -
资源池:
tPORT_CB
中的port
数组和rfc_mcb
数组作为资源池,动态分配端口和连接控制块,避免频繁内存分配,提高效率。
这些结构体共同构成了 RFCOMM 层的核心逻辑,确保在 L2CAP 通道上高效管理多个逻辑端口(串口仿真),并支持 QoS、流控等高级功能。
rfcomm_l2cap_if_init
packages/modules/Bluetooth/system/stack/rfcomm/rfc_l2cap_if.cc
BT_PSM_RFCOMM = 0x0003 // L2CAP 识别 RFCOMM 的唯一标识/* The L2CAP MTU; must be in accord with the HCI ACL buffer size. */
#ifndef L2CAP_MTU_SIZE
#define L2CAP_MTU_SIZE 1691
#endif/********************************************************************************* Function rfcomm_l2cap_if_init** Description This function is called during the RFCOMM task startup* to register interface functions with L2CAP.*******************************************************************************/
void rfcomm_l2cap_if_init(void) {tL2CAP_APPL_INFO* p_l2c = &rfc_cb.rfc.reg_info;// 存储 RFCOMM 向 L2CAP 注册的回调函数指针// 绑定 L2CAP 事件回调函数p_l2c->pL2CA_ConnectInd_Cb = RFCOMM_ConnectInd; // 连接请求指示回调p_l2c->pL2CA_ConnectCfm_Cb = RFCOMM_ConnectCnf; // 连接确认回调p_l2c->pL2CA_ConfigInd_Cb = RFCOMM_ConfigInd; // 配置请求指示回调p_l2c->pL2CA_ConfigCfm_Cb = RFCOMM_ConfigCnf; // 配置确认回调p_l2c->pL2CA_DisconnectInd_Cb = RFCOMM_DisconnectInd; // 断开请求指示回调p_l2c->pL2CA_DataInd_Cb = RFCOMM_BufDataInd; // 数据到达指示回调p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd; // 拥塞状态指示回调p_l2c->pL2CA_TxComplete_Cb = NULL; // 发送完成回调(未启用)p_l2c->pL2CA_Error_Cb = rfc_on_l2cap_error; // L2CAP错误回调// 向 L2CAP 注册 RFCOMML2CA_Register(BT_PSM_RFCOMM, rfc_cb.rfc.reg_info, true /* enable_snoop */,nullptr, L2CAP_MTU_SIZE, 0, 0);
}
建立 L2CAP 与 RFCOMM 的交互通道。L2CAP 是蓝牙协议栈的中间层,负责为上层(如 RFCOMM)提供面向连接的通道服务。RFCOMM 需要通过 L2CAP 传输数据,并处理 L2CAP 的连接、配置、断开等事件。核心作用是:
-
向 L2CAP 注册 RFCOMM 的事件回调函数(如连接请求、数据到达)。
-
声明 RFCOMM 使用的协议服务多路复用器(PSM),以便 L2CAP 识别目标上层协议。
L2CA_Register
packages/modules/Bluetooth/system/stack/l2cap/l2c_api.cc
/********************************************************************************* Function L2CA_Register** Description Other layers call this function to register for L2CAP* services.** Returns PSM to use or zero if error. Typically, the PSM returned* is the same as was passed in, but for an outgoing-only* connection to a dynamic PSM, a "virtual" PSM is returned* and should be used in the calls to L2CA_ConnectReq(),* L2CA_ErtmConnectReq() and L2CA_Deregister()*******************************************************************************/
uint16_t L2CA_Register(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info,bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info,uint16_t my_mtu, uint16_t required_remote_mtu,uint16_t sec_level) {// 1. 回调函数有效性校验// L2CAP 要求上层协议必须提供部分核心回调函数,否则注册失败const bool config_cfm_cb = (p_cb_info.pL2CA_ConfigCfm_Cb != nullptr);const bool config_ind_cb = (p_cb_info.pL2CA_ConfigInd_Cb != nullptr);const bool data_ind_cb = (p_cb_info.pL2CA_DataInd_Cb != nullptr);const bool disconnect_ind_cb = (p_cb_info.pL2CA_DisconnectInd_Cb != nullptr);tL2C_RCB* p_rcb; // L2CAP 通过注册控制块(RCB)管理所有已注册的上层协议。RCB 存储了上层协议的关键信息(回调、MTU、PSM 等)uint16_t vpsm = psm;/* Verify that the required callback info has been filled in** Note: Connection callbacks are required but not checked** for here because it is possible to be only a client** or only a server.*/if (!config_cfm_cb || !data_ind_cb || !disconnect_ind_cb) {log::error("L2CAP - no cb registering PSM: 0x{:04x} cfg_cfm:{} cfg_ind:{} ""data_ind:{} discon_int:{}",psm, config_cfm_cb, config_ind_cb, data_ind_cb, disconnect_ind_cb);return (0);}// 2. PSM 有效性校验/* Verify PSM is valid */if (L2C_INVALID_PSM(psm)) {log::error("L2CAP - invalid PSM value, PSM: 0x{:04x}", psm);return (0);}// 3. 动态 PSM 的虚拟 PSM 分配/* Check if this is a registration for an outgoing-only connection to *//* a dynamic PSM. If so, allocate a "virtual" PSM for the app to use. */if ((psm >= 0x1001) && (p_cb_info.pL2CA_ConnectInd_Cb == NULL)) {for (vpsm = 0x1002; vpsm < 0x8000; vpsm += 2) {p_rcb = l2cu_find_rcb_by_psm(vpsm);if (p_rcb == NULL) break;}log::debug("L2CAP - Real PSM: 0x{:04x} Virtual PSM: 0x{:04x}", psm, vpsm);}// 4. 注册控制块(RCB)的分配与初始化/* If registration block already there, just overwrite it */// 查找或分配 RCBp_rcb = l2cu_find_rcb_by_psm(vpsm); // 按虚拟PSM查找已有的RCBif (p_rcb == NULL) {p_rcb = l2cu_allocate_rcb(vpsm); // 分配新的RCBif (p_rcb == NULL) {log::warn("L2CAP - no RCB available, PSM: 0x{:04x} vPSM: 0x{:04x}", psm,vpsm);return (0);}}log::info("L2CAP Registered service classic PSM: 0x{:04x}", psm);p_rcb->log_packets = enable_snoop; // 启用/禁用Snoop日志p_rcb->api = p_cb_info; // 存储上层回调函数p_rcb->real_psm = psm; // 记录真实PSM(用于动态PSM场景)p_rcb->ertm_info = p_ertm_info == nullptr? tL2CAP_ERTM_INFO{L2CAP_FCR_BASIC_MODE}: *p_ertm_info; // ERTM配置p_rcb->my_mtu = my_mtu; // 本地MTUp_rcb->required_remote_mtu =std::max<uint16_t>(required_remote_mtu, L2CAP_MIN_MTU); // 对端最小MTU(至少为L2CAP_MIN_MTU)return (vpsm);
}
将上层协议(如 RFCOMM)注册到 L2CAP 层,并为其分配资源(如注册控制块)。L2CAP 通过此函数记录上层协议的回调函数、MTU(最大传输单元)等参数,从而在收到底层事件(如连接请求、数据到达)时,能够正确路由到对应的上层协议处理。
动态 PSM:
对于动态 PSM(
psm >= 0x1001
,通常用于客户端主动连接对端的场景),若上层协议未提供连接指示回调(pL2CA_ConnectInd_Cb == NULL
,说明是纯客户端,不接受连接请求),L2CAP 会分配一个虚拟 PSM(vpsm)。
动态 PSM(如
0x1001
及以上)通常由对端设备分配,本地客户端需要通过虚拟 PSM 在 L2CAP 层注册,避免与其他上层协议的 PSM 冲突。虚拟 PSM 从
0x1002
开始(偶数),按步长 2 递增(确保不与动态 PSM 的奇数冲突),直到找到未被占用的 PSM。
三、RFCOMM 初始化与 L2CAP 注册流程图
四、RFCOMM-L2CAP 交互时序图
五、总结
RFCOMM 与 L2CAP 的协作是蓝牙串口仿真功能的基础,其初始化与注册机制体现了蓝牙协议栈分层架构的设计优势:
-
解耦与模块化:L2CAP 通过统一的
L2CA_Register
接口管理上层协议,上层只需实现约定的回调函数即可接入,无需关心底层传输细节。 -
资源高效管理:通过预分配的资源池(如
rfc_mcb
数组、RCB 池)和虚拟 PSM 机制,避免频繁内存分配,提升协议栈性能。 -
事件驱动的可靠性:通过回调函数和 RCB 的长期保留,L2CAP 能高效路由连接、数据、断开等事件,确保上层协议及时响应,保障蓝牙通信的稳定性。
这些机制共同支撑了 RFCOMM 在 L2CAP 通道上的多逻辑端口管理、QoS 协商及流量控制等核心功能,是蓝牙串口仿真(SPP)等应用的底层基石。