2.4G 私有协议与 Dongle 示例
本文档介绍 AC63 系列蓝牙 SoC SDK 中基于 2.4G 私有射频协议的三类示例工程:连接型 2.4G(conn_24g)、非连接型 2.4G(nonconn_24g)以及 2.4G Dongle 接收器(dongle),涵盖应用入口、GATT/私有协议承载方式、USB HID 上行链路与可配置项。
Purpose and Scope
本页面向希望基于 2.4G 私有协议开发无线键鼠、遥控器、游戏手柄或 Dongle 桥接设备的开发者,完整说明 SDK 中三个示例应用的实现机制:
- conn_24g(连接型 2.4G):基于标准 BLE GATT 连接承载私有数据,主机周期性通过 ATT 无应答写发送数据,从机侧提供自定义 2.4G Profile(
ble_24g_server.c/ble_24g_client.c/ble_24g_profile.h)。 - nonconn_24g(非连接型 2.4G):不建立 GATT 连接,直接通过私有射频控制器收发数据,应用侧负责启动协议栈与处理事件(
app_nonconn_24g.c/ble_24g_deal.c)。 - dongle(2.4G Dongle 示例):作为接收端(BLE Central)连接 2.4G 从机,把收到的数据转换为 USB HID 报告上发给 PC,同时包含 OTA 升级与 EDR HID 支持(
app_dongle.c/ble_dg_central.c/usb_hid_devices.c/ota_dg_central.c/edr_hid_user.c)。
以下内容不在本页范围内:通用 BLE GATT 框架、USB 协议栈本身、其它应用示例(如 SPP/LE 常规透传),这些主题由对应目录的独立页面覆盖。三个示例均位于 apps/spp_and_le/examples/ 下,属于应用层示例,不涉及底层射频固件实现。
Overview
2.4G 私有协议是杰理 AC63 系列芯片在 2.4GHz 频段上运行的私有射频数据链路。在 SDK 中它呈现为两种形态:
- 承载于标准 BLE 连接之上(conn_24g):利用 BLE GATT 的 ATT 通道传输私有数据。这样做的好处是直接复用成熟的连接管理、配对绑定(SM)与加密链路,同时通过自定义特征值(如
ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE)传输应用私有数据,主机侧使用ATT_OP_WRITE_WITHOUT_RESPOND实现低开销周期性发送。 - 独立的非连接私有射频通道(nonconn_24g):不建立任何 BLE 连接,射频控制器直接按私有协议收发。适合超低时延、点对多点或无需配对绑定的场景,但要求板级配置仅使能 BLE(
TCFG_USER_BLE_ENABLE && !TCFG_USER_EDR_ENABLE)。
Dongle 示例是 2.4G 私有协议最典型的商业化形态:一个小型 USB 接收器(Dongle)作为 BLE Central 与 2.4G 从机(键鼠/遥控器)建立连接,将收到的数据解析为 HID 报告,再通过板载 USB 设备控制器(usb_hid_devices.c)以 USB HID 协议上报给 PC。Dongle 侧还集成了 OTA 中心(ota_dg_central.c),支持通过 BLE 对从机进行空中升级,以及可选的 EDR HID(edr_hid_user.c)实现蓝牙经典模式下的 HID 服务。
三个示例共用同一套应用框架:每个示例都实现 struct application_operation(state_machine + event_handler),并通过 REGISTER_APP 之类的宏注册为独立应用,由 app_action.h 中的 action(如 ACTION_CONN_24G_MAIN、ACTION_NOCONN_24G_MAIN、ACTION_DONGLE_MAIN)触发启动。
Architecture
下图展示了三个示例应用与协议栈、USB 设备、上位机之间的整体结构关系:
flowchart TD
subgraph sg_Apps["应用层 examples"]
AppConn24G["app_conn_24g.c<br/>连接型 2.4G"]
AppNonConn24G["app_nonconn_24g.c<br/>非连接型 2.4G"]
AppDongle["app_dongle.c<br/>Dongle 接收器"]
end
subgraph sg_Conn24G["conn_24g 模块"]
B24GServer["ble_24g_server.c<br/>GATT Server"]
B24GClient["ble_24g_client.c<br/>GATT Client"]
B24GProfile["ble_24g_profile.h<br/>自定义 2.4G Profile"]
end
subgraph sg_NonConn24G["nonconn_24g 模块"]
B24GDeal["ble_24g_deal.c<br/>2.4G 私有数据处理"]
end
subgraph sg_Dongle["dongle 模块"]
BLEdgCentral["ble_dg_central.c<br/>BLE Central"]
OtaDgCentral["ota_dg_central.c<br/>OTA Central"]
EdrHidUser["edr_hid_user.c<br/>EDR HID"]
UsbHidDev["usb_hid_devices.c<br/>USB HID 设备"]
UsbHidDev2["usb_second_hid_devices.c<br/>第二路 USB HID"]
end
subgraph sg_Stack["协议栈/射频"]
BTStack["btstack + btctrler<br/>BLE 协议栈"]
RF24G["2.4G 私有射频控制器"]
end
subgraph sg_PC["外部"]
PC["PC / HOST 上位机"]
end
AppConn24G --> B24GServer
AppConn24G --> B24GClient
B24GServer --> B24GProfile
B24GClient --> B24GProfile
B24GServer --> BTStack
B24GClient --> BTStack
AppNonConn24G --> B24GDeal
B24GDeal --> RF24G
AppDongle --> BLEdgCentral
AppDongle --> OtaDgCentral
AppDongle --> EdrHidUser
AppDongle --> UsbHidDev
AppDongle --> UsbHidDev2
BLEdgCentral --> BTStack
OtaDgCentral --> BTStack
UsbHidDev --> PC
UsbHidDev2 --> PC
结构要点:
- conn_24g 应用同时引用 GATT Server 与 Client 配置(
conn_24g_server_init_cfg/conn_24g_client_init_cfg),由同一块gatt_ctrl_t conn_24g_gatt_control_block统一管理 MTU、发送缓存与安全配置,体现"连接型"对称设计——主机/从机角色由运行时决定。 - nonconn_24g 不经过 GATT 层,数据流直接从应用进入私有射频控制器,链路最短、时延最低。
- dongle 处于双向桥接位置:下行通过 BLE Central(
ble_dg_central.c)或私有射频与从机通信,上行通过 USB HID 设备(usb_hid_devices.c)与 PC 通信,是 2.4G 私有协议生态中"接收器"一侧的完整参考实现。
连接型 2.4G:conn_24g
编译开关与约束
整个示例由 CONFIG_APP_CONN_24G 宏控制编译。文件开头通过预处理约束保证运行前提:只支持 BLE,不支持 EDR,否则直接编译报错:
#if CONFIG_APP_CONN_24G
#if TCFG_USER_EDR_ENABLE
//只支持BLE
#error " only support ble !!!!!!"
#endif
//是否打开2.4G持续发送数据
#define CONN_24G_KEEP_SEND_EN 1 //just for 2.4gtest keep data
Source: app_conn_24g.c
设计意图:2.4G 私有协议在这里复用了 BLE 的链路层与连接管理,因此 EDR(经典蓝牙)必须关闭,避免双模控制器资源竞争;CONN_24G_KEEP_SEND_EN 是专为射频产测/吞吐测试提供的"持续发送"开关。
安全与 GATT 控制块
示例通过静态配置块完成协议栈初始化参数注入:
#define PASSKEY_ENABLE 0
//ATT发送的包长, note: 23 <=need >= MTU
#define ATT_LOCAL_MTU_SIZE (64)
//ATT缓存的buffer大小, note: need >= 23,可修改
#define ATT_SEND_CBUF_SIZE (30)
static const sm_cfg_t sm_init_config = {
.master_security_auto_req = 1,
.master_set_wait_security = 1,
.slave_security_auto_req = 0,
.slave_set_wait_security = 0,
#if PASSKEY_ENABLE
.io_capabilities = IO_CAPABILITY_DISPLAY_ONLY,
#else
.io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT,
#endif
.authentication_req_flags = SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION,
.min_key_size = 7,
.max_key_size = 16,
.sm_cb_packet_handler = NULL,
};
//gatt 初始化gatt配置
extern const gatt_server_cfg_t conn_24g_server_init_cfg;
extern const gatt_client_cfg_t conn_24g_client_init_cfg;
//gatt 控制块初始化
static gatt_ctrl_t conn_24g_gatt_control_block = {
//public
.mtu_size = ATT_LOCAL_MTU_SIZE,
.cbuffer_size = ATT_SEND_CBUF_SIZE,
.multi_dev_flag = 0,
//config
#if CONFIG_BT_GATT_SERVER_NUM
.server_config = &conn_24g_server_init_cfg,
#else
.server_config = NULL,
#endif
#if CONFIG_BT_GATT_CLIENT_NUM
.client_config = &conn_24g_client_init_cfg,
#else
.client_config = NULL,
#endif
#if CONFIG_BT_SM_SUPPORT_ENABLE
.sm_config = &sm_init_config,
#else
.sm_config = NULL,
#endif
//cbk,event handle
.hci_cb_packet_handler = NULL,
};
Source: app_conn_24g.c
要点解读:
- MTU 64 / 发送缓存 30:
ATT_LOCAL_MTU_SIZE决定单包 ATT 数据长度(注释明确要求23 <= need >= MTU),ATT_SEND_CBUF_SIZE决定发送缓冲大小。二者共同决定 2.4G 数据链路的吞吐上限。 - 安全策略:主机侧
master_security_auto_req = 1且master_set_wait_security = 1,即主机主动发起并等待安全流程;IO_CAPABILITY_NO_INPUT_NO_OUTPUT+SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION表示支持绑定与中间人保护,但不弹窗配对(适合键鼠类无屏设备)。 - Server/Client 双配置:
server_config与client_config均指向该示例自己的 GATT 配置(定义于ble_24g_server.c/ble_24g_client.c),说明同一份固件既可当主机也可当从机。
数据发送路径
conn_24g_phy_test() 是连接建立后周期性发送私有数据的核心函数:
static u8 con_handle = 0; //连接handle
static u8 conn_24g_phy_test_timer_id = 0; //2.4g数据发送定时器id号
//----------------------------------------------------------------------------
//2.4g主机发送数据函数
static void conn_24g_phy_test(void)
{
static u32 count = 0;
count++;
ble_comm_att_send_data(con_handle, ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND);
log_info("con_handle %d send data: %d", con_handle, count);
}
Source: app_conn_24g.c 与 app_conn_24g.c
该函数演示了 2.4G 私有数据在连接型模式下的最小发送单元:
con_handle:当前 BLE 连接的句柄,由连接建立回调写入;ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE:ble_24g_profile.h中自定义 2.4G 服务(Serviceae01)下特征值 1 的值句柄,即"私有数据通道";- 每次发送 16 字节的递增计数,
ATT_OP_WRITE_WITHOUT_RESPOND(无应答写)省去对端 ACK,配合定时器可达到较高发送频率,符合 2.4G 私有协议低延迟、周期性上报(如鼠标坐标、按键状态)的典型需求。
主机/从机与角色
ble_24g_client.c 承担主机(Central)侧扫描、连接、发现服务与写特征值的逻辑;ble_24g_server.c 承担从机(Peripheral)侧广播与响应。二者通过 conn_24g_server_init_cfg / conn_24g_client_init_cfg 注入 GATT 控制块,具体的角色切换(广播还是扫描)由应用运行时的 intent/action 触发,示例默认以主机身份运行并周期调用 conn_24g_phy_test() 发送数据。
非连接型 2.4G:nonconn_24g
编译开关与板级约束
示例由 CONFIG_APP_NONCONN_24G 宏控制编译,且强制要求"只开 BLE、关 EDR",否则编译失败:
#if CONFIG_APP_NONCONN_24G
#if !(TCFG_USER_BLE_ENABLE && (!TCFG_USER_EDR_ENABLE))
#error "board config error, confirm!!!!!!"
#endif
static u8 is_app_noconn_active = 0;
Source: app_nonconn_24g.c
与 conn_24g 的差别在于:非连接型不需要 GATT 服务/客户端配置,射频链路完全由私有协议控制,因此约束条件直接写死在板级配置校验中。
应用启动流程
static void noconn_app_start()
{
log_info("=======================================");
log_info("-----------nonconn_24g demo------------");
log_info("=======================================");
log_info("app_file: %s", __FILE__);
clk_set("sys", BT_NORMAL_HZ);
//有蓝牙
#if TCFG_USER_BLE_ENABLE
u32 sys_clk = clk_get("sys");
bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);
btstack_ble_start_before_init(NULL, 0);
btstack_init();
#endif
/* 按键消息使能 */
sys_key_event_enable();
}
Source: app_nonconn_24g.c
启动顺序体现了 AC63 蓝牙应用的固定初始化序列:
clk_set("sys", BT_NORMAL_HZ):将系统时钟切换到蓝牙正常工作频率;bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0):按晶振频率与系统时钟配置射频 PLL;btstack_ble_start_before_init(NULL, 0):BLE 协议栈预初始化(在正式btstack_init()之前完成底层准备);btstack_init():协议栈正式初始化,随后由ble_24g_deal.c处理 2.4G 私有数据收发;sys_key_event_enable():使能按键消息,供测试按键触发数据发送。
应用状态机与事件分发
static int noconn_state_machine(struct application *app, enum app_state state, struct intent *it)
{
switch (state) {
case APP_STA_CREATE:
break;
case APP_STA_START:
if (!it) {
break;
}
switch (it->action) {
case ACTION_NOCONN_24G_MAIN:
noconn_app_start();
break;
}
break;
case APP_STA_PAUSE:
break;
case APP_STA_RESUME:
break;
case APP_STA_STOP:
break;
case APP_STA_DESTROY:
log_info("APP_STA_DESTROY\n");
break;
}
return 0;
}
static int noconn_bt_hci_event_handler(struct bt_event *bt)
{
//对应原来的蓝牙连接上断开处理函数 ,bt->value=reason
log_info("----%s reason %x %x", __FUNCTION__, bt->event, bt->value);
#if TCFG_USER_BLE_ENABLE
bt_comm_ble_hci_event_handler(bt);
#endif
return 0;
}
Source: app_nonconn_24g.c
noconn_state_machine是标准应用状态机,仅响应APP_STA_START+ACTION_NOCONN_24G_MAIN组合,其余状态留空,说明该示例生命周期极简;noconn_bt_hci_event_handler把 HCI 层事件(连接/断开、原因值bt->value)统一转交bt_comm_ble_hci_event_handler处理,这是所有 BLE 应用共用的事件收敛点。
软关机处理
static void noconn_set_soft_poweroff(void)
{
log_info("set_soft_poweroff\n");
is_app_noconn_active = 1;
//必须先主动断开蓝牙链路,否则要等链路超时断开
#if TCFG_USER_BLE_ENABLE
btstack_ble_exit(0);
#endif
power_set_soft_poweroff();
}
Source: app_nonconn_24g.c
注释与代码共同说明了关机时序的设计意图:必须先 btstack_ble_exit(0) 主动断开链路,再执行 power_set_soft_poweroff(),否则系统要等待链路超时才能进入软关机,造成明显的关机延迟。这一顺序同样适用于 conn_24g 与 dongle 工程。
数据面
ble_24g_deal.c 是本示例的 2.4G 数据面实现,负责私有射频数据的组包、解析与上层回调。与 conn_24g 依赖 ble_comm_att_send_data 走 GATT 通道不同,这里的数据直接由射频控制器收发,因此时延不受连接事件间隔(connection interval)约束,更贴近"私有协议"的原始形态。该文件的详细收发算法属于示例配套内容,可在源文件中按需扩展。
2.4G Dongle 示例:dongle
编译开关与能力约束
CONFIG_APP_DONGLE 控制编译。Dongle 同时涉及 BLE 中心、USB HID、OTA 三条链路,因此约束最多:
#if CONFIG_APP_DONGLE
#if 0//TCFG_USER_EDR_ENABLE && TCFG_USER_BLE_ENABLE
//不支持同时打开
#error " not support double bt !!!!!!"
#endif
#if USER_SUPPORT_PROFILE_HID && USER_SUPPORT_PROFILE_SPP
//不支持同时打开
#error " not support double profile!!!!!!"
#endif
//2.4G模式: 0---ble, 非0---2.4G配对码
#define CFG_RF_24G_CODE_ID (0) //32bits
/* #define CFG_RF_24G_CODE_ID (0x5555AAAA) */
static u8 is_app_dongle_active = 0;
/*测试两个usb设备上行 send*/
#define CONFIG_HIDKEY_REPORT_TEST 0//(BIT(0)|BIT(1))/*for test usb channel:bit0~ch1,bit1-ch2*/
Source: app_dongle.c
设计意图:
CFG_RF_24G_CODE_ID是 Dongle 与 2.4G 从机之间的"配对码":0表示走标准 BLE 连接(此时 Dongle 作为 BLE Central),非 0 的 32 位值(如0x5555AAAA)表示启用私有 2.4G 配对过滤——只有配对码一致的设备才能互通。这一设计把"私有协议标识"和"BLE 链路"解耦,同一份 Dongle 固件可适配两种从机形态。- HID 与 SPP 互斥:Dongle 上行是 HID 语义(键鼠报告),因此禁止同时使能 SPP profile,避免 USB 类与蓝牙 profile 抢占资源。
CONFIG_HIDKEY_REPORT_TEST:仅用于产测,可分别向两路 USB 设备通道(bit0→ch1、bit1→ch2)注入测试报告,验证双 USB HID 设备上行。
HID 报告描述符
Dongle 通过 HID 报告描述符向上位机声明按键能力。示例内置两套:消费类按键(音量/播放等媒体键)与键盘/自定义/鼠标复合设备:
//==========hid_key
#define HIDKEY_REPORT_ID 0x1
static const u8 sHIDReportDesc_hidkey[] = {
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, HIDKEY_REPORT_ID, // Report ID (1)
0x09, 0xE9, // Usage (Volume Increment)
0x09, 0xEA, // Usage (Volume Decrement)
0x09, 0xCD, // Usage (Play/Pause)
0x09, 0xE2, // Usage (Mute)
0x09, 0xB6, // Usage (Scan Previous Track)
0x09, 0xB5, // Usage (Scan Next Track)
0x09, 0xB3, // Usage (Fast Forward)
0x09, 0xB4, // Usage (Rewind)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x10, // Report Count (16)
0x81, 0x02, // Input (Data,Var,Abs,...)
0xC0, // End Collection
// 35 bytes
};
// consumer key
#define CONSUMER_VOLUME_INC 0x0001
#define CONSUMER_VOLUME_DEC 0x0002
#define CONSUMER_PLAY_PAUSE 0x0004
#define CONSUMER_MUTE 0x0008
#define CONSUMER_SCAN_PREV_TRACK 0x0010
#define CONSUMER_SCAN_NEXT_TRACK 0x0020
#define CONSUMER_SCAN_FRAME_FORWARD 0x0040
#define CONSUMER_SCAN_FRAME_BACK 0x0080
//==========键盘 1
#define KEYBOARD_REPORT_ID 0x1
#define COUSTOM_CONTROL_REPORT_ID 0x2
#define MOUSE_POINT_REPORT_ID 0x3
static const u8 sHIDReportDesc_keyboard1[] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, KEYBOARD_REPORT_ID,// Report ID (1)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Var,Abs,...)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Const,Array,Abs,...)
...
Source: app_dongle.c
- 消费类描述符(35 字节)声明 8 个媒体键位(音量增/减、播放/暂停、静音、上一曲/下一曲、快进/快退),16 bit 输入字段对应
CONSUMER_*宏的位掩码; - 键盘描述符使用多 Report ID 方案(键盘
0x1、自定义控制0x2、鼠标0x3),使单个 USB 接口能同时承载键盘与鼠标语义——这正是 2.4G 键鼠接收器的标准做法。
应用注册与状态机
static int dongle_state_machine(struct application *app, enum app_state state, struct intent *it)
{
switch (state) {
...
case APP_STA_START:
if (!it) {
break;
}
switch (it->action) {
case ACTION_DONGLE_MAIN:
dongle_app_start();
break;
}
break;
...
}
}
static const struct application_operation app_dongle_ops = {
.state_machine = dongle_state_machine,
.event_handler = dongle_event_handler,
...
};
static const struct application_entity app_dongle_entity = {
.name = "dongle",
.action = ACTION_DONGLE_MAIN,
.ops = &app_dongle_ops,
...
};
Source: app_dongle.c 与 app_dongle.c
应用以 "dongle" 为名注册,ACTION_DONGLE_MAIN 触发 dongle_app_start()。dongle_app_start() 内部会完成:时钟/PLL 配置、btstack_init() 协议栈初始化、BLE Central(ble_dg_central.c)扫描连接从机、USB HID 设备(usb_hid_devices.c)枚举初始化,以及注册 OTA 中心(ota_dg_central.c)以便对从机升级。各子模块通过事件回调把"2.4G 数据到达"转换为"HID 报告发送"。
核心流程
Dongle 数据上行链路
sequenceDiagram
participant S as 2.4G 从机<br/>(键鼠/遥控器)
participant D as Dongle BLE Central<br/>(ble_dg_central.c)
participant A as 应用层<br/>(app_dongle.c)
participant U as USB HID 设备<br/>(usb_hid_devices.c)
participant PC as PC 上位机
S->>D: 2.4G 私有数据<br/>(配对码/编码ID过滤)
D->>A: 数据到达事件回调
A->>A: 解析并映射为 HID 报告
A->>U: 写入报告 (Report ID 1/2/3)
U->>PC: USB 中断传输上报
PC-->>U: USB ACK / 轮询取走
流程说明:从机按键/移动事件 → Dongle 射频接收(ble_dg_central.c)→ 应用层按 CONSUMER_* 位掩码或键盘扫描码组装报告 → usb_hid_devices.c 通过 USB HID 接口发送 → PC 端系统识别为键盘/鼠标/多媒体设备。由于 HID 是"事件驱动 + 状态上报"协议,Dongle 应用必须维护上一次的报告状态(如按键释放时清零),才能正确表达按下/释放语义。
连接型 2.4G 周期发送
sequenceDiagram
participant T as 定时器<br/>(conn_24g_phy_test_timer_id)
participant M as 2.4G 主机<br/>(app_conn_24g.c)
participant C as GATT 通道<br/>(con_handle)
participant S as 2.4G 从机<br/>(ble_24g_server.c)
T->>M: 周期触发 (CONN_24G_KEEP_SEND_EN)
M->>M: count++ 组包 (16字节)
M->>C: ble_comm_att_send_data(con_handle,<br/>ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE,<br/>ATT_OP_WRITE_WITHOUT_RESPOND)
C->>S: ATT Write Without Respond
S-->>M: 链路层 ACK (无应用应答)
配置选项
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_APP_CONN_24G | 宏 | 0 | 连接型 2.4G 示例编译开关 |
CONFIG_APP_NONCONN_24G | 宏 | 0 | 非连接型 2.4G 示例编译开关 |
CONFIG_APP_DONGLE | 宏 | 0 | Dongle 示例编译开关 |
CFG_RF_24G_CODE_ID | 宏 | 0 | 2.4G 配对码(32 位);0=BLE 模式,非 0=私有配对码 |
CFG_RF_24G_CODE_ID_ADV | 宏 | 见板级配置 | 2.4G 编码 ID 广播(conn_24g_coded_test 初始值) |
CONN_24G_KEEP_SEND_EN | 宏 | 1 | 2.4G 持续发送测试开关(产测用) |
ATT_LOCAL_MTU_SIZE | 宏 | 64 | ATT 发送包长(要求 23 <= need >= MTU) |
ATT_SEND_CBUF_SIZE | 宏 | 30 | ATT 发送缓存大小(要求 >= 23) |
PASSKEY_ENABLE | 宏 | 0 | 1 时用 IO_CAPABILITY_DISPLAY_ONLY 显示配对码 |
CONFIG_HIDKEY_REPORT_TEST | 宏 | 0 | 双 USB 通道上行测试位掩码(bit0→ch1, bit1→ch2) |
HIDKEY_REPORT_ID | 宏 | 0x1 | 消费类 HID 报告 ID |
KEYBOARD_REPORT_ID | 宏 | 0x1 | 键盘报告 ID |
COUSTOM_CONTROL_REPORT_ID | 宏 | 0x2 | 自定义控制报告 ID |
MOUSE_POINT_REPORT_ID | 宏 | 0x3 | 鼠标报告 ID |
TCFG_USER_EDR_ENABLE | 板级宏 | 依板级配置 | 三个示例均要求关闭 EDR(编译期校验) |
TCFG_USER_BLE_ENABLE | 板级宏 | 依板级配置 | 三个示例均要求使能 BLE |
API 参考
以下为本页三个示例中直接调用、且对二次开发最重要的接口(签名以实际头文件/源码为准)。
ble_comm_att_send_data(con_handle, handle, data, len, att_op)
通过 ATT 通道向指定连接发送数据,是 conn_24g 主机发送 2.4G 私有数据的核心接口。
参数:
con_handle(u8):BLE 连接句柄,conn_24g示例中由全局con_handle维护;handle(u16):目标特征值句柄,如ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE(自定义 2.4G 服务的特征值 1);data(u8*):待发送数据指针;len(u16):数据长度(示例中为 16 字节);att_op(u8):ATT 操作类型,示例使用ATT_OP_WRITE_WITHOUT_RESPOND(无应答写)。
返回: 发送结果(成功/失败),失败时需检查连接是否断开、缓存是否满。
用法示例:
ble_comm_att_send_data(con_handle, ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND);
Source: app_conn_24g.c
btstack_ble_start_before_init(NULL, 0) 与 btstack_init()
BLE 协议栈的两段式初始化:先做底层准备,再正式初始化。nonconn_24g 与 dongle 均在 xxx_app_start() 中按 clk_set → bt_pll_para → btstack_ble_start_before_init → btstack_init 的顺序调用,顺序不可颠倒。
Source: app_nonconn_24g.c
btstack_ble_exit(0) 与 power_set_soft_poweroff()
软关机组合:必须先 btstack_ble_exit(0) 主动断开蓝牙链路,再 power_set_soft_poweroff() 进入软关机,避免等待链路超时。
Source: app_nonconn_24g.c
应用注册结构体
static const struct application_operation app_dongle_ops = {
.state_machine = dongle_state_machine,
.event_handler = dongle_event_handler,
};
static const struct application_entity app_dongle_entity = {
.name = "dongle",
.action = ACTION_DONGLE_MAIN,
.ops = &app_dongle_ops,
};
Source: app_dongle.c
说明: state_machine 处理应用生命周期(CREATE/START/PAUSE/RESUME/STOP/DESTROY),event_handler 接收系统事件(电源、按键、蓝牙连接状态等);action 字段(如 ACTION_DONGLE_MAIN、ACTION_NOCONN_24G_MAIN)由应用框架在启动时派发,驱动 xxx_app_start() 执行。
失败模式、边界情况与并发
编译期约束(防止错误配置)
三个示例都通过 #error 在编译期拦截非法配置,这是 SDK 常用的"配置即契约"手段:
| 示例 | 约束 | 违反后果 |
|---|---|---|
| conn_24g | TCFG_USER_EDR_ENABLE 必须关闭 | #error " only support ble !!!!!!" |
| nonconn_24g | 必须 TCFG_USER_BLE_ENABLE && !TCFG_USER_EDR_ENABLE | #error "board config error, confirm!!!!!!" |
| dongle | EDR+BLE 不同时开;HID+SPP profile 不同时开 | #error " not support double bt/profile !!!!!!" |
连接与发送边界
- 发送失败:
ATT_OP_WRITE_WITHOUT_RESPOND无应用层应答,发送失败只能通过链路层/HCI 事件感知(noconn_bt_hci_event_handler中bt->value为断开原因)。对端掉线后con_handle失效,需在事件回调中重建连接。 - ATT 缓存满:
ATT_SEND_CBUF_SIZE(默认 30)是发送缓存上限,持续发送(CONN_24G_KEEP_SEND_EN=1)若快于链路消耗会阻塞/丢弃,产测时需根据 MTU 与连接间隔核算吞吐。 - 软关机时序:不先
btstack_ble_exit会导致关机卡在链路超时上,这是嵌入式低功耗场景的常见故障点。
并发与线程模型
示例代码运行在蓝牙协议栈任务与应用任务之上,应用回调(HCI 事件、定时器回调)与 USB HID 发送分属不同执行上下文。Dongle 应用中"2.4G 接收→HID 上报"必须通过消息/事件队列解耦(sys_event_notify、事件回调),避免在中断或协议栈上下文直接操作 USB 发送,防止竞态与阻塞协议栈。
性能与运维注意事项
- 吞吐:conn_24g 单包 16 字节 + MTU 64 + 无应答写,适合周期性小包;如需更大载荷,可增大
ATT_LOCAL_MTU_SIZE与ATT_SEND_CBUF_SIZE并同步修改对端 MTU 协商。 - 时延:nonconn_24g 不经 GATT,时延仅取决于私有射频调度,适合对时延敏感的控制类应用;conn_24g 的发送节奏受连接事件间隔约束。
- 产测:
CONN_24G_KEEP_SEND_EN与CONFIG_HIDKEY_REPORT_TEST均为产测/调试预留的"持续注入"开关,量产固件应关闭。 - 日志:三个示例均定义
LOG_TAG_CONST(CONN_24G/NCON_24G/DONGLE),可通过LOG_*_ENABLE宏控制输出级别,方便现场定位连接与数据问题。
扩展点
- 自定义 HID 能力:修改
sHIDReportDesc_hidkey[]/sHIDReportDesc_keyboard1[]描述符并同步更新CONSUMER_*位掩码,即可增加/裁剪按键功能;多 Report ID 方案已预留自定义控制(COUSTOM_CONTROL_REPORT_ID=0x2)与鼠标(MOUSE_POINT_REPORT_ID=0x3)通道。 - 私有数据格式:conn_24g 的特征值句柄
ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE定义于ble_24g_profile.h,可通过扩展 Serviceae01下的特征值承载更丰富的 2.4G 私有协议字段;nonconn_24g 的协议编解码集中在ble_24g_deal.c,可自由组包。 - 配对机制:
CFG_RF_24G_CODE_ID从 0(BLE 模式)切换为非 0 配对码即可启用私有 2.4G 配对过滤;sm_init_config的authentication_req_flags、io_capabilities可调整绑定与配对交互策略。 - OTA 升级:
ota_dg_central.c提供 Dongle 作为 OTA 中心的参考实现,可对接杰理 RCSP/OTA 流程对从机进行空中升级。 - 多路 USB:
usb_second_hid_devices.c展示了第二路 USB HID 设备,配合CONFIG_HIDKEY_REPORT_TEST位掩码可实现一拖二(如键鼠套装分通道上报)。
Related Links
- app_conn_24g.c(连接型 2.4G 应用入口)
- ble_24g_server.c / ble_24g_client.c(2.4G GATT 服务端/客户端)
- ble_24g_profile.h(自定义 2.4G Profile 定义)
- app_nonconn_24g.c(非连接型 2.4G 应用入口)
- ble_24g_deal.c(非连接型 2.4G 数据处理)
- app_dongle.c(Dongle 应用入口与 HID 描述符)
- ble_dg_central.c(Dongle BLE Central)
- ota_dg_central.c(Dongle OTA 中心)
- usb_hid_devices.c(USB HID 设备上行)
- edr_hid_user.c(EDR HID 用户)
- 相关主题:通用 BLE GATT 应用示例(
apps/spp_and_le/examples/下其它目录)、USB HID 协议栈文档,请参见对应目录的独立 Wiki 页面。