Merge branch 'zmkfirmware:main' into main

This commit is contained in:
Timoyoungster 2024-06-26 20:15:28 +02:00 committed by GitHub
commit 8dcef74c39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
138 changed files with 1908 additions and 825 deletions

View file

@ -12,6 +12,12 @@ on:
schedule:
- cron: "22 4 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'schedule' }}
cancel-in-progress: true
permissions: {}
jobs:
build:
if: ${{ always() }}
@ -25,6 +31,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Cache west modules
uses: actions/cache@v4
env:
@ -131,7 +139,7 @@ jobs:
throw new Error('Failed to build one or more configurations');
}
compile-matrix:
if: ${{ always() }}
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
needs: [core-coverage, board-changes, nightly]
outputs:
@ -179,6 +187,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js
uses: actions/setup-node@v4
with:
@ -284,7 +294,7 @@ jobs:
});
}))).flat();
nightly:
if: ${{ github.event_name == 'schedule' }}
if: ${{ github.event_name == 'schedule' && github.repository_owner == 'zmkfirmware' }}
runs-on: ubuntu-latest
needs: get-grouped-hardware
outputs:
@ -335,6 +345,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js
uses: actions/setup-node@v4
with:
@ -413,7 +425,11 @@ jobs:
board-changes: ${{ steps.board-changes.outputs.result }}
core-changes: ${{ steps.core-changes.outputs.result }}
steps:
- uses: tj-actions/changed-files@v42
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- uses: tj-actions/changed-files@v44
id: changed-files
with:
json: true

View file

@ -113,6 +113,12 @@ config ZMK_HID_INDICATORS
Enable HID indicators, used for detecting state of Caps/Scroll/Num Lock,
Kata, and Compose.
config ZMK_HID_SEPARATE_MOD_RELEASE_REPORT
bool "Release Modifiers Separately"
help
Send a separate release event for the modifiers, to make sure the release
of the modifier doesn't get recognized before the actual key's release event.
menu "Output Types"
config ZMK_USB
@ -490,7 +496,11 @@ if USB_DEVICE_STACK
config ZMK_USB_INIT_PRIORITY
int "USB Init Priority"
default 50
default 94
config ZMK_USB_HID_INIT_PRIORITY
int "USB HID Init Priority"
default 95
#USB
endif

View file

@ -1,6 +1,12 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT
config ZMK_BEHAVIOR_METADATA
bool "Metadata"
help
Enabling this option adds APIs for documenting and fetching
metadata describing a behaviors name, and supported parameters.
config ZMK_BEHAVIOR_KEY_TOGGLE
bool
default y
@ -35,4 +41,4 @@ config ZMK_BEHAVIOR_SENSOR_ROTATE_VAR
config ZMK_BEHAVIOR_MACRO
bool
default y
depends on DT_HAS_ZMK_BEHAVIOR_MACRO_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_ONE_PARAM_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_TWO_PARAM_ENABLED
depends on DT_HAS_ZMK_BEHAVIOR_MACRO_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_ONE_PARAM_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_TWO_PARAM_ENABLED

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&xiao_serial { status = "disabled"; };

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&pro_micro_serial { status = "disabled"; };

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&xiao_serial { status = "disabled"; };

View file

