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

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

蓝牙 GAP(通用访问配置文件)模块是蓝牙协议栈的核心组件,负责设备发现、连接管理及基础属性暴露等关键功能。本文围绕 Android蓝牙协议栈 GAP 模块的初始化流程与连接管理实现展开,结合代码解析其核心函数(GAP_Initgap_conn_initgap_attr_db_init)的功能逻辑,以及关键数据结构(tGAP_CONNtGAP_CCBtGAP_ATTR等)的设计意图。通过分析 GAP 模块与 L2CAP 层的协议交互、连接状态机管理,以及 GATT 属性数据库的初始化过程,揭示 GAP 模块在蓝牙设备发现、配对及连接中的基础支撑作用。

一、概述

蓝牙 GAP 模块作为协议栈的 “入口”,其核心目标是为上层应用提供统一的设备管理接口,并确保底层协议(如 L2CAP、GATT)的高效协作。本文聚焦以下核心内容:

1.1 GAP 模块初始化流程:GAP_Init

GAP_Init是 GAP 模块的基础初始化入口函数,设计上确保 “每次栈调用仅执行一次”。其通过调用两个子函数完成初始化:

  • gap_conn_init:初始化 GAP 连接管理模块,通过注册 L2CAP 层事件回调(如连接请求、数据到达)建立与 L2CAP 的协议交互通道;

  • gap_attr_db_init:初始化 GAP 的 GATT 属性数据库,向外暴露 BLE 设备的基础属性(如设备名称、图标、地址解析状态),支撑设备发现与配对。

1.2 连接管理核心:gap_conn_init与数据结构

gap_conn_init的核心任务是初始化连接管理的全局状态,并建立与 L2CAP 层的事件交互。通过memset清零全局结构体tGAP_CONN确保初始状态可控,随后为reg_info成员注册 L2CAP 事件回调(如gap_connect_ind处理连接请求、gap_data_ind处理数据到达),实现对 L2CAP 事件的响应。

关键数据结构tGAP_CONN通过ccb_pool数组管理最多 30 个并发连接(GAP_MAX_CONNECTIONS),每个连接由tGAP_CCB结构体控制。tGAP_CCB通过状态机(con_state,如IDLE→LISTENING→CONNECTED)和标志位(con_flags,如配置完成、安全验证完成)严格管理连接生命周期,并通过队列(tx_queuerx_queue)实现流量控制,确保数据可靠传输。

1.3 属性数据库初始化:gap_attr_db_init

gap_attr_db_init的核心是在 GATT 服务器中创建 GAP 服务,并初始化其属性数据库,向外暴露 BLE 设备的基础信息。通过以下步骤实现:

  • 注册 GATT 服务:通过GATT_Register创建应用实例,获取 GATT 接口句柄gatt_if

  • 定义服务与特征:声明主服务(UUID 0x1800),并添加设备名称(0x2A00)、图标(0x2A01)、地址解析(0x2AA6)等特征,部分场景(外设模式)添加首选连接参数(0x2A04)特征;

  • 绑定属性缓存:将 GATT 服务器分配的特征句柄与本地数组gatt_attr绑定,便于后续快速访问或修改属性值(如更新设备名称)。

二、源码解析

GAP_Init

packages/modules/Bluetooth/system/stack/gap/gap_conn.cc
/** This routine should not be called except once per stack invocation.*/
void GAP_Init(void) {gap_conn_init();gap_attr_db_init();
}

GAP 模块的基础初始化,确保后续功能正确运行。

gap_conn_init

packages/modules/Bluetooth/system/stack/gap/gap_conn.cc
namespace {
tGAP_CONN conn;
}  // namespace/********************************************************************************* Function         gap_conn_init** Description      This function is called to initialize GAP connection*                  management** Returns          void*******************************************************************************/
void gap_conn_init(void) {memset(&conn, 0, sizeof(tGAP_CONN));// 注册 L2CAP 层回调函数:建立协议层交互通道conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;conn.reg_info.pL2CA_Error_Cb = gap_on_l2cap_error;
}

GAP模块的连接管理部分,主要实现 GAP 连接管理模块的初始化逻辑。为conn.reg_info(注册信息结构体)中的L2CAP 层事件回调函数指针赋值,建立 GAP 模块与 L2CAP 层的事件交互通道。每个回调函数对应 L2CAP 层的一个关键事件:

回调函数指针含义与作用
pL2CA_ConnectInd_CbL2CAP 连接请求指示回调。当底层收到 L2CAP 连接请求时,触发gap_connect_ind处理(如验证请求、分配资源)。
pL2CA_ConnectCfm_CbL2CAP 连接确认回调。当 L2CAP 连接成功建立后,触发gap_connect_cfm通知上层(如更新连接状态)。
pL2CA_ConfigInd_CbL2CAP 配置请求指示回调。当收到 L2CAP 连接参数配置请求时,触发gap_config_ind处理(如协商 MTU、QoS)。
pL2CA_ConfigCfm_CbL2CAP 配置确认回调。当配置完成后,触发gap_config_cfm同步最终配置结果。
pL2CA_DisconnectInd_CbL2CAP 断开连接指示回调。当 L2CAP 连接断开时,触发gap_disconnect_ind清理资源(如释放连接句柄)。
pL2CA_DataInd_CbL2CAP 数据到达指示回调。当收到 L2CAP 层数据时,触发gap_data_ind向上层传递数据(如 GATT/ATT 处理)。
pL2CA_CongestionStatus_CbL2CAP 拥塞状态变化回调。当底层发生拥塞或恢复时,触发gap_congestion_ind调整发送策略(如暂停发数据)。
pL2CA_TxComplete_CbL2CAP 数据发送完成回调。当数据成功发送到底层时,触发gap_tx_complete_ind释放发送缓冲区。
pL2CA_Error_CbL2CAP 错误通知回调。当 L2CAP 层发生错误(如协议异常)时,触发gap_on_l2cap_error处理错误(如断开连接)。

tGAP_CONN

packages/modules/Bluetooth/system/stack/gap/gap_conn.cc
// LE 信用模式(Credit-Based)连接的信用管理
// 背景:在蓝牙 LE 的 L2CAP 面向连接通道(CoC)中,信用模式(Credit-Based Flow Control)用于流量控制。发送方需根据接收方授予的信用值(每信用代表 1 个数据包)限制发送量
//作用:记录信用值的接收和消耗状态,确保发送方不会超出接收方的处理能力
struct tGAP_COC_CREDITS {uint16_t credits_received;  // 已接收的信用值(对端允许发送的数据包数量)uint16_t credit_count;  // 当前可用的信用值(剩余可发送的数据包数量)
};// GAP 连接事件回调数据联合体
union tGAP_CB_DATA {tGAP_COC_CREDITS coc_credits; // 当事件与LE信用模式相关时,存储信用值数据uint16_t l2cap_result;  // 当事件与L2CAP操作结果相关时,存储结果状态(如成功/失败码)
};// GAP 连接事件回调函数指针
/** Callback function for connection services
*/
typedef void(tGAP_CONN_CALLBACK)(uint16_t gap_handle, uint16_t event,tGAP_CB_DATA* data);// 增强重传模式(ERTM)配置    
// 背景:ERTM 是 L2CAP 的一种传输模式,支持重传和流量控制,用于提高数据传输可靠性
// 作用:配置连接的 ERTM 模式,影响 L2CAP 层的数据重传策略和错误处理方式                       
/* Define the structure that applications use to create or accept* connections with enhanced retransmission mode.*/
typedef struct {uint8_t preferred_mode;  // 首选的ERTM模式(如基本模式、增强模式)
} tL2CAP_ERTM_INFO;typedef uint8_t tBT_TRANSPORT;// LE L2CAP 面向连接通道(CoC)配置
/* Define a structure to hold the configuration parameter for LE L2CAP* connection oriented channels.*/
struct tL2CAP_LE_CFG_INFO {uint16_t result; /* Only used in confirm messages */uint16_t mtu = 100;uint16_t mps = 100; // 最大数据包大小(字节),默认100字节uint16_t credits = L2CA_LeCreditDefault();  // 初始信用值(默认由L2CAP层定义)uint8_t number_of_channels = L2CAP_CREDIT_BASED_MAX_CIDS; // 最大支持的CoC通道数
};// 单个 L2CAP 连接的状态管理核心结构,存储连接的生命周期状态、配置参数和交互接口
/* Define the GAP Connection Control Block */
typedef struct {
// 通过状态迁移(如IDLE → LISTENING → CONN_SETUP → CFG_SETUP → CONNECTED)严格管理连接的生命周期,确保各阶段操作(如连接请求、参数协商)按顺序执行
#define GAP_CCB_STATE_IDLE 0
#define GAP_CCB_STATE_LISTENING 1
#define GAP_CCB_STATE_CONN_SETUP 2
#define GAP_CCB_STATE_CFG_SETUP 3
#define GAP_CCB_STATE_CONNECTED 5uint8_t con_state;// 通过位掩码快速标记连接的关键里程碑(如是否完成配置、安全验证),避免复杂的状态判断逻辑
#define GAP_CCB_FLAGS_IS_ORIG 0x01
#define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02 // 标志位:对端配置已完成(对端参数协商完成)
#define GAP_CCB_FLAGS_MY_CFG_DONE 0x04 // 标志位:本地配置已完成(本地参数协商完成)
#define GAP_CCB_FLAGS_SEC_DONE 0x08
#define GAP_CCB_FLAGS_CONN_DONE 0x0Euint8_t con_flags;// 存储连接的基础标识信息(如句柄、CID、地址)和协商参数(如对端 MTU),用于在协议栈各层(GAP、L2CAP、BTM)间传递连接上下文uint8_t service_id;     /* Used by BTM */uint16_t gap_handle;    /* GAP handle */uint16_t connection_id; /* L2CAP CID */bool rem_addr_specified;uint8_t chan_mode_mask; /* Supported channel modes (FCR) */RawAddress rem_dev_address;uint16_t psm;uint16_t rem_mtu_size;// 流量控制与队列管理// 蓝牙底层可能因处理能力限制出现拥塞,需通过队列缓存数据并控制发送速率bool is_congested;fixed_queue_t* tx_queue; /* Queue of buffers waiting to be sent */fixed_queue_t* rx_queue; /* Queue of buffers waiting to be read */uint32_t rx_queue_size; /* Total data count in rx_queue */// 回调与配置参数tGAP_CONN_CALLBACK* p_callback; /* Users callback function */tL2CAP_CFG_INFO cfg;              /* Configuration */tL2CAP_ERTM_INFO ertm_info;       /* Pools and modes for ertm */tBT_TRANSPORT transport;          /* Transport channel BR/EDR or BLE */tL2CAP_LE_CFG_INFO local_coc_cfg; /* local configuration for LE Coc */tL2CAP_LE_CFG_INFO peer_coc_cfg;  /* local configuration for LE Coc */
} tGAP_CCB;/* The maximum number of simultaneous GAP L2CAP connections. */
#ifndef GAP_MAX_CONNECTIONS
#define GAP_MAX_CONNECTIONS 30
#endiftypedef struct {tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS];
} tGAP_CONN;

GAP模块中与连接管理相关的核心数据结构,用于管理L2CAP连接的状态、配置及事件交互。

这些结构体共同构成了 GAP 连接管理模块的核心数据模型:

  1. tGAP_CONN:作为全局管理结构,通过reg_info与 L2CAP 层交互,并通过ccb_pool管理所有活动连接。

  2. tGAP_CCB:每个连接的 “状态控制器”,通过状态机(con_state)、标志位(con_flags)和配置参数(如local_coc_cfg)管理连接的生命周期。

  3. tGAP_CONN_CALLBACK:上层应用的 “事件入口”,确保连接事件(如数据到达、断开)能被及时处理。

通过这套数据结构,GAP 模块实现了对 L2CAP 连接的高效管理(如连接建立、参数协商、流量控制),是蓝牙协议栈中连接层的核心基础。

gap_attr_db_init

packages/modules/Bluetooth/system/stack/gap/gap_ble.cc
// BLE 首选连接参数
typedef struct {uint16_t int_min;  // 最小连接间隔(单位:1.25ms,范围:0x0006~0x0C80)uint16_t int_max;  // 最大连接间隔(需≥int_min)uint16_t latency;  // 从机延迟(允许从机跳过的连接事件数)uint16_t sp_tout;  // 监督超时时间(单位:10ms,范围:0x000A~0x0C80)
} tGAP_BLE_PREF_PARAM;// GAP 属性值联合体
typedef union {tGAP_BLE_PREF_PARAM conn_param;  // BLE首选连接参数(当属性类型为连接参数时)RawAddress reconn_bda;           // 重连地址(当属性类型为重连地址时)uint16_t icon;                   // 设备图标类型(当属性类型为图标时)uint8_t* p_dev_name;             // 设备名称指针(当属性类型为设备名称时)uint8_t addr_resolution;         // 地址解析标志(当属性类型为地址解析时)
} tGAP_BLE_ATTR_VALUE;// GAP 属性描述结构体
typedef struct {uint16_t handle;                // GATT属性句柄(唯一标识GATT数据库中的属性)uint16_t uuid;                  // 属性UUID(标识属性类型,如设备名称、图标)tGAP_BLE_ATTR_VALUE attr_value; // 属性值(根据UUID类型选择对应存储方式)
} tGAP_ATTR;constexpr int GAP_MAX_CHAR_NUM = 4;  // GAP服务最多包含4个特征(属性)
/* LE GAP attribute database */
std::array<tGAP_ATTR, GAP_MAX_CHAR_NUM> gatt_attr;  // 存储所有GAP属性的数组
tGATT_IF gatt_if;  // GATT接口标识符(用于关联GATT服务器实例)/********************************************************************************* Function         btm_ble_att_db_init** Description      GAP ATT database initalization.** Returns          void.*******************************************************************************/
void gap_attr_db_init(void) { // 1. 创建并注册 GATT 服务/* Fill our internal UUID with a fixed pattern 0x82 */std::array<uint8_t, Uuid::kNumBytes128> tmp; // 创建固定模式的128位UUID(用于应用标识)tmp.fill(0x82);Uuid app_uuid = Uuid::From128BitBE(tmp);gatt_attr.fill({});// 注册GATT服务,获取接口句柄gatt_ifgatt_if = GATT_Register(app_uuid, "Gap", &gap_cback, false);GATT_StartIf(gatt_if); // 启动GATT接口// 2. 定义 GAP 服务的 GATT 数据库元素Uuid svc_uuid = Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER); // GAP服务UUID(标准16位)Uuid name_uuid = Uuid::From16Bit(GATT_UUID_GAP_DEVICE_NAME); // 设备名称特征UUIDUuid icon_uuid = Uuid::From16Bit(GATT_UUID_GAP_ICON); // 设备图标特征UUIDUuid addr_res_uuid = Uuid::From16Bit(GATT_UUID_GAP_CENTRAL_ADDR_RESOL); // 地址解析特征UUID// 定义GATT数据库元素(服务+特征)btgatt_db_element_t service[] = {{ /* 主服务 */.uuid = svc_uuid,.type = BTGATT_DB_PRIMARY_SERVICE,},{ /* 设备名称特征 */.uuid = name_uuid,.type = BTGATT_DB_CHARACTERISTIC,.properties = GATT_CHAR_PROP_BIT_READ, // 可读属性.permissions = GATT_PERM_READ_IF_ENCRYPTED_OR_DISCOVERABLE}, // 加密或可发现时可读{  /* 设备图标特征 */.uuid = icon_uuid,.type = BTGATT_DB_CHARACTERISTIC,.properties = GATT_CHAR_PROP_BIT_READ,.permissions = GATT_PERM_READ // 无条件可读}, { /* 中心地址解析特征 */.uuid = addr_res_uuid,.type = BTGATT_DB_CHARACTERISTIC,.properties = GATT_CHAR_PROP_BIT_READ,.permissions = GATT_PERM_READ}
#if (BTM_PERIPHERAL_ENABLED == TRUE) /* Only needed for peripheral testing */,{ /* 首选连接参数特征(仅外设需要) */.uuid = Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM),.type = BTGATT_DB_CHARACTERISTIC,.properties = GATT_CHAR_PROP_BIT_READ,.permissions = GATT_PERM_READ}
#endif};// 3. 向 GATT 服务器添加服务// 将定义好的服务和特征添加到 GATT 服务器的数据库中,使其他设备(如手机)可以通过 GATT 协议发现并访问这些属性/* Add a GAP service */GATTS_AddService(gatt_if, service,sizeof(service) / sizeof(btgatt_db_element_t));// 4. 初始化本地属性缓存(gatt_attr)// 设备名称属性gatt_attr[0].uuid = GATT_UUID_GAP_DEVICE_NAME;gatt_attr[0].handle = service[1].attribute_handle; // 特征句柄(由GATT服务器分配)// 设备图标属性gatt_attr[1].uuid = GATT_UUID_GAP_ICON;gatt_attr[1].handle = service[2].attribute_handle;// 地址解析属性(初始值设为0)gatt_attr[2].uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;gatt_attr[2].handle = service[3].attribute_handle;gatt_attr[2].attr_value.addr_resolution = 0;#if (BTM_PERIPHERAL_ENABLED == TRUE) /*  Only needed for peripheral testing */// 外设模式初始化连接参数gatt_attr[3].uuid = GATT_UUID_GAP_PREF_CONN_PARAM;// 默认最大间隔(6*1.25ms=7.5ms)gatt_attr[3].attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */// 默认最小间隔(0*1.25ms=0ms,实际需≥6)gatt_attr[3].attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */gatt_attr[3].attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */// 默认监督超时(2000*10ms=20s)gatt_attr[3].attr_value.conn_param.sp_tout =GAP_PREFER_CONN_SP_TOUT; /* 2000 */gatt_attr[3].handle = service[4].attribute_handle;
#endif
}

完成GAP GATT 属性数据库的初始化,用于向外暴露 BLE 设备的基础属性(如设备名称、图标、地址解析状态等)。这些属性是 BLE 设备发现、配对和连接的基础,其他设备(如手机)通过读取这些属性可获取设备的基本信息和能力,从而完成后续交互(如连接参数协商)。

  • 主服务(BTGATT_DB_PRIMARY_SERVICE:声明这是一个主 GAP 服务,UUID 为标准的UUID_SERVCLASS_GAP_SERVER(0x1800)。

  • 特征(BTGATT_DB_CHARACTERISTIC:每个特征对应一个具体属性:

    • 设备名称(GATT_UUID_GAP_DEVICE_NAME,0x2A00):存储设备的友好名称(如 “我的蓝牙耳机”);

    • 设备图标(GATT_UUID_GAP_ICON,0x2A01):标识设备类型的图标(如耳机图标对应的数值);

    • 中心地址解析(GATT_UUID_GAP_CENTRAL_ADDR_RESOL,0x2AA6):指示是否支持地址解析(隐私功能相关);

    • 首选连接参数(GATT_UUID_GAP_PREF_CONN_PARAM,0x2A04):仅在外设模式启用,存储设备希望的连接参数(如int_min/int_max)。

将 GATT 服务器分配的特征句柄(attribute_handle)与本地gatt_attr数组绑定,后续上层可通过gatt_attr快速访问或修改属性值(如更新设备名称)。

GATT_Register、GATT_StartI f和 GATTS_AddService分析见【Bluedroid】蓝牙启动之gatt_init 流程源码解析

三、GAP 模块初始化流程图

四、GAP 模块初始化时序图

五、总结

蓝牙 GAP 模块通过 “初始化流程 - 连接管理 - 属性暴露” 的协同设计,实现了对蓝牙设备发现、连接建立及基础属性交互的核心支撑:

  • 初始化流程(GAP_Init)确保模块在生命周期内仅执行一次基础配置,避免资源重复分配;

  • 连接管理(gap_conn_inittGAP_CONN/tGAP_CCB)通过状态机、队列和协议回调,实现对 L2CAP 连接的高效控制(如参数协商、流量控制);

  • 属性数据库(gap_attr_db_initgatt_attr)通过 GATT 协议向外暴露设备信息,是其他设备(如手机)发现、配对和协商连接参数的基础。

这些设计共同保障了蓝牙设备间的互操作性与通信可靠性,是蓝牙协议栈中连接层的核心基础。


相关文章:

  • Spring AOP与代理模式
  • 《单调队列》题集
  • HTTP全攻略:从入门到精通
  • 经济系统的「资源死锁」与「架构重构」:从通缩陷阱到可持续模型设计
  • 线性三角波连续调频毫米波雷达目标识别
  • 开源组件hive页面安全问题
  • 【面板数据】中国与世界各国新能源汽车进出口数据-分类别与不分类别(2017-2024年)
  • 【AI图像生成网站Golang】部署图像生成服务(阿里云ACK+GPU实例)
  • python打卡day53
  • ​​信息系统项目管理师-信息系统工程 知识点总结与例题分析​​
  • MultiTalk 是一种音频驱动的多人对话视频生成模型
  • 设计模式(二)
  • 上传IPA到App Store的步骤
  • Java线程异常处理与多线程编程实践
  • 当Python遇上多线程:ThreadPoolExecutor的实用指南
  • stl学习
  • 迁移学习基础
  • unity学习摘要
  • 利用pycharm搭建模型步骤
  • DIPLOMAT开源程序是基于深度学习的身份保留标记对象多动物跟踪(测试版)
  • 邢台做网站优化哪儿好/广州百度推广客服电话
  • 南京江宁网站制作/百度一下你知道
  • 网易短链接生成/优化seo招聘
  • 建设b2b2c网站/德州seo优化
  • 网站建设总流程/客户引流的最快方法是什么
  • 高端的网站建设公司/搜索引擎优化seo的英文全称是