Merge remote-tracking branch 'upstream/main' into ma730
This commit is contained in:
commit
2ea52befff
195 changed files with 2013 additions and 765 deletions
2
.github/workflows/clang-format-lint.yml
vendored
2
.github/workflows/clang-format-lint.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: DoozyX/clang-format-lint-action@v0.9
|
- uses: DoozyX/clang-format-lint-action@v0.11
|
||||||
with:
|
with:
|
||||||
source: "./app"
|
source: "./app"
|
||||||
extensions: "h,c"
|
extensions: "h,c"
|
||||||
|
|
|
@ -28,6 +28,7 @@ target_sources(app PRIVATE src/kscan.c)
|
||||||
target_sources(app PRIVATE src/matrix_transform.c)
|
target_sources(app PRIVATE src/matrix_transform.c)
|
||||||
target_sources(app PRIVATE src/hid.c)
|
target_sources(app PRIVATE src/hid.c)
|
||||||
target_sources(app PRIVATE src/sensors.c)
|
target_sources(app PRIVATE src/sensors.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c)
|
||||||
target_sources(app PRIVATE src/event_manager.c)
|
target_sources(app PRIVATE src/event_manager.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
|
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
|
||||||
target_sources(app PRIVATE src/events/activity_state_changed.c)
|
target_sources(app PRIVATE src/events/activity_state_changed.c)
|
||||||
|
@ -36,6 +37,7 @@ target_sources(app PRIVATE src/events/layer_state_changed.c)
|
||||||
target_sources(app PRIVATE src/events/keycode_state_changed.c)
|
target_sources(app PRIVATE src/events/keycode_state_changed.c)
|
||||||
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
|
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
|
||||||
target_sources(app PRIVATE src/events/sensor_event.c)
|
target_sources(app PRIVATE src/events/sensor_event.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
|
||||||
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
|
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
|
||||||
|
@ -45,6 +47,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c)
|
target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
||||||
|
target_sources(app PRIVATE src/behaviors/behavior_mod_morph.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_outputs.c)
|
target_sources(app PRIVATE src/behaviors/behavior_outputs.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
|
target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_to_layer.c)
|
target_sources(app PRIVATE src/behaviors/behavior_to_layer.c)
|
||||||
|
|
48
app/Kconfig
48
app/Kconfig
|
@ -41,7 +41,7 @@ config USB_NUMOF_EP_WRITE_RETRIES
|
||||||
#ZMK_USB
|
#ZMK_USB
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config ZMK_BLE
|
menuconfig ZMK_BLE
|
||||||
bool "BLE (HID over GATT)"
|
bool "BLE (HID over GATT)"
|
||||||
select BT
|
select BT
|
||||||
select BT_SMP
|
select BT_SMP
|
||||||
|
@ -58,6 +58,22 @@ if ZMK_BLE
|
||||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||||
default 2048
|
default 2048
|
||||||
|
|
||||||
|
config ZMK_BLE_THREAD_STACK_SIZE
|
||||||
|
int "BLE notify thread stack size"
|
||||||
|
default 512
|
||||||
|
|
||||||
|
config ZMK_BLE_THREAD_PRIORITY
|
||||||
|
int "BLE notify thread priority"
|
||||||
|
default 5
|
||||||
|
|
||||||
|
config ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE
|
||||||
|
int "Max number of keyboard HID reports to queue for sending over BLE"
|
||||||
|
default 20
|
||||||
|
|
||||||
|
config ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE
|
||||||
|
int "Max number of consumer HID reports to queue for sending over BLE"
|
||||||
|
default 5
|
||||||
|
|
||||||
config ZMK_BLE_CLEAR_BONDS_ON_START
|
config ZMK_BLE_CLEAR_BONDS_ON_START
|
||||||
bool "Configuration that clears all bond information from the keyboard on startup."
|
bool "Configuration that clears all bond information from the keyboard on startup."
|
||||||
default n
|
default n
|
||||||
|
@ -86,7 +102,7 @@ config ZMK_SPLIT
|
||||||
|
|
||||||
if ZMK_SPLIT
|
if ZMK_SPLIT
|
||||||
|
|
||||||
config ZMK_SPLIT_BLE
|
menuconfig ZMK_SPLIT_BLE
|
||||||
bool "Split keyboard support via BLE transport"
|
bool "Split keyboard support via BLE transport"
|
||||||
depends on ZMK_BLE
|
depends on ZMK_BLE
|
||||||
default y
|
default y
|
||||||
|
@ -94,13 +110,33 @@ config ZMK_SPLIT_BLE
|
||||||
|
|
||||||
if ZMK_SPLIT_BLE
|
if ZMK_SPLIT_BLE
|
||||||
|
|
||||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
menuconfig ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||||
bool "Central"
|
bool "Central"
|
||||||
select BT_CENTRAL
|
select BT_CENTRAL
|
||||||
select BT_GATT_CLIENT
|
select BT_GATT_CLIENT
|
||||||
|
|
||||||
|
if ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE
|
||||||
|
int "Max number of key position state events to queue when received from peripherals"
|
||||||
|
default 5
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
if !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
if !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE
|
||||||
|
int "BLE split peripheral notify thread stack size"
|
||||||
|
default 512
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY
|
||||||
|
int "BLE split peripheral notify thread priority"
|
||||||
|
default 5
|
||||||
|
|
||||||
|
config ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE
|
||||||
|
int "Max number of key position state events to queue to send to the central"
|
||||||
|
default 10
|
||||||
|
|
||||||
config ZMK_USB
|
config ZMK_USB
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
@ -301,11 +337,9 @@ config ZMK_KSCAN_EVENT_QUEUE_SIZE
|
||||||
|
|
||||||
config ZMK_KSCAN_MOCK_DRIVER
|
config ZMK_KSCAN_MOCK_DRIVER
|
||||||
bool "Enable mock kscan driver to simulate key presses"
|
bool "Enable mock kscan driver to simulate key presses"
|
||||||
default n
|
|
||||||
|
|
||||||
config ZMK_KSCAN_COMPOSITE_DRIVER
|
config ZMK_KSCAN_COMPOSITE_DRIVER
|
||||||
bool "Enable composite kscan driver to combine kscan devices"
|
bool "Enable composite kscan driver to combine kscan devices"
|
||||||
default n
|
|
||||||
|
|
||||||
#KSCAN Settings
|
#KSCAN Settings
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -381,6 +415,10 @@ config REBOOT
|
||||||
config USB
|
config USB
|
||||||
default y if HAS_HW_NRF_USBD
|
default y if HAS_HW_NRF_USBD
|
||||||
|
|
||||||
|
config ZMK_WPM
|
||||||
|
bool "Calculate WPM"
|
||||||
|
default n
|
||||||
|
|
||||||
module = ZMK
|
module = ZMK
|
||||||
module-str = zmk
|
module-str = zmk
|
||||||
source "subsys/logging/Kconfig.template.log_config"
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
|
@ -58,8 +58,6 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9)
|
||||||
page-offset = <0>;
|
page-offset = <0>;
|
||||||
display-offset = <0>;
|
display-offset = <0>;
|
||||||
multiplex-ratio = <31>;
|
multiplex-ratio = <31>;
|
||||||
segment-remap;
|
|
||||||
com-invdir;
|
|
||||||
com-sequential;
|
com-sequential;
|
||||||
prechargep = <0x22>;
|
prechargep = <0x22>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
col-offset = <5>;
|
col-offset = <5>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&oled {
|
||||||
|
segment-remap;
|
||||||
|
com-invdir;
|
||||||
|
};
|
||||||
|
|
||||||
&kscan0 {
|
&kscan0 {
|
||||||
col-gpios
|
col-gpios
|
||||||
= <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
|
= <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp HOME
|
&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp HOME
|
||||||
&kp C_VOL_UP &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH &kp DEL
|
&kp C_VOL_UP &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH &kp DEL
|
||||||
&kp C_VOL_DN &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp PG_UP
|
&kp C_VOL_DN &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp PG_UP
|
||||||
&trans &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp PG_DN
|
&trans &kp LSHFT &trans &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp PG_DN
|
||||||
&trans &kp LCTRL &kp LGUI &kp LALT &kp SPACE &mo FUNC &kp RALT &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT
|
&trans &kp LCTRL &kp LGUI &kp LALT &kp SPACE &mo FUNC &kp RALT &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
&kp TILDE &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &kp END
|
&kp TILDE &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &kp END
|
||||||
&bt BT_CLR &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &bootloader
|
&bt BT_CLR &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &bootloader
|
||||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
&bt BT_PRV &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
&bt BT_PRV &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
&bt BT_NXT &trans &trans &trans &trans &trans &trans &trans &kp C_PREV &kp C_PP &kp C_NEXT
|
&bt BT_NXT &trans &trans &trans &trans &trans &trans &trans &kp C_PREV &kp C_PP &kp C_NEXT
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
, <&pro_micro_d 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
, <&pro_micro_d 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||||
, <&pro_micro_d 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
, <&pro_micro_d 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||||
, <&pro_micro_d 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
, <&pro_micro_d 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||||
, <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
, <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||||
;
|
;
|
||||||
output-gpios
|
output-gpios
|
||||||
= <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
|
= <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
|
||||||
|
@ -39,11 +39,11 @@
|
||||||
//TODO: Add a keymap graphic here
|
//TODO: Add a keymap graphic here
|
||||||
|
|
||||||
map = <
|
map = <
|
||||||
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
|
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
|
||||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
|
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
|
||||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,14) RC(2,15)
|
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,14) RC(2,15)
|
||||||
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,14) RC(3,15)
|
RC(3,0) RC(3,1) RC(0,0) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,14) RC(3,15)
|
||||||
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,6) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,14) RC(4,15)
|
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,6) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,14) RC(4,15)
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ endif
|
||||||
if SHIELD_SPLITREUS62_RIGHT
|
if SHIELD_SPLITREUS62_RIGHT
|
||||||
|
|
||||||
config ZMK_KEYBOARD_NAME
|
config ZMK_KEYBOARD_NAME
|
||||||
default "Splitreus62 Right"
|
default "Splitreus62 Rt"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,9 @@ if ZMK_KSCAN_GPIO_DRIVER
|
||||||
|
|
||||||
config ZMK_KSCAN_MATRIX_POLLING
|
config ZMK_KSCAN_MATRIX_POLLING
|
||||||
bool "Poll for key event triggers instead of using interrupts on matrix boards."
|
bool "Poll for key event triggers instead of using interrupts on matrix boards."
|
||||||
default n
|
|
||||||
|
|
||||||
config ZMK_KSCAN_DIRECT_POLLING
|
config ZMK_KSCAN_DIRECT_POLLING
|
||||||
bool "Poll for key event triggers instead of using interrupts on direct wired boards."
|
bool "Poll for key event triggers instead of using interrupts on direct wired boards."
|
||||||
default n
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,11 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define COND_POLLING(code) COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (code), ())
|
||||||
|
#define COND_INTERRUPTS(code) COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (code))
|
||||||
|
#define COND_POLL_OR_INTERRUPTS(pollcode, intcode) \
|
||||||
|
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, pollcode, intcode)
|
||||||
|
|
||||||
#define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios)
|
#define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios)
|
||||||
#define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios)
|
#define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios)
|
||||||
#define INST_OUTPUT_LEN(n) \
|
#define INST_OUTPUT_LEN(n) \
|
||||||
|
@ -61,19 +66,21 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
(INST_MATRIX_ROWS(n)))
|
(INST_MATRIX_ROWS(n)))
|
||||||
|
|
||||||
#define GPIO_INST_INIT(n) \
|
#define GPIO_INST_INIT(n) \
|
||||||
struct kscan_gpio_irq_callback_##n { \
|
COND_INTERRUPTS( \
|
||||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
|
struct kscan_gpio_irq_callback_##n { \
|
||||||
struct gpio_callback callback; \
|
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * \
|
||||||
const struct device *dev; \
|
work; \
|
||||||
}; \
|
struct gpio_callback callback; \
|
||||||
static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \
|
const struct device *dev; \
|
||||||
|
}; \
|
||||||
|
static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)];) \
|
||||||
struct kscan_gpio_config_##n { \
|
struct kscan_gpio_config_##n { \
|
||||||
struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
|
struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
|
||||||
struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
|
struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
|
||||||
}; \
|
}; \
|
||||||
struct kscan_gpio_data_##n { \
|
struct kscan_gpio_data_##n { \
|
||||||
kscan_callback_t callback; \
|
kscan_callback_t callback; \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (struct k_timer poll_timer;), ()) \
|
COND_POLLING(struct k_timer poll_timer;) \
|
||||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \
|
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \
|
||||||
bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||||
const struct device *rows[INST_MATRIX_ROWS(n)]; \
|
const struct device *rows[INST_MATRIX_ROWS(n)]; \
|
||||||
|
@ -102,17 +109,16 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
return ( \
|
return ( \
|
||||||
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
|
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
|
||||||
} \
|
} \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \
|
COND_INTERRUPTS( \
|
||||||
( \
|
static int kscan_gpio_enable_interrupts_##n(const struct device *dev) { \
|
||||||
static int kscan_gpio_enable_interrupts_##n(const struct device *dev) { \
|
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
|
||||||
return kscan_gpio_config_interrupts( \
|
kscan_gpio_input_configs_##n(dev), \
|
||||||
kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), \
|
INST_INPUT_LEN(n), GPIO_INT_LEVEL_ACTIVE); \
|
||||||
INST_INPUT_LEN(n), GPIO_INT_LEVEL_ACTIVE); \
|
} static int kscan_gpio_disable_interrupts_##n(const struct device *dev) { \
|
||||||
} static int kscan_gpio_disable_interrupts_##n(const struct device *dev) { \
|
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
|
||||||
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
|
kscan_gpio_input_configs_##n(dev), \
|
||||||
kscan_gpio_input_configs_##n(dev), \
|
INST_INPUT_LEN(n), GPIO_INT_DISABLE); \
|
||||||
INST_INPUT_LEN(n), GPIO_INT_DISABLE); \
|
}) \
|
||||||
})) \
|
|
||||||
static void kscan_gpio_set_output_state_##n(const struct device *dev, int value) { \
|
static void kscan_gpio_set_output_state_##n(const struct device *dev, int value) { \
|
||||||
int err; \
|
int err; \
|
||||||
for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \
|
for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \
|
||||||
|
@ -132,17 +138,22 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
(output_index))] = value; \
|
(output_index))] = value; \
|
||||||
} \
|
} \
|
||||||
static int kscan_gpio_read_##n(const struct device *dev) { \
|
static int kscan_gpio_read_##n(const struct device *dev) { \
|
||||||
bool submit_follow_up_read = false; \
|
COND_INTERRUPTS(bool submit_follow_up_read = false;) \
|
||||||
struct kscan_gpio_data_##n *data = dev->data; \
|
struct kscan_gpio_data_##n *data = dev->data; \
|
||||||
static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||||
|
int err; \
|
||||||
/* Disable our interrupts temporarily while we scan, to avoid */ \
|
/* Disable our interrupts temporarily while we scan, to avoid */ \
|
||||||
/* re-entry while we iterate columns and set them active one by one */ \
|
/* re-entry while we iterate columns and set them active one by one */ \
|
||||||
/* to get pressed state for each matrix cell. */ \
|
/* to get pressed state for each matrix cell. */ \
|
||||||
kscan_gpio_set_output_state_##n(dev, 0); \
|
COND_INTERRUPTS(kscan_gpio_set_output_state_##n(dev, 0);) \
|
||||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
||||||
const struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \
|
const struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \
|
||||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||||
gpio_pin_set(out_dev, out_cfg->pin, 1); \
|
err = gpio_pin_set(out_dev, out_cfg->pin, 1); \
|
||||||
|
if (err) { \
|
||||||
|
LOG_ERR("Failed to set output active (err %d)", err); \
|
||||||
|
return err; \
|
||||||
|
} \
|
||||||
for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
|
for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
|
||||||
const struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
|
const struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
|
||||||
const struct kscan_gpio_item_config *in_cfg = \
|
const struct kscan_gpio_item_config *in_cfg = \
|
||||||
|
@ -150,16 +161,20 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
kscan_gpio_set_matrix_state_##n(read_state, i, o, \
|
kscan_gpio_set_matrix_state_##n(read_state, i, o, \
|
||||||
gpio_pin_get(in_dev, in_cfg->pin) > 0); \
|
gpio_pin_get(in_dev, in_cfg->pin) > 0); \
|
||||||
} \
|
} \
|
||||||
gpio_pin_set(out_dev, out_cfg->pin, 0); \
|
err = gpio_pin_set(out_dev, out_cfg->pin, 0); \
|
||||||
|
if (err) { \
|
||||||
|
LOG_ERR("Failed to set output inactive (err %d)", err); \
|
||||||
|
return err; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
/* Set all our outputs as active again. */ \
|
/* Set all our outputs as active again. */ \
|
||||||
kscan_gpio_set_output_state_##n(dev, 1); \
|
COND_INTERRUPTS(kscan_gpio_set_output_state_##n(dev, 1);) \
|
||||||
for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \
|
for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \
|
||||||
for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \
|
for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \
|
||||||
bool pressed = read_state[r][c]; \
|
bool pressed = read_state[r][c]; \
|
||||||
/* Follow up reads needed because further interrupts won't fire on already tripped \
|
/* Follow up reads needed because further interrupts won't fire on already tripped \
|
||||||
* input GPIO pins */ \
|
* input GPIO pins */ \
|
||||||
submit_follow_up_read = (submit_follow_up_read || pressed); \
|
COND_INTERRUPTS(submit_follow_up_read = (submit_follow_up_read || pressed);) \
|
||||||
if (pressed != data->matrix_state[r][c]) { \
|
if (pressed != data->matrix_state[r][c]) { \
|
||||||
LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \
|
LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \
|
||||||
data->matrix_state[r][c] = pressed; \
|
data->matrix_state[r][c] = pressed; \
|
||||||
|
@ -167,33 +182,31 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (submit_follow_up_read) { \
|
COND_INTERRUPTS( \
|
||||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), ({ \
|
if (submit_follow_up_read) { \
|
||||||
k_delayed_work_cancel(&data->work); \
|
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), \
|
||||||
k_delayed_work_submit(&data->work, K_MSEC(5)); \
|
({ \
|
||||||
})) \
|
k_delayed_work_cancel(&data->work); \
|
||||||
} else { \
|
k_delayed_work_submit(&data->work, K_MSEC(5)); \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \
|
})) \
|
||||||
(kscan_gpio_enable_interrupts_##n(dev);)) \
|
} else { kscan_gpio_enable_interrupts_##n(dev); }) \
|
||||||
} \
|
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
static void kscan_gpio_work_handler_##n(struct k_work *work) { \
|
static void kscan_gpio_work_handler_##n(struct k_work *work) { \
|
||||||
struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
|
struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
|
||||||
kscan_gpio_read_##n(data->dev); \
|
kscan_gpio_read_##n(data->dev); \
|
||||||
} \
|
} \
|
||||||
static void kscan_gpio_irq_callback_handler_##n( \
|
COND_INTERRUPTS(static void kscan_gpio_irq_callback_handler_##n( \
|
||||||
const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pin) { \
|
const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pin) { \
|
||||||
struct kscan_gpio_irq_callback_##n *data = \
|
struct kscan_gpio_irq_callback_##n *data = \
|
||||||
CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
|
CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \
|
kscan_gpio_disable_interrupts_##n(data->dev); \
|
||||||
(kscan_gpio_disable_interrupts_##n(data->dev);)) \
|
|
||||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
|
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
|
||||||
k_delayed_work_cancel(data->work); \
|
k_delayed_work_cancel(data->work); \
|
||||||
k_delayed_work_submit(data->work, \
|
k_delayed_work_submit(data->work, \
|
||||||
K_MSEC(DT_INST_PROP(n, debounce_period))); \
|
K_MSEC(DT_INST_PROP(n, debounce_period))); \
|
||||||
})) \
|
})) \
|
||||||
} \
|
}) \
|
||||||
\
|
\
|
||||||
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
|
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
|
||||||
.rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
|
.rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
|
||||||
|
@ -207,25 +220,22 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
return 0; \
|
return 0; \
|
||||||
}; \
|
}; \
|
||||||
static int kscan_gpio_enable_##n(const struct device *dev) { \
|
static int kscan_gpio_enable_##n(const struct device *dev) { \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \
|
COND_POLL_OR_INTERRUPTS((struct kscan_gpio_data_##n *data = dev->data; \
|
||||||
(struct kscan_gpio_data_##n *data = dev->data; \
|
k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \
|
||||||
k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;), \
|
return 0;), \
|
||||||
(int err = kscan_gpio_enable_interrupts_##n(dev); \
|
(int err = kscan_gpio_enable_interrupts_##n(dev); \
|
||||||
if (err) { return err; } return kscan_gpio_read_##n(dev);)) \
|
if (err) { return err; } return kscan_gpio_read_##n(dev);)) \
|
||||||
}; \
|
}; \
|
||||||
static int kscan_gpio_disable_##n(const struct device *dev) { \
|
static int kscan_gpio_disable_##n(const struct device *dev) { \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \
|
COND_POLL_OR_INTERRUPTS((struct kscan_gpio_data_##n *data = dev->data; \
|
||||||
(struct kscan_gpio_data_##n *data = dev->data; \
|
k_timer_stop(&data->poll_timer); return 0;), \
|
||||||
k_timer_stop(&data->poll_timer); return 0;), \
|
(return kscan_gpio_disable_interrupts_##n(dev);)) \
|
||||||
(return kscan_gpio_disable_interrupts_##n(dev);)) \
|
|
||||||
}; \
|
}; \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \
|
COND_POLLING(static void kscan_gpio_timer_handler_##n(struct k_timer *timer) { \
|
||||||
(static void kscan_gpio_timer_handler(struct k_timer *timer) { \
|
struct kscan_gpio_data_##n *data = \
|
||||||
struct kscan_gpio_data_##n *data = \
|
CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \
|
||||||
CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \
|
k_work_submit(&data->work.work); \
|
||||||
k_work_submit(&data->work.work); \
|
}) \
|
||||||
}), \
|
|
||||||
()) \
|
|
||||||
static int kscan_gpio_init_##n(const struct device *dev) { \
|
static int kscan_gpio_init_##n(const struct device *dev) { \
|
||||||
struct kscan_gpio_data_##n *data = dev->data; \
|
struct kscan_gpio_data_##n *data = dev->data; \
|
||||||
int err; \
|
int err; \
|
||||||
|
@ -244,15 +254,15 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
} else { \
|
} else { \
|
||||||
LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||||
} \
|
} \
|
||||||
irq_callbacks_##n[i].work = &data->work; \
|
COND_INTERRUPTS( \
|
||||||
irq_callbacks_##n[i].dev = dev; \
|
irq_callbacks_##n[i].work = &data->work; irq_callbacks_##n[i].dev = dev; \
|
||||||
gpio_init_callback(&irq_callbacks_##n[i].callback, \
|
gpio_init_callback(&irq_callbacks_##n[i].callback, \
|
||||||
kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
|
kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
|
||||||
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
||||||
if (err) { \
|
if (err) { \
|
||||||
LOG_ERR("Error adding the callback to the column device"); \
|
LOG_ERR("Error adding the callback to the input device"); \
|
||||||
return err; \
|
return err; \
|
||||||
} \
|
}) \
|
||||||
} \
|
} \
|
||||||
const struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
|
const struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
|
||||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
||||||
|
@ -262,8 +272,8 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
LOG_ERR("Unable to find output GPIO device"); \
|
LOG_ERR("Unable to find output GPIO device"); \
|
||||||
return -EINVAL; \
|
return -EINVAL; \
|
||||||
} \
|
} \
|
||||||
err = gpio_pin_configure(output_devices[o], out_cfg->pin, \
|
err = \
|
||||||
GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
|
gpio_pin_configure(output_devices[o], out_cfg->pin, GPIO_OUTPUT | out_cfg->flags); \
|
||||||
if (err) { \
|
if (err) { \
|
||||||
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
|
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
|
||||||
out_cfg->label); \
|
out_cfg->label); \
|
||||||
|
@ -271,10 +281,12 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
data->dev = dev; \
|
data->dev = dev; \
|
||||||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \
|
|
||||||
(k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \
|
|
||||||
(COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \
|
(COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \
|
||||||
&data->work, kscan_gpio_work_handler_##n); \
|
&data->work, kscan_gpio_work_handler_##n); \
|
||||||
|
COND_POLL_OR_INTERRUPTS( \
|
||||||
|
(k_timer_init(&data->poll_timer, kscan_gpio_timer_handler_##n, NULL); \
|
||||||
|
kscan_gpio_set_output_state_##n(dev, 0);), \
|
||||||
|
(kscan_gpio_set_output_state_##n(dev, 1);)) \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
static const struct kscan_driver_api gpio_driver_api_##n = { \
|
static const struct kscan_driver_api gpio_driver_api_##n = { \
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <behaviors/none.dtsi>
|
#include <behaviors/none.dtsi>
|
||||||
#include <behaviors/mod_tap.dtsi>
|
#include <behaviors/mod_tap.dtsi>
|
||||||
#include <behaviors/layer_tap.dtsi>
|
#include <behaviors/layer_tap.dtsi>
|
||||||
|
#include <behaviors/gresc.dtsi>
|
||||||
#include <behaviors/sticky_key.dtsi>
|
#include <behaviors/sticky_key.dtsi>
|
||||||
#include <behaviors/momentary_layer.dtsi>
|
#include <behaviors/momentary_layer.dtsi>
|
||||||
#include <behaviors/toggle_layer.dtsi>
|
#include <behaviors/toggle_layer.dtsi>
|
||||||
|
|
19
app/dts/behaviors/gresc.dtsi
Normal file
19
app/dts/behaviors/gresc.dtsi
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
/omit-if-no-ref/ gresc: grave_escape {
|
||||||
|
compatible = "zmk,behavior-mod-morph";
|
||||||
|
label = "GRAVE_ESCAPE";
|
||||||
|
#binding-cells = <0>;
|
||||||
|
bindings = <&kp ESC>, <&kp GRAVE>;
|
||||||
|
mods = <(MOD_LGUI|MOD_LSFT|MOD_RGUI|MOD_RSFT)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -19,6 +19,7 @@
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
release-after-ms = <1000>;
|
release-after-ms = <1000>;
|
||||||
bindings = <&mo>;
|
bindings = <&mo>;
|
||||||
|
quick-release;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Peter Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: Bluetooth Behavior
|
description: Bluetooth Behavior
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: Key press/release behavior
|
description: Key press/release behavior
|
||||||
|
|
16
app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml
Normal file
16
app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Keyboard Reset Behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-mod-morph"
|
||||||
|
|
||||||
|
include: zero_param.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
bindings:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
mods:
|
||||||
|
type: int
|
||||||
|
required: true
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: Momentary layer on press/release behavior
|
description: Momentary layer on press/release behavior
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: None Binding Behavior
|
description: None Binding Behavior
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: Keyboard Reset Behavior
|
description: Keyboard Reset Behavior
|
||||||
|
|
|
@ -13,3 +13,5 @@ properties:
|
||||||
required: true
|
required: true
|
||||||
release-after-ms:
|
release-after-ms:
|
||||||
type: int
|
type: int
|
||||||
|
quick-release:
|
||||||
|
type: boolean
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020 Pete Johanson
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
description: Transparent Binding Behavior
|
description: Transparent Binding Behavior
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Pete Johanson
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
18
app/include/zmk/display/widgets/wpm_status.h
Normal file
18
app/include/zmk/display/widgets/wpm_status.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
struct zmk_widget_wpm_status {
|
||||||
|
sys_snode_t node;
|
||||||
|
lv_obj_t *obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
int zmk_widget_wpm_status_init(struct zmk_widget_wpm_status *widget, lv_obj_t *parent);
|
||||||
|
lv_obj_t *zmk_widget_wpm_status_obj(struct zmk_widget_wpm_status *widget);
|
|
@ -14,16 +14,16 @@ struct zmk_event_type {
|
||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zmk_event_header {
|
typedef struct {
|
||||||
const struct zmk_event_type *event;
|
const struct zmk_event_type *event;
|
||||||
uint8_t last_listener_index;
|
uint8_t last_listener_index;
|
||||||
};
|
} zmk_event_t;
|
||||||
|
|
||||||
#define ZMK_EV_EVENT_BUBBLE 0
|
#define ZMK_EV_EVENT_BUBBLE 0
|
||||||
#define ZMK_EV_EVENT_HANDLED 1
|
#define ZMK_EV_EVENT_HANDLED 1
|
||||||
#define ZMK_EV_EVENT_CAPTURED 2
|
#define ZMK_EV_EVENT_CAPTURED 2
|
||||||
|
|
||||||
typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh);
|
typedef int (*zmk_listener_callback_t)(const zmk_event_t *eh);
|
||||||
struct zmk_listener {
|
struct zmk_listener {
|
||||||
zmk_listener_callback_t callback;
|
zmk_listener_callback_t callback;
|
||||||
};
|
};
|
||||||
|
@ -34,25 +34,28 @@ struct zmk_event_subscription {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZMK_EVENT_DECLARE(event_type) \
|
#define ZMK_EVENT_DECLARE(event_type) \
|
||||||
struct event_type *new_##event_type(); \
|
struct event_type##_event { \
|
||||||
bool is_##event_type(const struct zmk_event_header *eh); \
|
zmk_event_t header; \
|
||||||
struct event_type *cast_##event_type(const struct zmk_event_header *eh); \
|
struct event_type data; \
|
||||||
|
}; \
|
||||||
|
struct event_type##_event *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;
|
extern const struct zmk_event_type zmk_event_##event_type;
|
||||||
|
|
||||||
#define ZMK_EVENT_IMPL(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_##event_type = {.name = STRINGIFY(event_type)}; \
|
||||||
const struct zmk_event_type *zmk_event_ref_##event_type __used \
|
const struct zmk_event_type *zmk_event_ref_##event_type __used \
|
||||||
__attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
|
__attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
|
||||||
struct event_type *new_##event_type() { \
|
struct event_type##_event *new_##event_type(struct event_type data) { \
|
||||||
struct event_type *ev = (struct event_type *)k_malloc(sizeof(struct event_type)); \
|
struct event_type##_event *ev = \
|
||||||
|
(struct event_type##_event *)k_malloc(sizeof(struct event_type##_event)); \
|
||||||
ev->header.event = &zmk_event_##event_type; \
|
ev->header.event = &zmk_event_##event_type; \
|
||||||
|
ev->data = data; \
|
||||||
return ev; \
|
return ev; \
|
||||||
}; \
|
}; \
|
||||||
bool is_##event_type(const struct zmk_event_header *eh) { \
|
struct event_type *as_##event_type(const zmk_event_t *eh) { \
|
||||||
return eh->event == &zmk_event_##event_type; \
|
return (eh->event == &zmk_event_##event_type) ? &((struct event_type##_event *)eh)->data \
|
||||||
}; \
|
: NULL; \
|
||||||
struct event_type *cast_##event_type(const struct zmk_event_header *eh) { \
|
|
||||||
return (struct event_type *)eh; \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZMK_LISTENER(mod, cb) const struct zmk_listener zmk_listener_##mod = {.callback = cb};
|
#define ZMK_LISTENER(mod, cb) const struct zmk_listener zmk_listener_##mod = {.callback = cb};
|
||||||
|
@ -65,18 +68,19 @@ struct zmk_event_subscription {
|
||||||
.listener = &zmk_listener_##mod, \
|
.listener = &zmk_listener_##mod, \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((struct zmk_event_header *)ev);
|
#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((zmk_event_t *)ev);
|
||||||
|
|
||||||
#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
|
#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
|
||||||
zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##mod);
|
zmk_event_manager_raise_after((zmk_event_t *)ev, &zmk_listener_##mod);
|
||||||
|
|
||||||
#define ZMK_EVENT_RAISE_AT(ev, mod) \
|
#define ZMK_EVENT_RAISE_AT(ev, mod) \
|
||||||
zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod);
|
zmk_event_manager_raise_at((zmk_event_t *)ev, &zmk_listener_##mod);
|
||||||
|
|
||||||
#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((struct zmk_event_header *)ev);
|
#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((zmk_event_t *)ev);
|
||||||
|
|
||||||
int zmk_event_manager_raise(struct zmk_event_header *event);
|
#define ZMK_EVENT_FREE(ev) k_free((void *)ev);
|
||||||
int zmk_event_manager_raise_after(struct zmk_event_header *event,
|
|
||||||
const struct zmk_listener *listener);
|
int zmk_event_manager_raise(zmk_event_t *event);
|
||||||
int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener);
|
int zmk_event_manager_raise_after(zmk_event_t *event, const struct zmk_listener *listener);
|
||||||
int zmk_event_manager_release(struct zmk_event_header *event);
|
int zmk_event_manager_raise_at(zmk_event_t *event, const struct zmk_listener *listener);
|
||||||
|
int zmk_event_manager_release(zmk_event_t *event);
|
|
@ -10,17 +10,8 @@
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/activity.h>
|
#include <zmk/activity.h>
|
||||||
|
|
||||||
struct activity_state_changed {
|
struct zmk_activity_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
enum zmk_activity_state state;
|
enum zmk_activity_state state;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(activity_state_changed);
|
ZMK_EVENT_DECLARE(zmk_activity_state_changed);
|
||||||
|
|
||||||
static inline struct activity_state_changed *
|
|
||||||
create_activity_state_changed(enum zmk_activity_state state) {
|
|
||||||
struct activity_state_changed *ev = new_activity_state_changed();
|
|
||||||
ev->state = state;
|
|
||||||
|
|
||||||
return ev;
|
|
||||||
}
|
|
|
@ -9,10 +9,9 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
|
|
||||||
struct battery_state_changed {
|
struct zmk_battery_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
// TODO: Other battery channels
|
// TODO: Other battery channels
|
||||||
uint8_t state_of_charge;
|
uint8_t state_of_charge;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(battery_state_changed);
|
ZMK_EVENT_DECLARE(zmk_battery_state_changed);
|
|
@ -12,10 +12,9 @@
|
||||||
|
|
||||||
#include <zmk/ble/profile.h>
|
#include <zmk/ble/profile.h>
|
||||||
|
|
||||||
struct ble_active_profile_changed {
|
struct zmk_ble_active_profile_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
struct zmk_ble_profile *profile;
|
struct zmk_ble_profile *profile;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(ble_active_profile_changed);
|
ZMK_EVENT_DECLARE(zmk_ble_active_profile_changed);
|
||||||
|
|
|
@ -7,37 +7,42 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <dt-bindings/zmk/modifiers.h>
|
|
||||||
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/keys.h>
|
#include <zmk/keys.h>
|
||||||
|
|
||||||
struct keycode_state_changed {
|
struct zmk_keycode_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
uint16_t usage_page;
|
uint16_t usage_page;
|
||||||
uint32_t keycode;
|
uint32_t keycode;
|
||||||
uint8_t implicit_modifiers;
|
uint8_t implicit_modifiers;
|
||||||
|
uint8_t explicit_modifiers;
|
||||||
bool state;
|
bool state;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(keycode_state_changed);
|
ZMK_EVENT_DECLARE(zmk_keycode_state_changed);
|
||||||
|
|
||||||
static inline struct keycode_state_changed *
|
static inline struct zmk_keycode_state_changed_event *
|
||||||
keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
||||||
uint16_t page = HID_USAGE_PAGE(encoded) & 0xFF;
|
uint16_t page = HID_USAGE_PAGE(encoded) & 0xFF;
|
||||||
uint16_t id = HID_USAGE_ID(encoded);
|
uint16_t id = HID_USAGE_ID(encoded);
|
||||||
zmk_mod_flags_t implicit_mods = SELECT_MODS(encoded);
|
uint8_t implicit_modifiers = 0x00;
|
||||||
|
uint8_t explicit_modifiers = 0x00;
|
||||||
|
|
||||||
if (!page) {
|
if (!page) {
|
||||||
page = HID_USAGE_KEY;
|
page = HID_USAGE_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct keycode_state_changed *ev = new_keycode_state_changed();
|
if (is_mod(page, id)) {
|
||||||
ev->usage_page = page;
|
explicit_modifiers = SELECT_MODS(encoded);
|
||||||
ev->keycode = id;
|
} else {
|
||||||
ev->implicit_modifiers = implicit_mods;
|
implicit_modifiers = SELECT_MODS(encoded);
|
||||||
ev->state = pressed;
|
}
|
||||||
ev->timestamp = timestamp;
|
|
||||||
return ev;
|
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});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,20 +9,16 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
|
|
||||||
struct layer_state_changed {
|
struct zmk_layer_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
uint8_t layer;
|
uint8_t layer;
|
||||||
bool state;
|
bool state;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(layer_state_changed);
|
ZMK_EVENT_DECLARE(zmk_layer_state_changed);
|
||||||
|
|
||||||
static inline struct layer_state_changed *create_layer_state_changed(uint8_t layer, bool state) {
|
static inline struct zmk_layer_state_changed_event *create_layer_state_changed(uint8_t layer,
|
||||||
struct layer_state_changed *ev = new_layer_state_changed();
|
bool state) {
|
||||||
ev->layer = layer;
|
return new_zmk_layer_state_changed((struct zmk_layer_state_changed){
|
||||||
ev->state = state;
|
.layer = layer, .state = state, .timestamp = k_uptime_get()});
|
||||||
ev->timestamp = k_uptime_get();
|
|
||||||
|
|
||||||
return ev;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,9 @@
|
||||||
#include <zmk/keys.h>
|
#include <zmk/keys.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
|
|
||||||
struct modifiers_state_changed {
|
struct zmk_modifiers_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
zmk_mod_flags_t modifiers;
|
zmk_mod_flags_t modifiers;
|
||||||
bool state;
|
bool state;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(modifiers_state_changed);
|
ZMK_EVENT_DECLARE(zmk_modifiers_state_changed);
|
||||||
|
|
||||||
inline struct modifiers_state_changed *create_modifiers_state_changed(zmk_mod_flags_t modifiers,
|
|
||||||
bool state) {
|
|
||||||
struct modifiers_state_changed *ev = new_modifiers_state_changed();
|
|
||||||
ev->modifiers = modifiers;
|
|
||||||
ev->state = state;
|
|
||||||
|
|
||||||
return ev;
|
|
||||||
}
|
|
|
@ -8,12 +8,10 @@
|
||||||
|
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
|
struct zmk_position_state_changed {
|
||||||
struct position_state_changed {
|
|
||||||
struct zmk_event_header header;
|
|
||||||
uint32_t position;
|
uint32_t position;
|
||||||
bool state;
|
bool state;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(position_state_changed);
|
ZMK_EVENT_DECLARE(zmk_position_state_changed);
|
|
@ -9,12 +9,10 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
|
struct zmk_sensor_event {
|
||||||
struct sensor_event {
|
|
||||||
struct zmk_event_header header;
|
|
||||||
uint8_t sensor_number;
|
uint8_t sensor_number;
|
||||||
const struct device *sensor;
|
const struct device *sensor;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(sensor_event);
|
ZMK_EVENT_DECLARE(zmk_sensor_event);
|
|
@ -12,9 +12,8 @@
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/usb.h>
|
#include <zmk/usb.h>
|
||||||
|
|
||||||
struct usb_conn_state_changed {
|
struct zmk_usb_conn_state_changed {
|
||||||
struct zmk_event_header header;
|
|
||||||
enum zmk_usb_conn_state conn_state;
|
enum zmk_usb_conn_state conn_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZMK_EVENT_DECLARE(usb_conn_state_changed);
|
ZMK_EVENT_DECLARE(zmk_usb_conn_state_changed);
|
17
app/include/zmk/events/wpm_state_changed.h
Normal file
17
app/include/zmk/events/wpm_state_changed.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#include <zmk/wpm.h>
|
||||||
|
|
||||||
|
struct zmk_wpm_state_changed {
|
||||||
|
int state;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZMK_EVENT_DECLARE(zmk_wpm_state_changed);
|
|
@ -166,8 +166,11 @@ struct zmk_hid_consumer_report {
|
||||||
struct zmk_hid_consumer_report_body body;
|
struct zmk_hid_consumer_report_body body;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
zmk_mod_flags_t zmk_hid_get_explicit_mods();
|
||||||
int zmk_hid_register_mod(zmk_mod_t modifier);
|
int zmk_hid_register_mod(zmk_mod_t modifier);
|
||||||
int zmk_hid_unregister_mod(zmk_mod_t modifier);
|
int zmk_hid_unregister_mod(zmk_mod_t modifier);
|
||||||
|
int zmk_hid_register_mods(zmk_mod_flags_t explicit_modifiers);
|
||||||
|
int zmk_hid_unregister_mods(zmk_mod_flags_t explicit_modifiers);
|
||||||
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers);
|
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers);
|
||||||
int zmk_hid_implicit_modifiers_release();
|
int zmk_hid_implicit_modifiers_release();
|
||||||
int zmk_hid_keyboard_press(zmk_key_t key);
|
int zmk_hid_keyboard_press(zmk_key_t key);
|
||||||
|
|
|
@ -19,3 +19,12 @@ int zmk_keymap_layer_to(uint8_t layer);
|
||||||
const char *zmk_keymap_layer_label(uint8_t layer);
|
const char *zmk_keymap_layer_label(uint8_t layer);
|
||||||
|
|
||||||
int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp);
|
int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp);
|
||||||
|
|
||||||
|
#define ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst) \
|
||||||
|
{ \
|
||||||
|
.behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(drv_inst, bindings, idx)), \
|
||||||
|
.param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param1), (0), \
|
||||||
|
(DT_PHA_BY_IDX(drv_inst, bindings, idx, param1))), \
|
||||||
|
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param2), (0), \
|
||||||
|
(DT_PHA_BY_IDX(drv_inst, bindings, idx, param2))), \
|
||||||
|
}
|
||||||
|
|
|
@ -19,3 +19,8 @@ struct zmk_key_event {
|
||||||
zmk_key_t key;
|
zmk_key_t key;
|
||||||
bool pressed;
|
bool pressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline bool is_mod(uint8_t usage_page, uint32_t keycode) {
|
||||||
|
return (keycode >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL &&
|
||||||
|
keycode <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI && usage_page == HID_USAGE_KEY);
|
||||||
|
}
|
9
app/include/zmk/wpm.h
Normal file
9
app/include/zmk/wpm.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int zmk_wpm_get_state();
|
|
@ -17,7 +17,7 @@ testcases=$(find $path -name native_posix.keymap -exec dirname \{\} \;)
|
||||||
num_cases=$(echo "$testcases" | wc -l)
|
num_cases=$(echo "$testcases" | wc -l)
|
||||||
if [ $num_cases -gt 1 ]; then
|
if [ $num_cases -gt 1 ]; then
|
||||||
echo "" > ./build/tests/pass-fail.log
|
echo "" > ./build/tests/pass-fail.log
|
||||||
echo "$testcases" | xargs -l -P 4 ./run-test.sh
|
echo "$testcases" | xargs -L 1 -P 4 ./run-test.sh
|
||||||
err=$?
|
err=$?
|
||||||
sort -k2 ./build/tests/pass-fail.log
|
sort -k2 ./build/tests/pass-fail.log
|
||||||
exit $err
|
exit $err
|
||||||
|
|
|
@ -29,7 +29,10 @@ static uint32_t activity_last_uptime;
|
||||||
#define MAX_SLEEP_MS CONFIG_ZMK_IDLE_SLEEP_TIMEOUT
|
#define MAX_SLEEP_MS CONFIG_ZMK_IDLE_SLEEP_TIMEOUT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int raise_event() { return ZMK_EVENT_RAISE(create_activity_state_changed(activity_state)); }
|
int raise_event() {
|
||||||
|
return ZMK_EVENT_RAISE(new_zmk_activity_state_changed(
|
||||||
|
(struct zmk_activity_state_changed){.state = activity_state}));
|
||||||
|
}
|
||||||
|
|
||||||
int set_state(enum zmk_activity_state state) {
|
int set_state(enum zmk_activity_state state) {
|
||||||
if (activity_state == state)
|
if (activity_state == state)
|
||||||
|
@ -41,7 +44,7 @@ int set_state(enum zmk_activity_state state) {
|
||||||
|
|
||||||
enum zmk_activity_state zmk_activity_get_state() { return activity_state; }
|
enum zmk_activity_state zmk_activity_get_state() { return activity_state; }
|
||||||
|
|
||||||
int activity_event_listener(const struct zmk_event_header *eh) {
|
int activity_event_listener(const zmk_event_t *eh) {
|
||||||
activity_last_uptime = k_uptime_get();
|
activity_last_uptime = k_uptime_get();
|
||||||
|
|
||||||
return set_state(ZMK_ACTIVITY_ACTIVE);
|
return set_state(ZMK_ACTIVITY_ACTIVE);
|
||||||
|
@ -74,7 +77,7 @@ int activity_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(activity, activity_event_listener);
|
ZMK_LISTENER(activity, activity_event_listener);
|
||||||
ZMK_SUBSCRIPTION(activity, position_state_changed);
|
ZMK_SUBSCRIPTION(activity, zmk_position_state_changed);
|
||||||
ZMK_SUBSCRIPTION(activity, sensor_event);
|
ZMK_SUBSCRIPTION(activity, zmk_sensor_event);
|
||||||
|
|
||||||
SYS_INIT(activity_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
SYS_INIT(activity_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
|
@ -45,9 +45,8 @@ static int zmk_battery_update(const struct device *battery) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct battery_state_changed *ev = new_battery_state_changed();
|
return ZMK_EVENT_RAISE(new_zmk_battery_state_changed(
|
||||||
ev->state_of_charge = state_of_charge.val1;
|
(struct zmk_battery_state_changed){.state_of_charge = state_of_charge.val1}));
|
||||||
return ZMK_EVENT_RAISE(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zmk_battery_work(struct k_work *work) {
|
static void zmk_battery_work(struct k_work *work) {
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
#include <drivers/behavior.h>
|
#include <drivers/behavior.h>
|
||||||
|
#include <zmk/keys.h>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
#include <zmk/matrix.h>
|
#include <zmk/matrix.h>
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zmk/events/position_state_changed.h>
|
#include <zmk/events/position_state_changed.h>
|
||||||
#include <zmk/events/keycode_state_changed.h>
|
#include <zmk/events/keycode_state_changed.h>
|
||||||
#include <zmk/events/modifiers_state_changed.h>
|
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -36,14 +36,10 @@ enum flavor {
|
||||||
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
|
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct behavior_hold_tap_behaviors {
|
|
||||||
struct zmk_behavior_binding tap;
|
|
||||||
struct zmk_behavior_binding hold;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct behavior_hold_tap_config {
|
struct behavior_hold_tap_config {
|
||||||
int tapping_term_ms;
|
int tapping_term_ms;
|
||||||
struct behavior_hold_tap_behaviors *behaviors;
|
char *hold_behavior_dev;
|
||||||
|
char *tap_behavior_dev;
|
||||||
enum flavor flavor;
|
enum flavor flavor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,9 +65,9 @@ struct active_hold_tap {
|
||||||
struct active_hold_tap *undecided_hold_tap = NULL;
|
struct active_hold_tap *undecided_hold_tap = NULL;
|
||||||
struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {};
|
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.
|
// We capture most position_state_changed events and some modifiers_state_changed events.
|
||||||
const struct zmk_event_header *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
|
const zmk_event_t *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
|
||||||
|
|
||||||
static int capture_event(const struct zmk_event_header *event) {
|
static int capture_event(const zmk_event_t *event) {
|
||||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||||
if (captured_events[i] == NULL) {
|
if (captured_events[i] == NULL) {
|
||||||
captured_events[i] = event;
|
captured_events[i] = event;
|
||||||
|
@ -81,17 +77,18 @@ static int capture_event(const struct zmk_event_header *event) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct position_state_changed *find_captured_keydown_event(uint32_t position) {
|
static struct zmk_position_state_changed *find_captured_keydown_event(uint32_t position) {
|
||||||
struct position_state_changed *last_match = NULL;
|
struct zmk_position_state_changed *last_match = NULL;
|
||||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||||
const struct zmk_event_header *eh = captured_events[i];
|
const zmk_event_t *eh = captured_events[i];
|
||||||
if (eh == NULL) {
|
if (eh == NULL) {
|
||||||
return last_match;
|
return last_match;
|
||||||
}
|
}
|
||||||
if (!is_position_state_changed(eh)) {
|
struct zmk_position_state_changed *position_event = as_zmk_position_state_changed(eh);
|
||||||
|
if (position_event == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct position_state_changed *position_event = cast_position_state_changed(eh);
|
|
||||||
if (position_event->position == position && position_event->state) {
|
if (position_event->position == position && position_event->state) {
|
||||||
last_match = position_event;
|
last_match = position_event;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +129,7 @@ static void release_captured_events() {
|
||||||
// [k1_down, k1_up, null, null, null, ...]
|
// [k1_down, k1_up, null, null, null, ...]
|
||||||
// now mt2 will start releasing it's own captured positions.
|
// now mt2 will start releasing it's own captured positions.
|
||||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||||
const struct zmk_event_header *captured_event = captured_events[i];
|
const zmk_event_t *captured_event = captured_events[i];
|
||||||
if (captured_event == NULL) {
|
if (captured_event == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -140,14 +137,13 @@ static void release_captured_events() {
|
||||||
if (undecided_hold_tap != NULL) {
|
if (undecided_hold_tap != NULL) {
|
||||||
k_msleep(10);
|
k_msleep(10);
|
||||||
}
|
}
|
||||||
if (is_position_state_changed(captured_event)) {
|
|
||||||
struct position_state_changed *position_event =
|
struct zmk_position_state_changed *position_event;
|
||||||
cast_position_state_changed(captured_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,
|
LOG_DBG("Releasing key position event for position %d %s", position_event->position,
|
||||||
(position_event->state ? "pressed" : "released"));
|
(position_event->state ? "pressed" : "released"));
|
||||||
} else {
|
} else if ((modifier_event = as_zmk_keycode_state_changed(captured_event)) != NULL) {
|
||||||
struct keycode_state_changed *modifier_event =
|
|
||||||
cast_keycode_state_changed(captured_event);
|
|
||||||
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode,
|
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode,
|
||||||
(modifier_event->state ? "pressed" : "released"));
|
(modifier_event->state ? "pressed" : "released"));
|
||||||
}
|
}
|
||||||
|
@ -290,11 +286,11 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome
|
||||||
|
|
||||||
struct zmk_behavior_binding binding;
|
struct zmk_behavior_binding binding;
|
||||||
if (hold_tap->is_hold) {
|
if (hold_tap->is_hold) {
|
||||||
binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev;
|
binding.behavior_dev = hold_tap->config->hold_behavior_dev;
|
||||||
binding.param1 = hold_tap->param_hold;
|
binding.param1 = hold_tap->param_hold;
|
||||||
binding.param2 = 0;
|
binding.param2 = 0;
|
||||||
} else {
|
} else {
|
||||||
binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev;
|
binding.behavior_dev = hold_tap->config->tap_behavior_dev;
|
||||||
binding.param1 = hold_tap->param_tap;
|
binding.param1 = hold_tap->param_tap;
|
||||||
binding.param2 = 0;
|
binding.param2 = 0;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +347,8 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
|
||||||
decide_hold_tap(hold_tap, HT_KEY_UP);
|
decide_hold_tap(hold_tap, HT_KEY_UP);
|
||||||
|
|
||||||
// todo: set up the binding and data items inside of the active_hold_tap struct
|
// todo: set up the binding and data items inside of the
|
||||||
|
// active_hhold_tap->config->behaviors->tap.behavior_dev;old_tap struct
|
||||||
struct zmk_behavior_binding_event sub_behavior_data = {
|
struct zmk_behavior_binding_event sub_behavior_data = {
|
||||||
.position = hold_tap->position,
|
.position = hold_tap->position,
|
||||||
.timestamp = hold_tap->timestamp,
|
.timestamp = hold_tap->timestamp,
|
||||||
|
@ -359,11 +356,11 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
|
||||||
struct zmk_behavior_binding sub_behavior_binding;
|
struct zmk_behavior_binding sub_behavior_binding;
|
||||||
if (hold_tap->is_hold) {
|
if (hold_tap->is_hold) {
|
||||||
sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev;
|
sub_behavior_binding.behavior_dev = hold_tap->config->hold_behavior_dev;
|
||||||
sub_behavior_binding.param1 = hold_tap->param_hold;
|
sub_behavior_binding.param1 = hold_tap->param_hold;
|
||||||
sub_behavior_binding.param2 = 0;
|
sub_behavior_binding.param2 = 0;
|
||||||
} else {
|
} else {
|
||||||
sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev;
|
sub_behavior_binding.behavior_dev = hold_tap->config->tap_behavior_dev;
|
||||||
sub_behavior_binding.param1 = hold_tap->param_tap;
|
sub_behavior_binding.param1 = hold_tap->param_tap;
|
||||||
sub_behavior_binding.param2 = 0;
|
sub_behavior_binding.param2 = 0;
|
||||||
}
|
}
|
||||||
|
@ -387,8 +384,8 @@ static const struct behavior_driver_api behavior_hold_tap_driver_api = {
|
||||||
.binding_released = on_hold_tap_binding_released,
|
.binding_released = on_hold_tap_binding_released,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int position_state_changed_listener(const struct zmk_event_header *eh) {
|
static int position_state_changed_listener(const zmk_event_t *eh) {
|
||||||
struct position_state_changed *ev = cast_position_state_changed(eh);
|
struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh);
|
||||||
|
|
||||||
if (undecided_hold_tap == NULL) {
|
if (undecided_hold_tap == NULL) {
|
||||||
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
|
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
|
||||||
|
@ -428,21 +425,16 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) {
|
||||||
return ZMK_EV_EVENT_CAPTURED;
|
return ZMK_EV_EVENT_CAPTURED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool only_mods(struct keycode_state_changed *ev) {
|
static int keycode_state_changed_listener(const zmk_event_t *eh) {
|
||||||
return ev->usage_page == HID_USAGE_KEY && ev->keycode >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL &&
|
|
||||||
ev->keycode <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
|
|
||||||
// we want to catch layer-up events too... how?
|
// we want to catch layer-up events too... how?
|
||||||
struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
||||||
|
|
||||||
if (undecided_hold_tap == NULL) {
|
if (undecided_hold_tap == NULL) {
|
||||||
// LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
|
// LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!only_mods(ev)) {
|
if (!is_mod(ev->usage_page, ev->keycode)) {
|
||||||
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
|
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
}
|
}
|
||||||
|
@ -455,19 +447,19 @@ static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
|
||||||
return ZMK_EV_EVENT_CAPTURED;
|
return ZMK_EV_EVENT_CAPTURED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int behavior_hold_tap_listener(const struct zmk_event_header *eh) {
|
int behavior_hold_tap_listener(const zmk_event_t *eh) {
|
||||||
if (is_position_state_changed(eh)) {
|
if (as_zmk_position_state_changed(eh) != NULL) {
|
||||||
return position_state_changed_listener(eh);
|
return position_state_changed_listener(eh);
|
||||||
} else if (is_keycode_state_changed(eh)) {
|
} else if (as_zmk_keycode_state_changed(eh) != NULL) {
|
||||||
return keycode_state_changed_listener(eh);
|
return keycode_state_changed_listener(eh);
|
||||||
}
|
}
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener);
|
ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener);
|
||||||
ZMK_SUBSCRIPTION(behavior_hold_tap, position_state_changed);
|
ZMK_SUBSCRIPTION(behavior_hold_tap, zmk_position_state_changed);
|
||||||
// this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
|
// this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
|
||||||
ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed);
|
ZMK_SUBSCRIPTION(behavior_hold_tap, zmk_keycode_state_changed);
|
||||||
|
|
||||||
void behavior_hold_tap_timer_work_handler(struct k_work *item) {
|
void behavior_hold_tap_timer_work_handler(struct k_work *item) {
|
||||||
struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work);
|
struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work);
|
||||||
|
@ -495,22 +487,11 @@ static int behavior_hold_tap_init(const struct device *dev) {
|
||||||
struct behavior_hold_tap_data {};
|
struct behavior_hold_tap_data {};
|
||||||
static struct behavior_hold_tap_data behavior_hold_tap_data;
|
static struct behavior_hold_tap_data behavior_hold_tap_data;
|
||||||
|
|
||||||
/* todo: get rid of unused param1 and param2. */
|
|
||||||
#define _TRANSFORM_ENTRY(idx, node) \
|
|
||||||
{ \
|
|
||||||
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
|
|
||||||
.param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \
|
|
||||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \
|
|
||||||
.param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \
|
|
||||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \
|
|
||||||
},
|
|
||||||
|
|
||||||
#define KP_INST(n) \
|
#define KP_INST(n) \
|
||||||
static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \
|
|
||||||
.hold = _TRANSFORM_ENTRY(0, n).tap = _TRANSFORM_ENTRY(1, n)}; \
|
|
||||||
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
||||||
.behaviors = &behavior_hold_tap_behaviors_##n, \
|
|
||||||
.tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \
|
.tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \
|
||||||
|
.hold_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 0)), \
|
||||||
|
.tap_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \
|
||||||
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
|
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
|
||||||
}; \
|
}; \
|
||||||
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
|
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
|
||||||
|
|
|
@ -22,14 +22,14 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
struct zmk_behavior_binding_event event) {
|
struct zmk_behavior_binding_event event) {
|
||||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||||
return ZMK_EVENT_RAISE(
|
return ZMK_EVENT_RAISE(
|
||||||
keycode_state_changed_from_encoded(binding->param1, true, event.timestamp));
|
zmk_keycode_state_changed_from_encoded(binding->param1, true, event.timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
struct zmk_behavior_binding_event event) {
|
struct zmk_behavior_binding_event event) {
|
||||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||||
return ZMK_EVENT_RAISE(
|
return ZMK_EVENT_RAISE(
|
||||||
keycode_state_changed_from_encoded(binding->param1, false, event.timestamp));
|
zmk_keycode_state_changed_from_encoded(binding->param1, false, event.timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
||||||
|
|
99
app/src/behaviors/behavior_mod_morph.c
Normal file
99
app/src/behaviors/behavior_mod_morph.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_mod_morph
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
|
#include <zmk/matrix.h>
|
||||||
|
#include <zmk/endpoints.h>
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#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>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
|
struct behavior_mod_morph_config {
|
||||||
|
struct zmk_behavior_binding normal_binding;
|
||||||
|
struct zmk_behavior_binding morph_binding;
|
||||||
|
zmk_mod_flags_t mods;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct behavior_mod_morph_data {
|
||||||
|
struct zmk_behavior_binding *pressed_binding;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int on_mod_morph_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||||
|
const struct behavior_mod_morph_config *cfg = dev->config;
|
||||||
|
struct behavior_mod_morph_data *data = dev->data;
|
||||||
|
|
||||||
|
if (data->pressed_binding != NULL) {
|
||||||
|
LOG_ERR("Can't press the same mod-morph twice");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zmk_hid_get_explicit_mods() & cfg->mods) {
|
||||||
|
data->pressed_binding = (struct zmk_behavior_binding *)&cfg->morph_binding;
|
||||||
|
} else {
|
||||||
|
data->pressed_binding = (struct zmk_behavior_binding *)&cfg->normal_binding;
|
||||||
|
}
|
||||||
|
return behavior_keymap_binding_pressed(data->pressed_binding, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||||
|
struct behavior_mod_morph_data *data = dev->data;
|
||||||
|
|
||||||
|
if (data->pressed_binding == NULL) {
|
||||||
|
LOG_ERR("Mod-morph already released");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zmk_behavior_binding *pressed_binding = data->pressed_binding;
|
||||||
|
data->pressed_binding = NULL;
|
||||||
|
return behavior_keymap_binding_released(pressed_binding, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_mod_morph_driver_api = {
|
||||||
|
.binding_pressed = on_mod_morph_binding_pressed,
|
||||||
|
.binding_released = on_mod_morph_binding_released,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int behavior_mod_morph_init(const struct device *dev) { return 0; }
|
||||||
|
|
||||||
|
#define _TRANSFORM_ENTRY(idx, node) \
|
||||||
|
{ \
|
||||||
|
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
|
||||||
|
.param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \
|
||||||
|
(DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \
|
||||||
|
.param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \
|
||||||
|
(DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define KP_INST(n) \
|
||||||
|
static struct behavior_mod_morph_config behavior_mod_morph_config_##n = { \
|
||||||
|
.normal_binding = _TRANSFORM_ENTRY(0, n), \
|
||||||
|
.morph_binding = _TRANSFORM_ENTRY(1, n), \
|
||||||
|
.mods = DT_INST_PROP(n, mods), \
|
||||||
|
}; \
|
||||||
|
static struct behavior_mod_morph_data behavior_mod_morph_data_##n = {}; \
|
||||||
|
DEVICE_AND_API_INIT(behavior_mod_morph_##n, DT_INST_LABEL(n), behavior_mod_morph_init, \
|
||||||
|
&behavior_mod_morph_data_##n, &behavior_mod_morph_config_##n, APPLICATION, \
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mod_morph_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
||||||
|
|
||||||
|
#endif
|
|
@ -45,12 +45,12 @@ static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding,
|
||||||
|
|
||||||
LOG_DBG("SEND %d", keycode);
|
LOG_DBG("SEND %d", keycode);
|
||||||
|
|
||||||
ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, true, timestamp));
|
ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, true, timestamp));
|
||||||
|
|
||||||
// TODO: Better way to do this?
|
// TODO: Better way to do this?
|
||||||
k_msleep(5);
|
k_msleep(5);
|
||||||
|
|
||||||
return ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, false, timestamp));
|
return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, false, timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
|
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <zmk/events/keycode_state_changed.h>
|
#include <zmk/events/keycode_state_changed.h>
|
||||||
#include <zmk/events/modifiers_state_changed.h>
|
#include <zmk/events/modifiers_state_changed.h>
|
||||||
#include <zmk/hid.h>
|
#include <zmk/hid.h>
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
struct behavior_sticky_key_config {
|
struct behavior_sticky_key_config {
|
||||||
uint32_t release_after_ms;
|
uint32_t release_after_ms;
|
||||||
|
bool quick_release;
|
||||||
struct zmk_behavior_binding behavior;
|
struct zmk_behavior_binding behavior;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,11 +177,11 @@ static const struct behavior_driver_api behavior_sticky_key_driver_api = {
|
||||||
.binding_released = on_sticky_key_binding_released,
|
.binding_released = on_sticky_key_binding_released,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sticky_key_keycode_state_changed_listener(const struct zmk_event_header *eh) {
|
static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) {
|
||||||
if (!is_keycode_state_changed(eh)) {
|
struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
||||||
|
if (ev == NULL) {
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
}
|
}
|
||||||
struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
|
||||||
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
|
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
|
||||||
struct active_sticky_key *sticky_key = &active_sticky_keys[i];
|
struct active_sticky_key *sticky_key = &active_sticky_keys[i];
|
||||||
if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) {
|
if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) {
|
||||||
|
@ -209,10 +211,12 @@ static int sticky_key_keycode_state_changed_listener(const struct zmk_event_head
|
||||||
}
|
}
|
||||||
if (sticky_key->timer_started) {
|
if (sticky_key->timer_started) {
|
||||||
stop_timer(sticky_key);
|
stop_timer(sticky_key);
|
||||||
|
if (sticky_key->config->quick_release) {
|
||||||
|
release_sticky_key_behavior(sticky_key, ev->timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sticky_key->modified_key_usage_page = ev->usage_page;
|
sticky_key->modified_key_usage_page = ev->usage_page;
|
||||||
sticky_key->modified_key_keycode = ev->keycode;
|
sticky_key->modified_key_keycode = ev->keycode;
|
||||||
|
|
||||||
} else { // key up
|
} else { // key up
|
||||||
if (sticky_key->timer_started &&
|
if (sticky_key->timer_started &&
|
||||||
sticky_key->modified_key_usage_page == ev->usage_page &&
|
sticky_key->modified_key_usage_page == ev->usage_page &&
|
||||||
|
@ -226,7 +230,7 @@ static int sticky_key_keycode_state_changed_listener(const struct zmk_event_head
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(behavior_sticky_key, sticky_key_keycode_state_changed_listener);
|
ZMK_LISTENER(behavior_sticky_key, sticky_key_keycode_state_changed_listener);
|
||||||
ZMK_SUBSCRIPTION(behavior_sticky_key, keycode_state_changed);
|
ZMK_SUBSCRIPTION(behavior_sticky_key, zmk_keycode_state_changed);
|
||||||
|
|
||||||
void behavior_sticky_key_timer_handler(struct k_work *item) {
|
void behavior_sticky_key_timer_handler(struct k_work *item) {
|
||||||
struct active_sticky_key *sticky_key =
|
struct active_sticky_key *sticky_key =
|
||||||
|
@ -257,18 +261,11 @@ static int behavior_sticky_key_init(const struct device *dev) {
|
||||||
struct behavior_sticky_key_data {};
|
struct behavior_sticky_key_data {};
|
||||||
static struct behavior_sticky_key_data behavior_sticky_key_data;
|
static struct behavior_sticky_key_data behavior_sticky_key_data;
|
||||||
|
|
||||||
#define _TRANSFORM_ENTRY(idx, node) \
|
|
||||||
{ \
|
|
||||||
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
|
|
||||||
.param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \
|
|
||||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \
|
|
||||||
.param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \
|
|
||||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \
|
|
||||||
},
|
|
||||||
|
|
||||||
#define KP_INST(n) \
|
#define KP_INST(n) \
|
||||||
static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
|
static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
|
||||||
.behavior = _TRANSFORM_ENTRY(0, n).release_after_ms = DT_INST_PROP(n, release_after_ms), \
|
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \
|
||||||
|
.release_after_ms = DT_INST_PROP(n, release_after_ms), \
|
||||||
|
.quick_release = DT_INST_PROP(n, quick_release), \
|
||||||
}; \
|
}; \
|
||||||
DEVICE_AND_API_INIT(behavior_sticky_key_##n, DT_INST_LABEL(n), behavior_sticky_key_init, \
|
DEVICE_AND_API_INIT(behavior_sticky_key_##n, DT_INST_LABEL(n), behavior_sticky_key_init, \
|
||||||
&behavior_sticky_key_data, &behavior_sticky_key_config_##n, APPLICATION, \
|
&behavior_sticky_key_data, &behavior_sticky_key_config_##n, APPLICATION, \
|
||||||
|
|
|
@ -63,6 +63,8 @@ static uint8_t active_profile;
|
||||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||||
|
|
||||||
|
BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16");
|
||||||
|
|
||||||
#define IS_HOST_PERIPHERAL \
|
#define IS_HOST_PERIPHERAL \
|
||||||
(!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
(!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||||
#define IS_SPLIT_PERIPHERAL \
|
#define IS_SPLIT_PERIPHERAL \
|
||||||
|
@ -92,11 +94,8 @@ static bt_addr_le_t peripheral_addr;
|
||||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||||
|
|
||||||
static void raise_profile_changed_event() {
|
static void raise_profile_changed_event() {
|
||||||
struct ble_active_profile_changed *ev = new_ble_active_profile_changed();
|
ZMK_EVENT_RAISE(new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){
|
||||||
ev->index = active_profile;
|
.index = active_profile, .profile = &profiles[active_profile]}));
|
||||||
ev->profile = &profiles[active_profile];
|
|
||||||
|
|
||||||
ZMK_EVENT_RAISE(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raise_profile_changed_event_callback(struct k_work *work) {
|
static void raise_profile_changed_event_callback(struct k_work *work) {
|
||||||
|
@ -376,7 +375,10 @@ static void connected(struct bt_conn *conn, uint8_t err) {
|
||||||
|
|
||||||
LOG_DBG("Connected %s", log_strdup(addr));
|
LOG_DBG("Connected %s", log_strdup(addr));
|
||||||
|
|
||||||
bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 30, 400));
|
err = bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 30, 400));
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("Failed to update LE parameters (err %d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
#if IS_SPLIT_PERIPHERAL
|
#if IS_SPLIT_PERIPHERAL
|
||||||
bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
|
bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||||
|
@ -423,10 +425,20 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency,
|
||||||
|
uint16_t timeout) {
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
LOG_DBG("%s: interval %d latency %d timeout %d", log_strdup(addr), interval, latency, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
static struct bt_conn_cb conn_callbacks = {
|
static struct bt_conn_cb conn_callbacks = {
|
||||||
.connected = connected,
|
.connected = connected,
|
||||||
.disconnected = disconnected,
|
.disconnected = disconnected,
|
||||||
.security_changed = security_changed,
|
.security_changed = security_changed,
|
||||||
|
.le_param_updated = le_param_updated,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct active_combo {
|
||||||
// key_positions_pressed is filled with key_positions when the combo is pressed.
|
// key_positions_pressed is filled with key_positions when the combo is pressed.
|
||||||
// The keys are removed from this array when they are released.
|
// The keys are removed from this array when they are released.
|
||||||
// Once this array is empty, the behavior is released.
|
// Once this array is empty, the behavior is released.
|
||||||
struct position_state_changed *key_positions_pressed[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO];
|
const zmk_event_t *key_positions_pressed[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct combo_candidate {
|
struct combo_candidate {
|
||||||
|
@ -52,7 +52,7 @@ struct combo_candidate {
|
||||||
};
|
};
|
||||||
|
|
||||||
// set of keys pressed
|
// set of keys pressed
|
||||||
struct position_state_changed *pressed_keys[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO] = {NULL};
|
const zmk_event_t *pressed_keys[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO] = {NULL};
|
||||||
// the set of candidate combos based on the currently pressed_keys
|
// the set of candidate combos based on the currently pressed_keys
|
||||||
struct combo_candidate candidates[CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY];
|
struct combo_candidate candidates[CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY];
|
||||||
// the last candidate that was completely pressed
|
// the last candidate that was completely pressed
|
||||||
|
@ -202,7 +202,7 @@ static int clear_candidates() {
|
||||||
return CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY;
|
return CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int capture_pressed_key(struct position_state_changed *ev) {
|
static int capture_pressed_key(const zmk_event_t *ev) {
|
||||||
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) {
|
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) {
|
||||||
if (pressed_keys[i] != NULL) {
|
if (pressed_keys[i] != NULL) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -228,7 +228,7 @@ static void release_pressed_keys() {
|
||||||
if (pressed_keys[i] == NULL) {
|
if (pressed_keys[i] == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct position_state_changed *captured_event = pressed_keys[i];
|
const zmk_event_t *captured_event = pressed_keys[i];
|
||||||
pressed_keys[i] = NULL;
|
pressed_keys[i] = NULL;
|
||||||
ZMK_EVENT_RAISE(captured_event);
|
ZMK_EVENT_RAISE(captured_event);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,8 @@ static void activate_combo(struct combo_cfg *combo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
move_pressed_keys_to_active_combo(active_combo);
|
move_pressed_keys_to_active_combo(active_combo);
|
||||||
press_combo_behavior(combo, active_combo->key_positions_pressed[0]->timestamp);
|
press_combo_behavior(
|
||||||
|
combo, as_zmk_position_state_changed(active_combo->key_positions_pressed[0])->timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deactivate_combo(int active_combo_index) {
|
static void deactivate_combo(int active_combo_index) {
|
||||||
|
@ -314,10 +315,11 @@ static bool release_combo_key(int32_t position, int64_t timestamp) {
|
||||||
for (int i = 0; i < active_combo->combo->key_position_len; i++) {
|
for (int i = 0; i < active_combo->combo->key_position_len; i++) {
|
||||||
if (active_combo->key_positions_pressed[i] == NULL) {
|
if (active_combo->key_positions_pressed[i] == NULL) {
|
||||||
all_keys_pressed = false;
|
all_keys_pressed = false;
|
||||||
} else if (active_combo->key_positions_pressed[i]->position != position) {
|
} else if (as_zmk_position_state_changed(active_combo->key_positions_pressed[i])
|
||||||
|
->position != position) {
|
||||||
all_keys_released = false;
|
all_keys_released = false;
|
||||||
} else { // not null and position matches
|
} else { // not null and position matches
|
||||||
k_free(active_combo->key_positions_pressed[i]);
|
ZMK_EVENT_FREE(active_combo->key_positions_pressed[i]);
|
||||||
active_combo->key_positions_pressed[i] = NULL;
|
active_combo->key_positions_pressed[i] = NULL;
|
||||||
key_released = true;
|
key_released = true;
|
||||||
}
|
}
|
||||||
|
@ -362,16 +364,16 @@ static void update_timeout_task() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int position_state_down(struct position_state_changed *ev) {
|
static int position_state_down(const zmk_event_t *ev, struct zmk_position_state_changed *data) {
|
||||||
int num_candidates;
|
int num_candidates;
|
||||||
if (candidates[0].combo == NULL) {
|
if (candidates[0].combo == NULL) {
|
||||||
num_candidates = setup_candidates_for_first_keypress(ev->position, ev->timestamp);
|
num_candidates = setup_candidates_for_first_keypress(data->position, data->timestamp);
|
||||||
if (num_candidates == 0) {
|
if (num_candidates == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
filter_timed_out_candidates(ev->timestamp);
|
filter_timed_out_candidates(data->timestamp);
|
||||||
num_candidates = filter_candidates(ev->position);
|
num_candidates = filter_candidates(data->position);
|
||||||
}
|
}
|
||||||
update_timeout_task();
|
update_timeout_task();
|
||||||
|
|
||||||
|
@ -395,7 +397,7 @@ static int position_state_down(struct position_state_changed *ev) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int position_state_up(struct position_state_changed *ev) {
|
static int position_state_up(struct zmk_position_state_changed *ev) {
|
||||||
cleanup();
|
cleanup();
|
||||||
if (release_combo_key(ev->position, ev->timestamp)) {
|
if (release_combo_key(ev->position, ev->timestamp)) {
|
||||||
return ZMK_EV_EVENT_HANDLED;
|
return ZMK_EV_EVENT_HANDLED;
|
||||||
|
@ -415,21 +417,21 @@ static void combo_timeout_handler(struct k_work *item) {
|
||||||
update_timeout_task();
|
update_timeout_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int position_state_changed_listener(const struct zmk_event_header *eh) {
|
static int position_state_changed_listener(const zmk_event_t *ev) {
|
||||||
if (!is_position_state_changed(eh)) {
|
struct zmk_position_state_changed *data = as_zmk_position_state_changed(ev);
|
||||||
|
if (data == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct position_state_changed *ev = cast_position_state_changed(eh);
|
if (data->state) { // keydown
|
||||||
if (ev->state) { // keydown
|
return position_state_down(ev, data);
|
||||||
return position_state_down(ev);
|
|
||||||
} else { // keyup
|
} else { // keyup
|
||||||
return position_state_up(ev);
|
return position_state_up(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(combo, position_state_changed_listener);
|
ZMK_LISTENER(combo, position_state_changed_listener);
|
||||||
ZMK_SUBSCRIPTION(combo, position_state_changed);
|
ZMK_SUBSCRIPTION(combo, zmk_position_state_changed);
|
||||||
|
|
||||||
// todo: remove this once #506 is merged and #include <zmk/keymap.h>
|
// todo: remove this once #506 is merged and #include <zmk/keymap.h>
|
||||||
#define KEY_BINDING_TO_STRUCT(idx, drv_inst) \
|
#define KEY_BINDING_TO_STRUCT(idx, drv_inst) \
|
||||||
|
|
|
@ -75,8 +75,12 @@ int zmk_display_init() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int display_event_handler(const struct zmk_event_header *eh) {
|
int display_event_handler(const zmk_event_t *eh) {
|
||||||
struct activity_state_changed *ev = cast_activity_state_changed(eh);
|
struct zmk_activity_state_changed *ev = as_zmk_activity_state_changed(eh);
|
||||||
|
if (ev == NULL) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ev->state) {
|
switch (ev->state) {
|
||||||
case ZMK_ACTIVITY_ACTIVE:
|
case ZMK_ACTIVITY_ACTIVE:
|
||||||
start_display_updates();
|
start_display_updates();
|
||||||
|
@ -93,4 +97,4 @@ int display_event_handler(const struct zmk_event_header *eh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(display, display_event_handler);
|
ZMK_LISTENER(display, display_event_handler);
|
||||||
ZMK_SUBSCRIPTION(display, activity_state_changed);
|
ZMK_SUBSCRIPTION(display, zmk_activity_state_changed);
|
|
@ -7,6 +7,7 @@
|
||||||
#include <zmk/display/widgets/output_status.h>
|
#include <zmk/display/widgets/output_status.h>
|
||||||
#include <zmk/display/widgets/battery_status.h>
|
#include <zmk/display/widgets/battery_status.h>
|
||||||
#include <zmk/display/widgets/layer_status.h>
|
#include <zmk/display/widgets/layer_status.h>
|
||||||
|
#include <zmk/display/widgets/wpm_status.h>
|
||||||
#include <zmk/display/status_screen.h>
|
#include <zmk/display/status_screen.h>
|
||||||
|
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
|
@ -24,6 +25,10 @@ static struct zmk_widget_output_status output_status_widget;
|
||||||
static struct zmk_widget_layer_status layer_status_widget;
|
static struct zmk_widget_layer_status layer_status_widget;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_WIDGET_WPM_STATUS)
|
||||||
|
static struct zmk_widget_wpm_status wpm_status_widget;
|
||||||
|
#endif
|
||||||
|
|
||||||
lv_obj_t *zmk_display_status_screen() {
|
lv_obj_t *zmk_display_status_screen() {
|
||||||
lv_obj_t *screen;
|
lv_obj_t *screen;
|
||||||
|
|
||||||
|
@ -47,5 +52,10 @@ lv_obj_t *zmk_display_status_screen() {
|
||||||
0, 0);
|
0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_WIDGET_WPM_STATUS)
|
||||||
|
zmk_widget_wpm_status_init(&wpm_status_widget, screen);
|
||||||
|
lv_obj_align(zmk_widget_wpm_status_obj(&wpm_status_widget), NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -12,
|
||||||
|
0);
|
||||||
|
#endif
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
target_sources_ifdef(CONFIG_ZMK_WIDGET_BATTERY_STATUS app PRIVATE battery_status.c)
|
target_sources_ifdef(CONFIG_ZMK_WIDGET_BATTERY_STATUS app PRIVATE battery_status.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_WIDGET_OUTPUT_STATUS app PRIVATE output_status.c)
|
target_sources_ifdef(CONFIG_ZMK_WIDGET_OUTPUT_STATUS app PRIVATE output_status.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_WIDGET_LAYER_STATUS app PRIVATE layer_status.c)
|
target_sources_ifdef(CONFIG_ZMK_WIDGET_LAYER_STATUS app PRIVATE layer_status.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_WIDGET_WPM_STATUS app PRIVATE wpm_status.c)
|
||||||
|
|
|
@ -23,4 +23,11 @@ config ZMK_WIDGET_OUTPUT_STATUS
|
||||||
select LVGL_USE_LABEL
|
select LVGL_USE_LABEL
|
||||||
select LVGL_FONT_MONTSERRAT_16
|
select LVGL_FONT_MONTSERRAT_16
|
||||||
|
|
||||||
|
config ZMK_WIDGET_WPM_STATUS
|
||||||
|
bool "Widget for displaying typed words per minute"
|
||||||
|
depends on !ZMK_SPLIT || ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||||
|
select LVGL_USE_LABEL
|
||||||
|
select LVGL_FONT_MONTSERRAT_16
|
||||||
|
select ZMK_WPM
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -75,14 +75,14 @@ lv_obj_t *zmk_widget_battery_status_obj(struct zmk_widget_battery_status *widget
|
||||||
return widget->obj;
|
return widget->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
int battery_status_listener(const struct zmk_event_header *eh) {
|
int battery_status_listener(const zmk_event_t *eh) {
|
||||||
struct zmk_widget_battery_status *widget;
|
struct zmk_widget_battery_status *widget;
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_symbol(widget->obj); }
|
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_symbol(widget->obj); }
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(widget_battery_status, battery_status_listener)
|
ZMK_LISTENER(widget_battery_status, battery_status_listener)
|
||||||
ZMK_SUBSCRIPTION(widget_battery_status, battery_state_changed);
|
ZMK_SUBSCRIPTION(widget_battery_status, zmk_battery_state_changed);
|
||||||
#if IS_ENABLED(CONFIG_USB)
|
#if IS_ENABLED(CONFIG_USB)
|
||||||
ZMK_SUBSCRIPTION(widget_battery_status, usb_conn_state_changed);
|
ZMK_SUBSCRIPTION(widget_battery_status, zmk_usb_conn_state_changed);
|
||||||
#endif /* IS_ENABLED(CONFIG_USB) */
|
#endif /* IS_ENABLED(CONFIG_USB) */
|
||||||
|
|
|
@ -69,11 +69,11 @@ lv_obj_t *zmk_widget_layer_status_obj(struct zmk_widget_layer_status *widget) {
|
||||||
return widget->obj;
|
return widget->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
int layer_status_listener(const struct zmk_event_header *eh) {
|
int layer_status_listener(const zmk_event_t *eh) {
|
||||||
struct zmk_widget_layer_status *widget;
|
struct zmk_widget_layer_status *widget;
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_layer_symbol(widget->obj); }
|
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_layer_symbol(widget->obj); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(widget_layer_status, layer_status_listener)
|
ZMK_LISTENER(widget_layer_status, layer_status_listener)
|
||||||
ZMK_SUBSCRIPTION(widget_layer_status, layer_state_changed);
|
ZMK_SUBSCRIPTION(widget_layer_status, zmk_layer_state_changed);
|
|
@ -79,7 +79,7 @@ lv_obj_t *zmk_widget_output_status_obj(struct zmk_widget_output_status *widget)
|
||||||
return widget->obj;
|
return widget->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
int output_status_listener(const struct zmk_event_header *eh) {
|
int output_status_listener(const zmk_event_t *eh) {
|
||||||
struct zmk_widget_output_status *widget;
|
struct zmk_widget_output_status *widget;
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_status_symbol(widget->obj); }
|
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_status_symbol(widget->obj); }
|
||||||
return ZMK_EV_EVENT_BUBBLE;
|
return ZMK_EV_EVENT_BUBBLE;
|
||||||
|
@ -87,8 +87,8 @@ int output_status_listener(const struct zmk_event_header *eh) {
|
||||||
|
|
||||||
ZMK_LISTENER(widget_output_status, output_status_listener)
|
ZMK_LISTENER(widget_output_status, output_status_listener)
|
||||||
#if defined(CONFIG_USB)
|
#if defined(CONFIG_USB)
|
||||||
ZMK_SUBSCRIPTION(widget_output_status, usb_conn_state_changed);
|
ZMK_SUBSCRIPTION(widget_output_status, zmk_usb_conn_state_changed);
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ZMK_BLE)
|
#if defined(CONFIG_ZMK_BLE)
|
||||||
ZMK_SUBSCRIPTION(widget_output_status, ble_active_profile_changed);
|
ZMK_SUBSCRIPTION(widget_output_status, zmk_ble_active_profile_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
67
app/src/display/widgets/wpm_status.c
Normal file
67
app/src/display/widgets/wpm_status.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#include <zmk/display/widgets/wpm_status.h>
|
||||||
|
#include <zmk/events/wpm_state_changed.h>
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#include <zmk/endpoints.h>
|
||||||
|
#include <zmk/wpm.h>
|
||||||
|
|
||||||
|
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
|
||||||
|
static lv_style_t label_style;
|
||||||
|
|
||||||
|
static bool style_initialized = false;
|
||||||
|
|
||||||
|
void wpm_status_init() {
|
||||||
|
if (style_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
style_initialized = true;
|
||||||
|
lv_style_init(&label_style);
|
||||||
|
lv_style_set_text_color(&label_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
||||||
|
lv_style_set_text_font(&label_style, LV_STATE_DEFAULT, &lv_font_montserrat_12);
|
||||||
|
lv_style_set_text_letter_space(&label_style, LV_STATE_DEFAULT, 1);
|
||||||
|
lv_style_set_text_line_space(&label_style, LV_STATE_DEFAULT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_wpm_symbol(lv_obj_t *label, int wpm) {
|
||||||
|
char text[4] = {};
|
||||||
|
|
||||||
|
LOG_DBG("WPM changed to %i", wpm);
|
||||||
|
sprintf(text, "%i ", wpm);
|
||||||
|
|
||||||
|
lv_label_set_text(label, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_widget_wpm_status_init(struct zmk_widget_wpm_status *widget, lv_obj_t *parent) {
|
||||||
|
wpm_status_init();
|
||||||
|
widget->obj = lv_label_create(parent, NULL);
|
||||||
|
lv_obj_add_style(widget->obj, LV_LABEL_PART_MAIN, &label_style);
|
||||||
|
lv_label_set_align(widget->obj, LV_LABEL_ALIGN_RIGHT);
|
||||||
|
|
||||||
|
lv_obj_set_size(widget->obj, 40, 15);
|
||||||
|
set_wpm_symbol(widget->obj, 0);
|
||||||
|
|
||||||
|
sys_slist_append(&widgets, &widget->node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_obj_t *zmk_widget_wpm_status_obj(struct zmk_widget_wpm_status *widget) { return widget->obj; }
|
||||||
|
|
||||||
|
int wpm_status_listener(const zmk_event_t *eh) {
|
||||||
|
struct zmk_wpm_state_changed *ev = as_zmk_wpm_state_changed(eh);
|
||||||
|
struct zmk_widget_wpm_status *widget;
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_wpm_symbol(widget->obj, ev->state); }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_LISTENER(widget_wpm_status, wpm_status_listener)
|
||||||
|
ZMK_SUBSCRIPTION(widget_wpm_status, zmk_wpm_state_changed);
|
|
@ -245,17 +245,17 @@ static void update_current_endpoint() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int endpoint_listener(const struct zmk_event_header *eh) {
|
static int endpoint_listener(const zmk_event_t *eh) {
|
||||||
update_current_endpoint();
|
update_current_endpoint();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(endpoint_listener, endpoint_listener);
|
ZMK_LISTENER(endpoint_listener, endpoint_listener);
|
||||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||||
ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed);
|
ZMK_SUBSCRIPTION(endpoint_listener, zmk_usb_conn_state_changed);
|
||||||
#endif
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||||
ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed);
|
ZMK_SUBSCRIPTION(endpoint_listener, zmk_ble_active_profile_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SYS_INIT(zmk_endpoints_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
SYS_INIT(zmk_endpoints_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
|
@ -17,7 +17,7 @@ extern struct zmk_event_type *__event_type_end[];
|
||||||
extern struct zmk_event_subscription __event_subscriptions_start[];
|
extern struct zmk_event_subscription __event_subscriptions_start[];
|
||||||
extern struct zmk_event_subscription __event_subscriptions_end[];
|
extern struct zmk_event_subscription __event_subscriptions_end[];
|
||||||
|
|
||||||
int zmk_event_manager_handle_from(struct zmk_event_header *event, uint8_t start_index) {
|
int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||||
for (int i = start_index; i < len; i++) {
|
for (int i = start_index; i < len; i++) {
|
||||||
|
@ -48,12 +48,9 @@ release:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_event_manager_raise(struct zmk_event_header *event) {
|
int zmk_event_manager_raise(zmk_event_t *event) { return zmk_event_manager_handle_from(event, 0); }
|
||||||
return zmk_event_manager_handle_from(event, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int zmk_event_manager_raise_after(struct zmk_event_header *event,
|
int zmk_event_manager_raise_after(zmk_event_t *event, const struct zmk_listener *listener) {
|
||||||
const struct zmk_listener *listener) {
|
|
||||||
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
||||||
|
@ -68,8 +65,7 @@ int zmk_event_manager_raise_after(struct zmk_event_header *event,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_event_manager_raise_at(struct zmk_event_header *event,
|
int zmk_event_manager_raise_at(zmk_event_t *event, const struct zmk_listener *listener) {
|
||||||
const struct zmk_listener *listener) {
|
|
||||||
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
||||||
|
@ -84,6 +80,6 @@ int zmk_event_manager_raise_at(struct zmk_event_header *event,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_event_manager_release(struct zmk_event_header *event) {
|
int zmk_event_manager_release(zmk_event_t *event) {
|
||||||
return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
|
return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/activity_state_changed.h>
|
#include <zmk/events/activity_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(activity_state_changed);
|
ZMK_EVENT_IMPL(zmk_activity_state_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/battery_state_changed.h>
|
#include <zmk/events/battery_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(battery_state_changed);
|
ZMK_EVENT_IMPL(zmk_battery_state_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/ble_active_profile_changed.h>
|
#include <zmk/events/ble_active_profile_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(ble_active_profile_changed);
|
ZMK_EVENT_IMPL(zmk_ble_active_profile_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/keycode_state_changed.h>
|
#include <zmk/events/keycode_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(keycode_state_changed);
|
ZMK_EVENT_IMPL(zmk_keycode_state_changed);
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/layer_state_changed.h>
|
#include <zmk/events/layer_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(layer_state_changed);
|
ZMK_EVENT_IMPL(zmk_layer_state_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/modifiers_state_changed.h>
|
#include <zmk/events/modifiers_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(modifiers_state_changed);
|
ZMK_EVENT_IMPL(zmk_modifiers_state_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/position_state_changed.h>
|
#include <zmk/events/position_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(position_state_changed);
|
ZMK_EVENT_IMPL(zmk_position_state_changed);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/sensor_event.h>
|
#include <zmk/events/sensor_event.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(sensor_event);
|
ZMK_EVENT_IMPL(zmk_sensor_event);
|
|
@ -7,4 +7,4 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <zmk/events/usb_conn_state_changed.h>
|
#include <zmk/events/usb_conn_state_changed.h>
|
||||||
|
|
||||||
ZMK_EVENT_IMPL(usb_conn_state_changed);
|
ZMK_EVENT_IMPL(zmk_usb_conn_state_changed);
|
10
app/src/events/wpm_state_changed.c
Normal file
10
app/src/events/wpm_state_changed.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <zmk/events/wpm_state_changed.h>
|
||||||
|
|
||||||
|
ZMK_EVENT_IMPL(zmk_wpm_state_changed);
|
|
@ -26,6 +26,8 @@ static zmk_mod_flags_t explicit_modifiers = 0;
|
||||||
LOG_DBG("Modifiers set to 0x%02X", keyboard_report.body.modifiers); \
|
LOG_DBG("Modifiers set to 0x%02X", keyboard_report.body.modifiers); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zmk_mod_flags_t zmk_hid_get_explicit_mods() { return explicit_modifiers; }
|
||||||
|
|
||||||
int zmk_hid_register_mod(zmk_mod_t modifier) {
|
int zmk_hid_register_mod(zmk_mod_t modifier) {
|
||||||
explicit_modifier_counts[modifier]++;
|
explicit_modifier_counts[modifier]++;
|
||||||
LOG_DBG("Modifier %d count %d", modifier, explicit_modifier_counts[modifier]);
|
LOG_DBG("Modifier %d count %d", modifier, explicit_modifier_counts[modifier]);
|
||||||
|
@ -49,13 +51,33 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmk_hid_register_mods(zmk_mod_flags_t modifiers) {
|
||||||
|
for (zmk_mod_t i = 0; i < 8; i++) {
|
||||||
|
if (modifiers & (1 << i)) {
|
||||||
|
zmk_hid_register_mod(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) {
|
||||||
|
for (zmk_mod_t i = 0; i < 8; i++) {
|
||||||
|
if (modifiers & (1 << i)) {
|
||||||
|
zmk_hid_unregister_mod(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define TOGGLE_KEYBOARD(match, val) \
|
#define TOGGLE_KEYBOARD(match, val) \
|
||||||
for (int idx = 0; idx < ZMK_HID_KEYBOARD_NKRO_SIZE; idx++) { \
|
for (int idx = 0; idx < ZMK_HID_KEYBOARD_NKRO_SIZE; idx++) { \
|
||||||
if (keyboard_report.body.keys[idx] != match) { \
|
if (keyboard_report.body.keys[idx] != match) { \
|
||||||
continue; \
|
continue; \
|
||||||
} \
|
} \
|
||||||
keyboard_report.body.keys[idx] = val; \
|
keyboard_report.body.keys[idx] = val; \
|
||||||
break; \
|
if (val) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TOGGLE_CONSUMER(match, val) \
|
#define TOGGLE_CONSUMER(match, val) \
|
||||||
|
@ -64,7 +86,9 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) {
|
||||||
continue; \
|
continue; \
|
||||||
} \
|
} \
|
||||||
consumer_report.body.keys[idx] = val; \
|
consumer_report.body.keys[idx] = val; \
|
||||||
break; \
|
if (val) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers) {
|
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers) {
|
||||||
|
|
|
@ -16,71 +16,71 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <dt-bindings/zmk/hid_usage_pages.h>
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
||||||
#include <zmk/endpoints.h>
|
#include <zmk/endpoints.h>
|
||||||
|
|
||||||
static int hid_listener_keycode_pressed(uint16_t usage_page, uint32_t keycode,
|
static int hid_listener_keycode_pressed(const struct zmk_keycode_state_changed *ev) {
|
||||||
zmk_mod_flags_t implicit_modifiers) {
|
|
||||||
int err;
|
int err;
|
||||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode,
|
LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X",
|
||||||
implicit_modifiers);
|
ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers);
|
||||||
switch (usage_page) {
|
switch (ev->usage_page) {
|
||||||
case HID_USAGE_KEY:
|
case HID_USAGE_KEY:
|
||||||
err = zmk_hid_keyboard_press(keycode);
|
err = zmk_hid_keyboard_press(ev->keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to press keycode");
|
LOG_ERR("Unable to press keycode");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HID_USAGE_CONSUMER:
|
case HID_USAGE_CONSUMER:
|
||||||
err = zmk_hid_consumer_press(keycode);
|
err = zmk_hid_consumer_press(ev->keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to press keycode");
|
LOG_ERR("Unable to press keycode");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
zmk_hid_implicit_modifiers_press(implicit_modifiers);
|
zmk_hid_register_mods(ev->explicit_modifiers);
|
||||||
return zmk_endpoints_send_report(usage_page);
|
zmk_hid_implicit_modifiers_press(ev->implicit_modifiers);
|
||||||
|
return zmk_endpoints_send_report(ev->usage_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hid_listener_keycode_released(uint16_t usage_page, uint32_t keycode,
|
static int hid_listener_keycode_released(const struct zmk_keycode_state_changed *ev) {
|
||||||
zmk_mod_flags_t implicit_modifiers) {
|
|
||||||
int err;
|
int err;
|
||||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode,
|
LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X",
|
||||||
implicit_modifiers);
|
ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers);
|
||||||
switch (usage_page) {
|
switch (ev->usage_page) {
|
||||||
case HID_USAGE_KEY:
|
case HID_USAGE_KEY:
|
||||||
err = zmk_hid_keyboard_release(keycode);
|
err = zmk_hid_keyboard_release(ev->keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to release keycode");
|
LOG_ERR("Unable to release keycode");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HID_USAGE_CONSUMER:
|
case HID_USAGE_CONSUMER:
|
||||||
err = zmk_hid_consumer_release(keycode);
|
err = zmk_hid_consumer_release(ev->keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to release keycode");
|
LOG_ERR("Unable to release keycode");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
zmk_hid_unregister_mods(ev->explicit_modifiers);
|
||||||
// There is a minor issue with this code.
|
// 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
|
// 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.
|
// 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
|
// Solving this would require keeping track of which key's implicit modifiers are currently
|
||||||
// active and only releasing modifiers at that time.
|
// active and only releasing modifiers at that time.
|
||||||
zmk_hid_implicit_modifiers_release();
|
zmk_hid_implicit_modifiers_release();
|
||||||
return zmk_endpoints_send_report(usage_page);
|
return zmk_endpoints_send_report(ev->usage_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hid_listener(const struct zmk_event_header *eh) {
|
int hid_listener(const zmk_event_t *eh) {
|
||||||
if (is_keycode_state_changed(eh)) {
|
const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
||||||
const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
if (ev) {
|
||||||
if (ev->state) {
|
if (ev->state) {
|
||||||
hid_listener_keycode_pressed(ev->usage_page, ev->keycode, ev->implicit_modifiers);
|
hid_listener_keycode_pressed(ev);
|
||||||
} else {
|
} else {
|
||||||
hid_listener_keycode_released(ev->usage_page, ev->keycode, ev->implicit_modifiers);
|
hid_listener_keycode_released(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(hid_listener, hid_listener);
|
ZMK_LISTENER(hid_listener, hid_listener);
|
||||||
ZMK_SUBSCRIPTION(hid_listener, keycode_state_changed);
|
ZMK_SUBSCRIPTION(hid_listener, zmk_keycode_state_changed);
|
118
app/src/hog.c
118
app/src/hog.c
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <settings/settings.h>
|
#include <settings/settings.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
|
|
||||||
|
@ -156,28 +157,115 @@ struct bt_conn *destination_connection() {
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
K_THREAD_STACK_DEFINE(hog_q_stack, CONFIG_ZMK_BLE_THREAD_STACK_SIZE);
|
||||||
|
|
||||||
|
struct k_work_q hog_work_q;
|
||||||
|
|
||||||
|
K_MSGQ_DEFINE(zmk_hog_keyboard_msgq, sizeof(struct zmk_hid_keyboard_report_body),
|
||||||
|
CONFIG_ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE, 4);
|
||||||
|
|
||||||
|
void send_keyboard_report_callback(struct k_work *work) {
|
||||||
|
struct zmk_hid_keyboard_report_body report;
|
||||||
|
|
||||||
|
while (k_msgq_get(&zmk_hog_keyboard_msgq, &report, K_NO_WAIT) == 0) {
|
||||||
|
struct bt_conn *conn = destination_connection();
|
||||||
|
if (conn == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bt_gatt_notify_params notify_params = {
|
||||||
|
.attr = &hog_svc.attrs[5],
|
||||||
|
.data = &report,
|
||||||
|
.len = sizeof(report),
|
||||||
|
};
|
||||||
|
|
||||||
|
int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Error notifying %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_conn_unref(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(hog_keyboard_work, send_keyboard_report_callback);
|
||||||
|
|
||||||
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) {
|
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) {
|
||||||
struct bt_conn *conn = destination_connection();
|
int err = k_msgq_put(&zmk_hog_keyboard_msgq, report, K_MSEC(100));
|
||||||
if (conn == NULL) {
|
if (err) {
|
||||||
return -ENOTCONN;
|
switch (err) {
|
||||||
|
case -EAGAIN: {
|
||||||
|
LOG_WRN("Keyboard message queue full, popping first message and queueing again");
|
||||||
|
struct zmk_hid_keyboard_report_body discarded_report;
|
||||||
|
k_msgq_get(&zmk_hog_keyboard_msgq, &discarded_report, K_NO_WAIT);
|
||||||
|
return zmk_hog_send_keyboard_report(report);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_WRN("Failed to queue keyboard report to send (%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
|
k_work_submit_to_queue(&hog_work_q, &hog_keyboard_work);
|
||||||
|
|
||||||
int err = bt_gatt_notify(conn, &hog_svc.attrs[5], report,
|
return 0;
|
||||||
sizeof(struct zmk_hid_keyboard_report_body));
|
|
||||||
bt_conn_unref(conn);
|
|
||||||
return err;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
K_MSGQ_DEFINE(zmk_hog_consumer_msgq, sizeof(struct zmk_hid_consumer_report_body),
|
||||||
|
CONFIG_ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE, 4);
|
||||||
|
|
||||||
|
void send_consumer_report_callback(struct k_work *work) {
|
||||||
|
struct zmk_hid_consumer_report_body report;
|
||||||
|
|
||||||
|
while (k_msgq_get(&zmk_hog_consumer_msgq, &report, K_NO_WAIT) == 0) {
|
||||||
|
struct bt_conn *conn = destination_connection();
|
||||||
|
if (conn == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bt_gatt_notify_params notify_params = {
|
||||||
|
.attr = &hog_svc.attrs[10],
|
||||||
|
.data = &report,
|
||||||
|
.len = sizeof(report),
|
||||||
|
};
|
||||||
|
|
||||||
|
int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
||||||
|
if (err) {
|
||||||
|
LOG_DBG("Error notifying %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_conn_unref(conn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
K_WORK_DEFINE(hog_consumer_work, send_consumer_report_callback);
|
||||||
|
|
||||||
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
|
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
|
||||||
struct bt_conn *conn = destination_connection();
|
int err = k_msgq_put(&zmk_hog_consumer_msgq, report, K_MSEC(100));
|
||||||
if (conn == NULL) {
|
if (err) {
|
||||||
return -ENOTCONN;
|
switch (err) {
|
||||||
|
case -EAGAIN: {
|
||||||
|
LOG_WRN("Consumer message queue full, popping first message and queueing again");
|
||||||
|
struct zmk_hid_consumer_report_body discarded_report;
|
||||||
|
k_msgq_get(&zmk_hog_consumer_msgq, &discarded_report, K_NO_WAIT);
|
||||||
|
return zmk_hog_send_consumer_report(report);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_WRN("Failed to queue consumer report to send (%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = bt_gatt_notify(conn, &hog_svc.attrs[10], report,
|
k_work_submit_to_queue(&hog_work_q, &hog_consumer_work);
|
||||||
sizeof(struct zmk_hid_consumer_report_body));
|
|
||||||
bt_conn_unref(conn);
|
return 0;
|
||||||
return err;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int zmk_hog_init(const struct device *_arg) {
|
||||||
|
k_work_q_start(&hog_work_q, hog_q_stack, K_THREAD_STACK_SIZEOF(hog_q_stack),
|
||||||
|
CONFIG_ZMK_BLE_THREAD_PRIORITY);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(zmk_hog_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
|
||||||
|
|
|
@ -28,18 +28,10 @@ static uint8_t _zmk_keymap_layer_default = 0;
|
||||||
#define ZMK_KEYMAP_NODE DT_DRV_INST(0)
|
#define ZMK_KEYMAP_NODE DT_DRV_INST(0)
|
||||||
#define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0)
|
#define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0)
|
||||||
|
|
||||||
#define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l)
|
#define BINDING_WITH_COMMA(idx, drv_inst) ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst),
|
||||||
|
|
||||||
#define _TRANSFORM_ENTRY(idx, layer) \
|
#define TRANSFORMED_LAYER(node) \
|
||||||
{ \
|
{UTIL_LISTIFY(DT_PROP_LEN(node, bindings), BINDING_WITH_COMMA, node)},
|
||||||
.behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, bindings, idx)), \
|
|
||||||
.param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param1), (0), \
|
|
||||||
(DT_PHA_BY_IDX(layer, bindings, idx, param1))), \
|
|
||||||
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param2), (0), \
|
|
||||||
(DT_PHA_BY_IDX(layer, bindings, idx, param2))), \
|
|
||||||
},
|
|
||||||
|
|
||||||
#define TRANSFORMED_LAYER(node) {UTIL_LISTIFY(DT_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, node)},
|
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
|
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
|
||||||
|
@ -246,23 +238,27 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens
|
||||||
|
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
int keymap_listener(const struct zmk_event_header *eh) {
|
int keymap_listener(const zmk_event_t *eh) {
|
||||||
if (is_position_state_changed(eh)) {
|
const struct zmk_position_state_changed *pos_ev;
|
||||||
const struct position_state_changed *ev = cast_position_state_changed(eh);
|
if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) {
|
||||||
return zmk_keymap_position_state_changed(ev->position, ev->state, ev->timestamp);
|
return zmk_keymap_position_state_changed(pos_ev->position, pos_ev->state,
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
pos_ev->timestamp);
|
||||||
} else if (is_sensor_event(eh)) {
|
|
||||||
const struct sensor_event *ev = cast_sensor_event(eh);
|
|
||||||
return zmk_keymap_sensor_triggered(ev->sensor_number, ev->sensor, ev->timestamp);
|
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
|
const struct zmk_sensor_event *sensor_ev;
|
||||||
|
if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) {
|
||||||
|
return zmk_keymap_sensor_triggered(sensor_ev->sensor_number, sensor_ev->sensor,
|
||||||
|
sensor_ev->timestamp);
|
||||||
|
}
|
||||||
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(keymap, keymap_listener);
|
ZMK_LISTENER(keymap, keymap_listener);
|
||||||
ZMK_SUBSCRIPTION(keymap, position_state_changed);
|
ZMK_SUBSCRIPTION(keymap, zmk_position_state_changed);
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
ZMK_SUBSCRIPTION(keymap, sensor_event);
|
ZMK_SUBSCRIPTION(keymap, zmk_sensor_event);
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
|
@ -47,14 +47,10 @@ void zmk_kscan_process_msgq(struct k_work *item) {
|
||||||
while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) {
|
while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) {
|
||||||
bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
|
bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
|
||||||
uint32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
|
uint32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
|
||||||
struct position_state_changed *pos_ev;
|
|
||||||
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position,
|
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position,
|
||||||
(pressed ? "true" : "false"));
|
(pressed ? "true" : "false"));
|
||||||
pos_ev = new_position_state_changed();
|
ZMK_EVENT_RAISE(new_zmk_position_state_changed((struct zmk_position_state_changed){
|
||||||
pos_ev->state = pressed;
|
.state = pressed, .position = position, .timestamp = k_uptime_get()}));
|
||||||
pos_ev->position = position;
|
|
||||||
pos_ev->timestamp = k_uptime_get();
|
|
||||||
ZMK_EVENT_RAISE(pos_ev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ static struct sensors_data_item sensors[] = {UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN
|
||||||
static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_trigger *trigger) {
|
static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_trigger *trigger) {
|
||||||
int err;
|
int err;
|
||||||
struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger);
|
struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger);
|
||||||
struct sensor_event *event;
|
|
||||||
|
|
||||||
LOG_DBG("sensor %d", item->sensor_number);
|
LOG_DBG("sensor %d", item->sensor_number);
|
||||||
|
|
||||||
|
@ -45,12 +44,8 @@ static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event = new_sensor_event();
|
ZMK_EVENT_RAISE(new_zmk_sensor_event((struct zmk_sensor_event){
|
||||||
event->sensor_number = item->sensor_number;
|
.sensor_number = item->sensor_number, .sensor = dev, .timestamp = k_uptime_get()}));
|
||||||
event->sensor = dev;
|
|
||||||
event->timestamp = k_uptime_get();
|
|
||||||
|
|
||||||
ZMK_EVENT_RAISE(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) {
|
static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) {
|
||||||
|
|
|
@ -33,6 +33,19 @@ static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
|
||||||
static struct bt_gatt_discover_params discover_params;
|
static struct bt_gatt_discover_params discover_params;
|
||||||
static struct bt_gatt_subscribe_params subscribe_params;
|
static struct bt_gatt_subscribe_params subscribe_params;
|
||||||
|
|
||||||
|
K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed),
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4);
|
||||||
|
|
||||||
|
void peripheral_event_work_callback(struct k_work *work) {
|
||||||
|
struct zmk_position_state_changed ev;
|
||||||
|
while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) {
|
||||||
|
LOG_DBG("Trigger key position state change for %d", ev.position);
|
||||||
|
ZMK_EVENT_RAISE(new_zmk_position_state_changed(ev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback);
|
||||||
|
|
||||||
static uint8_t split_central_notify_func(struct bt_conn *conn,
|
static uint8_t split_central_notify_func(struct bt_conn *conn,
|
||||||
struct bt_gatt_subscribe_params *params, const void *data,
|
struct bt_gatt_subscribe_params *params, const void *data,
|
||||||
uint16_t length) {
|
uint16_t length) {
|
||||||
|
@ -58,13 +71,11 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
|
||||||
if (changed_positions[i] & BIT(j)) {
|
if (changed_positions[i] & BIT(j)) {
|
||||||
uint32_t position = (i * 8) + j;
|
uint32_t position = (i * 8) + j;
|
||||||
bool pressed = position_state[i] & BIT(j);
|
bool pressed = position_state[i] & BIT(j);
|
||||||
struct position_state_changed *pos_ev = new_position_state_changed();
|
struct zmk_position_state_changed ev = {
|
||||||
pos_ev->position = position;
|
.position = position, .state = pressed, .timestamp = k_uptime_get()};
|
||||||
pos_ev->state = pressed;
|
|
||||||
pos_ev->timestamp = k_uptime_get();
|
|
||||||
|
|
||||||
LOG_DBG("Trigger key position state change for %d", position);
|
k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT);
|
||||||
ZMK_EVENT_RAISE(pos_ev);
|
k_work_submit(&peripheral_event_work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
#include <sys/util.h>
|
#include <sys/util.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
|
|
||||||
|
@ -18,8 +19,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <zmk/split/bluetooth/uuid.h>
|
#include <zmk/split/bluetooth/uuid.h>
|
||||||
#include <zmk/split/bluetooth/service.h>
|
#include <zmk/split/bluetooth/service.h>
|
||||||
|
|
||||||
|
#define POS_STATE_LEN 16
|
||||||
|
|
||||||
static uint8_t num_of_positions = ZMK_KEYMAP_LEN;
|
static uint8_t num_of_positions = ZMK_KEYMAP_LEN;
|
||||||
static uint8_t position_state[16];
|
static uint8_t position_state[POS_STATE_LEN];
|
||||||
|
|
||||||
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||||
void *buf, uint16_t len, uint16_t offset) {
|
void *buf, uint16_t len, uint16_t offset) {
|
||||||
|
@ -45,12 +48,62 @@ BT_GATT_SERVICE_DEFINE(
|
||||||
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
|
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
|
||||||
&num_of_positions), );
|
&num_of_positions), );
|
||||||
|
|
||||||
|
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
|
||||||
|
|
||||||
|
struct k_work_q service_work_q;
|
||||||
|
|
||||||
|
K_MSGQ_DEFINE(position_state_msgq, sizeof(char[POS_STATE_LEN]),
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4);
|
||||||
|
|
||||||
|
void send_position_state_callback(struct k_work *work) {
|
||||||
|
uint8_t state[POS_STATE_LEN];
|
||||||
|
|
||||||
|
while (k_msgq_get(&position_state_msgq, &state, K_NO_WAIT) == 0) {
|
||||||
|
int err = bt_gatt_notify(NULL, &split_svc.attrs[1], &state, sizeof(state));
|
||||||
|
if (err) {
|
||||||
|
LOG_DBG("Error notifying %d", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
K_WORK_DEFINE(service_position_notify_work, send_position_state_callback);
|
||||||
|
|
||||||
|
int send_position_state() {
|
||||||
|
int err = k_msgq_put(&position_state_msgq, position_state, K_MSEC(100));
|
||||||
|
if (err) {
|
||||||
|
switch (err) {
|
||||||
|
case -EAGAIN: {
|
||||||
|
LOG_WRN("Position state message queue full, popping first message and queueing again");
|
||||||
|
uint8_t discarded_state[POS_STATE_LEN];
|
||||||
|
k_msgq_get(&position_state_msgq, &discarded_state, K_NO_WAIT);
|
||||||
|
return send_position_state();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_WRN("Failed to queue position state to send (%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_work_submit_to_queue(&service_work_q, &service_position_notify_work);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int zmk_split_bt_position_pressed(uint8_t position) {
|
int zmk_split_bt_position_pressed(uint8_t position) {
|
||||||
WRITE_BIT(position_state[position / 8], position % 8, true);
|
WRITE_BIT(position_state[position / 8], position % 8, true);
|
||||||
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
|
return send_position_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_split_bt_position_released(uint8_t position) {
|
int zmk_split_bt_position_released(uint8_t position) {
|
||||||
WRITE_BIT(position_state[position / 8], position % 8, false);
|
WRITE_BIT(position_state[position / 8], position % 8, false);
|
||||||
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
|
return send_position_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int service_init(const struct device *_arg) {
|
||||||
|
k_work_q_start(&service_work_q, service_q_stack, K_THREAD_STACK_SIZEOF(service_q_stack),
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(service_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
|
||||||
|
|
|
@ -19,10 +19,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <zmk/hid.h>
|
#include <zmk/hid.h>
|
||||||
#include <zmk/endpoints.h>
|
#include <zmk/endpoints.h>
|
||||||
|
|
||||||
int split_listener(const struct zmk_event_header *eh) {
|
int split_listener(const zmk_event_t *eh) {
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
if (is_position_state_changed(eh)) {
|
const struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh);
|
||||||
const struct position_state_changed *ev = cast_position_state_changed(eh);
|
if (ev != NULL) {
|
||||||
if (ev->state) {
|
if (ev->state) {
|
||||||
return zmk_split_bt_position_pressed(ev->position);
|
return zmk_split_bt_position_pressed(ev->position);
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,4 +33,4 @@ int split_listener(const struct zmk_event_header *eh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_LISTENER(split_listener, split_listener);
|
ZMK_LISTENER(split_listener, split_listener);
|
||||||
ZMK_SUBSCRIPTION(split_listener, position_state_changed);
|
ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed);
|
|
@ -55,10 +55,8 @@ int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
|
||||||
#endif /* CONFIG_ZMK_USB */
|
#endif /* CONFIG_ZMK_USB */
|
||||||
|
|
||||||
static void raise_usb_status_changed_event() {
|
static void raise_usb_status_changed_event() {
|
||||||
struct usb_conn_state_changed *ev = new_usb_conn_state_changed();
|
ZMK_EVENT_RAISE(new_zmk_usb_conn_state_changed(
|
||||||
ev->conn_state = zmk_usb_get_conn_state();
|
(struct zmk_usb_conn_state_changed){.conn_state = zmk_usb_get_conn_state()}));
|
||||||
|
|
||||||
ZMK_EVENT_RAISE(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum usb_dc_status_code zmk_usb_get_status() { return usb_status; }
|
enum usb_dc_status_code zmk_usb_get_status() { return usb_status; }
|
||||||
|
|
86
app/src/wpm.c
Normal file
86
app/src/wpm.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#include <zmk/events/wpm_state_changed.h>
|
||||||
|
#include <zmk/events/keycode_state_changed.h>
|
||||||
|
|
||||||
|
#include <zmk/wpm.h>
|
||||||
|
|
||||||
|
#define WPM_UPDATE_INTERVAL_SECONDS 1
|
||||||
|
#define WPM_RESET_INTERVAL_SECONDS 5
|
||||||
|
|
||||||
|
// See https://en.wikipedia.org/wiki/Words_per_minute
|
||||||
|
// "Since the length or duration of words is clearly variable, for the purpose of measurement of
|
||||||
|
// text entry, the definition of each "word" is often standardized to be five characters or
|
||||||
|
// keystrokes long in English"
|
||||||
|
#define CHARS_PER_WORD 5.0
|
||||||
|
|
||||||
|
static uint8_t wpm_state = -1;
|
||||||
|
static uint8_t last_wpm_state;
|
||||||
|
static uint8_t wpm_update_counter;
|
||||||
|
static uint32_t key_pressed_count;
|
||||||
|
|
||||||
|
int zmk_wpm_get_state() { return wpm_state; }
|
||||||
|
|
||||||
|
int wpm_event_listener(const zmk_event_t *eh) {
|
||||||
|
const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
||||||
|
if (ev) {
|
||||||
|
// count only key up events
|
||||||
|
if (!ev->state) {
|
||||||
|
key_pressed_count++;
|
||||||
|
LOG_DBG("key_pressed_count %d keycode %d", key_pressed_count, ev->keycode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpm_work_handler(struct k_work *work) {
|
||||||
|
wpm_update_counter++;
|
||||||
|
wpm_state = (key_pressed_count / CHARS_PER_WORD) /
|
||||||
|
(wpm_update_counter * WPM_UPDATE_INTERVAL_SECONDS / 60.0);
|
||||||
|
|
||||||
|
if (last_wpm_state != wpm_state) {
|
||||||
|
LOG_DBG("Raised WPM state changed %d wpm_update_counter %d", wpm_state, wpm_update_counter);
|
||||||
|
|
||||||
|
ZMK_EVENT_RAISE(
|
||||||
|
new_zmk_wpm_state_changed((struct zmk_wpm_state_changed){.state = wpm_state}));
|
||||||
|
|
||||||
|
last_wpm_state = wpm_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpm_update_counter >= WPM_RESET_INTERVAL_SECONDS) {
|
||||||
|
wpm_update_counter = 0;
|
||||||
|
key_pressed_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(wpm_work, wpm_work_handler);
|
||||||
|
|
||||||
|
void wpm_expiry_function() { k_work_submit(&wpm_work); }
|
||||||
|
|
||||||
|
K_TIMER_DEFINE(wpm_timer, wpm_expiry_function, NULL);
|
||||||
|
|
||||||
|
int wpm_init() {
|
||||||
|
wpm_state = 0;
|
||||||
|
wpm_update_counter = 0;
|
||||||
|
k_timer_start(&wpm_timer, K_SECONDS(WPM_UPDATE_INTERVAL_SECONDS),
|
||||||
|
K_SECONDS(WPM_UPDATE_INTERVAL_SECONDS));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_LISTENER(wpm, wpm_event_listener);
|
||||||
|
ZMK_SUBSCRIPTION(wpm, zmk_keycode_state_changed);
|
||||||
|
|
||||||
|
SYS_INIT(wpm_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0xe0 mods 0x00
|
pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0xe0 mods 0x00
|
released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pressed: usage_page 0x07 keycode 0xe0 mods 0x00
|
pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0xe4 mods 0x00
|
pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x04 mods 0x00
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x05 mods 0x00
|
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x04 mods 0x00
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x05 mods 0x00
|
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x04 mods 0x00
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x04 mods 0x00
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1b mods 0x00
|
pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1b mods 0x00
|
released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x1c mods 0x00
|
pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x1c mods 0x00
|
released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x04 mods 0x00
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x05 mods 0x00
|
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x04 mods 0x00
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x05 mods 0x00
|
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x07 mods 0x00
|
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x07 mods 0x00
|
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x07 mods 0x00
|
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x07 mods 0x00
|
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x06 mods 0x00
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
released: usage_page 0x07 keycode 0x07 mods 0x00
|
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
1
app/tests/gresc/gresc-press-release/events.patterns
Normal file
1
app/tests/gresc/gresc-press-release/events.patterns
Normal file
|
@ -0,0 +1 @@
|
||||||
|
s/.*hid_listener_keycode_//p
|
18
app/tests/gresc/gresc-press-release/keycode_events.snapshot
Normal file
18
app/tests/gresc/gresc-press-release/keycode_events.snapshot
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
pressed: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue