zmk/app/src/behaviors/behavior_backlight.c
Joel Spadin 36eda571b7 refactor(behaviors): Create a list to lookup behaviors
Added BEHAVIOR_DT_DEFINE() and BEHAVIOR_DT_INST_DEFINE(), which work
exactly like the DEVICE_*_DEFINE() macros, except they also register the
device as a behavior by adding a pointer to it to a memory section.

Added zmk_behavior_get_binding(), which works like device_get_binding()
except that it only searches the devices that have been registered as
behaviors. This ensures that behaviors cannot have name collisions with
other devices defined by the SoC, which will be important when we remove
the label property from behaviors so they are given their node names.

As an added benefit, this is faster since it searches a smaller list.
Some basic benchmark code I wrote indicates it takes 30-70% as long,
depending on where the behavior is in the list and whether the name
string is an exact pointer match.

From now on, behaviors should use BEHAVIOR_*_DEFINe() instead of
DEVICE_*_DEFINE(), and any code that looks up a behavior by name should
use zmk_behavior_get_binding() instead of device_get_binding().
2023-12-04 20:06:54 -06:00

97 lines
3 KiB
C

/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT zmk_behavior_backlight
#include <zephyr/device.h>
#include <drivers/behavior.h>
#include <zephyr/logging/log.h>
#include <dt-bindings/zmk/backlight.h>
#include <zmk/backlight.h>
#include <zmk/keymap.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
static int behavior_backlight_init(const struct device *dev) { return 0; }
static int
on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
case BL_TOG_CMD:
binding->param1 = zmk_backlight_is_on() ? BL_OFF_CMD : BL_ON_CMD;
break;
case BL_INC_CMD:
binding->param1 = BL_SET_CMD;
binding->param2 = zmk_backlight_calc_brt(1);
break;
case BL_DEC_CMD:
binding->param1 = BL_SET_CMD;
binding->param2 = zmk_backlight_calc_brt(-1);
break;
case BL_CYCLE_CMD:
binding->param1 = BL_SET_CMD;
binding->param2 = zmk_backlight_calc_brt_cycle();
break;
default:
return 0;
}
LOG_DBG("Backlight relative to absolute (%d/%d)", binding->param1, binding->param2);
return 0;
}
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
case BL_ON_CMD:
return zmk_backlight_on();
case BL_OFF_CMD:
return zmk_backlight_off();
case BL_TOG_CMD:
return zmk_backlight_toggle();
case BL_INC_CMD: {
uint8_t brt = zmk_backlight_calc_brt(1);
return zmk_backlight_set_brt(brt);
}
case BL_DEC_CMD: {
uint8_t brt = zmk_backlight_calc_brt(-1);
return zmk_backlight_set_brt(brt);
}
case BL_CYCLE_CMD: {
uint8_t brt = zmk_backlight_calc_brt_cycle();
return zmk_backlight_set_brt(brt);
}
case BL_SET_CMD:
return zmk_backlight_set_brt(binding->param2);
default:
LOG_ERR("Unknown backlight command: %d", binding->param1);
}
return -ENOTSUP;
}
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
return ZMK_BEHAVIOR_OPAQUE;
}
static const struct behavior_driver_api behavior_backlight_driver_api = {
.binding_convert_central_state_dependent_params =
on_keymap_binding_convert_central_state_dependent_params,
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
.locality = BEHAVIOR_LOCALITY_GLOBAL,
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_backlight_init, NULL, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_backlight_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */