mirror of
https://github.com/zmkfirmware/zmk.git
synced 2026-03-19 20:45:18 -05:00
Compare commits
14 Commits
revert-200
...
led-indica
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b23d07954 | ||
|
|
f14ac2b3d6 | ||
|
|
c23cc8ee42 | ||
|
|
6276e973d5 | ||
|
|
84b93350b8 | ||
|
|
a3f30ee799 | ||
|
|
f77e38f2b9 | ||
|
|
0a4b1a6533 | ||
|
|
d7d9eed317 | ||
|
|
8776911da5 | ||
|
|
3027b2a6e8 | ||
|
|
f6716f869a | ||
|
|
2a1904e184 | ||
|
|
afe65ead9c |
@@ -13,9 +13,13 @@
|
||||
"type=volume,source=zmk-zephyr-modules,target=${containerWorkspaceFolder}/modules",
|
||||
"type=volume,source=zmk-zephyr-tools,target=${containerWorkspaceFolder}/tools"
|
||||
],
|
||||
"extensions": ["ms-vscode.cpptools"],
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash"
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["ms-vscode.cpptools"],
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash"
|
||||
}
|
||||
}
|
||||
},
|
||||
"forwardPorts": [3000]
|
||||
}
|
||||
|
||||
6
.github/workflows/build-user-config.yml
vendored
6
.github/workflows/build-user-config.yml
vendored
@@ -55,12 +55,14 @@ jobs:
|
||||
- name: Prepare variables
|
||||
shell: sh -x {0}
|
||||
env:
|
||||
board: ${{ matrix.board }}
|
||||
shield: ${{ matrix.shield }}
|
||||
artifact_name: ${{ matrix.artifact-name }}
|
||||
run: |
|
||||
echo "zephyr_version=${ZEPHYR_VERSION}" >> $GITHUB_ENV
|
||||
echo "extra_cmake_args=${shield:+-DSHIELD=\"$shield\"}" >> $GITHUB_ENV
|
||||
echo "display_name=${shield:+$shield - }${{ matrix.board }}" >> $GITHUB_ENV
|
||||
echo "artifact_name=${shield:+$shield-}${{ matrix.board }}-zmk" >> $GITHUB_ENV
|
||||
echo "display_name=${shield:+$shield - }${board}" >> $GITHUB_ENV
|
||||
echo "artifact_name=${artifact_name:-${shield:+$shield-}${board}-zmk}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -31,12 +31,14 @@ target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
|
||||
target_sources(app PRIVATE src/events/activity_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/position_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/sensor_event.c)
|
||||
target_sources(app PRIVATE src/events/mouse_button_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/hid.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_KEY_TOGGLE app PRIVATE src/behaviors/behavior_key_toggle.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
@@ -54,6 +56,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE app PRIVATE src/behaviors/behavior_sensor_rotate.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_VAR app PRIVATE src/behaviors/behavior_sensor_rotate_var.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON app PRIVATE src/behaviors/behavior_sensor_rotate_common.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_MOUSE_KEY_PRESS app PRIVATE src/behaviors/behavior_mouse_key_press.c)
|
||||
target_sources(app PRIVATE src/combo.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_tap_dance.c)
|
||||
target_sources(app PRIVATE src/behavior_queue.c)
|
||||
@@ -65,6 +68,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/events/layer_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/keycode_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/hid_indicators.c)
|
||||
|
||||
if (CONFIG_ZMK_BLE)
|
||||
target_sources(app PRIVATE src/events/ble_active_profile_changed.c)
|
||||
@@ -80,6 +84,8 @@ target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_bac
|
||||
target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/events/battery_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/battery.c)
|
||||
|
||||
target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/events/hid_indicators_changed.c)
|
||||
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||
add_subdirectory(src/split)
|
||||
|
||||
|
||||
22
app/Kconfig
22
app/Kconfig
@@ -87,6 +87,12 @@ config ZMK_HID_CONSUMER_REPORT_USAGES_BASIC
|
||||
|
||||
endchoice
|
||||
|
||||
config ZMK_HID_INDICATORS
|
||||
bool "HID Indicators"
|
||||
help
|
||||
Enable HID indicators, used for detecting state of Caps/Scroll/Num Lock,
|
||||
Kata, and Compose.
|
||||
|
||||
menu "Output Types"
|
||||
|
||||
config ZMK_USB
|
||||
@@ -98,7 +104,6 @@ config ZMK_USB
|
||||
|
||||
config ZMK_USB_BOOT
|
||||
bool "USB Boot Protocol Support"
|
||||
default y
|
||||
depends on ZMK_USB
|
||||
select USB_HID_BOOT_PROTOCOL
|
||||
select USB_DEVICE_SOF
|
||||
@@ -157,6 +162,10 @@ config ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE
|
||||
int "Max number of consumer HID reports to queue for sending over BLE"
|
||||
default 5
|
||||
|
||||
config ZMK_BLE_MOUSE_REPORT_QUEUE_SIZE
|
||||
int "Max number of mouse HID reports to queue for sending over BLE"
|
||||
default 20
|
||||
|
||||
config ZMK_BLE_CLEAR_BONDS_ON_START
|
||||
bool "Configuration that clears all bond information from the keyboard on startup."
|
||||
default n
|
||||
@@ -316,13 +325,22 @@ endif
|
||||
#Display/LED Options
|
||||
endmenu
|
||||
|
||||
menu "Mouse Options"
|
||||
|
||||
config ZMK_MOUSE
|
||||
bool "Enable ZMK mouse emulation"
|
||||
default n
|
||||
|
||||
#Mouse Options
|
||||
endmenu
|
||||
|
||||
menu "Power Management"
|
||||
|
||||
config ZMK_BATTERY_REPORTING
|
||||
bool "Battery level detection/reporting"
|
||||
default n
|
||||
select SENSOR
|
||||
select BT_BAS if ZMK_BLE
|
||||
imply BT_BAS if ZMK_BLE
|
||||
|
||||
config ZMK_IDLE_TIMEOUT
|
||||
int "Milliseconds of inactivity before entering idle state (OLED shutoff, etc)"
|
||||
|
||||
@@ -6,6 +6,11 @@ config ZMK_BEHAVIOR_KEY_TOGGLE
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_KEY_TOGGLE_ENABLED
|
||||
|
||||
config ZMK_BEHAVIOR_MOUSE_KEY_PRESS
|
||||
bool
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED
|
||||
imply ZMK_MOUSE
|
||||
|
||||
config ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON
|
||||
bool
|
||||
|
||||
3
app/boards/arm/glove80/CMakeLists.txt
Normal file
3
app/boards/arm/glove80/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
zephyr_library()
|
||||
zephyr_library_sources(usb_serial_number.c)
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
|
||||
8
app/boards/arm/glove80/Kconfig
Normal file
8
app/boards/arm/glove80/Kconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_ENABLE_DCDC
|
||||
bool "Enable DCDC mode"
|
||||
select SOC_DCDC_NRF52X
|
||||
default y
|
||||
depends on (BOARD_GLOVE80_LH || BOARD_GLOVE80_RH)
|
||||
10
app/boards/arm/glove80/Kconfig.board
Normal file
10
app/boards/arm/glove80/Kconfig.board
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_GLOVE80_LH
|
||||
bool "Glove80 LH"
|
||||
depends on SOC_NRF52840_QIAA
|
||||
|
||||
config BOARD_GLOVE80_RH
|
||||
bool "Glove80 RH"
|
||||
depends on SOC_NRF52840_QIAA
|
||||
65
app/boards/arm/glove80/Kconfig.defconfig
Normal file
65
app/boards/arm/glove80/Kconfig.defconfig
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_GLOVE80_LH
|
||||
|
||||
config BOARD
|
||||
default "glove80 lh"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif # BOARD_GLOVE80_LH
|
||||
|
||||
if BOARD_GLOVE80_RH
|
||||
|
||||
config BOARD
|
||||
default "glove80 rh"
|
||||
|
||||
endif # BOARD_GLOVE80_RH
|
||||
|
||||
if BOARD_GLOVE80_LH || BOARD_GLOVE80_RH
|
||||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
||||
config BT_CTLR
|
||||
default BT
|
||||
|
||||
config ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS
|
||||
default 5
|
||||
|
||||
config PINCTRL
|
||||
default y
|
||||
|
||||
if USB
|
||||
|
||||
config USB_NRFX
|
||||
default y
|
||||
|
||||
config USB_DEVICE_STACK
|
||||
default y
|
||||
|
||||
endif # USB
|
||||
|
||||
if ZMK_BACKLIGHT
|
||||
|
||||
config PWM
|
||||
default y
|
||||
|
||||
config LED_PWM
|
||||
default y
|
||||
|
||||
endif # ZMK_BACKLIGHT
|
||||
|
||||
if ZMK_RGB_UNDERGLOW
|
||||
|
||||
config SPI
|
||||
default y
|
||||
|
||||
config WS2812_STRIP
|
||||
default y
|
||||
|
||||
endif # ZMK_RGB_UNDERGLOW
|
||||
|
||||
endif # BOARD_GLOVE80_LH || BOARD_GLOVE80_RH
|
||||
6
app/boards/arm/glove80/board.cmake
Normal file
6
app/boards/arm/glove80/board.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
107
app/boards/arm/glove80/glove80.dtsi
Normal file
107
app/boards/arm/glove80/glove80.dtsi
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <14>;
|
||||
rows = <6>;
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
|
||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
|
||||
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,13)
|
||||
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(0,6) RC(1,6) RC(2,6) RC(2,7) RC(1,7) RC(0,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,13)
|
||||
RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) RC(3,6) RC(4,6) RC(5,6) RC(5,7) RC(4,7) RC(3,7) RC(5,9) RC(5,10) RC(5,11) RC(5,12) RC(5,13)
|
||||
>;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
diode-direction = "col2row";
|
||||
debounce-press-ms = <4>;
|
||||
debounce-release-ms = <20>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbd {
|
||||
status = "okay";
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
label = "CDC_ACM_0";
|
||||
};
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
/*
|
||||
* For more information, see:
|
||||
* http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
|
||||
*/
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
sd_partition: partition@0 {
|
||||
label = "softdevice";
|
||||
reg = <0x00000000 0x00026000>;
|
||||
};
|
||||
code_partition: partition@26000 {
|
||||
label = "code_partition";
|
||||
reg = <0x00026000 0x000c6000>;
|
||||
};
|
||||
|
||||
/*
|
||||
* The flash starting at 0x000ec000 and ending at
|
||||
* 0x000f3fff is reserved for use by the application.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Storage partition will be used by FCB/LittleFS/NVS
|
||||
* if enabled.
|
||||
*/
|
||||
storage_partition: partition@ec000 {
|
||||
label = "storage";
|
||||
reg = <0x000ec000 0x00008000>;
|
||||
};
|
||||
|
||||
boot_partition: partition@f4000 {
|
||||
label = "adafruit_boot";
|
||||
reg = <0x000f4000 0x0000c000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
114
app/boards/arm/glove80/glove80.keymap
Normal file
114
app/boards/arm/glove80/glove80.keymap
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <dt-bindings/zmk/ext_power.h>
|
||||
#include <dt-bindings/zmk/outputs.h>
|
||||
#include <dt-bindings/zmk/rgb.h>
|
||||
|
||||
// layers
|
||||
#define DEFAULT 0
|
||||
#define LOWER 1
|
||||
#define MAGIC 2
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
// For the "layer" key, it'd nice to be able to use it as either a shift or a toggle.
|
||||
// Configure it as a tap dance, so the first tap (or hold) is a &mo and the second tap is a &to
|
||||
layer_td: tap_dance_0 {
|
||||
compatible = "zmk,behavior-tap-dance";
|
||||
label = "LAYER_TAP_DANCE";
|
||||
#binding-cells = <0>;
|
||||
tapping-term-ms = <200>;
|
||||
bindings = <&mo LOWER>, <&to LOWER>;
|
||||
};
|
||||
};
|
||||
|
||||
macros {
|
||||
bt_0: bt_profile_macro_0 {
|
||||
label = "BT_0";
|
||||
compatible = "zmk,behavior-macro";
|
||||
#binding-cells = <0>;
|
||||
bindings
|
||||
= <&out OUT_BLE>,
|
||||
<&bt BT_SEL 0>;
|
||||
};
|
||||
|
||||
bt_1: bt_profile_macro_1 {
|
||||
label = "BT_1";
|
||||
compatible = "zmk,behavior-macro";
|
||||
#binding-cells = <0>;
|
||||
bindings
|
||||
= <&out OUT_BLE>,
|
||||
<&bt BT_SEL 1>;
|
||||
};
|
||||
|
||||
bt_2: bt_profile_macro_2 {
|
||||
label = "BT_2";
|
||||
compatible = "zmk,behavior-macro";
|
||||
#binding-cells = <0>;
|
||||
bindings
|
||||
= <&out OUT_BLE>,
|
||||
<&bt BT_SEL 2>;
|
||||
};
|
||||
|
||||
bt_3: bt_profile_macro_3 {
|
||||
label = "BT_3";
|
||||
compatible = "zmk,behavior-macro";
|
||||
#binding-cells = <0>;
|
||||
bindings
|
||||
= <&out OUT_BLE>,
|
||||
<&bt BT_SEL 3>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||
// | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
|
||||
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
|
||||
// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
|
||||
// | ESC | A | S | D | F | G | | H | J | K | L | ; | ' |
|
||||
// | ` | Z | X | C | V | B | LSHFT | LCTRL | LOWER | | LGUI | RCTRL | RSHFT | N | M | , | . | / | PGUP |
|
||||
// | MAGIC | HOME| END | LEFT | RIGHT| | BSPC | DEL | LALT | | RALT | RET | SPACE | | UP | DOWN | [ | ] | PGDN |
|
||||
|
||||
bindings = <
|
||||
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10
|
||||
&kp EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS
|
||||
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
|
||||
&kp ESC &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
|
||||
&kp GRAVE &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LCTRL &layer_td &kp LGUI &kp RCTRL &kp RSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp PG_UP
|
||||
&mo MAGIC &kp HOME &kp END &kp LEFT &kp RIGHT &kp BSPC &kp DEL &kp LALT &kp RALT &kp RET &kp SPACE &kp UP &kp DOWN &kp LBKT &kp RBKT &kp PG_DN
|
||||
>;
|
||||
};
|
||||
|
||||
lower_layer {
|
||||
bindings = <
|
||||
&kp C_BRI_DN &kp C_BRI_UP &kp C_PREV &kp C_NEXT &kp C_PP &kp C_MUTE &kp C_VOL_DN &kp C_VOL_UP &none &kp PAUSE_BREAK
|
||||
&trans &none &none &none &none &kp HOME &kp LPAR &kp KP_NUM &kp KP_EQUAL &kp KP_DIVIDE &kp KP_MULTIPLY &kp PSCRN
|
||||
&trans &none &none &kp UP &none &kp END &kp RPAR &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp SLCK
|
||||
&trans &none &kp LEFT &kp DOWN &kp RIGHT &kp PG_UP &kp PRCNT &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &none
|
||||
&trans &kp K_CMENU &none &kp F11 &kp F12 &kp PG_DN &trans &trans &to DEFAULT &trans &trans &trans &kp COMMA &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER &trans
|
||||
&trans &kp CAPS &kp INS &kp F11 &kp F12 &trans &trans &trans &trans &trans &trans &kp KP_N0 &kp KP_N0 &kp KP_DOT &kp KP_ENTER &trans
|
||||
>;
|
||||
};
|
||||
|
||||
magic_layer {
|
||||
bindings = <
|
||||
&bt BT_CLR &none &none &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &none &none &none &none &none &none &none
|
||||
&none &rgb_ug RGB_SPI &rgb_ug RGB_SAI &rgb_ug RGB_HUI &rgb_ug RGB_BRI &rgb_ug RGB_TOG &none &none &none &none &none &none
|
||||
&bootloader &rgb_ug RGB_SPD &rgb_ug RGB_SAD &rgb_ug RGB_HUD &rgb_ug RGB_BRD &rgb_ug RGB_EFF &none &none &none &none &none &bootloader
|
||||
&sys_reset &none &none &none &none &none &bt_2 &bt_3 &none &none &none &none &none &none &none &none &none &sys_reset
|
||||
&none &none &none &none &none &bt_0 &bt_1 &out OUT_USB &none &none &none &none &none &none &none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
19
app/boards/arm/glove80/glove80.yaml
Normal file
19
app/boards/arm/glove80/glove80.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
identifier: glove80
|
||||
name: Glove80
|
||||
url: https://www.moergo.com/
|
||||
type: mcu
|
||||
arch: arm
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
supported:
|
||||
- adc
|
||||
- usb_device
|
||||
- ble
|
||||
- ieee802154
|
||||
- pwm
|
||||
- watchdog
|
||||
- gpio
|
||||
- i2c
|
||||
- spi
|
||||
16
app/boards/arm/glove80/glove80.zmk.yml
Normal file
16
app/boards/arm/glove80/glove80.zmk.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
file_format: "1"
|
||||
id: glove80
|
||||
name: Glove80
|
||||
type: board
|
||||
arch: arm
|
||||
url: https://www.moergo.com/
|
||||
features:
|
||||
- keys
|
||||
- underglow
|
||||
- backlight
|
||||
outputs:
|
||||
- usb
|
||||
- ble
|
||||
siblings:
|
||||
- glove80_lh
|
||||
- glove80_rh
|
||||
47
app/boards/arm/glove80/glove80_lh-pinctrl.dtsi
Normal file
47
app/boards/arm/glove80/glove80_lh-pinctrl.dtsi
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
spi3_default: spi3_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_MOSI, 0, 27)>; // WS2812_VEXT_DATA
|
||||
};
|
||||
};
|
||||
|
||||
spi3_sleep: spi3_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_MOSI, 0, 27)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 1, 15)>; // rear LED
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_sleep: pwm0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 1, 15)>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 22)>, // EXT1
|
||||
<NRF_PSEL(UART_RX, 0, 21)>; // EXT2
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 22)>,
|
||||
<NRF_PSEL(UART_RX, 0, 21)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
101
app/boards/arm/glove80/glove80_lh.dts
Normal file
101
app/boards/arm/glove80/glove80_lh.dts
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "glove80.dtsi"
|
||||
#include "glove80_lh-pinctrl.dtsi"
|
||||
|
||||
#include <dt-bindings/led/led.h>
|
||||
|
||||
/ {
|
||||
model = "glove80_lh";
|
||||
compatible = "glove80_lh";
|
||||
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
zmk,backlight = &back_led_backlight;
|
||||
zmk,battery = &vbatt;
|
||||
};
|
||||
|
||||
back_led_backlight: pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
label = "BACK LED";
|
||||
pwm_led_0 {
|
||||
pwms = <&pwm0 0 PWM_USEC(20) PWM_POLARITY_NORMAL>;
|
||||
label = "Back LED configured as backlight";
|
||||
};
|
||||
};
|
||||
|
||||
ext-power {
|
||||
compatible = "zmk,ext-power-generic";
|
||||
label = "EXT_POWER";
|
||||
control-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; /* WS2812_CE */
|
||||
init-delay-ms = <100>;
|
||||
};
|
||||
|
||||
vbatt: vbatt {
|
||||
compatible = "zmk,battery-nrf-vddh";
|
||||
label = "BATTERY";
|
||||
};
|
||||
};
|
||||
|
||||
&spi3 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
|
||||
pinctrl-0 = <&spi3_default>;
|
||||
pinctrl-1 = <&spi3_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812C-2020";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <40>; /* 40 keys have underglow at the moment */
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&pwm0_default>;
|
||||
pinctrl-1 = <&pwm0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
&kscan0 {
|
||||
row-gpios
|
||||
= <&gpio0 26 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW1
|
||||
, <&gpio0 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW2
|
||||
, <&gpio0 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW3
|
||||
, <&gpio0 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW4
|
||||
, <&gpio0 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW5
|
||||
, <&gpio1 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW6
|
||||
;
|
||||
col-gpios
|
||||
= <&gpio1 8 GPIO_ACTIVE_HIGH> // LH COL6
|
||||
, <&gpio1 4 GPIO_ACTIVE_HIGH> // LH COL5
|
||||
, <&gpio1 6 GPIO_ACTIVE_HIGH> // LH COL4
|
||||
, <&gpio1 7 GPIO_ACTIVE_HIGH> // LH COL3
|
||||
, <&gpio1 5 GPIO_ACTIVE_HIGH> // LH COL2
|
||||
, <&gpio1 3 GPIO_ACTIVE_HIGH> // LH COL1
|
||||
, <&gpio1 1 GPIO_ACTIVE_HIGH> // LH Thumb
|
||||
;
|
||||
};
|
||||
7
app/boards/arm/glove80/glove80_lh.keymap
Normal file
7
app/boards/arm/glove80/glove80_lh.keymap
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "glove80.keymap"
|
||||
92
app/boards/arm/glove80/glove80_lh_defconfig
Normal file
92
app/boards/arm/glove80/glove80_lh_defconfig
Normal file
@@ -0,0 +1,92 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
CONFIG_SOC_SERIES_NRF52X=y
|
||||
CONFIG_SOC_NRF52840_QIAA=y
|
||||
CONFIG_BOARD_GLOVE80_LH=y
|
||||
|
||||
# Enable both USB and BLE
|
||||
CONFIG_ZMK_USB=y
|
||||
CONFIG_ZMK_BLE=y
|
||||
|
||||
# Keyboard IDs
|
||||
CONFIG_ZMK_KEYBOARD_NAME="Glove80 Left"
|
||||
CONFIG_USB_DEVICE_PID=0x27db
|
||||
CONFIG_USB_DEVICE_VID=0x16c0
|
||||
CONFIG_USB_DEVICE_MANUFACTURER="MoErgo"
|
||||
CONFIG_USB_DEVICE_SN="moergo.com:GLV80-0123456789ABCDEF"
|
||||
|
||||
CONFIG_BT_DIS_PNP_PID=0x27db
|
||||
CONFIG_BT_DIS_PNP_VID=0x16c0
|
||||
CONFIG_BT_DIS_MANUF="MoErgo"
|
||||
CONFIG_BT_DIS_MODEL="Glove80"
|
||||
|
||||
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
|
||||
|
||||
# Work-around for Windows bug with battery notifications
|
||||
CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# Build configurations
|
||||
CONFIG_BUILD_OUTPUT_UF2=y
|
||||
CONFIG_BUILD_OUTPUT_UF2_FAMILY_ID="0x9807B007"
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
|
||||
# Flash configuration
|
||||
CONFIG_MPU_ALLOW_FLASH_WRITE=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS_NVS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
|
||||
# Enable 32kHz crystal
|
||||
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
|
||||
|
||||
# Enable RGB underglow
|
||||
CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=y
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP=4
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN=4
|
||||
|
||||
# DO NOT CHANGE CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX TO ABOVE 80. Configuring
|
||||
# BRT_MAX above 80% will draw additional current and can potentially damage your
|
||||
# computer. WARRANTY IS VOID IF BRT_MAX SET ABOVE 80.
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX=80
|
||||
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=285
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_SAT_START=75
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=16
|
||||
|
||||
# The power LED is implemented as a backlight
|
||||
# For now, the power LED is acting as a "USB connected" indicator
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
||||
CONFIG_ZMK_BACKLIGHT_ON_START=y
|
||||
CONFIG_ZMK_BACKLIGHT_BRT_START=5
|
||||
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE=y
|
||||
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB=y
|
||||
|
||||
# The full two-byte consumer report space has compatibility issues with some
|
||||
# operating systems, most notably macOS. Use the more basic single-byte usage
|
||||
# space.
|
||||
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
|
||||
|
||||
# Turn on debugging to disable optimization. Debug messages can result in larger
|
||||
# stacks, so enable stack protection and particularly a larger BLE peripheral stack.
|
||||
# CONFIG_DEBUG=y
|
||||
# CONFIG_DEBUG_THREAD_INFO=y
|
||||
# CONFIG_EXCEPTION_STACK_TRACE=y
|
||||
# CONFIG_HW_STACK_PROTECTION=y
|
||||
# CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE=1300
|
||||
|
||||
# Log via USB or Segger RTT
|
||||
CONFIG_ZMK_USB_LOGGING=n
|
||||
CONFIG_ZMK_RTT_LOGGING=n
|
||||
48
app/boards/arm/glove80/glove80_rh-pinctrl.dtsi
Normal file
48
app/boards/arm/glove80/glove80_rh-pinctrl.dtsi
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
spi3_default: spi3_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_MOSI, 0, 13)>; // WS2812_VEXT_DATA
|
||||
};
|
||||
};
|
||||
|
||||
spi3_sleep: spi3_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_MOSI, 0, 13)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 16)>; // Rear LED
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_sleep: pwm0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 16)>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 21)>, // EXT1
|
||||
<NRF_PSEL(UART_RX, 0, 24)>; // EXT2
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 21)>,
|
||||
<NRF_PSEL(UART_RX, 0, 24)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
108
app/boards/arm/glove80/glove80_rh.dts
Normal file
108
app/boards/arm/glove80/glove80_rh.dts
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#include "glove80.dtsi"
|
||||
#include "glove80_rh-pinctrl.dtsi"
|
||||
|
||||
#include <dt-bindings/led/led.h>
|
||||
|
||||
/ {
|
||||
model = "glove80_rh";
|
||||
compatible = "glove80_rh";
|
||||
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
zmk,backlight = &back_led_backlight;
|
||||
zmk,battery = &vbatt;
|
||||
};
|
||||
|
||||
back_led_backlight: pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
label = "BACK LED";
|
||||
pwm_led_0 {
|
||||
pwms = <&pwm0 0 PWM_USEC(20) PWM_POLARITY_NORMAL>;
|
||||
label = "Back LED configured as backlight";
|
||||
};
|
||||
};
|
||||
|
||||
ext-power {
|
||||
compatible = "zmk,ext-power-generic";
|
||||
label = "EXT_POWER";
|
||||
control-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; /* WS2812_CE */
|
||||
init-delay-ms = <100>;
|
||||
};
|
||||
|
||||
vbatt: vbatt {
|
||||
compatible = "zmk,battery-nrf-vddh";
|
||||
label = "BATTERY";
|
||||
};
|
||||
};
|
||||
|
||||
&spi3 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
|
||||
pinctrl-0 = <&spi3_default>;
|
||||
pinctrl-1 = <&spi3_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812C-2020";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <40>; /* 40 keys have underglow at the moment */
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&pwm0_default>;
|
||||
pinctrl-1 = <&pwm0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
/* For right hand, the columns are offset by 7 */
|
||||
&default_transform {
|
||||
col-offset = <7>;
|
||||
};
|
||||
|
||||
&kscan0 {
|
||||
row-gpios
|
||||
= <&gpio0 26 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW1
|
||||
, <&gpio0 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW2
|
||||
, <&gpio0 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW3
|
||||
, <&gpio1 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW4
|
||||
, <&gpio0 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW5
|
||||
, <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW6
|
||||
;
|
||||
col-gpios
|
||||
= <&gpio1 6 GPIO_ACTIVE_HIGH> // RH Thumb
|
||||
, <&gpio1 4 GPIO_ACTIVE_HIGH> // RH COL1
|
||||
, <&gpio0 2 GPIO_ACTIVE_HIGH> // RH COL2
|
||||
, <&gpio1 7 GPIO_ACTIVE_HIGH> // RH COL3
|
||||
, <&gpio1 5 GPIO_ACTIVE_HIGH> // RH COL4
|
||||
, <&gpio1 3 GPIO_ACTIVE_HIGH> // RH COL5
|
||||
, <&gpio1 1 GPIO_ACTIVE_HIGH> // RH COL6
|
||||
;
|
||||
};
|
||||
7
app/boards/arm/glove80/glove80_rh.keymap
Normal file
7
app/boards/arm/glove80/glove80_rh.keymap
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "glove80.keymap"
|
||||
89
app/boards/arm/glove80/glove80_rh_defconfig
Normal file
89
app/boards/arm/glove80/glove80_rh_defconfig
Normal file
@@ -0,0 +1,89 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
CONFIG_SOC_SERIES_NRF52X=y
|
||||
CONFIG_SOC_NRF52840_QIAA=y
|
||||
CONFIG_BOARD_GLOVE80_RH=y
|
||||
|
||||
# Enable both USB and BLE
|
||||
CONFIG_ZMK_USB=y
|
||||
CONFIG_ZMK_BLE=y
|
||||
|
||||
# Keyboard IDs
|
||||
CONFIG_ZMK_KEYBOARD_NAME="Glove80 Right"
|
||||
CONFIG_USB_DEVICE_PID=0x27d9
|
||||
CONFIG_USB_DEVICE_VID=0x16c0
|
||||
CONFIG_USB_DEVICE_MANUFACTURER="MoErgo"
|
||||
CONFIG_USB_DEVICE_SN="moergo.com:GLV80-0123456789ABCDEF"
|
||||
|
||||
CONFIG_BT_DIS_PNP_PID=0x27d9
|
||||
CONFIG_BT_DIS_PNP_VID=0x16c0
|
||||
CONFIG_BT_DIS_MANUF="MoErgo"
|
||||
CONFIG_BT_DIS_MODEL="Glove80 Right"
|
||||
|
||||
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# Build configurations
|
||||
CONFIG_BUILD_OUTPUT_UF2=y
|
||||
CONFIG_BUILD_OUTPUT_UF2_FAMILY_ID="0x9808B007"
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
|
||||
# Flash configuration
|
||||
CONFIG_MPU_ALLOW_FLASH_WRITE=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS_NVS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
|
||||
# Enable 32kHz crystal
|
||||
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
|
||||
|
||||
# Enable RGB underglow
|
||||
CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=y
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP=4
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN=4
|
||||
|
||||
# DO NOT CHANGE CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX TO ABOVE 80. Configuring
|
||||
# BRT_MAX above 80% will draw additional current and can potentially damage your
|
||||
# computer. WARRANTY IS VOID IF BRT_MAX SET ABOVE 80.
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX=80
|
||||
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=285
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_SAT_START=75
|
||||
CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=16
|
||||
|
||||
# The power LED is implemented as a backlight
|
||||
# For now, the power LED is acting as a "USB connected" indicator
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
||||
CONFIG_ZMK_BACKLIGHT_ON_START=y
|
||||
CONFIG_ZMK_BACKLIGHT_BRT_START=5
|
||||
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE=y
|
||||
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB=y
|
||||
|
||||
# The full two-byte consumer report space has compatibility issues with some
|
||||
# operating systems, most notably macOS. Use the more basic single-byte usage
|
||||
# space.
|
||||
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
|
||||
|
||||
# Turn on debugging to disable optimization. Debug messages can result in larger
|
||||
# stacks, so enable stack protection and particularly a larger BLE peripheral stack.
|
||||
# CONFIG_DEBUG=y
|
||||
# CONFIG_DEBUG_THREAD_INFO=y
|
||||
# CONFIG_EXCEPTION_STACK_TRACE=y
|
||||
# CONFIG_HW_STACK_PROTECTION=y
|
||||
# CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE=1300
|
||||
|
||||
# Log via USB or Segger RTT
|
||||
CONFIG_ZMK_USB_LOGGING=n
|
||||
CONFIG_ZMK_RTT_LOGGING=n
|
||||
13
app/boards/arm/glove80/readme.md
Normal file
13
app/boards/arm/glove80/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## MoErgo Glove80
|
||||
|
||||
This board definition provides ZMK support for the [MoErgo Glove80](https://www.moergo.com)
|
||||
keyboard.
|
||||
|
||||
MoErgo additionally offers a customized version of ZMK which adds additional functionality such as
|
||||
RGB status indicators, available on GitHub at [moergo-sc/zmk](https://github.com/moergo-sc/zmk). The
|
||||
MoErgo customized ZMK fork is regularly updated to include the latest changes from mainline ZMK, but
|
||||
will not always be completely up-to-date. MoErgo also offers an online layout configurator and
|
||||
firmware builder application using the customized fork at [my.glove80.com](https://my.glove80.com).
|
||||
|
||||
While mainline ZMK is expected to work well with Glove80, MoErgo only provides support for use of
|
||||
their customized fork. Likewise, the ZMK community cannot directly provide support for MoErgo's fork.
|
||||
67
app/boards/arm/glove80/usb_serial_number.c
Normal file
67
app/boards/arm/glove80/usb_serial_number.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <zephyr/usb/usb_device.h>
|
||||
#include <zephyr/drivers/hwinfo.h>
|
||||
#include "usb_descriptor.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(usb_descriptor);
|
||||
|
||||
int base16_encode(const uint8_t *data, int length, uint8_t *result, int bufSize);
|
||||
|
||||
uint8_t *usb_update_sn_string_descriptor(void) {
|
||||
/*
|
||||
* nrf52840 hwinfo returns a 64-bit hardware id. Glove80 uses this as a
|
||||
* serial number, encoded as base16 into the last 16 characters of the
|
||||
* CONFIG_USB_DEVICE_SN template. If insufficient template space is
|
||||
* available, instead return the static serial number string.
|
||||
*/
|
||||
const uint8_t template_len = sizeof(CONFIG_USB_DEVICE_SN);
|
||||
const uint8_t sn_len = 16;
|
||||
|
||||
if (template_len < sn_len + 1) {
|
||||
LOG_DBG("Serial number template too short");
|
||||
return CONFIG_USB_DEVICE_SN;
|
||||
}
|
||||
|
||||
static uint8_t serial[sizeof(CONFIG_USB_DEVICE_SN)];
|
||||
strncpy(serial, CONFIG_USB_DEVICE_SN, template_len);
|
||||
|
||||
uint8_t hwid[8];
|
||||
memset(hwid, 0, sizeof(hwid));
|
||||
uint8_t hwlen = hwinfo_get_device_id(hwid, sizeof(hwid));
|
||||
|
||||
if (hwlen > 0) {
|
||||
const uint8_t offset = template_len - sn_len - 1;
|
||||
LOG_HEXDUMP_DBG(&hwid, sn_len, "Serial Number");
|
||||
base16_encode(hwid, hwlen, serial + offset, sn_len + 1);
|
||||
}
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
int base16_encode(const uint8_t *data, int length, uint8_t *result, int bufSize) {
|
||||
const char hex[] = "0123456789ABCDEF";
|
||||
|
||||
int i = 0;
|
||||
while (i < bufSize && i < length * 2) {
|
||||
uint8_t nibble;
|
||||
if (i % 2 == 0) {
|
||||
nibble = data[i / 2] >> 4;
|
||||
} else {
|
||||
nibble = data[i / 2] & 0xF;
|
||||
}
|
||||
result[i] = hex[nibble];
|
||||
++i;
|
||||
}
|
||||
if (i < bufSize) {
|
||||
result[i] = '\0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -18,4 +18,5 @@
|
||||
#include <behaviors/caps_word.dtsi>
|
||||
#include <behaviors/key_repeat.dtsi>
|
||||
#include <behaviors/backlight.dtsi>
|
||||
#include <behaviors/macros.dtsi>
|
||||
#include <behaviors/macros.dtsi>
|
||||
#include <behaviors/mouse_key_press.dtsi>
|
||||
|
||||
9
app/dts/behaviors/mouse_key_press.dtsi
Normal file
9
app/dts/behaviors/mouse_key_press.dtsi
Normal file
@@ -0,0 +1,9 @@
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ mkp: behavior_mouse_key_press {
|
||||
compatible = "zmk,behavior-mouse-key-press";
|
||||
label = "MOUSE_KEY_PRESS";
|
||||
#binding-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
description: Mouse key press/release behavior
|
||||
|
||||
compatible: "zmk,behavior-mouse-key-press"
|
||||
|
||||
include: one_param.yaml
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BT_PRV_CMD 2
|
||||
#define BT_SEL_CMD 3
|
||||
// #define BT_FULL_RESET_CMD 4
|
||||
#define BT_DISC_CMD 5
|
||||
|
||||
/*
|
||||
Note: Some future commands will include additional parameters, so we
|
||||
@@ -19,3 +20,4 @@ defines these aliases up front.
|
||||
#define BT_NXT BT_NXT_CMD 0
|
||||
#define BT_PRV BT_PRV_CMD 0
|
||||
#define BT_SEL BT_SEL_CMD
|
||||
#define BT_DISC BT_DISC_CMD
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define HID_USAGE_GDV (0x06) // Generic Device Controls
|
||||
#define HID_USAGE_KEY (0x07) // Keyboard/Keypad
|
||||
#define HID_USAGE_LED (0x08) // LED
|
||||
#define HID_USAGE_BUTTON (0x09) // Button
|
||||
#define HID_USAGE_TELEPHONY (0x0B) // Telephony Device
|
||||
#define HID_USAGE_CONSUMER (0x0C) // Consumer
|
||||
#define HID_USAGE_DIGITIZERS (0x0D) // Digitizers
|
||||
|
||||
24
app/include/dt-bindings/zmk/mouse.h
Normal file
24
app/include/dt-bindings/zmk/mouse.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <zephyr/dt-bindings/dt-util.h>
|
||||
|
||||
/* Mouse press behavior */
|
||||
/* Left click */
|
||||
#define MB1 BIT(0)
|
||||
#define LCLK (MB1)
|
||||
|
||||
/* Right click */
|
||||
#define MB2 BIT(1)
|
||||
#define RCLK (MB2)
|
||||
|
||||
/* Middle click */
|
||||
#define MB3 BIT(2)
|
||||
#define MCLK (MB3)
|
||||
|
||||
#define MB4 BIT(3)
|
||||
#define MB5 BIT(4)
|
||||
@@ -24,8 +24,10 @@ int zmk_ble_clear_bonds();
|
||||
int zmk_ble_prof_next();
|
||||
int zmk_ble_prof_prev();
|
||||
int zmk_ble_prof_select(uint8_t index);
|
||||
int zmk_ble_prof_disconnect(uint8_t index);
|
||||
|
||||
int zmk_ble_active_profile_index();
|
||||
int zmk_ble_profile_index(const bt_addr_le_t *addr);
|
||||
bt_addr_le_t *zmk_ble_active_profile_addr();
|
||||
bool zmk_ble_active_profile_is_open();
|
||||
bool zmk_ble_active_profile_is_connected();
|
||||
|
||||
@@ -69,3 +69,7 @@ int zmk_endpoints_toggle_transport(void);
|
||||
struct zmk_endpoint_instance zmk_endpoints_selected(void);
|
||||
|
||||
int zmk_endpoints_send_report(uint16_t usage_page);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_endpoints_send_mouse_report();
|
||||
#endif // IS_ENABLE(CONFIG_ZMK_MOUSE)
|
||||
|
||||
16
app/include/zmk/events/hid_indicators_changed.h
Normal file
16
app/include/zmk/events/hid_indicators_changed.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/hid_indicators_types.h>
|
||||
#include <zmk/event_manager.h>
|
||||
|
||||
struct zmk_hid_indicators_changed {
|
||||
zmk_hid_indicators_t indicators;
|
||||
};
|
||||
|
||||
ZMK_EVENT_DECLARE(zmk_hid_indicators_changed);
|
||||
26
app/include/zmk/events/mouse_button_state_changed.h
Normal file
26
app/include/zmk/events/mouse_button_state_changed.h
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/mouse.h>
|
||||
|
||||
struct zmk_mouse_button_state_changed {
|
||||
zmk_mouse_button_t buttons;
|
||||
bool state;
|
||||
int64_t timestamp;
|
||||
};
|
||||
|
||||
ZMK_EVENT_DECLARE(zmk_mouse_button_state_changed);
|
||||
|
||||
static inline struct zmk_mouse_button_state_changed_event *
|
||||
zmk_mouse_button_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
||||
return new_zmk_mouse_button_state_changed((struct zmk_mouse_button_state_changed){
|
||||
.buttons = ZMK_HID_USAGE_ID(encoded), .state = pressed, .timestamp = timestamp});
|
||||
}
|
||||
@@ -10,10 +10,15 @@
|
||||
#include <zephyr/usb/class/usb_hid.h>
|
||||
|
||||
#include <zmk/keys.h>
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
#include <zmk/mouse.h>
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
#include <dt-bindings/zmk/hid_usage.h>
|
||||
#include <dt-bindings/zmk/hid_usage_pages.h>
|
||||
|
||||
#define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL
|
||||
#define ZMK_HID_MOUSE_NUM_BUTTONS 0x05
|
||||
|
||||
// See https://www.usb.org/sites/default/files/hid1_11.pdf section 6.2.2.4 Main Items
|
||||
|
||||
@@ -45,7 +50,9 @@
|
||||
#define ZMK_HID_MAIN_VAL_BUFFERED_BYTES (0x01 << 8)
|
||||
|
||||
#define ZMK_HID_REPORT_ID_KEYBOARD 0x01
|
||||
#define ZMK_HID_REPORT_ID_LEDS 0x01
|
||||
#define ZMK_HID_REPORT_ID_CONSUMER 0x02
|
||||
#define ZMK_HID_REPORT_ID_MOUSE 0x03
|
||||
|
||||
static const uint8_t zmk_hid_report_desc[] = {
|
||||
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP),
|
||||
@@ -67,6 +74,22 @@ static const uint8_t zmk_hid_report_desc[] = {
|
||||
HID_REPORT_COUNT(0x01),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
HID_USAGE_PAGE(HID_USAGE_LED),
|
||||
HID_USAGE_MIN8(HID_USAGE_LED_NUM_LOCK),
|
||||
HID_USAGE_MAX8(HID_USAGE_LED_KANA),
|
||||
HID_REPORT_SIZE(0x01),
|
||||
HID_REPORT_COUNT(0x05),
|
||||
HID_OUTPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
|
||||
|
||||
HID_USAGE_PAGE(HID_USAGE_LED),
|
||||
HID_REPORT_SIZE(0x03),
|
||||
HID_REPORT_COUNT(0x01),
|
||||
HID_OUTPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
HID_USAGE_PAGE(HID_USAGE_KEY),
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
|
||||
@@ -114,6 +137,39 @@ static const uint8_t zmk_hid_report_desc[] = {
|
||||
HID_REPORT_COUNT(CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS),
|
||||
HID_END_COLLECTION,
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
HID_USAGE_PAGE(HID_USAGE_GD),
|
||||
HID_USAGE(HID_USAGE_GD_MOUSE),
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION),
|
||||
HID_REPORT_ID(ZMK_HID_REPORT_ID_MOUSE),
|
||||
HID_USAGE(HID_USAGE_GD_POINTER),
|
||||
HID_COLLECTION(HID_COLLECTION_PHYSICAL),
|
||||
HID_USAGE_PAGE(HID_USAGE_BUTTON),
|
||||
HID_USAGE_MIN8(0x1),
|
||||
HID_USAGE_MAX8(ZMK_HID_MOUSE_NUM_BUTTONS),
|
||||
HID_LOGICAL_MIN8(0x00),
|
||||
HID_LOGICAL_MAX8(0x01),
|
||||
HID_REPORT_SIZE(0x01),
|
||||
HID_REPORT_COUNT(0x5),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
|
||||
// Constant padding for the last 3 bits.
|
||||
HID_REPORT_SIZE(0x03),
|
||||
HID_REPORT_COUNT(0x01),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
|
||||
// Some OSes ignore pointer devices without X/Y data.
|
||||
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP),
|
||||
HID_USAGE(HID_USAGE_GD_X),
|
||||
HID_USAGE(HID_USAGE_GD_Y),
|
||||
HID_USAGE(HID_USAGE_GD_WHEEL),
|
||||
HID_LOGICAL_MIN8(-0x7F),
|
||||
HID_LOGICAL_MAX8(0x7F),
|
||||
HID_REPORT_SIZE(0x08),
|
||||
HID_REPORT_COUNT(0x03),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL),
|
||||
HID_END_COLLECTION,
|
||||
HID_END_COLLECTION,
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||
@@ -150,6 +206,19 @@ struct zmk_hid_keyboard_report {
|
||||
struct zmk_hid_keyboard_report_body body;
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
struct zmk_hid_led_report_body {
|
||||
uint8_t leds;
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_led_report {
|
||||
uint8_t report_id;
|
||||
struct zmk_hid_led_report_body body;
|
||||
} __packed;
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
struct zmk_hid_consumer_report_body {
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC)
|
||||
uint8_t keys[CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE];
|
||||
@@ -163,6 +232,21 @@ struct zmk_hid_consumer_report {
|
||||
struct zmk_hid_consumer_report_body body;
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
struct zmk_hid_mouse_report_body {
|
||||
zmk_mouse_button_flags_t buttons;
|
||||
int8_t d_x;
|
||||
int8_t d_y;
|
||||
int8_t d_wheel;
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_mouse_report {
|
||||
uint8_t report_id;
|
||||
struct zmk_hid_mouse_report_body body;
|
||||
} __packed;
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
zmk_mod_flags_t zmk_hid_get_explicit_mods();
|
||||
int zmk_hid_register_mod(zmk_mod_t modifier);
|
||||
int zmk_hid_unregister_mod(zmk_mod_t modifier);
|
||||
@@ -189,9 +273,21 @@ int zmk_hid_press(uint32_t usage);
|
||||
int zmk_hid_release(uint32_t usage);
|
||||
bool zmk_hid_is_pressed(uint32_t usage);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_hid_mouse_button_press(zmk_mouse_button_t button);
|
||||
int zmk_hid_mouse_button_release(zmk_mouse_button_t button);
|
||||
int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons);
|
||||
int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons);
|
||||
void zmk_hid_mouse_clear();
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||
zmk_hid_boot_report_t *zmk_hid_get_boot_report();
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
struct zmk_hid_mouse_report *zmk_hid_get_mouse_report();
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
19
app/include/zmk/hid_indicators.h
Normal file
19
app/include/zmk/hid_indicators.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/endpoints_types.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/hid_indicators_types.h>
|
||||
|
||||
zmk_hid_indicators_t zmk_hid_indicators_get_current_profile(void);
|
||||
zmk_hid_indicators_t zmk_hid_indicators_get_profile(struct zmk_endpoint_instance endpoint);
|
||||
void zmk_hid_indicators_set_profile(zmk_hid_indicators_t indicators,
|
||||
struct zmk_endpoint_instance endpoint);
|
||||
|
||||
void zmk_hid_indicators_process_report(struct zmk_hid_led_report_body *report,
|
||||
struct zmk_endpoint_instance endpoint);
|
||||
9
app/include/zmk/hid_indicators_types.h
Normal file
9
app/include/zmk/hid_indicators_types.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef uint8_t zmk_hid_indicators_t;
|
||||
@@ -13,3 +13,7 @@ int zmk_hog_init();
|
||||
|
||||
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *body);
|
||||
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *body);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *body);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
12
app/include/zmk/mouse.h
Normal file
12
app/include/zmk/mouse.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
typedef uint8_t zmk_mouse_button_flags_t;
|
||||
typedef uint16_t zmk_mouse_button_t;
|
||||
@@ -4,5 +4,15 @@
|
||||
#include <zephyr/bluetooth/addr.h>
|
||||
#include <zmk/behavior.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
#include <zmk/hid_indicators_types.h>
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event, bool state);
|
||||
struct zmk_behavior_binding_event event, bool state);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators);
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
@@ -17,3 +17,4 @@
|
||||
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
|
||||
#define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002)
|
||||
#define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000003)
|
||||
#define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004)
|
||||
|
||||
@@ -10,4 +10,7 @@
|
||||
|
||||
int zmk_usb_hid_send_keyboard_report();
|
||||
int zmk_usb_hid_send_consumer_report();
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_usb_hid_send_mouse_report();
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
void zmk_usb_hid_set_protocol(uint8_t protocol);
|
||||
|
||||
@@ -18,6 +18,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/battery.h>
|
||||
#include <zmk/events/battery_state_changed.h>
|
||||
#include <zmk/events/activity_state_changed.h>
|
||||
#include <zmk/activity.h>
|
||||
#include <zmk/workqueue.h>
|
||||
|
||||
static uint8_t last_state_of_charge = 0;
|
||||
@@ -51,7 +53,7 @@ static int zmk_battery_update(const struct device *battery) {
|
||||
|
||||
if (last_state_of_charge != state_of_charge.val1) {
|
||||
last_state_of_charge = state_of_charge.val1;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_BAS)
|
||||
LOG_DBG("Setting BAS GATT battery level to %d.", last_state_of_charge);
|
||||
|
||||
rc = bt_bas_set_battery_level(last_state_of_charge);
|
||||
@@ -60,7 +62,7 @@ static int zmk_battery_update(const struct device *battery) {
|
||||
LOG_WRN("Failed to set BAS GATT battery level (err %d)", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
rc = ZMK_EVENT_RAISE(new_zmk_battery_state_changed(
|
||||
(struct zmk_battery_state_changed){.state_of_charge = last_state_of_charge}));
|
||||
}
|
||||
@@ -84,6 +86,10 @@ static void zmk_battery_timer(struct k_timer *timer) {
|
||||
|
||||
K_TIMER_DEFINE(battery_timer, zmk_battery_timer, NULL);
|
||||
|
||||
static void zmk_battery_start_reporting() {
|
||||
k_timer_start(&battery_timer, K_NO_WAIT, K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL));
|
||||
}
|
||||
|
||||
static int zmk_battery_init(const struct device *_arg) {
|
||||
#if !DT_HAS_CHOSEN(zmk_battery)
|
||||
battery = device_get_binding("BATTERY");
|
||||
@@ -100,9 +106,30 @@ static int zmk_battery_init(const struct device *_arg) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
k_timer_start(&battery_timer, K_NO_WAIT, K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL));
|
||||
|
||||
zmk_battery_start_reporting();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int battery_event_listener(const zmk_event_t *eh) {
|
||||
|
||||
if (as_zmk_activity_state_changed(eh)) {
|
||||
switch (zmk_activity_get_state()) {
|
||||
case ZMK_ACTIVITY_ACTIVE:
|
||||
zmk_battery_start_reporting();
|
||||
return 0;
|
||||
case ZMK_ACTIVITY_IDLE:
|
||||
case ZMK_ACTIVITY_SLEEP:
|
||||
k_timer_stop(&battery_timer);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(battery, battery_event_listener);
|
||||
|
||||
ZMK_SUBSCRIPTION(battery, zmk_activity_state_changed);
|
||||
|
||||
SYS_INIT(zmk_battery_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
||||
@@ -31,6 +31,8 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
return zmk_ble_prof_prev();
|
||||
case BT_SEL_CMD:
|
||||
return zmk_ble_prof_select(binding->param2);
|
||||
case BT_DISC_CMD:
|
||||
return zmk_ble_prof_disconnect(binding->param2);
|
||||
default:
|
||||
LOG_ERR("Unknown BT command: %d", binding->param1);
|
||||
}
|
||||
|
||||
48
app/src/behaviors/behavior_mouse_key_press.c
Normal file
48
app/src/behaviors/behavior_mouse_key_press.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_mouse_key_press
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/mouse_button_state_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
static int behavior_mouse_key_press_init(const struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
|
||||
return ZMK_EVENT_RAISE(
|
||||
zmk_mouse_button_state_changed_from_encoded(binding->param1, true, event.timestamp));
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
return ZMK_EVENT_RAISE(
|
||||
zmk_mouse_button_state_changed_from_encoded(binding->param1, false, event.timestamp));
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_mouse_key_press_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
||||
|
||||
#define MKP_INST(n) \
|
||||
DEVICE_DT_INST_DEFINE(n, behavior_mouse_key_press_init, NULL, NULL, NULL, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_mouse_key_press_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(MKP_INST)
|
||||
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
||||
@@ -224,6 +224,15 @@ int zmk_ble_clear_bonds() {
|
||||
|
||||
int zmk_ble_active_profile_index() { return active_profile; }
|
||||
|
||||
int zmk_ble_profile_index(const bt_addr_le_t *addr) {
|
||||
for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) {
|
||||
if (bt_addr_le_cmp(addr, &profiles[i].peer) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
static void ble_save_profile_work(struct k_work *work) {
|
||||
settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile));
|
||||
@@ -271,6 +280,27 @@ int zmk_ble_prof_prev() {
|
||||
ZMK_BLE_PROFILE_COUNT);
|
||||
};
|
||||
|
||||
int zmk_ble_prof_disconnect(uint8_t index) {
|
||||
if (index >= ZMK_BLE_PROFILE_COUNT)
|
||||
return -ERANGE;
|
||||
|
||||
bt_addr_le_t *addr = &profiles[index].peer;
|
||||
struct bt_conn *conn;
|
||||
int result;
|
||||
|
||||
if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
|
||||
return -ENODEV;
|
||||
} else if ((conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr)) == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
result = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
LOG_DBG("Disconnected from profile %d: %d", index, result);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
return result;
|
||||
}
|
||||
|
||||
bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].peer; }
|
||||
|
||||
char *zmk_ble_active_profile_name() { return profiles[active_profile].name; }
|
||||
|
||||
@@ -191,6 +191,36 @@ int zmk_endpoints_send_report(uint16_t usage_page) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_endpoints_send_mouse_report() {
|
||||
switch (current_instance.transport) {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||
case ZMK_TRANSPORT_USB: {
|
||||
int err = zmk_usb_hid_send_mouse_report();
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
case ZMK_TRANSPORT_BLE: {
|
||||
struct zmk_hid_mouse_report *mouse_report = zmk_hid_get_mouse_report();
|
||||
int err = zmk_hog_send_mouse_report(&mouse_report->body);
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */
|
||||
}
|
||||
|
||||
LOG_ERR("Unsupported endpoint transport %d", current_instance.transport);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
|
||||
static int endpoints_handle_set(const char *name, size_t len, settings_read_cb read_cb,
|
||||
@@ -295,6 +325,9 @@ static int zmk_endpoints_init(const struct device *_arg) {
|
||||
static void disconnect_current_endpoint() {
|
||||
zmk_hid_keyboard_clear();
|
||||
zmk_hid_consumer_clear();
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
zmk_hid_mouse_clear();
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
zmk_endpoints_send_report(HID_USAGE_KEY);
|
||||
zmk_endpoints_send_report(HID_USAGE_CONSUMER);
|
||||
|
||||
10
app/src/events/hid_indicators_changed.c
Normal file
10
app/src/events/hid_indicators_changed.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zmk/events/hid_indicators_changed.h>
|
||||
|
||||
ZMK_EVENT_IMPL(zmk_hid_indicators_changed);
|
||||
9
app/src/events/mouse_button_state_changed.c
Normal file
9
app/src/events/mouse_button_state_changed.c
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zmk/events/mouse_button_state_changed.h>
|
||||
|
||||
ZMK_EVENT_IMPL(zmk_mouse_button_state_changed);
|
||||
@@ -12,6 +12,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#include <dt-bindings/zmk/modifiers.h>
|
||||
|
||||
static struct zmk_hid_keyboard_report keyboard_report = {
|
||||
|
||||
.report_id = ZMK_HID_REPORT_ID_KEYBOARD, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
|
||||
|
||||
static struct zmk_hid_consumer_report consumer_report = {.report_id = ZMK_HID_REPORT_ID_CONSUMER,
|
||||
@@ -24,6 +25,13 @@ static uint8_t keys_held = 0;
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static struct zmk_hid_mouse_report mouse_report = {.report_id = ZMK_HID_REPORT_ID_MOUSE,
|
||||
.body = {.buttons = 0}};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
// Keep track of how often a modifier was pressed.
|
||||
// Only release the modifier if the count is 0.
|
||||
static int explicit_modifier_counts[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
@@ -357,6 +365,71 @@ bool zmk_hid_is_pressed(uint32_t usage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
// Keep track of how often a button was pressed.
|
||||
// Only release the button if the count is 0.
|
||||
static int explicit_button_counts[5] = {0, 0, 0, 0, 0};
|
||||
static zmk_mod_flags_t explicit_buttons = 0;
|
||||
|
||||
#define SET_MOUSE_BUTTONS(btns) \
|
||||
{ \
|
||||
mouse_report.body.buttons = btns; \
|
||||
LOG_DBG("Mouse buttons set to 0x%02X", mouse_report.body.buttons); \
|
||||
}
|
||||
|
||||
int zmk_hid_mouse_button_press(zmk_mouse_button_t button) {
|
||||
if (button >= ZMK_HID_MOUSE_NUM_BUTTONS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
explicit_button_counts[button]++;
|
||||
LOG_DBG("Button %d count %d", button, explicit_button_counts[button]);
|
||||
WRITE_BIT(explicit_buttons, button, true);
|
||||
SET_MOUSE_BUTTONS(explicit_buttons);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmk_hid_mouse_button_release(zmk_mouse_button_t button) {
|
||||
if (button >= ZMK_HID_MOUSE_NUM_BUTTONS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (explicit_button_counts[button] <= 0) {
|
||||
LOG_ERR("Tried to release button %d too often", button);
|
||||
return -EINVAL;
|
||||
}
|
||||
explicit_button_counts[button]--;
|
||||
LOG_DBG("Button %d count: %d", button, explicit_button_counts[button]);
|
||||
if (explicit_button_counts[button] == 0) {
|
||||
LOG_DBG("Button %d released", button);
|
||||
WRITE_BIT(explicit_buttons, button, false);
|
||||
}
|
||||
SET_MOUSE_BUTTONS(explicit_buttons);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons) {
|
||||
for (zmk_mouse_button_t i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
|
||||
if (buttons & BIT(i)) {
|
||||
zmk_hid_mouse_button_press(i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons) {
|
||||
for (zmk_mouse_button_t i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
|
||||
if (buttons & BIT(i)) {
|
||||
zmk_hid_mouse_button_release(i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void zmk_hid_mouse_clear() { memset(&mouse_report.body, 0, sizeof(mouse_report.body)); }
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
||||
return &keyboard_report;
|
||||
}
|
||||
@@ -364,3 +437,11 @@ struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
|
||||
return &consumer_report;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
struct zmk_hid_mouse_report *zmk_hid_get_mouse_report() {
|
||||
return &mouse_report;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
69
app/src/hid_indicators.c
Normal file
69
app/src/hid_indicators.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <zmk/ble.h>
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/hid_indicators.h>
|
||||
#include <zmk/events/hid_indicators_changed.h>
|
||||
#include <zmk/events/endpoint_changed.h>
|
||||
#include <zmk/split/bluetooth/central.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
static zmk_hid_indicators_t hid_indicators[ZMK_ENDPOINT_COUNT];
|
||||
|
||||
zmk_hid_indicators_t zmk_hid_indicators_get_current_profile(void) {
|
||||
return zmk_hid_indicators_get_profile(zmk_endpoints_selected());
|
||||
}
|
||||
|
||||
zmk_hid_indicators_t zmk_hid_indicators_get_profile(struct zmk_endpoint_instance endpoint) {
|
||||
const int profile = zmk_endpoint_instance_to_index(endpoint);
|
||||
return hid_indicators[profile];
|
||||
}
|
||||
|
||||
static void raise_led_changed_event(struct k_work *_work) {
|
||||
const zmk_hid_indicators_t indicators = zmk_hid_indicators_get_current_profile();
|
||||
|
||||
ZMK_EVENT_RAISE(new_zmk_hid_indicators_changed(
|
||||
(struct zmk_hid_indicators_changed){.indicators = indicators}));
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) && IS_ENABLED(CONFIG_ZMK_SPLIT_BLE)
|
||||
zmk_split_bt_update_hid_indicator(indicators);
|
||||
#endif
|
||||
}
|
||||
|
||||
static K_WORK_DEFINE(led_changed_work, raise_led_changed_event);
|
||||
|
||||
void zmk_hid_indicators_set_profile(zmk_hid_indicators_t indicators,
|
||||
struct zmk_endpoint_instance endpoint) {
|
||||
int profile = zmk_endpoint_instance_to_index(endpoint);
|
||||
|
||||
// This write is not happening on the main thread. To prevent potential data races, every
|
||||
// operation involving hid_indicators must be atomic. Currently, each function either reads
|
||||
// or writes only one entry at a time, so it is safe to do these operations without a lock.
|
||||
hid_indicators[profile] = indicators;
|
||||
|
||||
k_work_submit(&led_changed_work);
|
||||
}
|
||||
|
||||
void zmk_hid_indicators_process_report(struct zmk_hid_led_report_body *report,
|
||||
struct zmk_endpoint_instance endpoint) {
|
||||
const zmk_hid_indicators_t indicators = (zmk_hid_indicators_t)report->leds;
|
||||
zmk_hid_indicators_set_profile(indicators, endpoint);
|
||||
|
||||
LOG_DBG("Update HID indicators: endpoint=%d, indicators=%x", endpoint.transport, indicators);
|
||||
}
|
||||
|
||||
static int profile_listener(const zmk_event_t *eh) {
|
||||
raise_led_changed_event(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ZMK_LISTENER(profile_listener, profile_listener);
|
||||
static ZMK_SUBSCRIPTION(profile_listener, zmk_endpoint_changed);
|
||||
133
app/src/hog.c
133
app/src/hog.c
@@ -15,8 +15,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <zmk/ble.h>
|
||||
#include <zmk/endpoints_types.h>
|
||||
#include <zmk/hog.h>
|
||||
#include <zmk/hid.h>
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
#include <zmk/hid_indicators.h>
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
enum {
|
||||
HIDS_REMOTE_WAKE = BIT(0),
|
||||
@@ -51,11 +55,29 @@ static struct hids_report input = {
|
||||
.type = HIDS_INPUT,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
static struct hids_report led_indicators = {
|
||||
.id = ZMK_HID_REPORT_ID_LEDS,
|
||||
.type = HIDS_OUTPUT,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
static struct hids_report consumer_input = {
|
||||
.id = ZMK_HID_REPORT_ID_CONSUMER,
|
||||
.type = HIDS_INPUT,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static struct hids_report mouse_input = {
|
||||
.id = ZMK_HID_REPORT_ID_MOUSE,
|
||||
.type = HIDS_INPUT,
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static bool host_requests_notification = false;
|
||||
static uint8_t ctrl_point;
|
||||
// static uint8_t proto_mode;
|
||||
@@ -85,6 +107,34 @@ static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt
|
||||
sizeof(struct zmk_hid_keyboard_report_body));
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
static ssize_t write_hids_leds_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
const void *buf, uint16_t len, uint16_t offset,
|
||||
uint8_t flags) {
|
||||
if (offset != 0) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
}
|
||||
if (len != sizeof(struct zmk_hid_led_report_body)) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
|
||||
}
|
||||
|
||||
struct zmk_hid_led_report_body *report = (struct zmk_hid_led_report_body *)buf;
|
||||
int profile = zmk_ble_profile_index(bt_conn_get_dst(conn));
|
||||
if (profile < 0) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
|
||||
}
|
||||
|
||||
struct zmk_endpoint_instance endpoint = {.transport = ZMK_TRANSPORT_BLE,
|
||||
.ble = {
|
||||
.profile_index = profile,
|
||||
}};
|
||||
zmk_hid_indicators_process_report(report, endpoint);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset) {
|
||||
@@ -93,6 +143,15 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
||||
sizeof(struct zmk_hid_consumer_report_body));
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
static ssize_t read_hids_mouse_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset) {
|
||||
struct zmk_hid_mouse_report_body *report_body = &zmk_hid_get_mouse_report()->body;
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
||||
sizeof(struct zmk_hid_mouse_report_body));
|
||||
}
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
// static ssize_t write_proto_mode(struct bt_conn *conn,
|
||||
// const struct bt_gatt_attr *attr,
|
||||
// const void *buf, uint16_t len, uint16_t offset,
|
||||
@@ -134,11 +193,30 @@ BT_GATT_SERVICE_DEFINE(
|
||||
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
|
||||
NULL, &input),
|
||||
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
|
||||
BT_GATT_PERM_READ_ENCRYPT, read_hids_consumer_input_report, NULL, NULL),
|
||||
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
|
||||
NULL, &consumer_input),
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
|
||||
BT_GATT_PERM_READ_ENCRYPT, read_hids_mouse_input_report, NULL, NULL),
|
||||
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
|
||||
NULL, &mouse_input),
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
|
||||
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||
write_hids_leds_report, NULL),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
|
||||
NULL, &led_indicators),
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
|
||||
BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point));
|
||||
|
||||
@@ -224,7 +302,7 @@ void send_consumer_report_callback(struct k_work *work) {
|
||||
}
|
||||
|
||||
struct bt_gatt_notify_params notify_params = {
|
||||
.attr = &hog_svc.attrs[10],
|
||||
.attr = &hog_svc.attrs[9],
|
||||
.data = &report,
|
||||
.len = sizeof(report),
|
||||
};
|
||||
@@ -261,6 +339,59 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
K_MSGQ_DEFINE(zmk_hog_mouse_msgq, sizeof(struct zmk_hid_mouse_report_body),
|
||||
CONFIG_ZMK_BLE_MOUSE_REPORT_QUEUE_SIZE, 4);
|
||||
|
||||
void send_mouse_report_callback(struct k_work *work) {
|
||||
struct zmk_hid_mouse_report_body report;
|
||||
while (k_msgq_get(&zmk_hog_mouse_msgq, &report, K_NO_WAIT) == 0) {
|
||||
struct bt_conn *conn = destination_connection();
|
||||
if (conn == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct bt_gatt_notify_params notify_params = {
|
||||
.attr = &hog_svc.attrs[13],
|
||||
.data = &report,
|
||||
.len = sizeof(report),
|
||||
};
|
||||
|
||||
int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
||||
if (err) {
|
||||
LOG_DBG("Error notifying %d", err);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
};
|
||||
|
||||
int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) {
|
||||
struct bt_conn *conn = destination_connection();
|
||||
if (conn == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct bt_gatt_notify_params notify_params = {
|
||||
.attr = &hog_svc.attrs[13],
|
||||
.data = report,
|
||||
.len = sizeof(*report),
|
||||
};
|
||||
|
||||
int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
||||
if (err) {
|
||||
LOG_DBG("Error notifying %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
int zmk_hog_init(const struct device *_arg) {
|
||||
static const struct k_work_queue_config queue_config = {.name = "HID Over GATT Send Work"};
|
||||
k_work_queue_start(&hog_work_q, hog_q_stack, K_THREAD_STACK_SIZEOF(hog_q_stack),
|
||||
|
||||
43
app/src/mouse.c
Normal file
43
app/src/mouse.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/events/mouse_button_state_changed.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/mouse.h>
|
||||
|
||||
static void listener_mouse_button_pressed(const struct zmk_mouse_button_state_changed *ev) {
|
||||
LOG_DBG("buttons: 0x%02X", ev->buttons);
|
||||
zmk_hid_mouse_buttons_press(ev->buttons);
|
||||
zmk_endpoints_send_mouse_report();
|
||||
}
|
||||
|
||||
static void listener_mouse_button_released(const struct zmk_mouse_button_state_changed *ev) {
|
||||
LOG_DBG("buttons: 0x%02X", ev->buttons);
|
||||
zmk_hid_mouse_buttons_release(ev->buttons);
|
||||
zmk_endpoints_send_mouse_report();
|
||||
}
|
||||
|
||||
int mouse_listener(const zmk_event_t *eh) {
|
||||
const struct zmk_mouse_button_state_changed *mbt_ev = as_zmk_mouse_button_state_changed(eh);
|
||||
if (mbt_ev) {
|
||||
if (mbt_ev->state) {
|
||||
listener_mouse_button_pressed(mbt_ev);
|
||||
} else {
|
||||
listener_mouse_button_released(mbt_ev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(mouse_listener, mouse_listener);
|
||||
ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_button_state_changed);
|
||||
@@ -20,6 +20,12 @@ config ZMK_SPLIT_BLE
|
||||
|
||||
endchoice
|
||||
|
||||
config ZMK_SPLIT_PERIPHERAL_HID_INDICATORS
|
||||
bool "Peripheral HID Indicators"
|
||||
depends on ZMK_HID_INDICATORS
|
||||
help
|
||||
Enable propogating the HID (LED) Indicator state to the split peripheral(s).
|
||||
|
||||
#ZMK_SPLIT
|
||||
endif
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
#include <zmk/events/sensor_event.h>
|
||||
#include <zmk/hid_indicators_types.h>
|
||||
|
||||
static int start_scanning(void);
|
||||
|
||||
@@ -46,6 +47,9 @@ struct peripheral_slot {
|
||||
struct bt_gatt_subscribe_params sensor_subscribe_params;
|
||||
struct bt_gatt_discover_params sub_discover_params;
|
||||
uint16_t run_behavior_handle;
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
uint16_t update_hid_indicators;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
uint8_t position_state[POSITION_STATE_DATA_LEN];
|
||||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||
};
|
||||
@@ -131,6 +135,9 @@ int release_peripheral_slot(int index) {
|
||||
// Clean up previously discovered handles;
|
||||
slot->subscribe_params.value_handle = 0;
|
||||
slot->run_behavior_handle = 0;
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
slot->update_hid_indicators = 0;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -329,13 +336,23 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
||||
slot->discover_params.uuid = NULL;
|
||||
slot->discover_params.start_handle = attr->handle + 2;
|
||||
slot->run_behavior_handle = bt_gatt_attr_value_handle(attr);
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID))) {
|
||||
LOG_DBG("Found update HID indicators handle");
|
||||
slot->update_hid_indicators = bt_gatt_attr_value_handle(attr);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
}
|
||||
|
||||
bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle;
|
||||
bool subscribed = (slot->run_behavior_handle && slot->subscribe_params.value_handle);
|
||||
#if ZMK_KEYMAP_HAS_SENSORS
|
||||
subscribed = subscribed && slot->sensor_subscribe_params.value_handle;
|
||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
subscribed = subscribed && slot->update_hid_indicators;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
return subscribed ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -685,6 +702,43 @@ int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *bi
|
||||
return split_bt_invoke_behavior_payload(wrapper);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
static zmk_hid_indicators_t hid_indicators = 0;
|
||||
|
||||
static void split_central_update_indicators_callback(struct k_work *work) {
|
||||
zmk_hid_indicators_t indicators = hid_indicators;
|
||||
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peripherals[i].update_hid_indicators == 0) {
|
||||
// It appears that sometimes the peripheral is considered connected
|
||||
// before the GATT characteristics have been discovered. If this is
|
||||
// the case, the update_hid_indicators handle will not yet be set.
|
||||
continue;
|
||||
}
|
||||
|
||||
int err = bt_gatt_write_without_response(peripherals[i].conn,
|
||||
peripherals[i].update_hid_indicators, &indicators,
|
||||
sizeof(indicators), true);
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to write HID indicator characteristic (err %d)", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static K_WORK_DEFINE(split_central_update_indicators, split_central_update_indicators_callback);
|
||||
|
||||
int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) {
|
||||
hid_indicators = indicators;
|
||||
return k_work_submit_to_queue(&split_central_split_run_q, &split_central_update_indicators);
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
int zmk_split_bt_central_init(const struct device *_arg) {
|
||||
k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack,
|
||||
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
|
||||
|
||||
@@ -21,6 +21,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#include <zmk/matrix.h>
|
||||
#include <zmk/split/bluetooth/uuid.h>
|
||||
#include <zmk/split/bluetooth/service.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
#include <zmk/events/hid_indicators_changed.h>
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
#include <zmk/events/sensor_event.h>
|
||||
#include <zmk/sensors.h>
|
||||
|
||||
@@ -105,6 +110,34 @@ static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, uint16_t va
|
||||
LOG_DBG("value %d", value);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
static zmk_hid_indicators_t hid_indicators = 0;
|
||||
|
||||
static void split_svc_update_indicators_callback(struct k_work *work) {
|
||||
LOG_DBG("Raising HID indicators changed event: %x", hid_indicators);
|
||||
ZMK_EVENT_RAISE(new_zmk_hid_indicators_changed(
|
||||
(struct zmk_hid_indicators_changed){.indicators = hid_indicators}));
|
||||
}
|
||||
|
||||
static K_WORK_DEFINE(split_svc_update_indicators_work, split_svc_update_indicators_callback);
|
||||
|
||||
static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
const void *buf, uint16_t len, uint16_t offset,
|
||||
uint8_t flags) {
|
||||
if (offset + len > sizeof(zmk_hid_indicators_t)) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)&hid_indicators + offset, buf, len);
|
||||
|
||||
k_work_submit(&split_svc_update_indicators_work);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
|
||||
BT_GATT_SERVICE_DEFINE(
|
||||
split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID),
|
||||
@@ -122,6 +155,11 @@ BT_GATT_SERVICE_DEFINE(
|
||||
split_svc_sensor_state, NULL, &last_sensor_event),
|
||||
BT_GATT_CCC(split_svc_sensor_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID),
|
||||
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||
split_svc_update_indicators, NULL),
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
|
||||
);
|
||||
|
||||
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <zmk/usb.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/keymap.h>
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
#include <zmk/hid_indicators.h>
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
#include <zmk/event_manager.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
@@ -39,16 +42,16 @@ void zmk_usb_hid_set_protocol(uint8_t protocol) { hid_protocol = protocol; }
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
|
||||
|
||||
static uint8_t *get_keyboard_report(size_t *len) {
|
||||
if (hid_protocol == HID_PROTOCOL_REPORT) {
|
||||
struct zmk_hid_keyboard_report *report = zmk_hid_get_keyboard_report();
|
||||
*len = sizeof(*report);
|
||||
return (uint8_t *)report;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||
zmk_hid_boot_report_t *boot_report = zmk_hid_get_boot_report();
|
||||
*len = sizeof(*boot_report);
|
||||
return (uint8_t *)boot_report;
|
||||
if (hid_protocol != HID_PROTOCOL_REPORT) {
|
||||
zmk_hid_boot_report_t *boot_report = zmk_hid_get_boot_report();
|
||||
*len = sizeof(*boot_report);
|
||||
return (uint8_t *)boot_report;
|
||||
}
|
||||
#endif
|
||||
struct zmk_hid_keyboard_report *report = zmk_hid_get_keyboard_report();
|
||||
*len = sizeof(*report);
|
||||
return (uint8_t *)report;
|
||||
}
|
||||
|
||||
static int get_report_cb(const struct device *dev, struct usb_setup_packet *setup, int32_t *len,
|
||||
@@ -83,12 +86,44 @@ static int get_report_cb(const struct device *dev, struct usb_setup_packet *setu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_report_cb(const struct device *dev, struct usb_setup_packet *setup, int32_t *len,
|
||||
uint8_t **data) {
|
||||
if ((setup->wValue & HID_GET_REPORT_TYPE_MASK) != HID_REPORT_TYPE_OUTPUT) {
|
||||
LOG_ERR("Unsupported report type %d requested",
|
||||
(setup->wValue & HID_GET_REPORT_TYPE_MASK) >> 8);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (setup->wValue & HID_GET_REPORT_ID_MASK) {
|
||||
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
case ZMK_HID_REPORT_ID_LEDS:
|
||||
if (*len != sizeof(struct zmk_hid_led_report)) {
|
||||
LOG_ERR("LED set report is malformed: length=%d", *len);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct zmk_hid_led_report *report = (struct zmk_hid_led_report *)*data;
|
||||
struct zmk_endpoint_instance endpoint = {
|
||||
.transport = ZMK_TRANSPORT_USB,
|
||||
};
|
||||
zmk_hid_indicators_process_report(&report->body, endpoint);
|
||||
}
|
||||
break;
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
|
||||
default:
|
||||
LOG_ERR("Invalid report ID %d requested", setup->wValue & HID_GET_REPORT_ID_MASK);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_ops ops = {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||
.protocol_change = set_proto_cb,
|
||||
#endif
|
||||
.int_in_ready = in_ready_cb,
|
||||
.get_report = get_report_cb,
|
||||
.set_report = set_report_cb,
|
||||
};
|
||||
|
||||
static int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
|
||||
@@ -129,6 +164,19 @@ int zmk_usb_hid_send_consumer_report() {
|
||||
return zmk_usb_hid_send_report((uint8_t *)report, sizeof(*report));
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
int zmk_usb_hid_send_mouse_report() {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||
if (hid_protocol == HID_PROTOCOL_BOOT) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
|
||||
|
||||
struct zmk_hid_mouse_report *report = zmk_hid_get_mouse_report();
|
||||
return zmk_usb_hid_send_report((uint8_t *)report, sizeof(*report));
|
||||
}
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static int zmk_usb_hid_init(const struct device *_arg) {
|
||||
hid_dev = device_get_binding("HID_0");
|
||||
if (hid_dev == NULL) {
|
||||
|
||||
1
app/tests/mouse-keys/mkp/events.patterns
Normal file
1
app/tests/mouse-keys/mkp/events.patterns
Normal file
@@ -0,0 +1 @@
|
||||
s/.*zmk_hid_mouse_button_//p
|
||||
10
app/tests/mouse-keys/mkp/keycode_events.snapshot
Normal file
10
app/tests/mouse-keys/mkp/keycode_events.snapshot
Normal file
@@ -0,0 +1,10 @@
|
||||
press: Button 0 count 1
|
||||
press: Mouse buttons set to 0x01
|
||||
press: Button 1 count 1
|
||||
press: Mouse buttons set to 0x03
|
||||
release: Button 1 count: 0
|
||||
release: Button 1 released
|
||||
release: Mouse buttons set to 0x01
|
||||
release: Button 0 count: 0
|
||||
release: Button 0 released
|
||||
release: Mouse buttons set to 0x00
|
||||
28
app/tests/mouse-keys/mkp/native_posix.keymap
Normal file
28
app/tests/mouse-keys/mkp/native_posix.keymap
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label = "Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mkp LCLK &none
|
||||
&none &mkp RCLK
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS (0,0,100)
|
||||
ZMK_MOCK_PRESS (1,1,100)
|
||||
ZMK_MOCK_RELEASE(1,1, 10)
|
||||
ZMK_MOCK_RELEASE(0,0, 10)
|
||||
>;
|
||||
};
|
||||
28
app/tests/mouse-keys/mkp/native_posix_64.keymap
Normal file
28
app/tests/mouse-keys/mkp/native_posix_64.keymap
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label = "Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mkp LCLK &none
|
||||
&none &mkp RCLK
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS (0,0,100)
|
||||
ZMK_MOCK_PRESS (1,1,100)
|
||||
ZMK_MOCK_RELEASE(1,1, 10)
|
||||
ZMK_MOCK_RELEASE(0,0, 10)
|
||||
>;
|
||||
};
|
||||
@@ -13,6 +13,13 @@ computer/laptop/keyboard should receive the keyboard input; many of the commands
|
||||
When pairing to a host device ZMK saves bond information to the selected profile. It will not replace this when you initiate pairing with another device. To pair with a new device select an unused profile with `BT_SEL`, `BT_NXT` or `BT_PRV` bindings, or by clearing an existing profile using `BT_CLR`.
|
||||
|
||||
A ZMK device may show as "connected" on multiple hosts at the same time. This is working as intended, and only the host associated with the active profile will receive keystrokes.
|
||||
|
||||
An _inactive_ connected profile can be explicitly disconnected using the `BT_DISC` behavior. This can be helpful in
|
||||
cases when host devices behave differently when a bluetooth keyboard is connected, for example by hiding their on-screen
|
||||
keyboard. Note that at present the active bluetooth profile will immediately reconnect if disconnected. This is true
|
||||
even if OUT_USB is selected. To remain disconnected, another bluetooth profile must be first selected using (e.g.)
|
||||
`BT_SEL`.
|
||||
|
||||
:::
|
||||
|
||||
## Bluetooth Command Defines
|
||||
@@ -28,12 +35,14 @@ This will allow you to reference the actions defined in this header such as `BT_
|
||||
|
||||
Here is a table describing the command for each define:
|
||||
|
||||
| Define | Action |
|
||||
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `BT_CLR` | Clear bond information between the keyboard and host for the selected profile. |
|
||||
| `BT_NXT` | Switch to the next profile, cycling through to the first one when the end is reached. |
|
||||
| `BT_PRV` | Switch to the previous profile, cycling through to the last one when the beginning is reached. |
|
||||
| `BT_SEL` | Select the 0-indexed profile by number. Please note: this definition must include a number as an argument in the keymap to work correctly. eg. `BT_SEL 0` |
|
||||
| Define | Action |
|
||||
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `BT_CLR` | Clear bond information between the keyboard and host for the selected profile. |
|
||||
| `BT_NXT` | Switch to the next profile, cycling through to the first one when the end is reached. |
|
||||
| `BT_PRV` | Switch to the previous profile, cycling through to the last one when the beginning is reached. |
|
||||
| `BT_SEL` | Select the 0-indexed profile by number. Please note: this definition must include a number as an argument in the keymap to work correctly. eg. `BT_SEL 0` |
|
||||
| `BT_DISC` | Disconnect from the 0-indexed profile by number, if it's currently connected and inactive. Please note: this definition must include a number as an |
|
||||
| | argument in the keymap to work correctly. eg. `BT_DISC 0` |
|
||||
|
||||
:::note Selected profile persistence
|
||||
The profile that is selected by the `BT_SEL`/`BT_PRV`/`BT_NXT` actions will be saved to flash storage and hence persist across restarts and firmware flashes.
|
||||
|
||||
66
docs/docs/behaviors/mouse-emulation.md
Normal file
66
docs/docs/behaviors/mouse-emulation.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: Mouse Emulation Behaviors
|
||||
sidebar_label: Mouse Emulation
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Mouse emulation behaviors send mouse events. Currently, only mouse button presses are supported, but movement
|
||||
and scroll action support is planned for the future.
|
||||
|
||||
Whenever the Mouse Emulation feature is turned on or off, the HID protocol used to communicate events to hosts changes. Unfortunately, those changes are not always detected automatically, and might require re-pairing your keyboard to your devices to work over bluetooth. If mouse behaviors are still not recognized by your device after doing that, you can try [these troubleshooting steps](../features/bluetooth.md#windows-connected-but-not-working).
|
||||
|
||||
## Configuration Option
|
||||
|
||||
This feature can be enabled or disabled explicitly via a config option:
|
||||
|
||||
```
|
||||
CONFIG_ZMK_MOUSE=y
|
||||
```
|
||||
|
||||
If you use the mouse key press behavior in your keymap, the feature will automatically be enabled for you.
|
||||
|
||||
## Mouse Button Defines
|
||||
|
||||
To make it easier to encode the HID mouse button numeric values, include
|
||||
the [`dt-bindings/zmk/mouse.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/mouse.h) header
|
||||
provided by ZMK near the top:
|
||||
|
||||
```
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
```
|
||||
|
||||
## Mouse Button Press
|
||||
|
||||
This behavior can press/release up to 5 mouse buttons.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
- Reference: `&mkp`
|
||||
- Parameter: A `uint8` with bits 0 through 4 each referring to a button.
|
||||
|
||||
The following defines can be passed for the parameter:
|
||||
|
||||
| Define | Action |
|
||||
| :------------ | :------------- |
|
||||
| `MB1`, `LCLK` | Left click |
|
||||
| `MB2`, `RCLK` | Right click |
|
||||
| `MB3`, `MCLK` | Middle click |
|
||||
| `MB4` | Mouse button 4 |
|
||||
| `MB5` | Mouse button 5 |
|
||||
|
||||
Mouse buttons 4 and 5 typically map to "back" and "forward" actions in most applications.
|
||||
|
||||
### Examples
|
||||
|
||||
The following will send a left click press when the binding is triggered:
|
||||
|
||||
```
|
||||
&mkp LCLK
|
||||
```
|
||||
|
||||
This example will send press of the fourth mouse button when the binding is triggered:
|
||||
|
||||
```
|
||||
&mkp MB4
|
||||
```
|
||||
@@ -22,6 +22,12 @@ While `CONFIG_ZMK_BATTERY_REPORTING` is disabled by default it is implied by `CO
|
||||
|
||||
:::
|
||||
|
||||
:::note BLE reporting on MacOS
|
||||
|
||||
On macOS the BLE battery reporting packets can cause the computer to wakeup from sleep. To prevent this, the battery _reporting_ service can be disabled by setting `CONFIG_BT_BAS=n`. This setting is independent of battery _monitoring_, for instance the battery level can still be indicated on a display.
|
||||
|
||||
:::
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: [`/chosen` node](https://docs.zephyrproject.org/latest/guides/dts/intro.html#aliases-and-chosen-nodes)
|
||||
|
||||
@@ -22,9 +22,10 @@ Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/
|
||||
|
||||
### HID
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------- | ---- | ------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE` | int | Number of consumer keys simultaneously reportable | 6 |
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------- | ---- | -------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_HID_INDICATORS` | bool | Enable reciept of HID/LED indicator state from connected hosts | n |
|
||||
| `CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE` | int | Number of consumer keys simultaneously reportable | 6 |
|
||||
|
||||
Exactly zero or one of the following options may be set to `y`. The first is used if none are set.
|
||||
|
||||
@@ -66,6 +67,7 @@ for more information on configuring Bluetooth.
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------- | ---- | --------------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_BT` | bool | Enable Bluetooth support | |
|
||||
| `CONFIG_BT_BAS` | bool | Enable the Bluetooth BAS (battery reporting service) | y |
|
||||
| `CONFIG_BT_MAX_CONN` | int | Maximum number of simultaneous Bluetooth connections | 5 |
|
||||
| `CONFIG_BT_MAX_PAIRED` | int | Maximum number of paired Bluetooth devices | 5 |
|
||||
| `CONFIG_ZMK_BLE` | bool | Enable ZMK as a Bluetooth keyboard | |
|
||||
@@ -90,14 +92,15 @@ Note that `CONFIG_BT_MAX_CONN` and `CONFIG_BT_MAX_PAIRED` should be set to the s
|
||||
|
||||
Following split keyboard settings are defined in [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/Kconfig) (generic) and [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/bluetooth/Kconfig) (bluetooth).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ----------------------------------------------------- | ---- | ----------------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_SPLIT` | bool | Enable split keyboard support | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 650 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
||||
| Config | Type | Description | Default |
|
||||
| ----------------------------------------------------- | ---- | ------------------------------------------------------------------------ | ------- |
|
||||
| `CONFIG_ZMK_SPLIT` | bool | Enable split keyboard support | n |
|
||||
| `CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS` | bool | Enable split keyboard support for passing indicator state to peripherals | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 650 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
||||
|
||||
@@ -83,3 +83,32 @@ You should see tio printing `Disconnected` or `Connected` when you disconnect or
|
||||
</Tabs>
|
||||
|
||||
From there, you should see the various log messages from ZMK and Zephyr, depending on which systems you have set to what log levels.
|
||||
|
||||
## Adding USB Logging to a Board
|
||||
|
||||
Standard boards such as the nice!nano and Seeeduino XIAO family have the necessary configuration for logging already added, however if you are developing your own standalone board you may wish to add the ability to use USB logging in the future.
|
||||
|
||||
To add USB logging to a board you need to define the USB CDC ACM device that the serial output gets piped to, as well as adding the console in the `chosen` node inside `<board>.dts`.
|
||||
|
||||
Inside the USB device (`&usbd`), add the CDC ACM node:
|
||||
|
||||
```dts
|
||||
&usbd {
|
||||
status = "okay";
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Then you can add the `zephyr,console` binding in the `chosen` node:
|
||||
|
||||
```dts
|
||||
/ {
|
||||
chosen {
|
||||
...
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
};
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
@@ -36,6 +36,7 @@ module.exports = {
|
||||
"behaviors/caps-word",
|
||||
"behaviors/key-repeat",
|
||||
"behaviors/sensor-rotate",
|
||||
"behaviors/mouse-emulation",
|
||||
"behaviors/reset",
|
||||
"behaviors/bluetooth",
|
||||
"behaviors/outputs",
|
||||
|
||||
Reference in New Issue
Block a user