当前位置: 首页 > news >正文

【Bluedroid】蓝牙启动之 RFCOMM_Init 流程源码解析

本文围绕蓝牙协议栈中 RFCOMM(无线射频通信)层与 L2CAP(逻辑链路控制和适配协议)层的核心初始化流程及交互机制展开,重点分析了 RFCOMM 模块的初始化函数(RFCOMM_Init)、RFCOMM 与 L2CAP 的接口注册函数(rfcomm_l2cap_if_init),以及 L2CAP 层的服务注册函数(L2CA_Register)。结合关键数据结构(如tRFC_CBtRFC_MCBtL2CAP_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_CBrfc_cb)的内存置零,确保所有状态变量(如last_muxlast_port_index)初始化为默认值。

  • 连接映射表清空:清空rfc_lcid_mcb(SCI 到连接管理块的映射表),避免残留连接信息干扰后续操作。

  • 关键参数初始化:设置rfc_cb.rfc.last_muxMAX_BD_CONNECTIONS(默认 16),用于后续多路复用器编号的动态分配。

  • L2CAP 接口初始化:调用rfcomm_l2cap_if_init,完成 RFCOMM 与 L2CAP 的接口注册。

1.3 RFCOMM 与 L2CAP 的接口注册:rfcomm_l2cap_if_init

该函数的核心是将 RFCOMM 的事件回调函数注册到 L2CAP 层,建立两者的交互通道:

  • 回调绑定:将 RFCOMM 的连接、配置、断开、数据接收等事件处理函数(如RFCOMM_ConnectIndRFCOMM_BufDataInd)绑定到tL2CAP_APPL_INFO结构体(rfc_cb.rfc.reg_info),供 L2CAP 调用。

  • L2CAP 注册:调用L2CA_Register函数,以BT_PSM_RFCOMM0x0003,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_CBtPORT_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)和状态信息。

结构体间的协作关系

  1. L2CAP 与 RFCOMM 的交互: RFCOMM 通过向 L2CAP 注册回调,当 L2CAP 层收到连接请求、数据或状态变化时,通过这些回调通知 RFCOMM 层(如pL2CA_DataInd_Cb处理接收数据)。

  2. 连接管理: 每个物理连接(到不同蓝牙设备)对应一个tRFC_MCB,管理该连接上的所有逻辑端口(通过port_handles映射 DLCI 到端口句柄)。

  3. 资源池: 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)等应用的底层基石。


相关文章:

  • Android 默认第三方app运行权限(android11-13)
  • 【测试专栏】自动化测试——云存储项目
  • 计算机视觉与深度学习 | 基于Matlab的低照度图像增强算法原理,公式及实现
  • matlab红外与可见光图像配准算法
  • 学车笔记 变挡
  • 建站SEO优化之站点地图sitemap
  • Java多线程通信核心机制详解
  • UE5 学习系列(八)材质基础认知
  • 图数据库的理解
  • 【编译工具】(自动化)自动化测试工具:如何让我的开发效率提升300%并保证代码质量?
  • Ubuntu 22.04: 使用chroot切换到Ubuntu18.04运行环境进行开发编译
  • Roboguide工作站机器人重新安装软件包
  • Altair:让你爱上数据可视化的声明式魔法!
  • Hello Robot发布Stretch3机器人高保真模拟平台-Stretch MuJoCo v0.5-涵盖数百种Robocasa厨房应用测试场景
  • java转PHP开发需要几步?
  • 台湾TEMI协会竞赛——1、龙舟机器人组装教学
  • 七牛云域名配置与CNAME解析
  • 数据链抗干扰
  • 增强跳板机安全性的解决方案
  • 在 Windows 上安装和配置 Redis 及可视化工具指南
  • the 7 wordpress theme/天津seo排名扣费
  • 大连科技网站制作/seo数据是什么意思
  • 番禺网站建设服务/百度招聘
  • 建设什么网站/怎么制作网页页面
  • 潍坊专业网站建设哪家好/东莞网站设计公司
  • 做网站几天能学会/windows优化软件哪个好