#include #include #define MODULE mode_policy_module #include #include #include #include #include "module_lifecycle.h" #include "mode_switch_event.h" LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); struct mode_policy_module_ctx { struct module_lifecycle_ctx lc; bool ble_adv_suspended; bool usb_enabled; }; static int do_init(void); static int do_start(void); static int do_stop(void); static const struct module_lifecycle_cfg lifecycle_cfg = { .mode = ML_MODE_POWER, .stopped_state = MODULE_STATE_STANDBY, }; static const struct module_lifecycle_ops lifecycle_ops = { .do_init = do_init, .do_start = do_start, .do_stop = do_stop, }; static struct mode_policy_module_ctx ctx = { .lc = { .state = LC_UNINIT, .cfg = &lifecycle_cfg, .ops = &lifecycle_ops, }, .ble_adv_suspended = true, }; static void broadcast_ble_adv_req(bool suspend) { if (suspend) { struct module_suspend_req_event *event = new_module_suspend_req_event(); event->sink_module_id = MODULE_ID(ble_adv); event->src_module_id = MODULE_ID(MODULE); APP_EVENT_SUBMIT(event); } else { struct module_resume_req_event *event = new_module_resume_req_event(); event->sink_module_id = MODULE_ID(ble_adv); event->src_module_id = MODULE_ID(MODULE); APP_EVENT_SUBMIT(event); } } 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 != ctx.ble_adv_suspended) { ctx.ble_adv_suspended = should_suspend_ble_adv; broadcast_ble_adv_req(should_suspend_ble_adv); } if (should_enable_usb != ctx.usb_enabled) { ctx.usb_enabled = should_enable_usb; if (ctx.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 do_init(void) { ctx.ble_adv_suspended = true; ctx.usb_enabled = false; return 0; } static int do_start(void) { if (module_lifecycle_is_running(&ctx.lc)) { return 0; } return 0; } static int do_stop(void) { return 0; } static bool app_event_handler(const struct app_event_header *aeh) { if (is_mode_switch_event(aeh)) { const struct mode_switch_event *event = cast_mode_switch_event(aeh); if (module_lifecycle_is_running(&ctx.lc)) { apply_mode_policy(event->mode); } return false; } 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)) { (void)module_set_lifecycle(&ctx.lc, LC_RUNNING); } return false; } if (is_power_down_event(aeh)) { 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(&ctx.lc)) { (void)module_set_lifecycle(&ctx.lc, LC_RUNNING); } 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);