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

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

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

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

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

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

HID 设备应用

AC630N 蓝牙 SoC 上的 HID(Human Interface Device,人机接口设备)应用层实现。该应用将芯片配置为蓝牙 HID 外设(鼠标 / 遥控器 Keyfob / 键盘),通过经典蓝牙(BR/EDR)与主机配对连接后,上报 HID 报告(Report)实现键鼠控制功能。

Purpose and Scope

本文档介绍 apps/hid 目录下的 HID 设备应用:应用框架与任务调度、启动与模式选择、三种 HID 产品形态(鼠标、Keyfob、键盘)、HID 协议层(hid_user.c)、配置系统(user_cfg.c)以及低功耗与电源管理行为。

本页范围之外的内容:

  • 底层蓝牙协议栈(btstack/btctrler 任务)的 HCI 实现,属于平台协议栈范畴。
  • 公共 HID profile 的详细 report 描述符(见 standard_hid.h 与 hid_user.c,本文仅作引用)。
  • 其他非 HID 应用(如音频/音箱应用)由其各自目录的文档覆盖。

Overview

HID 设备应用是 AC630N 系列芯片面向低成本键鼠/遥控外设市场提供的参考实现。与音频类应用(耳机、音箱)不同,HID 应用不需要音频 DSP 流水线,核心诉求是:

  1. 极低的 BOM 与功耗:通过低功耗窗口(lp_winsize)与停止模式(Endless Sleep)优化待机电流。
  2. 快速的连接体验:开机即广播/可发现,与主机(手机、PC、电视)一键配对。
  3. 多种产品形态复用同一套代码框架:通过编译宏 CONFIG_APP_MOUSE / CONFIG_APP_KEYFOB / CONFIG_APP_KEYBOARD 三选一,app_main() 决定启动哪个子应用。

应用运行在 JieLi 自研 RTOS 之上,由 task_info_table 声明的系统任务(app_core、sys_event、btctrler、btstack、systimer 等)协同工作。上层使用"应用 + 意图(Intent)"框架:每个应用是一个状态机,通过 struct intent 描述要执行的动作(ACTION_MOUSE_MAIN、ACTION_HID_MAIN、ACTION_KEYFOB、ACTION_BACK 等),由 start_app() 统一调度。

Architecture

flowchart TD
    subgraph sg_App["应用层 apps/hid"]
        AppMain["app_main.c<br/>应用入口与模式选择"]
        AppMouse["app_mouse.c<br/>鼠标应用"]
        AppKeyfob["app_keyfob.c<br/>遥控器应用"]
        AppKeyboard["app_keyboard.c<br/>键盘应用"]
        AppIdle["app_idle.c<br/>空闲/待机应用"]
        UserCfg["user_cfg.c<br/>蓝牙配置与VM存储"]
        Misc["misc.c / log_config.c<br/>工具与日志"]
    end

    subgraph sg_Profile["HID Profile 层"]
        HidUser["hid_user.c / hid_user.h<br/>HID 用户协议"]
        StdHid["standard_hid.h<br/>标准 HID 报告定义"]
    end

    subgraph sg_Stack["蓝牙协议栈层"]
        Btstack["btstack 任务"]
        Btctrler["btctrler 任务<br/>控制器驱动"]
        SysEvent["sys_event 任务"]
        SysTimer["systimer 任务"]
    end

    subgraph sg_Host["外部主机"]
        Host["PC / 手机 / 电视主机"]
    end

    AppMain -->|"CONFIG_APP_MOUSE / KEYFOB / KEYBOARD 三选一"| AppMouse
    AppMain -->|"CONFIG_APP_KEYFOB"| AppKeyfob
    AppMain -->|"CONFIG_APP_KEYBOARD"| AppKeyboard
    AppMain --> AppIdle
    AppMain --> UserCfg
    AppMouse --> HidUser
    AppKeyfob --> HidUser
    AppKeyboard --> HidUser
    HidUser --> StdHid
    HidUser --> Btstack
    Btstack --> Btctrler
    Btctrler --> SysEvent
    SysTimer --> AppIdle
    Btctrler <-->|"HCI / 射频"| Host

架构说明:

  • 应用层(apps/hid):app_main() 根据编译宏选择启动鼠标、Keyfob 或键盘子应用,三者都通过 app_idle.c 管理空闲状态;user_cfg.c 提供全局的蓝牙配置对象(名称、MAC、射频功率)并负责 BTIF/VM 区域的持久化读写。
  • HID Profile 层:hid_user.c 位于 apps/common/third_party_profile/jieli/,是公共的 HID 用户 profile 实现,承载 HID 连接的建立、report 上报与断开处理;standard_hid.h 定义标准 HID 报告结构。
  • 协议栈层:btstack 任务运行蓝牙主机协议栈,btctrler 任务驱动射频控制器,sys_event 分发系统事件(按键、连接、电源),systimer 提供定时唤醒能力。
  • 外部主机:通过经典蓝牙与芯片配对,接收 HID 报告。

应用框架与任务调度

系统任务表

HID 应用启动后,JieLi RTOS 依据 task_info_table 创建系统任务。每个任务由四元组描述:任务名、优先级、栈大小(字节)、队列大小:

/*任务列表 */
const struct task_info task_info_table[] = {
    {"app_core",            1,     640,   128  },
    {"sys_event",           7,     256,   0    },
    {"btctrler",            4,     512,   256  },
    {"btstack",             3,     768,  256  },
    {"systimer",		    7,	   128,   0	},
#ifdef CONFIG_UPDATA_ENABLE
    {"update",				1,	   320,   0	},
#endif
#if (RCSP_BTMATE_EN)
    {"rcsp_task",		2,		640,	128	},
#endif
    {0, 0},
};

来源:app_main.c

任务划分的设计意图:

  • app_core(优先级 1,栈 640B):承载整个应用状态机,优先级最低但栈最大,因为应用逻辑调用链最深。
  • sys_event(优先级 7):最高优先级,负责事件分发,保证按键/连接事件不被长任务阻塞。
  • btctrler / btstack:蓝牙控制器与主机协议栈分离,btctrler 栈内含中断上下文(256B 队列),btstack 负责 L2CAP/SDP/HID 等协议。
  • update 与 rcsp_task:通过 CONFIG_UPDATA_ENABLE(OTA 升级)与 RCSP_BTMATE_EN(杰理私有 RCSP 协议,用于手机 App 调试)条件编译,不使能时这些任务不创建,节省 RAM。

全局应用变量

APP_VAR app_var;

void app_var_init(void)
{
    app_var.play_poweron_tone = 1;

    app_var.auto_off_time =  TCFG_AUTO_SHUT_DOWN_TIME;
    app_var.warning_tone_v = 340;
    app_var.poweroff_tone_v = 330;
}

来源:app_main.c

app_var 是全局共享的应用状态结构:play_poweron_tone 控制开机提示音、auto_off_time 继承配置宏 TCFG_AUTO_SHUT_DOWN_TIME 作为自动关机阈值、warning_tone_v / poweroff_tone_v 为提示音频率(HID 外设通过蜂鸣器或 LED 反馈电量低/关机)。设计上把"可变配置"与"固定配置"分离:可运行时修改的放入 app_var,编译期确定的写入配置宏。

应用启动与模式选择

app_main() 是应用层唯一入口。它先处理 OTA 升级结果(update_result_deal()),随后根据编译宏三选一构造 Intent 并启动应用:

void app_main()
{
    struct intent it;

#ifdef CONFIG_UPDATA_ENABLE
    int update = 0;
    update = update_result_deal();
#endif

    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>app_main...\n");
    init_intent(&it);

#if (CONFIG_APP_MOUSE)
    it.name = "mouse";
    it.action = ACTION_MOUSE_MAIN;
#elif(CONFIG_APP_KEYFOB)
    it.name = "keyfob";
    it.action = ACTION_KEYFOB;
#elif(CONFIG_APP_KEYBOARD)
    it.name = "hid_key";
    it.action = ACTION_HID_MAIN;
#else
	ASSERT(0,"no app!!!");
#endif

	log_info("run app>>>%s",it.name);

    start_app(&it);
}

来源:app_main.c

这段代码揭示了产品形态的切换机制:同一套工程,通过 CONFIG_APP_* 系列宏决定固件是哪一种 HID 外设。

编译宏Intent 名称动作对应源文件
CONFIG_APP_MOUSEmouseACTION_MOUSE_MAINapp_mouse.c
CONFIG_APP_KEYFOBkeyfobACTION_KEYFOBapp_keyfob.c
CONFIG_APP_KEYBOARDhid_keyACTION_HID_MAINapp_keyboard.c
以上皆非—ASSERT(0,"no app!!!")编译/运行期报错

ASSERT(0) 兜底的设计意图:防止产线误配出"没有应用"的固件,把配置错误尽早暴露在开发阶段而不是流入量产。

应用切换机制

void app_switch(const char *name, int action)
{
    struct intent it;
    struct application *app;

    log_info("app_exit\n");

    init_intent(&it);
    app = get_current_app();
    if (app) {
        /*
         * 退出当前app, 会执行state_machine()函数中APP_STA_STOP 和 APP_STA_DESTORY
         */
        it.name = app->name;
        it.action = ACTION_BACK;
        start_app(&it);
    }

    /*
     * 切换到app (name)并执行action分支
     */
    it.name = name;
    it.action = action;
    start_app(&it);
}

来源:app_main.c

app_switch() 是"先退后进"的两段式切换:先向当前应用发送 ACTION_BACK 使其依次经历 APP_STA_STOP → APP_STA_DESTORY 状态(释放资源),再携带新应用的名称与动作启动目标应用。这种设计保证任意时刻只有一个应用处于活动状态,避免两个状态机同时操作蓝牙资源造成竞争。

三种 HID 应用形态

apps/hid 目录下每个子应用都是基于"意图(Intent)+ 状态机"的应用模块,共享 app_idle.c 作为空闲态管理。三者差异集中在按键扫描、报告组装与消费模式上:

鼠标应用(app_mouse.c)

通过 ACTION_MOUSE_MAIN 启动。实现鼠标位移(X/Y 偏移)与左右键/滚轮上报。典型应用场景:演示翻页笔、空中鼠标、2.4G 转蓝牙鼠标。其核心逻辑是读取传感器/按键输入 → 组装 HID Mouse Report → 通过 hid_user 接口上报。

遥控器应用(app_keyfob.c)

通过 ACTION_KEYFOB 启动。面向电视盒子/机顶盒遥控器场景,按键数量多、多为组合键(音量+、频道切换、语音键等),报告类型以 Consumer Control(消费类控制)为主。该形态重视低功耗:遥控器大部分时间处于休眠,按键唤醒后瞬时连接上报再休眠。

键盘应用(app_keyboard.c)

通过 ACTION_HID_MAIN 启动(Intent 名称 hid_key)。实现标准键盘报告(Modifier + 按键码数组),支持组合键(Ctrl+Alt+Del 等)。与鼠标应用相比,键盘报告数据结构更大(8 字节 Boot Report:1 字节修饰键 + 1 字节保留 + 6 字节按键码)。

说明:三个子应用的按键扫描与报告组装的详细实现位于各自源文件(app_mouse.c、app_keyfob.c、app_keyboard.c),本页聚焦其公共框架。

空闲应用(app_idle.c)

管理无操作状态下的待机策略,与 eSystemConfirmStopStatus() 联动:系统进入"未来时间里无任务超时唤醒"时,可选择 Endless Sleep(深度停止,1)或 100ms 定时唤醒(0)。这是 HID 外设续航的关键路径——待机电流直接决定纽扣电池寿命。

HID 协议层

HID 报告的上报并不由各子应用直接操作射频,而是通过公共 profile 层完成:

  • hid_user.c / hid_user.h:实现 HID profile 的 SDP 服务注册、L2CAP 中断通道/控制通道建立、report 发送与连接事件回调。应用层调用其接口完成"连接建立 → 上报 → 断开"全流程,无需关心 HCI 细节。
  • standard_hid.h:定义标准 HID 报告描述符(Mouse/Keyboard/Consumer)的数据结构,保证与主机操作系统(Windows/macOS/Android/iOS)的 HID 驱动兼容。

设计意图:把 HID profile 放在 apps/common/third_party_profile 而非 apps/hid 内部,是因为它是跨产品复用的第三方协议实现——未来若有新的 HID 产品(如游戏手柄),只需在 apps 下新增应用并复用该 profile,无需改动协议层。

配置系统(user_cfg.c)

蓝牙基础配置

BT_CONFIG bt_cfg = {
    .edr_name        = "JL_HID_DEBUG",
    .mac_addr        = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
    .tws_local_addr  = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
    .rf_power        = 10,
    .dac_analog_gain = 25,
    .mic_analog_gain = 7,
    .tws_device_indicate = 0x6688,
};

来源:user_cfg.c

bt_cfg 是全局蓝牙配置对象,要点:

  • edr_name = "JL_HID_DEBUG":默认蓝牙名称,量产前通过 bt_set_local_name() 改写。
  • mac_addr 全 0xff:表示"未烧录",首次上电时由系统从 BTIF 区域读取/生成真实地址。
  • rf_power = 10:射频发射功率档位,直接影响连接距离与功耗,量产按天线调试。
  • tws_device_indicate = 0x6688:杰理私有标识,用于配套 App 识别设备类型。

BTIF 与 VM 存储分区

//======================================================================================//
//                                 		BTIF配置项表                              		//
//	参数1: 配置项名字                               	    								//
//	参数2: 配置项需要多少个byte存储							    							//
//	说明: 配置项ID注册到该表后该配置项将读写于BTIF区域, 其它没有注册到该表       			//
//		  的配置项则默认读写于VM区域.														//
//======================================================================================//
const struct btif_item btif_table[] = {
// 	 	item id 		  	   	len   	//
    {CFG_BT_MAC_ADDR, 			6 },
    {CFG_BT_FRE_OFFSET,  		6 },   //测试盒矫正频偏值
    //{CFG_DAC_DTB,  			2 },
    //{CFG_MC_BIAS,  			1 },
    {0, 						0 },   //reserved cfg
};

//============================= VM 区域空间最大值 ======================================//
const int vm_max_size_config = VM_MAX_SIZE_CONFIG; //该宏在app_cfg中配置
//======================================================================================//

来源:user_cfg.c

存储设计的关键:BTIF 区域专门存放出厂校准类数据(MAC 地址、频偏矫正值),与 VM 区域(用户可改写配置)物理隔离。这样 OTA 升级或恢复出厂设置时不会丢失射频校准数据;而 vm_max_size_config 决定 VM 区域上限,需在 app_cfg 中按产品功能裁剪(HID 应用功能少,可配置得比音频应用小,节省 Flash)。

名称、地址与 PIN 码接口

const u8 *bt_get_mac_addr()
{
    return bt_cfg.mac_addr;
}

void bt_set_mac_addr(u8 *addr)
{
    memcpy(bt_cfg.mac_addr, addr, 6);
}

const char *bt_get_local_name()
{
    return (const char *)(bt_cfg.edr_name);
}

void bt_set_local_name(char *name, u8 len)
{
    memcpy(bt_cfg.edr_name, name, len);
    bt_cfg.edr_name[len] = 0;
}

const char *bt_get_pin_code()
{
    return "0000";
}

来源:user_cfg.c

这些 getter/setter 是协议栈与应用层之间的配置适配层:协议栈通过回调获取名称/地址/PIN 码,应用层(如产测、手机 App)通过 setter 修改。bt_get_pin_code() 固定返回 "0000"——HID 设备的 PIN 码用于传统配对流程(Legacy Pairing),0000 是行业惯例(多数主机对键盘/鼠标默认接受 0000),设计上牺牲部分安全性换取配对成功率与用户体验。

Core Flow — 设备启动到 HID 连接上报的完整流程

