diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 1492be16c83..ccf0e56252c 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -82,6 +82,7 @@ target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c) +target_sources_ifdef(CONFIG_ZMK_EXT_POWER_USB_ONLY app PRIVATE src/ext_power_usb_only.c) target_sources(app PRIVATE src/endpoints.c) target_sources(app PRIVATE src/hid_listener.c) target_sources(app PRIVATE src/main.c) diff --git a/app/Kconfig b/app/Kconfig index fea2203d612..657280087b7 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -402,6 +402,10 @@ config ZMK_EXT_POWER bool "Enable support to control external power output" default y +config ZMK_EXT_POWER_USB_ONLY + bool "Turn off external power when USB is disconnected" + default n + #Power Management endmenu diff --git a/app/src/ext_power_usb_only.c b/app/src/ext_power_usb_only.c new file mode 100644 index 00000000000..36b3d5e22b3 --- /dev/null +++ b/app/src/ext_power_usb_only.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#if IS_ENABLED(CONFIG_ZMK_EXT_POWER_USB_ONLY) + +static bool initialized = false; + +void zmk_ext_power_usb_only_toggle() { + + // Do not touch external power until properly initialized. + // This prevents cutting external power until displays and other + // components are properly initialized + if (initialized == false) { + LOG_DBG("zmk_ext_power_usb_only not initialized yet. Ignoring."); + return; + } + + const struct device *ext_power = device_get_binding("EXT_POWER"); + const int ext_power_enabled = ext_power_get(ext_power); + + if (zmk_usb_is_powered() == true && ext_power_enabled == false) { + LOG_DBG("USB power was connected. Enabling external power."); + ext_power_enable(ext_power); + } else if (zmk_usb_is_powered() == false && ext_power_enabled == true) { + LOG_DBG("USB power was removed. Disabling external power."); + ext_power_disable(ext_power); + } +} + +static int zmk_ext_power_usb_only_event_listener(const zmk_event_t *eh) { + if (as_zmk_usb_conn_state_changed(eh)) { + LOG_DBG("USB conn state changed: %d", zmk_usb_is_powered()); + + zmk_ext_power_usb_only_toggle(); + } + + return 0; +} + +ZMK_LISTENER(ext_power, zmk_ext_power_usb_only_event_listener); +ZMK_SUBSCRIPTION(ext_power, zmk_usb_conn_state_changed); + +static int zmk_ext_power_usb_only_init(const struct device *_arg) { + + LOG_DBG("Running zmk_ext_power_usb_only_init"); + + initialized = true; + zmk_ext_power_usb_only_toggle(); + + return 0; +} + +// Initialized ext power usb only after everything else has been +// initialized. +// +// This avoids interrupting the iniitalization of displays for example. +#define ZMK_EXT_POWER_USB_ONLY_INIT_PRIORITY CONFIG_APPLICATION_INIT_PRIORITY+100 +SYS_INIT(zmk_ext_power_usb_only_init, APPLICATION, ZMK_EXT_POWER_USB_ONLY_INIT_PRIORITY); + +#endif