feat: 添加HID流控制模块和相关事件处理
- 添加hid_flowctrl_module.c实现HID报告流控制功能,包括FIFO队列管理和 报告发送控制 - 新增hid_report_sent_event、hid_transport_state_event和 hid_tx_report_event事件类型及其对应的头文件和实现 - 在CMakeLists.txt中注册新模块和事件源文件 - 修改keyboard_core_module.c以支持队列策略,并添加编码器事件处理逻辑 - 更新usb_hid_module.c将直接的键盘HID报告事件改为通过 hid_tx_report_event进行传输,并添加状态报告事件 - 在keyboard_hid_report_event中增加queue_policy字段以支持不同 队列策略
This commit is contained in:
@@ -14,10 +14,14 @@ target_sources(app PRIVATE
|
||||
src/main.c
|
||||
src/battery_module.c
|
||||
src/encoder_module.c
|
||||
src/hid_flowctrl_module.c
|
||||
src/keyboard_core_module.c
|
||||
src/usb_hid_module.c
|
||||
src/events/encoder_event.c
|
||||
src/events/hid_led_event.c
|
||||
src/events/hid_report_sent_event.c
|
||||
src/events/hid_transport_state_event.c
|
||||
src/events/hid_tx_report_event.c
|
||||
src/mode_switch_module.c
|
||||
src/events/keyboard_hid_report_event.c
|
||||
src/events/mode_switch_event.c
|
||||
|
||||
27
inc/events/hid_report_sent_event.h
Normal file
27
inc/events/hid_report_sent_event.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef BLINKY_HID_REPORT_SENT_EVENT_H_
|
||||
#define BLINKY_HID_REPORT_SENT_EVENT_H_
|
||||
|
||||
#include <app_event_manager.h>
|
||||
#include <app_event_manager_profiler_tracer.h>
|
||||
|
||||
#include "keyboard_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct hid_report_sent_event {
|
||||
struct app_event_header header;
|
||||
enum hid_transport transport;
|
||||
enum keyboard_report_type report_type;
|
||||
uint16_t sequence;
|
||||
bool error;
|
||||
};
|
||||
|
||||
APP_EVENT_TYPE_DECLARE(hid_report_sent_event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLINKY_HID_REPORT_SENT_EVENT_H_ */
|
||||
28
inc/events/hid_transport_state_event.h
Normal file
28
inc/events/hid_transport_state_event.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef BLINKY_HID_TRANSPORT_STATE_EVENT_H_
|
||||
#define BLINKY_HID_TRANSPORT_STATE_EVENT_H_
|
||||
|
||||
#include <app_event_manager.h>
|
||||
#include <app_event_manager_profiler_tracer.h>
|
||||
|
||||
#include "keyboard_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct hid_transport_state_event {
|
||||
struct app_event_header header;
|
||||
enum hid_transport transport;
|
||||
bool ready;
|
||||
bool keys_ready;
|
||||
bool consumer_ready;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
};
|
||||
|
||||
APP_EVENT_TYPE_DECLARE(hid_transport_state_event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLINKY_HID_TRANSPORT_STATE_EVENT_H_ */
|
||||
28
inc/events/hid_tx_report_event.h
Normal file
28
inc/events/hid_tx_report_event.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef BLINKY_HID_TX_REPORT_EVENT_H_
|
||||
#define BLINKY_HID_TX_REPORT_EVENT_H_
|
||||
|
||||
#include <app_event_manager.h>
|
||||
#include <app_event_manager_profiler_tracer.h>
|
||||
|
||||
#include "keyboard_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct hid_tx_report_event {
|
||||
struct app_event_header header;
|
||||
enum hid_transport transport;
|
||||
enum keyboard_report_type report_type;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
uint16_t sequence;
|
||||
struct event_dyndata dyndata;
|
||||
};
|
||||
|
||||
APP_EVENT_TYPE_DYNDATA_DECLARE(hid_tx_report_event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLINKY_HID_TX_REPORT_EVENT_H_ */
|
||||
@@ -16,6 +16,7 @@ struct keyboard_hid_report_event {
|
||||
enum mode_switch_mode mode;
|
||||
enum keyboard_report_type report_type;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
enum hid_queue_policy queue_policy;
|
||||
struct event_dyndata dyndata;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,15 @@ enum keyboard_report_type {
|
||||
KEYBOARD_REPORT_TYPE_CONSUMER,
|
||||
};
|
||||
|
||||
enum hid_queue_policy {
|
||||
HID_QUEUE_POLICY_LATEST,
|
||||
HID_QUEUE_POLICY_FIFO,
|
||||
};
|
||||
|
||||
enum hid_transport {
|
||||
HID_TRANSPORT_USB,
|
||||
};
|
||||
|
||||
enum keyboard_consumer_control {
|
||||
KEYBOARD_CONSUMER_CTRL_MUTE,
|
||||
KEYBOARD_CONSUMER_CTRL_VOLUME_UP,
|
||||
|
||||
59
src/events/hid_report_sent_event.c
Normal file
59
src/events/hid_report_sent_event.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "hid_report_sent_event.h"
|
||||
|
||||
static const char *transport_name(enum hid_transport transport)
|
||||
{
|
||||
switch (transport) {
|
||||
case HID_TRANSPORT_USB:
|
||||
return "USB";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *report_type_name(enum keyboard_report_type report_type)
|
||||
{
|
||||
switch (report_type) {
|
||||
case KEYBOARD_REPORT_TYPE_KEYS:
|
||||
return "keys";
|
||||
case KEYBOARD_REPORT_TYPE_CONSUMER:
|
||||
return "consumer";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_hid_report_sent_event(const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_report_sent_event *event = cast_hid_report_sent_event(aeh);
|
||||
|
||||
APP_EVENT_MANAGER_LOG(aeh, "transport:%s type:%s seq:%u error:%u",
|
||||
transport_name(event->transport),
|
||||
report_type_name(event->report_type),
|
||||
event->sequence,
|
||||
event->error);
|
||||
}
|
||||
|
||||
static void profile_hid_report_sent_event(struct log_event_buf *buf,
|
||||
const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_report_sent_event *event = cast_hid_report_sent_event(aeh);
|
||||
|
||||
nrf_profiler_log_encode_uint8(buf, event->transport);
|
||||
nrf_profiler_log_encode_uint8(buf, event->report_type);
|
||||
nrf_profiler_log_encode_uint16(buf, event->sequence);
|
||||
nrf_profiler_log_encode_uint8(buf, event->error);
|
||||
}
|
||||
|
||||
APP_EVENT_INFO_DEFINE(hid_report_sent_event,
|
||||
ENCODE(NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U16,
|
||||
NRF_PROFILER_ARG_U8),
|
||||
ENCODE("transport", "report_type", "sequence", "error"),
|
||||
profile_hid_report_sent_event);
|
||||
|
||||
APP_EVENT_TYPE_DEFINE(hid_report_sent_event,
|
||||
log_hid_report_sent_event,
|
||||
&hid_report_sent_event_info,
|
||||
APP_EVENT_FLAGS_CREATE(
|
||||
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||
66
src/events/hid_transport_state_event.c
Normal file
66
src/events/hid_transport_state_event.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "hid_transport_state_event.h"
|
||||
|
||||
static const char *transport_name(enum hid_transport transport)
|
||||
{
|
||||
switch (transport) {
|
||||
case HID_TRANSPORT_USB:
|
||||
return "USB";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *protocol_mode_name(enum keyboard_protocol_mode protocol_mode)
|
||||
{
|
||||
switch (protocol_mode) {
|
||||
case KEYBOARD_PROTOCOL_MODE_BOOT:
|
||||
return "boot";
|
||||
case KEYBOARD_PROTOCOL_MODE_REPORT:
|
||||
return "report";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_hid_transport_state_event(const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_transport_state_event *event =
|
||||
cast_hid_transport_state_event(aeh);
|
||||
|
||||
APP_EVENT_MANAGER_LOG(aeh,
|
||||
"transport:%s ready:%u keys_ready:%u consumer_ready:%u protocol:%s",
|
||||
transport_name(event->transport),
|
||||
event->ready,
|
||||
event->keys_ready,
|
||||
event->consumer_ready,
|
||||
protocol_mode_name(event->protocol_mode));
|
||||
}
|
||||
|
||||
static void profile_hid_transport_state_event(struct log_event_buf *buf,
|
||||
const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_transport_state_event *event =
|
||||
cast_hid_transport_state_event(aeh);
|
||||
|
||||
nrf_profiler_log_encode_uint8(buf, event->transport);
|
||||
nrf_profiler_log_encode_uint8(buf, event->ready);
|
||||
nrf_profiler_log_encode_uint8(buf, event->keys_ready);
|
||||
nrf_profiler_log_encode_uint8(buf, event->consumer_ready);
|
||||
nrf_profiler_log_encode_uint8(buf, event->protocol_mode);
|
||||
}
|
||||
|
||||
APP_EVENT_INFO_DEFINE(hid_transport_state_event,
|
||||
ENCODE(NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8),
|
||||
ENCODE("transport", "ready", "keys_ready", "consumer_ready",
|
||||
"protocol_mode"),
|
||||
profile_hid_transport_state_event);
|
||||
|
||||
APP_EVENT_TYPE_DEFINE(hid_transport_state_event,
|
||||
log_hid_transport_state_event,
|
||||
&hid_transport_state_event_info,
|
||||
APP_EVENT_FLAGS_CREATE(
|
||||
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||
105
src/events/hid_tx_report_event.c
Normal file
105
src/events/hid_tx_report_event.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hid_tx_report_event.h"
|
||||
|
||||
#define HID_TX_REPORT_EVENT_LOG_BUF_LEN 192
|
||||
|
||||
static const char *transport_name(enum hid_transport transport)
|
||||
{
|
||||
switch (transport) {
|
||||
case HID_TRANSPORT_USB:
|
||||
return "USB";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *report_type_name(enum keyboard_report_type report_type)
|
||||
{
|
||||
switch (report_type) {
|
||||
case KEYBOARD_REPORT_TYPE_KEYS:
|
||||
return "keys";
|
||||
case KEYBOARD_REPORT_TYPE_CONSUMER:
|
||||
return "consumer";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *protocol_mode_name(enum keyboard_protocol_mode protocol_mode)
|
||||
{
|
||||
switch (protocol_mode) {
|
||||
case KEYBOARD_PROTOCOL_MODE_BOOT:
|
||||
return "boot";
|
||||
case KEYBOARD_PROTOCOL_MODE_REPORT:
|
||||
return "report";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_hid_tx_report_event(const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_tx_report_event *event = cast_hid_tx_report_event(aeh);
|
||||
char log_buf[HID_TX_REPORT_EVENT_LOG_BUF_LEN];
|
||||
int pos;
|
||||
|
||||
pos = snprintf(log_buf, sizeof(log_buf),
|
||||
"transport:%s type:%s protocol:%s seq:%u len:%zu",
|
||||
transport_name(event->transport),
|
||||
report_type_name(event->report_type),
|
||||
protocol_mode_name(event->protocol_mode),
|
||||
event->sequence,
|
||||
event->dyndata.size);
|
||||
if ((pos > 0) && (pos < sizeof(log_buf))) {
|
||||
for (size_t i = 0; i < event->dyndata.size; i++) {
|
||||
int tmp = snprintf(&log_buf[pos], sizeof(log_buf) - pos,
|
||||
" %02x", event->dyndata.data[i]);
|
||||
|
||||
if (tmp < 0) {
|
||||
log_buf[sizeof(log_buf) - 2] = '~';
|
||||
pos = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
pos += tmp;
|
||||
if (pos >= sizeof(log_buf)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos < 0) {
|
||||
APP_EVENT_MANAGER_LOG(aeh, "log message preparation failure");
|
||||
return;
|
||||
}
|
||||
|
||||
APP_EVENT_MANAGER_LOG(aeh, "%s", log_buf);
|
||||
}
|
||||
|
||||
static void profile_hid_tx_report_event(struct log_event_buf *buf,
|
||||
const struct app_event_header *aeh)
|
||||
{
|
||||
const struct hid_tx_report_event *event = cast_hid_tx_report_event(aeh);
|
||||
|
||||
nrf_profiler_log_encode_uint8(buf, event->transport);
|
||||
nrf_profiler_log_encode_uint8(buf, event->report_type);
|
||||
nrf_profiler_log_encode_uint8(buf, event->protocol_mode);
|
||||
nrf_profiler_log_encode_uint16(buf, event->sequence);
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->dyndata.size);
|
||||
}
|
||||
|
||||
APP_EVENT_INFO_DEFINE(hid_tx_report_event,
|
||||
ENCODE(NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U16,
|
||||
NRF_PROFILER_ARG_U8),
|
||||
ENCODE("transport", "report_type", "protocol_mode", "sequence", "len"),
|
||||
profile_hid_tx_report_event);
|
||||
|
||||
APP_EVENT_TYPE_DEFINE(hid_tx_report_event,
|
||||
log_hid_tx_report_event,
|
||||
&hid_tx_report_event_info,
|
||||
APP_EVENT_FLAGS_CREATE(
|
||||
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||
@@ -42,6 +42,18 @@ static const char *protocol_mode_name(enum keyboard_protocol_mode protocol_mode)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *queue_policy_name(enum hid_queue_policy queue_policy)
|
||||
{
|
||||
switch (queue_policy) {
|
||||
case HID_QUEUE_POLICY_LATEST:
|
||||
return "latest";
|
||||
case HID_QUEUE_POLICY_FIFO:
|
||||
return "fifo";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_keyboard_hid_report_event(const struct app_event_header *aeh)
|
||||
{
|
||||
const struct keyboard_hid_report_event *event =
|
||||
@@ -49,10 +61,12 @@ static void log_keyboard_hid_report_event(const struct app_event_header *aeh)
|
||||
char log_buf[KEYBOARD_HID_REPORT_EVENT_LOG_BUF_LEN];
|
||||
int pos;
|
||||
|
||||
pos = snprintf(log_buf, sizeof(log_buf), "mode:%s type:%s protocol:%s len:%zu",
|
||||
pos = snprintf(log_buf, sizeof(log_buf),
|
||||
"mode:%s type:%s protocol:%s queue:%s len:%zu",
|
||||
mode_name(event->mode),
|
||||
report_type_name(event->report_type),
|
||||
protocol_mode_name(event->protocol_mode),
|
||||
queue_policy_name(event->queue_policy),
|
||||
event->dyndata.size);
|
||||
if ((pos > 0) && (pos < sizeof(log_buf))) {
|
||||
for (size_t i = 0; i < event->dyndata.size; i++) {
|
||||
@@ -89,15 +103,17 @@ static void profile_keyboard_hid_report_event(struct log_event_buf *buf,
|
||||
nrf_profiler_log_encode_uint8(buf, event->mode);
|
||||
nrf_profiler_log_encode_uint8(buf, event->report_type);
|
||||
nrf_profiler_log_encode_uint8(buf, event->protocol_mode);
|
||||
nrf_profiler_log_encode_uint8(buf, event->queue_policy);
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->dyndata.size);
|
||||
}
|
||||
|
||||
APP_EVENT_INFO_DEFINE(keyboard_hid_report_event,
|
||||
ENCODE(NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8),
|
||||
ENCODE("mode", "report_type", "protocol_mode", "len"),
|
||||
ENCODE("mode", "report_type", "protocol_mode", "queue_policy", "len"),
|
||||
profile_keyboard_hid_report_event);
|
||||
|
||||
APP_EVENT_TYPE_DEFINE(keyboard_hid_report_event,
|
||||
|
||||
390
src/hid_flowctrl_module.c
Normal file
390
src/hid_flowctrl_module.c
Normal file
@@ -0,0 +1,390 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <app_event_manager.h>
|
||||
|
||||
#define MODULE hid_flowctrl_module
|
||||
#include <caf/events/module_state_event.h>
|
||||
#include <caf/events/power_event.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "hid_report_sent_event.h"
|
||||
#include "hid_transport_state_event.h"
|
||||
#include "hid_tx_report_event.h"
|
||||
#include "keyboard_core.h"
|
||||
#include "keyboard_hid_report_event.h"
|
||||
#include "mode_switch_event.h"
|
||||
|
||||
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||
|
||||
#define HID_FLOWCTRL_FIFO_DEPTH 32U
|
||||
#define HID_FLOWCTRL_REPORT_DATA_MAX KEYBOARD_NKRO_REPORT_SIZE
|
||||
|
||||
struct pending_report {
|
||||
bool valid;
|
||||
enum keyboard_report_type report_type;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
size_t size;
|
||||
uint8_t data[HID_FLOWCTRL_REPORT_DATA_MAX];
|
||||
};
|
||||
|
||||
struct queued_report {
|
||||
enum keyboard_report_type report_type;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
size_t size;
|
||||
uint8_t data[HID_FLOWCTRL_REPORT_DATA_MAX];
|
||||
};
|
||||
|
||||
struct hid_transport_state_data {
|
||||
bool ready;
|
||||
bool keys_ready;
|
||||
bool consumer_ready;
|
||||
enum keyboard_protocol_mode protocol_mode;
|
||||
};
|
||||
|
||||
struct in_flight_report {
|
||||
bool active;
|
||||
enum keyboard_report_type report_type;
|
||||
uint16_t sequence;
|
||||
};
|
||||
|
||||
static struct hid_transport_state_data usb_state = {
|
||||
.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT,
|
||||
};
|
||||
static struct pending_report pending_keys;
|
||||
static struct pending_report pending_consumer_latest;
|
||||
static struct queued_report consumer_fifo[HID_FLOWCTRL_FIFO_DEPTH];
|
||||
static uint8_t consumer_fifo_head;
|
||||
static uint8_t consumer_fifo_tail;
|
||||
static uint8_t consumer_fifo_count;
|
||||
static struct in_flight_report in_flight;
|
||||
static enum mode_switch_mode current_mode;
|
||||
static uint16_t next_sequence;
|
||||
static bool initialized;
|
||||
static bool running;
|
||||
|
||||
static void clear_pending_reports(void)
|
||||
{
|
||||
memset(&pending_keys, 0, sizeof(pending_keys));
|
||||
memset(&pending_consumer_latest, 0, sizeof(pending_consumer_latest));
|
||||
consumer_fifo_head = 0U;
|
||||
consumer_fifo_tail = 0U;
|
||||
consumer_fifo_count = 0U;
|
||||
memset(&in_flight, 0, sizeof(in_flight));
|
||||
}
|
||||
|
||||
static void consumer_fifo_push(enum keyboard_report_type report_type,
|
||||
enum keyboard_protocol_mode protocol_mode,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
if (consumer_fifo_count == HID_FLOWCTRL_FIFO_DEPTH) {
|
||||
LOG_WRN("Consumer FIFO full, dropping oldest pulse");
|
||||
consumer_fifo_head = (consumer_fifo_head + 1U) % HID_FLOWCTRL_FIFO_DEPTH;
|
||||
consumer_fifo_count--;
|
||||
}
|
||||
|
||||
struct queued_report *entry = &consumer_fifo[consumer_fifo_tail];
|
||||
|
||||
entry->report_type = report_type;
|
||||
entry->protocol_mode = protocol_mode;
|
||||
entry->size = size;
|
||||
memcpy(entry->data, data, size);
|
||||
|
||||
consumer_fifo_tail = (consumer_fifo_tail + 1U) % HID_FLOWCTRL_FIFO_DEPTH;
|
||||
consumer_fifo_count++;
|
||||
}
|
||||
|
||||
static bool consumer_fifo_pop(struct queued_report *entry)
|
||||
{
|
||||
if (consumer_fifo_count == 0U) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*entry = consumer_fifo[consumer_fifo_head];
|
||||
consumer_fifo_head = (consumer_fifo_head + 1U) % HID_FLOWCTRL_FIFO_DEPTH;
|
||||
consumer_fifo_count--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool transport_can_send_report(enum keyboard_report_type report_type)
|
||||
{
|
||||
if ((current_mode != MODE_SWITCH_USB) || !usb_state.ready || in_flight.active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (report_type == KEYBOARD_REPORT_TYPE_KEYS) {
|
||||
return usb_state.keys_ready;
|
||||
}
|
||||
|
||||
return usb_state.consumer_ready;
|
||||
}
|
||||
|
||||
static void submit_hid_tx_report_event(enum keyboard_report_type report_type,
|
||||
enum keyboard_protocol_mode protocol_mode,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
struct hid_tx_report_event *event = new_hid_tx_report_event(size);
|
||||
|
||||
event->transport = HID_TRANSPORT_USB;
|
||||
event->report_type = report_type;
|
||||
event->protocol_mode = protocol_mode;
|
||||
event->sequence = next_sequence++;
|
||||
memcpy(event->dyndata.data, data, size);
|
||||
|
||||
in_flight.active = true;
|
||||
in_flight.report_type = report_type;
|
||||
in_flight.sequence = event->sequence;
|
||||
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void try_send_next(void)
|
||||
{
|
||||
struct queued_report queued;
|
||||
|
||||
if (!running || in_flight.active || (current_mode != MODE_SWITCH_USB) || !usb_state.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending_keys.valid && transport_can_send_report(KEYBOARD_REPORT_TYPE_KEYS)) {
|
||||
if (pending_keys.protocol_mode != usb_state.protocol_mode) {
|
||||
LOG_WRN("Drop stale keys report after protocol change");
|
||||
pending_keys.valid = false;
|
||||
} else {
|
||||
submit_hid_tx_report_event(pending_keys.report_type,
|
||||
pending_keys.protocol_mode,
|
||||
pending_keys.data,
|
||||
pending_keys.size);
|
||||
pending_keys.valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((consumer_fifo_count > 0U) &&
|
||||
transport_can_send_report(KEYBOARD_REPORT_TYPE_CONSUMER) &&
|
||||
consumer_fifo_pop(&queued)) {
|
||||
submit_hid_tx_report_event(queued.report_type,
|
||||
queued.protocol_mode,
|
||||
queued.data,
|
||||
queued.size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending_consumer_latest.valid &&
|
||||
transport_can_send_report(KEYBOARD_REPORT_TYPE_CONSUMER)) {
|
||||
submit_hid_tx_report_event(pending_consumer_latest.report_type,
|
||||
pending_consumer_latest.protocol_mode,
|
||||
pending_consumer_latest.data,
|
||||
pending_consumer_latest.size);
|
||||
pending_consumer_latest.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_event *event)
|
||||
{
|
||||
if (!running || (event->mode != MODE_SWITCH_USB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->queue_policy == HID_QUEUE_POLICY_FIFO) {
|
||||
consumer_fifo_push(event->report_type,
|
||||
event->protocol_mode,
|
||||
event->dyndata.data,
|
||||
event->dyndata.size);
|
||||
} else if (event->report_type == KEYBOARD_REPORT_TYPE_KEYS) {
|
||||
pending_keys.valid = true;
|
||||
pending_keys.report_type = event->report_type;
|
||||
pending_keys.protocol_mode = event->protocol_mode;
|
||||
pending_keys.size = event->dyndata.size;
|
||||
memcpy(pending_keys.data, event->dyndata.data, event->dyndata.size);
|
||||
} else {
|
||||
pending_consumer_latest.valid = true;
|
||||
pending_consumer_latest.report_type = event->report_type;
|
||||
pending_consumer_latest.protocol_mode = event->protocol_mode;
|
||||
pending_consumer_latest.size = event->dyndata.size;
|
||||
memcpy(pending_consumer_latest.data, event->dyndata.data,
|
||||
event->dyndata.size);
|
||||
}
|
||||
|
||||
try_send_next();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_hid_transport_state_event(const struct hid_transport_state_event *event)
|
||||
{
|
||||
if (event->transport != HID_TRANSPORT_USB) {
|
||||
return false;
|
||||
}
|
||||
|
||||
usb_state.ready = event->ready;
|
||||
usb_state.keys_ready = event->keys_ready;
|
||||
usb_state.consumer_ready = event->consumer_ready;
|
||||
|
||||
if (usb_state.protocol_mode != event->protocol_mode) {
|
||||
usb_state.protocol_mode = event->protocol_mode;
|
||||
pending_keys.valid = false;
|
||||
}
|
||||
|
||||
if (!usb_state.ready) {
|
||||
consumer_fifo_head = 0U;
|
||||
consumer_fifo_tail = 0U;
|
||||
consumer_fifo_count = 0U;
|
||||
in_flight.active = false;
|
||||
}
|
||||
|
||||
try_send_next();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_hid_report_sent_event(const struct hid_report_sent_event *event)
|
||||
{
|
||||
if ((event->transport != HID_TRANSPORT_USB) || !in_flight.active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->sequence != in_flight.sequence) {
|
||||
LOG_WRN("Unexpected HID sent sequence %u (expected %u)",
|
||||
event->sequence, in_flight.sequence);
|
||||
return false;
|
||||
}
|
||||
|
||||
in_flight.active = false;
|
||||
|
||||
if (event->error) {
|
||||
LOG_WRN("HID report send failed for seq %u", event->sequence);
|
||||
}
|
||||
|
||||
try_send_next();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_mode_switch_event(const struct mode_switch_event *event)
|
||||
{
|
||||
current_mode = event->mode;
|
||||
|
||||
if (current_mode != MODE_SWITCH_USB) {
|
||||
clear_pending_reports();
|
||||
}
|
||||
|
||||
try_send_next();
|
||||
return false;
|
||||
}
|
||||
|
||||
static int module_init(void)
|
||||
{
|
||||
clear_pending_reports();
|
||||
current_mode = MODE_SWITCH_USB;
|
||||
usb_state.ready = false;
|
||||
usb_state.keys_ready = false;
|
||||
usb_state.consumer_ready = false;
|
||||
usb_state.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
next_sequence = 1U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int module_start(void)
|
||||
{
|
||||
if (running) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
running = true;
|
||||
try_send_next();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void module_pause(void)
|
||||
{
|
||||
if (!running) {
|
||||
return;
|
||||
}
|
||||
|
||||
clear_pending_reports();
|
||||
running = false;
|
||||
}
|
||||
|
||||
static bool app_event_handler(const struct app_event_header *aeh)
|
||||
{
|
||||
if (is_keyboard_hid_report_event(aeh)) {
|
||||
return handle_keyboard_hid_report_event(cast_keyboard_hid_report_event(aeh));
|
||||
}
|
||||
|
||||
if (is_hid_transport_state_event(aeh)) {
|
||||
return handle_hid_transport_state_event(cast_hid_transport_state_event(aeh));
|
||||
}
|
||||
|
||||
if (is_hid_report_sent_event(aeh)) {
|
||||
return handle_hid_report_sent_event(cast_hid_report_sent_event(aeh));
|
||||
}
|
||||
|
||||
if (is_mode_switch_event(aeh)) {
|
||||
return handle_mode_switch_event(cast_mode_switch_event(aeh));
|
||||
}
|
||||
|
||||
if (is_module_state_event(aeh)) {
|
||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||
|
||||
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||
int err;
|
||||
|
||||
if (!initialized) {
|
||||
err = module_init();
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
err = module_start();
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
} else {
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_power_down_event(aeh)) {
|
||||
if (initialized) {
|
||||
module_pause();
|
||||
module_set_state(MODULE_STATE_STANDBY);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_wake_up_event(aeh)) {
|
||||
if (initialized) {
|
||||
int err = module_start();
|
||||
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
} else {
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, keyboard_hid_report_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, hid_transport_state_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, hid_report_sent_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "encoder_event.h"
|
||||
#include "keyboard_core.h"
|
||||
#include "keyboard_hid_report_event.h"
|
||||
#include "mode_switch_event.h"
|
||||
@@ -228,6 +229,7 @@ static void build_consumer_report(uint8_t report[KEYBOARD_CONSUMER_REPORT_SIZE])
|
||||
}
|
||||
|
||||
static void submit_keyboard_report_event(enum keyboard_report_type report_type,
|
||||
enum hid_queue_policy queue_policy,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
struct keyboard_hid_report_event *event =
|
||||
@@ -236,11 +238,49 @@ static void submit_keyboard_report_event(enum keyboard_report_type report_type,
|
||||
event->mode = current_mode;
|
||||
event->report_type = report_type;
|
||||
event->protocol_mode = protocol_mode;
|
||||
event->queue_policy = queue_policy;
|
||||
memcpy(event->dyndata.data, data, size);
|
||||
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void submit_consumer_fifo_frame(uint16_t usage_id)
|
||||
{
|
||||
uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE];
|
||||
|
||||
if (!running || !mode_valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
sys_put_le16(usage_id, report_buf);
|
||||
submit_keyboard_report_event(KEYBOARD_REPORT_TYPE_CONSUMER,
|
||||
HID_QUEUE_POLICY_FIFO,
|
||||
report_buf,
|
||||
KEYBOARD_CONSUMER_REPORT_SIZE);
|
||||
}
|
||||
|
||||
static void submit_consumer_pulse_frames(enum keyboard_consumer_control control_id,
|
||||
uint8_t pulse_count)
|
||||
{
|
||||
uint16_t usage_id;
|
||||
|
||||
if (control_id >= KEYBOARD_CONSUMER_CTRL_COUNT) {
|
||||
LOG_WRN("Unsupported consumer control id %u", control_id);
|
||||
return;
|
||||
}
|
||||
|
||||
usage_id = consumer_usage_map[control_id];
|
||||
if (usage_id == 0U) {
|
||||
LOG_WRN("Unmapped consumer control id %u", control_id);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < pulse_count; i++) {
|
||||
submit_consumer_fifo_frame(usage_id);
|
||||
submit_consumer_fifo_frame(0U);
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_keys_report(bool force)
|
||||
{
|
||||
uint8_t report_buf[KEYBOARD_NKRO_REPORT_SIZE];
|
||||
@@ -271,7 +311,10 @@ static void emit_keys_report(bool force)
|
||||
memcpy(cache_buf, report_buf, report_size);
|
||||
*cache_valid = true;
|
||||
|
||||
submit_keyboard_report_event(KEYBOARD_REPORT_TYPE_KEYS, report_buf, report_size);
|
||||
submit_keyboard_report_event(KEYBOARD_REPORT_TYPE_KEYS,
|
||||
HID_QUEUE_POLICY_LATEST,
|
||||
report_buf,
|
||||
report_size);
|
||||
}
|
||||
|
||||
static void emit_consumer_report(bool force)
|
||||
@@ -293,6 +336,7 @@ static void emit_consumer_report(bool force)
|
||||
reports_cache.consumer_valid = true;
|
||||
|
||||
submit_keyboard_report_event(KEYBOARD_REPORT_TYPE_CONSUMER,
|
||||
HID_QUEUE_POLICY_LATEST,
|
||||
report_buf,
|
||||
KEYBOARD_CONSUMER_REPORT_SIZE);
|
||||
}
|
||||
@@ -416,12 +460,33 @@ static bool handle_mode_switch_event(const struct mode_switch_event *event)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_encoder_event(const struct encoder_event *event)
|
||||
{
|
||||
if (!running || !mode_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->detents > 0) {
|
||||
submit_consumer_pulse_frames(KEYBOARD_CONSUMER_CTRL_VOLUME_UP,
|
||||
(uint8_t)event->detents);
|
||||
} else if (event->detents < 0) {
|
||||
submit_consumer_pulse_frames(KEYBOARD_CONSUMER_CTRL_VOLUME_DOWN,
|
||||
(uint8_t)(-event->detents));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool app_event_handler(const struct app_event_header *aeh)
|
||||
{
|
||||
if (is_button_event(aeh)) {
|
||||
return handle_button_event(cast_button_event(aeh));
|
||||
}
|
||||
|
||||
if (is_encoder_event(aeh)) {
|
||||
return handle_encoder_event(cast_encoder_event(aeh));
|
||||
}
|
||||
|
||||
if (is_set_protocol_event(aeh)) {
|
||||
const struct set_protocol_event *event = cast_set_protocol_event(aeh);
|
||||
|
||||
@@ -496,6 +561,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
|
||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, button_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, encoder_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, set_protocol_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#include <zephyr/usb/usbd.h>
|
||||
|
||||
#include "hid_led_event.h"
|
||||
#include "hid_report_sent_event.h"
|
||||
#include "hid_transport_state_event.h"
|
||||
#include "hid_tx_report_event.h"
|
||||
#include "keyboard_core.h"
|
||||
#include "keyboard_hid_report_event.h"
|
||||
#include "set_protocol_event.h"
|
||||
|
||||
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||
@@ -107,6 +109,8 @@ static bool running;
|
||||
static bool usb_enabled;
|
||||
static bool keyboard_report_in_flight;
|
||||
static bool consumer_report_in_flight;
|
||||
static uint16_t keyboard_in_flight_sequence;
|
||||
static uint16_t consumer_in_flight_sequence;
|
||||
|
||||
UDC_STATIC_BUF_DEFINE(keyboard_tx_buf, KEYBOARD_NKRO_REPORT_SIZE);
|
||||
UDC_STATIC_BUF_DEFINE(consumer_tx_buf, KEYBOARD_CONSUMER_REPORT_SIZE);
|
||||
@@ -158,6 +162,34 @@ static void submit_hid_led_event(uint8_t led_bm)
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void submit_transport_state_event(void)
|
||||
{
|
||||
struct hid_transport_state_event *event = new_hid_transport_state_event();
|
||||
|
||||
event->transport = HID_TRANSPORT_USB;
|
||||
event->ready = usb_enabled;
|
||||
event->keys_ready = usb_enabled &&
|
||||
hid_ifaces[USB_HID_INTERFACE_KEYBOARD].ready;
|
||||
event->consumer_ready = usb_enabled &&
|
||||
hid_ifaces[USB_HID_INTERFACE_CONSUMER].ready;
|
||||
event->protocol_mode = keyboard_protocol_mode;
|
||||
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void submit_hid_report_sent_event(enum keyboard_report_type report_type,
|
||||
uint16_t sequence, bool error)
|
||||
{
|
||||
struct hid_report_sent_event *event = new_hid_report_sent_event();
|
||||
|
||||
event->transport = HID_TRANSPORT_USB;
|
||||
event->report_type = report_type;
|
||||
event->sequence = sequence;
|
||||
event->error = error;
|
||||
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void keyboard_iface_ready(const struct device *dev, const bool ready)
|
||||
{
|
||||
struct usb_hid_interface_state *iface = iface_from_dev(dev);
|
||||
@@ -172,6 +204,7 @@ static void keyboard_iface_ready(const struct device *dev, const bool ready)
|
||||
}
|
||||
LOG_INF("%s interface %s",
|
||||
dev->name, ready ? "ready" : "not ready");
|
||||
submit_transport_state_event();
|
||||
}
|
||||
|
||||
static int keyboard_get_report(const struct device *dev,
|
||||
@@ -230,6 +263,7 @@ static void keyboard_set_protocol(const struct device *dev, const uint8_t proto)
|
||||
LOG_INF("USB keyboard protocol -> %s",
|
||||
(new_mode == KEYBOARD_PROTOCOL_MODE_BOOT) ? "boot" : "report");
|
||||
submit_set_protocol_event(new_mode);
|
||||
submit_transport_state_event();
|
||||
}
|
||||
|
||||
static void keyboard_input_report_done(const struct device *dev,
|
||||
@@ -239,6 +273,8 @@ static void keyboard_input_report_done(const struct device *dev,
|
||||
|
||||
keyboard_report_in_flight = false;
|
||||
LOG_DBG("USB keyboard report sent by %s", dev->name);
|
||||
submit_hid_report_sent_event(KEYBOARD_REPORT_TYPE_KEYS,
|
||||
keyboard_in_flight_sequence, false);
|
||||
}
|
||||
|
||||
static void keyboard_output_report(const struct device *dev,
|
||||
@@ -280,6 +316,7 @@ static void consumer_iface_ready(const struct device *dev, const bool ready)
|
||||
}
|
||||
LOG_INF("%s interface %s",
|
||||
dev->name, ready ? "ready" : "not ready");
|
||||
submit_transport_state_event();
|
||||
}
|
||||
|
||||
static int consumer_get_report(const struct device *dev,
|
||||
@@ -337,6 +374,8 @@ static void consumer_input_report_done(const struct device *dev,
|
||||
|
||||
consumer_report_in_flight = false;
|
||||
LOG_DBG("USB consumer report sent by %s", dev->name);
|
||||
submit_hid_report_sent_event(KEYBOARD_REPORT_TYPE_CONSUMER,
|
||||
consumer_in_flight_sequence, false);
|
||||
}
|
||||
|
||||
static void consumer_output_report(const struct device *dev,
|
||||
@@ -372,6 +411,7 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
|
||||
LOG_ERR("usbd_enable failed (%d)", err);
|
||||
} else {
|
||||
usb_enabled = true;
|
||||
submit_transport_state_event();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,6 +431,7 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
|
||||
}
|
||||
keyboard_report_in_flight = false;
|
||||
consumer_report_in_flight = false;
|
||||
submit_transport_state_event();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,6 +551,7 @@ static int module_start(void)
|
||||
}
|
||||
|
||||
running = true;
|
||||
submit_transport_state_event();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -518,11 +560,11 @@ static void module_pause(void)
|
||||
running = false;
|
||||
}
|
||||
|
||||
static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_event *event)
|
||||
static bool handle_hid_tx_report_event(const struct hid_tx_report_event *event)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!running || (event->mode != MODE_SWITCH_USB)) {
|
||||
if (!running || (event->transport != HID_TRANSPORT_USB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -550,8 +592,11 @@ static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_ev
|
||||
keyboard_tx_buf);
|
||||
if (err) {
|
||||
LOG_WRN("USB keyboard report submit failed (%d)", err);
|
||||
submit_hid_report_sent_event(KEYBOARD_REPORT_TYPE_KEYS,
|
||||
event->sequence, true);
|
||||
} else {
|
||||
keyboard_report_in_flight = true;
|
||||
keyboard_in_flight_sequence = event->sequence;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -576,8 +621,11 @@ static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_ev
|
||||
consumer_tx_buf);
|
||||
if (err) {
|
||||
LOG_WRN("USB consumer report submit failed (%d)", err);
|
||||
submit_hid_report_sent_event(KEYBOARD_REPORT_TYPE_CONSUMER,
|
||||
event->sequence, true);
|
||||
} else {
|
||||
consumer_report_in_flight = true;
|
||||
consumer_in_flight_sequence = event->sequence;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,9 +634,8 @@ static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_ev
|
||||
|
||||
static bool app_event_handler(const struct app_event_header *aeh)
|
||||
{
|
||||
if (is_keyboard_hid_report_event(aeh)) {
|
||||
return handle_keyboard_hid_report_event(
|
||||
cast_keyboard_hid_report_event(aeh));
|
||||
if (is_hid_tx_report_event(aeh)) {
|
||||
return handle_hid_tx_report_event(cast_hid_tx_report_event(aeh));
|
||||
}
|
||||
|
||||
if (is_module_state_event(aeh)) {
|
||||
@@ -647,6 +694,6 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
|
||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, keyboard_hid_report_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, hid_tx_report_event);
|
||||
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);
|
||||
|
||||
Reference in New Issue
Block a user