sequenceDiagram
    participant PWR as 上电复位
    participant APP as app_main (app_core)
    participant IDLE as app_idle
    participant SUB as 子应用 (mouse/keyfob/keyboard)
    participant CFG as user_cfg (BTIF/VM)
    participant STK as btstack / btctrler
    participant HID as hid_user profile
    participant HOST as 主机 (PC/手机)

    PWR->>APP: 系统启动,创建 task_info_table 任务
    APP->>APP: update_result_deal() 处理OTA结果
    APP->>APP: app_var_init() 初始化全局变量
    APP->>CFG: 读取 MAC/名称/频偏 (bt_get_*)
    APP->>APP: 按 CONFIG_APP_* 构造 Intent
    APP->>SUB: start_app(it) 启动子应用
    SUB->>IDLE: 进入空闲/可发现状态
    SUB->>HID: 注册 HID profile (SDP/L2CAP)
    HOST->>STK: 扫描到设备并发起配对
    STK->>CFG: bt_get_pin_code() 获取 "0000"
    STK-->>HOST: 配对成功,建立 HID 连接
    HOST->>HID: 中断通道就绪
    SUB->>HID: 上报 HID Report (鼠标/按键/消费类)
    HID->>STK: L2CAP 中断通道发送
    STK-->>HOST: 射频发送报告
    HOST->>SUB: 无操作超时
    SUB->>IDLE: eSystemConfirmStopStatus() 进入停止/定时唤醒

流程要点:

  1. 启动阶段:app_main() 先处理 OTA 升级结果(避免升级残留导致启动异常),再初始化 app_var,随后按编译宏三选一启动子应用。
  2. 配置加载:协议栈在初始化时通过 bt_get_mac_addr() / bt_get_local_name() / bt_get_pin_code() 等接口从 bt_cfg 与 BTIF 区域读取参数——这是设备身份(可被发现、可配对)的基础。
  3. 连接阶段:主机扫描到 JL_HID_DEBUG(或量产改写后的名称)发起配对,协议栈用 PIN "0000" 完成传统配对,hid_user 建立 SDP 服务与 L2CAP 中断/控制通道。
  4. 上报阶段:子应用将按键/位移转换为标准 HID 报告,经 hid_user 在中断通道上发送给主机,主机 HID 驱动解析后产生键鼠事件。
  5. 休眠阶段:空闲超时后进入 Endless Sleep 或 100ms 定时唤醒,等待下一次按键中断唤醒系统。

Usage Examples

示例 1:新增一种 HID 产品形态

以下模式展示了如何把现有代码复用到新产品:在 app_main() 中为新产品增加编译分支并指定 Intent(沿用 app_switch() 机制可支持运行时切换):

#if (CONFIG_APP_MOUSE)
    it.name = "mouse";
    it.action = ACTION_MOUSE_MAIN;
#elif(CONFIG_APP_KEYFOB)
    it.name = "keyfob";
    it.action = ACTION_KEYFOB;
#elif(CONFIG_APP_KEYBOARD)
    it.name = "hid_key";
    it.action = ACTION_HID_MAIN;
#else
	ASSERT(0,"no app!!!");
#endif

	log_info("run app>>>%s",it.name);

    start_app(&it);

来源:app_main.c

示例 2:量产时修改设备名称与 MAC

产测/量产工具通过 setter 接口改写设备身份,配置存储于 BTIF 区域,固件升级不丢失:

void bt_set_mac_addr(u8 *addr)
{
    memcpy(bt_cfg.mac_addr, addr, 6);
}

void bt_set_local_name(char *name, u8 len)
{
    memcpy(bt_cfg.edr_name, name, len);
    bt_cfg.edr_name[len] = 0;
}

来源:user_cfg.c 与 user_cfg.c

示例 3:调整射频功率与低功耗窗口

rf_power 决定发射功率档位(距离与电流的权衡);lp_winsize 各字段控制蓝牙振荡器(OSC)的省电窗口:

struct lp_ws_t lp_winsize = {
    .lrc_ws_inc = 480,      //260
    .lrc_ws_init = 160,
    .bt_osc_ws_inc = 100,
    .bt_osc_ws_init = 140,
    .osc_change_mode = 0,
};

来源:user_cfg.c

lrc_ws_inc/lrc_ws_init 是低速率时钟(LRC)的省电窗口增量与初值,bt_osc_ws_inc/bt_osc_ws_init 是蓝牙振荡器的对应参数;窗口越大,连接保持能力越强但平均电流越高。HID 外设通常需要低延迟响应(用户期望按键即时生效),因此窗口不能像音频设备那样开得极小,需要在响应速度与续航间调参。

Configuration Options

