diff --git a/CMakeLists.txt b/CMakeLists.txt index 910ac6c..83ef765 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project(blinky) list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb) include(nanopb) +zephyr_linker_sources(SECTIONS src/usb_function_hook.ld) zephyr_include_directories( inc @@ -21,7 +22,6 @@ zephyr_nanopb_sources(app target_sources(app PRIVATE src/main.c src/battery_module.c - src/ble_adv_ctrl_module.c src/ble_adv_uuid16.c src/ble_bas_module.c src/ble_hid_module.c @@ -33,6 +33,7 @@ target_sources(app PRIVATE src/led_effect/led_effect_registry.c src/led_effect/effects/led_effect_key_fade.c src/led_strip_module.c + src/mode_policy_module.c src/time_sync_module.c src/ui/ui_main.c src/protocol_module.c diff --git a/inc/events/usb_state_event.h b/inc/events/usb_state_event.h index 76fa759..f41f845 100644 --- a/inc/events/usb_state_event.h +++ b/inc/events/usb_state_event.h @@ -11,70 +11,29 @@ extern "C" { #endif -enum usb_state_event_op { - USB_STATE_EVENT_OP_SET_BITS, - USB_STATE_EVENT_OP_CLEAR_BITS, - USB_STATE_EVENT_OP_SNAPSHOT, -}; - -enum usb_state_flag { - USB_STATEF_PREPARE = BIT(0), - USB_STATEF_HID_READY = BIT(1), - USB_STATEF_CDC_READY = BIT(2), - USB_STATEF_STACK_READY = BIT(3), - USB_STATEF_POWERED = BIT(4), - USB_STATEF_ACTIVE = BIT(5), - USB_STATEF_SUSPENDED = BIT(6), - USB_STATEF_STACK_RUNNING = BIT(31), +enum usb_state { + USB_STATE_DISABLED = 0, + USB_STATE_DISCONNECTED, + USB_STATE_POWERED, + USB_STATE_ACTIVE, + USB_STATE_SUSPENDED, }; struct usb_state_event { struct app_event_header header; - const void *src_module_id; - const void *sink_module_id; - uint8_t op; - uint32_t flags; + enum usb_state state; }; APP_EVENT_TYPE_DECLARE(usb_state_event); -static inline void submit_usb_state_event(const void *src_module_id, - const void *sink_module_id, - uint8_t op, - uint32_t flags) +static inline void submit_usb_state(enum usb_state state) { struct usb_state_event *event = new_usb_state_event(); - event->src_module_id = src_module_id; - event->sink_module_id = sink_module_id; - event->op = op; - event->flags = flags; + event->state = state; APP_EVENT_SUBMIT(event); } -static inline void submit_usb_state_set(const void *src_module_id, - const void *sink_module_id, - uint32_t flags) -{ - submit_usb_state_event(src_module_id, sink_module_id, - USB_STATE_EVENT_OP_SET_BITS, flags); -} - -static inline void submit_usb_state_clear(const void *src_module_id, - const void *sink_module_id, - uint32_t flags) -{ - submit_usb_state_event(src_module_id, sink_module_id, - USB_STATE_EVENT_OP_CLEAR_BITS, flags); -} - -static inline void submit_usb_state_snapshot(const void *src_module_id, - uint32_t flags) -{ - submit_usb_state_event(src_module_id, NULL, - USB_STATE_EVENT_OP_SNAPSHOT, flags); -} - #ifdef __cplusplus } #endif diff --git a/inc/usb_function_hook.h b/inc/usb_function_hook.h new file mode 100644 index 0000000..24ff3df --- /dev/null +++ b/inc/usb_function_hook.h @@ -0,0 +1,25 @@ +#ifndef BLINKY_USB_FUNCTION_HOOK_H_ +#define BLINKY_USB_FUNCTION_HOOK_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct usb_function_hook { + const char *name; + int (*pre_stack_init)(void); +}; + +#define USB_FUNCTION_HOOK_DEFINE(_name, _pre_stack_init) \ + const STRUCT_SECTION_ITERABLE(usb_function_hook, _name) = { \ + .name = STRINGIFY(_name), \ + .pre_stack_init = (_pre_stack_init), \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* BLINKY_USB_FUNCTION_HOOK_H_ */ diff --git a/src/events/usb_state_event.c b/src/events/usb_state_event.c index 46aae02..7cb8bd1 100644 --- a/src/events/usb_state_event.c +++ b/src/events/usb_state_event.c @@ -2,35 +2,29 @@ #include "usb_state_event.h" -static const char *usb_state_event_op_name(uint8_t op) +static const char *usb_state_name(enum usb_state state) { - switch ((enum usb_state_event_op)op) { - case USB_STATE_EVENT_OP_SET_BITS: - return "set_bits"; - case USB_STATE_EVENT_OP_CLEAR_BITS: - return "clear_bits"; - case USB_STATE_EVENT_OP_SNAPSHOT: - return "snapshot"; + switch (state) { + case USB_STATE_DISABLED: + return "disabled"; + case USB_STATE_DISCONNECTED: + return "disconnected"; + case USB_STATE_POWERED: + return "powered"; + case USB_STATE_ACTIVE: + return "active"; + case USB_STATE_SUSPENDED: + return "suspended"; default: return "?"; } } -static const char *module_name_or_any(const void *module_id) -{ - return (module_id != NULL) ? module_name_get(module_id) : "*"; -} - static void log_usb_state_event(const struct app_event_header *aeh) { const struct usb_state_event *event = cast_usb_state_event(aeh); - APP_EVENT_MANAGER_LOG(aeh, - "src:%s sink:%s op:%s flags:0x%08x", - module_name_or_any(event->src_module_id), - module_name_or_any(event->sink_module_id), - usb_state_event_op_name(event->op), - event->flags); + APP_EVENT_MANAGER_LOG(aeh, "state:%s", usb_state_name(event->state)); } static void profile_usb_state_event(struct log_event_buf *buf, @@ -38,13 +32,12 @@ static void profile_usb_state_event(struct log_event_buf *buf, { const struct usb_state_event *event = cast_usb_state_event(aeh); - nrf_profiler_log_encode_uint8(buf, event->op); - nrf_profiler_log_encode_uint32(buf, event->flags); + nrf_profiler_log_encode_uint8(buf, event->state); } APP_EVENT_INFO_DEFINE(usb_state_event, - ENCODE(NRF_PROFILER_ARG_U8, NRF_PROFILER_ARG_U32), - ENCODE("op", "flags"), + ENCODE(NRF_PROFILER_ARG_U8), + ENCODE("state"), profile_usb_state_event); APP_EVENT_TYPE_DEFINE(usb_state_event, diff --git a/src/ble_adv_ctrl_module.c b/src/mode_policy_module.c similarity index 54% rename from src/ble_adv_ctrl_module.c rename to src/mode_policy_module.c index c7c7367..7cd6abb 100644 --- a/src/ble_adv_ctrl_module.c +++ b/src/mode_policy_module.c @@ -2,9 +2,10 @@ #include -#define MODULE ble_adv_ctrl_module +#define MODULE mode_policy_module #include #include +#include #include @@ -15,6 +16,7 @@ LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); static bool initialized; static bool running; static bool ble_adv_suspended = true; +static bool usb_enabled; static void broadcast_ble_adv_req(bool suspend) { @@ -33,10 +35,40 @@ static void broadcast_ble_adv_req(bool suspend) } } +static void apply_mode_policy(enum mode_switch_mode mode) +{ + bool should_suspend_ble_adv = (mode != MODE_SWITCH_BLE); + bool should_enable_usb = (mode == MODE_SWITCH_USB); + + if (should_suspend_ble_adv != ble_adv_suspended) { + ble_adv_suspended = should_suspend_ble_adv; + broadcast_ble_adv_req(should_suspend_ble_adv); + } + + if (should_enable_usb != usb_enabled) { + usb_enabled = should_enable_usb; + if (usb_enabled) { + struct module_resume_req_event *event = + new_module_resume_req_event(); + + event->sink_module_id = MODULE_ID(usb_device_module); + event->src_module_id = MODULE_ID(MODULE); + APP_EVENT_SUBMIT(event); + } else { + struct module_suspend_req_event *event = + new_module_suspend_req_event(); + + event->sink_module_id = MODULE_ID(usb_device_module); + event->src_module_id = MODULE_ID(MODULE); + APP_EVENT_SUBMIT(event); + } + } +} + static int module_init(void) { ble_adv_suspended = true; - + usb_enabled = false; return 0; } @@ -47,7 +79,6 @@ static int module_start(void) } running = true; - return 0; } @@ -56,28 +87,16 @@ static void module_pause(void) running = false; } -static bool handle_mode_switch_event(const struct mode_switch_event *event) -{ - bool should_suspend; - - if (!running) { - return false; - } - - should_suspend = (event->mode != MODE_SWITCH_BLE); - - if (should_suspend != ble_adv_suspended) { - ble_adv_suspended = should_suspend; - broadcast_ble_adv_req(should_suspend); - } - - return false; -} - static bool app_event_handler(const struct app_event_header *aeh) { if (is_mode_switch_event(aeh)) { - return handle_mode_switch_event(cast_mode_switch_event(aeh)); + const struct mode_switch_event *event = cast_mode_switch_event(aeh); + + if (running) { + apply_mode_policy(event->mode); + } + + return false; } if (is_module_state_event(aeh)) { @@ -107,9 +126,34 @@ static bool app_event_handler(const struct app_event_header *aeh) 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; + } + return false; } APP_EVENT_LISTENER(MODULE, app_event_handler); 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); diff --git a/src/usb_cdc_module.c b/src/usb_cdc_module.c index d310578..a61424a 100644 --- a/src/usb_cdc_module.c +++ b/src/usb_cdc_module.c @@ -49,13 +49,6 @@ static bool rx_enabled; static uint8_t proto_rx_buf[USB_CDC_PROTO_RX_BUF_SIZE]; static size_t proto_rx_len; -static bool is_usb_owner_snapshot(const struct usb_state_event *event) -{ - return (event->op == USB_STATE_EVENT_OP_SNAPSHOT) && - (event->src_module_id == MODULE_ID(usb_device_module)) && - (event->sink_module_id == NULL); -} - static void reset_ring_buffers(void) { unsigned int key = irq_lock(); @@ -315,19 +308,7 @@ static void module_pause(void) static bool handle_usb_state_event(const struct usb_state_event *event) { - if (!is_usb_owner_snapshot(event)) { - return false; - } - - if (running && !usb_function_prepared && - ((event->flags & USB_STATEF_PREPARE) != 0U)) { - usb_function_prepared = true; - submit_usb_state_set(MODULE_ID(MODULE), - MODULE_ID(usb_device_module), - USB_STATEF_CDC_READY); - } - - bool new_usb_active = (event->flags & USB_STATEF_ACTIVE) != 0U; + bool new_usb_active = (event->state == USB_STATE_ACTIVE); if (new_usb_active == usb_active) { return false; diff --git a/src/usb_device_module.c b/src/usb_device_module.c index 4b6b778..adbe9a8 100644 --- a/src/usb_device_module.c +++ b/src/usb_device_module.c @@ -6,6 +6,7 @@ #define MODULE usb_device_module #include +#include #include #include @@ -13,6 +14,7 @@ #include +#include "usb_function_hook.h" #include "usb_state_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); @@ -21,7 +23,6 @@ LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); #define USB_DEVICE_PID 0x52F0 #define USB_DEVICE_MANUFACTURER "Atguigu" #define USB_DEVICE_PRODUCT "WH Mini Keyboard" -#define USB_REQUIRED_READY_MASK (USB_STATEF_HID_READY | USB_STATEF_CDC_READY) USBD_DEVICE_DEFINE(blinky_usbd, DEVICE_DT_GET(DT_NODELABEL(usbd)), USB_DEVICE_VID, USB_DEVICE_PID); @@ -39,69 +40,65 @@ static const char *const class_blocklist[] = { static bool initialized; static bool running; -static bool usbd_initialized; -static bool usb_enabled; -static uint32_t usb_state_flags; -enum usb_runtime_state { - USB_RUNTIME_STATE_DISCONNECTED, - USB_RUNTIME_STATE_POWERED, - USB_RUNTIME_STATE_ACTIVE, - USB_RUNTIME_STATE_SUSPENDED, +enum usb_stack_state { + USB_STACK_UNINITIALIZED = 0, + USB_STACK_DISABLED, + USB_STACK_READY, + USB_STACK_ENABLED, }; -static enum usb_runtime_state device_state = USB_RUNTIME_STATE_DISCONNECTED; +enum usb_bus_state { + USB_BUS_DISCONNECTED = 0, + USB_BUS_POWERED, + USB_BUS_ACTIVE, + USB_BUS_SUSPENDED, +}; -static void broadcast_usb_state(void) +struct usb_owner_ctx { + enum usb_stack_state stack; + enum usb_bus_state bus; +}; + +static struct usb_owner_ctx usb_ctx = { + .stack = USB_STACK_UNINITIALIZED, + .bus = USB_BUS_DISCONNECTED, +}; + +static inline enum usb_state usb_public_state_get(void) { - submit_usb_state_snapshot(MODULE_ID(MODULE), usb_state_flags); + if ((usb_ctx.stack == USB_STACK_UNINITIALIZED) || + (usb_ctx.stack == USB_STACK_DISABLED)) { + return USB_STATE_DISABLED; + } + + switch (usb_ctx.bus) { + case USB_BUS_DISCONNECTED: + return USB_STATE_DISCONNECTED; + case USB_BUS_POWERED: + return USB_STATE_POWERED; + case USB_BUS_ACTIVE: + return USB_STATE_ACTIVE; + case USB_BUS_SUSPENDED: + return USB_STATE_SUSPENDED; + default: + return USB_STATE_DISABLED; + } } -static void set_usb_state_flags(uint32_t mask) +static inline bool usb_stack_was_initialized(void) { - usb_state_flags |= mask; + return (usb_ctx.stack != USB_STACK_UNINITIALIZED); } -static void clear_usb_state_flags(uint32_t mask) +static inline void usb_bus_set(enum usb_bus_state state) { - usb_state_flags &= ~mask; -} - -static void update_usb_runtime_state(enum usb_runtime_state state) -{ - if (device_state == state) { + if (usb_ctx.bus == state) { return; } - device_state = state; - - switch (state) { - case USB_RUNTIME_STATE_DISCONNECTED: - clear_usb_state_flags(USB_STATEF_POWERED | - USB_STATEF_ACTIVE | - USB_STATEF_SUSPENDED); - break; - - case USB_RUNTIME_STATE_POWERED: - set_usb_state_flags(USB_STATEF_POWERED); - clear_usb_state_flags(USB_STATEF_ACTIVE | USB_STATEF_SUSPENDED); - break; - - case USB_RUNTIME_STATE_ACTIVE: - set_usb_state_flags(USB_STATEF_POWERED | USB_STATEF_ACTIVE); - clear_usb_state_flags(USB_STATEF_SUSPENDED); - break; - - case USB_RUNTIME_STATE_SUSPENDED: - set_usb_state_flags(USB_STATEF_POWERED | USB_STATEF_SUSPENDED); - clear_usb_state_flags(USB_STATEF_ACTIVE); - break; - - default: - break; - } - - broadcast_usb_state(); + usb_ctx.bus = state; + submit_usb_state(usb_public_state_get()); } static void update_power_manager_restriction(bool vbus_present) @@ -153,21 +150,23 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx, switch (msg->type) { case USBD_MSG_VBUS_READY: update_power_manager_restriction(true); - if (!usb_enabled) { + + if (usb_ctx.stack == USB_STACK_READY) { int err = usbd_enable(&blinky_usbd); if (err) { LOG_ERR("usbd_enable failed (%d)", err); } else { - usb_enabled = true; - update_usb_runtime_state(USB_RUNTIME_STATE_POWERED); + usb_ctx.stack = USB_STACK_ENABLED; + usb_bus_set(USB_BUS_POWERED); } } break; case USBD_MSG_VBUS_REMOVED: update_power_manager_restriction(false); - if (usb_enabled) { + + if (usb_ctx.stack == USB_STACK_ENABLED) { int err = usbd_disable(&blinky_usbd); if (err) { @@ -175,27 +174,30 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx, } } - usb_enabled = false; - update_usb_runtime_state(USB_RUNTIME_STATE_DISCONNECTED); + if (usb_ctx.stack != USB_STACK_DISABLED) { + usb_ctx.stack = USB_STACK_READY; + } + + usb_bus_set(USB_BUS_DISCONNECTED); break; case USBD_MSG_CONFIGURATION: if (msg->status) { - update_usb_runtime_state(USB_RUNTIME_STATE_ACTIVE); - } else if (usb_enabled) { - update_usb_runtime_state(USB_RUNTIME_STATE_POWERED); + usb_bus_set(USB_BUS_ACTIVE); + } else if (usb_ctx.stack == USB_STACK_ENABLED) { + usb_bus_set(USB_BUS_POWERED); } break; case USBD_MSG_SUSPEND: - if (usb_enabled) { - update_usb_runtime_state(USB_RUNTIME_STATE_SUSPENDED); + if (usb_ctx.stack == USB_STACK_ENABLED) { + usb_bus_set(USB_BUS_SUSPENDED); } break; case USBD_MSG_RESUME: - if (usb_enabled) { - update_usb_runtime_state(USB_RUNTIME_STATE_ACTIVE); + if (usb_ctx.stack == USB_STACK_ENABLED) { + usb_bus_set(USB_BUS_ACTIVE); } break; @@ -204,10 +206,29 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx, } } -static int usb_stack_init(void) +static int usb_stack_init_once(void) { int err; + if (usb_stack_was_initialized()) { + if (usb_ctx.stack == USB_STACK_DISABLED) { + usb_ctx.stack = USB_STACK_READY; + } + return 0; + } + + STRUCT_SECTION_FOREACH(usb_function_hook, hook) { + if (hook->pre_stack_init == NULL) { + continue; + } + + err = hook->pre_stack_init(); + if (err) { + LOG_ERR("USB function hook %s failed (%d)", hook->name, err); + return err; + } + } + err = usbd_msg_register_cb(&blinky_usbd, usbd_msg_cb); if (err) { LOG_ERR("usbd_msg_register_cb failed (%d)", err); @@ -226,8 +247,7 @@ static int usb_stack_init(void) return err; } - usbd_initialized = true; - set_usb_state_flags(USB_STATEF_STACK_READY); + usb_ctx.stack = USB_STACK_READY; if (!usbd_can_detect_vbus(&blinky_usbd)) { err = usbd_enable(&blinky_usbd); @@ -236,34 +256,67 @@ static int usb_stack_init(void) return err; } - usb_enabled = true; - update_usb_runtime_state(USB_RUNTIME_STATE_POWERED); + usb_ctx.stack = USB_STACK_ENABLED; + usb_bus_set(USB_BUS_POWERED); } return 0; } -static int try_start_usb_stack(void) +static int usb_stack_enable_if_needed(void) { - if (usbd_initialized) { + int err; + + err = usb_stack_init_once(); + if (err) { + return err; + } + + if ((usb_ctx.stack == USB_STACK_READY) && + (!usbd_can_detect_vbus(&blinky_usbd) || + (usb_ctx.bus != USB_BUS_DISCONNECTED))) { + err = usbd_enable(&blinky_usbd); + if (err) { + LOG_ERR("usbd_enable failed (%d)", err); + return err; + } + + usb_ctx.stack = USB_STACK_ENABLED; + + if (usb_ctx.bus == USB_BUS_DISCONNECTED) { + usb_bus_set(USB_BUS_POWERED); + } else { + submit_usb_state(usb_public_state_get()); + } + return 0; } - if ((usb_state_flags & USB_REQUIRED_READY_MASK) != USB_REQUIRED_READY_MASK) { - set_usb_state_flags(USB_STATEF_PREPARE); - return 0; + submit_usb_state(usb_public_state_get()); + return 0; +} + +static int usb_stack_disable_if_needed(void) +{ + if (usb_ctx.stack == USB_STACK_ENABLED) { + int err = usbd_disable(&blinky_usbd); + + if (err) { + LOG_ERR("usbd_disable failed (%d)", err); + return err; + } } - clear_usb_state_flags(USB_STATEF_PREPARE); - return usb_stack_init(); + usb_ctx.stack = USB_STACK_DISABLED; + update_power_manager_restriction(false); + submit_usb_state(usb_public_state_get()); + return 0; } static int module_init(void) { - device_state = USB_RUNTIME_STATE_DISCONNECTED; - usb_enabled = false; - usbd_initialized = false; - usb_state_flags = 0U; + usb_ctx.stack = USB_STACK_UNINITIALIZED; + usb_ctx.bus = USB_BUS_DISCONNECTED; update_power_manager_restriction(false); return 0; @@ -276,12 +329,8 @@ static int module_start(void) } running = true; - set_usb_state_flags(USB_STATEF_STACK_RUNNING); - - int err = try_start_usb_stack(); - - broadcast_usb_state(); - return err; + submit_usb_state(usb_public_state_get()); + return 0; } static void module_pause(void) @@ -291,8 +340,7 @@ static void module_pause(void) } running = false; - clear_usb_state_flags(USB_STATEF_STACK_RUNNING); - broadcast_usb_state(); + submit_usb_state(usb_public_state_get()); } static bool handle_module_state_event(const struct module_state_event *event) @@ -317,7 +365,7 @@ static bool handle_module_state_event(const struct module_state_event *event) if (err) { module_set_state(MODULE_STATE_ERROR); - } else if (usbd_initialized) { + } else if (usb_stack_was_initialized()) { module_set_state(MODULE_STATE_READY); } } @@ -325,32 +373,42 @@ static bool handle_module_state_event(const struct module_state_event *event) return false; } -static bool handle_usb_state_event(const struct usb_state_event *event) +static bool handle_module_suspend_req_event( + const struct module_suspend_req_event *event) { - if ((event->op == USB_STATE_EVENT_OP_SNAPSHOT) || - (event->sink_module_id != MODULE_ID(MODULE))) { + if ((event->sink_module_id != MODULE_ID(MODULE)) || !running) { return false; } - if (event->op == USB_STATE_EVENT_OP_SET_BITS) { - usb_state_flags |= event->flags; - } else if (event->op == USB_STATE_EVENT_OP_CLEAR_BITS) { - usb_state_flags &= ~event->flags; - } else { - return false; - } + int err = usb_stack_disable_if_needed(); - int err = running ? try_start_usb_stack() : 0; if (err) { module_set_state(MODULE_STATE_ERROR); return false; } - broadcast_usb_state(); + module_set_state(MODULE_STATE_READY); + return false; +} - if (usbd_initialized) { +static bool handle_module_resume_req_event( + const struct module_resume_req_event *event) +{ + if ((event->sink_module_id != MODULE_ID(MODULE)) || !running) { + return false; + } + + int err = usb_stack_enable_if_needed(); + + if (err) { + module_set_state(MODULE_STATE_ERROR); + return false; + } + + if (usb_stack_was_initialized()) { module_set_state(MODULE_STATE_READY); } + return false; } @@ -360,8 +418,14 @@ static bool app_event_handler(const struct app_event_header *aeh) return handle_module_state_event(cast_module_state_event(aeh)); } - if (is_usb_state_event(aeh)) { - return handle_usb_state_event(cast_usb_state_event(aeh)); + if (is_module_suspend_req_event(aeh)) { + return handle_module_suspend_req_event( + cast_module_suspend_req_event(aeh)); + } + + if (is_module_resume_req_event(aeh)) { + return handle_module_resume_req_event( + cast_module_resume_req_event(aeh)); } if (is_power_down_event(aeh)) { @@ -379,7 +443,7 @@ static bool app_event_handler(const struct app_event_header *aeh) if (err) { module_set_state(MODULE_STATE_ERROR); - } else if (usbd_initialized) { + } else if (usb_stack_was_initialized()) { module_set_state(MODULE_STATE_READY); } } @@ -392,6 +456,7 @@ 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, usb_state_event); +APP_EVENT_SUBSCRIBE(MODULE, module_suspend_req_event); +APP_EVENT_SUBSCRIBE(MODULE, module_resume_req_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); APP_EVENT_SUBSCRIBE(MODULE, wake_up_event); diff --git a/src/usb_function_hook.ld b/src/usb_function_hook.ld new file mode 100644 index 0000000..99a5c84 --- /dev/null +++ b/src/usb_function_hook.ld @@ -0,0 +1 @@ +ITERABLE_SECTION_ROM(usb_function_hook, Z_LINK_ITERABLE_SUBALIGN) diff --git a/src/usb_hid_module.c b/src/usb_hid_module.c index 1a3b6b4..61b4da8 100644 --- a/src/usb_hid_module.c +++ b/src/usb_hid_module.c @@ -21,6 +21,7 @@ #include "hid_tx_report_event.h" #include "keyboard_core.h" #include "set_protocol_event.h" +#include "usb_function_hook.h" #include "usb_state_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); @@ -149,13 +150,6 @@ static void submit_usb_transport_state_event(void) keyboard_protocol_mode); } -static bool is_usb_owner_snapshot(const struct usb_state_event *event) -{ - return (event->op == USB_STATE_EVENT_OP_SNAPSHOT) && - (event->src_module_id == MODULE_ID(usb_device_module)) && - (event->sink_module_id == NULL); -} - static void keyboard_iface_ready(const struct device *dev, const bool ready) { struct usb_hid_interface_state *iface = iface_from_dev(dev); @@ -396,11 +390,18 @@ static int usb_hid_register_devices(void) return 0; } +static int usb_hid_pre_stack_init(void) +{ + return usb_hid_register_devices(); +} + +USB_FUNCTION_HOOK_DEFINE(usb_hid_hook, usb_hid_pre_stack_init); + static int module_init(void) { reset_usb_runtime_state(); keyboard_protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT; - usb_function_prepared = false; + usb_function_prepared = true; return 0; } @@ -424,27 +425,7 @@ static void module_pause(void) static bool handle_usb_state_event(const struct usb_state_event *event) { - if (!is_usb_owner_snapshot(event)) { - return false; - } - - if (running && !usb_function_prepared && - ((event->flags & USB_STATEF_PREPARE) != 0U)) { - int err = usb_hid_register_devices(); - - if (err) { - LOG_ERR("hid_device_register failed (%d)", err); - module_set_state(MODULE_STATE_ERROR); - return false; - } - - usb_function_prepared = true; - submit_usb_state_set(MODULE_ID(MODULE), - MODULE_ID(usb_device_module), - USB_STATEF_HID_READY); - } - - bool new_usb_active = (event->flags & USB_STATEF_ACTIVE) != 0U; + bool new_usb_active = (event->state == USB_STATE_ACTIVE); if (new_usb_active == usb_active) { return false;