杰理 SDK 文档中心
首页
首页
  • 项目概览

    • 项目概述与能力地图
    • 构建系统与编译流程
    • 芯片系列与规格
  • 应用示例

    • SPP 与 BLE 双模透传
    • AT 指令串口协议
    • HID 设备应用
    • 蓝牙 Mesh 应用
    • 公共组件与第三方协议
  • 芯片平台支持

    • 外设驱动
    • 电源与充电管理
    • 启动与链接脚本
    • 配置工具与 OTA 资源
  • 协议栈与系统库

    • 蓝牙控制器
    • BTStack 协议栈接口
    • 系统内核与服务
    • OTA 升级机制
  • 文档与参考

    • 蓝牙 AT 协议参考
    • 开发文档与认证信息

BTStack 协议栈接口

本页介绍杰理 AC630N 蓝牙 SDK 中 BTStack 协议栈对外暴露的接口层:从 HCI 数据包/事件定义、协议栈任务生命周期、模块裁剪配置,到低功耗蓝牙(BLE)的 GAP/ATT/GATT/SM 接口与经典蓝牙 AVRCP 用户接口,说明各接口的职责、控制流与使用方式。

Purpose and Scope

BTStack 协议栈接口(include_lib/btstack/ 目录)是 AC630N 芯片蓝牙协议栈与上层应用之间的唯一契约层。应用代码不直接接触控制器寄存器或链路层细节,而是通过本页所述的接口完成:

  • 协议栈的启动与退出(btstack_init / btstack_exit);
  • 协议栈功能模块的编译期/运行期裁剪(Classic、LE Advertising、LE 三类模块);
  • HCI 数据包与事件的定义和解析(广播、连接、配对等事件);
  • BLE 服务端(ATT Server / GATT)与客户端(GATT Client)的数据收发;
  • 安全管理(SM)的配对认证配置;
  • 经典蓝牙 AVRCP 用户接口。

本页不覆盖:具体 Profile(如 A2DP/AVRCP 的具体业务逻辑)的内部实现、音频编解码链路、以及芯片底层 HCI 传输(UART/SPI 驱动)。这些内容属于各自的 Profile 与驱动页面。

概述

背景与设计意图

在 AC630N 的软件架构中,蓝牙协议栈被封装为独立的库(btstack_lib.ld 链接脚本描述了库的内存布局),对外仅暴露头文件接口。这种"库 + 头文件契约"的设计有两点意图:

  1. 隔离性:上层应用与协议栈实现解耦,协议栈升级(如修复 HCI 事件解析 bug)时应用代码无需改动;
  2. 资源可控:通过 bt_profile_config.h 中的模块位掩码,可裁剪掉不需要的协议栈模块,节省 RAM/Flash——这对 RAM 受限的嵌入式蓝牙 SoC 至关重要。

头文件地图

头文件职责
bluetooth.hHCI 数据包类型、OGF 命令分组、HCI 事件码定义
btstack_task.h协议栈任务生命周期:btstack_init() / btstack_exit()
bt_profile_config.h协议栈模块裁剪(Classic / LE Adv / LE)与内存池长度查询
le_user.hBLE 用户侧接口:回调类型、事件码、ATT/GATT/SM/GAP API
ble_api.h底层 BLE API(被 le_user.h 包含)
avctp_user.h经典蓝牙 AVRCP 用户接口
ble_data_types.hBLE 数据类型定义
btstack_lib.ld协议栈库的链接脚本

关键概念

  • HCI 数据包类型:控制器与主机之间通过 4 种数据包通信——命令(0x01)、ACL 数据(0x02)、SCO 数据(0x03)、事件(0x04),定义见 bluetooth.h。
  • 回调驱动:BLE 接口以 btstack_packet_handler_t 回调为核心,事件异步到达,应用在回调中按 packet_type 分派处理。
  • ATT 事务模式:ATT 写入支持 NONE / ACTIVE / EXECUTE / CANCEL / VALIDATE 五种事务模式,用于长属性(Long Attribute)的分段写入。

架构

下图展示了 BTStack 协议栈接口层在 AC630N 固件中的位置与依赖关系:

