refactor(core): Move to stack allocated events.

* Move to local/stack allocated event API that doesn't require
  dynamic allocation/freeing.
* Disable heap, we no longer use alloc/free unless using LVGL.
* Tons of refactors all over to account for the new event approach.
This commit is contained in:
Peter Johanson
2023-03-23 08:56:02 +00:00
committed by Pete Johanson
parent 50e473276f
commit 33209dee1d
24 changed files with 172 additions and 147 deletions

View File

@@ -88,7 +88,24 @@ struct active_hold_tap {
struct active_hold_tap *undecided_hold_tap = NULL;
struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {};
// We capture most position_state_changed events and some modifiers_state_changed events.
const zmk_event_t *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
enum captured_event_tag {
ET_NONE,
ET_POS_CHANGED,
ET_CODE_CHANGED,
};
union captured_event_data {
struct zmk_position_state_changed_event position;
struct zmk_keycode_state_changed_event keycode;
};
struct captured_event {
enum captured_event_tag tag;
union captured_event_data data;
};
struct captured_event captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
// Keep track of which key was tapped most recently for the standard, if it is a hold-tap
// a position, will be given, if not it will just be INT32_MIN
@@ -122,33 +139,32 @@ static bool is_quick_tap(struct active_hold_tap *hold_tap) {
}
}
static int capture_event(const zmk_event_t *event) {
static int capture_event(struct captured_event *data) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
if (captured_events[i] == NULL) {
captured_events[i] = event;
if (captured_events[i].tag == ET_NONE) {
captured_events[i] = *data;
return 0;
}
}
return -ENOMEM;
}
static struct zmk_position_state_changed *find_captured_keydown_event(uint32_t position) {
struct zmk_position_state_changed *last_match = NULL;
static bool have_captured_keydown_event(uint32_t position) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
const zmk_event_t *eh = captured_events[i];
if (eh == NULL) {
return last_match;
struct captured_event *ev = &captured_events[i];
if (ev->tag == ET_NONE) {
return false;
}
struct zmk_position_state_changed *position_event = as_zmk_position_state_changed(eh);
if (position_event == NULL) {
if (ev->tag != ET_POS_CHANGED) {
continue;
}
if (position_event->position == position && position_event->state) {
last_match = position_event;
if (ev->data.position.data.position == position && ev->data.position.data.state) {
return true;
}
}
return last_match;
return false;
}
const struct zmk_listener zmk_listener_behavior_hold_tap;
@@ -184,25 +200,35 @@ static void release_captured_events() {
// [k1_down, k1_up, null, null, null, ...]
// now mt2 will start releasing it's own captured positions.
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
const zmk_event_t *captured_event = captured_events[i];
if (captured_event == NULL) {
struct captured_event *captured_event = &captured_events[i];
enum captured_event_tag tag = captured_event->tag;
if (tag == ET_NONE) {
return;
}
captured_events[i] = NULL;
captured_events[i].tag = ET_NONE;
if (undecided_hold_tap != NULL) {
k_msleep(10);
}
struct zmk_position_state_changed *position_event;
struct zmk_keycode_state_changed *modifier_event;
if ((position_event = as_zmk_position_state_changed(captured_event)) != NULL) {
LOG_DBG("Releasing key position event for position %d %s", position_event->position,
(position_event->state ? "pressed" : "released"));
} else if ((modifier_event = as_zmk_keycode_state_changed(captured_event)) != NULL) {
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode,
(modifier_event->state ? "pressed" : "released"));
switch (tag) {
case ET_CODE_CHANGED:
LOG_DBG("Releasing mods changed event 0x%02X %s",
captured_event->data.keycode.data.keycode,
(captured_event->data.keycode.data.state ? "pressed" : "released"));
ZMK_EVENT_RAISE_AT(captured_event->data.keycode, behavior_hold_tap);
break;
case ET_POS_CHANGED:
LOG_DBG("Releasing key position event for position %d %s",
captured_event->data.position.data.position,
(captured_event->data.position.data.state ? "pressed" : "released"));
ZMK_EVENT_RAISE_AT(captured_event->data.position, behavior_hold_tap);
break;
default:
LOG_ERR("Unhandled captured event type");
break;
}
ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap);
}
}
@@ -622,7 +648,7 @@ static int position_state_changed_listener(const zmk_event_t *eh) {
return ZMK_EV_EVENT_BUBBLE;
}
if (!ev->state && find_captured_keydown_event(ev->position) == NULL) {
if (!ev->state && !have_captured_keydown_event(ev->position)) {
// no keydown event has been captured, let it bubble.
// we'll catch modifiers later in modifier_state_changed_listener
LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position,
@@ -632,7 +658,11 @@ static int position_state_changed_listener(const zmk_event_t *eh) {
LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position,
ev->state ? "down" : "up");
capture_event(eh);
struct captured_event capture = {
.tag = ET_POS_CHANGED,
.data = {.position = copy_raised_zmk_position_state_changed(ev)},
};
capture_event(&capture);
decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
return ZMK_EV_EVENT_CAPTURED;
}
@@ -659,7 +689,9 @@ static int keycode_state_changed_listener(const zmk_event_t *eh) {
// if a undecided_hold_tap is active.
LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode,
ev->state ? "down" : "up");
capture_event(eh);
struct captured_event capture = {
.tag = ET_CODE_CHANGED, .data = {.keycode = copy_raised_zmk_keycode_state_changed(ev)}};
capture_event(&capture);
return ZMK_EV_EVENT_CAPTURED;
}

View File

@@ -21,14 +21,14 @@ static int behavior_key_press_init(const struct device *dev) { return 0; };
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
return ZMK_EVENT_RAISE(
return raise_zmk_keycode_state_changed(
zmk_keycode_state_changed_from_encoded(binding->param1, true, event.timestamp));
}
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
return ZMK_EVENT_RAISE(
return raise_zmk_keycode_state_changed(
zmk_keycode_state_changed_from_encoded(binding->param1, false, event.timestamp));
}

View File

@@ -43,7 +43,7 @@ static int on_key_repeat_binding_pressed(struct zmk_behavior_binding *binding,
sizeof(struct zmk_keycode_state_changed));
data->current_keycode_pressed.timestamp = k_uptime_get();
ZMK_EVENT_RAISE(new_zmk_keycode_state_changed(data->current_keycode_pressed));
raise_zmk_keycode_state_changed(data->current_keycode_pressed);
return ZMK_BEHAVIOR_OPAQUE;
}
@@ -60,7 +60,7 @@ static int on_key_repeat_binding_released(struct zmk_behavior_binding *binding,
data->current_keycode_pressed.timestamp = k_uptime_get();
data->current_keycode_pressed.state = false;
ZMK_EVENT_RAISE(new_zmk_keycode_state_changed(data->current_keycode_pressed));
raise_zmk_keycode_state_changed(data->current_keycode_pressed);
return ZMK_BEHAVIOR_OPAQUE;
}

