summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorOkke Formsma <okke@formsma.nl>2020-09-02 22:30:09 +0200
committerPete Johanson <peter@peterjohanson.com>2020-11-03 00:19:37 -0500
commit4f258efbf1602e212a808cc10915050a1b46e140 (patch)
treeed7601514e31895139ab91314610b2d570b1d326 /app/src
parenta9e729b427800fab230fc1fcdacd3cbdb6bedc19 (diff)
initial implementation for modifiers
https://github.com/zmkfirmware/zmk/issues/86
Diffstat (limited to 'app/src')
-rw-r--r--app/src/behaviors/behavior_hold_tap.c6
-rw-r--r--app/src/hid.c49
-rw-r--r--app/src/hid_listener.c51
-rw-r--r--app/src/keymap.c1
4 files changed, 58 insertions, 49 deletions
diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c
index 8b3620e..ac91e7d 100644
--- a/app/src/behaviors/behavior_hold_tap.c
+++ b/app/src/behaviors/behavior_hold_tap.c
@@ -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>
@@ -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);
@@ -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;
}
@@ -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;
}
diff --git a/app/src/hid.c b/app/src/hid.c
index 216cec7..001d7d3 100644
--- a/app/src/hid.c
+++ b/app/src/hid.c
@@ -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;
}
@@ -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);
diff --git a/app/src/hid_listener.c b/app/src/hid_listener.c
index 4467e6d..32e9d97 100644
--- a/app/src/hid_listener.c
+++ b/app/src/hid_listener.c
@@ -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);
@@ -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);
@@ -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); \ No newline at end of file
+ZMK_SUBSCRIPTION(hid_listener, keycode_state_changed); \ No newline at end of file
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 74fe60d..1d289e5 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -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>