mirror of
https://github.com/zmkfirmware/zmk.git
synced 2026-03-19 20:45:18 -05:00
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
@@ -23,6 +23,39 @@
|
||||
* (Internal use only.)
|
||||
*/
|
||||
|
||||
struct behavior_parameter_value_metadata {
|
||||
char *display_name;
|
||||
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
} range;
|
||||
};
|
||||
|
||||
enum {
|
||||
BEHAVIOR_PARAMETER_VALUE_TYPE_NIL = 0,
|
||||
BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE = 1,
|
||||
BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE = 2,
|
||||
BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE = 3,
|
||||
BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX = 4,
|
||||
} type;
|
||||
};
|
||||
|
||||
struct behavior_parameter_metadata_set {
|
||||
size_t param1_values_len;
|
||||
const struct behavior_parameter_value_metadata *param1_values;
|
||||
|
||||
size_t param2_values_len;
|
||||
const struct behavior_parameter_value_metadata *param2_values;
|
||||
};
|
||||
|
||||
struct behavior_parameter_metadata {
|
||||
size_t sets_len;
|
||||
const struct behavior_parameter_metadata_set *sets;
|
||||
};
|
||||
|
||||
enum behavior_sensor_binding_process_mode {
|
||||
BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER,
|
||||
BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD,
|
||||
@@ -37,6 +70,10 @@ typedef int (*behavior_sensor_keymap_binding_accept_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]);
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
typedef int (*behavior_get_parameter_metadata_t)(
|
||||
const struct device *behavior, struct behavior_parameter_metadata *param_metadata);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
enum behavior_locality {
|
||||
BEHAVIOR_LOCALITY_CENTRAL,
|
||||
@@ -51,23 +88,54 @@ __subsystem struct behavior_driver_api {
|
||||
behavior_keymap_binding_callback_t binding_released;
|
||||
behavior_sensor_keymap_binding_accept_data_callback_t sensor_binding_accept_data;
|
||||
behavior_sensor_keymap_binding_process_callback_t sensor_binding_process;
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
behavior_get_parameter_metadata_t get_parameter_metadata;
|
||||
const struct behavior_parameter_metadata *parameter_metadata;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
struct zmk_behavior_metadata {
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
const char *display_name;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
};
|
||||
|
||||
struct zmk_behavior_ref {
|
||||
const struct device *device;
|
||||
const struct zmk_behavior_metadata metadata;
|
||||
};
|
||||
|
||||
#define ZMK_BEHAVIOR_REF_DT_NAME(node_id) _CONCAT(zmk_behavior_, DEVICE_DT_NAME_GET(node_id))
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
#define ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id) \
|
||||
{ .display_name = DT_PROP_OR(node_id, display_name, DEVICE_DT_NAME(node_id)), }
|
||||
|
||||
#else
|
||||
|
||||
#define ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id) \
|
||||
{}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
#define ZMK_BEHAVIOR_REF_INITIALIZER(node_id, _dev) \
|
||||
{ .device = _dev, .metadata = ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id), }
|
||||
|
||||
#define ZMK_BEHAVIOR_REF_DEFINE(name, node_id, _dev) \
|
||||
static const STRUCT_SECTION_ITERABLE(zmk_behavior_ref, name) = \
|
||||
ZMK_BEHAVIOR_REF_INITIALIZER(node_id, _dev)
|
||||
|
||||
#define ZMK_BEHAVIOR_REF_DT_DEFINE(node_id) \
|
||||
ZMK_BEHAVIOR_REF_DEFINE(ZMK_BEHAVIOR_REF_DT_NAME(node_id), node_id, DEVICE_DT_GET(node_id))
|
||||
|
||||
/**
|
||||
* Registers @p node_id as a behavior.
|
||||
*/
|
||||
#define BEHAVIOR_DEFINE(node_id) \
|
||||
static const STRUCT_SECTION_ITERABLE(zmk_behavior_ref, \
|
||||
_CONCAT(zmk_behavior_, DEVICE_DT_NAME_GET(node_id))) = { \
|
||||
.device = DEVICE_DT_GET(node_id), \
|
||||
}
|
||||
#define BEHAVIOR_DEFINE(node_id) ZMK_BEHAVIOR_REF_DT_DEFINE(node_id)
|
||||
|
||||
/**
|
||||
* @brief Like DEVICE_DT_DEFINE(), but also registers the device as a behavior.
|
||||
@@ -89,6 +157,52 @@ struct zmk_behavior_ref {
|
||||
DEVICE_DT_INST_DEFINE(inst, __VA_ARGS__); \
|
||||
BEHAVIOR_DEFINE(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Validate a given behavior binding is valid, including parameter validation
|
||||
* if the metadata feature is enablued.
|
||||
*
|
||||
* @param binding The behavior binding to validate.
|
||||
*
|
||||
* @retval 0 if the passed in binding is valid.
|
||||
* @retval -ENODEV if the binding references a non-existant behavior.
|
||||
* @retval -EINVAL if parameters are not valid for the behavior metadata.
|
||||
*/
|
||||
int zmk_behavior_validate_binding(const struct zmk_behavior_binding *binding);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
int zmk_behavior_get_empty_param_metadata(const struct device *dev,
|
||||
struct behavior_parameter_metadata *metadata);
|
||||
|
||||
/**
|
||||
* @brief Validate a given behavior parameters match the behavior metadata.
|
||||
*
|
||||
* @param metadata The behavior metadata to validate against
|
||||
* @param param1 The first parameter value
|
||||
* @param param2 The second parameter value
|
||||
*
|
||||
* @retval 0 if the passed in parameters are valid.
|
||||
* @retval -ENODEV if metadata is NULL.
|
||||
* @retval -EINVAL if parameters are not valid for the metadata.
|
||||
*/
|
||||
int zmk_behavior_check_params_match_metadata(const struct behavior_parameter_metadata *metadata,
|
||||
uint32_t param1, uint32_t param2);
|
||||
/**
|
||||
* @brief Validate a given behavior parameter matches the behavior metadata parameter values.
|
||||
*
|
||||
* @param values The values to validate against
|
||||
* @param values_len How many values to check
|
||||
* @param param The value to check.
|
||||
*
|
||||
* @retval 0 if the passed in parameter is valid.
|
||||
* @retval -ENODEV if values is NULL.
|
||||
* @retval -EINVAL if parameter is not valid for the value metadata.
|
||||
*/
|
||||
int zmk_behavior_validate_param_values(const struct behavior_parameter_value_metadata *values,
|
||||
size_t values_len, uint32_t param);
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
/**
|
||||
* Syscall wrapper for zmk_behavior_get_binding().
|
||||
*
|
||||
@@ -120,6 +234,40 @@ static inline int z_impl_behavior_keymap_binding_convert_central_state_dependent
|
||||
return api->binding_convert_central_state_dependent_params(binding, event);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
/**
|
||||
* @brief Determine where the behavior should be run
|
||||
* @param behavior Pointer to the device structure for the driver instance.
|
||||
*
|
||||
* @retval Zero if successful.
|
||||
* @retval Negative errno code if failure.
|
||||
*/
|
||||
__syscall int behavior_get_parameter_metadata(const struct device *behavior,
|
||||
struct behavior_parameter_metadata *param_metadata);
|
||||
|
||||
static inline int
|
||||
z_impl_behavior_get_parameter_metadata(const struct device *behavior,
|
||||
struct behavior_parameter_metadata *param_metadata) {
|
||||
if (behavior == NULL || param_metadata == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)behavior->api;
|
||||
|
||||
if (api->get_parameter_metadata) {
|
||||
return api->get_parameter_metadata(behavior, param_metadata);
|
||||
} else if (api->parameter_metadata) {
|
||||
*param_metadata = *api->parameter_metadata;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
|
||||
|
||||
/**
|
||||
* @brief Determine where the behavior should be run
|
||||
* @param behavior Pointer to the device structure for the driver instance.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define ZMK_BEHAVIOR_TRANSPARENT 1
|
||||
|
||||
struct zmk_behavior_binding {
|
||||
char *behavior_dev;
|
||||
const char *behavior_dev;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user