forked from kofal.net/zmk
feat(behaviors): Add behavior metadata information.
* For upcoming ZMK studio work, make a set of rich metadata available to provide a friendly name for a behavior, and allow super flexible descriptions of the parameters the behaviors take. * Add ability to validate a zmk_behavior_binding against the behavior metadata available.
This commit is contained in:
committed by
Pete Johanson
parent
7cdf1e42ea
commit
03099b04b6
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <drivers/behavior.h>
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/matrix.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
@@ -39,6 +41,150 @@ const struct device *z_impl_behavior_get_binding(const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
int zmk_behavior_get_empty_param_metadata(const struct device *dev,
|
||||
struct behavior_parameter_metadata *metadata) {
|
||||
metadata->sets_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
static int validate_hid_usage(uint16_t usage_page, uint16_t usage_id) {
|
||||
LOG_DBG("Validate usage %d in page %d", usage_id, usage_page);
|
||||
switch (usage_page) {
|
||||
case HID_USAGE_KEY:
|
||||
if (usage_id == 0 || (usage_id > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE &&
|
||||
usage_id < LEFT_CONTROL && usage_id > RIGHT_GUI)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case HID_USAGE_CONSUMER:
|
||||
if (usage_id >
|
||||
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC), (0xFF), (0xFFF))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unsupported HID usage page %d", usage_page);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PARAM_MATCHES 0
|
||||
|
||||
static int check_param_matches_value(const struct behavior_parameter_value_metadata *value_meta,
|
||||
uint32_t param) {
|
||||
switch (value_meta->type) {
|
||||
case BEHAVIOR_PARAMETER_VALUE_TYPE_NIL:
|
||||
if (param == 0) {
|
||||
return PARAM_MATCHES;
|
||||
}
|
||||
break;
|
||||
case BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE:
|
||||
if (validate_hid_usage(ZMK_HID_USAGE_PAGE(param), ZMK_HID_USAGE_ID(param)) >= 0) {
|
||||
return PARAM_MATCHES;
|
||||
}
|
||||
|
||||
break;
|
||||
case BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX:
|
||||
if (param >= 0 && param < ZMK_KEYMAP_LEN) {
|
||||
return PARAM_MATCHES;
|
||||
}
|
||||
break;
|
||||
/* TODO: Restore with HSV -> RGB refactor
|
||||
case BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HSV:
|
||||
// TODO: No real way to validate? Maybe max brightness?
|
||||
break;
|
||||
*/
|
||||
case BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE:
|
||||
if (param == value_meta->value) {
|
||||
return PARAM_MATCHES;
|
||||
}
|
||||
break;
|
||||
case BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE:
|
||||
if (param >= value_meta->range.min && param <= value_meta->range.max) {
|
||||
return PARAM_MATCHES;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unknown type %d", value_meta->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int zmk_behavior_validate_param_values(const struct behavior_parameter_value_metadata *values,
|
||||
size_t values_len, uint32_t param) {
|
||||
if (values_len == 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (int v = 0; v < values_len; v++) {
|
||||
int ret = check_param_matches_value(&values[v], param);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int zmk_behavior_check_params_match_metadata(const struct behavior_parameter_metadata *metadata,
|
||||
uint32_t param1, uint32_t param2) {
|
||||
if (!metadata || metadata->sets_len == 0) {
|
||||
if (!metadata) {
|
||||
LOG_ERR("No metadata to check against");
|
||||
}
|
||||
|
||||
return (param1 == 0 && param2 == 0) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
for (int s = 0; s < metadata->sets_len; s++) {
|
||||
const struct behavior_parameter_metadata_set *set = &metadata->sets[s];
|
||||
int param1_ret =
|
||||
zmk_behavior_validate_param_values(set->param1_values, set->param1_values_len, param1);
|
||||
int param2_ret =
|
||||
zmk_behavior_validate_param_values(set->param2_values, set->param2_values_len, param2);
|
||||
|
||||
if ((param1_ret >= 0 || (param1_ret == -ENODEV && param1 == 0)) &&
|
||||
(param2_ret >= 0 || (param2_ret == -ENODEV && param2 == 0))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
int zmk_behavior_validate_binding(const struct zmk_behavior_binding *binding) {
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
const struct device *behavior = zmk_behavior_get_binding(binding->behavior_dev);
|
||||
|
||||
if (!behavior) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct behavior_parameter_metadata metadata;
|
||||
int ret = behavior_get_parameter_metadata(behavior, &metadata);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_WRN("Failed getting metadata for %s: %d", binding->behavior_dev, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return zmk_behavior_check_params_match_metadata(&metadata, binding->param1, binding->param2);
|
||||
#else
|
||||
return 0;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_LOG)
|
||||
static int check_behavior_names(void) {
|
||||
// Behavior names must be unique, but we don't have a good way to enforce this
|
||||
|
||||
@@ -18,6 +18,82 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata no_arg_values[] = {
|
||||
{
|
||||
.display_name = "Toggle On/Off",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_TOG_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Turn On",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_ON_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Turn OFF",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_OFF_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Increase Brightness",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_INC_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Decrease Brightness",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_DEC_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Cycle Brightness",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_CYCLE_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_value_metadata one_arg_p1_values[] = {
|
||||
{
|
||||
.display_name = "Set Brightness",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BL_SET_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_value_metadata one_arg_p2_values[] = {
|
||||
{
|
||||
.display_name = "Brightness",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE,
|
||||
.range =
|
||||
{
|
||||
.min = 0,
|
||||
.max = 255,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set no_args_set = {
|
||||
.param1_values = no_arg_values,
|
||||
.param1_values_len = ARRAY_SIZE(no_arg_values),
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set one_args_set = {
|
||||
.param1_values = one_arg_p1_values,
|
||||
.param1_values_len = ARRAY_SIZE(one_arg_p1_values),
|
||||
.param2_values = one_arg_p2_values,
|
||||
.param2_values_len = ARRAY_SIZE(one_arg_p2_values),
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set sets[] = {no_args_set, one_args_set};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(sets),
|
||||
.sets = sets,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static int behavior_backlight_init(const struct device *dev) { return 0; }
|
||||
|
||||
static int
|
||||
@@ -89,6 +165,9 @@ static const struct behavior_driver_api behavior_backlight_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_backlight_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -20,6 +20,74 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata no_arg_values[] = {
|
||||
{
|
||||
.display_name = "Next Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_NXT_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Previous Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_PRV_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Clear All Profiles",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_CLR_ALL_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Clear Selected Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_CLR_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set no_args_set = {
|
||||
.param1_values = no_arg_values,
|
||||
.param1_values_len = ARRAY_SIZE(no_arg_values),
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_value_metadata prof_index_param1_values[] = {
|
||||
{
|
||||
.display_name = "Select Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_SEL_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Disconnect Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = BT_DISC_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_value_metadata prof_index_param2_values[] = {
|
||||
{
|
||||
.display_name = "Profile",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE,
|
||||
.range = {.min = 0, .max = ZMK_BLE_PROFILE_COUNT},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set profile_index_metadata_set = {
|
||||
.param1_values = prof_index_param1_values,
|
||||
.param1_values_len = ARRAY_SIZE(prof_index_param1_values),
|
||||
.param2_values = prof_index_param2_values,
|
||||
.param2_values_len = ARRAY_SIZE(prof_index_param2_values),
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set metadata_sets[] = {no_args_set,
|
||||
profile_index_metadata_set};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(metadata_sets),
|
||||
.sets = metadata_sets,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
switch (binding->param1) {
|
||||
@@ -54,6 +122,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
static const struct behavior_driver_api behavior_bt_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_bt_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -68,6 +68,12 @@ struct behavior_hold_tap_config {
|
||||
int32_t hold_trigger_key_positions[];
|
||||
};
|
||||
|
||||
struct behavior_hold_tap_data {
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
struct behavior_parameter_metadata_set set;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
// this data is specific for each hold-tap
|
||||
struct active_hold_tap {
|
||||
int32_t position;
|
||||
@@ -652,9 +658,52 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
static int hold_tap_parameter_metadata(const struct device *hold_tap,
|
||||
struct behavior_parameter_metadata *param_metadata) {
|
||||
const struct behavior_hold_tap_config *cfg = hold_tap->config;
|
||||
struct behavior_hold_tap_data *data = hold_tap->data;
|
||||
int err;
|
||||
struct behavior_parameter_metadata child_meta;
|
||||
|
||||
err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->hold_behavior_dev),
|
||||
&child_meta);
|
||||
if (err < 0) {
|
||||
LOG_WRN("Failed to get the hold behavior parameter: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (child_meta.sets_len > 0) {
|
||||
data->set.param1_values = child_meta.sets[0].param1_values;
|
||||
data->set.param1_values_len = child_meta.sets[0].param1_values_len;
|
||||
}
|
||||
|
||||
err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->tap_behavior_dev),
|
||||
&child_meta);
|
||||
if (err < 0) {
|
||||
LOG_WRN("Failed to get the tap behavior parameter: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (child_meta.sets_len > 0) {
|
||||
data->set.param2_values = child_meta.sets[0].param1_values;
|
||||
data->set.param2_values_len = child_meta.sets[0].param1_values_len;
|
||||
}
|
||||
|
||||
param_metadata->sets = &data->set;
|
||||
param_metadata->sets_len = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_driver_api behavior_hold_tap_driver_api = {
|
||||
.binding_pressed = on_hold_tap_binding_pressed,
|
||||
.binding_released = on_hold_tap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = hold_tap_parameter_metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
static int position_state_changed_listener(const zmk_event_t *eh) {
|
||||
@@ -791,7 +840,7 @@ static int behavior_hold_tap_init(const struct device *dev) {
|
||||
}
|
||||
|
||||
#define KP_INST(n) \
|
||||
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
||||
static const struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
||||
.tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \
|
||||
.hold_behavior_dev = DEVICE_DT_NAME(DT_INST_PHANDLE_BY_IDX(n, bindings, 0)), \
|
||||
.tap_behavior_dev = DEVICE_DT_NAME(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \
|
||||
@@ -807,9 +856,10 @@ static int behavior_hold_tap_init(const struct device *dev) {
|
||||
.hold_trigger_key_positions = DT_INST_PROP(n, hold_trigger_key_positions), \
|
||||
.hold_trigger_key_positions_len = DT_INST_PROP_LEN(n, hold_trigger_key_positions), \
|
||||
}; \
|
||||
BEHAVIOR_DT_INST_DEFINE(n, behavior_hold_tap_init, NULL, NULL, &behavior_hold_tap_config_##n, \
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_hold_tap_driver_api);
|
||||
static struct behavior_hold_tap_data behavior_hold_tap_data_##n = {}; \
|
||||
BEHAVIOR_DT_INST_DEFINE(n, behavior_hold_tap_init, NULL, &behavior_hold_tap_data_##n, \
|
||||
&behavior_hold_tap_config_##n, POST_KERNEL, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
||||
|
||||
|
||||
@@ -16,6 +16,27 @@
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata param_values[] = {
|
||||
{
|
||||
.display_name = "Key",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
|
||||
.param1_values = param_values,
|
||||
.param1_values_len = ARRAY_SIZE(param_values),
|
||||
}};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(param_metadata_set),
|
||||
.sets = param_metadata_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int behavior_key_press_init(const struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
@@ -31,7 +52,12 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
#define KP_INST(n) \
|
||||
BEHAVIOR_DT_INST_DEFINE(n, behavior_key_press_init, NULL, NULL, NULL, POST_KERNEL, \
|
||||
|
||||
@@ -31,9 +31,34 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata param_values[] = {
|
||||
{
|
||||
.display_name = "Key",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
|
||||
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HID_USAGE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
|
||||
.param1_values = param_values,
|
||||
.param1_values_len = ARRAY_SIZE(param_values),
|
||||
}};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(param_metadata_set),
|
||||
.sets = param_metadata_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static const struct behavior_driver_api behavior_key_toggle_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
#define KT_INST(n) \
|
||||
|
||||
@@ -34,6 +34,10 @@ struct behavior_macro_trigger_state {
|
||||
struct behavior_macro_state {
|
||||
struct behavior_macro_trigger_state release_state;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
struct behavior_parameter_metadata_set set;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
uint32_t press_bindings_count;
|
||||
};
|
||||
|
||||
@@ -209,9 +213,100 @@ static int on_macro_binding_released(struct zmk_behavior_binding *binding,
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static void assign_values_to_set(enum param_source param_source,
|
||||
struct behavior_parameter_metadata_set *set,
|
||||
const struct behavior_parameter_value_metadata *values,
|
||||
size_t values_len) {
|
||||
if (param_source == PARAM_SOURCE_MACRO_1ST) {
|
||||
set->param1_values = values;
|
||||
set->param1_values_len = values_len;
|
||||
} else {
|
||||
set->param2_values = values;
|
||||
set->param2_values_len = values_len;
|
||||
}
|
||||
}
|
||||
|
||||
// This function will dynamically determine the parameter metadata for a particular macro by
|
||||
// inspecting the macro *bindings* to see what behaviors in that list receive the macro parameters,
|
||||
// and then using the metadata from those behaviors for the macro itself.
|
||||
//
|
||||
// Care need be taken, where a behavior in the list takes two parameters, and the macro passes along
|
||||
// a value for the *second* parameter, we need to make sure we find the right metadata set for the
|
||||
// referenced behavior that matches the first parameter.
|
||||
static int get_macro_parameter_metadata(const struct device *macro,
|
||||
struct behavior_parameter_metadata *param_metadata) {
|
||||
const struct behavior_macro_config *cfg = macro->config;
|
||||
struct behavior_macro_state *data = macro->data;
|
||||
struct behavior_macro_trigger_state state = {0};
|
||||
|
||||
for (int i = 0; (i < cfg->count) && (!data->set.param1_values || !data->set.param2_values);
|
||||
i++) {
|
||||
if (handle_control_binding(&state, &cfg->bindings[i]) ||
|
||||
(state.param1_source == PARAM_SOURCE_BINDING &&
|
||||
state.param2_source == PARAM_SOURCE_BINDING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_DBG("checking %d for the given state", i);
|
||||
|
||||
struct behavior_parameter_metadata binding_meta;
|
||||
int err = behavior_get_parameter_metadata(
|
||||
zmk_behavior_get_binding(cfg->bindings[i].behavior_dev), &binding_meta);
|
||||
if (err < 0 || binding_meta.sets_len == 0) {
|
||||
LOG_WRN("Failed to fetch macro binding parameter details %d", err);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
// If both macro parameters get passed to this one entry, use
|
||||
// the metadata for this behavior verbatim.
|
||||
if (state.param1_source != PARAM_SOURCE_BINDING &&
|
||||
state.param2_source != PARAM_SOURCE_BINDING) {
|
||||
param_metadata->sets_len = binding_meta.sets_len;
|
||||
param_metadata->sets = binding_meta.sets;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state.param1_source != PARAM_SOURCE_BINDING) {
|
||||
assign_values_to_set(state.param1_source, &data->set,
|
||||
binding_meta.sets[0].param1_values,
|
||||
binding_meta.sets[0].param1_values_len);
|
||||
}
|
||||
|
||||
if (state.param2_source != PARAM_SOURCE_BINDING) {
|
||||
// For the param2 metadata, we need to find a set that matches fully bound first
|
||||
// parameter of our macro entry, and use the metadata from that set.
|
||||
for (int s = 0; s < binding_meta.sets_len; s++) {
|
||||
if (zmk_behavior_validate_param_values(binding_meta.sets[s].param1_values,
|
||||
binding_meta.sets[s].param1_values_len,
|
||||
cfg->bindings[i].param1) >= 0) {
|
||||
assign_values_to_set(state.param2_source, &data->set,
|
||||
binding_meta.sets[s].param2_values,
|
||||
binding_meta.sets[s].param2_values_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.param1_source = PARAM_SOURCE_BINDING;
|
||||
state.param2_source = PARAM_SOURCE_BINDING;
|
||||
}
|
||||
|
||||
param_metadata->sets_len = 1;
|
||||
param_metadata->sets = &data->set;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_driver_api behavior_macro_driver_api = {
|
||||
.binding_pressed = on_macro_binding_pressed,
|
||||
.binding_released = on_macro_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = get_macro_parameter_metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
#define TRANSFORMED_BEHAVIORS(n) \
|
||||
|
||||
@@ -15,6 +15,27 @@
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata param_values[] = {
|
||||
{
|
||||
.display_name = "Layer",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
|
||||
.param1_values = param_values,
|
||||
.param1_values_len = ARRAY_SIZE(param_values),
|
||||
}};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(param_metadata_set),
|
||||
.sets = param_metadata_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct behavior_mo_config {};
|
||||
struct behavior_mo_data {};
|
||||
|
||||
@@ -33,7 +54,12 @@ static int mo_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_mo_driver_api = {
|
||||
.binding_pressed = mo_keymap_binding_pressed, .binding_released = mo_keymap_binding_released};
|
||||
.binding_pressed = mo_keymap_binding_pressed,
|
||||
.binding_released = mo_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
static const struct behavior_mo_config behavior_mo_config = {};
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
static const struct behavior_driver_api behavior_none_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_none_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -20,6 +20,42 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata std_values[] = {
|
||||
{
|
||||
.value = OUT_TOG,
|
||||
.display_name = "Toggle Outputs",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
},
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||
{
|
||||
.value = OUT_USB,
|
||||
.display_name = "USB Output",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
},
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_USB)
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
{
|
||||
.value = OUT_BLE,
|
||||
.display_name = "BLE Output",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
},
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set std_set = {
|
||||
.param1_values = std_values,
|
||||
.param1_values_len = ARRAY_SIZE(std_values),
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = 1,
|
||||
.sets = &std_set,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
switch (binding->param1) {
|
||||
@@ -40,6 +76,9 @@ static int behavior_out_init(const struct device *dev) { return 0; }
|
||||
|
||||
static const struct behavior_driver_api behavior_outputs_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_out_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -18,6 +18,119 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata no_arg_values[] = {
|
||||
{
|
||||
.display_name = "Toggle On/Off",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_TOG_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Turn On",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_ON_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Turn OFF",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_OFF_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Hue Up",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_HUI_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Hue Down",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_HUD_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Saturation Up",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_SAI_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Saturation Down",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_SAD_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Brightness Up",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_BRI_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Brightness Down",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_BRD_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Speed Up",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_SPI_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Speed Down",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_SPD_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Next Effect",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_EFF_CMD,
|
||||
},
|
||||
{
|
||||
.display_name = "Previous Effect",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_EFR_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set no_args_set = {
|
||||
.param1_values = no_arg_values,
|
||||
.param1_values_len = ARRAY_SIZE(no_arg_values),
|
||||
};
|
||||
|
||||
/*
|
||||
static const struct behavior_parameter_value_metadata hsv_p1_value_metadata_values[] = {
|
||||
{
|
||||
.display_name = "Set Color",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
|
||||
.value = RGB_COLOR_HSB_CMD,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_value_metadata hsv_p2_value_metadata_values[] = {
|
||||
{
|
||||
.display_name = "Color",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
|
||||
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HSV,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set hsv_value_metadata_set = {
|
||||
.param1_values = hsv_p1_value_metadata_values,
|
||||
.param1_values_len = ARRAY_SIZE(hsv_p1_value_metadata_values),
|
||||
.param_values = hsv_p2_value_metadata_values,
|
||||
.param_values_len = ARRAY_SIZE(hsv_p2_value_metadata_values),
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
static const struct behavior_parameter_metadata_set sets[] = {
|
||||
no_args_set,
|
||||
// hsv_value_metadata_set,
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(sets),
|
||||
.sets = sets,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static int behavior_rgb_underglow_init(const struct device *dev) { return 0; }
|
||||
|
||||
static int
|
||||
@@ -147,6 +260,9 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_rgb_underglow_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -74,6 +74,9 @@ static const struct behavior_driver_api behavior_soft_off_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
#define BSO_INST(n) \
|
||||
|
||||
@@ -188,9 +188,41 @@ static int on_sticky_key_binding_released(struct zmk_behavior_binding *binding,
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static int sticky_key_parameter_domains(const struct device *sk,
|
||||
struct behavior_parameter_metadata *param_metadata) {
|
||||
const struct behavior_sticky_key_config *cfg = sk->config;
|
||||
|
||||
struct behavior_parameter_metadata child_metadata;
|
||||
|
||||
int err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->behavior.behavior_dev),
|
||||
&child_metadata);
|
||||
if (err < 0) {
|
||||
LOG_WRN("Failed to get the sticky key bound behavior parameter: %d", err);
|
||||
}
|
||||
|
||||
for (int s = 0; s < child_metadata.sets_len; s++) {
|
||||
const struct behavior_parameter_metadata_set *set = &child_metadata.sets[s];
|
||||
|
||||
if (set->param2_values_len > 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
*param_metadata = child_metadata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_driver_api behavior_sticky_key_driver_api = {
|
||||
.binding_pressed = on_sticky_key_binding_pressed,
|
||||
.binding_released = on_sticky_key_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = sticky_key_parameter_domains,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh);
|
||||
@@ -337,7 +369,7 @@ struct behavior_sticky_key_data {};
|
||||
static struct behavior_sticky_key_data behavior_sticky_key_data;
|
||||
|
||||
#define KP_INST(n) \
|
||||
static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
|
||||
static const struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
|
||||
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \
|
||||
.release_after_ms = DT_INST_PROP(n, release_after_ms), \
|
||||
.quick_release = DT_INST_PROP(n, quick_release), \
|
||||
|
||||
@@ -189,6 +189,9 @@ void behavior_tap_dance_timer_handler(struct k_work *item) {
|
||||
static const struct behavior_driver_api behavior_tap_dance_driver_api = {
|
||||
.binding_pressed = on_tap_dance_binding_pressed,
|
||||
.binding_released = on_tap_dance_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
static int tap_dance_position_state_changed_listener(const zmk_event_t *eh);
|
||||
|
||||
@@ -32,9 +32,34 @@ static int to_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata param_values[] = {
|
||||
{
|
||||
.display_name = "Layer",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
|
||||
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_LAYER_INDEX,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
|
||||
.param1_values = param_values,
|
||||
.param1_values_len = ARRAY_SIZE(param_values),
|
||||
}};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(param_metadata_set),
|
||||
.sets = param_metadata_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static const struct behavior_driver_api behavior_to_driver_api = {
|
||||
.binding_pressed = to_keymap_binding_pressed,
|
||||
.binding_released = to_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_to_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
|
||||
@@ -34,9 +34,34 @@ static int tog_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
static const struct behavior_parameter_value_metadata param_values[] = {
|
||||
{
|
||||
.display_name = "Layer",
|
||||
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
|
||||
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_LAYER_INDEX,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
|
||||
.param1_values = param_values,
|
||||
.param1_values_len = ARRAY_SIZE(param_values),
|
||||
}};
|
||||
|
||||
static const struct behavior_parameter_metadata metadata = {
|
||||
.sets_len = ARRAY_SIZE(param_metadata_set),
|
||||
.sets = param_metadata_set,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static const struct behavior_driver_api behavior_tog_driver_api = {
|
||||
.binding_pressed = tog_keymap_binding_pressed,
|
||||
.binding_released = tog_keymap_binding_released,
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
.parameter_metadata = &metadata,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
static const struct behavior_tog_config behavior_tog_config = {};
|
||||
|
||||
Reference in New Issue
Block a user