杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • SDK 总览与芯片能力
    • 环境搭建与编译构建
    • 烧录与固件升级
    • 文档与版本资源
  • 应用与示例方案

    • demo 示例工程
    • WiFi 摄像头方案 (wifi_camera)
    • WiFi 音箱方案 (wifi_soundbox)
    • WiFi 婴儿监护方案 (wifi_bbm)
    • 公共应用模块库
    • 示例代码库 (example)
  • 系统架构与平台

    • 总体架构与工程分层
    • 系统启动与运行框架
    • 芯片驱动与板级适配
    • 设备管理与文件系统
    • 系统工具库与算法
  • 音频子系统

    • 音频框架与处理节点
    • 音频编解码与音效
    • 播放器与录音器
    • 语音交互与 AI 唤醒
    • LE Audio 与蓝牙音频
    • 音频调试与歌词
  • 视频与显示子系统

    • 摄像头驱动与 ISP
    • 视频编码与图像处理
    • 显示与 GPU 加速
    • 屏幕镜像 (screen_mirror)
  • 无线连接与网络

    • 蓝牙协议栈 (双模蓝牙)
    • WiFi 协议栈与配网
    • 网络协议栈
    • 云平台与 IoT 协议
  • UI 子系统

    • LVGL 集成与应用
    • UI 工程与工具链
  • 配置系统

    • 功能配置
    • 板级配置
    • 网络与蓝牙配置
    • 音频配置与提示音
  • 工具与测试

    • 产测与射频测试工具
    • 固件升级与更新机制
    • 调试与日志工具
  • 硬件参考设计

    • 原理图参考设计
    • 芯片数据手册

蓝牙协议栈 (双模蓝牙)

AC792N SDK(V3)内置的杰理双模蓝牙协议栈,基于 BTStack 架构实现经典蓝牙(BR/EDR)与低功耗蓝牙(BLE/LE)两条协议路径的统一管理,向上以事件回调的方式与用户 App 交互,向下通过 HCI 接口驱动单芯片内的控制器(Controller)。

Purpose and Scope

本文档说明 AC792N SDK 中双模蓝牙协议栈的整体架构、目录布局、HCI 层接口、事件驱动模型、双连接管理机制、Profile 支持(A2DP/AVCTP、ATT/GATT/SM、LE Audio ISO)以及连接失败错误码语义,帮助开发者在 App 模式中正确注册事件处理函数并处理连接生命周期。

本页不展开以下内容,相关能力由对应页面说明:

  • 协议栈对外暴露的常用接口函数清单 → 参见《常用蓝牙库接口函数》
  • 音频编解码细节(SBC/AAC 等)→ 参见 A2DP 音频编解码相关页面
  • LE Audio 广播(Auracast)的独立 API → 参见 Auracast Sink/Delegator 相关页面
  • 蓝牙连接管理 App(回连、提示音、低电关机等策略)→ 参见蓝牙 App 相关页面

Overview

蓝牙协议栈是 AC792N 芯片上所有蓝牙业务(音乐播放、通话、配对、回连、BLE 透传、LE Audio 等)的底层支撑。SDK 将协议栈以预编译库的形式随头文件发布,用户代码通过 sdk/include_lib/btstack/ 下的头文件与协议栈交互,编译时通过 btstack_lib.ld 系列链接脚本将协议栈库(text/data/bss 段)链接进固件。

协议栈采用事件驱动的异步模型:

  • 用户 App 注册一个事件处理函数(如 bt_connction_status_event_handler);
  • 协议栈把连接状态、HCI 事件、配对请求等以 struct bt_event 的形式投递给处理函数;
  • 处理函数根据 event 字段(协议栈状态)与 value 字段(子事件/错误码)分发到对应的业务逻辑。

双模能力体现在两条并行的协议路径上:

  • 经典路径(BR/EDR):HCI 层 → L2CAP → A2DP/AVRCP(AVCTP)等 Profile,用于音乐播放与通话;
  • 低功耗路径(LE):HCI LE 命令 → ATT/GATT/SM,用于 BLE 服务与配对;同时支持 ISO(LE Audio)通道与 Auracast 广播接收。

