summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorNick <nick.win999@gmail.com>2020-09-15 14:41:59 -0500
committerNick <nick.win999@gmail.com>2020-09-15 14:41:59 -0500
commit18d21b0362c5c09902836ed4791bd13e1efd9a9a (patch)
tree3f78a0ef43fc23e93195e1205a31f77154af7e76 /app
parent81bc157f539235ad032fde78b6f6cec7a16d2c39 (diff)
parentc0806d27f1d048db335ecc854eab61b59e23ea7a (diff)
Merge remote-tracking branch 'upstream/main' into underglow/state-persistence
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt28
-rw-r--r--app/Kconfig46
-rw-r--r--app/boards/arm/dz60rgb/CMakeLists.txt7
-rw-r--r--app/boards/arm/dz60rgb/Kconfig.board6
-rw-r--r--app/boards/arm/dz60rgb/Kconfig.defconfig14
-rw-r--r--app/boards/arm/dz60rgb/board.cmake7
-rw-r--r--app/boards/arm/dz60rgb/dz60rgb_rev1.dts88
-rw-r--r--app/boards/arm/dz60rgb/dz60rgb_rev1.keymap25
-rw-r--r--app/boards/arm/dz60rgb/dz60rgb_rev1.yaml19
-rw-r--r--app/boards/arm/dz60rgb/dz60rgb_rev1_defconfig27
-rw-r--r--app/boards/arm/dz60rgb/pinmux.c67
-rw-r--r--app/boards/arm/nrfmicro/Kconfig5
-rw-r--r--app/boards/arm/nrfmicro/Kconfig.board2
-rw-r--r--app/boards/arm/nrfmicro/Kconfig.defconfig11
-rw-r--r--app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi2
-rw-r--r--app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi2
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11.dts2
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts2
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_13.dts2
-rw-r--r--app/boards/arm/nrfmicro/pinmux.c37
-rw-r--r--app/boards/arm/planck/Kconfig.board2
-rw-r--r--app/boards/arm/planck/Kconfig.defconfig2
-rw-r--r--app/boards/arm/planck/pinmux.c52
-rw-r--r--app/boards/arm/planck/planck_rev6_defconfig3
-rw-r--r--app/boards/arm/proton_c/pinmux.c54
-rw-r--r--app/boards/native_posix.conf3
-rw-r--r--app/boards/native_posix.overlay73
-rw-r--r--app/boards/shields/corne/corne.keymap11
-rw-r--r--app/boards/shields/corne/corne_left.conf1
-rw-r--r--app/boards/shields/corne/corne_right.conf1
-rw-r--r--app/boards/shields/iris/Kconfig.defconfig16
-rw-r--r--app/boards/shields/iris/Kconfig.shield8
-rw-r--r--app/boards/shields/iris/iris.conf0
-rw-r--r--app/boards/shields/iris/iris.dtsi51
-rw-r--r--app/boards/shields/iris/iris.keymap60
-rw-r--r--app/boards/shields/iris/iris_left.conf2
-rw-r--r--app/boards/shields/iris/iris_left.overlay22
-rw-r--r--app/boards/shields/iris/iris_right.conf2
-rw-r--r--app/boards/shields/iris/iris_right.overlay26
-rw-r--r--app/boards/shields/kyria/kyria_left.conf3
-rw-r--r--app/boards/shields/kyria/kyria_right.conf1
-rw-r--r--app/boards/shields/lily58/lily58.conf4
-rw-r--r--app/boards/shields/lily58/lily58.dtsi15
-rw-r--r--app/boards/shields/lily58/lily58.keymap19
-rw-r--r--app/boards/shields/lily58/lily58_left.conf7
-rw-r--r--app/boards/shields/lily58/lily58_left.overlay6
-rw-r--r--app/boards/shields/lily58/lily58_right.conf1
-rw-r--r--app/boards/shields/lily58/lily58_right.overlay2
-rw-r--r--app/boards/shields/qaz/Kconfig.defconfig9
-rw-r--r--app/boards/shields/qaz/Kconfig.shield5
-rw-r--r--app/boards/shields/qaz/qaz.keymap58
-rw-r--r--app/boards/shields/qaz/qaz.overlay53
-rw-r--r--app/boards/shields/romac/Kconfig.defconfig10
-rw-r--r--app/boards/shields/romac/Kconfig.shield5
-rw-r--r--app/boards/shields/romac/romac.conf0
-rw-r--r--app/boards/shields/romac/romac.keymap47
-rw-r--r--app/boards/shields/romac/romac.overlay40
-rw-r--r--app/boards/shields/settings_reset/Kconfig.defconfig10
-rw-r--r--app/boards/shields/settings_reset/Kconfig.shield5
-rw-r--r--app/boards/shields/settings_reset/settings_reset.conf1
-rw-r--r--app/boards/shields/settings_reset/settings_reset.keymap22
-rw-r--r--app/boards/shields/settings_reset/settings_reset.overlay24
-rw-r--r--app/boards/shields/sofle/Kconfig.defconfig54
-rw-r--r--app/boards/shields/sofle/Kconfig.shield8
-rw-r--r--app/boards/shields/sofle/sofle.conf9
-rw-r--r--app/boards/shields/sofle/sofle.dtsi93
-rw-r--r--app/boards/shields/sofle/sofle.keymap64
-rw-r--r--app/boards/shields/sofle/sofle_left.conf5
-rw-r--r--app/boards/shields/sofle/sofle_left.overlay26
-rw-r--r--app/boards/shields/sofle/sofle_right.conf5
-rw-r--r--app/boards/shields/sofle/sofle_right.overlay30
-rw-r--r--app/boards/shields/splitreus62/Kconfig.defconfig22
-rw-r--r--app/boards/shields/splitreus62/Kconfig.shield8
-rw-r--r--app/boards/shields/splitreus62/splitreus62.conf0
-rw-r--r--app/boards/shields/splitreus62/splitreus62.dtsi50
-rw-r--r--app/boards/shields/splitreus62/splitreus62.keymap31
-rw-r--r--app/boards/shields/splitreus62/splitreus62_left.conf2
-rw-r--r--app/boards/shields/splitreus62/splitreus62_left.overlay18
-rw-r--r--app/boards/shields/splitreus62/splitreus62_right.conf2
-rw-r--r--app/boards/shields/splitreus62/splitreus62_right.overlay22
-rw-r--r--app/cmake/zmk_config.cmake1
-rw-r--r--app/drivers/zephyr/ec11.c211
-rw-r--r--app/drivers/zephyr/ec11.h51
-rw-r--r--app/drivers/zephyr/ec11_trigger.c178
-rw-r--r--app/drivers/zephyr/kscan_gpio_direct.c359
-rw-r--r--app/drivers/zephyr/kscan_gpio_matrix.c478
-rw-r--r--app/dts/behaviors.dtsi4
-rw-r--r--app/dts/behaviors/bluetooth.dtsi9
-rw-r--r--app/dts/behaviors/layer_tap.dtsi12
-rw-r--r--app/dts/behaviors/mod_tap.dtsi5
-rw-r--r--app/dts/behaviors/reset.dtsi9
-rw-r--r--app/dts/behaviors/toggle_layer.dtsi6
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml8
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml23
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml8
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-reset.yaml5
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-rgb-underglow.yaml4
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml2
-rw-r--r--app/dts/bindings/zmk,kscan-mock.yaml2
-rw-r--r--app/include/drivers/behavior.h71
-rw-r--r--app/include/dt-bindings/zmk/bt.h21
-rw-r--r--app/include/dt-bindings/zmk/keys.h11
-rw-r--r--app/include/dt-bindings/zmk/kscan-mock.h (renamed from app/include/zmk/kscan-mock.h)0
-rw-r--r--app/include/dt-bindings/zmk/reset.h13
-rw-r--r--app/include/linker/zmk-events.ld2
-rw-r--r--app/include/zmk/behavior.h5
-rw-r--r--app/include/zmk/ble.h18
-rw-r--r--app/include/zmk/ble/profile.h16
-rw-r--r--app/include/zmk/display.h2
-rw-r--r--app/include/zmk/endpoints.h6
-rw-r--r--app/include/zmk/event-manager.h80
-rw-r--r--app/include/zmk/events/ble-active-profile-changed.h21
-rw-r--r--app/include/zmk/events/keycode-state-changed.h8
-rw-r--r--app/include/zmk/events/modifiers-state-changed.h10
-rw-r--r--app/include/zmk/events/position-state-changed.h2
-rw-r--r--app/include/zmk/events/sensor-event.h2
-rw-r--r--app/include/zmk/handlers.h6
-rw-r--r--app/include/zmk/hid.h18
-rw-r--r--app/include/zmk/hog.h5
-rw-r--r--app/include/zmk/keymap.h6
-rw-r--r--app/include/zmk/keys.h9
-rw-r--r--app/include/zmk/kscan.h6
-rw-r--r--app/include/zmk/matrix.h24
-rw-r--r--app/include/zmk/matrix_transform.h6
-rw-r--r--app/include/zmk/rgb_underglow.h2
-rw-r--r--app/include/zmk/sensors.h2
-rw-r--r--app/include/zmk/split/bluetooth/uuid.h5
-rw-r--r--app/include/zmk/usb_hid.h11
-rw-r--r--app/prj.conf0
-rwxr-xr-xapp/run-test.sh41
-rw-r--r--app/src/behaviors/behavior_bt.c51
-rw-r--r--app/src/behaviors/behavior_hold_tap.c492
-rw-r--r--app/src/behaviors/behavior_key_press.c52
-rw-r--r--app/src/behaviors/behavior_mod_tap.c252
-rw-r--r--app/src/behaviors/behavior_momentary_layer.c37
-rw-r--r--app/src/behaviors/behavior_none.c34
-rw-r--r--app/src/behaviors/behavior_reset.c45
-rw-r--r--app/src/behaviors/behavior_rgb_underglow.c47
-rw-r--r--app/src/behaviors/behavior_sensor_rotate_key_press.c104
-rw-r--r--app/src/behaviors/behavior_toggle_layer.c34
-rw-r--r--app/src/behaviors/behavior_transparent.c34
-rw-r--r--app/src/ble.c400
-rw-r--r--app/src/ble_unpair_combo.c26
-rw-r--r--app/src/display.c8
-rw-r--r--app/src/endpoints.c26
-rw-r--r--app/src/event_manager.c60
-rw-r--r--app/src/events/ble_active_profile_changed.c10
-rw-r--r--app/src/events/keycode_state_changed.c2
-rw-r--r--app/src/events/modifiers_state_changed.c2
-rw-r--r--app/src/events/position_state_changed.c2
-rw-r--r--app/src/events/sensor_event.c2
-rw-r--r--app/src/hid.c97
-rw-r--r--app/src/hid_listener.c138
-rw-r--r--app/src/hog.c162
-rw-r--r--app/src/keymap.c286
-rw-r--r--app/src/kscan.c80
-rw-r--r--app/src/kscan_composite.c65
-rw-r--r--app/src/kscan_mock.c120
-rw-r--r--app/src/main.c22
-rw-r--r--app/src/matrix_transform.c16
-rw-r--r--app/src/rgb_underglow.c176
-rw-r--r--app/src/sensors.c34
-rw-r--r--app/src/split/bluetooth/central.c461
-rw-r--r--app/src/split/bluetooth/service.c50
-rw-r--r--app/src/split_listener.c22
-rw-r--r--app/src/usb_hid.c98
-rw-r--r--app/tests/hold-tap/README.md1
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/behavior_keymap.dtsi27
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi29
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi27
-rw-r--r--app/tests/hold-tap/zmk-modtap-proposal.odgbin0 -> 23148 bytes
-rw-r--r--app/tests/hold-tap/zmk-modtap-proposal.pdfbin0 -> 25493 bytes
-rw-r--r--app/tests/keypress/behavior_keymap.dtsi28
-rw-r--r--app/tests/keypress/cp-press-release/events.patterns1
-rw-r--r--app/tests/keypress/cp-press-release/keycode_events.snapshot2
-rw-r--r--app/tests/keypress/cp-press-release/native_posix.keymap5
-rw-r--r--app/tests/keypress/kp-press-release/events.patterns1
-rw-r--r--app/tests/keypress/kp-press-release/keycode_events.snapshot2
-rw-r--r--app/tests/keypress/kp-press-release/native_posix.keymap8
-rw-r--r--app/tests/momentary-layer/behavior_keymap.dtsi28
-rw-r--r--app/tests/momentary-layer/early-key-release/events.patterns2
-rw-r--r--app/tests/momentary-layer/early-key-release/keycode_events.snapshot4
-rw-r--r--app/tests/momentary-layer/early-key-release/native_posix.keymap8
-rw-r--r--app/tests/momentary-layer/normal/events.patterns2
-rw-r--r--app/tests/momentary-layer/normal/keycode_events.snapshot4
-rw-r--r--app/tests/momentary-layer/normal/native_posix.keymap8
-rw-r--r--app/tests/none/behavior_keymap.dtsi22
-rw-r--r--app/tests/none/layered/events.patterns1
-rw-r--r--app/tests/none/layered/keycode_events.snapshot0
-rw-r--r--app/tests/none/layered/native_posix.keymap8
-rw-r--r--app/tests/none/normal/events.patterns1
-rw-r--r--app/tests/none/normal/keycode_events.snapshot0
-rw-r--r--app/tests/none/normal/native_posix.keymap8
-rw-r--r--app/tests/toggle-layer/behavior_keymap.dtsi28
-rw-r--r--app/tests/toggle-layer/early-key-release/events.patterns2
-rw-r--r--app/tests/toggle-layer/early-key-release/keycode_events.snapshot6
-rw-r--r--app/tests/toggle-layer/early-key-release/native_posix.keymap9
-rw-r--r--app/tests/toggle-layer/normal/events.patterns2
-rw-r--r--app/tests/toggle-layer/normal/keycode_events.snapshot4
-rw-r--r--app/tests/toggle-layer/normal/native_posix.keymap8
-rw-r--r--app/tests/transparent/behavior_keymap.dtsi22
-rw-r--r--app/tests/transparent/layered/events.patterns1
-rw-r--r--app/tests/transparent/layered/keycode_events.snapshot2
-rw-r--r--app/tests/transparent/layered/native_posix.keymap8
-rw-r--r--app/tests/transparent/normal/events.patterns1
-rw-r--r--app/tests/transparent/normal/keycode_events.snapshot0
-rw-r--r--app/tests/transparent/normal/native_posix.keymap8
306 files changed, 5498 insertions, 2560 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index bbb54b9..8c21687 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,4 +1,3 @@
-# Find Zephyr. This also loads Zephyr's build system.
cmake_minimum_required(VERSION 3.13.1)
set(CONFIG_APPLICATION_DEFINED_SYSCALL true)
@@ -15,6 +14,7 @@ list(APPEND SYSCALL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/drivers/zephyr)
include(cmake/zmk_config.cmake)
+# Find Zephyr. This also loads Zephyr's build system.
find_package(Zephyr REQUIRED HINTS ../zephyr)
project(zmk)
@@ -25,26 +25,30 @@ zephyr_linker_sources(RODATA include/linker/zmk-events.ld)
target_include_directories(app PRIVATE include)
target_sources(app PRIVATE src/kscan.c)
target_sources(app PRIVATE src/matrix_transform.c)
-target_sources(app PRIVATE src/keymap.c)
target_sources(app PRIVATE src/hid.c)
target_sources(app PRIVATE src/sensors.c)
target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
target_sources(app PRIVATE src/event_manager.c)
+target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c)
target_sources(app PRIVATE src/events/position_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/sensor_event.c)
-target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
-target_sources(app PRIVATE src/behaviors/behavior_reset.c)
-target_sources(app PRIVATE src/behaviors/behavior_mod_tap.c)
-target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
-target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
-target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
-target_sources(app PRIVATE src/behaviors/behavior_none.c)
-target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
+target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
+if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
+ target_sources(app PRIVATE src/behaviors/behavior_reset.c)
+ target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
+ target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
+ target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
+ target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
+ target_sources(app PRIVATE src/behaviors/behavior_none.c)
+ target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
+ target_sources(app PRIVATE src/keymap.c)
+endif()
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
+target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
-target_sources_ifdef(CONFIG_ZMK_BLE_UNPAIR_COMBO app PRIVATE src/ble_unpair_combo.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split_listener.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/bluetooth/service.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c)
@@ -57,3 +61,5 @@ target_sources(app PRIVATE src/endpoints.c)
target_sources(app PRIVATE src/hid_listener.c)
target_sources_ifdef(CONFIG_SETTINGS app PRIVATE src/settings.c)
target_sources(app PRIVATE src/main.c)
+
+zephyr_cc_option(-Wfatal-errors)
diff --git a/app/Kconfig b/app/Kconfig
index cda5c58..a9d4f34 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -37,27 +37,26 @@ menuconfig ZMK_BLE
select BT
select BT_SMP
select BT_SMP_SC_PAIR_ONLY
+ select BT_SMP_APP_PAIRING_ACCEPT
select BT_PERIPHERAL
select BT_GATT_DIS
select BT_GATT_BAS
- select SETTINGS
select BT_SETTINGS
+ select SETTINGS
if ZMK_BLE
-config ZMK_BLE_UNPAIR_COMBO
- bool "Enable BT unpair combo"
- help
- Adds a magic key combo that can be held on startup to remove all paired devices
- default n
-
config ZMK_BLE_INIT_PRIORITY
int "Init Priority"
default 50
-
+
config SYSTEM_WORKQUEUE_STACK_SIZE
default 2048
+config ZMK_BLE_CLEAR_BONDS_ON_START
+ bool "Configuration that clears all bond information from the keyboard on startup."
+ default n
+
# HID GATT notifications sent this way are *not* picked up by Linux, and possibly others.
config BT_GATT_NOTIFY_MULTIPLE
default n
@@ -107,28 +106,20 @@ config ZMK_SPLIT_BLE_ROLE_CENTRAL
select BT_CENTRAL
select BT_GATT_CLIENT
-if ZMK_SPLIT_BLE_ROLE_CENTRAL
-
-config BT_MAX_CONN
- default 5
-
-config BT_MAX_PAIRED
- # Bump this everywhere once we support switching active connections!
- default 2
-
-endif
-
config ZMK_SPLIT_BLE_ROLE_PERIPHERAL
bool "Peripheral"
+ select BT_KEYS_OVERWRITE_OLDEST
if ZMK_SPLIT_BLE_ROLE_PERIPHERAL
config ZMK_USB
default n
+config BT_MAX_PAIRED
+ default 1
config BT_MAX_CONN
- default 5
+ default 1
config BT_GAP_AUTO_UPDATE_CONN_PARAMS
default n
@@ -141,8 +132,17 @@ endif
endif
-endmenu
+if ZMK_BLE && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL)
+
+config BT_MAX_CONN
+ default 6
+config BT_MAX_PAIRED
+ default 5
+
+endif
+
+endmenu
config ZMK_KSCAN_MOCK_DRIVER
bool "Enable mock kscan driver to simulate key presses"
@@ -227,6 +227,10 @@ source "subsys/logging/Kconfig.template.log_config"
rsource "boards/Kconfig"
rsource "boards/shields/*/Kconfig.defconfig"
+rsource "boards/shields/*/Kconfig.shield"
+
+osource "$(ZMK_CONFIG)/boards/shields/*/Kconfig.defconfig"
+osource "$(ZMK_CONFIG)/boards/shields/*/Kconfig.shield"
source "Kconfig.zephyr"
diff --git a/app/boards/arm/dz60rgb/CMakeLists.txt b/app/boards/arm/dz60rgb/CMakeLists.txt
new file mode 100644
index 0000000..940af1f
--- /dev/null
+++ b/app/boards/arm/dz60rgb/CMakeLists.txt
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+
+if(CONFIG_PINMUX)
+zephyr_library()
+zephyr_library_sources(pinmux.c)
+zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
+endif()
diff --git a/app/boards/arm/dz60rgb/Kconfig.board b/app/boards/arm/dz60rgb/Kconfig.board
new file mode 100644
index 0000000..ec8dad6
--- /dev/null
+++ b/app/boards/arm/dz60rgb/Kconfig.board
@@ -0,0 +1,6 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+config BOARD_DZ60RGB_REV1
+ bool "DZ60RGB Keyboard"
+ depends on SOC_STM32F303XC
diff --git a/app/boards/arm/dz60rgb/Kconfig.defconfig b/app/boards/arm/dz60rgb/Kconfig.defconfig
new file mode 100644
index 0000000..779d312
--- /dev/null
+++ b/app/boards/arm/dz60rgb/Kconfig.defconfig
@@ -0,0 +1,14 @@
+# DZ60RGB keyboard configuration
+
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+if BOARD_DZ60RGB_REV1
+
+config ZMK_KEYBOARD_NAME
+ default "DZ60RGB Rev 1"
+
+config ZMK_USB
+ default y
+
+endif # BOARD_DZ60RGB_REV1
diff --git a/app/boards/arm/dz60rgb/board.cmake b/app/boards/arm/dz60rgb/board.cmake
new file mode 100644
index 0000000..10f6e29
--- /dev/null
+++ b/app/boards/arm/dz60rgb/board.cmake
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+
+board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse")
+board_runner_args(jlink "--device=STM32F303CC" "--speed=4000")
+
+include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake)
+include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
diff --git a/app/boards/arm/dz60rgb/dz60rgb_rev1.dts b/app/boards/arm/dz60rgb/dz60rgb_rev1.dts
new file mode 100644
index 0000000..85c4ca5
--- /dev/null
+++ b/app/boards/arm/dz60rgb/dz60rgb_rev1.dts
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/dts-v1/;
+#include <st/f3/stm32f303Xc.dtsi>
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ model = "DZ60RGB, Rev 1";
+ compatible = "dz60rgb,rev1", "st,stm32f303";
+
+ chosen {
+ zephyr,sram = &sram0;
+ zephyr,flash = &flash0;
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <14>;
+ rows = <5>;
+ map = <
+RC(0,0) 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(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(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,13)
+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,13)
+RC(4,0) RC(4,1) RC(4,2) RC(4,5) RC(4,8) RC(4,9) RC(4,10) RC(4,11) RC(4,13)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&gpioa 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&gpiob 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&gpiob 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&gpiob 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&gpiob 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+ col-gpios
+ = <&gpioa 6 GPIO_ACTIVE_HIGH>
+ , <&gpioa 7 GPIO_ACTIVE_HIGH>
+ , <&gpiob 0 GPIO_ACTIVE_HIGH>
+ , <&gpiob 13 GPIO_ACTIVE_HIGH>
+ , <&gpiob 15 GPIO_ACTIVE_HIGH>
+ , <&gpioa 8 GPIO_ACTIVE_HIGH>
+ , <&gpioa 15 GPIO_ACTIVE_HIGH>
+ , <&gpiob 3 GPIO_ACTIVE_HIGH>
+ , <&gpiob 4 GPIO_ACTIVE_HIGH>
+ , <&gpiob 5 GPIO_ACTIVE_HIGH>
+ , <&gpiob 8 GPIO_ACTIVE_HIGH>
+ , <&gpiob 9 GPIO_ACTIVE_HIGH>
+ , <&gpioc 13 GPIO_ACTIVE_HIGH>
+ , <&gpioc 14 GPIO_ACTIVE_HIGH>
+ ;
+ };
+
+};
+
+&usb {
+ status = "okay";
+};
+
+&flash0 {
+ /*
+ * For more information, see:
+ * http://docs.zephyrproject.org/latest/guides/dts/index.html#flash-partitions
+ */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Set 6Kb of storage at the end of the 256Kb of flash */
+ storage_partition: partition@3e800 {
+ label = "storage";
+ reg = <0x0003e800 0x00001800>;
+ };
+ };
+};
diff --git a/app/boards/arm/dz60rgb/dz60rgb_rev1.keymap b/app/boards/arm/dz60rgb/dz60rgb_rev1.keymap
new file mode 100644
index 0000000..8de01c1
--- /dev/null
+++ b/app/boards/arm/dz60rgb/dz60rgb_rev1.keymap
@@ -0,0 +1,25 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BKSP |
+// | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | "|" |
+// | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | ENTER |
+// | SHIFT | Z | X | C | V | B | N | M | , | . | SHIFT(/) | ^ | DEL |
+// | CTL | WIN | ALT | SPACE | ALT | MO(1) | <- | v | -> |
+// ------------------------------------------------------------------------------------------
+ bindings = <
+ &kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp MINUS &kp EQL &kp BKSP
+ &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 CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT &kp RET
+ &kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &mt MOD_RSFT FSLH &kp UARW &kp DEL
+ &kp LCTL &kp LGUI &kp LALT &kp SPC &kp RALT &mo 1 &kp LARW &kp DARW &kp RARW
+ >;
+ };
+ };
+}; \ No newline at end of file
diff --git a/app/boards/arm/dz60rgb/dz60rgb_rev1.yaml b/app/boards/arm/dz60rgb/dz60rgb_rev1.yaml
new file mode 100644
index 0000000..d283621
--- /dev/null
+++ b/app/boards/arm/dz60rgb/dz60rgb_rev1.yaml
@@ -0,0 +1,19 @@
+identifier: DZ60RGB_rev1
+name: DZ60RGBREV1
+type: keyboard
+arch: arm
+toolchain:
+ - zephyr
+ - gnuarmemb
+ - xtools
+ram: 40
+supported:
+ - gpio
+ - i2c
+ - counter
+ - spi
+ - usb_device
+ - lsm303dlhc
+ - nvs
+ - can
+ - kscan
diff --git a/app/boards/arm/dz60rgb/dz60rgb_rev1_defconfig b/app/boards/arm/dz60rgb/dz60rgb_rev1_defconfig
new file mode 100644
index 0000000..33840f9
--- /dev/null
+++ b/app/boards/arm/dz60rgb/dz60rgb_rev1_defconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_SOC_SERIES_STM32F3X=y
+CONFIG_SOC_STM32F303XC=y
+# 72MHz system clock
+CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=72000000
+
+# enable pinmux
+CONFIG_PINMUX=y
+
+# enable GPIO
+CONFIG_GPIO=y
+
+# clock configuration
+CONFIG_CLOCK_CONTROL=y
+
+# Clock configuration for Cube Clock control driver
+CONFIG_CLOCK_STM32_HSE_CLOCK=8000000
+CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL=y
+# use HSE as PLL input
+CONFIG_CLOCK_STM32_PLL_SRC_HSE=y
+# produce 72MHz clock at PLL output
+CONFIG_CLOCK_STM32_PLL_PREDIV=1
+CONFIG_CLOCK_STM32_PLL_MULTIPLIER=9
+CONFIG_CLOCK_STM32_AHB_PRESCALER=1
+CONFIG_CLOCK_STM32_APB1_PRESCALER=2
+CONFIG_CLOCK_STM32_APB2_PRESCALER=1
diff --git a/app/boards/arm/dz60rgb/pinmux.c b/app/boards/arm/dz60rgb/pinmux.c
new file mode 100644
index 0000000..f59a31b
--- /dev/null
+++ b/app/boards/arm/dz60rgb/pinmux.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 I-SENSE group of ICCS
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <kernel.h>
+#include <device.h>
+#include <init.h>
+#include <drivers/pinmux.h>
+#include <sys/sys_io.h>
+
+#include <pinmux/stm32/pinmux_stm32.h>
+
+/* pin assignments for STM32F3DISCOVERY board */
+static const struct pin_config pinconf[] = {
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
+ {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
+ {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
+#endif
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
+ {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
+ {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
+#endif
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
+ {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
+ {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
+#endif
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
+ {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
+ {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
+#endif
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
+#ifdef CONFIG_SPI_STM32_USE_HW_SS
+ {STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
+#endif /* CONFIG_SPI_STM32_USE_HW_SS */
+ {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
+ {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
+ {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
+#endif
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
+#ifdef CONFIG_SPI_STM32_USE_HW_SS
+ {STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
+#endif /* CONFIG_SPI_STM32_USE_HW_SS */
+ {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
+ {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
+ {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
+#endif
+#ifdef CONFIG_USB_DC_STM32
+ {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
+ {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
+#endif /* CONFIG_USB_DC_STM32 */
+#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
+ {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
+ {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
+#endif
+};
+
+static int pinmux_stm32_init(struct device *port) {
+ ARG_UNUSED(port);
+
+ stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
+
+ return 0;
+}
+
+SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); \ No newline at end of file
diff --git a/app/boards/arm/nrfmicro/Kconfig b/app/boards/arm/nrfmicro/Kconfig
index 17a3347..3501972 100644
--- a/app/boards/arm/nrfmicro/Kconfig
+++ b/app/boards/arm/nrfmicro/Kconfig
@@ -3,3 +3,8 @@ config BOARD_ENABLE_DCDC
select SOC_DCDC_NRF52X
default y
depends on (BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13)
+
+config BOARD_NRFMICRO_CHARGER
+ bool "Enable battery charger"
+ default y
+ depends on (BOARD_NRFMICRO_13)
diff --git a/app/boards/arm/nrfmicro/Kconfig.board b/app/boards/arm/nrfmicro/Kconfig.board
index 177373a..36b2d55 100644
--- a/app/boards/arm/nrfmicro/Kconfig.board
+++ b/app/boards/arm/nrfmicro/Kconfig.board
@@ -1,6 +1,6 @@
# nrfmicro board configuration
-# Copyright (c) 2020 Okke Formsma, joric
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
config BOARD_NRFMICRO_11
diff --git a/app/boards/arm/nrfmicro/Kconfig.defconfig b/app/boards/arm/nrfmicro/Kconfig.defconfig
index 2212277..7957b4a 100644
--- a/app/boards/arm/nrfmicro/Kconfig.defconfig
+++ b/app/boards/arm/nrfmicro/Kconfig.defconfig
@@ -1,6 +1,6 @@
# Electronut Labs Papyr board configuration
-# Copyright (c) 2020 Okke Formsma, joric
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
if BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
@@ -29,5 +29,12 @@ config ZMK_USB
config PINMUX
default y
-
+
+if BOARD_NRFMICRO_13
+
+config BOARD_NRFMICRO_CHARGER
+ default y
+
+endif # BOARD_NRFMICRO_13
+
endif # BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
diff --git a/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi b/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi
index 6cde2b4..558391d 100644
--- a/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi
+++ b/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi b/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi
index 9bad7f4..68ca266 100644
--- a/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi
+++ b/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.dts b/app/boards/arm/nrfmicro/nrfmicro_11.dts
index dc07ac8..95bd8ad 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_11.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_11.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
index 5bf493f..85693a8 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.dts b/app/boards/arm/nrfmicro/nrfmicro_13.dts
index dc07ac8..95bd8ad 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_13.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_13.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/boards/arm/nrfmicro/pinmux.c b/app/boards/arm/nrfmicro/pinmux.c
index 803d20d..4e330b6 100644
--- a/app/boards/arm/nrfmicro/pinmux.c
+++ b/app/boards/arm/nrfmicro/pinmux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Okke Formsma, joric
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -11,27 +11,30 @@
#include <sys/sys_io.h>
#include <devicetree.h>
-static int pinmux_nrfmicro_init(struct device *port)
-{
- ARG_UNUSED(port);
+static int pinmux_nrfmicro_init(struct device *port) {
+ ARG_UNUSED(port);
- struct device *p1 = device_get_binding("GPIO_1");
+ struct device *p1 = device_get_binding("GPIO_1");
-#if defined(BOARD_NRFMICRO_13)
- struct device *p0 = device_get_binding("GPIO_0");
- // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
- gpio_pin_configure(p1, 9, GPIO_OUTPUT);
- gpio_pin_set(p1, 9, 0);
+#if CONFIG_BOARD_NRFMICRO_13
+ struct device *p0 = device_get_binding("GPIO_0");
+ // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
+ gpio_pin_configure(p1, 9, GPIO_OUTPUT);
+ gpio_pin_set(p1, 9, 0);
+
+#if CONFIG_BOARD_NRFMICRO_CHARGER
+ gpio_pin_configure(p0, 5, GPIO_OUTPUT);
+ gpio_pin_set(p0, 5, 0);
+#else
+ gpio_pin_configure(p0, 5, GPIO_INPUT);
+#endif
- // enable charger (nRFMicro 1.3 only)
- gpio_pin_configure(p0, 5, GPIO_OUTPUT);
- gpio_pin_set(p0, 5, 0);
#else
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
- gpio_pin_configure(p1, 9, GPIO_OUTPUT);
- gpio_pin_set(p1, 9, 1);
+ gpio_pin_configure(p1, 9, GPIO_OUTPUT);
+ gpio_pin_set(p1, 9, 1);
#endif
- return 0;
+ return 0;
}
-SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); \ No newline at end of file
+SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
diff --git a/app/boards/arm/planck/Kconfig.board b/app/boards/arm/planck/Kconfig.board
index 0952448..fe15e1a 100644
--- a/app/boards/arm/planck/Kconfig.board
+++ b/app/boards/arm/planck/Kconfig.board
@@ -1,6 +1,6 @@
# Planck V6 board configuration
-# Copyright (c) 2020 Peter Johanson
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
config BOARD_PLANCK_REV6
diff --git a/app/boards/arm/planck/Kconfig.defconfig b/app/boards/arm/planck/Kconfig.defconfig
index 93118d4..6f5bf52 100644
--- a/app/boards/arm/planck/Kconfig.defconfig
+++ b/app/boards/arm/planck/Kconfig.defconfig
@@ -1,6 +1,6 @@
# Planck keyboard configuration
-# Copyright (c) 2020 Peter Johanson
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
if BOARD_PLANCK_REV6
diff --git a/app/boards/arm/planck/pinmux.c b/app/boards/arm/planck/pinmux.c
index 5df5c90..61cc16a 100644
--- a/app/boards/arm/planck/pinmux.c
+++ b/app/boards/arm/planck/pinmux.c
@@ -15,55 +15,53 @@
/* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = {
#ifdef CONFIG_UART_1
- {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
- {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
+ {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
+ {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif /* CONFIG_UART_1 */
#ifdef CONFIG_UART_2
- {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
- {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
+ {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
+ {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif /* CONFIG_UART_2 */
#ifdef CONFIG_I2C_1
- {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
- {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
+ {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
+ {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif /* CONFIG_I2C_1 */
#ifdef CONFIG_I2C_2
- {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
- {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
+ {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
+ {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif /* CONFIG_I2C_2 */
#ifdef CONFIG_SPI_1
#ifdef CONFIG_SPI_STM32_USE_HW_SS
- {STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
+ {STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
- {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
- {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
- {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
+ {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
+ {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
+ {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif /* CONFIG_SPI_1 */
#ifdef CONFIG_SPI_2
#ifdef CONFIG_SPI_STM32_USE_HW_SS
- {STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
+ {STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
- {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
- {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
- {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
+ {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
+ {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
+ {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif /* CONFIG_SPI_2 */
#ifdef CONFIG_USB_DC_STM32
- {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
- {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
+ {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
+ {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
#endif /* CONFIG_USB_DC_STM32 */
#ifdef CONFIG_CAN_1
- {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
- {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
+ {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
+ {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif /* CONFIG_CAN_1 */
};
-static int pinmux_stm32_init(struct device *port)
-{
- ARG_UNUSED(port);
+static int pinmux_stm32_init(struct device *port) {
+ ARG_UNUSED(port);
- stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
+ stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
- return 0;
+ return 0;
}
-SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1,
- CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
+SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
diff --git a/app/boards/arm/planck/planck_rev6_defconfig b/app/boards/arm/planck/planck_rev6_defconfig
index a440ff1..e34ce00 100644
--- a/app/boards/arm/planck/planck_rev6_defconfig
+++ b/app/boards/arm/planck/planck_rev6_defconfig
@@ -20,9 +20,6 @@ CONFIG_CLOCK_STM32_HSE_CLOCK=8000000
CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL=y
# use HSE as PLL input
CONFIG_CLOCK_STM32_PLL_SRC_HSE=y
-# however, the board does not have an external oscillator, so just use
-# the 8MHz clock signal coming from integrated STLink
-CONFIG_CLOCK_STM32_HSE_BYPASS=y
# produce 72MHz clock at PLL output
CONFIG_CLOCK_STM32_PLL_PREDIV=1
CONFIG_CLOCK_STM32_PLL_MULTIPLIER=9
diff --git a/app/boards/arm/proton_c/pinmux.c b/app/boards/arm/proton_c/pinmux.c
index a6aaae0..9ffabd7 100644
--- a/app/boards/arm/proton_c/pinmux.c
+++ b/app/boards/arm/proton_c/pinmux.c
@@ -15,55 +15,53 @@
/* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
- {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
- {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
+ {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
+ {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
- {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
- {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
+ {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
+ {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
- {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
- {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
+ {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
+ {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
- {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
- {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
+ {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
+ {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS
- {STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
+ {STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
- {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
- {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
- {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
+ {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
+ {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
+ {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS
- {STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
+ {STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
- {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
- {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
- {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
+ {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
+ {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
+ {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif
#ifdef CONFIG_USB_DC_STM32
- {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
- {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
-#endif /* CONFIG_USB_DC_STM32 */
+ {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
+ {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
+#endif /* CONFIG_USB_DC_STM32 */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
- {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
- {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
+ {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
+ {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif
};
-static int pinmux_stm32_init(struct device *port)
-{
- ARG_UNUSED(port);
+static int pinmux_stm32_init(struct device *port) {
+ ARG_UNUSED(port);
- stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
+ stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
- return 0;
+ return 0;
}
-SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1,
- CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
+SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
diff --git a/app/boards/native_posix.conf b/app/boards/native_posix.conf
index 5bfb366..357b1b8 100644
--- a/app/boards/native_posix.conf
+++ b/app/boards/native_posix.conf
@@ -1,9 +1,8 @@
CONFIG_KSCAN=n
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
-CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER=y
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
-CONFIG_KSCAN_LOG_LEVEL_DBG=y
+CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index e9c4c95..bbb23b6 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,79 +1,18 @@
-#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
-#include <zmk/kscan-mock.h>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/kscan-mock.h>
/ {
chosen {
- zmk,kscan = &kscan0;
- zmk,keymap = &keymap0;
- };
-
- kscan0: kscan_0 {
- compatible = "zmk,kscan-composite";
- label = "KSCAN_COMP";
- rows = <2>;
- columns = <4>;
-
- left: left {
- kscan = <&left_hand>;
- };
-
- right: right {
- kscan = <&right_hand>;
- column-offset = <2>;
- };
+ zmk,kscan = &kscan;
};
- left_hand: kscan_1 {
+ kscan: kscan {
compatible = "zmk,kscan-mock";
- label = "KSCAN_LEFT";
+ label = "KSCAN_MOCK";
rows = <2>;
columns = <2>;
- events = <ZMK_MOCK_PRESS(0,1,300) ZMK_MOCK_PRESS(0,0,300) ZMK_MOCK_RELEASE(0,0,300) ZMK_MOCK_RELEASE(0,1,300)>;
- // events = <ZMK_MOCK_PRESS(0,0,800) ZMK_MOCK_RELEASE(0,0,800) ZMK_MOCK_PRESS(0,1,800) ZMK_MOCK_RELEASE(0,1,800)>;
- };
-
- right_hand: kscan_2 {
- compatible = "zmk,kscan-mock";
- label = "KSCAN_RIGHT";
-
- rows = <2>;
- columns = <2>;
- events = <ZMK_MOCK_PRESS(1,1,800) ZMK_MOCK_RELEASE(1,1,100) ZMK_MOCK_PRESS(0,1,800) ZMK_MOCK_RELEASE(0,1,100)>;
- };
-
- keymap0: keymap {
- compatible = "zmk,keymap";
- label ="Default keymap";
- layers = <&default &lower &raise>;
- };
-
- layers {
- compatible = "zmk,layers";
-
- default: layer_0 {
- label = "DEFAULT";
-
- bindings = <
- &kp B &mo 1 &kp C &kp E
- &kp D &kp G &kp F &kp Q>;
- };
-
- lower: layer_1 {
- label = "LOWER";
-
- bindings = <
- &cp M_NEXT &trans &kp O &kp Q
- &kp L &kp J &kp P &kp K>;
- };
-
- raise: layer_2 {
- label = "RAISE";
-
- bindings = <
- &kp W &kp U &kp I &kp N
- &kp X &kp M &kp C &kp B>;
- };
+ exit-after;
};
};
diff --git a/app/boards/shields/corne/corne.keymap b/app/boards/shields/corne/corne.keymap
index c0bbb4a..5f0f15f 100644
--- a/app/boards/shields/corne/corne.keymap
+++ b/app/boards/shields/corne/corne.keymap
@@ -1,5 +1,6 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
/ {
keymap {
@@ -21,14 +22,14 @@
lower_layer {
// -----------------------------------------------------------------------------------------
// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP |
-// | CTRL | | | | | | | LFT | DWN | UP | RGT | | |
+// | BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | LFT | DWN | UP | RGT | | |
// | SHFT | | | | | | | | | | | | |
// | GUI | | SPC | | ENT | | ALT |
bindings = <
- &kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp BKSP
- &kp LCTL &trans &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans &trans
- &kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
- &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
+ &kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp BKSP
+ &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LARW &kp DARW &kp UARW &kp RARW &trans &trans
+ &kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
>;
};
diff --git a/app/boards/shields/corne/corne_left.conf b/app/boards/shields/corne/corne_left.conf
index 338fa59..1e028a7 100644
--- a/app/boards/shields/corne/corne_left.conf
+++ b/app/boards/shields/corne/corne_left.conf
@@ -1,3 +1,2 @@
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file
diff --git a/app/boards/shields/corne/corne_right.conf b/app/boards/shields/corne/corne_right.conf
index be344c4..990cf7c 100644
--- a/app/boards/shields/corne/corne_right.conf
+++ b/app/boards/shields/corne/corne_right.conf
@@ -1,3 +1,2 @@
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file
diff --git a/app/boards/shields/iris/Kconfig.defconfig b/app/boards/shields/iris/Kconfig.defconfig
new file mode 100644
index 0000000..6439780
--- /dev/null
+++ b/app/boards/shields/iris/Kconfig.defconfig
@@ -0,0 +1,16 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+if SHIELD_IRIS_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Iris Left"
+
+endif
+
+if SHIELD_IRIS_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Iris Right"
+
+endif
diff --git a/app/boards/shields/iris/Kconfig.shield b/app/boards/shields/iris/Kconfig.shield
new file mode 100644
index 0000000..370bd22
--- /dev/null
+++ b/app/boards/shields/iris/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+config SHIELD_IRIS_LEFT
+ def_bool $(shields_list_contains,iris_left)
+
+config SHIELD_IRIS_RIGHT
+ def_bool $(shields_list_contains,iris_right)
diff --git a/app/boards/shields/iris/iris.conf b/app/boards/shields/iris/iris.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/boards/shields/iris/iris.conf
diff --git a/app/boards/shields/iris/iris.dtsi b/app/boards/shields/iris/iris.dtsi
new file mode 100644
index 0000000..f6e32c4
--- /dev/null
+++ b/app/boards/shields/iris/iris.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <16>;
+ rows = <4>;
+// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
+// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
+// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
+// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
+// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 |
+ map = <
+RC(0,0) 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(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(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(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,2) RC(4,9) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+ RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+}; \ No newline at end of file
diff --git a/app/boards/shields/iris/iris.keymap b/app/boards/shields/iris/iris.keymap
new file mode 100644
index 0000000..3bd74ed
--- /dev/null
+++ b/app/boards/shields/iris/iris.keymap
@@ -0,0 +1,60 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` |
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | - |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | "[" | | "]" | N | M | , | . | / | SHIFT |
+// | GUI | LOWER| SPACE | | ENTER | RAISE| ALT |
+ bindings = <
+&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp GRAV
+&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp MINUS
+&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp RALT
+ >;
+ };
+
+ lower_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | BTCLR | BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
+// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
+// | | | | | | | | | | | _ | + | { | } | "|" |
+// | | | | | | | |
+ bindings = <
+&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
+&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
+ &trans &trans &trans &trans &trans &trans
+ >;
+ };
+
+ raise_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | | <- | ^ | v | -> | |
+// | F7 | F8 | F9 | F10 | F11 | F12 | | | | + | - | = | [ | ] | \ |
+// | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans
+&kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &kp KPLS &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH
+ &trans &trans &trans &trans &trans &trans
+ >;
+ };
+ };
+};
diff --git a/app/boards/shields/iris/iris_left.conf b/app/boards/shields/iris/iris_left.conf
new file mode 100644
index 0000000..1e028a7
--- /dev/null
+++ b/app/boards/shields/iris/iris_left.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
diff --git a/app/boards/shields/iris/iris_left.overlay b/app/boards/shields/iris/iris_left.overlay
new file mode 100644
index 0000000..e04638e
--- /dev/null
+++ b/app/boards/shields/iris/iris_left.overlay
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "iris.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <0 42>;
+};
diff --git a/app/boards/shields/iris/iris_right.conf b/app/boards/shields/iris/iris_right.conf
new file mode 100644
index 0000000..990cf7c
--- /dev/null
+++ b/app/boards/shields/iris/iris_right.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/iris/iris_right.overlay b/app/boards/shields/iris/iris_right.overlay
new file mode 100644
index 0000000..2d5dce8
--- /dev/null
+++ b/app/boards/shields/iris/iris_right.overlay
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "iris.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <11 43>;
+};
diff --git a/app/boards/shields/kyria/kyria_left.conf b/app/boards/shields/kyria/kyria_left.conf
index 338fa59..e51dee4 100644
--- a/app/boards/shields/kyria/kyria_left.conf
+++ b/app/boards/shields/kyria/kyria_left.conf
@@ -1,3 +1,2 @@
CONFIG_ZMK_SPLIT=y
-CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file
diff --git a/app/boards/shields/kyria/kyria_right.conf b/app/boards/shields/kyria/kyria_right.conf
index be344c4..990cf7c 100644
--- a/app/boards/shields/kyria/kyria_right.conf
+++ b/app/boards/shields/kyria/kyria_right.conf
@@ -1,3 +1,2 @@
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file
diff --git a/app/boards/shields/lily58/lily58.conf b/app/boards/shields/lily58/lily58.conf
index 73f0d9d..31eb7c6 100644
--- a/app/boards/shields/lily58/lily58.conf
+++ b/app/boards/shields/lily58/lily58.conf
@@ -1,2 +1,6 @@
+# Uncomment to enable encoder
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
+
# Uncomment the following line to enable the Lily58 OLED Display
# CONFIG_ZMK_DISPLAY=y
diff --git a/app/boards/shields/lily58/lily58.dtsi b/app/boards/shields/lily58/lily58.dtsi
index 24f6805..556909f 100644
--- a/app/boards/shields/lily58/lily58.dtsi
+++ b/app/boards/shields/lily58/lily58.dtsi
@@ -15,7 +15,7 @@
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <16>;
- rows = <4>;
+ rows = <5>;
// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
@@ -45,6 +45,19 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7)
};
+ left_encoder: encoder_left {
+ compatible = "alps,ec11";
+ label = "LEFT_ENCODER";
+ a-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ };
+
+ sensors {
+ compatible = "zmk,keymap-sensors";
+ sensors = <&left_encoder>;
+ };
+
bt_unpair_combo: bt_unpair_combo {
compatible = "zmk,bt-unpair-combo";
};
diff --git a/app/boards/shields/lily58/lily58.keymap b/app/boards/shields/lily58/lily58.keymap
index 71bf4ad..61c19f8 100644
--- a/app/boards/shields/lily58/lily58.keymap
+++ b/app/boards/shields/lily58/lily58.keymap
@@ -1,5 +1,6 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
/ {
keymap {
@@ -19,22 +20,26 @@
&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
&kp LALT &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp BKSP &kp RGUI
>;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
};
lower_layer {
// ------------------------------------------------------------------------------------------------------------
-// | | | | | | | | | | | | | |
+// | BTCLR | BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
// | | | | | | | | | | | _ | + | { | } | "|" |
// | | | | | | | | | |
bindings = <
-&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
-&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
-&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
-&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
- &trans &trans &trans &trans &trans &trans &trans &trans
+&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
+&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
+ &trans &trans &trans &trans &trans &trans &trans &trans
>;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
};
raise_layer {
@@ -51,6 +56,8 @@
&kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &kp KPLS &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH
&trans &trans &trans &trans &trans &trans &trans &trans
>;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
};
};
};
diff --git a/app/boards/shields/lily58/lily58_left.conf b/app/boards/shields/lily58/lily58_left.conf
index 338fa59..6ff95d5 100644
--- a/app/boards/shields/lily58/lily58_left.conf
+++ b/app/boards/shields/lily58/lily58_left.conf
@@ -1,3 +1,6 @@
+# Uncomment to enable encoder
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
+
CONFIG_ZMK_SPLIT=y
-CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y \ No newline at end of file
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file
diff --git a/app/boards/shields/lily58/lily58_left.overlay b/app/boards/shields/lily58/lily58_left.overlay
index c6f630f..1752b6e 100644
--- a/app/boards/shields/lily58/lily58_left.overlay
+++ b/app/boards/shields/lily58/lily58_left.overlay
@@ -17,6 +17,10 @@
;
};
+&left_encoder {
+ status = "okay";
+};
+
&bt_unpair_combo {
- key-positions = <0 42>;
+ key-positions = <0 53>;
};
diff --git a/app/boards/shields/lily58/lily58_right.conf b/app/boards/shields/lily58/lily58_right.conf
index cf16779..990cf7c 100644
--- a/app/boards/shields/lily58/lily58_right.conf
+++ b/app/boards/shields/lily58/lily58_right.conf
@@ -1,3 +1,2 @@
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
-CONFIG_ZMK_BLE_UNPAIR_COMBO=y
diff --git a/app/boards/shields/lily58/lily58_right.overlay b/app/boards/shields/lily58/lily58_right.overlay
index 84f0b06..6c8e493 100644
--- a/app/boards/shields/lily58/lily58_right.overlay
+++ b/app/boards/shields/lily58/lily58_right.overlay
@@ -22,5 +22,5 @@
};
&bt_unpair_combo {
- key-positions = <11 43>;
+ key-positions = <11 54>;
};
diff --git a/app/boards/shields/qaz/Kconfig.defconfig b/app/boards/shields/qaz/Kconfig.defconfig
new file mode 100644
index 0000000..c84180b
--- /dev/null
+++ b/app/boards/shields/qaz/Kconfig.defconfig
@@ -0,0 +1,9 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+if SHIELD_QAZ
+
+config ZMK_KEYBOARD_NAME
+ default "QAZ"
+
+endif \ No newline at end of file
diff --git a/app/boards/shields/qaz/Kconfig.shield b/app/boards/shields/qaz/Kconfig.shield
new file mode 100644
index 0000000..7cc8f1e
--- /dev/null
+++ b/app/boards/shields/qaz/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+config SHIELD_QAZ
+ def_bool $(shields_list_contains,qaz)
diff --git a/app/boards/shields/qaz/qaz.keymap b/app/boards/shields/qaz/qaz.keymap
new file mode 100644
index 0000000..3622972
--- /dev/null
+++ b/app/boards/shields/qaz/qaz.keymap
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
+
+#define DEFAULT 0
+#define NUM_SYM 1
+#define NAV 2
+
+/ {
+ behaviors {
+ hm: homerow_mods {
+ compatible = "zmk,behavior-hold-tap";
+ label = "homerow mods";
+ #binding-cells = <2>;
+ tapping_term_ms = <225>;
+ flavor = "tap-preferred";
+ bindings = <&kp>, <&kp>;
+ };
+ };
+};
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+ bindings = <
+ &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P
+ &hm LGUI A &hm LALT S &hm LCTL D &hm LSFT F &kp G &kp H &hm RSFT J &hm RCTL K &hm RALT L &hm RGUI RET
+ &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT
+ &kp LSFT &kp LGUI &kp LALT &lt NAV RET &lt NUM_SYM SPC &kp COLN &kp QUOT &kp FSLH
+ >;
+ };
+ num_sym {
+ bindings = <
+ &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0
+ &trans &trans &trans &trans &trans &trans &trans &trans &kp EQL &kp MINUS
+ &kp DEL &none &none &none &none &none &none &none &kp DOT
+ &bootloader &reset &none &trans &trans &kp RET &trans &kp FSLH
+ >;
+ };
+
+ nav {
+ bindings = <
+ &bt BT_CLR &bt BT_NXT &bt BT_PRV &none &none &none &none &kp UARW &none &kp BKSP
+ &trans &trans &trans &trans &none &none &kp LARW &kp DARW &kp RARW &none
+ &none &none &none &none &none &none &none &none &none
+ &none &none &none &trans &trans &kp RET &trans &kp FSLH
+ >;
+ };
+ };
+}; \ No newline at end of file
diff --git a/app/boards/shields/qaz/qaz.overlay b/app/boards/shields/qaz/qaz.overlay
new file mode 100644
index 0000000..4e73370
--- /dev/null
+++ b/app/boards/shields/qaz/qaz.overlay
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <7>;
+ rows = <6>;
+ map = <
+ RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(4,0) RC(4,1) RC(4,2)
+ RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(5,0) RC(5,1) RC(5,2)
+ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(4,3) RC(5,3)
+ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(4,4)
+ >;
+ };
+
+
+ kscan0: kscan_0 {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+ diode-direction = "col2row";
+
+ col-gpios
+ = <&pro_micro_d 8 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 9 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 6 GPIO_ACTIVE_HIGH>
+ ;
+
+ row-gpios
+ = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+ };
+
+}; \ No newline at end of file
diff --git a/app/boards/shields/romac/Kconfig.defconfig b/app/boards/shields/romac/Kconfig.defconfig
new file mode 100644
index 0000000..5352797
--- /dev/null
+++ b/app/boards/shields/romac/Kconfig.defconfig
@@ -0,0 +1,10 @@
+# Copyright (c) 2020 Pete Johanson, Richard Jones
+# SPDX-License-Identifier: MIT
+
+if SHIELD_ROMAC
+
+config ZMK_KEYBOARD_NAME
+ default "RoMac"
+
+endif
+
diff --git a/app/boards/shields/romac/Kconfig.shield b/app/boards/shields/romac/Kconfig.shield
new file mode 100644
index 0000000..59669d3
--- /dev/null
+++ b/app/boards/shields/romac/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Pete Johanson, Richard Jones
+# SPDX-License-Identifier: MIT
+
+config SHIELD_ROMAC
+ def_bool $(shields_list_contains,romac)
diff --git a/app/boards/shields/romac/romac.conf b/app/boards/shields/romac/romac.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/boards/shields/romac/romac.conf
diff --git a/app/boards/shields/romac/romac.keymap b/app/boards/shields/romac/romac.keymap
new file mode 100644
index 0000000..97ea9c5
--- /dev/null
+++ b/app/boards/shields/romac/romac.keymap
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Richard Jones
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// -------------------
+// | 7 | 8 | 9 |
+// | 4 | 5 | 6 |
+// | 1 | 2 | 3 |
+// | MO(1) | 0 | . |
+// ----------------------
+ bindings = <
+ &kp NUM_7 &kp NUM_8 &kp NUM_9
+ &kp NUM_4 &kp NUM_5 &kp NUM_6
+ &kp NUM_1 &kp NUM_2 &kp NUM_3
+ &mo 1 &kp NUM_0 &kp DOT
+ >;
+ };
+
+ nav_layer {
+// -----------------------
+// | BTNXT | HOME | PGUP |
+// | BTPRV | END | PGDN |
+// | BTCLR | _ | _ |
+// | _ | _ | RET |
+// -----------------------
+ bindings = <
+ &bt BT_NXT &kp HOME &kp PGUP
+ &bt BT_PRV &kp END &kp PGDN
+ &bt BT_CLR &trans &trans
+ &trans &trans &kp RET
+ >;
+ };
+ };
+};
+
+
diff --git a/app/boards/shields/romac/romac.overlay b/app/boards/shields/romac/romac.overlay
new file mode 100644
index 0000000..67d5868
--- /dev/null
+++ b/app/boards/shields/romac/romac.overlay
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Richard Jones
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ col-gpios
+ = <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ ;
+
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ key-positions = <0 11>;
+ };
+
+};
+
diff --git a/app/boards/shields/settings_reset/Kconfig.defconfig b/app/boards/shields/settings_reset/Kconfig.defconfig
new file mode 100644
index 0000000..6d050cb
--- /dev/null
+++ b/app/boards/shields/settings_reset/Kconfig.defconfig
@@ -0,0 +1,10 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+if SHIELD_SETTINGS_RESET
+
+config ZMK_KEYBOARD_NAME
+ default "SETTINGS RESET"
+
+endif
+
diff --git a/app/boards/shields/settings_reset/Kconfig.shield b/app/boards/shields/settings_reset/Kconfig.shield
new file mode 100644
index 0000000..b5ce97f
--- /dev/null
+++ b/app/boards/shields/settings_reset/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+config SHIELD_SETTINGS_RESET
+ def_bool $(shields_list_contains,settings_reset)
diff --git a/app/boards/shields/settings_reset/settings_reset.conf b/app/boards/shields/settings_reset/settings_reset.conf
new file mode 100644
index 0000000..8052a6c
--- /dev/null
+++ b/app/boards/shields/settings_reset/settings_reset.conf
@@ -0,0 +1 @@
+CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START=y
diff --git a/app/boards/shields/settings_reset/settings_reset.keymap b/app/boards/shields/settings_reset/settings_reset.keymap
new file mode 100644
index 0000000..0523644
--- /dev/null
+++ b/app/boards/shields/settings_reset/settings_reset.keymap
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+ bindings = <
+ &reset
+ >;
+ };
+ };
+};
+
+
diff --git a/app/boards/shields/settings_reset/settings_reset.overlay b/app/boards/shields/settings_reset/settings_reset.overlay
new file mode 100644
index 0000000..a2b5799
--- /dev/null
+++ b/app/boards/shields/settings_reset/settings_reset.overlay
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-direct";
+ label = "KSCAN";
+
+ input-gpios
+ = <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
+ ;
+ };
+
+};
+
diff --git a/app/boards/shields/sofle/Kconfig.defconfig b/app/boards/shields/sofle/Kconfig.defconfig
new file mode 100644
index 0000000..58d8217
--- /dev/null
+++ b/app/boards/shields/sofle/Kconfig.defconfig
@@ -0,0 +1,54 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+if SHIELD_SOFLE_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Sofle Left"
+endif
+
+if SHIELD_SOFLE_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Sofle Right"
+endif
+
+if SHIELD_SOFLE_LEFT || SHIELD_SOFLE_RIGHT
+
+if ZMK_DISPLAY
+
+config I2C
+ default y
+
+config SSD1306
+ default y
+
+config SSD1306_REVERSE_MODE
+ default y
+
+endif # ZMK_DISPLAY
+
+if LVGL
+
+config LVGL_HOR_RES
+ default 128
+
+config LVGL_VER_RES
+ default 32
+
+config LVGL_VDB_SIZE
+ default 64
+
+config LVGL_DPI
+ default 148
+
+config LVGL_BITS_PER_PIXEL
+ default 1
+
+choice LVGL_COLOR_DEPTH
+ default LVGL_COLOR_DEPTH_1
+endchoice
+
+endif # LVGL
+
+endif
diff --git a/app/boards/shields/sofle/Kconfig.shield b/app/boards/shields/sofle/Kconfig.shield
new file mode 100644
index 0000000..e23a97a
--- /dev/null
+++ b/app/boards/shields/sofle/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+config SHIELD_SOFLE_LEFT
+ def_bool $(shields_list_contains,sofle_left)
+
+config SHIELD_SOFLE_RIGHT
+ def_bool $(shields_list_contains,sofle_right)
diff --git a/app/boards/shields/sofle/sofle.conf b/app/boards/shields/sofle/sofle.conf
new file mode 100644
index 0000000..fe3f0f4
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.conf
@@ -0,0 +1,9 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+# Uncomment the following line to enable the Sofle OLED Display
+# CONFIG_ZMK_DISPLAY=y
+
+# Uncomment these two lines to add support for encoders
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
diff --git a/app/boards/shields/sofle/sofle.dtsi b/app/boards/shields/sofle/sofle.dtsi
new file mode 100644
index 0000000..bff42f6
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.dtsi
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <16>;
+ rows = <4>;
+// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
+// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
+// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
+// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
+// | SW30 | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 | SW30 |
+ map = <
+RC(0,0) 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(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(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(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+ RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+ };
+
+ left_encoder: encoder_left {
+ compatible = "alps,ec11";
+ label = "LEFT_ENCODER";
+ a-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ status = "disabled";
+ };
+
+ right_encoder: encoder_right {
+ compatible = "alps,ec11";
+ label = "RIGHT_ENCODER";
+ a-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ status = "disabled";
+ };
+
+ sensors {
+ compatible = "zmk,keymap-sensors";
+ sensors = <&left_encoder &right_encoder>;
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+};
+
+&pro_micro_i2c {
+ status = "okay";
+
+ ssd1306@3c {
+ compatible = "solomon,ssd1306fb";
+ reg = <0x3c>;
+ label = "DISPLAY";
+ width = <128>;
+ height = <32>;
+ segment-offset = <0>;
+ page-offset = <0>;
+ display-offset = <0>;
+ multiplex-ratio = <31>;
+ segment-remap;
+ com-invdir;
+ com-sequential;
+ prechargep = <0x22>;
+ };
+};
diff --git a/app/boards/shields/sofle/sofle.keymap b/app/boards/shields/sofle/sofle.keymap
new file mode 100644
index 0000000..1cbe742
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.keymap
@@ -0,0 +1,64 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
+// | ESC | Q | W | E | R | T | | Y | U | I | O | P | BKSPC |
+// | TAB | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | MUTE | | | N | M | , | . | / | SHIFT |
+// | GUI | ALT | CTRL | LOWER| ENTER | | SPACE | RAISE| CTRL | ALT | GUI |
+ bindings = <
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &none
+&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BKSP
+&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &cp M_MUTE &none &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LGUI &kp LALT &kp LCTL &mo 1 &kp RET &kp SPC &mo 2 &kp RCTL &kp RALT &kp RGUI
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+
+ lower_layer {
+// TODO: Some binds are waiting for shifted keycode support.
+// ------------------------------------------------------------------------------------------------------------
+// | | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | F12 |
+// | | ! | @ | # | $ | % | | ^ | & | * | ( | ) | | |
+// | | = | - | + | { | } | | | | [ | ] | ; | : | \ | |
+// | | | | | | | | | | | |
+ bindings = <
+&trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp F12
+&trans &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp PIPE
+&trans &kp EQL &kp MINUS &kp KPLS &kp LCUR &kp RCUR &trans &trans &kp LBKT &kp RBKT &kp SCLN &kp COLN &kp BSLH &trans
+ &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+
+ raise_layer {
+// ------------------------------------------------------------------------------------------------------------
+// |BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
+// | | INS | PSCR | GUI | | | | PGUP | | ^ | | | |
+// | | ALT | CTRL | SHIFT | | CAPS | | PGDN | <- | v | -> | DEL | BKSPC |
+// | | UNDO | CUT | COPY | PASTE | | | | | | | | | | |
+// | | | | | | | | | | | |
+ bindings = <
+&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
+&trans &kp INS &kp PRSC &kp GUI &trans &trans &kp PGUP &trans &kp UARW &trans &kp NUM_0 &trans
+&trans &kp LALT &kp LCTL &kp LSFT &trans &kp CLCK &kp PGDN &kp LARW &kp DARW &kp RARW &kp DEL &kp BKSP
+&trans &kp UNDO &kp CUT &kp COPY &kp PSTE &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+ };
+};
diff --git a/app/boards/shields/sofle/sofle_left.conf b/app/boards/shields/sofle/sofle_left.conf
new file mode 100644
index 0000000..bbac735
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_left.conf
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
diff --git a/app/boards/shields/sofle/sofle_left.overlay b/app/boards/shields/sofle/sofle_left.overlay
new file mode 100644
index 0000000..0dfb753
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_left.overlay
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020 Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "sofle.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&left_encoder {
+ status = "okay";
+};
+
+&bt_unpair_combo {
+ key-positions = <0 54>;
+};
diff --git a/app/boards/shields/sofle/sofle_right.conf b/app/boards/shields/sofle/sofle_right.conf
new file mode 100644
index 0000000..ca5de38
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_right.conf
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/sofle/sofle_right.overlay b/app/boards/shields/sofle/sofle_right.overlay
new file mode 100644
index 0000000..8eaf076
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_right.overlay
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "sofle.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&right_encoder {
+ status = "okay";
+};
+
+&bt_unpair_combo {
+ key-positions = <11 55>;
+};
diff --git a/app/boards/shields/splitreus62/Kconfig.defconfig b/app/boards/shields/splitreus62/Kconfig.defconfig
new file mode 100644
index 0000000..a2464a7
--- /dev/null
+++ b/app/boards/shields/splitreus62/Kconfig.defconfig
@@ -0,0 +1,22 @@
+
+#Copyright (c) 2020 Derek Schmell
+#SPDX-License-Identifier: MIT
+
+
+if SHIELD_SPLITREUS62_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Splitreus62 Left"
+
+endif
+
+if SHIELD_SPLITREUS62_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Splitreus62 Right"
+
+endif
+
+if SHIELD_SPLITREUS62_LEFT || SHIELD_SPLITREUS62_RIGHT
+
+endif
diff --git a/app/boards/shields/splitreus62/Kconfig.shield b/app/boards/shields/splitreus62/Kconfig.shield
new file mode 100644
index 0000000..762d991
--- /dev/null
+++ b/app/boards/shields/splitreus62/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Derek Schmell
+# SPDX-License-Identifier: MIT
+
+config SHIELD_SPLITREUS62_LEFT
+ def_bool $(shields_list_contains,splitreus62_left)
+
+config SHIELD_SPLITREUS62_RIGHT
+ def_bool $(shields_list_contains,splitreus62_right)
diff --git a/app/boards/shields/splitreus62/splitreus62.conf b/app/boards/shields/splitreus62/splitreus62.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.conf
diff --git a/app/boards/shields/splitreus62/splitreus62.dtsi b/app/boards/shields/splitreus62/splitreus62.dtsi
new file mode 100644
index 0000000..c2bfbc4
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <12>;
+ rows = <6>;
+// | SW0 | SW5 | SW10 | SW15 | SW20 | SW25 | SW25 | SW20 | SW15 | SW10 | SW5 | SW1 |
+// | SW1 | SW6 | SW11 | SW16 | SW21 | SW26 | SW26 | SW21 | SW16 | SW11 | SW6 | SW2 |
+// | SW2 | SW7 | SW12 | SW17 | SW22 | SW27 | SW27 | SW22 | SW17 | SW12 | SW7 | SW3 |
+// | SW3 | SW8 | SW13 | SW18 | SW23 | SW28 | SW28 | SW23 | SW18 | SW13 | SW8 | SW4 |
+// | SW4 | SW9 | SW14 | SW19 | SW24 | SW29 | SW29 | SW24 | SW19 | SW14 | SW9 | SW5 |
+// SW30 | SW30
+ map = <
+RC(0,0) 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(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(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(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(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11)
+ RC(5,5) RC(5,6)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "row2col";
+ row-gpios
+ = <&pro_micro_d 1 GPIO_ACTIVE_HIGH >
+ , <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 4 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 5 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 6 GPIO_ACTIVE_HIGH>
+ ;
+
+ };
+};
diff --git a/app/boards/shields/splitreus62/splitreus62.keymap b/app/boards/shields/splitreus62/splitreus62.keymap
new file mode 100644
index 0000000..920e61a
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.keymap
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | | N | M | , | . | / | SHIFT |
+// | LCTL | LGUI | LALT | GRAV | | EQL | DEL | BKSP| | RET | SPC | LBKT | RBKT | LBKT | HOME | END |
+ bindings = <
+&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp MINUS
+&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
+&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+&kp LCTL &kp LGUI &kp LALT &kp GRAV &kp EQL &kp DEL &kp SPC &kp LBKT &kp RBKT &kp MINUS &kp HOME &kp END
+ &kp BKSP &kp RET
+ >;
+ };
+ };
+};
diff --git a/app/boards/shields/splitreus62/splitreus62_left.conf b/app/boards/shields/splitreus62/splitreus62_left.conf
new file mode 100644
index 0000000..e51dee4
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_left.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file
diff --git a/app/boards/shields/splitreus62/splitreus62_left.overlay b/app/boards/shields/splitreus62/splitreus62_left.overlay
new file mode 100644
index 0000000..b156d60
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_left.overlay
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "splitreus62.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+};
diff --git a/app/boards/shields/splitreus62/splitreus62_right.conf b/app/boards/shields/splitreus62/splitreus62_right.conf
new file mode 100644
index 0000000..a835adc
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_right.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y \ No newline at end of file
diff --git a/app/boards/shields/splitreus62/splitreus62_right.overlay b/app/boards/shields/splitreus62/splitreus62_right.overlay
new file mode 100644
index 0000000..5db87cc
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_right.overlay
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "splitreus62.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+};
diff --git a/app/cmake/zmk_config.cmake b/app/cmake/zmk_config.cmake
index 518c3c3..017dd11 100644
--- a/app/cmake/zmk_config.cmake
+++ b/app/cmake/zmk_config.cmake
@@ -44,6 +44,7 @@ endif()
set(CACHED_ZMK_CONFIG ${ZMK_CONFIG} CACHE STRING "Selected user ZMK config")
if (ZMK_CONFIG)
+ set(ENV{ZMK_CONFIG} "${ZMK_CONFIG}")
if(EXISTS ${ZMK_CONFIG}/boards)
message(STATUS "Adding ZMK config directory as board root: ${ZMK_CONFIG}")
list(APPEND BOARD_ROOT ${ZMK_CONFIG})
diff --git a/app/drivers/zephyr/ec11.c b/app/drivers/zephyr/ec11.c
index 1bc5d6a..a4e96c2 100644
--- a/app/drivers/zephyr/ec11.c
+++ b/app/drivers/zephyr/ec11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -18,136 +18,131 @@
LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL);
-static int ec11_get_ab_state(struct device *dev)
-{
- struct ec11_data *drv_data = dev->driver_data;
- const struct ec11_config *drv_cfg = dev->config_info;
+static int ec11_get_ab_state(struct device *dev) {
+ struct ec11_data *drv_data = dev->driver_data;
+ const struct ec11_config *drv_cfg = dev->config_info;
- return (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) | gpio_pin_get(drv_data->b, drv_cfg->b_pin);
+ return (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) |
+ gpio_pin_get(drv_data->b, drv_cfg->b_pin);
}
-static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan)
-{
- struct ec11_data *drv_data = dev->driver_data;
- const struct ec11_config *drv_cfg = dev->config_info;
- u8_t val;
- s8_t delta;
-
- __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
-
- val = ec11_get_ab_state(dev);
-
- LOG_DBG("prev: %d, new: %d", drv_data->ab_state, val);
-
- switch(val | (drv_data->ab_state << 2)) {
- case 0b0010: case 0b0100: case 0b1101: case 0b1011:
- delta = -1;
- break;
- case 0b0001: case 0b0111: case 0b1110: case 0b1000:
- delta = 1;
- break;
- default:
- delta = 0;
- break;
- }
-
- LOG_DBG("Delta: %d", delta);
-
- drv_data->pulses += delta;
- drv_data->ab_state = val;
-
- drv_data->ticks = drv_data->pulses / drv_cfg->resolution;
- drv_data->delta = delta;
- drv_data->pulses %= drv_cfg->resolution;
-
- return 0;
+static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan) {
+ struct ec11_data *drv_data = dev->driver_data;
+ const struct ec11_config *drv_cfg = dev->config_info;
+ u8_t val;
+ s8_t delta;
+
+ __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
+
+ val = ec11_get_ab_state(dev);
+
+ LOG_DBG("prev: %d, new: %d", drv_data->ab_state, val);
+
+ switch (val | (drv_data->ab_state << 2)) {
+ case 0b0010:
+ case 0b0100:
+ case 0b1101:
+ case 0b1011:
+ delta = -1;
+ break;
+ case 0b0001:
+ case 0b0111:
+ case 0b1110:
+ case 0b1000:
+ delta = 1;
+ break;
+ default:
+ delta = 0;
+ break;
+ }
+
+ LOG_DBG("Delta: %d", delta);
+
+ drv_data->pulses += delta;
+ drv_data->ab_state = val;
+
+ drv_data->ticks = drv_data->pulses / drv_cfg->resolution;
+ drv_data->delta = delta;
+ drv_data->pulses %= drv_cfg->resolution;
+
+ return 0;
}
-static int ec11_channel_get(struct device *dev,
- enum sensor_channel chan,
- struct sensor_value *val)
-{
- struct ec11_data *drv_data = dev->driver_data;
-
- if (chan != SENSOR_CHAN_ROTATION) {
- return -ENOTSUP;
- }
-
- val->val1 = drv_data->ticks;
- val->val2 = drv_data->delta;
-
- return 0;
+static int ec11_channel_get(struct device *dev, enum sensor_channel chan,
+ struct sensor_value *val) {
+ struct ec11_data *drv_data = dev->driver_data;
+
+ if (chan != SENSOR_CHAN_ROTATION) {
+ return -ENOTSUP;
+ }
+
+ val->val1 = drv_data->ticks;
+ val->val2 = drv_data->delta;
+
+ return 0;
}
static const struct sensor_driver_api ec11_driver_api = {
#ifdef CONFIG_EC11_TRIGGER
- .trigger_set = ec11_trigger_set,
+ .trigger_set = ec11_trigger_set,
#endif
- .sample_fetch = ec11_sample_fetch,
- .channel_get = ec11_channel_get,
+ .sample_fetch = ec11_sample_fetch,
+ .channel_get = ec11_channel_get,
};
-int ec11_init(struct device *dev)
-{
- struct ec11_data *drv_data = dev->driver_data;
- const struct ec11_config *drv_cfg = dev->config_info;
-
- LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label, drv_cfg->b_pin, drv_cfg->resolution);
-
- drv_data->a = device_get_binding(drv_cfg->a_label);
- if (drv_data->a == NULL) {
- LOG_ERR("Failed to get pointer to A GPIO device");
- return -EINVAL;
- }
+int ec11_init(struct device *dev) {
+ struct ec11_data *drv_data = dev->driver_data;
+ const struct ec11_config *drv_cfg = dev->config_info;
- drv_data->b = device_get_binding(drv_cfg->b_label);
- if (drv_data->b == NULL) {
- LOG_ERR("Failed to get pointer to B GPIO device");
- return -EINVAL;
- }
+ LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label,
+ drv_cfg->b_pin, drv_cfg->resolution);
- if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin,
- drv_cfg->a_flags
- | GPIO_INPUT)) {
- LOG_DBG("Failed to configure A pin");
- return -EIO;
- }
+ drv_data->a = device_get_binding(drv_cfg->a_label);
+ if (drv_data->a == NULL) {
+ LOG_ERR("Failed to get pointer to A GPIO device");
+ return -EINVAL;
+ }
- if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin,
- drv_cfg->b_flags
- | GPIO_INPUT)) {
- LOG_DBG("Failed to configure B pin");
- return -EIO;
- }
+ drv_data->b = device_get_binding(drv_cfg->b_label);
+ if (drv_data->b == NULL) {
+ LOG_ERR("Failed to get pointer to B GPIO device");
+ return -EINVAL;
+ }
+ if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin, drv_cfg->a_flags | GPIO_INPUT)) {
+ LOG_DBG("Failed to configure A pin");
+ return -EIO;
+ }
+ if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin, drv_cfg->b_flags | GPIO_INPUT)) {
+ LOG_DBG("Failed to configure B pin");
+ return -EIO;
+ }
#ifdef CONFIG_EC11_TRIGGER
- if (ec11_init_interrupt(dev) < 0) {
- LOG_DBG("Failed to initialize interrupt!");
- return -EIO;
- }
+ if (ec11_init_interrupt(dev) < 0) {
+ LOG_DBG("Failed to initialize interrupt!");
+ return -EIO;
+ }
#endif
- drv_data->ab_state = ec11_get_ab_state(dev);
+ drv_data->ab_state = ec11_get_ab_state(dev);
- return 0;
+ return 0;
}
-#define EC11_INST(n) \
- struct ec11_data ec11_data_##n; \
- const struct ec11_config ec11_cfg_##n = { \
- .a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
- .a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
- .a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
- .b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
- .b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
- .b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
- COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
- }; \
- DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, \
- &ec11_data_##n, \
- &ec11_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
- &ec11_driver_api);
+#define EC11_INST(n) \
+ struct ec11_data ec11_data_##n; \
+ const struct ec11_config ec11_cfg_##n = { \
+ .a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
+ .a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
+ .a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
+ .b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
+ .b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
+ .b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
+ COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
+ }; \
+ DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \
+ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api);
DT_INST_FOREACH_STATUS_OKAY(EC11_INST) \ No newline at end of file
diff --git a/app/drivers/zephyr/ec11.h b/app/drivers/zephyr/ec11.h
index 823d92d..e62e733 100644
--- a/app/drivers/zephyr/ec11.h
+++ b/app/drivers/zephyr/ec11.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -11,39 +11,39 @@
#include <sys/util.h>
struct ec11_config {
- const char *a_label;
- const u8_t a_pin;
- const u8_t a_flags;
+ const char *a_label;
+ const u8_t a_pin;
+ const u8_t a_flags;
- const char *b_label;
- const u8_t b_pin;
- const u8_t b_flags;
+ const char *b_label;
+ const u8_t b_pin;
+ const u8_t b_flags;
- const u8_t resolution;
+ const u8_t resolution;
};
struct ec11_data {
- struct device *a;
- struct device *b;
- u8_t ab_state;
- s8_t pulses;
- s8_t ticks;
- s8_t delta;
+ struct device *a;
+ struct device *b;
+ u8_t ab_state;
+ s8_t pulses;
+ s8_t ticks;
+ s8_t delta;
#ifdef CONFIG_EC11_TRIGGER
- struct gpio_callback a_gpio_cb;
- struct gpio_callback b_gpio_cb;
- struct device *dev;
+ struct gpio_callback a_gpio_cb;
+ struct gpio_callback b_gpio_cb;
+ struct device *dev;
- sensor_trigger_handler_t handler;
- const struct sensor_trigger *trigger;
+ sensor_trigger_handler_t handler;
+ const struct sensor_trigger *trigger;
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
- K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
- struct k_sem gpio_sem;
- struct k_thread thread;
+ K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
+ struct k_sem gpio_sem;
+ struct k_thread thread;
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
- struct k_work work;
+ struct k_work work;
#endif
#endif /* CONFIG_EC11_TRIGGER */
@@ -51,9 +51,8 @@ struct ec11_data {
#ifdef CONFIG_EC11_TRIGGER
-int ec11_trigger_set(struct device *dev,
- const struct sensor_trigger *trig,
- sensor_trigger_handler_t handler);
+int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
+ sensor_trigger_handler_t handler);
int ec11_init_interrupt(struct device *dev);
#endif
diff --git a/app/drivers/zephyr/ec11_trigger.c b/app/drivers/zephyr/ec11_trigger.c
index 709d1fb..248ac32 100644
--- a/app/drivers/zephyr/ec11_trigger.c
+++ b/app/drivers/zephyr/ec11_trigger.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -19,158 +19,130 @@ extern struct ec11_data ec11_driver;
#include <logging/log.h>
LOG_MODULE_DECLARE(EC11, CONFIG_SENSOR_LOG_LEVEL);
-static inline void setup_int(struct device *dev,
- bool enable)
-{
- struct ec11_data *data = dev->driver_data;
- const struct ec11_config *cfg = dev->config_info;
-
- LOG_DBG("enabled %s", (enable ? "true" : "false"));
-
- if (gpio_pin_interrupt_configure(data->a,
- cfg->a_pin,
- enable
- ? GPIO_INT_EDGE_BOTH
- : GPIO_INT_DISABLE)) {
- LOG_WRN("Unable to set A pin GPIO interrupt");
- }
-
- if (gpio_pin_interrupt_configure(data->b,
- cfg->b_pin,
- enable
- ? GPIO_INT_EDGE_BOTH
- : GPIO_INT_DISABLE)) {
- LOG_WRN("Unable to set A pin GPIO interrupt");
- }
+static inline void setup_int(struct device *dev, bool enable) {
+ struct ec11_data *data = dev->driver_data;
+ const struct ec11_config *cfg = dev->config_info;
+
+ LOG_DBG("enabled %s", (enable ? "true" : "false"));
+
+ if (gpio_pin_interrupt_configure(data->a, cfg->a_pin,
+ enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
+ LOG_WRN("Unable to set A pin GPIO interrupt");
+ }
+
+ if (gpio_pin_interrupt_configure(data->b, cfg->b_pin,
+ enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
+ LOG_WRN("Unable to set A pin GPIO interrupt");
+ }
}
-static void ec11_a_gpio_callback(struct device *dev,
- struct gpio_callback *cb, u32_t pins)
-{
- struct ec11_data *drv_data =
- CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
+static void ec11_a_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
+ struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
- LOG_DBG("");
+ LOG_DBG("");
- setup_int(drv_data->dev, false);
+ setup_int(drv_data->dev, false);
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
- k_sem_give(&drv_data->gpio_sem);
+ k_sem_give(&drv_data->gpio_sem);
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
- k_work_submit(&drv_data->work);
+ k_work_submit(&drv_data->work);
#endif
}
-static void ec11_b_gpio_callback(struct device *dev,
- struct gpio_callback *cb, u32_t pins)
-{
- struct ec11_data *drv_data =
- CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
+static void ec11_b_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
+ struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
- LOG_DBG("");
+ LOG_DBG("");
- setup_int(drv_data->dev, false);
+ setup_int(drv_data->dev, false);
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
- k_sem_give(&drv_data->gpio_sem);
+ k_sem_give(&drv_data->gpio_sem);
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
- k_work_submit(&drv_data->work);
+ k_work_submit(&drv_data->work);
#endif
}
-static void ec11_thread_cb(void *arg)
-{
- struct device *dev = arg;
- struct ec11_data *drv_data = dev->driver_data;
+static void ec11_thread_cb(void *arg) {
+ struct device *dev = arg;
+ struct ec11_data *drv_data = dev->driver_data;
- drv_data->handler(dev, drv_data->trigger);
+ drv_data->handler(dev, drv_data->trigger);
- setup_int(dev, true);
+ setup_int(dev, true);
}
#ifdef CONFIG_EC11_TRIGGER_OWN_THREAD
-static void ec11_thread(int dev_ptr, int unused)
-{
- struct device *dev = INT_TO_POINTER(dev_ptr);
- struct ec11_data *drv_data = dev->driver_data;
+static void ec11_thread(int dev_ptr, int unused) {
+ struct device *dev = INT_TO_POINTER(dev_ptr);
+ struct ec11_data *drv_data = dev->driver_data;
- ARG_UNUSED(unused);
+ ARG_UNUSED(unused);
- while (1) {
- k_sem_take(&drv_data->gpio_sem, K_FOREVER);
- ec11_thread_cb(dev);
- }
+ while (1) {
+ k_sem_take(&drv_data->gpio_sem, K_FOREVER);
+ ec11_thread_cb(dev);
+ }
}
#endif
#ifdef CONFIG_EC11_TRIGGER_GLOBAL_THREAD
-static void ec11_work_cb(struct k_work *work)
-{
- struct ec11_data *drv_data =
- CONTAINER_OF(work, struct ec11_data, work);
+static void ec11_work_cb(struct k_work *work) {
+ struct ec11_data *drv_data = CONTAINER_OF(work, struct ec11_data, work);
- LOG_DBG("");
+ LOG_DBG("");
- ec11_thread_cb(drv_data->dev);
+ ec11_thread_cb(drv_data->dev);
}
#endif
-int ec11_trigger_set(struct device *dev,
- const struct sensor_trigger *trig,
- sensor_trigger_handler_t handler)
-{
- struct ec11_data *drv_data = dev->driver_data;
+int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
+ sensor_trigger_handler_t handler) {
+ struct ec11_data *drv_data = dev->driver_data;
- setup_int(dev, false);
+ setup_int(dev, false);
- k_msleep(5);
+ k_msleep(5);
- drv_data->trigger = trig;
- drv_data->handler = handler;
+ drv_data->trigger = trig;
+ drv_data->handler = handler;
- setup_int(dev, true);
+ setup_int(dev, true);
- return 0;
+ return 0;
}
-int ec11_init_interrupt(struct device *dev)
-{
- struct ec11_data *drv_data = dev->driver_data;
- const struct ec11_config *drv_cfg = dev->config_info;
-
- drv_data->dev = dev;
- /* setup gpio interrupt */
+int ec11_init_interrupt(struct device *dev) {
+ struct ec11_data *drv_data = dev->driver_data;
+ const struct ec11_config *drv_cfg = dev->config_info;
+ drv_data->dev = dev;
+ /* setup gpio interrupt */
- gpio_init_callback(&drv_data->a_gpio_cb,
- ec11_a_gpio_callback,
- BIT(drv_cfg->a_pin));
+ gpio_init_callback(&drv_data->a_gpio_cb, ec11_a_gpio_callback, BIT(drv_cfg->a_pin));
- if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
- LOG_DBG("Failed to set A callback!");
- return -EIO;
- }
+ if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
+ LOG_DBG("Failed to set A callback!");
+ return -EIO;
+ }
- gpio_init_callback(&drv_data->b_gpio_cb,
- ec11_b_gpio_callback,
- BIT(drv_cfg->b_pin));
+ gpio_init_callback(&drv_data->b_gpio_cb, ec11_b_gpio_callback, BIT(drv_cfg->b_pin));
- if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
- LOG_DBG("Failed to set B callback!");
- return -EIO;
- }
+ if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
+ LOG_DBG("Failed to set B callback!");
+ return -EIO;
+ }
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
- k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
+ k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
- k_thread_create(&drv_data->thread, drv_data->thread_stack,
- CONFIG_EC11_THREAD_STACK_SIZE,
- (k_thread_entry_t)ec11_thread, dev,
- 0, NULL, K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY),
- 0, K_NO_WAIT);
+ k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_EC11_THREAD_STACK_SIZE,
+ (k_thread_entry_t)ec11_thread, dev, 0, NULL,
+ K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY), 0, K_NO_WAIT);
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
- k_work_init(&drv_data->work, ec11_work_cb);
+ k_work_init(&drv_data->work, ec11_work_cb);
#endif
- return 0;
+ return 0;
}
diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c
index 6e0beb0..1e5ab59 100644
--- a/app/drivers/zephyr/kscan_gpio_direct.c
+++ b/app/drivers/zephyr/kscan_gpio_direct.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -15,248 +15,215 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
-struct kscan_gpio_item_config
-{
- char *label;
- gpio_pin_t pin;
- gpio_flags_t flags;
+struct kscan_gpio_item_config {
+ char *label;
+ gpio_pin_t pin;
+ gpio_flags_t flags;
};
union work_reference {
- struct k_delayed_work delayed;
- struct k_work direct;
+ struct k_delayed_work delayed;
+ struct k_work direct;
};
-struct kscan_gpio_config
-{
- u8_t num_of_inputs;
- u8_t debounce_period;
- struct kscan_gpio_item_config inputs[];
+struct kscan_gpio_config {
+ u8_t num_of_inputs;
+ u8_t debounce_period;
+ struct kscan_gpio_item_config inputs[];
};
-struct kscan_gpio_data
-{
+struct kscan_gpio_data {
#if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
- struct k_timer poll_timer;
+ struct k_timer poll_timer;
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
- kscan_callback_t callback;
- union work_reference work;
- struct device *dev;
- u32_t pin_state;
- struct device *inputs[];
+ kscan_callback_t callback;
+ union work_reference work;
+ struct device *dev;
+ u32_t pin_state;
+ struct device *inputs[];
};
-static struct device **kscan_gpio_input_devices(struct device *dev)
-{
- struct kscan_gpio_data *data = dev->driver_data;
- return data->inputs;
+static struct device **kscan_gpio_input_devices(struct device *dev) {
+ struct kscan_gpio_data *data = dev->driver_data;
+ return data->inputs;
}
-static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev)
-{
- const struct kscan_gpio_config *cfg = dev->config_info;
- return cfg->inputs;
+static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev) {
+ const struct kscan_gpio_config *cfg = dev->config_info;
+ return cfg->inputs;
}
#if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
-struct kscan_gpio_irq_callback
-{
- union work_reference *work;
- u8_t debounce_period;
- struct gpio_callback callback;
+struct kscan_gpio_irq_callback {
+ union work_reference *work;
+ u8_t debounce_period;
+ struct gpio_callback callback;
};
-static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags)
-{
- const struct kscan_gpio_config *cfg = dev->config_info;
- struct device **devices = kscan_gpio_input_devices(dev);
- const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
-
- for (int i = 0; i < cfg->num_of_inputs; i++)
- {
- struct device *dev = devices[i];
- const struct kscan_gpio_item_config *cfg = &configs[i];
-
- int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
-
- if (err)
- {
- LOG_ERR("Unable to enable matrix GPIO interrupt");
- return err;
- }
- }
-
- return 0;
+static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags) {
+ const struct kscan_gpio_config *cfg = dev->config_info;
+ struct device **devices = kscan_gpio_input_devices(dev);
+ const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
+
+ for (int i = 0; i < cfg->num_of_inputs; i++) {
+ struct device *dev = devices[i];
+ const struct kscan_gpio_item_config *cfg = &configs[i];
+
+ int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
+
+ if (err) {
+ LOG_ERR("Unable to enable matrix GPIO interrupt");
+ return err;
+ }
+ }
+
+ return 0;
}
-static int kscan_gpio_direct_enable(struct device *dev)
-{
- return kscan_gpio_config_interrupts(dev,
- GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
+static int kscan_gpio_direct_enable(struct device *dev) {
+ return kscan_gpio_config_interrupts(dev, GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
}
-static int kscan_gpio_direct_disable(struct device *dev)
-{
- return kscan_gpio_config_interrupts(dev,
- GPIO_INT_DISABLE);
+static int kscan_gpio_direct_disable(struct device *dev) {
+ return kscan_gpio_config_interrupts(dev, GPIO_INT_DISABLE);
}
-static void kscan_gpio_irq_callback_handler(struct device *dev,
- struct gpio_callback *cb, gpio_port_pins_t pin)
-{
- struct kscan_gpio_irq_callback *data =
- CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
-
- if (data->debounce_period > 0) {
- k_delayed_work_cancel(&data->work->delayed);
- k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period));
- } else {
- k_work_submit(&data->work->direct);
- }
+static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_callback *cb,
+ gpio_port_pins_t pin) {
+ struct kscan_gpio_irq_callback *data =
+ CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
+
+ if (data->debounce_period > 0) {
+ k_delayed_work_cancel(&data->work->delayed);
+ k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period));
+ } else {
+ k_work_submit(&data->work->direct);
+ }
}
-#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
+#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
-static void kscan_gpio_timer_handler(struct k_timer *timer)
-{
- struct kscan_gpio_data *data =
- CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer);
+static void kscan_gpio_timer_handler(struct k_timer *timer) {
+ struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer);
- k_work_submit(&data->work.direct);
+ k_work_submit(&data->work.direct);
}
-static int kscan_gpio_direct_enable(struct device *dev)
-{
- struct kscan_gpio_data *data = dev->driver_data;
- k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10));
- return 0;
+static int kscan_gpio_direct_enable(struct device *dev) {
+ struct kscan_gpio_data *data = dev->driver_data;
+ k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10));
+ return 0;
}
-static int kscan_gpio_direct_disable(struct device *dev)
-{
- struct kscan_gpio_data *data = dev->driver_data;
- k_timer_stop(&data->poll_timer);
- return 0;
+static int kscan_gpio_direct_disable(struct device *dev) {
+ struct kscan_gpio_data *data = dev->driver_data;
+ k_timer_stop(&data->poll_timer);
+ return 0;
}
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
-static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback)
-{
- struct kscan_gpio_data *data = dev->driver_data;
- if (!callback)
- {
- return -EINVAL;
- }
- data->callback = callback;
- return 0;
+static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) {
+ struct kscan_gpio_data *data = dev->driver_data;
+ if (!callback) {
+ return -EINVAL;
+ }
+ data->callback = callback;
+ return 0;
}
-static int kscan_gpio_read(struct device *dev)
-{
- struct kscan_gpio_data *data = dev->driver_data;
- const struct kscan_gpio_config *cfg = dev->config_info;
- u32_t read_state = data->pin_state;
- LOG_DBG("Scanning the pins for updated state");
- for (int i = 0; i < cfg->num_of_inputs; i++)
- {
- struct device *in_dev = kscan_gpio_input_devices(dev)[i];
- const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i];
- WRITE_BIT(read_state, i, gpio_pin_get(in_dev, in_cfg->pin) > 0);
- }
- for (int i = 0; i < cfg->num_of_inputs; i++)
- {
- bool pressed = BIT(i) & read_state;
- if (pressed != (BIT(i) & data->pin_state))
- {
- LOG_DBG("Sending event at %d,%d state %s",
- 0, i, (pressed ? "on" : "off"));
- WRITE_BIT(data->pin_state, i, pressed);
- data->callback(dev, 0, i, pressed);
- }
- }
- return 0;
+static int kscan_gpio_read(struct device *dev) {
+ struct kscan_gpio_data *data = dev->driver_data;
+ const struct kscan_gpio_config *cfg = dev->config_info;
+ u32_t read_state = data->pin_state;
+ for (int i = 0; i < cfg->num_of_inputs; i++) {
+ struct device *in_dev = kscan_gpio_input_devices(dev)[i];
+ const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i];
+ WRITE_BIT(read_state, i, gpio_pin_get(in_dev, in_cfg->pin) > 0);
+ }
+ for (int i = 0; i < cfg->num_of_inputs; i++) {
+ bool prev_pressed = BIT(i) & data->pin_state;
+ bool pressed = BIT(i) & read_state;
+ if (pressed != prev_pressed) {
+ LOG_DBG("Sending event at %d,%d state %s", 0, i, (pressed ? "on" : "off"));
+ WRITE_BIT(data->pin_state, i, pressed);
+ data->callback(dev, 0, i, pressed);
+ }
+ }
+ return 0;
}
-static void kscan_gpio_work_handler(struct k_work *work)
-{
- struct kscan_gpio_data *data =
- CONTAINER_OF(work, struct kscan_gpio_data, work);
- kscan_gpio_read(data->dev);
+static void kscan_gpio_work_handler(struct k_work *work) {
+ struct kscan_gpio_data *data = CONTAINER_OF(work, struct kscan_gpio_data, work);
+ kscan_gpio_read(data->dev);
}
static const struct kscan_driver_api gpio_driver_api = {
- .config = kscan_gpio_direct_configure,
- .enable_callback = kscan_gpio_direct_enable,
- .disable_callback = kscan_gpio_direct_disable,
+ .config = kscan_gpio_direct_configure,
+ .enable_callback = kscan_gpio_direct_enable,
+ .disable_callback = kscan_gpio_direct_disable,
};
-#define KSCAN_DIRECT_INPUT_ITEM(i,n) \
- { \
- .label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \
- .pin = DT_INST_GPIO_PIN_BY_IDX(n, input_gpios, i), \
- .flags = DT_INST_GPIO_FLAGS_BY_IDX(n, input_gpios, i), \
- },
+#define KSCAN_DIRECT_INPUT_ITEM(i, n) \
+ { \
+ .label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \
+ .pin = DT_INST_GPIO_PIN_BY_IDX(n, input_gpios, i), \
+ .flags = DT_INST_GPIO_FLAGS_BY_IDX(n, input_gpios, i), \
+ },
#define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios)
-#define GPIO_INST_INIT(n) \
- COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, (static struct kscan_gpio_irq_callback \
- irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \
- static struct kscan_gpio_data kscan_gpio_data_##n = { \
- .inputs = { [INST_INPUT_LEN(n)-1] = NULL } \
- }; \
- static int kscan_gpio_init_##n(struct device *dev) \
- { \
- struct kscan_gpio_data *data = dev->driver_data; \
- const struct kscan_gpio_config *cfg = dev->config_info; \
- int err; \
- struct device **input_devices = kscan_gpio_input_devices(dev); \
- for (int i = 0; i < cfg->num_of_inputs; i++) \
- { \
- const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \
- input_devices[i] = device_get_binding(in_cfg->label); \
- if (!input_devices[i]) \
- { \
- LOG_ERR("Unable to find input GPIO device"); \
- return -EINVAL; \
- } \
- err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
- if (err) \
- { \
- LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
- return err; \
- } \
- COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
- ( \
- irq_callbacks_##n[i].work = &data->work; \
- irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \
- gpio_init_callback(&irq_callbacks_##n[i].callback, kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \
- err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
- if (err) \
- { \
- LOG_ERR("Error adding the callback to the column device"); \
- return err; \
- } \
- ), ()) \
- } \
- data->dev = dev; \
- COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ( )) \
- if (cfg->debounce_period > 0) { \
- k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \
- } else { \
- k_work_init(&data->work.direct, kscan_gpio_work_handler); \
- } \
- return 0; \
- } \
- static const struct kscan_gpio_config kscan_gpio_config_##n = { \
- .inputs = { UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n) }, \
- .num_of_inputs = INST_INPUT_LEN(n), \
- .debounce_period = DT_INST_PROP(n, debounce_period) \
- }; \
- DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
- &kscan_gpio_data_##n, &kscan_gpio_config_##n, \
- POST_KERNEL, CONFIG_ZMK_KSCAN_INIT_PRIORITY, \
- &gpio_driver_api);
+#define GPIO_INST_INIT(n) \
+ COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
+ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \
+ static struct kscan_gpio_data kscan_gpio_data_##n = { \
+ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \
+ static int kscan_gpio_init_##n(struct device *dev) { \
+ struct kscan_gpio_data *data = dev->driver_data; \
+ const struct kscan_gpio_config *cfg = dev->config_info; \
+ int err; \
+ struct device **input_devices = kscan_gpio_input_devices(dev); \
+ for (int i = 0; i < cfg->num_of_inputs; i++) { \
+ const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \
+ input_devices[i] = device_get_binding(in_cfg->label); \
+ if (!input_devices[i]) { \
+ LOG_ERR("Unable to find input GPIO device"); \
+ return -EINVAL; \
+ } \
+ err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
+ if (err) { \
+ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
+ return err; \
+ } \
+ COND_CODE_0( \
+ CONFIG_ZMK_KSCAN_GPIO_POLLING, \
+ (irq_callbacks_##n[i].work = &data->work; \
+ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \
+ gpio_init_callback(&irq_callbacks_##n[i].callback, \
+ kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \
+ err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
+ if (err) { \
+ LOG_ERR("Error adding the callback to the column device"); \
+ return err; \
+ }), \
+ ()) \
+ } \
+ data->dev = dev; \
+ COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
+ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \
+ if (cfg->debounce_period > 0) { \
+ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \
+ } else { \
+ k_work_init(&data->work.direct, kscan_gpio_work_handler); \
+ } \
+ return 0; \
+ } \
+ static const struct kscan_gpio_config kscan_gpio_config_##n = { \
+ .inputs = {UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n)}, \
+ .num_of_inputs = INST_INPUT_LEN(n), \
+ .debounce_period = DT_INST_PROP(n, debounce_period)}; \
+ DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
+ &kscan_gpio_data_##n, &kscan_gpio_config_##n, POST_KERNEL, \
+ CONFIG_ZMK_KSCAN_INIT_PRIORITY, &gpio_driver_api);
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)
diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c
index b19c492..634f694 100644
--- a/app/drivers/zephyr/kscan_gpio_matrix.c
+++ b/app/drivers/zephyr/kscan_gpio_matrix.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -15,266 +15,248 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
-struct kscan_gpio_item_config
-{
- char *label;
- gpio_pin_t pin;
- gpio_flags_t flags;
+struct kscan_gpio_item_config {
+ char *label;
+ gpio_pin_t pin;
+ gpio_flags_t flags;
};
-
-#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
- { \
- .label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
- .pin = DT_INST_GPIO_PIN_BY_IDX(n, prop, idx), \
- .flags = DT_INST_GPIO_FLAGS_BY_IDX(n, prop, idx), \
- },
+#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
+ { \
+ .label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
+ .pin = DT_INST_GPIO_PIN_BY_IDX(n, prop, idx), \
+ .flags = DT_INST_GPIO_FLAGS_BY_IDX(n, prop, idx), \
+ },
#define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx)
#define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx)
-
+
static int kscan_gpio_config_interrupts(struct device **devices,
- const struct kscan_gpio_item_config *configs,
- size_t len, gpio_flags_t flags)
-{
- for (int i = 0; i < len; i++)
- {
- struct device *dev = devices[i];
- const struct kscan_gpio_item_config *cfg = &configs[i];
+ const struct kscan_gpio_item_config *configs, size_t len,
+ gpio_flags_t flags) {
+ for (int i = 0; i < len; i++) {
+ struct device *dev = devices[i];
+ const struct kscan_gpio_item_config *cfg = &configs[i];
- int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
+ int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
- if (err)
- {
- LOG_ERR("Unable to enable matrix GPIO interrupt");
- return err;
- }
- }
+ if (err) {
+ LOG_ERR("Unable to enable matrix GPIO interrupt");
+ return err;
+ }
+ }
- return 0;
+ return 0;
}
#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_OUTPUT_LEN(n) COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_ROWS(n)), (INST_MATRIX_COLS(n)))
-#define INST_INPUT_LEN(n) COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_COLS(n)), (INST_MATRIX_ROWS(n)))
+#define INST_OUTPUT_LEN(n) \
+ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_ROWS(n)), \
+ (INST_MATRIX_COLS(n)))
+#define INST_INPUT_LEN(n) \
+ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_COLS(n)), \
+ (INST_MATRIX_ROWS(n)))
-#define GPIO_INST_INIT(n) \
- struct kscan_gpio_irq_callback_##n \
- { \
- struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
- struct gpio_callback callback; \
- }; \
- static struct kscan_gpio_irq_callback_##n \
- irq_callbacks_##n[INST_INPUT_LEN(n)]; \
- struct kscan_gpio_config_##n \
- { \
- struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
- struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
- }; \
- struct kscan_gpio_data_##n \
- { \
- kscan_callback_t callback; \
- 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)]; \
- struct device *rows[INST_MATRIX_ROWS(n)]; \
- struct device *cols[INST_MATRIX_COLS(n)]; \
- struct device *dev; \
- }; \
- static struct device **kscan_gpio_input_devices_##n(struct device *dev) \
- { \
- struct kscan_gpio_data_##n *data = dev->driver_data; \
- return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), (data->rows))); \
- } \
- static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) \
- { \
- const struct kscan_gpio_config_##n *cfg = dev->config_info; \
- return ((COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \
- } \
- static struct device **kscan_gpio_output_devices_##n(struct device *dev) \
- { \
- struct kscan_gpio_data_##n *data = dev->driver_data; \
- return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), (data->cols))); \
- } \
- static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n(struct device *dev) \
- { \
- const struct kscan_gpio_config_##n *cfg = dev->config_info; \
- return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
- } \
- static int kscan_gpio_enable_interrupts_##n(struct device *dev) \
- { \
- return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
- GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \
- } \
- static int kscan_gpio_disable_interrupts_##n(struct device *dev) \
- { \
- return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
- GPIO_INT_DISABLE); \
- } \
- static void kscan_gpio_set_output_state_##n(struct device *dev, int value) \
- { \
- for (int i = 0; i < INST_OUTPUT_LEN(n); i++) \
- { \
- struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \
- const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \
- gpio_pin_set(in_dev, cfg->pin, value); \
- } \
- } \
- static void kscan_gpio_set_matrix_state_##n(bool state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)], u32_t input_index, u32_t output_index, bool value) \
- { \
- state[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (output_index), (input_index))][COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (input_index), (output_index))] = value; \
- } \
- static int kscan_gpio_read_##n(struct device *dev) \
- { \
- bool submit_follow_up_read = false; \
- struct kscan_gpio_data_##n *data = dev->driver_data; \
- static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
- /* Disable our interrupts temporarily while we scan, to avoid */ \
- /* re-entry while we iterate columns and set them active one by one */ \
- /* to get pressed state for each matrix cell. */ \
- kscan_gpio_disable_interrupts_##n(dev); \
- kscan_gpio_set_output_state_##n(dev, 0); \
- for (int o = 0; o < INST_OUTPUT_LEN(n); o++) \
- { \
- 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]; \
- gpio_pin_set(out_dev, out_cfg->pin, 1); \
- for (int i = 0; i < INST_INPUT_LEN(n); i++) \
- { \
- struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
- const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
- kscan_gpio_set_matrix_state_##n(read_state, i, o, gpio_pin_get(in_dev, in_cfg->pin) > 0); \
- } \
- gpio_pin_set(out_dev, out_cfg->pin, 0); \
- } \
- /* Set all our outputs as active again, then re-enable interrupts, */ \
- /* so we can trigger interrupts again for future press/release */ \
- kscan_gpio_set_output_state_##n(dev, 1); \
- kscan_gpio_enable_interrupts_##n(dev); \
- for (int r = 0; r < INST_MATRIX_ROWS(n); r++) \
- { \
- for (int c = 0; c < INST_MATRIX_COLS(n); c++) \
- { \
- bool pressed = read_state[r][c]; \
- /* Follow up reads needed because further interrupts won't fire on already tripped input GPIO pins */ \
- submit_follow_up_read = (submit_follow_up_read || pressed); \
- if (pressed != data->matrix_state[r][c]) \
- { \
- LOG_DBG("Sending event at %d,%d state %s", \
- r, c, (pressed ? "on" : "off")); \
- data->matrix_state[r][c] = pressed; \
- data->callback(dev, r, c, pressed); \
- } \
- } \
- } \
- if (submit_follow_up_read) { \
- COND_CODE_0(DT_INST_PROP(n, debounce_period), \
- ({ k_work_submit(&data->work); }), \
- ({ \
- k_delayed_work_cancel(&data->work); \
- k_delayed_work_submit(&data->work, K_MSEC(5)); })) \
- } \
- return 0; \
- } \
- 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); \
- kscan_gpio_read_##n(data->dev); \
- } \
- static void kscan_gpio_irq_callback_handler_##n(struct device *dev, \
- struct gpio_callback *cb, gpio_port_pins_t pin) \
- { \
- struct kscan_gpio_irq_callback_##n *data = \
- CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
- COND_CODE_0(DT_INST_PROP(n, debounce_period), \
- ({ k_work_submit(data->work); }), \
- ({ \
- k_delayed_work_cancel(data->work); \
- k_delayed_work_submit(data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); })) \
- } \
- static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
- .rows = { [INST_MATRIX_ROWS(n)-1] = NULL}, \
- .cols = { [INST_MATRIX_COLS(n)-1] = NULL }\
- }; \
- static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) \
- { \
- struct kscan_gpio_data_##n *data = dev->driver_data; \
- if (!callback) \
- { \
- return -EINVAL; \
- } \
- data->callback = callback; \
- return 0; \
- }; \
- static int kscan_gpio_enable_##n(struct device *dev) \
- { \
- int err = kscan_gpio_enable_interrupts_##n(dev); \
- if (err) { return err; } \
- return kscan_gpio_read_##n(dev); \
- }; \
- static int kscan_gpio_init_##n(struct device *dev) \
- { \
- struct kscan_gpio_data_##n *data = dev->driver_data; \
- int err; \
- struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
- for (int i = 0; i < INST_INPUT_LEN(n); i++) \
- { \
- const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
- input_devices[i] = device_get_binding(in_cfg->label); \
- if (!input_devices[i]) \
- { \
- LOG_ERR("Unable to find input GPIO device"); \
- return -EINVAL; \
- } \
- err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
- if (err) \
- { \
- LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
- return err; \
- } \
- irq_callbacks_##n[i].work = &data->work; \
- gpio_init_callback(&irq_callbacks_##n[i].callback, kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
- err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
- if (err) \
- { \
- LOG_ERR("Error adding the callback to the column device"); \
- return err; \
- } \
- } \
- struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
- for (int o = 0; o < INST_OUTPUT_LEN(n); o++) \
- { \
- const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
- output_devices[o] = device_get_binding(out_cfg->label); \
- if (!output_devices[o]) \
- { \
- LOG_ERR("Unable to find output GPIO device"); \
- return -EINVAL; \
- } \
- err = gpio_pin_configure(output_devices[o], out_cfg->pin, GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
- if (err) \
- { \
- LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, out_cfg->label); \
- return err; \
- } \
- } \
- data->dev = dev; \
- (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))(&data->work, kscan_gpio_work_handler_##n); \
- return 0; \
- } \
- static const struct kscan_driver_api gpio_driver_api_##n = { \
- .config = kscan_gpio_configure_##n, \
- .enable_callback = kscan_gpio_enable_##n, \
- .disable_callback = kscan_gpio_disable_interrupts_##n, \
- }; \
- static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
- .rows = { UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n) }, \
- .cols = { UTIL_LISTIFY(INST_MATRIX_COLS(n), _KSCAN_GPIO_COL_CFG_INIT, n) }, \
- }; \
- DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
- &kscan_gpio_data_##n, &kscan_gpio_config_##n, \
- APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \
- &gpio_driver_api_##n);
+#define GPIO_INST_INIT(n) \
+ struct kscan_gpio_irq_callback_##n { \
+ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
+ struct gpio_callback callback; \
+ }; \
+ static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \
+ struct kscan_gpio_config_##n { \
+ struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
+ struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
+ }; \
+ struct kscan_gpio_data_##n { \
+ kscan_callback_t callback; \
+ 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)]; \
+ struct device *rows[INST_MATRIX_ROWS(n)]; \
+ struct device *cols[INST_MATRIX_COLS(n)]; \
+ struct device *dev; \
+ }; \
+ static struct device **kscan_gpio_input_devices_##n(struct device *dev) { \
+ struct kscan_gpio_data_##n *data = dev->driver_data; \
+ return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), \
+ (data->rows))); \
+ } \
+ static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) { \
+ const struct kscan_gpio_config_##n *cfg = dev->config_info; \
+ return (( \
+ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \
+ } \
+ static struct device **kscan_gpio_output_devices_##n(struct device *dev) { \
+ struct kscan_gpio_data_##n *data = dev->driver_data; \
+ return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), \
+ (data->cols))); \
+ } \
+ static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n( \
+ struct device *dev) { \
+ const struct kscan_gpio_config_##n *cfg = dev->config_info; \
+ return ( \
+ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
+ } \
+ static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \
+ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
+ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
+ GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \
+ } \
+ static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \
+ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
+ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
+ GPIO_INT_DISABLE); \
+ } \
+ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \
+ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \
+ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \
+ const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \
+ gpio_pin_set(in_dev, cfg->pin, value); \
+ } \
+ } \
+ static void kscan_gpio_set_matrix_state_##n( \
+ bool state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)], u32_t input_index, \
+ u32_t output_index, bool value) { \
+ state[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (output_index), \
+ (input_index))] \
+ [COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (input_index), \
+ (output_index))] = value; \
+ } \
+ static int kscan_gpio_read_##n(struct device *dev) { \
+ bool submit_follow_up_read = false; \
+ struct kscan_gpio_data_##n *data = dev->driver_data; \
+ static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
+ /* Disable our interrupts temporarily while we scan, to avoid */ \
+ /* re-entry while we iterate columns and set them active one by one */ \
+ /* to get pressed state for each matrix cell. */ \
+ kscan_gpio_disable_interrupts_##n(dev); \
+ kscan_gpio_set_output_state_##n(dev, 0); \
+ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
+ 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]; \
+ gpio_pin_set(out_dev, out_cfg->pin, 1); \
+ for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
+ struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
+ const struct kscan_gpio_item_config *in_cfg = \
+ &kscan_gpio_input_configs_##n(dev)[i]; \
+ kscan_gpio_set_matrix_state_##n(read_state, i, o, \
+ gpio_pin_get(in_dev, in_cfg->pin) > 0); \
+ } \
+ gpio_pin_set(out_dev, out_cfg->pin, 0); \
+ } \
+ /* Set all our outputs as active again, then re-enable interrupts, */ \
+ /* so we can trigger interrupts again for future press/release */ \
+ kscan_gpio_set_output_state_##n(dev, 1); \
+ kscan_gpio_enable_interrupts_##n(dev); \
+ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \
+ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \
+ bool pressed = read_state[r][c]; \
+ /* Follow up reads needed because further interrupts won't fire on already tripped \
+ * input GPIO pins */ \
+ submit_follow_up_read = (submit_follow_up_read || pressed); \
+ if (pressed != data->matrix_state[r][c]) { \
+ LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \
+ data->matrix_state[r][c] = pressed; \
+ data->callback(dev, r, c, pressed); \
+ } \
+ } \
+ } \
+ if (submit_follow_up_read) { \
+ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), ({ \
+ k_delayed_work_cancel(&data->work); \
+ k_delayed_work_submit(&data->work, K_MSEC(5)); \
+ })) \
+ } \
+ return 0; \
+ } \
+ 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); \
+ kscan_gpio_read_##n(data->dev); \
+ } \
+ static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \
+ gpio_port_pins_t pin) { \
+ struct kscan_gpio_irq_callback_##n *data = \
+ CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
+ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
+ k_delayed_work_cancel(data->work); \
+ k_delayed_work_submit(data->work, \
+ K_MSEC(DT_INST_PROP(n, debounce_period))); \
+ })) \
+ } \
+ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
+ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
+ static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \
+ struct kscan_gpio_data_##n *data = dev->driver_data; \
+ if (!callback) { \
+ return -EINVAL; \
+ } \
+ data->callback = callback; \
+ return 0; \
+ }; \
+ static int kscan_gpio_enable_##n(struct device *dev) { \
+ int err = kscan_gpio_enable_interrupts_##n(dev); \
+ if (err) { \
+ return err; \
+ } \
+ return kscan_gpio_read_##n(dev); \
+ }; \
+ static int kscan_gpio_init_##n(struct device *dev) { \
+ struct kscan_gpio_data_##n *data = dev->driver_data; \
+ int err; \
+ struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
+ for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
+ const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
+ input_devices[i] = device_get_binding(in_cfg->label); \
+ if (!input_devices[i]) { \
+ LOG_ERR("Unable to find input GPIO device"); \
+ return -EINVAL; \
+ } \
+ err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
+ if (err) { \
+ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
+ return err; \
+ } \
+ irq_callbacks_##n[i].work = &data->work; \
+ gpio_init_callback(&irq_callbacks_##n[i].callback, \
+ kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
+ err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
+ if (err) { \
+ LOG_ERR("Error adding the callback to the column device"); \
+ return err; \
+ } \
+ } \
+ struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
+ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
+ const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
+ output_devices[o] = device_get_binding(out_cfg->label); \
+ if (!output_devices[o]) { \
+ LOG_ERR("Unable to find output GPIO device"); \
+ return -EINVAL; \
+ } \
+ err = gpio_pin_configure(output_devices[o], out_cfg->pin, \
+ GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
+ if (err) { \
+ LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
+ out_cfg->label); \
+ return err; \
+ } \
+ } \
+ data->dev = dev; \
+ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \
+ &data->work, kscan_gpio_work_handler_##n); \
+ return 0; \
+ } \
+ static const struct kscan_driver_api gpio_driver_api_##n = { \
+ .config = kscan_gpio_configure_##n, \
+ .enable_callback = kscan_gpio_enable_##n, \
+ .disable_callback = kscan_gpio_disable_interrupts_##n, \
+ }; \
+ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
+ .rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \
+ .cols = {UTIL_LISTIFY(INST_MATRIX_COLS(n), _KSCAN_GPIO_COL_CFG_INIT, n)}, \
+ }; \
+ DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
+ &kscan_gpio_data_##n, &kscan_gpio_config_##n, APPLICATION, \
+ CONFIG_APPLICATION_INIT_PRIORITY, &gpio_driver_api_##n);
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
index 4cfb7a0..202202b 100644
--- a/app/dts/behaviors.dtsi
+++ b/app/dts/behaviors.dtsi
@@ -2,8 +2,10 @@
#include <behaviors/transparent.dtsi>
#include <behaviors/none.dtsi>
#include <behaviors/mod_tap.dtsi>
+#include <behaviors/layer_tap.dtsi>
#include <behaviors/momentary_layer.dtsi>
#include <behaviors/toggle_layer.dtsi>
#include <behaviors/reset.dtsi>
#include <behaviors/sensor_rotate_key_press.dtsi>
-#include <behaviors/rgb_underglow.dtsi> \ No newline at end of file
+#include <behaviors/rgb_underglow.dtsi>
+#include <behaviors/bluetooth.dtsi> \ No newline at end of file
diff --git a/app/dts/behaviors/bluetooth.dtsi b/app/dts/behaviors/bluetooth.dtsi
new file mode 100644
index 0000000..ea09f4a
--- /dev/null
+++ b/app/dts/behaviors/bluetooth.dtsi
@@ -0,0 +1,9 @@
+/ {
+ behaviors {
+ bt: behavior_bluetooth {
+ compatible = "zmk,behavior-bluetooth";
+ label = "BLUETOOTH";
+ #binding-cells = <2>;
+ };
+ };
+};
diff --git a/app/dts/behaviors/layer_tap.dtsi b/app/dts/behaviors/layer_tap.dtsi
new file mode 100644
index 0000000..af7319b
--- /dev/null
+++ b/app/dts/behaviors/layer_tap.dtsi
@@ -0,0 +1,12 @@
+/ {
+ behaviors {
+ lt: behavior_layer_tap {
+ compatible = "zmk,behavior-hold-tap";
+ label = "LAYER_TAP";
+ #binding-cells = <2>;
+ flavor = "tap-preferred";
+ tapping_term_ms = <200>;
+ bindings = <&mo>, <&kp>;
+ };
+ };
+};
diff --git a/app/dts/behaviors/mod_tap.dtsi b/app/dts/behaviors/mod_tap.dtsi
index 8e3b4e9..4ce732b 100644
--- a/app/dts/behaviors/mod_tap.dtsi
+++ b/app/dts/behaviors/mod_tap.dtsi
@@ -1,9 +1,12 @@
/ {
behaviors {
mt: behavior_mod_tap {
- compatible = "zmk,behavior-mod-tap";
+ compatible = "zmk,behavior-hold-tap";
label = "MOD_TAP";
#binding-cells = <2>;
+ flavor = "hold-preferred";
+ tapping_term_ms = <200>;
+ bindings = <&kp>, <&kp>;
};
};
};
diff --git a/app/dts/behaviors/reset.dtsi b/app/dts/behaviors/reset.dtsi
index 4e3b444..fc4fa14 100644
--- a/app/dts/behaviors/reset.dtsi
+++ b/app/dts/behaviors/reset.dtsi
@@ -1,3 +1,5 @@
+#include <dt-bindings/zmk/reset.h>
+
/ {
behaviors {
reset: behavior_reset {
@@ -5,5 +7,12 @@
label = "RESET";
#binding-cells = <0>;
};
+
+ bootloader: behavior_reset_dfu {
+ compatible = "zmk,behavior-reset";
+ label = "BOOTLOADER_RESET";
+ type = <RST_UF2>;
+ #binding-cells = <0>;
+ };
};
};
diff --git a/app/dts/behaviors/toggle_layer.dtsi b/app/dts/behaviors/toggle_layer.dtsi
index 86a050d..4045396 100644
--- a/app/dts/behaviors/toggle_layer.dtsi
+++ b/app/dts/behaviors/toggle_layer.dtsi
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
-
- / {
+
+/ {
behaviors {
tog: behavior_toggle_layer {
compatible = "zmk,behavior-toggle-layer";
diff --git a/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml b/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml
new file mode 100644
index 0000000..127ebe0
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Peter Johanson
+# SPDX-License-Identifier: MIT
+
+description: Bluetooth Behavior
+
+compatible: "zmk,behavior-bluetooth"
+
+include: two_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml b/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml
new file mode 100644
index 0000000..5f74e9a
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml
@@ -0,0 +1,23 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+description: Hold or Tap behavior
+
+compatible: "zmk,behavior-hold-tap"
+
+include: two_param.yaml
+
+properties:
+ bindings:
+ type: phandles
+ required: true
+ tapping_term_ms:
+ type: int
+ flavor:
+ type: string
+ required: false
+ default: "hold-preferred"
+ enum:
+ - "hold-preferred"
+ - "balanced"
+ - "tap-preferred"
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml b/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
deleted file mode 100644
index 7911082..0000000
--- a/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2020, Pete Johanson
-# SPDX-License-Identifier: MIT
-
-description: Mod-Tap Beavhior
-
-compatible: "zmk,behavior-mod-tap"
-
-include: two_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
index c8e5e6f..061b15e 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
@@ -6,3 +6,8 @@ description: Keyboard Reset Behavior
compatible: "zmk,behavior-reset"
include: zero_param.yaml
+
+properties:
+ type:
+ type: int
+ default: 0
diff --git a/app/dts/bindings/behaviors/zmk,behavior-rgb-underglow.yaml b/app/dts/bindings/behaviors/zmk,behavior-rgb-underglow.yaml
index 6b6d5b0..2cb74b9 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-rgb-underglow.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-rgb-underglow.yaml
@@ -1,8 +1,8 @@
-# Copyright (c) 2020, Nick Winans
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
description: RGB Underglow Action
compatible: "zmk,behavior-rgb-underglow"
-include: one_param.yaml \ No newline at end of file
+include: one_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml
index 065949f..0a9723f 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, Cody McGinnis <brainwart@gmail.com>
+# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
description: Toggle Layer
diff --git a/app/dts/bindings/zmk,kscan-mock.yaml b/app/dts/bindings/zmk,kscan-mock.yaml
index 41dd5b8..f9d83fa 100644
--- a/app/dts/bindings/zmk,kscan-mock.yaml
+++ b/app/dts/bindings/zmk,kscan-mock.yaml
@@ -15,3 +15,5 @@ properties:
type: int
columns:
type: int
+ exit-after:
+ type: boolean
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
index c24d11b..45b8bea 100644
--- a/app/include/drivers/behavior.h
+++ b/app/include/drivers/behavior.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -19,19 +19,20 @@
* (Internal use only.)
*/
-typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1, u32_t param2);
-typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor, u32_t param1, u32_t param2);
+typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1,
+ u32_t param2);
+typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor,
+ u32_t param1, u32_t param2);
__subsystem struct behavior_driver_api {
- behavior_keymap_binding_callback_t binding_pressed;
- behavior_keymap_binding_callback_t binding_released;
- behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
+ behavior_keymap_binding_callback_t binding_pressed;
+ behavior_keymap_binding_callback_t binding_released;
+ behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
};
/**
* @endcond
*/
-
/**
* @brief Handle the keymap binding being pressed
* @param dev Pointer to the device structure for the driver instance.
@@ -41,18 +42,18 @@ __subsystem struct behavior_driver_api {
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2);
+__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1,
+ u32_t param2);
-static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2)
-{
- const struct behavior_driver_api *api =
- (const struct behavior_driver_api *)dev->driver_api;
+static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position,
+ u32_t param1, u32_t param2) {
+ const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
- if (api->binding_pressed == NULL) {
- return -ENOTSUP;
- }
+ if (api->binding_pressed == NULL) {
+ return -ENOTSUP;
+ }
- return api->binding_pressed(dev, position, param1, param2);
+ return api->binding_pressed(dev, position, param1, param2);
}
/**
@@ -63,18 +64,18 @@ static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, u32_t param2);
+__syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1,
+ u32_t param2);
-static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, u32_t param2)
-{
- const struct behavior_driver_api *api =
- (const struct behavior_driver_api *)dev->driver_api;
+static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position,
+ u32_t param1, u32_t param2) {
+ const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
- if (api->binding_released == NULL) {
- return -ENOTSUP;
- }
+ if (api->binding_released == NULL) {
+ return -ENOTSUP;
+ }
- return api->binding_released(dev, position, param1, param2);
+ return api->binding_released(dev, position, param1, param2);
}
/**
@@ -87,21 +88,21 @@ static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u3
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor, u32_t param1, u32_t param2);
+__syscall int behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor,
+ u32_t param1, u32_t param2);
-static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor, u32_t param1, u32_t param2)
-{
- const struct behavior_driver_api *api =
- (const struct behavior_driver_api *)dev->driver_api;
+static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev,
+ struct device *sensor,
+ u32_t param1, u32_t param2) {
+ const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
- if (api->sensor_binding_triggered == NULL) {
- return -ENOTSUP;
- }
+ if (api->sensor_binding_triggered == NULL) {
+ return -ENOTSUP;
+ }
- return api->sensor_binding_triggered(dev, sensor, param1, param2);
+ return api->sensor_binding_triggered(dev, sensor, param1, param2);
}
-
/**
* @}
*/
diff --git a/app/include/dt-bindings/zmk/bt.h b/app/include/dt-bindings/zmk/bt.h
new file mode 100644
index 0000000..05fd65c
--- /dev/null
+++ b/app/include/dt-bindings/zmk/bt.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define BT_CLR_CMD 0
+#define BT_NXT_CMD 1
+#define BT_PRV_CMD 2
+#define BT_SEL_CMD 3
+// #define BT_FULL_RESET_CMD 4
+
+/*
+Note: Some future commands will include additional parameters, so we
+defines these aliases up front.
+*/
+
+#define BT_CLR BT_CLR_CMD 0
+#define BT_NXT BT_NXT_CMD 0
+#define BT_PRV BT_PRV_CMD 0
+#define BT_SEL BT_SEL_CMD \ No newline at end of file
diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h
index 0a52857..d3dd634 100644
--- a/app/include/dt-bindings/zmk/keys.h
+++ b/app/include/dt-bindings/zmk/keys.h
@@ -55,7 +55,7 @@
#define QUOT 0x34
#define GRAV 0x35
#define CMMA 0x36
-#define DOT 0x37
+#define DOT 0x37
#define FSLH 0x38
#define CLCK 0x39
#define F1 0x3A
@@ -77,8 +77,8 @@
#define INS 0x49
#define HOME 0x4A
#define PGUP 0x4B
-#define DEL 0x4C
-#define END 0x4D
+#define DEL 0x4C
+#define END 0x4D
#define PGDN 0x4E
#define RARW 0x4F
#define LARW 0x50
@@ -92,6 +92,11 @@
#define GUI 0x65
+#define UNDO 0x7A
+#define CUT 0x7B
+#define COPY 0x7C
+#define PSTE 0x7D
+
#define CURU 0xB4
#define LPRN 0xB6
diff --git a/app/include/zmk/kscan-mock.h b/app/include/dt-bindings/zmk/kscan-mock.h
index d481899..d481899 100644
--- a/app/include/zmk/kscan-mock.h
+++ b/app/include/dt-bindings/zmk/kscan-mock.h
diff --git a/app/include/dt-bindings/zmk/reset.h b/app/include/dt-bindings/zmk/reset.h
new file mode 100644
index 0000000..2b3d876
--- /dev/null
+++ b/app/include/dt-bindings/zmk/reset.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define RST_WARM 0x00
+#define RST_COLD 0x01
+
+// AdaFruit nrf52 Bootloader Specific. See
+// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
+
+#define RST_UF2 0x57 \ No newline at end of file
diff --git a/app/include/linker/zmk-events.ld b/app/include/linker/zmk-events.ld
index 44063be..78d00bb 100644
--- a/app/include/linker/zmk-events.ld
+++ b/app/include/linker/zmk-events.ld
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h
index 63edcc9..6f5815f 100644
--- a/app/include/zmk/behavior.h
+++ b/app/include/zmk/behavior.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#pragma once
diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h
index e760ed7..1cf71a7 100644
--- a/app/include/zmk/ble.h
+++ b/app/include/zmk/ble.h
@@ -1,7 +1,25 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#pragma once
#include <zmk/keys.h>
+#include <zmk/ble/profile.h>
+
+int zmk_ble_clear_bonds();
+int zmk_ble_prof_next();
+int zmk_ble_prof_prev();
+int zmk_ble_prof_select(u8_t index);
+
+bt_addr_le_t *zmk_ble_active_profile_addr();
+char *zmk_ble_active_profile_name();
int zmk_ble_unpair_all();
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event);
+
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr);
+#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ \ No newline at end of file
diff --git a/app/include/zmk/ble/profile.h b/app/include/zmk/ble/profile.h
new file mode 100644
index 0000000..9a79c6d
--- /dev/null
+++ b/app/include/zmk/ble/profile.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <bluetooth/addr.h>
+
+#define ZMK_BLE_PROFILE_NAME_MAX 15
+
+struct zmk_ble_profile {
+ char name[ZMK_BLE_PROFILE_NAME_MAX];
+ bt_addr_le_t peer;
+};
diff --git a/app/include/zmk/display.h b/app/include/zmk/display.h
index 93ac3ff..def4392 100644
--- a/app/include/zmk/display.h
+++ b/app/include/zmk/display.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/endpoints.h b/app/include/zmk/endpoints.h
index 4c0f442..aad6265 100644
--- a/app/include/zmk/endpoints.h
+++ b/app/include/zmk/endpoints.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
#include <zmk/keys.h>
diff --git a/app/include/zmk/event-manager.h b/app/include/zmk/event-manager.h
index 43d3f29..4b8f72c 100644
--- a/app/include/zmk/event-manager.h
+++ b/app/include/zmk/event-manager.h
@@ -1,22 +1,21 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
-
+
#pragma once
#include <stddef.h>
#include <kernel.h>
#include <zephyr/types.h>
-struct zmk_event_type
-{
+struct zmk_event_type {
const char *name;
};
struct zmk_event_header {
- const struct zmk_event_type* event;
+ const struct zmk_event_type *event;
u8_t last_listener_index;
};
@@ -24,8 +23,7 @@ struct zmk_event_header {
#define ZMK_EV_EVENT_CAPTURED 2
typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh);
-struct zmk_listener
-{
+struct zmk_listener {
zmk_listener_callback_t callback;
};
@@ -34,50 +32,50 @@ struct zmk_event_subscription {
const struct zmk_listener *listener;
};
-#define ZMK_EVENT_DECLARE(event_type) \
- struct event_type* new_##event_type(); \
- bool is_##event_type(const struct zmk_event_header *eh); \
- struct event_type* cast_##event_type(const struct zmk_event_header *eh); \
+#define ZMK_EVENT_DECLARE(event_type) \
+ struct event_type *new_##event_type(); \
+ bool is_##event_type(const struct zmk_event_header *eh); \
+ struct event_type *cast_##event_type(const struct zmk_event_header *eh); \
extern const struct zmk_event_type zmk_event_##event_type;
-#define ZMK_EVENT_IMPL(event_type) \
- const struct zmk_event_type zmk_event_##event_type = { \
- .name = STRINGIFY(event_type) \
- }; \
- const struct zmk_event_type* zmk_event_ref_##event_type __used __attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
- struct event_type* new_##event_type() { \
- struct event_type* ev = (struct event_type *) k_malloc(sizeof(struct event_type)); \
- ev->header.event = &zmk_event_##event_type; \
- return ev; \
- }; \
- bool is_##event_type(const struct zmk_event_header *eh) { \
- return eh->event == &zmk_event_##event_type; \
- }; \
- struct event_type* cast_##event_type(const struct zmk_event_header *eh) {\
- return (struct event_type*)eh; \
+#define ZMK_EVENT_IMPL(event_type) \
+ const struct zmk_event_type zmk_event_##event_type = {.name = STRINGIFY(event_type)}; \
+ const struct zmk_event_type *zmk_event_ref_##event_type __used \
+ __attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
+ struct event_type *new_##event_type() { \
+ struct event_type *ev = (struct event_type *)k_malloc(sizeof(struct event_type)); \
+ ev->header.event = &zmk_event_##event_type; \
+ return ev; \
+ }; \
+ bool is_##event_type(const struct zmk_event_header *eh) { \
+ return eh->event == &zmk_event_##event_type; \
+ }; \
+ 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};
-#define ZMK_SUBSCRIPTION(mod, ev_type) \
- const Z_DECL_ALIGN(struct zmk_event_subscription) _CONCAT(_CONCAT(zmk_event_sub_,mod),ev_type) __used __attribute__((__section__(".event_subscription"))) = { \
- .event_type = &zmk_event_##ev_type, \
- .listener = &zmk_listener_##mod, \
+#define ZMK_SUBSCRIPTION(mod, ev_type) \
+ const Z_DECL_ALIGN(struct zmk_event_subscription) \
+ _CONCAT(_CONCAT(zmk_event_sub_, mod), ev_type) __used \
+ __attribute__((__section__(".event_subscription"))) = { \
+ .event_type = &zmk_event_##ev_type, \
+ .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((struct zmk_event_header *)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);
-#define ZMK_EVENT_RELEASE(ev) \
- zmk_event_manager_release((struct zmk_event_header *)ev);
+#define ZMK_EVENT_RAISE_AT(ev, mod) \
+ zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod);
+
+#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((struct zmk_event_header *)ev);
int zmk_event_manager_raise(struct zmk_event_header *event);
-int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener);
+int zmk_event_manager_raise_after(struct zmk_event_header *event,
+ const struct zmk_listener *listener);
+int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener);
int zmk_event_manager_release(struct zmk_event_header *event);
diff --git a/app/include/zmk/events/ble-active-profile-changed.h b/app/include/zmk/events/ble-active-profile-changed.h
new file mode 100644
index 0000000..66f40c7
--- /dev/null
+++ b/app/include/zmk/events/ble-active-profile-changed.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <zephyr.h>
+#include <zmk/event-manager.h>
+#include <device.h>
+
+#include <zmk/ble/profile.h>
+
+struct ble_active_profile_changed {
+ struct zmk_event_header header;
+ u8_t index;
+ struct zmk_ble_profile *profile;
+};
+
+ZMK_EVENT_DECLARE(ble_active_profile_changed);
diff --git a/app/include/zmk/events/keycode-state-changed.h b/app/include/zmk/events/keycode-state-changed.h
index e12813c..4c00654 100644
--- a/app/include/zmk/events/keycode-state-changed.h
+++ b/app/include/zmk/events/keycode-state-changed.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -18,9 +18,9 @@ struct keycode_state_changed {
ZMK_EVENT_DECLARE(keycode_state_changed);
-inline struct keycode_state_changed* create_keycode_state_changed(u8_t usage_page, u32_t keycode, bool state)
-{
- struct keycode_state_changed* ev = new_keycode_state_changed();
+inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_page, u32_t keycode,
+ bool state) {
+ struct keycode_state_changed *ev = new_keycode_state_changed();
ev->usage_page = usage_page;
ev->keycode = keycode;
ev->state = state;
diff --git a/app/include/zmk/events/modifiers-state-changed.h b/app/include/zmk/events/modifiers-state-changed.h
index a17a093..d2e02f8 100644
--- a/app/include/zmk/events/modifiers-state-changed.h
+++ b/app/include/zmk/events/modifiers-state-changed.h
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
-
+
#pragma once
#include <zephyr.h>
@@ -18,9 +18,9 @@ struct modifiers_state_changed {
ZMK_EVENT_DECLARE(modifiers_state_changed);
-inline struct modifiers_state_changed* create_modifiers_state_changed(zmk_mod_flags modifiers, bool state)
-{
- struct modifiers_state_changed* ev = new_modifiers_state_changed();
+inline struct modifiers_state_changed *create_modifiers_state_changed(zmk_mod_flags modifiers,
+ bool state) {
+ struct modifiers_state_changed *ev = new_modifiers_state_changed();
ev->modifiers = modifiers;
ev->state = state;
diff --git a/app/include/zmk/events/position-state-changed.h b/app/include/zmk/events/position-state-changed.h
index c91688e..f88080d 100644
--- a/app/include/zmk/events/position-state-changed.h
+++ b/app/include/zmk/events/position-state-changed.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/events/sensor-event.h b/app/include/zmk/events/sensor-event.h
index f881ac5..a9302a5 100644
--- a/app/include/zmk/events/sensor-event.h
+++ b/app/include/zmk/events/sensor-event.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/handlers.h b/app/include/zmk/handlers.h
index a10851f..7ce1d27 100644
--- a/app/include/zmk/handlers.h
+++ b/app/include/zmk/handlers.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
#include <dt-bindings/zmk/keys.h>
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
index 138606a..744de98 100644
--- a/app/include/zmk/hid.h
+++ b/app/include/zmk/hid.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
#include <usb/usb_device.h>
@@ -134,25 +140,21 @@ static const u8_t zmk_hid_report_desc[] = {
// u8_t keys[6];
// } __packed;
-struct zmk_hid_keypad_report_body
-{
+struct zmk_hid_keypad_report_body {
zmk_mod_flags modifiers;
u8_t keys[13];
} __packed;
-struct zmk_hid_keypad_report
-{
+struct zmk_hid_keypad_report {
u8_t report_id;
struct zmk_hid_keypad_report_body body;
} __packed;
-struct zmk_hid_consumer_report_body
-{
+struct zmk_hid_consumer_report_body {
u8_t keys[6];
} __packed;
-struct zmk_hid_consumer_report
-{
+struct zmk_hid_consumer_report {
u8_t report_id;
struct zmk_hid_consumer_report_body body;
} __packed;
diff --git a/app/include/zmk/hog.h b/app/include/zmk/hog.h
index e2f976a..a7dda51 100644
--- a/app/include/zmk/hog.h
+++ b/app/include/zmk/hog.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#pragma once
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index c1f6393..6192587 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
bool zmk_keymap_layer_active(u8_t layer);
diff --git a/app/include/zmk/keys.h b/app/include/zmk/keys.h
index 6966bba..af474b1 100644
--- a/app/include/zmk/keys.h
+++ b/app/include/zmk/keys.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
#include <zephyr.h>
@@ -8,8 +14,7 @@ typedef u8_t zmk_action;
typedef u8_t zmk_mod;
typedef u8_t zmk_mod_flags;
-struct zmk_key_event
-{
+struct zmk_key_event {
u32_t column;
u32_t row;
zmk_key key;
diff --git a/app/include/zmk/kscan.h b/app/include/zmk/kscan.h
index ebffccd..3352600 100644
--- a/app/include/zmk/kscan.h
+++ b/app/include/zmk/kscan.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
int zmk_kscan_init(char *name);
diff --git a/app/include/zmk/matrix.h b/app/include/zmk/matrix.h
index 3088263..b3e2323 100644
--- a/app/include/zmk/matrix.h
+++ b/app/include/zmk/matrix.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
#include <devicetree.h>
@@ -9,20 +15,20 @@
#define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform)
#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
-#define ZMK_MATRIX_ROWS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE,rows)
-#define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE,columns)
+#define ZMK_MATRIX_ROWS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, rows)
+#define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, columns)
#else /* DT_HAS_CHOSEN(zmk_matrix_transform) */
-#if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,row_gpios)
-#define ZMK_MATRIX_ROWS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,row_gpios)
-#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,col_gpios)
-#elif DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,input_gpios)
+#if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID, row_gpios)
+#define ZMK_MATRIX_ROWS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, row_gpios)
+#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, col_gpios)
+#elif DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID, input_gpios)
#define ZMK_MATRIX_ROWS 1
-#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,input_gpios)
+#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, input_gpios)
#else
-#define ZMK_MATRIX_ROWS DT_PROP(ZMK_MATRIX_NODE_ID,rows)
-#define ZMK_MATRIX_COLS DT_PROP(ZMK_MATRIX_NODE_ID,columns)
+#define ZMK_MATRIX_ROWS DT_PROP(ZMK_MATRIX_NODE_ID, rows)
+#define ZMK_MATRIX_COLS DT_PROP(ZMK_MATRIX_NODE_ID, columns)
#endif
#define ZMK_KEYMAP_LEN (ZMK_MATRIX_COLS * ZMK_MATRIX_ROWS)
diff --git a/app/include/zmk/matrix_transform.h b/app/include/zmk/matrix_transform.h
index e9e969a..29c2afc 100644
--- a/app/include/zmk/matrix_transform.h
+++ b/app/include/zmk/matrix_transform.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#pragma once
u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column); \ No newline at end of file
diff --git a/app/include/zmk/rgb_underglow.h b/app/include/zmk/rgb_underglow.h
index 69e9a9b..94cc32c 100644
--- a/app/include/zmk/rgb_underglow.h
+++ b/app/include/zmk/rgb_underglow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Nick Winans <nick@winans.codes>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h
index c60cd4b..63dcade 100644
--- a/app/include/zmk/sensors.h
+++ b/app/include/zmk/sensors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h
index 59f2f71..a8dfbf6 100644
--- a/app/include/zmk/split/bluetooth/uuid.h
+++ b/app/include/zmk/split/bluetooth/uuid.h
@@ -3,10 +3,9 @@
#include <bluetooth/uuid.h>
#ifndef BT_UUID_NUM_OF_DIGITALS
-#define BT_UUID_NUM_OF_DIGITALS BT_UUID_DECLARE_16(0x2909)
+#define BT_UUID_NUM_OF_DIGITALS BT_UUID_DECLARE_16(0x2909)
#endif
-#define ZMK_BT_SPLIT_UUID(num) BT_UUID_128_ENCODE(num, 0x0096, 0x7107, 0xc967, 0xc5cfb1c2482a)
+#define ZMK_BT_SPLIT_UUID(num) BT_UUID_128_ENCODE(num, 0x0096, 0x7107, 0xc967, 0xc5cfb1c2482a)
#define ZMK_SPLIT_BT_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000)
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
-
diff --git a/app/include/zmk/usb_hid.h b/app/include/zmk/usb_hid.h
index 5d7c744..7ee2629 100644
--- a/app/include/zmk/usb_hid.h
+++ b/app/include/zmk/usb_hid.h
@@ -1,5 +1,10 @@
-#ifndef ZMK_USB_HID
-#define ZMK_USB_HID
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>
@@ -10,5 +15,3 @@
int zmk_usb_hid_init();
int zmk_usb_hid_send_report(u8_t *report, size_t len);
-
-#endif
diff --git a/app/prj.conf b/app/prj.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/prj.conf
diff --git a/app/run-test.sh b/app/run-test.sh
new file mode 100755
index 0000000..dd8c8ee
--- /dev/null
+++ b/app/run-test.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Copyright (c) 2020 The ZMK Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+if [ -z "$1" ]; then
+ echo "Usage: ./run-test.sh <path to testcase>"
+ exit 1
+elif [ "$1" = "all" ]; then
+ echo "" > ./build/tests/pass-fail.log
+ find tests -name native_posix.keymap -exec dirname \{\} \; | xargs -l -P 4 ./run-test.sh
+ err=$?
+ sort -k2 ./build/tests/pass-fail.log
+ exit $err
+fi
+
+testcase="$1"
+echo "Running $testcase:"
+
+west build -d build/$testcase -b native_posix -- -DZMK_CONFIG=$testcase > /dev/null 2>&1
+if [ $? -gt 0 ]; then
+ echo "FAIL: $testcase did not build" >> ./build/tests/pass-fail.log
+ exit 1
+else
+ ./build/$testcase/zephyr/zmk.exe | sed -e "s/.*> //" | tee build/$testcase/keycode_events_full.log | sed -n -f $testcase/events.patterns > build/$testcase/keycode_events.log
+ diff -au $testcase/keycode_events.snapshot build/$testcase/keycode_events.log
+ if [ $? -gt 0 ]; then
+ if [ -f $testcase/pending ]; then
+ echo "PEND: $testcase" >> ./build/tests/pass-fail.log
+ exit 0
+ else
+ echo "FAIL: $testcase" >> ./build/tests/pass-fail.log
+ exit 1
+ fi
+ else
+ echo "PASS: $testcase" >> ./build/tests/pass-fail.log
+ exit 0
+ fi
+fi \ No newline at end of file
diff --git a/app/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c
new file mode 100644
index 0000000..09fadba
--- /dev/null
+++ b/app/src/behaviors/behavior_bt.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_bluetooth
+
+#include <device.h>
+#include <drivers/behavior.h>
+
+#include <dt-bindings/zmk/bt.h>
+
+#include <bluetooth/conn.h>
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <zmk/ble.h>
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) {
+ switch (command) {
+ case BT_CLR_CMD:
+ return zmk_ble_clear_bonds();
+ case BT_NXT_CMD:
+ return zmk_ble_prof_next();
+ case BT_PRV_CMD:
+ return zmk_ble_prof_prev();
+ case BT_SEL_CMD:
+ return zmk_ble_prof_select(arg);
+ default:
+ LOG_ERR("Unknown BT command: %d", command);
+ }
+
+ return -ENOTSUP;
+}
+
+static int behavior_bt_init(struct device *dev) { return 0; };
+
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command,
+ u32_t arg) {
+ return 0;
+}
+
+static const struct behavior_driver_api behavior_bt_driver_api = {
+ .binding_pressed = on_keymap_binding_pressed,
+ .binding_released = on_keymap_binding_released,
+};
+
+DEVICE_AND_API_INIT(behavior_bt, DT_INST_LABEL(0), behavior_bt_init, NULL, NULL, APPLICATION,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_bt_driver_api);
diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c
new file mode 100644
index 0000000..8f307a6
--- /dev/null
+++ b/app/src/behaviors/behavior_hold_tap.c
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_hold_tap
+
+#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_NODE_EXISTS(DT_DRV_INST(0))
+
+#define ZMK_BHV_HOLD_TAP_MAX_HELD 10
+#define ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS 40
+
+// increase if you have keyboard with more keys.
+#define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999
+
+enum flavor {
+ ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
+ ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
+ ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
+};
+
+struct behavior_hold_tap_behaviors {
+ struct zmk_behavior_binding tap;
+ struct zmk_behavior_binding hold;
+};
+
+typedef k_timeout_t (*timer_func)();
+
+struct behavior_hold_tap_config {
+ timer_func tapping_term_ms;
+ struct behavior_hold_tap_behaviors *behaviors;
+ enum flavor flavor;
+};
+
+// this data is specific for each hold-tap
+struct active_hold_tap {
+ s32_t position;
+ u32_t param_hold;
+ u32_t param_tap;
+ bool is_decided;
+ bool is_hold;
+ const struct behavior_hold_tap_config *config;
+ struct k_delayed_work work;
+ bool work_is_cancelled;
+};
+
+// The undecided hold tap is the hold tap that needs to be decided before
+// other keypress events can be released. While the undecided_hold_tap is
+// not NULL, most events are captured in captured_events.
+// After the hold_tap is decided, it will stay in the active_hold_taps until
+// its key-up has been processed and the delayed work is cleaned up.
+struct active_hold_tap *undecided_hold_tap = NULL;
+struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {};
+// We capture most position_state_changed events and some modifiers_state_changed events.
+const struct zmk_event_header *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
+
+static int capture_event(const struct zmk_event_header *event) {
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
+ if (captured_events[i] == NULL) {
+ captured_events[i] = event;
+ return 0;
+ }
+ }
+ return -ENOMEM;
+}
+
+static struct position_state_changed *find_captured_keydown_event(u32_t position) {
+ struct position_state_changed *last_match = NULL;
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
+ const struct zmk_event_header *eh = captured_events[i];
+ if (eh == NULL) {
+ return last_match;
+ }
+ if (!is_position_state_changed(eh)) {
+ continue;
+ }
+ struct position_state_changed *position_event = cast_position_state_changed(eh);
+ if (position_event->position == position && position_event->state) {
+ last_match = position_event;
+ }
+ }
+ return last_match;
+}
+
+const struct zmk_listener zmk_listener_behavior_hold_tap;
+
+static void release_captured_events() {
+ if (undecided_hold_tap != NULL) {
+ return;
+ }
+
+ // We use a trick to prevent copying the captured_events array.
+ //
+ // Events for different mod-tap instances are separated by a NULL pointer.
+ //
+ // The first event popped will never be catched by the next active hold-tap
+ // because to start capturing a mod-tap-key-down event must first completely
+ // go through the events queue.
+ //
+ // Example of this release process;
+ // [mt2_down, k1_down, k1_up, mt2_up, null, ...]
+ // ^
+ // mt2_down position event isn't captured because no hold-tap is active.
+ // mt2_down behavior event is handled, now we have an undecided hold-tap
+ // [null, k1_down, k1_up, mt2_up, null, ...]
+ // ^
+ // k1_down is captured by the mt2 mod-tap
+ // !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the
+ // first null encountered [mt1_down, null, k1_up, mt2_up, null, ...]
+ // ^
+ // k1_up event is captured by the new hold-tap:
+ // [k1_down, k1_up, null, mt2_up, null, ...]
+ // ^
+ // mt2_up event is not captured but causes release of mt2 behavior
+ // [k1_down, k1_up, null, null, null, ...]
+ // now mt2 will start releasing it's own captured positions.
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
+ const struct zmk_event_header *captured_event = captured_events[i];
+ if (captured_event == NULL) {
+ return;
+ }
+ captured_events[i] = NULL;
+ if (undecided_hold_tap != NULL) {
+ k_msleep(10);
+ }
+ if (is_position_state_changed(captured_event)) {
+ struct position_state_changed *position_event =
+ cast_position_state_changed(captured_event);
+ LOG_DBG("Releasing key position event for position %d %s", position_event->position,
+ (position_event->state ? "pressed" : "released"));
+ } else {
+ struct keycode_state_changed *modifier_event =
+ cast_keycode_state_changed(captured_event);
+ LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode,
+ (modifier_event->state ? "pressed" : "released"));
+ }
+ ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap);
+ }
+}
+
+static struct active_hold_tap *find_hold_tap(u32_t position) {
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ if (active_hold_taps[i].position == position) {
+ return &active_hold_taps[i];
+ }
+ }
+ return NULL;
+}
+
+static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap,
+ const struct behavior_hold_tap_config *config) {
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) {
+ continue;
+ }
+ active_hold_taps[i].position = position;
+ active_hold_taps[i].is_decided = false;
+ active_hold_taps[i].is_hold = false;
+ active_hold_taps[i].config = config;
+ active_hold_taps[i].param_hold = param_hold;
+ active_hold_taps[i].param_tap = param_tap;
+ return &active_hold_taps[i];
+ }
+ return NULL;
+}
+
+static void clear_hold_tap(struct active_hold_tap *hold_tap) {
+ hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
+ hold_tap->is_decided = false;
+ hold_tap->is_hold = false;
+ hold_tap->work_is_cancelled = false;
+}
+
+enum decision_moment {
+ HT_KEY_UP = 0,
+ HT_OTHER_KEY_DOWN = 1,
+ HT_OTHER_KEY_UP = 2,
+ HT_TIMER_EVENT = 3,
+};
+
+static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) {
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_OTHER_KEY_UP:
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default:
+ return;
+ }
+}
+
+static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default:
+ return;
+ }
+}
+
+static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_OTHER_KEY_DOWN:
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default:
+ return;
+ }
+}
+
+static inline char *flavor_str(enum flavor flavor) {
+ switch (flavor) {
+ case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
+ return "hold-preferred";
+ case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
+ return "balanced";
+ case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
+ return "tap-preferred";
+ }
+ return "UNKNOWN FLAVOR";
+}
+
+static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) {
+ if (hold_tap->is_decided) {
+ return;
+ }
+
+ if (hold_tap != undecided_hold_tap) {
+ LOG_DBG("ERROR found undecided tap hold that is not the active tap hold");
+ return;
+ }
+
+ switch (hold_tap->config->flavor) {
+ case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
+ decide_hold_preferred(hold_tap, event);
+ case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
+ decide_balanced(hold_tap, event);
+ case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
+ decide_tap_preferred(hold_tap, event);
+ }
+
+ if (!hold_tap->is_decided) {
+ return;
+ }
+
+ LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap",
+ flavor_str(hold_tap->config->flavor), event);
+ undecided_hold_tap = NULL;
+
+ struct zmk_behavior_binding *behavior;
+ if (hold_tap->is_hold) {
+ behavior = &hold_tap->config->behaviors->hold;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold,
+ 0);
+ } else {
+ behavior = &hold_tap->config->behaviors->tap;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap,
+ 0);
+ }
+ release_captured_events();
+}
+
+static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold,
+ u32_t param_tap) {
+ const struct behavior_hold_tap_config *cfg = dev->config_info;
+
+ if (undecided_hold_tap != NULL) {
+ LOG_DBG("ERROR another hold-tap behavior is undecided.");
+ // if this happens, make sure the behavior events occur AFTER other position events.
+ return 0;
+ }
+
+ struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
+ if (hold_tap == NULL) {
+ LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?",
+ ZMK_BHV_HOLD_TAP_MAX_HELD);
+ return 0;
+ }
+
+ LOG_DBG("%d new undecided hold_tap", position);
+ undecided_hold_tap = hold_tap;
+ k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms());
+
+ // todo: once we get timing info for keypresses, start the timer relative to the original
+ // keypress don't forget to simulate a timer-event before the event after that time was handled.
+
+ return 0;
+}
+
+static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __) {
+ struct active_hold_tap *hold_tap = find_hold_tap(position);
+
+ if (hold_tap == NULL) {
+ LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
+ return 0;
+ }
+
+ int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
+ decide_hold_tap(hold_tap, HT_KEY_UP);
+
+ struct zmk_behavior_binding *behavior;
+ if (hold_tap->is_hold) {
+ behavior = &hold_tap->config->behaviors->hold;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold,
+ 0);
+ } else {
+ behavior = &hold_tap->config->behaviors->tap;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap,
+ 0);
+ }
+
+ if (work_cancel_result == -EINPROGRESS) {
+ // let the timer handler clean up
+ // if we'd clear now, the timer may call back for an uninitialized active_hold_tap.
+ LOG_DBG("%d hold-tap timer work in event queue", position);
+ hold_tap->work_is_cancelled = true;
+ } else {
+ LOG_DBG("%d cleaning up hold-tap", position);
+ clear_hold_tap(hold_tap);
+ }
+
+ return 0;
+}
+
+static const struct behavior_driver_api behavior_hold_tap_driver_api = {
+ .binding_pressed = on_hold_tap_binding_pressed,
+ .binding_released = on_hold_tap_binding_released,
+};
+
+static int position_state_changed_listener(const struct zmk_event_header *eh) {
+ struct position_state_changed *ev = cast_position_state_changed(eh);
+
+ if (undecided_hold_tap == NULL) {
+ LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
+ return 0;
+ }
+
+ if (undecided_hold_tap->position == ev->position) {
+ if (ev->state) { // keydown
+ LOG_ERR("hold-tap listener should be called before before most other listeners!");
+ return 0;
+ } else { // keyup
+ LOG_DBG("%d bubble undecided hold-tap keyrelease event", undecided_hold_tap->position);
+ return 0;
+ }
+ }
+
+ if (!ev->state && find_captured_keydown_event(ev->position) == NULL) {
+ // no keydown event has been captured, let it bubble.
+ // we'll catch modifiers later in modifier_state_changed_listener
+ LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position,
+ ev->state ? "down" : "up");
+ return 0;
+ }
+
+ LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position,
+ ev->state ? "down" : "up");
+ capture_event(eh);
+ decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
+ return ZMK_EV_EVENT_CAPTURED;
+}
+
+static bool is_mod(struct keycode_state_changed *ev) {
+ return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
+}
+
+static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
+ // we want to catch layer-up events too... how?
+ struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
+
+ if (undecided_hold_tap == NULL) {
+ // LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
+ return 0;
+ }
+
+ if (!is_mod(ev)) {
+ // LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
+ return 0;
+ }
+
+ // only key-up events will bubble through position_state_changed_listener
+ // if a undecided_hold_tap is active.
+ LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode,
+ ev->state ? "down" : "up");
+ capture_event(eh);
+ return ZMK_EV_EVENT_CAPTURED;
+}
+
+int behavior_hold_tap_listener(const struct zmk_event_header *eh) {
+ if (is_position_state_changed(eh)) {
+ return position_state_changed_listener(eh);
+ } else if (is_keycode_state_changed(eh)) {
+ return keycode_state_changed_listener(eh);
+ }
+ return 0;
+}
+
+ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener);
+ZMK_SUBSCRIPTION(behavior_hold_tap, position_state_changed);
+// this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
+ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed);
+
+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);
+
+ if (hold_tap->work_is_cancelled) {
+ clear_hold_tap(hold_tap);
+ } else {
+ decide_hold_tap(hold_tap, HT_TIMER_EVENT);
+ }
+}
+
+static int behavior_hold_tap_init(struct device *dev) {
+ static bool init_first_run = true;
+
+ if (init_first_run) {
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ k_delayed_work_init(&active_hold_taps[i].work, behavior_hold_tap_timer_work_handler);
+ active_hold_taps[i].position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
+ }
+ }
+ init_first_run = false;
+ return 0;
+}
+
+struct behavior_hold_tap_data {};
+static struct behavior_hold_tap_data behavior_hold_tap_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) \
+ static k_timeout_t behavior_hold_tap_config_##n##_gettime() { \
+ return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); \
+ } \
+ 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 = { \
+ .behaviors = &behavior_hold_tap_behaviors_##n, \
+ .tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \
+ .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, \
+ &behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
+
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
+
+#endif \ No newline at end of file
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index 7404c79..bbfbe36 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -16,45 +16,35 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_key_press_config {
- u8_t usage_page;
+ u8_t usage_page;
};
-struct behavior_key_press_data { };
+struct behavior_key_press_data {};
-static int behavior_key_press_init(struct device *dev)
-{
- return 0;
-};
+static int behavior_key_press_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
-{
- const struct behavior_key_press_config *cfg = dev->config_info;
- LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
+ const struct behavior_key_press_config *cfg = dev->config_info;
+ LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
- return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
-{
- const struct behavior_key_press_config *cfg = dev->config_info;
- LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
+ const struct behavior_key_press_config *cfg = dev->config_info;
+ LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
- return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
}
static const struct behavior_driver_api behavior_key_press_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
- .binding_released = on_keymap_binding_released
-};
-
-#define KP_INST(n) \
- static const struct behavior_key_press_config behavior_key_press_config_##n = { \
- .usage_page = DT_INST_PROP(n, usage_page) \
- }; \
- static struct behavior_key_press_data behavior_key_press_data_##n; \
- DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
- &behavior_key_press_data_##n, \
- &behavior_key_press_config_##n, \
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
- &behavior_key_press_driver_api);
+ .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
+
+#define KP_INST(n) \
+ static const struct behavior_key_press_config behavior_key_press_config_##n = { \
+ .usage_page = DT_INST_PROP(n, usage_page)}; \
+ static struct behavior_key_press_data behavior_key_press_data_##n; \
+ DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
+ &behavior_key_press_data_##n, &behavior_key_press_config_##n, APPLICATION, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_press_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST) \ No newline at end of file
diff --git a/app/src/behaviors/behavior_mod_tap.c b/app/src/behaviors/behavior_mod_tap.c
deleted file mode 100644
index 6151f7e..0000000
--- a/app/src/behaviors/behavior_mod_tap.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
- *
- * SPDX-License-Identifier: MIT
- */
-
-#define DT_DRV_COMPAT zmk_behavior_mod_tap
-
-#include <device.h>
-#include <drivers/behavior.h>
-#include <logging/log.h>
-
-#include <zmk/matrix.h>
-#include <zmk/endpoints.h>
-#include <zmk/event-manager.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);
-
-#define ZMK_BHV_MOD_TAP_MAX_HELD 4
-#define ZMK_BHV_MOD_TAP_MAX_PENDING_KC 4
-
-struct active_mod_tap_item {
- u32_t keycode;
- u8_t mods;
- bool pending;
- zmk_mod_flags active_mods;
-};
-
-struct captured_keycode_state_change_item {
- struct keycode_state_changed* event;
- zmk_mod_flags active_mods;
-};
-
-struct behavior_mod_tap_config { };
-struct behavior_mod_tap_data {
- struct active_mod_tap_item active_mod_taps[ZMK_BHV_MOD_TAP_MAX_HELD];
- struct captured_keycode_state_change_item captured_keycode_events[ZMK_BHV_MOD_TAP_MAX_PENDING_KC];
-};
-
-bool have_pending_mods(char *label) {
- struct device *dev = device_get_binding(label);
- struct behavior_mod_tap_data *data = dev->driver_data;
-
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
- if (data->active_mod_taps[i].mods) {
- LOG_DBG("Found pending mods for %d and keycode 0x%02X", data->active_mod_taps[i].mods, data->active_mod_taps[i].keycode);
- return true;
- }
- }
-
- return false;
-}
-
-struct captured_keycode_state_change_item* find_pending_keycode(struct behavior_mod_tap_data *data, u32_t keycode)
-{
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; i++) {
- if (data->captured_keycode_events[i].event == NULL) {
- continue;
- }
-
- if (data->captured_keycode_events[i].event->keycode == keycode) {
- return &data->captured_keycode_events[i];
- }
- }
-
- return NULL;
-}
-
-zmk_mod_flags behavior_mod_tap_active_mods(struct behavior_mod_tap_data *data)
-{
- zmk_mod_flags mods = 0;
-
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
- mods |= data->active_mod_taps[i].mods;
- }
-
- return mods;
-}
-
-int behavior_mod_tap_capture_keycode_event(struct behavior_mod_tap_data *data, struct keycode_state_changed *ev)
-{
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; i++) {
- if (data->captured_keycode_events[i].event != NULL) {
- continue;
- }
-
- data->captured_keycode_events[i].event = ev;
- data->captured_keycode_events[i].active_mods = behavior_mod_tap_active_mods(data);
- return 0;
- }
-
- return -ENOMEM;
-}
-
-void behavior_mod_tap_update_active_mods_state(struct behavior_mod_tap_data *data, zmk_mod_flags used_flags)
-{
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
- if ((data->active_mod_taps[i].mods & used_flags) == data->active_mod_taps[i].mods) {
- data->active_mod_taps[i].pending = false;
- }
- }
-}
-
-// How to pass context to subscription?!
-int behavior_mod_tap_listener(const struct zmk_event_header *eh)
-{
- if (is_keycode_state_changed(eh) && have_pending_mods(DT_INST_LABEL(0))) {
- struct device *dev = device_get_binding(DT_INST_LABEL(0));
- struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
- struct behavior_mod_tap_data *data = dev->driver_data;
- struct captured_keycode_state_change_item* pending_keycode;
- if (ev->state) {
- LOG_DBG("Have pending mods, capturing keycode 0x%02X event to ressend later", ev->keycode);
- behavior_mod_tap_capture_keycode_event(data, ev);
- return ZMK_EV_EVENT_CAPTURED;
- } else if ((pending_keycode = find_pending_keycode(data, ev->keycode)) != NULL) {
- LOG_DBG("Key released, going to activate mods 0x%02X then send pending key press for keycode 0x%02X",
- pending_keycode->active_mods, pending_keycode->event->keycode);
-
- zmk_hid_register_mods(pending_keycode->active_mods);
- behavior_mod_tap_update_active_mods_state(data, pending_keycode->active_mods);
-
- ZMK_EVENT_RELEASE(pending_keycode->event);
- k_msleep(10);
-
- pending_keycode->event = NULL;
- pending_keycode->active_mods = 0;
- }
- }
- return 0;
-}
-
-ZMK_LISTENER(behavior_mod_tap, behavior_mod_tap_listener);
-ZMK_SUBSCRIPTION(behavior_mod_tap, keycode_state_changed);
-
-static int behavior_mod_tap_init(struct device *dev)
-{
- return 0;
-};
-
-
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
-{
- struct behavior_mod_tap_data *data = dev->driver_data;
- LOG_DBG("mods: %d, keycode: 0x%02X", mods, keycode);
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
- if (data->active_mod_taps[i].mods != 0) {
- continue;
- }
-
- zmk_mod_flags active_mods = behavior_mod_tap_active_mods(data);
-
- data->active_mod_taps[i].active_mods = active_mods;
- data->active_mod_taps[i].mods = mods;
- data->active_mod_taps[i].keycode = keycode;
- data->active_mod_taps[i].pending = true;
-
- return 0;
- }
-
- LOG_WRN("Failed to record mod-tap activation, at maximum concurrent mod-tap activations");
-
- return -ENOMEM;
-}
-
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
-{
- struct behavior_mod_tap_data *data = dev->driver_data;
- LOG_DBG("mods: %d, keycode: %d", mods, keycode);
-
- for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
- struct active_mod_tap_item *item = &data->active_mod_taps[i];
- if (item->mods == mods && item->keycode == keycode) {
- if (item->pending) {
- LOG_DBG("Sending un-triggered mod-tap for keycode: 0x%02X", keycode);
-
- if (item->active_mods) {
- LOG_DBG("Registering recorded active mods captured when mod-tap initially activated: 0x%02X", item->active_mods);
- behavior_mod_tap_update_active_mods_state(data, item->active_mods);
- zmk_hid_register_mods(item->active_mods);
- }
-
- struct keycode_state_changed *key_press = create_keycode_state_changed(USAGE_KEYPAD, item->keycode, true);
- ZMK_EVENT_RAISE_AFTER(key_press, behavior_mod_tap);
- k_msleep(10);
-
- for (int j = 0; j < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; j++) {
- if (data->captured_keycode_events[j].event == NULL) {
- continue;
- }
-
- struct keycode_state_changed *ev = data->captured_keycode_events[j].event;
- data->captured_keycode_events[i].event = NULL;
- data->captured_keycode_events[i].active_mods = 0;
- LOG_DBG("Re-sending latched key press for usage page 0x%02X keycode 0x%02X state %s", ev->usage_page, ev->keycode, (ev->state ? "pressed" : "released"));
- ZMK_EVENT_RELEASE(ev);
- k_msleep(10);
- }
-
- struct keycode_state_changed *key_release = create_keycode_state_changed(USAGE_KEYPAD, keycode, false);
- LOG_DBG("Sending un-triggered mod-tap release for keycode: 0x%02X", keycode);
- ZMK_EVENT_RAISE_AFTER(key_release, behavior_mod_tap);
- k_msleep(10);
-
- if (item->active_mods) {
- LOG_DBG("Unregistering recorded active mods captured when mod-tap initially activated: 0x%02X", item->active_mods);
- zmk_hid_unregister_mods(item->active_mods);
- zmk_endpoints_send_report(USAGE_KEYPAD);
- }
-
-
- } else {
- LOG_DBG("Releasing triggered mods: %d", mods);
- zmk_hid_unregister_mods(mods);
- zmk_endpoints_send_report(USAGE_KEYPAD);
- }
-
- item->mods = 0;
- item->keycode = 0;
- item->active_mods = 0;
-
- LOG_DBG("Removing mods %d from active_mods for other held mod-taps", mods);
- for (int j = 0; j < ZMK_BHV_MOD_TAP_MAX_HELD; j++) {
- if (data->active_mod_taps[j].active_mods & mods) {
- LOG_DBG("Removing 0x%02X from active mod tap mods 0x%02X keycode 0x%02X", mods, data->active_mod_taps[j].mods, data->active_mod_taps[j].keycode);
- data->active_mod_taps[j].active_mods &= ~mods;
- }
- }
- break;
- }
- }
-
- return 0;
-}
-
-static const struct behavior_driver_api behavior_mod_tap_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
- .binding_released = on_keymap_binding_released,
-};
-
-static const struct behavior_mod_tap_config behavior_mod_tap_config = {};
-
-static struct behavior_mod_tap_data behavior_mod_tap_data;
-
-DEVICE_AND_API_INIT(behavior_mod_tap, DT_INST_LABEL(0), behavior_mod_tap_init,
- &behavior_mod_tap_data,
- &behavior_mod_tap_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
- &behavior_mod_tap_driver_api);
diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c
index 8a8584a..80b7165 100644
--- a/app/src/behaviors/behavior_momentary_layer.c
+++ b/app/src/behaviors/behavior_momentary_layer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -14,41 +14,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_mo_config { };
-struct behavior_mo_data { };
+struct behavior_mo_config {};
+struct behavior_mo_data {};
-static int behavior_mo_init(struct device *dev)
-{
- return 0;
-};
+static int behavior_mo_init(struct device *dev) { return 0; };
+static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) {
+ LOG_DBG("position %d layer %d", position, layer);
-static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
-{
- LOG_DBG("position %d layer %d", position, layer);
-
- return zmk_keymap_layer_activate(layer);
+ return zmk_keymap_layer_activate(layer);
}
-static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
-{
- LOG_DBG("position %d layer %d", position, layer);
+static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) {
+ LOG_DBG("position %d layer %d", position, layer);
- return zmk_keymap_layer_deactivate(layer);
+ return zmk_keymap_layer_deactivate(layer);
}
static const struct behavior_driver_api behavior_mo_driver_api = {
- .binding_pressed = mo_keymap_binding_pressed,
- .binding_released = mo_keymap_binding_released
-};
-
+ .binding_pressed = mo_keymap_binding_pressed, .binding_released = mo_keymap_binding_released};
static const struct behavior_mo_config behavior_mo_config = {};
static struct behavior_mo_data behavior_mo_data;
-DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init,
- &behavior_mo_data,
- &behavior_mo_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init, &behavior_mo_data,
+ &behavior_mo_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_driver_api);
diff --git a/app/src/behaviors/behavior_none.c b/app/src/behaviors/behavior_none.c
index 7e77e54..b548e6f 100644
--- a/app/src/behaviors/behavior_none.c
+++ b/app/src/behaviors/behavior_none.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -13,36 +13,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_none_config { };
-struct behavior_none_data { };
+struct behavior_none_config {};
+struct behavior_none_data {};
-static int behavior_none_init(struct device *dev)
-{
- return 0;
-};
+static int behavior_none_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
-{
- return 1;
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
+ u32_t _param2) {
+ return 0;
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
-{
- return 1;
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
+ u32_t _param2) {
+ return 0;
}
static const struct behavior_driver_api behavior_none_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
- .binding_released = on_keymap_binding_released,
+ .binding_pressed = on_keymap_binding_pressed,
+ .binding_released = on_keymap_binding_released,
};
-
static const struct behavior_none_config behavior_none_config = {};
static struct behavior_none_data behavior_none_data;
-DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init,
- &behavior_none_data,
- &behavior_none_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init, &behavior_none_data,
+ &behavior_none_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_none_driver_api); \ No newline at end of file
diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c
index 44cbc21..90de20b 100644
--- a/app/src/behaviors/behavior_reset.c
+++ b/app/src/behaviors/behavior_reset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -13,33 +13,32 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_reset_config { };
-struct behavior_reset_data { };
-
-static int behavior_reset_init(struct device *dev)
-{
- return 0;
+struct behavior_reset_config {
+ int type;
};
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
-{
- // TODO: Correct magic code for going into DFU?
- // See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
- sys_reboot(0);
- return 0;
+static int behavior_reset_init(struct device *dev) { return 0; };
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
+ u32_t _param2) {
+ const struct behavior_reset_config *cfg = dev->config_info;
+
+ // TODO: Correct magic code for going into DFU?
+ // See
+ // https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
+ sys_reboot(cfg->type);
+ return 0;
}
static const struct behavior_driver_api behavior_reset_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
+ .binding_pressed = on_keymap_binding_pressed,
};
+#define RST_INST(n) \
+ static const struct behavior_reset_config behavior_reset_config_##n = { \
+ .type = DT_INST_PROP(n, type)}; \
+ DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, NULL, \
+ &behavior_reset_config_##n, APPLICATION, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_reset_driver_api);
-static const struct behavior_reset_config behavior_reset_config = {};
-
-static struct behavior_reset_data behavior_reset_data;
-
-DEVICE_AND_API_INIT(behavior_reset, DT_INST_LABEL(0), behavior_reset_init,
- &behavior_reset_data,
- &behavior_reset_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
- &behavior_reset_driver_api); \ No newline at end of file
+DT_INST_FOREACH_STATUS_OKAY(RST_INST) \ No newline at end of file
diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c
index 7a48e07..621eab5 100644
--- a/app/src/behaviors/behavior_rgb_underglow.c
+++ b/app/src/behaviors/behavior_rgb_underglow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Nick Winans <nick@winans.codes>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -15,48 +15,41 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-static int behavior_rgb_underglow_init(struct device *dev)
-{
- return 0;
-}
+static int behavior_rgb_underglow_init(struct device *dev) { return 0; }
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _)
-{
- switch (action)
- {
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) {
+ switch (action) {
case RGB_TOG:
- return zmk_rgb_underglow_toggle();
+ return zmk_rgb_underglow_toggle();
case RGB_HUI:
- return zmk_rgb_underglow_change_hue(1);
+ return zmk_rgb_underglow_change_hue(1);
case RGB_HUD:
- return zmk_rgb_underglow_change_hue(-1);
+ return zmk_rgb_underglow_change_hue(-1);
case RGB_SAI:
- return zmk_rgb_underglow_change_sat(1);
+ return zmk_rgb_underglow_change_sat(1);
case RGB_SAD:
- return zmk_rgb_underglow_change_sat(-1);
+ return zmk_rgb_underglow_change_sat(-1);
case RGB_BRI:
- return zmk_rgb_underglow_change_brt(1);
+ return zmk_rgb_underglow_change_brt(1);
case RGB_BRD:
- return zmk_rgb_underglow_change_brt(-1);
+ return zmk_rgb_underglow_change_brt(-1);
case RGB_SPI:
- return zmk_rgb_underglow_change_spd(1);
+ return zmk_rgb_underglow_change_spd(1);
case RGB_SPD:
- return zmk_rgb_underglow_change_spd(-1);
+ return zmk_rgb_underglow_change_spd(-1);
case RGB_EFF:
- return zmk_rgb_underglow_cycle_effect(1);
+ return zmk_rgb_underglow_cycle_effect(1);
case RGB_EFR:
- return zmk_rgb_underglow_cycle_effect(-1);
- }
+ return zmk_rgb_underglow_cycle_effect(-1);
+ }
- return -ENOTSUP;
+ return -ENOTSUP;
}
static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
+ .binding_pressed = on_keymap_binding_pressed,
};
-DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init,
- NULL,
- NULL,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init, NULL,
+ NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_rgb_underglow_driver_api); \ No newline at end of file
diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c
index fb0fb85..1a0bf03 100644
--- a/app/src/behaviors/behavior_sensor_rotate_key_press.c
+++ b/app/src/behaviors/behavior_sensor_rotate_key_press.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -17,75 +17,69 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_sensor_rotate_key_press_config {
- u8_t usage_page;
-};
-struct behavior_sensor_rotate_key_press_data { };
-
-static int behavior_sensor_rotate_key_press_init(struct device *dev)
-{
- return 0;
+ u8_t usage_page;
};
+struct behavior_sensor_rotate_key_press_data {};
+static int behavior_sensor_rotate_key_press_init(struct device *dev) { return 0; };
-static int on_sensor_binding_triggered(struct device *dev, struct device *sensor, u32_t increment_keycode, u32_t decrement_keycode)
-{
- const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
- struct sensor_value value;
- int err;
- u32_t keycode;
- struct keycode_state_changed *ev;
- LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page, increment_keycode, decrement_keycode);
+static int on_sensor_binding_triggered(struct device *dev, struct device *sensor,
+ u32_t increment_keycode, u32_t decrement_keycode) {
+ const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
+ struct sensor_value value;
+ int err;
+ u32_t keycode;
+ struct keycode_state_changed *ev;
+ LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page,
+ increment_keycode, decrement_keycode);
- err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
+ err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
- if (err) {
- LOG_WRN("Failed to ge sensor rotation value: %d", err);
- return err;
- }
+ if (err) {
+ LOG_WRN("Failed to ge sensor rotation value: %d", err);
+ return err;
+ }
- switch (value.val1) {
+ switch (value.val1) {
case 1:
- keycode = increment_keycode;
- break;
+ keycode = increment_keycode;
+ break;
case -1:
- keycode = decrement_keycode;
- break;
+ keycode = decrement_keycode;
+ break;
default:
- return -ENOTSUP;
- }
-
- LOG_DBG("SEND %d", keycode);
+ return -ENOTSUP;
+ }
+ LOG_DBG("SEND %d", keycode);
- ev = new_keycode_state_changed();
- ev->usage_page = cfg->usage_page;
- ev->keycode = keycode;
- ev->state = true;
- ZMK_EVENT_RAISE(ev);
+ ev = new_keycode_state_changed();
+ ev->usage_page = cfg->usage_page;
+ ev->keycode = keycode;
+ ev->state = true;
+ ZMK_EVENT_RAISE(ev);
- // TODO: Better way to do this?
- k_msleep(5);
+ // TODO: Better way to do this?
+ k_msleep(5);
- ev = new_keycode_state_changed();
- ev->usage_page = cfg->usage_page;
- ev->keycode = keycode;
- ev->state = false;
- return ZMK_EVENT_RAISE(ev);
+ ev = new_keycode_state_changed();
+ ev->usage_page = cfg->usage_page;
+ ev->keycode = keycode;
+ ev->state = false;
+ return ZMK_EVENT_RAISE(ev);
}
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
- .sensor_binding_triggered = on_sensor_binding_triggered
-};
-
-#define KP_INST(n) \
- static const struct behavior_sensor_rotate_key_press_config behavior_sensor_rotate_key_press_config_##n = { \
- .usage_page = DT_INST_PROP(n, usage_page) \
- }; \
- static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \
- DEVICE_AND_API_INIT(behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), behavior_sensor_rotate_key_press_init, \
- &behavior_sensor_rotate_key_press_data_##n, \
- &behavior_sensor_rotate_key_press_config_##n, \
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
- &behavior_sensor_rotate_key_press_driver_api);
+ .sensor_binding_triggered = on_sensor_binding_triggered};
+
+#define KP_INST(n) \
+ static const struct behavior_sensor_rotate_key_press_config \
+ behavior_sensor_rotate_key_press_config_##n = {.usage_page = DT_INST_PROP(n, usage_page)}; \
+ static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \
+ DEVICE_AND_API_INIT( \
+ behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), \
+ behavior_sensor_rotate_key_press_init, &behavior_sensor_rotate_key_press_data_##n, \
+ &behavior_sensor_rotate_key_press_config_##n, APPLICATION, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_key_press_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST) \ No newline at end of file
diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c
index 13f4a29..2819451 100644
--- a/app/src/behaviors/behavior_toggle_layer.c
+++ b/app/src/behaviors/behavior_toggle_layer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -14,36 +14,32 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_tog_config { };
-struct behavior_tog_data { };
+struct behavior_tog_config {};
+struct behavior_tog_data {};
-static int behavior_tog_init(struct device *dev)
-{
- return 0;
-};
+static int behavior_tog_init(struct device *dev) { return 0; };
+static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) {
+ LOG_DBG("position %d layer %d", position, layer);
-static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
-{
- return zmk_keymap_layer_toggle(layer);
+ return zmk_keymap_layer_toggle(layer);
}
-static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
-{
- return 0;
+static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) {
+ LOG_DBG("position %d layer %d", position, layer);
+
+ return 0;
}
static const struct behavior_driver_api behavior_tog_driver_api = {
- .binding_pressed = tog_keymap_binding_pressed,
- .binding_released = tog_keymap_binding_released,
+ .binding_pressed = tog_keymap_binding_pressed,
+ .binding_released = tog_keymap_binding_released,
};
static const struct behavior_tog_config behavior_tog_config = {};
static struct behavior_tog_data behavior_tog_data;
-DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init,
- &behavior_tog_data,
- &behavior_tog_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init, &behavior_tog_data,
+ &behavior_tog_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_tog_driver_api);
diff --git a/app/src/behaviors/behavior_transparent.c b/app/src/behaviors/behavior_transparent.c
index 5109264..f7852f3 100644
--- a/app/src/behaviors/behavior_transparent.c
+++ b/app/src/behaviors/behavior_transparent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -13,36 +13,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_transparent_config { };
-struct behavior_transparent_data { };
+struct behavior_transparent_config {};
+struct behavior_transparent_data {};
-static int behavior_transparent_init(struct device *dev)
-{
- return 0;
-};
+static int behavior_transparent_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
-{
- return 1;
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
+ u32_t _param2) {
+ return 1;
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
-{
- return 1;
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
+ u32_t _param2) {
+ return 1;
}
static const struct behavior_driver_api behavior_transparent_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
- .binding_released = on_keymap_binding_released,
+ .binding_pressed = on_keymap_binding_pressed,
+ .binding_released = on_keymap_binding_released,
};
-
static const struct behavior_transparent_config behavior_transparent_config = {};
static struct behavior_transparent_data behavior_transparent_data;
DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init,
- &behavior_transparent_data,
- &behavior_transparent_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
- &behavior_transparent_driver_api); \ No newline at end of file
+ &behavior_transparent_data, &behavior_transparent_config, APPLICATION,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_transparent_driver_api); \ No newline at end of file
diff --git a/app/src/ble.c b/app/src/ble.c
index 0e96d16..49e2b3b 100644
--- a/app/src/ble.c
+++ b/app/src/ble.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -8,6 +8,8 @@
#include <init.h>
#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h>
@@ -15,37 +17,224 @@
#include <bluetooth/hci.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
+#include <bluetooth/hci_err.h>
+#if IS_ENABLED(CONFIG_SETTINGS)
+
+#include <settings/settings.h>
+
+#endif
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+#include <zmk/ble.h>
#include <zmk/keys.h>
#include <zmk/split/bluetooth/uuid.h>
+#include <zmk/event-manager.h>
+#include <zmk/events/ble-active-profile-changed.h>
static struct bt_conn *auth_passkey_entry_conn;
static u8_t passkey_entries[6] = {0, 0, 0, 0, 0, 0};
static u8_t passkey_digit = 0;
-#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
-#define ZMK_ADV_PARAMS BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
- BT_LE_ADV_OPT_USE_NAME | \
- BT_LE_ADV_OPT_ONE_TIME, \
- BT_GAP_ADV_FAST_INT_MIN_2, \
- BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
#else
-#define ZMK_ADV_PARAMS BT_LE_ADV_CONN_NAME
+#define PROFILE_COUNT CONFIG_BT_MAX_PAIRED
#endif
-static void connected(struct bt_conn *conn, u8_t err)
-{
- char addr[BT_ADDR_LE_STR_LEN];
+static struct zmk_ble_profile profiles[PROFILE_COUNT];
+static u8_t active_profile;
+
+static const struct bt_data zmk_ble_ad[] = {
+ BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+ BT_DATA_BYTES(BT_DATA_UUID16_SOME,
+#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ 0x12, 0x18, /* HID Service */
+#endif
+ 0x0f, 0x18 /* Battery Service */
+ ),
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)
+#endif
+};
+
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+
+static bt_addr_le_t peripheral_addr;
+
+#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
+
+static void raise_profile_changed_event() {
+ struct ble_active_profile_changed *ev = new_ble_active_profile_changed();
+ ev->index = active_profile;
+ ev->profile = &profiles[active_profile];
+
+ ZMK_EVENT_RAISE(ev);
+}
+
+static bool active_profile_is_open() {
+ return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY);
+}
+
+void set_profile_address(u8_t index, const bt_addr_le_t *addr) {
+ char setting_name[15];
+ char addr_str[BT_ADDR_LE_STR_LEN];
+
+ bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
+
+ memcpy(&profiles[index].peer, addr, sizeof(bt_addr_le_t));
+ sprintf(setting_name, "ble/profiles/%d", index);
+ LOG_DBG("Setting profile addr for %s to %s", log_strdup(setting_name), log_strdup(addr_str));
+ settings_save_one(setting_name, &profiles[index], sizeof(struct zmk_ble_profile));
+ raise_profile_changed_event();
+}
+
+int zmk_ble_adv_pause() {
+ int err = bt_le_adv_stop();
+ if (err) {
+ LOG_ERR("Failed to stop advertising (err %d)", err);
+ return err;
+ }
+
+ return 0;
+};
+
+int zmk_ble_adv_resume() {
+ LOG_DBG("active_profile %d, directed? %s", active_profile,
+ active_profile_is_open() ? "no" : "yes");
+
+ int err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
+ if (err) {
+ LOG_ERR("Advertising failed to start (err %d)", err);
+ return err;
+ }
+
+ return 0;
+};
+
+int zmk_ble_clear_bonds() {
+ LOG_DBG("");
+
+ if (bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY)) {
+ LOG_DBG("Unpairing!");
+ bt_unpair(BT_ID_DEFAULT, &profiles[active_profile].peer);
+ set_profile_address(active_profile, BT_ADDR_LE_ANY);
+ }
+
+ return 0;
+};
+
+int zmk_ble_prof_select(u8_t index) {
+ LOG_DBG("profile %d", index);
+ if (active_profile == index) {
+ return 0;
+ }
+
+ active_profile = index;
+ return settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile));
+
+ raise_profile_changed_event();
+};
+
+int zmk_ble_prof_next() {
+ LOG_DBG("");
+ return zmk_ble_prof_select((active_profile + 1) % PROFILE_COUNT);
+};
+
+int zmk_ble_prof_prev() {
+ LOG_DBG("");
+ return zmk_ble_prof_select((active_profile + PROFILE_COUNT - 1) % PROFILE_COUNT);
+};
+
+bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].peer; }
+
+char *zmk_ble_active_profile_name() { return profiles[active_profile].name; }
+
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+
+void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) {
+ memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t));
+ settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t));
+}
+
+#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
+
+#if IS_ENABLED(CONFIG_SETTINGS)
+
+static int ble_profiles_handle_set(const char *name, size_t len, settings_read_cb read_cb,
+ void *cb_arg) {
+ const char *next;
+
+ LOG_DBG("Setting BLE value %s", log_strdup(name));
+
+ if (settings_name_steq(name, "profiles", &next) && next) {
+ char *endptr;
+ u8_t idx = strtoul(next, &endptr, 10);
+ if (*endptr != '\0') {
+ LOG_WRN("Invalid profile index: %s", log_strdup(next));
+ return -EINVAL;
+ }
+
+ if (len != sizeof(struct zmk_ble_profile)) {
+ LOG_ERR("Invalid profile size (got %d expected %d)", len,
+ sizeof(struct zmk_ble_profile));
+ return -EINVAL;
+ }
+ if (idx >= PROFILE_COUNT) {
+ LOG_WRN("Profile address for index %d is larger than max of %d", idx, PROFILE_COUNT);
+ return -EINVAL;
+ }
+
+ int err = read_cb(cb_arg, &profiles[idx], sizeof(struct zmk_ble_profile));
+ if (err <= 0) {
+ LOG_ERR("Failed to handle profile address from settings (err %d)", err);
+ return err;
+ }
+
+ char addr_str[BT_ADDR_LE_STR_LEN];
+ bt_addr_le_to_str(&profiles[idx].peer, addr_str, sizeof(addr_str));
+
+ LOG_DBG("Loaded %s address for profile %d", log_strdup(addr_str), idx);
+ } else if (settings_name_steq(name, "active_profile", &next) && !next) {
+ if (len != sizeof(active_profile)) {
+ return -EINVAL;
+ }
+
+ int err = read_cb(cb_arg, &active_profile, sizeof(active_profile));
+ if (err <= 0) {
+ LOG_ERR("Failed to handle active profile from settings (err %d)", err);
+ return err;
+ }
+ }
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+ else if (settings_name_steq(name, "peripheral_address", &next) && !next) {
+ if (len != sizeof(bt_addr_le_t)) {
+ return -EINVAL;
+ }
+
+ int err = read_cb(cb_arg, &peripheral_addr, sizeof(bt_addr_le_t));
+ if (err <= 0) {
+ LOG_ERR("Failed to handle peripheral address from settings (err %d)", err);
+ return err;
+ }
+ }
+#endif
+
+ return 0;
+};
+
+struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set};
+#endif /* IS_ENABLED(CONFIG_SETTINGS) */
+
+static void connected(struct bt_conn *conn, u8_t err) {
+ char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- if (err)
- {
+ if (err) {
LOG_WRN("Failed to connect to %s (%u)", log_strdup(addr), err);
return;
}
@@ -58,36 +247,37 @@ static void connected(struct bt_conn *conn, u8_t err)
bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
#endif
- if (bt_conn_set_security(conn, BT_SECURITY_L2))
- {
+ if (bt_conn_set_security(conn, BT_SECURITY_L2)) {
LOG_ERR("Failed to set security");
}
}
-static void disconnected(struct bt_conn *conn, u8_t reason)
-{
+static void disconnected(struct bt_conn *conn, u8_t reason) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason);
+
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
+ // if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr,
+ // bt_conn_get_dst(conn))) {
+ // zmk_ble_adv_resume();
+ // }
+#else
+ // zmk_ble_adv_resume();
+#endif
}
-static void security_changed(struct bt_conn *conn, bt_security_t level,
- enum bt_security_err err)
-{
+static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- if (!err)
- {
+ if (!err) {
LOG_DBG("Security changed: %s level %u", log_strdup(addr), level);
- }
- else
- {
- LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level,
- err);
+ } else {
+ LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level, err);
}
}
@@ -97,8 +287,7 @@ static struct bt_conn_cb conn_callbacks = {
.security_changed = security_changed,
};
-static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
-{
+static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@@ -108,8 +297,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
-static void auth_passkey_entry(struct bt_conn *conn)
-{
+static void auth_passkey_entry(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@@ -120,14 +308,12 @@ static void auth_passkey_entry(struct bt_conn *conn)
#endif
-static void auth_cancel(struct bt_conn *conn)
-{
+static void auth_cancel(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- if (auth_passkey_entry_conn)
- {
+ if (auth_passkey_entry_conn) {
bt_conn_unref(auth_passkey_entry_conn);
auth_passkey_entry_conn = NULL;
}
@@ -137,7 +323,51 @@ static void auth_cancel(struct bt_conn *conn)
LOG_DBG("Pairing cancelled: %s", log_strdup(addr));
}
+#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+static enum bt_security_err auth_pairing_accept(struct bt_conn *conn,
+ const struct bt_conn_pairing_feat *const feat) {
+ struct bt_conn_info info;
+ bt_conn_get_info(conn, &info);
+
+ LOG_DBG("role %d, open? %s", info.role, active_profile_is_open() ? "yes" : "no");
+ if (info.role == BT_CONN_ROLE_SLAVE && !active_profile_is_open()) {
+ LOG_WRN("Rejecting pairing request to taken profile %d", active_profile);
+ return BT_SECURITY_ERR_PAIR_NOT_ALLOWED;
+ }
+
+ return BT_SECURITY_ERR_SUCCESS;
+};
+#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
+
+static void auth_pairing_complete(struct bt_conn *conn, bool bonded) {
+ struct bt_conn_info info;
+ char addr[BT_ADDR_LE_STR_LEN];
+ const bt_addr_le_t *dst = bt_conn_get_dst(conn);
+
+ bt_addr_le_to_str(dst, addr, sizeof(addr));
+ bt_conn_get_info(conn, &info);
+
+ if (info.role != BT_CONN_ROLE_SLAVE) {
+ LOG_DBG("SKIPPING FOR ROLE %d", info.role);
+ return;
+ }
+
+#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ if (!active_profile_is_open()) {
+ LOG_ERR("Pairing completed but current profile is not open: %s", log_strdup(addr));
+ bt_unpair(BT_ID_DEFAULT, dst);
+ return;
+ }
+#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
+
+ set_profile_address(active_profile, dst);
+};
+
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
+#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ .pairing_accept = auth_pairing_accept,
+#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
+ .pairing_complete = auth_pairing_complete,
// .passkey_display = auth_passkey_display,
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
@@ -146,51 +376,54 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
.cancel = auth_cancel,
};
-static const struct bt_data zmk_ble_ad[] = {
- BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_SOME,
-#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
- 0x12, 0x18, /* HID Service */
-#endif
- 0x0f, 0x18 /* Battery Service */
- ),
-#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
- BT_DATA_BYTES(BT_DATA_UUID128_ALL,
- ZMK_SPLIT_BT_SERVICE_UUID)
-#endif
-};
-
-static void zmk_ble_ready(int err)
-{
+static void zmk_ble_ready(int err) {
LOG_DBG("ready? %d", err);
- if (err)
- {
+ if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
return;
}
- err = bt_le_adv_start(ZMK_ADV_PARAMS, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
- if (err)
- {
- LOG_ERR("Advertising failed to start (err %d)", err);
- return;
- }
+ zmk_ble_adv_resume();
}
-static int zmk_ble_init(struct device *_arg)
-{
+static int zmk_ble_init(struct device *_arg) {
int err = bt_enable(NULL);
- if (err)
- {
+ if (err) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
- if (IS_ENABLED(CONFIG_BT_SETTINGS))
- {
- settings_load();
+#if IS_ENABLED(CONFIG_SETTINGS)
+ settings_subsys_init();
+
+ err = settings_register(&profiles_handler);
+ if (err) {
+ LOG_ERR("Failed to setup the profile settings handler (err %d)", err);
+ return err;
+ }
+
+ settings_load();
+
+#endif
+
+#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
+ LOG_WRN("Clearing all existing BLE bond information from the keyboard");
+
+ for (int i = 0; i < 10; i++) {
+ bt_unpair(i, NULL);
+ }
+
+ for (int i = 0; i < PROFILE_COUNT; i++) {
+ char setting_name[15];
+ sprintf(setting_name, "ble/profiles/%d", i);
+
+ err = settings_delete(setting_name);
+ if (err) {
+ LOG_ERR("Failed to delete setting: %d", err);
+ }
}
+#endif
bt_conn_cb_register(&conn_callbacks);
bt_conn_auth_cb_register(&zmk_ble_auth_cb_display);
@@ -200,23 +433,28 @@ static int zmk_ble_init(struct device *_arg)
return 0;
}
-int zmk_ble_unpair_all()
-{
- LOG_DBG("");
- return bt_unpair(BT_ID_DEFAULT, NULL);
+int zmk_ble_unpair_all() {
+ int resp = 0;
+ for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) {
+
+ int err = bt_unpair(BT_ID_DEFAULT, NULL);
+ if (err) {
+ resp = err;
+ LOG_ERR("Failed to unpair devices (err %d)", err);
+ }
+ }
+
+ return resp;
};
-bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
-{
+bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) {
zmk_key key = key_event->key;
- if (!auth_passkey_entry_conn)
- {
+ if (!auth_passkey_entry_conn) {
return true;
}
- if (key < NUM_1 || key > NUM_0)
- {
+ if (key < NUM_1 || key > NUM_0) {
return true;
}
@@ -224,11 +462,9 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
passkey_entries[passkey_digit++] = val;
- if (passkey_digit == 6)
- {
+ if (passkey_digit == 6) {
u32_t passkey = 0;
- for (int i = 5; i >= 0; i--)
- {
+ for (int i = 5; i >= 0; i--) {
passkey = (passkey * 10) + val;
}
bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey);
@@ -239,6 +475,4 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
return false;
}
-SYS_INIT(zmk_ble_init,
- APPLICATION,
- CONFIG_ZMK_BLE_INIT_PRIORITY);
+SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
diff --git a/app/src/ble_unpair_combo.c b/app/src/ble_unpair_combo.c
index a33a8e2..b6e542d 100644
--- a/app/src/ble_unpair_combo.c
+++ b/app/src/ble_unpair_combo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -7,24 +7,23 @@
#include <device.h>
#include <init.h>
-#include <logging/log.h>
-
#define DT_DRV_COMPAT zmk_bt_unpair_combo
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
+
+#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/ble.h>
#include <zmk/event-manager.h>
#include <zmk/events/position-state-changed.h>
-
static u8_t combo_state;
const u32_t key_positions[] = DT_INST_PROP(0, key_positions);
#define KP_LEN DT_INST_PROP_LEN(0, key_positions)
-int index_for_key_position(u32_t kp)
-{
+int index_for_key_position(u32_t kp) {
for (int i = 0; i < KP_LEN; i++) {
if (key_positions[i] == kp) {
return i;
@@ -34,8 +33,7 @@ int index_for_key_position(u32_t kp)
return -1;
}
-int unpair_combo_listener(const struct zmk_event_header *eh)
-{
+int unpair_combo_listener(const struct zmk_event_header *eh) {
if (is_position_state_changed(eh)) {
const struct position_state_changed *psc = cast_position_state_changed(eh);
@@ -50,8 +48,7 @@ int unpair_combo_listener(const struct zmk_event_header *eh)
return 0;
};
-void unpair_combo_work_handler(struct k_work *work)
-{
+void unpair_combo_work_handler(struct k_work *work) {
for (int i = 0; i < KP_LEN; i++) {
if (!(combo_state & BIT(i))) {
LOG_DBG("Key position %d not held, skipping unpair combo", key_positions[i]);
@@ -64,8 +61,7 @@ void unpair_combo_work_handler(struct k_work *work)
struct k_delayed_work unpair_combo_work;
-int zmk_ble_unpair_combo_init(struct device *_unused)
-{
+int zmk_ble_unpair_combo_init(struct device *_unused) {
k_delayed_work_init(&unpair_combo_work, unpair_combo_work_handler);
k_delayed_work_submit(&unpair_combo_work, K_SECONDS(2));
@@ -75,6 +71,6 @@ int zmk_ble_unpair_combo_init(struct device *_unused)
ZMK_LISTENER(zmk_ble_unpair_combo, unpair_combo_listener);
ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed);
-SYS_INIT(zmk_ble_unpair_combo_init,
- APPLICATION,
- CONFIG_APPLICATION_INIT_PRIORITY);
+SYS_INIT(zmk_ble_unpair_combo_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
+
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
diff --git a/app/src/display.c b/app/src/display.c
index 9021914..ecd1908 100644
--- a/app/src/display.c
+++ b/app/src/display.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -20,8 +20,7 @@ static struct device *display;
static lv_obj_t *screen;
-int zmk_display_init()
-{
+int zmk_display_init() {
lv_obj_t *hello_world_label;
lv_obj_t *count_label;
@@ -48,8 +47,7 @@ int zmk_display_init()
return 0;
}
-void zmk_display_task_handler()
-{
+void zmk_display_task_handler() {
lv_tick_inc(10);
lv_task_handler();
k_sleep(K_MSEC(10));
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
index c9ba716..ae78587 100644
--- a/app/src/endpoints.c
+++ b/app/src/endpoints.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <zmk/endpoints.h>
#include <zmk/hid.h>
@@ -7,27 +12,24 @@
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-int zmk_endpoints_send_report(u8_t usage_page)
-{
+int zmk_endpoints_send_report(u8_t usage_page) {
int err;
struct zmk_hid_keypad_report *keypad_report;
struct zmk_hid_consumer_report *consumer_report;
LOG_DBG("usage page 0x%02X", usage_page);
- switch (usage_page)
- {
+ switch (usage_page) {
case USAGE_KEYPAD:
keypad_report = zmk_hid_get_keypad_report();
#ifdef CONFIG_ZMK_USB
- if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) != 0)
- {
+ if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) !=
+ 0) {
LOG_DBG("USB Send Failed");
}
#endif /* CONFIG_ZMK_USB */
#ifdef CONFIG_ZMK_BLE
err = zmk_hog_send_keypad_report(&keypad_report->body);
- if (err)
- {
+ if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
}
#endif /* CONFIG_ZMK_BLE */
@@ -36,16 +38,15 @@ int zmk_endpoints_send_report(u8_t usage_page)
case USAGE_CONSUMER:
consumer_report = zmk_hid_get_consumer_report();
#ifdef CONFIG_ZMK_USB
- if (zmk_usb_hid_send_report((u8_t *)consumer_report, sizeof(struct zmk_hid_consumer_report)) != 0)
- {
+ if (zmk_usb_hid_send_report((u8_t *)consumer_report,
+ sizeof(struct zmk_hid_consumer_report)) != 0) {
LOG_DBG("USB Send Failed");
}
#endif /* CONFIG_ZMK_USB */
#ifdef CONFIG_ZMK_BLE
err = zmk_hog_send_consumer_report(&consumer_report->body);
- if (err)
- {
+ if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
}
#endif /* CONFIG_ZMK_BLE */
@@ -58,4 +59,3 @@ int zmk_endpoints_send_report(u8_t usage_page)
return 0;
}
-
diff --git a/app/src/event_manager.c b/app/src/event_manager.c
index c405176..226f3ce 100644
--- a/app/src/event_manager.c
+++ b/app/src/event_manager.c
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
-
+
#include <zephyr.h>
#include <logging/log.h>
@@ -11,15 +11,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event-manager.h>
-extern struct zmk_event_type* __event_type_start[];
-extern struct zmk_event_type* __event_type_end[];
+extern struct zmk_event_type *__event_type_start[];
+extern struct zmk_event_type *__event_type_end[];
extern struct zmk_event_subscription __event_subscriptions_start[];
extern struct zmk_event_subscription __event_subscriptions_end[];
-
-int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_index)
-{
+int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_index) {
int ret = 0;
u8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = start_index; i < len; i++) {
@@ -31,15 +29,15 @@ int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_ind
goto release;
} else if (ret > 0) {
switch (ret) {
- case ZMK_EV_EVENT_HANDLED:
- LOG_DBG("Listener handled the event");
- ret = 0;
- goto release;
- case ZMK_EV_EVENT_CAPTURED:
- LOG_DBG("Listener captured the event");
- event->last_listener_index = i;
- // Listeners are expected to free events they capture
- return 0;
+ case ZMK_EV_EVENT_HANDLED:
+ LOG_DBG("Listener handled the event");
+ ret = 0;
+ goto release;
+ case ZMK_EV_EVENT_CAPTURED:
+ LOG_DBG("Listener captured the event");
+ event->last_listener_index = i;
+ // Listeners are expected to free events they capture
+ return 0;
}
}
}
@@ -50,19 +48,18 @@ release:
return ret;
}
-int zmk_event_manager_raise(struct zmk_event_header *event)
-{
+int zmk_event_manager_raise(struct zmk_event_header *event) {
return zmk_event_manager_handle_from(event, 0);
}
-int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener)
-{
+int zmk_event_manager_raise_after(struct zmk_event_header *event,
+ const struct zmk_listener *listener) {
u8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = 0; i < len; i++) {
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
- return zmk_event_manager_handle_from(event, i+1);
+ return zmk_event_manager_handle_from(event, i + 1);
}
}
@@ -71,7 +68,22 @@ int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct z
return -EINVAL;
}
-int zmk_event_manager_release(struct zmk_event_header *event)
-{
+int zmk_event_manager_raise_at(struct zmk_event_header *event,
+ const struct zmk_listener *listener) {
+ u8_t len = __event_subscriptions_end - __event_subscriptions_start;
+ for (int i = 0; i < len; i++) {
+ struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
+
+ if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
+ return zmk_event_manager_handle_from(event, i);
+ }
+ }
+
+ LOG_WRN("Unable to find where to raise this event");
+
+ return -EINVAL;
+}
+
+int zmk_event_manager_release(struct zmk_event_header *event) {
return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
-} \ No newline at end of file
+}
diff --git a/app/src/events/ble_active_profile_changed.c b/app/src/events/ble_active_profile_changed.c
new file mode 100644
index 0000000..a270a14
--- /dev/null
+++ b/app/src/events/ble_active_profile_changed.c
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <kernel.h>
+#include <zmk/events/ble-active-profile-changed.h>
+
+ZMK_EVENT_IMPL(ble_active_profile_changed); \ No newline at end of file
diff --git a/app/src/events/keycode_state_changed.c b/app/src/events/keycode_state_changed.c
index 73508e1..9a1984a 100644
--- a/app/src/events/keycode_state_changed.c
+++ b/app/src/events/keycode_state_changed.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/src/events/modifiers_state_changed.c b/app/src/events/modifiers_state_changed.c
index 71ec015..8becd02 100644
--- a/app/src/events/modifiers_state_changed.c
+++ b/app/src/events/modifiers_state_changed.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/src/events/position_state_changed.c b/app/src/events/position_state_changed.c
index 69cba03..f8f1a26 100644
--- a/app/src/events/position_state_changed.c
+++ b/app/src/events/position_state_changed.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/src/events/sensor_event.c b/app/src/events/sensor_event.c
index 1b0302d..c6b80cd 100644
--- a/app/src/events/sensor_event.c
+++ b/app/src/events/sensor_event.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/src/hid.c b/app/src/hid.c
index ca04056..f80906c 100644
--- a/app/src/hid.c
+++ b/app/src/hid.c
@@ -1,44 +1,36 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h>
static struct zmk_hid_keypad_report kp_report = {
- .report_id = 1,
- .body = {
- .modifiers = 0,
- .keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
-
-static struct zmk_hid_consumer_report consumer_report = {
- .report_id = 2,
- .body = {
- .keys = {0,0,0,0,0,0}}};
-
-#define _TOGGLE_MOD(mod, state) \
- if (modifier > MOD_RGUI) \
- { \
- return -EINVAL; \
- } \
- WRITE_BIT(kp_report.body.modifiers, mod, state); \
+ .report_id = 1, .body = {.modifiers = 0, .keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
+
+static struct zmk_hid_consumer_report consumer_report = {.report_id = 2,
+ .body = {.keys = {0, 0, 0, 0, 0, 0}}};
+
+#define _TOGGLE_MOD(mod, state) \
+ if (modifier > MOD_RGUI) { \
+ return -EINVAL; \
+ } \
+ WRITE_BIT(kp_report.body.modifiers, mod, state); \
return 0;
-int zmk_hid_register_mod(zmk_mod modifier)
-{
- _TOGGLE_MOD(modifier, true);
-}
-int zmk_hid_unregister_mod(zmk_mod modifier)
-{
- _TOGGLE_MOD(modifier, false);
-}
+int zmk_hid_register_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, true); }
+int zmk_hid_unregister_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, false); }
-int zmk_hid_register_mods(zmk_mod_flags modifiers)
-{
+int zmk_hid_register_mods(zmk_mod_flags modifiers) {
kp_report.body.modifiers |= modifiers;
return 0;
}
-int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
-{
+int zmk_hid_unregister_mods(zmk_mod_flags modifiers) {
kp_report.body.modifiers &= ~modifiers;
return 0;
}
@@ -61,28 +53,21 @@ int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
#define TOGGLE_KEY(code, val) WRITE_BIT(kp_report.body.keys[code / 8], code % 8, val)
-#define TOGGLE_CONSUMER(match, val) \
- for (int idx = 0; idx < MAX_KEYS; idx++) \
- { \
- if (consumer_report.body.keys[idx] != match) \
- { \
- continue; \
- } \
- consumer_report.body.keys[idx] = val; \
- break; \
+#define TOGGLE_CONSUMER(match, val) \
+ for (int idx = 0; idx < MAX_KEYS; idx++) { \
+ if (consumer_report.body.keys[idx] != match) { \
+ continue; \
+ } \
+ consumer_report.body.keys[idx] = val; \
+ break; \
}
-
-int zmk_hid_keypad_press(zmk_key code)
-{
- if (code >= LCTL && code <= RGUI)
- {
+int zmk_hid_keypad_press(zmk_key code) {
+ if (code >= LCTL && code <= RGUI) {
return zmk_hid_register_mod(code - LCTL);
}
-
- if (code > ZMK_HID_MAX_KEYCODE)
- {
+ if (code > ZMK_HID_MAX_KEYCODE) {
return -EINVAL;
}
@@ -93,15 +78,12 @@ int zmk_hid_keypad_press(zmk_key code)
return 0;
};
-int zmk_hid_keypad_release(zmk_key code)
-{
- if (code >= LCTL && code <= RGUI)
- {
+int zmk_hid_keypad_release(zmk_key code) {
+ if (code >= LCTL && code <= RGUI) {
return zmk_hid_unregister_mod(code - LCTL);
}
- if (code > ZMK_HID_MAX_KEYCODE)
- {
+ if (code > ZMK_HID_MAX_KEYCODE) {
return -EINVAL;
}
@@ -112,25 +94,20 @@ int zmk_hid_keypad_release(zmk_key code)
return 0;
};
-int zmk_hid_consumer_press(zmk_key code)
-{
+int zmk_hid_consumer_press(zmk_key code) {
TOGGLE_CONSUMER(0U, code);
return 0;
};
-
-int zmk_hid_consumer_release(zmk_key code)
-{
+int zmk_hid_consumer_release(zmk_key code) {
TOGGLE_CONSUMER(code, 0U);
return 0;
};
-struct zmk_hid_keypad_report *zmk_hid_get_keypad_report()
-{
+struct zmk_hid_keypad_report *zmk_hid_get_keypad_report() {
return &kp_report;
}
-struct zmk_hid_consumer_report *zmk_hid_get_consumer_report()
-{
+struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
return &consumer_report;
}
diff --git a/app/src/hid_listener.c b/app/src/hid_listener.c
index 69aa23e..4467e6d 100644
--- a/app/src/hid_listener.c
+++ b/app/src/hid_listener.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -15,90 +15,84 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h>
#include <zmk/endpoints.h>
+static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode) {
+ int err;
+ LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
-static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode)
-{
- int err;
- LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
-
- switch (usage_page) {
- case USAGE_KEYPAD:
- err = zmk_hid_keypad_press(keycode);
- if (err) {
- LOG_ERR("Unable to press keycode");
- return err;
+ switch (usage_page) {
+ case USAGE_KEYPAD:
+ err = zmk_hid_keypad_press(keycode);
+ if (err) {
+ LOG_ERR("Unable to press keycode");
+ return err;
+ }
+ break;
+ case USAGE_CONSUMER:
+ err = zmk_hid_consumer_press(keycode);
+ if (err) {
+ LOG_ERR("Unable to press keycode");
+ return err;
+ }
+ break;
}
- break;
- case USAGE_CONSUMER:
- err = zmk_hid_consumer_press(keycode);
- if (err) {
- LOG_ERR("Unable to press keycode");
- return err;
- }
- break;
- }
- return zmk_endpoints_send_report(usage_page);
+ return zmk_endpoints_send_report(usage_page);
}
-static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode)
-{
- int err;
- LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
-
- switch (usage_page) {
- case USAGE_KEYPAD:
- err = zmk_hid_keypad_release(keycode);
- if (err) {
- LOG_ERR("Unable to release keycode");
- return err;
- }
- break;
- case USAGE_CONSUMER:
- err = zmk_hid_consumer_release(keycode);
- if (err) {
- LOG_ERR("Unable to release keycode");
- return err;
+static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode) {
+ int err;
+ LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
+
+ switch (usage_page) {
+ case USAGE_KEYPAD:
+ err = zmk_hid_keypad_release(keycode);
+ if (err) {
+ LOG_ERR("Unable to release keycode");
+ return err;
+ }
+ break;
+ case USAGE_CONSUMER:
+ err = zmk_hid_consumer_release(keycode);
+ if (err) {
+ LOG_ERR("Unable to release keycode");
+ return err;
+ }
+ break;
}
- break;
- }
- return zmk_endpoints_send_report(usage_page);
+ return zmk_endpoints_send_report(usage_page);
}
-static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers)
-{
- LOG_DBG("modifiers %d", modifiers);
-
- zmk_hid_register_mods(modifiers);
- return zmk_endpoints_send_report(USAGE_KEYPAD);
+static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers) {
+ LOG_DBG("modifiers %d", modifiers);
+
+ zmk_hid_register_mods(modifiers);
+ return zmk_endpoints_send_report(USAGE_KEYPAD);
}
-static int hid_listener_modifiers_released(zmk_mod_flags modifiers)
-{
- LOG_DBG("modifiers %d", modifiers);
-
- zmk_hid_unregister_mods(modifiers);
- return zmk_endpoints_send_report(USAGE_KEYPAD);
+static int hid_listener_modifiers_released(zmk_mod_flags modifiers) {
+ LOG_DBG("modifiers %d", modifiers);
+
+ zmk_hid_unregister_mods(modifiers);
+ return zmk_endpoints_send_report(USAGE_KEYPAD);
}
-int hid_listener(const struct zmk_event_header *eh)
-{
- if (is_keycode_state_changed(eh)) {
- const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
- if (ev->state) {
- hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
- } else {
- hid_listener_keycode_released(ev->usage_page, ev->keycode);
- }
- } else if (is_modifiers_state_changed(eh)) {
- const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
- if (ev->state) {
- hid_listener_modifiers_pressed(ev->modifiers);
- } else {
- hid_listener_modifiers_released(ev->modifiers);
+int hid_listener(const struct zmk_event_header *eh) {
+ if (is_keycode_state_changed(eh)) {
+ const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
+ if (ev->state) {
+ hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
+ } else {
+ hid_listener_keycode_released(ev->usage_page, ev->keycode);
+ }
+ } else if (is_modifiers_state_changed(eh)) {
+ const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
+ if (ev->state) {
+ hid_listener_modifiers_pressed(ev->modifiers);
+ } else {
+ hid_listener_modifiers_released(ev->modifiers);
+ }
}
- }
- return 0;
+ return 0;
}
ZMK_LISTENER(hid_listener, hid_listener);
diff --git a/app/src/hog.c b/app/src/hog.c
index 589c28f..11349ac 100644
--- a/app/src/hog.c
+++ b/app/src/hog.c
@@ -1,5 +1,15 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
#include <settings/settings.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
#include <bluetooth/bluetooth.h>
#include <bluetooth/gatt.h>
@@ -7,21 +17,18 @@
#include <zmk/hog.h>
#include <zmk/hid.h>
-enum
-{
+enum {
HIDS_REMOTE_WAKE = BIT(0),
HIDS_NORMALLY_CONNECTABLE = BIT(1),
};
-struct hids_info
-{
+struct hids_info {
u16_t version; /* version number of base USB HID Specification */
u8_t code; /* country HID Device hardware is localized for. */
u8_t flags;
} __packed;
-struct hids_report
-{
+struct hids_report {
u8_t id; /* report id */
u8_t type; /* report type */
} __packed;
@@ -32,8 +39,7 @@ static struct hids_info info = {
.flags = HIDS_NORMALLY_CONNECTABLE & HIDS_REMOTE_WAKE,
};
-enum
-{
+enum {
HIDS_INPUT = 0x01,
HIDS_OUTPUT = 0x02,
HIDS_FEATURE = 0x03,
@@ -53,31 +59,37 @@ static bool host_requests_notification = false;
static u8_t ctrl_point;
// static u8_t proto_mode;
-static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
-{
- return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_info));
+static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
+ u16_t len, u16_t offset) {
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
+ sizeof(struct hids_info));
}
-static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
-{
- return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_report));
+static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, u16_t len, u16_t offset) {
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
+ sizeof(struct hids_report));
}
-static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
-{
- return bt_gatt_attr_read(conn, attr, buf, len, offset, zmk_hid_report_desc, sizeof(zmk_hid_report_desc));
+static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, u16_t len, u16_t offset) {
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, zmk_hid_report_desc,
+ sizeof(zmk_hid_report_desc));
}
-static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
-{
+static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, u16_t len, u16_t offset) {
struct zmk_hid_keypad_report_body *report_body = &zmk_hid_get_keypad_report()->body;
- return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body, sizeof(struct zmk_hid_keypad_report_body));
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
+ sizeof(struct zmk_hid_keypad_report_body));
}
-static ssize_t read_hids_consumer_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset)
-{
+static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
+ const struct bt_gatt_attr *attr, void *buf,
+ u16_t len, u16_t offset) {
struct zmk_hid_consumer_report_body *report_body = &zmk_hid_get_consumer_report()->body;
- return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body, sizeof(struct zmk_hid_consumer_report_body));
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
+ sizeof(struct zmk_hid_consumer_report_body));
}
// static ssize_t write_proto_mode(struct bt_conn *conn,
@@ -89,20 +101,15 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn, const struc
// return 0;
// }
-static void input_ccc_changed(const struct bt_gatt_attr *attr, u16_t value)
-{
+static void input_ccc_changed(const struct bt_gatt_attr *attr, u16_t value) {
host_requests_notification = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
}
-static ssize_t write_ctrl_point(struct bt_conn *conn,
- const struct bt_gatt_attr *attr,
- const void *buf, u16_t len, u16_t offset,
- u8_t flags)
-{
+static ssize_t write_ctrl_point(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ const void *buf, u16_t len, u16_t offset, u8_t flags) {
u8_t *value = attr->user_data;
- if (offset + len > sizeof(ctrl_point))
- {
+ if (offset + len > sizeof(ctrl_point)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
@@ -112,42 +119,61 @@ static ssize_t write_ctrl_point(struct bt_conn *conn,
}
/* HID Service Declaration */
-BT_GATT_SERVICE_DEFINE(hog_svc,
- BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
- // BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
- // BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode),
- BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ,
- BT_GATT_PERM_READ, read_hids_info, NULL, &info),
- BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ,
- BT_GATT_PERM_READ, read_hids_report_map, NULL, NULL),
-
- BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
- BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
- BT_GATT_PERM_READ_ENCRYPT,
- read_hids_input_report, NULL, NULL),
- BT_GATT_CCC(input_ccc_changed,
- BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
- BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ,
- read_hids_report_ref, NULL, &input),
- BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
- BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
- BT_GATT_PERM_READ_ENCRYPT,
- read_hids_consumer_input_report, NULL, NULL),
- BT_GATT_CCC(input_ccc_changed,
- BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
- BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ,
- read_hids_report_ref, NULL, &consumer_input),
- BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT,
- BT_GATT_CHRC_WRITE_WITHOUT_RESP,
- BT_GATT_PERM_WRITE,
- NULL, write_ctrl_point, &ctrl_point));
-
-int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report)
-{
- return bt_gatt_notify(NULL, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_keypad_report_body));
+BT_GATT_SERVICE_DEFINE(
+ hog_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
+ // BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
+ // BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_hids_info,
+ NULL, &info),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+ read_hids_report_map, NULL, NULL),
+
+ BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
+ BT_GATT_PERM_READ_ENCRYPT, read_hids_input_report, NULL, NULL),
+ BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
+ BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, read_hids_report_ref, NULL,
+ &input),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
+ BT_GATT_PERM_READ_ENCRYPT, read_hids_consumer_input_report, NULL, NULL),
+ BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
+ BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, read_hids_report_ref, NULL,
+ &consumer_input),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
+ BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point));
+
+struct bt_conn *destination_connection() {
+ struct bt_conn *conn;
+ bt_addr_le_t *addr = zmk_ble_active_profile_addr();
+ LOG_DBG("Address pointer %p", addr);
+ if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
+ LOG_WRN("Not sending, no active address for current profile");
+ return NULL;
+ } else if ((conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr)) == NULL) {
+ LOG_WRN("Not sending, not connected to active profile");
+ return NULL;
+ }
+
+ return conn;
+}
+
+int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) {
+ struct bt_conn *conn = destination_connection();
+ if (conn == NULL) {
+ return -ENOTCONN;
+ }
+
+ LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
+
+ return bt_gatt_notify(conn, &hog_svc.attrs[5], report,
+ sizeof(struct zmk_hid_keypad_report_body));
};
-int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report)
-{
- return bt_gatt_notify(NULL, &hog_svc.attrs[10], report, sizeof(struct zmk_hid_consumer_report_body));
+int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
+ struct bt_conn *conn = destination_connection();
+ if (conn == NULL) {
+ return -ENOTCONN;
+ }
+
+ return bt_gatt_notify(conn, &hog_svc.attrs[10], report,
+ sizeof(struct zmk_hid_consumer_report_body));
};
diff --git a/app/src/keymap.c b/app/src/keymap.c
index ee6e370..a87ce04 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <sys/util.h>
#include <logging/log.h>
@@ -19,189 +24,185 @@ static u8_t zmk_keymap_layer_default = 0;
#define DT_DRV_COMPAT zmk_keymap
-#define LAYER_CHILD_LEN(node) 1+
+#define LAYER_CHILD_LEN(node) 1 +
#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 _TRANSFORM_ENTRY(idx, layer) \
- { .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) },
+#define _TRANSFORM_ENTRY(idx, layer) \
+ { \
+ .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
-#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
- { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, sensor_bindings, idx)), \
- .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param1), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param1))), \
- .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param2), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param2))), \
- },
-
-#define SENSOR_LAYER(node) \
- COND_CODE_1(DT_NODE_HAS_PROP(node, sensor_bindings), \
- ({ UTIL_LISTIFY(DT_PROP_LEN(node, sensor_bindings), _TRANSFORM_SENSOR_ENTRY, node) }), \
- ({})),
+#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
+ { \
+ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, sensor_bindings, idx)), \
+ .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param1), (0), \
+ (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param1))), \
+ .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param2), (0), \
+ (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param2))), \
+ },
+
+#define SENSOR_LAYER(node) \
+ COND_CODE_1( \
+ DT_NODE_HAS_PROP(node, sensor_bindings), \
+ ({UTIL_LISTIFY(DT_PROP_LEN(node, sensor_bindings), _TRANSFORM_SENSOR_ENTRY, node)}), \
+ ({})),
#endif /* ZMK_KEYMAP_HAS_SENSORS */
// State
-// When a behavior handles a key position "down" event, we record that layer
+// When a behavior handles a key position "down" event, we record the layer state
// here so that even if that layer is deactivated before the "up", event, we
// still send the release event to the behavior in that layer also.
-static u8_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
+static u32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = {
- DT_INST_FOREACH_CHILD(0, TRANSFORMED_LAYER)
-};
+ DT_INST_FOREACH_CHILD(0, TRANSFORMED_LAYER)};
#if ZMK_KEYMAP_HAS_SENSORS
-static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_SENSORS_LEN] = {
- DT_INST_FOREACH_CHILD(0, SENSOR_LAYER)
-};
+static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN]
+ [ZMK_KEYMAP_SENSORS_LEN] = {
+ DT_INST_FOREACH_CHILD(0, SENSOR_LAYER)};
#endif /* ZMK_KEYMAP_HAS_SENSORS */
-#define SET_LAYER_STATE(layer, state) \
- if (layer >= 32) \
- { \
- return -EINVAL; \
- } \
- WRITE_BIT(zmk_keymap_layer_state, layer, state); \
- return 0;
-
-bool zmk_keymap_layer_active(u8_t layer)
-{
- return (zmk_keymap_layer_state & (BIT(layer))) == (BIT(layer));
-};
+#define SET_LAYER_STATE(layer, state) \
+ if (layer >= 32) { \
+ return -EINVAL; \
+ } \
+ WRITE_BIT(zmk_keymap_layer_state, layer, state); \
+ return 0;
-int zmk_keymap_layer_activate(u8_t layer)
-{
- SET_LAYER_STATE(layer, true);
+bool zmk_keymap_layer_active(u8_t layer) {
+ return (zmk_keymap_layer_state & (BIT(layer))) == (BIT(layer));
};
-int zmk_keymap_layer_deactivate(u8_t layer)
-{
- SET_LAYER_STATE(layer, false);
-};
+int zmk_keymap_layer_activate(u8_t layer) { SET_LAYER_STATE(layer, true); };
+
+int zmk_keymap_layer_deactivate(u8_t layer) { SET_LAYER_STATE(layer, false); };
-int zmk_keymap_layer_toggle(u8_t layer)
-{
- if (zmk_keymap_layer_active(layer))
- {
- return zmk_keymap_layer_deactivate(layer);
- }
+int zmk_keymap_layer_toggle(u8_t layer) {
+ if (zmk_keymap_layer_active(layer)) {
+ return zmk_keymap_layer_deactivate(layer);
+ }
- return zmk_keymap_layer_activate(layer);
+ return zmk_keymap_layer_activate(layer);
};
-bool is_active_position(u32_t position, u8_t layer)
-{
- return (zmk_keymap_layer_state & BIT(layer)) == BIT(layer)
- || layer == zmk_keymap_layer_default
- || zmk_keymap_active_behavior_layer[position] == layer;
+bool is_active_layer(u8_t layer, u32_t layer_state) {
+ return (layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default;
}
-int zmk_keymap_position_state_changed(u32_t position, bool pressed)
-{
- for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--)
- {
- if (is_active_position(position, layer))
- {
- struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
- struct device *behavior;
- int ret;
-
- LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev));
-
- behavior = device_get_binding(binding->behavior_dev);
-
- if (!behavior) {
- LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
- continue;
- }
- if (pressed) {
- ret = behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2);
- } else {
- ret = behavior_keymap_binding_released(behavior, position, binding->param1, binding->param2);
- }
-
-
- if (ret > 0) {
- LOG_DBG("behavior processing to continue to next layer");
- continue;
- } else if (ret < 0) {
- LOG_DBG("Behavior returned error: %d", ret);
- zmk_keymap_active_behavior_layer[position] = 0;
- return ret;
- } else {
- zmk_keymap_active_behavior_layer[position] = pressed ? layer : 0;
- return ret;
- }
- }
- }
-
- return -ENOTSUP;
+int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) {
+ struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
+ struct device *behavior;
+
+ LOG_DBG("layer: %d position: %d, binding name: %s", layer, position,
+ log_strdup(binding->behavior_dev));
+
+ behavior = device_get_binding(binding->behavior_dev);
+
+ if (!behavior) {
+ LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
+ return 1;
+ }
+
+ if (pressed) {
+ return behavior_keymap_binding_pressed(behavior, position, binding->param1,
+ binding->param2);
+ } else {
+ return behavior_keymap_binding_released(behavior, position, binding->param1,
+ binding->param2);
+ }
+}
+
+int zmk_keymap_position_state_changed(u32_t position, bool pressed) {
+ for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) {
+ u32_t layer_state =
+ pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position];
+ if (is_active_layer(layer, layer_state)) {
+ int ret = zmk_keymap_apply_position_state(layer, position, pressed);
+
+ zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state;
+
+ if (ret > 0) {
+ LOG_DBG("behavior processing to continue to next layer");
+ continue;
+ } else if (ret < 0) {
+ LOG_DBG("Behavior returned error: %d", ret);
+ return ret;
+ } else {
+ return ret;
+ }
+ }
+ }
+
+ return -ENOTSUP;
}
#if ZMK_KEYMAP_HAS_SENSORS
-int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor)
-{
- for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--)
- {
- if (((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default) && zmk_sensor_keymap[layer] != NULL)
- {
- struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number];
- struct device *behavior;
- int ret;
-
- LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number, log_strdup(binding->behavior_dev));
-
- behavior = device_get_binding(binding->behavior_dev);
-
- if (!behavior) {
- LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer);
- continue;
- }
-
- ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1, binding->param2);
-
- if (ret > 0) {
- LOG_DBG("behavior processing to continue to next layer");
- continue;
- } else if (ret < 0) {
- LOG_DBG("Behavior returned error: %d", ret);
- return ret;
- } else {
- return ret;
- }
- }
- }
-
- return -ENOTSUP;
+int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) {
+ for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) {
+ if (((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) ||
+ layer == zmk_keymap_layer_default) &&
+ zmk_sensor_keymap[layer] != NULL) {
+ struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number];
+ struct device *behavior;
+ int ret;
+
+ LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number,
+ log_strdup(binding->behavior_dev));
+
+ behavior = device_get_binding(binding->behavior_dev);
+
+ if (!behavior) {
+ LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer);
+ continue;
+ }
+
+ ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1,
+ binding->param2);
+
+ if (ret > 0) {
+ LOG_DBG("behavior processing to continue to next layer");
+ continue;
+ } else if (ret < 0) {
+ LOG_DBG("Behavior returned error: %d", ret);
+ return ret;
+ } else {
+ return ret;
+ }
+ }
+ }
+
+ return -ENOTSUP;
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
-int keymap_listener(const struct zmk_event_header *eh)
-{
- if (is_position_state_changed(eh)) {
- const struct position_state_changed *ev = cast_position_state_changed(eh);
- return zmk_keymap_position_state_changed(ev->position, ev->state);
+int keymap_listener(const struct zmk_event_header *eh) {
+ if (is_position_state_changed(eh)) {
+ const struct position_state_changed *ev = cast_position_state_changed(eh);
+ return zmk_keymap_position_state_changed(ev->position, ev->state);
#if ZMK_KEYMAP_HAS_SENSORS
- } 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);
+ } 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);
#endif /* ZMK_KEYMAP_HAS_SENSORS */
- }
+ }
- return -ENOTSUP;
+ return -ENOTSUP;
}
ZMK_LISTENER(keymap, keymap_listener);
@@ -210,4 +211,3 @@ ZMK_SUBSCRIPTION(keymap, position_state_changed);
#if ZMK_KEYMAP_HAS_SENSORS
ZMK_SUBSCRIPTION(keymap, sensor_event);
#endif /* ZMK_KEYMAP_HAS_SENSORS */
-
diff --git a/app/src/kscan.c b/app/src/kscan.c
index 63713f1..0046f5c 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -18,61 +18,55 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_KSCAN_EVENT_STATE_PRESSED 0
#define ZMK_KSCAN_EVENT_STATE_RELEASED 1
-struct zmk_kscan_event
-{
- u32_t row;
- u32_t column;
- u32_t state;
+struct zmk_kscan_event {
+ u32_t row;
+ u32_t column;
+ u32_t state;
};
-struct zmk_kscan_msg_processor
-{
- struct k_work work;
+struct zmk_kscan_msg_processor {
+ struct k_work work;
} msg_processor;
K_MSGQ_DEFINE(zmk_kscan_msgq, sizeof(struct zmk_kscan_event), CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE, 4);
-static void zmk_kscan_callback(struct device *dev, u32_t row, u32_t column, bool pressed)
-{
- struct zmk_kscan_event ev = {
- .row = row,
- .column = column,
- .state = (pressed ? ZMK_KSCAN_EVENT_STATE_PRESSED : ZMK_KSCAN_EVENT_STATE_RELEASED)};
+static void zmk_kscan_callback(struct device *dev, u32_t row, u32_t column, bool pressed) {
+ struct zmk_kscan_event ev = {
+ .row = row,
+ .column = column,
+ .state = (pressed ? ZMK_KSCAN_EVENT_STATE_PRESSED : ZMK_KSCAN_EVENT_STATE_RELEASED)};
- k_msgq_put(&zmk_kscan_msgq, &ev, K_NO_WAIT);
- k_work_submit(&msg_processor.work);
+ k_msgq_put(&zmk_kscan_msgq, &ev, K_NO_WAIT);
+ k_work_submit(&msg_processor.work);
}
-void zmk_kscan_process_msgq(struct k_work *item)
-{
- struct zmk_kscan_event ev;
+void zmk_kscan_process_msgq(struct k_work *item) {
+ struct zmk_kscan_event ev;
- while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0)
- {
- bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
- u32_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, (pressed ? "true" : "false"));
- pos_ev = new_position_state_changed();
- pos_ev->state = pressed;
- pos_ev->position = position;
- ZMK_EVENT_RAISE(pos_ev);
- }
+ while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) {
+ bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
+ u32_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,
+ (pressed ? "true" : "false"));
+ pos_ev = new_position_state_changed();
+ pos_ev->state = pressed;
+ pos_ev->position = position;
+ ZMK_EVENT_RAISE(pos_ev);
+ }
}
-int zmk_kscan_init(char *name)
-{
- struct device *dev = device_get_binding(name);
- if (dev == NULL)
- {
- LOG_ERR("Failed to get the KSCAN device");
- return -EINVAL;
- }
+int zmk_kscan_init(char *name) {
+ struct device *dev = device_get_binding(name);
+ if (dev == NULL) {
+ LOG_ERR("Failed to get the KSCAN device");
+ return -EINVAL;
+ }
- k_work_init(&msg_processor.work, zmk_kscan_process_msgq);
+ k_work_init(&msg_processor.work, zmk_kscan_process_msgq);
- kscan_config(dev, zmk_kscan_callback);
- kscan_enable_callback(dev);
+ kscan_config(dev, zmk_kscan_callback);
+ kscan_enable_callback(dev);
- return 0;
+ return 0;
}
diff --git a/app/src/kscan_composite.c b/app/src/kscan_composite.c
index d46484b..0249140 100644
--- a/app/src/kscan_composite.c
+++ b/app/src/kscan_composite.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -15,37 +15,31 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define MATRIX_ROWS DT_PROP(MATRIX_NODE_ID, rows)
#define MATRIX_COLS DT_PROP(MATRIX_NODE_ID, columns)
-struct kscan_composite_child_config
-{
+struct kscan_composite_child_config {
char *label;
u8_t row_offset;
u8_t column_offset;
};
-#define CHILD_CONFIG(inst) \
- { \
- .label = DT_LABEL(DT_PHANDLE(inst, kscan)), \
- .row_offset = DT_PROP(inst, row_offset), \
- .column_offset = DT_PROP(inst, column_offset)},
+#define CHILD_CONFIG(inst) \
+ {.label = DT_LABEL(DT_PHANDLE(inst, kscan)), \
+ .row_offset = DT_PROP(inst, row_offset), \
+ .column_offset = DT_PROP(inst, column_offset)},
const struct kscan_composite_child_config kscan_composite_children[] = {
DT_FOREACH_CHILD(MATRIX_NODE_ID, CHILD_CONFIG)};
-struct kscan_composite_config
-{
-};
+struct kscan_composite_config {};
-struct kscan_composite_data
-{
+struct kscan_composite_data {
kscan_callback_t callback;
struct device *dev;
};
-static int kscan_composite_enable_callback(struct device *dev)
-{
- for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++)
- {
+static int kscan_composite_enable_callback(struct device *dev) {
+ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
+ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_enable_callback(device_get_binding(cfg->label));
@@ -53,10 +47,9 @@ static int kscan_composite_enable_callback(struct device *dev)
return 0;
}
-static int kscan_composite_disable_callback(struct device *dev)
-{
- for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++)
- {
+static int kscan_composite_disable_callback(struct device *dev) {
+ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
+ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_disable_callback(device_get_binding(cfg->label));
@@ -64,18 +57,17 @@ static int kscan_composite_disable_callback(struct device *dev)
return 0;
}
-static void kscan_composite_child_callback(struct device *child_dev, u32_t row, u32_t column, bool pressed)
-{
+static void kscan_composite_child_callback(struct device *child_dev, u32_t row, u32_t column,
+ bool pressed) {
// TODO: Ideally we can get this passed into our callback!
struct device *dev = device_get_binding(DT_INST_LABEL(0));
struct kscan_composite_data *data = dev->driver_data;
- for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++)
- {
+ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
+ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
- if (device_get_binding(cfg->label) != child_dev)
- {
+ if (device_get_binding(cfg->label) != child_dev) {
continue;
}
@@ -83,17 +75,15 @@ static void kscan_composite_child_callback(struct device *child_dev, u32_t row,
}
}
-static int kscan_composite_configure(struct device *dev, kscan_callback_t callback)
-{
+static int kscan_composite_configure(struct device *dev, kscan_callback_t callback) {
struct kscan_composite_data *data = dev->driver_data;
- if (!callback)
- {
+ if (!callback) {
return -EINVAL;
}
- for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++)
- {
+ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
+ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback);
@@ -104,8 +94,7 @@ static int kscan_composite_configure(struct device *dev, kscan_callback_t callba
return 0;
}
-static int kscan_composite_init(struct device *dev)
-{
+static int kscan_composite_init(struct device *dev) {
struct kscan_composite_data *data = dev->driver_data;
data->dev = dev;
@@ -123,8 +112,6 @@ static const struct kscan_composite_config kscan_composite_config = {};
static struct kscan_composite_data kscan_composite_data;
-DEVICE_AND_API_INIT(kscan_composite, DT_INST_LABEL(0), kscan_composite_init,
- &kscan_composite_data,
- &kscan_composite_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+DEVICE_AND_API_INIT(kscan_composite, DT_INST_LABEL(0), kscan_composite_init, &kscan_composite_data,
+ &kscan_composite_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&mock_driver_api);
diff --git a/app/src/kscan_mock.c b/app/src/kscan_mock.c
index b0ba90b..e9c15a0 100644
--- a/app/src/kscan_mock.c
+++ b/app/src/kscan_mock.c
@@ -1,21 +1,21 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT zmk_kscan_mock
+#include <stdlib.h>
#include <device.h>
#include <drivers/kscan.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-#include <zmk/kscan-mock.h>
+#include <dt-bindings/zmk/kscan-mock.h>
-struct kscan_mock_data
-{
+struct kscan_mock_data {
kscan_callback_t callback;
u8_t event_index;
@@ -23,20 +23,17 @@ struct kscan_mock_data
struct device *dev;
};
-static int kscan_mock_disable_callback(struct device *dev)
-{
+static int kscan_mock_disable_callback(struct device *dev) {
struct kscan_mock_data *data = dev->driver_data;
k_delayed_work_cancel(&data->work);
return 0;
}
-static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
-{
+static int kscan_mock_configure(struct device *dev, kscan_callback_t callback) {
struct kscan_mock_data *data = dev->driver_data;
- if (!callback)
- {
+ if (!callback) {
return -EINVAL;
}
@@ -46,58 +43,53 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
return 0;
}
-#define MOCK_INST_INIT(n) \
- struct kscan_mock_config_##n \
- { \
- u32_t events[DT_INST_PROP_LEN(n, events)]; \
- }; \
- static void kscan_mock_schedule_next_event_##n(struct device *dev) \
- { \
- struct kscan_mock_data *data = dev->driver_data; \
- const struct kscan_mock_config_##n *cfg = dev->config_info; \
- if (data->event_index < DT_INST_PROP_LEN(n, events)) \
- { \
- u32_t ev = cfg->events[data->event_index]; \
- LOG_DBG("delaying next keypress: %d", ZMK_MOCK_MSEC(ev)); \
- k_delayed_work_submit(&data->work, K_MSEC(ZMK_MOCK_MSEC(ev))); \
- } \
- } \
- static void kscan_mock_work_handler_##n(struct k_work *work) \
- { \
- struct kscan_mock_data *data = \
- CONTAINER_OF(work, struct kscan_mock_data, work); \
- const struct kscan_mock_config_##n *cfg = data->dev->config_info; \
- u32_t ev = cfg->events[data->event_index++]; \
- LOG_DBG("ev %u row %d column %d state %d\n", ev, \
- ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
- data->callback(data->dev, \
- ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
- kscan_mock_schedule_next_event_##n(data->dev); \
- } \
- static int kscan_mock_init_##n(struct device *dev) \
- { \
- struct kscan_mock_data *data = dev->driver_data; \
- data->dev = dev; \
- k_delayed_work_init(&data->work, kscan_mock_work_handler_##n); \
- return 0; \
- } \
- static int kscan_mock_enable_callback_##n(struct device *dev) \
- { \
- kscan_mock_schedule_next_event_##n(dev); \
- return 0; \
- } \
- static const struct kscan_driver_api mock_driver_api_##n = { \
- .config = kscan_mock_configure, \
- .enable_callback = kscan_mock_enable_callback_##n, \
- .disable_callback = kscan_mock_disable_callback, \
- }; \
- static struct kscan_mock_data kscan_mock_data_##n; \
- static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
- .events = DT_INST_PROP(n, events)}; \
- DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
- &kscan_mock_data_##n, \
- &kscan_mock_config_##n, \
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
- &mock_driver_api_##n);
+#define MOCK_INST_INIT(n) \
+ struct kscan_mock_config_##n { \
+ u32_t events[DT_INST_PROP_LEN(n, events)]; \
+ bool exit_after; \
+ }; \
+ static void kscan_mock_schedule_next_event_##n(struct device *dev) { \
+ struct kscan_mock_data *data = dev->driver_data; \
+ const struct kscan_mock_config_##n *cfg = dev->config_info; \
+ if (data->event_index < DT_INST_PROP_LEN(n, events)) { \
+ u32_t ev = cfg->events[data->event_index]; \
+ LOG_DBG("delaying next keypress: %d", ZMK_MOCK_MSEC(ev)); \
+ k_delayed_work_submit(&data->work, K_MSEC(ZMK_MOCK_MSEC(ev))); \
+ } else if (cfg->exit_after) { \
+ LOG_DBG("Exiting"); \
+ exit(0); \
+ } \
+ } \
+ static void kscan_mock_work_handler_##n(struct k_work *work) { \
+ struct kscan_mock_data *data = CONTAINER_OF(work, struct kscan_mock_data, work); \
+ const struct kscan_mock_config_##n *cfg = data->dev->config_info; \
+ u32_t ev = cfg->events[data->event_index]; \
+ LOG_DBG("ev %u row %d column %d state %d\n", ev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), \
+ ZMK_MOCK_IS_PRESS(ev)); \
+ data->callback(data->dev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
+ kscan_mock_schedule_next_event_##n(data->dev); \
+ data->event_index++; \
+ } \
+ static int kscan_mock_init_##n(struct device *dev) { \
+ struct kscan_mock_data *data = dev->driver_data; \
+ data->dev = dev; \
+ k_delayed_work_init(&data->work, kscan_mock_work_handler_##n); \
+ return 0; \
+ } \
+ static int kscan_mock_enable_callback_##n(struct device *dev) { \
+ kscan_mock_schedule_next_event_##n(dev); \
+ return 0; \
+ } \
+ static const struct kscan_driver_api mock_driver_api_##n = { \
+ .config = kscan_mock_configure, \
+ .enable_callback = kscan_mock_enable_callback_##n, \
+ .disable_callback = kscan_mock_disable_callback, \
+ }; \
+ static struct kscan_mock_data kscan_mock_data_##n; \
+ static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
+ .events = DT_INST_PROP(n, events), .exit_after = DT_INST_PROP(n, exit_after)}; \
+ DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
+ &kscan_mock_data_##n, &kscan_mock_config_##n, APPLICATION, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api_##n);
-DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT) \ No newline at end of file
+DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT)
diff --git a/app/src/main.c b/app/src/main.c
index 5a678ee..dca923e 100644
--- a/app/src/main.c
+++ b/app/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -18,20 +18,18 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
-void main(void)
-{
- LOG_INF("Welcome to ZMK!\n");
+void main(void) {
+ LOG_INF("Welcome to ZMK!\n");
- if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0)
- {
- return;
- }
+ if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) {
+ return;
+ }
#ifdef CONFIG_ZMK_DISPLAY
- zmk_display_init();
+ zmk_display_init();
- while (1) {
- zmk_display_task_handler();
- }
+ while (1) {
+ zmk_display_task_handler();
+ }
#endif /* CONFIG_ZMK_DISPLAY */
}
diff --git a/app/src/matrix_transform.c b/app/src/matrix_transform.c
index 7ecf1ae..4e68a56 100644
--- a/app/src/matrix_transform.c
+++ b/app/src/matrix_transform.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <zephyr.h>
#include <zmk/matrix_transform.h>
@@ -6,16 +11,15 @@
#ifdef ZMK_KEYMAP_TRANSFORM_NODE
-#define _TRANSFORM_ENTRY(i, _) \
- [(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = i,
+#define _TRANSFORM_ENTRY(i, _) \
+ [(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + \
+ KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = i,
-static u32_t transform[] =
- { UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0) };
+static u32_t transform[] = {UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0)};
#endif
-u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column)
-{
+u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column) {
u32_t matrix_index;
#if DT_NODE_HAS_PROP(ZMK_KEYMAP_TRANSFORM_NODE, col_offset)
diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c
index cb98e8d..d453755 100644
--- a/app/src/rgb_underglow.c
+++ b/app/src/rgb_underglow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Nick Winans <nick@winans.codes>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -18,8 +18,8 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
-#define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
+#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
+#define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
enum rgb_underglow_effect {
UNDERGLOW_EFFECT_SOLID,
@@ -30,19 +30,19 @@ enum rgb_underglow_effect {
};
struct led_hsb {
- u16_t h;
- u8_t s;
- u8_t b;
+ u16_t h;
+ u8_t s;
+ u8_t b;
};
struct rgb_underglow_state {
u16_t hue;
- u8_t saturation;
- u8_t brightness;
- u8_t animation_speed;
- u8_t current_effect;
+ u8_t saturation;
+ u8_t brightness;
+ u8_t animation_speed;
+ u8_t current_effect;
u16_t animation_step;
- bool on;
+ bool on;
};
struct device *led_strip;
@@ -92,17 +92,40 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb)
double q = v * (1 - f * s);
double t = v * (1 - (1 - f) * s);
- switch (i % 6)
- {
- case 0: r = v; g = t; b = p; break;
- case 1: r = q; g = v; b = p; break;
- case 2: r = p; g = v; b = t; break;
- case 3: r = p; g = q; b = v; break;
- case 4: r = t; g = p; b = v; break;
- case 5: r = v; g = p; b = q; break;
+ switch (i % 6) {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = v;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = v;
+ break;
+ case 5:
+ r = v;
+ g = p;
+ b = q;
+ break;
}
- struct led_rgb rgb = { r: r*255, g: g*255, b: b*255 };
+ struct led_rgb rgb = {r : r * 255, g : g * 255, b : b * 255};
return rgb;
}
@@ -125,41 +148,37 @@ static void zmk_rgb_underglow_effect_solid()
int sat = state.saturation;
int brt = state.brightness;
- struct led_hsb hsb = { hue, sat, brt };
+ struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb);
}
}
-static void zmk_rgb_underglow_effect_breathe()
-{
- for (int i=0; i<STRIP_NUM_PIXELS; i++)
- {
+static void zmk_rgb_underglow_effect_breathe() {
+ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = state.hue;
int sat = state.saturation;
int brt = abs(state.animation_step - 1200) / 12;
- struct led_hsb hsb = { hue, sat, brt };
+ struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb);
}
state.animation_step += state.animation_speed * 10;
-
+
if (state.animation_step > 2400) {
state.animation_step = 0;
}
}
-static void zmk_rgb_underglow_effect_spectrum()
-{
- for (int i=0; i<STRIP_NUM_PIXELS; i++)
- {
+static void zmk_rgb_underglow_effect_spectrum() {
+ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = state.animation_step;
int sat = state.saturation;
int brt = state.brightness;
- struct led_hsb hsb = { hue, sat, brt };
+ struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb);
}
@@ -168,15 +187,13 @@ static void zmk_rgb_underglow_effect_spectrum()
state.animation_step = state.animation_step % 360;
}
-static void zmk_rgb_underglow_effect_swirl()
-{
- for (int i=0; i<STRIP_NUM_PIXELS; i++)
- {
+static void zmk_rgb_underglow_effect_swirl() {
+ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360;
int sat = state.saturation;
int brt = state.brightness;
- struct led_hsb hsb = { hue, sat, brt };
+ struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb);
}
@@ -185,22 +202,20 @@ static void zmk_rgb_underglow_effect_swirl()
state.animation_step = state.animation_step % 360;
}
-static void zmk_rgb_underglow_tick(struct k_work *work)
-{
- switch (state.current_effect)
- {
- case UNDERGLOW_EFFECT_SOLID:
- zmk_rgb_underglow_effect_solid();
- break;
- case UNDERGLOW_EFFECT_BREATHE:
- zmk_rgb_underglow_effect_breathe();
- break;
- case UNDERGLOW_EFFECT_SPECTRUM:
- zmk_rgb_underglow_effect_spectrum();
- break;
- case UNDERGLOW_EFFECT_SWIRL:
- zmk_rgb_underglow_effect_swirl();
- break;
+static void zmk_rgb_underglow_tick(struct k_work *work) {
+ switch (state.current_effect) {
+ case UNDERGLOW_EFFECT_SOLID:
+ zmk_rgb_underglow_effect_solid();
+ break;
+ case UNDERGLOW_EFFECT_BREATHE:
+ zmk_rgb_underglow_effect_breathe();
+ break;
+ case UNDERGLOW_EFFECT_SPECTRUM:
+ zmk_rgb_underglow_effect_spectrum();
+ break;
+ case UNDERGLOW_EFFECT_SWIRL:
+ zmk_rgb_underglow_effect_swirl();
+ break;
}
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
@@ -224,15 +239,14 @@ static void zmk_rgb_underglow_tick_handler(struct k_timer *timer)
K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL);
-static int zmk_rgb_underglow_init(struct device *_arg)
-{
- led_strip = device_get_binding(STRIP_LABEL);
- if (led_strip) {
- LOG_INF("Found LED strip device %s", STRIP_LABEL);
- } else {
- LOG_ERR("LED strip device %s not found", STRIP_LABEL);
- return -EINVAL;
- }
+static int zmk_rgb_underglow_init(struct device *_arg) {
+ led_strip = device_get_binding(STRIP_LABEL);
+ if (led_strip) {
+ LOG_INF("Found LED strip device %s", STRIP_LABEL);
+ } else {
+ LOG_ERR("LED strip device %s not found", STRIP_LABEL);
+ return -EINVAL;
+ }
state = (struct rgb_underglow_state){
hue: CONFIG_ZMK_RGB_UNDERGLOW_HUE_START,
@@ -276,15 +290,15 @@ int zmk_rgb_underglow_cycle_effect(int direction)
if (state.current_effect >= UNDERGLOW_EFFECT_NUMBER) {
state.current_effect = 0;
}
-
+
state.animation_step = 0;
return zmk_rgb_underglow_save_state();
}
-int zmk_rgb_underglow_toggle()
-{
- if (!led_strip) return -ENODEV;
+int zmk_rgb_underglow_toggle() {
+ if (!led_strip)
+ return -ENODEV;
state.on = !state.on;
@@ -300,15 +314,15 @@ int zmk_rgb_underglow_toggle()
return zmk_rgb_underglow_save_state();
}
-int zmk_rgb_underglow_change_hue(int direction)
-{
- if (!led_strip) return -ENODEV;
+int zmk_rgb_underglow_change_hue(int direction) {
+ if (!led_strip)
+ return -ENODEV;
if (state.hue == 0 && direction < 0) {
state.hue = 360 - CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
return 0;
}
-
+
state.hue += direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
state.hue = state.hue % 360;
@@ -316,9 +330,9 @@ int zmk_rgb_underglow_change_hue(int direction)
return zmk_rgb_underglow_save_state();
}
-int zmk_rgb_underglow_change_sat(int direction)
-{
- if (!led_strip) return -ENODEV;
+int zmk_rgb_underglow_change_sat(int direction) {
+ if (!led_strip)
+ return -ENODEV;
if (state.saturation == 0 && direction < 0) {
return 0;
@@ -333,9 +347,9 @@ int zmk_rgb_underglow_change_sat(int direction)
return zmk_rgb_underglow_save_state();
}
-int zmk_rgb_underglow_change_brt(int direction)
-{
- if (!led_strip) return -ENODEV;
+int zmk_rgb_underglow_change_brt(int direction) {
+ if (!led_strip)
+ return -ENODEV;
if (state.brightness == 0 && direction < 0) {
return 0;
@@ -350,9 +364,9 @@ int zmk_rgb_underglow_change_brt(int direction)
return zmk_rgb_underglow_save_state();
}
-int zmk_rgb_underglow_change_spd(int direction)
-{
- if (!led_strip) return -ENODEV;
+int zmk_rgb_underglow_change_spd(int direction) {
+ if (!led_strip)
+ return -ENODEV;
if (state.animation_speed == 1 && direction < 0) {
return 0;
@@ -367,6 +381,4 @@ int zmk_rgb_underglow_change_spd(int direction)
return zmk_rgb_underglow_save_state();
}
-SYS_INIT(zmk_rgb_underglow_init,
- APPLICATION,
- CONFIG_APPLICATION_INIT_PRIORITY);
+SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
diff --git a/app/src/sensors.c b/app/src/sensors.c
index 501ce15..15f374b 100644
--- a/app/src/sensors.c
+++ b/app/src/sensors.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -24,19 +24,19 @@ struct sensors_data_item {
struct sensor_trigger trigger;
};
-#define _SENSOR_ITEM(node) {.dev = NULL, .trigger = { .type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION } },
-#define SENSOR_ITEM(idx, _) COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx),okay), (_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))),())
+#define _SENSOR_ITEM(node) \
+ {.dev = NULL, .trigger = {.type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION}},
+#define SENSOR_ITEM(idx, _) \
+ COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
+ (_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), ())
-static struct sensors_data_item sensors[] = {
- UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, 0)
-};
+static struct sensors_data_item sensors[] = {UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, 0)};
-static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigger *trigger)
-{
+static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigger *trigger) {
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);
err = sensor_sample_fetch(dev);
@@ -52,8 +52,7 @@ static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigge
ZMK_EVENT_RAISE(event);
}
-static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i)
-{
+static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i) {
LOG_DBG("Init %s at index %d with sensor_number %d", node, i, abs_i);
sensors[i].dev = device_get_binding(node);
@@ -68,10 +67,11 @@ static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i)
}
#define _SENSOR_INIT(node) zmk_sensors_init_item(DT_LABEL(node), local_index++, absolute_index++);
-#define SENSOR_INIT(idx, _i) COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx),okay), (_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))),(absolute_index++;))
+#define SENSOR_INIT(idx, _i) \
+ COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
+ (_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), (absolute_index++;))
-static int zmk_sensors_init(struct device *_arg)
-{
+static int zmk_sensors_init(struct device *_arg) {
int local_index = 0;
int absolute_index = 0;
@@ -79,8 +79,6 @@ static int zmk_sensors_init(struct device *_arg)
return 0;
}
-SYS_INIT(zmk_sensors_init,
- APPLICATION,
- CONFIG_APPLICATION_INIT_PRIORITY);
+SYS_INIT(zmk_sensors_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
#endif /* ZMK_KEYMAP_HAS_SENSORS */ \ No newline at end of file
diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c
index 237096f..cb1b68b 100644
--- a/app/src/split/bluetooth/central.c
+++ b/app/src/split/bluetooth/central.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -10,12 +10,14 @@
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
+#include <bluetooth/hci.h>
#include <sys/byteorder.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+#include <zmk/ble.h>
#include <zmk/split/bluetooth/uuid.h>
#include <zmk/event-manager.h>
#include <zmk/events/position-state-changed.h>
@@ -31,283 +33,290 @@ 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_subscribe_params subscribe_params;
-static u8_t split_central_notify_func(struct bt_conn *conn,
- struct bt_gatt_subscribe_params *params,
- const void *data, u16_t length)
-{
- static u8_t position_state[POSITION_STATE_DATA_LEN];
+static u8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
+ const void *data, u16_t length) {
+ static u8_t position_state[POSITION_STATE_DATA_LEN];
- u8_t changed_positions[POSITION_STATE_DATA_LEN];
+ u8_t changed_positions[POSITION_STATE_DATA_LEN];
- if (!data) {
- LOG_DBG("[UNSUBSCRIBED]");
- params->value_handle = 0U;
- return BT_GATT_ITER_STOP;
- }
+ if (!data) {
+ LOG_DBG("[UNSUBSCRIBED]");
+ params->value_handle = 0U;
+ return BT_GATT_ITER_STOP;
+ }
- LOG_DBG("[NOTIFICATION] data %p length %u", data, length);
+ LOG_DBG("[NOTIFICATION] data %p length %u", data, length);
- for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
- changed_positions[i] = ((u8_t *)data)[i] ^ position_state[i];
- position_state[i] = ((u8_t *)data)[i];
- }
+ for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
+ changed_positions[i] = ((u8_t *)data)[i] ^ position_state[i];
+ position_state[i] = ((u8_t *)data)[i];
+ }
- for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
- for (int j = 0; j < 8; j++) {
- if (changed_positions[i] & BIT(j)) {
- u32_t position = (i * 8) + j;
- bool pressed = position_state[i] & BIT(j);
- struct position_state_changed *pos_ev = new_position_state_changed();
- pos_ev->position = position;
- pos_ev->state = pressed;
+ for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
+ for (int j = 0; j < 8; j++) {
+ if (changed_positions[i] & BIT(j)) {
+ u32_t position = (i * 8) + j;
+ bool pressed = position_state[i] & BIT(j);
+ struct position_state_changed *pos_ev = new_position_state_changed();
+ pos_ev->position = position;
+ pos_ev->state = pressed;
- LOG_DBG("Trigger key position state change for %d", position);
- ZMK_EVENT_RAISE(pos_ev);
- }
- }
- }
+ LOG_DBG("Trigger key position state change for %d", position);
+ ZMK_EVENT_RAISE(pos_ev);
+ }
+ }
+ }
+
+ return BT_GATT_ITER_CONTINUE;
+}
+static int split_central_subscribe(struct bt_conn *conn) {
+ int err = bt_gatt_subscribe(conn, &subscribe_params);
+ switch (err) {
+ case -EALREADY:
+ LOG_DBG("[ALREADY SUBSCRIBED]");
+ break;
+ // break;
+ // bt_gatt_unsubscribe(conn, &subscribe_params);
+ // return split_central_subscribe(conn);
+ case 0:
+ LOG_DBG("[SUBSCRIBED]");
+ break;
+ default:
+ LOG_ERR("Subscribe failed (err %d)", err);
+ break;
+ }
- return BT_GATT_ITER_CONTINUE;
+ return 0;
}
-static u8_t split_central_discovery_func(struct bt_conn *conn,
- const struct bt_gatt_attr *attr,
- struct bt_gatt_discover_params *params)
-{
- int err;
-
- if (!attr) {
- LOG_DBG("Discover complete");
- (void)memset(params, 0, sizeof(*params));
- return BT_GATT_ITER_STOP;
- }
-
- LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
-
- if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
- memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid));
- discover_params.uuid = &uuid.uuid;
- discover_params.start_handle = attr->handle + 1;
- discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
-
- err = bt_gatt_discover(conn, &discover_params);
- if (err) {
- LOG_ERR("Discover failed (err %d)", err);
- }
- } else if (!bt_uuid_cmp(discover_params.uuid,
- BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
- memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
- discover_params.uuid = &uuid.uuid;
- discover_params.start_handle = attr->handle + 2;
- discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
- subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
-
- err = bt_gatt_discover(conn, &discover_params);
- if (err) {
- LOG_ERR("Discover failed (err %d)", err);
- }
- } else {
- subscribe_params.notify = split_central_notify_func;
- subscribe_params.value = BT_GATT_CCC_NOTIFY;
- subscribe_params.ccc_handle = attr->handle;
-
- err = bt_gatt_subscribe(conn, &subscribe_params);
- if (err && err != -EALREADY) {
- LOG_ERR("Subscribe failed (err %d)", err);
- } else {
- LOG_DBG("[SUBSCRIBED]");
- }
-
- return BT_GATT_ITER_STOP;
- }
-
- return BT_GATT_ITER_STOP;
+static u8_t split_central_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ struct bt_gatt_discover_params *params) {
+ int err;
+
+ if (!attr) {
+ LOG_DBG("Discover complete");
+ (void)memset(params, 0, sizeof(*params));
+ return BT_GATT_ITER_STOP;
+ }
+
+ LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
+
+ if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
+ memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid));
+ discover_params.uuid = &uuid.uuid;
+ discover_params.start_handle = attr->handle + 1;
+ discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
+
+ err = bt_gatt_discover(conn, &discover_params);
+ if (err) {
+ LOG_ERR("Discover failed (err %d)", err);
+ }
+ } else if (!bt_uuid_cmp(discover_params.uuid,
+ BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
+ memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
+ discover_params.uuid = &uuid.uuid;
+ discover_params.start_handle = attr->handle + 2;
+ discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
+ subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
+
+ err = bt_gatt_discover(conn, &discover_params);
+ if (err) {
+ LOG_ERR("Discover failed (err %d)", err);
+ }
+ } else {
+ subscribe_params.notify = split_central_notify_func;
+ subscribe_params.value = BT_GATT_CCC_NOTIFY;
+ subscribe_params.ccc_handle = attr->handle;
+
+ split_central_subscribe(conn);
+
+ return BT_GATT_ITER_STOP;
+ }
+
+ return BT_GATT_ITER_STOP;
}
static void split_central_process_connection(struct bt_conn *conn) {
- int err;
-
- LOG_DBG("Current security for connection: %d", bt_conn_get_security(conn));
-
- err = bt_conn_set_security(conn, BT_SECURITY_L2);
- if (err) {
- LOG_ERR("Failed to set security (reason %d)", err);
- return;
- }
-
- if (conn == default_conn) {
- discover_params.uuid = &uuid.uuid;
- discover_params.func = split_central_discovery_func;
- discover_params.start_handle = 0x0001;
- discover_params.end_handle = 0xffff;
- discover_params.type = BT_GATT_DISCOVER_PRIMARY;
-
- err = bt_gatt_discover(default_conn, &discover_params);
- if (err) {
- LOG_ERR("Discover failed(err %d)", err);
- return;
- }
- }
-
- struct bt_conn_info info;
-
- bt_conn_get_info(conn, &info);
-
- LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval, info.le.latency, info.le.phy->rx_phy);
+ int err;
+
+ LOG_DBG("Current security for connection: %d", bt_conn_get_security(conn));
+
+ err = bt_conn_set_security(conn, BT_SECURITY_L2);
+ if (err) {
+ LOG_ERR("Failed to set security (reason %d)", err);
+ return;
+ }
+
+ if (conn == default_conn && !subscribe_params.value) {
+ discover_params.uuid = &uuid.uuid;
+ discover_params.func = split_central_discovery_func;
+ discover_params.start_handle = 0x0001;
+ discover_params.end_handle = 0xffff;
+ discover_params.type = BT_GATT_DISCOVER_PRIMARY;
+
+ err = bt_gatt_discover(default_conn, &discover_params);
+ if (err) {
+ LOG_ERR("Discover failed(err %d)", err);
+ return;
+ }
+ }
+
+ struct bt_conn_info info;
+
+ bt_conn_get_info(conn, &info);
+
+ LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval,
+ info.le.latency, info.le.phy->rx_phy);
}
-static bool split_central_eir_found(struct bt_data *data, void *user_data)
-{
- bt_addr_le_t *addr = user_data;
- int i;
+static bool split_central_eir_found(struct bt_data *data, void *user_data) {
+ bt_addr_le_t *addr = user_data;
+ int i;
- LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len);
+ LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len);
- switch (data->type) {
- case BT_DATA_UUID128_SOME:
- case BT_DATA_UUID128_ALL:
- if (data->data_len % 16 != 0U) {
- LOG_ERR("AD malformed");
- return true;
- }
+ switch (data->type) {
+ case BT_DATA_UUID128_SOME:
+ case BT_DATA_UUID128_ALL:
+ if (data->data_len % 16 != 0U) {
+ LOG_ERR("AD malformed");
+ return true;
+ }
- for (i = 0; i < data->data_len; i += 16) {
- struct bt_le_conn_param *param;
- struct bt_uuid uuid;
- int err;
+ for (i = 0; i < data->data_len; i += 16) {
+ struct bt_le_conn_param *param;
+ struct bt_uuid uuid;
+ int err;
if (!bt_uuid_create(&uuid, &data->data[i], 16)) {
LOG_ERR("Unable to load UUID");
continue;
}
- if (!bt_uuid_cmp(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
- char uuid_str[BT_UUID_STR_LEN];
- char service_uuid_str[BT_UUID_STR_LEN];
-
- bt_uuid_to_str(&uuid, uuid_str, sizeof(uuid_str));
- bt_uuid_to_str(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID), service_uuid_str, sizeof(service_uuid_str));
- LOG_DBG("UUID %s does not match split UUID: %s", log_strdup(uuid_str), log_strdup(service_uuid_str));
- continue;
- }
-
- LOG_DBG("Found the split service");
-
- err = bt_le_scan_stop();
- if (err) {
- LOG_ERR("Stop LE scan failed (err %d)", err);
- continue;
- }
-
- default_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
- if (default_conn) {
- LOG_DBG("Found existing connection");
- split_central_process_connection(default_conn);
- } else {
- param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400);
- err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
- param, &default_conn);
- if (err) {
- LOG_ERR("Create conn failed (err %d)", err);
- start_scan();
- }
-
- err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M);
- if (err) {
- LOG_ERR("Update phy conn failed (err %d)", err);
- start_scan();
- }
- }
-
- return false;
- }
- }
-
- return true;
+ if (!bt_uuid_cmp(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
+ char uuid_str[BT_UUID_STR_LEN];
+ char service_uuid_str[BT_UUID_STR_LEN];
+
+ bt_uuid_to_str(&uuid, uuid_str, sizeof(uuid_str));
+ bt_uuid_to_str(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID), service_uuid_str,
+ sizeof(service_uuid_str));
+ LOG_DBG("UUID %s does not match split UUID: %s", log_strdup(uuid_str),
+ log_strdup(service_uuid_str));
+ continue;
+ }
+
+ LOG_DBG("Found the split service");
+
+ zmk_ble_set_peripheral_addr(addr);
+
+ err = bt_le_scan_stop();
+ if (err) {
+ LOG_ERR("Stop LE scan failed (err %d)", err);
+ continue;
+ }
+
+ default_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
+ if (default_conn) {
+ LOG_DBG("Found existing connection");
+ split_central_process_connection(default_conn);
+ } else {
+ param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400);
+
+ err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn);
+ if (err) {
+ LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err,
+ BT_HCI_OP_LE_CREATE_CONN);
+ start_scan();
+ }
+
+ err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M);
+ if (err) {
+ LOG_ERR("Update phy conn failed (err %d)", err);
+ start_scan();
+ }
+ }
+
+ return false;
+ }
+ }
+
+ return true;
}
static void split_central_device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type,
- struct net_buf_simple *ad)
-{
- char dev[BT_ADDR_LE_STR_LEN];
-
- bt_addr_le_to_str(addr, dev, sizeof(dev));
- LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i",
- log_strdup(dev), type, ad->len, rssi);
-
- /* We're only interested in connectable events */
- if (type == BT_GAP_ADV_TYPE_ADV_IND ||
- type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
- bt_data_parse(ad, split_central_eir_found, (void *)addr);
- }
+ struct net_buf_simple *ad) {
+ char dev[BT_ADDR_LE_STR_LEN];
+
+ bt_addr_le_to_str(addr, dev, sizeof(dev));
+ LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i", log_strdup(dev), type, ad->len,
+ rssi);
+
+ /* We're only interested in connectable events */
+ if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
+ bt_data_parse(ad, split_central_eir_found, (void *)addr);
+ }
}
-static int start_scan(void)
-{
- int err;
+static int start_scan(void) {
+ int err;
- err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found);
- if (err) {
- LOG_ERR("Scanning failed to start (err %d)", err);
- return err;
- }
+ err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found);
+ if (err) {
+ LOG_ERR("Scanning failed to start (err %d)", err);
+ return err;
+ }
- LOG_DBG("Scanning successfully started");
+ LOG_DBG("Scanning successfully started");
return 0;
}
-static void split_central_connected(struct bt_conn *conn, u8_t conn_err)
-{
- char addr[BT_ADDR_LE_STR_LEN];
+static void split_central_connected(struct bt_conn *conn, u8_t conn_err) {
+ char addr[BT_ADDR_LE_STR_LEN];
- bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+ bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- if (conn_err) {
- LOG_ERR("Failed to connect to %s (%u)", addr, conn_err);
+ if (conn_err) {
+ LOG_ERR("Failed to connect to %s (%u)", log_strdup(addr), conn_err);
- bt_conn_unref(default_conn);
- default_conn = NULL;
+ bt_conn_unref(default_conn);
+ default_conn = NULL;
- start_scan();
- return;
- }
+ start_scan();
+ return;
+ }
- LOG_DBG("Connected: %s", log_strdup(addr));
+ LOG_DBG("Connected: %s", log_strdup(addr));
- split_central_process_connection(conn);
+ split_central_process_connection(conn);
}
-static void split_central_disconnected(struct bt_conn *conn, u8_t reason)
-{
- char addr[BT_ADDR_LE_STR_LEN];
+static void split_central_disconnected(struct bt_conn *conn, u8_t reason) {
+ char addr[BT_ADDR_LE_STR_LEN];
- bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+ bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- LOG_DBG("Disconnected: %s (reason %d)", log_strdup(addr), reason);
+ LOG_DBG("Disconnected: %s (reason %d)", log_strdup(addr), reason);
- if (default_conn != conn) {
- return;
- }
+ if (default_conn != conn) {
+ return;
+ }
- bt_conn_unref(default_conn);
- default_conn = NULL;
+ bt_conn_unref(default_conn);
+ default_conn = NULL;
- start_scan();
+ start_scan();
}
static struct bt_conn_cb conn_callbacks = {
- .connected = split_central_connected,
- .disconnected = split_central_disconnected,
+ .connected = split_central_connected,
+ .disconnected = split_central_disconnected,
};
-int zmk_split_bt_central_init(struct device *_arg)
-{
- bt_conn_cb_register(&conn_callbacks);
+int zmk_split_bt_central_init(struct device *_arg) {
+ bt_conn_cb_register(&conn_callbacks);
- return start_scan();
+ return start_scan();
}
-SYS_INIT(zmk_split_bt_central_init,
- APPLICATION,
- CONFIG_ZMK_BLE_INIT_PRIORITY); \ No newline at end of file
+SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); \ No newline at end of file
diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c
index e1d232a..86af685 100644
--- a/app/src/split/bluetooth/service.c
+++ b/app/src/split/bluetooth/service.c
@@ -1,6 +1,16 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <zephyr/types.h>
#include <sys/util.h>
+
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
#include <bluetooth/gatt.h>
#include <bluetooth/uuid.h>
@@ -11,40 +21,36 @@
static u8_t num_of_positions = ZMK_KEYMAP_LEN;
static u8_t position_state[16];
-static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, u16_t len, u16_t offset)
-{
- return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state, sizeof(position_state));
+static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
+ void *buf, u16_t len, u16_t offset) {
+ return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state,
+ sizeof(position_state));
}
-static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, u16_t len, u16_t offset)
-{
+static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
+ void *buf, u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(u8_t));
}
-static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, u16_t value)
-{
+static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, u16_t value) {
+ LOG_DBG("value %d", value);
}
+BT_GATT_SERVICE_DEFINE(
+ split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
+ BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID),
+ BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT,
+ split_svc_pos_state, NULL, &position_state),
+ BT_GATT_CCC(split_svc_pos_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
+ BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
+ &num_of_positions), );
-BT_GATT_SERVICE_DEFINE(split_svc,
- BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
- BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
- BT_GATT_PERM_READ_ENCRYPT,
- split_svc_pos_state, NULL, &position_state),
- BT_GATT_CCC(split_svc_pos_state_ccc,
- BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
- BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ,
- split_svc_num_of_positions, NULL, &num_of_positions),
-);
-
-int zmk_split_bt_position_pressed(u8_t position)
-{
+int zmk_split_bt_position_pressed(u8_t position) {
WRITE_BIT(position_state[position / 8], position % 8, true);
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
}
-int zmk_split_bt_position_released(u8_t position)
-{
+int zmk_split_bt_position_released(u8_t position) {
WRITE_BIT(position_state[position / 8], position % 8, false);
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
} \ No newline at end of file
diff --git a/app/src/split_listener.c b/app/src/split_listener.c
index 65f835a..b2adfb2 100644
--- a/app/src/split_listener.c
+++ b/app/src/split_listener.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -19,17 +19,17 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h>
#include <zmk/endpoints.h>
-int split_listener(const struct zmk_event_header *eh)
-{
- if (is_position_state_changed(eh)) {
- const struct position_state_changed *ev = cast_position_state_changed(eh);
- if (ev->state) {
- zmk_split_bt_position_pressed(ev->position);
- } else {
- zmk_split_bt_position_released(ev->position);
+int split_listener(const struct zmk_event_header *eh) {
+ LOG_DBG("");
+ if (is_position_state_changed(eh)) {
+ const struct position_state_changed *ev = cast_position_state_changed(eh);
+ if (ev->state) {
+ return zmk_split_bt_position_pressed(ev->position);
+ } else {
+ return zmk_split_bt_position_released(ev->position);
+ }
}
- }
- return 0;
+ return 0;
}
ZMK_LISTENER(split_listener, split_listener);
diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c
index 784fc25..530ffea 100644
--- a/app/src/usb_hid.c
+++ b/app/src/usb_hid.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <device.h>
#include <init.h>
@@ -17,71 +22,56 @@ static struct device *hid_dev;
static K_SEM_DEFINE(hid_sem, 1, 1);
-static void in_ready_cb(void)
-{
- k_sem_give(&hid_sem);
-}
+static void in_ready_cb(void) { k_sem_give(&hid_sem); }
-static const struct hid_ops ops =
-{
- .int_in_ready = in_ready_cb,
+static const struct hid_ops ops = {
+ .int_in_ready = in_ready_cb,
};
-int zmk_usb_hid_send_report(const u8_t *report, size_t len)
-{
- switch(usb_status) {
- case USB_DC_SUSPEND:
- return usb_wakeup_request();
- case USB_DC_ERROR:
- case USB_DC_RESET:
- case USB_DC_DISCONNECTED:
- case USB_DC_UNKNOWN:
- return -ENODEV;
- default:
- k_sem_take(&hid_sem, K_MSEC(30));
- int err = hid_int_ep_write(hid_dev, report, len, NULL);
-
- if (err) {
- k_sem_give(&hid_sem);
- }
-
- return err;
- }
+int zmk_usb_hid_send_report(const u8_t *report, size_t len) {
+ switch (usb_status) {
+ case USB_DC_SUSPEND:
+ return usb_wakeup_request();
+ case USB_DC_ERROR:
+ case USB_DC_RESET:
+ case USB_DC_DISCONNECTED:
+ case USB_DC_UNKNOWN:
+ return -ENODEV;
+ default:
+ k_sem_take(&hid_sem, K_MSEC(30));
+ int err = hid_int_ep_write(hid_dev, report, len, NULL);
+
+ if (err) {
+ k_sem_give(&hid_sem);
+ }
+
+ return err;
+ }
}
-void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params)
-{
- usb_status = status;
-};
+void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; };
-static int zmk_usb_hid_init(struct device *_arg)
-{
- int usb_enable_ret;
+static int zmk_usb_hid_init(struct device *_arg) {
+ int usb_enable_ret;
- hid_dev = device_get_binding("HID_0");
- if (hid_dev == NULL)
- {
- LOG_ERR("Unable to locate HID device");
- return -EINVAL;
- }
+ hid_dev = device_get_binding("HID_0");
+ if (hid_dev == NULL) {
+ LOG_ERR("Unable to locate HID device");
+ return -EINVAL;
+ }
- usb_hid_register_device(hid_dev,
- zmk_hid_report_desc, sizeof(zmk_hid_report_desc),
- &ops);
+ usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops);
- usb_hid_init(hid_dev);
+ usb_hid_init(hid_dev);
- usb_enable_ret = usb_enable(usb_hid_status_cb);
+ usb_enable_ret = usb_enable(usb_hid_status_cb);
- if (usb_enable_ret != 0)
- {
- LOG_ERR("Unable to enable USB");
- return -EINVAL;
- }
+ if (usb_enable_ret != 0) {
+ LOG_ERR("Unable to enable USB");
+ return -EINVAL;
+ }
- return 0;
+ return 0;
}
-SYS_INIT(zmk_usb_hid_init,
- APPLICATION,
- CONFIG_ZMK_USB_INIT_PRIORITY);
+SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY);
diff --git a/app/tests/hold-tap/README.md b/app/tests/hold-tap/README.md
new file mode 100644
index 0000000..0630132
--- /dev/null
+++ b/app/tests/hold-tap/README.md
@@ -0,0 +1 @@
+Refer to the pdf/open document "zmk-modtap-proposal.{pdf,odt}" in this directory for a visual representation of the numbered tests for hold-tap.
diff --git a/app/tests/hold-tap/balanced/1-dn-up/events.patterns b/app/tests/hold-tap/balanced/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot
new file mode 100644
index 0000000..5f6a266
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap b/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns b/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..ddda1ae
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot
new file mode 100644
index 0000000..a435103
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..c0da94f
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..ce6e7b7
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..1ec384a
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
new file mode 100644
index 0000000..8a1980b
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +1,10 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..b89b21d
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..798e2ee
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 2)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..798e2ee
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 2)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_PRESS(1,0,10)
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
new file mode 100644
index 0000000..5c9f4e3
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/behavior_keymap.dtsi b/app/tests/hold-tap/balanced/behavior_keymap.dtsi
new file mode 100644
index 0000000..df56fb5
--- /dev/null
+++ b/app/tests/hold-tap/balanced/behavior_keymap.dtsi
@@ -0,0 +1,27 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ behaviors {
+ ht_bal: behavior_hold_tap_balanced {
+ compatible = "zmk,behavior-hold-tap";
+ label = "HOLD_TAP_BALANCED";
+ #binding-cells = <2>;
+ flavor = "balanced";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &ht_bal LSFT F &ht_bal LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns b/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot
new file mode 100644
index 0000000..cf787d8
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..03329d5
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
new file mode 100644
index 0000000..adf4fe2
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..69b64a9
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..b06a1d7
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..bf31955
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (hold-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
new file mode 100644
index 0000000..3ed7de0
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +1,10 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 1)
+kp_pressed: usage_page 0x07 keycode 0xe1
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 1)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 1)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 1)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_PRESS(1,0,10)
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
new file mode 100644
index 0000000..cac579d
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 1)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi b/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi
new file mode 100644
index 0000000..375ffd9
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi
@@ -0,0 +1,29 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+
+
+/ {
+ behaviors {
+ ht_hold: behavior_hold_hold_tap {
+ compatible = "zmk,behavior-hold-tap";
+ label = "hold_hold_tap";
+ #binding-cells = <2>;
+ flavor = "hold-preferred";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &ht_hold LSFT F &ht_hold LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns b/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot
new file mode 100644
index 0000000..2a250fb
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..4f1ee63
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +1,5 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
new file mode 100644
index 0000000..87d1406
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..7455d2a
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..3d7eaf1
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..059d99c
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
new file mode 100644
index 0000000..a8cf490
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +1,10 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..92a3569
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
new file mode 100644
index 0000000..92a3569
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
new file mode 100644
index 0000000..bc8aa8e
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_PRESS(1,0,10)
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
new file mode 100644
index 0000000..b106f13
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +1,7 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi b/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi
new file mode 100644
index 0000000..e514fa6
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi
@@ -0,0 +1,27 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ behaviors {
+ tp: behavior_tap_preferred {
+ compatible = "zmk,behavior-hold-tap";
+ label = "MOD_TAP";
+ #binding-cells = <2>;
+ flavor = "tap-preferred";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &tp LSFT F &tp LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/zmk-modtap-proposal.odg b/app/tests/hold-tap/zmk-modtap-proposal.odg
new file mode 100644
index 0000000..82f8436
--- /dev/null
+++ b/app/tests/hold-tap/zmk-modtap-proposal.odg
Binary files differ
diff --git a/app/tests/hold-tap/zmk-modtap-proposal.pdf b/app/tests/hold-tap/zmk-modtap-proposal.pdf
new file mode 100644
index 0000000..33048ca
--- /dev/null
+++ b/app/tests/hold-tap/zmk-modtap-proposal.pdf
Binary files differ
diff --git a/app/tests/keypress/behavior_keymap.dtsi b/app/tests/keypress/behavior_keymap.dtsi
new file mode 100644
index 0000000..34c445c
--- /dev/null
+++ b/app/tests/keypress/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &mo 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/keypress/cp-press-release/events.patterns b/app/tests/keypress/cp-press-release/events.patterns
new file mode 100644
index 0000000..833100f
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode_//p \ No newline at end of file
diff --git a/app/tests/keypress/cp-press-release/keycode_events.snapshot b/app/tests/keypress/cp-press-release/keycode_events.snapshot
new file mode 100644
index 0000000..f1ef0ed
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/keycode_events.snapshot
@@ -0,0 +1,2 @@
+pressed: usage_page 0x0c keycode 0xb5
+released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/keypress/cp-press-release/native_posix.keymap b/app/tests/keypress/cp-press-release/native_posix.keymap
new file mode 100644
index 0000000..0e86f93
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/native_posix.keymap
@@ -0,0 +1,5 @@
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/keypress/kp-press-release/events.patterns b/app/tests/keypress/kp-press-release/events.patterns
new file mode 100644
index 0000000..833100f
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode_//p \ No newline at end of file
diff --git a/app/tests/keypress/kp-press-release/keycode_events.snapshot b/app/tests/keypress/kp-press-release/keycode_events.snapshot
new file mode 100644
index 0000000..f1ef0ed
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/keycode_events.snapshot
@@ -0,0 +1,2 @@
+pressed: usage_page 0x0c keycode 0xb5
+released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/keypress/kp-press-release/native_posix.keymap b/app/tests/keypress/kp-press-release/native_posix.keymap
new file mode 100644
index 0000000..7f73690
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/momentary-layer/behavior_keymap.dtsi b/app/tests/momentary-layer/behavior_keymap.dtsi
new file mode 100644
index 0000000..34c445c
--- /dev/null
+++ b/app/tests/momentary-layer/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &mo 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/momentary-layer/early-key-release/events.patterns b/app/tests/momentary-layer/early-key-release/events.patterns
new file mode 100644
index 0000000..bd7b488
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p \ No newline at end of file
diff --git a/app/tests/momentary-layer/early-key-release/keycode_events.snapshot b/app/tests/momentary-layer/early-key-release/keycode_events.snapshot
new file mode 100644
index 0000000..474eef7
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/keycode_events.snapshot
@@ -0,0 +1,4 @@
+kp_pressed: usage_page 0x07 keycode 0x05
+mo_pressed: position 1 layer 1
+kp_released: usage_page 0x07 keycode 0x05
+mo_released: position 1 layer 1
diff --git a/app/tests/momentary-layer/early-key-release/native_posix.keymap b/app/tests/momentary-layer/early-key-release/native_posix.keymap
new file mode 100644
index 0000000..e7628c0
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/momentary-layer/normal/events.patterns b/app/tests/momentary-layer/normal/events.patterns
new file mode 100644
index 0000000..bd7b488
--- /dev/null
+++ b/app/tests/momentary-layer/normal/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p \ No newline at end of file
diff --git a/app/tests/momentary-layer/normal/keycode_events.snapshot b/app/tests/momentary-layer/normal/keycode_events.snapshot
new file mode 100644
index 0000000..9dc6101
--- /dev/null
+++ b/app/tests/momentary-layer/normal/keycode_events.snapshot
@@ -0,0 +1,4 @@
+mo_pressed: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
+mo_released: position 1 layer 1
diff --git a/app/tests/momentary-layer/normal/native_posix.keymap b/app/tests/momentary-layer/normal/native_posix.keymap
new file mode 100644
index 0000000..7f73690
--- /dev/null
+++ b/app/tests/momentary-layer/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/none/behavior_keymap.dtsi b/app/tests/none/behavior_keymap.dtsi
new file mode 100644
index 0000000..0a4f7cb
--- /dev/null
+++ b/app/tests/none/behavior_keymap.dtsi
@@ -0,0 +1,22 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &none &mo 1
+ &kp A &none>;
+ };
+
+ lower_layer {
+ bindings = <
+ &none &trans
+ &none &kp A>;
+ };
+ };
+};
diff --git a/app/tests/none/layered/events.patterns b/app/tests/none/layered/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/none/layered/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/none/layered/keycode_events.snapshot b/app/tests/none/layered/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/none/layered/keycode_events.snapshot
diff --git a/app/tests/none/layered/native_posix.keymap b/app/tests/none/layered/native_posix.keymap
new file mode 100644
index 0000000..59ea481
--- /dev/null
+++ b/app/tests/none/layered/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/none/normal/events.patterns b/app/tests/none/normal/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/none/normal/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/none/normal/keycode_events.snapshot b/app/tests/none/normal/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/none/normal/keycode_events.snapshot
diff --git a/app/tests/none/normal/native_posix.keymap b/app/tests/none/normal/native_posix.keymap
new file mode 100644
index 0000000..94d7539
--- /dev/null
+++ b/app/tests/none/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/toggle-layer/behavior_keymap.dtsi b/app/tests/toggle-layer/behavior_keymap.dtsi
new file mode 100644
index 0000000..d2b41a9
--- /dev/null
+++ b/app/tests/toggle-layer/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &tog 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/toggle-layer/early-key-release/events.patterns b/app/tests/toggle-layer/early-key-release/events.patterns
new file mode 100644
index 0000000..397fef4
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*tog_keymap_binding/tog/p \ No newline at end of file
diff --git a/app/tests/toggle-layer/early-key-release/keycode_events.snapshot b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot
new file mode 100644
index 0000000..3ac017c
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot
@@ -0,0 +1,6 @@
+kp_pressed: usage_page 0x07 keycode 0x05
+tog_pressed: position 1 layer 1
+kp_released: usage_page 0x07 keycode 0x05
+tog_released: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/toggle-layer/early-key-release/native_posix.keymap b/app/tests/toggle-layer/early-key-release/native_posix.keymap
new file mode 100644
index 0000000..6b2b8f2
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/native_posix.keymap
@@ -0,0 +1,9 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/toggle-layer/normal/events.patterns b/app/tests/toggle-layer/normal/events.patterns
new file mode 100644
index 0000000..397fef4
--- /dev/null
+++ b/app/tests/toggle-layer/normal/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*tog_keymap_binding/tog/p \ No newline at end of file
diff --git a/app/tests/toggle-layer/normal/keycode_events.snapshot b/app/tests/toggle-layer/normal/keycode_events.snapshot
new file mode 100644
index 0000000..42174cc
--- /dev/null
+++ b/app/tests/toggle-layer/normal/keycode_events.snapshot
@@ -0,0 +1,4 @@
+tog_pressed: position 1 layer 1
+tog_released: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/toggle-layer/normal/native_posix.keymap b/app/tests/toggle-layer/normal/native_posix.keymap
new file mode 100644
index 0000000..202c105
--- /dev/null
+++ b/app/tests/toggle-layer/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/transparent/behavior_keymap.dtsi b/app/tests/transparent/behavior_keymap.dtsi
new file mode 100644
index 0000000..d6c5e27
--- /dev/null
+++ b/app/tests/transparent/behavior_keymap.dtsi
@@ -0,0 +1,22 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &trans &mo 1
+ &kp A &none>;
+ };
+
+ lower_layer {
+ bindings = <
+ &trans &trans
+ &trans &kp A>;
+ };
+ };
+};
diff --git a/app/tests/transparent/layered/events.patterns b/app/tests/transparent/layered/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/transparent/layered/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/transparent/layered/keycode_events.snapshot b/app/tests/transparent/layered/keycode_events.snapshot
new file mode 100644
index 0000000..d0bd245
--- /dev/null
+++ b/app/tests/transparent/layered/keycode_events.snapshot
@@ -0,0 +1,2 @@
+kp_pressed: usage_page 0x07 keycode 0x04
+kp_released: usage_page 0x07 keycode 0x04
diff --git a/app/tests/transparent/layered/native_posix.keymap b/app/tests/transparent/layered/native_posix.keymap
new file mode 100644
index 0000000..59ea481
--- /dev/null
+++ b/app/tests/transparent/layered/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/transparent/normal/events.patterns b/app/tests/transparent/normal/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/transparent/normal/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/transparent/normal/keycode_events.snapshot b/app/tests/transparent/normal/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/transparent/normal/keycode_events.snapshot
diff --git a/app/tests/transparent/normal/native_posix.keymap b/app/tests/transparent/normal/native_posix.keymap
new file mode 100644
index 0000000..94d7539
--- /dev/null
+++ b/app/tests/transparent/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file