Skip to content

Commit

Permalink
refactor(core): Move to stack allocated events.
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
petejohanson committed Sep 6, 2023
1 parent 7f9e9f8 commit a827778
Show file tree
Hide file tree
Showing 22 changed files with 158 additions and 134 deletions.
2 changes: 1 addition & 1 deletion app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ endmenu
endmenu

config HEAP_MEM_POOL_SIZE
default 8192
default 8192 if ZMK_DISPLAY

config KERNEL_BIN_NAME
default "zmk"
Expand Down
25 changes: 13 additions & 12 deletions app/include/zmk/event_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,24 @@ struct zmk_event_subscription {
zmk_event_t header; \
struct event_type data; \
}; \
struct event_type##_event *new_##event_type(struct event_type); \
struct event_type##_event new_##event_type(struct event_type); \
int raise_new_##event_type(struct event_type); \
struct event_type *as_##event_type(const zmk_event_t *eh); \
extern const struct zmk_event_type zmk_event_##event_type;

#define ZMK_EVENT_IMPL(event_type) \
const struct zmk_event_type zmk_event_##event_type = {.name = STRINGIFY(event_type)}; \
const struct zmk_event_type *zmk_event_ref_##event_type __used \
__attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
struct event_type##_event *new_##event_type(struct event_type data) { \
struct event_type##_event *ev = \
(struct event_type##_event *)k_malloc(sizeof(struct event_type##_event)); \
ev->header.event = &zmk_event_##event_type; \
ev->data = data; \
struct event_type##_event new_##event_type(struct event_type data) { \
struct event_type##_event ev = {.data = data}; \
ev.header.event = &zmk_event_##event_type; \
return ev; \
}; \
int raise_new_##event_type(struct event_type data) { \
struct event_type##_event ev = new_##event_type(data); \
return ZMK_EVENT_RAISE(ev); \
}; \
struct event_type *as_##event_type(const zmk_event_t *eh) { \
return (eh->event == &zmk_event_##event_type) ? &((struct event_type##_event *)eh)->data \
: NULL; \
Expand All @@ -68,17 +71,15 @@ struct zmk_event_subscription {
.listener = &zmk_listener_##mod, \
};

#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((zmk_event_t *)ev);
#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((zmk_event_t *)&ev);

#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
zmk_event_manager_raise_after((zmk_event_t *)ev, &zmk_listener_##mod);
zmk_event_manager_raise_after((zmk_event_t *)&ev, &zmk_listener_##mod);

#define ZMK_EVENT_RAISE_AT(ev, mod) \
zmk_event_manager_raise_at((zmk_event_t *)ev, &zmk_listener_##mod);

#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((zmk_event_t *)ev);
zmk_event_manager_raise_at((zmk_event_t *)&ev, &zmk_listener_##mod);

#define ZMK_EVENT_FREE(ev) k_free((void *)ev);
#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((zmk_event_t *)&ev);

int zmk_event_manager_raise(zmk_event_t *event);
int zmk_event_manager_raise_after(zmk_event_t *event, const struct zmk_listener *listener);
Expand Down
15 changes: 7 additions & 8 deletions app/include/zmk/events/keycode_state_changed.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct zmk_keycode_state_changed {

ZMK_EVENT_DECLARE(zmk_keycode_state_changed);

static inline struct zmk_keycode_state_changed_event *
static inline struct zmk_keycode_state_changed
zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
uint16_t page = ZMK_HID_USAGE_PAGE(encoded);
uint16_t id = ZMK_HID_USAGE_ID(encoded);
Expand All @@ -38,11 +38,10 @@ zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t t
implicit_modifiers = SELECT_MODS(encoded);
}

return new_zmk_keycode_state_changed(
(struct zmk_keycode_state_changed){.usage_page = page,
.keycode = id,
.implicit_modifiers = implicit_modifiers,
.explicit_modifiers = explicit_modifiers,
.state = pressed,
.timestamp = timestamp});
return (struct zmk_keycode_state_changed){.usage_page = page,
.keycode = id,
.implicit_modifiers = implicit_modifiers,
.explicit_modifiers = explicit_modifiers,
.state = pressed,
.timestamp = timestamp};
}
4 changes: 2 additions & 2 deletions app/include/zmk/events/layer_state_changed.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ struct zmk_layer_state_changed {

ZMK_EVENT_DECLARE(zmk_layer_state_changed);

static inline struct zmk_layer_state_changed_event *create_layer_state_changed(uint8_t layer,
bool state) {
static inline struct zmk_layer_state_changed_event create_layer_state_changed(uint8_t layer,
bool state) {
return new_zmk_layer_state_changed((struct zmk_layer_state_changed){
.layer = layer, .state = state, .timestamp = k_uptime_get()});
}
4 changes: 2 additions & 2 deletions app/src/activity.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ static uint32_t activity_last_uptime;
#endif

int raise_event() {
return ZMK_EVENT_RAISE(new_zmk_activity_state_changed(
(struct zmk_activity_state_changed){.state = activity_state}));
return raise_new_zmk_activity_state_changed(
(struct zmk_activity_state_changed){.state = activity_state});
}

int set_state(enum zmk_activity_state state) {
Expand Down
4 changes: 2 additions & 2 deletions app/src/battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ static int zmk_battery_update(const struct device *battery) {
return rc;
}

rc = ZMK_EVENT_RAISE(new_zmk_battery_state_changed(
(struct zmk_battery_state_changed){.state_of_charge = last_state_of_charge}));
rc = raise_new_zmk_battery_state_changed(
(struct zmk_battery_state_changed){.state_of_charge = last_state_of_charge});
}

return rc;
Expand Down
88 changes: 59 additions & 29 deletions app/src/behaviors/behavior_hold_tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -119,33 +136,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) {
memcpy(&captured_events[i], &data, sizeof(struct captured_event));
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;
Expand Down Expand Up @@ -181,25 +197,33 @@ 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];
if (captured_event.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 (captured_event.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);
}
}

Expand Down Expand Up @@ -619,7 +643,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,
Expand All @@ -629,7 +653,10 @@ 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;
capture.tag = ET_POS_CHANGED;
memcpy(&capture.data.position, eh, sizeof(struct zmk_position_state_changed_event));
capture_event(capture);
decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
return ZMK_EV_EVENT_CAPTURED;
}
Expand All @@ -656,7 +683,10 @@ 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;
capture.tag = ET_CODE_CHANGED;
memcpy(&capture.data.keycode, eh, sizeof(struct zmk_keycode_state_changed_event));
capture_event(capture);
return ZMK_EV_EVENT_CAPTURED;
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/behaviors/behavior_key_press.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_new_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_new_zmk_keycode_state_changed(
zmk_keycode_state_changed_from_encoded(binding->param1, false, event.timestamp));
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/behaviors/behavior_key_repeat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_new_zmk_keycode_state_changed(data->current_keycode_pressed);

return ZMK_BEHAVIOR_OPAQUE;
}
Expand All @@ -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_new_zmk_keycode_state_changed(data->current_keycode_pressed);
return ZMK_BEHAVIOR_OPAQUE;
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/behaviors/behavior_key_toggle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_new_zmk_keycode_state_changed(
zmk_keycode_state_changed_from_encoded(binding->param1, !pressed, event.timestamp));
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/behaviors/behavior_sticky_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,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);
Expand Down
4 changes: 2 additions & 2 deletions app/src/ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ static bt_addr_le_t peripheral_addrs[ZMK_SPLIT_BLE_PERIPHERAL_COUNT];
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */

static void raise_profile_changed_event() {
ZMK_EVENT_RAISE(new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){
.index = active_profile, .profile = &profiles[active_profile]}));
raise_new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){
.index = active_profile, .profile = &profiles[active_profile]});
}

static void raise_profile_changed_event_callback(struct k_work *work) {
Expand Down
Loading

0 comments on commit a827778

Please sign in to comment.