2026-04-11 17:15:11 +08:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
#include <app_event_manager.h>
|
|
|
|
|
|
|
|
|
|
#define MODULE usb_device_module
|
|
|
|
|
#include <caf/events/module_state_event.h>
|
2026-04-15 15:13:44 +08:00
|
|
|
#include <caf/events/module_suspend_event.h>
|
2026-04-11 17:15:11 +08:00
|
|
|
#include <caf/events/power_event.h>
|
|
|
|
|
|
2026-04-17 11:13:11 +08:00
|
|
|
#include <zephyr/drivers/uart.h>
|
2026-04-11 17:15:11 +08:00
|
|
|
#include <zephyr/logging/log.h>
|
|
|
|
|
#include <zephyr/usb/usbd.h>
|
|
|
|
|
|
2026-04-11 17:57:00 +08:00
|
|
|
#include <caf/events/power_manager_event.h>
|
|
|
|
|
|
2026-04-17 19:12:57 +08:00
|
|
|
#include "module_lifecycle.h"
|
2026-04-15 15:13:44 +08:00
|
|
|
#include "usb_function_hook.h"
|
2026-04-17 11:13:11 +08:00
|
|
|
#include "usb_control_event.h"
|
2026-04-15 09:30:40 +08:00
|
|
|
#include "usb_state_event.h"
|
2026-04-11 17:15:11 +08:00
|
|
|
|
|
|
|
|
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
|
|
|
|
|
|
|
|
|
#define USB_DEVICE_VID 0x1915
|
|
|
|
|
#define USB_DEVICE_PID 0x52F0
|
|
|
|
|
#define USB_DEVICE_MANUFACTURER "Atguigu"
|
|
|
|
|
#define USB_DEVICE_PRODUCT "WH Mini Keyboard"
|
|
|
|
|
|
|
|
|
|
USBD_DEVICE_DEFINE(blinky_usbd, DEVICE_DT_GET(DT_NODELABEL(usbd)),
|
|
|
|
|
USB_DEVICE_VID, USB_DEVICE_PID);
|
|
|
|
|
|
|
|
|
|
USBD_DESC_LANG_DEFINE(blinky_lang);
|
|
|
|
|
USBD_DESC_MANUFACTURER_DEFINE(blinky_mfr, USB_DEVICE_MANUFACTURER);
|
|
|
|
|
USBD_DESC_PRODUCT_DEFINE(blinky_product, USB_DEVICE_PRODUCT);
|
|
|
|
|
|
|
|
|
|
USBD_DESC_CONFIG_DEFINE(blinky_fs_cfg_desc, "FS Configuration");
|
|
|
|
|
USBD_CONFIGURATION_DEFINE(blinky_fs_config, 0, 250, &blinky_fs_cfg_desc);
|
|
|
|
|
|
|
|
|
|
static const char *const class_blocklist[] = {
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
enum usb_stack_state {
|
|
|
|
|
USB_STACK_UNINITIALIZED = 0,
|
|
|
|
|
USB_STACK_READY,
|
|
|
|
|
USB_STACK_ENABLED,
|
2026-04-15 09:30:40 +08:00
|
|
|
};
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
enum usb_bus_state {
|
|
|
|
|
USB_BUS_DISCONNECTED = 0,
|
|
|
|
|
USB_BUS_POWERED,
|
|
|
|
|
USB_BUS_ACTIVE,
|
|
|
|
|
USB_BUS_SUSPENDED,
|
|
|
|
|
};
|
2026-04-15 09:30:40 +08:00
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
struct usb_owner_ctx {
|
2026-04-17 19:12:57 +08:00
|
|
|
struct module_lifecycle_ctx lc;
|
2026-04-15 15:13:44 +08:00
|
|
|
enum usb_stack_state stack;
|
|
|
|
|
enum usb_bus_state bus;
|
|
|
|
|
};
|
2026-04-15 09:30:40 +08:00
|
|
|
|
2026-04-17 19:12:57 +08:00
|
|
|
static int do_init(void);
|
|
|
|
|
static int do_start(void);
|
|
|
|
|
static int do_stop(void);
|
|
|
|
|
|
|
|
|
|
/* Project exception: mode policy suspend/resume controls USB availability,
|
|
|
|
|
* while global power events still map to standby lifecycle transitions.
|
|
|
|
|
*/
|
|
|
|
|
static const struct module_lifecycle_cfg lifecycle_cfg = {
|
|
|
|
|
.mode = ML_MODE_SUSPEND,
|
|
|
|
|
.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,
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
static struct usb_owner_ctx usb_ctx = {
|
2026-04-17 19:12:57 +08:00
|
|
|
.lc = {
|
|
|
|
|
.state = LC_UNINIT,
|
|
|
|
|
.cfg = &lifecycle_cfg,
|
|
|
|
|
.ops = &lifecycle_ops,
|
|
|
|
|
},
|
2026-04-15 15:13:44 +08:00
|
|
|
.stack = USB_STACK_UNINITIALIZED,
|
|
|
|
|
.bus = USB_BUS_DISCONNECTED,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline enum usb_state usb_public_state_get(void)
|
2026-04-15 09:30:40 +08:00
|
|
|
{
|
2026-04-18 11:27:48 +08:00
|
|
|
if (!module_lifecycle_is_running(&usb_ctx.lc) ||
|
|
|
|
|
(usb_ctx.stack == USB_STACK_UNINITIALIZED)) {
|
2026-04-15 15:13:44 +08:00
|
|
|
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;
|
|
|
|
|
}
|
2026-04-15 09:30:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
static inline void usb_bus_set(enum usb_bus_state state)
|
2026-04-11 17:15:11 +08:00
|
|
|
{
|
2026-04-15 15:13:44 +08:00
|
|
|
if (usb_ctx.bus == state) {
|
2026-04-11 17:15:11 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
usb_ctx.bus = state;
|
2026-04-18 11:27:48 +08:00
|
|
|
|
|
|
|
|
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
|
|
|
|
}
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-11 17:57:00 +08:00
|
|
|
static void update_power_manager_restriction(bool vbus_present)
|
|
|
|
|
{
|
|
|
|
|
power_manager_restrict(MODULE_IDX(MODULE),
|
|
|
|
|
vbus_present ? POWER_MANAGER_LEVEL_ALIVE :
|
|
|
|
|
POWER_MANAGER_LEVEL_SUSPENDED);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-11 17:15:11 +08:00
|
|
|
static int usb_descriptors_init(void)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
err = usbd_add_descriptor(&blinky_usbd, &blinky_lang);
|
|
|
|
|
if (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usbd_add_descriptor(&blinky_usbd, &blinky_mfr);
|
|
|
|
|
if (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usbd_add_descriptor(&blinky_usbd, &blinky_product);
|
|
|
|
|
if (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usbd_add_configuration(&blinky_usbd, USBD_SPEED_FS, &blinky_fs_config);
|
|
|
|
|
if (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usbd_register_all_classes(&blinky_usbd, USBD_SPEED_FS, 1, class_blocklist);
|
|
|
|
|
if (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usbd_device_set_code_triple(&blinky_usbd, USBD_SPEED_FS, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
|
|
|
|
|
const struct usbd_msg *const msg)
|
|
|
|
|
{
|
|
|
|
|
ARG_UNUSED(usbd_ctx);
|
|
|
|
|
|
2026-04-17 11:13:11 +08:00
|
|
|
if (msg->type == USBD_MSG_CDC_ACM_CONTROL_LINE_STATE) {
|
|
|
|
|
uint32_t dtr = 0U;
|
|
|
|
|
int err = uart_line_ctrl_get(msg->dev, UART_LINE_CTRL_DTR, &dtr);
|
|
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_WRN("Failed to get CDC DTR (%d)", err);
|
|
|
|
|
} else {
|
|
|
|
|
submit_usb_control_cdc_line_state_event(msg->dev, dtr != 0U);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING) {
|
|
|
|
|
uint32_t baudrate = 0U;
|
|
|
|
|
uint8_t data_bits = 0U;
|
|
|
|
|
uint8_t stop_bits = 0U;
|
|
|
|
|
uint8_t parity = 0U;
|
|
|
|
|
uint8_t flow_ctrl = 0U;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
err = uart_line_ctrl_get(msg->dev, UART_LINE_CTRL_BAUD_RATE, &baudrate);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_WRN("Failed to get CDC baudrate (%d)", err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
|
|
|
|
{
|
|
|
|
|
struct uart_config cfg;
|
|
|
|
|
|
|
|
|
|
err = uart_config_get(msg->dev, &cfg);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_WRN("uart_config_get failed (%d)", err);
|
|
|
|
|
} else {
|
|
|
|
|
data_bits = (uint8_t)cfg.data_bits;
|
|
|
|
|
stop_bits = (uint8_t)cfg.stop_bits;
|
|
|
|
|
parity = (uint8_t)cfg.parity;
|
|
|
|
|
flow_ctrl = (uint8_t)cfg.flow_ctrl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
submit_usb_control_cdc_line_coding_event(msg->dev, baudrate,
|
|
|
|
|
data_bits, stop_bits,
|
|
|
|
|
parity, flow_ctrl);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-11 17:15:11 +08:00
|
|
|
switch (msg->type) {
|
|
|
|
|
case USBD_MSG_VBUS_READY:
|
2026-04-11 17:57:00 +08:00
|
|
|
update_power_manager_restriction(true);
|
2026-04-18 11:27:48 +08:00
|
|
|
usb_bus_set(USB_BUS_POWERED);
|
2026-04-15 15:13:44 +08:00
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_lifecycle_is_running(&usb_ctx.lc) &&
|
|
|
|
|
(usb_ctx.stack == USB_STACK_READY)) {
|
|
|
|
|
int err = do_start();
|
2026-04-11 17:15:11 +08:00
|
|
|
|
|
|
|
|
if (err) {
|
2026-04-18 11:27:48 +08:00
|
|
|
LOG_ERR("USB start on VBUS ready failed (%d)", err);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case USBD_MSG_VBUS_REMOVED:
|
2026-04-15 15:13:44 +08:00
|
|
|
if (usb_ctx.stack == USB_STACK_ENABLED) {
|
2026-04-18 11:27:48 +08:00
|
|
|
int err = do_stop();
|
2026-04-11 17:15:11 +08:00
|
|
|
|
|
|
|
|
if (err) {
|
2026-04-18 11:27:48 +08:00
|
|
|
LOG_ERR("USB stop on VBUS removed failed (%d)", err);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
2026-04-18 11:27:48 +08:00
|
|
|
} else {
|
|
|
|
|
update_power_manager_restriction(false);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (usb_ctx.stack != USB_STACK_UNINITIALIZED) {
|
2026-04-15 15:13:44 +08:00
|
|
|
usb_ctx.stack = USB_STACK_READY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_bus_set(USB_BUS_DISCONNECTED);
|
2026-04-11 17:15:11 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case USBD_MSG_CONFIGURATION:
|
|
|
|
|
if (msg->status) {
|
2026-04-15 15:13:44 +08:00
|
|
|
usb_bus_set(USB_BUS_ACTIVE);
|
|
|
|
|
} else if (usb_ctx.stack == USB_STACK_ENABLED) {
|
|
|
|
|
usb_bus_set(USB_BUS_POWERED);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case USBD_MSG_SUSPEND:
|
2026-04-15 15:13:44 +08:00
|
|
|
if (usb_ctx.stack == USB_STACK_ENABLED) {
|
|
|
|
|
usb_bus_set(USB_BUS_SUSPENDED);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case USBD_MSG_RESUME:
|
2026-04-15 15:13:44 +08:00
|
|
|
if (usb_ctx.stack == USB_STACK_ENABLED) {
|
|
|
|
|
usb_bus_set(USB_BUS_ACTIVE);
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
static int do_init(void)
|
2026-04-11 17:15:11 +08:00
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
usb_ctx.stack = USB_STACK_UNINITIALIZED;
|
|
|
|
|
usb_ctx.bus = USB_BUS_DISCONNECTED;
|
|
|
|
|
update_power_manager_restriction(false);
|
2026-04-15 15:13:44 +08:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-11 17:15:11 +08:00
|
|
|
err = usbd_msg_register_cb(&blinky_usbd, usbd_msg_cb);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usbd_msg_register_cb failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usb_descriptors_init();
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usb descriptor init failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = usbd_init(&blinky_usbd);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usbd_init failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
usb_ctx.stack = USB_STACK_READY;
|
2026-04-11 17:15:11 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
static int do_start(void)
|
2026-04-15 09:30:40 +08:00
|
|
|
{
|
2026-04-15 15:13:44 +08:00
|
|
|
int err;
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (usb_ctx.stack == USB_STACK_ENABLED) {
|
|
|
|
|
return 0;
|
2026-04-15 09:30:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (!usbd_can_detect_vbus(&blinky_usbd)) {
|
2026-04-15 15:13:44 +08:00
|
|
|
err = usbd_enable(&blinky_usbd);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usbd_enable failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_ctx.stack = USB_STACK_ENABLED;
|
2026-04-18 11:27:48 +08:00
|
|
|
usb_ctx.bus = USB_BUS_POWERED;
|
|
|
|
|
update_power_manager_restriction(true);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2026-04-15 15:13:44 +08:00
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (usb_ctx.bus == USB_BUS_DISCONNECTED) {
|
2026-04-15 09:30:40 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
err = usbd_enable(&blinky_usbd);
|
|
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usbd_enable failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_ctx.stack = USB_STACK_ENABLED;
|
|
|
|
|
update_power_manager_restriction(true);
|
2026-04-15 15:13:44 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
static int do_stop(void)
|
2026-04-15 15:13:44 +08:00
|
|
|
{
|
2026-04-18 11:27:48 +08:00
|
|
|
int err;
|
2026-04-15 15:13:44 +08:00
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (usb_ctx.stack == USB_STACK_ENABLED) {
|
|
|
|
|
err = usbd_disable(&blinky_usbd);
|
2026-04-15 15:13:44 +08:00
|
|
|
if (err) {
|
|
|
|
|
LOG_ERR("usbd_disable failed (%d)", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
usb_ctx.stack = USB_STACK_READY;
|
2026-04-11 17:57:00 +08:00
|
|
|
update_power_manager_restriction(false);
|
2026-04-17 19:12:57 +08:00
|
|
|
return 0;
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool handle_module_state_event(const struct module_state_event *event)
|
|
|
|
|
{
|
|
|
|
|
if (!check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
|
|
|
|
}
|
2026-04-11 17:15:11 +08:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
static bool handle_module_suspend_req_event(
|
|
|
|
|
const struct module_suspend_req_event *event)
|
2026-04-11 17:15:11 +08:00
|
|
|
{
|
2026-04-17 19:12:57 +08:00
|
|
|
if ((event->sink_module_id != MODULE_ID(MODULE)) ||
|
|
|
|
|
(usb_ctx.lc.state != LC_RUNNING)) {
|
2026-04-15 15:13:44 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_set_lifecycle(&usb_ctx.lc, LC_SUSPENDED) == 0) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool handle_module_resume_req_event(
|
|
|
|
|
const struct module_resume_req_event *event)
|
|
|
|
|
{
|
2026-04-17 19:12:57 +08:00
|
|
|
if ((event->sink_module_id != MODULE_ID(MODULE)) ||
|
|
|
|
|
(usb_ctx.lc.state != LC_SUSPENDED)) {
|
2026-04-11 17:15:11 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool app_event_handler(const struct app_event_header *aeh)
|
|
|
|
|
{
|
|
|
|
|
if (is_module_state_event(aeh)) {
|
|
|
|
|
return handle_module_state_event(cast_module_state_event(aeh));
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:13:44 +08:00
|
|
|
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));
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_power_down_event(aeh)) {
|
2026-04-17 19:12:57 +08:00
|
|
|
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_set_lifecycle(&usb_ctx.lc, LC_STOPPED) == 0) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
|
|
|
|
}
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_wake_up_event(aeh)) {
|
2026-04-17 19:12:57 +08:00
|
|
|
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
|
2026-04-18 11:27:48 +08:00
|
|
|
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
|
|
|
|
|
submit_usb_state(usb_public_state_get());
|
|
|
|
|
}
|
2026-04-11 17:15:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
|
|
|
|
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
2026-04-15 15:13:44 +08:00
|
|
|
APP_EVENT_SUBSCRIBE(MODULE, module_suspend_req_event);
|
|
|
|
|
APP_EVENT_SUBSCRIBE(MODULE, module_resume_req_event);
|
2026-04-11 17:15:11 +08:00
|
|
|
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
|
|
|
|
|
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);
|