From 7e7110d85f0fe24948b319382bed723e38f5336c Mon Sep 17 00:00:00 2001
From: Peter Johanson <peter@peterjohanson.com>
Date: Mon, 25 Mar 2024 02:39:54 -0700
Subject: [PATCH] fix(pm): Fixes for dedicated on/off on peripherals.

* Add new flag to differentiate soft off on peripherals that
  is invoked by split GATT svc and dedicated additional ones
  tied to GPIO pin.
---
 .../zmk_uno/boards/nrf52840dk_nrf52840.overlay  |  5 ++---
 app/dts/behaviors/soft_off.dtsi                 |  3 ++-
 .../behaviors/zmk,behavior-soft-off.yaml        |  3 +++
 app/src/behaviors/behavior_soft_off.c           | 17 ++++++++++++-----
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay
index b9c68e5a..d798eca7 100644
--- a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay
+++ b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay
@@ -35,10 +35,9 @@ encoder: &qdec0 {
 
 / {
     behaviors {
-        soft_off: soft_off {
+        hw_soft_off: hw_soft_off {
             compatible = "zmk,behavior-soft-off";
             #binding-cells = <0>;
-            status = "okay";
         };
     };
 
@@ -54,7 +53,7 @@ encoder: &qdec0 {
         soft_off {
             row = <0>;
             column = <0>;
-            bindings = <&soft_off>;
+            bindings = <&hw_soft_off>;
         };
     };
 
diff --git a/app/dts/behaviors/soft_off.dtsi b/app/dts/behaviors/soft_off.dtsi
index 1e58c771..63c04b1d 100644
--- a/app/dts/behaviors/soft_off.dtsi
+++ b/app/dts/behaviors/soft_off.dtsi
@@ -6,9 +6,10 @@
 
 / {
     behaviors {
-        /omit-if-no-ref/ soft_off: soft_off {
+        /omit-if-no-ref/ soft_off: keymap_soft_off {
             compatible = "zmk,behavior-soft-off";
             #binding-cells = <0>;
+            split-peripheral-off-on-press;
         };
     };
 };
diff --git a/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml b/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml
index 1467ede4..865e656f 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml
@@ -12,3 +12,6 @@ properties:
     type: int
     required: false
     description: Number of milliseconds the behavior must be held before releasing will actually trigger a soft-off.
+  split-peripheral-off-on-press:
+    type: boolean
+    description: When built for a split peripheral, turn off on press, not release
diff --git a/app/src/behaviors/behavior_soft_off.c b/app/src/behaviors/behavior_soft_off.c
index 8b8ba4f9..3a4ae424 100644
--- a/app/src/behaviors/behavior_soft_off.c
+++ b/app/src/behaviors/behavior_soft_off.c
@@ -16,6 +16,7 @@
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
 struct behavior_soft_off_config {
+    bool split_peripheral_turn_off_on_press;
     uint32_t hold_time_ms;
 };
 
@@ -23,18 +24,22 @@ struct behavior_soft_off_data {
     uint32_t press_start;
 };
 
+#define IS_SPLIT_PERIPHERAL                                                                        \
+    (IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL))
+
 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 = zmk_behavior_get_binding(binding->behavior_dev);
     struct behavior_soft_off_data *data = dev->data;
+    const struct behavior_soft_off_config *config = dev->config;
 
-#if IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
-    zmk_pm_soft_off();
-#else
-    data->press_start = k_uptime_get();
-#endif
+    if (IS_SPLIT_PERIPHERAL && config->split_peripheral_turn_off_on_press) {
+        zmk_pm_soft_off();
+    } else {
+        data->press_start = k_uptime_get();
+    }
 
     return ZMK_BEHAVIOR_OPAQUE;
 }
@@ -71,6 +76,8 @@ static const struct behavior_driver_api behavior_soft_off_driver_api = {
 #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),                                       \
+        .split_peripheral_turn_off_on_press =                                                      \
+            DT_INST_PROP_OR(n, split_peripheral_off_on_press, false),                              \
     };                                                                                             \
     static struct behavior_soft_off_data bso_data_##n = {};                                        \
     BEHAVIOR_DT_INST_DEFINE(0, behavior_soft_off_init, NULL, &bso_data_##n, &bso_config_##n,       \