diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 0aa5d85e..d7e57d02 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -23,9 +23,17 @@ * (Internal use only.) */ +enum behavior_sensor_binding_process_mode { + BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER, + BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD, +}; + typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event); -typedef int (*behavior_sensor_keymap_binding_callback_t)( +typedef int (*behavior_sensor_keymap_binding_process_callback_t)( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode); +typedef int (*behavior_sensor_keymap_binding_data_callback_t)( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data channel_data[channel_data_size]); @@ -41,7 +49,8 @@ __subsystem struct behavior_driver_api { behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params; behavior_keymap_binding_callback_t binding_pressed; behavior_keymap_binding_callback_t binding_released; - behavior_sensor_keymap_binding_callback_t sensor_binding_triggered; + behavior_sensor_keymap_binding_data_callback_t sensor_binding_data; + behavior_sensor_keymap_binding_process_callback_t sensor_binding_process; }; /** * @endcond @@ -151,7 +160,7 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi } /** - * @brief Handle the a sensor keymap binding being triggered + * @brief Handle the a sensor keymap binding processing any incoming data from the sensor * @param binding Sensor keymap binding which was triggered. * @param sensor Pointer to the sensor device structure for the sensor driver instance. * @param virtual_key_position ZMK_KEYMAP_LEN + sensor number @@ -160,12 +169,12 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi * @retval 0 If successful. * @retval Negative errno code if failure. */ -__syscall int behavior_sensor_keymap_binding_triggered( +__syscall int behavior_sensor_keymap_binding_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data); -static inline int z_impl_behavior_sensor_keymap_binding_triggered( +static inline int z_impl_behavior_sensor_keymap_binding_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data) { @@ -177,12 +186,46 @@ static inline int z_impl_behavior_sensor_keymap_binding_triggered( const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; - if (api->sensor_binding_triggered == NULL) { + if (api->sensor_binding_data == NULL) { return -ENOTSUP; } - return api->sensor_binding_triggered(binding, event, sensor_config, channel_data_size, - channel_data); + return api->sensor_binding_data(binding, event, sensor_config, channel_data_size, channel_data); +} + +/** + * @brief Handle the keymap sensor binding being triggered after updating any local data + * @param dev Pointer to the device structure for the driver instance. + * @param param1 User parameter specified at time of behavior binding. + * @param param2 User parameter specified at time of behavior binding. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +// clang-format off +__syscall int behavior_sensor_keymap_binding_process( + struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode); +// clang-format on + +static inline int +z_impl_behavior_sensor_keymap_binding_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode) { + const struct device *dev = device_get_binding(binding->behavior_dev); + + if (dev == NULL) { + return -EINVAL; + } + + const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; + + if (api->sensor_binding_process == NULL) { + return -ENOTSUP; + } + + return api->sensor_binding_process(binding, event, mode); } /** diff --git a/app/src/behaviors/behavior_sensor_rotate.c b/app/src/behaviors/behavior_sensor_rotate.c index 86846d5b..3b5bef62 100644 --- a/app/src/behaviors/behavior_sensor_rotate.c +++ b/app/src/behaviors/behavior_sensor_rotate.c @@ -13,7 +13,8 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_driver_api = { - .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_init(const struct device *dev) { return 0; }; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 99e4e019..0a2b619d 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -11,13 +11,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); -int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, - struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data) { +int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data) { const struct device *dev = device_get_binding(binding->behavior_dev); - const struct behavior_sensor_rotate_config *cfg = dev->config; struct behavior_sensor_rotate_data *data = dev->data; const struct sensor_value value = channel_data[0].value; @@ -52,6 +51,26 @@ int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *bindi value.val1, value.val2, data->remainder[sensor_position].val1, data->remainder[sensor_position].val2, triggers, binding->param1, binding->param2); + data->triggers[sensor_position] = triggers; + return 0; +} + +int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode) { + const struct device *dev = device_get_binding(binding->behavior_dev); + const struct behavior_sensor_rotate_config *cfg = dev->config; + struct behavior_sensor_rotate_data *data = dev->data; + + const int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); + + if (mode != BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER) { + data->triggers[sensor_position] = 0; + return 0; + } + + int triggers = data->triggers[sensor_position]; + struct zmk_behavior_binding triggered_binding; if (triggers > 0) { triggered_binding = cfg->cw_binding; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h index eab443a3..d9d4d855 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.h +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -4,6 +4,7 @@ * SPDX-License-Identifier: MIT */ +#include #include #include @@ -16,10 +17,14 @@ struct behavior_sensor_rotate_config { struct behavior_sensor_rotate_data { struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN]; + int triggers[ZMK_KEYMAP_SENSORS_LEN]; }; -int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, +int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data); +int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data); \ No newline at end of file + enum behavior_sensor_binding_process_mode mode); \ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_var.c b/app/src/behaviors/behavior_sensor_rotate_var.c index 95bb9961..3c2373b0 100644 --- a/app/src/behaviors/behavior_sensor_rotate_var.c +++ b/app/src/behaviors/behavior_sensor_rotate_var.c @@ -13,7 +13,8 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_var_driver_api = { - .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0; }; diff --git a/app/src/keymap.c b/app/src/keymap.c index 16543d37..c8121176 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -252,48 +252,59 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr } #if ZMK_KEYMAP_HAS_SENSORS -int zmk_keymap_sensor_triggered( - uint8_t sensor_position, size_t channel_data_size, - const struct zmk_sensor_channel_data channel_data[channel_data_size], int64_t timestamp) { - for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { - if (zmk_keymap_layer_active(layer)) { - struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; - const struct device *behavior; - int ret; +int zmk_keymap_sensor_event(uint8_t sensor_position, size_t channel_data_size, + const struct zmk_sensor_channel_data channel_data[channel_data_size], + int64_t timestamp) { + bool opaque_response = false; - LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, - binding->behavior_dev); + for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= 0; layer--) { + struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; + const struct device *behavior; + int ret; - behavior = device_get_binding(binding->behavior_dev); + LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, + binding->behavior_dev); - if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); - continue; - } + behavior = device_get_binding(binding->behavior_dev); - struct zmk_behavior_binding_event event = { - .layer = layer, - .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), - .timestamp = timestamp, - }; + if (!behavior) { + LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); + continue; + } - ret = behavior_sensor_keymap_binding_triggered( - binding, event, zmk_sensors_get_config_at_position(sensor_position), - channel_data_size, channel_data); + struct zmk_behavior_binding_event event = { + .layer = layer, + .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), + .timestamp = timestamp, + }; - if (ret > 0) { - LOG_DBG("behavior processing to continue to next layer"); - continue; - } else if (ret < 0) { - LOG_DBG("Behavior returned error: %d", ret); - return ret; - } else { - return ret; - } + ret = behavior_sensor_keymap_binding_data( + binding, event, zmk_sensors_get_config_at_position(sensor_position), channel_data_size, + channel_data); + + if (ret > 0) { + LOG_DBG("behavior processing to continue to next layer"); + continue; + } + + enum behavior_sensor_binding_process_mode mode = + (!opaque_response && layer >= _zmk_keymap_layer_default && + zmk_keymap_layer_active(layer)) + ? BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER + : BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD; + + ret = behavior_sensor_keymap_binding_process(binding, event, mode); + + if (ret == ZMK_BEHAVIOR_OPAQUE) { + LOG_DBG("sensor event processing complete, behavior response was opaque"); + opaque_response = true; + } else if (ret < 0) { + LOG_DBG("Behavior returned error: %d", ret); + return ret; } } - return -ENOTSUP; + return 0; } #endif /* ZMK_KEYMAP_HAS_SENSORS */ @@ -308,8 +319,8 @@ int keymap_listener(const zmk_event_t *eh) { #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_keymap_sensor_triggered(sensor_ev->sensor_position, sensor_ev->channel_data_size, - sensor_ev->channel_data, sensor_ev->timestamp); + return zmk_keymap_sensor_event(sensor_ev->sensor_position, sensor_ev->channel_data_size, + sensor_ev->channel_data, sensor_ev->timestamp); } #endif /* ZMK_KEYMAP_HAS_SENSORS */