From 9b299102995c6d2c32684a1f67ce7c00e4b2c00b Mon Sep 17 00:00:00 2001 From: skiinder Date: Fri, 20 Mar 2026 13:47:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(hid=5Ftx=5Fmanager):=20=E9=87=8D=E6=9E=84H?= =?UTF-8?q?ID=E4=BC=A0=E8=BE=93=E7=AE=A1=E7=90=86=E5=99=A8=E4=BB=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=8A=A5=E5=91=8A=E7=8A=B6=E6=80=81=E8=B7=9F?= =?UTF-8?q?=E8=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入原子标志位替换布尔变量,提高线程安全性 - 使用消息队列替代循环缓冲区实现传输队列 - 添加boot和NKRO报告状态管理功能 - 实现脏标记机制优化报告发送流程 - 改进传输完成事件处理逻辑 --- src/modules/hid_tx_manager_module.c | 137 ++++++++++++++++------------ 1 file changed, 79 insertions(+), 58 deletions(-) diff --git a/src/modules/hid_tx_manager_module.c b/src/modules/hid_tx_manager_module.c index 7dbb2cb..e8ca058 100644 --- a/src/modules/hid_tx_manager_module.c +++ b/src/modules/hid_tx_manager_module.c @@ -1,10 +1,14 @@ #include +#include +#include + #include #define MODULE hid_tx_manager #include +#include "hid_report_descriptor.h" #include "hid_boot_event.h" #include "hid_report_event.h" #include "hid_tx_done_event.h" @@ -17,6 +21,15 @@ LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); #define HID_TX_QUEUE_SIZE 16 #define HID_TX_MAX_DATA 32 +enum hid_tx_flag { + HID_TX_FLAG_INITIALIZED = 0, + HID_TX_FLAG_IN_FLIGHT, + HID_TX_FLAG_BOOT_VALID, + HID_TX_FLAG_BOOT_DIRTY, + HID_TX_FLAG_NKRO_VALID, + HID_TX_FLAG_NKRO_DIRTY, +}; + struct hid_tx_item { enum hid_tx_kind kind; size_t len; @@ -24,86 +37,92 @@ struct hid_tx_item { }; struct hid_tx_ctx { - struct hid_tx_item queue[HID_TX_QUEUE_SIZE]; - uint8_t head; - uint8_t tail; - uint8_t count; - bool initialized; - bool in_flight; + atomic_t flags; + struct hid_tx_item boot_state; + struct hid_tx_item nkro_state; + struct hid_tx_item inflight_item; mode_type_t active_mode; - enum hid_tx_kind inflight_kind; }; static struct hid_tx_ctx tx = { .active_mode = MODE_TYPE_COUNT, }; -static bool hid_tx_queue_push(enum hid_tx_kind kind, const uint8_t *data, size_t len) -{ - struct hid_tx_item *item; +K_MSGQ_DEFINE(hid_tx_queue_msgq, sizeof(struct hid_tx_item), HID_TX_QUEUE_SIZE, 4); +static bool hid_tx_item_store(struct hid_tx_item *item, + enum hid_tx_kind kind, + const uint8_t *data, + size_t len) +{ if (len > HID_TX_MAX_DATA) { LOG_WRN("Drop HID tx kind=%u len=%u: too large", kind, len); return false; } - if (tx.count >= HID_TX_QUEUE_SIZE) { - LOG_WRN("Drop HID tx kind=%u len=%u: queue full", kind, len); - return false; - } - - item = &tx.queue[tx.tail]; item->kind = kind; item->len = len; if ((len > 0U) && (data != NULL)) { memcpy(item->data, data, len); } - tx.tail = (tx.tail + 1U) % HID_TX_QUEUE_SIZE; - tx.count++; return true; } -static struct hid_tx_item *hid_tx_queue_front(void) +static bool hid_tx_queue_push(enum hid_tx_kind kind, const uint8_t *data, size_t len) { - if (tx.count == 0U) { - return NULL; + struct hid_tx_item item; + + if (!hid_tx_item_store(&item, kind, data, len)) { + return false; } - return &tx.queue[tx.head]; + if (k_msgq_put(&hid_tx_queue_msgq, &item, K_NO_WAIT)) { + LOG_WRN("Drop HID tx kind=%u len=%u: queue full", kind, len); + return false; + } + + return true; } -static void hid_tx_queue_pop(void) +static bool hid_tx_dispatch_item(const struct hid_tx_item *item) { - __ASSERT_NO_MSG(tx.count > 0U); - tx.head = (tx.head + 1U) % HID_TX_QUEUE_SIZE; - tx.count--; + tx.inflight_item = *item; + atomic_set_bit(&tx.flags, HID_TX_FLAG_IN_FLIGHT); + hid_tx_event_submit(item->kind, item->data, item->len); + return true; } static void dispatch_next_if_possible(void) { - struct hid_tx_item *item; + struct hid_tx_item item; - if (!tx.initialized || tx.in_flight) { - return; - } - - item = hid_tx_queue_front(); - if (item == NULL) { + if (!atomic_test_bit(&tx.flags, HID_TX_FLAG_INITIALIZED) || + atomic_test_bit(&tx.flags, HID_TX_FLAG_IN_FLIGHT)) { return; } if ((tx.active_mode != MODE_TYPE_USB) && (tx.active_mode != MODE_TYPE_BLE)) { - LOG_WRN("Drop HID tx kind=%u: unsupported mode=%u", - item->kind, tx.active_mode); - hid_tx_queue_pop(); - dispatch_next_if_possible(); return; } - tx.in_flight = true; - tx.inflight_kind = item->kind; - hid_tx_event_submit(item->kind, item->data, item->len); + if (atomic_test_bit(&tx.flags, HID_TX_FLAG_NKRO_DIRTY) && + atomic_test_bit(&tx.flags, HID_TX_FLAG_NKRO_VALID)) { + atomic_clear_bit(&tx.flags, HID_TX_FLAG_NKRO_DIRTY); + (void)hid_tx_dispatch_item(&tx.nkro_state); + return; + } + + if (atomic_test_bit(&tx.flags, HID_TX_FLAG_BOOT_DIRTY) && + atomic_test_bit(&tx.flags, HID_TX_FLAG_BOOT_VALID)) { + atomic_clear_bit(&tx.flags, HID_TX_FLAG_BOOT_DIRTY); + (void)hid_tx_dispatch_item(&tx.boot_state); + return; + } + + if (!k_msgq_get(&hid_tx_queue_msgq, &item, K_NO_WAIT)) { + (void)hid_tx_dispatch_item(&item); + } } static bool handle_module_state_event(const struct module_state_event *event) @@ -112,8 +131,8 @@ static bool handle_module_state_event(const struct module_state_event *event) return false; } - __ASSERT_NO_MSG(!tx.initialized); - tx.initialized = true; + __ASSERT_NO_MSG(!atomic_test_bit(&tx.flags, HID_TX_FLAG_INITIALIZED)); + atomic_set_bit(&tx.flags, HID_TX_FLAG_INITIALIZED); module_set_state(MODULE_STATE_READY); dispatch_next_if_possible(); @@ -129,42 +148,44 @@ static bool handle_mode_event(const struct mode_event *event) static bool handle_hid_boot_request_event(const struct hid_boot_event *event) { - (void)hid_tx_queue_push(HID_TX_KIND_BOOT, + (void)hid_tx_item_store(&tx.boot_state, + HID_TX_KIND_BOOT, hid_boot_event_get_data(event), hid_boot_event_get_size(event)); + atomic_set_bit(&tx.flags, HID_TX_FLAG_BOOT_VALID); + atomic_set_bit(&tx.flags, HID_TX_FLAG_BOOT_DIRTY); dispatch_next_if_possible(); return true; } static bool handle_hid_report_request_event(const struct hid_report_event *event) { - (void)hid_tx_queue_push(HID_TX_KIND_REPORT, - hid_report_event_get_data(event), - hid_report_event_get_size(event)); + const uint8_t *data = hid_report_event_get_data(event); + size_t len = hid_report_event_get_size(event); + + if ((len > 0U) && (data[0] == REPORT_ID_KEYBOARD)) { + (void)hid_tx_item_store(&tx.nkro_state, HID_TX_KIND_REPORT, data, len); + atomic_set_bit(&tx.flags, HID_TX_FLAG_NKRO_VALID); + atomic_set_bit(&tx.flags, HID_TX_FLAG_NKRO_DIRTY); + } else { + (void)hid_tx_queue_push(HID_TX_KIND_REPORT, data, len); + } + dispatch_next_if_possible(); return true; } static bool handle_hid_tx_done_event(const struct hid_tx_done_event *event) { - struct hid_tx_item *item; - - if (!tx.in_flight) { + if (!atomic_test_bit(&tx.flags, HID_TX_FLAG_IN_FLIGHT)) { return false; } - if (event->kind != tx.inflight_kind) { + if (event->kind != tx.inflight_item.kind) { return false; } - item = hid_tx_queue_front(); - if (item == NULL) { - tx.in_flight = false; - return false; - } - - hid_tx_queue_pop(); - tx.in_flight = false; + atomic_clear_bit(&tx.flags, HID_TX_FLAG_IN_FLIGHT); dispatch_next_if_possible(); return false;