forked from kofal.net/zmk
feat: Add soft on/off support.
Initial work on a soft on/off support for ZMK. Triggering soft off puts the device into deep sleep with only a specific GPIO pin configured to wake the device, avoiding waking from other key presses in the matrix like the normal deep sleep. Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
This commit is contained in:
committed by
Pete Johanson
parent
58ccc5970d
commit
adb3a13dc5
59
app/src/pm.c
Normal file
59
app/src/pm.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2023 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/pm.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#define HAS_WAKERS DT_HAS_COMPAT_STATUS_OKAY(zmk_soft_off_wakeup_sources)
|
||||
|
||||
#if HAS_WAKERS
|
||||
|
||||
#define DEVICE_WITH_SEP(node_id, prop, idx) DEVICE_DT_GET(DT_PROP_BY_IDX(node_id, prop, idx)),
|
||||
|
||||
const struct device *soft_off_wakeup_sources[] = {
|
||||
DT_FOREACH_PROP_ELEM(DT_INST(0, zmk_soft_off_wakeup_sources), wakeup_sources, DEVICE_WITH_SEP)};
|
||||
|
||||
#endif
|
||||
|
||||
int zmk_pm_soft_off(void) {
|
||||
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||
size_t device_count;
|
||||
const struct device *devs;
|
||||
|
||||
device_count = z_device_get_all_static(&devs);
|
||||
|
||||
// There may be some matrix/direct kscan devices that would be used for wakeup
|
||||
// from normal "inactive goes to sleep" behavior, so disable them as wakeup devices
|
||||
// and then suspend them so we're ready to take over setting up our system
|
||||
// and then putting it into an off state.
|
||||
for (int i = 0; i < device_count; i++) {
|
||||
const struct device *dev = &devs[i];
|
||||
|
||||
LOG_DBG("soft-on-off pressed cb: suspend device");
|
||||
if (pm_device_wakeup_is_enabled(dev)) {
|
||||
pm_device_wakeup_enable(dev, false);
|
||||
}
|
||||
pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
|
||||
}
|
||||
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||
|
||||
#if HAS_WAKERS
|
||||
for (int i = 0; i < ARRAY_SIZE(soft_off_wakeup_sources); i++) {
|
||||
const struct device *dev = soft_off_wakeup_sources[i];
|
||||
pm_device_wakeup_enable(dev, true);
|
||||
pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME);
|
||||
}
|
||||
#endif // HAS_WAKERS
|
||||
|
||||
LOG_DBG("soft-on-off interrupt: go to sleep");
|
||||
return pm_state_force(0U, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});
|
||||
}
|
||||
Reference in New Issue
Block a user