蓝牙公共模块与消息联动
蓝牙公共模块(bt_common)是 AC63 系列蓝牙 SoC 上承载 BR/EDR 与 BLE 公共能力(初始化、广播、连接、SPP、GATT、MAC 地址、字节序转换等)的薄封装层;消息联动则依赖系统事件总线(event 模块)以 struct bt_event 为载体,将蓝牙协议栈状态(连接状态、HCI 状态、BLE 状态)与键值、TWS、AT 指令等来源的事件统一投递到应用层。
Purpose and Scope
本文档讲解两大主题:
- 蓝牙公共模块(bt_common):
apps/common/include/bt_common.h中声明的公共宏、状态位、LE Controller 扩展命令结构体、公共 API(bt_ble_init/bt_ble_exit/bt_ble_adv_enable/user_spp_data_handler等)以及apps/common/bt_common/bt_test_api.c中的 BLE 射频 DUT 测试 API。 - 消息联动机制:
include_lib/system/event.h中定义的蓝牙事件类型(SYS_BT_EVENT)、事件来源(SYS_BT_EVENT_FROM_TWS/SYS_BT_EVENT_TYPE_CON_STATUS等)与struct bt_event载荷格式,以及bt_common.h中COMMON_EVENT_*与应用逻辑联动的约定。
不属于本文范围、请参阅其他目录页的主题:蓝牙协议栈具体状态机(见 btstack 相关文档)、TWS 对箱联动(见 TWS 模块)、AT 指令解析(见 AT 模块)、OTA 升级流程(见 update 模块)。本文只覆盖公共底座与事件投递约定。
Overview
AC63 SDK 的应用代码(apps/ 目录)通过两层机制与蓝牙协议栈交互:
- 直接调用层(bt_common 公共 API):应用无需关心底层 btstack 细节,通过
bt_common.h提供的函数完成 BLE 初始化、广播开关、断开连接、MAC 地址读取、SPP 数据收发、GATT 数据收发、发射功率设置等操作。这些 API 是应用与协议栈之间的"稳定接口面"。 - 事件通知层(消息联动):协议栈内部的异步状态变化(连接/断开、HCI 事件、BLE 配对状态、远端类型变化等)通过系统事件总线以
struct bt_event广播给应用。应用注册SYS_BT_EVENT事件处理器即可响应这些变化,从而实现"协议栈 → 公共模块 → 应用"的解耦联动。
事件来源通过 32 位魔数(('C' << 24) | ('O' << 16) | ('N' << 8) | '\0' 这类写法)编码为可读字符串形式的 from/type 字段,事件载荷为 struct bt_event { u8 event; u8 args[7]; u32 value; }——固定 1 字节事件号 + 7 字节参数 + 4 字节值,结构紧凑、适合嵌入式环境下零拷贝投递。
Architecture
下图展示蓝牙公共模块与消息联动在 AC63 系统中的位置与数据流向:
flowchart TD
subgraph sg_Stack["蓝牙协议栈(btstack / 控制器)"]
BREDR["BR/EDR 控制器"]
LE["BLE 控制器"]
end
subgraph sg_Common["蓝牙公共模块 bt_common"]
API["公共 API<br/>bt_ble_init / bt_ble_adv_enable<br/>user_spp_data_handler / le_att_server_send_data"]
MAC["MAC 地址与字节序工具<br/>bt_get_mac_addr / little_endian_read_16"]
DUT["BLE DUT 测试 API<br/>ble_dut_mode_init / ble_fix_fre_api"]
PWR["功率与射频配置<br/>bt_max_pwr_set / bredr_power_get"]
end
subgraph sg_Event["消息联动(事件总线)"]
BT_EVENT["SYS_BT_EVENT (0x0010)"]
BT_MSG["struct bt_event<br/>event + args[7] + value"]
SOURCES["事件来源<br/>TWS / CON_STATUS / HCI_STATUS<br/>BLE_STATUS / KEY / AT / SELF"]
end
subgraph sg_App["应用层"]
APP_HANDLER["应用事件处理器<br/>COMMON_EVENT_* 联动逻辑"]
end
BREDR -->|"异步状态"| BT_EVENT
LE -->|"异步状态"| BT_EVENT
BT_EVENT --> BT_MSG
SOURCES --> BT_MSG
BT_MSG --> APP_HANDLER
APP_HANDLER -->|"回调公共 API"| API
API --> BREDR
API --> LE
DUT --> LE
PWR --> BREDR
MAC --> API
架构说明:底层协议栈(BR/EDR 与 BLE 控制器)产生两类输出——同步可调用的服务能力(由公共 API 封装)和异步状态事件(经事件总线投递)。公共模块夹在中间,既为应用提供稳定的函数接口,又把事件按 SYS_BT_EVENT 分类后以统一载荷格式上抛。应用处理器在收到事件后可以再回调公共 API 执行动作(例如收到断开事件后重新开启广播),形成闭环联动。DUT 测试 API 直接操作 LE 控制器(ll_hci_destory 后接管 HCI),属于调试/产测通道,与正常业务路径隔离。
消息联动机制:事件源、载荷与分发约定
事件总线的注册位
系统事件总线(include_lib/system/event.h)为每个子系统分配一个独立的位掩码,蓝牙占用 0x0010:
#define SYS_ALL_EVENT 0xffff
#define SYS_KEY_EVENT 0x0001
#define SYS_TOUCH_EVENT 0x0002
#define SYS_DEVICE_EVENT 0x0004
#define SYS_NET_EVENT 0x0008
#define SYS_BT_EVENT 0x0010
Source: event.h
设计意图:应用可以一次性订阅 SYS_ALL_EVENT(0xffff)接收全部子系统事件,也可以只订阅 SYS_BT_EVENT 精确过滤蓝牙事件。位掩码设计使事件分发的过滤判断退化为一次位与运算,在中断/低功耗场景下开销极低。
事件来源(from)与类型(type)魔数
事件通过 32 位可读魔数标识"来源"或"类型",例如 ('C' << 24) | ('O' << 16) | ('N' << 8) | '\0' 即字符串 "CON" 的 ASCII 编码:
#define SYS_BT_EVENT_FROM_TWS (('T' << 24) | ('W' << 16) | ('S' << 8) | '\0')
#define SYS_BT_EVENT_TYPE_CON_STATUS (('C' << 24) | ('O' << 16) | ('N' << 8) | '\0')
#define SYS_BT_EVENT_TYPE_HCI_STATUS (('H' << 24) | ('C' << 16) | ('I' << 8) | '\0')
#define SYS_BT_EVENT_BLE_STATUS (('B' << 24) | ('L' << 16) | ('E' << 8) | '\0')
#define SYS_BT_EVENT_FORM_COMMON (('C' << 24) | ('M' << 16) | ('M' << 8) | '\0')
#define SYS_BT_EVENT_FROM_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '\0')
#define SYS_BT_EVENT_FORM_SELF (('S' << 24) | ('E' << 16) | ('F' << 8) | '\0')
#define SYS_BT_EVENT_FORM_AT (('I' << 24) | ('A' << 16) | ('T' << 8) | '\0')
Source: event.h
这些宏揭示了消息联动的完整来源矩阵:TWS(对箱)、CON_STATUS(连接状态)、HCI_STATUS(HCI 层状态)、BLE_STATUS(BLE 专属状态)、COMMON(公共模块自产事件)、KEY(按键转蓝牙事件)、SELF(模块自省)、AT(AT 指令触发)。应用处理器据此判断事件语义,避免为不同来源的事件设计同一套处理分支时发生语义混淆。
事件载荷:struct bt_event
所有蓝牙事件统一使用紧凑载荷结构:
struct bt_event {
u8 event;
u8 args[7];
u32 value;
};
Source: event.h
event:1 字节事件编号,区分同一来源下的不同子事件;args[7]:7 字节扩展参数,用于携带地址、句柄等小数据;value:4 字节值,用于携带计数值、状态码或大参数。
固定 12 字节的结构便于通过环形队列或邮箱零拷贝投递;应用处理器按 from 宏 + event 编号 + args/value 的组合解析完整语义。
公共联动事件(COMMON_EVENT_*)
bt_common.h 定义了公共模块向应用联动广播的子事件号:
enum {
COMMON_EVENT_EDR_REMOTE_TYPE = 1,
COMMON_EVENT_BLE_REMOTE_TYPE,
COMMON_EVENT_SHUTDOWN_ENABLE,
COMMON_EVENT_SHUTDOWN_DISABLE,
COMMON_EVENT_MODE_DETECT,
};
Source: bt_common.h
每个枚举项代表一类联动场景:EDR/BLE 远端类型变化(应用据此切换 UI 或协议栈行为)、关机使能/禁止(配合 sys_auto_shut_down_disable 类逻辑)、模式检测(进入/退出某工作模式)。这些事件通常由公共模块内部产生,通过 SYS_BT_EVENT_FORM_COMMON 来源上抛,应用只需订阅 SYS_BT_EVENT 即可全部接收。
联动时序
下图描述一次典型的"BLE 连接断开 → 应用联动恢复广播"的消息流:
sequenceDiagram
participant LE as BLE 控制器
participant Stack as btstack / 公共模块
participant Bus as 事件总线 SYS_BT_EVENT
participant App as 应用事件处理器
participant API as bt_common API
LE->>Stack: 连接断开(HCI 事件)
Stack->>Bus: 构造 struct bt_event<br/>(from=BLE_STATUS, event=disconnect)
Bus->>App: 投递 bt_event
App->>App: 解析 from/event,执行联动逻辑<br/>(如更新状态图标、清除配对态)
App->>API: 调用 bt_ble_adv_enable(1) 重新广播
API->>LE: 下发 HCI LE Set Advertising Enable
LE-->>API: 广播恢复
设计要点:联动逻辑全部收敛在应用处理器中,协议栈与公共模块不感知应用状态;事件总线只负责搬运,不执行业务,保证各层可独立替换与测试。
蓝牙公共 API(bt_common.h)
常用宏与状态位
公共模块提供一组面向协议栈数据布局的辅助宏,用于把时间、长度、槽位等概念转换为协议字节:
#define SYNC_TIMEOUT_MS(x) {(x / 10) & 0xff, (x / 10) >> 8}
#define ALIGN_2BYTE(size) (((size)+1)&0xfffffffe)
#define BYTE_LEN(x...) sizeof((u8 []) {x})
#define MS_TO_SLOT(x) (x * 8 / 5)
#define UINT24_TO_BYTE(x) \
{ \
x, \
x >> 8, \
x >> 16 \
}
Source: bt_common.h
SYNC_TIMEOUT_MS:把毫秒超时转换为 LE 同步超时双字节(10ms 为 1 单位);MS_TO_SLOT:把毫秒转换为 BR/EDR 时隙(1 时隙 = 0.625ms,即 x * 8 / 5);UINT24_TO_BYTE:把 24 位数值展开为小端 3 字节,用于 LE 广播间隔等 3 字节字段;BYTE_LEN:由初始化列表推导字节长度,用于构造 GATT 数据载荷。
状态位枚举用于标识当前各协议通道的使能状态,供应用查询与联动:
enum {
ST_BIT_INQUIRY = 0,
ST_BIT_PAGE_SCAN,
ST_BIT_BLE_ADV,
ST_BIT_SPP_CONN,
ST_BIT_BLE_CONN,
ST_BIT_WEIXIN_CONN,
};
Source: bt_common.h
BLE 私有消息枚举定义配对链路的应用层消息号(0xF0 起,避开标准 ATT 消息空间):
enum {
BLE_PRIV_MSG_PAIR_CONFIRM = 0xF0,
BLE_PRIV_PAIR_ENCRYPTION_CHANGE,
};
Source: bt_common.h
公共 API 总览
| API | 作用 | 备注 |
|---|---|---|
bt_ble_init() / bt_ble_exit() | BLE 协议栈初始化 / 退出 | 生命周期入口 |
bt_ble_adv_enable(u8 enable) | 开关 BLE 广播 | 联动恢复广播的常用调用 |
ble_app_disconnect() | 断开 BLE 连接 | 主动断开 |
ble_module_enable(u8 en) | 使能/禁止 BLE 模块 | 省电场景 |
bt_get_mac_addr() | 读取本机 MAC(返回 const u8 *) | 用于广播/配对 |
lib_make_ble_address(u8 *ble, u8 *edr) | 由 EDR 地址派生 BLE 地址 | 保证双模同源地址 |
bt_get_vm_mac_addr(u8 *addr) | 从 VM 区读取 MAC | 掉电保持 |
user_spp_data_handler(packet_type, ch, packet, size) | SPP 数据接收回调 | 用户覆写实现 |
transport_spp_init() / transport_spp_disconnect() | SPP 传输初始化 / 断开 | |
le_att_server_send_data(cid, packet, size) | GATT Server 发送数据 | 返回 int |
le_att_client_send_data(cid, packet, size) | GATT Client 发送数据 | 返回 int |
le_at_client_creat_connection(addr, addr_type) | 主动建立 LE 连接 | Client 角色 |
att_set_conn_handle(handle, type) | 设置 ATT 连接句柄 | |
bt_max_pwr_set(pwr, pg_pwr, iq_pwr, ble_pwr) | 设置发射功率最大值 | 解析见 btcontroller_modules.h |
bredr_power_get() / bredr_power_put() | BR/EDR 射频电源管理 | 低功耗联动 |
wdt_clear() | 喂狗 | 长流程防复位 |
reset_PK_cb_register(cb) / _ext(cb, u16) | 注册复位配对键回调 | 双模配对复位 |
Source: bt_common.h
字节序工具
LE 协议大量使用小端序,公共模块提供显式读写函数,避免应用直接解引用可能未对齐的 buffer:
extern uint16_t little_endian_read_16(const uint8_t *buffer, int pos);
extern uint32_t little_endian_read_24(const uint8_t *buffer, int pos);
extern uint32_t little_endian_read_32(const uint8_t *buffer, int pos);
extern void swapX(const uint8_t *src, uint8_t *dst, int len);
extern void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
extern void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
extern void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
extern void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
Source: bt_common.h
LE 扩展广播命令结构体
为支持蓝牙 5 扩展广播/扫描,公共头文件按 HCI LE Controller 命令字节布局定义了紧凑结构体(全部 _GNU_PACKED_),包括 __ext_adv_report_event、__periodic_adv_report_event、__periodic_creat_sync、__ext_scan_param、__ext_scan_enable、ext_advertising_param、ext_advertising_data、ext_advertising_enable、periodic_advertising_param 等。以广播参数为例:
struct ext_advertising_param {
u8 Advertising_Handle;
u16 Advertising_Event_Properties;
u8 Primary_Advertising_Interval_Min[3];
u8 Primary_Advertising_Interval_Max[3];
u8 Primary_Advertising_Channel_Map;
u8 Own_Address_Type;
u8 Peer_Address_Type;
u8 Peer_Address[6];
u8 Advertising_Filter_Policy;
u8 Advertising_Tx_Power;
u8 Primary_Advertising_PHY;
u8 Secondary_Advertising_Max_Skip;
u8 Secondary_Advertising_PHY;
u8 Advertising_SID;
u8 Scan_Request_Notification_Enable;
} _GNU_PACKED_;
Source: bt_common.h
这些结构体直接映射 HCI LE Set Extended Advertising Parameters 命令参数,字段顺序与蓝牙规范一致,便于公共模块直接 memcpy 到命令缓冲区下发控制器。
配置项
公共模块依赖以下编译期/链接期配置(在 bt_profile_cfg.h / lib_profile_cfg.h 中定义,头文件通过 APP_PRIVATE_PROFILE_CFG 宏选择):
| 配置项 | 类型 | 默认值(取决于配置) | 说明 |
|---|---|---|---|
config_le_hci_connection_num | const int | 配置决定 | 支持同时连接的 LE 连接个数 |
config_le_sm_support_enable | const int | 配置决定 | 是否支持 BLE 加密配对(SM) |
config_le_gatt_server_num | const int | 配置决定 | 支持的 GATT Server 角色个数 |
config_le_gatt_client_num | const int | 配置决定 | 支持的 GATT Client 角色个数 |
TCFG_USER_BLE_ENABLE | 宏 | 配置决定 | BLE 功能总开关(app_config.h) |
CONFIG_BT_MODE | 宏 | BT_NORMAL | 蓝牙工作模式(影响 DUT 行为) |
Source: bt_common.h
这些 extern const int 由库侧(btstack/profile 配置)提供,公共 API 与 DUT 代码通过 TCFG_USER_BLE_ENABLE、CONFIG_BT_MODE == BT_NORMAL 等条件编译裁剪行为,保证同一套应用代码可适配不同产品配置。
BLE 射频 DUT 测试 API(bt_test_api.c)
apps/common/bt_common/bt_test_api.c 是公共模块中面向产测/认证的 BLE Direct Test Mode(DUT)实现,独立于正常业务路径编译。
测试参数定义
enum BLE_DUT_PAYLOAD_TYPE {
PAYLOAD_TYPE_PRBS9 = 0,
PAYLOAD_TYPE_11110000,
PAYLOAD_TYPE_10101010,
PAYLOAD_TYPE_PRBS15,
PAYLOAD_TYPE_11111111,
PAYLOAD_TYPE_00000000,
PAYLOAD_TYPE_00001111,
PAYLOAD_TYPE_01010101,
PAYLOAD_TYPE_SINGLE_CARRIER = 0xf0,
};
enum BLE_DUT_PHY_TYPE {
BLE_1M_UNCODED_PHY = 1,
BLE_2M_UNCODED_PHY,
BLE_1M_CODED_PHY_S8,
BLE_1M_CODED_PHY_S2,
};
struct ble_dut_param_set {
u8 ch_index; //tx ch index;(0~39 -> 2402~2480)
u8 payload_type; //tx payload type
u8 payload_len; //payload_len(0~0xff) when continuous_tx = 0;
u8 continuous_tx; //enable or disable continuous transmission mode(0/1)
};
Source: bt_test_api.c
BLE_DUT_PAYLOAD_TYPE 覆盖蓝牙认证要求的 PRBS9/PRBS15 伪随机序列与多种固定图案(0xAA、0x0F、0xF0、全 0/全 1)以及单载波模式;ch_index 直接映射信道频率 2402~2480MHz。
定频发射与 DUT 模式切换
void ble_fix_fre_api()
{
#if TCFG_USER_BLE_ENABLE
#if (CONFIG_BT_MODE == BT_NORMAL)
bt_ble_adv_enable(0);
#endif
os_time_dly(10);
struct ble_dut_param_set dut_param = {
.ch_index = 0,
.payload_type = PAYLOAD_TYPE_10101010,
.payload_len = 0x20,
.continuous_tx = 1,
};
ble_enter_dut_tx_mode(&dut_param);
#endif
}
Source: bt_test_api.c
ble_fix_fre_api 展示了 DUT 的进入策略:先关闭正常广播(bt_ble_adv_enable(0))以避免射频竞争,延时 10 个系统 tick 让控制器收敛,再以信道 0、0xAA 图案、连续发射模式进入 DUT。条件编译保证 TCFG_USER_BLE_ENABLE 关闭或非 BT_NORMAL 模式下该函数为空操作。
static void *ble_dut_hdl = NULL;
extern void ll_hci_destory(void);
void ble_dut_mode_init(void)
{
if (!ble_dut_hdl) {
ll_hci_destory();
ble_dut_hdl = __ble_dut_ops->init();
}
}
void ble_dut_mode_exit(void)
{
if (ble_dut_hdl) {
// ...释放 DUT 句柄并恢复 HCI
}
}
Source: bt_test_api.c
ble_dut_mode_init 先调用 ll_hci_destory() 销毁正常 HCI 通道,再通过 __ble_dut_ops->init() 取得 DUT 操作句柄——这解释了为什么注释强调"调用此 API 前必须退出睡眠模式":接管 HCI 后正常协议栈调度已不可用。句柄判空(if (!ble_dut_hdl))保证重复调用只初始化一次,ble_dut_mode_exit 则负责释放并回到正常模式。
公共模块 → DUT 联动
flowchart LR
A["产测指令/测试盒"] -->|"触发"| B["bt_fix_fre_api()"]
B --> C{"TCFG_USER_BLE_ENABLE<br/>且 BT_NORMAL?"}
C -->|"否"| D["空操作"]
C -->|"是"| E["bt_ble_adv_enable(0)<br/>关闭正常广播"]
E --> F["os_time_dly(10)<br/>等待收敛"]
F --> G["构造 ble_dut_param_set"]
G --> H["ble_enter_dut_tx_mode<br/>进入定频发射"]
H --> I["ble_dut_mode_init<br/>ll_hci_destory + ops->init"]
失败模式、边界情况与并发
- 睡眠模式冲突:源码注释明确警告 DUT API 必须在退出睡眠模式后调用。
ll_hci_destory()接管 HCI 后,若系统进入睡眠,射频时钟可能停止导致测试失效,产测流程必须先调用sys_auto_shut_down_disable()之类的接口(见bt_dut_api中的TCFG_AUTO_SHUT_DOWN_TIME分支)。 - 重复初始化保护:
ble_dut_hdl静态句柄 + 判空初始化是公共模块典型的"一次性资源"保护模式;若init()失败返回 NULL,下次调用会重试,但不会重复销毁已存在的句柄。 - 双模竞争:
ble_fix_fre_api中先关广播再延时,就是为了避免 EDR/BLE 同频竞争导致的测试功率测量偏差;同理 BR/EDR 测试(bt_fix_fre_api,被#if 0屏蔽)需要先bit_clr_ie(IRQ_BREDR_IDX)关闭中断。 - 事件竞争:
struct bt_event的value与args由发送方一次性填好再投递,总线按队列顺序分发;应用处理器不应在中断上下文执行长逻辑,应只做状态标记后延后处理。 - 事件号冲突风险:
COMMON_EVENT_EDR_REMOTE_TYPE = 1起始、BLE_PRIV_MSG_PAIR_CONFIRM = 0xF0起始,两者处于不同事件域(前者是公共事件号,后者是 BLE 私有消息号),扩展时需保持各自域内编号唯一。
扩展点与操作注意事项
- 新增公共事件:在
bt_common.h的COMMON_EVENT_*枚举尾部追加编号,保持既有编号不变(嵌入式固件无动态重编号机制,编号变化会破坏已发布固件的联动协议)。 - 新增公共 API:在
bt_common.h声明extern并在apps/common/bt_common/下实现,注意_GNU_PACKED_结构体必须保持字段顺序与蓝牙规范一致,不得按编译器默认对齐。 - 新增 DUT 图案:向
BLE_DUT_PAYLOAD_TYPE枚举追加值,并在__ble_dut_ops驱动的实现中补充对应图案生成逻辑;PHY 类型同理扩展BLE_DUT_PHY_TYPE。 - 产测联调:产测脚本通过测试盒/串口触发 DUT 模式,完成后必须调用
ble_dut_mode_exit恢复 HCI,否则设备无法再连接手机。 - 日志开关:
bt_test_api.c顶部通过LOG_TAG "[BT_DUT]"与LOG_*_ENABLE宏控制调试输出(默认开启 ERROR/DEBUG/INFO 与 CLI 日志),量产版本建议按需裁剪。
测试覆盖
源码中 DUT 路径通过 #if 0 屏蔽了 BR/EDR 定频 API(bt_dut_api/bt_fix_fre_api),说明 BR/EDR 产测默认走库侧 bredr_fcc_init 通道;BLE DUT 路径(ble_fix_fre_api/ble_dut_mode_init/ble_dut_mode_exit)处于可用状态,配合 __ble_dut_ops 驱动完成认证所需的 PRBS/固定图案/单载波发射。公共 API 与事件联动本身无独立单元测试,其正确性依赖集成测试(产测 + 真机连接 + TWS 对箱场景)验证。
典型用法示例
业务路径:开关广播(联动恢复)
从 bt_test_api.c 可以看到公共 API 在业务代码中的标准调用姿势——条件编译保护 + 直接调用:
#if TCFG_USER_BLE_ENABLE
#if (CONFIG_BT_MODE == BT_NORMAL)
bt_ble_adv_enable(0); // 关闭广播:进入 DUT 前避免射频竞争
#endif
os_time_dly(10);
#endif
Source: bt_test_api.c
应用在收到 SYS_BT_EVENT 断开事件后,用同样的方式调用 bt_ble_adv_enable(1) 即可实现"断开即重连广播"的联动逻辑——事件处理器只负责判断(from/event),动作一律落到公共 API。
协议数据路径:解析小端字段
解析广播/扫描报告时,优先使用公共模块的字节序工具而非直接指针转换:
// 假设 buf 指向 __ext_adv_report_event,RSSI 位于 Data 之后偏移处
uint16_t event_type = little_endian_read_16(buf, offsetof(struct __ext_adv_report_event, Event_Type));
uint32_t adv_interval = little_endian_read_24(adv_data, 1); // 3 字节广播间隔
Source: bt_common.h(工具函数声明)与 bt_common.h(事件结构布局)
这种做法的价值在于:LE 载荷多为字节流且可能未对齐,直接 *(u16*)ptr 在部分内核/架构上会触发异常或读到错位数据,而显式小端读取函数是零风险且可移植的。
事件消费路径:订阅与解析
应用侧订阅 SYS_BT_EVENT 后,处理器按三要素解析事件:
// 伪代码示意:应用事件处理器(基于 event.h 定义的宏与结构)
static int app_bt_event_handler(struct bt_event *bt)
{
switch (bt->event) {
case COMMON_EVENT_EDR_REMOTE_TYPE: // bt_common.h 公共联动事件
// 更新 EDR 远端设备类型 UI
break;
case COMMON_EVENT_BLE_REMOTE_TYPE: // 更新 BLE 远端类型
break;
case COMMON_EVENT_SHUTDOWN_DISABLE: // 联动:禁止自动关机
break;
}
return 0;
}
Source(事件宏与结构定义): bt_common.h、event.h
说明:上述处理器示例为基于头文件定义的标准消费模式示意;实际应用代码位于各产品 app 目录(如
apps/下的自定义事件表),本文档仅以公共头文件契约演示联动写法。
相关链接
- bt_common.h(公共 API 与宏定义)
- event.h(事件系统与 bt_event 载荷)
- bt_test_api.c(BLE DUT 测试 API)
- 蓝牙协议栈状态机与连接管理:见 btstack 相关目录文档
- TWS 对箱消息(
SYS_BT_EVENT_FROM_TWS):见 TWS 模块文档 - AT 指令触发事件(
SYS_BT_EVENT_FORM_AT):见 AT 模块文档