两条路径共享同一个 HCI 传输层与同一个事件回调入口,这使得 SDK 可以在一颗芯片上同时维护两个经典连接(BT_STATUS_FIRST_CONNECTED / BT_STATUS_SECOND_CONNECTED)以及若干 LE 链路。

Architecture

下图展示双模协议栈的分层架构与数据流向(节点名称均对应实际头文件/模块):

flowchart TD
    subgraph sg_App["应用层 (App)"]
        App["用户 App / 蓝牙 App 模式"]
        Handler["bt_connction_status_event_handler"]
    end

    subgraph sg_Stack["双模协议栈 (BTStack)"]
        HCI["HCI 层<br/>(Command/Event/ACL/SCO/ISO)"]
        L2CAP["L2CAP"]
        Classic["经典 Profile<br/>A2DP / AVRCP(AVCTP)"]
        LE["LE 协议族<br/>ATT / GATT / SM"]
        ISO["LE Audio ISO<br/>Auracast Sink/Delegator"]
    end

    subgraph sg_Controller["控制器与存储 (Controller)"]
        RF["BR/EDR + LE 射频控制器"]
        VM["VM 存储<br/>(LinkKey / 配对信息)"]
    end

    App -->|"注册回调"| Handler
    Handler -->|"bt_event 事件"| HCI
    Handler -->|"BT_STATUS_* 状态"| App
    HCI <--> L2CAP
    L2CAP <--> Classic
    L2CAP <--> LE
    LE <--> ISO
    HCI <--> RF
    Classic -->|"配对信息读写"| VM
    LE -->|"配对信息读写"| VM

架构说明:

  • HCI 层(bluetooth.h 中的包类型/OGF/事件定义):协议栈与控制器之间的统一接口,承载命令、事件、ACL、SCO、ISO 五类数据包;
  • L2CAP:经典与 LE 共用的逻辑链路复用层,向上承载各类 Profile 与 ATT;
  • 经典 Profile:a2dp_media_codec.h 提供 A2DP 媒体编解码接口,avctp_user.h 提供 AVRCP/AVCTP 控制通道接口;
  • LE 协议族:le/att.h、le/gatt.h、le/sm.h、le/ble_api.h 等头文件提供 BLE 的 Attribute、GATT 服务与安全管理(配对/加密);
  • LE Audio ISO:bluetooth.h 中定义了 ISO SDU/PDU 长度与间隔常量,配合 le/auracast_sink_api.h、le/auracast_delegator_api.h 支持 LE Audio 广播接收与转发;
  • VM 存储:配对 LinkKey、回连地址等持久化数据保存在 VM 区,协议栈事件 HCI_EVENT_VENDOR_NO_RECONN_ADDR 正是“上电回连时从 VM 读不到地址”的杰理自定义事件。

关于事件如何从 HCI 一路投递到用户 App 的完整时序,参见下文「核心流程」一节。

协议栈文件布局

协议栈头文件统一位于 sdk/include_lib/btstack/,其组织方式反映了协议栈的分层结构:

文件/目录职责
bluetooth.h总入口:聚合 LE 头文件与公共头文件,定义 HCI 包类型、OGF 命令组、HCI 事件码、ISO 常量
btstack_event.h公共事件定义(含杰理自定义事件,如 BTSTACK_EVENT_HCI_CONNECTIONS_DELETE)
btstack_typedef.h协议栈基础类型定义
btstack_task.h协议栈任务/调度接口
bt_profile_config.hProfile 配置入口(A2DP/AVRCP 等使能与参数配置)
a2dp_media_codec.hA2DP 媒体流编解码接口
avctp_user.hAVRCP/AVCTP 控制通道用户接口
le/LE 协议族:ble_data_types.h、ble_api.h、le_user.h、att.h、gatt.h、sm.h 及 auracast_sink_api.h、auracast_delegator_api.h
btstack_lib.ld / btstack_lib_text.ld / btstack_lib_data.ld / btstack_lib_bss.ld协议栈预编译库的链接脚本(代码段/数据段/BSS 段)

