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

    • SDK 总览
    • 支持芯片与蓝牙认证
    • 工程结构导航
  • 开发环境与构建

    • 环境搭建与工具链安装
    • 编译指南与工程选择
    • 烧录与生产工具
  • BLE 透传/数传应用

    • 透传应用框架与处理模块
    • 透传与数传示例
    • 多连接与自定义服务示例
    • FindMy 与查找网络示例
  • HID 人机交互应用

    • 键盘与按键设备示例
    • 鼠标设备示例
    • 遥控器示例
    • HID 蓝牙应用模块
  • 公共 BSP 模块

    • 按键、编码器与红外输入
    • 传感器驱动
    • LED 与显示控制
    • 串口与 USB 通信
    • 存储、参数与时钟
    • 电源与温度管理
    • 消息、内存与系统配置
    • OTA 升级框架
  • 蓝牙协议栈与库

    • BLE 控制器与协议栈适配
    • 经典蓝牙 BR/EDR 支持
    • 第三方蓝牙协议
    • 设备管理框架
    • DUT 测试与射频认证
  • 构建系统与开发工具

    • Makefile 构建系统
    • 固件后处理与配置工具
    • 辅助脚本与库合并
  • 文档与硬件资料

    • AT 命令参考
    • 硬件参考资料
    • SDK 文档与在线资源

鼠标设备示例

本文档介绍 AW33N BLE SDK 中 HID 鼠标设备的示例工程,涵盖 apps/demo/hid/examples 下的单模(BLE)、双模(BLE + 2.4G + USB)及低延迟鼠标示例的实现机制、数据上报流程、BLE HOGP / USB HID 协议栈接入方式,以及底层 USB HID 鼠标驱动 hid_mouse.c 的描述符与初始化逻辑。

Purpose and Scope

本页面向希望基于 AW33N 芯片开发无线鼠标产品的工程师,说明 SDK 中鼠标示例的完整工作原理:

  • 单模鼠标(mouse_single):仅通过 BLE 以 133Hz 回报率上报 HID 数据;
  • 双模鼠标(mouse_dual):BLE(133Hz)与 2.4G(1KHz)双模切换,可扩展 USB 模式;
  • 低延迟鼠标(mouse_low_latency):面向低时延场景的示例;
  • USB HID 鼠标驱动(hid_mouse.c):设备端 USB HID 描述符、报告描述符与初始化流程;
  • 板级配置(board/bd57/board_aw33n_mouse*.c/h):鼠标工程的外设引脚与编译配置。

以下主题不属于本页范围,请参见对应目录页:

  • 键盘类 HID 示例 → hid_keyboard.c、键盘示例页;
  • RCSP HID 透传 → rcsp_hid_inter.c;
  • 其他 USB 设备类(声卡、存储等)→ USB 设备示例页。

Overview

鼠标是典型的低功耗 HID 外设:芯片内部采集光学传感器位移、按键和滚轮事件,按固定周期(7ms 对应约 133Hz)打包为 HID Report,经 BLE HOGP 协议或 2.4G 私有链路 / USB 枚举发送给主机。SDK 将「示例应用」与「协议栈实现」分层:

  • 示例层(apps/demo/hid/examples/*)负责事件采集、数据打包、连接参数管理、低功耗与看门狗维护;
  • 协议栈层(ble_hogp.h、hogp_bt_ble_init、rcsp_hid_inter.c)负责 BLE 广播、连接与 HID 服务;
  • USB 设备层(apps/app/bsp/common/usb/device/hid_mouse.c)负责 USB 枚举时的 HID 描述符与端点配置。

示例之间通过编译宏 CONFIG_APP_MOUSE_SINGLE / CONFIG_APP_MOUSE_DUAL 选择编译,互不冲突。

Architecture

flowchart TD
    subgraph sg_Examples["HID 鼠标示例层 apps/demo/hid/examples"]
        Single["app_mouse_single.c<br/>单模 BLE 鼠标 (133Hz)"]
        Dual["app_mouse_dual.c<br/>双模 BLE + 2.4G (+USB)"]
        LowLat["app_mouse_low_latency.c<br/>低延迟鼠标"]
    end

    subgraph sg_Input["输入采集"]
        Sensor["光学传感器<br/>OMSensor_manage / gsensor"]
        Key["按键扫描 / code_switch"]
        Wheel["滚轮事件 sys_event"]
    end

    subgraph sg_Stack["协议栈层"]
        BLE["BLE HOGP<br/>ble_hogp.h / hogp_bt_ble_init"]
        USB["USB HID 设备<br/>hid_mouse.c"]
        Rcsp["RCSP HID<br/>rcsp_hid_inter.c"]
    end

    subgraph sg_Board["板级配置 board/bd57"]
        Board["board_aw33n_mouse*.c/h"]
    end

    Sensor --> Single
    Key --> Single
    Wheel --> Single
    Sensor --> Dual
    Key --> Dual
    Wheel --> Dual
    Single --> BLE
    Dual --> BLE
    Dual --> USB
    LowLat --> BLE
    Board --> Single
    Board --> Dual
    BLE --> Host["BLE 主机 (PC/手机)"]
    USB --> HostUsb["USB 主机 (PC Dongle)"]

架构分四层:最上层为三个鼠标示例应用(通过编译宏互斥选择);输入采集层由光学传感器管理模块(OMSensor_manage)、按键/滚轮事件(sys_event 与 code_switch)组成;协议栈层负责将打包好的 HID 报告经 BLE HOGP 或 USB 发出;板级配置层为鼠标工程提供 GPIO、电源、传感器等外设初始化。鼠标示例不直接操作射频寄存器,而是通过 ble_init_cfg_t 将回调(如 hogp_bt_ble_init)注入 BLE 协议栈——这种「配置注入 + 事件回调」的设计使示例代码与协议栈实现解耦,便于复用。

示例工程总览

鼠标示例位于 apps/demo/hid/examples/,工程编译入口在 apps/demo/hid/board/bd57/ 下的板级配置。三个示例的关系与差异如下:

示例目录回报率连接方式编译宏
单模鼠标examples/mouse_singleBLE 133Hz仅 BLE HOGPCONFIG_APP_MOUSE_SINGLE
双模鼠标examples/mouse_dualBLE 133Hz / 2.4G 1KHzBLE + 2.4G(可加 USB)CONFIG_APP_MOUSE_DUAL
低延迟鼠标examples/mouse_low_latency面向低时延优化BLECONFIG_APP_MOUSE_LOW_LATENCY(按命名约定)

双模示例额外包含 mouse_usb.c/h,用于在 USB 模式下复用 HID 报告描述符,使同一套打包逻辑可同时服务 BLE、2.4G 与 USB 三种物理通道。

单模鼠标实现(app_mouse_single.c)

文件头注释明确其定位:鼠标单模 BLE(133 回报率),即约 7ms 一个发送周期。核心数据结构与配置如下:

static const char mouse_ble_name[] = "AW31N_MOUSE_SINGLE";
static volatile uint8_t mouse_is_active;// 1-临界点,系统不允许进入低功耗,0-系统可以进入低功耗
static uint32_t mouse_reset_cnt;
static uint8_t  mouse_double_key_long_cnt; // key cnt
static uint8_t  mouse_switch_key_long_cnt;
static uint8_t  mouse_cpi_mode = MOUSE_CPI_1000; // mouse cpi setting, default 1000

static mouse_info_t mouse_info;
static mouse_send_flags_t mouse_flag;

static mouse_packet_data_t mouse_send_packet;

static const ble_init_cfg_t mouse_ble_config = {
    .same_address = 0,
    .appearance = BLE_APPEARANCE_HID_MOUSE,
    .report_map = mouse_report_map,
    .report_map_size = sizeof(mouse_report_map),
};

Source: app_mouse_single.c

设计要点:

  • mouse_is_active:volatile 临界点标志。置 1 时系统禁止进入低功耗(例如数据发送临界区),置 0 时允许低功耗——这是鼠标这类周期性上报外设与电源管理协同的关键机制;
  • mouse_cpi_mode:CPI(每英寸计数)设置,默认 MOUSE_CPI_1000;
  • mouse_send_flags_t:由 sensor_send_flag、wheel_send_flag、button_send_flag 三个标志组成,分别表示「传感器位移 / 滚轮 / 按键」是否已消费,用于合并多个事件到同一包并决定是否继续上报;
  • ble_init_cfg_t:注入 BLE 初始化配置。appearance = BLE_APPEARANCE_HID_MOUSE 使广播/连接对外呈现为 HID 鼠标,report_map 指向 HID 报告描述符(mouse_report_map,定义于 standard_hid.h 相关头文件)。

数据上报主路径:mouse_data_send

定时器每 7ms 触发一次上报,核心逻辑在 mouse_data_send:

static void mouse_data_send(void *priv_hw, uint8_t hw_state, bool is_24g)
{
#if TEST_MOUSE_SIMULATION_ENABLE
    mouse_send_data_test();
#else
#ifdef TCFG_OMSENSOR_ENABLE
    optical_mouse_read_sensor_handler_high(&mouse_send_packet, &mouse_flag);
#endif
#endif
    // 取数
    if (!(mouse_flag.sensor_send_flag && mouse_flag.wheel_send_flag && mouse_flag.button_send_flag)) {
        mouse_reset_cnt++;
        uint32_t mouse_reset_cnt_max;
        mouse_reset_cnt_max = MOUSE_7MS_CLEAR_WDT_CNT_MAX;

        if (mouse_reset_cnt > mouse_reset_cnt_max) {
#if (TCFG_HID_AUTO_SHUTDOWN_TIME)
            sys_timer_modify(mouse_info.mouse_auto_shutdown_timer, TCFG_HID_AUTO_SHUTDOWN_TIME * 1000);
#endif
            // 避免看门狗超时
            wdt_clear();
            mouse_reset_cnt = 0;
        }
        ble_hid_data_send(MOUSE_SEND_DATA_REPORT_ID, (uint8_t *)&mouse_send_packet, sizeof(mouse_send_packet));

        // 清除鼠标信息
        if (mouse_flag.button_send_flag == 0) {
            mouse_flag.button_send_flag = 1;
        }

        if (mouse_flag.wheel_send_flag == 0) {
            mouse_flag.wheel_send_flag = 1;
            mouse_send_packet.wheel = 0;
        }

        if (mouse_flag.sensor_send_flag == 0) {
            mouse_flag.sensor_send_flag = 1;
            memset((void *)&mouse_send_packet.xymovement, 0, sizeof(mouse_send_packet.xymovement));
        }
    } else {
        // 未取到按键/传感器数据,过滤
        return;
    }
}

Source: app_mouse_single.c

执行流程与设计意图:

  1. 取数:优先走 TEST_MOUSE_SIMULATION_ENABLE 模拟数据路径(无需传感器硬件即可联调);否则在 TCFG_OMSENSOR_ENABLE 下调用 optical_mouse_read_sensor_handler_high 从光学传感器读取位移并填充 mouse_send_packet;
  2. 空包过滤:若三个标志全部为 1(即按键/滚轮/位移均无新数据),直接 return,避免无意义空包占用 BLE 带宽——这是降低功耗的关键;
  3. 看门狗维护:连续空包计数超过 MOUSE_7MS_CLEAR_WDT_CNT_MAX 时调用 wdt_clear(),防止长时间无有效数据导致看门狗复位,同时顺带刷新自动关机定时器(TCFG_HID_AUTO_SHUTDOWN_TIME);
  4. 发送:ble_hid_data_send(MOUSE_SEND_DATA_REPORT_ID, ...) 将打包好的 mouse_packet_data_t 通过 BLE HOGP 发出;
  5. 数据清位:发送后重置标志并将滚轮、位移清零,保证「边沿触发」语义——下一次事件到来时才再次上报。

事件采集与坐标系处理

滚轮事件通过 sys_event 的 code_sw 通道进入:

static void mouse_code_sw_event_handler(struct sys_event *event)
{
    static s8 sw_val = 0;

    if (mouse_flag.wheel_send_flag) {
        sw_val = 0;
    }

    if (event->u.codesw.event == 0) {
        sw_val += event->u.codesw.value;
        mouse_send_packet.wheel = -sw_val;
    }

    mouse_flag.wheel_send_flag = 0;
}

Source: app_mouse_single.c

光学传感器(GSensor)位移则按坐标轴换算并做 ±2047 钳位:

void mouse_optical_sensor_event(uint8_t event, s16 x, s16 y)
{
    static s16 delta_x = 0, delta_y = 0;
    if (mouse_flag.sensor_send_flag) {
        delta_x = 0;
        delta_y = 0;
    }

    if (event == 0) {
        if (((delta_x + x) >= -2047) && ((delta_x + x) <= 2047)) {
        } else {
            x = 0;
        }

        if (((delta_y + y) >= -2047) && ((delta_y + y) <= 2047)) {
        } else {
            y = 0;
        }

        //坐标调整
        delta_x += (-y);
        delta_y += (x);
        ...

Source: app_mouse_single.c

要点:传感器原始坐标轴与 HID 报告坐标轴不一致,因此做了 delta_x += (-y); delta_y += x 的旋转映射;-2047..2047 的钳位将单包位移限制在 12 位有符号范围内,防止溢出破坏 HID 报告的 X/Y 字段。

双模鼠标实现(app_mouse_dual.c)

双模示例在单模基础上增加了 BLE(133Hz)↔ 2.4G(1KHz) 模式切换,并可通过 mouse_usb.c 扩展 USB 模式。其 BLE 初始化配置更完整,显式注册了 HOGP 生命周期回调:

static const ble_init_cfg_t mouse_ble_config = {
    .same_address = 0,
    .appearance = BLE_APPEARANCE_HID_MOUSE,
    .report_map = mouse_report_map,
    .report_map_size = sizeof(mouse_report_map),
    .ble_profile_init = comm_ble_profile_init,
    .bt_ble_init  = hogp_bt_ble_init,
    .bt_ble_before_start_init = hogp_bt_ble_before_start_init,
    .bt_ble_exit = hogp_bt_ble_exit,
    .ble_module_enable = hogp_ble_module_enable,
};
static const struct conn_update_param_t mouse_connection_parameters[] = {
    {6, 6,  133, 300}, //mouse
    {9, 9,  89, 300}, //mouse
    {12, 12, 30, 300}, //ios
    {6,  12, 30, 400},// ios fast
};

Source: app_mouse_dual.c

设计意图:

  • HOGP 回调全量注入:hogp_bt_ble_init / hogp_bt_ble_exit 等回调使协议栈在连接建立、断开时能通知示例层,示例层据此更新 mouse_is_paired、连接状态与低功耗策略;
  • 连接参数表:conn_update_param_t 元组为 {min_interval, max_interval, slave_latency, timeout}(单位 1.25ms)。首项 {6,6,133,300} 即 7.5ms 间隔 + 133 次从机延迟,对应 133Hz 回报率;{12,12,30,300}、{6,12,30,400} 是针对 iOS 主机的兼容参数,示例层可根据对端类型动态切换连接参数,在功耗与回报率之间折中。

双模示例用多个标志位协调并发路径,防止数据竞争:

  • mouse_conn_send_flag:保证每个连接事件只发一包;
  • mouse_usb_send_flag:保证 USB 数据处理完再推消息,避免 USB 与 BLE 路径交叉发包;
  • mouse_sleep_exit_send_flag:避免「退出低功耗」与「事件触发」同时发包;
  • mouse_switch_start_mode(TCFG_POWER_CHECK_MODE_ENABLE 下):记录上电启动模式,用于恢复上次使用的连接模式。

模式切换流程(按键事件驱动,mouse_code_sw_event_handle + mouse_select_btmode + mouse_vm_deal 持久化到 VM):

flowchart TD
    Start([上电]) --> Init["初始化 mouse_ble_config / 连接参数表"]
    Init --> Mode{"当前模式"}
    Mode -->|"BLE"| B1["BLE 广播 / 连接<br/>hogp_bt_ble_init"]
    Mode -->|"2.4G"| G1["2.4G 发包<br/>mouse_data_send(..., is_24g=true)"]
    Mode -->|"USB"| U1["USB HID 枚举<br/>mouse_usb.c"]
    B1 --> Key{"按键 / codesw 事件"}
    G1 --> Key
    U1 --> Key
    Key -->|"切换键 (短按/长按)"| Switch["mouse_code_sw_event_handle<br/>计数判定"]
    Switch --> Sel["mouse_select_btmode 切换物理通道"]
    Sel --> VM["mouse_vm_deal 保存模式到 VM<br/>(下次上电恢复)"]
    VM --> Mode

注:mouse_vm_deal(rw_flag) 负责读写 VM(Value Management)存储,使模式选择具备掉电记忆能力;mouse_select_btmode(uint8_t mode) 为实际切换 BLE/2.4G 物理链路的入口。二者具体实现位于 app_mouse_dual.c 后半部分(本文未逐行展示)。

USB HID 鼠标设备驱动(hid_mouse.c)

当鼠标示例启用 USB 模式时,设备端复用 apps/app/bsp/common/usb/device/hid_mouse.c 作为 USB HID 类实现。该文件通过 #pragma 段指令将代码与数据放入 .usb_slave.hid.* 段,由 USB 栈在枚举时加载。

接口与 HID 描述符

static const u8 sHIDDescriptor[] = {
    //InterfaceDeszcriptor:
    USB_DT_INTERFACE_SIZE,     // Length
    USB_DT_INTERFACE,          // DescriptorType
    0x00,                      // bInterface number
    0x00,                      // AlternateSetting
    0x01,                      // NumEndpoint
    USB_CLASS_HID,             // Class = Human Interface Device
    0x01,                      // Subclass, 0 No subclass, 1 Boot Interface subclass
    0x02,                      // Procotol, 0 None, 1 Keyboard, 2 Mouse
    ...
    USB_DIR_IN | HID_MOUSE_EP_IN,     // bEndpointAddress
    USB_ENDPOINT_XFER_INT,      // Interrupt
    LOBYTE(HID_MOUSE_EP_IN_MAX_SIZE), HIBYTE(HID_MOUSE_EP_IN_MAX_SIZE),// Maximum packet size
    0x01,     // Poll every 10msec seconds
};

Source: hid_mouse.c

要点:Protocol = 0x02 声明为 Boot Mouse;使用一个中断 IN 端点 HID_MOUSE_EP_IN,最大包长 HID_MOUSE_EP_IN_MAX_SIZE,轮询间隔 10ms;HID_MOUSE_EP_OUT_EN 可开启 OUT 端点用于主机下行数据(如灯效控制)。

报告描述符(Report Descriptor)

#define HID_MOUSE_REPORT_ID               0x2
static const u8 sHIDReportDesc[] = {
    0x05, 0x01,                    // Usage Page (Generic Desktop Ctrls)
    0x09, 0x02,                    // Usage (Mouse)
    0xA1, 0x01,                    // Collection (Application)
    0x85, HID_MOUSE_REPORT_ID,     // Report ID (2)
    0x09, 0x01,                    // Usage (Pointer)
    0xA1, 0x00,                    // Collection (Physical)
    // Buttons (5 buttons)
    0x95, 0x05, 0x75, 0x01,        // 5 buttons x 1 bit
    0x05, 0x09,                    // Usage Page (Button)
    0x19, 0x01, 0x29, 0x05,        // Usage 1..5
    0x15, 0x00, 0x25, 0x01,        // Logical 0..1
    0x81, 0x02,                    // Input (Data,Var,Abs)
    // Wheel (8 bits)
    0x75, 0x08, 0x95, 0x01,
    0x09, 0x38,                    // Usage (Wheel)
    0x15, 0x81, 0x25, 0x7F,        // Logical -127..127
    0x81, 0x06,                    // Input (Data,Var,Rel)
    // X and Y Axis (16 bits each)
    0x75, 0x10, 0x95, 0x02,
    0x09, 0x30, 0x09, 0x31,        // Usage (X), (Y)
    0x16, 0x00, 0x80, 0x26, 0xFF, 0x7F, // Logical -32768..32767
    0x81, 0x06,                    // Input (Data,Var,Rel)
    0xC0, 0xC0,                    // End Collection x2
};

Source: hid_mouse.c

该描述符定义了 5 个按键位、8 位滚轮(-127..127)与两个 16 位相对位移轴(-32768..32767),并指定 Report ID = 0x2——与示例层 ble_hid_data_send(MOUSE_SEND_DATA_REPORT_ID, ...) 使用的报告 ID 语义一致(BLE HOGP 报告映射与 USB 报告描述符共用同一套报告结构)。

初始化

void *usb_hid_mouse_init(void)
{
    memset((void *)&_hid_var, 0, sizeof(_hid_var));
    _hid_var.ep_in_buffer = usb_get_ep_buffer(0, HID_MOUSE_EP_IN | USB_DIR_IN);
#if HID_MOUSE_EP_OUT_EN
    _hid_var.ep_out_buffer = usb_get_ep_buffer(0, HID_MOUSE_EP_OUT | USB_DIR_OUT);
#endif
    return (void *)&_hid_var;
}

Source: hid_mouse.c

usb_hid_mouse_init 清零设备变量、从 USB 栈申请 IN/OUT 端点缓冲并返回句柄。_hid_var 存放于 .hid_config_var 段、hid_var 指针存放于 .usb_hid.keep_ram 段——保持 RAM 段在低功耗/复位期间不丢失,保证 USB 枚举状态可恢复。

核心流程:鼠标数据上报时序

鼠标示例的完整工作流以「定时器驱动 + 事件合并 + 标志位消抖」为骨架。以单模 BLE 鼠标为例,一个完整上报周期的时序如下:

sequenceDiagram
    participant T as sys_timer (≈7ms)
    participant M as app_mouse_single.c
    participant S as 光学传感器 / 按键 / 滚轮
    participant B as BLE HOGP 协议栈
    participant H as BLE 主机

    T->>M: mouse_timer_handler(tid, priv)
    activate M
    M->>M: 检查 mouse_info.mouse_is_paired
    alt 未配对
        M-->>T: 直接返回,不发包
    else 已配对
        M->>M: mouse_data_send(NULL, 0, false)
        M->>S: optical_mouse_read_sensor_handler_high(&packet, &flag)
        S-->>M: 填充 xymovement / 按键 / 滚轮
        M->>M: 检查 sensor/wheel/button 标志
        alt 有新数据 (任一标志为 0)
            M->>B: ble_hid_data_send(REPORT_ID, &packet, sizeof)
            B-->>H: BLE 通知上报 (133Hz 间隔)
            M->>M: 复位标志并清零 wheel / xymovement
        else 无新数据 (三标志均为 1)
            M->>M: mouse_reset_cnt++
            Note over M: 超限后 wdt_clear()<br/>并刷新自动关机定时器
        end
    end
    deactivate M

关键设计决策:

  1. 定时器优先于中断:传感器、按键、滚轮事件以回调/事件方式置位标志,真正的数据发送统一由 7ms 定时器驱动。这保证了上报节奏恒定(133Hz),且多类输入可合并到同一包,减少 BLE 空包与唤醒次数;
  2. 未配对即静默:mouse_timer_handler 在 !mouse_is_paired 时直接返回——未连接时不产生任何射频活动,是鼠标续航的核心;
  3. 标志位消抖:sensor_send_flag / wheel_send_flag / button_send_flag 的「0 表示有新数据」约定(发送后置 1、事件到达时清零)实现边沿触发,避免同一事件被重复上报。

配置选项

鼠标示例的编译与运行行为由以下宏/配置控制(宏定义于各示例头文件、app_config.h 与板级 board_aw33n_mouse*_cfg.h 中):

配置项类型默认值说明
CONFIG_APP_MOUSE_SINGLE编译宏0/1使能单模 BLE 鼠标示例编译
CONFIG_APP_MOUSE_DUAL编译宏0/1使能双模鼠标示例编译(与单模互斥)
TEST_MOUSE_SIMULATION_ENABLE编译宏0使能模拟数据路径(mouse_send_data_test),无需传感器硬件联调
TCFG_OMSENSOR_ENABLE编译宏按板级使能光学传感器数据采集
TCFG_HID_AUTO_SHUTDOWN_TIME数值按板级自动关机时间(秒),空包计数超限时刷新该定时器
MOUSE_CPI_1000枚举值1000默认 CPI 档位(mouse_cpi_mode 初值)
MOUSE_7MS_CLEAR_WDT_CNT_MAX数值按头文件连续空包计数上限,超限执行 wdt_clear()
MOUSE_SEND_DATA_REPORT_ID数值与报告描述符一致BLE 上报使用的 HID Report ID
HID_MOUSE_EP_IN_MAX_SIZE数值按 usb_config.hUSB 中断 IN 端点最大包长
HID_MOUSE_EP_OUT_EN编译宏0是否使能 USB OUT 端点(主机下行)
mouse_connection_parameters[]数组4 组BLE 连接参数表(interval/latency/timeout),按主机类型选择
TCFG_POWER_CHECK_MODE_ENABLE编译宏0使能上电模式检测(双模启动模式记忆)

表中「按头文件/按板级」的值以实际工程配置为准;本文仅列出源文件中已确认存在且语义明确的配置项。

API 参考

mouse_data_send(void *priv_hw, uint8_t hw_state, bool is_24g)

定时器驱动的数据上报入口(单模/双模共用命名与语义)。

  • 参数:priv_hw 硬件私有指针(单模传 NULL);hw_state 硬件状态;is_24g 是否为 2.4G 通道发送;
  • 行为:采集传感器/按键/滚轮 → 空包过滤 → ble_hid_data_send → 清标志位;
  • 无返回值。

mouse_timer_handler(u32 tid, void *private_data)

7ms 系统定时器回调。未配对时直接返回;配对后调用 mouse_data_send。

mouse_optical_sensor_event(uint8_t event, s16 x, s16 y)

GSensor 位移事件处理:坐标旋转映射(dx += -y; dy += x)并做 ±2047 钳位后写入 mouse_send_packet.xymovement,同时将 sensor_send_flag 清零。

mouse_code_sw_event_handler(struct sys_event *event)

滚轮事件处理:累加 event->u.codesw.value 到 sw_val,写 mouse_send_packet.wheel = -sw_val 并清零 wheel_send_flag。

ble_hid_data_send(uint8_t report_id, uint8_t *buf, uint32_t len)

协议栈层 HID 数据发送接口(来自 ble_hogp.h),将打包好的报告经 BLE 通知发出。

usb_hid_mouse_init(void) : void*

USB HID 鼠标设备初始化:清零设备变量、申请端点缓冲并返回设备句柄(hid_mouse.c)。

usb_get_hid_mouse_report_id(void) : u32

返回 USB HID 报告 ID(HID_MOUSE_REPORT_ID = 0x2),供 USB 栈查询(hid_mouse.c,__attribute__((always_inline)) 内联实现)。

故障模式、边界情况与并发

看门狗与空包风暴

鼠标在静止时(无位移、无按键、无滚轮)会被空包过滤逻辑拦截而不发数据,但定时器仍持续运行。若长时间无有效事件,mouse_reset_cnt 持续累加,超过 MOUSE_7MS_CLEAR_WDT_CNT_MAX 后执行 wdt_clear()。设计意图:既不发送空包浪费射频功耗,又保证看门狗不被饿死。风险点是若 ble_hid_data_send 阻塞或系统卡死,看门狗仍会复位——mouse_set_soft_reset(cpu_reset())则提供了软件主动复位路径,用于异常恢复。

低功耗临界点保护

mouse_is_active(volatile)是电源管理与数据发送之间的握手信号:置 1 表示处于临界区,系统禁止进入低功耗;置 0 允许低功耗。双模示例进一步用 mouse_sleep_exit_send_flag 防止「退出低功耗」与「事件触发」在同一时刻竞争发包。若临界区标志未正确复位,可能导致系统长期无法休眠、待机电流异常——这是低功耗鼠标调试中最常见的现场问题。

多通道并发(双模)

双模示例同时存在 BLE、2.4G、USB 三条发送路径,用 mouse_conn_send_flag(每连接事件一包)、mouse_usb_send_flag(USB 数据先处理完再推消息)保证同一份 mouse_send_packet 不会被两条路径交叉改写。切换模式时 mouse_select_btmode 负责停止旧通道、启动新通道,mouse_vm_deal 将模式写入 VM 以便掉电恢复——若 VM 读写失败,则回退到默认模式(首次上电默认 BLE)。

数据包边界与溢出

  • 传感器位移钳位 ±2047,滚轮钳位 -127..127(与报告描述符 Logical Min/Max 一致),防止越界值破坏 HID 报告解析;
  • 单模在发送后清零 wheel 与 xymovement,保证「边沿触发」语义,避免主机端收到重复滚轮/位移;
  • 未配对时定时器直接返回,杜绝无连接状态下的无效射频活动。

性能与运维考虑

  • 回报率:BLE 路径固定约 133Hz(7ms 周期),2.4G 路径 1KHz,USB 路径 10ms 轮询(中断端点);BLE 高回报率依赖连接参数表中的 {6,6,133,300}(7.5ms 间隔 + 133 latency),与 iOS 主机兼容时自动降级为 {12,12,30,...} 参数组;
  • 功耗:静止无事件时不发空包 + 未配对静默 + mouse_is_active 低功耗门控,三者共同构成鼠标续航策略;TCFG_HID_AUTO_SHUTDOWN_TIME 提供空闲自动关机兜底;
  • 调试手段:TEST_MOUSE_SIMULATION_ENABLE 可在无传感器硬件时用 mouse_send_data_test() 注入模拟数据,便于协议栈联调;LOG_TAG "[MOUSE]" 的 debug 日志(LOG_DEBUG_ENABLE/LOG_INFO_ENABLE)覆盖发送与事件路径;
  • 内存布局:USB HID 驱动将设备变量放入 .usb_slave.hid.data 段、指针放入 .usb_hid.keep_ram 保持 RAM 段,低功耗唤醒后无需重新枚举即可继续收发。

扩展点

  • 新增连接模式:在 mouse_connection_parameters[] 增加 conn_update_param_t 元组,并依据对端类型(普通 PC / iOS / iOS fast)选择索引;
  • 新增按键功能:mouse_double_key_long_cnt、mouse_switch_key_long_cnt 已预留双击/长按计数骨架,可在按键事件回调中扩展组合键逻辑;
  • 新增 USB 模式:以 mouse_usb.c 为模板复用报告描述符,并保持 mouse_usb_send_flag 与 BLE 路径互斥;
  • 自定义 HID 报告:BLE 侧修改 mouse_report_map(standard_hid.h),USB 侧同步修改 sHIDReportDesc,两处报告结构必须保持一致,否则主机端按键/滚轮/位移字段错位;
  • 其他传感器:TCFG_OMSENSOR_ENABLE 路径抽象了 optical_mouse_read_sensor_handler_high 取数接口,可替换为激光/轨迹球等不同传感方案。

Related Links

  • app_mouse_single.c(单模 BLE 鼠标示例)
  • app_mouse_dual.c(双模 BLE+2.4G 鼠标示例)
  • mouse_usb.c(双模 USB 通道)
  • hid_mouse.c(USB HID 鼠标设备驱动)
  • standard_hid.h(HID 报告映射定义)
  • board_aw33n_mouse.c(鼠标板级配置)
  • rcsp_hid_inter.c(RCSP HID 透传,键盘/复合设备可参考)
Prev
键盘与按键设备示例
Next
遥控器示例