diff --git a/CMakeLists.txt b/CMakeLists.txt index 411936a..6369b5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ target_sources(app PRIVATE src/events/set_protocol_event.c src/events/theme_rgb_update_event.c src/events/time_sync_event.c + src/events/transport_policy_event.c src/events/usb_control_event.c src/events/usb_state_event.c ) diff --git a/inc/events/transport_policy_event.h b/inc/events/transport_policy_event.h new file mode 100644 index 0000000..9ead5d9 --- /dev/null +++ b/inc/events/transport_policy_event.h @@ -0,0 +1,42 @@ +#ifndef BLINKY_TRANSPORT_POLICY_EVENT_H_ +#define BLINKY_TRANSPORT_POLICY_EVENT_H_ + +#include + +#include "mode_switch_event.h" + +enum hid_transport_policy { + HID_TRANSPORT_POLICY_NONE = 0, + HID_TRANSPORT_POLICY_USB, + HID_TRANSPORT_POLICY_BLE, +}; + +enum ble_profile_policy { + BLE_PROFILE_POLICY_NONE = 0, + BLE_PROFILE_POLICY_GENERAL, + BLE_PROFILE_POLICY_DONGLE, +}; + +struct transport_policy_event { + struct app_event_header header; + enum mode_switch_mode source_mode; + enum hid_transport_policy hid_transport; + enum ble_profile_policy ble_profile; +}; + +APP_EVENT_TYPE_DECLARE(transport_policy_event); + +static inline void submit_transport_policy_event( + enum mode_switch_mode source_mode, + enum hid_transport_policy hid_transport, + enum ble_profile_policy ble_profile) +{ + struct transport_policy_event *event = new_transport_policy_event(); + + event->source_mode = source_mode; + event->hid_transport = hid_transport; + event->ble_profile = ble_profile; + APP_EVENT_SUBMIT(event); +} + +#endif /* BLINKY_TRANSPORT_POLICY_EVENT_H_ */ diff --git a/src/events/transport_policy_event.c b/src/events/transport_policy_event.c new file mode 100644 index 0000000..05f5ee0 --- /dev/null +++ b/src/events/transport_policy_event.c @@ -0,0 +1,78 @@ +#include "transport_policy_event.h" + +static const char *source_mode_name(enum mode_switch_mode mode) +{ + switch (mode) { + case MODE_SWITCH_USB: + return "USB"; + case MODE_SWITCH_BLE: + return "BLE"; + case MODE_SWITCH_24G: + return "24G"; + default: + return "?"; + } +} + +static const char *hid_transport_policy_name(enum hid_transport_policy transport) +{ + switch (transport) { + case HID_TRANSPORT_POLICY_NONE: + return "none"; + case HID_TRANSPORT_POLICY_USB: + return "usb"; + case HID_TRANSPORT_POLICY_BLE: + return "ble"; + default: + return "?"; + } +} + +static const char *ble_profile_policy_name(enum ble_profile_policy profile) +{ + switch (profile) { + case BLE_PROFILE_POLICY_NONE: + return "none"; + case BLE_PROFILE_POLICY_GENERAL: + return "general"; + case BLE_PROFILE_POLICY_DONGLE: + return "dongle"; + default: + return "?"; + } +} + +static void log_transport_policy_event(const struct app_event_header *aeh) +{ + const struct transport_policy_event *event = + cast_transport_policy_event(aeh); + + APP_EVENT_MANAGER_LOG(aeh, "source:%s hid:%s ble:%s", + source_mode_name(event->source_mode), + hid_transport_policy_name(event->hid_transport), + ble_profile_policy_name(event->ble_profile)); +} + +static void profile_transport_policy_event(struct log_event_buf *buf, + const struct app_event_header *aeh) +{ + const struct transport_policy_event *event = + cast_transport_policy_event(aeh); + + nrf_profiler_log_encode_uint8(buf, event->source_mode); + nrf_profiler_log_encode_uint8(buf, event->hid_transport); + nrf_profiler_log_encode_uint8(buf, event->ble_profile); +} + +APP_EVENT_INFO_DEFINE(transport_policy_event, + ENCODE(NRF_PROFILER_ARG_U8, NRF_PROFILER_ARG_U8, + NRF_PROFILER_ARG_U8), + ENCODE("source_mode", "hid_transport", "ble_profile"), + profile_transport_policy_event); + +APP_EVENT_TYPE_DEFINE(transport_policy_event, + log_transport_policy_event, + &transport_policy_event_info, + APP_EVENT_FLAGS_CREATE( + IF_ENABLED(CONFIG_BRIDGE_LOG_TRANSPORT_POLICY_EVENT, + (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/src/hid_flowctrl_module.c b/src/hid_flowctrl_module.c index e0d450c..ae2a905 100644 --- a/src/hid_flowctrl_module.c +++ b/src/hid_flowctrl_module.c @@ -16,7 +16,7 @@ #include "keyboard_core.h" #include "keyboard_hid_report_event.h" #include "module_lifecycle.h" -#include "mode_switch_event.h" +#include "transport_policy_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); @@ -60,7 +60,7 @@ struct hid_flowctrl_module_ctx { uint8_t consumer_fifo_tail; uint8_t consumer_fifo_count; struct in_flight_report in_flight[HID_SEND_CH_COUNT]; - enum mode_switch_mode current_mode; + enum hid_transport_policy current_transport; uint16_t next_sequence; }; @@ -107,25 +107,25 @@ static struct hid_flowctrl_module_ctx ctx = { #define consumer_fifo_tail ctx.consumer_fifo_tail #define consumer_fifo_count ctx.consumer_fifo_count #define in_flight ctx.in_flight -#define current_mode ctx.current_mode +#define current_transport ctx.current_transport #define next_sequence ctx.next_sequence #define running module_lifecycle_is_running(&ctx.lc) -static bool current_mode_to_channel(enum keyboard_report_type report_type, - enum hid_send_channel *channel) +static bool current_transport_to_channel(enum keyboard_report_type report_type, + enum hid_send_channel *channel) { if (channel == NULL) { return false; } - switch (current_mode) { - case MODE_SWITCH_USB: + switch (current_transport) { + case HID_TRANSPORT_POLICY_USB: *channel = (report_type == KEYBOARD_REPORT_TYPE_KEYS) ? HID_SEND_CH_USB_KEYS : HID_SEND_CH_USB_CONSUMER; return true; - case MODE_SWITCH_BLE: + case HID_TRANSPORT_POLICY_BLE: *channel = HID_SEND_CH_BLE_SHARED; return true; @@ -209,7 +209,7 @@ static void try_send_keys(void) return; } - if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_KEYS, &channel)) { + if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_KEYS, &channel)) { return; } @@ -238,7 +238,7 @@ static void try_send_consumer_fifo(void) return; } - if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { + if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { return; } @@ -273,7 +273,7 @@ static void try_send_consumer_latest(void) return; } - if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { + if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { return; } @@ -383,14 +383,15 @@ static bool handle_hid_report_sent_event(const struct hid_report_sent_event *eve return false; } -static bool handle_mode_switch_event(const struct mode_switch_event *event) +static bool handle_transport_policy_event( + const struct transport_policy_event *event) { - bool mode_changed = (current_mode != event->mode); + bool transport_changed = (current_transport != event->hid_transport); - current_mode = event->mode; + current_transport = event->hid_transport; - if (mode_changed || ((current_mode != MODE_SWITCH_USB) && - (current_mode != MODE_SWITCH_BLE))) { + if (transport_changed || + (current_transport == HID_TRANSPORT_POLICY_NONE)) { clear_pending_reports(); } @@ -401,7 +402,7 @@ static bool handle_mode_switch_event(const struct mode_switch_event *event) static int do_init(void) { clear_pending_reports(); - current_mode = MODE_SWITCH_USB; + current_transport = HID_TRANSPORT_POLICY_USB; memset(channel_state, 0, sizeof(channel_state)); channel_state[HID_SEND_CH_USB_KEYS].protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT; @@ -451,8 +452,9 @@ static bool app_event_handler(const struct app_event_header *aeh) cast_hid_report_sent_event(aeh)); } - if (is_mode_switch_event(aeh)) { - return handle_mode_switch_event(cast_mode_switch_event(aeh)); + if (is_transport_policy_event(aeh)) { + return handle_transport_policy_event( + cast_transport_policy_event(aeh)); } if (is_module_state_event(aeh)) { @@ -490,7 +492,7 @@ APP_EVENT_LISTENER(MODULE, app_event_handler); APP_EVENT_SUBSCRIBE(MODULE, keyboard_hid_report_event); APP_EVENT_SUBSCRIBE(MODULE, hid_channel_state_event); APP_EVENT_SUBSCRIBE(MODULE, hid_report_sent_event); -APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event); +APP_EVENT_SUBSCRIBE(MODULE, transport_policy_event); APP_EVENT_SUBSCRIBE(MODULE, module_state_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); APP_EVENT_SUBSCRIBE(MODULE, wake_up_event); diff --git a/src/keyboard_core_module.c b/src/keyboard_core_module.c index d5aa94f..14f1835 100644 --- a/src/keyboard_core_module.c +++ b/src/keyboard_core_module.c @@ -20,8 +20,8 @@ #include "keyboard_core.h" #include "keyboard_hid_report_event.h" #include "module_lifecycle.h" -#include "mode_switch_event.h" #include "set_protocol_event.h" +#include "transport_policy_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); @@ -92,7 +92,7 @@ struct keyboard_core_module_ctx { struct keyboard_reports_cache reports_cache; uint8_t function_usage_mask[KEYBOARD_PROTOCOL_BITMAP_BYTES]; enum keyboard_protocol_mode transport_protocol_modes[HID_TRANSPORT_COUNT]; - enum mode_switch_mode current_mode; + enum hid_transport_policy current_transport; bool mode_valid; }; @@ -128,18 +128,19 @@ static struct keyboard_core_module_ctx ctx = { #define reports_cache ctx.reports_cache #define function_usage_mask ctx.function_usage_mask #define transport_protocol_modes ctx.transport_protocol_modes -#define current_mode ctx.current_mode +#define current_transport ctx.current_transport #define mode_valid ctx.mode_valid #define running module_lifecycle_is_running(&ctx.lc) -static bool mode_to_transport(enum mode_switch_mode mode, enum hid_transport *transport) +static bool policy_to_transport(enum hid_transport_policy policy, + enum hid_transport *transport) { - switch (mode) { - case MODE_SWITCH_USB: + switch (policy) { + case HID_TRANSPORT_POLICY_USB: *transport = HID_TRANSPORT_USB; return true; - case MODE_SWITCH_BLE: + case HID_TRANSPORT_POLICY_BLE: *transport = HID_TRANSPORT_BLE; return true; @@ -152,13 +153,32 @@ static enum keyboard_protocol_mode active_protocol_mode_get(void) { enum hid_transport transport; - if (mode_valid && mode_to_transport(current_mode, &transport)) { + if (mode_valid && policy_to_transport(current_transport, &transport)) { return transport_protocol_modes[transport]; } return KEYBOARD_PROTOCOL_MODE_REPORT; } +static bool transport_policy_to_mode(enum hid_transport_policy policy, + enum mode_switch_mode *mode) +{ + if (mode == NULL) { + return false; + } + + switch (policy) { + case HID_TRANSPORT_POLICY_USB: + *mode = MODE_SWITCH_USB; + return true; + case HID_TRANSPORT_POLICY_BLE: + *mode = MODE_SWITCH_BLE; + return true; + default: + return false; + } +} + static const struct keymap_entry *keymap_get(uint16_t key_id) { size_t left = 0; @@ -341,15 +361,17 @@ static void submit_consumer_fifo_frame(uint16_t usage_id) { uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE]; enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); + enum mode_switch_mode mode; if (!running || !mode_valid || + !transport_policy_to_mode(current_transport, &mode) || (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) { return; } sys_put_le16(usage_id, report_buf); (void)submit_keyboard_hid_report_event( - current_mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, + mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, HID_QUEUE_POLICY_FIFO, report_buf, KEYBOARD_CONSUMER_REPORT_SIZE); } @@ -386,8 +408,9 @@ static void emit_keys_report(bool force) uint8_t *cache_buf; bool *cache_valid; enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); + enum mode_switch_mode mode; - if (!mode_valid) { + if (!mode_valid || !transport_policy_to_mode(current_transport, &mode)) { return; } @@ -411,7 +434,7 @@ static void emit_keys_report(bool force) *cache_valid = true; (void)submit_keyboard_hid_report_event( - current_mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode, + mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode, HID_QUEUE_POLICY_LATEST, report_buf, report_size); } @@ -419,8 +442,10 @@ static void emit_consumer_report(bool force) { uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE]; enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); + enum mode_switch_mode mode; - if (!mode_valid || (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) { + if (!mode_valid || !transport_policy_to_mode(current_transport, &mode) || + (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) { return; } @@ -435,7 +460,7 @@ static void emit_consumer_report(bool force) reports_cache.consumer_valid = true; (void)submit_keyboard_hid_report_event( - current_mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, + mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, HID_QUEUE_POLICY_LATEST, report_buf, KEYBOARD_CONSUMER_REPORT_SIZE); } @@ -454,15 +479,27 @@ static void emit_function_state_event(void) (void)submit_function_bitmap_state_event(keyboard_state.pressed_usage_bitmap); } -static void emit_release_reports(enum mode_switch_mode mode) +static void emit_release_reports(enum hid_transport_policy transport_policy) { uint8_t keys_report[KEYBOARD_NKRO_REPORT_SIZE] = { 0 }; uint8_t consumer_report[KEYBOARD_CONSUMER_REPORT_SIZE] = { 0 }; enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); + enum mode_switch_mode mode; size_t keys_report_size = (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT) ? KEYBOARD_BOOT_REPORT_SIZE : KEYBOARD_NKRO_REPORT_SIZE; + switch (transport_policy) { + case HID_TRANSPORT_POLICY_USB: + mode = MODE_SWITCH_USB; + break; + case HID_TRANSPORT_POLICY_BLE: + mode = MODE_SWITCH_BLE; + break; + default: + return; + } + (void)submit_keyboard_hid_report_event( mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode, HID_QUEUE_POLICY_LATEST, keys_report, keys_report_size); @@ -505,7 +542,7 @@ static int do_stop(void) } if (mode_valid) { - emit_release_reports(current_mode); + emit_release_reports(current_transport); } emit_function_state_event(); @@ -568,26 +605,30 @@ static bool handle_button_event(const struct button_event *event) return false; } -static bool handle_mode_switch_event(const struct mode_switch_event *event) +static bool handle_transport_policy_event( + const struct transport_policy_event *event) { - bool mode_changed; + bool transport_changed; if (!running) { - current_mode = event->mode; + current_transport = event->hid_transport; return false; } - mode_changed = mode_valid && (current_mode != event->mode); - if (mode_changed) { - emit_release_reports(current_mode); + transport_changed = mode_valid && (current_transport != event->hid_transport); + if (transport_changed) { + emit_release_reports(current_transport); emit_function_state_event(); keyboard_state_clear(); reports_cache_invalidate(); } - current_mode = event->mode; - mode_valid = true; - emit_all_reports(true); + current_transport = event->hid_transport; + mode_valid = (current_transport != HID_TRANSPORT_POLICY_NONE); + + if (mode_valid) { + emit_all_reports(true); + } return false; } @@ -643,7 +684,7 @@ static bool app_event_handler(const struct app_event_header *aeh) transport_protocol_modes[event->transport] = event->protocol_mode; if (running && mode_valid && - mode_to_transport(current_mode, &active_transport) && + policy_to_transport(current_transport, &active_transport) && (active_transport == event->transport)) { reports_cache_invalidate(); emit_keys_report(true); @@ -657,8 +698,9 @@ static bool app_event_handler(const struct app_event_header *aeh) return false; } - if (is_mode_switch_event(aeh)) { - return handle_mode_switch_event(cast_mode_switch_event(aeh)); + if (is_transport_policy_event(aeh)) { + return handle_transport_policy_event( + cast_transport_policy_event(aeh)); } if (is_module_state_event(aeh)) { @@ -696,7 +738,7 @@ APP_EVENT_SUBSCRIBE(MODULE, button_event); APP_EVENT_SUBSCRIBE(MODULE, encoder_event); APP_EVENT_SUBSCRIBE(MODULE, function_bitmap_update_event); APP_EVENT_SUBSCRIBE(MODULE, set_protocol_event); -APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event); +APP_EVENT_SUBSCRIBE(MODULE, transport_policy_event); APP_EVENT_SUBSCRIBE(MODULE, module_state_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); APP_EVENT_SUBSCRIBE(MODULE, wake_up_event); diff --git a/src/mode_policy_module.c b/src/mode_policy_module.c index 4fa2f9d..6481108 100644 --- a/src/mode_policy_module.c +++ b/src/mode_policy_module.c @@ -10,12 +10,19 @@ #include "module_lifecycle.h" #include "mode_switch_event.h" +#include "transport_policy_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); +struct transport_policy_state { + enum hid_transport_policy hid_transport; + enum ble_profile_policy ble_profile; +}; + struct mode_policy_module_ctx { struct module_lifecycle_ctx lc; enum mode_switch_mode active_mode; + struct transport_policy_state policy; }; static int do_init(void); @@ -40,8 +47,51 @@ static struct mode_policy_module_ctx ctx = { .ops = &lifecycle_ops, }, .active_mode = MODE_SWITCH_USB, + .policy = { + .hid_transport = HID_TRANSPORT_POLICY_USB, + .ble_profile = BLE_PROFILE_POLICY_NONE, + }, }; +static void build_policy_from_mode(enum mode_switch_mode mode, + struct transport_policy_state *policy) +{ + switch (mode) { + case MODE_SWITCH_USB: + policy->hid_transport = HID_TRANSPORT_POLICY_USB; + policy->ble_profile = BLE_PROFILE_POLICY_NONE; + break; + + case MODE_SWITCH_BLE: + policy->hid_transport = HID_TRANSPORT_POLICY_BLE; + policy->ble_profile = BLE_PROFILE_POLICY_GENERAL; + break; + + case MODE_SWITCH_24G: + policy->hid_transport = HID_TRANSPORT_POLICY_BLE; + policy->ble_profile = BLE_PROFILE_POLICY_DONGLE; + break; + + default: + policy->hid_transport = HID_TRANSPORT_POLICY_NONE; + policy->ble_profile = BLE_PROFILE_POLICY_NONE; + break; + } +} + +static bool policy_equal(const struct transport_policy_state *a, + const struct transport_policy_state *b) +{ + return (a->hid_transport == b->hid_transport) && + (a->ble_profile == b->ble_profile); +} + +static void broadcast_policy(void) +{ + submit_transport_policy_event(ctx.active_mode, ctx.policy.hid_transport, + ctx.policy.ble_profile); +} + static void mode_policy_set_ble(bool enable) { if (enable) { @@ -76,7 +126,7 @@ static void mode_policy_set_usb(bool enable) } } -static void apply_active_mode(void) +static void apply_stack_policy(void) { switch (ctx.active_mode) { case MODE_SWITCH_BLE: @@ -90,7 +140,7 @@ static void apply_active_mode(void) break; case MODE_SWITCH_24G: - mode_policy_set_ble(false); + mode_policy_set_ble(true); mode_policy_set_usb(false); break; @@ -111,7 +161,7 @@ static void apply_ble_mode_policy(void) break; case MODE_SWITCH_24G: - mode_policy_set_ble(false); + mode_policy_set_ble(true); break; default: @@ -139,15 +189,36 @@ static void apply_usb_mode_policy(void) } } +static void update_mode_policy(enum mode_switch_mode mode) +{ + struct transport_policy_state next_policy; + bool mode_changed = (ctx.active_mode != mode); + bool policy_changed; + + build_policy_from_mode(mode, &next_policy); + policy_changed = !policy_equal(&ctx.policy, &next_policy); + + ctx.active_mode = mode; + ctx.policy = next_policy; + + if (policy_changed || mode_changed) { + broadcast_policy(); + } + + apply_stack_policy(); +} + static int do_init(void) { ctx.active_mode = MODE_SWITCH_USB; + build_policy_from_mode(ctx.active_mode, &ctx.policy); return 0; } static int do_start(void) { - apply_active_mode(); + broadcast_policy(); + apply_stack_policy(); return 0; } @@ -162,8 +233,7 @@ static bool app_event_handler(const struct app_event_header *aeh) const struct mode_switch_event *event = cast_mode_switch_event(aeh); if (module_lifecycle_is_running(&ctx.lc)) { - ctx.active_mode = event->mode; - apply_active_mode(); + update_mode_policy(event->mode); } return false;