bluetooth.h 作为唯一总入口,通过条件式聚合把 LE 与公共模块组织在一起:

//LE
#include "le/ble_data_types.h"
#include "le/ble_api.h"
#include "le/le_user.h"
#include "le/att.h"
#include "le/gatt.h"
#include "le/sm.h"
...
//Common
#include "btstack_event.h"

Source: bluetooth.h

设计意图:bluetooth.h 采用“伞形头文件”模式,用户 App 只需包含一个头文件即可获得双模协议栈的全部接口声明,避免在业务代码中维护复杂的包含关系;同时预编译库配合独立链接脚本(btstack_lib.ld 系列)发布,SDK 只暴露接口、不暴露实现,便于协议栈独立迭代升级。

HCI 层:协议栈与控制器之间的统一接口

HCI 数据包类型

HCI 层承载五类数据包,定义于 bluetooth.h:

宏值用途
HCI_COMMAND_DATA_PACKET0x01主机 → 控制器命令
HCI_ACL_DATA_PACKET0x02经典 ACL 数据
HCI_SCO_DATA_PACKET0x03同步面向连接(SCO)语音数据
HCI_EVENT_PACKET0x04控制器 → 主机事件
HCI_ISO_DATA_PACKET0x05LE Audio ISO 数据(定义于 ISO 常量区)
#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 命令组

HCI 命令按 OGF(Opcode Group Field)分组,bluetooth.h 定义了全部标准命令组以及杰理厂商命令组:

宏值命令组
OGF_LINK_CONTROL0x01链路控制(查询、连接、配对)
OGF_LINK_POLICY0x02链路策略
OGF_CONTROLLER_BASEBAND0x03控制器基带
OGF_INFORMATIONAL_PARAMETERS0x04信息参数(本地版本/支持特性)
OGF_STATUS_PARAMETERS0x05状态参数
OGF_TESTING0x06测试
OGF_LE_CONTROLLER0x08LE 控制器命令
OGF_VENDOR_LE_CONTROLLER0x3E杰理厂商 LE 命令
OGF_VENDOR0x3F杰理厂商命令

Source: bluetooth.h

ISO(LE Audio)常量

协议栈为 LE Audio 预留了 ISO 通道参数,表明 SDK 对 LE Audio 的支持已内建到 HCI 层:

#define ISO_SDU_DTAT_LENGTH 0x032c       //812byte
#define ISO_PDU_DTAT_LENGTH 251          //251byte
#define ISO_PDU_INTERVAL_M_S 0x4e20          //20ms
#define ISO_PDU_INTERVAL_S_M 0x4e20          //20ms
#define HCI_ISO_DATA_PACKET         0x05

Source: bluetooth.h

设计意图:SDU 812 字节、PDU 251 字节、20ms 间隔的组合对应 LE Audio 单声道 LC3 低延迟配置,为 Auracast 接收(auracast_sink_api.h)与转发(auracast_delegator_api.h)提供统一的数据通路参数。

事件驱动模型与回调机制

事件结构体 struct bt_event

协议栈向用户投递事件的统一载体定义如下:

struct bt_event {
    u8 event;   // 事件类型
    u8 args[7]; // 事件参数,如带蓝牙地址等
    u32 value;  // 事件值,如HCI_EVENT_CONNECTION_COMPLETE事件的子事件
};

Source: event.rst.txt

三个字段的分工:

  • event:事件主类型,取值来自 BT_STATUS_* 或 HCI_EVENT_*;
  • args[7]:最多 7 字节的附加参数,常见为蓝牙地址(BD_ADDR)等;
  • value:32 位事件值,承载子事件——典型场景是 HCI_EVENT_CONNECTION_COMPLETE 事件的子事件(连接错误码,即 ERROR_CODE_*)。

协议栈状态事件(BT_STATUS_*)

在蓝牙 App 模式及需要处理连接生命周期的其他 App 中,用户注册的处理函数会收到以下协议栈级事件:

事件说明
BT_STATUS_INIT_OK蓝牙协议栈初始化完成
BT_STATUS_FIRST_CONNECTED首个设备连接成功
BT_STATUS_SECOND_CONNECTED第二个设备连接成功
BT_STATUS_FIRST_DISCONNECT首个连接设备断开
BT_STATUS_SECOND_DISCONNECT第二个连接设备断开
BT_STATUS_CONN_A2DP_CHA2DP 连接
BT_STATUS_DISCON_A2DP_CHA2DP 断开

Source: event.rst.txt

HCI 事件

协议栈会把需要用户感知的 HCI 事件透传上来,常见的有:

HCI 事件说明
HCI_EVENT_VENDOR_META杰理厂商事件容器
HCI_EVENT_INQUIRY_COMPLETE蓝牙搜索完成
HCI_EVENT_USER_CONFIRMATION_REQUEST蓝牙连接确认(配对确认)
HCI_EVENT_USER_PASSKEY_REQUEST配对码请求
HCI_EVENT_USER_PRESSKEY_NOTIFICATION配对码通知
HCI_EVENT_PIN_CODE_REQUEST连接 PIN Code 请求
HCI_EVENT_VENDOR_NO_RECONN_ADDR杰理自定义:上电回连时读不到 VM 中的回连地址
HCI_EVENT_DISCONNECTION_COMPLETE蓝牙断连完成
BTSTACK_EVENT_HCI_CONNECTIONS_DELETE杰理自定义:断开后协议栈资源释放完成
HCI_EVENT_CONNECTION_COMPLETE连接完成事件(其子事件即 ERROR_CODE_*)

Source: event.rst.txt

设计意图:事件语义分层是这套协议栈的核心设计——BT_STATUS_* 是协议栈加工后的“业务状态”(双连接、A2DP 通道),直接驱动 UI/业务;HCI_EVENT_* 是原始控制器事件,用于配对交互、回连、资源释放等需要细粒度控制的场景;ERROR_CODE_* 则把连接失败归因到具体原因,供上层决定“重试、重新配对还是放弃”。HCI_EVENT_VENDOR_NO_RECONN_ADDR 与 BTSTACK_EVENT_HCI_CONNECTIONS_DELETE 两个杰理自定义事件则暴露了回连链路与资源释放的边界,这是国产 SDK 为低成本单芯片优化而做的典型扩展。

双模连接管理:双连接与回连机制

AC792N 协议栈在经典蓝牙路径上支持双设备连接,这是 BT_STATUS_FIRST_* 与 BT_STATUS_SECOND_* 成对事件存在的原因:协议栈内部维护两个独立的连接槽位,每个槽位有独立的连接句柄、A2DP 通道与断开状态机。

典型生命周期如下:

  1. 上电初始化:协议栈完成初始化后上报 BT_STATUS_INIT_OK;
  2. 回连:App 根据 VM 中保存的回连地址发起连接。若 VM 中读不到地址,协议栈会上报 HCI_EVENT_VENDOR_NO_RECONN_ADDR,提示上层放弃回连、进入可发现/可配对状态;
  3. 首个连接建立:HCI_EVENT_CONNECTION_COMPLETE(子事件 ERROR_CODE_SUCCESS)→ 业务收到 BT_STATUS_FIRST_CONNECTED;
  4. 第二个连接建立:同样流程上报 BT_STATUS_SECOND_CONNECTED;若资源不足,控制器会以 ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED 拒绝;
  5. 断开:HCI_EVENT_DISCONNECTION_COMPLETE 之后,协议栈继续释放 L2CAP 资源,资源释放完成再上报杰理自定义事件 BTSTACK_EVENT_HCI_CONNECTIONS_DELETE——只有收到该事件,连接槽位才真正可复用。

回连场景中协议栈还会遇到一种经典竞态:断电后立即开机回连时,对端(手机)可能还认为旧 ACL 连接存在,此时连接请求会得到 ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS 或 ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR(本机地址全 0 或异常时),上层需要据此调整回连策略。

Profile 支持:经典与 LE 两条路径

