From b34b7f8e8e9e39b241d2a17fc7f644de3c25f279 Mon Sep 17 00:00:00 2001 From: snoyer Date: Sat, 22 Oct 2022 04:52:35 +0000 Subject: [PATCH] persist base layer selection --- app/src/behaviors/behavior_base_layer.c | 61 +++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/app/src/behaviors/behavior_base_layer.c b/app/src/behaviors/behavior_base_layer.c index dc472900..314d105b 100644 --- a/app/src/behaviors/behavior_base_layer.c +++ b/app/src/behaviors/behavior_base_layer.c @@ -16,13 +16,60 @@ #include #include +#if IS_ENABLED(CONFIG_SETTINGS) +#include +#endif + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) -uint8_t base_layer_by_profile[ZMK_PROFILE_COUNT] = {0}; +struct base_layer_state { + uint8_t base_layer_by_profile[ZMK_PROFILE_COUNT]; +}; -static int behavior_to_init(const struct device *dev) { return 0; }; +static struct base_layer_state state = {.base_layer_by_profile = {0}}; + +#if IS_ENABLED(CONFIG_SETTINGS) +static int base_layer_settings_set(const char *name, size_t len, settings_read_cb read_cb, + void *cb_arg) { + const char *next; + if (settings_name_steq(name, "state", &next) && !next) { + if (len != sizeof(state)) { + return -EINVAL; + } + int rc = read_cb(cb_arg, &state, sizeof(state)); + return MIN(rc, 0); + } + return -ENOENT; +} + +static void base_layer_save_work_handler(struct k_work *work) { + settings_save_one("base_layer/state", &state, sizeof(state)); +} + +static struct k_work_delayable base_layer_save_work; +struct settings_handler base_layer_settings_handler = {.name = "base_layer", + .h_set = base_layer_settings_set}; +#endif + +static int behavior_base_layer_init(const struct device *dev) { +#if IS_ENABLED(CONFIG_SETTINGS) + settings_subsys_init(); + + int err = settings_register(&base_layer_settings_handler); + if (err) { + LOG_ERR("Failed to register the base_layer settings handler (err %d)", err); + return err; + } + + k_work_init_delayable(&base_layer_save_work, base_layer_save_work_handler); + + settings_load_subtree("base_layer"); +#endif + + return 0; +}; static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { @@ -31,10 +78,14 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, const zmk_profile_index_t profile_index = zmk_current_profile_index(); const uint8_t layer = binding->param1; - base_layer_by_profile[profile_index] = layer; + state.base_layer_by_profile[profile_index] = layer; zmk_keymap_layer_to(layer); LOG_INF("saved base layer %d for profile %d", layer, profile_index); +#if IS_ENABLED(CONFIG_SETTINGS) + k_work_reschedule(&base_layer_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); +#endif /* IS_ENABLED(CONFIG_SETTINGS) */ + return ZMK_BEHAVIOR_OPAQUE; } @@ -50,7 +101,7 @@ static int base_layer_listener(const zmk_event_t *e) { } const zmk_profile_index_t profile_index = zmk_current_profile_index(); - const uint8_t layer = base_layer_by_profile[profile_index]; + const uint8_t layer = state.base_layer_by_profile[profile_index]; zmk_keymap_layer_to(layer); LOG_INF("restored base layer %d for profile %d", layer, profile_index); @@ -70,7 +121,7 @@ static const struct behavior_driver_api behavior_base_layer_driver_api = { .binding_released = on_keymap_binding_released, }; -DEVICE_DT_INST_DEFINE(0, behavior_to_init, NULL, NULL, NULL, APPLICATION, +DEVICE_DT_INST_DEFINE(0, behavior_base_layer_init, NULL, NULL, NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_base_layer_driver_api); #endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */