feat(proto): 添加设备通信协议v1修订版及统一帧格式
- 新增docs/device_communication_protocol_v1.md文档,定义V1修订版协议 - CDC和BLE GATT均改为直接传输业务消息,去掉外层协议封装 - BLE改为使用NUS(Nordic UART Service)替代原有GATT服务 - 统一键盘位图为29字节格式,FunctionKeyEvent改为上报全键盘位图 - 顶层消息增加msg_id和reply_to字段用于请求响应匹配 - Ack和Error合并为统一Response消息类型 - CDC和NUS均增加统一外层帧格式:magic(2) + len(1) + protobuf - 添加Proto frame常量定义及长度验证逻辑 - 更新proto文件定义,包含DeviceMessage统一信封和ResponseCode枚举 - 重构hid_flowctrl_module.c中的上下文访问方式,统一使用ctx前缀
This commit is contained in:
@@ -125,16 +125,6 @@ static struct keyboard_core_module_ctx ctx = {
|
||||
},
|
||||
};
|
||||
|
||||
#define lifecycle ctx.lc
|
||||
#define keyboard_state ctx.keyboard_state
|
||||
#define reports_cache ctx.reports_cache
|
||||
#define function_usage_mask ctx.function_usage_mask
|
||||
#define transport_protocol_modes ctx.transport_protocol_modes
|
||||
#define current_transport ctx.current_transport
|
||||
#define mode_valid ctx.mode_valid
|
||||
#define settings_active ctx.settings_active
|
||||
#define running module_lifecycle_is_running(&ctx.lc)
|
||||
|
||||
static bool policy_to_transport(enum hid_transport_policy policy,
|
||||
enum hid_transport *transport)
|
||||
{
|
||||
@@ -156,8 +146,9 @@ static enum keyboard_protocol_mode active_protocol_mode_get(void)
|
||||
{
|
||||
enum hid_transport transport;
|
||||
|
||||
if (mode_valid && policy_to_transport(current_transport, &transport)) {
|
||||
return transport_protocol_modes[transport];
|
||||
if (ctx.mode_valid &&
|
||||
policy_to_transport(ctx.current_transport, &transport)) {
|
||||
return ctx.transport_protocol_modes[transport];
|
||||
}
|
||||
|
||||
return KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
@@ -269,38 +260,39 @@ static bool consumer_key_update(uint16_t consumer_id, bool pressed)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool was_pressed = (keyboard_state.consumer_bits & BIT(consumer_id)) != 0U;
|
||||
bool was_pressed =
|
||||
(ctx.keyboard_state.consumer_bits & BIT(consumer_id)) != 0U;
|
||||
|
||||
if (was_pressed == pressed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WRITE_BIT(keyboard_state.consumer_bits, consumer_id, pressed);
|
||||
WRITE_BIT(ctx.keyboard_state.consumer_bits, consumer_id, pressed);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void keyboard_state_clear(void)
|
||||
{
|
||||
memset(&keyboard_state, 0, sizeof(keyboard_state));
|
||||
memset(&ctx.keyboard_state, 0, sizeof(ctx.keyboard_state));
|
||||
}
|
||||
|
||||
static void function_usage_mask_clear(void)
|
||||
{
|
||||
memset(function_usage_mask, 0, sizeof(function_usage_mask));
|
||||
memset(ctx.function_usage_mask, 0, sizeof(ctx.function_usage_mask));
|
||||
}
|
||||
|
||||
static void reports_cache_invalidate(void)
|
||||
{
|
||||
reports_cache.boot_valid = false;
|
||||
reports_cache.nkro_valid = false;
|
||||
reports_cache.consumer_valid = false;
|
||||
ctx.reports_cache.boot_valid = false;
|
||||
ctx.reports_cache.nkro_valid = false;
|
||||
ctx.reports_cache.consumer_valid = false;
|
||||
}
|
||||
|
||||
static void build_effective_hid_bitmap(uint8_t bitmap[KEYBOARD_PROTOCOL_BITMAP_BYTES])
|
||||
{
|
||||
for (size_t i = 0; i < KEYBOARD_PROTOCOL_BITMAP_BYTES; i++) {
|
||||
bitmap[i] = keyboard_state.pressed_usage_bitmap[i] &
|
||||
(uint8_t)~keyboard_state.function_pressed_bitmap[i];
|
||||
bitmap[i] = ctx.keyboard_state.pressed_usage_bitmap[i] &
|
||||
(uint8_t)~ctx.keyboard_state.function_pressed_bitmap[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +339,7 @@ static void build_nkro_report(uint8_t report[KEYBOARD_NKRO_REPORT_SIZE])
|
||||
static uint16_t active_consumer_usage_get(void)
|
||||
{
|
||||
for (uint8_t consumer_id = 0; consumer_id < KEYBOARD_CONSUMER_CTRL_COUNT; consumer_id++) {
|
||||
if ((keyboard_state.consumer_bits & BIT(consumer_id)) != 0U) {
|
||||
if ((ctx.keyboard_state.consumer_bits & BIT(consumer_id)) != 0U) {
|
||||
return consumer_usage_map[consumer_id];
|
||||
}
|
||||
}
|
||||
@@ -366,9 +358,9 @@ static void submit_consumer_fifo_frame(uint16_t usage_id)
|
||||
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
|
||||
enum mode_switch_mode mode;
|
||||
|
||||
if (!running || !mode_valid ||
|
||||
settings_active ||
|
||||
!transport_policy_to_mode(current_transport, &mode) ||
|
||||
if (!module_lifecycle_is_running(&ctx.lc) || !ctx.mode_valid ||
|
||||
ctx.settings_active ||
|
||||
!transport_policy_to_mode(ctx.current_transport, &mode) ||
|
||||
(protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) {
|
||||
return;
|
||||
}
|
||||
@@ -414,24 +406,25 @@ static void emit_keys_report(bool force)
|
||||
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
|
||||
enum mode_switch_mode mode;
|
||||
|
||||
if (!mode_valid || !transport_policy_to_mode(current_transport, &mode)) {
|
||||
if (!ctx.mode_valid ||
|
||||
!transport_policy_to_mode(ctx.current_transport, &mode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings_active) {
|
||||
if (ctx.settings_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT) {
|
||||
build_boot_report(report_buf);
|
||||
report_size = KEYBOARD_BOOT_REPORT_SIZE;
|
||||
cache_buf = reports_cache.boot_report;
|
||||
cache_valid = &reports_cache.boot_valid;
|
||||
cache_buf = ctx.reports_cache.boot_report;
|
||||
cache_valid = &ctx.reports_cache.boot_valid;
|
||||
} else {
|
||||
build_nkro_report(report_buf);
|
||||
report_size = KEYBOARD_NKRO_REPORT_SIZE;
|
||||
cache_buf = reports_cache.nkro_report;
|
||||
cache_valid = &reports_cache.nkro_valid;
|
||||
cache_buf = ctx.reports_cache.nkro_report;
|
||||
cache_valid = &ctx.reports_cache.nkro_valid;
|
||||
}
|
||||
|
||||
if (!force && *cache_valid && (memcmp(cache_buf, report_buf, report_size) == 0)) {
|
||||
@@ -452,21 +445,23 @@ static void emit_consumer_report(bool force)
|
||||
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
|
||||
enum mode_switch_mode mode;
|
||||
|
||||
if (!mode_valid || !transport_policy_to_mode(current_transport, &mode) ||
|
||||
settings_active ||
|
||||
if (!ctx.mode_valid ||
|
||||
!transport_policy_to_mode(ctx.current_transport, &mode) ||
|
||||
ctx.settings_active ||
|
||||
(protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
build_consumer_report(report_buf);
|
||||
if (!force && reports_cache.consumer_valid &&
|
||||
(memcmp(reports_cache.consumer_report, report_buf,
|
||||
if (!force && ctx.reports_cache.consumer_valid &&
|
||||
(memcmp(ctx.reports_cache.consumer_report, report_buf,
|
||||
KEYBOARD_CONSUMER_REPORT_SIZE) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(reports_cache.consumer_report, report_buf, KEYBOARD_CONSUMER_REPORT_SIZE);
|
||||
reports_cache.consumer_valid = true;
|
||||
memcpy(ctx.reports_cache.consumer_report, report_buf,
|
||||
KEYBOARD_CONSUMER_REPORT_SIZE);
|
||||
ctx.reports_cache.consumer_valid = true;
|
||||
|
||||
(void)submit_keyboard_hid_report_event(
|
||||
mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode,
|
||||
@@ -485,7 +480,8 @@ static void emit_all_reports(bool force)
|
||||
|
||||
static void emit_function_state_event(void)
|
||||
{
|
||||
(void)submit_function_bitmap_state_event(keyboard_state.pressed_usage_bitmap);
|
||||
(void)submit_function_bitmap_state_event(
|
||||
ctx.keyboard_state.pressed_usage_bitmap);
|
||||
}
|
||||
|
||||
static void emit_release_reports(enum hid_transport_policy transport_policy)
|
||||
@@ -526,11 +522,11 @@ static int do_init(void)
|
||||
keyboard_state_clear();
|
||||
reports_cache_invalidate();
|
||||
function_usage_mask_clear();
|
||||
mode_valid = false;
|
||||
settings_active = false;
|
||||
transport_protocol_modes[HID_TRANSPORT_USB] =
|
||||
ctx.mode_valid = false;
|
||||
ctx.settings_active = false;
|
||||
ctx.transport_protocol_modes[HID_TRANSPORT_USB] =
|
||||
KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
transport_protocol_modes[HID_TRANSPORT_BLE] =
|
||||
ctx.transport_protocol_modes[HID_TRANSPORT_BLE] =
|
||||
KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
|
||||
return 0;
|
||||
@@ -538,7 +534,7 @@ static int do_init(void)
|
||||
|
||||
static int do_start(void)
|
||||
{
|
||||
if (running) {
|
||||
if (module_lifecycle_is_running(&ctx.lc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -547,18 +543,18 @@ static int do_start(void)
|
||||
|
||||
static int do_stop(void)
|
||||
{
|
||||
if (!running) {
|
||||
if (!module_lifecycle_is_running(&ctx.lc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode_valid) {
|
||||
emit_release_reports(current_transport);
|
||||
if (ctx.mode_valid) {
|
||||
emit_release_reports(ctx.current_transport);
|
||||
}
|
||||
emit_function_state_event();
|
||||
|
||||
keyboard_state_clear();
|
||||
reports_cache_invalidate();
|
||||
mode_valid = false;
|
||||
ctx.mode_valid = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -568,11 +564,11 @@ static bool handle_button_event(const struct button_event *event)
|
||||
const struct keymap_entry *entry;
|
||||
bool changed;
|
||||
|
||||
if (!running) {
|
||||
if (!module_lifecycle_is_running(&ctx.lc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings_active) {
|
||||
if (ctx.settings_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -585,7 +581,7 @@ static bool handle_button_event(const struct button_event *event)
|
||||
if (entry->usage_type == KEY_USAGE_TYPE_KEYBOARD) {
|
||||
bool routed_to_function;
|
||||
|
||||
changed = usage_bitmap_write(keyboard_state.pressed_usage_bitmap,
|
||||
changed = usage_bitmap_write(ctx.keyboard_state.pressed_usage_bitmap,
|
||||
entry->usage_id, event->pressed);
|
||||
if (!changed) {
|
||||
return false;
|
||||
@@ -593,14 +589,14 @@ static bool handle_button_event(const struct button_event *event)
|
||||
|
||||
if (event->pressed) {
|
||||
routed_to_function =
|
||||
usage_bitmap_test(function_usage_mask, entry->usage_id);
|
||||
(void)usage_bitmap_write(keyboard_state.function_pressed_bitmap,
|
||||
usage_bitmap_test(ctx.function_usage_mask, entry->usage_id);
|
||||
(void)usage_bitmap_write(ctx.keyboard_state.function_pressed_bitmap,
|
||||
entry->usage_id, routed_to_function);
|
||||
} else {
|
||||
routed_to_function =
|
||||
usage_bitmap_test(keyboard_state.function_pressed_bitmap,
|
||||
usage_bitmap_test(ctx.keyboard_state.function_pressed_bitmap,
|
||||
entry->usage_id);
|
||||
(void)usage_bitmap_write(keyboard_state.function_pressed_bitmap,
|
||||
(void)usage_bitmap_write(ctx.keyboard_state.function_pressed_bitmap,
|
||||
entry->usage_id, false);
|
||||
}
|
||||
|
||||
@@ -624,23 +620,24 @@ static bool handle_transport_policy_event(
|
||||
{
|
||||
bool transport_changed;
|
||||
|
||||
if (!running) {
|
||||
current_transport = event->hid_transport;
|
||||
if (!module_lifecycle_is_running(&ctx.lc)) {
|
||||
ctx.current_transport = event->hid_transport;
|
||||
return false;
|
||||
}
|
||||
|
||||
transport_changed = mode_valid && (current_transport != event->hid_transport);
|
||||
transport_changed =
|
||||
ctx.mode_valid && (ctx.current_transport != event->hid_transport);
|
||||
if (transport_changed) {
|
||||
emit_release_reports(current_transport);
|
||||
emit_release_reports(ctx.current_transport);
|
||||
emit_function_state_event();
|
||||
keyboard_state_clear();
|
||||
reports_cache_invalidate();
|
||||
}
|
||||
|
||||
current_transport = event->hid_transport;
|
||||
mode_valid = (current_transport != HID_TRANSPORT_POLICY_NONE);
|
||||
ctx.current_transport = event->hid_transport;
|
||||
ctx.mode_valid = (ctx.current_transport != HID_TRANSPORT_POLICY_NONE);
|
||||
|
||||
if (mode_valid) {
|
||||
if (ctx.mode_valid) {
|
||||
emit_all_reports(true);
|
||||
}
|
||||
|
||||
@@ -649,11 +646,11 @@ static bool handle_transport_policy_event(
|
||||
|
||||
static bool handle_encoder_event(const struct encoder_event *event)
|
||||
{
|
||||
if (!running || !mode_valid) {
|
||||
if (!module_lifecycle_is_running(&ctx.lc) || !ctx.mode_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings_active) {
|
||||
if (ctx.settings_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -671,7 +668,8 @@ static bool handle_encoder_event(const struct encoder_event *event)
|
||||
static bool handle_function_bitmap_update_event(
|
||||
const struct function_bitmap_update_event *event)
|
||||
{
|
||||
memcpy(function_usage_mask, event->bitmap, sizeof(function_usage_mask));
|
||||
memcpy(ctx.function_usage_mask, event->bitmap,
|
||||
sizeof(ctx.function_usage_mask));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -698,11 +696,13 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transport_protocol_modes[event->transport] != event->protocol_mode) {
|
||||
transport_protocol_modes[event->transport] = event->protocol_mode;
|
||||
if (ctx.transport_protocol_modes[event->transport] !=
|
||||
event->protocol_mode) {
|
||||
ctx.transport_protocol_modes[event->transport] =
|
||||
event->protocol_mode;
|
||||
|
||||
if (running && mode_valid &&
|
||||
policy_to_transport(current_transport, &active_transport) &&
|
||||
if (module_lifecycle_is_running(&ctx.lc) && ctx.mode_valid &&
|
||||
policy_to_transport(ctx.current_transport, &active_transport) &&
|
||||
(active_transport == event->transport)) {
|
||||
reports_cache_invalidate();
|
||||
emit_keys_report(true);
|
||||
@@ -725,14 +725,14 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
const struct settings_mode_event *event =
|
||||
cast_settings_mode_event(aeh);
|
||||
|
||||
if (settings_active == event->active) {
|
||||
if (ctx.settings_active == event->active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
settings_active = event->active;
|
||||
if (settings_active) {
|
||||
if (mode_valid) {
|
||||
emit_release_reports(current_transport);
|
||||
ctx.settings_active = event->active;
|
||||
if (ctx.settings_active) {
|
||||
if (ctx.mode_valid) {
|
||||
emit_release_reports(ctx.current_transport);
|
||||
}
|
||||
emit_function_state_event();
|
||||
keyboard_state_clear();
|
||||
@@ -746,23 +746,23 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||
|
||||
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||
(void)module_set_lifecycle(&lifecycle, LC_RUNNING);
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_power_down_event(aeh)) {
|
||||
if (module_lifecycle_is_initialized(&lifecycle)) {
|
||||
(void)module_set_lifecycle(&lifecycle, LC_STOPPED);
|
||||
if (module_lifecycle_is_initialized(&ctx.lc)) {
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_STOPPED);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_wake_up_event(aeh)) {
|
||||
if (module_lifecycle_is_initialized(&lifecycle)) {
|
||||
(void)module_set_lifecycle(&lifecycle, LC_RUNNING);
|
||||
if (module_lifecycle_is_initialized(&ctx.lc)) {
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user