经典路径:A2DP 与 AVRCP

  • a2dp_media_codec.h:A2DP 媒体流的编解码接口,负责音频数据在协议栈与音频框架之间的搬运;
  • avctp_user.h:AVRCP/AVCTP 控制通道接口,承载播放/暂停、上一曲/下一曲、音量等远程控制命令;
  • bt_profile_config.h:Profile 级配置入口,控制 A2DP/AVRCP 等功能的使能、参数与初始化行为。

A2DP 通道的状态变化通过 BT_STATUS_CONN_A2DP_CH / BT_STATUS_DISCON_A2DP_CH 上报,业务层据此刷新音乐播放状态(如提示音、播放器暂停/恢复)。

LE 路径:ATT / GATT / SM

  • le/att.h:Attribute Protocol,GATT 的底层传输;
  • le/gatt.h:GATT 层,提供服务发现、特征读写、通知/指示等 API;
  • le/sm.h:Security Manager,负责 BLE 配对、加密与密钥分发(对应 HCI 层的 HCI_EVENT_USER_CONFIRMATION_REQUEST、HCI_EVENT_USER_PASSKEY_REQUEST 等配对事件);
  • le/ble_api.h、le/le_user.h、le/ble_data_types.h:BLE 能力聚合与数据类型定义。

LE Audio:ISO 与 Auracast

bluetooth.h 中 ISO 常量(SDU/PDU 长度、20ms 间隔)为 LE Audio 定义了数据通路;le/auracast_sink_api.h 与 le/auracast_delegator_api.h 分别提供 Auracast 广播接收与转发(Delegator)能力,使设备既可以收听公共广播,也可以作为转发节点扩展广播覆盖。

Core Flow:连接建立与事件投递时序

下图以“上电 → 初始化 → 回连 → 首个连接成功 → A2DP 建立”为主线,展示一次完整的双模连接生命周期:

sequenceDiagram
    participant App as 用户 App
    participant Stack as 双模协议栈
    participant Ctl as 控制器
    participant VM as VM 存储

    App->>Stack: 协议栈初始化
    Stack->>Ctl: HCI 命令(Reset/读本地版本)
    Ctl-->>Stack: HCI_EVENT_COMMAND_COMPLETE
    Stack-->>App: BT_STATUS_INIT_OK

    App->>Stack: 发起回连
    Stack->>VM: 读取回连地址/LinkKey
    alt VM 中无回连地址
        VM-->>Stack: 无地址
        Stack-->>App: HCI_EVENT_VENDOR_NO_RECONN_ADDR
    else VM 中有回连地址
        VM-->>Stack: LinkKey
        Stack->>Ctl: HCI Create Connection(经典)
        Ctl-->>Stack: HCI_EVENT_CONNECTION_COMPLETE
        alt 子事件 ERROR_CODE_SUCCESS
            Stack-->>App: BT_STATUS_FIRST_CONNECTED
            App->>Stack: 建立 A2DP 流
            Stack-->>App: BT_STATUS_CONN_A2DP_CH
        else 子事件 ERROR_CODE_*
            Stack-->>App: 错误码(Page Timeout/Key Missing等)
        end
    end

时序要点:

  • 初始化成功标志是 BT_STATUS_INIT_OK,在此之前用户不应发起连接类操作;
  • 回连与配对是两条路径:有 LinkKey 走回连(HCI Create Connection),无地址/无 Key 则等待配对交互(PIN Code / Passkey / 确认请求类事件);
  • 连接成功以 HCI 事件为权威,业务状态(BT_STATUS_FIRST_CONNECTED)在 HCI 成功之后由协议栈合成上报;
  • A2DP 是连接之上的独立状态,连接成功 ≠ 音乐通道就绪,业务层还需等待 BT_STATUS_CONN_A2DP_CH。

错误码的详细语义与处理建议见下文「失败模式与边界场景」一节。

Usage Examples

示例 1:注册协议栈事件处理函数

所有蓝牙业务(连接、配对、A2DP)都从这一个回调入口开始。SDK 文档给出的标准原型如下:

/*-----------------------------------------------------------------------------
@brief 蓝牙协议栈处理函数
    @param   bt : 事件结构体
    @return  默认0
    @note
    @demo
------------------------------------------------------------------------------*/
static int bt_connction_status_event_handler(struct bt_event *bt)

Source: event.rst.txt

在 App 中实现该函数后,需要把它注册到协议栈(注册入口由 btstack_task.h 提供,具体注册函数见《常用蓝牙库接口函数》页面)。处理函数内部通常按 bt->event 与 bt->value 双重分发,例如:

static int bt_connction_status_event_handler(struct bt_event *bt)
{
    switch (bt->event) {
    case BT_STATUS_INIT_OK:
        /* 协议栈就绪,可开启回连或可发现模式 */
        break;
    case HCI_EVENT_CONNECTION_COMPLETE:
        /* bt->value 携带 ERROR_CODE_* 子事件 */
        switch (bt->value) {
        case ERROR_CODE_SUCCESS:
            /* 连接成功 */
            break;
        case ERROR_CODE_PAGE_TIMEOUT:
            /* 回连超时退出 */
            break;
        case ERROR_CODE_PIN_OR_KEY_MISSING:
            /* LinkKey 丢失,需重新配对 */
            break;
        }
        break;
    case BTSTACK_EVENT_HCI_CONNECTIONS_DELETE:
        /* 协议栈资源释放完成,槽位可复用 */
        break;
    }
    return 0;
}

说明:上述 switch 分支为根据官方事件语义整理的推荐写法示意;bt_event 字段定义与事件语义见 event.rst.txt。

示例 2:事件结构体字段使用

协议栈投递的事件载荷统一为 struct bt_event,其中 value 字段专门用于承载连接完成事件的子事件(错误码):

struct bt_event {
    u8 event;   // 事件类型
    u8 args[7]; // 事件参数,如带蓝牙地址等
    u32 value;  // 事件值,如HCI_EVENT_CONNECTION_COMPLETE事件的子事件
};

Source: event.rst.txt

示例 3:HCI 数据包类型与命令组常量

需要直接构造 HCI 命令或解析 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

Configuration Options

协议栈的配置分三类入口,均在 sdk/include_lib/btstack/ 下:

配置项/入口类型说明
bt_profile_config.h头文件宏配置Profile 级使能与参数(A2DP/AVRCP 等),具体宏在文件中定义
btstack_lib.ld 系列链接脚本协议栈库 text/data/bss 段的内存布局,一般无需修改
ISO_SDU_DTAT_LENGTH (0x032c)编译期常量ISO SDU 长度 812 字节
ISO_PDU_DTAT_LENGTH (251)编译期常量ISO PDU 长度 251 字节
ISO_PDU_INTERVAL_M_S / ISO_PDU_INTERVAL_S_M (0x4e20)编译期常量ISO PDU 间隔 20ms(主/从方向)

ISO 常量定义见 bluetooth.h。

设计意图:把 ISO 参数做成编译期常量,是因为 SDU/PDU/间隔三者必须与对端 LC3 编码参数严格匹配;固件侧固定这些值可避免运行时参数错误导致的链路不稳定。Profile 配置收敛到 bt_profile_config.h,则是为了让双模功能裁剪(如仅 BLE、仅经典)通过编译期配置完成,减少代码体积。

API Reference

事件处理回调

static int bt_connction_status_event_handler(struct bt_event *bt)

蓝牙协议栈事件处理函数,是协议栈向用户 App 投递事件的入口。

参数:

  • bt (struct bt_event *):事件结构体指针,包含 event(事件类型)、args[7](附加参数,如蓝牙地址)、value(事件值/子事件)。

返回: int,默认返回 0。

Source: event.rst.txt

事件结构体

struct bt_event

字段类型说明
eventu8事件类型(BT_STATUS_* / HCI_EVENT_*)
args[7]u8事件参数,如带蓝牙地址等
valueu32事件值,如 HCI_EVENT_CONNECTION_COMPLETE 事件的子事件

Source: event.rst.txt

关键常量汇总

