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 committed Sep 2, 2020
1 parent c80b0a7 commit c7dfbce
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 13 deletions.
1 change: 1 addition & 0 deletions app/dts/behaviors.dtsi
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <behaviors/key_press.dtsi>
#include <behaviors/modifiers.dtsi>
#include <behaviors/transparent.dtsi>
#include <behaviors/none.dtsi>
#include <behaviors/mod_tap.dtsi>
Expand Down
94 changes: 94 additions & 0 deletions app/dts/behaviors/modifiers.dtsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include <dt-bindings/zmk/keys.h>

/ {
behaviors {
ctl: behavior_ctl {
compatible = "zmk,behavior-key-press";
label = "MOD_CTRL";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LCTL)>;
};

sft: behavior_sft {
compatible = "zmk,behavior-key-press";
label = "MOD_SHIFT";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LSFT)>;
};

alt: behavior_alt {
compatible = "zmk,behavior-key-press";
label = "MOD_ALT";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LALT)>;
};

gui: behavior_gui {
compatible = "zmk,behavior-key-press";
label = "MOD_GUI";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LALT)>;
};


rctl: behavior_rtcl {
compatible = "zmk,behavior-key-press";
label = "RCTL";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_RCTL)>;
};

rsft: behavior_rsft {
compatible = "zmk,behavior-key-press";
label = "RSFT";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_RALT)>;
};

ralt: behavior_ralt {
compatible = "zmk,behavior-key-press";
label = "RALT";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_RALT)>;
};

rgui: behavior_rgui {
compatible = "zmk,behavior-key-press";
label = "RGUI";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_RGUI)>;
};

ctl_alt: behavior_ctl_alt {
compatible = "zmk,behavior-key-press";
label = "CTL_ALT";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LCTL | MOD_LALT)>;
};

meh: behavior_meh {
compatible = "zmk,behavior-key-press";
label = "MEH";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LCTL | MOD_LSFT | MOD_LALT)>;
};

hypr: behavior_hypr {
compatible = "zmk,behavior-key-press";
label = "HYPR";
usage_page = <USAGE_KEYPAD>;
#binding-cells = <1>;
modifiers = <(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI)>;
};
};
};
3 changes: 3 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ properties:
usage_page:
type: int
default: 0
modifiers:
type: int
default: 0
3 changes: 2 additions & 1 deletion app/include/dt-bindings/zmk/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,5 @@
#define MOD_RCTL (1 << 0x04)
#define MOD_RSFT (1 << 0x05)
#define MOD_RALT (1 << 0x06)
#define MOD_RGUI (1 << 0x07)
#define MOD_RGUI (1 << 0x07)
#define MOD_LAST_MODIFIER MOD_RGUI
7 changes: 6 additions & 1 deletion app/src/behaviors/behavior_key_press.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
#include <drivers/behavior.h>
#include <logging/log.h>

#include <zmk/hid.h>
#include <zmk/event-manager.h>
#include <zmk/events/keycode-state-changed.h>

LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

struct behavior_key_press_config {
u8_t usage_page;
zmk_mod_flags modifiers;
};
struct behavior_key_press_data { };

Expand All @@ -30,6 +32,7 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t k
const struct behavior_key_press_config *cfg = dev->config_info;
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);

zmk_hid_register_mods(cfg->modifiers);
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
}

Expand All @@ -38,6 +41,7 @@ static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t
const struct behavior_key_press_config *cfg = dev->config_info;
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);

zmk_hid_unregister_mods(cfg->modifiers);
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
}

Expand All @@ -48,7 +52,8 @@ static const struct behavior_driver_api behavior_key_press_driver_api = {

#define KP_INST(n) \
static const struct behavior_key_press_config behavior_key_press_config_##n = { \
.usage_page = DT_INST_PROP(n, usage_page) \
.usage_page = DT_INST_PROP(n, usage_page), \
.modifiers = DT_INST_PROP(n, modifiers), \
}; \
static struct behavior_key_press_data behavior_key_press_data_##n; \
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
Expand Down
48 changes: 37 additions & 11 deletions app/src/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,58 @@ static struct zmk_hid_consumer_report consumer_report = {
.body = {
.keys = {0,0,0,0,0,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 iff the count is 0.
static int modifier_counts[8] = {0, 0, 0, 0, 0, 0, 0, 0};

int zmk_hid_register_mod(zmk_mod modifier)
{
_TOGGLE_MOD(modifier, true);
modifier_counts[modifier]++;
WRITE_BIT(kp_report.body.modifiers, modifier, true);
return 0;
}

int zmk_hid_unregister_mod(zmk_mod modifier)
{
_TOGGLE_MOD(modifier, false);
if(modifier >= 8) {
LOG_ERR("This modifier does not exist %d", modifier);
return -EINVAL;
}
if(modifier_counts[modifier] <= 0) {
LOG_ERR("Tried to unregister modifier %d too often", modifier);
return -EINVAL;
}
modifier_counts[modifier]--;
if (modifier_counts[modifier] == 0) {
LOG_DBG("Modifier %d released.", modifier);
WRITE_BIT(kp_report.body.modifiers, modifier, false);
}
return 0;
}

int zmk_hid_register_mods(zmk_mod_flags modifiers)
{
kp_report.body.modifiers |= modifiers;
for(int modifier = 0; modifier < 8; modifier++) {
if ((modifiers >> modifier) & 1) {
int ret;
if((ret = zmk_hid_register_mod(modifier)) < 0) {
return ret;
}
}
}
return 0;
}

int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
{
kp_report.body.modifiers &= ~modifiers;
for(int modifier = 0; modifier < 8; modifier++) {
if ((modifiers >> modifier) & 1) {
int ret;
if((ret = zmk_hid_unregister_mod(modifier)) < 0) {
return ret;
}
}
}
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions app/tests/keypress/kp-press-release-mod/events.patterns
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
s/.*hid_listener_keycode_//p
s/.*hid_register_mod/reg/p
s/.*hid_unregister_mod/unreg/p
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pressed: usage_page 0x07 keycode 0x05
pressed: usage_page 0x07 keycode 0x04
released: usage_page 0x07 keycode 0x04
unreg: Modifier 1 released.
released: usage_page 0x07 keycode 0x05
27 changes: 27 additions & 0 deletions app/tests/keypress/kp-press-release-mod/native_posix.keymap
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan-mock.h>


&kscan {
events = <
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_RELEASE(0,0,10)
ZMK_MOCK_RELEASE(0,1,10)
>;
};

/ {
keymap {
compatible = "zmk,keymap";
label ="Default keymap";

default_layer {
bindings = <
&sft A &sft B
&kp D &kp G
>;
};
};
};

0 comments on commit c7dfbce

Please sign in to comment.