flowchart TD
    subgraph sg_App["应用层 (App)"]
        App["上层应用 / Profile 业务"]
    end

    subgraph sg_Interface["接口层 include_lib/btstack"]
        TaskAPI["btstack_task.h<br/>btstack_init / btstack_exit"]
        LEUser["le_user.h<br/>GAP / ATT / GATT / SM 接口"]
        BLEAPI["ble_api.h<br/>底层 BLE API"]
        AVRCP["avctp_user.h<br/>AVRCP 用户接口"]
        Config["bt_profile_config.h<br/>模块裁剪 / 内存池"]
        HCI["bluetooth.h<br/>HCI 数据包与事件定义"]
    end

    subgraph sg_Stack["协议栈实现 (btstack_lib.ld)"]
        StackLib["BTStack 库"]
    end

    subgraph sg_HW["硬件层"]
        Controller["蓝牙控制器 / 射频"]
    end

    App --> TaskAPI
    App --> LEUser
    App --> AVRCP
    LEUser --> BLEAPI
    LEUser --> HCI
    TaskAPI --> StackLib
    LEUser --> StackLib
    AVRCP --> StackLib
    Config --> StackLib
    StackLib --> Controller

架构要点:

  • le_user.h 是 BLE 侧最主要的"门面"(Facade):它统一定义了回调函数类型(btstack_packet_handler_t、sm_stack_packet_handler_t)、事件码(BTSTACK_EVENT_STATE、GATT_EVENT_*、SM_EVENT_* 等)、以及服务端/客户端的操作表(ble_server_operation_t / ble_client_operation_t)。
  • bluetooth.h 提供的是纯常量契约:HCI 事件码与参数格式注释(如 @format 1B11132)用于解析控制器上报的事件,上层通过 le_user.h 中内联的解析函数(如 hci_event_le_meta_get_subevent_code())读取事件字段。
  • bt_profile_config.h 用 config_stack_modules 位掩码控制协议栈裁剪,并通过 app_bredr_pool[]、app_le_pool[]、app_l2cap_pool[]、app_bredr_profile[] 等外部数组描述各模块的内存池,get_*_len() 函数返回池长度供应用查询。

协议栈分层详解

HCI 数据包与事件层(bluetooth.h)

bluetooth.h 是协议栈最底层的契约头文件,定义了主机-控制器接口(HCI)的数据包类型与事件码。这些定义在整个协议栈中作为"公共语言"被上层接口引用。

数据包类型(bluetooth.h):

#define HCI_COMMAND_DATA_PACKET				0x01
#define HCI_ACL_DATA_PACKET	    			0x02
#define HCI_SCO_DATA_PACKET	    			0x03
#define HCI_EVENT_PACKET	    			0x04

Source: bluetooth.h

OGF 命令分组:链路控制(0x01)、链路策略(0x02)、控制器基带(0x03)、信息参数(0x04)、状态参数(0x05)、测试(0x06)、LE 控制器(0x08)、厂商 LE(0x3E)、厂商(0x3F)。其中 OGF_VENDOR 与 OGF_VENDOR_LE_CONTROLLER 为杰理芯片扩展命令保留了空间,这是芯片厂商在标准 HCI 之上扩展私有命令的惯例做法。

事件码设计意图:每个事件码都配有 @format 注释描述参数布局(如 HCI_EVENT_CONNECTION_COMPLETE 为 12B11——1 字节 status、2 字节 connection_handle、6 字节 bd_addr、1 字节 link_type、1 字节 encryption_enabled)。这种"格式字符串"式注释是 BTStack 上游的经典风格,SDK 头文件保留了它,便于上层解析器与上游实现保持同步。关键事件包括:

事件码用途
HCI_EVENT_CONNECTION_COMPLETE0x03经典蓝牙连接建立完成
HCI_EVENT_DISCONNECTION_COMPLETE0x05连接断开
HCI_EVENT_COMMAND_COMPLETE0x0EHCI 命令完成(带返回参数)
HCI_EVENT_COMMAND_STATUS0x0FHCI 命令状态
HCI_EVENT_INQUIRY_RESULT_WITH_RSSI0x22带 RSSI 的经典查询结果
HCI_EVENT_EXTENDED_INQUIRY_RESULT0x2F扩展查询结果(含 EIR 数据)
HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE0x2CSCO/eSCO 同步连接完成

协议栈任务生命周期(btstack_task.h)

btstack_task.h 只暴露两个函数,构成协议栈的完整生命周期:

int btstack_init();
int btstack_exit();

Source: btstack_task.h

  • btstack_init():初始化协议栈。应用通常在系统启动早期(如主循环或系统任务创建阶段)调用一次,内部会完成 HCI 层、L2CAP、GATT 等子系统的初始化,并根据 config_stack_modules 裁剪加载模块。
  • btstack_exit():反初始化协议栈,释放资源,进入可重新初始化的状态。典型使用场景是系统级省电或协议栈复位。

接口如此精简的原因:协议栈作为一个整体运行在自己的任务/中断上下文中,应用侧只需要"启动/停止"两个钩子,其余交互全部通过回调与事件完成。

模块裁剪与内存池(bt_profile_config.h)

嵌入式蓝牙 SoC 的 RAM 极为有限,因此协议栈支持按需裁剪。bt_profile_config.h 用三个位定义模块类型:

#define BT_BTSTACK_CLASSIC                   BIT(0)
#define BT_BTSTACK_LE_ADV                    BIT(1)
#define BT_BTSTACK_LE                        BIT(2)

extern const int config_stack_modules;
#define STACK_MODULES_IS_SUPPORT(x)         (config_stack_modules & (x))

Source: bt_profile_config.h

  • BT_BTSTACK_CLASSIC:经典蓝牙(BR/EDR),支撑 A2DP/AVRCP 等传统 Profile;
  • BT_BTSTACK_LE_ADV:仅 BLE 广播(Beacon 类应用,无需连接);
  • BT_BTSTACK_LE:完整 BLE(GATT 客户端/服务端)。

STACK_MODULES_IS_SUPPORT(x) 宏用于运行时判断某个模块是否被编译进固件,应用代码据此决定是否调用对应 Profile 的初始化流程。这一设计让同一份应用源码可以适配不同配置的固件(例如"仅 Beacon"与"全功能"两个固件变体)。

内存池方面,头文件声明了四个外部数组及其长度查询函数:

数组长度查询函数用途
app_bredr_pool[]get_bredr_pool_len()经典蓝牙协议栈堆
app_le_pool[]get_le_pool_len()BLE 协议栈堆
app_l2cap_pool[]get_l2cap_stack_len()L2CAP 层堆
app_bredr_profile[]get_profile_pool_len()经典 Profile(AVRCP 等)堆

这些池的实际大小由链接脚本(btstack_lib.ld)与编译配置决定,应用可通过 get_*_len() 查询实际可用长度,用于内存统计与调试。

BLE 用户接口(le_user.h)

le_user.h 是 BLE 功能的核心接口文件,按职责可分为五组:

1. 回调与事件契约

typedef void (*btstack_packet_handler_t)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
typedef int (*sm_stack_packet_handler_t)(uint8_t packet_type, uint8_t *packet, uint16_t size);
typedef void (*ble_cbk_handler_t)(void);

Source: le_user.h

btstack_packet_handler_t 是协议栈向应用分发事件的统一回调:packet_type 区分 HCI 事件/GATT 事件/SM 事件,channel 携带连接句柄(con_handle),packet/size 指向事件负载。所有 BLE 异步结果(MTU 交换、通知、GATT 查询结果、SM 配对请求)都通过这类回调到达应用,这是 BTStack 事件驱动模型的核心。

2. 状态机与枚举

  • HCI 状态枚举:HCI_STATE_OFF / INITIALIZING / WORKING / HALTING / SLEEPING / FALLING_ASLEEP,BTSTACK_EVENT_STATE(0x60)事件上报状态迁移,应用据此感知协议栈可用性(例如 WORKING 后才能开启广播)。
  • IO 能力枚举 io_capability_t:IO_CAPABILITY_DISPLAY_ONLY / DISPLAY_YES_NO / KEYBOARD_ONLY / NO_INPUT_NO_OUTPUT / KEYBOARD_DISPLAY,用于 SM 配对时选择认证方式(Just Works / Passkey / 数字比较)。

3. 服务端(Peripheral)操作表

struct ble_server_operation_t {
    int(*adv_enable)(void *priv, u32 enable);
    int(*disconnect)(void *priv);
    int(*get_buffer_vaild)(void *priv);
    int(*send_data)(void *priv, void *buf, u16 len);
    int(*regist_wakeup_send)(void *priv, void *cbk);
    int(*regist_recieve_cbk)(void *priv, void *cbk);
    int(*regist_state_cbk)(void *priv, void *cbk);
    int(*latency_enable)(void *priv, u32 enable);
};
void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt);

Source: le_user.h

ble_get_server_operation_table() 返回服务端操作表,这是 SDK 对上层隐藏具体协议栈实现、以"操作函数指针表"形式提供接口的典型模式(类似内核的 file_operations 表)。latency_enable 支持低功耗连接参数(减少监听窗口),是 BLE 低功耗优化的关键钩子。

4. 客户端(Central)操作表

struct ble_client_operation_t {
    int(*scan_enable)(void *priv, u32 enable);
    int(*disconnect)(void *priv);
    int(*get_buffer_vaild)(void *priv);
    int(*write_data)(void *priv, void *buf, u16 len);
    int(*read_do)(void *priv);
    int(*regist_wakeup_send)(void *priv, void *cbk);
    int(*regist_recieve_cbk)(void *priv, void *cbk);
    int(*regist_state_cbk)(void *priv, void *cbk);
};
void ble_get_client_operation_table(struct ble_client_operation_t **interface_pt);

Source: le_user.h

与服务端对称,客户端操作表提供扫描、断开、写数据、读数据等原语,应用通过统一接口驱动 GATT 客户端流程,不感知底层是标准 BTStack 还是厂商优化实现。

5. ATT/GATT/SM 关键 API

  • ATT 服务端:ble_att_server_setup_init(const u8 *profile_db, att_read_callback_t read_cbk, att_write_callback_t write_cbk) 注册属性数据库与读写回调;att_server_notify() / att_server_indicate() 发送通知/指示。
  • GATT 客户端:gatt_client_read_value_of_characteristic_using_value_handle()、gatt_client_write_value_of_characteristic() 等读写特征值,结果同样经回调异步返回。
  • SM:ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) 配置配对参数;SM_EVENT_JUST_WORKS_REQUEST(0xD0)、SM_EVENT_PASSKEY_DISPLAY_NUMBER(0xD2)事件驱动配对交互。
  • GAP:gap_advertisements_enable()、gap_advertisements_set_data()、gap_scan_response_set_data()、gap_advertisements_set_params() 控制广播;gap_request_connection_parameter_update() 请求更新连接参数。
  • 动态数据读写回调:att_read_callback_t 支持"buffer 为 NULL 时只返回长度"的两阶段读取协议,避免大属性值(如 512 字节长特征)拷贝浪费;att_write_callback_t 通过 transaction_mode 参数支持 ATT 准备写(Prepared Write)与执行写(Execute Write)事务。

核心流程

BLE 服务端事件分发流程

BLE 外设(Peripheral)的数据通路以"回调注册 → 事件分派"为主线。下图为从控制器事件到应用回调的完整链路:

sequenceDiagram
    participant HC as HCI 控制器
    participant ST as BTStack 库
    participant APP as 应用 (le_user.h 接口)
    participant CBK as 回调 handler

    APP->>ST: ble_att_server_setup_init(profile_db, read_cbk, write_cbk)
    APP->>ST: ble_cbk_handler_register(packet_cbk, sm_cbk)
    APP->>ST: gap_advertisements_set_data(...)
    APP->>ST: gap_advertisements_enable(1)
    ST->>HC: HCI LE Set Advertising Enable
    HC-->>ST: HCI_EVENT_COMMAND_COMPLETE
    ST-->>APP: BTSTACK_EVENT_STATE (WORKING)
    HC-->>ST: HCI_EVENT_LE_META (Connection Complete)
    ST-->>CBK: btstack_packet_handler_t(packet_type=HCI_EVENT_PACKET)
    APP->>ST: att_server_notify(con_handle, attr_handle, value, len)
    ST->>HC: ATT Handle Value Notification

流程要点:

  1. 应用先注册 ATT 属性数据库(profile_db)与读写回调,再注册全局事件回调(ble_cbk_handler_register);
  2. 开启广播后,协议栈收到 HCI_EVENT_COMMAND_COMPLETE,随后状态迁移到 WORKING;
  3. 对端连接建立时,控制器上报 LE Meta 事件,协议栈解析连接句柄后分派给应用回调;
  4. 应用通过 att_server_notify() / att_server_indicate() 主动推送数据,写操作则由协议栈调用 att_write_callback_t 回调应用。

协议栈状态机

HCI 状态枚举构成了协议栈生命周期状态机:

stateDiagram-v2
    [*] --> OFF
    OFF --> INITIALIZING: btstack_init()
    INITIALIZING --> WORKING: 初始化完成
    WORKING --> HALTING: btstack_exit() / 错误
    HALTING --> OFF: 资源释放
    WORKING --> SLEEPING: 低功耗请求
    SLEEPING --> FALLING_ASLEEP: 睡眠握手
    FALLING_ASLEEP --> SLEEPING: 唤醒失败
    FALLING_ASLEEP --> OFF: 深度睡眠
    SLEEPING --> WORKING: 唤醒

应用通过 BTSTACK_EVENT_STATE 事件观察状态迁移;只有 WORKING 状态下才允许执行广播、扫描、连接等 GAP 操作,这避免了在协议栈未就绪时下发命令导致的竞态。

使用示例

示例 1:注册 BLE 事件回调与状态监听

应用通过 ble_cbk_handler_register 注册两类回调:全局协议栈事件回调与 SM 安全事件回调:

void ble_cbk_handler_register(btstack_packet_handler_t packet_cbk, sm_stack_packet_handler_t sm_cbk);

Source: le_user.h

在回调中,应用先用 hci_event_packet_get_type(event) 与 hci_event_le_meta_get_subevent_code(event) 两个内联解析函数判断事件类型,再按需读取字段:

static inline uint8_t hci_event_packet_get_type(const uint8_t *event)
{
    return event[0];
}

static inline uint8_t hci_event_le_meta_get_subevent_code(const uint8_t *event)
{
    return event[2];
}

Source: le_user.h

这两个内联函数避免了重复的字节偏移计算:event[0] 是包类型字节,event[2] 在 LE Meta 事件中保存子事件码(如连接完成 0x01、连接更新完成 0x03)。

示例 2:配置并启动广播

设置广播数据与参数,然后使能广播。参数接口与标准 BTStack GAP API 对齐:

extern void gap_advertisements_enable(int enabled);
extern void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t *advertising_data);
extern void gap_scan_response_set_data(uint8_t scan_response_data_length, uint8_t *scan_response_data);
extern void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
        uint8_t direct_address_typ, uint8_t *direct_address, uint8_t channel_map, uint8_t filter_policy);

Source: le_user.h

示例 3:服务端数据推送与客户端特征读写

服务端使用 att_server_notify 推送通知;客户端使用 gatt_client_* 系列发起读/写:

extern int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t *value, uint16_t value_len);
extern uint8_t gatt_client_read_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle);
extern uint8_t gatt_client_write_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t *data);

Source: le_user.h

注意 GATT 客户端的读/写结果不是同步返回的,而是通过调用时传入的 callback 以 GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT(0xA5)、GATT_EVENT_NOTIFICATION(0xA7)、GATT_EVENT_INDICATION(0xA8)等事件异步送达。

示例 4:SM 配对配置

ble_sm_setup_init 一次性配置安全管理的认证参数,sm_just_event_t 结构体描述配对请求中的对端信息:

extern void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en);

typedef struct {
    //base info
    uint8_t   type;                 ///< See <btstack/hci_cmds.h> SM_...
    uint8_t   size;
    hci_con_handle_t con_handle;
    uint8_t   addr_type;
    uint8_t   address[6];
    //extend info
    uint8_t   data[4];
} sm_just_event_t;

Sources: le_user.h 与 le_user.h

auth_req 可取 SM_AUTHREQ_BONDING(0x01,支持绑定)、SM_AUTHREQ_MITM_PROTECTION(0x04,防中间人)、SM_AUTHREQ_SECURE_CONNECTION(0x08,LE Secure Connections)。min_key_size 设定最小密钥长度,security_en 开关安全功能;io_type 选择 Just Works(NO_INPUT_NO_OUTPUT)或 Passkey(DISPLAY_YES_NO)等认证方式,最终通过 SM_EVENT_JUST_WORKS_REQUEST / SM_EVENT_PASSKEY_DISPLAY_NUMBER 事件与用户交互。