HCI 数据包类型(bluetooth.h):HCI_COMMAND_DATA_PACKET(0x01)、HCI_ACL_DATA_PACKET(0x02)、HCI_SCO_DATA_PACKET(0x03)、HCI_EVENT_PACKET(0x04)、HCI_ISO_DATA_PACKET(0x05)。

OGF 命令组(bluetooth.h):OGF_LINK_CONTROL(0x01)、OGF_LINK_POLICY(0x02)、OGF_CONTROLLER_BASEBAND(0x03)、OGF_INFORMATIONAL_PARAMETERS(0x04)、OGF_STATUS_PARAMETERS(0x05)、OGF_TESTING(0x06)、OGF_LE_CONTROLLER(0x08)、OGF_VENDOR_LE_CONTROLLER(0x3E)、OGF_VENDOR(0x3F)。

主要 HCI 事件(bluetooth.h,节选):HCI_EVENT_INQUIRY_COMPLETE(0x01)、HCI_EVENT_INQUIRY_RESULT(0x02)、HCI_EVENT_CONNECTION_COMPLETE(0x03)、HCI_EVENT_CONNECTION_REQUEST(0x04)、HCI_EVENT_DISCONNECTION_COMPLETE(0x05)、HCI_EVENT_AUTHENTICATION_COMPLETE(0x06)、HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE(0x07)、HCI_EVENT_ENCRYPTION_CHANGE(0x08)、HCI_EVENT_COMMAND_COMPLETE(0x0E)、HCI_EVENT_COMMAND_STATUS(0x0F)、HCI_EVENT_HARDWARE_ERROR(0x10)、HCI_EVENT_ROLE_CHANGE(0x12)、HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS(0x13)、HCI_EVENT_MODE_CHANGE(0x14)、HCI_EVENT_PIN_CODE_REQUEST(0x16)、HCI_EVENT_LINK_KEY_REQUEST(0x17)、HCI_EVENT_LINK_KEY_NOTIFICATION(0x18)、HCI_EVENT_DATA_BUFFER_OVERFLOW(0x1A)、HCI_EVENT_INQUIRY_RESULT_WITH_RSSI(0x22)。

Source: bluetooth.h

失败模式与边界场景

协议栈把连接失败的原因通过 HCI_EVENT_CONNECTION_COMPLETE 的子事件(bt->value)暴露给上层,官方文档给出了完整语义。这是本 SDK 调试回连问题最重要的查错表:

错误码(子事件)含义与处理建议
ERROR_CODE_SUCCESS连接成功
ERROR_CODE_PIN_OR_KEY_MISSING连接过程中 LinkKey 丢失(手机删除了 LinkKey),需触发重新配对
ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED连接个数超出资源允许,第二个连接请求被拒
ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES回连目标资源不足(部分手机连接一台设备后即以此拒绝),或本机资源不足
ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR对端只允许指定地址连接;或本机地址全 0/异常
ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED连接耗时过长,对端主动放弃
ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION最常见的断开消息(对端主动断开)
ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST正常断开,本地 L2CAP 资源释放完成后上报
ERROR_CODE_AUTHENTICATION_FAILURE鉴权失败:LinkKey 丢失,回连时会出现一次
ERROR_CODE_PAGE_TIMEOUT回连超时退出消息
ERROR_CODE_CONNECTION_TIMEOUT连接过程中 LinkKey 错误
ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS回连时对端尚未释放本机地址(常见于断电立即开机回连)

Source: event.rst.txt

错误码驱动的决策流程可抽象为:

flowchart TD
    Start(["连接请求 / 回连"]) --> Evt{"HCI_EVENT_CONNECTION_COMPLETE"}
    Evt -->|"ERROR_CODE_SUCCESS"| Ok["BT_STATUS_*_CONNECTED 连接成功"]
    Evt -->|"ERROR_CODE_PAGE_TIMEOUT"| Timeout["回连超时退出"]
    Evt -->|"ERROR_CODE_PIN_OR_KEY_MISSING /<br/>ERROR_CODE_AUTHENTICATION_FAILURE"| RePair["重新配对"]
    Evt -->|"ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES"| Limit["资源不足,稍后重试"]
    Evt -->|"ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS"| Already["对端地址未释放,延迟重试"]
    Evt -->|"ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR"| Addr["检查本机地址是否为全0/异常"]
    Ok --> End(["处理完成"])
    Timeout --> End
    RePair --> End
    Limit --> End
    Already --> End
    Addr --> End

