diff options
Diffstat (limited to 'app')
50 files changed, 755 insertions, 163 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 3e59d75..39509ed 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -31,6 +31,7 @@ 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_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.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) @@ -45,6 +46,7 @@ if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) 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_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c) target_sources(app PRIVATE src/keymap.c) endif() target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c) diff --git a/app/Kconfig b/app/Kconfig index edf5867..fca4912 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -95,6 +95,10 @@ config ZMK_IDLE_SLEEP_TIMEOUT endif +config ZMK_EXT_POWER + bool "Enable support to control external power output" + default y + config ZMK_DISPLAY bool "ZMK display support" default n diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts index 3ffb0ea..0538b1d 100644 --- a/app/boards/arm/nice_nano/nice_nano.dts +++ b/app/boards/arm/nice_nano/nice_nano.dts @@ -29,6 +29,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + }; }; &gpiote { diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.dts b/app/boards/arm/nrfmicro/nrfmicro_11.dts index 95bd8ad..87c650e 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_11.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_11.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts index 85693a8..ea15b81 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.dts b/app/boards/arm/nrfmicro/nrfmicro_13.dts index 95bd8ad..ef43946 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_13.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_13.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/pinmux.c b/app/boards/arm/nrfmicro/pinmux.c index 4e330b6..30117d0 100644 --- a/app/boards/arm/nrfmicro/pinmux.c +++ b/app/boards/arm/nrfmicro/pinmux.c @@ -14,25 +14,14 @@ static int pinmux_nrfmicro_init(struct device *port) { ARG_UNUSED(port); - struct device *p1 = device_get_binding("GPIO_1"); - #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 - -#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); #endif return 0; } diff --git a/app/boards/shields/lily58/lily58.keymap b/app/boards/shields/lily58/lily58.keymap index 997a124..d44b3fe 100644 --- a/app/boards/shields/lily58/lily58.keymap +++ b/app/boards/shields/lily58/lily58.keymap @@ -7,6 +7,7 @@ #include <behaviors.dtsi> #include <dt-bindings/zmk/keys.h> #include <dt-bindings/zmk/bt.h> +#include <dt-bindings/zmk/ext_power.h> / { keymap { @@ -38,11 +39,11 @@ // | | | | | | | | | | | _ | + | { | } | "|" | // | | | | | | | | | | 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 &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 &ext_power EP_ON &ext_power EP_OFF &ext_power EP_TOG &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>; diff --git a/app/boards/shields/tg4x/Kconfig.defconfig b/app/boards/shields/tg4x/Kconfig.defconfig new file mode 100644 index 0000000..ca9fa2c --- /dev/null +++ b/app/boards/shields/tg4x/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if SHIELD_TG4X + +config ZMK_KEYBOARD_NAME + default "TG4X" + +endif
\ No newline at end of file diff --git a/app/boards/shields/tg4x/Kconfig.shield b/app/boards/shields/tg4x/Kconfig.shield new file mode 100644 index 0000000..7e98b71 --- /dev/null +++ b/app/boards/shields/tg4x/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_TG4X + def_bool $(shields_list_contains,tg4x) diff --git a/app/boards/shields/tg4x/tg4x.keymap b/app/boards/shields/tg4x/tg4x.keymap new file mode 100644 index 0000000..bee5c87 --- /dev/null +++ b/app/boards/shields/tg4x/tg4x.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 LOWER 1 +#define RAISE 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 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 &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 SCLN &kp RET + &kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp QUOT + &kp LCTL &kp LALT &kp LGUI < 1 BKSP < 2 SPC &kp LARW &kp DARW &kp UARW &kp RARW + >; + }; + lower { + bindings = < + &kp GRAV &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 PRSC + &kp DEL &trans &kp VOLU &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans + &trans &trans &kp VOLD &trans &trans &trans &trans &trans &trans &bt BT_PRV &bt BT_NXT &bt BT_CLR + &bootloader &reset &trans &trans &trans &trans &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 + >; + }; + + raise { + 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 &kp PRSC + &kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH + &trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp TILD &kp HOME &kp PGUP &kp PGDN &kp END + &trans &trans &trans &trans &trans &trans &kp M_NEXT &kp M_VOLD &kp M_VOLU &kp M_PLAY + >; + }; + }; +};
\ No newline at end of file diff --git a/app/boards/shields/tg4x/tg4x.overlay b/app/boards/shields/tg4x/tg4x.overlay new file mode 100644 index 0000000..10ce524 --- /dev/null +++ b/app/boards/shields/tg4x/tg4x.overlay @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 The ZMK Contrbutors + * + * 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 = <8>; + 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(4,3) RC(4,5) + 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(5,3) RC(5,4) + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4) + RC(3,0) RC(3,1) RC(3,2) RC(3,4) RC(3,5) RC(7,1) RC(7,2) RC(7,3) RC(7,4) + >; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + diode-direction = "col2row"; + + col-gpios + = <&pro_micro_d 1 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> + , <&pro_micro_a 2 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 3 GPIO_ACTIVE_HIGH> + ; + + row-gpios + = <&pro_micro_a 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_a 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_a 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_a 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + + }; + +}; + diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index a0b22e4..ec4fb39 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -181,19 +181,18 @@ static int kscan_gpio_config_interrupts(struct device **devices, struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ kscan_gpio_read_##n(data->dev); \ } \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - (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); \ - kscan_gpio_disable_interrupts_##n(data->dev); \ - 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 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_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + (kscan_gpio_disable_interrupts_##n(data->dev);)) \ + 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}}; \ diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi index 202202b..36c918c 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -8,4 +8,5 @@ #include <behaviors/reset.dtsi> #include <behaviors/sensor_rotate_key_press.dtsi> #include <behaviors/rgb_underglow.dtsi> -#include <behaviors/bluetooth.dtsi>
\ No newline at end of file +#include <behaviors/bluetooth.dtsi> +#include <behaviors/ext_power.dtsi> diff --git a/app/dts/behaviors/ext_power.dtsi b/app/dts/behaviors/ext_power.dtsi new file mode 100644 index 0000000..92f0035 --- /dev/null +++ b/app/dts/behaviors/ext_power.dtsi @@ -0,0 +1,9 @@ +/ { + behaviors { + ext_power: behavior_ext_power { + compatible = "zmk,behavior-ext-power"; + label = "EXT_POWER_BEHAVIOR"; + #binding-cells = <1>; + }; + }; +}; diff --git a/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml b/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml new file mode 100644 index 0000000..d86c6f9 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml @@ -0,0 +1,10 @@ +# +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +description: External power control Behavior + +compatible: "zmk,behavior-ext-power" + +include: one_param.yaml diff --git a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml index bbf3537..6b33910 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020, Pete Johanson +# Copyright (c) 2020, The ZMK Contributors # SPDX-License-Identifier: MIT description: Sensor rotate key press/release behavior diff --git a/app/dts/bindings/zmk,ext-power-generic.yaml b/app/dts/bindings/zmk,ext-power-generic.yaml new file mode 100644 index 0000000..5a38a09 --- /dev/null +++ b/app/dts/bindings/zmk,ext-power-generic.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +description: | + Generic driver for controlling the external power output + by toggling the control-gpio pin status + (Only in supported hardware) + +compatible: "zmk,ext-power-generic" + +properties: + control-gpios: + type: phandle-array + required: true + label: + type: string + required: true + diff --git a/app/dts/bindings/zmk,keymap-sensors.yaml b/app/dts/bindings/zmk,keymap-sensors.yaml index c56361d..86ae5c2 100644 --- a/app/dts/bindings/zmk,keymap-sensors.yaml +++ b/app/dts/bindings/zmk,keymap-sensors.yaml @@ -1,3 +1,8 @@ +# +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT +# + description: | Allows defining the collection of sensors bound in the keymap layers diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 45b8bea..cf259b1 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -10,6 +10,7 @@ #include <stddef.h> #include <device.h> #include <zmk/keys.h> +#include <zmk/behavior.h> /** * @cond INTERNAL_HIDDEN @@ -19,10 +20,10 @@ * (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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event); +typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_binding *binding, + struct device *sensor); __subsystem struct behavior_driver_api { behavior_keymap_binding_callback_t binding_pressed; @@ -42,18 +43,19 @@ __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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event); -static inline int z_impl_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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api; if (api->binding_pressed == NULL) { return -ENOTSUP; } - return api->binding_pressed(dev, position, param1, param2); + return api->binding_pressed(binding, event); } /** @@ -64,18 +66,19 @@ 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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event); -static inline int z_impl_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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api; if (api->binding_released == NULL) { return -ENOTSUP; } - return api->binding_released(dev, position, param1, param2); + return api->binding_released(binding, event); } /** @@ -88,19 +91,20 @@ 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 zmk_behavior_binding *binding, + struct device *sensor); -static inline int z_impl_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 zmk_behavior_binding *binding, + struct device *sensor) { + struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api; if (api->sensor_binding_triggered == NULL) { return -ENOTSUP; } - return api->sensor_binding_triggered(dev, sensor, param1, param2); + return api->sensor_binding_triggered(binding, sensor); } /** diff --git a/app/include/drivers/ext_power.h b/app/include/drivers/ext_power.h new file mode 100644 index 0000000..6c1923e --- /dev/null +++ b/app/include/drivers/ext_power.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include <zephyr/types.h> +#include <stddef.h> +#include <device.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @cond INTERNAL_HIDDEN + * + * Behavior driver API definition and system call entry points. + * + * (Internal use only.) + */ + +typedef int (*ext_power_enable_t)(struct device *dev); +typedef int (*ext_power_disable_t)(struct device *dev); +typedef int (*ext_power_get_t)(struct device *dev); + +__subsystem struct ext_power_api { + ext_power_enable_t enable; + ext_power_disable_t disable; + ext_power_get_t get; +}; +/** + * @endcond + */ + +/** + * @brief Enable the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_enable(struct device *dev); + +static inline int z_impl_ext_power_enable(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->enable == NULL) { + return -ENOTSUP; + } + + return api->enable(dev); +} + +/** + * @brief Disable the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_disable(struct device *dev); + +static inline int z_impl_ext_power_disable(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->disable == NULL) { + return -ENOTSUP; + } + + return api->disable(dev); +} + +/** + * @brief Get the current status of the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If ext power is disabled. + * @retval 1 if ext power is enabled. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_get(struct device *dev); + +static inline int z_impl_ext_power_get(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->get == NULL) { + return -ENOTSUP; + } + + return api->get(dev); +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#include <syscalls/ext_power.h> diff --git a/app/include/dt-bindings/zmk/bt.h b/app/include/dt-bindings/zmk/bt.h index a403d35..8ca1060 100644 --- a/app/include/dt-bindings/zmk/bt.h +++ b/app/include/dt-bindings/zmk/bt.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/dt-bindings/zmk/ext_power.h b/app/include/dt-bindings/zmk/ext_power.h new file mode 100644 index 0000000..2a3e846 --- /dev/null +++ b/app/include/dt-bindings/zmk/ext_power.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define EXT_POWER_OFF_CMD 0 +#define EXT_POWER_ON_CMD 1 +#define EXT_POWER_TOGGLE_CMD 2 + +#define EP_ON EXT_POWER_ON_CMD +#define EP_OFF EXT_POWER_OFF_CMD +#define EP_TOG EXT_POWER_TOGGLE_CMD diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h index 6f5815f..428ae24 100644 --- a/app/include/zmk/behavior.h +++ b/app/include/zmk/behavior.h @@ -10,4 +10,10 @@ struct zmk_behavior_binding { char *behavior_dev; u32_t param1; u32_t param2; +}; + +struct zmk_behavior_binding_event { + int layer; + u32_t position; + s64_t timestamp; };
\ No newline at end of file diff --git a/app/include/zmk/ble/profile.h b/app/include/zmk/ble/profile.h index 9a79c6d..1df2743 100644 --- a/app/include/zmk/ble/profile.h +++ b/app/include/zmk/ble/profile.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/ble-active-profile-changed.h b/app/include/zmk/events/ble-active-profile-changed.h index 66f40c7..1e3a198 100644 --- a/app/include/zmk/events/ble-active-profile-changed.h +++ b/app/include/zmk/events/ble-active-profile-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/keycode-state-changed.h b/app/include/zmk/events/keycode-state-changed.h index 4c00654..1e2c24e 100644 --- a/app/include/zmk/events/keycode-state-changed.h +++ b/app/include/zmk/events/keycode-state-changed.h @@ -24,6 +24,5 @@ inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_pag ev->usage_page = usage_page; ev->keycode = keycode; ev->state = state; - return ev; }
\ No newline at end of file diff --git a/app/include/zmk/events/position-state-changed.h b/app/include/zmk/events/position-state-changed.h index f88080d..e4cbbbe 100644 --- a/app/include/zmk/events/position-state-changed.h +++ b/app/include/zmk/events/position-state-changed.h @@ -13,6 +13,7 @@ struct position_state_changed { struct zmk_event_header header; u32_t position; bool state; + s64_t timestamp; }; ZMK_EVENT_DECLARE(position_state_changed);
\ No newline at end of file diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 6192587..b8f4969 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -11,4 +11,4 @@ int zmk_keymap_layer_activate(u8_t layer); int zmk_keymap_layer_deactivate(u8_t layer); int zmk_keymap_layer_toggle(u8_t layer); -int zmk_keymap_position_state_changed(u32_t position, bool pressed); +int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp); diff --git a/app/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c index 09fadba..066c437 100644 --- a/app/src/behaviors/behavior_bt.c +++ b/app/src/behaviors/behavior_bt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com> + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ @@ -8,18 +8,18 @@ #include <device.h> #include <drivers/behavior.h> - #include <dt-bindings/zmk/bt.h> - #include <bluetooth/conn.h> - #include <logging/log.h> +#include <zmk/behavior.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) { +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + switch (binding->param1) { case BT_CLR_CMD: return zmk_ble_clear_bonds(); case BT_NXT_CMD: @@ -27,9 +27,9 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c case BT_PRV_CMD: return zmk_ble_prof_prev(); case BT_SEL_CMD: - return zmk_ble_prof_select(arg); + return zmk_ble_prof_select(binding->param2); default: - LOG_ERR("Unknown BT command: %d", command); + LOG_ERR("Unknown BT command: %d", binding->param1); } return -ENOTSUP; @@ -37,8 +37,8 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c 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) { +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { return 0; } diff --git a/app/src/behaviors/behavior_ext_power.c b/app/src/behaviors/behavior_ext_power.c new file mode 100644 index 0000000..825f983 --- /dev/null +++ b/app/src/behaviors/behavior_ext_power.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_ext_power + +#include <device.h> +#include <devicetree.h> +#include <drivers/behavior.h> +#include <drivers/ext_power.h> + +#include <dt-bindings/zmk/ext_power.h> + +#include <logging/log.h> +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *ext_power = device_get_binding("EXT_POWER"); + if (ext_power == NULL) { + LOG_ERR("Unable to retrieve ext_power device: %d", binding->param1); + return -EIO; + } + + switch (binding->param1) { + case EXT_POWER_OFF_CMD: + return ext_power_disable(ext_power); + case EXT_POWER_ON_CMD: + return ext_power_enable(ext_power); + case EXT_POWER_TOGGLE_CMD: + if (ext_power_get(ext_power) > 0) + return ext_power_disable(ext_power); + else + return ext_power_enable(ext_power); + default: + LOG_ERR("Unknown ext_power command: %d", binding->param1); + } + + return -ENOTSUP; +} + +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + return 0; +} + +static int behavior_ext_power_init(struct device *dev) { return 0; }; + +static const struct behavior_driver_api behavior_ext_power_driver_api = { + .binding_pressed = on_keymap_binding_pressed, + .binding_released = on_keymap_binding_released, +}; + +DEVICE_AND_API_INIT(behavior_ext_power, DT_INST_LABEL(0), behavior_ext_power_init, NULL, NULL, + APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, &behavior_ext_power_driver_api); diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index 8f307a6..8b3620e 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -10,7 +10,6 @@ #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> @@ -18,6 +17,7 @@ #include <zmk/events/keycode-state-changed.h> #include <zmk/events/modifiers-state-changed.h> #include <zmk/hid.h> +#include <zmk/behavior.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -40,10 +40,8 @@ struct behavior_hold_tap_behaviors { struct zmk_behavior_binding hold; }; -typedef k_timeout_t (*timer_func)(); - struct behavior_hold_tap_config { - timer_func tapping_term_ms; + int tapping_term_ms; struct behavior_hold_tap_behaviors *behaviors; enum flavor flavor; }; @@ -51,8 +49,10 @@ struct behavior_hold_tap_config { // this data is specific for each hold-tap struct active_hold_tap { s32_t position; + // todo: move these params into the config->behaviors->tap and u32_t param_hold; u32_t param_tap; + s64_t timestamp; bool is_decided; bool is_hold; const struct behavior_hold_tap_config *config; @@ -164,6 +164,7 @@ static struct active_hold_tap *find_hold_tap(u32_t position) { } static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap, + s64_t timestamp, 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) { @@ -175,6 +176,7 @@ static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, active_hold_taps[i].config = config; active_hold_taps[i].param_hold = param_hold; active_hold_taps[i].param_tap = param_tap; + active_hold_taps[i].timestamp = timestamp; return &active_hold_taps[i]; } return NULL; @@ -253,7 +255,7 @@ static inline char *flavor_str(enum flavor flavor) { return "UNKNOWN FLAVOR"; } -static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) { +static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event_type) { if (hold_tap->is_decided) { return; } @@ -265,11 +267,11 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome switch (hold_tap->config->flavor) { case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED: - decide_hold_preferred(hold_tap, event); + decide_hold_preferred(hold_tap, event_type); case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED: - decide_balanced(hold_tap, event); + decide_balanced(hold_tap, event_type); case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED: - decide_tap_preferred(hold_tap, event); + decide_tap_preferred(hold_tap, event_type); } if (!hold_tap->is_decided) { @@ -277,26 +279,31 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome } LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap", - flavor_str(hold_tap->config->flavor), event); + flavor_str(hold_tap->config->flavor), event_type); undecided_hold_tap = NULL; - struct zmk_behavior_binding *behavior; + struct zmk_behavior_binding_event event = { + .position = hold_tap->position, + .timestamp = hold_tap->timestamp, + }; + + struct zmk_behavior_binding binding; 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); + binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev; + binding.param1 = hold_tap->param_hold; + binding.param2 = 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); + binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev; + binding.param1 = hold_tap->param_tap; + binding.param2 = 0; } + behavior_keymap_binding_pressed(&binding, event); release_captured_events(); } -static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold, - u32_t param_tap) { +static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_hold_tap_config *cfg = dev->config_info; if (undecided_hold_tap != NULL) { @@ -305,54 +312,69 @@ static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t return 0; } - struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg); + struct active_hold_tap *hold_tap = + store_hold_tap(event.position, binding->param1, binding->param2, event.timestamp, 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); + LOG_DBG("%d new undecided hold_tap", event.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. + // if this behavior was queued we have to adjust the timer to only + // wait for the remaining time. + s32_t tapping_term_ms_left = (hold_tap->timestamp + cfg->tapping_term_ms) - k_uptime_get(); + if (tapping_term_ms_left > 0) { + k_delayed_work_submit(&hold_tap->work, K_MSEC(tapping_term_ms_left)); + } 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); - +static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct active_hold_tap *hold_tap = find_hold_tap(event.position); if (hold_tap == NULL) { LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY"); return 0; } + // If these events were queued, the timer event may be queued too late or not at all. + // We insert a timer event before the TH_KEY_UP event to verify. int work_cancel_result = k_delayed_work_cancel(&hold_tap->work); + if (event.timestamp > (hold_tap->timestamp + hold_tap->config->tapping_term_ms)) { + decide_hold_tap(hold_tap, HT_TIMER_EVENT); + } + decide_hold_tap(hold_tap, HT_KEY_UP); - struct zmk_behavior_binding *behavior; + // todo: set up the binding and data items inside of the active_hold_tap struct + struct zmk_behavior_binding_event sub_behavior_data = { + .position = hold_tap->position, + .timestamp = hold_tap->timestamp, + }; + + struct zmk_behavior_binding sub_behavior_binding; 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); + sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev; + sub_behavior_binding.param1 = hold_tap->param_hold; + sub_behavior_binding.param2 = 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); + sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev; + sub_behavior_binding.param1 = hold_tap->param_tap; + sub_behavior_binding.param2 = 0; } + behavior_keymap_binding_released(&sub_behavior_binding, sub_behavior_data); 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); + LOG_DBG("%d hold-tap timer work in event queue", event.position); hold_tap->work_is_cancelled = true; } else { - LOG_DBG("%d cleaning up hold-tap", position); + LOG_DBG("%d cleaning up hold-tap", event.position); clear_hold_tap(hold_tap); } @@ -382,6 +404,14 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) { } } + // If these events were queued, the timer event may be queued too late or not at all. + // We make a timer decision before the other key events are handled if the timer would + // have run out. + if (ev->timestamp > + (undecided_hold_tap->timestamp + undecided_hold_tap->config->tapping_term_ms)) { + decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT); + } + 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 @@ -463,6 +493,7 @@ static int behavior_hold_tap_init(struct device *dev) { struct behavior_hold_tap_data {}; static struct behavior_hold_tap_data behavior_hold_tap_data; +/* todo: get rid of unused param1 and param2. */ #define _TRANSFORM_ENTRY(idx, node) \ { \ .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ @@ -473,14 +504,11 @@ static struct behavior_hold_tap_data behavior_hold_tap_data; }, #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, \ + .tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \ .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, \ diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c index bbfbe36..923b098 100644 --- a/app/src/behaviors/behavior_key_press.c +++ b/app/src/behaviors/behavior_key_press.c @@ -12,6 +12,7 @@ #include <zmk/event-manager.h> #include <zmk/events/keycode-state-changed.h> +#include <zmk/behavior.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -22,18 +23,24 @@ struct behavior_key_press_data {}; 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 _) { +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); 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); + LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page, + binding->param1); - return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true)); + return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, true)); } -static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _) { +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); 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); + LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page, + binding->param1); - return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false)); + return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, false)); } static const struct behavior_driver_api behavior_key_press_driver_api = { @@ -47,4 +54,4 @@ static const struct behavior_driver_api behavior_key_press_driver_api = { &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 +DT_INST_FOREACH_STATUS_OKAY(KP_INST) diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c index 80b7165..b1fb14b 100644 --- a/app/src/behaviors/behavior_momentary_layer.c +++ b/app/src/behaviors/behavior_momentary_layer.c @@ -11,6 +11,7 @@ #include <logging/log.h> #include <zmk/keymap.h> +#include <zmk/behavior.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -19,16 +20,16 @@ struct behavior_mo_data {}; 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); - - return zmk_keymap_layer_activate(layer); +static int mo_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + LOG_DBG("position %d layer %d", event.position, binding->param1); + return zmk_keymap_layer_activate(binding->param1); } -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); +static int mo_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + LOG_DBG("position %d layer %d", event.position, binding->param1); + return zmk_keymap_layer_deactivate(binding->param1); } static const struct behavior_driver_api behavior_mo_driver_api = { diff --git a/app/src/behaviors/behavior_none.c b/app/src/behaviors/behavior_none.c index b548e6f..96ea9d5 100644 --- a/app/src/behaviors/behavior_none.c +++ b/app/src/behaviors/behavior_none.c @@ -11,6 +11,8 @@ #include <drivers/behavior.h> #include <logging/log.h> +#include <zmk/behavior.h> + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct behavior_none_config {}; @@ -18,13 +20,13 @@ struct behavior_none_data {}; 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) { +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { return 0; } -static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { return 0; } diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c index 90de20b..d1233a5 100644 --- a/app/src/behaviors/behavior_reset.c +++ b/app/src/behaviors/behavior_reset.c @@ -11,6 +11,8 @@ #include <drivers/behavior.h> #include <logging/log.h> +#include <zmk/behavior.h> + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct behavior_reset_config { @@ -19,8 +21,9 @@ struct behavior_reset_config { 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) { +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_reset_config *cfg = dev->config_info; // TODO: Correct magic code for going into DFU? diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c index 621eab5..2ee6716 100644 --- a/app/src/behaviors/behavior_rgb_underglow.c +++ b/app/src/behaviors/behavior_rgb_underglow.c @@ -12,13 +12,15 @@ #include <dt-bindings/zmk/rgb.h> #include <zmk/rgb_underglow.h> +#include <zmk/keymap.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); 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 zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + switch (binding->param1) { case RGB_TOG: return zmk_rgb_underglow_toggle(); case RGB_HUI: diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c index 1a0bf03..71c4376 100644 --- a/app/src/behaviors/behavior_sensor_rotate_key_press.c +++ b/app/src/behaviors/behavior_sensor_rotate_key_press.c @@ -23,15 +23,16 @@ 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) { +static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding, + struct device *sensor) { + struct device *dev = device_get_binding(binding->behavior_dev); 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); + binding->param1, binding->param2); err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value); @@ -42,10 +43,10 @@ static int on_sensor_binding_triggered(struct device *dev, struct device *sensor switch (value.val1) { case 1: - keycode = increment_keycode; + keycode = binding->param1; break; case -1: - keycode = decrement_keycode; + keycode = binding->param2; break; default: return -ENOTSUP; diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c index 2819451..b3c6961 100644 --- a/app/src/behaviors/behavior_toggle_layer.c +++ b/app/src/behaviors/behavior_toggle_layer.c @@ -11,6 +11,7 @@ #include <logging/log.h> #include <zmk/keymap.h> +#include <zmk/behavior.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -19,15 +20,15 @@ struct behavior_tog_data {}; 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); - - return zmk_keymap_layer_toggle(layer); +static int tog_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + LOG_DBG("position %d layer %d", event.position, binding->param1); + return zmk_keymap_layer_toggle(binding->param1); } -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); - +static int tog_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + LOG_DBG("position %d layer %d", event.position, binding->param1); return 0; } diff --git a/app/src/behaviors/behavior_transparent.c b/app/src/behaviors/behavior_transparent.c index f7852f3..cede369 100644 --- a/app/src/behaviors/behavior_transparent.c +++ b/app/src/behaviors/behavior_transparent.c @@ -11,6 +11,8 @@ #include <drivers/behavior.h> #include <logging/log.h> +#include <zmk/behavior.h> + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct behavior_transparent_config {}; @@ -18,13 +20,13 @@ struct behavior_transparent_data {}; 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) { +static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { return 1; } -static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { return 1; } diff --git a/app/src/events/ble_active_profile_changed.c b/app/src/events/ble_active_profile_changed.c index a270a14..06988e2 100644 --- a/app/src/events/ble_active_profile_changed.c +++ b/app/src/events/ble_active_profile_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/ext_power_generic.c b/app/src/ext_power_generic.c new file mode 100644 index 0000000..4817030 --- /dev/null +++ b/app/src/ext_power_generic.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_ext_power_generic + +#include <device.h> +#include <init.h> +#include <drivers/gpio.h> +#include <drivers/ext_power.h> + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +#include <logging/log.h> +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +struct ext_power_generic_config { + const char *label; + const u8_t pin; + const u8_t flags; +}; + +struct ext_power_generic_data { + struct device *gpio; + bool status; +}; + +static int ext_power_generic_enable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 1)) { + LOG_WRN("Failed to set ext-power control pin"); + return -EIO; + } + data->status = true; + return 0; +} + +static int ext_power_generic_disable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 0)) { + LOG_WRN("Failed to clear ext-power control pin"); + return -EIO; + } + data->status = false; + return 0; +} + +static int ext_power_generic_get(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + return data->status; +} + +static int ext_power_generic_init(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + data->gpio = device_get_binding(config->label); + if (data->gpio == NULL) { + LOG_ERR("Failed to get ext-power control device"); + return -EINVAL; + } + + if (gpio_pin_configure(data->gpio, config->pin, config->flags | GPIO_OUTPUT)) { + LOG_ERR("Failed to configure ext-power control pin"); + return -EIO; + } + + return 0; +} + +static const struct ext_power_generic_config config = { + .label = DT_INST_GPIO_LABEL(0, control_gpios), + .pin = DT_INST_GPIO_PIN(0, control_gpios), + .flags = DT_INST_GPIO_FLAGS(0, control_gpios)}; + +static struct ext_power_generic_data data = {.status = false}; + +static const struct ext_power_api api = {.enable = ext_power_generic_enable, + .disable = ext_power_generic_disable, + .get = ext_power_generic_get}; + +DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config, + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &api); + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/hog.c b/app/src/hog.c index 11349ac..bcd652d 100644 --- a/app/src/hog.c +++ b/app/src/hog.c @@ -164,8 +164,10 @@ int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) { 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 err = + bt_gatt_notify(conn, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_keypad_report_body)); + bt_conn_unref(conn); + return err; }; int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) { @@ -174,6 +176,8 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) { return -ENOTCONN; } - return bt_gatt_notify(conn, &hog_svc.attrs[10], report, - sizeof(struct zmk_hid_consumer_report_body)); + int err = bt_gatt_notify(conn, &hog_svc.attrs[10], report, + sizeof(struct zmk_hid_consumer_report_body)); + bt_conn_unref(conn); + return err; }; diff --git a/app/src/keymap.c b/app/src/keymap.c index a87ce04..74fe60d 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -104,9 +104,14 @@ 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_apply_position_state(int layer, u32_t position, bool pressed) { +int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed, s64_t timestamp) { struct zmk_behavior_binding *binding = &zmk_keymap[layer][position]; struct device *behavior; + struct zmk_behavior_binding_event event = { + .layer = layer, + .position = position, + .timestamp = timestamp, + }; LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev)); @@ -119,20 +124,18 @@ int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) { } if (pressed) { - return behavior_keymap_binding_pressed(behavior, position, binding->param1, - binding->param2); + return behavior_keymap_binding_pressed(binding, event); } else { - return behavior_keymap_binding_released(behavior, position, binding->param1, - binding->param2); + return behavior_keymap_binding_released(binding, event); } } -int zmk_keymap_position_state_changed(u32_t position, bool pressed) { +int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp) { 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); + int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp); zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state; @@ -171,8 +174,7 @@ int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) { continue; } - ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1, - binding->param2); + ret = behavior_sensor_keymap_binding_triggered(binding, sensor); if (ret > 0) { LOG_DBG("behavior processing to continue to next layer"); @@ -194,7 +196,7 @@ int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) { 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); + return zmk_keymap_position_state_changed(ev->position, ev->state, ev->timestamp); #if ZMK_KEYMAP_HAS_SENSORS } else if (is_sensor_event(eh)) { const struct sensor_event *ev = cast_sensor_event(eh); diff --git a/app/src/kscan.c b/app/src/kscan.c index 0046f5c..8575e70 100644 --- a/app/src/kscan.c +++ b/app/src/kscan.c @@ -52,6 +52,7 @@ void zmk_kscan_process_msgq(struct k_work *item) { pos_ev = new_position_state_changed(); pos_ev->state = pressed; pos_ev->position = position; + pos_ev->timestamp = k_uptime_get(); ZMK_EVENT_RAISE(pos_ev); } } diff --git a/app/src/main.c b/app/src/main.c index dca923e..0551356 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -15,16 +15,25 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); #include <zmk/matrix.h> #include <zmk/kscan.h> #include <zmk/display.h> +#include <drivers/ext_power.h> #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID) void main(void) { + struct device *ext_power; LOG_INF("Welcome to ZMK!\n"); if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) { return; } + // Enable the external VCC output + ext_power = device_get_binding("EXT_POWER"); + if (ext_power != NULL) { + const struct ext_power_api *ext_power_api = ext_power->driver_api; + ext_power_api->enable(ext_power); + } + #ifdef CONFIG_ZMK_DISPLAY zmk_display_init(); diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index cb1b68b..ed52ba0 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -60,6 +60,7 @@ static u8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subsc struct position_state_changed *pos_ev = new_position_state_changed(); pos_ev->position = position; pos_ev->state = pressed; + pos_ev->timestamp = k_uptime_get(); LOG_DBG("Trigger key position state change for %d", position); ZMK_EVENT_RAISE(pos_ev); diff --git a/app/tests/hold-tap/balanced/many-nested/events.patterns b/app/tests/hold-tap/balanced/many-nested/events.patterns new file mode 100644 index 0000000..fdf2b15 --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/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/many-nested/keycode_events.snapshot b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot new file mode 100644 index 0000000..806896f --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot @@ -0,0 +1,20 @@ +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 hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe0 +ht_binding_pressed: 2 new undecided hold_tap +ht_binding_released: 0 cleaning up hold-tap +ht_decide: 2 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe3 +ht_binding_pressed: 3 new undecided hold_tap +ht_binding_released: 1 cleaning up hold-tap +ht_decide: 3 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe2 +kp_released: usage_page 0x07 keycode 0xe1 +kp_released: usage_page 0x07 keycode 0xe0 +kp_released: usage_page 0x07 keycode 0xe3 +ht_binding_released: 2 cleaning up hold-tap +kp_released: usage_page 0x07 keycode 0xe2 +ht_binding_released: 3 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/many-nested/native_posix.keymap b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap new file mode 100644 index 0000000..3cb04c3 --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap @@ -0,0 +1,41 @@ +#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 + &ht_bal LGUI H &ht_bal LALT L + >; + }; + }; +}; + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,100) + ZMK_MOCK_PRESS(0,1,100) + ZMK_MOCK_PRESS(1,0,100) + ZMK_MOCK_PRESS(1,1,100) + ZMK_MOCK_RELEASE(0,0,100) + ZMK_MOCK_RELEASE(0,1,100) + ZMK_MOCK_RELEASE(1,0,100) + ZMK_MOCK_RELEASE(1,1,100) + >; +}; |