View File

@@ -23,7 +23,7 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
bool pressed = zmk_hid_is_pressed(binding->param1);
return ZMK_EVENT_RAISE(
return raise_zmk_keycode_state_changed(
zmk_keycode_state_changed_from_encoded(binding->param1, !pressed, event.timestamp));
}

View File

@@ -24,15 +24,15 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
return ZMK_EVENT_RAISE(
zmk_mouse_button_state_changed_from_encoded(binding->param1, true, event.timestamp));
return raise_zmk_mouse_button_state_changed_from_encoded(binding->param1, true,
event.timestamp);
}
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
return ZMK_EVENT_RAISE(
zmk_mouse_button_state_changed_from_encoded(binding->param1, false, event.timestamp));
return raise_zmk_mouse_button_state_changed_from_encoded(binding->param1, false,
event.timestamp);
}
static const struct behavior_driver_api behavior_mouse_key_press_driver_api = {

View File

@@ -236,7 +236,9 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) {
if (sticky_key->config->quick_release) {
// immediately release the sticky key after the key press is handled.
if (!event_reraised) {
ZMK_EVENT_RAISE_AFTER(eh, behavior_sticky_key);
struct zmk_keycode_state_changed_event dupe_ev;
memcpy(&dupe_ev, eh, sizeof(struct zmk_keycode_state_changed_event));
ZMK_EVENT_RAISE_AFTER(dupe_ev, behavior_sticky_key);
event_reraised = true;
}
release_sticky_key_behavior(sticky_key, ev_copy.timestamp);