配置选项

协议栈模块裁剪

选项类型默认值说明
config_stack_modulesconst int由固件编译配置决定模块位掩码,BIT(0) Classic、BIT(1) LE Adv、BIT(2) LE
BT_BTSTACK_CLASSIC宏 (BIT(0))取决于固件启用经典蓝牙 BR/EDR
BT_BTSTACK_LE_ADV宏 (BIT(1))取决于固件仅启用 BLE 广播(Beacon)
BT_BTSTACK_LE宏 (BIT(2))取决于固件启用完整 BLE(连接 + GATT)
STACK_MODULES_IS_SUPPORT(x)宏—运行时判断模块是否被支持

内存池

选项类型说明
app_bredr_pool[] / get_bredr_pool_len()u8 数组 / u16经典蓝牙协议栈堆
app_le_pool[] / get_le_pool_len()u8 数组 / u16BLE 协议栈堆
app_l2cap_pool[] / get_l2cap_stack_len()u8 数组 / u16L2CAP 层堆
app_bredr_profile[] / get_profile_pool_len()u8 数组 / u16经典 Profile 堆

BLE 行为常量

选项值说明
ATT_DEFAULT_MTU23默认 ATT MTU(BLE 4.x 最小 MTU)
BT_NAME_LEN_MAX29本地名称最大长度
ADV_RSP_PACKET_MAX31广播/扫描响应数据最大字节数
HCI_CON_HANDLE_INVALID0xffff无效连接句柄哨兵值

SM 认证选项(ble_sm_setup_init 参数)

参数类型取值/默认说明
io_typeio_capability_t无默认IO 能力:DISPLAY_ONLY、DISPLAY_YES_NO、KEYBOARD_ONLY、NO_INPUT_NO_OUTPUT
auth_requ8无默认SM_AUTHREQ_NO_BONDING(0x00)、BONDING(0x01)、MITM_PROTECTION(0x04)、SECURE_CONNECTION(0x08)、KEYPRESS(0x10),可位或组合
min_key_sizeuint8_t无默认最小密钥长度(字节)
security_enu8无默认是否启用安全配对

API 参考

生命周期

函数签名说明
btstack_initint btstack_init()初始化协议栈,返回 0 表示成功
btstack_exitint btstack_exit()反初始化协议栈,释放资源

GAP(广播与连接参数)

函数签名说明
gap_advertisements_enablevoid (int enabled)使能/关闭广播
gap_advertisements_set_datavoid (uint8_t len, uint8_t *data)设置广播数据(≤31 字节)
gap_scan_response_set_datavoid (uint8_t len, uint8_t *data)设置扫描响应数据
gap_advertisements_set_paramsvoid (adv_int_min, adv_int_max, adv_type, direct_addr_typ, direct_addr, channel_map, filter_policy)设置广播参数(间隔、类型、信道、过滤策略)
gap_request_connection_parameter_updateint (con_handle, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout)请求更新连接参数

ATT/GATT 服务端

函数签名说明
ble_att_server_setup_initvoid (const u8 *profile_db, att_read_callback_t read_cbk, att_write_callback_t write_cbk)注册属性数据库与动态读写回调
att_server_notifyint (con_handle, attribute_handle, value, value_len)发送通知(无需对端确认)
att_server_indicateint (con_handle, attribute_handle, value, value_len)发送指示(需要对端确认)
att_server_request_can_send_now_eventvoid (con_handle)请求"可以发送"事件(流控)

GATT 客户端

函数签名说明
gatt_client_read_value_of_characteristic_using_value_handleuint8_t (callback, con_handle, value_handle)读特征值,结果异步回调
gatt_client_read_long_value_of_characteristic_using_value_handle_with_offsetuint8_t (callback, con_handle, value_handle, offset)从偏移读长特征值
gatt_client_write_value_of_characteristicuint8_t (callback, con_handle, value_handle, value_length, data)写特征值,带确认
gatt_client_write_value_of_characteristic_without_responseuint8_t (con_handle, value_handle, value_length, value)无响应写(Write Command)
gatt_client_request_can_send_now_eventvoid (con_handle)请求客户端发送窗口

SM 安全

函数签名说明
ble_sm_setup_initvoid (io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en)配置 SM 配对参数

回调类型

类型签名说明
btstack_packet_handler_tvoid (*)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)全局协议栈事件回调
sm_stack_packet_handler_tint (*)(uint8_t packet_type, uint8_t *packet, uint16_t size)SM 安全事件回调
att_read_callback_tuint16_t (*)(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)ATT 动态读回调(buffer 为 NULL 时返回长度)
att_write_callback_tint (*)(uint16_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)ATT 动态写回调,返回 0 表示成功

关键事件码

事件值说明
BTSTACK_EVENT_STATE0x60协议栈状态迁移
GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT0xA5GATT 读结果
GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT0xA6长特征读结果
GATT_EVENT_NOTIFICATION0xA7收到通知
GATT_EVENT_INDICATION0xA8收到指示
ATT_EVENT_MTU_EXCHANGE_COMPLETE0xB5MTU 交换完成
ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE0xB6指示确认完成
ATT_EVENT_CAN_SEND_NOW0xB7允许发送通知/指示
SM_EVENT_JUST_WORKS_REQUEST0xD0请求 Just Works 确认
SM_EVENT_PASSKEY_DISPLAY_NUMBER0xD2显示 Passkey
GAP_EVENT_ADVERTISING_REPORT0xE2扫描到广播包
L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE0x77连接参数更新响应

失败模式、边界情况与并发

状态机竞态

协议栈未进入 HCI_STATE_WORKING 时,广播、扫描、连接等 GAP 命令会被协议栈拒绝或静默丢弃。应用必须在收到 BTSTACK_EVENT_STATE 且状态为 WORKING 之后再下发命令。这一约束是事件驱动架构的必然结果——协议栈命令是异步的,不能假设"调用即生效"。HCI_STATE_SLEEPING / FALLING_ASLEEP 状态下,发送数据会触发 regist_wakeup_send 注册的唤醒回调,应用需配合低功耗调度。

连接句柄无效

HCI_CON_HANDLE_INVALID(0xffff)是无效句柄哨兵值。当连接已断开(HCI_EVENT_DISCONNECTION_COMPLETE 之后),应用仍持有旧句柄调用 att_server_notify() / gatt_client_*() 时,应主动用该哨兵值校验句柄合法性,避免对已释放的连接执行 ATT 操作。协议栈内部对无效句柄的响应未在本头文件契约中保证,因此上层必须自行管理句柄生命周期。

缓冲区不足与流控

  • get_buffer_vaild(服务端/客户端操作表成员):发送数据前应先查询发送缓冲是否可用,返回非 0 表示可发送;否则数据应排队等待 ATT_EVENT_CAN_SEND_NOW(0xB7)事件(由 att_server_request_can_send_now_event() / gatt_client_request_can_send_now_event() 触发)。这是避免 ATT 层丢包的关键机制。
  • att_write_callback_t 返回值契约:返回 0 表示写入成功;ATT_ERROR_PREPARE_QUEUE_FULL 表示准备写队列已满;ATT_ERROR_INVALID_OFFSET 表示偏移越界。应用在实现该回调时必须正确处理这两个错误码,否则长属性分段写入会失败。

广播数据超限

ADV_RSP_PACKET_MAX(31 字节)是 BLE 广播/扫描响应数据硬上限。gap_advertisements_set_data() 传入超过 31 字节的数据会被截断或导致广播失败(具体行为由协议栈实现决定),SDK 未在接口层做长度校验,因此应用在构造广播载荷时必须以 BT_NAME_LEN_MAX(29,含长度/类型头)与 31 字节为约束进行静态规划。

并发模型

接口层为单线程 + 中断回调模型:协议栈事件回调(btstack_packet_handler_t)运行在协议栈任务/中断上下文,应用主循环运行在应用上下文。二者共享的数据(如发送缓冲、连接状态标志)必须通过临界区保护或仅在回调内修改,避免数据竞争。regist_wakeup_send 回调用于从低功耗唤醒路径触发发送,同样需要注意上下文切换开销。

MTU 协商

默认 ATT_DEFAULT_MTU 为 23(3 字节 ATT 头 + 20 字节有效载荷)。若应用需要更大传输单元,须在连接建立后发起 MTU 交换,并通过 ATT_EVENT_MTU_EXCHANGE_COMPLETE(0xB5)事件读取协商结果——解析函数 att_event_mtu_exchange_complete_get_MTU(event) 返回 little_endian_read_16(event, 4)。在 MTU 协商完成前按 23 字节 MTU 分片发送,可避免对端无法解析。

性能与运维注意事项

  • 内存池感知:通过 get_bredr_pool_len() / get_le_pool_len() 等函数可统计协议栈内存占用。若出现异常(如经典蓝牙连接频繁失败),应检查对应池是否耗尽;SDK 头文件未暴露池水位查询,运维上可借助链接脚本(btstack_lib.ld)确认池的静态分配。
  • 低功耗优化:latency_enable(服务端)与 gap_request_connection_parameter_update() 配合,可增大连接间隔与从延迟(conn_latency),显著降低待机功耗;代价是双向数据时延上升。广播间隔(adv_int_min/max)同理,需在功耗与发现时延间权衡。
  • 发送路径:send_data / write_data 均要求"先查缓冲、再发送"的顺序,违反该顺序在高吞吐场景(如数据透传)下会丢包。流控事件 ATT_EVENT_CAN_SEND_NOW 是最高效的背压信号,优于轮询。
  • 厂商扩展命令空间:OGF_VENDOR(0x3F)与 OGF_VENDOR_LE_CONTROLLER(0x3E)为杰理私有 HCI 命令保留,芯片级调试(如 RF 测试、功率控制)经由这些命令下发,与标准命令共存于同一 HCI 通道。

扩展点

  1. 动态 ATT 属性:att_read_callback_t / att_write_callback_t 允许属性值不静态存储于 profile_db,而是每次读写时动态生成/消费(如传感器读数、流式数据)。两阶段读(buffer == NULL 返回长度)机制支持超大属性,是实现"动态 GATT 服务"的标准扩展路径。
  2. 操作表注入:ble_get_server_operation_table() / ble_get_client_operation_table() 返回的 ble_server_operation_t / ble_client_operation_t 函数指针表是 SDK 的注入点——替换该表即可用自定义协议栈实现(如厂商私有 BLE)替换标准 BTStack,而上层应用代码无需改动。这是"接口与实现分离"的最直接体现。
  3. 事件回调注册:ble_cbk_handler_register() 允许应用同时挂接协议栈事件与 SM 安全事件两条回调链,可在此基础上扩展安全 UI(Passkey 显示、Just Works 确认弹窗)。
  4. 唤醒钩子:regist_wakeup_send 回调为低功耗发送路径预留,可接入 RTOS 信号量/事件组,实现"睡眠中被唤醒后立即补发数据"。

测试与使用模式启示

SDK 未在 include_lib/btstack 目录内提供单元测试源码(该目录为纯头文件契约层)。但接口设计本身揭示了推荐的测试策略:

  • 回调契约测试:针对 att_read_callback_t 的两阶段读(NULL buffer 返回长度)与 att_write_callback_t 的错误码返回进行桩测试,这是最容易出错的边界;
  • 状态机测试:验证应用在 BTSTACK_EVENT_STATE 非 WORKING 时不下发 GAP 命令,以及断线后句柄置为 HCI_CON_HANDLE_INVALID 的逻辑;
  • 流控测试:模拟发送缓冲占满 → ATT_EVENT_CAN_SEND_NOW → 补发 的完整链路,确保高吞吐下无丢失。

相关链接

  • bluetooth.h - HCI 数据包与事件定义
  • le_user.h - BLE 用户接口
  • ble_api.h - 底层 BLE API
  • ble_data_types.h - BLE 数据类型
  • bt_profile_config.h - 协议栈模块配置
  • btstack_task.h - 协议栈任务生命周期
  • avctp_user.h - AVRCP 用户接口
  • btstack_lib.ld - 协议栈库链接脚本

相关主题页:BLE 广播与连接管理、AVRCP 协议控制、协议栈内存配置等页面分别从 Profile 与系统资源角度展开,本页聚焦于接口契约本身。

Prev
蓝牙控制器
Next
系统内核与服务