Skip to content

Commit

Permalink
initial implementation for modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
okke-formsma authored and petejohanson committed Nov 3, 2020
1 parent a9e729b commit 4f258ef
Show file tree
Hide file tree
Showing 77 changed files with 597 additions and 229 deletions.
30 changes: 21 additions & 9 deletions app/include/dt-bindings/zmk/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#define USAGE_KEYPAD 0x07
Expand Down Expand Up @@ -144,11 +143,24 @@
#define M_VOLU 0xE9
#define M_VOLD 0xEA

#define MOD_LCTL (1 << 0x00)
#define MOD_LSFT (1 << 0x01)
#define MOD_LALT (1 << 0x02)
#define MOD_LGUI (1 << 0x03)
#define MOD_RCTL (1 << 0x04)
#define MOD_RSFT (1 << 0x05)
#define MOD_RALT (1 << 0x06)
#define MOD_RGUI (1 << 0x07)
#define MOD_LCTL 0x01
#define MOD_LSFT 0x02
#define MOD_LALT 0x04
#define MOD_LGUI 0x08
#define MOD_RCTL 0x10
#define MOD_RSFT 0x20
#define MOD_RALT 0x40
#define MOD_RGUI 0x80

#define SELECT_MODS(keycode) (keycode >> 24)
#define STRIP_MODS(keycode) (keycode & ~(0xFF << 24))
#define APPLY_MODS(mods, keycode) (mods << 24 | keycode)

#define LC(keycode) APPLY_MODS(MOD_LCTL, keycode)
#define LS(keycode) APPLY_MODS(MOD_LSFT, keycode)
#define LA(keycode) APPLY_MODS(MOD_LALT, keycode)
#define LG(keycode) APPLY_MODS(MOD_LGUI, keycode)
#define RC(keycode) APPLY_MODS(MOD_RCTL, keycode)
#define RS(keycode) APPLY_MODS(MOD_RSFT, keycode)
#define RA(keycode) APPLY_MODS(MOD_RALT, keycode)
#define RG(keycode) APPLY_MODS(MOD_RGUI, keycode)
10 changes: 6 additions & 4 deletions app/include/zmk/events/keycode-state-changed.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
#pragma once

#include <zephyr.h>
#include <dt-bindings/zmk/keys.h>
#include <zmk/event-manager.h>

struct keycode_state_changed {
struct zmk_event_header header;
u8_t usage_page;
u32_t keycode;
u8_t implicit_modifiers;
bool state;
};

ZMK_EVENT_DECLARE(keycode_state_changed);

inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_page, u32_t keycode,
bool state) {
static inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_page, u32_t keycode, bool state) {
struct keycode_state_changed *ev = new_keycode_state_changed();
ev->usage_page = usage_page;
ev->keycode = keycode;
ev->keycode = STRIP_MODS(keycode);
ev->implicit_modifiers = SELECT_MODS(keycode);
ev->state = state;
return ev;
}
}
4 changes: 2 additions & 2 deletions app/include/zmk/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ struct zmk_hid_consumer_report {

int zmk_hid_register_mod(zmk_mod modifier);
int zmk_hid_unregister_mod(zmk_mod modifier);
int zmk_hid_register_mods(zmk_mod_flags modifiers);
int zmk_hid_unregister_mods(zmk_mod_flags modifiers);
int zmk_hid_implicit_modifiers_press(zmk_mod_flags implicit_modifiers);
int zmk_hid_implicit_modifiers_release();
int zmk_hid_keypad_press(zmk_key key);
int zmk_hid_keypad_release(zmk_key key);
void zmk_hid_keypad_clear();
Expand Down
6 changes: 3 additions & 3 deletions app/src/behaviors/behavior_hold_tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <device.h>
#include <drivers/behavior.h>
#include <dt-bindings/zmk/keys.h>
#include <logging/log.h>
#include <zmk/behavior.h>
#include <zmk/matrix.h>
Expand All @@ -16,7 +17,6 @@
#include <zmk/events/position-state-changed.h>
#include <zmk/events/keycode-state-changed.h>
#include <zmk/events/modifiers-state-changed.h>
#include <zmk/hid.h>
#include <zmk/behavior.h>

LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
Expand Down Expand Up @@ -427,7 +427,7 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) {
return ZMK_EV_EVENT_CAPTURED;
}

static bool is_mod(struct keycode_state_changed *ev) {
static inline bool only_mods(struct keycode_state_changed *ev) {
return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
}

Expand All @@ -440,7 +440,7 @@ static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
return 0;
}

if (!is_mod(ev)) {
if (!only_mods(ev)) {
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
return 0;
}
Expand Down
49 changes: 37 additions & 12 deletions app/src/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,44 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

#include <zmk/hid.h>
#include <dt-bindings/zmk/keys.h>

static struct zmk_hid_keypad_report kp_report = {
.report_id = 1, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};

static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};

#define _TOGGLE_MOD(mod, state) \
if (modifier > MOD_RGUI) { \
return -EINVAL; \
} \
WRITE_BIT(kp_report.body.modifiers, mod, state); \
return 0;
// Keep track of how often a modifier was pressed.
// Only release the modifier if the count is 0.
static int explicit_modifier_counts[8] = {0, 0, 0, 0, 0, 0, 0, 0};
static zmk_mod_flags explicit_modifiers = 0;

int zmk_hid_register_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, true); }
int zmk_hid_unregister_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, false); }
#define SET_MODIFIERS(mods) \
{ \
kp_report.body.modifiers = mods; \
LOG_DBG("Modifiers set to 0x%02X", kp_report.body.modifiers); \
}

int zmk_hid_register_mods(zmk_mod_flags modifiers) {
kp_report.body.modifiers |= modifiers;
int zmk_hid_register_mod(zmk_mod modifier) {
explicit_modifier_counts[modifier]++;
LOG_DBG("Modifier %d count %d", modifier, explicit_modifier_counts[modifier]);
WRITE_BIT(explicit_modifiers, modifier, true);
SET_MODIFIERS(explicit_modifiers);
return 0;
}

int zmk_hid_unregister_mods(zmk_mod_flags modifiers) {
kp_report.body.modifiers &= ~modifiers;
int zmk_hid_unregister_mod(zmk_mod modifier) {
if (explicit_modifier_counts[modifier] <= 0) {
LOG_ERR("Tried to unregister modifier %d too often", modifier);
return -EINVAL;
}
explicit_modifier_counts[modifier]--;
LOG_DBG("Modifier %d count: %d", modifier, explicit_modifier_counts[modifier]);
if (explicit_modifier_counts[modifier] == 0) {
LOG_DBG("Modifier %d released", modifier);
WRITE_BIT(explicit_modifiers, modifier, false);
}
SET_MODIFIERS(explicit_modifiers);
return 0;
}

Expand All @@ -52,6 +67,16 @@ int zmk_hid_unregister_mods(zmk_mod_flags modifiers) {
break; \
}

int zmk_hid_implicit_modifiers_press(zmk_mod_flags implicit_modifiers) {
SET_MODIFIERS(explicit_modifiers | implicit_modifiers);
return 0;
}

int zmk_hid_implicit_modifiers_release() {
SET_MODIFIERS(explicit_modifiers);
return 0;
}

int zmk_hid_keypad_press(zmk_key code) {
if (code >= LCTL && code <= RGUI) {
return zmk_hid_register_mod(code - LCTL);
Expand Down
51 changes: 18 additions & 33 deletions app/src/hid_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h>
#include <zmk/endpoints.h>

static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode) {
static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode,
zmk_mod_flags implicit_modifiers) {
int err;
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);

LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode,
implicit_modifiers);
switch (usage_page) {
case USAGE_KEYPAD:
err = zmk_hid_keypad_press(keycode);
Expand All @@ -35,14 +36,15 @@ static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode) {
}
break;
}

zmk_hid_implicit_modifiers_press(implicit_modifiers);
return zmk_endpoints_send_report(usage_page);
}

static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode) {
static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode,
zmk_mod_flags implicit_modifiers) {
int err;
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);

LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode,
implicit_modifiers);
switch (usage_page) {
case USAGE_KEYPAD:
err = zmk_hid_keypad_release(keycode);
Expand All @@ -57,44 +59,27 @@ static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode) {
LOG_ERR("Unable to release keycode");
return err;
}
break;
}
// There is a minor issue with this code.
// If LC(A) is pressed, then LS(B), then LC(A) is released, the shift for B will be released
// prematurely. This causes if LS(B) to repeat like Bbbbbbbb when pressed for a long time.
// Solving this would require keeping track of which key's implicit modifiers are currently
// active and only releasing modifiers at that time.
zmk_hid_implicit_modifiers_release();
return zmk_endpoints_send_report(usage_page);
}

static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers) {
LOG_DBG("modifiers %d", modifiers);

zmk_hid_register_mods(modifiers);
return zmk_endpoints_send_report(USAGE_KEYPAD);
}

static int hid_listener_modifiers_released(zmk_mod_flags modifiers) {
LOG_DBG("modifiers %d", modifiers);

zmk_hid_unregister_mods(modifiers);
return zmk_endpoints_send_report(USAGE_KEYPAD);
}

int hid_listener(const struct zmk_event_header *eh) {
if (is_keycode_state_changed(eh)) {
const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
if (ev->state) {
hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
} else {
hid_listener_keycode_released(ev->usage_page, ev->keycode);
}
} else if (is_modifiers_state_changed(eh)) {
const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
if (ev->state) {
hid_listener_modifiers_pressed(ev->modifiers);
hid_listener_keycode_pressed(ev->usage_page, ev->keycode, ev->implicit_modifiers);
} else {
hid_listener_modifiers_released(ev->modifiers);
hid_listener_keycode_released(ev->usage_page, ev->keycode, ev->implicit_modifiers);
}
}
return 0;
}

ZMK_LISTENER(hid_listener, hid_listener);
ZMK_SUBSCRIPTION(hid_listener, keycode_state_changed);
ZMK_SUBSCRIPTION(hid_listener, modifiers_state_changed);
ZMK_SUBSCRIPTION(hid_listener, keycode_state_changed);
1 change: 0 additions & 1 deletion app/src/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/matrix.h>
#include <zmk/sensors.h>
#include <zmk/keymap.h>
#include <dt-bindings/zmk/matrix-transform.h>
#include <drivers/behavior.h>
#include <zmk/behavior.h>

Expand Down
4 changes: 2 additions & 2 deletions app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
kp_pressed: usage_page 0x07 keycode 0x09
kp_released: usage_page 0x07 keycode 0x09
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_released: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0xe4
kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
kp_pressed: usage_page 0x07 keycode 0x09
kp_released: usage_page 0x07 keycode 0xe4
kp_released: usage_page 0x07 keycode 0x09
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 mods 0x00
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0xe4
kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_released: usage_page 0x07 keycode 0xe4
kp_released: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
ht_decide: 0 decided tap (balanced event 0)
kp_pressed: usage_page 0x07 keycode 0x09
kp_released: usage_page 0x07 keycode 0x09
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
ht_decide: 0 decided hold (balanced event 3)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_released: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_pressed: 1 new undecided hold_tap
ht_decide: 1 decided tap (balanced event 0)
kp_pressed: usage_page 0x07 keycode 0x0d
kp_released: usage_page 0x07 keycode 0x0d
kp_pressed: usage_page 0x07 keycode 0x0d mods 0x00
kp_released: usage_page 0x07 keycode 0x0d mods 0x00
ht_binding_released: 1 cleaning up hold-tap
kp_released: usage_page 0x07 keycode 0xe1
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 2)
kp_pressed: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0x07
kp_released: usage_page 0x07 keycode 0xe1
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
ht_binding_released: 0 cleaning up hold-tap
Loading

0 comments on commit 4f258ef

Please sign in to comment.