边界场景要点:

  • 断电开机立即回连:对端 ACL 未释放 → ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS,应退避重试而非立即放弃;
  • LinkKey 丢失:回连会出现 ERROR_CODE_PIN_OR_KEY_MISSING 或 ERROR_CODE_AUTHENTICATION_FAILURE,随后应进入配对流程;
  • 断开资源释放是异步的:HCI_EVENT_DISCONNECTION_COMPLETE 之后还需等待 BTSTACK_EVENT_HCI_CONNECTIONS_DELETE,在此之前槽位不可复用,重复连接会触发资源类错误;
  • 地址异常:ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR 出现时优先排查本机 BD_ADDR(全 0/未写入 VM)。

并发与一致性

协议栈采用单线程事件循环 + 回调模型:所有 HCI 事件与 BT_STATUS_* 状态都在协议栈上下文中按序投递,用户回调内不应做阻塞操作(如等待 I/O 或长时间自旋),否则会拖慢协议栈事件处理、放大超时类错误。双连接槽位(FIRST/SECOND)由协议栈串行管理,业务侧只需按事件顺序维护状态即可,无需额外加锁;但回调中访问共享资源(如 UI、音频状态)时仍需按 App 自身线程模型加锁,因为回调上下文与 App 其他任务上下文是并发的。

性能与运维考虑

  • ISO 参数固定:LE Audio 通道使用 20ms 间隔、812 字节 SDU,音频数据按该节奏调度,上层搬移音频数据应与之对齐,避免缓冲溢出;
  • 回连节奏:ERROR_CODE_PAGE_TIMEOUT 意味着一次回连尝试耗时已超时,App 应控制重试次数与间隔,避免反复回连消耗射频与功耗;
  • 资源上限:经典双连接 + LE 多链路共享同一控制器资源,超限时控制器以 ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED 拒绝,业务侧需做连接优先级管理;
  • 内存布局:协议栈库通过 btstack_lib_text/data/bss.ld 链接脚本放置,修改链接脚本会影响协议栈静态内存(如 ACL 缓冲区、连接槽位)的可用性,非必要不调整。

扩展点

  1. 事件处理函数:bt_connction_status_event_handler(struct bt_event *bt) 是协议栈对上层唯一的标准化扩展入口,所有自定义业务(回连策略、提示音、UI 状态机)都挂接在此回调上;
  2. 杰理自定义事件:HCI_EVENT_VENDOR_NO_RECONN_ADDR、BTSTACK_EVENT_HCI_CONNECTIONS_DELETE 是协议栈为 SDK 场景扩展的事件,上层可据此实现更精准的回连与资源管理;
  3. Profile 配置裁剪:通过 bt_profile_config.h 可按产品需求裁剪双模能力(仅经典 / 仅 BLE / 双模 + LE Audio);
  4. LE Audio / Auracast:auracast_sink_api.h 与 auracast_delegator_api.h 提供独立 API,可在现有双模协议栈之上叠加广播接收与转发业务,无需改动核心连接逻辑。

Related Links

  • 协议栈事件说明(完整事件表):event.rst.txt
  • 常用蓝牙库接口函数:常用蓝牙库接口函数.rst.txt
  • 协议栈总入口头文件:bluetooth.h
  • 协议栈事件定义:btstack_event.h
  • 协议栈任务/调度接口:btstack_task.h
  • Profile 配置:bt_profile_config.h
  • A2DP 媒体编解码:a2dp_media_codec.h
  • AVRCP/AVCTP 用户接口:avctp_user.h
  • LE 协议族目录:le/
  • 相关页面:《常用蓝牙库接口函数》《蓝牙连接管理 App》
Next
WiFi 协议栈与配网