配置项类型默认值说明
CONFIG_APP_MOUSE编译宏0/1使能鼠标应用(与 KEYFOB/KEYBOARD 三选一)
CONFIG_APP_KEYFOB编译宏0/1使能遥控器应用
CONFIG_APP_KEYBOARD编译宏0/1使能键盘应用
CONFIG_UPDATA_ENABLE编译宏条件编译使能 OTA 升级任务(update,优先级 1,栈 320B)
RCSP_BTMATE_EN编译宏条件编译使能 RCSP 调试任务(rcsp_task,优先级 2,栈 640B)
TCFG_AUTO_SHUT_DOWN_TIME宏见 app_cfg自动关机时间,初始化进 app_var.auto_off_time
VM_MAX_SIZE_CONFIG宏见 app_cfgVM 区域最大空间,由 vm_max_size_config 引用
bt_cfg.edr_namestring"JL_HID_DEBUG"经典蓝牙广播/查询名称
bt_cfg.mac_addru8[6]{0xff,...}蓝牙 MAC(全 ff 表示待烧录)
bt_cfg.rf_poweru810射频发射功率档位
bt_cfg.dac_analog_gainu825DAC 模拟增益(提示音路径)
bt_cfg.mic_analog_gainu87MIC 模拟增益(语音按键场景)
bt_cfg.tws_device_indicateu160x6688杰理私有设备标识
btif_table表MAC(6)/频偏(6)注册到 BTIF 区域的配置项(出厂校准数据)
lp_winsize.lrc_ws_incint480LRC 省电窗口增量
lp_winsize.lrc_ws_initint160LRC 省电窗口初值
lp_winsize.bt_osc_ws_incint100蓝牙 OSC 省电窗口增量
lp_winsize.bt_osc_ws_initint140蓝牙 OSC 省电窗口初值
lp_winsize.osc_change_modeint0振荡器切换模式
PIN 码string"0000"传统配对 PIN(bt_get_pin_code() 返回)

API Reference

应用入口与切换(app_main.c)

void app_main()

应用层唯一入口。处理 OTA 结果、初始化 app_var、按 CONFIG_APP_* 宏构造 Intent 并调用 start_app()。

  • 参数:无
  • 返回:无
  • 副作用:根据编译宏启动 mouse / keyfob / hid_key 应用;无匹配宏时触发 ASSERT(0,"no app!!!")

void app_var_init(void)

初始化全局 app_var:开机提示音使能、auto_off_time = TCFG_AUTO_SHUT_DOWN_TIME、提示音频率(340/330)。

  • 参数:无
  • 返回:无

void app_switch(const char *name, int action)

先向当前应用发送 ACTION_BACK(触发 APP_STA_STOP → APP_STA_DESTORY 状态),再启动目标应用。

  • 参数:
    • name (const char *):目标应用名称
    • action (int):目标动作(如 ACTION_MOUSE_MAIN、ACTION_HID_MAIN、ACTION_KEYFOB)
  • 返回:无

int eSystemConfirmStopStatus(void)

决定系统空闲时的停止策略:返回 1 表示 Endless Sleep(深度停止,无任务超时唤醒),返回 0 表示 100ms 定时唤醒。

  • 参数:无
  • 返回:1(深度停止)或 0(100ms 唤醒)

配置访问接口(user_cfg.c)

const u8 *bt_get_mac_addr()

返回 bt_cfg.mac_addr 指针(6 字节)。

void bt_set_mac_addr(u8 *addr)

将 6 字节地址拷贝进 bt_cfg.mac_addr。注意:仅更新内存镜像,持久化由 BTIF 层负责。

void bt_get_vm_mac_addr(u8 *addr)

获取产测使用的 VM 区 MAC 副本(bt_mac_addr_for_testbox)。源码注释提示中断上下文不能调用 syscfg_read,故使用内存副本。

const char *bt_get_local_name()

返回 bt_cfg.edr_name 字符串。

void bt_set_local_name(char *name, u8 len)

按长度 len 拷贝新名称并补 \0。

const char *bt_get_pin_code()

返回固定 PIN 码 "0000",供传统配对流程使用。

u16 bt_get_tws_device_indicate(u8 *tws_device_indicate)

返回 bt_cfg.tws_device_indicate(0x6688)。

HID 协议层(hid_user.c / standard_hid.h)

HID 连接建立、report 发送与断开回调的详细接口见 hid_user.h(本页未逐行读取,建议查阅该头文件获取完整签名);标准报告数据结构定义见 standard_hid.h。

Failure Modes、边界情况与并发

配置缺失兜底

  • bt_cfg.mac_addr 默认全 0xff(未烧录)。若量产未写入 MAC,设备会以非法地址广播,主机可能无法连接。bt_get_vm_mac_addr() 的注释明确提示:中断上下文禁止调用 syscfg_read,否则可能造成总线忙/数据错乱——这是并发访问 Flash 存储的硬约束。
  • 三个 CONFIG_APP_* 宏全部未定义时 ASSERT(0) 直接停机,属于"失败快"(Fail Fast)策略,防止无应用固件流入市场。

配对与连接失败

  • PIN 固定 "0000":若主机策略拒绝 0000(企业安全策略),配对失败。这是 HID 外设的通用取舍——无法支持复杂配对流程(如 NFC 配对、Passkey 显示)。
  • 未注册 HID profile 就上报报告:应用必须等 hid_user 连接回调确认中断通道就绪后再发报告,否则数据丢弃。源码中 app_switch 的 ACTION_BACK 设计(先停后启)正是为了避免新旧应用同时操作 profile 导致通道状态错乱。

并发与资源竞争

  • 任务优先级差异显著(sys_event 优先级 7 vs app_core 优先级 1):按键中断在 sys_event 上下文产生事件,应用逻辑在 app_core 消费,两者通过事件队列解耦,避免在中断里做重活。
  • 低功耗窗口与连接保持的竞争:lp_winsize 窗口开得越大,系统越晚进入深睡、连接越稳,但电流越高。HID 应用必须在"按键即时报"与"待机续航"之间权衡,这也是 eSystemConfirmStopStatus() 提供两种停止策略的原因。

Performance 与运维注意事项

  • 任务栈预算紧张:app_core 仅 640B 栈,sys_event 仅 256B——应用回调里不应出现深递归或大局部数组,否则栈溢出将表现为随机崩溃。新增功能时优先使用事件驱动而非阻塞式轮询。
  • VM 区域按需裁剪:vm_max_size_config = VM_MAX_SIZE_CONFIG,HID 应用配置项少,可缩小 VM 预留,把 Flash 空间让给固件/字库/图片资源。
  • OTA 兼容:CONFIG_UPDATA_ENABLE 开启时创建 update 任务并在 app_main() 开头处理升级结果,保证升级中断后仍能正确恢复。
  • 产测流程:通过 bt_set_mac_addr() / bt_set_local_name() 改写身份,CFG_BT_FRE_OFFSET 保存测试盒矫正频偏——这些数据存 BTIF 区域,恢复出厂/升级不会擦除。

Extension Points

  1. 新增产品形态:复制 app_mouse.c 的模式新建子应用(如游戏手柄),在 app_main() 中增加 CONFIG_APP_* 分支,复用 hid_user profile 与 app_switch() 切换框架。
  2. 自定义 HID 报告:修改 standard_hid.h 中的报告结构或扩展 hid_user 的 report 回调,可支持多媒体键盘、消费类控制(Consumer Control)等高级报告。
  3. 产测/调试通道:RCSP_BTMATE_EN 使能 rcsp_task,通过杰理 RCSP 私有协议实现手机 App 远程调试、按键抓取与参数下发。
  4. 电源策略定制:重写 eSystemConfirmStopStatus() 返回逻辑,或调整 lp_winsize,可按产品(遥控器 vs 鼠标)定制唤醒周期与窗口。

Related Links

  • app_main.c — 应用入口与任务表
  • user_cfg.c — 蓝牙配置与存储
  • app_mouse.c — 鼠标应用
  • app_keyfob.c — 遥控器应用
  • app_keyboard.c — 键盘应用
  • app_idle.c — 空闲/待机管理
  • hid_user.c — HID 用户协议实现
  • standard_hid.h — 标准 HID 报告定义
  • 平台级蓝牙协议栈与 RTOS 行为请参阅对应平台文档(btstack / btctrler / 系统任务调度)。
Prev
AT 指令串口协议
Next
蓝牙 Mesh 应用