@ -21,7 +21,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan0;
zmk,backlight = &backlight;
zmk,battery = &vbatt;
@ -90,11 +89,8 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -16,7 +16,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan;
zmk,underglow = &led_strip;
};
@ -106,13 +105,10 @@
apb1-prescaler = <1>;
};
&usb {
zephyr_udc0: &usb {
status = "okay";
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
pinctrl-names = "default";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&rtc {

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -82,11 +81,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -16,7 +16,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
@ -70,11 +69,8 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -142,7 +142,7 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
};

View file

@ -20,7 +20,6 @@
zephyr,flash = &flash0;
zmk,kscan = &kscan0;
zmk,display = &epd;
zephyr,console = &cdc_acm_uart;
zmk,matrix-transform = &default_transform;
};
@ -76,11 +75,8 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -16,7 +16,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
};
@ -65,11 +64,8 @@ RC(4,0) RC(4,1) RC(4,2) RC(4,5) RC(
};
&usb {
zephyr_udc0: &usb {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -17,7 +17,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan;
zmk,matrix-transform = &transform;
/* TODO: Enable once we support the IC for underglow
@ -110,14 +109,11 @@
};
};
&usb {
zephyr_udc0: &usb {
status = "okay";
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
pinctrl-names = "default";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&clk_hsi {

View file

@ -15,7 +15,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
};
default_transform: keymap_transform_0 {
@ -59,11 +58,8 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -13,8 +13,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zephyr,shell-uart = &cdc_acm_uart;
zephyr,code-partition = &code_partition;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
@ -108,11 +106,8 @@ RC(4,0) RC(4,1) RC(4,2) RC(4,6) RC(4,8) RC(4,9)
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -81,11 +80,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -20,7 +20,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
@ -129,11 +128,8 @@ RC(4,0) RC(4,1) RC(4,2) RC(4,5) R
};
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -16,7 +16,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
};
leds {
@ -65,11 +64,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -15,7 +15,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -57,12 +56,9 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
compatible = "nordic,nrf-usbd";
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
};
leds {
@ -69,11 +68,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
};
leds {
@ -69,11 +68,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -81,11 +80,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -81,11 +80,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -18,7 +18,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -83,11 +82,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -16,7 +16,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan0;
zmk,matrix-transform = &layout_grid_transform;
};
@ -96,13 +95,10 @@ layout_2x2u_transform:
};
};
&usb {
zephyr_udc0: &usb {
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
pinctrl-names = "default";
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&clk_hse {

View file

@ -17,7 +17,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan0;
zmk,matrix-transform = &layout_grid_transform;
};
@ -90,13 +89,10 @@
};
};
&usb {
zephyr_udc0: &usb {
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
pinctrl-names = "default";
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&clk_hse {

View file

@ -16,7 +16,6 @@
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart0;
};
aliases {
@ -66,13 +65,10 @@
apb2-prescaler = <1>;
};
&usb {
zephyr_udc0: &usb {
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
pinctrl-names = "default";
status = "okay";
cdc_acm_uart0: cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
};
};
&rtc {

View file

@ -17,7 +17,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -72,11 +71,8 @@
pinctrl-names = "default", "sleep";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -16,7 +16,6 @@
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
@ -93,11 +92,8 @@
status = "okay";
};
&usbd {
zephyr_udc0: &usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&flash0 {

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&pro_micro_serial { status = "disabled"; };

View file

@ -1,8 +0,0 @@
/*
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"

View file

@ -1,18 +0,0 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/ {
chosen {
zephyr,console = &cdc_acm_uart;
};
};
&usb0 {
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -7,7 +7,6 @@
/ {
chosen {
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
@ -24,12 +23,6 @@
status = "okay";
};
&usbd {
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&qspi {
status = "okay";
pinctrl-0 = <&qspi_default>;

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&xiao_serial { status = "disabled"; };

View file

@ -4,6 +4,4 @@
* SPDX-License-Identifier: MIT
*/
#include "usb_console.dtsi"
&pro_micro_serial { status = "disabled"; };

View file

@ -1,19 +0,0 @@
/*
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/ {
chosen {
zephyr,console = &cdc_acm_uart;
};
};
&usbd {
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -22,6 +22,9 @@ include:
shield: kyria_left
cmake-args: "-DCONFIG_ZMK_DISPLAY=y"
nickname: "display"
- board: sparkfun_pro_micro_rp2040
shield: reviung41
cmake-args: "-DSNIPPET='zmk-usb-logging'"
- board: nice_nano_v2
shield: kyria_right
cmake-args: "-DCONFIG_ZMK_DISPLAY=y"

View file

@ -10,6 +10,7 @@
/omit-if-no-ref/ bl: bcklight {
compatible = "zmk,behavior-backlight";
#binding-cells = <2>;
display-name = "Backlight";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ bt: bluetooth {
compatible = "zmk,behavior-bluetooth";
#binding-cells = <2>;
display-name = "Bluetooth";
};
};
};

View file

@ -12,6 +12,7 @@
compatible = "zmk,behavior-caps-word";
#binding-cells = <0>;
continue-list = <UNDERSCORE BACKSPACE DELETE>;
display-name = "Caps Word";
};
};
};

View file

@ -10,6 +10,7 @@
ext_power: extpower {
compatible = "zmk,behavior-ext-power";
#binding-cells = <1>;
display-name = "External Power";
};
};
};

View file

@ -13,6 +13,7 @@
#binding-cells = <0>;
bindings = <&kp ESC>, <&kp GRAVE>;
mods = <(MOD_LGUI|MOD_LSFT|MOD_RGUI|MOD_RSFT)>;
display-name = "Grave/Escape";
};
};
};

View file

@ -10,6 +10,7 @@
/omit-if-no-ref/ cp: kp: key_press {
compatible = "zmk,behavior-key-press";
#binding-cells = <1>;
display-name = "Key Press";
};
};
};

View file

@ -12,6 +12,7 @@
compatible = "zmk,behavior-key-repeat";
#binding-cells = <0>;
usage-pages = <HID_USAGE_KEY>;
display-name = "Key Repeat";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ kt: key_toggle {
compatible = "zmk,behavior-key-toggle";
#binding-cells = <1>;
display-name = "Key Toggle";
};
};
};

View file

@ -12,6 +12,7 @@
flavor = "tap-preferred";
tapping-term-ms = <200>;
bindings = <&mo>, <&kp>;
display-name = "Layer-Tap";
};
};
};

View file

@ -12,6 +12,7 @@
flavor = "hold-preferred";
tapping-term-ms = <200>;
bindings = <&kp>, <&kp>;
display-name = "Mod-Tap";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ mo: momentary_layer {
compatible = "zmk,behavior-momentary-layer";
#binding-cells = <1>;
display-name = "Momentary Layer";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ none: none {
compatible = "zmk,behavior-none";
#binding-cells = <0>;
display-name = "None";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ out: outputs {
compatible = "zmk,behavior-outputs";
#binding-cells = <1>;
display-name = "Output Selection";
};
};
};

View file

@ -12,6 +12,7 @@
sys_reset: sysreset {
compatible = "zmk,behavior-reset";
#binding-cells = <0>;
display-name = "Reset";
};
// Behavior can be invoked on peripherals, so name must be <= 8 characters.
@ -19,6 +20,7 @@
compatible = "zmk,behavior-reset";
type = <RST_UF2>;
#binding-cells = <0>;
display-name = "Bootloader";
};
};
};

View file

@ -10,6 +10,7 @@
rgb_ug: rgb_ug {
compatible = "zmk,behavior-rgb-underglow";
#binding-cells = <2>;
display-name = "Underglow";
};
};
};

View file

@ -12,6 +12,7 @@
release-after-ms = <1000>;
bindings = <&kp>;
ignore-modifiers;
display-name = "Sticky Key";
};
/omit-if-no-ref/ sl: sticky_layer {
compatible = "zmk,behavior-sticky-key";
@ -19,6 +20,7 @@
release-after-ms = <1000>;
bindings = <&mo>;
quick-release;
display-name = "Sticky Layer";
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ to: to_layer {
compatible = "zmk,behavior-to-layer";
#binding-cells = <1>;
display-name = "To Layer";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ tog: toggle_layer {
compatible = "zmk,behavior-toggle-layer";
#binding-cells = <1>;
display-name = "Toggle Layer";
};
};
};

View file

@ -9,6 +9,7 @@
/omit-if-no-ref/ trans: transparent {
compatible = "zmk,behavior-transparent";
#binding-cells = <0>;
display-name = "Transparent";
};
};
};

View file

@ -0,0 +1,6 @@
# Copyright (c) 2024 The ZMK Contributors
# SPDX-License-Identifier: MIT
properties:
display-name:
type: string

View file

@ -1,6 +1,8 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
include: behavior-metadata.yaml
properties:
label:
type: string

View file

@ -1,6 +1,8 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
include: behavior-metadata.yaml
properties:
label:
type: string

View file

@ -1,6 +1,8 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
include: behavior-metadata.yaml
properties:
label:
type: string

View file

@ -23,6 +23,39 @@
* (Internal use only.)
*/
struct behavior_parameter_value_metadata {
char *display_name;
union {
uint32_t value;
struct {
int32_t min;
int32_t max;
} range;
};
enum {
BEHAVIOR_PARAMETER_VALUE_TYPE_NIL = 0,
BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE = 1,
BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE = 2,
BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE = 3,
BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX = 4,
} type;
};
struct behavior_parameter_metadata_set {
size_t param1_values_len;
const struct behavior_parameter_value_metadata *param1_values;
size_t param2_values_len;
const struct behavior_parameter_value_metadata *param2_values;
};
struct behavior_parameter_metadata {
size_t sets_len;
const struct behavior_parameter_metadata_set *sets;
};
enum behavior_sensor_binding_process_mode {
BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER,
BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD,
@ -37,6 +70,10 @@ typedef int (*behavior_sensor_keymap_binding_accept_data_callback_t)(
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
const struct zmk_sensor_config *sensor_config, size_t channel_data_size,
const struct zmk_sensor_channel_data channel_data[channel_data_size]);
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
typedef int (*behavior_get_parameter_metadata_t)(
const struct device *behavior, struct behavior_parameter_metadata *param_metadata);
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
enum behavior_locality {
BEHAVIOR_LOCALITY_CENTRAL,
@ -51,23 +88,54 @@ __subsystem struct behavior_driver_api {
behavior_keymap_binding_callback_t binding_released;
behavior_sensor_keymap_binding_accept_data_callback_t sensor_binding_accept_data;
behavior_sensor_keymap_binding_process_callback_t sensor_binding_process;
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
behavior_get_parameter_metadata_t get_parameter_metadata;
const struct behavior_parameter_metadata *parameter_metadata;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
/**
* @endcond
*/
struct zmk_behavior_metadata {
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
const char *display_name;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
struct zmk_behavior_ref {
const struct device *device;
const struct zmk_behavior_metadata metadata;
};
#define ZMK_BEHAVIOR_REF_DT_NAME(node_id) _CONCAT(zmk_behavior_, DEVICE_DT_NAME_GET(node_id))
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
#define ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id) \
{ .display_name = DT_PROP_OR(node_id, display_name, DEVICE_DT_NAME(node_id)), }
#else
#define ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id) \
{}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
#define ZMK_BEHAVIOR_REF_INITIALIZER(node_id, _dev) \
{ .device = _dev, .metadata = ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id), }
#define ZMK_BEHAVIOR_REF_DEFINE(name, node_id, _dev) \
static const STRUCT_SECTION_ITERABLE(zmk_behavior_ref, name) = \
ZMK_BEHAVIOR_REF_INITIALIZER(node_id, _dev)
#define ZMK_BEHAVIOR_REF_DT_DEFINE(node_id) \
ZMK_BEHAVIOR_REF_DEFINE(ZMK_BEHAVIOR_REF_DT_NAME(node_id), node_id, DEVICE_DT_GET(node_id))
/**
* Registers @p node_id as a behavior.
*/
#define BEHAVIOR_DEFINE(node_id) \
static const STRUCT_SECTION_ITERABLE(zmk_behavior_ref, \
_CONCAT(zmk_behavior_, DEVICE_DT_NAME_GET(node_id))) = { \
.device = DEVICE_DT_GET(node_id), \
}
#define BEHAVIOR_DEFINE(node_id) ZMK_BEHAVIOR_REF_DT_DEFINE(node_id)
/**
* @brief Like DEVICE_DT_DEFINE(), but also registers the device as a behavior.
@ -89,6 +157,52 @@ struct zmk_behavior_ref {
DEVICE_DT_INST_DEFINE(inst, __VA_ARGS__); \
BEHAVIOR_DEFINE(DT_DRV_INST(inst))
/**
* @brief Validate a given behavior binding is valid, including parameter validation
* if the metadata feature is enablued.
*
* @param binding The behavior binding to validate.
*
* @retval 0 if the passed in binding is valid.
* @retval -ENODEV if the binding references a non-existant behavior.
* @retval -EINVAL if parameters are not valid for the behavior metadata.
*/
int zmk_behavior_validate_binding(const struct zmk_behavior_binding *binding);
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
int zmk_behavior_get_empty_param_metadata(const struct device *dev,
struct behavior_parameter_metadata *metadata);
/**
* @brief Validate a given behavior parameters match the behavior metadata.
*
* @param metadata The behavior metadata to validate against
* @param param1 The first parameter value
* @param param2 The second parameter value
*
* @retval 0 if the passed in parameters are valid.
* @retval -ENODEV if metadata is NULL.
* @retval -EINVAL if parameters are not valid for the metadata.
*/
int zmk_behavior_check_params_match_metadata(const struct behavior_parameter_metadata *metadata,
uint32_t param1, uint32_t param2);
/**
* @brief Validate a given behavior parameter matches the behavior metadata parameter values.
*
* @param values The values to validate against
* @param values_len How many values to check
* @param param The value to check.
*
* @retval 0 if the passed in parameter is valid.
* @retval -ENODEV if values is NULL.
* @retval -EINVAL if parameter is not valid for the value metadata.
*/
int zmk_behavior_validate_param_values(const struct behavior_parameter_value_metadata *values,
size_t values_len, uint32_t param);
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
/**
* Syscall wrapper for zmk_behavior_get_binding().
*
@ -120,6 +234,40 @@ static inline int z_impl_behavior_keymap_binding_convert_central_state_dependent
return api->binding_convert_central_state_dependent_params(binding, event);
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
/**
* @brief Determine where the behavior should be run
* @param behavior Pointer to the device structure for the driver instance.
*
* @retval Zero if successful.
* @retval Negative errno code if failure.
*/
__syscall int behavior_get_parameter_metadata(const struct device *behavior,
struct behavior_parameter_metadata *param_metadata);
static inline int
z_impl_behavior_get_parameter_metadata(const struct device *behavior,
struct behavior_parameter_metadata *param_metadata) {
if (behavior == NULL || param_metadata == NULL) {
return -EINVAL;
}
const struct behavior_driver_api *api = (const struct behavior_driver_api *)behavior->api;
if (api->get_parameter_metadata) {
return api->get_parameter_metadata(behavior, param_metadata);
} else if (api->parameter_metadata) {
*param_metadata = *api->parameter_metadata;
} else {
return -ENODEV;
}
return 0;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
/**
* @brief Determine where the behavior should be run
* @param behavior Pointer to the device structure for the driver instance.

View file

@ -12,7 +12,7 @@
#define ZMK_BEHAVIOR_TRANSPARENT 1
struct zmk_behavior_binding {
char *behavior_dev;
const char *behavior_dev;
uint32_t param1;
uint32_t param2;
};

View file

@ -0,0 +1,4 @@
name: zmk-usb-logging
append:
EXTRA_CONF_FILE: zmk-usb-logging.conf
EXTRA_DTC_OVERLAY_FILE: zmk-usb-logging.overlay

View file

@ -0,0 +1,2 @@
CONFIG_ZMK_USB_LOGGING=y

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/ {
chosen {
zephyr,console = &snippet_zmk_usb_logging_uart;
zephyr,shell-uart = &snippet_zmk_usb_logging_uart;
};
};
&zephyr_udc0 {
snippet_zmk_usb_logging_uart: snippet_zmk_usb_logging_uart {
compatible = "zephyr,cdc-acm-uart";
};
};

View file

@ -11,6 +11,8 @@
#include <drivers/behavior.h>
#include <zmk/behavior.h>
#include <zmk/hid.h>
#include <zmk/matrix.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@ -39,6 +41,150 @@ const struct device *z_impl_behavior_get_binding(const char *name) {
return NULL;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
int zmk_behavior_get_empty_param_metadata(const struct device *dev,
struct behavior_parameter_metadata *metadata) {
metadata->sets_len = 0;
return 0;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int validate_hid_usage(uint16_t usage_page, uint16_t usage_id) {
LOG_DBG("Validate usage %d in page %d", usage_id, usage_page);
switch (usage_page) {
case HID_USAGE_KEY:
if (usage_id == 0 || (usage_id > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE &&
usage_id < LEFT_CONTROL && usage_id > RIGHT_GUI)) {
return -EINVAL;
}
break;
case HID_USAGE_CONSUMER:
if (usage_id >
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC), (0xFF), (0xFFF))) {
return -EINVAL;
}
break;
default:
LOG_WRN("Unsupported HID usage page %d", usage_page);
return -EINVAL;
}
return 0;
}
#define PARAM_MATCHES 0
static int check_param_matches_value(const struct behavior_parameter_value_metadata *value_meta,
uint32_t param) {
switch (value_meta->type) {
case BEHAVIOR_PARAMETER_VALUE_TYPE_NIL:
if (param == 0) {
return PARAM_MATCHES;
}
break;
case BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE:
if (validate_hid_usage(ZMK_HID_USAGE_PAGE(param), ZMK_HID_USAGE_ID(param)) >= 0) {
return PARAM_MATCHES;
}
break;
case BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX:
if (param >= 0 && param < ZMK_KEYMAP_LEN) {
return PARAM_MATCHES;
}
break;
/* TODO: Restore with HSV -> RGB refactor
case BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HSV:
// TODO: No real way to validate? Maybe max brightness?
break;
*/
case BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE:
if (param == value_meta->value) {
return PARAM_MATCHES;
}
break;
case BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE:
if (param >= value_meta->range.min && param <= value_meta->range.max) {
return PARAM_MATCHES;
}
break;
default:
LOG_WRN("Unknown type %d", value_meta->type);
break;
}
return -ENOTSUP;
}
int zmk_behavior_validate_param_values(const struct behavior_parameter_value_metadata *values,
size_t values_len, uint32_t param) {
if (values_len == 0) {
return -ENODEV;
}
for (int v = 0; v < values_len; v++) {
int ret = check_param_matches_value(&values[v], param);
if (ret >= 0) {
return ret;
}
}
return -EINVAL;
}
int zmk_behavior_check_params_match_metadata(const struct behavior_parameter_metadata *metadata,
uint32_t param1, uint32_t param2) {
if (!metadata || metadata->sets_len == 0) {
if (!metadata) {
LOG_ERR("No metadata to check against");
}
return (param1 == 0 && param2 == 0) ? 0 : -ENODEV;
}
for (int s = 0; s < metadata->sets_len; s++) {
const struct behavior_parameter_metadata_set *set = &metadata->sets[s];
int param1_ret =
zmk_behavior_validate_param_values(set->param1_values, set->param1_values_len, param1);
int param2_ret =
zmk_behavior_validate_param_values(set->param2_values, set->param2_values_len, param2);
if ((param1_ret >= 0 || (param1_ret == -ENODEV && param1 == 0)) &&
(param2_ret >= 0 || (param2_ret == -ENODEV && param2 == 0))) {
return 0;
}
}
return -EINVAL;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
int zmk_behavior_validate_binding(const struct zmk_behavior_binding *binding) {
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
const struct device *behavior = zmk_behavior_get_binding(binding->behavior_dev);
if (!behavior) {
return -ENODEV;
}
struct behavior_parameter_metadata metadata;
int ret = behavior_get_parameter_metadata(behavior, &metadata);
if (ret < 0) {
LOG_WRN("Failed getting metadata for %s: %d", binding->behavior_dev, ret);
return ret;
}
return zmk_behavior_check_params_match_metadata(&metadata, binding->param1, binding->param2);
#else
return 0;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
}
#if IS_ENABLED(CONFIG_LOG)
static int check_behavior_names(void) {
// Behavior names must be unique, but we don't have a good way to enforce this

View file

@ -18,6 +18,82 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata no_arg_values[] = {
{
.display_name = "Toggle On/Off",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_TOG_CMD,
},
{
.display_name = "Turn On",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_ON_CMD,
},
{
.display_name = "Turn OFF",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_OFF_CMD,
},
{
.display_name = "Increase Brightness",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_INC_CMD,
},
{
.display_name = "Decrease Brightness",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_DEC_CMD,
},
{
.display_name = "Cycle Brightness",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_CYCLE_CMD,
},
};
static const struct behavior_parameter_value_metadata one_arg_p1_values[] = {
{
.display_name = "Set Brightness",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BL_SET_CMD,
},
};
static const struct behavior_parameter_value_metadata one_arg_p2_values[] = {
{
.display_name = "Brightness",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE,
.range =
{
.min = 0,
.max = 255,
},
},
};
static const struct behavior_parameter_metadata_set no_args_set = {
.param1_values = no_arg_values,
.param1_values_len = ARRAY_SIZE(no_arg_values),
};
static const struct behavior_parameter_metadata_set one_args_set = {
.param1_values = one_arg_p1_values,
.param1_values_len = ARRAY_SIZE(one_arg_p1_values),
.param2_values = one_arg_p2_values,
.param2_values_len = ARRAY_SIZE(one_arg_p2_values),
};
static const struct behavior_parameter_metadata_set sets[] = {no_args_set, one_args_set};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(sets),
.sets = sets,
};
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int behavior_backlight_init(const struct device *dev) { return 0; }
static int
@ -89,6 +165,9 @@ static const struct behavior_driver_api behavior_backlight_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
.locality = BEHAVIOR_LOCALITY_GLOBAL,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_backlight_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -20,6 +20,74 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata no_arg_values[] = {
{
.display_name = "Next Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_NXT_CMD,
},
{
.display_name = "Previous Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_PRV_CMD,
},
{
.display_name = "Clear All Profiles",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_CLR_ALL_CMD,
},
{
.display_name = "Clear Selected Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_CLR_CMD,
},
};
static const struct behavior_parameter_metadata_set no_args_set = {
.param1_values = no_arg_values,
.param1_values_len = ARRAY_SIZE(no_arg_values),
};
static const struct behavior_parameter_value_metadata prof_index_param1_values[] = {
{
.display_name = "Select Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_SEL_CMD,
},
{
.display_name = "Disconnect Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = BT_DISC_CMD,
},
};
static const struct behavior_parameter_value_metadata prof_index_param2_values[] = {
{
.display_name = "Profile",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE,
.range = {.min = 0, .max = ZMK_BLE_PROFILE_COUNT},
},
};
static const struct behavior_parameter_metadata_set profile_index_metadata_set = {
.param1_values = prof_index_param1_values,
.param1_values_len = ARRAY_SIZE(prof_index_param1_values),
.param2_values = prof_index_param2_values,
.param2_values_len = ARRAY_SIZE(prof_index_param2_values),
};
static const struct behavior_parameter_metadata_set metadata_sets[] = {no_args_set,
profile_index_metadata_set};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(metadata_sets),
.sets = metadata_sets,
};
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
@ -54,6 +122,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_bt_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_bt_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -75,6 +75,9 @@ static int on_caps_word_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_caps_word_driver_api = {
.binding_pressed = on_caps_word_binding_pressed,
.binding_released = on_caps_word_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int caps_word_keycode_state_changed_listener(const zmk_event_t *eh);

View file

@ -68,6 +68,12 @@ struct behavior_hold_tap_config {
int32_t hold_trigger_key_positions[];
};
struct behavior_hold_tap_data {
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
struct behavior_parameter_metadata_set set;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
// this data is specific for each hold-tap
struct active_hold_tap {
int32_t position;
@ -652,9 +658,52 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
return ZMK_BEHAVIOR_OPAQUE;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int hold_tap_parameter_metadata(const struct device *hold_tap,
struct behavior_parameter_metadata *param_metadata) {
const struct behavior_hold_tap_config *cfg = hold_tap->config;
struct behavior_hold_tap_data *data = hold_tap->data;
int err;
struct behavior_parameter_metadata child_meta;
err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->hold_behavior_dev),
&child_meta);
if (err < 0) {
LOG_WRN("Failed to get the hold behavior parameter: %d", err);
return err;
}
if (child_meta.sets_len > 0) {
data->set.param1_values = child_meta.sets[0].param1_values;
data->set.param1_values_len = child_meta.sets[0].param1_values_len;
}
err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->tap_behavior_dev),
&child_meta);
if (err < 0) {
LOG_WRN("Failed to get the tap behavior parameter: %d", err);
return err;
}
if (child_meta.sets_len > 0) {
data->set.param2_values = child_meta.sets[0].param1_values;
data->set.param2_values_len = child_meta.sets[0].param1_values_len;
}
param_metadata->sets = &data->set;
param_metadata->sets_len = 1;
return 0;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
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,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = hold_tap_parameter_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int position_state_changed_listener(const zmk_event_t *eh) {
@ -791,7 +840,7 @@ static int behavior_hold_tap_init(const struct device *dev) {
}
#define KP_INST(n) \
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
static const struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
.tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \
.hold_behavior_dev = DEVICE_DT_NAME(DT_INST_PHANDLE_BY_IDX(n, bindings, 0)), \
.tap_behavior_dev = DEVICE_DT_NAME(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \
@ -807,9 +856,10 @@ static int behavior_hold_tap_init(const struct device *dev) {
.hold_trigger_key_positions = DT_INST_PROP(n, hold_trigger_key_positions), \
.hold_trigger_key_positions_len = DT_INST_PROP_LEN(n, hold_trigger_key_positions), \
}; \
BEHAVIOR_DT_INST_DEFINE(n, behavior_hold_tap_init, NULL, NULL, &behavior_hold_tap_config_##n, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_hold_tap_driver_api);
static struct behavior_hold_tap_data behavior_hold_tap_data_##n = {}; \
BEHAVIOR_DT_INST_DEFINE(n, behavior_hold_tap_init, NULL, &behavior_hold_tap_data_##n, \
&behavior_hold_tap_config_##n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)

View file

@ -16,6 +16,27 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Key",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
static int behavior_key_press_init(const struct device *dev) { return 0; };
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
@ -31,7 +52,12 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
}
static const struct behavior_driver_api behavior_key_press_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,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define KP_INST(n) \
BEHAVIOR_DT_INST_DEFINE(n, behavior_key_press_init, NULL, NULL, NULL, POST_KERNEL, \

View file

@ -19,6 +19,27 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Key",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_HID_USAGE,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
struct behavior_key_repeat_config {
uint8_t index;
uint8_t usage_pages_count;
@ -67,6 +88,9 @@ static int on_key_repeat_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_key_repeat_driver_api = {
.binding_pressed = on_key_repeat_binding_pressed,
.binding_released = on_key_repeat_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int key_repeat_keycode_state_changed_listener(const zmk_event_t *eh);

View file

@ -31,9 +31,34 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
return 0;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Key",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HID_USAGE,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
static const struct behavior_driver_api behavior_key_toggle_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define KT_INST(n) \

View file

@ -34,6 +34,10 @@ struct behavior_macro_trigger_state {
struct behavior_macro_state {
struct behavior_macro_trigger_state release_state;
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
struct behavior_parameter_metadata_set set;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
uint32_t press_bindings_count;
};
@ -209,9 +213,100 @@ static int on_macro_binding_released(struct zmk_behavior_binding *binding,
return ZMK_BEHAVIOR_OPAQUE;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static void assign_values_to_set(enum param_source param_source,
struct behavior_parameter_metadata_set *set,
const struct behavior_parameter_value_metadata *values,
size_t values_len) {
if (param_source == PARAM_SOURCE_MACRO_1ST) {
set->param1_values = values;
set->param1_values_len = values_len;
} else {
set->param2_values = values;
set->param2_values_len = values_len;
}
}
// This function will dynamically determine the parameter metadata for a particular macro by
// inspecting the macro *bindings* to see what behaviors in that list receive the macro parameters,
// and then using the metadata from those behaviors for the macro itself.
//
// Care need be taken, where a behavior in the list takes two parameters, and the macro passes along
// a value for the *second* parameter, we need to make sure we find the right metadata set for the
// referenced behavior that matches the first parameter.
static int get_macro_parameter_metadata(const struct device *macro,
struct behavior_parameter_metadata *param_metadata) {
const struct behavior_macro_config *cfg = macro->config;
struct behavior_macro_state *data = macro->data;
struct behavior_macro_trigger_state state = {0};
for (int i = 0; (i < cfg->count) && (!data->set.param1_values || !data->set.param2_values);
i++) {
if (handle_control_binding(&state, &cfg->bindings[i]) ||
(state.param1_source == PARAM_SOURCE_BINDING &&
state.param2_source == PARAM_SOURCE_BINDING)) {
continue;
}
LOG_DBG("checking %d for the given state", i);
struct behavior_parameter_metadata binding_meta;
int err = behavior_get_parameter_metadata(
zmk_behavior_get_binding(cfg->bindings[i].behavior_dev), &binding_meta);
if (err < 0 || binding_meta.sets_len == 0) {
LOG_WRN("Failed to fetch macro binding parameter details %d", err);
return -ENOTSUP;
}
// If both macro parameters get passed to this one entry, use
// the metadata for this behavior verbatim.
if (state.param1_source != PARAM_SOURCE_BINDING &&
state.param2_source != PARAM_SOURCE_BINDING) {
param_metadata->sets_len = binding_meta.sets_len;
param_metadata->sets = binding_meta.sets;
return 0;
}
if (state.param1_source != PARAM_SOURCE_BINDING) {
assign_values_to_set(state.param1_source, &data->set,
binding_meta.sets[0].param1_values,
binding_meta.sets[0].param1_values_len);
}
if (state.param2_source != PARAM_SOURCE_BINDING) {
// For the param2 metadata, we need to find a set that matches fully bound first
// parameter of our macro entry, and use the metadata from that set.
for (int s = 0; s < binding_meta.sets_len; s++) {
if (zmk_behavior_validate_param_values(binding_meta.sets[s].param1_values,
binding_meta.sets[s].param1_values_len,
cfg->bindings[i].param1) >= 0) {
assign_values_to_set(state.param2_source, &data->set,
binding_meta.sets[s].param2_values,
binding_meta.sets[s].param2_values_len);
break;
}
}
}
state.param1_source = PARAM_SOURCE_BINDING;
state.param2_source = PARAM_SOURCE_BINDING;
}
param_metadata->sets_len = 1;
param_metadata->sets = &data->set;
return 0;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_driver_api behavior_macro_driver_api = {
.binding_pressed = on_macro_binding_pressed,
.binding_released = on_macro_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = get_macro_parameter_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define TRANSFORMED_BEHAVIORS(n) \

View file

@ -75,6 +75,9 @@ static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_mod_morph_driver_api = {
.binding_pressed = on_mod_morph_binding_pressed,
.binding_released = on_mod_morph_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int behavior_mod_morph_init(const struct device *dev) { return 0; }

View file

@ -15,6 +15,27 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Layer",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_LAYER_INDEX,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
struct behavior_mo_config {};
struct behavior_mo_data {};
@ -33,7 +54,12 @@ static int mo_keymap_binding_released(struct zmk_behavior_binding *binding,
}
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,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static const struct behavior_mo_config behavior_mo_config = {};

View file

@ -31,6 +31,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_none_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_none_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -20,6 +20,42 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata std_values[] = {
{
.value = OUT_TOG,
.display_name = "Toggle Outputs",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
},
#if IS_ENABLED(CONFIG_ZMK_USB)
{
.value = OUT_USB,
.display_name = "USB Output",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
},
#endif // IS_ENABLED(CONFIG_ZMK_USB)
#if IS_ENABLED(CONFIG_ZMK_BLE)
{
.value = OUT_BLE,
.display_name = "BLE Output",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
},
#endif // IS_ENABLED(CONFIG_ZMK_BLE)
};
static const struct behavior_parameter_metadata_set std_set = {
.param1_values = std_values,
.param1_values_len = ARRAY_SIZE(std_values),
};
static const struct behavior_parameter_metadata metadata = {
.sets_len = 1,
.sets = &std_set,
};
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
@ -40,6 +76,9 @@ static int behavior_out_init(const struct device *dev) { return 0; }
static const struct behavior_driver_api behavior_outputs_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_out_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -38,6 +38,9 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_reset_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.locality = BEHAVIOR_LOCALITY_EVENT_SOURCE,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define RST_INST(n) \

View file

@ -18,6 +18,119 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata no_arg_values[] = {
{
.display_name = "Toggle On/Off",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_TOG_CMD,
},
{
.display_name = "Turn On",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_ON_CMD,
},
{
.display_name = "Turn OFF",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_OFF_CMD,
},
{
.display_name = "Hue Up",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_HUI_CMD,
},
{
.display_name = "Hue Down",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_HUD_CMD,
},
{
.display_name = "Saturation Up",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_SAI_CMD,
},
{
.display_name = "Saturation Down",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_SAD_CMD,
},
{
.display_name = "Brightness Up",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_BRI_CMD,
},
{
.display_name = "Brightness Down",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_BRD_CMD,
},
{
.display_name = "Speed Up",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_SPI_CMD,
},
{
.display_name = "Speed Down",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_SPD_CMD,
},
{
.display_name = "Next Effect",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_EFF_CMD,
},
{
.display_name = "Previous Effect",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_EFR_CMD,
},
};
static const struct behavior_parameter_metadata_set no_args_set = {
.param1_values = no_arg_values,
.param1_values_len = ARRAY_SIZE(no_arg_values),
};
/*
static const struct behavior_parameter_value_metadata hsv_p1_value_metadata_values[] = {
{
.display_name = "Set Color",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE,
.value = RGB_COLOR_HSB_CMD,
},
};
static const struct behavior_parameter_value_metadata hsv_p2_value_metadata_values[] = {
{
.display_name = "Color",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_HSV,
},
};
static const struct behavior_parameter_metadata_set hsv_value_metadata_set = {
.param1_values = hsv_p1_value_metadata_values,
.param1_values_len = ARRAY_SIZE(hsv_p1_value_metadata_values),
.param_values = hsv_p2_value_metadata_values,
.param_values_len = ARRAY_SIZE(hsv_p2_value_metadata_values),
};
*/
static const struct behavior_parameter_metadata_set sets[] = {
no_args_set,
// hsv_value_metadata_set,
};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(sets),
.sets = sets,
};
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int behavior_rgb_underglow_init(const struct device *dev) { return 0; }
static int
@ -147,6 +260,9 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
.locality = BEHAVIOR_LOCALITY_GLOBAL,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_rgb_underglow_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -74,6 +74,9 @@ static const struct behavior_driver_api behavior_soft_off_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
.locality = BEHAVIOR_LOCALITY_GLOBAL,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define BSO_INST(n) \

View file

@ -188,9 +188,41 @@ static int on_sticky_key_binding_released(struct zmk_behavior_binding *binding,
return ZMK_BEHAVIOR_OPAQUE;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static int sticky_key_parameter_domains(const struct device *sk,
struct behavior_parameter_metadata *param_metadata) {
const struct behavior_sticky_key_config *cfg = sk->config;
struct behavior_parameter_metadata child_metadata;
int err = behavior_get_parameter_metadata(zmk_behavior_get_binding(cfg->behavior.behavior_dev),
&child_metadata);
if (err < 0) {
LOG_WRN("Failed to get the sticky key bound behavior parameter: %d", err);
}
for (int s = 0; s < child_metadata.sets_len; s++) {
const struct behavior_parameter_metadata_set *set = &child_metadata.sets[s];
if (set->param2_values_len > 0) {
return -ENOTSUP;
}
}
*param_metadata = child_metadata;
return 0;
}
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_driver_api behavior_sticky_key_driver_api = {
.binding_pressed = on_sticky_key_binding_pressed,
.binding_released = on_sticky_key_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = sticky_key_parameter_domains,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh);
@ -337,7 +369,7 @@ struct behavior_sticky_key_data {};
static struct behavior_sticky_key_data behavior_sticky_key_data;
#define KP_INST(n) \
static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
static const struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \
.release_after_ms = DT_INST_PROP(n, release_after_ms), \
.quick_release = DT_INST_PROP(n, quick_release), \

View file

@ -189,6 +189,9 @@ void behavior_tap_dance_timer_handler(struct k_work *item) {
static const struct behavior_driver_api behavior_tap_dance_driver_api = {
.binding_pressed = on_tap_dance_binding_pressed,
.binding_released = on_tap_dance_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static int tap_dance_position_state_changed_listener(const zmk_event_t *eh);

View file

@ -32,9 +32,34 @@ static int to_keymap_binding_released(struct zmk_behavior_binding *binding,
return ZMK_BEHAVIOR_OPAQUE;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Layer",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_LAYER_INDEX,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
static const struct behavior_driver_api behavior_to_driver_api = {
.binding_pressed = to_keymap_binding_pressed,
.binding_released = to_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_to_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -34,9 +34,34 @@ static int tog_keymap_binding_released(struct zmk_behavior_binding *binding,
return ZMK_BEHAVIOR_OPAQUE;
}
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
{
.display_name = "Layer",
.type = BEHAVIOR_PARAMETER_VALUE_TYPE_STANDARD,
.standard = BEHAVIOR_PARAMETER_STANDARD_DOMAIN_LAYER_INDEX,
},
};
static const struct behavior_parameter_metadata_set param_metadata_set[] = {{
.param1_values = param_values,
.param1_values_len = ARRAY_SIZE(param_values),
}};
static const struct behavior_parameter_metadata metadata = {
.sets_len = ARRAY_SIZE(param_metadata_set),
.sets = param_metadata_set,
};
#endif
static const struct behavior_driver_api behavior_tog_driver_api = {
.binding_pressed = tog_keymap_binding_pressed,
.binding_released = tog_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.parameter_metadata = &metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
static const struct behavior_tog_config behavior_tog_config = {};

View file

@ -31,6 +31,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
static const struct behavior_driver_api behavior_transparent_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
.get_parameter_metadata = zmk_behavior_get_empty_param_metadata,
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, behavior_transparent_init, NULL, NULL, NULL, POST_KERNEL,

View file

@ -66,6 +66,17 @@ static int hid_listener_keycode_released(const struct zmk_keycode_state_changed
return err;
}
#if IS_ENABLED(CONFIG_ZMK_HID_SEPARATE_MOD_RELEASE_REPORT)
// send report of normal key release early to fix the issue
// of some programs recognizing the implicit_mod release before the actual key release
err = zmk_endpoints_send_report(ev->usage_page);
if (err < 0) {
LOG_ERR("Failed to send key report for the released keycode (%d)", err);
}
#endif // IS_ENABLED(CONFIG_ZMK_HID_SEPARATE_MOD_RELEASE_REPORT)
explicit_mods_changed = zmk_hid_unregister_mods(ev->explicit_modifiers);
// There is a minor issue with this code.
// If LC(A) is pressed, then LS(B), then LC(A) is released, the shift for B will be released
@ -73,7 +84,7 @@ static int hid_listener_keycode_released(const struct zmk_keycode_state_changed
// Solving this would require keeping track of which key's implicit modifiers are currently
// active and only releasing modifiers at that time.
implicit_mods_changed = zmk_hid_implicit_modifiers_release();
;
if (ev->usage_page != HID_USAGE_KEY &&
(explicit_mods_changed > 0 || implicit_mods_changed > 0)) {
err = zmk_endpoints_send_report(HID_USAGE_KEY);

View file

@ -195,4 +195,4 @@ static int zmk_usb_hid_init(void) {
return 0;
}
SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_ZMK_USB_HID_INIT_PRIORITY);

View file

@ -19,7 +19,7 @@ There's been lots of various activity in ZMK land!
- Tons of [documentation](/docs) work.
- Refactoring ([#73](https://github.com/zmkfirmware/zmk/pull/73), [#74](https://github.com/zmkfirmware/zmk/pull/74)) of [keymaps](/docs/features/keymaps) to make them simpler for users.
- Mod-Tap Behavior (docs coming!) is much improved ([#69](https://github.com/zmkfirmware/zmk/pull/69)) and usable now.
- An initial [`setup.sh`](http://localhost:3000/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
- An initial [`setup.sh`](/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
- Corne shield ([#80](https://github.com/zmkfirmware/zmk/pull/80)) shield definition was added.
- Initial [encoder](/docs/features/encoders) support ([#61](https://github.com/zmkfirmware/zmk/pull/61)) was added.

View file

@ -61,7 +61,7 @@ Once the container has rebuilt, VS Code will be running the 2.5 Docker image.
The following steps will get you building ZMK locally against Zephyr 2.5:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View file

@ -62,7 +62,7 @@ Once the container has rebuilt, VS Code will be running the 3.0 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.0:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View file

@ -132,7 +132,7 @@ Another persistent bug that Apple users experienced was related to crashes and p
The long awaited locality enhancement was finally merged by [petejohanson] in [#547](https://github.com/zmkfirmware/zmk/pull/547), allowing more fine grained control of where certain behaviors are invoked. Some key improvements thanks to the changes:
- [RGB Underglow](/docs/features/underglow) behaviors now run globally, so enabling/disabling RGB, changing the color, animation, etc. applies to both sides of a split properly.
- [Reset](/docs/behaviors/reset#reset)/[Bootloader](/docs/behaviors/reset#bootloader) behaviors now run wherever the key was pressed. For example, adding a `&bootloader` reference to the peripheral side of a split will now put that side of the split into the bootloader when pressed.
- [Reset](/docs/behaviors/reset#reset)/[Bootloader](/docs/behaviors/reset#bootloader-reset) behaviors now run wherever the key was pressed. For example, adding a `&bootloader` reference to the peripheral side of a split will now put that side of the split into the bootloader when pressed.
#### Split Connections

View file

@ -57,7 +57,7 @@ and then update it as appropriate to build the right shields/boards for your con
### Upgrade a manual script
If you have a custom GitHub Actions workflow you need to maintain for some reason, you can update the workflow to to use the `stable` Docker image tag for the build:
If you have a custom GitHub Actions workflow you need to maintain for some reason, you can update the workflow to use the `stable` Docker image tag for the build:
- Open `.github/workflows/build.yml` in your editor/IDE
- Change `zmkfirmware/zmk-build-arm:2.5` to `zmkfirmware/zmk-build-arm:stable` wherever it is found
@ -87,7 +87,7 @@ Once the container has rebuilt, VS Code will be running the 3.2 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.2:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Install the latest version of `west` by running `pip3 install --user --update west`.
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View file

@ -105,7 +105,7 @@ Note that documentation is still lacking for utilizing more than one peripheral
[petejohanson] contributed a fix to release held keys on peripheral disconnect [#1340](https://github.com/zmkfirmware/zmk/pull/1340), which makes scenarios where a split disconnects unexpectedly less painful.
[petejohanson] also improved [the `settings_reset` shield](/docs/troubleshooting#split-keyboard-halves-unable-to-pair) by making it clear bonds more reliably, and allow it to build for all boards in [#1879](https://github.com/zmkfirmware/zmk/pull/1879).
[petejohanson] also improved [the `settings_reset` shield](/docs/troubleshooting/connection-issues#split-keyboard-halves-unable-to-pair) by making it clear bonds more reliably, and allow it to build for all boards in [#1879](https://github.com/zmkfirmware/zmk/pull/1879).
[petejohanson] and [xudongzheng] contributed additional split connectivity improvements, via using directed advertising in [#1913](https://github.com/zmkfirmware/zmk/pull/1913) and improving the robustness of central scanning in [#1912](https://github.com/zmkfirmware/zmk/pull/1912).

View file

@ -70,7 +70,7 @@ Once the container has rebuilt, VS Code will be running the 3.5 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.5:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Install the latest version of `west` by running `pip3 install --user --update west`.
- Pull the latest ZMK `main` with `git pull` for your ZMK checkout
- Run `west update` to pull the updated Zephyr version and its dependencies

View file

@ -7,7 +7,7 @@ sidebar_label: Caps Word
The caps word behavior behaves similar to a caps lock, but will automatically deactivate when any key not in a continue list is pressed, or if the caps word key is pressed again. For smaller keyboards using [mod-taps](/docs/behaviors/mod-tap), this can help avoid repeated alternating holds when typing words in all caps.
The modifiers are applied only to to the alphabetic (`A` to `Z`) keycodes, to avoid automatically applying them to numeric values, etc.
The modifiers are applied only to the alphabetic (`A` to `Z`) keycodes, to avoid automatically applying them to numeric values, etc.
### Behavior Binding
@ -21,7 +21,7 @@ Example:
### Configuration
#### Continue List
#### Continue list
By default, the caps word will remain active when any alphanumeric character or underscore (`UNDERSCORE`), backspace (`BACKSPACE`), or delete (`DELETE`) characters are pressed. Any other non-modifier keycode sent will turn off caps word. If you would like to override this, you can set a new array of keys in the `continue-list` property in your keymap:
@ -37,7 +37,7 @@ By default, the caps word will remain active when any alphanumeric character or
};
```
#### Applied Modifier(s)
#### Applied modifier(s)
In addition, if you would like _multiple_ modifiers, instead of just `MOD_LSFT`, you can override the `mods` property:

View file

@ -35,7 +35,7 @@ When the hold-tap key is released and the hold behavior has not been triggered,
![Hold-tap comparison](../assets/hold-tap/comparison.svg)
### Basic usage
### Basic Usage
For basic usage, please see the [mod-tap](mod-tap.md) and [layer-tap](layers.md#layer-tap) pages.

View file

@ -9,7 +9,7 @@ sidebar_label: Overview
Below is a summary of pre-defined behavior bindings and user-definable behaviors available in ZMK, with references to documentation pages describing them.
## Key press behaviors
## Key Press Behaviors
| Binding | Behavior | Description |
| ------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@ -21,14 +21,14 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
| `&caps_word` | [Caps Word](caps-word.md) | Behaves similar to caps lock, but automatically deactivates when any key not in a continue list is pressed, or if the caps word key is pressed again |
| `&key_repeat` | [Key Repeat](key-repeat.md) | Sends again whatever keycode was last sent |
## Miscellaneous behaviors
## Miscellaneous Behaviors
| Binding | Behavior | Description |
| -------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `&trans` | [Transparent](misc.md#transparent) | Passes the key press down to the next active layer in the stack for processing |
| `&none` | [None](misc.md#none) | Swallows and stops the key press, no keycode will be sent nor will the key press be passed down to the next active layer in the stack |
## Layer navigation behaviors
## Layer Navigation Behaviors
| Binding | Behavior | Description |
| ------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
@ -38,41 +38,41 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
| `&tog` | [Toggle Layer](layers.md#toggle-layer) | Enables a layer until the layer is manually disabled |
| `&sl` | [Sticky Layer](sticky-layer.md) | Activates a layer until another key is pressed, then deactivates it |
## Mouse emulation behaviors
## Mouse Emulation Behaviors
| Binding | Behavior | Description |
| ------- | ----------------------------------------------------------- | ------------------------------- |
| `&mkp` | [Mouse Button Press](mouse-emulation.md#mouse-button-press) | Emulates pressing mouse buttons |
## Reset behaviors
## Reset Behaviors
| Binding | Behavior | Description |
| ------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `&sys_reset` | [Reset](reset.md#reset) | Resets the keyboard and re-runs the firmware flashed to the device |
| `&bootloader` | [Bootloader](reset.md#bootloader) | Resets the keyboard and puts it into bootloader mode, allowing you to flash new firmware |
| Binding | Behavior | Description |
| ------------- | --------------------------------------- | ---------------------------------------------------------------------------------------- |
| `&sys_reset` | [Reset](reset.md#reset) | Resets the keyboard and re-runs the firmware flashed to the device |
| `&bootloader` | [Bootloader](reset.md#bootloader-reset) | Resets the keyboard and puts it into bootloader mode, allowing you to flash new firmware |
## Output selection behaviors
## Output Selection Behaviors
| Binding | Behavior | Description |
| ------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `&bt` | [Bluetooth](bluetooth.md#bluetooth-behavior) | Completes a bluetooth action given on press, for example switching between devices |
| `&out` | [Output Selection](outputs.md#output-selection-behavior) | Allows selecting whether output is sent to the USB or bluetooth connection when both are connected |
## Lighting behaviors
## Lighting Behaviors
| Binding | Behavior | Description |
| --------- | ---------------------------------------------- | ---------------------------------------------------------------------------- |
| `&rgb_ug` | [RGB Underglow](underglow.md#behavior-binding) | Controls the RGB underglow, usually placed underneath the keyboard |
| `&bl` | [Backlight](backlight.md#behavior-binding) | Controls the keyboard backlighting, usually placed through or under switches |
## Power management behaviors
## Power Management Behaviors
| Binding | Behavior | Description |
| ------------ | --------------------------------------------- | --------------------------------------------------------------- |
| `&ext_power` | [Power management](power.md#behavior-binding) | Allows enabling or disabling the VCC power output to save power |
| `&soft_off` | [Soft off](soft-off.md#behavior-binding) | Turns the keyboard off. |
## User-defined behaviors
## User-Defined Behaviors
| Behavior | Description |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

View file

@ -19,7 +19,7 @@ Example:
### Configuration
#### Usage Pages
#### Usage pages
By default, the key repeat will only track the last pressed key from the HID "Key" usage page, and ignore events from other usages, e.g. Consumer page.

Some files were not shown because too many files have changed in this diff Show more