Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional binding_convert_central_state_dependent_params callback to the behavior driver API. #626

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions app/include/drivers/behavior.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_bin
int64_t timestamp);

__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;
Expand All @@ -35,6 +36,30 @@ __subsystem struct behavior_driver_api {
* @endcond
*/

/**
* @brief Handle the keymap binding which needs to be converted from relative "toggle" to absolute
* "turn on"
* @param binding Pointer to the details so of the binding
* @param event The event that triggered use of the binding
*
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
__syscall int behavior_keymap_binding_convert_central_state_dependent_params(
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event);

static inline int z_impl_behavior_keymap_binding_convert_central_state_dependent_params(
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) {
const struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api;

if (api->binding_convert_central_state_dependent_params == NULL) {
return 0;
}

return api->binding_convert_central_state_dependent_params(binding, event);
}

/**
* @brief Handle the keymap binding being pressed
* @param dev Pointer to the device structure for the driver instance.
Expand Down
29 changes: 17 additions & 12 deletions app/include/dt-bindings/zmk/rgb.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
*/

#define RGB_TOG_CMD 0
#define RGB_HUI_CMD 1
#define RGB_HUD_CMD 2
#define RGB_SAI_CMD 3
#define RGB_SAD_CMD 4
#define RGB_BRI_CMD 5
#define RGB_BRD_CMD 6
#define RGB_SPI_CMD 7
#define RGB_SPD_CMD 8
#define RGB_EFF_CMD 9
#define RGB_EFR_CMD 10
#define RGB_COLOR_HSB_CMD 11
#define RGB_ON_CMD 1
#define RGB_OFF_CMD 2
#define RGB_HUI_CMD 3
#define RGB_HUD_CMD 4
#define RGB_SAI_CMD 5
#define RGB_SAD_CMD 6
#define RGB_BRI_CMD 7
#define RGB_BRD_CMD 8
#define RGB_SPI_CMD 9
#define RGB_SPD_CMD 10
#define RGB_EFF_CMD 11
#define RGB_EFR_CMD 12
#define RGB_COLOR_HSB_CMD 13

#define RGB_TOG RGB_TOG_CMD 0
#define RGB_ON RGB_ON_CMD 0
#define RGB_OFF RGB_OFF_CMD 0
#define RGB_HUI RGB_HUI_CMD 0
#define RGB_HUD RGB_HUD_CMD 0
#define RGB_SAI RGB_SAI_CMD 0
Expand All @@ -28,5 +32,6 @@
#define RGB_SPD RGB_SPD_CMD 0
#define RGB_EFF RGB_EFF_CMD 0
#define RGB_EFR RGB_EFR_CMD 0
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD(((h) << 16) + ((s) << 8) + (v))
#define RGB_COLOR_HSB_VAL(h, s, v) (((h) << 16) + ((s) << 8) + (v))
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD##(RGB_COLOR_HSB_VAL(h, s, v))
#define RGB_COLOR_HSV RGB_COLOR_HSB
14 changes: 13 additions & 1 deletion app/include/zmk/rgb_underglow.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,22 @@

#pragma once

struct zmk_led_hsb {
uint16_t h;
uint8_t s;
uint8_t b;
};

int zmk_rgb_underglow_toggle();
int zmk_rgb_underglow_get_state(bool *state);
int zmk_rgb_underglow_on();
int zmk_rgb_underglow_off();
int zmk_rgb_underglow_cycle_effect(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction);
int zmk_rgb_underglow_change_hue(int direction);
int zmk_rgb_underglow_change_sat(int direction);
int zmk_rgb_underglow_change_brt(int direction);
int zmk_rgb_underglow_change_spd(int direction);
int zmk_rgb_underglow_set_hsb(uint16_t hue, uint8_t saturation, uint8_t brightness);
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color);
18 changes: 18 additions & 0 deletions app/src/behaviors/behavior_ext_power.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)

static int
on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
const struct device *ext_power = device_get_binding("EXT_POWER");
if (ext_power == NULL) {
LOG_ERR("Unable to retrieve ext_power device: %d", binding->param1);
return -EIO;
}

if (binding->param1 == EXT_POWER_TOGGLE_CMD) {
binding->param1 = ext_power_get(ext_power) > 0 ? EXT_POWER_OFF_CMD : EXT_POWER_ON_CMD;
}

return 0;
}

static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
const struct device *ext_power = device_get_binding("EXT_POWER");
Expand Down Expand Up @@ -51,6 +67,8 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
static int behavior_ext_power_init(const struct device *dev) { return 0; };

static const struct behavior_driver_api behavior_ext_power_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,
};
Expand Down
77 changes: 75 additions & 2 deletions app/src/behaviors/behavior_rgb_underglow.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,81 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

static int behavior_rgb_underglow_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 RGB_TOG_CMD: {
bool state;
int err = zmk_rgb_underglow_get_state(&state);
if (err) {
LOG_ERR("Failed to get RGB underglow state (err %d)", err);
return err;
}

binding->param1 = state ? RGB_OFF_CMD : RGB_ON_CMD;
break;
}
case RGB_BRI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_BRD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(-1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_HUI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_HUD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(-1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_SAI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_SAD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(-1);

binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
default:
return 0;
}

LOG_DBG("RGB relative convert 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 RGB_TOG_CMD:
return zmk_rgb_underglow_toggle();
case RGB_ON_CMD:
return zmk_rgb_underglow_on();
case RGB_OFF_CMD:
return zmk_rgb_underglow_off();
case RGB_HUI_CMD:
return zmk_rgb_underglow_change_hue(1);
case RGB_HUD_CMD:
Expand All @@ -46,8 +116,9 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
case RGB_EFR_CMD:
return zmk_rgb_underglow_cycle_effect(-1);
case RGB_COLOR_HSB_CMD:
return zmk_rgb_underglow_set_hsb((binding->param2 >> 16) & 0xFFFF,
(binding->param2 >> 8) & 0xFF, binding->param2 & 0xFF);
return zmk_rgb_underglow_set_hsb((struct zmk_led_hsb){.h = (binding->param2 >> 16) & 0xFFFF,
.s = (binding->param2 >> 8) & 0xFF,
.b = binding->param2 & 0xFF});
}

return -ENOTSUP;
Expand All @@ -59,6 +130,8 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
}

static const struct behavior_driver_api behavior_rgb_underglow_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,
};
Expand Down
18 changes: 13 additions & 5 deletions app/src/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ const char *zmk_keymap_layer_label(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];
// We want to make a copy of this, since it may be converted from
// relative to absolute before being invoked
struct zmk_behavior_binding binding = zmk_keymap[layer][position];
const struct device *behavior;
struct zmk_behavior_binding_event event = {
.layer = layer,
Expand All @@ -162,19 +164,25 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed,
};

LOG_DBG("layer: %d position: %d, binding name: %s", layer, position,
log_strdup(binding->behavior_dev));
log_strdup(binding.behavior_dev));

behavior = device_get_binding(binding->behavior_dev);
behavior = device_get_binding(binding.behavior_dev);

if (!behavior) {
LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
return 1;
}

int err = behavior_keymap_binding_convert_central_state_dependent_params(&binding, event);
if (err) {
LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err);
return err;
}

if (pressed) {
return behavior_keymap_binding_pressed(binding, event);
return behavior_keymap_binding_pressed(&binding, event);
} else {
return behavior_keymap_binding_released(binding, event);
return behavior_keymap_binding_released(&binding, event);
}
}

Expand Down
Loading