feat(keyboard): 添加蓝牙HID支持和电池状态事件

- 添加BLE相关模块:ble_adv_ctrl_module、ble_adv_uuid16、ble_bas_module、
  ble_hid_module
- 新增电池状态事件(bat_state_event)用于监控电池电量、充电状态
- 在多个事件中添加HID_TRANSPORT_BLE支持,包括hid_led_event、
  set_protocol_event等
- 更新配置文件prj.conf以启用蓝牙功能、HID服务和设置系统
- 修改电池模块以计算并报告电池SOC百分比
- 集成CAF设置加载器以管理蓝牙配对信息
This commit is contained in:
2026-04-10 19:28:20 +08:00
parent b9b7d342f5
commit 39d2962258
21 changed files with 1186 additions and 60 deletions

View File

@@ -1,5 +1,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <app_event_manager.h>
@@ -16,11 +17,15 @@
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include "bat_state_event.h"
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
#define VBATT_NODE DT_PATH(vbatt)
#define IP5306_NODE DT_NODELABEL(ip5306)
#define BATTERY_SAMPLE_INTERVAL K_SECONDS(1)
#define BATTERY_SOC_MIN_MV 3300
#define BATTERY_SOC_MAX_MV 4200
BUILD_ASSERT(DT_NODE_HAS_STATUS(VBATT_NODE, okay),
"Missing /vbatt voltage-divider node in devicetree");
@@ -30,6 +35,12 @@ BUILD_ASSERT(DT_NODE_HAS_STATUS(IP5306_NODE, okay),
static const struct device *const vbatt_dev = DEVICE_DT_GET(VBATT_NODE);
static const struct device *const ip5306_dev = DEVICE_DT_GET(IP5306_NODE);
static struct k_work_delayable battery_sample_work;
static struct {
bool valid;
uint8_t soc;
bool charging;
bool full;
} last_bat_state;
static bool initialized;
static bool running;
@@ -52,6 +63,48 @@ static int measurement_enable(bool enable)
return 0;
}
static uint8_t battery_soc_from_mv(int voltage_mv)
{
const int span_mv = BATTERY_SOC_MAX_MV - BATTERY_SOC_MIN_MV;
int bucket;
if (voltage_mv <= BATTERY_SOC_MIN_MV) {
return 0U;
}
if (voltage_mv >= BATTERY_SOC_MAX_MV) {
return 100U;
}
bucket = ((voltage_mv - BATTERY_SOC_MIN_MV) * 10 + (span_mv / 2)) / span_mv;
return (uint8_t)(bucket * 10);
}
static void submit_bat_state_event(uint8_t soc, bool charging, bool full)
{
struct bat_state_event *event;
if (last_bat_state.valid &&
(last_bat_state.soc == soc) &&
(last_bat_state.charging == charging) &&
(last_bat_state.full == full)) {
return;
}
last_bat_state.valid = true;
last_bat_state.soc = soc;
last_bat_state.charging = charging;
last_bat_state.full = full;
event = new_bat_state_event();
event->soc = soc;
event->charging = charging;
event->full = full;
APP_EVENT_SUBMIT(event);
}
static void battery_sample_fn(struct k_work *work)
{
struct ip5306_status pmic_status;
@@ -84,8 +137,9 @@ static void battery_sample_fn(struct k_work *work)
}
voltage_mv = sensor_value_to_mv(&voltage);
// LOG_INF("Battery: %d mV, charging=%d, full=%d",
// voltage_mv, pmic_status.charging, pmic_status.full);
submit_bat_state_event(battery_soc_from_mv(voltage_mv),
pmic_status.charging,
pmic_status.full);
reschedule:
if (running) {
@@ -112,6 +166,7 @@ static int module_init(void)
}
k_work_init_delayable(&battery_sample_work, battery_sample_fn);
memset(&last_bat_state, 0, sizeof(last_bat_state));
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_SUSPENDED);
return 0;