diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 5fb3827c..a4c884ee 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources(app PRIVATE src/sensors.c) target_sources(app PRIVATE src/event_manager.c) target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c) target_sources(app PRIVATE src/events/activity_state_changed.c) +target_sources(app PRIVATE src/events/behavior_state_changed.c) target_sources(app PRIVATE src/events/position_state_changed.c) target_sources(app PRIVATE src/events/layer_state_changed.c) target_sources(app PRIVATE src/events/keycode_state_changed.c) @@ -70,6 +71,7 @@ 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(app PRIVATE src/endpoints.c) target_sources(app PRIVATE src/hid_listener.c) +target_sources(app PRIVATE src/behavior.c) target_sources(app PRIVATE src/main.c) add_subdirectory(src/display/) diff --git a/app/include/zmk/events/behavior_state_changed.h b/app/include/zmk/events/behavior_state_changed.h new file mode 100644 index 00000000..99bdd99d --- /dev/null +++ b/app/include/zmk/events/behavior_state_changed.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include +#include + +struct behavior_state_changed { + struct zmk_event_header header; + char *behavior_dev; + uint32_t param1; + uint32_t param2; + bool pressed; + int layer; + uint32_t position; + int64_t timestamp; +}; + +ZMK_EVENT_DECLARE(behavior_state_changed); + +static inline struct behavior_state_changed * +create_behavior_state_changed_from_binding(struct zmk_behavior_binding *binding, bool pressed, + int layer, uint32_t position, int64_t timestamp) { + struct behavior_state_changed *ev = new_behavior_state_changed(); + ev->behavior_dev = binding->behavior_dev; + ev->param1 = binding->param1; + ev->param2 = binding->param2; + ev->pressed = pressed; + ev->layer = layer; + ev->position = position; + ev->timestamp = timestamp; + return ev; +} + +static inline struct behavior_state_changed * +create_behavior_state_changed(char *behavior_dev, uint32_t param1, uint32_t param2, bool pressed, + int layer, uint32_t position, int64_t timestamp) { + struct behavior_state_changed *ev = new_behavior_state_changed(); + ev->behavior_dev = behavior_dev; + ev->param1 = param1; + ev->param2 = param2; + ev->pressed = pressed; + ev->layer = layer; + ev->position = position; + ev->timestamp = timestamp; + return ev; +} diff --git a/app/src/behavior.c b/app/src/behavior.c new file mode 100644 index 00000000..4d59af6d --- /dev/null +++ b/app/src/behavior.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int zmk_behavior_state_changed(const struct behavior_state_changed *ev) { + struct zmk_behavior_binding binding = { + .behavior_dev = ev->behavior_dev, + .param1 = ev->param1, + .param2 = ev->param2, + }; + const struct zmk_behavior_binding_event event = { + .layer = ev->layer, + .position = ev->position, + .timestamp = ev->timestamp, + }; + int ret; + if (ev->pressed) { + ret = behavior_keymap_binding_pressed(&binding, event); + } else { + ret = behavior_keymap_binding_released(&binding, event); + } + if (ret < 0) { + return ret; + } + switch (ret) { + case ZMK_BEHAVIOR_TRANSPARENT: + return ZMK_EV_EVENT_BUBBLE; + case ZMK_BEHAVIOR_OPAQUE: + return ZMK_EV_EVENT_HANDLED; + default: + return -ENOTSUP; + } +} + +int behavior_listener(const struct zmk_event_header *eh) { + if (is_behavior_state_changed(eh)) { + const struct behavior_state_changed *ev = cast_position_state_changed(eh); + return zmk_behavior_state_changed(ev); + } +} + +ZMK_LISTENER(behavior, behavior_listener); +ZMK_SUBSCRIPTION(behavior, behavior_state_changed); \ No newline at end of file diff --git a/app/src/event_manager.c b/app/src/event_manager.c index 872f5c86..dfaa2cd8 100644 --- a/app/src/event_manager.c +++ b/app/src/event_manager.c @@ -17,6 +17,12 @@ extern struct zmk_event_type *__event_type_end[]; extern struct zmk_event_subscription __event_subscriptions_start[]; extern struct zmk_event_subscription __event_subscriptions_end[]; +/* + * Returns negative values for errors. + * Returns ZMK_EV_EVENT_HANDLED if the event was handled + * Returns ZMK_EV_EVENT_CAPTURED if the event was captured + * Returns ZMK_EV_EVENT_BUBBLE if no handler handled the event + */ int zmk_event_manager_handle_from(struct zmk_event_header *event, uint8_t start_index) { int ret = 0; uint8_t len = __event_subscriptions_end - __event_subscriptions_start; @@ -31,13 +37,12 @@ int zmk_event_manager_handle_from(struct zmk_event_header *event, uint8_t start_ switch (ret) { case ZMK_EV_EVENT_HANDLED: LOG_DBG("Listener handled the event"); - ret = 0; goto release; case ZMK_EV_EVENT_CAPTURED: LOG_DBG("Listener captured the event"); event->last_listener_index = i; // Listeners are expected to free events they capture - return 0; + return ret; } } } diff --git a/app/src/events/behavior_state_changed.c b/app/src/events/behavior_state_changed.c new file mode 100644 index 00000000..c0802ecb --- /dev/null +++ b/app/src/events/behavior_state_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(behavior_state_changed); \ No newline at end of file diff --git a/app/src/keymap.c b/app/src/keymap.c index 786a1773..714f1079 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -16,6 +16,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#include #include #include @@ -146,11 +147,6 @@ int zmk_keymap_layer_to(uint8_t layer) { int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, int64_t timestamp) { struct zmk_behavior_binding *binding = &zmk_keymap[layer][position]; const struct device *behavior; - struct zmk_behavior_binding_event event = { - .layer = layer, - .position = position, - .timestamp = timestamp, - }; LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev)); @@ -159,14 +155,11 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, if (!behavior) { LOG_DBG("No behavior assigned to %d on layer %d", position, layer); - return 1; + return ZMK_EV_EVENT_HANDLED; } - if (pressed) { - return behavior_keymap_binding_pressed(binding, event); - } else { - return behavior_keymap_binding_released(binding, event); - } + return ZMK_EVENT_RAISE( + create_behavior_state_changed_from_binding(binding, pressed, layer, position, timestamp)); } int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp) { @@ -176,7 +169,7 @@ int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t t for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { if (zmk_keymap_layer_active_with_state(layer, zmk_keymap_active_behavior_layer[position])) { int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp); - if (ret > 0) { + if (ret == ZMK_EV_EVENT_BUBBLE) { LOG_DBG("behavior processing to continue to next layer"); continue; } else if (ret < 0) {