杰理 SDK 文档中心
首页
首页
  • 概述

    • SDK 概览与产品定位
    • 支持芯片平台与蓝牙认证
    • SDK 架构与目录分层
  • 快速开始

    • 环境搭建与编译工具链
    • 编译构建系统
    • 板级工程与配置
    • 烧录与固件升级工具
  • 应用工程

    • 应用选择与工程总览
    • SPP + BLE 数传应用框架
    • 透传与 AT 指令示例
    • BLE 广播/中心与定位示例
    • 2.4G 私有协议与 Dongle 示例
    • 云平台接入示例
    • HID 人机交互应用框架
    • HID 示例工程(键盘/鼠标/遥控器/手柄)
    • Bluetooth Mesh 应用框架
    • Mesh 模型与 Mesh DFU 固件升级
    • Mesh 音频编解码演示
  • 芯片平台与硬件抽象

    • 芯片平台总览与差异
    • 音频编解码与时钟管理
    • 外设驱动接口(ADC/IIC/SPI/PWM/LED/充电)
    • 芯片配置工具与下载支持
  • 蓝牙协议栈

    • 蓝牙控制器层(btctrler)
    • 蓝牙协议栈与 Profile(btstack)
    • 蓝牙模块选择与配置
  • 媒体与音频框架

    • 音频流框架
    • 音频编解码与 A2DP 媒体
    • 音频效果处理(EQ/频谱/变调/环绕/超低音)
    • 本地 TWS 与音频同步
  • 系统服务与运行时

    • 实时操作系统与任务调度
    • 消息事件机制
    • 电源管理与低功耗
    • 存储与配置系统
    • 设备驱动框架(USB/RTC)
  • 应用公共组件

    • 音频应用组件
    • 设备外设抽象(按键/触摸/传感器/存储)
    • 蓝牙公共模块与消息联动
    • 调试与配置组件
    • 杰理关键词唤醒(jl_kws)
  • 第三方协议与云平台接入

    • 杰理 RCSP 私有协议
    • 低功耗蓝牙 Mesh 方案(llsync_mesh)
    • Sig Mesh 方案
    • 涂鸦协议接入
    • 腾讯连连接入
    • 华为 HiLink 接入
  • 固件升级与维护

    • OTA 升级机制
    • 升级补丁与版本维护
    • 升级工具链(BLE OTA / USB Dongle OTA)
  • 文档与开发资源

    • 数据手册与架构文档
    • 协议与云平台开发文档
    • 常见问题与技术支持

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 中它呈现为两种形态:

  1. 承载于标准 BLE 连接之上(conn_24g):利用 BLE GATT 的 ATT 通道传输私有数据。这样做的好处是直接复用成熟的连接管理、配对绑定(SM)与加密链路,同时通过自定义特征值(如 ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE)传输应用私有数据,主机侧使用 ATT_OP_WRITE_WITHOUT_RESPOND 实现低开销周期性发送。
  2. 独立的非连接私有射频通道(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 服务(Service ae01)下特征值 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 蓝牙应用的固定初始化序列:

  1. clk_set("sys", BT_NORMAL_HZ):将系统时钟切换到蓝牙正常工作频率;
  2. bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0):按晶振频率与系统时钟配置射频 PLL;
  3. btstack_ble_start_before_init(NULL, 0):BLE 协议栈预初始化(在正式 btstack_init() 之前完成底层准备);
  4. btstack_init():协议栈正式初始化,随后由 ble_24g_deal.c 处理 2.4G 私有数据收发;
  5. 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宏0Dongle 示例编译开关
CFG_RF_24G_CODE_ID宏02.4G 配对码(32 位);0=BLE 模式,非 0=私有配对码
CFG_RF_24G_CODE_ID_ADV宏见板级配置2.4G 编码 ID 广播(conn_24g_coded_test 初始值)
CONN_24G_KEEP_SEND_EN宏12.4G 持续发送测试开关(产测用)
ATT_LOCAL_MTU_SIZE宏64ATT 发送包长(要求 23 <= need >= MTU)
ATT_SEND_CBUF_SIZE宏30ATT 发送缓存大小(要求 >= 23)
PASSKEY_ENABLE宏01 时用 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_24gTCFG_USER_EDR_ENABLE 必须关闭#error " only support ble !!!!!!"
nonconn_24g必须 TCFG_USER_BLE_ENABLE && !TCFG_USER_EDR_ENABLE#error "board config error, confirm!!!!!!"
dongleEDR+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,可通过扩展 Service ae01 下的特征值承载更丰富的 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 页面。
Prev
BLE 广播/中心与定位示例
Next
云平台接入示例