From 3e146089d316e727c70b17cd0cc428f278c01e67 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 13 Sep 2023 20:01:02 +0000 Subject: [PATCH] feat(behaviors): Add soft off behavior. * New soft-off behavior that can be used to force the device into soft-off state with only certain configured wakeup devices. --- app/CMakeLists.txt | 1 + app/Kconfig.behaviors | 6 ++ .../behaviors/zmk,behavior-soft-off.yaml | 14 ++++ app/src/behaviors/behavior_soft_off.c | 65 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml create mode 100644 app/src/behaviors/behavior_soft_off.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 09bb4ddd8f0c..1b68858c2528 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -52,6 +52,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) target_sources(app PRIVATE src/behaviors/behavior_to_layer.c) target_sources(app PRIVATE src/behaviors/behavior_transparent.c) target_sources(app PRIVATE src/behaviors/behavior_none.c) + target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SOFT_OFF app PRIVATE src/behaviors/behavior_soft_off.c) target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE app PRIVATE src/behaviors/behavior_sensor_rotate.c) target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_VAR app PRIVATE src/behaviors/behavior_sensor_rotate_var.c) target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON app PRIVATE src/behaviors/behavior_sensor_rotate_common.c) diff --git a/app/Kconfig.behaviors b/app/Kconfig.behaviors index 9d1773c3d1fe..2b1304b2770a 100644 --- a/app/Kconfig.behaviors +++ b/app/Kconfig.behaviors @@ -22,6 +22,12 @@ config ZMK_BEHAVIOR_MOUSE_KEY_PRESS depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED imply ZMK_MOUSE +config ZMK_BEHAVIOR_SOFT_OFF + bool + default y + select ZMK_PM_SOFT_OFF + depends on DT_HAS_ZMK_BEHAVIOR_SOFT_OFF_ENABLED + config ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON bool default n diff --git a/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml b/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml new file mode 100644 index 000000000000..1467ede47721 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Soft-Off Behavior + +compatible: "zmk,behavior-soft-off" + +include: zero_param.yaml + +properties: + hold-time-ms: + type: int + required: false + description: Number of milliseconds the behavior must be held before releasing will actually trigger a soft-off. diff --git a/app/src/behaviors/behavior_soft_off.c b/app/src/behaviors/behavior_soft_off.c new file mode 100644 index 000000000000..a2095b6ae558 --- /dev/null +++ b/app/src/behaviors/behavior_soft_off.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_soft_off + +#include +#include +#include + +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +struct behavior_soft_off_config { + uint32_t hold_time_ms; +}; + +struct behavior_soft_off_data { + uint32_t press_start; +}; + +static int behavior_soft_off_init(const struct device *dev) { return 0; }; + +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + struct behavior_soft_off_data *data = dev->data; + + data->press_start = k_uptime_get(); + + return ZMK_BEHAVIOR_OPAQUE; +} + +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + struct behavior_soft_off_data *data = dev->data; + const struct behavior_soft_off_config *config = dev->config; + + if (config->hold_time_ms == 0 || (k_uptime_get() - data->press_start) >= config->hold_time_ms) { + zmk_pm_soft_off(); + } + + return ZMK_BEHAVIOR_OPAQUE; +} + +static const struct behavior_driver_api behavior_soft_off_driver_api = { + .binding_pressed = on_keymap_binding_pressed, + .binding_released = on_keymap_binding_released, +}; + +#define BSO_INST(n) \ + static const struct behavior_soft_off_config bso_config_##n = { \ + .hold_time_ms = DT_INST_PROP_OR(n, hold_time_ms, 0), \ + }; \ + static struct behavior_soft_off_data bso_data_##n = {}; \ + DEVICE_DT_INST_DEFINE(0, behavior_soft_off_init, NULL, &bso_data_##n, &bso_config_##n, \ + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &behavior_soft_off_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(BSO_INST)