diff --git a/0001-esb-nrf-fix.patch b/0001-esb-nrf-fix.patch new file mode 100644 index 00000000000..12d4c3bbd7b --- /dev/null +++ b/0001-esb-nrf-fix.patch @@ -0,0 +1,117 @@ +From 46e84d0dfcb21acde11d531eb40f91ee551942c6 Mon Sep 17 00:00:00 2001 +From: william <43848894@qq.com> +Date: Mon, 13 Jan 2025 12:16:43 +0800 +Subject: [PATCH] esb nrf fix + +--- + drivers/usb/device/usb_dc_nrfx.c | 4 ++- + .../controller/ll_sw/nordic/lll/lll.c | 29 ++++++++++++++++++- + subsys/bluetooth/services/bas.c | 14 +++++++++ + 3 files changed, 45 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/device/usb_dc_nrfx.c b/drivers/usb/device/usb_dc_nrfx.c +index c0b661007..c2014c3ba 100644 +--- a/drivers/usb/device/usb_dc_nrfx.c ++++ b/drivers/usb/device/usb_dc_nrfx.c +@@ -1075,7 +1075,9 @@ static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event) + case NRFX_USBD_EVT_SOF: + if (IS_ENABLED(CONFIG_USB_DEVICE_SOF)) { + evt.evt_type = USBD_EVT_SOF; +- put_evt = true; ++ // put_evt = true; ++ extern uint32_t usb_sof_count; ++ usb_sof_count ++; + } + break; + +diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +index e3ce60282..5bfe7d38d 100644 +--- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c ++++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +@@ -84,7 +84,11 @@ static void ticker_op_job_disable(uint32_t status, void *op_context); + #endif + #endif /* CONFIG_BT_CTLR_LOW_LAT */ + ++#if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) ++static void radio_nrf5_isr(const void *arg) ++#else /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + ISR_DIRECT_DECLARE(radio_nrf5_isr) ++#endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + { + DEBUG_RADIO_ISR(1); + +@@ -97,7 +101,9 @@ ISR_DIRECT_DECLARE(radio_nrf5_isr) + lll_prof_exit_radio(); + + DEBUG_RADIO_ISR(0); ++#if !defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) + return 1; ++#endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + } + + static void rtc0_nrf5_isr(const void *arg) +@@ -183,7 +189,27 @@ int lll_init(void) + + /* Initialize SW IRQ structure */ + hal_swi_init(); ++#if defined(CONFIG_DYNAMIC_INTERRUPTS) ++#if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) ++ ARM_IRQ_DIRECT_DYNAMIC_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, ++ IRQ_CONNECT_FLAGS, no_reschedule); ++ irq_connect_dynamic(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, ++ radio_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); ++#else /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ ++ IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, ++ radio_nrf5_isr, IRQ_CONNECT_FLAGS); ++#endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ ++ irq_connect_dynamic(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, ++ rtc0_nrf5_isr, NULL, 0U); ++ irq_connect_dynamic(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO, ++ swi_lll_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); ++#if defined(CONFIG_BT_CTLR_LOW_LAT) || \ ++ (CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO) ++ irq_connect_dynamic(HAL_SWI_JOB_IRQ, CONFIG_BT_CTLR_ULL_LOW_PRIO, ++ swi_ull_low_nrf5_isr, NULL, 0U); ++#endif + ++#else /* !CONFIG_DYNAMIC_INTERRUPTS */ + /* Connect ISRs */ + IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + radio_nrf5_isr, IRQ_CONNECT_FLAGS); +@@ -196,7 +222,8 @@ int lll_init(void) + IRQ_CONNECT(HAL_SWI_JOB_IRQ, CONFIG_BT_CTLR_ULL_LOW_PRIO, + swi_ull_low_nrf5_isr, NULL, 0); + #endif +- ++#endif /* !CONFIG_DYNAMIC_INTERRUPTS */ ++ + /* Enable IRQs */ + irq_enable(RADIO_IRQn); + irq_enable(RTC0_IRQn); +diff --git a/subsys/bluetooth/services/bas.c b/subsys/bluetooth/services/bas.c +index cf6482d53..ead09c15a 100644 +--- a/subsys/bluetooth/services/bas.c ++++ b/subsys/bluetooth/services/bas.c +@@ -95,5 +95,19 @@ int bt_bas_set_battery_level(uint8_t level) + + return rc == -ENOTCONN ? 0 : rc; + } ++//add by cwl @2023/11/23 ++int bt_bas_set_battery_level_fix(struct bt_conn *conn,uint8_t level) ++{ ++ int rc; ++ battery_level = level; ++ if (level > 100U || conn ==NULL) { ++ if(level > 100U) battery_level =100; ++ return -EINVAL; ++ } ++ ++ rc = bt_gatt_notify(conn, &bas.attrs[1], &level, sizeof(level)); ++ ++ return rc == -ENOTCONN ? 0 : rc; ++} + + SYS_INIT(bas_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); +-- +2.42.0.windows.2 + diff --git a/README.md b/README.md index f112b0f9705..a3784efe8fa 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,27 @@ Check out the website to learn more: https://zmk.dev/. You can also come join our [ZMK Discord Server](https://zmk.dev/community/discord/invite). To review features, check out the [feature overview](https://zmk.dev/docs/). ZMK is under active development, and new features are listed with the [enhancement label](https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) in GitHub. Please feel free to add 👍 to the issue description of any requests to upvote the feature. + +[Keychron](https://keychron.com/) use zmk source code for Bpro series keyboards ,have made big changes fro Bpro, also add proprietary 2.4g communication. + +To build the firmware ,for example: keychorn b1 pro + +prepare: +``` + mkdir keychron + cd keychron + git clone -b keychron_bpro https://github.com/keychron/zmk.git + cd zmk + west init -l app/ + west update +``` +patch zephyr: +``` + cd zephyr + git am ../001-esb-nrf-fix.patch +``` +build firmware: +``` + cd app + west build -b keychron -p -- -DSHIELD=keychron_b1_us +``` \ No newline at end of file diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index c41153cb17c..13caa4319f7 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -107,6 +107,9 @@ target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c) target_sources_ifdef(CONFIG_ZMK_LOW_PRIORITY_WORK_QUEUE app PRIVATE src/workqueue.c) target_sources(app PRIVATE src/main.c) +target_sources(app PRIVATE src/leds.c) +zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth/host) + add_subdirectory(src/display/) add_subdirectory_ifdef(CONFIG_SETTINGS src/settings/) @@ -133,4 +136,13 @@ if (CONFIG_ZMK_STUDIO_RPC) add_subdirectory(src/studio) endif() + +add_subdirectory_ifdef(CONFIG_ZMK_NRF_24G_ECB src/24G) +zephyr_library_include_directories(src/24G) + + +add_subdirectory_ifdef(CONFIG_ZMK_LAUNCHER src/launcher) +add_subdirectory(src/dfu/) + + zephyr_cc_option(-Wfatal-errors) diff --git a/app/Kconfig b/app/Kconfig index 8c0675e0d68..24fa220971e 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -177,6 +177,12 @@ config ZMK_BLE_EXPERIMENTAL_CONN Enables settings that are planned to be default in future versions of ZMK to improve connection stability. +<<<<<<< HEAD +#choice BT_LL_SW_LLCP_IMPL +# default BT_LL_SW_LLCP_LEGACY + +#endchoice +======= config ZMK_BLE_EXPERIMENTAL_SEC bool "Experimental BLE security changes" imply BT_SMP_ALLOW_UNAUTH_OVERWRITE @@ -189,6 +195,7 @@ config ZMK_BLE_EXPERIMENTAL_FEATURES select ZMK_BLE_EXPERIMENTAL_SEC help Enables experimental connection changes and security features. +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 config ZMK_BLE_PASSKEY_ENTRY bool "Require passkey entry on the keyboard to complete pairing" @@ -210,7 +217,7 @@ config ZMK_BLE_THREAD_PRIORITY config ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE int "Max number of keyboard HID reports to queue for sending over BLE" - default 20 + default 64 config ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE int "Max number of consumer HID reports to queue for sending over BLE" @@ -470,7 +477,7 @@ menu "Behavior Options" config ZMK_BEHAVIORS_QUEUE_SIZE int "Maximum number of behaviors to allow queueing from a macro or other complex behavior" - default 64 + default 512 rsource "Kconfig.behaviors" @@ -553,7 +560,7 @@ config ZMK_LOGGING_MINIMAL if !ZMK_LOGGING_MINIMAL config ZMK_LOG_LEVEL - default 4 + default 1 #4 endif @@ -599,6 +606,16 @@ config ZMK_RTT_LOGGING select CONSOLE select RTT_CONSOLE +config ZMK_UART_LOGGING + bool "Enable UART logging to help debug" + select LOG + select DEBUG + select ASSERT + select SERIAL + select SERIAL_HAS_DRIVER + select CONSOLE + select UART_CONSOLE + if ZMK_RTT_LOGGING config SEGGER_RTT_BUFFER_SIZE_UP @@ -606,7 +623,7 @@ config SEGGER_RTT_BUFFER_SIZE_UP endif # ZMK_RTT_LOGGING -if ZMK_USB_LOGGING || ZMK_RTT_LOGGING +if ZMK_USB_LOGGING || ZMK_RTT_LOGGING || ZMK_UART_LOGGING config LOG_BUFFER_SIZE default 8192 @@ -643,11 +660,15 @@ endif # SETTINGS config ZMK_BATTERY_REPORT_INTERVAL depends on ZMK_BATTERY_REPORTING int "Battery level report interval in seconds" +<<<<<<< HEAD + default 30 +======= config ZMK_LOW_PRIORITY_WORK_QUEUE bool "Work queue for low priority items" if ZMK_LOW_PRIORITY_WORK_QUEUE +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 config ZMK_LOW_PRIORITY_THREAD_STACK_SIZE int "Low priority thread stack size" @@ -704,6 +725,48 @@ config ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION endif # ZMK_KEYMAP_SENSORS +<<<<<<< HEAD +choice CBPRINTF_IMPLEMENTATION + default CBPRINTF_NANO + +endchoice + +config ZMK_LED_INIT_PRIORITY + int "LED Init Priority" + default 40 + +config ZMK_NRF_24G_ECB + bool "enabel nordic 24g ecb" + select NRFX_TIMER2 + default n + +if ZMK_NRF_24G_ECB +config ESB_PTX_APP_LOG_LEVEL + int + default 4 +config ESB_DYNAMIC_INTERRUPTS + bool "enable dynamic interrupt" + default y +config ESB_MAX_PAYLOAD_LENGTH + int "max payload length" + default 40 +endif + + + +if ZMK_NRF_24G_ECB + config ZMK_NRF_24G + bool + default y +endif + +config ZMK_LAUNCHER + bool "enable via dynamic setting" + default y + + +======= +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 module = ZMK module-str = zmk source "subsys/logging/Kconfig.template.log_config" diff --git a/app/VERSION b/app/VERSION index 07a7f21fc3b..3ae86440b01 100644 --- a/app/VERSION +++ b/app/VERSION @@ -1,3 +1,10 @@ +<<<<<<< HEAD +VERSION_MAJOR = 1 +VERSION_MINOR = 2 +PATCHLEVEL = 3 +VERSION_TWEAK = 0 +EXTRAVERSION = ZMK +======= # x-release-please-start-major VERSION_MAJOR = 0 # x-release-please-end @@ -10,4 +17,5 @@ VERSION_MINOR = 3 PATCHLEVEL = 0 # x-release-please-end -VERSION_TWEAK = 0 \ No newline at end of file +VERSION_TWEAK = 0 +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/boards/arm/keychron/Kconfig b/app/boards/arm/keychron/Kconfig new file mode 100644 index 00000000000..573e6740cd1 --- /dev/null +++ b/app/boards/arm/keychron/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config BOARD_ENABLE_DCDC + bool "Enable DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_KEYCHRON diff --git a/app/boards/arm/keychron/Kconfig.board b/app/boards/arm/keychron/Kconfig.board new file mode 100644 index 00000000000..a6627cca672 --- /dev/null +++ b/app/boards/arm/keychron/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config BOARD_KEYCHRON + bool "keychron" + depends on SOC_NRF52840_QIAA diff --git a/app/boards/arm/keychron/Kconfig.defconfig b/app/boards/arm/keychron/Kconfig.defconfig new file mode 100644 index 00000000000..27e70bb2e1e --- /dev/null +++ b/app/boards/arm/keychron/Kconfig.defconfig @@ -0,0 +1,36 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if BOARD_KEYCHRON + +config ZMK_KEYBOARD_NAME + default "Keychron B6 Pro" + +if USB_DEVICE_STACK + +config USB_NRFX + default y + +endif # USB_DEVICE_STACK + +config BT_CTLR + default BT + +config ZMK_BLE + default y + +config ZMK_USB + default y + +config ZMK_LEDS_GPIO + bool "enable gpio leds" + default y + select LED + +config ZMK_LEDS_PWM + bool "enable pwm leds" + default n + select PWM + select LED_PWM + +endif # BOARD_KEYCHRON diff --git a/app/boards/arm/keychron/README.md b/app/boards/arm/keychron/README.md new file mode 100644 index 00000000000..e82686cc9ab --- /dev/null +++ b/app/boards/arm/keychron/README.md @@ -0,0 +1,32 @@ +# Keychron `NRF52840` Experimental Support + + + +### Specifications: + + - `NRF52840` + - 15 column x 5 row key matrix with a ROW -> COL (`row2col`) layout + - DIP switch embedded in matrix at `(4,4)` + - LED Matrix + - 2x I2C `CKLED2001` LED Drivers + - EC11 Encoder + +### Current Progress: + +### Flashing: + + + +### Development: + +1. Follow the [ZMK Documentation](https://zmk.dev/docs/development/setup) to set up your local build environment +2. To build the firmware, run: +```sh +west build -p -b keychron +``` +3. To build and flash the the firmware, hold down the RESET button while connecting the keyboard over USB. The run: +```sh +west build -p -b keychron && west flash +``` + + diff --git a/app/boards/arm/keychron/board.cmake b/app/boards/arm/keychron/board.cmake new file mode 100644 index 00000000000..8bc0fdc8bfd --- /dev/null +++ b/app/boards/arm/keychron/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +set(OPENOCD_NRF5_SUBFAMILY nrf52) +board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset") +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) diff --git a/app/boards/arm/keychron/keychron.dts b/app/boards/arm/keychron/keychron.dts new file mode 100644 index 00000000000..3c2164a81dc --- /dev/null +++ b/app/boards/arm/keychron/keychron.dts @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +/dts-v1/; +#include + +#include +#include + + +/ { + model = "keychron"; + compatible = "keychron"; + + chosen { + zephyr,code-partition = &code_partition; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; //&cdc_acm_uart; + zmk,battery = &vbatt; + zmk,kscan = &kscan_comp;//&kscan0; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //print //scr //pause + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(5,17) RC(7,9) RC(0,9) RC(0,0) RC(7,16) RC(4,16) RC(2,16) RC(5,16) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //ins //home //pg up //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(6,12) RC(6,14) RC(6,13) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //\ //del //end //pg dn //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(2,10) RC(6,11) RC(7,14) RC(7,13) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //rshit //up //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(3,14) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt r //win r //fn //ctrl r //left //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,7) RC(4,0) RC(5,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + + + kscan0: kscan_matrix { + compatible = "zmk,kscan-gpio-matrix"; + //label = "KSCAN"; + diode-direction = "col2row"; + debounce-scan-period-ms =<4>; + debounce-press-ms =<8>; + debounce-release-ms=<8>; + + row-gpios + = <&gpio1 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r0 + , <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r1 + , <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r2 + , <&gpio1 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r3 + , <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r4 + , <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r5 + , <&gpio1 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r6 + , <&gpio1 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> //r7 + ; + col-gpios + = <&gpio0 0 (GPIO_ACTIVE_HIGH )> //c0 + , <&gpio0 1 (GPIO_ACTIVE_HIGH)> //c1 + , <&gpio0 26 (GPIO_ACTIVE_HIGH)> //c2 + , <&gpio0 27 (GPIO_ACTIVE_HIGH)> //c3 + , <&gpio0 4 (GPIO_ACTIVE_HIGH)> //c4 + , <&gpio0 5 (GPIO_ACTIVE_HIGH)> //c5 + , <&gpio0 6 (GPIO_ACTIVE_HIGH)> //c6 + , <&gpio0 7 (GPIO_ACTIVE_HIGH)> //c7 + , <&gpio0 8 (GPIO_ACTIVE_HIGH)> //c8 + , <&gpio0 11 (GPIO_ACTIVE_HIGH)> //c9 + , <&gpio0 12 (GPIO_ACTIVE_HIGH)> //c10 + , <&gpio0 13 (GPIO_ACTIVE_HIGH)> //c11 + , <&gpio0 14 (GPIO_ACTIVE_HIGH)> //c12 + , <&gpio0 15 (GPIO_ACTIVE_HIGH)> //c13 + , <&gpio0 16 (GPIO_ACTIVE_HIGH)> //c14 + , <&gpio0 17 (GPIO_ACTIVE_HIGH)> //c15 + , <&gpio0 18 (GPIO_ACTIVE_HIGH)> //c16 + , <&gpio0 20 (GPIO_ACTIVE_HIGH)> //c17 + ; + + }; + + kscan1:kscan_direct { + compatible = "zmk,kscan-gpio-direct"; + //label = "CONTROL"; + input-gpios + = <&gpio0 24 GPIO_ACTIVE_LOW> //mac/win + , <&gpio1 8 (GPIO_ACTIVE_LOW)> //bt + , <&gpio1 9 (GPIO_ACTIVE_LOW)> //24g + , <&gpio0 21 GPIO_ACTIVE_LOW> //charging + , <&gpio0 22 GPIO_ACTIVE_LOW> //charge done + ; + }; + + kscan_comp: kscan { + compatible = "zmk,kscan-composite"; + label = "KSCAN_ALL"; + rows = <9>; + columns = <18>; + + // Include the matrix driver + matrix { + kscan = <&kscan0>; + }; + + // Include the direct GPIO driver... + direct { + kscan = <&kscan1>; + row-offset = <8>; // ...and shift it to not overlap + }; + }; + + + + ext-power { + compatible = "zmk,ext-power-generic"; + status ="disabled"; + label = "EXT_POWER"; + control-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + }; + + vbatt: vbatt { + compatible = "zmk,battery-voltage-divider"; + //label = "BATTERY"; + io-channels = <&adc 7>; + output-ohms = <510000>; + full-ohms = <(510000 + 510000)>; + }; + + led_blue { + compatible = "gpio-leds"; + label = "LED_BLUE"; + blue_led: led_01 { + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + + }; + }; + led_numlock { + compatible = "gpio-leds"; + label = "LED_NumLock"; + status = "okay"; + numlock_led: led_02 { + gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; + + }; + }; + led_CAPS { + compatible = "gpio-leds"; + label = "LED_CAPS"; + status = "okay"; + caps_led: led_03 { + gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + + }; + }; + led_24G { + compatible = "gpio-leds"; + label = "LED_24G"; + status = "okay"; + led_24g: led_04 { + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + + }; + }; + led_rgb { + compatible = "gpio-leds"; + label = "LED_RGB"; + status = "okay"; + + myled_r: led_r { + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + label = "led_r"; + }; + myled_g: led_g { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "led_g"; + }; + myled_b: led_b { + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + label = "led_b"; + }; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&pinctrl { + i2c0_default:i2c0_default{ + group1 { + psels = , + ; + }; + }; + i2c0_sleep:i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart0_default:uart0_default { + group1 { + psels = ; + low-power-enable; + }; + + group2 { + psels = ; + low-power-enable; + }; + }; + uart0_sleep:uart0_sleep { + group1 { + psels = ; + low-power-enable; + }; + + group2 { + psels = ; + low-power-enable; + }; + }; + +}; + + + + + + +&usbd { + status = "okay"; + //cdc_acm_uart: cdc_acm_uart { + // compatible = "zephyr,cdc-acm-uart"; + // label = "CDC_ACM_0"; + //}; +}; + + +&uart0 { + compatible = "nordic,nrf-uarte"; + status = "disabled";//"okay";// + current-speed = <1000000>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + + +&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 = "mbr"; + reg = <0x00000000 0x00001000>; + }; + + code_partition: partition@1000 { + label = "code_partition"; + reg = <0x00001000 0x000d3000>; + }; + + /* + * The flash starting at 0x000d4000 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@d4000 { + label = "storage"; + reg = <0x000d4000 0x00020000>; + }; + + boot_partition: partition@f4000 { + label = "adafruit_boot"; + reg = <0x000f4000 0x0000c000>; + }; + }; +}; +#include +&mt { + tapping-term-ms = <400>; +}; diff --git a/app/boards/arm/keychron/keychron.yaml b/app/boards/arm/keychron/keychron.yaml new file mode 100644 index 00000000000..e20286072d3 --- /dev/null +++ b/app/boards/arm/keychron/keychron.yaml @@ -0,0 +1,14 @@ +identifier: keychron +name: keychron +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - adc + - usb_device + - ble + - ieee802154 + - pwm + - watchdog diff --git a/app/boards/arm/keychron/keychron.zmk.yml b/app/boards/arm/keychron/keychron.zmk.yml new file mode 100644 index 00000000000..6f648122afa --- /dev/null +++ b/app/boards/arm/keychron/keychron.zmk.yml @@ -0,0 +1,12 @@ +file_format: "1" +id: keychron +name: keychron +type: board +arch: arm +features: + - keys + - underglow +outputs: + - usb + - ble +url: https://www.keychron.com/ diff --git a/app/boards/arm/keychron/keychron_defconfig b/app/boards/arm/keychron/keychron_defconfig new file mode 100644 index 00000000000..dde9a028a1a --- /dev/null +++ b/app/boards/arm/keychron/keychron_defconfig @@ -0,0 +1,123 @@ +# Copyright (c) 2021 Nick Winans +# SPDX-License-Identifier: MIT + +CONFIG_SOC_SERIES_NRF52X=y +CONFIG_SOC_NRF52840_QIAA=y +CONFIG_BOARD_KEYCHRON=y + +# Enable MPU +CONFIG_ARM_MPU=y + +CONFIG_PINCTRL=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable i2c +CONFIG_I2C=n + +CONFIG_USE_DT_CODE_PARTITION=y +CONFIG_BUILD_OUTPUT_UF2=y + +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 + +# CONFIG_ZMK_RTT_LOGGING=y +# CONFIG_ZMK_USB_LOGGING=y +#CONFIG_ZMK_UART_LOGGING=y + +# RGB +# Uncomment these to enable RGB underglow +# CONFIG_CKLED2001=n +#CONFIG_ZMK_RGB_UNDERGLOW=n +#CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=n +#CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3 +#CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=10 +#CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=100 +#CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n + +CONFIG_BT_ID_MAX=5 +CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE=y +# CONFIG_BT_ID_UNPAIR_MATCHING_BONDS=y +CONFIG_BT_FILTER_ACCEPT_LIST=y +CONFIG_BT_PRIVACY=n +CONFIG_BT_CTLR_PRIVACY=y + +# CONFIG_ZMK_HID_REPORT_TYPE_NKRO=y +CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_FULL=y + +#CONFIG_USB_HID_LOG_LEVEL_DBG=y +#CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y + + +#CONFIG_ZERO_LATENCY_IRQS=y +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_DYNAMIC_DIRECT_INTERRUPTS=y + + + +CONFIG_GPIO_AS_PINRESET=n +# Clock Source +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y + +CONFIG_ZMK_EXT_POWER=n + +#CONFIG_ZMK_KSCAN_MATRIX_POLLING=y + +#CONFIG_ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS=10 +#CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS=10 + +CONFIG_ZMK_BLE_THREAD_PRIORITY=-1 + + +CONFIG_ZMK_NRF_24G_ECB=y + + + +CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE=32 +CONFIG_ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE=64 + +CONFIG_USB_DEVICE_PRODUCT="Keychron B6 Pro" +CONFIG_USB_DEVICE_MANUFACTURER="Keychron" +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0761 + +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0761 +CONFIG_BT_DIS_MODEL="Keychron B6 Pro" +CONFIG_BT_DIS_MANUF="Keychron" +CONFIG_BT_DIS_SETTINGS=y +CONFIG_BT_DIS_FW_REV=y +CONFIG_BT_DIS_HW_REV=y +CONFIG_BT_DIS_SERIAL_NUMBER=y +CONFIG_BT_DIS_FW_REV_STR="v1.2.9" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024013114230078" + +CONFIG_ZMK_SLEEP=y +CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=7200000 + + +#CONFIG_USB_DRIVER_LOG_LEVEL_DBG=y +#CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y + +CONFIG_USB_HID_BOOT_PROTOCOL=y +CONFIG_USB_HID_DEVICE_COUNT=2 +CONFIG_ENABLE_HID_INT_OUT_EP=y +CONFIG_HID_INTERRUPT_EP_MPS=32 +CONFIG_USB_DEVICE_SOF=y + + +CONFIG_RING_BUFFER=y +#disable ble 2M +CONFIG_BT_CTLR_PHY_2M=n +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +CONFIG_BT_CONN_TX_MAX=8 \ No newline at end of file diff --git a/app/boards/arm/keychron/keychron_z1-287f3d87.keymap b/app/boards/arm/keychron/keychron_z1-287f3d87.keymap new file mode 100644 index 00000000000..bc061a0b81e --- /dev/null +++ b/app/boards/arm/keychron/keychron_z1-287f3d87.keymap @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +// &main_encoder { +// status = "okay"; +// }; + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + //fn = 95+7 -1 + //j = 63+8 -1 + //z = 79+2 -1 + //x = 79+3 -1 + //l = 63+10 -1 + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <69 81>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <82 71>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <85>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <97>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_win_r { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <101>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + // hold-tap that doesn't do anything on tap and BT_CLR on hold + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &uc LG(LS(N4)) &none &none &kp C_AC_SEARCH &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &uc LC(LEFT) &uc LC(RIGHT) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &uc RALT &mo 1 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp PSCRN &kp SLCK &kp PAUS &kp C_AL_CALC &uc LG(TAB) &uc LG(LC(LEFT)) &uc LG(LC(RIGHT)) //21 + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp KP_MINUS //42 + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS //63 + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 //63+21-5 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 //79+21-5 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &kp RGUI &mo 3 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans &trans &trans &long_press_bootloader 0 0 + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b1/jis/Kconfig.shield b/app/boards/shields/keychron/b1/jis/Kconfig.shield new file mode 100644 index 00000000000..d6eec1464e3 --- /dev/null +++ b/app/boards/shields/keychron/b1/jis/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B1 + bool + +config SHIELD_KEYCHRON_B1_JIS + def_bool $(shields_list_contains,keychron_b1_jis) + select SHIELD_KEYCHRON_B1 + + + diff --git a/app/boards/shields/keychron/b1/jis/keychron_b1_jis.conf b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.conf new file mode 100644 index 00000000000..bf1c4518f5e --- /dev/null +++ b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B1 Pro" +CONFIG_BT_DIS_MODEL="Keychron B1 pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B1 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0713 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0713 +CONFIG_BT_DIS_FW_REV_STR="v1.0.4" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024040814230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b1/jis/keychron_b1_jis.keymap b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.keymap new file mode 100644 index 00000000000..145cca9f282 --- /dev/null +++ b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <49 57>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <58 51>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <61>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <70>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //DEL + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &kp DEL + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT + &kp LCTRL &uc LALT &uc LCMD &kp LANG2 &kp SPACE &kp LANG1 &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) + &trans &trans &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp DEL + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT + &kp LCTRL &kp LGUI &kp LALT &kp INT5 &kp SPACE &kp INT4 &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) + &trans &trans &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b1/jis/keychron_b1_jis.overlay b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.overlay new file mode 100644 index 00000000000..d05970233bb --- /dev/null +++ b/app/boards/shields/keychron/b1/jis/keychron_b1_jis.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //del + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(6,11) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //int3 //back + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(0,10) RC(1,10) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4, 8) RC(4,10) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //int1 //rshit + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(5,6) RC(2,15) + //lctrl //win l //alt l //int5/lan2 //space //int4/lan1 //alt gr //fn //left //up //down //right + RC(6,0) RC(1,16) RC(3,9) RC(5,1) RC(3,11) RC(5,2) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/b1/uk/Kconfig.shield b/app/boards/shields/keychron/b1/uk/Kconfig.shield new file mode 100644 index 00000000000..7e1ca10da6f --- /dev/null +++ b/app/boards/shields/keychron/b1/uk/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B1 + bool + +config SHIELD_KEYCHRON_B1_UK + def_bool $(shields_list_contains,keychron_b1_uk) + select SHIELD_KEYCHRON_B1 + + + diff --git a/app/boards/shields/keychron/b1/uk/keychron_b1_uk.conf b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.conf new file mode 100644 index 00000000000..c580deb5568 --- /dev/null +++ b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B1 Pro" +CONFIG_BT_DIS_MODEL="Keychron B1 pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B1 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0712 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0712 +CONFIG_BT_DIS_FW_REV_STR="v1.0.4" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024040814230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b1/uk/keychron_b1_uk.keymap b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.keymap new file mode 100644 index 00000000000..4e90e435d2b --- /dev/null +++ b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <48 57>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <58 50>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <61>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <69>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //DEL + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &kp DEL + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp DEL + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b1/uk/keychron_b1_uk.overlay b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.overlay new file mode 100644 index 00000000000..b0e55ed57f6 --- /dev/null +++ b/app/boards/shields/keychron/b1/uk/keychron_b1_uk.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //del + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(6,11) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(2,10) RC(4,10) + //lshit //NUBS //z //x //c //v //b //n //m //,< //.> //?/ //rshit + RC(1,15) RC(3,2) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) + //lctrl //win l //alt l //space //alt gr //fn //left //up //down //right + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/b1/us/Kconfig.shield b/app/boards/shields/keychron/b1/us/Kconfig.shield new file mode 100644 index 00000000000..e5db86e96d3 --- /dev/null +++ b/app/boards/shields/keychron/b1/us/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B1 + bool + +config SHIELD_KEYCHRON_B1_US + def_bool $(shields_list_contains,keychron_b1_us) + select SHIELD_KEYCHRON_B1 + + + diff --git a/app/boards/shields/keychron/b1/us/keychron_b1_us.conf b/app/boards/shields/keychron/b1/us/keychron_b1_us.conf new file mode 100644 index 00000000000..8a15f87e52c --- /dev/null +++ b/app/boards/shields/keychron/b1/us/keychron_b1_us.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B1 Pro" +CONFIG_BT_DIS_MODEL="Keychron B1 pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B1 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0711 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0711 +CONFIG_BT_DIS_FW_REV_STR="v1.0.4" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024040814230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b1/us/keychron_b1_us.keymap b/app/boards/shields/keychron/b1/us/keychron_b1_us.keymap new file mode 100644 index 00000000000..29506472a44 --- /dev/null +++ b/app/boards/shields/keychron/b1/us/keychron_b1_us.keymap @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <49 56>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <57 51>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <60>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <68>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + //--------USキーボードの記号を日本語OSで表示通りに入力するための処理----------------------------- + //`~マーク + jis_GRAVE: jis_GRAVE { + compatible = "zmk,behavior-mod-morph"; + label = "jis_GRAVE"; + #binding-cells = <0>; + bindings = <&kp LS(LBKT)>, <&kp EQUAL>; //通常時でもレフトシフトするようにしてある。 + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; //shiftを押しっぱなしにするための記述 + }; + + + //@マーク + jis_N2: jis_N2 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N2"; + #binding-cells = <0>; + bindings = <&kp N2>, <&kp LBKT>; + mods = <(MOD_LSFT|MOD_RSFT)>; + //keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //^マーク + jis_N6: jis_N6 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N6"; + #binding-cells = <0>; + bindings = <&kp N6>, <&kp EQUAL>; + mods = <(MOD_LSFT|MOD_RSFT)>; + //keep-mods = <(MOD_LSFT|MOD_RSFT)>; + //&マーク + }; + jis_N7: jis_N7 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N7"; + #binding-cells = <0>; + bindings = <&kp N7>, <&kp N6>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //アスタリスクマーク + jis_N8: jis_N8 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N8"; + #binding-cells = <0>; + bindings = <&kp N8>, <&kp SQT>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + // (マーク + jis_N9: jis_N9 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N9"; + #binding-cells = <0>; + bindings = <&kp N9>, <&kp N8>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + // )マーク + jis_N0: jis_N0 { + compatible = "zmk,behavior-mod-morph"; + label = "jis_N0"; + #binding-cells = <0>; + bindings = <&kp N0>, <&kp N9>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //アンダーバー + jis_MINUS: jis_MINUS { + compatible = "zmk,behavior-mod-morph"; + label = "jis_MINUS"; + #binding-cells = <0>; + bindings = <&kp MINUS>, <&kp INT1>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //イコールとプラス + jis_EQUAL: jis_EQUAL { + compatible = "zmk,behavior-mod-morph"; + label = "jis_EQUAL"; + #binding-cells = <0>; + bindings = <&kp LS(MINUS)>, <&kp SEMI>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + // [マーク + jis_LBKT: jis_LBKT { + compatible = "zmk,behavior-mod-morph"; + label = "jis_LBKT"; + #binding-cells = <0>; + bindings = <&kp RBKT>, <&kp RBKT>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + // ]マーク + jis_RBKT: jis_RBKT { + compatible = "zmk,behavior-mod-morph"; + label = "jis_RBKT"; + #binding-cells = <0>; + bindings = <&kp BSLH>, <&kp BSLH>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + // yenマーク + jis_BSLH: jis_BSLH { + compatible = "zmk,behavior-mod-morph"; + label = "jis_BSLH"; + #binding-cells = <0>; + bindings = <&kp INT3>, <&kp INT3>; //INT3ではないかも + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //コロンセミコロン + jis_SEMI: jis_SEMI { + compatible = "zmk,behavior-mod-morph"; + label = "jis_SEMI"; + #binding-cells = <0>; + bindings = <&kp SEMI>, <&kp SQT>; + mods = <(MOD_LSFT|MOD_RSFT)>; + //keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + //クオーテーション + jis_SQT: jis_SQT { + compatible = "zmk,behavior-mod-morph"; + label = "jis_SQT"; + #binding-cells = <0>; + bindings = <&kp LS(N7)>, <&kp N2>; + mods = <(MOD_LSFT|MOD_RSFT)>; + keep-mods = <(MOD_LSFT|MOD_RSFT)>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //DEL + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &kp DEL + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(N4)) + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + //win + //レイヤー2のリマップが必要な箇所を修正してある + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp DEL + &jis_GRAVE &kp N1 &jis_N2 &kp N3 &kp N4 &kp N5 &jis_N6 &jis_N7 &jis_N8 &jis_N9 &jis_N0 &jis_MINUS &jis_EQUAL &kp BSPC + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &jis_LBKT &jis_RBKT &jis_BSLH + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &jis_SEMI &jis_SQT &kp RET + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + //ハイフンキーにbootloaderを入れてある。 + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &bootloader &kp C_AL_CALC &trans //bootloaderを入れる + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(S)) + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END + // + &none &none &none &none &none + >; + }; + + + + + }; +}; diff --git a/app/boards/shields/keychron/b1/us/keychron_b1_us.overlay b/app/boards/shields/keychron/b1/us/keychron_b1_us.overlay new file mode 100644 index 00000000000..56bd7621c8d --- /dev/null +++ b/app/boards/shields/keychron/b1/us/keychron_b1_us.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //del + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(6,11) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //'\' + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(2,10) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //enter + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,10) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //rshit + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) + //lctrl //win l //alt l //space //alt r //fn //left //up //down //right + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/b2/jis/Kconfig.shield b/app/boards/shields/keychron/b2/jis/Kconfig.shield new file mode 100644 index 00000000000..7d4912281cd --- /dev/null +++ b/app/boards/shields/keychron/b2/jis/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B2 + bool + +config SHIELD_KEYCHRON_B2_JIS + def_bool $(shields_list_contains,keychron_b2_jis) + select SHIELD_KEYCHRON_B2 + + + diff --git a/app/boards/shields/keychron/b2/jis/keychron_b2_jis.conf b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.conf new file mode 100644 index 00000000000..0b6f5509ec3 --- /dev/null +++ b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B2 Pro" +CONFIG_BT_DIS_MODEL="Keychron B2 Pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B2 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0722 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0722 +CONFIG_BT_DIS_FW_REV_STR="v1.0.2" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024051614230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b2/jis/keychron_b2_jis.keymap b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.keymap new file mode 100644 index 00000000000..8b3a4a85fff --- /dev/null +++ b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <61 72>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <73 63>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <76>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <88>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp LANG2 &kp SPACE &kp LANG1 &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &trans &trans &trans + &trans &trans &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &kp LGUI &kp LALT &kp INT5 &kp SPACE &kp INT4 &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &trans &trans &trans + &trans &trans &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b2/jis/keychron_b2_jis.overlay b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.overlay new file mode 100644 index 00000000000..64aa6c80055 --- /dev/null +++ b/app/boards/shields/keychron/b2/jis/keychron_b2_jis.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(3, 0) RC(6,11) RC(6,14) RC(6,13) RC(7,13) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //int3 //back //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(0,10) RC(1,10) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4, 8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //int1 //rshit //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(5,6) RC(2,15) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //int5 //space //int4 //int2 //fn //left //up //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(5,1) RC(3,11) RC(5,2) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/b2/kr/Kconfig.shield b/app/boards/shields/keychron/b2/kr/Kconfig.shield new file mode 100644 index 00000000000..b59549bd5d2 --- /dev/null +++ b/app/boards/shields/keychron/b2/kr/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B2 + bool + +config SHIELD_KEYCHRON_B2_KR + def_bool $(shields_list_contains,keychron_b2_kr) + select SHIELD_KEYCHRON_B2 + + + diff --git a/app/boards/shields/keychron/b2/kr/keychron_b2_kr.conf b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.conf new file mode 100644 index 00000000000..88438b9b3b1 --- /dev/null +++ b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.conf @@ -0,0 +1,14 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B2 Pro" +CONFIG_BT_DIS_MODEL="Keychron B2 Pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B2 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0723 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0723 +CONFIG_BT_DIS_FW_REV_STR="v1.0.2" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024071214230078" + +#uart debug +#CONFIG_ZMK_UART_LOGGING=y \ No newline at end of file diff --git a/app/boards/shields/keychron/b2/kr/keychron_b2_kr.keymap b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.keymap new file mode 100644 index 00000000000..d3dbab76caf --- /dev/null +++ b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <61 71>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <72 63>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <75>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <86>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &kp C_AC_SEARCH &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &uc LC(LEFT) &uc LC(RIGHT) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp BSLH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &trans &trans &trans + &MA 0x770100 &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(N4)) &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &trans &trans &trans + &trans &trans &trans &trans &kp LANG2 &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp C_AL_CALC &uc LG(TAB) &uc LG(LC(LEFT)) &uc LG(LC(RIGHT)) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp BSLH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp LANG1 &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans + &MA 0x770100 &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(S)) &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &trans &trans &trans + &trans &trans &trans &trans &kp LANG2 &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b2/kr/keychron_b2_kr.overlay b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.overlay new file mode 100644 index 00000000000..031c649489f --- /dev/null +++ b/app/boards/shields/keychron/b2/kr/keychron_b2_kr.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(3, 0) RC(6,11) RC(6,14) RC(6,13) RC(7,13) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //'\' //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(2,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //rshit //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt r //fn //left //up //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + +//&uart0{ +// status="okay"; +//}; \ No newline at end of file diff --git a/app/boards/shields/keychron/b2/uk/Kconfig.shield b/app/boards/shields/keychron/b2/uk/Kconfig.shield new file mode 100644 index 00000000000..38147600b8f --- /dev/null +++ b/app/boards/shields/keychron/b2/uk/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B2 + bool + +config SHIELD_KEYCHRON_B2_UK + def_bool $(shields_list_contains,keychron_b2_uk) + select SHIELD_KEYCHRON_B2 + + + diff --git a/app/boards/shields/keychron/b2/uk/keychron_b2_uk.conf b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.conf new file mode 100644 index 00000000000..d298b262a71 --- /dev/null +++ b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B2 Pro" +CONFIG_BT_DIS_MODEL="Keychron B2 Pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B2 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0721 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0721 +CONFIG_BT_DIS_FW_REV_STR="v1.0.2" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024051614230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b2/uk/keychron_b2_uk.keymap b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.keymap new file mode 100644 index 00000000000..2b234dbcbd6 --- /dev/null +++ b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <60 72>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <73 62>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <76>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <87>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &trans &trans &trans + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &trans &trans &trans + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b2/uk/keychron_b2_uk.overlay b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.overlay new file mode 100644 index 00000000000..23a92e2599a --- /dev/null +++ b/app/boards/shields/keychron/b2/uk/keychron_b2_uk.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(3, 0) RC(6,11) RC(6,14) RC(6,13) RC(7,13) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //NUBS //z //x //c //v //b //n //m //,< //.> //?/ //rshit //1 //2 //3 + RC(1,15) RC(3,2) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt gr //fn //left //up //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/b2/us/Kconfig.shield b/app/boards/shields/keychron/b2/us/Kconfig.shield new file mode 100644 index 00000000000..06ecc2f9272 --- /dev/null +++ b/app/boards/shields/keychron/b2/us/Kconfig.shield @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B2 + bool + +config SHIELD_KEYCHRON_B2_US + def_bool $(shields_list_contains,keychron_b2_us) + select SHIELD_KEYCHRON_B2 + + + diff --git a/app/boards/shields/keychron/b2/us/keychron_b2_us.conf b/app/boards/shields/keychron/b2/us/keychron_b2_us.conf new file mode 100644 index 00000000000..911658fdad2 --- /dev/null +++ b/app/boards/shields/keychron/b2/us/keychron_b2_us.conf @@ -0,0 +1,14 @@ +CONFIG_USB_DEVICE_PRODUCT="Keychron B2 Pro" +CONFIG_BT_DIS_MODEL="Keychron B2 Pro" +CONFIG_ZMK_KEYBOARD_NAME="Keychron B2 Pro" + +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0720 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0720 +CONFIG_BT_DIS_FW_REV_STR="v1.0.2" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024051614230078" + +#uart debug +#CONFIG_ZMK_UART_LOGGING=y \ No newline at end of file diff --git a/app/boards/shields/keychron/b2/us/keychron_b2_us.keymap b/app/boards/shields/keychron/b2/us/keychron_b2_us.keymap new file mode 100644 index 00000000000..dfd28a5fbed --- /dev/null +++ b/app/boards/shields/keychron/b2/us/keychron_b2_us.keymap @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <61 71>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <72 63>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <75>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <86>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //ESC //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp BSLH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &mo 1 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(N4)) &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &trans &trans &trans + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp DEL &kp HOME &kp PG_UP &kp PG_DN + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp BSLH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &mo 3 &kp LEFT &kp UP &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(S)) &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &trans &trans &trans + &trans &trans &trans &trans &kp RCTRL &trans &kp HOME &kp PG_UP &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b2/us/keychron_b2_us.overlay b/app/boards/shields/keychron/b2/us/keychron_b2_us.overlay new file mode 100644 index 00000000000..031c649489f --- /dev/null +++ b/app/boards/shields/keychron/b2/us/keychron_b2_us.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //del //home //pgup //pgdn + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(3, 0) RC(6,11) RC(6,14) RC(6,13) RC(7,13) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //'\' //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(2,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //rshit //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt r //fn //left //up //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,14) RC(3,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + +//&uart0{ +// status="okay"; +//}; \ No newline at end of file diff --git a/app/boards/shields/keychron/b6/jis/Kconfig.shield b/app/boards/shields/keychron/b6/jis/Kconfig.shield new file mode 100644 index 00000000000..24175117c51 --- /dev/null +++ b/app/boards/shields/keychron/b6/jis/Kconfig.shield @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B6_JIS + def_bool $(shields_list_contains,keychron_b6_jis) + + + + diff --git a/app/boards/shields/keychron/b6/jis/keychron_b6_jis.conf b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.conf new file mode 100644 index 00000000000..ef048dcb9d6 --- /dev/null +++ b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.conf @@ -0,0 +1,7 @@ +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0763 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0763 +CONFIG_BT_DIS_FW_REV_STR="v1.3.3" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024041614230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b6/jis/keychron_b6_jis.keymap b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.keymap new file mode 100644 index 00000000000..5b8b6b4231e --- /dev/null +++ b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.keymap @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +// &main_encoder { +// status = "okay"; +// }; + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + //fn = 95+7 -1 + //j = 63+8 -1 + //z = 79+2 -1 + //x = 79+3 -1 + //l = 63+10 -1 + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <70 81>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <82 72>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <85>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <98>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_win_r { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <106>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + // hold-tap that doesn't do anything on tap and BT_CLR on hold + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &uc LG(LS(N4)) &none &none &kp C_AC_SEARCH &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &uc LC(LEFT) &uc LC(RIGHT) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp LANG2 &kp SPACE &kp LANG1 &uc RCMD &mo 1 &uc RALT &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp PSCRN &kp SLCK &kp PAUS &kp C_AL_CALC &uc LG(TAB) &uc LG(LC(LEFT)) &uc LG(LC(RIGHT)) //21 + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp INT3 &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp KP_MINUS //42 + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS //63 + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 //63+21-5 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp INT1 &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 //79+21-5 + &kp LCTRL &kp LGUI &kp LALT &kp INT5 &kp SPACE &kp INT4 &kp RALT &mo 3 &kp RGUI &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b6/jis/keychron_b6_jis.overlay b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.overlay new file mode 100644 index 00000000000..81dcf191550 --- /dev/null +++ b/app/boards/shields/keychron/b6/jis/keychron_b6_jis.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //print //scr //pause + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(5,17) RC(7,9) RC(0,9) RC(0,0) RC(7,16) RC(4,16) RC(2,16) RC(5,16) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //int3 //back //ins //home //pg up //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(0,10) RC(1,10) RC(6,12) RC(6,14) RC(6,13) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //del //end //pg dn //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(6,11) RC(7,14) RC(7,13) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4, 8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //int1 //rshit //up //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(5,6) RC(2,15) RC(3,14) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //int5/lan2 //space //int4/lan1 //alt r //fn //win r //ctrl r //left //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(5,1) RC(3,11) RC(5,2) RC(5,9) RC(2,9) RC(2,17) RC(4,0) RC(5,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + + +}; + diff --git a/app/boards/shields/keychron/b6/uk/Kconfig.shield b/app/boards/shields/keychron/b6/uk/Kconfig.shield new file mode 100644 index 00000000000..0d437d27a35 --- /dev/null +++ b/app/boards/shields/keychron/b6/uk/Kconfig.shield @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + + +config SHIELD_KEYCHRON_B6_UK + def_bool $(shields_list_contains,keychron_b6_uk) + + + + diff --git a/app/boards/shields/keychron/b6/uk/keychron_b6_uk.conf b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.conf new file mode 100644 index 00000000000..c1f61841b8e --- /dev/null +++ b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.conf @@ -0,0 +1,7 @@ +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0762 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0762 +CONFIG_BT_DIS_FW_REV_STR="v1.3.3" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024040914230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b6/uk/keychron_b6_uk.keymap b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.keymap new file mode 100644 index 00000000000..0646f763f2f --- /dev/null +++ b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.keymap @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + + + +#include +#include +#include +#include +#include + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + //fn = 95+7 -1 + //j = 63+8 -1 + //z = 79+2 -1 + //x = 79+3 -1 + //l = 63+10 -1 + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <69 81>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <82 71>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <85>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <97>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_win_r { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <101>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + // hold-tap that doesn't do anything on tap and BT_CLR on hold + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &uc LG(LS(N4)) &none &none &kp C_AC_SEARCH &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &uc LC(LEFT) &uc LC(RIGHT) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &uc RALT &mo 1 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp PSCRN &kp SLCK &kp PAUS &kp C_AL_CALC &uc LG(TAB) &uc LG(LC(LEFT)) &uc LG(LC(RIGHT)) //21 + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp KP_MINUS //42 + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS //63 + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp NUHS &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 //63+21-5 + &kp LSHFT &kp NUBS &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 //79+21-5 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &kp RGUI &mo 3 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + // + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b6/uk/keychron_b6_uk.overlay b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.overlay new file mode 100644 index 00000000000..9f696b6d055 --- /dev/null +++ b/app/boards/shields/keychron/b6/uk/keychron_b6_uk.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + + + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //print //scr //pause + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(5,17) RC(7,9) RC(0,9) RC(0,0) RC(7,16) RC(4,16) RC(2,16) RC(5,16) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //ins //home //pg up //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(6,12) RC(6,14) RC(6,13) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //del //end //pg dn //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(6,11) RC(7,14) RC(7,13) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //NUHS //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(2,10) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //NUBS //z //x //c //v //b //n //m //,< //.> //?/ //rshit //up //1 //2 //3 + RC(1,15) RC(3,2) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(3,14) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt r //win r //fn //ctrl r //left //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,7) RC(4,0) RC(5,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; +}; + + \ No newline at end of file diff --git a/app/boards/shields/keychron/b6/us/Kconfig.shield b/app/boards/shields/keychron/b6/us/Kconfig.shield new file mode 100644 index 00000000000..6d95f78a0e9 --- /dev/null +++ b/app/boards/shields/keychron/b6/us/Kconfig.shield @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Keychron +# SPDX-License-Identifier: MIT + + +config SHIELD_KEYCHRON_B6_US + def_bool $(shields_list_contains,keychron_b6_us) + + + diff --git a/app/boards/shields/keychron/b6/us/keychron_b6_us.conf b/app/boards/shields/keychron/b6/us/keychron_b6_us.conf new file mode 100644 index 00000000000..1b23d1c66f2 --- /dev/null +++ b/app/boards/shields/keychron/b6/us/keychron_b6_us.conf @@ -0,0 +1,7 @@ +CONFIG_USB_DEVICE_VID=0x3434 +CONFIG_USB_DEVICE_PID=0x0761 +CONFIG_BT_DIS_PNP_VID=0x3434 +CONFIG_BT_DIS_PNP_PID=0x0761 +CONFIG_BT_DIS_FW_REV_STR="v1.3.3" +CONFIG_BT_DIS_HW_REV_STR="v1.0.0" +CONFIG_BT_DIS_SERIAL_NUMBER_STR="SN2024013114230078" \ No newline at end of file diff --git a/app/boards/shields/keychron/b6/us/keychron_b6_us.keymap b/app/boards/shields/keychron/b6/us/keychron_b6_us.keymap new file mode 100644 index 00000000000..fbb7be638ae --- /dev/null +++ b/app/boards/shields/keychron/b6/us/keychron_b6_us.keymap @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +// &main_encoder { +// status = "okay"; +// }; + +/ { + ZMK_MACRO(recover, bindings = <&out OUT_RECOVER>;) + ZMK_MACRO(change, bindings = <&out OUT_FN>;) + ZMK_MACRO(fn_win, bindings = <&out OUT_FN_WIN>;) + + ZMK_MACRO(en_bootloader, bindings = <&bootloader>;) + ZMK_MACRO1(MA,bindings=<&kp 0x770000>;) + + long_press_recover:l1 { + compatible = "zmk,behavior-hold-tap"; + label = "l1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&recover>, <&none>; + }; + + long_press_change:l2{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_change"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&change>, <&none>; + }; + long_press_bootloader:l3{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_bootloader"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&en_bootloader>, <&none>; + }; + long_press_fn_win:l4{ + compatible = "zmk,behavior-hold-tap"; + label = "lp_fn_win"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; + bindings = <&fn_win>, <&none>; + }; + + //fn = 95+7 -1 + //j = 63+8 -1 + //z = 79+2 -1 + //x = 79+3 -1 + //l = 63+10 -1 + combos1 { + compatible = "zmk,combos"; + combo_jz { + timeout-ms = <1000>; + layers = <1 3>; + key-positions = <70 80>; //fn+j+z + bindings = <&long_press_recover 0 0>; + }; + combo_xl { + timeout-ms = <1000>; + layers =< 1 3>; + key-positions = <81 72>; //fn+x+l + bindings = <&long_press_change 0 0>; + }; + combo_b { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <84>; //fn+b + bindings = <&out OUT_BAT>; + }; + + combo_win_l { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <96>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_win_r { + timeout-ms = <1000>; + layers =< 1 3>; + //slow-release = ; + key-positions = <100>; //fn+win + bindings = <&long_press_fn_win 0 0>; + }; + combo_t0 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 90>; + bindings = <&to 3 >; + }; + combo_t1 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 91>; + bindings = <&tog 3 >; + }; + combo_t2 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <80 92>; + bindings = <&sl 3 >; + }; + combo_t3 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <70 93>; + bindings = << 3 SPACE>; + }; + combo_t4 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 94>; + bindings = <&sk LSHIFT>; + }; + combo_t5 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&mt LSHIFT SPACE>; + }; + combo_t6 { + timeout-ms = <10 >; + layers =<4>; + + key-positions = <81 93>; + bindings = <&gresc>; + }; + }; + + td0 { + compatible = "zmk,behavior-tap-dance"; + label = "TAPD_LAYER"; + #binding-cells = <1>; + tapping-term-ms = <350>; + bindings =<&mo 0>,<&mo 0>,<&mo 0>,<&mo 0>,<&to 0>; + }; + ZMK_MACRO(bt_pair0, bindings = <&bt BT_PAIR 0>;) + ZMK_MACRO(bt_pair1, bindings = <&bt BT_PAIR 1>;) + ZMK_MACRO(bt_pair2, bindings = <&bt BT_PAIR 2>;) + ZMK_MACRO(bt_pair3, bindings = <&bt BT_PAIR 3>;) + ZMK_MACRO(bt_recon_0, bindings = <&bt BT_SEL 0>;) + ZMK_MACRO(bt_recon_1, bindings = <&bt BT_SEL 1>;) + ZMK_MACRO(bt_recon_2, bindings = <&bt BT_SEL 2>;) + ZMK_MACRO(bt_recon_3, bindings = <&bt BT_SEL 3>;) + + + // hold-tap that doesn't do anything on tap and BT_CLR on hold + bt_pair_0: bt_pair_0 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair0"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair0>, <&bt_recon_0>; + }; + bt_pair_1: bt_pair_1 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair1"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair1>, <&bt_recon_1>; + }; + bt_pair_2: bt_pair_2 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair2"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair2>, <&bt_recon_2>; + }; + bt_pair_3: bt_pair_3 { + compatible = "zmk,behavior-hold-tap"; + label = "bt_pair3"; + #binding-cells = <2>; + flavor = "tap-preferred"; + tapping-term-ms = <3000>; // delay amount in ms + bindings = <&bt_pair3>, <&bt_recon_3>; + }; + uc:user_custom { + compatible = "zmk,behavior-key-press"; + label ="user_custom"; + #binding-cells =<1>; + }; + keymap { + compatible = "zmk,keymap"; + //mac + default_layer { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //f14 //f15 //f16 //f17 + &kp ESC &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &kp C_AC_MAC_LAUNCH &kp C_AC_SEARCH &kp C_AL_LOCK &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(COMMA) &uc LG(LS(N4)) &none &none &kp C_AC_SEARCH &kp C_AC_DESKTOP_SHOW_ALL_WINDOWS &uc LC(LEFT) &uc LC(RIGHT) + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp 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 LBKT &kp RBKT &kp BSLH &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 + &kp LCTRL &uc LALT &uc LCMD &kp SPACE &uc RCMD &uc RALT &mo 1 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &mo 2 &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //mac + layer_one { + bindings = < + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AC_SEARCH &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(N4)) &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LC(LG(SPACE)) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + &none &none &none &none &none + >; + }; + //win + layer_two { + bindings = < + &kp ESC &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp F13 &kp PSCRN &kp SLCK &kp PAUS &kp C_AL_CALC &uc LG(TAB) &uc LG(LC(LEFT)) &uc LG(LC(RIGHT)) //21 + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp INS &kp HOME &kp PG_UP &kp KP_NLCK &kp KP_SLASH &kp KP_ASTERISK &kp KP_MINUS //42 + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH &kp DEL &kp END &kp PG_DN &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS //63 + &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp KP_N4 &kp KP_N5 &kp KP_N6 //63+21-5 + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp KP_N1 &kp KP_N2 &kp KP_N3 //79+21-5 + &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &kp RGUI &mo 3 &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT &kp KP_N0 &kp KP_DOT &kp KP_ENTER + // + &none &out OUT_BLE &out OUT_24G &out OUT_CHG &out OUT_CHGD + >; + }; + //win + layer_three { + bindings = < + //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f14 //f15 //f16 //f17 + &trans &kp C_BRIGHTNESS_DEC &kp C_BRIGHTNESS_INC &uc LG(TAB) &uc LG(E) &kp C_AC_SEARCH &uc LG(L) &kp C_PREVIOUS &kp C_PLAY_PAUSE &kp C_NEXT &kp C_MUTE &kp C_VOLUME_DOWN &kp C_VOLUME_UP &uc LG(I) &trans &trans &trans &trans &trans &trans &trans + &trans &bt_pair_0 0 0 &bt_pair_1 0 0 &bt_pair_2 0 0 &bt_pair_3 0 0 &trans &trans &trans &trans &trans &trans &trans &kp C_AL_CALC &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp INS &trans &trans &trans &trans &uc LG(LS(S)) &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &uc LG(DOT) &kp PG_UP &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp END &trans &trans &trans + &none &none &none &none &none + >; + }; + + + + + }; +}; + + diff --git a/app/boards/shields/keychron/b6/us/keychron_b6_us.overlay b/app/boards/shields/keychron/b6/us/keychron_b6_us.overlay new file mode 100644 index 00000000000..92e54e3a6fe --- /dev/null +++ b/app/boards/shields/keychron/b6/us/keychron_b6_us.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Nick Winans + * + * SPDX-License-Identifier: MIT + */ + +#include + + +/ { + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <18>; + rows = <8>; + map = < + //esc //f1 //f2 //f3 //f4 //f5 //f6 //f7 //f8 //f9 //f10 //f11 //f12 //f13 //print //scr //pause + RC(3,1) RC(6,2) RC(6,3) RC(1,3) RC(3,3) RC(7,0) RC(3,6) RC(1,7) RC(6,7) RC(6,10) RC(7,10) RC(3,10) RC(5,10) RC(5,17) RC(7,9) RC(0,9) RC(0,0) RC(7,16) RC(4,16) RC(2,16) RC(5,16) + //grave //1 //2 //3 //4 //5 //6 //7 //8 //9 //0 //- //+= //back //ins //home //pg up //num // / //* // - + RC(6,1) RC(7,1) RC(7,2) RC(7,3) RC(7,4) RC(6,4) RC(6,5) RC(7,5) RC(7,6) RC(7,7) RC(7,8) RC(6,8) RC(6,6) RC(1,10) RC(6,12) RC(6,14) RC(6,13) RC(4,11) RC(4,12) RC(4,13) RC(5,13) + //tab //q //w //e //r // t //y //u //i //o //p //[ //] //\ //del //end //pg dn //kp 7 //kp8 //kp 9 //kp + + RC(1,1) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(1,4) RC(1,5) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(1,8) RC(1,6) RC(2,10) RC(6,11) RC(7,14) RC(7,13) RC(0,11) RC(0,12) RC(0,13) RC(0,14) + //cap //a //s //d //f //g //h //j //k //l // ; //' " //enter //4 //5 //6 + RC(1,2) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(3,8) RC(4,10) RC(1,11) RC(1,12) RC(1,13) + //lshit //z //x //c //v //b //n //m //,< //.> //?/ //rshit //up //1 //2 //3 + RC(1,15) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(5,4) RC(5,5) RC(4,5) RC(4,6) RC(4,7) RC(5,8) RC(2,15) RC(3,14) RC(2,11) RC(2,12) RC(2,13) + //lctrl //win l //alt l //space //alt r //win r //fn //ctrl r //left //down //right //0 //dot //kp enter + RC(6,0) RC(1,16) RC(3,9) RC(3,11) RC(5,9) RC(2,9) RC(5,7) RC(4,0) RC(5,14) RC(5,11) RC(5,12) RC(3,12) RC(3,13) RC(2,14) + //m/w //bt //24g //ch //ch done + RC(8,0) RC(8,1) RC(8,2) RC(8,3) RC(8,4) + >; + }; + +}; + diff --git a/app/boards/shields/keychron/keychron.zmk.yml b/app/boards/shields/keychron/keychron.zmk.yml new file mode 100644 index 00000000000..be217dd1792 --- /dev/null +++ b/app/boards/shields/keychron/keychron.zmk.yml @@ -0,0 +1,14 @@ +file_format: "1" +id: keychron +name: keychron +type: board +arch: arm +features: + - keys + +outputs: + - usb + - ble + - 24G + +url: https://www.keychron.com/ diff --git a/app/dts/bindings/behaviors/zmk,behavior-tap-dance.yaml b/app/dts/bindings/behaviors/zmk,behavior-tap-dance.yaml index 82e1517dac9..455b21d55e4 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-tap-dance.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-tap-dance.yaml @@ -5,7 +5,7 @@ description: Tap Dance Behavior compatible: "zmk,behavior-tap-dance" -include: zero_param.yaml +include: one_param.yaml properties: bindings: diff --git a/app/include/dt-bindings/zmk/bt.h b/app/include/dt-bindings/zmk/bt.h index aaad4dc5b8b..97ad41b9984 100644 --- a/app/include/dt-bindings/zmk/bt.h +++ b/app/include/dt-bindings/zmk/bt.h @@ -8,8 +8,13 @@ #define BT_NXT_CMD 1 #define BT_PRV_CMD 2 #define BT_SEL_CMD 3 +<<<<<<< HEAD +#define BT_PAIR_CMD 4 +// #define BT_FULL_RESET_CMD 4 +======= #define BT_CLR_ALL_CMD 4 #define BT_DISC_CMD 5 +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 /* Note: Some future commands will include additional parameters, so we @@ -20,5 +25,9 @@ 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 +<<<<<<< HEAD +#define BT_PAIR BT_PAIR_CMD +======= #define BT_CLR_ALL BT_CLR_ALL_CMD 0 #define BT_DISC BT_DISC_CMD +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h index 364ffa8647a..f4bf5d1cd9b 100644 --- a/app/include/dt-bindings/zmk/keys.h +++ b/app/include/dt-bindings/zmk/keys.h @@ -1443,3 +1443,5 @@ /* Apple Globe key */ #define C_AC_NEXT_KEYBOARD_LAYOUT_SELECT (ZMK_HID_USAGE(HID_USAGE_CONSUMER, 0x029D)) #define GLOBE (C_AC_NEXT_KEYBOARD_LAYOUT_SELECT) +/* add */ +#define C_AC_MAC_LAUNCH (ZMK_HID_USAGE(HID_USAGE_CONSUMER, 0x02A0)) diff --git a/app/include/dt-bindings/zmk/outputs.h b/app/include/dt-bindings/zmk/outputs.h index 1bb8d740f9c..05d5f021051 100644 --- a/app/include/dt-bindings/zmk/outputs.h +++ b/app/include/dt-bindings/zmk/outputs.h @@ -7,4 +7,15 @@ #define OUT_TOG 0 #define OUT_USB 1 #define OUT_BLE 2 -#define OUT_NONE 3 \ No newline at end of file +<<<<<<< HEAD +#define OUT_24G 3 +#define OUT_CHG 4 +#define OUT_CHGD 5 +#define OUT_BAT 6 +#define OUT_FN 7 +#define OUT_RECOVER 8 +#define OUT_FN_WIN 9 + +======= +#define OUT_NONE 3 +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/include/zmk/activity.h b/app/include/zmk/activity.h index 2aad024a848..416e95fe9dd 100644 --- a/app/include/zmk/activity.h +++ b/app/include/zmk/activity.h @@ -8,4 +8,9 @@ enum zmk_activity_state { ZMK_ACTIVITY_ACTIVE, ZMK_ACTIVITY_IDLE, ZMK_ACTIVITY_SLEEP }; +<<<<<<< HEAD +enum zmk_activity_state zmk_activity_get_state(); +int set_state(enum zmk_activity_state state); +======= enum zmk_activity_state zmk_activity_get_state(void); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index 92b2107d88b..b31bf267008 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -23,13 +23,22 @@ void zmk_ble_clear_bonds(void); int zmk_ble_prof_next(void); int zmk_ble_prof_prev(void); int zmk_ble_prof_select(uint8_t index); +<<<<<<< HEAD +int zmk_ble_prof_pair_start(uint8_t index); +======= void zmk_ble_clear_all_bonds(void); int zmk_ble_prof_disconnect(uint8_t index); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 int zmk_ble_active_profile_index(void); int zmk_ble_profile_index(const bt_addr_le_t *addr); bt_addr_le_t *zmk_ble_profile_address(uint8_t index); +<<<<<<< HEAD +int zmk_ble_unpair_all(); +uint8_t zmk_ble_get_active_profile_bt_id(void); +uint8_t zmk_ble_is_connected(void); +======= bt_addr_le_t *zmk_ble_active_profile_addr(void); struct bt_conn *zmk_ble_active_profile_conn(void); @@ -43,6 +52,7 @@ char *zmk_ble_active_profile_name(void); int zmk_ble_unpair_all(void); int zmk_ble_set_device_name(char *name); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr); diff --git a/app/include/zmk/ble/profile.h b/app/include/zmk/ble/profile.h index 0a57f16fa4b..166cb9defb3 100644 --- a/app/include/zmk/ble/profile.h +++ b/app/include/zmk/ble/profile.h @@ -12,5 +12,10 @@ struct zmk_ble_profile { char name[ZMK_BLE_PROFILE_NAME_MAX]; + uint8_t bt_id : 4; + uint8_t is_rpa : 2; + uint8_t connected:1; + uint8_t bonded:1; + uint8_t fn_exchange; bt_addr_le_t peer; }; diff --git a/app/include/zmk/endpoints.h b/app/include/zmk/endpoints.h index c10e387dcde..694b3fa3927 100644 --- a/app/include/zmk/endpoints.h +++ b/app/include/zmk/endpoints.h @@ -28,6 +28,10 @@ #define ZMK_ENDPOINT_BLE_COUNT 0 #endif +enum { + REBOOT_ENDPOINT_BLE=0xc0, + REBOOT_ENDPOINT_24G +}; /** * The total number of different (struct zmk_endpoint_instance) values that can * be selected. @@ -74,6 +78,11 @@ enum zmk_transport zmk_endpoint_get_preferred_transport(void); */ int zmk_endpoint_toggle_preferred_transport(void); +<<<<<<< HEAD +int zmk_endpoints_send_report(uint16_t usage_page); + +uint8_t get_current_transport(void); +======= /** * Gets the endpoint instance that will be preferred if it is connected. */ @@ -110,3 +119,4 @@ int zmk_endpoint_send_mouse_report(); * Clears all HID reports for the selected endpoint. */ void zmk_endpoint_clear_reports(void); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/include/zmk/endpoints_types.h b/app/include/zmk/endpoints_types.h index 5117544b7a2..d1953791c44 100644 --- a/app/include/zmk/endpoints_types.h +++ b/app/include/zmk/endpoints_types.h @@ -11,9 +11,16 @@ * @note This type is used in settings. Do not modify existing values. */ enum zmk_transport { +<<<<<<< HEAD + ZMK_TRANSPORT_USB, + ZMK_TRANSPORT_BLE, + ZMK_TRANSPORT_24G, + ZMK_TRANSPORT_NONE +======= ZMK_TRANSPORT_NONE = 0, ZMK_TRANSPORT_USB = 1, ZMK_TRANSPORT_BLE = 2, +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 }; /** diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h index 962180e706d..9643da42957 100644 --- a/app/include/zmk/hid.h +++ b/app/include/zmk/hid.h @@ -75,6 +75,13 @@ #define ZMK_HID_REPORT_ID_KEYBOARD 0x01 #define ZMK_HID_REPORT_ID_LEDS 0x01 #define ZMK_HID_REPORT_ID_CONSUMER 0x02 +<<<<<<< HEAD +#define ZMK_HID_REPORT_ID_SYSTEM 0x03 +#define ZMK_HID_REPORT_ID_MOUSE 0x04 + +#define HID_USAGE_2(a,b) \ + HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), a,b +======= #define ZMK_HID_REPORT_ID_MOUSE 0x03 #ifndef HID_ITEM_TAG_PUSH @@ -100,6 +107,7 @@ #define HID_USAGE16(a, b) HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), a, b #define HID_USAGE16_SINGLE(a) HID_USAGE16((a & 0xFF), ((a >> 8) & 0xFF)) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 static const uint8_t zmk_hid_report_desc[] = { HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), @@ -121,6 +129,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), +<<<<<<< HEAD + //add led output + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(5), + HID_USAGE_PAGE(HID_USAGE_GEN_LEDS), + /* HID_USAGE_MINIMUM(Num Lock) */ + HID_USAGE_MIN8(1), + /* HID_USAGE_MAXIMUM(Kana) */ + HID_USAGE_MAX8(5), + /* HID_OUTPUT(Data,Var,Abs) */ + HID_OUTPUT(0x02), + HID_REPORT_SIZE(3), + HID_REPORT_COUNT(1), + /* HID_OUTPUT(Cnst,Var,Abs) */ + HID_OUTPUT(0x03), +======= #if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) HID_USAGE_PAGE(HID_USAGE_LED), @@ -136,6 +160,7 @@ static const uint8_t zmk_hid_report_desc[] = { HID_OUTPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS), #endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 HID_USAGE_PAGE(HID_USAGE_KEY), @@ -185,6 +210,43 @@ static const uint8_t zmk_hid_report_desc[] = { HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS), HID_END_COLLECTION, +<<<<<<< HEAD + HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), + HID_USAGE(HID_USAGE_GD_MOUSE), + HID_COLLECTION(HID_COLLECTION_APPLICATION), + HID_REPORT_ID(ZMK_HID_REPORT_ID_MOUSE), + HID_USAGE(HID_USAGE_GEN_DESKTOP_POINTER), + HID_COLLECTION(HID_COLLECTION_PHYSICAL), + HID_USAGE_PAGE(HID_USAGE_GEN_BUTTON), + HID_USAGE_MIN8(0x01), + HID_USAGE_MAX8(0x08), + HID_LOGICAL_MIN8(0x00), + HID_LOGICAL_MAX8(0x01), + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(8), + HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS), + + HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), + HID_USAGE(HID_USAGE_GEN_DESKTOP_X), + HID_USAGE(HID_USAGE_GEN_DESKTOP_Y), + HID_USAGE(HID_USAGE_GEN_DESKTOP_WHEEL), + HID_LOGICAL_MIN8(-127), + HID_LOGICAL_MAX8(127), + HID_REPORT_SIZE(8), + HID_REPORT_COUNT(3), + HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL), + + HID_USAGE_PAGE(HID_USAGE_CONSUMER), + HID_USAGE_2(0x38,0x02), //AC Pan + HID_LOGICAL_MIN8(-127), + HID_LOGICAL_MAX8(127), + HID_REPORT_SIZE(8), + HID_REPORT_COUNT(1), + HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL), + HID_END_COLLECTION, + HID_END_COLLECTION, + +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) HID_USAGE_PAGE(HID_USAGE_GD), HID_USAGE(HID_USAGE_GD_MOUSE), @@ -253,6 +315,7 @@ static const uint8_t zmk_hid_report_desc[] = { HID_END_COLLECTION, HID_END_COLLECTION, #endif // IS_ENABLED(CONFIG_ZMK_POINTING) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 }; #if IS_ENABLED(CONFIG_ZMK_USB_BOOT) diff --git a/app/include/zmk/leds.h b/app/include/zmk/leds.h new file mode 100644 index 00000000000..dd64ecee370 --- /dev/null +++ b/app/include/zmk/leds.h @@ -0,0 +1,34 @@ +#ifndef __LEDS_H__ +#define __LEDS_H__ +// int leds_init(void); +void leds_start(void); +void leds_stop(void); +void blue_led_set_state(uint8_t led_state); +void keyboad_led_set_onoff(uint8_t led_state); +void led_24G_set_state(uint8_t led_state); +void led_charge_set_state(uint8_t led_state); +void led_recover(void); +void led_bat_display(void); +void led_bat_display_off(void); +uint8_t get_charge_led_state(void); +enum { + LED_PEER_STATE_DISCONNECTED, + LED_PEER_STATE_CONNECTED, + LED_PEER_STATE_PAIR, + LED_PEER_STATE_RECONN, + LED_PEER_STATE_FAILE, + LED_PEER_STATE_POWER_ON, + LED_PEER_STATE_ON_100MS, + LED_PEER_STATE_BAT_LOW, + LED_PEER_STATE_BAT_CHARGING, + LED_PEER_STATE_BAT_CHARGEDONE, + LED_PEER_STATE_RECOVER, +}; +enum { + LED_BAT_NONE, + LED_BAT_CHARGING, + LED_BAT_CHARGE_DONE, + LED_BAT_LOW, + LED_BAT_SHUT_DOWN, +}; +#endif \ No newline at end of file diff --git a/app/module/drivers/CMakeLists.txt b/app/module/drivers/CMakeLists.txt index a3a15c65168..5a995e2e015 100644 --- a/app/module/drivers/CMakeLists.txt +++ b/app/module/drivers/CMakeLists.txt @@ -5,4 +5,8 @@ add_subdirectory_ifdef(CONFIG_GPIO gpio) add_subdirectory_ifdef(CONFIG_KSCAN kscan) add_subdirectory_ifdef(CONFIG_SENSOR sensor) add_subdirectory_ifdef(CONFIG_DISPLAY display) +<<<<<<< HEAD +add_subdirectory_ifdef(CONFIG_ZMK_RGB_UNDERGLOW led_strip) +======= add_subdirectory_ifdef(CONFIG_INPUT input) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/module/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c index 45fc8634e2f..6dca9abb5f8 100644 --- a/app/module/drivers/kscan/kscan_gpio_direct.c +++ b/app/module/drivers/kscan/kscan_gpio_direct.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -77,6 +77,9 @@ struct kscan_direct_config { int32_t poll_period_ms; bool toggle_mode; }; +static uint8_t long_poll; +bool is_usb_power_present(void); +void switch_to_usb(void); #if USE_INTERRUPTS static int kscan_direct_interrupt_configure(const struct device *dev, const gpio_flags_t flags) { @@ -153,7 +156,7 @@ static void kscan_direct_read_continue(const struct device *dev) { const struct kscan_direct_config *config = dev->config; struct kscan_direct_data *data = dev->data; - data->scan_time += config->debounce_scan_period_ms; + data->scan_time += long_poll?400: config->debounce_scan_period_ms; k_work_reschedule(&data->work, K_TIMEOUT_ABS_MS(data->scan_time)); } @@ -188,14 +191,16 @@ static int kscan_direct_read(const struct device *dev) { LOG_ERR("Failed to read port %s: %i", gpio->spec.port->name, active); return active; } - + zmk_debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms, &config->debounce_config); + // if(!long_poll) + // LOG_DBG("pin:%d,v:%d,counter:%d",gpio->spec.pin,active,data->pin_state[gpio->index].counter); } // Process the new state. bool continue_scan = false; - + bool changed=false; for (int i = 0; i < data->inputs.len; i++) { const struct kscan_gpio *gpio = &data->inputs.gpios[i]; struct zmk_debounce_state *deb_state = &data->pin_state[gpio->index]; @@ -210,9 +215,14 @@ static int kscan_direct_read(const struct device *dev) { } } +<<<<<<< HEAD + continue_scan = continue_scan || zmk_debounce_is_active(state); + if(state->counter) changed =true; +======= continue_scan = continue_scan || zmk_debounce_is_active(deb_state); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } - + long_poll = !changed; if (continue_scan) { // At least one key is pressed or the debouncer has not yet decided if // it is pressed. Poll quickly until everything is released. @@ -415,3 +425,37 @@ static const struct kscan_driver_api kscan_direct_api = { &kscan_direct_api); DT_INST_FOREACH_STATUS_OKAY(KSCAN_DIRECT_INIT); + + +void kscan_gpio_direct_enter_sleep(void) +{ + const struct kscan_direct_data *data = &kscan_direct_data_0; + //set p1.8/p1.9 to wakeup from system_off + //note: can't set pullup in dts!!! + for (int i = 0; i < 2; i++) { + const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec; + //NOTE:can't set interrupts more than 8 ; + // gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_LEVEL_ACTIVE); + uint32_t pin_num =NRF_GPIO_PIN_MAP(1,gpio->pin); + // LOG_ERR("pin value:%d",gpio_pin_get_raw(gpio->port,gpio->pin)); + { + // LOG_ERR("set sense ,pin:%d",pin_num); + nrf_gpio_cfg_input(pin_num, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_sense_t sense_config =GPIO_PIN_CNF_SENSE_Low; + nrf_gpio_cfg_sense_set(pin_num, sense_config); + } + } +} +uint8_t get_mode_status(void) +{ + uint8_t status =0; + const struct kscan_direct_data *data = &kscan_direct_data_0; + + for (int i = 0; i < 2; i++) { + const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec; + status |= gpio_pin_get_raw(gpio->port,gpio->pin)<<(i); + + } + LOG_ERR("mode status:%x",status); + return status; +} \ No newline at end of file diff --git a/app/module/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c index d68f1593009..8227c8503aa 100644 --- a/app/module/drivers/kscan/kscan_gpio_matrix.c +++ b/app/module/drivers/kscan/kscan_gpio_matrix.c @@ -17,8 +17,10 @@ #include #include +#include +#include -LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); +LOG_MODULE_DECLARE(zmk, 4);//CONFIG_ZMK_LOG_LEVEL); #define DT_DRV_COMPAT zmk_kscan_gpio_matrix @@ -83,6 +85,7 @@ struct kscan_matrix_data { * (config->rows * config->cols) */ struct zmk_debounce_state *matrix_state; + uint32_t *rows; }; struct kscan_matrix_config { @@ -94,7 +97,42 @@ struct kscan_matrix_config { int32_t poll_period_ms; enum kscan_diode_direction diode_direction; }; +//add ---- +static uint8_t slow_poll; +struct user_debounce_config { + struct zmk_debounce_config debounce_config; + uint32_t debounce_scan_period_ms; +}; + +static struct user_debounce_config user_debounce; +static struct user_debounce_config defualt_debouce; +void user_set_debounce(uint32_t scan_period_ms,uint32_t debounce_press_ms,uint32_t debounce_release_ms) +{ + if(scan_period_ms ==0 || debounce_press_ms==0 || debounce_release_ms==0) + { + user_debounce.debounce_scan_period_ms =defualt_debouce.debounce_scan_period_ms; + user_debounce.debounce_config.debounce_press_ms = defualt_debouce.debounce_config.debounce_press_ms; + user_debounce.debounce_config.debounce_release_ms =defualt_debouce.debounce_config.debounce_release_ms; + } + else + { + user_debounce.debounce_scan_period_ms =scan_period_ms; + user_debounce.debounce_config.debounce_press_ms = debounce_press_ms; + user_debounce.debounce_config.debounce_release_ms = debounce_release_ms; + LOG_DBG("set debounce,scan:%d,press:%d,release:%d",scan_period_ms,debounce_press_ms,debounce_release_ms); + } +} + +//esc key =row3,col1 +struct gpio_dt_spec esc_gpio = { //row3,input + .pin = 4, + .port = DEVICE_DT_GET(DT_NODELABEL(gpio1)), + .dt_flags = GPIO_ACTIVE_HIGH| GPIO_PULL_DOWN, +}; + +//--- +static int kscan_matrix_init_outputs(const struct device *dev); /** * Get the index into a matrix state array from a row and column. */ @@ -120,7 +158,7 @@ static int kscan_matrix_set_all_outputs(const struct device *dev, const int valu for (int i = 0; i < config->outputs.len; i++) { const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec; - + gpio_pin_configure_dt(gpio, GPIO_OUTPUT); int err = gpio_pin_set_dt(gpio, value); if (err) { LOG_ERR("Failed to set output %i to %i: %i", i, value, err); @@ -130,7 +168,21 @@ static int kscan_matrix_set_all_outputs(const struct device *dev, const int valu return 0; } +static int kscan_matrix_set_esc_check_outputs(const struct device *dev) { + const struct kscan_matrix_config *config = dev->config; + + for (int i = 0; i < config->outputs.len; i++) { + const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec; + gpio_pin_configure_dt(gpio, GPIO_OUTPUT); + int err = gpio_pin_set_dt(gpio, (gpio->pin == 1) ? 1 : 0); //col1,ouput=1 + if (err) { + LOG_ERR("Failed to set output %i to %i: %i", i, gpio->pin, err); + return err; + } + } + return 0; +} #if USE_INTERRUPTS static int kscan_matrix_interrupt_configure(const struct device *dev, const gpio_flags_t flags) { const struct kscan_matrix_data *data = dev->data; @@ -155,7 +207,7 @@ static int kscan_matrix_interrupt_enable(const struct device *dev) { if (err) { return err; } - + // kscan_matrix_init_outputs(dev); // While interrupts are enabled, set all outputs active so a pressed key // will trigger an interrupt. return kscan_matrix_set_all_outputs(dev, 1); @@ -168,7 +220,7 @@ static int kscan_matrix_interrupt_disable(const struct device *dev) { if (err) { return err; } - + // LOG_DBG("x"); // While interrupts are disabled, set all outputs inactive so // kscan_matrix_read() can scan them one by one. return kscan_matrix_set_all_outputs(dev, 0); @@ -192,15 +244,43 @@ static void kscan_matrix_irq_callback_handler(const struct device *port, struct #endif static void kscan_matrix_read_continue(const struct device *dev) { - const struct kscan_matrix_config *config = dev->config; + // const struct kscan_matrix_config *config = dev->config; struct kscan_matrix_data *data = dev->data; + if(slow_poll) + { + if(user_debounce.debounce_scan_period_ms<5) + data->scan_time += 10; + else + data->scan_time += user_debounce.debounce_scan_period_ms*2; + } + else + data->scan_time += user_debounce.debounce_scan_period_ms; //config->debounce_scan_period_ms; - data->scan_time += config->debounce_scan_period_ms; k_work_reschedule(&data->work, K_TIMEOUT_ABS_MS(data->scan_time)); } - +static inline bool check_more_than_one(uint32_t rowdata) { + rowdata &= rowdata - 1; + return rowdata; +} +static inline bool has_ghost_in_row(const struct device *dev,uint8_t row, uint32_t rowdata) { + struct kscan_matrix_data *data = dev->data; + const struct kscan_matrix_config *config = dev->config; + if ((check_more_than_one(rowdata)) == 0) { + return false; + } + for (uint8_t i = 0; i < config->cols; i++) { + if(data->rows[i]) + LOG_DBG("col:%d,data:%04x",i,data->rows[i]); + if (i != row && check_more_than_one(data->rows[i] & rowdata)) { + LOG_DBG("ghost ,col:%d,row:%d,data:%04x",i,row,rowdata); + return true; + } + } + return false; +} static void kscan_matrix_read_end(const struct device *dev) { + #if USE_INTERRUPTS // Return to waiting for an interrupt. kscan_matrix_interrupt_enable(dev); @@ -222,8 +302,8 @@ static int kscan_matrix_read(const struct device *dev) { // Scan the matrix. for (int i = 0; i < config->outputs.len; i++) { const struct kscan_gpio *out_gpio = &config->outputs.gpios[i]; - - int err = gpio_pin_set_dt(&out_gpio->spec, 1); + gpio_pin_configure_dt(&out_gpio->spec, GPIO_OUTPUT); + int err = gpio_pin_set_dt(&out_gpio->spec,1); if (err) { LOG_ERR("Failed to set output %i active: %i", out_gpio->index, err); return err; @@ -233,22 +313,29 @@ static int kscan_matrix_read(const struct device *dev) { k_busy_wait(CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS); #endif struct kscan_gpio_port_state state = {0}; - + uint32_t row =0; for (int j = 0; j < data->inputs.len; j++) { const struct kscan_gpio *in_gpio = &data->inputs.gpios[j]; - + const int index = state_index_io(config, in_gpio->index, out_gpio->index); + + const int active = kscan_gpio_pin_get(in_gpio, &state); if (active < 0) { LOG_ERR("Failed to read port %s: %i", in_gpio->spec.port->name, active); return active; } - - zmk_debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms, - &config->debounce_config); + row |= (active<matrix_state[index], active, user_debounce.debounce_scan_period_ms, + &user_debounce.debounce_config); } - + data->rows[i] = row; + // if(row) + // { + // LOG_DBG("col:%d,row :%04x",i,row); + // } err = gpio_pin_set_dt(&out_gpio->spec, 0); + gpio_pin_configure_dt(&out_gpio->spec, GPIO_INPUT); if (err) { LOG_ERR("Failed to set output %i inactive: %i", out_gpio->index, err); return err; @@ -261,23 +348,27 @@ static int kscan_matrix_read(const struct device *dev) { // Process the new state. bool continue_scan = false; - + bool changed=false; for (int r = 0; r < config->rows; r++) { for (int c = 0; c < config->cols; c++) { const int index = state_index_rc(config, r, c); struct zmk_debounce_state *state = &data->matrix_state[index]; if (zmk_debounce_get_changed(state)) { + const bool pressed = zmk_debounce_is_pressed(state); + if(has_ghost_in_row(dev,c,data->rows[c]) && pressed) + continue; LOG_DBG("Sending event at %i,%i state %s", r, c, pressed ? "on" : "off"); data->callback(dev, r, c, pressed); } continue_scan = continue_scan || zmk_debounce_is_active(state); + if(state->counter) changed =true; } } - + slow_poll = !changed; if (continue_scan) { // At least one key is pressed or the debouncer has not yet decided if // it is pressed. Poll quickly until everything is released. @@ -341,7 +432,7 @@ static int kscan_matrix_init_input_inst(const struct device *dev, const struct k return err; } - LOG_DBG("Configured pin %u on %s for input", gpio->spec.pin, gpio->spec.port->name); + // LOG_DBG("Configured pin %u on %s for input", gpio->spec.pin, gpio->spec.port->name); #if USE_INTERRUPTS struct kscan_matrix_data *data = dev->data; @@ -364,6 +455,7 @@ static int kscan_matrix_init_inputs(const struct device *dev) { for (int i = 0; i < data->inputs.len; i++) { const struct kscan_gpio *gpio = &data->inputs.gpios[i]; + // LOG_DBG("input,gpio:%d, index:%d,pin:%d",i,gpio->index,gpio->spec.pin); int err = kscan_matrix_init_input_inst(dev, gpio); if (err) { return err; @@ -386,7 +478,7 @@ static int kscan_matrix_init_output_inst(const struct device *dev, return err; } - LOG_DBG("Configured pin %u on %s for output", gpio->pin, gpio->port->name); + // LOG_DBG("Configured pin %u on %s for output", gpio->pin, gpio->port->name); return 0; } @@ -396,6 +488,7 @@ static int kscan_matrix_init_outputs(const struct device *dev) { for (int i = 0; i < config->outputs.len; i++) { const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec; + // LOG_DBG("output,gpio:%d index:%d,pin:%d",i,config->outputs.gpios[i].index,gpio->pin); int err = kscan_matrix_init_output_inst(dev, gpio); if (err) { return err; @@ -445,12 +538,42 @@ static void kscan_matrix_setup_pins(const struct device *dev) { static int kscan_matrix_init(const struct device *dev) { struct kscan_matrix_data *data = dev->data; + const struct kscan_matrix_config *config = dev->config; + + defualt_debouce.debounce_scan_period_ms =config->debounce_scan_period_ms; + defualt_debouce.debounce_config.debounce_press_ms =config->debounce_config.debounce_press_ms; + defualt_debouce.debounce_config.debounce_release_ms =config->debounce_config.debounce_release_ms; + + user_debounce.debounce_scan_period_ms =config->debounce_scan_period_ms; + user_debounce.debounce_config.debounce_press_ms =config->debounce_config.debounce_press_ms; + user_debounce.debounce_config.debounce_release_ms =config->debounce_config.debounce_release_ms; data->dev = dev; // Sort inputs by port so we can read each port just once per scan. kscan_gpio_list_sort_by_port(&data->inputs); +<<<<<<< HEAD + kscan_matrix_init_inputs(dev); + kscan_matrix_init_outputs(dev); + // add esc key check + kscan_matrix_set_esc_check_outputs(dev); + k_msleep(2); + + if (gpio_pin_get_dt(&esc_gpio) == 1) { + LOG_ERR("esc_press_when_poweron"); + uint8_t type = nrf_power_gpregret_get(NRF_POWER); + LOG_ERR("reboot type:%02x", type); + if(type == 0) + { + sys_reboot(0x4e);//only serial! + } + } + + kscan_matrix_set_all_outputs(dev, 0); + +======= +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 k_work_init_delayable(&data->work, kscan_matrix_work_handler); #if IS_ENABLED(CONFIG_PM_DEVICE) @@ -505,11 +628,13 @@ static const struct kscan_driver_api kscan_matrix_api = { LISTIFY(INST_COLS_LEN(n), KSCAN_GPIO_COL_CFG_INIT, (, ), n)}; \ \ static struct zmk_debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \ + static uint32_t matrix_rows[INST_COLS_LEN(n)]; \ \ COND_INTERRUPTS( \ (static struct kscan_matrix_irq_callback kscan_matrix_irqs_##n[INST_INPUTS_LEN(n)];)) \ \ static struct kscan_matrix_data kscan_matrix_data_##n = { \ + .rows = matrix_rows, \ .inputs = \ KSCAN_GPIO_LIST(COND_DIODE_DIR(n, (kscan_matrix_cols_##n), (kscan_matrix_rows_##n))), \ .matrix_state = kscan_matrix_state_##n, \ @@ -537,3 +662,30 @@ static const struct kscan_driver_api kscan_matrix_api = { &kscan_matrix_api); DT_INST_FOREACH_STATUS_OKAY(KSCAN_MATRIX_INIT); +#define MATRIX_ROWS DT_PROP_LEN(DT_NODELABEL(kscan0), row_gpios) +uint32_t matrix_get_row(uint8_t row) +{ + uint32_t col_values=0; + uint32_t cols = sizeof(matrix_rows)/4; + uint8_t read_row = (row -1 +MATRIX_ROWS) % MATRIX_ROWS; + for(int i=0;i #endif +<<<<<<< HEAD +bool all_keys_up(void); +bool is_usb_power_present() { +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) #include #endif bool is_usb_power_present(void) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #if IS_ENABLED(CONFIG_USB_DEVICE_STACK) return zmk_usb_is_powered(); #else @@ -65,7 +70,17 @@ enum zmk_activity_state zmk_activity_get_state(void) { return activity_state; } static int note_activity(void) { activity_last_uptime = k_uptime_get(); - + struct zmk_position_state_changed *pos_state; + + pos_state = as_zmk_position_state_changed(eh); + if(pos_state) + { + if(pos_state->state) + { + void bat_low_check(void); + bat_low_check(); + } + } return set_state(ZMK_ACTIVITY_ACTIVE); } @@ -75,8 +90,13 @@ void activity_work_handler(struct k_work *work) { int32_t current = k_uptime_get(); int32_t inactive_time = current - activity_last_uptime; #if IS_ENABLED(CONFIG_ZMK_SLEEP) - if (inactive_time > MAX_SLEEP_MS && !is_usb_power_present()) { + if ((inactive_time > MAX_SLEEP_MS || activity_state == ZMK_ACTIVITY_SLEEP) && !is_usb_power_present() && all_keys_up()) { // Put devices in suspend power mode before sleeping + void leds_turnoff(void); + leds_turnoff(); + void kscan_gpio_direct_enter_sleep(void); + kscan_gpio_direct_enter_sleep(); + LOG_DBG("ZMK_ACTIVITY_SLEEP"); set_state(ZMK_ACTIVITY_SLEEP); if (zmk_pm_suspend_devices() < 0) { diff --git a/app/src/battery.c b/app/src/battery.c index 811baf8e9bd..04a6ae5b6af 100644 --- a/app/src/battery.c +++ b/app/src/battery.c @@ -21,8 +21,20 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include - -static uint8_t last_state_of_charge = 0; +#include +#include +#include +#include +#include +#define BAT_VOLTAGE_LOW 3320 +#define BAT_VOLTAGE_SHUTDOWN (3045) +void zmk_battery_check(void); +void check_voltage_when_boot(void); +bool is_usb_power_present(void); +static uint8_t last_state_of_charge = 100; +static bool bat_shutdown; +static const struct device *adc = DEVICE_DT_GET(DT_NODELABEL(adc)); +static uint16_t voltage; uint8_t zmk_battery_state_of_charge(void) { return last_state_of_charge; } @@ -34,6 +46,18 @@ static const struct device *const battery = DEVICE_DT_GET(DT_CHOSEN(zmk_battery) static const struct device *battery; #endif +<<<<<<< HEAD +extern struct bt_conn *destination_connection(); +extern int bt_bas_set_battery_level_fix(struct bt_conn *conn,uint8_t level); +extern void bt_conn_unref(struct bt_conn *conn); + +static int zmk_battery_update(const struct device *battery) { + struct sensor_value state_of_charge; + struct sensor_value sensor_voltage; + + pm_device_action_run(adc,PM_DEVICE_ACTION_RESUME); + int rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE); +======= #if IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE) static uint8_t lithium_ion_mv_to_pct(int16_t bat_mv) { // Simple linear approximation of a battery based off adafruit's discharge graph: @@ -55,6 +79,7 @@ static int zmk_battery_update(const struct device *battery) { int rc; #if IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE); if (rc != 0) { @@ -68,12 +93,26 @@ static int zmk_battery_update(const struct device *battery) { LOG_DBG("Failed to get battery state of charge: %d", rc); return rc; } +<<<<<<< HEAD + rc = sensor_channel_get(battery, SENSOR_CHAN_GAUGE_VOLTAGE, &sensor_voltage); +======= #elif IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE) rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_VOLTAGE); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 if (rc != 0) { LOG_DBG("Failed to fetch battery values: %d", rc); return rc; } +<<<<<<< HEAD + voltage = sensor_voltage.val1*1000+ sensor_voltage.val2/1000; + if(voltage >BAT_VOLTAGE_LOW) + { + bat_shutdown=false; + } + zmk_battery_check(); + + LOG_DBG("bat,last per:%d,cur:%d",last_state_of_charge,state_of_charge.val1); +======= struct sensor_value voltage; rc = sensor_channel_get(battery, SENSOR_CHAN_VOLTAGE, &voltage); @@ -90,8 +129,9 @@ static int zmk_battery_update(const struct device *battery) { #else #error "Not a supported reporting fetch mode" #endif +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 - if (last_state_of_charge != state_of_charge.val1) { + if (last_state_of_charge != state_of_charge.val1 && ((state_of_charge.val1 < last_state_of_charge) ||is_usb_power_present())) { last_state_of_charge = state_of_charge.val1; rc = raise_zmk_battery_state_changed( @@ -107,15 +147,22 @@ static int zmk_battery_update(const struct device *battery) { if (bt_bas_get_battery_level() != last_state_of_charge) { LOG_DBG("Setting BAS GATT battery level to %d.", last_state_of_charge); - rc = bt_bas_set_battery_level(last_state_of_charge); + // rc = bt_bas_set_battery_level(last_state_of_charge); + struct bt_conn *conn=destination_connection(); + rc = bt_bas_set_battery_level_fix(conn,last_state_of_charge); + bt_conn_unref(conn); if (rc != 0) { LOG_WRN("Failed to set BAS GATT battery level (err %d)", rc); return rc; } } +<<<<<<< HEAD + pm_device_action_run(adc,PM_DEVICE_ACTION_SUSPEND); +======= #endif +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 return rc; } @@ -157,7 +204,14 @@ static int zmk_battery_init(void) { return -ENODEV; } +<<<<<<< HEAD + k_timer_start(&battery_timer, K_SECONDS(1), K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL)); + + check_voltage_when_boot(); + pm_device_action_run(adc,PM_DEVICE_ACTION_SUSPEND); +======= zmk_battery_start_reporting(); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 return 0; } @@ -184,3 +238,106 @@ ZMK_LISTENER(battery, battery_event_listener); ZMK_SUBSCRIPTION(battery, zmk_activity_state_changed); SYS_INIT(zmk_battery_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); + + +void zmk_battery_check(void) +{ + static uint8_t check_count=0; + LOG_DBG("voltage:%d,count:%d,state:%d",voltage,check_count,get_charge_led_state()); + if(zmk_usb_is_powered()) return; + if(voltage 2) + { + set_state(ZMK_ACTIVITY_SLEEP); + } + } + else + { + check_count=0; + } + } + else + { + if(get_charge_led_state()==LED_BAT_LOW) + led_charge_set_state(LED_BAT_NONE); + } + +} + +void check_voltage_when_boot(void) +{ + struct sensor_value sensor_voltage; + uint16_t voltage=0; + uint16_t max=0; + uint16_t min=0xffff; + uint32_t sum=0; + int i; + bat_shutdown =false; + for(i=0;i<10;i++) + { + int rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE); + if (rc != 0) { + LOG_DBG("Failed to fetch battery values: %d", rc); + return ; + } + rc = sensor_channel_get(battery, SENSOR_CHAN_GAUGE_VOLTAGE, &sensor_voltage); + if (rc != 0) { + LOG_DBG("Failed to fetch battery values: %d", rc); + return ; + } + voltage = sensor_voltage.val1*1000+ sensor_voltage.val2/1000; + sum +=voltage; + if(voltage>=max) + { + max = voltage ; + } + if(voltage2000) + { + + LOG_ERR("bat low to shutdown"); + bat_shutdown =true; + } + +} +bool bat_is_shutdown(void) +{ + return bat_shutdown; +} + +void clear_bat_shutdown(void) +{ + bat_shutdown =false; +} + +void bat_low_check(void) +{ + static int64_t last_time=0; + int64_t uptime= k_uptime_get(); + int64_t delta_time= uptime -last_time; + if((delta_time>30*1000) ||(last_time==0)) + { + if((voltage BAT_VOLTAGE_SHUTDOWN) && !zmk_usb_is_powered()) + { + led_charge_set_state(LED_BAT_LOW); + last_time = uptime; + } + } + +} \ No newline at end of file diff --git a/app/src/behavior_queue.c b/app/src/behavior_queue.c index 82c58ca8548..dcac51c934a 100644 --- a/app/src/behavior_queue.c +++ b/app/src/behavior_queue.c @@ -27,13 +27,13 @@ K_MSGQ_DEFINE(zmk_behavior_queue_msgq, sizeof(struct q_item), CONFIG_ZMK_BEHAVIO static void behavior_queue_process_next(struct k_work *work); static K_WORK_DELAYABLE_DEFINE(queue_work, behavior_queue_process_next); - +uint8_t macro_running; static void behavior_queue_process_next(struct k_work *work) { struct q_item item = {.wait = 0}; while (k_msgq_get(&zmk_behavior_queue_msgq, &item, K_NO_WAIT) == 0) { - LOG_DBG("Invoking %s: 0x%02x 0x%02x", item.binding.behavior_dev, item.binding.param1, - item.binding.param2); + LOG_DBG("Invoking %s: 0x%02x 0x%02x,%d", item.binding.behavior_dev, item.binding.param1, + item.binding.param2,item.press); struct zmk_behavior_binding_event event = {.position = item.position, .timestamp = k_uptime_get(), @@ -55,6 +55,14 @@ static void behavior_queue_process_next(struct k_work *work) { break; } } + if(k_msgq_num_used_get(&zmk_behavior_queue_msgq)>0) + { + macro_running =1; + } + else + { + macro_running =0; + } } int zmk_behavior_queue_add(const struct zmk_behavior_binding_event *event, @@ -71,6 +79,7 @@ int zmk_behavior_queue_add(const struct zmk_behavior_binding_event *event, const int ret = k_msgq_put(&zmk_behavior_queue_msgq, &item, K_NO_WAIT); if (ret < 0) { + LOG_ERR("behavior_queue full"); return ret; } @@ -80,3 +89,7 @@ int zmk_behavior_queue_add(const struct zmk_behavior_binding_event *event, return 0; } +uint8_t behavior_queue_is_full(void) +{ + return (k_msgq_num_used_get(&zmk_behavior_queue_msgq)>(CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE-32))?1:0; +} \ No newline at end of file diff --git a/app/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c index 5b15abff238..c8850cea1af 100644 --- a/app/src/behaviors/behavior_bt.c +++ b/app/src/behaviors/behavior_bt.c @@ -100,11 +100,16 @@ 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); +<<<<<<< HEAD + case BT_PAIR_CMD: + return zmk_ble_prof_pair_start(binding->param2); +======= case BT_CLR_ALL_CMD: zmk_ble_clear_all_bonds(); return 0; case BT_DISC_CMD: return zmk_ble_prof_disconnect(binding->param2); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 default: LOG_ERR("Unknown BT command: %d", binding->param1); } diff --git a/app/src/behaviors/behavior_macro.c b/app/src/behaviors/behavior_macro.c index 3e4d17321fa..5776e54f295 100644 --- a/app/src/behaviors/behavior_macro.c +++ b/app/src/behaviors/behavior_macro.c @@ -13,6 +13,21 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include "../launcher/keycodes.h" +#include "../launcher/send_string.h" + +char keychron_web_win[]= +{ + "\1\2\xe3r\1\3\xe3\1\004100|msedge.exe https://keychron.com\n" + // SS_LWIN(R)SS_DELAY(100)"msedge.exe https://keychron.com\r" +}; +char keychron_web_mac[]= +{ + "\1\2\xe3 \1\3\xe3\1\004100|safari\n\1\004100|\1\2\xe3t\1\3\xe3\1\004100|https://keychron.com\n" + //SS_LCMD( )SS_DELAY(100)"safari\r"SS_DELAY(100)SS_LCMD(T)SS_DELAY(100)"https://keychron.com\r" +}; + enum behavior_macro_mode { MACRO_MODE_TAP, MACRO_MODE_PRESS, @@ -165,11 +180,13 @@ static void queue_macro(struct zmk_behavior_binding_event *event, struct behavior_macro_trigger_state state, const struct zmk_behavior_binding *macro_binding) { LOG_DBG("Iterating macro bindings - starting: %d, count: %d", state.start_index, state.count); + LOG_DBG("state.mode:%d,macro binding:%s",state.mode,macro_binding->behavior_dev); for (int i = state.start_index; i < state.start_index + state.count; i++) { + LOG_DBG("bindings:%d,dev:%s,p1:%d,p2:%d",i,bindings[i].behavior_dev,bindings[i].param1,bindings[i].param2); if (!handle_control_binding(&state, &bindings[i])) { struct zmk_behavior_binding binding = bindings[i]; replace_params(&state, &binding, macro_binding); - + LOG_DBG("state.mode:%d",state.mode); switch (state.mode) { case MACRO_MODE_TAP: zmk_behavior_queue_add(event, binding, true, state.tap_ms); @@ -188,7 +205,7 @@ static void queue_macro(struct zmk_behavior_binding_event *event, } } } - +void dynamic_keymap_macro_send(uint8_t id); static int on_macro_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev); @@ -199,8 +216,30 @@ static int on_macro_binding_pressed(struct zmk_behavior_binding *binding, .wait_ms = cfg->default_wait_ms, .start_index = 0, .count = state->press_bindings_count}; +<<<<<<< HEAD + if(memcmp(binding->behavior_dev,"ZM_MA",5)==0) + { + LOG_DBG("via macro,p1:%x,p2:%d",binding->param1,binding->param2); + if(binding->param1 !=0x770100) + dynamic_keymap_macro_send(binding->param1 &0xff); + else + { + char * p = zmk_keymap_highest_layer_active()>=2? keychron_web_win:keychron_web_mac; + // uint8_t len = strlen(p); + // LOG_HEXDUMP_ERR(p,len,"macro"); + send_string_with_delay(p,0); + send_string_end(); + } + } + + else + { + queue_macro(event.position, cfg->bindings, trigger_state, binding); + } +======= queue_macro(&event, cfg->bindings, trigger_state, binding); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 return ZMK_BEHAVIOR_OPAQUE; } diff --git a/app/src/behaviors/behavior_outputs.c b/app/src/behaviors/behavior_outputs.c index e6b51d0c737..9a75b309142 100644 --- a/app/src/behaviors/behavior_outputs.c +++ b/app/src/behaviors/behavior_outputs.c @@ -14,12 +14,38 @@ #include #include - +#include +#include +#include +#include #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +<<<<<<< HEAD +static uint8_t bat_charge_state; +static uint8_t bat_charge_done; +static uint8_t hardware_select_transport; +static uint8_t fn_win_lock; +extern void do_f1_f13_fn_exchange(void); +void bt_24g_switch_pulldown(uint8_t current); +void bt_24g_switch_reset(void); +uint8_t skip_switch_change(void); +bool keyboard_os_is_mac(void); +void clear_bat_shutdown(void); +void reset_led_power_on(void); +uint8_t get_mode_status(void); + +uint8_t get_hardware_select_transport(void) +{ + return hardware_select_transport; +} +bool get_fn_win_lock(void) +{ + return !keyboard_os_is_mac() &&fn_win_lock ; +} +======= #if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) static const struct behavior_parameter_value_metadata std_values[] = { @@ -60,6 +86,7 @@ static const struct behavior_parameter_metadata metadata = { }; #endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { @@ -69,21 +96,208 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, case OUT_USB: return zmk_endpoint_set_preferred_transport(ZMK_TRANSPORT_USB); case OUT_BLE: +<<<<<<< HEAD + { + LOG_ERR("out ble"); + reset_led_power_on(); + hardware_select_transport = ZMK_TRANSPORT_BLE; + // nrf_power_gpregret_set(NRF_POWER,REBOOT_ENDPOINT_BLE); + // if(zmk_usb_is_powered()) return 0; + uint8_t type = nrf_power_gpregret_get(NRF_POWER); + LOG_DBG("reboot type:%02x", type); + if (type == REBOOT_ENDPOINT_BLE) + { + // bt_24g_switch_pulldown(0); + zmk_endpoints_select_transport(ZMK_TRANSPORT_BLE); + + } + else + { + nrf_power_gpregret_set(NRF_POWER,REBOOT_ENDPOINT_BLE); + LOG_ERR("set:%x",REBOOT_ENDPOINT_BLE); + LOG_DBG("REBOOT"); + + k_msleep(200); + sys_reboot(REBOOT_ENDPOINT_BLE); + } + return 0; + } + case OUT_24G: + { + LOG_ERR("out 24g"); + reset_led_power_on(); + hardware_select_transport = ZMK_TRANSPORT_24G; + // nrf_power_gpregret_set(NRF_POWER,REBOOT_ENDPOINT_24G); + // if(zmk_usb_is_powered()) return 0; + uint8_t type = nrf_power_gpregret_get(NRF_POWER); + + LOG_DBG("reboot type:%02x", type); + if (type == REBOOT_ENDPOINT_24G) + { + // bt_24g_switch_pulldown(1); + zmk_endpoints_select_transport(ZMK_TRANSPORT_24G); + + } + else + { + nrf_power_gpregret_set(NRF_POWER,REBOOT_ENDPOINT_24G); + LOG_ERR("set:%x",REBOOT_ENDPOINT_24G); + LOG_DBG("REBOOT"); + k_msleep(200); + sys_reboot(REBOOT_ENDPOINT_24G); + } + return 0; + } + case OUT_CHG: + LOG_ERR("charging"); + led_charge_set_state(LED_BAT_CHARGING); + bat_charge_state =1; + // bt_24g_switch_reset(); + clear_bat_shutdown(); + return 0;; + case OUT_CHGD: + LOG_ERR("charge done"); + led_charge_set_state(LED_BAT_CHARGE_DONE); + bat_charge_done=1; + // bt_24g_switch_reset(); + return 0; + case OUT_BAT: + led_bat_display(); + return 0; + case OUT_FN: + do_f1_f13_fn_exchange(); + return 0; + case OUT_RECOVER: + void zmk_factory_recover(void); + zmk_factory_recover(); + return 0; + case OUT_FN_WIN: + { + fn_win_lock = ~fn_win_lock; + LOG_ERR("fn win lock:%d",fn_win_lock); + } + return 0; +======= return zmk_endpoint_set_preferred_transport(ZMK_TRANSPORT_BLE); case OUT_NONE: return zmk_endpoint_set_preferred_transport(ZMK_TRANSPORT_NONE); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 default: LOG_ERR("Unknown output command: %d", binding->param1); } return -ENOTSUP; } +void zmk_24g_endpoint_disconnect(void); +void zmk_ble_endpoint_disconnect(void); + + +static int on_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + +<<<<<<< HEAD + switch (binding->param1) { + case OUT_TOG: + case OUT_USB: + break; + case OUT_BLE: + LOG_ERR("switch off:%d",binding->param1); + zmk_ble_endpoint_disconnect(); + if(zmk_usb_is_powered()&&get_mode_status()==0x03) + { + hardware_select_transport=ZMK_TRANSPORT_USB; + reset_led_power_on(); + zmk_endpoints_select_transport(ZMK_TRANSPORT_USB); + } + else + { + LOG_ERR("select transport none"); + zmk_endpoints_select_transport(ZMK_TRANSPORT_NONE); + } + return 0; + case OUT_24G: + LOG_ERR("switch off:%d",binding->param1); + // if(skip_switch_change()) + // { + // LOG_ERR("skip"); + // return 0; + // } + zmk_24g_endpoint_disconnect(); + if(zmk_usb_is_powered()&&get_mode_status()==0x03) + { + hardware_select_transport=ZMK_TRANSPORT_USB; + reset_led_power_on(); + zmk_endpoints_select_transport(ZMK_TRANSPORT_USB); + } + else + { + LOG_ERR("select transport none"); + zmk_endpoints_select_transport(ZMK_TRANSPORT_NONE); + } + return 0; + // hardware_select_transport=ZMK_TRANSPORT_USB; + // return zmk_endpoints_select_transport(ZMK_TRANSPORT_USB); + case OUT_CHG: + LOG_ERR("not charging"); + led_charge_set_state(LED_BAT_NONE); + bat_charge_state =0; + // if(bat_charge_done==0) + // { + // LOG_ERR("reset pulldown"); + // if(get_current_transport()==ZMK_TRANSPORT_BLE) + // { + // bt_24g_switch_pulldown(0); + // } + // else if(get_current_transport()==ZMK_TRANSPORT_24G) + // { + // bt_24g_switch_pulldown(1); + // } + // } + return 0; + case OUT_CHGD: + LOG_ERR("not charge done"); + if(bat_charge_state) + led_charge_set_state(LED_BAT_CHARGING); + else + led_charge_set_state(LED_BAT_NONE); + bat_charge_done=0; + // if(bat_charge_state==0) + // { + // LOG_ERR("reset pulldown"); + // if(get_current_transport()==ZMK_TRANSPORT_BLE) + // { + // bt_24g_switch_pulldown(0); + // } + // else if(get_current_transport()==ZMK_TRANSPORT_24G) + // { + // bt_24g_switch_pulldown(1); + // } + // } + return 0; + case OUT_BAT: + led_bat_display_off(); + return 0; + case OUT_FN_WIN: + return 0; + default: + LOG_ERR("Unknown output command: %d", binding->param1); + } + + return -ENOTSUP; +} +static int behavior_out_init(const struct device *dev) { return 0; } + +static const struct behavior_driver_api behavior_outputs_driver_api = { + .binding_pressed = on_keymap_binding_pressed, + .binding_released = on_keymap_binding_released, +======= static const struct behavior_driver_api behavior_outputs_driver_api = { .binding_pressed = on_keymap_binding_pressed, #if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) .parameter_metadata = &metadata, #endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 }; BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, diff --git a/app/src/behaviors/behavior_tap_dance.c b/app/src/behaviors/behavior_tap_dance.c index bbc301f1e1a..1ee6cb0dd84 100644 --- a/app/src/behaviors/behavior_tap_dance.c +++ b/app/src/behaviors/behavior_tap_dance.c @@ -119,7 +119,18 @@ static inline int press_tap_dance_behavior(struct active_tap_dance *tap_dance, i .source = tap_dance->source, #endif }; +<<<<<<< HEAD + LOG_DBG("binding:%s,p1:%d",binding.behavior_dev,binding.param1); + if((tap_dance->param1 &0x520000) ==0x520000) + { + uint8_t layer=tap_dance->param1 &0x1f; + LOG_DBG("to layer:%d",layer); + binding.param1= layer; + } + return behavior_keymap_binding_pressed(&binding, event); +======= return zmk_behavior_invoke_binding(&binding, event, true); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } static inline int release_tap_dance_behavior(struct active_tap_dance *tap_dance, @@ -132,6 +143,12 @@ static inline int release_tap_dance_behavior(struct active_tap_dance *tap_dance, .source = tap_dance->source, #endif }; + if((tap_dance->param1 &0x520000) ==0x520000) + { + uint8_t layer=tap_dance->param1 &0x1f; + LOG_DBG("to layer:%d",layer); + binding.param1= layer; + } clear_tap_dance(tap_dance); return zmk_behavior_invoke_binding(&binding, event, false); } @@ -150,6 +167,10 @@ static int on_tap_dance_binding_pressed(struct zmk_behavior_binding *binding, LOG_DBG("%d created new tap dance", event.position); } tap_dance->is_pressed = true; + LOG_DBG("binding:%s,p1:%d,counter:%d",binding->behavior_dev,binding->param1, tap_dance->counter); + if(memcmp(binding->behavior_dev,"TAPD_LAYER",10)==0 ) + tap_dance->param1 = binding->param1|0x520000; + LOG_DBG("%d tap dance pressed", event.position); stop_timer(tap_dance); // Increment the counter on keypress. If the counter has reached its maximum diff --git a/app/src/ble.c b/app/src/ble.c index 51b172b9f5f..71139010cc9 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -19,7 +19,15 @@ #include #include #include +<<<<<<< HEAD +#include +// #include +#include "conn_internal.h" +#include +#include +======= #include +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #if IS_ENABLED(CONFIG_SETTINGS) @@ -30,16 +38,17 @@ #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); - +#include #include #include #include #include #include - -#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) +#include +#include #include - +#include +#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) #define PASSKEY_DIGITS 6 static struct bt_conn *auth_passkey_entry_conn; @@ -47,12 +56,77 @@ RING_BUF_DECLARE(passkey_entries, PASSKEY_DIGITS); #endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ +#define ADV_RECONN_TIME_OUT (3000)//(3*60*1000) +#define ADV_PAIR_TIME_OUT (3*60*1000) +#if EN_UPATE_PARAM_DYNAMIC //disable for sometime send data fail! +void ble_param_update_work_callback(struct k_work *work); +void ble_active_work_callback(struct k_work *work); +K_WORK_DELAYABLE_DEFINE(ble_active_work, ble_active_work_callback); +K_WORK_DELAYABLE_DEFINE(ble_param_update_work, ble_param_update_work_callback); +static uint8_t ble_active; +static uint8_t ble_param_update_try_count =0; +#endif + +void update_conn_param_worker(struct k_work *work); +K_WORK_DELAYABLE_DEFINE(update_conn_param_work, update_conn_param_worker); + +bt_addr_le_t * inc_bt_addr(uint8_t index); +void print_device_addr(uint8_t id); +void zmk_24g_pair(void); +void zmk_24g_reconn(void); +void set_dis_value(void); +int load_immediate_value(const char *name, void *dest, size_t len); +bool bat_is_shutdown(void); +void zmk_ble_disconn_active_profile(void); +void zmk_24g_endpoint_disconnect(void); +void ble_active_handler(void); +void set_delay_clear_bonds(uint8_t set); +uint8_t delay_clear_bonds(void); + enum advertising_type { ZMK_ADV_NONE, ZMK_ADV_DIR, ZMK_ADV_CONN, + ZMK_ADV_RECONN, + ZMK_ADV_PAIR, } advertising_status; +static uint8_t adv_state; +void sleep_worker(struct k_work *work); +K_WORK_DELAYABLE_DEFINE(sleep_work, sleep_worker); + + +static void load_identities(void) { + + bt_addr_le_t addrs[CONFIG_BT_ID_MAX]; + size_t count = ARRAY_SIZE(addrs); + + bt_id_get(addrs, &count); + + LOG_INF("Device has %zu identities\n", count); + + /* Default identity should always exist */ + for (int i = 0; i < count; i++) { + char addr_str[64] = {0}; + + bt_addr_le_to_str(&addrs[i], addr_str, sizeof(addr_str)); + LOG_INF("Device i:%d,addr:%s\n", i, addr_str); + } + + for (; count < CONFIG_BT_ID_MAX; count++) { + int err = bt_id_create(NULL, NULL); + + if (err < 0) { + printk("Cannot create identity (err:%d)\n", err); + + break; + } else { + + printk("Identity %zu created\n", count); + } + } +} + #define CURR_ADV(adv) (adv << 4) #define ZMK_ADV_CONN_NAME \ @@ -61,6 +135,8 @@ enum advertising_type { static struct zmk_ble_profile profiles[ZMK_BLE_PROFILE_COUNT]; static uint8_t active_profile; +enum advertising_type desired_adv = ZMK_ADV_NONE; // change +static uint8_t adv_bt_id; #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) @@ -76,6 +152,140 @@ static struct bt_data zmk_ble_ad[] = { BT_UUID_16_ENCODE(BT_UUID_BAS_VAL) /* Battery Service */ ), }; +//add swift pair +static const struct bt_data zmk_ble_ad_win[] = { + BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0xC1, 0x03), + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_SOME, 0x12, 0x18, /* HID Service */ + 0x0f, 0x18 /* Battery Service */ + ), + //swift pair + BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,0x06,0x00, 0x03,0x00,0x80, 'K','e','y','c','h','r','o','n',' ','K','B') + +}; +static const struct bt_data zmk_ble_ad_sr[] = { + BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), +}; + +static const struct bt_data zmk_ble_reconn_ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), +}; + +void adv_timeout_work_callback(struct k_work *work) { + int err = bt_le_adv_stop(); + advertising_status = ZMK_ADV_NONE; + blue_led_set_state( LED_PEER_STATE_DISCONNECTED); + + LOG_INF("adv timeout ,stop"); + if (err) { + LOG_ERR("Failed to stop advertising (err %d)", err); + } + k_work_reschedule(&sleep_work, (adv_state ==ZMK_ADV_RECONN)?K_MSEC(40*1000-ADV_RECONN_TIME_OUT):K_NO_WAIT); + adv_state = ZMK_ADV_NONE; +} +void sleep_worker(struct k_work *work) +{ + LOG_INF("sleep"); + set_state(ZMK_ACTIVITY_SLEEP); +} +K_WORK_DELAYABLE_DEFINE(adv_timeout_work, adv_timeout_work_callback); +void print_bt_addr(const bt_addr_le_t *addr); +int update_advertising(void); +// static struct k_work_delayable update_advertising_work; +static void update_advertising_callback(struct k_work *work) { + LOG_INF("update_advertising_callback"); + update_advertising(); +} +// K_WORK_DELAYABLE_DEFINE(update_advertising_work, update_advertising_callback); +K_WORK_DEFINE(update_advertising_work, update_advertising_callback); + +bool zmk_ble_active_profile_is_connected(void); +bool zmk_ble_active_profile_is_open(void); +int zmk_ble_prof_pair_start(uint8_t index); +int zmk_ble_prof_select(uint8_t index); +void hid_disconnected(struct bt_conn *conn, uint8_t reason); +void insert_conn_object(struct bt_conn *conn); +void load_identities(void); +struct switch_to_adv { + uint8_t adv_type : 4; + uint8_t index : 4; +}; +struct switch_to_adv switch_state; +// static uint8_t switch_to_pair; +/* Bonded address queue. */ +// K_MSGQ_DEFINE(bonds_queue, +// sizeof(bt_addr_le_t), +// CONFIG_BT_MAX_PAIRED, +// 4); + +static void bond_cnt_cb(const struct bt_bond_info *info, void *user_data) { + size_t *cnt = user_data; + if (bt_addr_le_cmp(&info->addr, zmk_ble_active_profile_addr())) { + // not same + return; + } + (*cnt)++; +} + +static size_t bond_check(uint8_t local_id) { + size_t cnt = 0; + + bt_foreach_bond(local_id, bond_cnt_cb, &cnt); + + // if(cnt==0) + // { + // profiles[local_id].bt_id =0xff; + // } + + return cnt; +} + +// extern struct k_msgq bonds_queue; + +// static void bond_find(const struct bt_bond_info *info, void *user_data) { +// int err; + +// if (bt_addr_le_cmp(&info->addr, zmk_ble_active_profile_addr()) || +// zmk_ble_active_profile_is_connected()) { +// // not same +// return; +// } +// printk("id:%d,bond peer ", active_profile); +// print_bt_addr(&info->addr); +// err = k_msgq_put(&bonds_queue, (void *)&info->addr, K_NO_WAIT); +// if (err) { +// printk("No space in the queue for the bond.\n"); +// } +// } + +static int setup_accept_list(void) { + int err = bt_le_filter_accept_list_clear(); + if (err) { + LOG_ERR("Cannot clear filter accept list (err: %d)", err); + return err; + } + + err = bt_le_filter_accept_list_add(zmk_ble_active_profile_addr()); + if (err) { + LOG_ERR("Cannot add peer to filter accept list (err: %d)", err); + return err; + } + + return 0; +} +static void advertising_start(void) { + // if (zmk_ble_active_profile_is_open()) { + // desired_adv = ZMK_ADV_CONN; + // } else if (!zmk_ble_active_profile_is_connected()) { + // desired_adv = ZMK_ADV_RECONN; + // } + + // LOG_INF("advertising_start,desired_adv:%d\n",desired_adv); + // k_work_submit(&update_advertising_work); + if(adv_state!=ZMK_ADV_PAIR) + zmk_ble_prof_select(active_profile); +} #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE) && IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) @@ -83,9 +293,28 @@ static bt_addr_le_t peripheral_addrs[ZMK_SPLIT_BLE_PERIPHERAL_COUNT]; #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */ +<<<<<<< HEAD +static void raise_profile_changed_event() { + // ZMK_EVENT_RAISE(new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){ + // .index = active_profile, .profile = &profiles[active_profile]})); + LOG_INF("raise_profile_changed_event"); + if (!zmk_ble_active_profile_is_connected() && switch_state.adv_type) { + switch (switch_state.adv_type) { + case ZMK_ADV_PAIR: + switch_state.adv_type = 0; + zmk_ble_prof_pair_start(switch_state.index); + break; + case ZMK_ADV_RECONN: + switch_state.adv_type = 0; + zmk_ble_prof_select(switch_state.index); + break; + } + } +======= static void raise_profile_changed_event(void) { raise_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){ .index = active_profile, .profile = &profiles[active_profile]}); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } static void raise_profile_changed_event_callback(struct k_work *work) { @@ -102,9 +331,27 @@ bool zmk_ble_profile_is_open(uint8_t index) { } return !bt_addr_le_cmp(&profiles[index].peer, BT_ADDR_LE_ANY); } - +void copy_profile_to_same_peer(const bt_addr_le_t *peer) { + for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) { + if (!bt_addr_le_cmp(&profiles[i].peer, peer) && + (profiles[i].bt_id != profiles[active_profile].bt_id)) { + bt_id_reset(profiles[i].bt_id,inc_bt_addr(profiles[i].bt_id), NULL); + profiles[i].bt_id = profiles[active_profile].bt_id; + // profiles[i].is_rpa = profiles[active_profile].is_rpa; + profiles[i].bonded = profiles[active_profile].bonded; + char setting_name[20]; + sprintf(setting_name, "ble/profiles/%d", i); + settings_save_one(setting_name, &profiles[i], sizeof(struct zmk_ble_profile)); + LOG_INF("copy profle %d to %d", active_profile, i); + } + } +} void set_profile_address(uint8_t index, const bt_addr_le_t *addr) { +<<<<<<< HEAD + char setting_name[20]; +======= char setting_name[17]; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 char addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); @@ -117,6 +364,11 @@ void set_profile_address(uint8_t index, const bt_addr_le_t *addr) { #endif k_work_submit(&raise_profile_changed_event_work); } +void save_profile(uint8_t index) { + char setting_name[20]; + sprintf(setting_name, "ble/profiles/%d", index); + settings_save_one(setting_name, &profiles[index], sizeof(struct zmk_ble_profile)); +} bool zmk_ble_active_profile_is_connected(void) { return zmk_ble_profile_is_connected(active_profile); @@ -128,10 +380,19 @@ bool zmk_ble_profile_is_connected(uint8_t index) { } struct bt_conn *conn; struct bt_conn_info info; +<<<<<<< HEAD + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + char addr_str[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + // LOG_INF("active profie:%d,peer:%s",active_profile,addr_str); +======= bt_addr_le_t *addr = &profiles[index].peer; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { return false; - } else if ((conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr)) == NULL) { + } else if ((conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr)) == NULL) { + LOG_INF("pro:%d,conn found none", active_profile); return false; } @@ -150,7 +411,7 @@ bool zmk_ble_profile_is_connected(uint8_t index) { return err; \ } -#define CHECKED_DIR_ADV() \ +#define _CHECKED_DIR_ADV() \ addr = zmk_ble_active_profile_addr(); \ conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); \ if (conn != NULL) { /* TODO: Check status of connection */ \ @@ -165,15 +426,135 @@ bool zmk_ble_profile_is_connected(uint8_t index) { return err; \ } \ advertising_status = ZMK_ADV_DIR; +// adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; +#define CHECKED_DIR_ADV() \ + { \ + char addr_buf[BT_ADDR_LE_STR_LEN]; \ + addr = zmk_ble_active_profile_addr(); \ + struct bt_le_adv_param adv_param; \ + adv_param = *BT_LE_ADV_CONN_DIR(addr); \ + adv_param.id = adv_bt_id; \ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { \ + adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; \ + } \ + adv_param.options |= BT_LE_ADV_OPT_USE_IDENTITY; \ + int err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); \ + if (err) { \ + LOG_ERR("Directed advertising failed to start\n"); \ + return err; \ + } \ + bt_addr_le_to_str(addr, addr_buf, BT_ADDR_LE_STR_LEN); \ + LOG_INF("Direct advertising to %s started,prof:%d,id:%d\n", addr_buf, active_profile, \ + profiles[active_profile].bt_id); \ + advertising_status = ZMK_ADV_DIR; \ + } #define CHECKED_OPEN_ADV() \ - err = bt_le_adv_start(ZMK_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); \ - if (err) { \ - LOG_ERR("Advertising failed to start (err %d)", err); \ - return err; \ - } \ + { \ + struct bt_le_adv_param adv_param; \ + adv_param = *ZMK_ADV_CONN_NAME; \ + adv_param.id = adv_bt_id; \ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { \ + adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; \ + } \ + adv_param.options |= BT_LE_ADV_OPT_USE_IDENTITY; \ + if (enable_filter == 0) { \ + adv_param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ; \ + adv_param.options |= BT_LE_ADV_OPT_FILTER_CONN; \ + } \ + err = bt_le_adv_start(&adv_param, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); \ + if (err) { \ + LOG_ERR("Advertising failed to start (err %d)", err); \ + return err; \ + } \ + advertising_status = ZMK_ADV_CONN; \ + } + +static int enable_filter = -1; +void checked_adv_stop(void) { + int err = bt_le_adv_stop(); + advertising_status = ZMK_ADV_NONE; + if (err) { + LOG_ERR("Failed to stop advertising (err %d)", err); + } + return; +} + +void checked_dir_adv(void) { + char addr_buf[BT_ADDR_LE_STR_LEN]; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + struct bt_le_adv_param adv_param; + adv_param = *BT_LE_ADV_CONN_DIR(addr); + adv_param.id = adv_bt_id; + if (profiles[active_profile].is_rpa) { + adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; + LOG_INF("dir add adv opt: RPA"); + } + if (!IS_ENABLED(CONFIG_BT_PRIVACY)) { + adv_param.options |= BT_LE_ADV_OPT_USE_IDENTITY; + LOG_INF("dir add adv opt: IDENTITY,id:%d", adv_bt_id); + } + int err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); + if (err) { + LOG_ERR("Directed advertising failed to start:%d\n", err); + return; + } + bt_addr_le_to_str(addr, addr_buf, BT_ADDR_LE_STR_LEN); + LOG_INF("Direct advertising to %s started,prof:%d,id:%d\n", addr_buf, active_profile, + profiles[active_profile].bt_id); + advertising_status = ZMK_ADV_DIR; +} + +void checked_open_adv(void) { + struct bt_le_adv_param adv_param; + adv_param = *ZMK_ADV_CONN_NAME; + adv_param.id = adv_bt_id; + + adv_param.options |= BT_LE_ADV_OPT_USE_IDENTITY; + LOG_INF("adv opt: IDENTITY,id:%d", adv_bt_id); + if (enable_filter == 0) { + adv_param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ; + adv_param.options |= BT_LE_ADV_OPT_FILTER_CONN; + LOG_INF("adv opt: FILTER"); + } + int err; + if(adv_state == ZMK_ADV_RECONN) + { + err = bt_le_adv_start(&adv_param, zmk_ble_reconn_ad, ARRAY_SIZE(zmk_ble_reconn_ad), NULL, 0); + } + else + { + if(zmk_keymap_highest_layer_active()>=2) + { + err=bt_le_adv_start(&adv_param, zmk_ble_ad_win, ARRAY_SIZE(zmk_ble_ad_win), zmk_ble_ad_sr, ARRAY_SIZE(zmk_ble_ad_sr)); + } + else + err = bt_le_adv_start(&adv_param, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); + } + if (err) { + LOG_ERR("Advertising failed to start (err %d)", err); + return; + } advertising_status = ZMK_ADV_CONN; +} +<<<<<<< HEAD +int update_advertising() { + // int err = 0; + // bt_addr_le_t *addr; + enable_filter = -1; + keyboad_led_set_onoff(0); + if (desired_adv == ZMK_ADV_RECONN) { + if (bond_check(profiles[active_profile].bt_id)) { + desired_adv = ZMK_ADV_DIR; + enable_filter = setup_accept_list(); + blue_led_set_state( LED_PEER_STATE_RECONN); + } else { + desired_adv = ZMK_ADV_CONN; + blue_led_set_state( LED_PEER_STATE_RECONN); + } + } else if (desired_adv == ZMK_ADV_PAIR) { +======= int update_advertising(void) { int err = 0; bt_addr_le_t *addr; @@ -181,55 +562,125 @@ int update_advertising(void) { enum advertising_type desired_adv = ZMK_ADV_NONE; if (zmk_ble_active_profile_is_open()) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 desired_adv = ZMK_ADV_CONN; - } else if (!zmk_ble_active_profile_is_connected()) { - desired_adv = ZMK_ADV_CONN; - // Need to fix directed advertising for privacy centrals. See - // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char - // addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(zmk_ble_active_profile_addr(), addr_str, - // sizeof(addr_str)); - - // LOG_DBG("Directed advertising to %s", addr_str); - // desired_adv = ZMK_ADV_DIR; + blue_led_set_state( LED_PEER_STATE_PAIR); + k_work_cancel_delayable(&sleep_work); } - LOG_DBG("advertising from %d to %d", advertising_status, desired_adv); + + LOG_DBG("advertising from %d to %d,adv id:%d", advertising_status, desired_adv, adv_bt_id); switch (desired_adv + CURR_ADV(advertising_status)) { case ZMK_ADV_NONE + CURR_ADV(ZMK_ADV_DIR): case ZMK_ADV_NONE + CURR_ADV(ZMK_ADV_CONN): - CHECKED_ADV_STOP(); + checked_adv_stop(); break; case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_DIR): case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_CONN): - CHECKED_ADV_STOP(); - CHECKED_DIR_ADV(); + checked_adv_stop(); + checked_dir_adv(); break; case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_NONE): - CHECKED_DIR_ADV(); + checked_dir_adv(); break; + case ZMK_ADV_CONN + CURR_ADV(ZMK_ADV_CONN): case ZMK_ADV_CONN + CURR_ADV(ZMK_ADV_DIR): - CHECKED_ADV_STOP(); - CHECKED_OPEN_ADV(); + { + checked_adv_stop(); + checked_open_adv(); + k_timeout_t timeout = (adv_state== ZMK_ADV_PAIR) ? K_MSEC(ADV_PAIR_TIME_OUT):K_MSEC(ADV_RECONN_TIME_OUT); + k_work_reschedule(&adv_timeout_work, timeout); + } break; case ZMK_ADV_CONN + CURR_ADV(ZMK_ADV_NONE): - CHECKED_OPEN_ADV(); + { + checked_open_adv(); + k_timeout_t timeout = (adv_state== ZMK_ADV_PAIR) ? K_MSEC(ADV_PAIR_TIME_OUT):K_MSEC(ADV_RECONN_TIME_OUT); + k_work_reschedule(&adv_timeout_work, timeout); + } break; } return 0; }; -static void update_advertising_callback(struct k_work *work) { update_advertising(); } - +static struct k_work_delayable factory_recover_work; +static void factory_recover_work_cb(struct k_work *work) +{ + static uint8_t state =0; + if(state==0) + { + led_recover(); + k_work_reschedule(&factory_recover_work, K_MSEC(2800)); + state++; + } + else + { + k_msleep(200); + sys_reboot(0); + } +} +void zmk_factory_recover(void) +{ + if(get_current_transport()==ZMK_TRANSPORT_BLE) + { + zmk_ble_disconn_active_profile(); + k_msleep(100); + bt_le_adv_stop(); + zmk_ble_clear_bonds(); + } + else + { + zmk_24g_endpoint_disconnect(); + set_delay_clear_bonds(1); + } +#if CONFIG_ZMK_LAUNCHER + void via_ee_delete(void); + via_ee_delete(); +#endif + settings_delete("fn_exchange"); + +<<<<<<< HEAD + + k_work_init_delayable(&factory_recover_work, factory_recover_work_cb); + k_work_reschedule(&factory_recover_work, K_MSEC(200)); +} +int zmk_ble_clear_bonds(void) +{ + char setting_name[20]; + LOG_DBG(""); + + int i; + for(i=1;i>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } } +<<<<<<< HEAD + for(i=0;i>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #if IS_ENABLED(CONFIG_SETTINGS) static void ble_save_profile_work(struct k_work *work) { + LOG_INF("-->ble_save_profile"); settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile)); } @@ -278,28 +731,148 @@ static struct k_work_delayable ble_save_work; static int ble_save_profile(void) { #if IS_ENABLED(CONFIG_SETTINGS) - return k_work_reschedule(&ble_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); + return k_work_reschedule(&ble_save_work, K_MSEC(2500)); #else return 0; #endif } +int get_empty_bt_id(void) { + uint8_t ret = -1; + uint8_t id; + for (id = 1; id < CONFIG_BT_ID_MAX; id++) { //not use id=0; + uint8_t used = 0; + for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) { + if ((id == profiles[i].bt_id) && (profiles[i].bt_id != 0x0f)) { + used = 1; + break; + } + } + if (!used) { + ret = id; + break; + } + } + LOG_INF("get empty id:%d", ret); + return ret; +} +int zmk_ble_prof_pair_start(uint8_t index) { + if (index >= ZMK_BLE_PROFILE_COUNT) { + return -ERANGE; + } + if(get_current_transport()==ZMK_TRANSPORT_24G) + { + if(index ==3) + zmk_24g_pair(); + return 0; + } + if(get_current_transport()!=ZMK_TRANSPORT_BLE || (index>=3)) + { + return -ENOTSUP; + } + if (zmk_ble_active_profile_is_connected()) // wait for disconnect! + { + struct bt_conn *conn = NULL; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + LOG_INF("wait for disconnect %d", active_profile); + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + if (conn != NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + } + switch_state.adv_type = ZMK_ADV_PAIR; + switch_state.index = index; + return -ERANGE; + } + + LOG_DBG("profile %d,pairing", index); + if (active_profile != index) { + active_profile = index; + ble_save_profile(); + raise_profile_changed_event(); + } + + if ((profiles[active_profile].bt_id == 0x0f) || + (bond_check(profiles[active_profile].bt_id) > 0)) { + int id = get_empty_bt_id(); + if (id >= 0) { + adv_bt_id = id; + } else { + LOG_ERR("bt id get failed"); + } + } else + adv_bt_id = profiles[active_profile].bt_id; + + profiles[active_profile].is_rpa = 0; + LOG_INF("in pair,prof:%d,adv bt id:%d", active_profile, adv_bt_id); + print_device_addr(adv_bt_id); + + desired_adv = ZMK_ADV_PAIR; + adv_state =ZMK_ADV_PAIR; + k_work_submit(&update_advertising_work); + return 0; +} int zmk_ble_prof_select(uint8_t index) { if (index >= ZMK_BLE_PROFILE_COUNT) { return -ERANGE; } - - LOG_DBG("profile %d", index); - if (active_profile == index) { + if(get_current_transport() == ZMK_TRANSPORT_24G) + { + if(index ==3) + { + zmk_24g_reconn(); + } + return 0; + } + if(get_current_transport()!=ZMK_TRANSPORT_BLE || (index>=3)) + { + return -ENOTSUP; + } + LOG_DBG("active profile %d need to :%d", active_profile, index); + if (active_profile == index && zmk_ble_active_profile_is_connected()) { return 0; } - active_profile = index; - ble_save_profile(); + if (zmk_ble_active_profile_is_connected()) // wait for disconnect! + { + struct bt_conn *conn = NULL; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + LOG_INF("wait for disconnect %d", active_profile); + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + if (conn != NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + } - update_advertising(); + switch_state.adv_type = ZMK_ADV_RECONN; + switch_state.index = index; + return -ERANGE; + } + if(active_profile !=index) + { + active_profile = index; + ble_save_profile(); + } - raise_profile_changed_event(); + if ((profiles[active_profile].bt_id == 0x0f)) { + int id = get_empty_bt_id(); + if (id >= 0) { + adv_bt_id = id; + profiles[active_profile].is_rpa = 0; + LOG_INF("prof:%d,bt id:%d", active_profile, adv_bt_id); + } else { + LOG_ERR("bt id get failed"); + } + } else + adv_bt_id = profiles[active_profile].bt_id; + + print_device_addr(adv_bt_id); + + desired_adv = ZMK_ADV_RECONN; + adv_state = ZMK_ADV_RECONN; + k_work_submit(&update_advertising_work); + + // raise_profile_changed_event(); return 0; }; @@ -500,8 +1073,21 @@ static bool is_conn_active_profile(const struct bt_conn *conn) { static void connected(struct bt_conn *conn, uint8_t err) { char addr[BT_ADDR_LE_STR_LEN]; struct bt_conn_info info; - LOG_DBG("Connected thread: %p", k_current_get()); + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + LOG_DBG("Connected thread: %p,conn id:%d", k_current_get(), conn->id); + if (err) { + if (err == BT_HCI_ERR_ADV_TIMEOUT) { + printk("Direct advertising to %s timed out\n", addr); + advertising_status = ZMK_ADV_NONE; + desired_adv = ZMK_ADV_CONN; + k_work_submit(&update_advertising_work); + + } else { + printk("Failed to connect to %s (%u)\n", addr, err); + } + return; + } bt_conn_get_info(conn, &info); if (info.role != BT_CONN_ROLE_PERIPHERAL) { @@ -509,29 +1095,39 @@ static void connected(struct bt_conn *conn, uint8_t err) { return; } - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); advertising_status = ZMK_ADV_NONE; + adv_state = advertising_status; + k_work_cancel_delayable(&adv_timeout_work); + blue_led_set_state( LED_PEER_STATE_CONNECTED); - if (err) { - LOG_WRN("Failed to connect to %s (%u)", addr, err); - update_advertising(); - return; - } + profiles[active_profile].connected=1; LOG_DBG("Connected %s", addr); +<<<<<<< HEAD + int ret = bt_conn_set_security(conn, BT_SECURITY_L2); + if (ret) { + LOG_ERR("Failed to set security,err:%d", ret); //,id:%d", ret,conn->id); + } +======= update_advertising(); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 if (is_conn_active_profile(conn)) { LOG_DBG("Active profile connected"); k_work_submit(&raise_profile_changed_event_work); } +#if EN_UPATE_PARAM_DYNAMIC + k_work_reschedule(&ble_active_work,K_MSEC(15000)); +#endif + k_work_reschedule(&update_conn_param_work,K_MSEC(5000)); } static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; struct bt_conn_info info; - + if(!zmk_usb_is_powered()) + keyboad_led_set_onoff(0); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("Disconnected from %s (reason 0x%02x)", addr, reason); @@ -542,15 +1138,25 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) { LOG_DBG("SKIPPING FOR ROLE %d", info.role); return; } - + profiles[active_profile].connected=0; // We need to do this in a work callback, otherwise the advertising update will still see the // connection for a profile as active, and not start advertising yet. - k_work_submit(&update_advertising_work); + // k_work_submit(&update_advertising_work); + if ((reason != BT_HCI_ERR_REMOTE_USER_TERM_CONN) && + (reason != BT_HCI_ERR_LOCALHOST_TERM_CONN) && (reason != BT_HCI_ERR_REMOTE_POWER_OFF)) { + advertising_start(); + } + else + { + if(switch_state.adv_type==0) + set_state(ZMK_ACTIVITY_SLEEP); + } if (is_conn_active_profile(conn)) { LOG_DBG("Active profile disconnected"); k_work_submit(&raise_profile_changed_event_work); } + k_work_cancel_delayable(&update_conn_param_work); } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { @@ -560,8 +1166,31 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ if (!err) { LOG_DBG("Security changed: %s level %u", addr, level); + if (level >= BT_SECURITY_L2) { + + if (bt_addr_le_is_rpa(bt_conn_get_dst(conn))) { + profiles[active_profile].is_rpa = 1; + LOG_INF("host:%s is rpa", addr); + } + if(!profiles[active_profile].bonded) + { + profiles[active_profile].bonded =1; + set_profile_address(active_profile, bt_conn_get_dst(conn)); + LOG_DBG("NOT BOND,SAVE AGAIN"); + } + } } else { LOG_ERR("Security failed: %s level %u err %d", addr, level, err); + if(err ==BT_SECURITY_ERR_PIN_OR_KEY_MISSING) + { + // bt_unpair(conn->id, bt_conn_get_dst(conn)); + bt_id_reset(conn->id,inc_bt_addr(conn->id),NULL); + profiles[active_profile].is_rpa = 0; + profiles[active_profile].bonded = 0; + set_profile_address(active_profile, BT_ADDR_LE_ANY); + LOG_INF("clear pair info"); + blue_led_set_state( LED_PEER_STATE_FAILE); + } } } @@ -572,6 +1201,10 @@ static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t l bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("%s: interval %d latency %d timeout %d", addr, interval, latency, timeout); +#if EN_UPATE_PARAM_DYNAMIC + k_work_cancel_delayable(&ble_param_update_work); + ble_param_update_try_count=0; +#endif } static struct bt_conn_cb conn_callbacks = { @@ -581,7 +1214,7 @@ static struct bt_conn_cb conn_callbacks = { .le_param_updated = le_param_updated, }; -/* + static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) { char addr[BT_ADDR_LE_STR_LEN]; @@ -589,7 +1222,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) { LOG_DBG("Passkey for %s: %06u", addr, passkey); } -*/ + #if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) @@ -655,19 +1288,45 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded) { return; } +<<<<<<< HEAD + // if (!zmk_ble_active_profile_is_open()) { + // LOG_ERR("Pairing completed but current profile is not open: %s", addr); + // bt_unpair(BT_ID_DEFAULT, dst); + // return; + // } + if (profiles[active_profile].bt_id != conn->id) + { + // if (profiles[active_profile].bt_id != 0x0f) + // { + // if(conn->id==0) + // { + // LOG_DBG("-->unpair bt 0\n"); + // bt_unpair(conn->id, bt_conn_get_dst(conn)); + // } + // else + // { + // bt_id_reset(profiles[active_profile].bt_id, inc_bt_addr(profiles[active_profile].bt_id), NULL); + // } + // LOG_INF("reset bt id:%d,new:%d", profiles[active_profile].bt_id, conn->id); + // } + profiles[active_profile].bt_id = conn->id; +======= if (!pairing_allowed_for_current_profile(conn)) { LOG_ERR("Pairing completed but current profile is not open: %s", addr); bt_unpair(BT_ID_DEFAULT, dst); return; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } + profiles[active_profile].bonded=1; set_profile_address(active_profile, dst); - update_advertising(); + // due to CONFIG_BT_ID_UNPAIR_MATCHING_BONDS + copy_profile_to_same_peer(dst); }; static struct bt_conn_auth_cb zmk_ble_auth_cb_display = { .pairing_accept = auth_pairing_accept, -// .passkey_display = auth_passkey_display, + .passkey_display = auth_passkey_display, #if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) .passkey_entry = auth_passkey_entry, @@ -675,6 +1334,7 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = { .cancel = auth_cancel, }; + static struct bt_conn_auth_info_cb zmk_ble_auth_info_cb_display = { .pairing_complete = auth_pairing_complete, }; @@ -686,10 +1346,77 @@ static void zmk_ble_ready(int err) { return; } - update_advertising(); + // update_advertising(); + // advertising_start(); + profiles[active_profile].connected=0; + // settings_subsys_init(); + + // err = settings_register(&profiles_handler); + // if (err) { + // LOG_ERR("Failed to setup the profile settings handler (err %d)", err); + // return ; + // } + + // settings_load_subtree("ble"); + advertising_start(); } +<<<<<<< HEAD +// static int zmk_ble_init(const struct device *_arg) +int zmk_ble_init(const struct device *_arg) { + + // uint8_t addr[]={0x31,0x10,0x23,0x26,0x2c,0xdc}; + // int ret=bt_ctlr_set_public_addr(addr); + // LOG_INF("bt_ctlr_set_public_addr,ret:%d\n",ret); + static bool inited =false; + if(bat_is_shutdown()) return 0; + if(inited) + { + advertising_start(); + return 0; + } + inited =true; + + for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) + profiles[i].bt_id = 0x0f; + int err = bt_enable(NULL); + + if (err) { + LOG_ERR("BLUETOOTH FAILED (%d)", err); + return err; + } + // leds_init(NULL); + +#if IS_ENABLED(CONFIG_SETTINGS) + LOG_INF("settings init"); + settings_subsys_init(); + + + err = settings_register(&profiles_handler); + if (err) { + LOG_ERR("Failed to setup the profile settings handler (err %d)", err); + return err; + } + + k_work_init_delayable(&ble_save_work, ble_save_profile_work); + + settings_load_subtree("ble"); + settings_load_subtree("bt"); + load_identities(); + + set_dis_value(); + // advertising_start(); + + if(delay_clear_bonds()) + { + zmk_ble_clear_bonds(); + set_delay_clear_bonds(0); + } + +#endif +======= static int zmk_ble_complete_startup(void) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) LOG_WRN("Clearing all existing BLE bond information from the keyboard"); @@ -721,11 +1448,13 @@ static int zmk_ble_complete_startup(void) { #endif // IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) bt_conn_cb_register(&conn_callbacks); - bt_conn_auth_cb_register(&zmk_ble_auth_cb_display); + // bt_conn_auth_cb_register(&zmk_ble_auth_cb_display); bt_conn_auth_info_cb_register(&zmk_ble_auth_info_cb_display); zmk_ble_ready(0); + // enable_llpm_mode(); + return 0; } @@ -814,14 +1543,34 @@ static int zmk_ble_handle_key_user(struct zmk_keycode_state_changed *event) { return ZMK_EV_EVENT_HANDLED; } +#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ static int zmk_ble_listener(const zmk_event_t *eh) { struct zmk_keycode_state_changed *kc_state; - + kc_state = as_zmk_keycode_state_changed(eh); - if (kc_state != NULL) { - return zmk_ble_handle_key_user(kc_state); + if ((kc_state != NULL) && !bat_is_shutdown()) { + if(kc_state->state) { + LOG_DBG("."); + if(get_current_transport()==ZMK_TRANSPORT_BLE){ + LOG_DBG("profiles:%d,bonded:%d,connected:%d",active_profile,profiles[active_profile].bonded,profiles[active_profile].connected); + if(!profiles[active_profile].connected ) + { + advertising_start(); + } +#if EN_UPATE_PARAM_DYNAMIC + else + { + ble_active_handler(); + } +#endif + } + else if(get_current_transport()==ZMK_TRANSPORT_24G) + { + zmk_24g_reconn(); + } + } } return 0; @@ -829,6 +1578,213 @@ static int zmk_ble_listener(const zmk_event_t *eh) { ZMK_LISTENER(zmk_ble, zmk_ble_listener); ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed); -#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ -SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); + +// SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); + +uint8_t zmk_ble_get_active_profile(void) { return active_profile; } + +uint8_t zmk_ble_get_active_profile_bt_id(void) { return profiles[active_profile].bt_id; } + +uint8_t zmk_ble_is_connected(void) {return profiles[active_profile].connected;} + +void zmk_ble_disconn_active_profile(void) { + if (zmk_ble_active_profile_is_connected()) // wait for disconnect! + { + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + LOG_INF("try for disconnect %d", active_profile); + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + if (conn != NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + } + } +} +void zmk_ble_endpoint_disconnect(void) +{ + if(get_current_transport()==ZMK_TRANSPORT_BLE) + { + struct bt_conn *conn = NULL; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + if (conn != NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + } + k_work_reschedule(&adv_timeout_work,K_MSEC(20)); + } +} + + +static bt_addr_le_t inced_bt_addr; +bt_addr_le_t * inc_bt_addr(uint8_t index) +{ + bt_addr_le_t addrs[CONFIG_BT_ID_MAX]; + size_t count = ARRAY_SIZE(addrs); + bt_id_get(addrs, &count); + LOG_DBG("index:%d,count:%d",index,count); + if(index DEVICEID[0]>>(i*8)); + } + sprintf(&sn[10],"%02x%02x%02x%02x",deviceid[0],deviceid[1],deviceid[2],deviceid[3]); + settings_save_one("bt/dis/serial",sn,strlen(sn)); + LOG_DBG("set sn:%s",sn); + } + else + { + LOG_DBG("sn is:%s",sn); + } +} +#if EN_UPATE_PARAM_DYNAMIC +int update_ble_conn_param(void) +{ + int rc=0; + struct bt_le_conn_param *slow_param =BT_LE_CONN_PARAM(40, 40,30,400); + struct bt_le_conn_param *active_param =BT_LE_CONN_PARAM(6, 12,30,400); + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + LOG_DBG("conn:%p,active:%d",conn,ble_active); + if (conn != NULL) { + rc= bt_conn_le_param_update(conn,ble_active?active_param:slow_param); + LOG_DBG("rc:%d",rc); + bt_conn_unref(conn); + } + return rc; +} + +void ble_active_work_callback(struct k_work *work) +{ + ble_active=0; + LOG_DBG("."); + k_work_reschedule(&ble_param_update_work,K_NO_WAIT); +} +void ble_param_update_work_callback(struct k_work *work) +{ + LOG_DBG("try_count:%d",ble_param_update_try_count); + int rc =update_ble_conn_param(); + if(rc!=0 && rc !=-EALREADY) + { + if(++ble_param_update_try_count <=3) + { + k_work_reschedule(&ble_param_update_work,K_MSEC(1000)); + } + } + else + ble_param_update_try_count =0; +} +void ble_active_handler(void) +{ + ble_active =1; + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + if(conn !=NULL) + { + struct bt_conn_info info ; + bt_conn_get_info(conn,&info); + LOG_DBG("conn interval:%d,latency:%d,timeout:%d,count:%d",info.le.interval,info.le.latency,info.le.timeout,ble_param_update_try_count); + if(info.le.interval>24) + { + if(ble_param_update_try_count==0) + { + //int rc=update_ble_conn_param(); + ble_param_update_try_count=1; + //if(rc !=0 && rc != -EALREADY) + { + // k_work_cancel_delayable(&ble_param_update_work); + k_work_reschedule(&ble_param_update_work,K_MSEC(500)); + } + } + } + bt_conn_unref(conn); + k_work_reschedule(&ble_active_work,K_MSEC(15000)); + } +} +#endif + +void update_conn_param_worker(struct k_work *work) +{ + int rc=0; + struct bt_le_conn_param *active_param =BT_LE_CONN_PARAM(6, 12,30,400); + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + + conn = bt_conn_lookup_addr_le(profiles[active_profile].bt_id, addr); + LOG_DBG("conn:%p",conn); + if (conn != NULL) { + LOG_ERR("ch inteval:%d",active_param->interval_max); + rc= bt_conn_le_param_update(conn,active_param); + LOG_ERR("rc:%d",rc); + bt_conn_unref(conn); + } +} + +uint8_t delay_clear_bonds(void) +{ + uint8_t delay_clear_bond=0; + int rc =load_immediate_value("delay_clear_bond", &delay_clear_bond, sizeof(delay_clear_bond)); + if (rc == -ENOENT) { + delay_clear_bond = 0; + LOG_DBG("delay_clear_bond:%d,default",delay_clear_bond); + } + else if(rc ==0) + { + LOG_DBG("delay_clear_bond:%d",delay_clear_bond); + } + return delay_clear_bond; +} +void set_delay_clear_bonds(uint8_t set) +{ + uint8_t delay_clear_bond=set; + LOG_ERR("set_delay_clear_bonds:%d",set); + settings_save_one("delay_clear_bond", &delay_clear_bond, sizeof(delay_clear_bond)); +} \ No newline at end of file diff --git a/app/src/dfu/CMakeLists.txt b/app/src/dfu/CMakeLists.txt new file mode 100644 index 00000000000..3db24e45a8f --- /dev/null +++ b/app/src/dfu/CMakeLists.txt @@ -0,0 +1,3 @@ +# zephyr_sources(usb_dfu.c) +zephyr_sources(tdfu_prv.c) +zephyr_sources(tdfu.c) \ No newline at end of file diff --git a/app/src/dfu/tdfu.c b/app/src/dfu/tdfu.c new file mode 100644 index 00000000000..5dbdbb07656 --- /dev/null +++ b/app/src/dfu/tdfu.c @@ -0,0 +1,739 @@ + +#include "tdfu.h" +#include "tdfu_prv.h" +#include +#if EN_ZEPHYR_DFU +#include +#include +#include +#include +#include +#endif +#include +#include +#include +LOG_MODULE_REGISTER(usb_dfu, 4); + +unsigned char my_scdfu_is_active(void) ; + + + +#define USE_VIA_USAGE_PAGE + +static unsigned char sc_dfu_rsp_buf[128]; +static unsigned char sc_dfu_sn =1; +static unsigned char sc_dfu_security_mode = DFU_ENC_NONE; +static unsigned char sc_dfu_enable = 0; +static unsigned short sc_dfu_sq=0xffff; +static unsigned char sc_dfu_wait_reboot=0; + + +UINT32 Dfu_CRC_Val = 0xFFFFFFFF; +UINT32 Dfu_CRC_Val_for_XXTEA = 0xFFFFFFFF; +static unsigned int dfu_location=0; + +static unsigned int last_sn = 0; + +// #define FLASH_WR_TEMP_BUFF_MAX_IDX 512 +static unsigned short flash_wr_temp_idx=0; +// static unsigned char flash_wr_temp_buff[FLASH_WR_TEMP_BUFF_MAX_IDX]; + +int zmk_usb_hid_send_report(const uint8_t *report, size_t len); +int zmk_usb_hid_via_send(const uint8_t *report, size_t len); +#if EN_ZEPHYR_DFU +#define SLOT0_PARTITION slot0_partition +#define SLOT1_PARTITION slot1_partition + +#define FIRMWARE_IMAGE_0_LABEL "image_0" +#define FIRMWARE_IMAGE_1_LABEL "image_1" + +#define USB_DFU_MAX_XFER_SIZE 32//CONFIG_USB_REQUEST_BUFFER_SIZE +enum dfu_state { + appIDLE, + appDETACH, + dfuIDLE, + dfuDNLOAD_SYNC, + dfuDNBUSY, + dfuDNLOAD_IDLE, + dfuMANIFEST_SYNC, + dfuMANIFEST, + dfuMANIFEST_WAIT_RST, + dfuUPLOAD_IDLE, + dfuERROR, +}; +enum dfu_status { + statusOK, + errTARGET, + errFILE, + errWRITE, + errERASE, + errCHECK_ERASED, + errPROG, + errVERIFY, + errADDRESS, + errNOTDONE, + errFIRMWARE, + errVENDOR, + errUSB, + errPOR, + errUNKNOWN, + errSTALLEDPKT +}; +#if FIXED_PARTITION_EXISTS(SLOT1_PARTITION) + #define DOWNLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT1_PARTITION) +#else + #define DOWNLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT0_PARTITION) +#endif +struct dfu_worker_data_t { + uint8_t buf[USB_DFU_MAX_XFER_SIZE]; + enum dfu_state worker_state; + uint16_t worker_len; +}; +struct dfu_data_t { + uint8_t flash_area_id; + uint32_t flash_upload_size; + /* Number of bytes sent during upload */ + uint32_t bytes_sent; + uint32_t alt_setting; /* DFU alternate setting */ + struct flash_img_context ctx; + enum dfu_state state; /* State of the DFU device */ + enum dfu_status status; /* Status of the DFU device */ + uint16_t block_nr; /* DFU block number */ + uint16_t bwPollTimeout; +}; +static struct dfu_data_t dfu_data = { + .state = appIDLE, + .status = statusOK, + .flash_area_id = DOWNLOAD_FLASH_AREA_ID, + .alt_setting = 0, + .bwPollTimeout = 0, +}; +static struct dfu_worker_data_t dfu_data_worker; +static struct k_work dfu_work; +static void dfu_work_handler(struct k_work *item); +#endif +#ifndef USE_VIA_USAGE_PAGE +int usb_send_user_if_data(uint8_t id, uint8_t *data,uint8_t len) +{ + uint8_t buf[33]={0}; + buf[0]=id; + memcpy(buf+1,data,len); + // LOG_HEXDUMP_DBG(buf,33,"tx"); + return zmk_usb_hid_send_report(buf,sizeof(buf)); + +} +#else +int usb_send_user_if_data(uint8_t id, uint8_t *data,uint8_t len) +{ + uint8_t buf[32]={0}; + buf[0]=0x03; + memcpy(buf+1,data,len>31?31:len); + return zmk_usb_hid_via_send(buf,sizeof(buf)); +} +int usb_send_user_if_data_1(uint8_t id, uint8_t *data,uint8_t len) +{ + uint8_t buf[32]={0}; + + memcpy(buf,data,len); + return zmk_usb_hid_via_send(buf,sizeof(buf)); +} +#endif +#if EN_ZEPHYR_DFU +static void dfu_reset_counters(void) +{ + dfu_data.bytes_sent = 0U; + dfu_data.block_nr = 0U; + dfu_data.state = dfuIDLE; + if (flash_img_init(&dfu_data.ctx)) { + LOG_ERR("flash img init error"); + dfu_data.state = dfuERROR; + dfu_data.status = errUNKNOWN; + } + + LOG_DBG("."); +} +static void dfu_flash_write(uint8_t *data, size_t len) +{ + bool flush = false; + + if (!len) { + /* Download completed */ + flush = true; + } + + if (flash_img_buffered_write(&dfu_data.ctx, data, len, flush)) { + LOG_ERR("flash write error"); + dfu_data.state = dfuERROR; + dfu_data.status = errWRITE; + sc_dfu_enable =0; + } else if (!len) { + const bool should_confirm = true;//IS_ENABLED(CONFIG_USB_DFU_PERMANENT_DOWNLOAD); + + LOG_DBG("flash write done"); + dfu_data.state = dfuMANIFEST_SYNC; + + + LOG_DBG("Should confirm: %d", should_confirm); + if (boot_request_upgrade(should_confirm)) { + dfu_data.state = dfuERROR; + dfu_data.status = errWRITE; + } + + } else { + dfu_data.state = dfuDNLOAD_IDLE; + } + + // LOG_DBG("bytes written 0x%x", flash_img_bytes_written(&dfu_data.ctx)); +} +static void dfu_work_handler(struct k_work *item) +{ + ARG_UNUSED(item); + + switch (dfu_data_worker.worker_state) { + case dfuIDLE: +/* + * If progressive erase is enabled, then erase take place while + * image collection, so not erase whole bank at DFU beginning + */ +#ifndef CONFIG_IMG_ERASE_PROGRESSIVELY + if (boot_erase_img_bank(DOWNLOAD_FLASH_AREA_ID)) { + dfu_data.state = dfuERROR; + dfu_data.status = errERASE; + break; + } +#endif + case dfuDNLOAD_IDLE: + dfu_flash_write(dfu_data_worker.buf, + dfu_data_worker.worker_len); + break; + default: + LOG_ERR("OUT of state machine"); + break; + } +} +#endif +void my_scdfu_init(void) +{ + +} + +static unsigned char fw_sc_upgrade_over_myhid_start(void) +{ + sc_dfu_enable=1; + dfu_location=0; + sc_dfu_sq=0; + sc_dfu_wait_reboot=0; + Dfu_CRC_Val = 0xFFFFFFFF; + Dfu_CRC_Val_for_XXTEA =0xFFFFFFFF; + + flash_wr_temp_idx=0; + last_sn = 0; + +#if (WATCH_DOG_ENABLE == 1) + app_watchdog_close(); + app_watchdog_open(MY_DFU_WATCH_DOG_TIMEOUT_MS, RESET_ALL_EXCEPT_AON); +#endif +#if EN_ZEPHYR_DFU + k_work_init(&dfu_work, dfu_work_handler); + dfu_reset_counters(); +#endif + return 0; +} + + +static void dfu_commit_temp_buff_to_flash(void) +{ +#if EN_ZEPHYR_DFU + dfu_flash_write(NULL,0); +#endif +} + +static unsigned char fw_sc_upgrade_over_myhid_write_to_flash(unsigned char *pdata ,unsigned char len) +{ + + +#if EN_ZEPHYR_DFU + switch (dfu_data.state) { + case dfuIDLE: + LOG_DBG("DFU_DNLOAD start"); + dfu_reset_counters(); + + if (dfu_data.flash_area_id != DOWNLOAD_FLASH_AREA_ID) { + dfu_data.status = errWRITE; + dfu_data.state = dfuERROR; + LOG_ERR("This area can not be overwritten"); + break; + } + LOG_INF("flash id:%d",dfu_data.flash_area_id); + dfu_data.state = dfuDNBUSY; + dfu_data_worker.worker_state = dfuIDLE; + dfu_data_worker.worker_len = len; + memcpy(dfu_data_worker.buf, pdata, len); + k_work_submit_to_queue(&USB_WORK_Q, &dfu_work); + break; + case dfuDNLOAD_IDLE: + dfu_data.state = dfuDNBUSY; + dfu_data_worker.worker_state = dfuDNLOAD_IDLE; + dfu_data_worker.worker_len = len; + + memcpy(dfu_data_worker.buf, pdata, len); + k_work_submit_to_queue(&USB_WORK_Q, &dfu_work); + break; + default: + LOG_ERR("DFU_DNLOAD wrong state %d", dfu_data.state); + dfu_data.state = dfuERROR; + dfu_data.status = errUNKNOWN; + dfu_reset_counters(); + return -EINVAL; + } + + return dfu_data.state !=dfuERROR; +#else + return 0; +#endif +} + +/* +*/ +static void fw_sc_upgrade_rsp_ack(unsigned char *pdata,unsigned char len) +{ +#ifdef USE_VIA_USAGE_PAGE + #define MAX_SIZE (32-1) +#else + #define MAX_SIZE (32) +#endif + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)pdata; + unsigned short sum; + + len+=2; //len of sum + + ackhdr->hdr_h = 0x55; + ackhdr->hdr_l = 0xaa; + ackhdr->len = len; + ackhdr->len_n = ~len; + ackhdr->sn = sc_dfu_sn++; + + if(sc_dfu_sn==0) + sc_dfu_sn=1; + + sum=0; + for(unsigned char i=0;i<(len-2);i++) + sum+=sc_dfu_rsp_buf[i+5]; + + pdata[5+len-2] = sum&0xff; + pdata[5+len-1] = (sum>>8)&0xff; + + int ret = FW_SC_UPGRADE_HID_REPORT_SEND(MY_DFU_RPT_INPUT_ID,pdata,MAX_SIZE); + + + + //retry again + if(ret) + { + + ret = FW_SC_UPGRADE_HID_REPORT_SEND(MY_DFU_RPT_INPUT_ID,pdata,MAX_SIZE); + } + + if(ret==0) + { + if((len+5)>MAX_SIZE) + { + + #ifndef USE_VIA_USAGE_PAGE + ret = FW_SC_UPGRADE_HID_REPORT_SEND(MY_DFU_RPT_INPUT_ID,(pdata+MAX_SIZE),MAX_SIZE); + #else + ret = usb_send_user_if_data_1(MY_DFU_RPT_INPUT_ID,(pdata+MAX_SIZE),MAX_SIZE); + #endif + + if(ret) + { + #ifndef USE_VIA_USAGE_PAGE + ret = FW_SC_UPGRADE_HID_REPORT_SEND(MY_DFU_RPT_INPUT_ID,(pdata+32),MAX_SIZE); + #else + ret=usb_send_user_if_data_1(MY_DFU_RPT_INPUT_ID,(pdata+MAX_SIZE),MAX_SIZE); + #endif + } + } + } + + if(ret) + { + LOG_DBG("fw_sc_upgrade_rsp_ack fail,ret = %d",ret); + sc_dfu_enable = 0; + } +} + +static void fw_sc_upgrade_rsp_model_info(unsigned char sn) +{ + //unsigned char rsp_idx=0; + BT_INFORMATION_TYPE *ackpkt = (BT_INFORMATION_TYPE *)(&sc_dfu_rsp_buf[9]); + unsigned char str_len; + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + ackhdr->rsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd =SCFWU_OPCODE_GET_MODEL_INFO; + ackhdr->ack_status = 0; + + ackpkt->BR_LE_mode = SUPPORT_LE|SUPPORT_RF; + ackpkt->bluetooth_version = 0x03; + ackpkt->command_version[0] = 0x01; + + //model string + for(unsigned char i=0;i<10;i++) + { + ackpkt->model_number[i]=0; + ackpkt->fw_version[i]=0; + ackpkt->hw_version[i]=0; + } + + str_len=sizeof(MY_FWU_STRING_NAME)-1; + if(str_len>10) + str_len=10; + memcpy(((unsigned char*)(ackpkt->model_number)),MY_FWU_STRING_NAME,str_len); + + str_len=sizeof(MY_FW_VERSION)-1; + if(str_len>10) + str_len=10; + memcpy(((unsigned char*)(ackpkt->fw_version)),MY_FW_VERSION,str_len); + + str_len=sizeof(MY_HW_VERSION)-1; + if(str_len>10) + str_len=10; + memcpy(((unsigned char*)(ackpkt->hw_version)),MY_HW_VERSION,str_len); + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,sizeof(BT_INFORMATION_TYPE)+4); +} + + +static void fw_sc_upgrade_rsp_dfu_version(unsigned char sn) +{ + tDFU_VERSION *ackpkt = (tDFU_VERSION *)(&sc_dfu_rsp_buf[9]); + CMD_RSP_HDR *ackhdr= (CMD_RSP_HDR *)sc_dfu_rsp_buf; + + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + ackpkt->dfu_version_l = DFU_VERSION_VALUE&0xff; + ackpkt->dfu_version_h = (DFU_VERSION_VALUE>>8) & 0xff; + ackpkt->encrytion_m = DFU_ENC_SUPPORT; + + ackhdr->rsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd =SCFWU_OPCODE_GET_DFU_VERSION; + ackhdr->ack_status = 0; + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,sizeof(tDFU_VERSION)+4); +} + +static void fw_sc_upgrade_set_security_level(unsigned char sn,unsigned char mode) +{ + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + if(mode<=DFU_ENC_AES128) + sc_dfu_security_mode=mode; + +#if(MY_DFU_TRACE_ENABLE) + + LOG_DBG("sc_dfu_security_mode = %d \r\n",sc_dfu_security_mode); + +#endif + + ackhdr->rsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd =SCFWU_OPCODE_SET_SC_METHOED; + ackhdr->ack_status =(mode<=DFU_ENC_AES128)?0:1; + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,5+4); +} + +static void fw_sc_upgrade_ack_success(unsigned char sn,unsigned char rx_cmd) +{ + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + ackhdr->rsp_cmd = TX__RSP_RX_CMD_SUCCESS; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd = rx_cmd; + ackhdr->ack_status = 0; + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,1+4); +} + +static void fw_sc_upgrade_ack_fail(unsigned char sn,unsigned char rx_cmd,unsigned char reason) +{ + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + ackhdr->rsp_cmd = TX__RSP_RX_CMD_SUCCESS; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd = rx_cmd; + ackhdr->ack_status = reason; + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,4); +} + +UINT32 CRC32(UINT32 crcval, UINT8 *buf, UINT32 length) +{ + UINT32 crc32_table = 0; + UINT32 bit = 0; + + while(length--) + { + crc32_table = ((crcval ^ *buf++)&0xff); + + for(bit = 0; bit < 8; bit++) + { + if(crc32_table&1) + { + crc32_table = (crc32_table >> 1)^(0xEDB88320); + } + else + { + crc32_table = crc32_table >> 1; + } + + } + + crcval = (crcval >> 8)^crc32_table; + } + + return crcval; +} + + + + +static void fw_sc_upgrade_write_bin_handle(unsigned char sn, unsigned char *dfu_data,unsigned char len) +{ + unsigned char ret=0; + + if(!sc_dfu_enable) + { + fw_sc_upgrade_ack_fail(sn,SCFWU_OPCODE_SEND_BIN,0x01); + return ; + } + + if(last_sn==sn) + { + fw_sc_upgrade_ack_success(sn,SCFWU_OPCODE_SEND_BIN); + return ; + } + + last_sn = sn; + + + if(sc_dfu_security_mode==DFU_ENC_NONE) + { + Dfu_CRC_Val = CRC32(Dfu_CRC_Val, dfu_data, len); + } + + + ret=fw_sc_upgrade_over_myhid_write_to_flash(dfu_data,len); + + + if(ret==0) + fw_sc_upgrade_ack_success(sn,SCFWU_OPCODE_SEND_BIN); + else + fw_sc_upgrade_ack_fail(sn,SCFWU_OPCODE_SEND_BIN,0x01); + +} + +static void fw_sc_upgrade_verify_crc(unsigned char sn,unsigned char *pdata ,unsigned char len) +{ + unsigned int Ciphertext_CRC32; + unsigned int Plaintext_CRC32; + unsigned char crc=1; + + unsigned char *ackpkt = &sc_dfu_rsp_buf[9]; + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + Ciphertext_CRC32=0; + Ciphertext_CRC32|= (pdata[0] & 0xff); + Ciphertext_CRC32|= ((pdata[1]<<8) & 0xff00); + Ciphertext_CRC32|= ((pdata[2]<<16) & 0xff0000); + Ciphertext_CRC32|= ((pdata[3]<<24) & 0xff000000); + + Plaintext_CRC32=0; + Plaintext_CRC32|= (pdata[4] & 0xff); + Plaintext_CRC32|= ((pdata[5]<<8) & 0xff00); + Plaintext_CRC32|= ((pdata[6]<<16) & 0xff0000); + Plaintext_CRC32|= ((pdata[7]<<24) & 0xff000000); + +#if(MY_DFU_TRACE_ENABLE) + + LOG_DBG("fw_sc_upgrade_verify_crc(%d),rx crc:%x,%x,cal crc:%x,%x\r\n",sc_dfu_security_mode,Ciphertext_CRC32,Plaintext_CRC32,Dfu_CRC_Val,Dfu_CRC_Val_for_XXTEA); + +#endif + + if(sc_dfu_security_mode==DFU_ENC_NONE) + { + if((Ciphertext_CRC32==Plaintext_CRC32) + && (Ciphertext_CRC32==Dfu_CRC_Val)) + { + crc=0; + } + } + + + ackhdr->rsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd = SCFWU_OPCODE_VERIFY_CRC32; + ackhdr->ack_status = 0; + + if(crc==0) + { + bool check_result = false; + #if EN_ZEPHYR_DFU + check_result = dfu_data.state != dfuERROR; + #endif + if(check_result==false) + { + crc = 2;//error + LOG_ERR("crc:%d",crc); + } + } + + ackpkt[0]= crc; + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,1+4); +} + +static unsigned char fw_sc_upgrade_image_switch(unsigned char sn) +{ + + if(sc_dfu_enable) + sys_reboot(SYS_REBOOT_WARM); + return 1; +} + +static void fw_sc_upgrade_build_info(unsigned char sn) +{ + CMD_RSP_HDR *ackhdr=(CMD_RSP_HDR *)sc_dfu_rsp_buf; + unsigned char *str_buf = &sc_dfu_rsp_buf[9]; + unsigned char offset=0; + + memset(sc_dfu_rsp_buf,0,sizeof(sc_dfu_rsp_buf)); + + ackhdr->rsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd =APP_CMD_DFU_BUILD_INFO; + ackhdr->ack_status = 0; + + memcpy(str_buf,__DATE__,sizeof(__DATE__)); + str_buf[sizeof(__DATE__)-1]=' '; + offset += sizeof(__DATE__); + memcpy(str_buf+sizeof(__DATE__),__TIME__,sizeof(__TIME__)); + offset += sizeof(__TIME__); + + fw_sc_upgrade_rsp_ack(sc_dfu_rsp_buf,offset+4); +} + + +void my_scdfu_data_handle(unsigned char *pdata,unsigned char rxlen) +{ + unsigned short hdr = 0; + unsigned char len = pdata[2]; + unsigned char len_n = (~pdata[3]); + unsigned char sn = pdata[4]; + + hdr= pdata[1]; + hdr |= pdata[0]<<8; + + if((hdr == SC_FWU_HEADER)||(hdr == SC_FWU_HEADER_ACK)) + { + if((len == len_n) && (len >2)) + { + unsigned short sum = 0; + unsigned short sum_rx=0; + unsigned char len_of_dfu = len -2; + unsigned char op_code = pdata[5]; + + for(unsigned char i=0;irsp_cmd = TX__OTA_REPORT; //rsp type + ackhdr->ack_sn = sn; + ackhdr->ack_cmd = 0xf2; + ackhdr->ack_status = 0; + + if(len>50) + len=50; + + for(unsigned char i=0;i +unsigned char *my_dfu_get_prv_data(void); +unsigned char my_dfu_get_prv_len(void); + +#if CONFIG_SHIELD_KEYCHRON_B1 +#define MY_FWU_STRING_NAME "ZMK_KB_B1" +#define MY_FW_VERSION APP_VERSION_STRING +#define MY_HW_VERSION "B1N_v1.0" +#elif CONFIG_SHIELD_KEYCHRON_B2 +#define MY_FWU_STRING_NAME "ZMK_KB_B2" +#define MY_FW_VERSION APP_VERSION_STRING +#define MY_HW_VERSION "B2N_v1.0" +#else +#define MY_FWU_STRING_NAME "ZMK_KB_B6" +#define MY_FW_VERSION APP_VERSION_STRING +#define MY_HW_VERSION "B6N_v1.0" +#endif + +#endif + diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 17cdc5d7fb8..75b303ba35d 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -21,10 +21,32 @@ #include #include +#include +#include + #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); +<<<<<<< HEAD +#include "./launcher/mousekey.h" + +extern uint8_t get_hardware_select_transport(void); +extern int zmk_ble_init(const struct device *_arg); +#if CONFIG_ZMK_NRF_24G +extern void zmk_24g_init(void); +extern int zmk_24g_send_report(uint8_t *data,uint8_t len) ; +#endif +int zmk_hog_send_mouse_report(report_mouse_t *report); +void keyboad_led_set_onoff(uint8_t led_state); +void bt_24g_switch_reset(void); +uint8_t get_mode_status(void); + +// #define DEFAULT_TRANSPORT +// COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ZMK_TRANSPORT_BLE), (ZMK_TRANSPORT_USB)) + +#define DEFAULT_TRANSPORT ZMK_TRANSPORT_USB +======= // Name of the subtree for endpoint-related settings #define SETTING_SUBTREE "endpoints" @@ -45,6 +67,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #else #define DEFAULT_TRANSPORT ZMK_TRANSPORT_NONE #endif +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 static struct zmk_endpoint_instance current_instance = {}; @@ -53,6 +76,11 @@ static enum zmk_transport preferred_transport = DEFAULT_TRANSPORT; static void update_current_endpoint(void); +void switch_to_usb(void) +{ + zmk_endpoints_select_transport(ZMK_TRANSPORT_USB); +} +#if 0 #if IS_ENABLED(CONFIG_SETTINGS) static void endpoints_save_preferred_work(struct k_work *work) { settings_save_one(SETTING_PREFERRED_TRANSPORT, &preferred_transport, @@ -69,6 +97,7 @@ static int endpoints_save_preferred(void) { return 0; #endif } +#endif bool zmk_endpoint_instance_eq(struct zmk_endpoint_instance a, struct zmk_endpoint_instance b) { if (a.transport != b.transport) { @@ -82,6 +111,11 @@ bool zmk_endpoint_instance_eq(struct zmk_endpoint_instance a, struct zmk_endpoin case ZMK_TRANSPORT_BLE: return a.ble.profile_index == b.ble.profile_index; + case ZMK_TRANSPORT_24G: + return true; + break; + default : + return false; } LOG_ERR("Invalid transport %d", a.transport); @@ -98,6 +132,8 @@ int zmk_endpoint_instance_to_str(struct zmk_endpoint_instance endpoint, char *st case ZMK_TRANSPORT_BLE: return snprintf(str, len, "BLE:%d", endpoint.ble.profile_index); + case ZMK_TRANSPORT_24G: + return snprintf(str, len, "24G"); default: return snprintf(str, len, "Invalid"); @@ -118,6 +154,10 @@ int zmk_endpoint_instance_to_index(struct zmk_endpoint_instance endpoint) { case ZMK_TRANSPORT_BLE: return INSTANCE_INDEX_OFFSET_BLE + endpoint.ble.profile_index; + case ZMK_TRANSPORT_24G: + break; + default : + break; } LOG_ERR("Invalid transport %d", endpoint.transport); @@ -127,14 +167,23 @@ int zmk_endpoint_instance_to_index(struct zmk_endpoint_instance endpoint) { int zmk_endpoint_set_preferred_transport(enum zmk_transport transport) { LOG_DBG("Selected endpoint transport %d", transport); - if (preferred_transport == transport) { + // if (preferred_transport == transport) { + // return 0; + // } + + // preferred_transport = transport; + + // endpoints_save_preferred(); + if(current_instance.transport == transport) + { + return 0; + } + if(transport == ZMK_TRANSPORT_NONE) + { + current_instance.transport = transport; return 0; } - preferred_transport = transport; - - endpoints_save_preferred(); - update_current_endpoint(); return 0; @@ -203,6 +252,20 @@ static int send_keyboard_report(void) { LOG_ERR("BLE HOG endpoint is not supported"); return -ENOTSUP; #endif /* IS_ENABLED(CONFIG_ZMK_BLE) */ +#if CONFIG_ZMK_NRF_24G + case ZMK_TRANSPORT_24G: + { + + int err=zmk_24g_send_report((uint8_t *)keyboard_report, sizeof(*keyboard_report)); + if (err) { + LOG_ERR("FAILED TO SEND OVER HOG: %d", err); + } + return err; + } + break; +#endif + default: + break; } } @@ -240,6 +303,19 @@ static int send_consumer_report(void) { LOG_ERR("BLE HOG endpoint is not supported"); return -ENOTSUP; #endif /* IS_ENABLED(CONFIG_ZMK_BLE) */ +#if CONFIG_ZMK_NRF_24G + case ZMK_TRANSPORT_24G: + { + int err=zmk_24g_send_report((uint8_t *)consumer_report, sizeof(*consumer_report)); + if (err) { + LOG_ERR("FAILED TO SEND OVER HOG: %d", err); + } + return err; + } + break; +#endif + default: + break; } } @@ -255,6 +331,9 @@ int zmk_endpoint_send_report(uint16_t usage_page) { case HID_USAGE_CONSUMER: return send_consumer_report(); + case HID_USAGE_GEN_BUTTON: + mousekey_send(); + return 0; } LOG_ERR("Unsupported usage page %d", usage_page); @@ -404,7 +483,7 @@ SETTINGS_STATIC_HANDLER_DEFINE(endpoints, SETTING_SUBTREE, NULL, endpoint_settin endpoint_settings_commit, NULL); #endif /* IS_ENABLED(CONFIG_SETTINGS) */ - +#if 0 static bool is_usb_ready(void) { #if IS_ENABLED(CONFIG_ZMK_USB) return zmk_usb_is_hid_ready(); @@ -415,7 +494,7 @@ static bool is_usb_ready(void) { static bool is_ble_ready(void) { #if IS_ENABLED(CONFIG_ZMK_BLE) - return zmk_ble_active_profile_is_connected(); + return zmk_ble_is_connected();//zmk_ble_active_profile_is_connected(); #else return false; #endif @@ -450,20 +529,58 @@ static enum zmk_transport get_selected_transport(void) { break; } +<<<<<<< HEAD + if (is_usb_ready()) { + LOG_DBG("Only USB is ready."); + return ZMK_TRANSPORT_USB; + } + + LOG_DBG("No endpoint transports are ready."); + return current_instance.transport;// DEFAULT_TRANSPORT; +======= LOG_DBG("Preferred endpoint transport is %d but no transports are ready", preferred_transport); return ZMK_TRANSPORT_NONE; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } - +#endif +uint8_t get_current_transport(void) +{ + return current_instance.transport; +} +#if 0 static struct zmk_endpoint_instance get_selected_instance(void) { return get_instance_from_transport(get_selected_transport()); } +#endif + +<<<<<<< HEAD +static int zmk_endpoints_init(const struct device *_arg) { +#if 0// IS_ENABLED(CONFIG_SETTINGS) + settings_subsys_init(); + + int err = settings_register(&endpoints_handler); + if (err) { + LOG_ERR("Failed to register the endpoints settings handler (err %d)", err); + return err; + } + + k_work_init_delayable(&endpoints_save_work, endpoints_save_preferred_work); + // settings_load_subtree("endpoints"); +======= static int zmk_endpoints_init(void) { #if IS_ENABLED(CONFIG_SETTINGS) k_work_init_delayable(&endpoints_save_work, endpoints_save_preferred_work); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #endif - current_instance = get_selected_instance(); + uint32_t reason_reset_pin = nrf_power_resetreas_get(NRF_POWER) & POWER_RESETREAS_RESETPIN_Msk; + if (reason_reset_pin) { + LOG_DBG("reason_reset_pin"); + nrf_power_resetreas_clear(NRF_POWER, POWER_RESETREAS_RESETPIN_Msk); + } + + current_instance.transport =ZMK_TRANSPORT_NONE;//ZMK_TRANSPORT_USB; return 0; } @@ -475,18 +592,57 @@ void zmk_endpoint_clear_reports(void) { zmk_hid_mouse_clear(); #endif // IS_ENABLED(CONFIG_ZMK_POINTING) +<<<<<<< HEAD + zmk_endpoints_send_report(HID_USAGE_KEY); + zmk_endpoints_send_report(HID_USAGE_CONSUMER); +======= zmk_endpoint_send_report(HID_USAGE_KEY); zmk_endpoint_send_report(HID_USAGE_CONSUMER); } +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 + keyboad_led_set_onoff(0); + void zmk_24g_endpoint_disconnect(void); + void zmk_ble_endpoint_disconnect(void); + zmk_24g_endpoint_disconnect(); + zmk_ble_endpoint_disconnect(); +} +void led_power_on(void); static void update_current_endpoint(void) { - struct zmk_endpoint_instance new_instance = get_selected_instance(); + LOG_DBG("curr:%d,new:%d",current_instance.transport,preferred_transport); + struct zmk_endpoint_instance new_instance ={.transport = preferred_transport};// get_selected_instance(); if (!zmk_endpoint_instance_eq(new_instance, current_instance)) { // Cancel all current keypresses so keys don't stay held on the old endpoint. +<<<<<<< HEAD + if(current_instance.transport !=ZMK_TRANSPORT_NONE) + disconnect_current_endpoint(); +======= zmk_endpoint_clear_reports(); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 current_instance = new_instance; + led_power_on(); + + switch(current_instance.transport) + { + case ZMK_TRANSPORT_BLE: + LOG_DBG("change to ble"); + zmk_ble_init(NULL); + break; +#if CONFIG_ZMK_NRF_24G + case ZMK_TRANSPORT_24G: + LOG_DBG("change to 24g"); + zmk_24g_init(); + break; +#endif + case ZMK_TRANSPORT_USB: + LOG_ERR("usb_dc_reset"); + usb_dc_reset(); + break; + default: + break; + } char endpoint_str[ZMK_ENDPOINT_STR_LEN]; zmk_endpoint_instance_to_str(current_instance, endpoint_str, sizeof(endpoint_str)); @@ -497,10 +653,83 @@ static void update_current_endpoint(void) { } static int endpoint_listener(const zmk_event_t *eh) { - update_current_endpoint(); + + const struct zmk_usb_conn_state_changed *ev = as_zmk_usb_conn_state_changed(eh); + if(ev) + { + LOG_DBG("usb state:%d",ev->conn_state); + if(ev->conn_state == ZMK_USB_CONN_HID) + { + if(current_instance.transport ==ZMK_TRANSPORT_USB) + { + LOG_DBG("usb status:%d",zmk_usb_get_status()); + + if(zmk_usb_get_status()==USB_DC_SUSPEND) + { + + keyboad_led_set_onoff(0); + } + } + if(get_hardware_select_transport()==0 && get_mode_status()==3) + { + preferred_transport = ZMK_TRANSPORT_USB; + update_current_endpoint(); + } + } + else if(ev->conn_state == ZMK_USB_CONN_NONE) + { + preferred_transport =get_hardware_select_transport(); + update_current_endpoint(); + } + + } + return 0; } + +int host_mouse_send(report_mouse_t *rp) { + + switch (current_instance.transport) { +#if IS_ENABLED(CONFIG_ZMK_USB) + case ZMK_TRANSPORT_USB: { + int err = zmk_usb_hid_send_report((uint8_t *)rp,sizeof(report_mouse_t)); + 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: { + int err = zmk_hog_send_mouse_report(rp); + if (err) { + LOG_ERR("FAILED TO SEND OVER HOG: %d", err); + } + return err; + } +#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */ +#if CONFIG_ZMK_NRF_24G + case ZMK_TRANSPORT_24G: + { + + int err=zmk_24g_send_report((uint8_t*)rp,sizeof(report_mouse_t)); + if (err) { + LOG_ERR("FAILED TO SEND OVER HOG: %d", err); + } + return err; + } + break; +#endif + default: + break; + } + + LOG_ERR("Unsupported endpoint transport %d", current_instance.transport); + return -ENOTSUP; +} + ZMK_LISTENER(endpoint_listener, endpoint_listener); #if IS_ENABLED(CONFIG_ZMK_USB) ZMK_SUBSCRIPTION(endpoint_listener, zmk_usb_conn_state_changed); diff --git a/app/src/hid.c b/app/src/hid.c index d8700c3f4a8..ff574f689ae 100644 --- a/app/src/hid.c +++ b/app/src/hid.c @@ -40,6 +40,9 @@ static zmk_mod_flags_t explicit_modifiers = 0; static zmk_mod_flags_t implicit_modifiers = 0; static zmk_mod_flags_t masked_modifiers = 0; +extern uint8_t macro_running; +bool get_fn_win_lock(void); + #define SET_MODIFIERS(mods) \ { \ keyboard_report.body.modifiers = (mods & ~masked_modifiers) | implicit_modifiers; \ @@ -51,6 +54,13 @@ static zmk_mod_flags_t masked_modifiers = 0; zmk_mod_flags_t zmk_hid_get_explicit_mods(void) { return explicit_modifiers; } int zmk_hid_register_mod(zmk_mod_t modifier) { + if(get_fn_win_lock() && (modifier == 7 || modifier ==3)) + { + explicit_modifier_counts[modifier]=0; + LOG_ERR("not send modifier:%d",modifier); + return 0; + } + explicit_modifier_counts[modifier]++; LOG_DBG("Modifier %d count %d", modifier, explicit_modifier_counts[modifier]); WRITE_BIT(explicit_modifiers, modifier, true); @@ -65,6 +75,12 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) { return -EINVAL; } explicit_modifier_counts[modifier]--; + + if(macro_running) + { + explicit_modifier_counts[modifier]=0; + } + LOG_DBG("Modifier %d count: %d", modifier, explicit_modifier_counts[modifier]); if (explicit_modifier_counts[modifier] == 0) { LOG_DBG("Modifier %d released", modifier); @@ -178,7 +194,7 @@ static inline bool check_keyboard_usage(zmk_key_t usage) { #define TOGGLE_KEYBOARD(match, val) \ for (int idx = 0; idx < CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE; idx++) { \ - if (keyboard_report.body.keys[idx] != match) { \ + if (keyboard_report.body.keys[idx] != match && keyboard_report.body.keys[idx] != val ) { \ continue; \ } \ keyboard_report.body.keys[idx] = val; \ diff --git a/app/src/hog.c b/app/src/hog.c index c7d9b861d4a..f6f2e28eea4 100644 --- a/app/src/hog.c +++ b/app/src/hog.c @@ -18,12 +18,16 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +<<<<<<< HEAD +#include "./launcher/mousekey.h" +======= #if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING) #include #endif // IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING) #if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) #include #endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 enum { HIDS_REMOTE_WAKE = BIT(0), @@ -72,12 +76,21 @@ static struct hids_report consumer_input = { .type = HIDS_INPUT, }; +<<<<<<< HEAD +static struct hids_report output = { + .id = ZMK_HID_REPORT_ID_KEYBOARD, + .type = HIDS_OUTPUT, +}; +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 static struct hids_report mouse_input = { .id = ZMK_HID_REPORT_ID_MOUSE, .type = HIDS_INPUT, }; +<<<<<<< HEAD +======= #if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING) @@ -90,8 +103,10 @@ static struct hids_report mouse_feature = { #endif // IS_ENABLED(CONFIG_ZMK_POINTING) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 static bool host_requests_notification = false; static uint8_t ctrl_point; +static uint8_t hids_outp_rep[20]; // static uint8_t proto_mode; static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, @@ -102,6 +117,8 @@ static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *a static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { + uint8_t *p_data = attr->user_data; + LOG_DBG("report ref,id:%d,type:%d",p_data[0],p_data[1]); return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_report)); } @@ -154,6 +171,15 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn, return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body, sizeof(struct zmk_hid_consumer_report_body)); } +<<<<<<< HEAD +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) { + report_mouse_t report =mousekey_get_report(); + return bt_gatt_attr_read(conn, attr, buf, len, offset, &report.buttons, + sizeof(report_mouse_t)-1); +} +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) @@ -222,6 +248,7 @@ static ssize_t write_hids_mouse_feature_report(struct bt_conn *conn, #endif // IS_ENABLED(CONFIG_ZMK_POINTING) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 // 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, @@ -235,6 +262,27 @@ static void input_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value) { host_requests_notification = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0; } +void keyboad_led_set_onoff(uint8_t led_state); + +static ssize_t hids_outp_rep_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { + uint8_t *value = attr->user_data; + LOG_DBG("hids_outp_rep_write"); + if (offset + len > sizeof(hids_outp_rep)) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + memcpy(value + offset, buf, len); + LOG_HEXDUMP_INF(buf, len, "ble report"); + const uint8_t *report =buf; + // if(report[0]==ZMK_HID_REPORT_ID_KEYBOARD) + { + keyboad_led_set_onoff(report[0]); + } + + return len; + +} static ssize_t write_ctrl_point(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { uint8_t *value = attr->user_data; @@ -244,7 +292,7 @@ static ssize_t write_ctrl_point(struct bt_conn *conn, const struct bt_gatt_attr } memcpy(value + offset, buf, len); - + LOG_HEXDUMP_INF(buf, len, "write_ctrl_point"); return len; } @@ -269,13 +317,25 @@ 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, &consumer_input), +<<<<<<< HEAD + //mouse reprot +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 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), +<<<<<<< HEAD + //led out + BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,BT_GATT_CHRC_READ|BT_GATT_CHRC_WRITE |BT_GATT_CHRC_WRITE_WITHOUT_RESP, + BT_GATT_PERM_WRITE, NULL, hids_outp_rep_write,hids_outp_rep), + BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref, + NULL, &output), + +======= #if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING) BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, @@ -297,9 +357,33 @@ BT_GATT_SERVICE_DEFINE( NULL, &led_indicators), #endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP, - BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point)); + BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point), + + + + + ); + +<<<<<<< HEAD +struct bt_conn *destination_connection() { + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + // LOG_DBG("Address pointer %p", addr); + if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { + LOG_WRN("Not sending, no active address for current profile"); + return NULL; + } else if ((conn = bt_conn_lookup_addr_le(zmk_ble_get_active_profile_bt_id(), addr)) == NULL) { + LOG_WRN("Not sending, not connected to active profile"); + return NULL; + } + return conn; +} + +======= +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 K_THREAD_STACK_DEFINE(hog_q_stack, CONFIG_ZMK_BLE_THREAD_STACK_SIZE); struct k_work_q hog_work_q; @@ -321,7 +405,7 @@ void send_keyboard_report_callback(struct k_work *work) { .data = &report, .len = sizeof(report), }; - + // LOG_HEXDUMP_INF(notify_params.data, notify_params.len, "report:"); int err = bt_gatt_notify_cb(conn, ¬ify_params); if (err == -EPERM) { bt_conn_set_security(conn, BT_SECURITY_L2); @@ -330,6 +414,10 @@ void send_keyboard_report_callback(struct k_work *work) { } bt_conn_unref(conn); + // if (k_msgq_num_used_get(&zmk_hog_keyboard_msgq) == 0) { + // LOG_DBG("---->msgq empty,break:%d", 0); + // return; + // } } } @@ -351,8 +439,9 @@ int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) { } } - k_work_submit_to_queue(&hog_work_q, &hog_keyboard_work); + err = k_work_submit_to_queue(&hog_work_q, &hog_keyboard_work); + LOG_DBG("k_work_submit_to_queue:%d", err); return 0; }; @@ -408,6 +497,15 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) { return 0; }; +<<<<<<< HEAD +K_MSGQ_DEFINE(zmk_hog_mouse_msgq, sizeof(report_mouse_t),10, 4); + +void send_mouse_report_callback(struct k_work *work) { + report_mouse_t report; + + while (k_msgq_get(&zmk_hog_mouse_msgq, &report, K_NO_WAIT) == 0) { + struct bt_conn *conn = destination_connection(); +======= #if IS_ENABLED(CONFIG_ZMK_POINTING) K_MSGQ_DEFINE(zmk_hog_mouse_msgq, sizeof(struct zmk_hid_mouse_report_body), @@ -417,12 +515,21 @@ 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 = zmk_ble_active_profile_conn(); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 if (conn == NULL) { return; } struct bt_gatt_notify_params notify_params = { .attr = &hog_svc.attrs[13], +<<<<<<< HEAD + .data = &report.buttons, + .len = sizeof(report)-1, + }; + + int err = bt_gatt_notify_cb(conn, ¬ify_params); + if (err) { +======= .data = &report, .len = sizeof(report), }; @@ -431,6 +538,7 @@ void send_mouse_report_callback(struct k_work *work) { if (err == -EPERM) { bt_conn_set_security(conn, BT_SECURITY_L2); } else if (err) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 LOG_DBG("Error notifying %d", err); } @@ -440,13 +548,21 @@ void send_mouse_report_callback(struct k_work *work) { K_WORK_DEFINE(hog_mouse_work, send_mouse_report_callback); +<<<<<<< HEAD +int zmk_hog_send_mouse_report(report_mouse_t *report) { +======= int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 int err = k_msgq_put(&zmk_hog_mouse_msgq, report, K_MSEC(100)); if (err) { switch (err) { case -EAGAIN: { LOG_WRN("Consumer message queue full, popping first message and queueing again"); +<<<<<<< HEAD + report_mouse_t discarded_report; +======= struct zmk_hid_mouse_report_body discarded_report; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 k_msgq_get(&zmk_hog_mouse_msgq, &discarded_report, K_NO_WAIT); return zmk_hog_send_mouse_report(report); } @@ -460,9 +576,15 @@ int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) { return 0; }; +<<<<<<< HEAD + + +int zmk_hog_init(const struct device *_arg) { +======= #endif // IS_ENABLED(CONFIG_ZMK_POINTING) static int zmk_hog_init(void) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 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), CONFIG_ZMK_BLE_THREAD_PRIORITY, &queue_config); diff --git a/app/src/keymap.c b/app/src/keymap.c index 547d6612f50..b1a44cc0470 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -22,6 +22,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include +#include static zmk_keymap_layers_state_t _zmk_keymap_layer_locks = 0; static zmk_keymap_layers_state_t _zmk_keymap_layer_state = 0; @@ -712,8 +714,12 @@ int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_ #endif }; +<<<<<<< HEAD + LOG_DBG("layer: %d position: %d, binding name: %s,p1:%x,p2:%x", layer, position, binding.behavior_dev,binding.param1,binding.param2); +======= LOG_DBG("layer_id: %d position: %d, binding name: %s", layer_id, position, binding->behavior_dev); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 return zmk_behavior_invoke_binding(binding, event, pressed); } @@ -839,6 +845,141 @@ ZMK_SUBSCRIPTION(keymap, zmk_position_state_changed); ZMK_SUBSCRIPTION(keymap, zmk_sensor_event); #endif /* ZMK_KEYMAP_HAS_SENSORS */ +<<<<<<< HEAD + +void led_recover(void); + +static uint8_t fn_exchange_flag_mac; +static uint8_t fn_exchange_flag_win; +static uint8_t fn_exchange; + +#define WIN_LAYER 2 +#define MAC_LAYER 0 + +static inline uint8_t get_fn_exchange_state(void) +{ + return fn_exchange; +} +static void save_fn_exchange_state(uint8_t state) +{ + fn_exchange =state; + + settings_save_one("fn_exchange", &fn_exchange, sizeof(fn_exchange)); +} +int load_immediate_value(const char *name, void *dest, size_t len); +void fn_exchange_setting_init(void) +{ + + LOG_INF("settings init"); + settings_subsys_init(); + + // int err = settings_register(&profiles_handler); + // if (err) { + // LOG_ERR("Failed to setup the profile settings handler (err %d)", err); + // return ; + // } + // settings_load_subtree("ble/profiles"); + int rc; + rc = load_immediate_value("fn_exchange", &fn_exchange, sizeof(fn_exchange)); + if (rc == -ENOENT) { + fn_exchange = 0; + LOG_DBG("fn_exchange:%d,default",fn_exchange); + } + else if(rc ==0) + { + LOG_DBG("fn_exchange:%d",fn_exchange); + } + +} +bool keyboard_os_is_mac(void) +{ + return ((_zmk_keymap_layer_state & BIT(MAC_LAYER)) || (_zmk_keymap_layer_state &BIT(MAC_LAYER+1)) || _zmk_keymap_layer_state==MAC_LAYER); +} +void f1_f13_fn_exchange_mac(void) +{ +#if CONFIG_SHIELD_KEYCHRON_B1 + struct zmk_behavior_binding backup_bindings[12]; +#else + struct zmk_behavior_binding backup_bindings[13]; +#endif + LOG_DBG("cur lay_state:%x",_zmk_keymap_layer_state); + + { + LOG_DBG("layer:mac"); + memcpy(backup_bindings,&zmk_keymap[MAC_LAYER][1],sizeof(backup_bindings)); + memcpy(&zmk_keymap[MAC_LAYER][1],&zmk_keymap[MAC_LAYER+1][1],sizeof(backup_bindings)); + memcpy(&zmk_keymap[MAC_LAYER+1][1],backup_bindings,sizeof(backup_bindings)); + } + +} +void f1_f13_fn_exchange_win(void) +{ +#if CONFIG_SHIELD_KEYCHRON_B1 + struct zmk_behavior_binding backup_bindings[12]; +#else + struct zmk_behavior_binding backup_bindings[13]; +#endif + LOG_DBG("cur lay_state:%x",_zmk_keymap_layer_state); + + { + LOG_DBG("layer:win"); + memcpy(backup_bindings,&zmk_keymap[WIN_LAYER][1],sizeof(backup_bindings)); + memcpy(&zmk_keymap[WIN_LAYER][1],&zmk_keymap[WIN_LAYER+1][1],sizeof(backup_bindings)); + memcpy(&zmk_keymap[WIN_LAYER+1][1],backup_bindings,sizeof(backup_bindings)); + } +} +void f1_f13_fn_exchange_start_check(void) +{ + fn_exchange_setting_init(); + uint8_t fn_exchange_flag=get_fn_exchange_state(); + + fn_exchange_flag_mac=(fn_exchange_flag &0x02) ?0xff:0; + fn_exchange_flag_win=(fn_exchange_flag &0x01) ?0xff:0; + + LOG_DBG("mac:%d,win:%d",fn_exchange_flag_mac,fn_exchange_flag_win); + if(fn_exchange_flag_mac ) f1_f13_fn_exchange_mac(); + if(fn_exchange_flag_win ) f1_f13_fn_exchange_win(); +} + +uint8_t keyboard_get_led_state(void); +void keyboad_led_set_onoff(uint8_t led_state); +static struct k_work_delayable reset_led_work; +static void reset_led_work_cb(struct k_work *work) +{ + keyboad_led_set_onoff(keyboard_get_led_state()); +} + +void do_f1_f13_fn_exchange(void) +{ + + if(keyboard_os_is_mac()) + { + f1_f13_fn_exchange_mac(); + fn_exchange_flag_mac = ~fn_exchange_flag_mac; + } + else + { + f1_f13_fn_exchange_win(); + fn_exchange_flag_win = ~fn_exchange_flag_win; + } + led_recover(); + LOG_DBG("mac:%d,win:%d",fn_exchange_flag_mac,fn_exchange_flag_win); + save_fn_exchange_state((fn_exchange_flag_win?0x01:0) | (fn_exchange_flag_mac?0x02:0)); + k_work_init_delayable(&reset_led_work, reset_led_work_cb); + k_work_reschedule(&reset_led_work, K_MSEC(2800)); +} + +void update_zmk_keymap(uint8_t layer,uint8_t pos,struct zmk_behavior_binding* binding) +{ + zmk_keymap[layer][pos].behavior_dev =binding->behavior_dev; + zmk_keymap[layer][pos].param1 =binding->param1; + zmk_keymap[layer][pos].param2 =binding->param2; +} +struct zmk_behavior_binding * get_zmk_keymap(uint8_t layer ,uint8_t pos) +{ + return &zmk_keymap[layer][pos]; +} +======= #if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) static int keymap_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) { @@ -981,3 +1122,4 @@ int keymap_init(void) { } SYS_INIT(keymap_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 diff --git a/app/src/kscan.c b/app/src/kscan.c new file mode 100644 index 00000000000..7a11e4b9d3e --- /dev/null +++ b/app/src/kscan.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include + +#define ZMK_KSCAN_EVENT_STATE_PRESSED 0 +#define ZMK_KSCAN_EVENT_STATE_RELEASED 1 +bool dip_switch_update_user(uint8_t index, bool active); +struct zmk_kscan_event { + uint32_t row; + uint32_t column; + uint32_t state; +}; + +struct zmk_kscan_msg_processor { + struct k_work work; +} msg_processor; + +K_MSGQ_DEFINE(zmk_kscan_msgq, sizeof(struct zmk_kscan_event), CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE, 4); + +static void zmk_kscan_callback(const struct device *dev, uint32_t row, uint32_t column, + bool pressed) { + struct zmk_kscan_event ev = { + .row = row, + .column = column, + .state = (pressed ? ZMK_KSCAN_EVENT_STATE_PRESSED : ZMK_KSCAN_EVENT_STATE_RELEASED)}; + //report mac/win dip status. + if(row==8&&column==0) + { + dip_switch_update_user(0,pressed?1:0); + } + k_msgq_put(&zmk_kscan_msgq, &ev, K_NO_WAIT); + k_work_submit(&msg_processor.work); +} + +void zmk_kscan_process_msgq(struct k_work *item) { + struct zmk_kscan_event ev; + + while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) { + bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED); + int32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column); + + if (position < 0) { + LOG_WRN("Not found in transform: row: %d, col: %d, pressed: %s", ev.row, ev.column, + (pressed ? "true" : "false")); + continue; + } + + LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s", ev.row, ev.column, position, + (pressed ? "true" : "false")); + ZMK_EVENT_RAISE(new_zmk_position_state_changed( + (struct zmk_position_state_changed){.source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, + .state = pressed, + .position = position, + .timestamp = k_uptime_get()})); + } +} + +int zmk_kscan_init(const struct device *dev) { + if (dev == NULL) { + LOG_ERR("Failed to get the KSCAN device"); + return -EINVAL; + } + + k_work_init(&msg_processor.work, zmk_kscan_process_msgq); + + kscan_config(dev, zmk_kscan_callback); + kscan_enable_callback(dev); + + return 0; +} diff --git a/app/src/launcher/CMakeLists.txt b/app/src/launcher/CMakeLists.txt new file mode 100644 index 00000000000..e35dd393ec5 --- /dev/null +++ b/app/src/launcher/CMakeLists.txt @@ -0,0 +1,6 @@ + +target_sources_ifdef(CONFIG_ZMK_LAUNCHER app PRIVATE launcher.c) +target_sources_ifdef(CONFIG_ZMK_LAUNCHER app PRIVATE dynamic_keymap.c) +target_sources_ifdef(CONFIG_ZMK_LAUNCHER app PRIVATE map_keycode.c) +target_sources_ifdef(CONFIG_ZMK_LAUNCHER app PRIVATE send_string.c) +target_sources_ifdef(CONFIG_ZMK_LAUNCHER app PRIVATE mousekey.c) \ No newline at end of file diff --git a/app/src/launcher/dynamic_keymap.c b/app/src/launcher/dynamic_keymap.c new file mode 100644 index 00000000000..a12ed05163c --- /dev/null +++ b/app/src/launcher/dynamic_keymap.c @@ -0,0 +1,509 @@ +/* Copyright 2017 Jason Williams (Wilba) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "dynamic_keymap.h" +#include "keycodes.h" +#include "send_string.h" +#include "launcher.h" +#include +#include + +LOG_MODULE_DECLARE(zmk, 4);//CONFIG_ZMK_LOG_LEVEL); +uint8_t behavior_queue_is_full(void); +void send_string_end(void); +void macro_timer_expiry(struct k_timer *timer); +void macro_exec(void); + +K_TIMER_DEFINE(macro_timer, macro_timer_expiry, NULL); +static uint16_t p_macro; +enum { + SAVE_VIA_LAYOUT =0x01, + SAVE_VIA_ENCODER =0x02, + SAVE_VIA_CUSTOM =0x04, + SAVE_VIA_MACROS =0x08, + SAVE_VIA_KEYMAPS =0x10, + SAVE_VIA_CHANGED =0x20, + SAVE_VIA_KEYMAPS_RESET =0x40, + SAVE_VIA_MACROS_RESET =0x80, + SAVE_VIA_DEBOUNCE =0x20, + SAVE_VIA_MAX =8 +}; + +struct _save_info { + uint16_t save_type; + uint16_t save_index; +}; + +static struct _save_info save_info; +void storage_via_worker(struct k_work *work) +{ + LOG_DBG("save,type:%x,index:%d",save_info.save_type,save_info.save_index); + uint8_t bits=0x80; + for(int i=0;i>=1; + } +} +K_WORK_DELAYABLE_DEFINE(storage_via_work, storage_via_worker); + +extern uint16_t gen_via_keymaps[DYNAMIC_KEYMAP_LAYER_COUNT][MATRIX_ROWS][MATRIX_COLS]; +uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column) { + if (layer_num < NUM_KEYMAP_LAYERS_RAW && row < MATRIX_ROWS && column < MATRIX_COLS) { + // return (layer_num <<8) | (row*MATRIX_COLS+column);//via_ee_device.keymaps[layer_num][row][column]; + return gen_via_keymaps[layer_num][row][column]; + } + return KC_TRNS; +} +uint8_t dynamic_keymap_get_layer_count(void) { + return DYNAMIC_KEYMAP_LAYER_COUNT; +} + +inline uint16_t dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column) { + // TODO: optimize this with some left shifts + return (DYNAMIC_KEYMAP_EEPROM_ADDR) + (layer * MATRIX_ROWS * MATRIX_COLS * 2) + (row * MATRIX_COLS * 2) + (column * 2); +} + +uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column) { + if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return KC_NO; + uint16_t address = dynamic_keymap_key_to_eeprom_address(layer, row, column); + // Big endian, so we can read/write EEPROM directly from host if we want + uint16_t keycode = eeprom_read_byte(address) << 8; + keycode |= eeprom_read_byte(address + 1); + return keycode; +} +void dynamic_keymap_set_keycode_no_update(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) { + if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return; + uint16_t address = dynamic_keymap_key_to_eeprom_address(layer, row, column); + // Big endian, so we can read/write EEPROM directly from host if we want + eeprom_update_byte(address, (uint8_t)(keycode >> 8)); + eeprom_update_byte(address + 1, (uint8_t)(keycode & 0xFF)); +} +void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) { + if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return; + uint16_t address = dynamic_keymap_key_to_eeprom_address(layer, row, column); + // Big endian, so we can read/write EEPROM directly from host if we want + eeprom_update_byte(address, (uint8_t)(keycode >> 8)); + eeprom_update_byte(address + 1, (uint8_t)(keycode & 0xFF)); + + // via_set_changed_key(layer,row,column); + set_zmk_keymap(layer,row,column,keycode); + + save_info.save_type |= SAVE_VIA_KEYMAPS ; + save_info.save_index |= 1<= DYNAMIC_KEYMAP_LAYER_COUNT || encoder_id >= NUM_ENCODERS) return KC_NO; + uint16_t address = dynamic_keymap_encoder_to_eeprom_address(layer, encoder_id); + // Big endian, so we can read/write EEPROM directly from host if we want + uint16_t keycode = ((uint16_t)eeprom_read_byte(address + (clockwise ? 0 : 2))) << 8; + keycode |= eeprom_read_byte(address + (clockwise ? 0 : 2) + 1); + return keycode; +} + +void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode) { + if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || encoder_id >= NUM_ENCODERS) return; + uint16_t address = dynamic_keymap_encoder_to_eeprom_address(layer, encoder_id); + // Big endian, so we can read/write EEPROM directly from host if we want + eeprom_update_byte(address + (clockwise ? 0 : 2), (uint8_t)(keycode >> 8)); + eeprom_update_byte(address + (clockwise ? 0 : 2) + 1, (uint8_t)(keycode & 0xFF)); + + save_info.save_type |= SAVE_VIA_ENCODER; + + k_work_reschedule(&storage_via_work, K_MSEC(1500)); +} +#endif // ENCODER_MAP_ENABLE + +void dynamic_keymap_reset(bool save) { + // Reset the keymaps in EEPROM to what is in flash. + for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) { + #if 1 + for (int row = 0; row < MATRIX_ROWS; row++) { + for (int column = 0; column < MATRIX_COLS; column++) { + dynamic_keymap_set_keycode_no_update(layer, row, column, keycode_at_keymap_location_raw(layer, row, column)); + set_zmk_keymap(layer, row, column, keycode_at_keymap_location_raw(layer, row, column)); + } + } + #endif + // memcpy(&via_ee_device.keymaps[layer*KEYMAP_LEN],&gen_via_keymaps[layer],KEYMAP_LEN); +#ifdef ENCODER_MAP_ENABLE + for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) { + dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true)); + dynamic_keymap_set_encoder(layer, encoder, false, keycode_at_encodermap_location_raw(layer, encoder, false)); + } +#endif // ENCODER_MAP_ENABLE + } + LOG_DBG("MATRIX_ROWS:%d,MATRIX_COLS:%d",MATRIX_ROWS,MATRIX_COLS); + LOG_HEXDUMP_DBG(&via_ee_device.keymaps[0],32,"keymap"); + + if(save) + { + save_info.save_type = SAVE_VIA_KEYMAPS_RESET; + save_info.save_index =0xff; + k_work_reschedule(&storage_via_work,K_MSEC(100)); + } +} + +void dynamic_keymap_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) { + uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2; + uint16_t source = (DYNAMIC_KEYMAP_EEPROM_ADDR + offset); + uint8_t *target = data; + for (uint16_t i = 0; i < size; i++) { + if (offset + i < dynamic_keymap_eeprom_size) { + *target = eeprom_read_byte(source); + } else { + *target = 0x00; + } + source++; + target++; + } +} + +void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) { + uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2; + uint16_t target = (DYNAMIC_KEYMAP_EEPROM_ADDR + offset); + uint8_t *source = data; + for (uint16_t i = 0; i < size; i++) { + if (offset + i < dynamic_keymap_eeprom_size) { + eeprom_update_byte(target, *source); + } + source++; + target++; + } + //TODO: + LOG_DBG("."); +} + +uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) { + if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && row < MATRIX_ROWS && column < MATRIX_COLS) { + return dynamic_keymap_get_keycode(layer_num, row, column); + } + return KC_NO; +} + +#ifdef ENCODER_MAP_ENABLE +uint16_t keycode_at_encodermap_location(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) { + if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && encoder_idx < NUM_ENCODERS) { + return dynamic_keymap_get_encoder(layer_num, encoder_idx, clockwise); + } + return KC_NO; +} +#endif // ENCODER_MAP_ENABLE + +uint8_t dynamic_keymap_macro_get_count(void) { + return DYNAMIC_KEYMAP_MACRO_COUNT; +} + +uint16_t dynamic_keymap_macro_get_buffer_size(void) { + return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE; +} + +void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) { + uint16_t source = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + offset); + uint8_t *target = data; + for (uint16_t i = 0; i < size; i++) { + if (offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) { + *target = eeprom_read_byte(source); + } else { + *target = 0x00; + } + source++; + target++; + } +} + +void dynamic_keymap_macro_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) { + uint16_t target = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + offset); + uint8_t *source = data; + for (uint16_t i = 0; i < size; i++) { + if (offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) { + eeprom_update_byte(target, *source); + } + source++; + target++; + } + + save_info.save_type |= SAVE_VIA_MACROS; + + k_work_reschedule(&storage_via_work, K_MSEC(1500)); +} + +void dynamic_keymap_macro_reset(bool save) { + uint16_t p = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR); + uint16_t end = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE); + // int i=0; + while (p != end) { + eeprom_update_byte(p, 0); + ++p; + } + if(save) + { + save_info.save_type = SAVE_VIA_MACROS_RESET; + k_work_reschedule(&storage_via_work,K_MSEC(100)); + } +} +void via_save_debounce(void) +{ + save_info.save_type |= SAVE_VIA_DEBOUNCE; + k_work_reschedule(&storage_via_work,K_MSEC(1000)); +} +uint32_t convert_time(uint8_t *ch); +void send_string_delay(uint32_t delay_time); +void dynamic_keymap_macro_send(uint8_t id) { + if (id >= DYNAMIC_KEYMAP_MACRO_COUNT || (p_macro !=0)) { + return; + } + + // Check the last byte of the buffer. + // If it's not zero, then we are in the middle + // of buffer writing, possibly an aborted buffer + // write. So do nothing. + uint16_t p = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE - 1); + if (eeprom_read_byte(p) != 0) { + return; + } + + // Skip N null characters + // p will then point to the Nth macro + p = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR); + uint16_t end = (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE); + while (id > 0) { + // If we are past the end of the buffer, then there is + // no Nth macro in the buffer. + if (p == end) { + return; + } + if (eeprom_read_byte(p) == 0) { + --id; + } + ++p; + } + p_macro =p; + macro_exec(); + +} +#include +uint32_t convert_time(uint8_t *ch) +{ + uint32_t ms=0; + while(isdigit(*ch)) + { + ms *= 10; + ms += *ch - '0'; + ch++; + } + return ms; +} +void send_string_delay(uint32_t delay_time) +{ + uint8_t data[8]={SS_QMK_PREFIX,SS_DELAY_CODE}; + if(delay_time>9999) delay_time =9999; + sprintf(&data[2],"%d",delay_time); + send_string_with_delay(data, DYNAMIC_KEYMAP_MACRO_DELAY); +} + +void macro_exec(void) +{ + static uint16_t total=0; + uint8_t err=0; + uint32_t delay_time =0; + // Send the macro string by making a temporary string. + char data[8] = {0}; + // We already checked there was a null at the end of + // the buffer, so this cannot go past the end + uint8_t count=0; + if(behavior_queue_is_full()) + { + LOG_WRN("behavior_queue_is_full!"); + k_timer_start(¯o_timer,K_MSEC(10),K_FOREVER); + return; + } + while (1) { + data[0] = eeprom_read_byte(p_macro++); + data[1] = 0; + // Stop at the null terminator of this macro string + if (data[0] == 0) { + err=2; + break; + } + if (data[0] == SS_QMK_PREFIX) { + // Get the code + data[1] = eeprom_read_byte(p_macro++); + // Unexpected null, abort. + if (data[1] == 0) { + err=1; + break; + } + if (data[1] == SS_TAP_CODE || data[1] == SS_DOWN_CODE || data[1] == SS_UP_CODE) { + // Get the keycode + data[2] = eeprom_read_byte(p_macro++); + // Unexpected null, abort. + if (data[2] == 0) { + err=1; + break; + } + // Null terminate + data[3] = 0; + } else if (data[1] == SS_DELAY_CODE) { + // Get the number and '|' + // At most this is 4 digits plus '|' + uint8_t i = 2; + while (1) { + data[i] = eeprom_read_byte(p_macro++); + // Unexpected null, abort + if (data[i] == 0) { + err=1; + break; + } + // Found '|', send it + if (data[i] == '|') { + data[i + 1] = 0; + break; + } + // If haven't found '|' by i==6 then + // number too big, abort + if (i == 6) { + err=1; + break; + } + ++i; + } + delay_time += convert_time(&data[2]); + } + } + // LOG_HEXDUMP_DBG(data,sizeof(data),"macro"); + LOG_DBG("macro:%d,data:%02x",total,data[0]); + if(data[1]!=SS_DELAY_CODE) + { + if(delay_time) + { + send_string_delay(delay_time); + LOG_DBG("send_string_delay:%d",delay_time); + } + send_string_with_delay(data, DYNAMIC_KEYMAP_MACRO_DELAY); + delay_time =0; + } + total ++; + if(++count>=10) + { + break; + } + + } + if(err==0) + { + LOG_DBG("macro continue"); + k_timer_start(¯o_timer,K_MSEC(10),K_FOREVER); + } + else if(err==2) + { + LOG_DBG("macro done,t:%d",total); + send_string_end(); + total=0; + p_macro =0; + } + else if(err ==1) + { + LOG_ERR("macro ERR"); + p_macro =0; + } +} +void macro_timer_expiry(struct k_timer *timer) +{ + macro_exec(); +} diff --git a/app/src/launcher/dynamic_keymap.h b/app/src/launcher/dynamic_keymap.h new file mode 100644 index 00000000000..ec476bc4621 --- /dev/null +++ b/app/src/launcher/dynamic_keymap.h @@ -0,0 +1,73 @@ +/* Copyright 2017 Jason Williams (Wilba) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +uint8_t dynamic_keymap_get_layer_count(void); +uint16_t dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column); +uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column); +void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode); +#ifdef ENCODER_MAP_ENABLE +uint16_t dynamic_keymap_get_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise); +void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode); +#endif // ENCODER_MAP_ENABLE +void dynamic_keymap_reset(bool save); +// These get/set the keycodes as stored in the EEPROM buffer +// Data is big-endian 16-bit values (the keycodes) +// Order is by layer/row/column +// Thus offset 0 = 0,0,0, offset MATRIX_COLS*2 = 0,1,0, offset MATRIX_ROWS*MATRIX_COLS*2 = 1,0,0 +// Note the *2, because offset is in bytes and keycodes are two bytes +// This is only really useful for host applications that want to get a whole keymap fast, +// by reading 14 keycodes (28 bytes) at a time, reducing the number of raw HID transfers by +// a factor of 14. +void dynamic_keymap_get_buffer(uint16_t offset, uint16_t size, uint8_t *data); +void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data); + +// This overrides the one in quantum/keymap_common.c +// uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key); + +// Note regarding dynamic_keymap_macro_set_buffer(): +// The last byte of the buffer is used as a valid flag, +// so macro sending is disabled during writing a new buffer, +// should it happen during, or after an interrupted transfer. +// +// Users writing to the buffer must first set the last byte of the buffer +// to non-zero (i.e. 0xFF). After (or during) the final write, set the +// last byte of the buffer to zero. +// +// Since the contents of the buffer must be a list of null terminated +// strings, the last byte must be a null when at maximum capacity, +// and it not being null means the buffer can be considered in an +// invalid state. +// +// The buffer *may* contain less macro strings than the maximum. +// This allows a higher maximum number of macros without requiring that +// number of nulls to be in the buffer. +// Note: dynamic_keymap_macro_get_count() returns the maximum that *can* be +// stored, not the current count of macros in the buffer. + +uint8_t dynamic_keymap_macro_get_count(void); +uint16_t dynamic_keymap_macro_get_buffer_size(void); +void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data); +void dynamic_keymap_macro_set_buffer(uint16_t offset, uint16_t size, uint8_t *data); +void dynamic_keymap_macro_reset(bool save); + +void dynamic_keymap_macro_send(uint8_t id); +void dynamic_keymap_set_keycode_no_update(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode); +void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode); +uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column); \ No newline at end of file diff --git a/app/src/launcher/dynamic_macro.h b/app/src/launcher/dynamic_macro.h new file mode 100644 index 00000000000..64c532e6ce5 --- /dev/null +++ b/app/src/launcher/dynamic_macro.h @@ -0,0 +1,264 @@ +/* Copyright 2016 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ +#pragma once + +/* Warn users that this is now deprecated and they should use the core feature instead. */ +#pragma message "Dynamic Macros is now a core feature. See updated documentation to see how to configure it: https://docs.qmk.fm/#/feature_dynamic_macros" + +#include "action_layer.h" + +#ifndef DYNAMIC_MACRO_SIZE +/* May be overridden with a custom value. Be aware that the effective + * macro length is half of this value: each keypress is recorded twice + * because of the down-event and up-event. This is not a bug, it's the + * intended behavior. + * + * Usually it should be fine to set the macro size to at least 256 but + * there have been reports of it being too much in some users' cases, + * so 128 is considered a safe default. + */ +# define DYNAMIC_MACRO_SIZE 128 +#endif + +/* Blink the LEDs to notify the user about some event. */ +void dynamic_macro_led_blink(void) { +#ifdef BACKLIGHT_ENABLE + backlight_toggle(); + wait_ms(100); + backlight_toggle(); +#endif +} + +/* Convenience macros used for retrieving the debug info. All of them + * need a `direction` variable accessible at the call site. + */ +#define DYNAMIC_MACRO_CURRENT_SLOT() (direction > 0 ? 1 : 2) +#define DYNAMIC_MACRO_CURRENT_LENGTH(BEGIN, POINTER) ((int)(direction * ((POINTER) - (BEGIN)))) +#define DYNAMIC_MACRO_CURRENT_CAPACITY(BEGIN, END2) ((int)(direction * ((END2) - (BEGIN)) + 1)) + +/** + * Start recording of the dynamic macro. + * + * @param[out] macro_pointer The new macro buffer iterator. + * @param[in] macro_buffer The macro buffer used to initialize macro_pointer. + */ +void dynamic_macro_record_start(keyrecord_t **macro_pointer, keyrecord_t *macro_buffer) { + dprintln("dynamic macro recording: started"); + + dynamic_macro_led_blink(); + + clear_keyboard(); + layer_clear(); + *macro_pointer = macro_buffer; +} + +/** + * Play the dynamic macro. + * + * @param macro_buffer[in] The beginning of the macro buffer being played. + * @param macro_end[in] The element after the last macro buffer element. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + */ +void dynamic_macro_play(keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction) { + dprintf("dynamic macro: slot %d playback\n", DYNAMIC_MACRO_CURRENT_SLOT()); + + uint32_t saved_layer_state = layer_state; + + clear_keyboard(); + layer_clear(); + + while (macro_buffer != macro_end) { + process_record(macro_buffer); + macro_buffer += direction; + } + + clear_keyboard(); + + layer_state = saved_layer_state; +} + +/** + * Record a single key in a dynamic macro. + * + * @param macro_buffer[in] The start of the used macro buffer. + * @param macro_pointer[in,out] The current buffer position. + * @param macro2_end[in] The end of the other macro. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + * @param record[in] The current keypress. + */ +void dynamic_macro_record_key(keyrecord_t *macro_buffer, keyrecord_t **macro_pointer, keyrecord_t *macro2_end, int8_t direction, keyrecord_t *record) { + /* If we've just started recording, ignore all the key releases. */ + if (!record->event.pressed && *macro_pointer == macro_buffer) { + dprintln("dynamic macro: ignoring a leading key-up event"); + return; + } + + /* The other end of the other macro is the last buffer element it + * is safe to use before overwriting the other macro. + */ + if (*macro_pointer - direction != macro2_end) { + **macro_pointer = *record; + *macro_pointer += direction; + } else { + dynamic_macro_led_blink(); + } + + dprintf("dynamic macro: slot %d length: %d/%d\n", DYNAMIC_MACRO_CURRENT_SLOT(), DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, *macro_pointer), DYNAMIC_MACRO_CURRENT_CAPACITY(macro_buffer, macro2_end)); +} + +/** + * End recording of the dynamic macro. Essentially just update the + * pointer to the end of the macro. + */ +void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_pointer, int8_t direction, keyrecord_t **macro_end) { + dynamic_macro_led_blink(); + + /* Do not save the keys being held when stopping the recording, + * i.e. the keys used to access the layer DM_RSTP is on. + */ + while (macro_pointer != macro_buffer && (macro_pointer - direction)->event.pressed) { + dprintln("dynamic macro: trimming a trailing key-down event"); + macro_pointer -= direction; + } + + dprintf("dynamic macro: slot %d saved, length: %d\n", DYNAMIC_MACRO_CURRENT_SLOT(), DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, macro_pointer)); + + *macro_end = macro_pointer; +} + +/* Handle the key events related to the dynamic macros. Should be + * called from process_record_user() like this: + * + * bool process_record_user(uint16_t keycode, keyrecord_t *record) { + * if (!process_record_dynamic_macro(keycode, record)) { + * return false; + * } + * <...THE REST OF THE FUNCTION...> + * } + */ +bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record) { + /* Both macros use the same buffer but read/write on different + * ends of it. + * + * Macro1 is written left-to-right starting from the beginning of + * the buffer. + * + * Macro2 is written right-to-left starting from the end of the + * buffer. + * + * ¯o_buffer macro_end + * v v + * +------------------------------------------------------------+ + * |>>>>>> MACRO1 >>>>>> <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| + * +------------------------------------------------------------+ + * ^ ^ + * r_macro_end r_macro_buffer + * + * During the recording when one macro encounters the end of the + * other macro, the recording is stopped. Apart from this, there + * are no arbitrary limits for the macros' length in relation to + * each other: for example one can either have two medium sized + * macros or one long macro and one short macro. Or even one empty + * and one using the whole buffer. + */ + static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; + + /* Pointer to the first buffer element after the first macro. + * Initially points to the very beginning of the buffer since the + * macro is empty. */ + static keyrecord_t *macro_end = macro_buffer; + + /* The other end of the macro buffer. Serves as the beginning of + * the second macro. */ + static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; + + /* Like macro_end but for the second macro. */ + static keyrecord_t *r_macro_end = r_macro_buffer; + + /* A persistent pointer to the current macro position (iterator) + * used during the recording. */ + static keyrecord_t *macro_pointer = NULL; + + /* 0 - no macro is being recorded right now + * 1,2 - either macro 1 or 2 is being recorded */ + static uint8_t macro_id = 0; + + if (macro_id == 0) { + /* No macro recording in progress. */ + if (!record->event.pressed) { + switch (keycode) { + case QK_DYNAMIC_MACRO_RECORD_START_1: + dynamic_macro_record_start(¯o_pointer, macro_buffer); + macro_id = 1; + return false; + case QK_DYNAMIC_MACRO_RECORD_START_2: + dynamic_macro_record_start(¯o_pointer, r_macro_buffer); + macro_id = 2; + return false; + case QK_DYNAMIC_MACRO_PLAY_1: + dynamic_macro_play(macro_buffer, macro_end, +1); + return false; + case QK_DYNAMIC_MACRO_PLAY_2: + dynamic_macro_play(r_macro_buffer, r_macro_end, -1); + return false; + } + } + } else { + /* A macro is being recorded right now. */ + switch (keycode) { + case QK_DYNAMIC_MACRO_RECORD_STOP: + /* Stop the macro recording. */ + if (record->event.pressed) { /* Ignore the initial release + * just after the recoding + * starts. */ + switch (macro_id) { + case 1: + dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); + break; + case 2: + dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); + break; + } + macro_id = 0; + } + return false; + case QK_DYNAMIC_MACRO_PLAY_1: + case QK_DYNAMIC_MACRO_PLAY_2: + dprintln("dynamic macro: ignoring macro play key while recording"); + return false; + default: + /* Store the key in the macro buffer and process it normally. */ + switch (macro_id) { + case 1: + dynamic_macro_record_key(macro_buffer, ¯o_pointer, r_macro_end, +1, record); + break; + case 2: + dynamic_macro_record_key(r_macro_buffer, ¯o_pointer, macro_end, -1, record); + break; + } + return true; + break; + } + } + + return true; +} + +#undef DYNAMIC_MACRO_CURRENT_SLOT +#undef DYNAMIC_MACRO_CURRENT_LENGTH +#undef DYNAMIC_MACRO_CURRENT_CAPACITY diff --git a/app/src/launcher/keycodes.h b/app/src/launcher/keycodes.h new file mode 100644 index 00000000000..da0d887f0c6 --- /dev/null +++ b/app/src/launcher/keycodes.h @@ -0,0 +1,1519 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +/******************************************************************************* + 88888888888 888 d8b .d888 d8b 888 d8b + 888 888 Y8P d88P" Y8P 888 Y8P + 888 888 888 888 + 888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b + 888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K + 888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b. + 888 888 888 888 X88 888 888 888 Y8b. 888 X88 + 888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P' + 888 888 + 888 888 + 888 888 + .d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888 + d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888 + 888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888 + Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888 + "Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888 + 888 + Y8b d88P + "Y88P" +*******************************************************************************/ + +#pragma once +// clang-format off + +enum qk_keycode_ranges { +// Ranges + QK_BASIC = 0x0000, + QK_BASIC_MAX = 0x00FF, + QK_MODS = 0x0100, + QK_MODS_MAX = 0x1FFF, + QK_MOD_TAP = 0x2000, + QK_MOD_TAP_MAX = 0x3FFF, + QK_LAYER_TAP = 0x4000, + QK_LAYER_TAP_MAX = 0x4FFF, + QK_LAYER_MOD = 0x5000, + QK_LAYER_MOD_MAX = 0x51FF, + QK_TO = 0x5200, + QK_TO_MAX = 0x521F, + QK_MOMENTARY = 0x5220, + QK_MOMENTARY_MAX = 0x523F, + QK_DEF_LAYER = 0x5240, + QK_DEF_LAYER_MAX = 0x525F, + QK_TOGGLE_LAYER = 0x5260, + QK_TOGGLE_LAYER_MAX = 0x527F, + QK_ONE_SHOT_LAYER = 0x5280, + QK_ONE_SHOT_LAYER_MAX = 0x529F, + QK_ONE_SHOT_MOD = 0x52A0, + QK_ONE_SHOT_MOD_MAX = 0x52BF, + QK_LAYER_TAP_TOGGLE = 0x52C0, + QK_LAYER_TAP_TOGGLE_MAX = 0x52DF, + QK_SWAP_HANDS = 0x5600, + QK_SWAP_HANDS_MAX = 0x56FF, + QK_TAP_DANCE = 0x5700, + QK_TAP_DANCE_MAX = 0x57FF, + QK_MAGIC = 0x7000, + QK_MAGIC_MAX = 0x70FF, + QK_MIDI = 0x7100, + QK_MIDI_MAX = 0x71FF, + QK_SEQUENCER = 0x7200, + QK_SEQUENCER_MAX = 0x73FF, + QK_JOYSTICK = 0x7400, + QK_JOYSTICK_MAX = 0x743F, + QK_PROGRAMMABLE_BUTTON = 0x7440, + QK_PROGRAMMABLE_BUTTON_MAX = 0x747F, + QK_AUDIO = 0x7480, + QK_AUDIO_MAX = 0x74BF, + QK_STENO = 0x74C0, + QK_STENO_MAX = 0x74FF, + QK_MACRO = 0x7700, + QK_MACRO_MAX = 0x777F, + QK_LIGHTING = 0x7800, + QK_LIGHTING_MAX = 0x78FF, + QK_QUANTUM = 0x7C00, + QK_QUANTUM_MAX = 0x7DFF, + QK_KB = 0x7E00, + QK_KB_MAX = 0x7E3F, + QK_USER = 0x7E40, + QK_USER_MAX = 0x7FFF, + QK_UNICODEMAP = 0x8000, + QK_UNICODEMAP_MAX = 0xBFFF, + QK_UNICODE = 0x8000, + QK_UNICODE_MAX = 0xFFFF, + QK_UNICODEMAP_PAIR = 0xC000, + QK_UNICODEMAP_PAIR_MAX = 0xFFFF, +}; + +enum qk_keycode_defines { +// Keycodes + KC_NO = 0x0000, + KC_TRANSPARENT = 0x0001, + KC_A = 0x0004, + KC_B = 0x0005, + KC_C = 0x0006, + KC_D = 0x0007, + KC_E = 0x0008, + KC_F = 0x0009, + KC_G = 0x000A, + KC_H = 0x000B, + KC_I = 0x000C, + KC_J = 0x000D, + KC_K = 0x000E, + KC_L = 0x000F, + KC_M = 0x0010, + KC_N = 0x0011, + KC_O = 0x0012, + KC_P = 0x0013, + KC_Q = 0x0014, + KC_R = 0x0015, + KC_S = 0x0016, + KC_T = 0x0017, + KC_U = 0x0018, + KC_V = 0x0019, + KC_W = 0x001A, + KC_X = 0x001B, + KC_Y = 0x001C, + KC_Z = 0x001D, + KC_1 = 0x001E, + KC_2 = 0x001F, + KC_3 = 0x0020, + KC_4 = 0x0021, + KC_5 = 0x0022, + KC_6 = 0x0023, + KC_7 = 0x0024, + KC_8 = 0x0025, + KC_9 = 0x0026, + KC_0 = 0x0027, + KC_ENTER = 0x0028, + KC_ESCAPE = 0x0029, + KC_BACKSPACE = 0x002A, + KC_TAB = 0x002B, + KC_SPACE = 0x002C, + KC_MINUS = 0x002D, + KC_EQUAL = 0x002E, + KC_LEFT_BRACKET = 0x002F, + KC_RIGHT_BRACKET = 0x0030, + KC_BACKSLASH = 0x0031, + KC_NONUS_HASH = 0x0032, + KC_SEMICOLON = 0x0033, + KC_QUOTE = 0x0034, + KC_GRAVE = 0x0035, + KC_COMMA = 0x0036, + KC_DOT = 0x0037, + KC_SLASH = 0x0038, + KC_CAPS_LOCK = 0x0039, + KC_F1 = 0x003A, + KC_F2 = 0x003B, + KC_F3 = 0x003C, + KC_F4 = 0x003D, + KC_F5 = 0x003E, + KC_F6 = 0x003F, + KC_F7 = 0x0040, + KC_F8 = 0x0041, + KC_F9 = 0x0042, + KC_F10 = 0x0043, + KC_F11 = 0x0044, + KC_F12 = 0x0045, + KC_PRINT_SCREEN = 0x0046, + KC_SCROLL_LOCK = 0x0047, + KC_PAUSE = 0x0048, + KC_INSERT = 0x0049, + KC_HOME = 0x004A, + KC_PAGE_UP = 0x004B, + KC_DELETE = 0x004C, + KC_END = 0x004D, + KC_PAGE_DOWN = 0x004E, + KC_RIGHT = 0x004F, + KC_LEFT = 0x0050, + KC_DOWN = 0x0051, + KC_UP = 0x0052, + KC_NUM_LOCK = 0x0053, + KC_KP_SLASH = 0x0054, + KC_KP_ASTERISK = 0x0055, + KC_KP_MINUS = 0x0056, + KC_KP_PLUS = 0x0057, + KC_KP_ENTER = 0x0058, + KC_KP_1 = 0x0059, + KC_KP_2 = 0x005A, + KC_KP_3 = 0x005B, + KC_KP_4 = 0x005C, + KC_KP_5 = 0x005D, + KC_KP_6 = 0x005E, + KC_KP_7 = 0x005F, + KC_KP_8 = 0x0060, + KC_KP_9 = 0x0061, + KC_KP_0 = 0x0062, + KC_KP_DOT = 0x0063, + KC_NONUS_BACKSLASH = 0x0064, + KC_APPLICATION = 0x0065, + KC_KB_POWER = 0x0066, + KC_KP_EQUAL = 0x0067, + KC_F13 = 0x0068, + KC_F14 = 0x0069, + KC_F15 = 0x006A, + KC_F16 = 0x006B, + KC_F17 = 0x006C, + KC_F18 = 0x006D, + KC_F19 = 0x006E, + KC_F20 = 0x006F, + KC_F21 = 0x0070, + KC_F22 = 0x0071, + KC_F23 = 0x0072, + KC_F24 = 0x0073, + KC_EXECUTE = 0x0074, + KC_HELP = 0x0075, + KC_MENU = 0x0076, + KC_SELECT = 0x0077, + KC_STOP = 0x0078, + KC_AGAIN = 0x0079, + KC_UNDO = 0x007A, + KC_CUT = 0x007B, + KC_COPY = 0x007C, + KC_PASTE = 0x007D, + KC_FIND = 0x007E, + KC_KB_MUTE = 0x007F, + KC_KB_VOLUME_UP = 0x0080, + KC_KB_VOLUME_DOWN = 0x0081, + KC_LOCKING_CAPS_LOCK = 0x0082, + KC_LOCKING_NUM_LOCK = 0x0083, + KC_LOCKING_SCROLL_LOCK = 0x0084, + KC_KP_COMMA = 0x0085, + KC_KP_EQUAL_AS400 = 0x0086, + KC_INTERNATIONAL_1 = 0x0087, + KC_INTERNATIONAL_2 = 0x0088, + KC_INTERNATIONAL_3 = 0x0089, + KC_INTERNATIONAL_4 = 0x008A, + KC_INTERNATIONAL_5 = 0x008B, + KC_INTERNATIONAL_6 = 0x008C, + KC_INTERNATIONAL_7 = 0x008D, + KC_INTERNATIONAL_8 = 0x008E, + KC_INTERNATIONAL_9 = 0x008F, + KC_LANGUAGE_1 = 0x0090, + KC_LANGUAGE_2 = 0x0091, + KC_LANGUAGE_3 = 0x0092, + KC_LANGUAGE_4 = 0x0093, + KC_LANGUAGE_5 = 0x0094, + KC_LANGUAGE_6 = 0x0095, + KC_LANGUAGE_7 = 0x0096, + KC_LANGUAGE_8 = 0x0097, + KC_LANGUAGE_9 = 0x0098, + KC_ALTERNATE_ERASE = 0x0099, + KC_SYSTEM_REQUEST = 0x009A, + KC_CANCEL = 0x009B, + KC_CLEAR = 0x009C, + KC_PRIOR = 0x009D, + KC_RETURN = 0x009E, + KC_SEPARATOR = 0x009F, + KC_OUT = 0x00A0, + KC_OPER = 0x00A1, + KC_CLEAR_AGAIN = 0x00A2, + KC_CRSEL = 0x00A3, + KC_EXSEL = 0x00A4, + KC_SYSTEM_POWER = 0x00A5, + KC_SYSTEM_SLEEP = 0x00A6, + KC_SYSTEM_WAKE = 0x00A7, + KC_AUDIO_MUTE = 0x00A8, + KC_AUDIO_VOL_UP = 0x00A9, + KC_AUDIO_VOL_DOWN = 0x00AA, + KC_MEDIA_NEXT_TRACK = 0x00AB, + KC_MEDIA_PREV_TRACK = 0x00AC, + KC_MEDIA_STOP = 0x00AD, + KC_MEDIA_PLAY_PAUSE = 0x00AE, + KC_MEDIA_SELECT = 0x00AF, + KC_MEDIA_EJECT = 0x00B0, + KC_MAIL = 0x00B1, + KC_CALCULATOR = 0x00B2, + KC_MY_COMPUTER = 0x00B3, + KC_WWW_SEARCH = 0x00B4, + KC_WWW_HOME = 0x00B5, + KC_WWW_BACK = 0x00B6, + KC_WWW_FORWARD = 0x00B7, + KC_WWW_STOP = 0x00B8, + KC_WWW_REFRESH = 0x00B9, + KC_WWW_FAVORITES = 0x00BA, + KC_MEDIA_FAST_FORWARD = 0x00BB, + KC_MEDIA_REWIND = 0x00BC, + KC_BRIGHTNESS_UP = 0x00BD, + KC_BRIGHTNESS_DOWN = 0x00BE, + KC_CONTROL_PANEL = 0x00BF, + KC_ASSISTANT = 0x00C0, + KC_MISSION_CONTROL = 0x00C1, + KC_LAUNCHPAD = 0x00C2, + KC_MS_UP = 0x00CD, + KC_MS_DOWN = 0x00CE, + KC_MS_LEFT = 0x00CF, + KC_MS_RIGHT = 0x00D0, + KC_MS_BTN1 = 0x00D1, + KC_MS_BTN2 = 0x00D2, + KC_MS_BTN3 = 0x00D3, + KC_MS_BTN4 = 0x00D4, + KC_MS_BTN5 = 0x00D5, + KC_MS_BTN6 = 0x00D6, + KC_MS_BTN7 = 0x00D7, + KC_MS_BTN8 = 0x00D8, + KC_MS_WH_UP = 0x00D9, + KC_MS_WH_DOWN = 0x00DA, + KC_MS_WH_LEFT = 0x00DB, + KC_MS_WH_RIGHT = 0x00DC, + KC_MS_ACCEL0 = 0x00DD, + KC_MS_ACCEL1 = 0x00DE, + KC_MS_ACCEL2 = 0x00DF, + KC_LEFT_CTRL = 0x00E0, + KC_LEFT_SHIFT = 0x00E1, + KC_LEFT_ALT = 0x00E2, + KC_LEFT_GUI = 0x00E3, + KC_RIGHT_CTRL = 0x00E4, + KC_RIGHT_SHIFT = 0x00E5, + KC_RIGHT_ALT = 0x00E6, + KC_RIGHT_GUI = 0x00E7, + QK_SWAP_HANDS_TOGGLE = 0x56F0, + QK_SWAP_HANDS_TAP_TOGGLE = 0x56F1, + QK_SWAP_HANDS_MOMENTARY_ON = 0x56F2, + QK_SWAP_HANDS_MOMENTARY_OFF = 0x56F3, + QK_SWAP_HANDS_OFF = 0x56F4, + QK_SWAP_HANDS_ON = 0x56F5, + QK_SWAP_HANDS_ONE_SHOT = 0x56F6, + QK_MAGIC_SWAP_CONTROL_CAPS_LOCK = 0x7000, + QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK = 0x7001, + QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK = 0x7002, + QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF = 0x7003, + QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON = 0x7004, + QK_MAGIC_SWAP_LALT_LGUI = 0x7005, + QK_MAGIC_UNSWAP_LALT_LGUI = 0x7006, + QK_MAGIC_SWAP_RALT_RGUI = 0x7007, + QK_MAGIC_UNSWAP_RALT_RGUI = 0x7008, + QK_MAGIC_GUI_ON = 0x7009, + QK_MAGIC_GUI_OFF = 0x700A, + QK_MAGIC_TOGGLE_GUI = 0x700B, + QK_MAGIC_SWAP_GRAVE_ESC = 0x700C, + QK_MAGIC_UNSWAP_GRAVE_ESC = 0x700D, + QK_MAGIC_SWAP_BACKSLASH_BACKSPACE = 0x700E, + QK_MAGIC_UNSWAP_BACKSLASH_BACKSPACE = 0x700F, + QK_MAGIC_TOGGLE_BACKSLASH_BACKSPACE = 0x7010, + QK_MAGIC_NKRO_ON = 0x7011, + QK_MAGIC_NKRO_OFF = 0x7012, + QK_MAGIC_TOGGLE_NKRO = 0x7013, + QK_MAGIC_SWAP_ALT_GUI = 0x7014, + QK_MAGIC_UNSWAP_ALT_GUI = 0x7015, + QK_MAGIC_TOGGLE_ALT_GUI = 0x7016, + QK_MAGIC_SWAP_LCTL_LGUI = 0x7017, + QK_MAGIC_UNSWAP_LCTL_LGUI = 0x7018, + QK_MAGIC_SWAP_RCTL_RGUI = 0x7019, + QK_MAGIC_UNSWAP_RCTL_RGUI = 0x701A, + QK_MAGIC_SWAP_CTL_GUI = 0x701B, + QK_MAGIC_UNSWAP_CTL_GUI = 0x701C, + QK_MAGIC_TOGGLE_CTL_GUI = 0x701D, + QK_MAGIC_EE_HANDS_LEFT = 0x701E, + QK_MAGIC_EE_HANDS_RIGHT = 0x701F, + QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK = 0x7020, + QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK = 0x7021, + QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK = 0x7022, + QK_MIDI_ON = 0x7100, + QK_MIDI_OFF = 0x7101, + QK_MIDI_TOGGLE = 0x7102, + QK_MIDI_NOTE_C_0 = 0x7103, + QK_MIDI_NOTE_C_SHARP_0 = 0x7104, + QK_MIDI_NOTE_D_0 = 0x7105, + QK_MIDI_NOTE_D_SHARP_0 = 0x7106, + QK_MIDI_NOTE_E_0 = 0x7107, + QK_MIDI_NOTE_F_0 = 0x7108, + QK_MIDI_NOTE_F_SHARP_0 = 0x7109, + QK_MIDI_NOTE_G_0 = 0x710A, + QK_MIDI_NOTE_G_SHARP_0 = 0x710B, + QK_MIDI_NOTE_A_0 = 0x710C, + QK_MIDI_NOTE_A_SHARP_0 = 0x710D, + QK_MIDI_NOTE_B_0 = 0x710E, + QK_MIDI_NOTE_C_1 = 0x710F, + QK_MIDI_NOTE_C_SHARP_1 = 0x7110, + QK_MIDI_NOTE_D_1 = 0x7111, + QK_MIDI_NOTE_D_SHARP_1 = 0x7112, + QK_MIDI_NOTE_E_1 = 0x7113, + QK_MIDI_NOTE_F_1 = 0x7114, + QK_MIDI_NOTE_F_SHARP_1 = 0x7115, + QK_MIDI_NOTE_G_1 = 0x7116, + QK_MIDI_NOTE_G_SHARP_1 = 0x7117, + QK_MIDI_NOTE_A_1 = 0x7118, + QK_MIDI_NOTE_A_SHARP_1 = 0x7119, + QK_MIDI_NOTE_B_1 = 0x711A, + QK_MIDI_NOTE_C_2 = 0x711B, + QK_MIDI_NOTE_C_SHARP_2 = 0x711C, + QK_MIDI_NOTE_D_2 = 0x711D, + QK_MIDI_NOTE_D_SHARP_2 = 0x711E, + QK_MIDI_NOTE_E_2 = 0x711F, + QK_MIDI_NOTE_F_2 = 0x7120, + QK_MIDI_NOTE_F_SHARP_2 = 0x7121, + QK_MIDI_NOTE_G_2 = 0x7122, + QK_MIDI_NOTE_G_SHARP_2 = 0x7123, + QK_MIDI_NOTE_A_2 = 0x7124, + QK_MIDI_NOTE_A_SHARP_2 = 0x7125, + QK_MIDI_NOTE_B_2 = 0x7126, + QK_MIDI_NOTE_C_3 = 0x7127, + QK_MIDI_NOTE_C_SHARP_3 = 0x7128, + QK_MIDI_NOTE_D_3 = 0x7129, + QK_MIDI_NOTE_D_SHARP_3 = 0x712A, + QK_MIDI_NOTE_E_3 = 0x712B, + QK_MIDI_NOTE_F_3 = 0x712C, + QK_MIDI_NOTE_F_SHARP_3 = 0x712D, + QK_MIDI_NOTE_G_3 = 0x712E, + QK_MIDI_NOTE_G_SHARP_3 = 0x712F, + QK_MIDI_NOTE_A_3 = 0x7130, + QK_MIDI_NOTE_A_SHARP_3 = 0x7131, + QK_MIDI_NOTE_B_3 = 0x7132, + QK_MIDI_NOTE_C_4 = 0x7133, + QK_MIDI_NOTE_C_SHARP_4 = 0x7134, + QK_MIDI_NOTE_D_4 = 0x7135, + QK_MIDI_NOTE_D_SHARP_4 = 0x7136, + QK_MIDI_NOTE_E_4 = 0x7137, + QK_MIDI_NOTE_F_4 = 0x7138, + QK_MIDI_NOTE_F_SHARP_4 = 0x7139, + QK_MIDI_NOTE_G_4 = 0x713A, + QK_MIDI_NOTE_G_SHARP_4 = 0x713B, + QK_MIDI_NOTE_A_4 = 0x713C, + QK_MIDI_NOTE_A_SHARP_4 = 0x713D, + QK_MIDI_NOTE_B_4 = 0x713E, + QK_MIDI_NOTE_C_5 = 0x713F, + QK_MIDI_NOTE_C_SHARP_5 = 0x7140, + QK_MIDI_NOTE_D_5 = 0x7141, + QK_MIDI_NOTE_D_SHARP_5 = 0x7142, + QK_MIDI_NOTE_E_5 = 0x7143, + QK_MIDI_NOTE_F_5 = 0x7144, + QK_MIDI_NOTE_F_SHARP_5 = 0x7145, + QK_MIDI_NOTE_G_5 = 0x7146, + QK_MIDI_NOTE_G_SHARP_5 = 0x7147, + QK_MIDI_NOTE_A_5 = 0x7148, + QK_MIDI_NOTE_A_SHARP_5 = 0x7149, + QK_MIDI_NOTE_B_5 = 0x714A, + QK_MIDI_OCTAVE_N2 = 0x714B, + QK_MIDI_OCTAVE_N1 = 0x714C, + QK_MIDI_OCTAVE_0 = 0x714D, + QK_MIDI_OCTAVE_1 = 0x714E, + QK_MIDI_OCTAVE_2 = 0x714F, + QK_MIDI_OCTAVE_3 = 0x7150, + QK_MIDI_OCTAVE_4 = 0x7151, + QK_MIDI_OCTAVE_5 = 0x7152, + QK_MIDI_OCTAVE_6 = 0x7153, + QK_MIDI_OCTAVE_7 = 0x7154, + QK_MIDI_OCTAVE_DOWN = 0x7155, + QK_MIDI_OCTAVE_UP = 0x7156, + QK_MIDI_TRANSPOSE_N6 = 0x7157, + QK_MIDI_TRANSPOSE_N5 = 0x7158, + QK_MIDI_TRANSPOSE_N4 = 0x7159, + QK_MIDI_TRANSPOSE_N3 = 0x715A, + QK_MIDI_TRANSPOSE_N2 = 0x715B, + QK_MIDI_TRANSPOSE_N1 = 0x715C, + QK_MIDI_TRANSPOSE_0 = 0x715D, + QK_MIDI_TRANSPOSE_1 = 0x715E, + QK_MIDI_TRANSPOSE_2 = 0x715F, + QK_MIDI_TRANSPOSE_3 = 0x7160, + QK_MIDI_TRANSPOSE_4 = 0x7161, + QK_MIDI_TRANSPOSE_5 = 0x7162, + QK_MIDI_TRANSPOSE_6 = 0x7163, + QK_MIDI_TRANSPOSE_DOWN = 0x7164, + QK_MIDI_TRANSPOSE_UP = 0x7165, + QK_MIDI_VELOCITY_0 = 0x7166, + QK_MIDI_VELOCITY_1 = 0x7167, + QK_MIDI_VELOCITY_2 = 0x7168, + QK_MIDI_VELOCITY_3 = 0x7169, + QK_MIDI_VELOCITY_4 = 0x716A, + QK_MIDI_VELOCITY_5 = 0x716B, + QK_MIDI_VELOCITY_6 = 0x716C, + QK_MIDI_VELOCITY_7 = 0x716D, + QK_MIDI_VELOCITY_8 = 0x716E, + QK_MIDI_VELOCITY_9 = 0x716F, + QK_MIDI_VELOCITY_10 = 0x7170, + QK_MIDI_VELOCITY_DOWN = 0x7171, + QK_MIDI_VELOCITY_UP = 0x7172, + QK_MIDI_CHANNEL_1 = 0x7173, + QK_MIDI_CHANNEL_2 = 0x7174, + QK_MIDI_CHANNEL_3 = 0x7175, + QK_MIDI_CHANNEL_4 = 0x7176, + QK_MIDI_CHANNEL_5 = 0x7177, + QK_MIDI_CHANNEL_6 = 0x7178, + QK_MIDI_CHANNEL_7 = 0x7179, + QK_MIDI_CHANNEL_8 = 0x717A, + QK_MIDI_CHANNEL_9 = 0x717B, + QK_MIDI_CHANNEL_10 = 0x717C, + QK_MIDI_CHANNEL_11 = 0x717D, + QK_MIDI_CHANNEL_12 = 0x717E, + QK_MIDI_CHANNEL_13 = 0x717F, + QK_MIDI_CHANNEL_14 = 0x7180, + QK_MIDI_CHANNEL_15 = 0x7181, + QK_MIDI_CHANNEL_16 = 0x7182, + QK_MIDI_CHANNEL_DOWN = 0x7183, + QK_MIDI_CHANNEL_UP = 0x7184, + QK_MIDI_ALL_NOTES_OFF = 0x7185, + QK_MIDI_SUSTAIN = 0x7186, + QK_MIDI_PORTAMENTO = 0x7187, + QK_MIDI_SOSTENUTO = 0x7188, + QK_MIDI_SOFT = 0x7189, + QK_MIDI_LEGATO = 0x718A, + QK_MIDI_MODULATION = 0x718B, + QK_MIDI_MODULATION_SPEED_DOWN = 0x718C, + QK_MIDI_MODULATION_SPEED_UP = 0x718D, + QK_MIDI_PITCH_BEND_DOWN = 0x718E, + QK_MIDI_PITCH_BEND_UP = 0x718F, + QK_SEQUENCER_ON = 0x7200, + QK_SEQUENCER_OFF = 0x7201, + QK_SEQUENCER_TOGGLE = 0x7202, + QK_SEQUENCER_TEMPO_DOWN = 0x7203, + QK_SEQUENCER_TEMPO_UP = 0x7204, + QK_SEQUENCER_RESOLUTION_DOWN = 0x7205, + QK_SEQUENCER_RESOLUTION_UP = 0x7206, + QK_SEQUENCER_STEPS_ALL = 0x7207, + QK_SEQUENCER_STEPS_CLEAR = 0x7208, + QK_JOYSTICK_BUTTON_0 = 0x7400, + QK_JOYSTICK_BUTTON_1 = 0x7401, + QK_JOYSTICK_BUTTON_2 = 0x7402, + QK_JOYSTICK_BUTTON_3 = 0x7403, + QK_JOYSTICK_BUTTON_4 = 0x7404, + QK_JOYSTICK_BUTTON_5 = 0x7405, + QK_JOYSTICK_BUTTON_6 = 0x7406, + QK_JOYSTICK_BUTTON_7 = 0x7407, + QK_JOYSTICK_BUTTON_8 = 0x7408, + QK_JOYSTICK_BUTTON_9 = 0x7409, + QK_JOYSTICK_BUTTON_10 = 0x740A, + QK_JOYSTICK_BUTTON_11 = 0x740B, + QK_JOYSTICK_BUTTON_12 = 0x740C, + QK_JOYSTICK_BUTTON_13 = 0x740D, + QK_JOYSTICK_BUTTON_14 = 0x740E, + QK_JOYSTICK_BUTTON_15 = 0x740F, + QK_JOYSTICK_BUTTON_16 = 0x7410, + QK_JOYSTICK_BUTTON_17 = 0x7411, + QK_JOYSTICK_BUTTON_18 = 0x7412, + QK_JOYSTICK_BUTTON_19 = 0x7413, + QK_JOYSTICK_BUTTON_20 = 0x7414, + QK_JOYSTICK_BUTTON_21 = 0x7415, + QK_JOYSTICK_BUTTON_22 = 0x7416, + QK_JOYSTICK_BUTTON_23 = 0x7417, + QK_JOYSTICK_BUTTON_24 = 0x7418, + QK_JOYSTICK_BUTTON_25 = 0x7419, + QK_JOYSTICK_BUTTON_26 = 0x741A, + QK_JOYSTICK_BUTTON_27 = 0x741B, + QK_JOYSTICK_BUTTON_28 = 0x741C, + QK_JOYSTICK_BUTTON_29 = 0x741D, + QK_JOYSTICK_BUTTON_30 = 0x741E, + QK_JOYSTICK_BUTTON_31 = 0x741F, + QK_PROGRAMMABLE_BUTTON_1 = 0x7440, + QK_PROGRAMMABLE_BUTTON_2 = 0x7441, + QK_PROGRAMMABLE_BUTTON_3 = 0x7442, + QK_PROGRAMMABLE_BUTTON_4 = 0x7443, + QK_PROGRAMMABLE_BUTTON_5 = 0x7444, + QK_PROGRAMMABLE_BUTTON_6 = 0x7445, + QK_PROGRAMMABLE_BUTTON_7 = 0x7446, + QK_PROGRAMMABLE_BUTTON_8 = 0x7447, + QK_PROGRAMMABLE_BUTTON_9 = 0x7448, + QK_PROGRAMMABLE_BUTTON_10 = 0x7449, + QK_PROGRAMMABLE_BUTTON_11 = 0x744A, + QK_PROGRAMMABLE_BUTTON_12 = 0x744B, + QK_PROGRAMMABLE_BUTTON_13 = 0x744C, + QK_PROGRAMMABLE_BUTTON_14 = 0x744D, + QK_PROGRAMMABLE_BUTTON_15 = 0x744E, + QK_PROGRAMMABLE_BUTTON_16 = 0x744F, + QK_PROGRAMMABLE_BUTTON_17 = 0x7450, + QK_PROGRAMMABLE_BUTTON_18 = 0x7451, + QK_PROGRAMMABLE_BUTTON_19 = 0x7452, + QK_PROGRAMMABLE_BUTTON_20 = 0x7453, + QK_PROGRAMMABLE_BUTTON_21 = 0x7454, + QK_PROGRAMMABLE_BUTTON_22 = 0x7455, + QK_PROGRAMMABLE_BUTTON_23 = 0x7456, + QK_PROGRAMMABLE_BUTTON_24 = 0x7457, + QK_PROGRAMMABLE_BUTTON_25 = 0x7458, + QK_PROGRAMMABLE_BUTTON_26 = 0x7459, + QK_PROGRAMMABLE_BUTTON_27 = 0x745A, + QK_PROGRAMMABLE_BUTTON_28 = 0x745B, + QK_PROGRAMMABLE_BUTTON_29 = 0x745C, + QK_PROGRAMMABLE_BUTTON_30 = 0x745D, + QK_PROGRAMMABLE_BUTTON_31 = 0x745E, + QK_PROGRAMMABLE_BUTTON_32 = 0x745F, + QK_AUDIO_ON = 0x7480, + QK_AUDIO_OFF = 0x7481, + QK_AUDIO_TOGGLE = 0x7482, + QK_AUDIO_CLICKY_TOGGLE = 0x748A, + QK_AUDIO_CLICKY_ON = 0x748B, + QK_AUDIO_CLICKY_OFF = 0x748C, + QK_AUDIO_CLICKY_UP = 0x748D, + QK_AUDIO_CLICKY_DOWN = 0x748E, + QK_AUDIO_CLICKY_RESET = 0x748F, + QK_MUSIC_ON = 0x7490, + QK_MUSIC_OFF = 0x7491, + QK_MUSIC_TOGGLE = 0x7492, + QK_MUSIC_MODE_NEXT = 0x7493, + QK_AUDIO_VOICE_NEXT = 0x7494, + QK_AUDIO_VOICE_PREVIOUS = 0x7495, + QK_STENO_BOLT = 0x74F0, + QK_STENO_GEMINI = 0x74F1, + QK_STENO_COMB = 0x74F2, + QK_STENO_COMB_MAX = 0x74FC, + QK_MACRO_0 = 0x7700, + QK_MACRO_1 = 0x7701, + QK_MACRO_2 = 0x7702, + QK_MACRO_3 = 0x7703, + QK_MACRO_4 = 0x7704, + QK_MACRO_5 = 0x7705, + QK_MACRO_6 = 0x7706, + QK_MACRO_7 = 0x7707, + QK_MACRO_8 = 0x7708, + QK_MACRO_9 = 0x7709, + QK_MACRO_10 = 0x770A, + QK_MACRO_11 = 0x770B, + QK_MACRO_12 = 0x770C, + QK_MACRO_13 = 0x770D, + QK_MACRO_14 = 0x770E, + QK_MACRO_15 = 0x770F, + QK_MACRO_16 = 0x7710, + QK_MACRO_17 = 0x7711, + QK_MACRO_18 = 0x7712, + QK_MACRO_19 = 0x7713, + QK_MACRO_20 = 0x7714, + QK_MACRO_21 = 0x7715, + QK_MACRO_22 = 0x7716, + QK_MACRO_23 = 0x7717, + QK_MACRO_24 = 0x7718, + QK_MACRO_25 = 0x7719, + QK_MACRO_26 = 0x771A, + QK_MACRO_27 = 0x771B, + QK_MACRO_28 = 0x771C, + QK_MACRO_29 = 0x771D, + QK_MACRO_30 = 0x771E, + QK_MACRO_31 = 0x771F, + QK_BACKLIGHT_ON = 0x7800, + QK_BACKLIGHT_OFF = 0x7801, + QK_BACKLIGHT_TOGGLE = 0x7802, + QK_BACKLIGHT_DOWN = 0x7803, + QK_BACKLIGHT_UP = 0x7804, + QK_BACKLIGHT_STEP = 0x7805, + QK_BACKLIGHT_TOGGLE_BREATHING = 0x7806, + RGB_TOG = 0x7820, + RGB_MODE_FORWARD = 0x7821, + RGB_MODE_REVERSE = 0x7822, + RGB_HUI = 0x7823, + RGB_HUD = 0x7824, + RGB_SAI = 0x7825, + RGB_SAD = 0x7826, + RGB_VAI = 0x7827, + RGB_VAD = 0x7828, + RGB_SPI = 0x7829, + RGB_SPD = 0x782A, + RGB_MODE_PLAIN = 0x782B, + RGB_MODE_BREATHE = 0x782C, + RGB_MODE_RAINBOW = 0x782D, + RGB_MODE_SWIRL = 0x782E, + RGB_MODE_SNAKE = 0x782F, + RGB_MODE_KNIGHT = 0x7830, + RGB_MODE_XMAS = 0x7831, + RGB_MODE_GRADIENT = 0x7832, + RGB_MODE_RGBTEST = 0x7833, + RGB_MODE_TWINKLE = 0x7834, + QK_BOOTLOADER = 0x7C00, + QK_REBOOT = 0x7C01, + QK_DEBUG_TOGGLE = 0x7C02, + QK_CLEAR_EEPROM = 0x7C03, + QK_MAKE = 0x7C04, + QK_AUTO_SHIFT_DOWN = 0x7C10, + QK_AUTO_SHIFT_UP = 0x7C11, + QK_AUTO_SHIFT_REPORT = 0x7C12, + QK_AUTO_SHIFT_ON = 0x7C13, + QK_AUTO_SHIFT_OFF = 0x7C14, + QK_AUTO_SHIFT_TOGGLE = 0x7C15, + QK_GRAVE_ESCAPE = 0x7C16, + QK_VELOCIKEY_TOGGLE = 0x7C17, + QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN = 0x7C18, + QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE = 0x7C19, + QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN = 0x7C1A, + QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE = 0x7C1B, + QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN = 0x7C1C, + QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE = 0x7C1D, + QK_SPACE_CADET_RIGHT_SHIFT_ENTER = 0x7C1E, + QK_OUTPUT_AUTO = 0x7C20, + QK_OUTPUT_USB = 0x7C21, + QK_OUTPUT_BLUETOOTH = 0x7C22, + QK_UNICODE_MODE_NEXT = 0x7C30, + QK_UNICODE_MODE_PREVIOUS = 0x7C31, + QK_UNICODE_MODE_MACOS = 0x7C32, + QK_UNICODE_MODE_LINUX = 0x7C33, + QK_UNICODE_MODE_WINDOWS = 0x7C34, + QK_UNICODE_MODE_BSD = 0x7C35, + QK_UNICODE_MODE_WINCOMPOSE = 0x7C36, + QK_UNICODE_MODE_EMACS = 0x7C37, + QK_HAPTIC_ON = 0x7C40, + QK_HAPTIC_OFF = 0x7C41, + QK_HAPTIC_TOGGLE = 0x7C42, + QK_HAPTIC_RESET = 0x7C43, + QK_HAPTIC_FEEDBACK_TOGGLE = 0x7C44, + QK_HAPTIC_BUZZ_TOGGLE = 0x7C45, + QK_HAPTIC_MODE_NEXT = 0x7C46, + QK_HAPTIC_MODE_PREVIOUS = 0x7C47, + QK_HAPTIC_CONTINUOUS_TOGGLE = 0x7C48, + QK_HAPTIC_CONTINUOUS_UP = 0x7C49, + QK_HAPTIC_CONTINUOUS_DOWN = 0x7C4A, + QK_HAPTIC_DWELL_UP = 0x7C4B, + QK_HAPTIC_DWELL_DOWN = 0x7C4C, + QK_COMBO_ON = 0x7C50, + QK_COMBO_OFF = 0x7C51, + QK_COMBO_TOGGLE = 0x7C52, + QK_DYNAMIC_MACRO_RECORD_START_1 = 0x7C53, + QK_DYNAMIC_MACRO_RECORD_START_2 = 0x7C54, + QK_DYNAMIC_MACRO_RECORD_STOP = 0x7C55, + QK_DYNAMIC_MACRO_PLAY_1 = 0x7C56, + QK_DYNAMIC_MACRO_PLAY_2 = 0x7C57, + QK_LEADER = 0x7C58, + QK_LOCK = 0x7C59, + QK_ONE_SHOT_ON = 0x7C5A, + QK_ONE_SHOT_OFF = 0x7C5B, + QK_ONE_SHOT_TOGGLE = 0x7C5C, + QK_KEY_OVERRIDE_TOGGLE = 0x7C5D, + QK_KEY_OVERRIDE_ON = 0x7C5E, + QK_KEY_OVERRIDE_OFF = 0x7C5F, + QK_SECURE_LOCK = 0x7C60, + QK_SECURE_UNLOCK = 0x7C61, + QK_SECURE_TOGGLE = 0x7C62, + QK_SECURE_REQUEST = 0x7C63, + QK_DYNAMIC_TAPPING_TERM_PRINT = 0x7C70, + QK_DYNAMIC_TAPPING_TERM_UP = 0x7C71, + QK_DYNAMIC_TAPPING_TERM_DOWN = 0x7C72, + QK_CAPS_WORD_TOGGLE = 0x7C73, + QK_AUTOCORRECT_ON = 0x7C74, + QK_AUTOCORRECT_OFF = 0x7C75, + QK_AUTOCORRECT_TOGGLE = 0x7C76, + QK_TRI_LAYER_LOWER = 0x7C77, + QK_TRI_LAYER_UPPER = 0x7C78, + QK_REPEAT_KEY = 0x7C79, + QK_ALT_REPEAT_KEY = 0x7C7A, + QK_KB_0 = 0x7E00, + QK_KB_1 = 0x7E01, + QK_KB_2 = 0x7E02, + QK_KB_3 = 0x7E03, + QK_KB_4 = 0x7E04, + QK_KB_5 = 0x7E05, + QK_KB_6 = 0x7E06, + QK_KB_7 = 0x7E07, + QK_KB_8 = 0x7E08, + QK_KB_9 = 0x7E09, + QK_KB_10 = 0x7E0A, + QK_KB_11 = 0x7E0B, + QK_KB_12 = 0x7E0C, + QK_KB_13 = 0x7E0D, + QK_KB_14 = 0x7E0E, + QK_KB_15 = 0x7E0F, + QK_KB_16 = 0x7E10, + QK_KB_17 = 0x7E11, + QK_KB_18 = 0x7E12, + QK_KB_19 = 0x7E13, + QK_KB_20 = 0x7E14, + QK_KB_21 = 0x7E15, + QK_KB_22 = 0x7E16, + QK_KB_23 = 0x7E17, + QK_KB_24 = 0x7E18, + QK_KB_25 = 0x7E19, + QK_KB_26 = 0x7E1A, + QK_KB_27 = 0x7E1B, + QK_KB_28 = 0x7E1C, + QK_KB_29 = 0x7E1D, + QK_KB_30 = 0x7E1E, + QK_KB_31 = 0x7E1F, + QK_USER_0 = 0x7E40, + QK_USER_1 = 0x7E41, + QK_USER_2 = 0x7E42, + QK_USER_3 = 0x7E43, + QK_USER_4 = 0x7E44, + QK_USER_5 = 0x7E45, + QK_USER_6 = 0x7E46, + QK_USER_7 = 0x7E47, + QK_USER_8 = 0x7E48, + QK_USER_9 = 0x7E49, + QK_USER_10 = 0x7E4A, + QK_USER_11 = 0x7E4B, + QK_USER_12 = 0x7E4C, + QK_USER_13 = 0x7E4D, + QK_USER_14 = 0x7E4E, + QK_USER_15 = 0x7E4F, + QK_USER_16 = 0x7E50, + QK_USER_17 = 0x7E51, + QK_USER_18 = 0x7E52, + QK_USER_19 = 0x7E53, + QK_USER_20 = 0x7E54, + QK_USER_21 = 0x7E55, + QK_USER_22 = 0x7E56, + QK_USER_23 = 0x7E57, + QK_USER_24 = 0x7E58, + QK_USER_25 = 0x7E59, + QK_USER_26 = 0x7E5A, + QK_USER_27 = 0x7E5B, + QK_USER_28 = 0x7E5C, + QK_USER_29 = 0x7E5D, + QK_USER_30 = 0x7E5E, + QK_USER_31 = 0x7E5F, + +// Alias + XXXXXXX = KC_NO, + _______ = KC_TRANSPARENT, + KC_TRNS = KC_TRANSPARENT, + KC_ENT = KC_ENTER, + KC_ESC = KC_ESCAPE, + KC_BSPC = KC_BACKSPACE, + KC_SPC = KC_SPACE, + KC_MINS = KC_MINUS, + KC_EQL = KC_EQUAL, + KC_LBRC = KC_LEFT_BRACKET, + KC_RBRC = KC_RIGHT_BRACKET, + KC_BSLS = KC_BACKSLASH, + KC_NUHS = KC_NONUS_HASH, + KC_SCLN = KC_SEMICOLON, + KC_QUOT = KC_QUOTE, + KC_GRV = KC_GRAVE, + KC_COMM = KC_COMMA, + KC_SLSH = KC_SLASH, + KC_CAPS = KC_CAPS_LOCK, + KC_PSCR = KC_PRINT_SCREEN, + KC_SCRL = KC_SCROLL_LOCK, + KC_BRMD = KC_SCROLL_LOCK, + KC_PAUS = KC_PAUSE, + KC_BRK = KC_PAUSE, + KC_BRMU = KC_PAUSE, + KC_INS = KC_INSERT, + KC_PGUP = KC_PAGE_UP, + KC_DEL = KC_DELETE, + KC_PGDN = KC_PAGE_DOWN, + KC_RGHT = KC_RIGHT, + KC_NUM = KC_NUM_LOCK, + KC_PSLS = KC_KP_SLASH, + KC_PAST = KC_KP_ASTERISK, + KC_PMNS = KC_KP_MINUS, + KC_PPLS = KC_KP_PLUS, + KC_PENT = KC_KP_ENTER, + KC_P1 = KC_KP_1, + KC_P2 = KC_KP_2, + KC_P3 = KC_KP_3, + KC_P4 = KC_KP_4, + KC_P5 = KC_KP_5, + KC_P6 = KC_KP_6, + KC_P7 = KC_KP_7, + KC_P8 = KC_KP_8, + KC_P9 = KC_KP_9, + KC_P0 = KC_KP_0, + KC_PDOT = KC_KP_DOT, + KC_NUBS = KC_NONUS_BACKSLASH, + KC_APP = KC_APPLICATION, + KC_PEQL = KC_KP_EQUAL, + KC_EXEC = KC_EXECUTE, + KC_SLCT = KC_SELECT, + KC_AGIN = KC_AGAIN, + KC_PSTE = KC_PASTE, + KC_LCAP = KC_LOCKING_CAPS_LOCK, + KC_LNUM = KC_LOCKING_NUM_LOCK, + KC_LSCR = KC_LOCKING_SCROLL_LOCK, + KC_PCMM = KC_KP_COMMA, + KC_INT1 = KC_INTERNATIONAL_1, + KC_INT2 = KC_INTERNATIONAL_2, + KC_INT3 = KC_INTERNATIONAL_3, + KC_INT4 = KC_INTERNATIONAL_4, + KC_INT5 = KC_INTERNATIONAL_5, + KC_INT6 = KC_INTERNATIONAL_6, + KC_INT7 = KC_INTERNATIONAL_7, + KC_INT8 = KC_INTERNATIONAL_8, + KC_INT9 = KC_INTERNATIONAL_9, + KC_LNG1 = KC_LANGUAGE_1, + KC_LNG2 = KC_LANGUAGE_2, + KC_LNG3 = KC_LANGUAGE_3, + KC_LNG4 = KC_LANGUAGE_4, + KC_LNG5 = KC_LANGUAGE_5, + KC_LNG6 = KC_LANGUAGE_6, + KC_LNG7 = KC_LANGUAGE_7, + KC_LNG8 = KC_LANGUAGE_8, + KC_LNG9 = KC_LANGUAGE_9, + KC_ERAS = KC_ALTERNATE_ERASE, + KC_SYRQ = KC_SYSTEM_REQUEST, + KC_CNCL = KC_CANCEL, + KC_CLR = KC_CLEAR, + KC_PRIR = KC_PRIOR, + KC_RETN = KC_RETURN, + KC_SEPR = KC_SEPARATOR, + KC_CLAG = KC_CLEAR_AGAIN, + KC_CRSL = KC_CRSEL, + KC_EXSL = KC_EXSEL, + KC_PWR = KC_SYSTEM_POWER, + KC_SLEP = KC_SYSTEM_SLEEP, + KC_WAKE = KC_SYSTEM_WAKE, + KC_MUTE = KC_AUDIO_MUTE, + KC_VOLU = KC_AUDIO_VOL_UP, + KC_VOLD = KC_AUDIO_VOL_DOWN, + KC_MNXT = KC_MEDIA_NEXT_TRACK, + KC_MPRV = KC_MEDIA_PREV_TRACK, + KC_MSTP = KC_MEDIA_STOP, + KC_MPLY = KC_MEDIA_PLAY_PAUSE, + KC_MSEL = KC_MEDIA_SELECT, + KC_EJCT = KC_MEDIA_EJECT, + KC_CALC = KC_CALCULATOR, + KC_MYCM = KC_MY_COMPUTER, + KC_WSCH = KC_WWW_SEARCH, + KC_WHOM = KC_WWW_HOME, + KC_WBAK = KC_WWW_BACK, + KC_WFWD = KC_WWW_FORWARD, + KC_WSTP = KC_WWW_STOP, + KC_WREF = KC_WWW_REFRESH, + KC_WFAV = KC_WWW_FAVORITES, + KC_MFFD = KC_MEDIA_FAST_FORWARD, + KC_MRWD = KC_MEDIA_REWIND, + KC_BRIU = KC_BRIGHTNESS_UP, + KC_BRID = KC_BRIGHTNESS_DOWN, + KC_CPNL = KC_CONTROL_PANEL, + KC_ASST = KC_ASSISTANT, + KC_MCTL = KC_MISSION_CONTROL, + KC_LPAD = KC_LAUNCHPAD, + KC_MS_U = KC_MS_UP, + KC_MS_D = KC_MS_DOWN, + KC_MS_L = KC_MS_LEFT, + KC_MS_R = KC_MS_RIGHT, + KC_BTN1 = KC_MS_BTN1, + KC_BTN2 = KC_MS_BTN2, + KC_BTN3 = KC_MS_BTN3, + KC_BTN4 = KC_MS_BTN4, + KC_BTN5 = KC_MS_BTN5, + KC_BTN6 = KC_MS_BTN6, + KC_BTN7 = KC_MS_BTN7, + KC_BTN8 = KC_MS_BTN8, + KC_WH_U = KC_MS_WH_UP, + KC_WH_D = KC_MS_WH_DOWN, + KC_WH_L = KC_MS_WH_LEFT, + KC_WH_R = KC_MS_WH_RIGHT, + KC_ACL0 = KC_MS_ACCEL0, + KC_ACL1 = KC_MS_ACCEL1, + KC_ACL2 = KC_MS_ACCEL2, + KC_LCTL = KC_LEFT_CTRL, + KC_LSFT = KC_LEFT_SHIFT, + KC_LALT = KC_LEFT_ALT, + KC_LOPT = KC_LEFT_ALT, + KC_LGUI = KC_LEFT_GUI, + KC_LCMD = KC_LEFT_GUI, + KC_LWIN = KC_LEFT_GUI, + KC_RCTL = KC_RIGHT_CTRL, + KC_RSFT = KC_RIGHT_SHIFT, + KC_RALT = KC_RIGHT_ALT, + KC_ROPT = KC_RIGHT_ALT, + KC_ALGR = KC_RIGHT_ALT, + KC_RGUI = KC_RIGHT_GUI, + KC_RCMD = KC_RIGHT_GUI, + KC_RWIN = KC_RIGHT_GUI, + SH_TOGG = QK_SWAP_HANDS_TOGGLE, + SH_TT = QK_SWAP_HANDS_TAP_TOGGLE, + SH_MON = QK_SWAP_HANDS_MOMENTARY_ON, + SH_MOFF = QK_SWAP_HANDS_MOMENTARY_OFF, + SH_OFF = QK_SWAP_HANDS_OFF, + SH_ON = QK_SWAP_HANDS_ON, + SH_OS = QK_SWAP_HANDS_ONE_SHOT, + CL_SWAP = QK_MAGIC_SWAP_CONTROL_CAPS_LOCK, + CL_NORM = QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK, + CL_TOGG = QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK, + CL_CAPS = QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF, + CL_CTRL = QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON, + AG_LSWP = QK_MAGIC_SWAP_LALT_LGUI, + AG_LNRM = QK_MAGIC_UNSWAP_LALT_LGUI, + AG_RSWP = QK_MAGIC_SWAP_RALT_RGUI, + AG_RNRM = QK_MAGIC_UNSWAP_RALT_RGUI, + GU_ON = QK_MAGIC_GUI_ON, + GU_OFF = QK_MAGIC_GUI_OFF, + GU_TOGG = QK_MAGIC_TOGGLE_GUI, + GE_SWAP = QK_MAGIC_SWAP_GRAVE_ESC, + GE_NORM = QK_MAGIC_UNSWAP_GRAVE_ESC, + BS_SWAP = QK_MAGIC_SWAP_BACKSLASH_BACKSPACE, + BS_NORM = QK_MAGIC_UNSWAP_BACKSLASH_BACKSPACE, + BS_TOGG = QK_MAGIC_TOGGLE_BACKSLASH_BACKSPACE, + NK_ON = QK_MAGIC_NKRO_ON, + NK_OFF = QK_MAGIC_NKRO_OFF, + NK_TOGG = QK_MAGIC_TOGGLE_NKRO, + AG_SWAP = QK_MAGIC_SWAP_ALT_GUI, + AG_NORM = QK_MAGIC_UNSWAP_ALT_GUI, + AG_TOGG = QK_MAGIC_TOGGLE_ALT_GUI, + CG_LSWP = QK_MAGIC_SWAP_LCTL_LGUI, + CG_LNRM = QK_MAGIC_UNSWAP_LCTL_LGUI, + CG_RSWP = QK_MAGIC_SWAP_RCTL_RGUI, + CG_RNRM = QK_MAGIC_UNSWAP_RCTL_RGUI, + CG_SWAP = QK_MAGIC_SWAP_CTL_GUI, + CG_NORM = QK_MAGIC_UNSWAP_CTL_GUI, + CG_TOGG = QK_MAGIC_TOGGLE_CTL_GUI, + EH_LEFT = QK_MAGIC_EE_HANDS_LEFT, + EH_RGHT = QK_MAGIC_EE_HANDS_RIGHT, + EC_SWAP = QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK, + EC_NORM = QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK, + EC_TOGG = QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK, + MI_ON = QK_MIDI_ON, + MI_OFF = QK_MIDI_OFF, + MI_TOGG = QK_MIDI_TOGGLE, + MI_C = QK_MIDI_NOTE_C_0, + MI_Cs = QK_MIDI_NOTE_C_SHARP_0, + MI_Db = QK_MIDI_NOTE_C_SHARP_0, + MI_D = QK_MIDI_NOTE_D_0, + MI_Ds = QK_MIDI_NOTE_D_SHARP_0, + MI_Eb = QK_MIDI_NOTE_D_SHARP_0, + MI_E = QK_MIDI_NOTE_E_0, + MI_F = QK_MIDI_NOTE_F_0, + MI_Fs = QK_MIDI_NOTE_F_SHARP_0, + MI_Gb = QK_MIDI_NOTE_F_SHARP_0, + MI_G = QK_MIDI_NOTE_G_0, + MI_Gs = QK_MIDI_NOTE_G_SHARP_0, + MI_Ab = QK_MIDI_NOTE_G_SHARP_0, + MI_A = QK_MIDI_NOTE_A_0, + MI_As = QK_MIDI_NOTE_A_SHARP_0, + MI_Bb = QK_MIDI_NOTE_A_SHARP_0, + MI_B = QK_MIDI_NOTE_B_0, + MI_C1 = QK_MIDI_NOTE_C_1, + MI_Cs1 = QK_MIDI_NOTE_C_SHARP_1, + MI_Db1 = QK_MIDI_NOTE_C_SHARP_1, + MI_D1 = QK_MIDI_NOTE_D_1, + MI_Ds1 = QK_MIDI_NOTE_D_SHARP_1, + MI_Eb1 = QK_MIDI_NOTE_D_SHARP_1, + MI_E1 = QK_MIDI_NOTE_E_1, + MI_F1 = QK_MIDI_NOTE_F_1, + MI_Fs1 = QK_MIDI_NOTE_F_SHARP_1, + MI_Gb1 = QK_MIDI_NOTE_F_SHARP_1, + MI_G1 = QK_MIDI_NOTE_G_1, + MI_Gs1 = QK_MIDI_NOTE_G_SHARP_1, + MI_Ab1 = QK_MIDI_NOTE_G_SHARP_1, + MI_A1 = QK_MIDI_NOTE_A_1, + MI_As1 = QK_MIDI_NOTE_A_SHARP_1, + MI_Bb1 = QK_MIDI_NOTE_A_SHARP_1, + MI_B1 = QK_MIDI_NOTE_B_1, + MI_C2 = QK_MIDI_NOTE_C_2, + MI_Cs2 = QK_MIDI_NOTE_C_SHARP_2, + MI_Db2 = QK_MIDI_NOTE_C_SHARP_2, + MI_D2 = QK_MIDI_NOTE_D_2, + MI_Ds2 = QK_MIDI_NOTE_D_SHARP_2, + MI_Eb2 = QK_MIDI_NOTE_D_SHARP_2, + MI_E2 = QK_MIDI_NOTE_E_2, + MI_F2 = QK_MIDI_NOTE_F_2, + MI_Fs2 = QK_MIDI_NOTE_F_SHARP_2, + MI_Gb2 = QK_MIDI_NOTE_F_SHARP_2, + MI_G2 = QK_MIDI_NOTE_G_2, + MI_Gs2 = QK_MIDI_NOTE_G_SHARP_2, + MI_Ab2 = QK_MIDI_NOTE_G_SHARP_2, + MI_A2 = QK_MIDI_NOTE_A_2, + MI_As2 = QK_MIDI_NOTE_A_SHARP_2, + MI_Bb2 = QK_MIDI_NOTE_A_SHARP_2, + MI_B2 = QK_MIDI_NOTE_B_2, + MI_C3 = QK_MIDI_NOTE_C_3, + MI_Cs3 = QK_MIDI_NOTE_C_SHARP_3, + MI_Db3 = QK_MIDI_NOTE_C_SHARP_3, + MI_D3 = QK_MIDI_NOTE_D_3, + MI_Ds3 = QK_MIDI_NOTE_D_SHARP_3, + MI_Eb3 = QK_MIDI_NOTE_D_SHARP_3, + MI_E3 = QK_MIDI_NOTE_E_3, + MI_F3 = QK_MIDI_NOTE_F_3, + MI_Fs3 = QK_MIDI_NOTE_F_SHARP_3, + MI_Gb3 = QK_MIDI_NOTE_F_SHARP_3, + MI_G3 = QK_MIDI_NOTE_G_3, + MI_Gs3 = QK_MIDI_NOTE_G_SHARP_3, + MI_Ab3 = QK_MIDI_NOTE_G_SHARP_3, + MI_A3 = QK_MIDI_NOTE_A_3, + MI_As3 = QK_MIDI_NOTE_A_SHARP_3, + MI_Bb3 = QK_MIDI_NOTE_A_SHARP_3, + MI_B3 = QK_MIDI_NOTE_B_3, + MI_C4 = QK_MIDI_NOTE_C_4, + MI_Cs4 = QK_MIDI_NOTE_C_SHARP_4, + MI_Db4 = QK_MIDI_NOTE_C_SHARP_4, + MI_D4 = QK_MIDI_NOTE_D_4, + MI_Ds4 = QK_MIDI_NOTE_D_SHARP_4, + MI_Eb4 = QK_MIDI_NOTE_D_SHARP_4, + MI_E4 = QK_MIDI_NOTE_E_4, + MI_F4 = QK_MIDI_NOTE_F_4, + MI_Fs4 = QK_MIDI_NOTE_F_SHARP_4, + MI_Gb4 = QK_MIDI_NOTE_F_SHARP_4, + MI_G4 = QK_MIDI_NOTE_G_4, + MI_Gs4 = QK_MIDI_NOTE_G_SHARP_4, + MI_Ab4 = QK_MIDI_NOTE_G_SHARP_4, + MI_A4 = QK_MIDI_NOTE_A_4, + MI_As4 = QK_MIDI_NOTE_A_SHARP_4, + MI_Bb4 = QK_MIDI_NOTE_A_SHARP_4, + MI_B4 = QK_MIDI_NOTE_B_4, + MI_C5 = QK_MIDI_NOTE_C_5, + MI_Cs5 = QK_MIDI_NOTE_C_SHARP_5, + MI_Db5 = QK_MIDI_NOTE_C_SHARP_5, + MI_D5 = QK_MIDI_NOTE_D_5, + MI_Ds5 = QK_MIDI_NOTE_D_SHARP_5, + MI_Eb5 = QK_MIDI_NOTE_D_SHARP_5, + MI_E5 = QK_MIDI_NOTE_E_5, + MI_F5 = QK_MIDI_NOTE_F_5, + MI_Fs5 = QK_MIDI_NOTE_F_SHARP_5, + MI_Gb5 = QK_MIDI_NOTE_F_SHARP_5, + MI_G5 = QK_MIDI_NOTE_G_5, + MI_Gs5 = QK_MIDI_NOTE_G_SHARP_5, + MI_Ab5 = QK_MIDI_NOTE_G_SHARP_5, + MI_A5 = QK_MIDI_NOTE_A_5, + MI_As5 = QK_MIDI_NOTE_A_SHARP_5, + MI_Bb5 = QK_MIDI_NOTE_A_SHARP_5, + MI_B5 = QK_MIDI_NOTE_B_5, + MI_OCN2 = QK_MIDI_OCTAVE_N2, + MI_OCN1 = QK_MIDI_OCTAVE_N1, + MI_OC0 = QK_MIDI_OCTAVE_0, + MI_OC1 = QK_MIDI_OCTAVE_1, + MI_OC2 = QK_MIDI_OCTAVE_2, + MI_OC3 = QK_MIDI_OCTAVE_3, + MI_OC4 = QK_MIDI_OCTAVE_4, + MI_OC5 = QK_MIDI_OCTAVE_5, + MI_OC6 = QK_MIDI_OCTAVE_6, + MI_OC7 = QK_MIDI_OCTAVE_7, + MI_OCTD = QK_MIDI_OCTAVE_DOWN, + MI_OCTU = QK_MIDI_OCTAVE_UP, + MI_TRN6 = QK_MIDI_TRANSPOSE_N6, + MI_TRN5 = QK_MIDI_TRANSPOSE_N5, + MI_TRN4 = QK_MIDI_TRANSPOSE_N4, + MI_TRN3 = QK_MIDI_TRANSPOSE_N3, + MI_TRN2 = QK_MIDI_TRANSPOSE_N2, + MI_TRN1 = QK_MIDI_TRANSPOSE_N1, + MI_TR0 = QK_MIDI_TRANSPOSE_0, + MI_TR1 = QK_MIDI_TRANSPOSE_1, + MI_TR2 = QK_MIDI_TRANSPOSE_2, + MI_TR3 = QK_MIDI_TRANSPOSE_3, + MI_TR4 = QK_MIDI_TRANSPOSE_4, + MI_TR5 = QK_MIDI_TRANSPOSE_5, + MI_TR6 = QK_MIDI_TRANSPOSE_6, + MI_TRSD = QK_MIDI_TRANSPOSE_DOWN, + MI_TRSU = QK_MIDI_TRANSPOSE_UP, + MI_VL0 = QK_MIDI_VELOCITY_0, + MI_VL1 = QK_MIDI_VELOCITY_1, + MI_VL2 = QK_MIDI_VELOCITY_2, + MI_VL3 = QK_MIDI_VELOCITY_3, + MI_VL4 = QK_MIDI_VELOCITY_4, + MI_VL5 = QK_MIDI_VELOCITY_5, + MI_VL6 = QK_MIDI_VELOCITY_6, + MI_VL7 = QK_MIDI_VELOCITY_7, + MI_VL8 = QK_MIDI_VELOCITY_8, + MI_VL9 = QK_MIDI_VELOCITY_9, + MI_VL10 = QK_MIDI_VELOCITY_10, + MI_VELD = QK_MIDI_VELOCITY_DOWN, + MI_VELU = QK_MIDI_VELOCITY_UP, + MI_CH1 = QK_MIDI_CHANNEL_1, + MI_CH2 = QK_MIDI_CHANNEL_2, + MI_CH3 = QK_MIDI_CHANNEL_3, + MI_CH4 = QK_MIDI_CHANNEL_4, + MI_CH5 = QK_MIDI_CHANNEL_5, + MI_CH6 = QK_MIDI_CHANNEL_6, + MI_CH7 = QK_MIDI_CHANNEL_7, + MI_CH8 = QK_MIDI_CHANNEL_8, + MI_CH9 = QK_MIDI_CHANNEL_9, + MI_CH10 = QK_MIDI_CHANNEL_10, + MI_CH11 = QK_MIDI_CHANNEL_11, + MI_CH12 = QK_MIDI_CHANNEL_12, + MI_CH13 = QK_MIDI_CHANNEL_13, + MI_CH14 = QK_MIDI_CHANNEL_14, + MI_CH15 = QK_MIDI_CHANNEL_15, + MI_CH16 = QK_MIDI_CHANNEL_16, + MI_CHND = QK_MIDI_CHANNEL_DOWN, + MI_CHNU = QK_MIDI_CHANNEL_UP, + MI_AOFF = QK_MIDI_ALL_NOTES_OFF, + MI_SUST = QK_MIDI_SUSTAIN, + MI_PORT = QK_MIDI_PORTAMENTO, + MI_SOST = QK_MIDI_SOSTENUTO, + MI_SOFT = QK_MIDI_SOFT, + MI_LEG = QK_MIDI_LEGATO, + MI_MOD = QK_MIDI_MODULATION, + MI_MODD = QK_MIDI_MODULATION_SPEED_DOWN, + MI_MODU = QK_MIDI_MODULATION_SPEED_UP, + MI_BNDD = QK_MIDI_PITCH_BEND_DOWN, + MI_BNDU = QK_MIDI_PITCH_BEND_UP, + SQ_ON = QK_SEQUENCER_ON, + SQ_OFF = QK_SEQUENCER_OFF, + SQ_TOGG = QK_SEQUENCER_TOGGLE, + SQ_TMPD = QK_SEQUENCER_TEMPO_DOWN, + SQ_TMPU = QK_SEQUENCER_TEMPO_UP, + SQ_RESD = QK_SEQUENCER_RESOLUTION_DOWN, + SQ_RESU = QK_SEQUENCER_RESOLUTION_UP, + SQ_SALL = QK_SEQUENCER_STEPS_ALL, + SQ_SCLR = QK_SEQUENCER_STEPS_CLEAR, + JS_0 = QK_JOYSTICK_BUTTON_0, + JS_1 = QK_JOYSTICK_BUTTON_1, + JS_2 = QK_JOYSTICK_BUTTON_2, + JS_3 = QK_JOYSTICK_BUTTON_3, + JS_4 = QK_JOYSTICK_BUTTON_4, + JS_5 = QK_JOYSTICK_BUTTON_5, + JS_6 = QK_JOYSTICK_BUTTON_6, + JS_7 = QK_JOYSTICK_BUTTON_7, + JS_8 = QK_JOYSTICK_BUTTON_8, + JS_9 = QK_JOYSTICK_BUTTON_9, + JS_10 = QK_JOYSTICK_BUTTON_10, + JS_11 = QK_JOYSTICK_BUTTON_11, + JS_12 = QK_JOYSTICK_BUTTON_12, + JS_13 = QK_JOYSTICK_BUTTON_13, + JS_14 = QK_JOYSTICK_BUTTON_14, + JS_15 = QK_JOYSTICK_BUTTON_15, + JS_16 = QK_JOYSTICK_BUTTON_16, + JS_17 = QK_JOYSTICK_BUTTON_17, + JS_18 = QK_JOYSTICK_BUTTON_18, + JS_19 = QK_JOYSTICK_BUTTON_19, + JS_20 = QK_JOYSTICK_BUTTON_20, + JS_21 = QK_JOYSTICK_BUTTON_21, + JS_22 = QK_JOYSTICK_BUTTON_22, + JS_23 = QK_JOYSTICK_BUTTON_23, + JS_24 = QK_JOYSTICK_BUTTON_24, + JS_25 = QK_JOYSTICK_BUTTON_25, + JS_26 = QK_JOYSTICK_BUTTON_26, + JS_27 = QK_JOYSTICK_BUTTON_27, + JS_28 = QK_JOYSTICK_BUTTON_28, + JS_29 = QK_JOYSTICK_BUTTON_29, + JS_30 = QK_JOYSTICK_BUTTON_30, + JS_31 = QK_JOYSTICK_BUTTON_31, + PB_1 = QK_PROGRAMMABLE_BUTTON_1, + PB_2 = QK_PROGRAMMABLE_BUTTON_2, + PB_3 = QK_PROGRAMMABLE_BUTTON_3, + PB_4 = QK_PROGRAMMABLE_BUTTON_4, + PB_5 = QK_PROGRAMMABLE_BUTTON_5, + PB_6 = QK_PROGRAMMABLE_BUTTON_6, + PB_7 = QK_PROGRAMMABLE_BUTTON_7, + PB_8 = QK_PROGRAMMABLE_BUTTON_8, + PB_9 = QK_PROGRAMMABLE_BUTTON_9, + PB_10 = QK_PROGRAMMABLE_BUTTON_10, + PB_11 = QK_PROGRAMMABLE_BUTTON_11, + PB_12 = QK_PROGRAMMABLE_BUTTON_12, + PB_13 = QK_PROGRAMMABLE_BUTTON_13, + PB_14 = QK_PROGRAMMABLE_BUTTON_14, + PB_15 = QK_PROGRAMMABLE_BUTTON_15, + PB_16 = QK_PROGRAMMABLE_BUTTON_16, + PB_17 = QK_PROGRAMMABLE_BUTTON_17, + PB_18 = QK_PROGRAMMABLE_BUTTON_18, + PB_19 = QK_PROGRAMMABLE_BUTTON_19, + PB_20 = QK_PROGRAMMABLE_BUTTON_20, + PB_21 = QK_PROGRAMMABLE_BUTTON_21, + PB_22 = QK_PROGRAMMABLE_BUTTON_22, + PB_23 = QK_PROGRAMMABLE_BUTTON_23, + PB_24 = QK_PROGRAMMABLE_BUTTON_24, + PB_25 = QK_PROGRAMMABLE_BUTTON_25, + PB_26 = QK_PROGRAMMABLE_BUTTON_26, + PB_27 = QK_PROGRAMMABLE_BUTTON_27, + PB_28 = QK_PROGRAMMABLE_BUTTON_28, + PB_29 = QK_PROGRAMMABLE_BUTTON_29, + PB_30 = QK_PROGRAMMABLE_BUTTON_30, + PB_31 = QK_PROGRAMMABLE_BUTTON_31, + PB_32 = QK_PROGRAMMABLE_BUTTON_32, + AU_ON = QK_AUDIO_ON, + AU_OFF = QK_AUDIO_OFF, + AU_TOGG = QK_AUDIO_TOGGLE, + CK_TOGG = QK_AUDIO_CLICKY_TOGGLE, + CK_ON = QK_AUDIO_CLICKY_ON, + CK_OFF = QK_AUDIO_CLICKY_OFF, + CK_UP = QK_AUDIO_CLICKY_UP, + CK_DOWN = QK_AUDIO_CLICKY_DOWN, + CK_RST = QK_AUDIO_CLICKY_RESET, + MU_ON = QK_MUSIC_ON, + MU_OFF = QK_MUSIC_OFF, + MU_TOGG = QK_MUSIC_TOGGLE, + MU_NEXT = QK_MUSIC_MODE_NEXT, + AU_NEXT = QK_AUDIO_VOICE_NEXT, + AU_PREV = QK_AUDIO_VOICE_PREVIOUS, + MC_0 = QK_MACRO_0, + MC_1 = QK_MACRO_1, + MC_2 = QK_MACRO_2, + MC_3 = QK_MACRO_3, + MC_4 = QK_MACRO_4, + MC_5 = QK_MACRO_5, + MC_6 = QK_MACRO_6, + MC_7 = QK_MACRO_7, + MC_8 = QK_MACRO_8, + MC_9 = QK_MACRO_9, + MC_10 = QK_MACRO_10, + MC_11 = QK_MACRO_11, + MC_12 = QK_MACRO_12, + MC_13 = QK_MACRO_13, + MC_14 = QK_MACRO_14, + MC_15 = QK_MACRO_15, + MC_16 = QK_MACRO_16, + MC_17 = QK_MACRO_17, + MC_18 = QK_MACRO_18, + MC_19 = QK_MACRO_19, + MC_20 = QK_MACRO_20, + MC_21 = QK_MACRO_21, + MC_22 = QK_MACRO_22, + MC_23 = QK_MACRO_23, + MC_24 = QK_MACRO_24, + MC_25 = QK_MACRO_25, + MC_26 = QK_MACRO_26, + MC_27 = QK_MACRO_27, + MC_28 = QK_MACRO_28, + MC_29 = QK_MACRO_29, + MC_30 = QK_MACRO_30, + MC_31 = QK_MACRO_31, + BL_ON = QK_BACKLIGHT_ON, + BL_OFF = QK_BACKLIGHT_OFF, + BL_TOGG = QK_BACKLIGHT_TOGGLE, + BL_DOWN = QK_BACKLIGHT_DOWN, + BL_UP = QK_BACKLIGHT_UP, + BL_STEP = QK_BACKLIGHT_STEP, + BL_BRTG = QK_BACKLIGHT_TOGGLE_BREATHING, + RGB_MOD = RGB_MODE_FORWARD, + RGB_RMOD = RGB_MODE_REVERSE, + RGB_M_P = RGB_MODE_PLAIN, + RGB_M_B = RGB_MODE_BREATHE, + RGB_M_R = RGB_MODE_RAINBOW, + RGB_M_SW = RGB_MODE_SWIRL, + RGB_M_SN = RGB_MODE_SNAKE, + RGB_M_K = RGB_MODE_KNIGHT, + RGB_M_X = RGB_MODE_XMAS, + RGB_M_G = RGB_MODE_GRADIENT, + RGB_M_T = RGB_MODE_RGBTEST, + RGB_M_TW = RGB_MODE_TWINKLE, + QK_BOOT = QK_BOOTLOADER, + QK_RBT = QK_REBOOT, + DB_TOGG = QK_DEBUG_TOGGLE, + EE_CLR = QK_CLEAR_EEPROM, + AS_DOWN = QK_AUTO_SHIFT_DOWN, + AS_UP = QK_AUTO_SHIFT_UP, + AS_RPT = QK_AUTO_SHIFT_REPORT, + AS_ON = QK_AUTO_SHIFT_ON, + AS_OFF = QK_AUTO_SHIFT_OFF, + AS_TOGG = QK_AUTO_SHIFT_TOGGLE, + QK_GESC = QK_GRAVE_ESCAPE, + VK_TOGG = QK_VELOCIKEY_TOGGLE, + SC_LCPO = QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN, + SC_RCPC = QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE, + SC_LSPO = QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN, + SC_RSPC = QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE, + SC_LAPO = QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN, + SC_RAPC = QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE, + SC_SENT = QK_SPACE_CADET_RIGHT_SHIFT_ENTER, + OU_AUTO = QK_OUTPUT_AUTO, + OU_USB = QK_OUTPUT_USB, + OU_BT = QK_OUTPUT_BLUETOOTH, + UC_NEXT = QK_UNICODE_MODE_NEXT, + UC_PREV = QK_UNICODE_MODE_PREVIOUS, + UC_MAC = QK_UNICODE_MODE_MACOS, + UC_LINX = QK_UNICODE_MODE_LINUX, + UC_WIN = QK_UNICODE_MODE_WINDOWS, + UC_BSD = QK_UNICODE_MODE_BSD, + UC_WINC = QK_UNICODE_MODE_WINCOMPOSE, + UC_EMAC = QK_UNICODE_MODE_EMACS, + HF_ON = QK_HAPTIC_ON, + HF_OFF = QK_HAPTIC_OFF, + HF_TOGG = QK_HAPTIC_TOGGLE, + HF_RST = QK_HAPTIC_RESET, + HF_FDBK = QK_HAPTIC_FEEDBACK_TOGGLE, + HF_BUZZ = QK_HAPTIC_BUZZ_TOGGLE, + HF_NEXT = QK_HAPTIC_MODE_NEXT, + HF_PREV = QK_HAPTIC_MODE_PREVIOUS, + HF_CONT = QK_HAPTIC_CONTINUOUS_TOGGLE, + HF_CONU = QK_HAPTIC_CONTINUOUS_UP, + HF_COND = QK_HAPTIC_CONTINUOUS_DOWN, + HF_DWLU = QK_HAPTIC_DWELL_UP, + HF_DWLD = QK_HAPTIC_DWELL_DOWN, + CM_ON = QK_COMBO_ON, + CM_OFF = QK_COMBO_OFF, + CM_TOGG = QK_COMBO_TOGGLE, + DM_REC1 = QK_DYNAMIC_MACRO_RECORD_START_1, + DM_REC2 = QK_DYNAMIC_MACRO_RECORD_START_2, + DM_RSTP = QK_DYNAMIC_MACRO_RECORD_STOP, + DM_PLY1 = QK_DYNAMIC_MACRO_PLAY_1, + DM_PLY2 = QK_DYNAMIC_MACRO_PLAY_2, + QK_LEAD = QK_LEADER, + OS_ON = QK_ONE_SHOT_ON, + OS_OFF = QK_ONE_SHOT_OFF, + OS_TOGG = QK_ONE_SHOT_TOGGLE, + KO_TOGG = QK_KEY_OVERRIDE_TOGGLE, + KO_ON = QK_KEY_OVERRIDE_ON, + KO_OFF = QK_KEY_OVERRIDE_OFF, + SE_LOCK = QK_SECURE_LOCK, + SE_UNLK = QK_SECURE_UNLOCK, + SE_TOGG = QK_SECURE_TOGGLE, + SE_REQ = QK_SECURE_REQUEST, + DT_PRNT = QK_DYNAMIC_TAPPING_TERM_PRINT, + DT_UP = QK_DYNAMIC_TAPPING_TERM_UP, + DT_DOWN = QK_DYNAMIC_TAPPING_TERM_DOWN, + CW_TOGG = QK_CAPS_WORD_TOGGLE, + AC_ON = QK_AUTOCORRECT_ON, + AC_OFF = QK_AUTOCORRECT_OFF, + AC_TOGG = QK_AUTOCORRECT_TOGGLE, + TL_LOWR = QK_TRI_LAYER_LOWER, + TL_UPPR = QK_TRI_LAYER_UPPER, + QK_REP = QK_REPEAT_KEY, + QK_AREP = QK_ALT_REPEAT_KEY, +}; + +// Range Helpers +#define IS_QK_BASIC(code) ((code) >= QK_BASIC && (code) <= QK_BASIC_MAX) +#define IS_QK_MODS(code) ((code) >= QK_MODS && (code) <= QK_MODS_MAX) +#define IS_QK_MOD_TAP(code) ((code) >= QK_MOD_TAP && (code) <= QK_MOD_TAP_MAX) +#define IS_QK_LAYER_TAP(code) ((code) >= QK_LAYER_TAP && (code) <= QK_LAYER_TAP_MAX) +#define IS_QK_LAYER_MOD(code) ((code) >= QK_LAYER_MOD && (code) <= QK_LAYER_MOD_MAX) +#define IS_QK_TO(code) ((code) >= QK_TO && (code) <= QK_TO_MAX) +#define IS_QK_MOMENTARY(code) ((code) >= QK_MOMENTARY && (code) <= QK_MOMENTARY_MAX) +#define IS_QK_DEF_LAYER(code) ((code) >= QK_DEF_LAYER && (code) <= QK_DEF_LAYER_MAX) +#define IS_QK_TOGGLE_LAYER(code) ((code) >= QK_TOGGLE_LAYER && (code) <= QK_TOGGLE_LAYER_MAX) +#define IS_QK_ONE_SHOT_LAYER(code) ((code) >= QK_ONE_SHOT_LAYER && (code) <= QK_ONE_SHOT_LAYER_MAX) +#define IS_QK_ONE_SHOT_MOD(code) ((code) >= QK_ONE_SHOT_MOD && (code) <= QK_ONE_SHOT_MOD_MAX) +#define IS_QK_LAYER_TAP_TOGGLE(code) ((code) >= QK_LAYER_TAP_TOGGLE && (code) <= QK_LAYER_TAP_TOGGLE_MAX) +#define IS_QK_SWAP_HANDS(code) ((code) >= QK_SWAP_HANDS && (code) <= QK_SWAP_HANDS_MAX) +#define IS_QK_TAP_DANCE(code) ((code) >= QK_TAP_DANCE && (code) <= QK_TAP_DANCE_MAX) +#define IS_QK_MAGIC(code) ((code) >= QK_MAGIC && (code) <= QK_MAGIC_MAX) +#define IS_QK_MIDI(code) ((code) >= QK_MIDI && (code) <= QK_MIDI_MAX) +#define IS_QK_SEQUENCER(code) ((code) >= QK_SEQUENCER && (code) <= QK_SEQUENCER_MAX) +#define IS_QK_JOYSTICK(code) ((code) >= QK_JOYSTICK && (code) <= QK_JOYSTICK_MAX) +#define IS_QK_PROGRAMMABLE_BUTTON(code) ((code) >= QK_PROGRAMMABLE_BUTTON && (code) <= QK_PROGRAMMABLE_BUTTON_MAX) +#define IS_QK_AUDIO(code) ((code) >= QK_AUDIO && (code) <= QK_AUDIO_MAX) +#define IS_QK_STENO(code) ((code) >= QK_STENO && (code) <= QK_STENO_MAX) +#define IS_QK_MACRO(code) ((code) >= QK_MACRO && (code) <= QK_MACRO_MAX) +#define IS_QK_LIGHTING(code) ((code) >= QK_LIGHTING && (code) <= QK_LIGHTING_MAX) +#define IS_QK_QUANTUM(code) ((code) >= QK_QUANTUM && (code) <= QK_QUANTUM_MAX) +#define IS_QK_KB(code) ((code) >= QK_KB && (code) <= QK_KB_MAX) +#define IS_QK_USER(code) ((code) >= QK_USER && (code) <= QK_USER_MAX) +#define IS_QK_UNICODEMAP(code) ((code) >= QK_UNICODEMAP && (code) <= QK_UNICODEMAP_MAX) +#define IS_QK_UNICODE(code) ((code) >= QK_UNICODE && (code) <= QK_UNICODE_MAX) +#define IS_QK_UNICODEMAP_PAIR(code) ((code) >= QK_UNICODEMAP_PAIR && (code) <= QK_UNICODEMAP_PAIR_MAX) + +// Group Helpers +#define IS_INTERNAL_KEYCODE(code) ((code) >= KC_NO && (code) <= KC_TRANSPARENT) +#define IS_BASIC_KEYCODE(code) ((code) >= KC_A && (code) <= KC_EXSEL) +#define IS_SYSTEM_KEYCODE(code) ((code) >= KC_SYSTEM_POWER && (code) <= KC_SYSTEM_WAKE) +#define IS_CONSUMER_KEYCODE(code) ((code) >= KC_AUDIO_MUTE && (code) <= KC_LAUNCHPAD) +#define IS_MOUSE_KEYCODE(code) ((code) >= KC_MS_UP && (code) <= KC_MS_ACCEL2) +#define IS_MODIFIER_KEYCODE(code) ((code) >= KC_LEFT_CTRL && (code) <= KC_RIGHT_GUI) +#define IS_SWAP_HANDS_KEYCODE(code) ((code) >= QK_SWAP_HANDS_TOGGLE && (code) <= QK_SWAP_HANDS_ONE_SHOT) +#define IS_MAGIC_KEYCODE(code) ((code) >= QK_MAGIC_SWAP_CONTROL_CAPS_LOCK && (code) <= QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK) +#define IS_MIDI_KEYCODE(code) ((code) >= QK_MIDI_ON && (code) <= QK_MIDI_PITCH_BEND_UP) +#define IS_SEQUENCER_KEYCODE(code) ((code) >= QK_SEQUENCER_ON && (code) <= QK_SEQUENCER_STEPS_CLEAR) +#define IS_JOYSTICK_KEYCODE(code) ((code) >= QK_JOYSTICK_BUTTON_0 && (code) <= QK_JOYSTICK_BUTTON_31) +#define IS_PROGRAMMABLE_BUTTON_KEYCODE(code) ((code) >= QK_PROGRAMMABLE_BUTTON_1 && (code) <= QK_PROGRAMMABLE_BUTTON_32) +#define IS_AUDIO_KEYCODE(code) ((code) >= QK_AUDIO_ON && (code) <= QK_AUDIO_VOICE_PREVIOUS) +#define IS_STENO_KEYCODE(code) ((code) >= QK_STENO_BOLT && (code) <= QK_STENO_COMB_MAX) +#define IS_MACRO_KEYCODE(code) ((code) >= QK_MACRO_0 && (code) <= QK_MACRO_31) +#define IS_BACKLIGHT_KEYCODE(code) ((code) >= QK_BACKLIGHT_ON && (code) <= QK_BACKLIGHT_TOGGLE_BREATHING) +#define IS_RGB_KEYCODE(code) ((code) >= RGB_TOG && (code) <= RGB_MODE_TWINKLE) +#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_ALT_REPEAT_KEY) +#define IS_KB_KEYCODE(code) ((code) >= QK_KB_0 && (code) <= QK_KB_31) +#define IS_USER_KEYCODE(code) ((code) >= QK_USER_0 && (code) <= QK_USER_31) + +// Switch statement Helpers +#define INTERNAL_KEYCODE_RANGE KC_NO ... KC_TRANSPARENT +#define BASIC_KEYCODE_RANGE KC_A ... KC_EXSEL +#define SYSTEM_KEYCODE_RANGE KC_SYSTEM_POWER ... KC_SYSTEM_WAKE +#define CONSUMER_KEYCODE_RANGE KC_AUDIO_MUTE ... KC_LAUNCHPAD +#define MOUSE_KEYCODE_RANGE KC_MS_UP ... KC_MS_ACCEL2 +#define MODIFIER_KEYCODE_RANGE KC_LEFT_CTRL ... KC_RIGHT_GUI +#define SWAP_HANDS_KEYCODE_RANGE QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT +#define MAGIC_KEYCODE_RANGE QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK +#define MIDI_KEYCODE_RANGE QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP +#define SEQUENCER_KEYCODE_RANGE QK_SEQUENCER_ON ... QK_SEQUENCER_STEPS_CLEAR +#define JOYSTICK_KEYCODE_RANGE QK_JOYSTICK_BUTTON_0 ... QK_JOYSTICK_BUTTON_31 +#define PROGRAMMABLE_BUTTON_KEYCODE_RANGE QK_PROGRAMMABLE_BUTTON_1 ... QK_PROGRAMMABLE_BUTTON_32 +#define AUDIO_KEYCODE_RANGE QK_AUDIO_ON ... QK_AUDIO_VOICE_PREVIOUS +#define STENO_KEYCODE_RANGE QK_STENO_BOLT ... QK_STENO_COMB_MAX +#define MACRO_KEYCODE_RANGE QK_MACRO_0 ... QK_MACRO_31 +#define BACKLIGHT_KEYCODE_RANGE QK_BACKLIGHT_ON ... QK_BACKLIGHT_TOGGLE_BREATHING +#define RGB_KEYCODE_RANGE RGB_TOG ... RGB_MODE_TWINKLE +#define QUANTUM_KEYCODE_RANGE QK_BOOTLOADER ... QK_ALT_REPEAT_KEY +#define KB_KEYCODE_RANGE QK_KB_0 ... QK_KB_31 +#define USER_KEYCODE_RANGE QK_USER_0 ... QK_USER_31 + +/* Consumer Page (0x0C) + * + * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=75 + */ +enum consumer_usages { + // 15.5 Display Controls + SNAPSHOT = 0x065, + BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf + BRIGHTNESS_DOWN = 0x070, + // 15.7 Transport Controls + TRANSPORT_RECORD = 0x0B2, + TRANSPORT_FAST_FORWARD = 0x0B3, + TRANSPORT_REWIND = 0x0B4, + TRANSPORT_NEXT_TRACK = 0x0B5, + TRANSPORT_PREV_TRACK = 0x0B6, + TRANSPORT_STOP = 0x0B7, + TRANSPORT_EJECT = 0x0B8, + TRANSPORT_RANDOM_PLAY = 0x0B9, + TRANSPORT_STOP_EJECT = 0x0CC, + TRANSPORT_PLAY_PAUSE = 0x0CD, + // 15.9.1 Audio Controls - Volume + AUDIO_MUTE = 0x0E2, + AUDIO_VOL_UP = 0x0E9, + AUDIO_VOL_DOWN = 0x0EA, + // 15.15 Application Launch Buttons + AL_CC_CONFIG = 0x183, + AL_EMAIL = 0x18A, + AL_CALCULATOR = 0x192, + AL_LOCAL_BROWSER = 0x194, + AL_LOCK = 0x19E, + AL_CONTROL_PANEL = 0x19F, + AL_ASSISTANT = 0x1CB, + AL_KEYBOARD_LAYOUT = 0x1AE, + // 15.16 Generic GUI Application Controls + AC_NEW = 0x201, + AC_OPEN = 0x202, + AC_CLOSE = 0x203, + AC_EXIT = 0x204, + AC_MAXIMIZE = 0x205, + AC_MINIMIZE = 0x206, + AC_SAVE = 0x207, + AC_PRINT = 0x208, + AC_PROPERTIES = 0x209, + AC_UNDO = 0x21A, + AC_COPY = 0x21B, + AC_CUT = 0x21C, + AC_PASTE = 0x21D, + AC_SELECT_ALL = 0x21E, + AC_FIND = 0x21F, + AC_SEARCH = 0x221, + AC_HOME = 0x223, + AC_BACK = 0x224, + AC_FORWARD = 0x225, + AC_STOP = 0x226, + AC_REFRESH = 0x227, + AC_BOOKMARKS = 0x22A, + AC_NEXT_KEYBOARD_LAYOUT_SELECT = 0x29D, + AC_DESKTOP_SHOW_ALL_WINDOWS = 0x29F, + AC_SOFT_KEY_LEFT = 0x2A0 +}; + +/* Generic Desktop Page (0x01) + * + * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=26 + */ +enum desktop_usages { + // 4.5.1 System Controls - Power Controls + SYSTEM_POWER_DOWN = 0x81, + SYSTEM_SLEEP_0 = 0x82, + SYSTEM_WAKE_UP_0 = 0x83, + SYSTEM_RESTART = 0x8F, + // 4.10 System Display Controls + SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5 +}; diff --git a/app/src/launcher/keymap_japanese.h b/app/src/launcher/keymap_japanese.h new file mode 100644 index 00000000000..947317833ed --- /dev/null +++ b/app/src/launcher/keymap_japanese.h @@ -0,0 +1,106 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +/******************************************************************************* + 88888888888 888 d8b .d888 d8b 888 d8b + 888 888 Y8P d88P" Y8P 888 Y8P + 888 888 888 888 + 888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b + 888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K + 888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b. + 888 888 888 888 X88 888 888 888 Y8b. 888 X88 + 888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P' + 888 888 + 888 888 + 888 888 + .d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888 + d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888 + 888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888 + Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888 + "Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888 + 888 + Y8b d88P + "Y88P" +*******************************************************************************/ + +#pragma once +#include "keycodes.h" +// clang-format off + +// Aliases +#define JP_ZKHK KC_GRV // Zenkaku ↔ Hankaku ↔ Kanji (半角 ↔ 全角 ↔ 漢字) +#define JP_1 KC_1 // 1 +#define JP_2 KC_2 // 2 +#define JP_3 KC_3 // 3 +#define JP_4 KC_4 // 4 +#define JP_5 KC_5 // 5 +#define JP_6 KC_6 // 6 +#define JP_7 KC_7 // 7 +#define JP_8 KC_8 // 8 +#define JP_9 KC_9 // 9 +#define JP_0 KC_0 // 0 +#define JP_MINS KC_MINS // - +#define JP_CIRC KC_EQL // ^ +#define JP_YEN KC_INT3 // ¥ +#define JP_Q KC_Q // Q +#define JP_W KC_W // W +#define JP_E KC_E // E +#define JP_R KC_R // R +#define JP_T KC_T // T +#define JP_Y KC_Y // Y +#define JP_U KC_U // U +#define JP_I KC_I // I +#define JP_O KC_O // O +#define JP_P KC_P // P +#define JP_AT KC_LBRC // @ +#define JP_LBRC KC_RBRC // [ +#define JP_EISU KC_CAPS // Eisū (英数) +#define JP_A KC_A // A +#define JP_S KC_S // S +#define JP_D KC_D // D +#define JP_F KC_F // F +#define JP_G KC_G // G +#define JP_H KC_H // H +#define JP_J KC_J // J +#define JP_K KC_K // K +#define JP_L KC_L // L +#define JP_SCLN KC_SCLN // ; +#define JP_COLN KC_QUOT // : +#define JP_RBRC KC_NUHS // ] +#define JP_Z KC_Z // Z +#define JP_X KC_X // X +#define JP_C KC_C // C +#define JP_V KC_V // V +#define JP_B KC_B // B +#define JP_N KC_N // N +#define JP_M KC_M // M +#define JP_COMM KC_COMM // , +#define JP_DOT KC_DOT // . +#define JP_SLSH KC_SLSH // / +#define JP_BSLS KC_INT1 // (backslash) +#define JP_MHEN KC_INT5 // Muhenkan (無変換) +#define JP_HENK KC_INT4 // Henkan (変換) +#define JP_KANA KC_INT2 // Katakana ↔ Hiragana ↔ Rōmaji (カタカナ ↔ ひらがな ↔ ローマ字) +#define JP_EXLM S(JP_1) // ! +#define JP_DQUO S(JP_2) // " +#define JP_HASH S(JP_3) // # +#define JP_DLR S(JP_4) // $ +#define JP_PERC S(JP_5) // % +#define JP_AMPR S(JP_6) // & +#define JP_QUOT S(JP_7) // ' +#define JP_LPRN S(JP_8) // ( +#define JP_RPRN S(JP_9) // ) +#define JP_EQL S(JP_MINS) // = +#define JP_TILD S(JP_CIRC) // ~ +#define JP_PIPE S(JP_YEN) // | +#define JP_GRV S(JP_AT) // ` +#define JP_LCBR S(JP_LBRC) // { +#define JP_CAPS S(JP_EISU) // Caps Lock +#define JP_PLUS S(JP_SCLN) // + +#define JP_ASTR S(JP_COLN) // * +#define JP_RCBR S(JP_RBRC) // } +#define JP_LABK S(JP_COMM) // < +#define JP_RABK S(JP_DOT) // > +#define JP_QUES S(JP_SLSH) // ? +#define JP_UNDS S(JP_BSLS) // _ + diff --git a/app/src/launcher/launcher.c b/app/src/launcher/launcher.c new file mode 100644 index 00000000000..1825f58777c --- /dev/null +++ b/app/src/launcher/launcher.c @@ -0,0 +1,1527 @@ + +#include "../version.h" +#include "launcher.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include "keycodes.h" +#include "dynamic_keymap.h" +#include +#include +#include +#if (CONFIG_SHIELD_KEYCHRON_B6_JIS||CONFIG_SHIELD_KEYCHRON_B1_JIS ||CONFIG_SHIELD_KEYCHRON_B2_JIS) +//for jis layout! +#include "sendstring_japanese.h" +#endif + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +enum { + VIA_PATH_USB, + VIA_PATH_BLE, + VIA_PATH_24G, +}; +static uint8_t via_path; + +void via_set_path(uint8_t path) +{ + via_path = path; +} +void user_set_debounce(uint32_t scan_period_ms,uint32_t debounce_press_ms,uint32_t debounce_release_ms); + +uint8_t zmk_keymap_highest_layer_active(); + +int zmk_24g_send_via_report(uint8_t *payload,uint8_t payload_len); +static uint8_t report_os_sw_state; +void factory_test_rx(uint8_t *data, uint8_t length); +K_MSGQ_DEFINE(via_usb_msgq, 32,16, 4); +void via_usb_worker(struct k_work *work); +K_WORK_DEFINE(via_usb_work, via_usb_worker); + +static const struct device *hid_via_dev; + +static K_SEM_DEFINE(hid_via_sem, 1, 1); + +void via_usb_worker(struct k_work *work) +{ + uint8_t usb_data[32]; + while (k_msgq_get(&via_usb_msgq, usb_data, K_NO_WAIT) == 0) { + raw_hid_receive(usb_data,sizeof(usb_data)); + } +} + +static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_via_sem); } + +static void out_ready_cb(const struct device *dev) +{ + uint8_t rev_buf[32]={0}; + uint32_t rev_bytes =0; + hid_int_ep_read(dev,rev_buf,sizeof(rev_buf),&rev_bytes); + LOG_HEXDUMP_DBG(rev_buf,8,"rx"); + // raw_hid_receive(rev_buf,rev_bytes); + uint16_t hdr = (rev_buf[0]<<8) | rev_buf[1]; + if(hdr == 0xaa55 || hdr== 0xaa56) + { + void my_scdfu_data_handle(unsigned char *pdata,unsigned char rxlen); + return my_scdfu_data_handle(&rev_buf[0],rev_bytes); + } + via_path = VIA_PATH_USB; + int err = k_msgq_put(&via_usb_msgq, rev_buf, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("queue full"); + uint8_t buf[32]; + k_msgq_get(&via_usb_msgq, buf, K_NO_WAIT); + k_msgq_put(&via_usb_msgq, rev_buf, K_MSEC(100)); + } + default: + LOG_WRN("Failed to queue via data (%d)", err); + } + } + + err = k_work_submit(&via_usb_work); +} + +static const struct hid_ops ops = { + .int_in_ready = in_ready_cb, + .int_out_ready = out_ready_cb, +}; + +int zmk_usb_hid_via_send(const uint8_t *report, size_t len) { + switch (zmk_usb_get_status()) { + + case USB_DC_ERROR: + case USB_DC_RESET: + case USB_DC_DISCONNECTED: + case USB_DC_UNKNOWN: + return -ENODEV; + case USB_DC_SUSPEND: + usb_wakeup_request(); + k_msleep(20); + default: + k_sem_take(&hid_via_sem, K_MSEC(10)); + LOG_HEXDUMP_DBG(report,8,"usb"); + int err = hid_int_ep_write(hid_via_dev, report, len, NULL); + + if (err!=0) { + LOG_ERR("write err:%d",err); + // k_sem_give(&hid_via_sem); + } + + return err; + } +} + +static int zmk_usb_hid_via_init(const struct device *_arg) { + hid_via_dev = device_get_binding("HID_1"); + if (hid_via_dev == NULL) { + LOG_ERR("Unable to locate HID device"); + return -EINVAL; + } + + usb_hid_register_device(hid_via_dev, zmk_hid_via_report_desc, sizeof(zmk_hid_via_report_desc), &ops); + usb_hid_init(hid_via_dev); + via_init(); + return 0; +} + +SYS_INIT(zmk_usb_hid_via_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); + +_via_ee_device via_ee_device; + +static struct user_debounce debouce; + +struct direct_immediate_value { + size_t len; + void *dest; + uint8_t fetched; +}; +static int direct_loader_immediate_value(const char *name, size_t len, + settings_read_cb read_cb, void *cb_arg, + void *param) +{ + const char *next; + size_t name_len; + int rc; + struct direct_immediate_value *one_value = + (struct direct_immediate_value *)param; + + name_len = settings_name_next(name, &next); + + if (name_len == 0) { + if (len == one_value->len) { + rc = read_cb(cb_arg, one_value->dest, len); + if (rc >= 0) { + one_value->fetched = 1; + LOG_DBG("immediate load: OK.\n"); + return 0; + } + + LOG_DBG("err:%d", rc); + return rc; + } + return -EINVAL; + } + + /* other keys aren't served by the callback + * Return success in order to skip them + * and keep storage processing. + */ + return 0; +} + +int load_immediate_value(const char *name, void *dest, size_t len) +{ + int rc; + struct direct_immediate_value dov; + + dov.fetched = 0; + dov.len = len; + dov.dest = dest; + + rc = settings_load_subtree_direct(name, direct_loader_immediate_value, + (void *)&dov); + if (rc == 0) { + if (!dov.fetched) { + rc = -ENOENT; + } + } + + return rc; +} +void via_ee_delete(void) +{ + LOG_DBG("."); + settings_delete("via_ee/magic"); + settings_delete("via_ee/layout"); + settings_delete("via_ee/custom"); + // settings_delete("via_ee/keymaps"); + settings_delete("via_ee/encoder"); + settings_delete("via_ee/macros/len"); + settings_delete("via_ee/macros/datas"); + settings_delete("via_ee/debounce"); + // settings_delete("via_ee/changed"); + char setting_name[20]={0}; + for(int i=0;i=DYNAMIC_KEYMAP_LAYER_COUNT) return; + int rc; + char setting_name[20]; + sprintf(setting_name,"via_ee/keymaps/%d",i); + rc = settings_save_one(setting_name, &via_ee_device.keymaps[i*KEYMAP_LEN], KEYMAP_LEN); + if (rc) { + LOG_DBG("write failed:%d", rc); + } else { + LOG_DBG("OK.\n"); + } + + // via_ee_update_changed_keys(i); +} +void via_ee_read_keymap(uint8_t layer) +{ + if(layer >=DYNAMIC_KEYMAP_LAYER_COUNT) return; + int rc; + char setting_name[20]; + sprintf(setting_name,"via_ee/keymaps/%d",layer); + LOG_HEXDUMP_DBG(&via_ee_device.keymaps[layer*KEYMAP_LEN],32,"keymap"); + rc = load_immediate_value(setting_name, &via_ee_device.keymaps[layer*KEYMAP_LEN], KEYMAP_LEN); + if (rc == -ENOENT) { + LOG_DBG("via_ee/keymaps/%d:%02x (default)\n",layer,via_ee_device.keymaps[layer*KEYMAP_LEN]); + } else if (rc == 0) { + LOG_HEXDUMP_DBG(&via_ee_device.keymaps[layer*KEYMAP_LEN],32,"store keymap"); + + for (int row = 0; row < MATRIX_ROWS; row++) { + for (int column = 0; column < MATRIX_COLS; column++) { + uint16_t keycode=(via_ee_device.keymaps[layer * KEYMAP_LEN+row*MATRIX_COLS*2+ column*2]<<8) +via_ee_device.keymaps[layer * KEYMAP_LEN+row*MATRIX_COLS*2+ column*2+1]; + if(keycode !=keycode_at_keymap_location_raw(layer, row, column)) + { + LOG_DBG("set layer:%d,row:%d,column:%d,keycode:%x",layer,row,column,keycode); + set_zmk_keymap(layer,row,column,keycode); + } + } + } + } +} + +void via_ee_read_keymaps(void) +{ + for(int i=0;i=0;i--) + { + if(via_ee_device.macros[i]!=0) + break; + } + return i+1; +} +void via_ee_update_macros(void) +{ + int rc; + int len =check_macros_len(); + LOG_DBG("macros len:%d",len); + if(len >0) + { + rc = settings_save_one("via_ee/macros/len", (const void *)&len, sizeof(len)); + if (rc) { + LOG_DBG("write failed:%d", rc); + } else { + LOG_DBG("OK.\n"); + } + rc = settings_save_one("via_ee/macros/datas", (const void *)&via_ee_device.macros[0], len); + if (rc) { + LOG_DBG("write failed:%d", rc); + } else { + LOG_DBG("OK.\n"); + } + } +} +void via_ee_delete_macros(void) +{ + LOG_DBG("."); + settings_delete("via_ee/macros/len"); + settings_delete("via_ee/macros/datas"); +} +void via_ee_read_macros(void) +{ + int rc; + int len=0; + rc=load_immediate_value("via_ee/macros/len", &len, sizeof(len)); + if (rc == -ENOENT) { + LOG_DBG("via_ee/macros/len:%02x (default)\n",len); + memset(&via_ee_device.macros,0,sizeof(via_ee_device.macros)); + } else if (rc == 0) { + LOG_DBG("via_ee/macros/len:%02x \n",len); + } + + if(len >0) + { + rc=load_immediate_value("via_ee/macros/datas", &via_ee_device.macros[0], len); + if (rc == -ENOENT) { + + LOG_DBG("via_ee/macros/data:%02x (default)\n",len); + } else if (rc == 0) { + + LOG_HEXDUMP_DBG(&via_ee_device.macros[0],32,"macros"); + } + } +} +// void via_ee_read_changed_keys(void) +// { +// int rc; + +// char setting_name[20]={0}; +// for(int i=0;i=DYNAMIC_KEYMAP_LAYER_COUNT) return; +// int rc; +// char setting_name[20]={0}; +// sprintf(setting_name,"via_ee/changed/%d",layer); +// rc = settings_save_one(setting_name, &via_ee_device.changed_keys[layer], 20); +// if (rc) { +// LOG_DBG("write failed:%d", rc); +// } else { +// LOG_DBG("OK.\n"); +// } +// } +// void via_set_changed_key(uint8_t layer,uint8_t row,uint8_t col) +// { +// uint8_t index = row*MATRIX_COLS +col; +// uint8_t pos = index/8; +// uint8_t bits = 1<<(index %8); +// via_ee_device.changed_keys[layer][pos] |= bits; +// LOG_DBG("layer:%d,row:%d,col:%d,pos:%d,bits:%x",layer,row,col,pos,bits); +// } +// void via_ee_reset_changed_keys(void) +// { +// // settings_delete("via_ee/changed"); +// char setting_name[20]={0}; +// for(int i=0;i> 8; + target--; + } + via_ee_update_layout(); +} + +#if defined(AUDIO_ENABLE) +float via_device_indication_song[][2] = SONG(STARTUP_SOUND); +#endif // AUDIO_ENABLE + +// Used by VIA to tell a device to flash LEDs (or do something else) when that +// device becomes the active device being configured, on startup or switching +// between devices. This function will be called six times, at 200ms interval, +// with an incrementing value starting at zero. Since this function is called +// an even number of times, it can call a toggle function and leave things in +// the original state. +__attribute__((weak)) void via_set_device_indication(uint8_t value) { +#if defined(BACKLIGHT_ENABLE) + backlight_toggle(); +#endif // BACKLIGHT_ENABLE +#if defined(RGBLIGHT_ENABLE) + rgblight_toggle_noeeprom(); +#endif // RGBLIGHT_ENABLE +#if defined(RGB_MATRIX_ENABLE) + rgb_matrix_toggle_noeeprom(); +#endif // RGB_MATRIX_ENABLE +#if defined(LED_MATRIX_ENABLE) + led_matrix_toggle_noeeprom(); +#endif // LED_MATRIX_ENABLE +#if defined(AUDIO_ENABLE) + if (value == 0) { + wait_ms(10); + PLAY_SONG(via_device_indication_song); + } +#endif // AUDIO_ENABLE +} + +// Called by QMK core to process VIA-specific keycodes. +// bool process_record_via(uint16_t keycode, keyrecord_t *record) { +// // Handle macros +// if (record->event.pressed) { +// if (keycode >= QK_MACRO && keycode <= QK_MACRO_MAX) { +// uint8_t id = keycode - QK_MACRO; +// dynamic_keymap_macro_send(id); +// return false; +// } +// } + +// return true; +// } + +// +// via_custom_value_command() has the default handling of custom values for Core modules. +// If a keyboard is using the default Core modules, it does not need to be overridden, +// the VIA keyboard definition will have matching channel/IDs. +// +// If a keyboard has some extra custom values, then via_custom_value_command_kb() can be +// overridden to handle the extra custom values, leaving via_custom_value_command() to +// handle the custom values for Core modules. +// +// If a keyboard has custom values and code that are overlapping with Core modules, +// then via_custom_value_command() can be overridden and call the same functions +// as the default implementation, or do whatever else is required. +// +// DO NOT call raw_hid_send() in the override function. +// + +// This is the default handler for "extra" custom values, i.e. keyboard-specific custom values +// that are not handled by via_custom_value_command(). +__attribute__((weak)) void via_custom_value_command_kb(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + // Return the unhandled state + *command_id = id_unhandled; +} + +// This is the default handler for custom value commands. +// It routes commands with channel IDs to command handlers as such: +// +// id_qmk_backlight_channel -> via_qmk_backlight_command() +// id_qmk_rgblight_channel -> via_qmk_rgblight_command() +// id_qmk_rgb_matrix_channel -> via_qmk_rgb_matrix_command() +// id_qmk_led_matrix_channel -> via_qmk_led_matrix_command() +// id_qmk_audio_channel -> via_qmk_audio_command() +// +__attribute__((weak)) void via_custom_value_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *channel_id = &(data[1]); + +#if defined(BACKLIGHT_ENABLE) + if (*channel_id == id_qmk_backlight_channel) { + via_qmk_backlight_command(data, length); + return; + } +#endif // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) + if (*channel_id == id_qmk_rgblight_channel) { + via_qmk_rgblight_command(data, length); + return; + } +#endif // RGBLIGHT_ENABLE + +#if defined(RGB_MATRIX_ENABLE) + if (*channel_id == id_qmk_rgb_matrix_channel) { + via_qmk_rgb_matrix_command(data, length); + return; + } +#endif // RGB_MATRIX_ENABLE + +#if defined(LED_MATRIX_ENABLE) + if (*channel_id == id_qmk_led_matrix_channel) { + via_qmk_led_matrix_command(data, length); + return; + } +#endif // LED_MATRIX_ENABLE + +#if defined(AUDIO_ENABLE) + if (*channel_id == id_qmk_audio_channel) { + via_qmk_audio_command(data, length); + return; + } +#endif // AUDIO_ENABLE + + (void)channel_id; // force use of variable + + // If we haven't returned before here, then let the keyboard level code + // handle this, if it is overridden, otherwise by default, this will + // return the unhandled state. + via_custom_value_command_kb(data, length); +} + +// Keyboard level code can override this, but shouldn't need to. +// Controlling custom features should be done by overriding +// via_custom_value_command_kb() instead. +__attribute__((weak)) bool via_command_kb(uint8_t *data, uint8_t length) { + return false; +} + +void raw_hid_receive(uint8_t *data, uint8_t length) { + uint8_t *command_id = &(data[0]); + uint8_t *command_data = &(data[1]); + + // If via_command_kb() returns true, the command was fully + // handled, including calling raw_hid_send() + if (via_command_kb(data, length)) { + return; + } + + switch (*command_id) { + case id_bootloader_jump: + sys_reboot(0x4e); + break; + case kc_get_protocol_version: + command_data[0]=1; + break; + case kc_get_default_layer: + command_data[0]=zmk_keymap_highest_layer_active(); + break; + case kc_get_firmware_version: + // uint32_t value = ZMK_VERSION; + // command_data[1] = (value >> 24) & 0xFF; + // command_data[2] = (value >> 16) & 0xFF; + // command_data[3] = (value >> 8) & 0xFF; + // command_data[4] = value & 0xFF; + uint8_t offset =0; + uint8_t len =strlen(APP_VERSION_STRING); + memcpy(&command_data[offset],APP_VERSION_STRING,len); + + offset += len; + command_data[offset++] =' '; + len =strlen(__DATE__); + memcpy(&command_data[offset],__DATE__,len); + + offset += len; + command_data[offset++] =' '; + + len =strlen(__TIME__); + memcpy(&command_data[offset],__TIME__,len); + + break; + + case id_get_protocol_version: { + command_data[0] = VIA_PROTOCOL_VERSION >> 8; + command_data[1] = VIA_PROTOCOL_VERSION & 0xFF; + break; + } + case id_get_keyboard_value: { + switch (command_data[0]) { + case id_uptime: { + uint32_t value = k_uptime_get();//timer_read32(); + command_data[1] = (value >> 24) & 0xFF; + command_data[2] = (value >> 16) & 0xFF; + command_data[3] = (value >> 8) & 0xFF; + command_data[4] = value & 0xFF; + break; + } + case id_layout_options: { + uint32_t value = via_get_layout_options(); + command_data[1] = (value >> 24) & 0xFF; + command_data[2] = (value >> 16) & 0xFF; + command_data[3] = (value >> 8) & 0xFF; + command_data[4] = value & 0xFF; + break; + } + case id_switch_matrix_state: { + uint8_t offset = command_data[1]; + uint8_t rows = 28 / ((MATRIX_COLS + 7) / 8); + uint8_t i = 2; + for (uint8_t row = 0; row < rows && row + offset < MATRIX_ROWS; row++) { + matrix_row_t value = matrix_get_row(row + offset); +#if (MATRIX_COLS > 24) + command_data[i++] = (value >> 24) & 0xFF; +#endif +#if (MATRIX_COLS > 16) + command_data[i++] = (value >> 16) & 0xFF; +#endif +#if (MATRIX_COLS > 8) + command_data[i++] = (value >> 8) & 0xFF; +#endif + command_data[i++] = value & 0xFF; + } + break; + } + case id_firmware_version: { + uint32_t value = VIA_FIRMWARE_VERSION; + command_data[1] = (value >> 24) & 0xFF; + command_data[2] = (value >> 16) & 0xFF; + command_data[3] = (value >> 8) & 0xFF; + command_data[4] = value & 0xFF; + break; + } + default: { + // The value ID is not known + // Return the unhandled state + *command_id = id_unhandled; + break; + } + } + break; + } + case id_set_keyboard_value: { + switch (command_data[0]) { + case id_layout_options: { + uint32_t value = ((uint32_t)command_data[1] << 24) | ((uint32_t)command_data[2] << 16) | ((uint32_t)command_data[3] << 8) | (uint32_t)command_data[4]; + via_set_layout_options(value); + break; + } + case id_device_indication: { + uint8_t value = command_data[1]; + via_set_device_indication(value); + break; + } + default: { + // The value ID is not known + // Return the unhandled state + *command_id = id_unhandled; + break; + } + } + break; + } + case id_dynamic_keymap_get_keycode: { + uint16_t keycode = dynamic_keymap_get_keycode(command_data[0], command_data[1], command_data[2]); + command_data[3] = keycode >> 8; + command_data[4] = keycode & 0xFF; + break; + } + case id_dynamic_keymap_set_keycode: { + dynamic_keymap_set_keycode(command_data[0], command_data[1], command_data[2], (command_data[3] << 8) | command_data[4]); + break; + } + case id_dynamic_keymap_reset: { + dynamic_keymap_reset(true); + + break; + } + case id_custom_set_value: + case id_custom_get_value: + case id_custom_save: { + via_custom_value_command(data, length); + break; + } +#ifdef VIA_EEPROM_ALLOW_RESET + case id_eeprom_reset: { + via_eeprom_set_valid(false); + eeconfig_init_via(); + break; + } +#endif + case id_dynamic_keymap_macro_get_count: { + command_data[0] = dynamic_keymap_macro_get_count(); + break; + } + case id_dynamic_keymap_macro_get_buffer_size: { + uint16_t size = dynamic_keymap_macro_get_buffer_size(); + command_data[0] = size >> 8; + command_data[1] = size & 0xFF; + break; + } + case id_dynamic_keymap_macro_get_buffer: { + uint16_t offset = (command_data[0] << 8) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_macro_get_buffer(offset, size, &command_data[3]); + break; + } + case id_dynamic_keymap_macro_set_buffer: { + uint16_t offset = (command_data[0] << 8) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_macro_set_buffer(offset, size, &command_data[3]); + break; + } + case id_dynamic_keymap_macro_reset: { + dynamic_keymap_macro_reset(true); + break; + } + case id_dynamic_keymap_get_layer_count: { + command_data[0] = dynamic_keymap_get_layer_count(); + break; + } + case id_dynamic_keymap_get_buffer: { + uint16_t offset = (command_data[0] << 8) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_get_buffer(offset, size, &command_data[3]); + break; + } + case id_dynamic_keymap_set_buffer: { + uint16_t offset = (command_data[0] << 8) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_set_buffer(offset, size, &command_data[3]); + break; + } +#ifdef ENCODER_MAP_ENABLE + case id_dynamic_keymap_get_encoder: { + uint16_t keycode = dynamic_keymap_get_encoder(command_data[0], command_data[1], command_data[2] != 0); + command_data[3] = keycode >> 8; + command_data[4] = keycode & 0xFF; + break; + } + case id_dynamic_keymap_set_encoder: { + dynamic_keymap_set_encoder(command_data[0], command_data[1], command_data[2] != 0, (command_data[3] << 8) | command_data[4]); + break; + } +#endif + case 0xAB: + factory_test_rx(data, length); + break; + + case kc_set_key_debounce: + if(command_data[0]==0 || command_data[1]==0 ||command_data[2] ==0) + { + break; + } + user_set_debounce(command_data[0],command_data[1],command_data[2]); + debouce.scan_period_ms =command_data[0]; + debouce.debounce_press_ms = command_data[1]; + debouce.debounce_release_ms = command_data[2]; + via_save_debounce(); + break; + case kc_get_key_debounce: + command_data[0] =debouce.scan_period_ms; + command_data[1] =debouce.debounce_press_ms; + command_data[2] =debouce.debounce_release_ms; + break; + default: { + // The command ID is not known + // Return the unhandled state + *command_id = id_unhandled; + break; + } + } + + // Return the same buffer, optionally with values changed + // (i.e. returning state to the host, or the unhandled state). + raw_hid_send(data, length); +} + +#if defined(BACKLIGHT_ENABLE) + +void via_qmk_backlight_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + uint8_t *value_id_and_data = &(data[2]); + + switch (*command_id) { + case id_custom_set_value: { + via_qmk_backlight_set_value(value_id_and_data); + break; + } + case id_custom_get_value: { + via_qmk_backlight_get_value(value_id_and_data); + break; + } + case id_custom_save: { + via_qmk_backlight_save(); + break; + } + default: { + *command_id = id_unhandled; + break; + } + } +} + +# if BACKLIGHT_LEVELS == 0 +# error BACKLIGHT_LEVELS == 0 +# endif + +void via_qmk_backlight_get_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_backlight_brightness: { + // level / BACKLIGHT_LEVELS * 255 + value_data[0] = ((uint16_t)get_backlight_level() * UINT8_MAX) / BACKLIGHT_LEVELS; + break; + } + case id_qmk_backlight_effect: { +# ifdef BACKLIGHT_BREATHING + value_data[0] = is_backlight_breathing() ? 1 : 0; +# else + value_data[0] = 0; +# endif + break; + } + } +} + +void via_qmk_backlight_set_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_backlight_brightness: { + // level / 255 * BACKLIGHT_LEVELS + backlight_level_noeeprom(((uint16_t)value_data[0] * BACKLIGHT_LEVELS) / UINT8_MAX); + break; + } + case id_qmk_backlight_effect: { +# ifdef BACKLIGHT_BREATHING + if (value_data[0] == 0) { + backlight_disable_breathing(); + } else { + backlight_enable_breathing(); + } +# endif + break; + } + } +} + +void via_qmk_backlight_save(void) { + eeconfig_update_backlight_current(); +} + +#endif // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) +# ifndef RGBLIGHT_LIMIT_VAL +# define RGBLIGHT_LIMIT_VAL 255 +# endif + +void via_qmk_rgblight_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + uint8_t *value_id_and_data = &(data[2]); + + switch (*command_id) { + case id_custom_set_value: { + via_qmk_rgblight_set_value(value_id_and_data); + break; + } + case id_custom_get_value: { + via_qmk_rgblight_get_value(value_id_and_data); + break; + } + case id_custom_save: { + via_qmk_rgblight_save(); + break; + } + default: { + *command_id = id_unhandled; + break; + } + } +} + +void via_qmk_rgblight_get_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_rgblight_brightness: { + value_data[0] = ((uint16_t)rgblight_get_val() * UINT8_MAX) / RGBLIGHT_LIMIT_VAL; + break; + } + case id_qmk_rgblight_effect: { + value_data[0] = rgblight_is_enabled() ? rgblight_get_mode() : 0; + break; + } + case id_qmk_rgblight_effect_speed: { + value_data[0] = rgblight_get_speed(); + break; + } + case id_qmk_rgblight_color: { + value_data[0] = rgblight_get_hue(); + value_data[1] = rgblight_get_sat(); + break; + } + } +} + +void via_qmk_rgblight_set_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_rgblight_brightness: { + rgblight_sethsv_noeeprom(rgblight_get_hue(), rgblight_get_sat(), ((uint16_t)value_data[0] * RGBLIGHT_LIMIT_VAL) / UINT8_MAX); + break; + } + case id_qmk_rgblight_effect: { + if (value_data[0] == 0) { + rgblight_disable_noeeprom(); + } else { + rgblight_enable_noeeprom(); + rgblight_mode_noeeprom(value_data[0]); + } + break; + } + case id_qmk_rgblight_effect_speed: { + rgblight_set_speed_noeeprom(value_data[0]); + break; + } + case id_qmk_rgblight_color: { + rgblight_sethsv_noeeprom(value_data[0], value_data[1], rgblight_get_val()); + break; + } + } +} + +void via_qmk_rgblight_save(void) { + eeconfig_update_rgblight_current(); +} + +#endif // QMK_RGBLIGHT_ENABLE + +#if defined(RGB_MATRIX_ENABLE) + +void via_qmk_rgb_matrix_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + uint8_t *value_id_and_data = &(data[2]); + + switch (*command_id) { + case id_custom_set_value: { + via_qmk_rgb_matrix_set_value(value_id_and_data); + break; + } + case id_custom_get_value: { + via_qmk_rgb_matrix_get_value(value_id_and_data); + break; + } + case id_custom_save: { + via_qmk_rgb_matrix_save(); + break; + } + default: { + *command_id = id_unhandled; + break; + } + } +} + +void via_qmk_rgb_matrix_get_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + + switch (*value_id) { + case id_qmk_rgb_matrix_brightness: { + value_data[0] = ((uint16_t)rgb_matrix_get_val() * UINT8_MAX) / RGB_MATRIX_MAXIMUM_BRIGHTNESS; + break; + } + case id_qmk_rgb_matrix_effect: { + value_data[0] = rgb_matrix_is_enabled() ? rgb_matrix_get_mode() : 0; + break; + } + case id_qmk_rgb_matrix_effect_speed: { + value_data[0] = rgb_matrix_get_speed(); + break; + } + case id_qmk_rgb_matrix_color: { + value_data[0] = rgb_matrix_get_hue(); + value_data[1] = rgb_matrix_get_sat(); + break; + } + } +} + +void via_qmk_rgb_matrix_set_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_rgb_matrix_brightness: { + rgb_matrix_sethsv_noeeprom(rgb_matrix_get_hue(), rgb_matrix_get_sat(), scale8(value_data[0], RGB_MATRIX_MAXIMUM_BRIGHTNESS)); + break; + } + case id_qmk_rgb_matrix_effect: { + if (value_data[0] == 0) { + rgb_matrix_disable_noeeprom(); + } else { + rgb_matrix_enable_noeeprom(); + rgb_matrix_mode_noeeprom(value_data[0]); + } + break; + } + case id_qmk_rgb_matrix_effect_speed: { + rgb_matrix_set_speed_noeeprom(value_data[0]); + break; + } + case id_qmk_rgb_matrix_color: { + rgb_matrix_sethsv_noeeprom(value_data[0], value_data[1], rgb_matrix_get_val()); + break; + } + } +} + +void via_qmk_rgb_matrix_save(void) { + eeconfig_update_rgb_matrix(); +} + +#endif // RGB_MATRIX_ENABLE + +#if defined(LED_MATRIX_ENABLE) + +void via_qmk_led_matrix_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + uint8_t *value_id_and_data = &(data[2]); + + switch (*command_id) { + case id_custom_set_value: { + via_qmk_led_matrix_set_value(value_id_and_data); + break; + } + case id_custom_get_value: { + via_qmk_led_matrix_get_value(value_id_and_data); + break; + } + case id_custom_save: { + via_qmk_led_matrix_save(); + break; + } + default: { + *command_id = id_unhandled; + break; + } + } +} + +void via_qmk_led_matrix_get_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + + switch (*value_id) { + case id_qmk_led_matrix_brightness: { + value_data[0] = ((uint16_t)led_matrix_get_val() * UINT8_MAX) / LED_MATRIX_MAXIMUM_BRIGHTNESS; + break; + } + case id_qmk_led_matrix_effect: { + value_data[0] = led_matrix_is_enabled() ? led_matrix_get_mode() : 0; + break; + } + case id_qmk_led_matrix_effect_speed: { + value_data[0] = led_matrix_get_speed(); + break; + } + } +} + +void via_qmk_led_matrix_set_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_led_matrix_brightness: { + led_matrix_set_val_noeeprom(scale8(value_data[0], LED_MATRIX_MAXIMUM_BRIGHTNESS)); + break; + } + case id_qmk_led_matrix_effect: { + if (value_data[0] == 0) { + led_matrix_disable_noeeprom(); + } else { + led_matrix_enable_noeeprom(); + led_matrix_mode_noeeprom(value_data[0]); + } + break; + } + case id_qmk_led_matrix_effect_speed: { + led_matrix_set_speed_noeeprom(value_data[0]); + break; + } + } +} + +void via_qmk_led_matrix_save(void) { + eeconfig_update_led_matrix(); +} + +#endif // LED_MATRIX_ENABLE + +#if defined(AUDIO_ENABLE) + +extern audio_config_t audio_config; + +void via_qmk_audio_command(uint8_t *data, uint8_t length) { + // data = [ command_id, channel_id, value_id, value_data ] + uint8_t *command_id = &(data[0]); + uint8_t *value_id_and_data = &(data[2]); + + switch (*command_id) { + case id_custom_set_value: { + via_qmk_audio_set_value(value_id_and_data); + break; + } + case id_custom_get_value: { + via_qmk_audio_get_value(value_id_and_data); + break; + } + case id_custom_save: { + via_qmk_audio_save(); + break; + } + default: { + *command_id = id_unhandled; + break; + } + } +} + +void via_qmk_audio_get_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_audio_enable: { + value_data[0] = audio_config.enable ? 1 : 0; + break; + } + case id_qmk_audio_clicky_enable: { + value_data[0] = audio_config.clicky_enable ? 1 : 0; + break; + } + } +} + +void via_qmk_audio_set_value(uint8_t *data) { + // data = [ value_id, value_data ] + uint8_t *value_id = &(data[0]); + uint8_t *value_data = &(data[1]); + switch (*value_id) { + case id_qmk_audio_enable: { + audio_config.enable = value_data[0] ? 1 : 0; + break; + } + case id_qmk_audio_clicky_enable: { + audio_config.clicky_enable = value_data[0] ? 1 : 0; + break; + } + } +} + +void via_qmk_audio_save(void) { + eeconfig_update_audio(audio_config.raw); +} + +#endif // QMK_AUDIO_ENABLE + +void factory_test_send(uint8_t *payload, uint8_t length) { + + uint16_t checksum = 0; + uint8_t data[RAW_EPSIZE] = {0}; + + uint8_t i = 0; + data[i++] = 0xAB; + + memcpy(&data[i], payload, length); + i += length; + + for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++) + checksum += data[i]; + data[RAW_EPSIZE - 2] = checksum & 0xFF; + data[RAW_EPSIZE - 1] = (checksum >> 8) & 0xFF; + + raw_hid_send(data, RAW_EPSIZE); + +} +enum { + FACTORY_TEST_CMD_BACKLIGHT = 0x01, + FACTORY_TEST_CMD_OS_SWITCH, + FACTORY_TEST_CMD_JUMP_TO_BL, + FACTORY_TEST_CMD_INT_PIN, + FACTORY_TEST_CMD_GET_TRANSPORT, + FACTORY_TEST_CMD_CHARGING_ADC, + FACTORY_TEST_CMD_RADIO_CARRIER, + FACTORY_TEST_CMD_GET_BUILD_TIME, +}; +enum { + OS_SWITCH = 0x01, +}; +void factory_test_rx(uint8_t *data, uint8_t length) { + if (data[0] == 0xAB) { + uint16_t checksum = 0; + + for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++) { + checksum += data[i]; + } + /* Verify checksum */ + if ((checksum & 0xFF) != data[RAW_EPSIZE - 2] || checksum >> 8 != data[RAW_EPSIZE - 1]) return; + + + + switch (data[1]) { + + case FACTORY_TEST_CMD_OS_SWITCH: + report_os_sw_state = data[2]; + if (report_os_sw_state) { + // dip_switch_read(true); + } + break; + + } + } +} + +bool dip_switch_update_user(uint8_t index, bool active) { + LOG_ERR("index:%d,active:%d",index,active); + if (report_os_sw_state) { + + uint8_t payload[3] = {FACTORY_TEST_CMD_OS_SWITCH, OS_SWITCH, active}; + factory_test_send(payload, 3); + } + + return true; +} + +void via_ee_read_debounce(void) +{ + int rc; + rc = load_immediate_value("via_ee/debounce", &debouce, sizeof(debouce)); + if (rc == -ENOENT) { + + LOG_DBG("via_ee/debounce,(default)\n"); + debouce.scan_period_ms = DT_PROP(DT_NODELABEL(kscan0), debounce_scan_period_ms); + debouce.debounce_press_ms = DT_PROP(DT_NODELABEL(kscan0), debounce_press_ms); + debouce.debounce_release_ms = DT_PROP(DT_NODELABEL(kscan0), debounce_release_ms); + } else if (rc == 0) { + user_set_debounce(debouce.scan_period_ms,debouce.debounce_press_ms,debouce.debounce_release_ms); + } + LOG_ERR("via_ee/debounce:%02x%02x%02x\n",debouce.scan_period_ms,debouce.debounce_press_ms,debouce.debounce_release_ms ); + +} +void via_ee_update_debounce(void) +{ + int rc; + rc = settings_save_one("via_ee/debounce", (const void *)&debouce, sizeof(debouce)); + if (rc) { + LOG_DBG("write failed:%d", rc); + } else { + LOG_DBG("OK.\n"); + } +} + diff --git a/app/src/launcher/launcher.h b/app/src/launcher/launcher.h new file mode 100644 index 00000000000..3d35d78f553 --- /dev/null +++ b/app/src/launcher/launcher.h @@ -0,0 +1,466 @@ +#pragma once + +#include +#include +#include +// #include +#include +#include "keycodes.h" + +// #define VIA_FIRMWARE_VERSION 0x000102002 + +#define ZMK_HID_MAIN_VAL_DATA (0x00 << 0) +#define ZMK_HID_MAIN_VAL_CONST (0x01 << 0) + +#define ZMK_HID_MAIN_VAL_ARRAY (0x00 << 1) +#define ZMK_HID_MAIN_VAL_VAR (0x01 << 1) + +#define ZMK_HID_MAIN_VAL_ABS (0x00 << 2) +#define ZMK_HID_MAIN_VAL_REL (0x01 << 2) + +#define ZMK_HID_MAIN_VAL_NO_WRAP (0x00 << 3) +#define ZMK_HID_MAIN_VAL_WRAP (0x01 << 3) + +#define ZMK_HID_MAIN_VAL_LIN (0x00 << 4) +#define ZMK_HID_MAIN_VAL_NON_LIN (0x01 << 4) + +#define ZMK_HID_MAIN_VAL_PREFERRED (0x00 << 5) +#define ZMK_HID_MAIN_VAL_NO_PREFERRED (0x01 << 5) + +#define ZMK_HID_MAIN_VAL_NO_NULL (0x00 << 6) +#define ZMK_HID_MAIN_VAL_NULL (0x01 << 6) + +#define ZMK_HID_MAIN_VAL_NON_VOL (0x00 << 7) +#define ZMK_HID_MAIN_VAL_VOL (0x01 << 7) + +#define HID_USAGE_PAGE_2(a,b) \ + HID_ITEM(HID_ITEM_TAG_USAGE_PAGE, HID_ITEM_TYPE_GLOBAL, 2), a,b + + +#define RAW_USAGE_PAGE 0xFF60 +#define RAW_USAGE_ID 0x61 +#define RAW_EPSIZE 32 + +static const uint8_t zmk_hid_via_report_desc[]= { + HID_USAGE_PAGE_2((RAW_USAGE_PAGE &0xff),(RAW_USAGE_PAGE>>8) ), // Vendor Defined + HID_USAGE(RAW_USAGE_ID), // Vendor Defined + HID_COLLECTION(0x01), // Application + // Data to host + HID_USAGE( 0x62), // Vendor Defined + HID_LOGICAL_MIN8(0x00), + HID_LOGICAL_MAX16(0xFF,0x00), + HID_REPORT_COUNT(RAW_EPSIZE), + HID_REPORT_SIZE(0x08), + HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS), + + // Data from host + HID_USAGE(0x63), // Vendor Defined + HID_LOGICAL_MIN8(0x00), + HID_LOGICAL_MAX16(0xFF,0x00), + HID_REPORT_COUNT(RAW_EPSIZE), + HID_REPORT_SIZE(0x08), + HID_OUTPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS | ZMK_HID_MAIN_VAL_NON_VOL), + + HID_END_COLLECTION +}; + +enum via_command_id { + id_get_protocol_version = 0x01, // always 0x01 + id_get_keyboard_value = 0x02, + id_set_keyboard_value = 0x03, + id_dynamic_keymap_get_keycode = 0x04, + id_dynamic_keymap_set_keycode = 0x05, + id_dynamic_keymap_reset = 0x06, + id_custom_set_value = 0x07, + id_custom_get_value = 0x08, + id_custom_save = 0x09, + id_eeprom_reset = 0x0A, + id_bootloader_jump = 0x0B, + id_dynamic_keymap_macro_get_count = 0x0C, + id_dynamic_keymap_macro_get_buffer_size = 0x0D, + id_dynamic_keymap_macro_get_buffer = 0x0E, + id_dynamic_keymap_macro_set_buffer = 0x0F, + id_dynamic_keymap_macro_reset = 0x10, + id_dynamic_keymap_get_layer_count = 0x11, + id_dynamic_keymap_get_buffer = 0x12, + id_dynamic_keymap_set_buffer = 0x13, + id_dynamic_keymap_get_encoder = 0x14, + id_dynamic_keymap_set_encoder = 0x15, + + kc_get_protocol_version = 0xa0, + kc_get_firmware_version = 0xa1, //ascii ver + kc_get_support_feature = 0xa2, + kc_get_default_layer = 0xa3, + kc_set_key_debounce = 0xb0, + kc_get_key_debounce = 0xb1, + + id_unhandled = 0xFF, +}; + +enum via_keyboard_value_id { + id_uptime = 0x01, + id_layout_options = 0x02, + id_switch_matrix_state = 0x03, + id_firmware_version = 0x04, + id_device_indication = 0x05, +}; + +enum via_channel_id { + id_custom_channel = 0, + id_qmk_backlight_channel = 1, + id_qmk_rgblight_channel = 2, + id_qmk_rgb_matrix_channel = 3, + id_qmk_audio_channel = 4, + id_qmk_led_matrix_channel = 5, +}; + +enum via_qmk_backlight_value { + id_qmk_backlight_brightness = 1, + id_qmk_backlight_effect = 2, +}; + +enum via_qmk_rgblight_value { + id_qmk_rgblight_brightness = 1, + id_qmk_rgblight_effect = 2, + id_qmk_rgblight_effect_speed = 3, + id_qmk_rgblight_color = 4, +}; + +enum via_qmk_rgb_matrix_value { + id_qmk_rgb_matrix_brightness = 1, + id_qmk_rgb_matrix_effect = 2, + id_qmk_rgb_matrix_effect_speed = 3, + id_qmk_rgb_matrix_color = 4, +}; + +enum via_qmk_led_matrix_value { + id_qmk_led_matrix_brightness = 1, + id_qmk_led_matrix_effect = 2, + id_qmk_led_matrix_effect_speed = 3, +}; + +enum via_qmk_audio_value { + id_qmk_audio_enable = 1, + id_qmk_audio_clicky_enable = 2, +}; + +typedef uint32_t matrix_row_t ; + +#if CONFIG_ZMK_LAUNCHER +#define VIA_ENABLE +#endif + +enum{ + BT_HST1 = QK_KB_0, + BT_HST2 , + BT_HST3 , + KC_BOOT , + PAIR_24G , + KC_SCRN_LOCK, + UC_CMD_CMA,//Command-Comma (,): Open preferences for the front app. + UC_LOPT,//Left Option + UC_ROPT,//Right Option + UC_LCMD,//Left Command + UC_RCMD,//Right Command + UC_CTRL_LEFT,//ctrl+ <- ,switch desktops + UC_CTRL_RIGHT,//ctrl+ -> ,switch desktops + UC_EMOJI_MAC,//Command+Control+space open emoji in mac + UC_TASK_VIEW,//LG(TAB) Open Task View + UC_SWITCH_DESKTOP_LEFT,//LG(LC(LEFT)) switch desktops + UC_SWITCH_DESKTOP_RIGHT,//LG(LC(RIGHT)) switch desktops + UC_FILE_EXPLORER,//LG(E) ,Open File Explorer. + UC_LOCK,//LG(L),Lock your PC or switch accounts. + UC_SETTINGS,//LG(I),Open Settings. + UC_EMOJI_WIN,//LG(DOT),open emoji in win + UC_PRNS_WIN,//LG(LS(S)) + UC_PRNS_MAC,//LG(LS(N4)) + UC_KEYCHRON,//0x770100 +}; + +#if CONFIG_SHIELD_KEYCHRON_B6_UK +#define QMK_BUILDDATE "2024-03-02" +#elif CONFIG_SHIELD_KEYCHRON_B6_US +#define QMK_BUILDDATE "2024-03-03" +#elif CONFIG_SHIELD_KEYCHRON_B6_JIS +#define QMK_BUILDDATE "2024-03-04" +#elif CONFIG_SHIELD_KEYCHRON_B1_US +#define QMK_BUILDDATE "2024-04-05" +#elif CONFIG_SHIELD_KEYCHRON_B1_UK +#define QMK_BUILDDATE "2024-04-06" +#elif CONFIG_SHIELD_KEYCHRON_B1_JIS +#define QMK_BUILDDATE "2024-04-07" +#elif CONFIG_SHIELD_KEYCHRON_B2_JIS +#define QMK_BUILDDATE "2024-05-08" +#elif CONFIG_SHIELD_KEYCHRON_B2_US +#define QMK_BUILDDATE "2024-05-09" +#elif CONFIG_SHIELD_KEYCHRON_B2_UK +#define QMK_BUILDDATE "2024-05-10" +#elif CONFIG_SHIELD_KEYCHRON_B2_KR +#define QMK_BUILDDATE "2024-08-21" +#else +#define QMK_BUILDDATE "2024-05-27" +#endif + +#define EECONFIG_SIZE 0 +#define MATRIX_COLS DT_PROP_LEN(DT_NODELABEL(kscan0), col_gpios) +#define MATRIX_ROWS DT_PROP_LEN(DT_NODELABEL(kscan0), row_gpios) +#define DYNAMIC_KEYMAP_LAYER_COUNT ZMK_KEYMAP_LAYERS_LEN +#define TOTAL_EEPROM_BYTE_COUNT 2560//4000 +#define KEYMAP_LEN (MATRIX_COLS*MATRIX_ROWS*2) +// Keyboard level code can change where VIA stores the magic. +// The magic is the build date YYMMDD encoded as BCD in 3 bytes, +// thus installing firmware built on a different date to the one +// already installed can be detected and the EEPROM data is reset. +// The only reason this is important is in case EEPROM usage changes +// and the EEPROM was not explicitly reset by bootmagic lite. +#ifndef VIA_EEPROM_MAGIC_ADDR +# define VIA_EEPROM_MAGIC_ADDR (EECONFIG_SIZE) +#endif + +#define VIA_EEPROM_LAYOUT_OPTIONS_ADDR (VIA_EEPROM_MAGIC_ADDR + 3) + +// Changing the layout options size after release will invalidate EEPROM, +// but this is something that should be set correctly on initial implementation. +// 1 byte is enough for most uses (i.e. 8 binary states, or 6 binary + 1 ternary/quaternary ) +#ifndef VIA_EEPROM_LAYOUT_OPTIONS_SIZE +# define VIA_EEPROM_LAYOUT_OPTIONS_SIZE 1 +#endif + +// Allow override of the layout options default value. +// This requires advanced knowledge of how VIA stores layout options +// and is only really useful for setting a boolean layout option +// state to true by default. +#ifndef VIA_EEPROM_LAYOUT_OPTIONS_DEFAULT +# define VIA_EEPROM_LAYOUT_OPTIONS_DEFAULT 0x00000000 +#endif + +// The end of the EEPROM memory used by VIA +// By default, dynamic keymaps will start at this if there is no +// custom config +#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE) + +#ifndef VIA_EEPROM_CUSTOM_CONFIG_SIZE +# define VIA_EEPROM_CUSTOM_CONFIG_SIZE 0 +#endif + +#define VIA_EEPROM_CONFIG_END (VIA_EEPROM_CUSTOM_CONFIG_ADDR + VIA_EEPROM_CUSTOM_CONFIG_SIZE) + +#ifdef VIA_ENABLE +# define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END) +#else +# include "eeconfig.h" +# define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE) +#endif + +#ifdef ENCODER_ENABLE +# include "encoder.h" +#else +# define NUM_ENCODERS 0 +#endif + +#ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +#endif + +#ifndef DYNAMIC_KEYMAP_MACRO_COUNT +# define DYNAMIC_KEYMAP_MACRO_COUNT 16 +#endif + +#ifndef TOTAL_EEPROM_BYTE_COUNT +# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps. +#endif + +#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR +# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1) +#endif + +#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > (TOTAL_EEPROM_BYTE_COUNT - 1) +# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > " STR((TOTAL_EEPROM_BYTE_COUNT - 1)) +# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver +#endif + +// Due to usage of uint16_t check for max 65535 +#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 65535 +# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > 65535" +# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536 +#endif + +// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h, +#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR +# define DYNAMIC_KEYMAP_EEPROM_ADDR DYNAMIC_KEYMAP_EEPROM_START +#endif + +// Dynamic encoders starts after dynamic keymaps +#ifndef DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR +# define DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2)) +#endif + +// Dynamic macro starts after dynamic encoders, but only when using ENCODER_MAP +#ifdef ENCODER_MAP_ENABLE +# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * NUM_ENCODERS * 2 * 2)) +# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +#else // ENCODER_MAP_ENABLE +# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR) +# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +#endif // ENCODER_MAP_ENABLE + +// Sanity check that dynamic keymaps fit in available EEPROM +// If there's not 100 bytes available for macros, then something is wrong. +// The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it, +// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has +// more than the default. +_Static_assert((DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available."); + +// Dynamic macros are stored after the keymaps and use what is available +// up to and including DYNAMIC_KEYMAP_EEPROM_MAX_ADDR. +#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE +# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 1) +#endif + +#ifndef DYNAMIC_KEYMAP_MACRO_DELAY +# define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY +#endif +//keympas[][] + +#define NUM_KEYMAP_LAYERS_RAW DYNAMIC_KEYMAP_LAYER_COUNT //((uint8_t)(sizeof(keymaps) / ((MATRIX_ROWS) * (MATRIX_COLS) * sizeof(uint16_t)))) +// +// This is changed only when the command IDs change, +// so VIA Configurator can detect compatible firmware. +#define VIA_PROTOCOL_VERSION 0x000C + +// This is a version number for the firmware for the keyboard. +// It can be used to ensure the VIA keyboard definition and the firmware +// have the same version, especially if there are changes to custom values. +// Define this in config.h to override and bump this number. +// This is *not* required if the keyboard is only using basic functionality +// and not using custom values for lighting, rotary encoders, etc. +#ifndef VIA_FIRMWARE_VERSION +# define VIA_FIRMWARE_VERSION 0x00000000 +#endif + +#ifndef TAP_CODE_DELAY +# define TAP_CODE_DELAY 10 +#endif + +// Can be called in an overriding via_init_kb() to test if keyboard level code usage of +// EEPROM is invalid and use/save defaults. +bool via_eeprom_is_valid(void); + +// Sets VIA/keyboard level usage of EEPROM to valid/invalid +// Keyboard level code (eg. via_init_kb()) should not call this +void via_eeprom_set_valid(bool valid); + +// Called by QMK core to initialize dynamic keymaps etc. +void eeconfig_init_via(void); +void via_init(void); + +// Used by VIA to store and retrieve the layout options. +uint32_t via_get_layout_options(void); +void via_set_layout_options(uint32_t value); +void via_set_layout_options_kb(uint32_t value); + +// Used by VIA to tell a device to flash LEDs (or do something else) when that +// device becomes the active device being configured, on startup or switching +// between devices. +void via_set_device_indication(uint8_t value); + +// Called by QMK core to process VIA-specific keycodes. +// bool process_record_via(uint16_t keycode, keyrecord_t *record); + +// These are made external so that keyboard level custom value handlers can use them. +#if defined(BACKLIGHT_ENABLE) +void via_qmk_backlight_command(uint8_t *data, uint8_t length); +void via_qmk_backlight_set_value(uint8_t *data); +void via_qmk_backlight_get_value(uint8_t *data); +void via_qmk_backlight_save(void); +#endif + +#if defined(RGBLIGHT_ENABLE) +void via_qmk_rgblight_command(uint8_t *data, uint8_t length); +void via_qmk_rgblight_set_value(uint8_t *data); +void via_qmk_rgblight_get_value(uint8_t *data); +void via_qmk_rgblight_save(void); +#endif + +#if defined(RGB_MATRIX_ENABLE) +void via_qmk_rgb_matrix_command(uint8_t *data, uint8_t length); +void via_qmk_rgb_matrix_set_value(uint8_t *data); +void via_qmk_rgb_matrix_get_value(uint8_t *data); +void via_qmk_rgb_matrix_save(void); +#endif + +#if defined(LED_MATRIX_ENABLE) +void via_qmk_led_matrix_command(uint8_t *data, uint8_t length); +void via_qmk_led_matrix_set_value(uint8_t *data); +void via_qmk_led_matrix_get_value(uint8_t *data); +void via_qmk_led_matrix_save(void); +#endif + +#if defined(AUDIO_ENABLE) +void via_qmk_audio_command(uint8_t *data, uint8_t length); +void via_qmk_audio_set_value(uint8_t *data); +void via_qmk_audio_get_value(uint8_t *data); +void via_qmk_audio_save(void); +#endif + +void raw_hid_receive(uint8_t *data, uint8_t length); + +union VIA_EE_DEVICE { + uint8_t raw[TOTAL_EEPROM_BYTE_COUNT]; + struct { + uint8_t magic[3]; + uint8_t layout_options[VIA_EEPROM_LAYOUT_OPTIONS_SIZE]; + #if VIA_EEPROM_CUSTOM_CONFIG_SIZE + uint8_t custom[VIA_EEPROM_CUSTOM_CONFIG_SIZE]; + #endif + uint8_t keymaps[(DYNAMIC_KEYMAP_LAYER_COUNT * KEYMAP_LEN)]; + #ifdef ENCODER_MAP_ENABLE + uint8_t encoder[DYNAMIC_KEYMAP_LAYER_COUNT * NUM_ENCODERS * 2 * 2]; + #endif + uint8_t macros[DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE]; + uint8_t changed_keys[DYNAMIC_KEYMAP_LAYER_COUNT][20]; + } __packed; +}; + +typedef union VIA_EE_DEVICE _via_ee_device; +extern _via_ee_device via_ee_device; + +struct user_debounce{ + uint8_t scan_period_ms; + uint8_t debounce_press_ms; + uint8_t debounce_release_ms; +}; + +void via_ee_read_all(void); +void via_ee_read_macros(void); +void via_ee_read_keymaps(void); +void via_ee_read_magic(void); +void via_ee_read_debounce(void); +void via_ee_update_debounce(void); +void via_ee_update_magic(void); +void via_ee_update_layout(void); +void via_ee_update_custom(void); +void via_ee_update_keymaps(void); +void via_ee_update_keymap(uint8_t i); +void via_ee_update_encoder(void); +void via_ee_update_macros(void); +void via_ee_delete_macros(void); +void via_ee_read_changed_keys(void); +void via_ee_update_changed_keys(uint8_t layer); +void via_set_changed_key(uint8_t layer,uint8_t row,uint8_t col); +void via_ee_reset_changed_keys(void); +void via_ee_reset_keymaps(void); +void set_zmk_keymap(uint8_t layer,uint8_t row ,uint8_t column ,uint16_t keycode) ; +void generate_via_keymaps(void); +void via_save_debounce(void); + +static inline uint8_t eeprom_read_byte(uint16_t addr) +{ + return via_ee_device.raw[addr]; +} +static inline void eeprom_update_byte(uint16_t addr, uint8_t value) +{ + via_ee_device.raw[addr]=value; +} \ No newline at end of file diff --git a/app/src/launcher/map_keycode.c b/app/src/launcher/map_keycode.c new file mode 100644 index 00000000000..0afb2627a26 --- /dev/null +++ b/app/src/launcher/map_keycode.c @@ -0,0 +1,703 @@ + +#include "launcher.h" +#include "keycodes.h" +#include +#include +#include +#include +#include +#include "dynamic_keymap.h" + + +LOG_MODULE_DECLARE(zmk,4);// CONFIG_ZMK_LOG_LEVEL); + +uint16_t gen_via_keymaps[DYNAMIC_KEYMAP_LAYER_COUNT][MATRIX_ROWS][MATRIX_COLS]; +void update_zmk_keymap(uint8_t layer,uint8_t pos,struct zmk_behavior_binding* binding); +struct zmk_behavior_binding * get_zmk_keymap(uint8_t layer ,uint8_t pos); + +static inline uint16_t KEYCODE2SYSTEM_R(uint16_t key) { + switch (key) { + case SYSTEM_POWER_DOWN: + return KC_SYSTEM_POWER; + case SYSTEM_SLEEP_0: + return KC_SYSTEM_SLEEP; + case SYSTEM_WAKE_UP_0: + return KC_SYSTEM_WAKE; + default: + return 0; + } +} +static inline uint16_t KEYCODE2CONSUMER_R(uint16_t key) { + switch (key) { + case AUDIO_MUTE: + return KC_AUDIO_MUTE; + case AUDIO_VOL_UP: + return KC_AUDIO_VOL_UP; + case AUDIO_VOL_DOWN: + return KC_AUDIO_VOL_DOWN; + case TRANSPORT_NEXT_TRACK: + return KC_MEDIA_NEXT_TRACK; + case TRANSPORT_PREV_TRACK: + return KC_MEDIA_PREV_TRACK; + case TRANSPORT_FAST_FORWARD: + return KC_MEDIA_FAST_FORWARD; + case TRANSPORT_REWIND: + return KC_MEDIA_REWIND; + case TRANSPORT_STOP: + return KC_MEDIA_STOP; + case TRANSPORT_STOP_EJECT: + return KC_MEDIA_EJECT; + case TRANSPORT_PLAY_PAUSE: + return KC_MEDIA_PLAY_PAUSE; + case AL_CC_CONFIG: + return KC_MEDIA_SELECT; + case AL_EMAIL: + return KC_MAIL; + case AL_CALCULATOR: + return KC_CALCULATOR; + case AL_LOCAL_BROWSER: + return KC_MY_COMPUTER; + case AL_CONTROL_PANEL: + return KC_CONTROL_PANEL; + case AL_ASSISTANT: + return KC_ASSISTANT; + case AC_SEARCH: + return KC_WWW_SEARCH; + case AC_HOME: + return KC_WWW_HOME; + case AC_BACK: + return KC_WWW_BACK; + case AC_FORWARD: + return KC_WWW_FORWARD; + case AC_STOP: + return KC_WWW_STOP; + case AC_REFRESH: + return KC_WWW_REFRESH; + case BRIGHTNESS_UP: + return KC_BRIGHTNESS_UP; + case BRIGHTNESS_DOWN: + return KC_BRIGHTNESS_DOWN; + case AC_BOOKMARKS: + return KC_WWW_FAVORITES; + case AC_DESKTOP_SHOW_ALL_WINDOWS: + return KC_MISSION_CONTROL; + case AC_SOFT_KEY_LEFT: + return KC_LAUNCHPAD; + default: + return 0; + } +} +/* keycode to system usage */ +static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { + switch (key) { + case KC_SYSTEM_POWER: + return SYSTEM_POWER_DOWN; + case KC_SYSTEM_SLEEP: + return SYSTEM_SLEEP_0; + case KC_SYSTEM_WAKE: + return SYSTEM_WAKE_UP_0; + default: + return 0; + } +} + +/* keycode to consumer usage */ +static inline uint16_t KEYCODE2CONSUMER(uint8_t key) { + switch (key) { + case KC_AUDIO_MUTE: + return AUDIO_MUTE; + case KC_AUDIO_VOL_UP: + return AUDIO_VOL_UP; + case KC_AUDIO_VOL_DOWN: + return AUDIO_VOL_DOWN; + case KC_MEDIA_NEXT_TRACK: + return TRANSPORT_NEXT_TRACK; + case KC_MEDIA_PREV_TRACK: + return TRANSPORT_PREV_TRACK; + case KC_MEDIA_FAST_FORWARD: + return TRANSPORT_FAST_FORWARD; + case KC_MEDIA_REWIND: + return TRANSPORT_REWIND; + case KC_MEDIA_STOP: + return TRANSPORT_STOP; + case KC_MEDIA_EJECT: + return TRANSPORT_STOP_EJECT; + case KC_MEDIA_PLAY_PAUSE: + return TRANSPORT_PLAY_PAUSE; + case KC_MEDIA_SELECT: + return AL_CC_CONFIG; + case KC_MAIL: + return AL_EMAIL; + case KC_CALCULATOR: + return AL_CALCULATOR; + case KC_MY_COMPUTER: + return AL_LOCAL_BROWSER; + case KC_CONTROL_PANEL: + return AL_CONTROL_PANEL; + case KC_ASSISTANT: + return AL_ASSISTANT; + case KC_WWW_SEARCH: + return AC_SEARCH; + case KC_WWW_HOME: + return AC_HOME; + case KC_WWW_BACK: + return AC_BACK; + case KC_WWW_FORWARD: + return AC_FORWARD; + case KC_WWW_STOP: + return AC_STOP; + case KC_WWW_REFRESH: + return AC_REFRESH; + case KC_BRIGHTNESS_UP: + return BRIGHTNESS_UP; + case KC_BRIGHTNESS_DOWN: + return BRIGHTNESS_DOWN; + case KC_WWW_FAVORITES: + return AC_BOOKMARKS; + case KC_MISSION_CONTROL: + return AC_DESKTOP_SHOW_ALL_WINDOWS; + case KC_LAUNCHPAD: + return AC_SOFT_KEY_LEFT; + default: + return 0; + } +} +uint8_t mod_to_zmk(uint8_t mod) +{ + if(mod &0x10) + { + mod &= 0x0f; + mod <<= 4; + return mod; + } + else + { + return mod ; + } +} +uint8_t mod_to_zmk_keycode(uint8_t mod_5bits) +{ + uint8_t mod=mod_to_zmk(mod_5bits); + for(int i=0;i<8;i++) + { + if(mod &(1<>4; + if(left_mode) + { + mod = left_mode; + } + else if(right_mode) + { + mod =0x10 | right_mode; + } + return mod; +} +uint8_t mod_kc_to_via(uint8_t kc) +{ + uint8_t mod =1<< (kc-LCTRL); + return mod_to_via(mod); +} +#define QK_MODS_GET_MODS(kc) (((kc) >> 8) & 0x1F) +#define QK_MODS_GET_BASIC_KEYCODE(kc) ((kc)&0xFF) + +void via_keycode_to_binding(uint8_t keycode,struct zmk_behavior_binding * binding) +{ + switch (keycode) { + case BASIC_KEYCODE_RANGE: + case MODIFIER_KEYCODE_RANGE: + binding->behavior_dev="KEY_PRESS";//"&kp"; + binding->param1 =keycode; + break; + + case SYSTEM_KEYCODE_RANGE: + binding->behavior_dev="KEY_PRESS";//"&kp"; + binding->param1 =KEYCODE2SYSTEM(keycode)|(HID_USAGE_GD<<16); + break; + case CONSUMER_KEYCODE_RANGE: + binding->behavior_dev="KEY_PRESS";//"&kp"; + binding->param1 =KEYCODE2CONSUMER(keycode)|(HID_USAGE_CONSUMER<<16); + break; + } +} + +void set_zmk_keymap(uint8_t layer,uint8_t row ,uint8_t column ,uint16_t keycode) { + + int32_t position = zmk_matrix_transform_row_column_to_position(row, column); + if(position<0) return; + struct zmk_behavior_binding binding; + memset(&binding,0,sizeof(binding)); + + switch (keycode) { + case BASIC_KEYCODE_RANGE: + case MODIFIER_KEYCODE_RANGE: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 =keycode; + break; + + case SYSTEM_KEYCODE_RANGE: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 =KEYCODE2SYSTEM(keycode)|(HID_USAGE_GD<<16); + break; + case CONSUMER_KEYCODE_RANGE: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 =KEYCODE2CONSUMER(keycode)|(HID_USAGE_CONSUMER<<16); + break; + + case MOUSE_KEYCODE_RANGE: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 = keycode|(HID_USAGE_GEN_BUTTON<<16); + break; + case KC_NO: + binding.behavior_dev="NONE";//"&none"; + break; + case KC_TRANSPARENT: + binding.behavior_dev="TRANS";//"&trans"; + break; + case QK_MODS ... QK_MODS_MAX: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 =(mod_to_zmk(QK_MODS_GET_MODS(keycode))<<24) | (HID_USAGE_KEY<<16)|QK_MODS_GET_BASIC_KEYCODE(keycode); + + break; + case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: + binding.behavior_dev="LAYER_TAP"; + binding.param1= (keycode>>8) &0x0f; + binding.param2= keycode&0xff; + break; + + case QK_TO ... QK_TO_MAX:; + // Layer set "GOTO" + binding.behavior_dev="TO_LAYER";//"&to"; + binding.param1= keycode &0x1f; + break; + case QK_MOMENTARY ... QK_MOMENTARY_MAX:; + // Momentary action_layer + binding.behavior_dev="MO";// "&mo"; + binding.param1= keycode &0x1f; + break; + // case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:; + // // Set default action_layer + // action_layer = QK_DEF_LAYER_GET_LAYER(keycode); + // action.code = ACTION_DEFAULT_LAYER_SET(action_layer); + // break; + case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:; + // Set toggle + binding.behavior_dev="TOGGLE_LAYER";//"&tog"; + binding.param1= keycode &0x1f; + break; + + case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:; + // OSL(action_layer) - One-shot action_layer + binding.behavior_dev="STICKY_LAYER";//"&sl"; + binding.param1= keycode &0x1f; + break; + case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: + binding.behavior_dev="TAPD_LAYER"; + // void update_td_layer(uint32_t pos,uint8_t layer); + // update_td_layer(position,keycode&0x1f); + binding.param1 =keycode&0x1f; + break; + + case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:; + // OSM(mod) - One-shot mod + binding.behavior_dev="STICKY_KEY";//"&sk"; + binding.param1= keycode &0x1f; + break; + + // case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: + // binding.behavior_dev="LAYER_TAP";//"<"; + // binding.param1= (keycode>>8) &0x0f; + // binding.param2= keycode &0xff; + // break; + // case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: + // mod = mod_config(QK_LAYER_MOD_GET_MODS(keycode)); + // action_layer = QK_LAYER_MOD_GET_LAYER(keycode); + // action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? mod << 4 : mod); + // break; + + case QK_MOD_TAP ... QK_MOD_TAP_MAX: + binding.behavior_dev="MOD_TAP";//"&mt"; + binding.param1 =mod_to_zmk_keycode(QK_MODS_GET_MODS(keycode));//fix mod + binding.param2 =QK_MODS_GET_BASIC_KEYCODE(keycode); + break; + case QK_MACRO ... QK_MACRO_MAX: + binding.behavior_dev="ZM_MA"; + binding.param1 =0x770000 |(keycode&0xff); + break; + case QK_GRAVE_ESCAPE: + binding.behavior_dev="GRAVE_ESCAPE"; + break; + case QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN: + binding.behavior_dev="MOD_TAP"; + binding.param1 =LCTRL; + binding.param2 =LS(N9); + break; + case QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE: + binding.behavior_dev="MOD_TAP"; + binding.param1 =RCTRL; + binding.param2 =LS(N0); + break; + case QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN: + binding.behavior_dev="MOD_TAP"; + binding.param1 =LSHFT; + binding.param2 =LS(N9); + break; + case QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE: + binding.behavior_dev="MOD_TAP"; + binding.param1 =RSHFT; + binding.param2 =LS(N0); + break; + case QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN: + binding.behavior_dev="MOD_TAP"; + binding.param1 =LALT; + binding.param2 =LS(N9); + break; + case QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE: + binding.behavior_dev="MOD_TAP"; + binding.param1 =RALT; + binding.param2 =LS(N0); + break; + case QK_SPACE_CADET_RIGHT_SHIFT_ENTER: + binding.behavior_dev="MOD_TAP"; + binding.param1 =RSHFT; + binding.param2 =RET; + break; + + case QK_KB ... QK_KB_MAX: + switch(keycode) + { + case BT_HST1: + binding.behavior_dev="bt_pair0"; + break; + case BT_HST2: + binding.behavior_dev="bt_pair1"; + break; + case BT_HST3: + binding.behavior_dev="bt_pair2"; + break; + case PAIR_24G: + binding.behavior_dev="bt_pair3"; + break; + case KC_BOOT: + binding.behavior_dev="lp_bootloader"; + break; + case KC_SCRN_LOCK: + binding.behavior_dev="KEY_PRESS";//"&kp"; + binding.param1 =C_AL_LOCK; + break; + case UC_CMD_CMA: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(COMMA); + break; + case UC_LOPT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LALT; + break; + case UC_ROPT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =RALT; + break; + case UC_LCMD: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LCMD; + break; + case UC_RCMD: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =RCMD; + break; + case UC_CTRL_LEFT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LC(LEFT); + break; + case UC_CTRL_RIGHT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LC(RIGHT); + break; + case UC_EMOJI_MAC: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LC(LG(SPACE)); + break; + case UC_TASK_VIEW: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(TAB); + break; + case UC_SWITCH_DESKTOP_LEFT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(LC(LEFT)); + break; + case UC_SWITCH_DESKTOP_RIGHT: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(LC(RIGHT)); + break; + case UC_FILE_EXPLORER: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(E); + break; + case UC_LOCK: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(L); + break; + case UC_SETTINGS: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(I); + break; + case UC_EMOJI_WIN: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(DOT); + break; + case UC_PRNS_WIN: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(LS(S)); + break; + case UC_PRNS_MAC: + binding.behavior_dev="user_custom";//"&kp"; + binding.param1 =LG(LS(N4)); + break; + case UC_KEYCHRON: + binding.behavior_dev="ZM_MA";//"&kp"; + binding.param1 =0x770100; + break; + } + break; + default: + binding.behavior_dev="NONE";//"&none"; + break; + } + // LOG_DBG("layer:%d,row:%d,col:%d,keycode:%d to binding:%s,p1:%x,p2:%x",layer,row,column,keycode,binding.behavior_dev,binding.param1,binding.param2); + update_zmk_keymap(layer,position,&binding); +} +void generate_via_keymaps(void) +{ + for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) { + for (int row = 0; row < MATRIX_ROWS; row++) { + for (int column = 0; column < MATRIX_COLS; column++) { + int32_t position = zmk_matrix_transform_row_column_to_position(row, column); + if(position>=0) + { + struct zmk_behavior_binding * binding =get_zmk_keymap(layer,position); + char * behavior_dev=binding->behavior_dev; + if(memcmp(behavior_dev,"KEY_PRESS",9)==0)//&kp + { + uint16_t keycode= binding->param1 &0xffff; + uint8_t page = binding->param1 >>16 &0xff; + uint8_t mod = binding->param1>>24; + + switch(page) + { + case HID_USAGE_GD: + gen_via_keymaps[layer][row][column]=KEYCODE2SYSTEM_R(keycode); + break; + case HID_USAGE_KEY: + gen_via_keymaps[layer][row][column]=keycode; + if(mod) gen_via_keymaps[layer][row][column]|=mod_to_via(mod) <<8; + break; + case HID_USAGE_CONSUMER: + if(keycode == HID_USAGE_CONSUMER_AL_TERMINAL_LOCK_SCREENSAVER) + { + gen_via_keymaps[layer][row][column]=KC_SCRN_LOCK; //custom + } + else + gen_via_keymaps[layer][row][column]=KEYCODE2CONSUMER_R(keycode); + break; + case HID_USAGE_GEN_BUTTON: + gen_via_keymaps[layer][row][column] =keycode; + break; + } + + } else if(memcmp(behavior_dev,"MO",2)==0) { //&mo + uint16_t keycode= binding->param1 &0xffff; + gen_via_keymaps[layer][row][column]=QK_MOMENTARY | (keycode &0x1f); + + } else if(memcmp(behavior_dev,"TO_LAYER",8)==0) {//&to + uint16_t keycode= binding->param1 &0xffff; + gen_via_keymaps[layer][row][column]=QK_TO | (keycode &0x1f); + + } else if(memcmp(behavior_dev,"TOGGLE_LAYER",12)==0) {//&tog + uint16_t keycode= binding->param1 &0xffff; + gen_via_keymaps[layer][row][column]=QK_TOGGLE_LAYER | (keycode &0x1f); + + } else if(memcmp(behavior_dev,"TAPD_LAYER",10)==0) {//&tog + uint16_t keycode= binding->param1 &0x1f; + gen_via_keymaps[layer][row][column]=QK_LAYER_TAP_TOGGLE | (keycode ); + + } else if(memcmp(behavior_dev,"LAYER_TAP",9)==0) {//< + + uint8_t layer=binding->param1&0x0f; + uint8_t keycode =binding->param2&0xff; + gen_via_keymaps[layer][row][column]=QK_LAYER_TAP | (layer<<8)| (keycode); + + } else if(memcmp(behavior_dev,"MOD_TAP",7)==0) {//&mt + + uint8_t mod=binding->param1; + uint32_t keycode =binding->param2; + LOG_DBG("mod_tap,mod:%d,keycode:%x",mod,keycode); + if(mod ==RSHFT && keycode == RET ) + { + gen_via_keymaps[layer][row][column] =SC_SENT; + } + else if(keycode >0xffff) + { + switch(keycode) + { + case LS(N9): + if(mod ==LSHFT) + { + gen_via_keymaps[layer][row][column]=SC_LSPO; + }else if (mod ==LCTRL) + { + gen_via_keymaps[layer][row][column]=SC_LCPO; + }else if (mod ==LALT) + { + gen_via_keymaps[layer][row][column]=SC_LAPO; + } + break; + case LS(N0): + if(mod ==RSHFT) + { + gen_via_keymaps[layer][row][column]=SC_RSPC; + }else if (mod ==RCTRL) + { + gen_via_keymaps[layer][row][column]=SC_RCPC; + }else if (mod ==RALT) + { + gen_via_keymaps[layer][row][column]=SC_RAPC; + } + break; + + } + } + else + gen_via_keymaps[layer][row][column]=QK_MOD_TAP | (mod_kc_to_via(mod)<<8) | (keycode &0xff); + + } else if(memcmp(behavior_dev,"STICKY_LAYER",12)==0) {//&sl + + uint8_t layer =binding->param1&0x1f; + gen_via_keymaps[layer][row][column]=QK_ONE_SHOT_LAYER | (layer); + + } else if(memcmp(behavior_dev,"STICKY_KEY",9)==0) {//&sk + + uint8_t mod =binding->param1&0x1f; + gen_via_keymaps[layer][row][column]=QK_ONE_SHOT_MOD | (mod); + + } else if(memcmp(behavior_dev,"TRANS",5)==0) {//&trans + + gen_via_keymaps[layer][row][column]=KC_TRANSPARENT; + + } else if(memcmp(behavior_dev,"NONE",4)==0) {//&none + + gen_via_keymaps[layer][row][column]=KC_NO; + + } else if(memcmp(behavior_dev,"ZM_MA",5)==0){ + + if(binding->param1 ==0x770100) + { + gen_via_keymaps[layer][row][column]=UC_KEYCHRON; + } + else + gen_via_keymaps[layer][row][column]=QK_MACRO | (binding->param1 &0xff); + + } else if(memcmp(behavior_dev,"bt_pair0",8)==0){ + + gen_via_keymaps[layer][row][column] =BT_HST1; + } else if(memcmp(behavior_dev,"bt_pair1",8)==0){ + + gen_via_keymaps[layer][row][column] =BT_HST2; + + } else if(memcmp(behavior_dev,"bt_pair2",8)==0){ + + gen_via_keymaps[layer][row][column] =BT_HST3; + + } else if(memcmp(behavior_dev,"bt_pair3",8)==0){ + + gen_via_keymaps[layer][row][column] =PAIR_24G; + + } else if(memcmp(behavior_dev,"lp_bootloader",13)==0){ + + gen_via_keymaps[layer][row][column] =KC_BOOT; + + } else if(memcmp(behavior_dev,"GRAVE_ESCAPE",12)==0){ + + gen_via_keymaps[layer][row][column] =QK_GRAVE_ESCAPE; + + } else if(memcmp(behavior_dev,"user_custom",11)==0) { + + switch(binding->param1) + { + case LG(COMMA): + gen_via_keymaps[layer][row][column] =UC_CMD_CMA; + break; + case LALT: + gen_via_keymaps[layer][row][column] =UC_LOPT; + break; + case RALT: + gen_via_keymaps[layer][row][column] =UC_ROPT; + break; + case LCMD: + gen_via_keymaps[layer][row][column] =UC_LCMD; + break; + case RCMD: + gen_via_keymaps[layer][row][column] =UC_RCMD; + break; + case LC(LEFT): + gen_via_keymaps[layer][row][column] =UC_CTRL_LEFT; + break; + case LC(RIGHT): + gen_via_keymaps[layer][row][column] =UC_CTRL_RIGHT; + break; + case LC(LG(SPACE)): + gen_via_keymaps[layer][row][column] =UC_EMOJI_MAC; + break; + case LG(TAB): + gen_via_keymaps[layer][row][column] =UC_TASK_VIEW; + break; + case LG(LC(LEFT)): + gen_via_keymaps[layer][row][column] =UC_SWITCH_DESKTOP_LEFT; + break; + case LG(LC(RIGHT)): + gen_via_keymaps[layer][row][column] =UC_SWITCH_DESKTOP_RIGHT; + break; + case LG(E): + gen_via_keymaps[layer][row][column] =UC_FILE_EXPLORER; + break; + case LG(L): + gen_via_keymaps[layer][row][column] =UC_LOCK; + break; + case LG(I): + gen_via_keymaps[layer][row][column] =UC_SETTINGS; + break; + case LG(DOT): + gen_via_keymaps[layer][row][column] =UC_EMOJI_WIN; + break; + case LG(LS(N4)): + gen_via_keymaps[layer][row][column] =UC_PRNS_MAC; + break; + case LG(LS(S)): + gen_via_keymaps[layer][row][column] =UC_PRNS_WIN; + break; + + } + + } + + else { + gen_via_keymaps[layer][row][column]=KC_NO; + } + dynamic_keymap_set_keycode_no_update(layer, row, column, gen_via_keymaps[layer][row][column]); + //if(memcmp(behavior_dev,"TRANS",5)&&memcmp(behavior_dev,"KEY_PRESS",9) || layer ==3) + // if(memcmp(behavior_dev,"TRANS",5) && layer ==3) + // LOG_DBG("layer:%d,row:%d,col:%d,pos:%d,binding:%s,p1:%x,p2:%x,via keycode:%x",layer,row,column,position, binding->behavior_dev, binding->param1,binding->param2, gen_via_keymaps[layer][row][column]); + } + } + } + } +} diff --git a/app/src/launcher/mousekey.c b/app/src/launcher/mousekey.c new file mode 100644 index 00000000000..edb90abfb38 --- /dev/null +++ b/app/src/launcher/mousekey.c @@ -0,0 +1,785 @@ +/* + * Copyright 2011 Jun Wako + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "mousekey.h" +#include "keycodes.h" +#include +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8) + +static uint32_t timer_read(void){ + return k_uptime_get_32(); +} +uint32_t timer_elapsed(uint32_t last) { + return TIMER_DIFF_32(k_uptime_get_32(), last); +} + +static inline int8_t times_inv_sqrt2(int8_t x) { + // 181/256 (0.70703125) is used as an approximation for 1/sqrt(2) + // because it is close to the exact value which is 0.707106781 + const int16_t n = x * 181; + const uint16_t d = 256; + + // To ensure that the integer result is rounded accurately after + // division, check the sign of the numerator: + // If negative, subtract half of the denominator before dividing + // Otherwise, add half of the denominator before dividing + return n < 0 ? (n - d / 2) / d : (n + d / 2) / d; +} + +static report_mouse_t mouse_report = {ZMK_HID_REPORT_ID_MOUSE,0}; +static void mousekey_debug(void); +static uint8_t mousekey_accel = 0; +static uint8_t mousekey_repeat = 0; +static uint8_t mousekey_wheel_repeat = 0; +#ifdef MOUSEKEY_INERTIA +static uint8_t mousekey_frame = 0; // track whether gesture is inactive, first frame, or repeating +static int8_t mousekey_x_dir = 0; // -1 / 0 / 1 = left / neutral / right +static int8_t mousekey_y_dir = 0; // -1 / 0 / 0 = up / neutral / down +static int8_t mousekey_x_inertia = 0; // current velocity, limit +/- MOUSEKEY_TIME_TO_MAX +static int8_t mousekey_y_inertia = 0; // ... +#endif +#ifdef MK_KINETIC_SPEED +static uint32_t mouse_timer = 0; +#endif + +#ifndef MK_3_SPEED + +static uint32_t last_timer_c = 0; +static uint32_t last_timer_w = 0; + +/* + * Mouse keys acceleration algorithm + * http://en.wikipedia.org/wiki/Mouse_keys + * + * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000) + */ +/* milliseconds between the initial key press and first repeated motion event (0-2550) */ +uint8_t mk_delay = MOUSEKEY_DELAY / 10; +/* milliseconds between repeated motion events (0-255) */ +uint8_t mk_interval = MOUSEKEY_INTERVAL; +/* steady speed (in action_delta units) applied each event (0-255) */ +uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED; +/* number of events (count) accelerating to steady speed (0-255) */ +uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX; +/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */ +// int8_t mk_curve = 0; +/* wheel params */ +/* milliseconds between the initial key press and first repeated motion event (0-2550) */ +uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10; +/* milliseconds between repeated motion events (0-255) */ +# ifdef MK_KINETIC_SPEED +uint16_t mk_wheel_interval = 1000U / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; +# else +uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL; +# endif +uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; +uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; + +# ifndef MK_COMBINED +# ifndef MK_KINETIC_SPEED +# ifndef MOUSEKEY_INERTIA + +/* Default accelerated mode */ + +static uint8_t move_unit(void) { + uint16_t unit; + if (mousekey_accel & (1 << 0)) { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; + } else if (mousekey_accel & (1 << 1)) { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; + } else if (mousekey_accel & (1 << 2)) { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed); + } else if (mousekey_repeat == 0) { + unit = MOUSEKEY_MOVE_DELTA; + } else if (mousekey_repeat >= mk_time_to_max) { + unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; + } else { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; + } + return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); +} + +# else // MOUSEKEY_INERTIA mode + +static int8_t move_unit(uint8_t axis) { + int16_t unit; + + // handle X or Y axis + int8_t inertia, dir; + if (axis) { + inertia = mousekey_y_inertia; + dir = mousekey_y_dir; + } else { + inertia = mousekey_x_inertia; + dir = mousekey_x_dir; + } + + if (mousekey_frame < 2) { // first frame(s): initial keypress moves one pixel + mousekey_frame = 1; + unit = dir * MOUSEKEY_MOVE_DELTA; + } else { // acceleration + // linear acceleration (is here for reference, but doesn't feel as good during use) + // unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * inertia) / mk_time_to_max; + + // x**2 acceleration (quadratic, more precise for short movements) + int16_t percent = (inertia << 8) / mk_time_to_max; + percent = ((int32_t)percent * percent) >> 8; + if (inertia < 0) percent = -percent; + + // unit = sign(inertia) + (percent of max speed) + if (inertia > 0) + unit = 1; + else if (inertia < 0) + unit = -1; + else + unit = 0; + + unit = unit + ((mk_max_speed * percent) >> 8); + } + + if (unit > MOUSEKEY_MOVE_MAX) + unit = MOUSEKEY_MOVE_MAX; + else if (unit < -MOUSEKEY_MOVE_MAX) + unit = -MOUSEKEY_MOVE_MAX; + return unit; +} + +# endif // end MOUSEKEY_INERTIA mode + +static uint8_t wheel_unit(void) { + uint16_t unit; + if (mousekey_accel & (1 << 0)) { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; + } else if (mousekey_accel & (1 << 1)) { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; + } else if (mousekey_accel & (1 << 2)) { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed); + } else if (mousekey_wheel_repeat == 0) { + unit = MOUSEKEY_WHEEL_DELTA; + } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { + unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; + } else { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max; + } + return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); +} + +# else /* #ifndef MK_KINETIC_SPEED */ + +/* + * Kinetic movement acceleration algorithm + * + * current speed = I + A * T/50 + A * (T/50)^2 * 1/2 | maximum B + * + * T: time since the mouse movement started + * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the + * pro micro on my Signum 3.0 sends only 125!) + * I: initial speed at time 0 + * A: acceleration + * B: base mouse travel speed + */ +const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED; +const uint16_t mk_base_speed = MOUSEKEY_BASE_SPEED; +const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED; +const uint16_t mk_initial_speed = MOUSEKEY_INITIAL_SPEED; + +static uint8_t move_unit(void) { + uint16_t speed = mk_initial_speed; + + if (mousekey_accel & (1 << 0)) { + speed = mk_decelerated_speed; + } else if (mousekey_accel & (1 << 2)) { + speed = mk_accelerated_speed; + } else if (mousekey_repeat && mouse_timer) { + const uint16_t time_elapsed = timer_elapsed(mouse_timer) / 50; + speed = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + (MOUSEKEY_MOVE_DELTA * time_elapsed * time_elapsed) / 2; + if (speed > mk_base_speed) { + speed = mk_base_speed; + } + } + /* convert speed to USB mouse speed 1 to 127 */ + speed = (uint8_t)(speed / (1000U / mk_interval)); + + if (speed > MOUSEKEY_MOVE_MAX) { + speed = MOUSEKEY_MOVE_MAX; + } else if (speed < 1) { + speed = 1; + } + return speed; +} + +static uint8_t wheel_unit(void) { + uint16_t speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; + + if (mousekey_accel & (1 << 0)) { + speed = MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS; + } else if (mousekey_accel & (1 << 2)) { + speed = MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS; + } else if (mousekey_wheel_repeat && mouse_timer) { + if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) { + const uint16_t time_elapsed = timer_elapsed(mouse_timer) / 50; + speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + (1 * time_elapsed * time_elapsed) / 2; + } + if (speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS) { + speed = MOUSEKEY_WHEEL_BASE_MOVEMENTS; + } + } + mk_wheel_interval = 1000U / speed; + return 1; +} + +# endif /* #ifndef MK_KINETIC_SPEED */ +# else /* #ifndef MK_COMBINED */ + +/* Combined mode */ + +static uint8_t move_unit(void) { + uint16_t unit; + if (mousekey_accel & (1 << 0)) { + unit = 1; + } else if (mousekey_accel & (1 << 1)) { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; + } else if (mousekey_accel & (1 << 2)) { + unit = MOUSEKEY_MOVE_MAX; + } else if (mousekey_repeat == 0) { + unit = MOUSEKEY_MOVE_DELTA; + } else if (mousekey_repeat >= mk_time_to_max) { + unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; + } else { + unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; + } + return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); +} + +static uint8_t wheel_unit(void) { + uint16_t unit; + if (mousekey_accel & (1 << 0)) { + unit = 1; + } else if (mousekey_accel & (1 << 1)) { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; + } else if (mousekey_accel & (1 << 2)) { + unit = MOUSEKEY_WHEEL_MAX; + } else if (mousekey_repeat == 0) { + unit = MOUSEKEY_WHEEL_DELTA; + } else if (mousekey_repeat >= mk_wheel_time_to_max) { + unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; + } else { + unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max; + } + return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); +} + +# endif /* #ifndef MK_COMBINED */ + +# ifdef MOUSEKEY_INERTIA + +static int8_t calc_inertia(int8_t direction, int8_t velocity) { + // simulate acceleration and deceleration + + // deceleration + if ((direction > -1) && (velocity < 0)) + velocity = (velocity + 1) * (256 - MOUSEKEY_FRICTION) / 256; + else if ((direction < 1) && (velocity > 0)) + velocity = velocity * (256 - MOUSEKEY_FRICTION) / 256; + + // acceleration + if ((direction > 0) && (velocity < mk_time_to_max)) + velocity++; + else if ((direction < 0) && (velocity > -mk_time_to_max)) + velocity--; + + return velocity; +} + +# endif + +void mousekey_task(void) { + // report cursor and scroll movement independently + report_mouse_t tmpmr = mouse_report; + + mouse_report.x = 0; + mouse_report.y = 0; + mouse_report.v = 0; + mouse_report.h = 0; + +# ifdef MOUSEKEY_INERTIA + + // if an animation is in progress and it's time for the next frame + if ((mousekey_frame) && timer_elapsed(last_timer_c) > ((mousekey_frame > 1) ? mk_interval : mk_delay * 10)) { + mousekey_x_inertia = calc_inertia(mousekey_x_dir, mousekey_x_inertia); + mousekey_y_inertia = calc_inertia(mousekey_y_dir, mousekey_y_inertia); + + mouse_report.x = move_unit(0); + mouse_report.y = move_unit(1); + + // prevent sticky "drift" + if ((!mousekey_x_dir) && (!mousekey_x_inertia)) tmpmr.x = 0; + if ((!mousekey_y_dir) && (!mousekey_y_inertia)) tmpmr.y = 0; + + if (mousekey_frame < 2) mousekey_frame++; + } + + // reset if not moving and no movement keys are held + if ((!mousekey_x_dir) && (!mousekey_y_dir) && (!mousekey_x_inertia) && (!mousekey_y_inertia)) { + mousekey_frame = 0; + tmpmr.x = 0; + tmpmr.y = 0; + } + +# else // default acceleration + + if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { + if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; + if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1); + if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1); + + /* diagonal move [1/sqrt(2)] */ + if (mouse_report.x && mouse_report.y) { + mouse_report.x = times_inv_sqrt2(mouse_report.x); + if (mouse_report.x == 0) { + mouse_report.x = 1; + } + mouse_report.y = times_inv_sqrt2(mouse_report.y); + if (mouse_report.y == 0) { + mouse_report.y = 1; + } + } + } + +# endif // MOUSEKEY_INERTIA or not + + if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) { + if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++; + if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1); + if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1); + + /* diagonal move [1/sqrt(2)] */ + if (mouse_report.v && mouse_report.h) { + mouse_report.v = times_inv_sqrt2(mouse_report.v); + if (mouse_report.v == 0) { + mouse_report.v = 1; + } + mouse_report.h = times_inv_sqrt2(mouse_report.h); + if (mouse_report.h == 0) { + mouse_report.h = 1; + } + } + } + + if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) { + mousekey_send(); + } + // save the state for later + memcpy(&mouse_report, &tmpmr, sizeof(tmpmr)); +} + +void mousekey_on(uint8_t code) { +# ifdef MK_KINETIC_SPEED + if (mouse_timer == 0) { + mouse_timer = timer_read(); + } +# endif + +# ifndef MOUSEKEY_INERTIA + // If mouse report is not zero, the current mousekey press is overlapping + // with another. Restart acceleration for smoother directional transition. + if (mouse_report.x || mouse_report.y || mouse_report.h || mouse_report.v) { +# ifdef MK_KINETIC_SPEED + mouse_timer = timer_read() - (MOUSEKEY_INTERVAL << 2); +# else + mousekey_repeat = MOUSEKEY_MOVE_DELTA; + mousekey_wheel_repeat = MOUSEKEY_WHEEL_DELTA; +# endif + } +# endif // ifndef MOUSEKEY_INERTIA + +# ifdef MOUSEKEY_INERTIA + + // initial keypress sets impulse and activates first frame of movement + if ((code == KC_MS_UP) || (code == KC_MS_DOWN)) { + mousekey_y_dir = (code == KC_MS_DOWN) ? 1 : -1; + if (mousekey_frame < 2) mouse_report.y = move_unit(1); + } else if ((code == KC_MS_LEFT) || (code == KC_MS_RIGHT)) { + mousekey_x_dir = (code == KC_MS_RIGHT) ? 1 : -1; + if (mousekey_frame < 2) mouse_report.x = move_unit(0); + } + +# else // no inertia + + if (code == KC_MS_UP) + mouse_report.y = move_unit() * -1; + else if (code == KC_MS_DOWN) + mouse_report.y = move_unit(); + else if (code == KC_MS_LEFT) + mouse_report.x = move_unit() * -1; + else if (code == KC_MS_RIGHT) + mouse_report.x = move_unit(); + +# endif // inertia or not + + else if (code == KC_MS_WH_UP) + mouse_report.v = wheel_unit(); + else if (code == KC_MS_WH_DOWN) + mouse_report.v = wheel_unit() * -1; + else if (code == KC_MS_WH_LEFT) + mouse_report.h = wheel_unit() * -1; + else if (code == KC_MS_WH_RIGHT) + mouse_report.h = wheel_unit(); + else if (IS_MOUSEKEY_BUTTON(code)) + mouse_report.buttons |= 1 << (code - KC_MS_BTN1); + else if (code == KC_MS_ACCEL0) + mousekey_accel |= (1 << 0); + else if (code == KC_MS_ACCEL1) + mousekey_accel |= (1 << 1); + else if (code == KC_MS_ACCEL2) + mousekey_accel |= (1 << 2); +} + +void mousekey_off(uint8_t code) { +# ifdef MOUSEKEY_INERTIA + + // key release clears impulse unless opposite direction is held + if ((code == KC_MS_UP) && (mousekey_y_dir < 1)) + mousekey_y_dir = 0; + else if ((code == KC_MS_DOWN) && (mousekey_y_dir > -1)) + mousekey_y_dir = 0; + else if ((code == KC_MS_LEFT) && (mousekey_x_dir < 1)) + mousekey_x_dir = 0; + else if ((code == KC_MS_RIGHT) && (mousekey_x_dir > -1)) + mousekey_x_dir = 0; + +# else // no inertia + + if (code == KC_MS_UP && mouse_report.y < 0) + mouse_report.y = 0; + else if (code == KC_MS_DOWN && mouse_report.y > 0) + mouse_report.y = 0; + else if (code == KC_MS_LEFT && mouse_report.x < 0) + mouse_report.x = 0; + else if (code == KC_MS_RIGHT && mouse_report.x > 0) + mouse_report.x = 0; + +# endif // inertia or not + + else if (code == KC_MS_WH_UP && mouse_report.v > 0) + mouse_report.v = 0; + else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) + mouse_report.v = 0; + else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) + mouse_report.h = 0; + else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) + mouse_report.h = 0; + else if (IS_MOUSEKEY_BUTTON(code)) + mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1)); + else if (code == KC_MS_ACCEL0) + mousekey_accel &= ~(1 << 0); + else if (code == KC_MS_ACCEL1) + mousekey_accel &= ~(1 << 1); + else if (code == KC_MS_ACCEL2) + mousekey_accel &= ~(1 << 2); + if (mouse_report.x == 0 && mouse_report.y == 0) { + mousekey_repeat = 0; +# ifdef MK_KINETIC_SPEED + mouse_timer = 0; +# endif /* #ifdef MK_KINETIC_SPEED */ + } + if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0; +} + +#else /* #ifndef MK_3_SPEED */ + +enum { mkspd_unmod, mkspd_0, mkspd_1, mkspd_2, mkspd_COUNT }; +# ifndef MK_MOMENTARY_ACCEL +static uint8_t mk_speed = mkspd_1; +# else +static uint8_t mk_speed = mkspd_unmod; +static uint8_t mkspd_DEFAULT = mkspd_unmod; +# endif +static uint16_t last_timer_c = 0; +static uint16_t last_timer_w = 0; +uint16_t c_offsets[mkspd_COUNT] = {MK_C_OFFSET_UNMOD, MK_C_OFFSET_0, MK_C_OFFSET_1, MK_C_OFFSET_2}; +uint16_t c_intervals[mkspd_COUNT] = {MK_C_INTERVAL_UNMOD, MK_C_INTERVAL_0, MK_C_INTERVAL_1, MK_C_INTERVAL_2}; +uint16_t w_offsets[mkspd_COUNT] = {MK_W_OFFSET_UNMOD, MK_W_OFFSET_0, MK_W_OFFSET_1, MK_W_OFFSET_2}; +uint16_t w_intervals[mkspd_COUNT] = {MK_W_INTERVAL_UNMOD, MK_W_INTERVAL_0, MK_W_INTERVAL_1, MK_W_INTERVAL_2}; + +void mousekey_task(void) { + // report cursor and scroll movement independently + report_mouse_t tmpmr = mouse_report; + mouse_report.x = 0; + mouse_report.y = 0; + mouse_report.v = 0; + mouse_report.h = 0; + + if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) { + mouse_report.x = tmpmr.x; + mouse_report.y = tmpmr.y; + } + if ((tmpmr.h || tmpmr.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) { + mouse_report.v = tmpmr.v; + mouse_report.h = tmpmr.h; + } + + if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) { + mousekey_send(); + } + memcpy(&mouse_report, &tmpmr, sizeof(tmpmr)); +} + +void adjust_speed(void) { + uint16_t const c_offset = c_offsets[mk_speed]; + uint16_t const w_offset = w_offsets[mk_speed]; + if (mouse_report.x > 0) mouse_report.x = c_offset; + if (mouse_report.x < 0) mouse_report.x = c_offset * -1; + if (mouse_report.y > 0) mouse_report.y = c_offset; + if (mouse_report.y < 0) mouse_report.y = c_offset * -1; + if (mouse_report.h > 0) mouse_report.h = w_offset; + if (mouse_report.h < 0) mouse_report.h = w_offset * -1; + if (mouse_report.v > 0) mouse_report.v = w_offset; + if (mouse_report.v < 0) mouse_report.v = w_offset * -1; + // adjust for diagonals + if (mouse_report.x && mouse_report.y) { + mouse_report.x = times_inv_sqrt2(mouse_report.x); + if (mouse_report.x == 0) { + mouse_report.x = 1; + } + mouse_report.y = times_inv_sqrt2(mouse_report.y); + if (mouse_report.y == 0) { + mouse_report.y = 1; + } + } + if (mouse_report.h && mouse_report.v) { + mouse_report.h = times_inv_sqrt2(mouse_report.h); + mouse_report.v = times_inv_sqrt2(mouse_report.v); + } +} + +void mousekey_on(uint8_t code) { + uint16_t const c_offset = c_offsets[mk_speed]; + uint16_t const w_offset = w_offsets[mk_speed]; + uint8_t const old_speed = mk_speed; + if (code == KC_MS_UP) + mouse_report.y = c_offset * -1; + else if (code == KC_MS_DOWN) + mouse_report.y = c_offset; + else if (code == KC_MS_LEFT) + mouse_report.x = c_offset * -1; + else if (code == KC_MS_RIGHT) + mouse_report.x = c_offset; + else if (code == KC_MS_WH_UP) + mouse_report.v = w_offset; + else if (code == KC_MS_WH_DOWN) + mouse_report.v = w_offset * -1; + else if (code == KC_MS_WH_LEFT) + mouse_report.h = w_offset * -1; + else if (code == KC_MS_WH_RIGHT) + mouse_report.h = w_offset; + else if (IS_MOUSEKEY_BUTTON(code)) + mouse_report.buttons |= 1 << (code - KC_MS_BTN1); + else if (code == KC_MS_ACCEL0) + mk_speed = mkspd_0; + else if (code == KC_MS_ACCEL1) + mk_speed = mkspd_1; + else if (code == KC_MS_ACCEL2) + mk_speed = mkspd_2; + if (mk_speed != old_speed) adjust_speed(); +} + +void mousekey_off(uint8_t code) { +# ifdef MK_MOMENTARY_ACCEL + uint8_t const old_speed = mk_speed; +# endif + if (code == KC_MS_UP && mouse_report.y < 0) + mouse_report.y = 0; + else if (code == KC_MS_DOWN && mouse_report.y > 0) + mouse_report.y = 0; + else if (code == KC_MS_LEFT && mouse_report.x < 0) + mouse_report.x = 0; + else if (code == KC_MS_RIGHT && mouse_report.x > 0) + mouse_report.x = 0; + else if (code == KC_MS_WH_UP && mouse_report.v > 0) + mouse_report.v = 0; + else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) + mouse_report.v = 0; + else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) + mouse_report.h = 0; + else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) + mouse_report.h = 0; + else if (IS_MOUSEKEY_BUTTON(code)) + mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1)); +# ifdef MK_MOMENTARY_ACCEL + else if (code == KC_MS_ACCEL0) + mk_speed = mkspd_DEFAULT; + else if (code == KC_MS_ACCEL1) + mk_speed = mkspd_DEFAULT; + else if (code == KC_MS_ACCEL2) + mk_speed = mkspd_DEFAULT; + if (mk_speed != old_speed) adjust_speed(); +# endif +} + +#endif /* #ifndef MK_3_SPEED */ + +void mousekey_send(void) { + mousekey_debug(); + uint32_t time = timer_read(); + if (mouse_report.x || mouse_report.y) last_timer_c = time; + if (mouse_report.v || mouse_report.h) last_timer_w = time; + host_mouse_send(&mouse_report); +} + +void mousekey_clear(void) { + mouse_report = (report_mouse_t){}; + mousekey_repeat = 0; + mousekey_wheel_repeat = 0; + mousekey_accel = 0; +#ifdef MOUSEKEY_INERTIA + mousekey_frame = 0; + mousekey_x_inertia = 0; + mousekey_y_inertia = 0; + mousekey_x_dir = 0; + mousekey_y_dir = 0; +#endif +} + +static inline void mousekey_debug(void) { + LOG_DBG("mousekey [btn|x y v h](rep/acl): [%02x|%d %d %d %d](%d/%d)",mouse_report.buttons,mouse_report.x,mouse_report.y,mouse_report.v,mouse_report.h,mousekey_repeat,mousekey_accel); + // if (!debug_mouse) return; + // print("mousekey [btn|x y v h](rep/acl): ["); + // print_hex8(mouse_report.buttons); + // print("|"); + // print_decs(mouse_report.x); + // print(" "); + // print_decs(mouse_report.y); + // print(" "); + // print_decs(mouse_report.v); + // print(" "); + // print_decs(mouse_report.h); + // print("]("); + // print_dec(mousekey_repeat); + // print("/"); + // print_dec(mousekey_accel); + // print(")\n"); +} + +report_mouse_t mousekey_get_report(void) { + return mouse_report; +} + +bool should_mousekey_report_send(report_mouse_t *mouse_report) { + return mouse_report->x || mouse_report->y || mouse_report->v || mouse_report->h; +} +__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report) { + // memcmp doesn't work here because of the `report_id` field when using + // shared mouse endpoint + bool changed = ((new_report->buttons != old_report->buttons) || + (new_report->x != 0 && new_report->x != old_report->x) || (new_report->y != 0 && new_report->y != old_report->y) || (new_report->h != 0 && new_report->h != old_report->h) || (new_report->v != 0 && new_report->v != old_report->v)); + return changed; +} + +#define MY_STACK_SIZE 1024 +#define MY_PRIORITY 2 +void zmk_mouse_thread(void); +static void mouse_sleep_worker(struct k_work *work) ; + +K_THREAD_DEFINE(zmk_mouse_tid, MY_STACK_SIZE, + zmk_mouse_thread, NULL, NULL, NULL, + MY_PRIORITY, 0, 0); + +static K_WORK_DELAYABLE_DEFINE(mouse_sleep_work, mouse_sleep_worker); + +static K_SEM_DEFINE(thread_wait_sem, 0, 1); +static bool zmk_mouse_enable; +static void mouse_sleep_worker(struct k_work *work) +{ + // k_thread_suspend(zmk_mouse_tid); + zmk_mouse_enable =false; + LOG_DBG("."); +} +void zmk_mouse_thread(void) +{ + // k_sem_take(&thread_wait_sem,K_FOREVER); + LOG_DBG("."); + static uint8_t count=0; + while(1) + { + if(!zmk_mouse_enable) + { + k_sem_take(&thread_wait_sem,K_FOREVER); + zmk_mouse_enable =true; + } + mousekey_task(); + k_msleep(8); + if(count++>125) + { + LOG_DBG("."); + count=0; + } + } +} + +static int mouse_listener_keycode_pressed(const struct zmk_keycode_state_changed *ev) { + LOG_DBG("usage_page 0x%02X keycode 0x%02X", + ev->usage_page, ev->keycode); + if(ev->usage_page ==HID_USAGE_GEN_BUTTON) + { + if(!zmk_mouse_enable) + k_sem_give(&thread_wait_sem); + k_work_cancel_delayable(&mouse_sleep_work); + // k_thread_resume(zmk_mouse_tid); + mousekey_on(ev->keycode); + return zmk_endpoints_send_report(ev->usage_page); + } + return 0; +} +static int mouse_listener_keycode_released(const struct zmk_keycode_state_changed *ev) { + LOG_DBG("usage_page 0x%02X keycode 0x%02X ", + ev->usage_page, ev->keycode); + if(ev->usage_page ==HID_USAGE_GEN_BUTTON) + { + mousekey_off(ev->keycode); + k_work_reschedule(&mouse_sleep_work,K_MSEC(200)); + return zmk_endpoints_send_report(ev->usage_page); + } + return 0; +} +int mouse_listener(const zmk_event_t *eh) { + const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); + if (ev) { + if (ev->state) { + mouse_listener_keycode_pressed(ev); + } else { + mouse_listener_keycode_released(ev); + } + } + return 0; +} +ZMK_LISTENER(mouse_listener, mouse_listener); +ZMK_SUBSCRIPTION(mouse_listener, zmk_keycode_state_changed); + + diff --git a/app/src/launcher/mousekey.h b/app/src/launcher/mousekey.h new file mode 100644 index 00000000000..b10a159adf0 --- /dev/null +++ b/app/src/launcher/mousekey.h @@ -0,0 +1,220 @@ +/* +Copyright 2011 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include + + +#ifndef MK_3_SPEED + +/* max value on report descriptor */ +# ifndef MOUSEKEY_MOVE_MAX +# define MOUSEKEY_MOVE_MAX 127 +# elif MOUSEKEY_MOVE_MAX > 127 +# error MOUSEKEY_MOVE_MAX needs to be smaller than 127 +# endif + +# ifndef MOUSEKEY_WHEEL_MAX +# define MOUSEKEY_WHEEL_MAX 127 +# elif MOUSEKEY_WHEEL_MAX > 127 +# error MOUSEKEY_WHEEL_MAX needs to be smaller than 127 +# endif + +# ifndef MOUSEKEY_MOVE_DELTA +# if defined(MK_KINETIC_SPEED) +# define MOUSEKEY_MOVE_DELTA 16 +# elif defined(MOUSEKEY_INERTIA) +# define MOUSEKEY_MOVE_DELTA 1 +# else +# define MOUSEKEY_MOVE_DELTA 8 +# endif +# endif +# ifndef MOUSEKEY_DELAY +# if defined(MK_KINETIC_SPEED) +# define MOUSEKEY_DELAY 5 +# elif defined(MOUSEKEY_INERTIA) +# define MOUSEKEY_DELAY 150 // allow single-pixel movements before repeat activates +# else +# define MOUSEKEY_DELAY 10 +# endif +# endif +# ifndef MOUSEKEY_INTERVAL +# if defined(MK_KINETIC_SPEED) +# define MOUSEKEY_INTERVAL 10 +# elif defined(MOUSEKEY_INERTIA) +# define MOUSEKEY_INTERVAL 16 // 60 fps +# else +# define MOUSEKEY_INTERVAL 20 +# endif +# endif +# ifndef MOUSEKEY_MAX_SPEED +# if defined(MOUSEKEY_INERTIA) +# define MOUSEKEY_MAX_SPEED 32 +# else +# define MOUSEKEY_MAX_SPEED 10 +# endif +# endif +# ifndef MOUSEKEY_TIME_TO_MAX +# if defined(MOUSEKEY_INERTIA) +# define MOUSEKEY_TIME_TO_MAX 32 +# else +# define MOUSEKEY_TIME_TO_MAX 30 +# endif +# endif +# ifndef MOUSEKEY_WHEEL_DELAY +# define MOUSEKEY_WHEEL_DELAY 10 +# endif +# ifndef MOUSEKEY_WHEEL_INTERVAL +# define MOUSEKEY_WHEEL_INTERVAL 80 +# endif +# ifndef MOUSEKEY_WHEEL_DELTA +# define MOUSEKEY_WHEEL_DELTA 1 +# endif +# ifndef MOUSEKEY_WHEEL_MAX_SPEED +# define MOUSEKEY_WHEEL_MAX_SPEED 8 +# endif +# ifndef MOUSEKEY_WHEEL_TIME_TO_MAX +# define MOUSEKEY_WHEEL_TIME_TO_MAX 40 +# endif + +# ifndef MOUSEKEY_FRICTION +# define MOUSEKEY_FRICTION 24 // 0 to 255 +# endif +# ifndef MOUSEKEY_INITIAL_SPEED +# define MOUSEKEY_INITIAL_SPEED 100 +# endif +# ifndef MOUSEKEY_BASE_SPEED +# define MOUSEKEY_BASE_SPEED 5000 +# endif +# ifndef MOUSEKEY_DECELERATED_SPEED +# define MOUSEKEY_DECELERATED_SPEED 400 +# endif +# ifndef MOUSEKEY_ACCELERATED_SPEED +# define MOUSEKEY_ACCELERATED_SPEED 3000 +# endif +# ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS +# define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 16 +# endif +# ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS +# define MOUSEKEY_WHEEL_BASE_MOVEMENTS 32 +# endif +# ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS +# define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48 +# endif +# ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS +# define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8 +# endif + +#else /* #ifndef MK_3_SPEED */ + +# ifndef MK_C_OFFSET_UNMOD +# define MK_C_OFFSET_UNMOD 16 +# endif +# ifndef MK_C_INTERVAL_UNMOD +# define MK_C_INTERVAL_UNMOD 16 +# endif +# ifndef MK_C_OFFSET_0 +# define MK_C_OFFSET_0 1 +# endif +# ifndef MK_C_INTERVAL_0 +# define MK_C_INTERVAL_0 32 +# endif +# ifndef MK_C_OFFSET_1 +# define MK_C_OFFSET_1 4 +# endif +# ifndef MK_C_INTERVAL_1 +# define MK_C_INTERVAL_1 16 +# endif +# ifndef MK_C_OFFSET_2 +# define MK_C_OFFSET_2 32 +# endif +# ifndef MK_C_INTERVAL_2 +# define MK_C_INTERVAL_2 16 +# endif + +# ifndef MK_W_OFFSET_UNMOD +# define MK_W_OFFSET_UNMOD 1 +# endif +# ifndef MK_W_INTERVAL_UNMOD +# define MK_W_INTERVAL_UNMOD 40 +# endif +# ifndef MK_W_OFFSET_0 +# define MK_W_OFFSET_0 1 +# endif +# ifndef MK_W_INTERVAL_0 +# define MK_W_INTERVAL_0 360 +# endif +# ifndef MK_W_OFFSET_1 +# define MK_W_OFFSET_1 1 +# endif +# ifndef MK_W_INTERVAL_1 +# define MK_W_INTERVAL_1 120 +# endif +# ifndef MK_W_OFFSET_2 +# define MK_W_OFFSET_2 1 +# endif +# ifndef MK_W_INTERVAL_2 +# define MK_W_INTERVAL_2 20 +# endif + +#endif /* #ifndef MK_3_SPEED */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t mk_delay; +extern uint8_t mk_interval; +extern uint8_t mk_max_speed; +extern uint8_t mk_time_to_max; +extern uint8_t mk_wheel_max_speed; +extern uint8_t mk_wheel_time_to_max; + +struct _report_mouse { + uint8_t report_id; + uint8_t buttons; + + int8_t x; + int8_t y; + int8_t v; + int8_t h; +} __packed; + +typedef struct _report_mouse report_mouse_t; + +#define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a))))) +#define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX) +#define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX) +#define TIMER_DIFF_32(a, b) TIMER_DIFF(a, b, UINT32_MAX) +#define TIMER_DIFF_RAW(a, b) TIMER_DIFF_8(a, b) + + + +void mousekey_task(void); +void mousekey_on(uint8_t code); +void mousekey_off(uint8_t code); +void mousekey_clear(void); +void mousekey_send(void); +report_mouse_t mousekey_get_report(void); +bool should_mousekey_report_send(report_mouse_t *mouse_report); +int host_mouse_send(report_mouse_t *rp); +bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report); + +#ifdef __cplusplus +} +#endif diff --git a/app/src/launcher/send_string.c b/app/src/launcher/send_string.c new file mode 100644 index 00000000000..1b71cd1123b --- /dev/null +++ b/app/src/launcher/send_string.c @@ -0,0 +1,341 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "send_string.h" + +#include +#include +#include "keycodes.h" + +#include + +#include +#include +#include +LOG_MODULE_DECLARE(zmk,CONFIG_ZMK_LOG_LEVEL); + +#define PROGMEM + + +// clang-format off + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [Shift] needs to be sent with the keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_shift_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 0), + KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 1, 0, 1, 0, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 1, 1), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0) +}; + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [AltGr] needs to be sent with the keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_altgr_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [Space] needs to be sent after the keycode + */ +__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +/* Look-up table to convert an ASCII character to a keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = { + // NUL SOH STX ETX EOT ENQ ACK BEL + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // BS TAB LF VT FF CR SO SI + KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // DLE DC1 DC2 DC3 DC4 NAK SYN ETB + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // CAN EM SUB ESC FS GS RS US + XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + + // ! " # $ % & ' + KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, + // ( ) * + , - . / + KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + // 0 1 2 3 4 5 6 7 + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + // 8 9 : ; < = > ? + KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, + // @ A B C D E F G + KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + // H I J K L M N O + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + // P Q R S T U V W + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + // X Y Z [ \ ] ^ _ + KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, + // ` a b c d e f g + KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + // h i j k l m n o + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + // p q r s t u v w + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + // x y z { | } ~ DEL + KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL +}; + +// clang-format on + +// Note: we bit-pack in "reverse" order to optimize loading +#define PGM_LOADBIT(mem, pos) ((mem[(pos) / 8] >> ((pos) % 8)) & 0x01) + +#ifndef TAP_CODE_DELAY +# define TAP_CODE_DELAY 10 +#endif +#ifndef TAP_HOLD_CAPS_DELAY +# define TAP_HOLD_CAPS_DELAY 80 +#endif +void via_keycode_to_binding(uint8_t keycode,struct zmk_behavior_binding * binding); +int zmk_macro_queue_add(uint8_t code,uint8_t type ,uint16_t delay); + + +struct q_item { + uint8_t code; + uint8_t type; + uint16_t delay; +}; +K_MSGQ_DEFINE(zmk_macro_queue_msgq, sizeof(struct q_item), 256, 4); +void send_string_with_delay(const char *string, uint8_t interval) { + + while (1) { + char ascii_code = *string; + if (!ascii_code) break; + if (ascii_code == SS_QMK_PREFIX) { + ascii_code = *(++string); + if (ascii_code == SS_TAP_CODE) { + // tap + uint8_t keycode = *(++string); + zmk_macro_queue_add(keycode,SS_TAP_CODE,0); + + } else if (ascii_code == SS_DOWN_CODE) { + // down + uint8_t keycode = *(++string); + // register_code(keycode); + zmk_macro_queue_add(keycode,SS_DOWN_CODE,0); + LOG_DBG("press,code:%x",keycode); + + } else if (ascii_code == SS_UP_CODE) { + // up + uint8_t keycode = *(++string); + // unregister_code(keycode); + zmk_macro_queue_add(keycode,SS_UP_CODE,0); + LOG_DBG("release,code:%x",keycode); + + } else if (ascii_code == SS_DELAY_CODE) { + // delay + int ms = 0; + uint8_t keycode = *(++string); + while (isdigit(keycode)) { + ms *= 10; + ms += keycode - '0'; + keycode = *(++string); + } + LOG_DBG("delay:%d",ms); + zmk_macro_queue_add(0,SS_DELAY_CODE,ms); + } + } else { + send_char(ascii_code); + + } + ++string; + + } +} +void send_string_end(void) +{ + struct q_item item; + + uint16_t num = k_msgq_num_used_get(&zmk_macro_queue_msgq); + LOG_DBG("queue num:%d",num); + const int ret = k_msgq_get(&zmk_macro_queue_msgq, &item, K_NO_WAIT); + if (ret < 0) { + return ; + } + LOG_DBG("item type:%d,code:%x,delay:%d",item.type,item.code,item.delay); + struct zmk_behavior_binding keycode_binding; + via_keycode_to_binding(item.code,&keycode_binding); + + switch(item.type) + { + + case SS_TAP_CODE: + { + uint16_t delay = (item.code == KC_CAPS_LOCK) ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY; + + zmk_behavior_queue_add(0,keycode_binding,true,delay); + zmk_behavior_queue_add(0,keycode_binding,false,TAP_CODE_DELAY); + } + break; + case SS_DOWN_CODE: + zmk_behavior_queue_add(0,keycode_binding,true,TAP_CODE_DELAY); + break; + + case SS_UP_CODE: + zmk_behavior_queue_add(0,keycode_binding,false,TAP_CODE_DELAY); + break; + } +} +void send_char(char ascii_code) { + + + uint8_t keycode = ascii_to_keycode_lut[(uint8_t)ascii_code]; + bool is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code); + bool is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code); + bool is_dead = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code); + + if (is_shifted) { + // register_code(KC_LEFT_SHIFT); + zmk_macro_queue_add(KC_LEFT_SHIFT,SS_DOWN_CODE,0); + } + if (is_altgred) { + // register_code(KC_RIGHT_ALT); + + zmk_macro_queue_add(KC_RIGHT_ALT,SS_DOWN_CODE,0); + } + // tap_code(keycode); + zmk_macro_queue_add(keycode,SS_TAP_CODE,0); + + + if (is_altgred) { + // unregister_code(KC_RIGHT_ALT); + zmk_macro_queue_add(KC_RIGHT_ALT,SS_UP_CODE,0); + } + if (is_shifted) { + // unregister_code(KC_LEFT_SHIFT); + zmk_macro_queue_add(KC_LEFT_SHIFT,SS_UP_CODE,0); + } + if (is_dead) { + // tap_code(KC_SPACE); + zmk_macro_queue_add(KC_SPACE,SS_TAP_CODE,0); + + } +} + + + +int zmk_macro_queue_add(uint8_t code,uint8_t type ,uint16_t delay) { + + struct q_item item = {.code = code, .type = type, .delay = delay}; + + int ret = k_msgq_put(&zmk_macro_queue_msgq, &item, K_NO_WAIT); + if (ret < 0) { + LOG_ERR("macro queue full"); + return ret; + } + LOG_DBG("macro queue num:%d",k_msgq_num_used_get(&zmk_macro_queue_msgq)); + if(k_msgq_num_used_get(&zmk_macro_queue_msgq)>=2) + { + struct q_item item1={.delay =0}; + struct q_item item2={.delay =0}; + ret =k_msgq_get(&zmk_macro_queue_msgq,&item1,K_NO_WAIT); + if(ret <0) + { + return ret; + } + LOG_DBG("item1 type:%d,char:%c,delay:%d",item1.type,item1.code,item1.delay); + ret =k_msgq_peek(&zmk_macro_queue_msgq,&item2); + if(ret <0 ) + { + return ret; + } + LOG_DBG("item2 type:%d,char:%c,delay:%d",item2.type,item2.code,item2.delay); + if(item2.type ==SS_DELAY_CODE) + { + k_msgq_get(&zmk_macro_queue_msgq,&item2,K_NO_WAIT); + } + + struct zmk_behavior_binding keycode_binding; + via_keycode_to_binding(item1.code,&keycode_binding); + switch(item1.type) + { + case SS_TAP_CODE: + { + uint16_t delay = (item1.code == KC_CAPS_LOCK) ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY; + + zmk_behavior_queue_add(0,keycode_binding,true,delay); + zmk_behavior_queue_add(0,keycode_binding,false,item2.delay ? item2.delay: TAP_CODE_DELAY); + + } + break; + + case SS_DOWN_CODE: + zmk_behavior_queue_add(0,keycode_binding,true,item2.delay ? item2.delay: TAP_CODE_DELAY); + + break; + case SS_UP_CODE: + zmk_behavior_queue_add(0,keycode_binding,false,item2.delay ? item2.delay: TAP_CODE_DELAY); + break; + + } + + + } + return 0; +} + + diff --git a/app/src/launcher/send_string.h b/app/src/launcher/send_string.h new file mode 100644 index 00000000000..4f78d2938da --- /dev/null +++ b/app/src/launcher/send_string.h @@ -0,0 +1,156 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file + * + * \defgroup send_string Send String API + * + * \brief These functions allow you to create macros by typing out sequences of keystrokes. + * \{ + */ + +#include + +// #include "progmem.h" +#include "send_string_keycodes.h" + +// Look-Up Tables (LUTs) to convert ASCII character to keycode sequence. +extern const uint8_t ascii_to_shift_lut[16]; +extern const uint8_t ascii_to_altgr_lut[16]; +extern const uint8_t ascii_to_dead_lut[16]; +extern const uint8_t ascii_to_keycode_lut[128]; + +// clang-format off +#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \ + ( ((a) ? 1 : 0) << 0 \ + | ((b) ? 1 : 0) << 1 \ + | ((c) ? 1 : 0) << 2 \ + | ((d) ? 1 : 0) << 3 \ + | ((e) ? 1 : 0) << 4 \ + | ((f) ? 1 : 0) << 5 \ + | ((g) ? 1 : 0) << 6 \ + | ((h) ? 1 : 0) << 7 ) +// clang-format on + +/** + * \brief Type out a string of ASCII characters. + * + * This function simply calls `send_string_with_delay(string, 0)`. + * + * Most keycodes from the basic keycode range are also supported by way of a special sequence - see `send_string_keycodes.h`. + * + * \param string The string to type out. + */ +void send_string(const char *string); + +/** + * \brief Type out a string of ASCII characters, with a delay between each character. + * + * \param string The string to type out. + * \param interval The amount of time, in milliseconds, to wait before typing the next character. + */ +void send_string_with_delay(const char *string, uint8_t interval); + +/** + * \brief Type out an ASCII character. + * + * \param ascii_code The character to type. + */ +void send_char(char ascii_code); + +void send_string_end(void); + +/** + * \brief Type out an eight digit (unsigned 32-bit) hexadecimal value. + * + * The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`. + * + * \param number The value to type, from 0 to 4,294,967,295. + */ +void send_dword(uint32_t number); + +/** + * \brief Type out a four digit (unsigned 16-bit) hexadecimal value. + * + * The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`. + * + * \param number The value to type, from 0 to 65,535. + */ +void send_word(uint16_t number); + +/** + * \brief Type out a two digit (8-bit) hexadecimal value. + * + * The format is `[0-9a-f]{2}`, eg. `00` through `ff`. + * + * \param number The value to type, from 0 to 255. + */ +void send_byte(uint8_t number); + +/** + * \brief Type out a single hexadecimal digit. + * + * The format is `[0-9a-f]{1}`, eg. `0` through `f`. + * + * \param number The value to type, from 0 to 15. + */ +void send_nibble(uint8_t number); + +/** + * \brief Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`. + */ +void tap_random_base64(void); + +#if defined(__AVR__) || defined(__DOXYGEN__) +/** + * \brief Type out a PROGMEM string of ASCII characters. + * + * On ARM devices, this function is simply an alias for send_string_with_delay(string, 0). + * + * \param string The string to type out. + */ +void send_string_P(const char *string); + +/** + * \brief Type out a PROGMEM string of ASCII characters, with a delay between each character. + * + * On ARM devices, this function is simply an alias for send_string_with_delay(string, interval). + * + * \param string The string to type out. + * \param interval The amount of time, in milliseconds, to wait before typing the next character. + */ +void send_string_with_delay_P(const char *string, uint8_t interval); +#else +# define send_string_P(string) send_string_with_delay(string, 0) +# define send_string_with_delay_P(string, interval) send_string_with_delay(string, interval) +#endif + +/** + * \brief Shortcut macro for send_string_with_delay_P(PSTR(string), 0). + * + * On ARM devices, this define evaluates to send_string_with_delay(string, 0). + */ +#define SEND_STRING(string) send_string_with_delay_P(PSTR(string), 0) + +/** + * \brief Shortcut macro for send_string_with_delay_P(PSTR(string), interval). + * + * On ARM devices, this define evaluates to send_string_with_delay(string, interval). + */ +#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval) + +/** \} */ diff --git a/app/src/launcher/send_string_keycodes.h b/app/src/launcher/send_string_keycodes.h new file mode 100644 index 00000000000..54b83820531 --- /dev/null +++ b/app/src/launcher/send_string_keycodes.h @@ -0,0 +1,445 @@ +/* Copyright 2019 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +// clang-format off + +/* Punctuation */ +#define X_ENT X_ENTER +#define X_ESC X_ESCAPE +#define X_BSPC X_BACKSPACE +#define X_SPC X_SPACE +#define X_MINS X_MINUS +#define X_EQL X_EQUAL +#define X_LBRC X_LEFT_BRACKET +#define X_RBRC X_RIGHT_BRACKET +#define X_BSLS X_BACKSLASH +#define X_NUHS X_NONUS_HASH +#define X_SCLN X_SEMICOLON +#define X_QUOT X_QUOTE +#define X_GRV X_GRAVE +#define X_COMM X_COMMA +#define X_SLSH X_SLASH +#define X_NUBS X_NONUS_BACKSLASH + +/* Lock Keys */ +#define X_CAPS X_CAPS_LOCK +#define X_SCRL X_SCROLL_LOCK +#define X_NUM X_NUM_LOCK +#define X_LCAP X_LOCKING_CAPS_LOCK +#define X_LNUM X_LOCKING_NUM_LOCK +#define X_LSCR X_LOCKING_SCROLL_LOCK + +/* Commands */ +#define X_PSCR X_PRINT_SCREEN +#define X_PAUS X_PAUSE +#define X_BRK X_PAUSE +#define X_INS X_INSERT +#define X_PGUP X_PAGE_UP +#define X_DEL X_DELETE +#define X_PGDN X_PAGE_DOWN +#define X_RGHT X_RIGHT +#define X_APP X_APPLICATION +#define X_EXEC X_EXECUTE +#define X_SLCT X_SELECT +#define X_AGIN X_AGAIN +#define X_PSTE X_PASTE +#define X_ERAS X_ALTERNATE_ERASE +#define X_SYRQ X_SYSTEM_REQUEST +#define X_CNCL X_CANCEL +#define X_CLR X_CLEAR +#define X_PRIR X_PRIOR +#define X_RETN X_RETURN +#define X_SEPR X_SEPARATOR +#define X_CLAG X_CLEAR_AGAIN +#define X_CRSL X_CRSEL +#define X_EXSL X_EXSEL + +/* Keypad */ +#define X_PSLS X_KP_SLASH +#define X_PAST X_KP_ASTERISK +#define X_PMNS X_KP_MINUS +#define X_PPLS X_KP_PLUS +#define X_PENT X_KP_ENTER +#define X_P1 X_KP_1 +#define X_P2 X_KP_2 +#define X_P3 X_KP_3 +#define X_P4 X_KP_4 +#define X_P5 X_KP_5 +#define X_P6 X_KP_6 +#define X_P7 X_KP_7 +#define X_P8 X_KP_8 +#define X_P9 X_KP_9 +#define X_P0 X_KP_0 +#define X_PDOT X_KP_DOT +#define X_PEQL X_KP_EQUAL +#define X_PCMM X_KP_COMMA + +/* Language Specific */ +#define X_INT1 X_INTERNATIONAL_1 +#define X_INT2 X_INTERNATIONAL_2 +#define X_INT3 X_INTERNATIONAL_3 +#define X_INT4 X_INTERNATIONAL_4 +#define X_INT5 X_INTERNATIONAL_5 +#define X_INT6 X_INTERNATIONAL_6 +#define X_INT7 X_INTERNATIONAL_7 +#define X_INT8 X_INTERNATIONAL_8 +#define X_INT9 X_INTERNATIONAL_9 +#define X_LNG1 X_LANGUAGE_1 +#define X_LNG2 X_LANGUAGE_2 +#define X_LNG3 X_LANGUAGE_3 +#define X_LNG4 X_LANGUAGE_4 +#define X_LNG5 X_LANGUAGE_5 +#define X_LNG6 X_LANGUAGE_6 +#define X_LNG7 X_LANGUAGE_7 +#define X_LNG8 X_LANGUAGE_8 +#define X_LNG9 X_LANGUAGE_9 + +/* Modifiers */ +#define X_LCTL X_LEFT_CTRL +#define X_LSFT X_LEFT_SHIFT +#define X_LALT X_LEFT_ALT +#define X_LOPT X_LEFT_ALT +#define X_LGUI X_LEFT_GUI +#define X_LCMD X_LEFT_GUI +#define X_LWIN X_LEFT_GUI +#define X_RCTL X_RIGHT_CTRL +#define X_RSFT X_RIGHT_SHIFT +#define X_RALT X_RIGHT_ALT +#define X_ALGR X_RIGHT_ALT +#define X_ROPT X_RIGHT_ALT +#define X_RGUI X_RIGHT_GUI +#define X_RCMD X_RIGHT_GUI +#define X_RWIN X_RIGHT_GUI + +/* Generic Desktop Page (0x01) */ +#define X_PWR X_SYSTEM_POWER +#define X_SLEP X_SYSTEM_SLEEP +#define X_WAKE X_SYSTEM_WAKE + +/* Consumer Page (0x0C) */ +#define X_MUTE X_AUDIO_MUTE +#define X_VOLU X_AUDIO_VOL_UP +#define X_VOLD X_AUDIO_VOL_DOWN +#define X_MNXT X_MEDIA_NEXT_TRACK +#define X_MPRV X_MEDIA_PREV_TRACK +#define X_MSTP X_MEDIA_STOP +#define X_MPLY X_MEDIA_PLAY_PAUSE +#define X_MSEL X_MEDIA_SELECT +#define X_EJCT X_MEDIA_EJECT +#define X_CALC X_CALCULATOR +#define X_MYCM X_MY_COMPUTER +#define X_WSCH X_WWW_SEARCH +#define X_WHOM X_WWW_HOME +#define X_WBAK X_WWW_BACK +#define X_WFWD X_WWW_FORWARD +#define X_WSTP X_WWW_STOP +#define X_WREF X_WWW_REFRESH +#define X_WFAV X_WWW_FAVORITES +#define X_MFFD X_MEDIA_FAST_FORWARD +#define X_MRWD X_MEDIA_REWIND +#define X_BRIU X_BRIGHTNESS_UP +#define X_BRID X_BRIGHTNESS_DOWN +#define X_CPNL X_CONTROL_PANEL +#define X_ASST X_ASSISTANT + +/* System Specific */ +#define X_BRMU X_PAUSE +#define X_BRMD X_SCROLL_LOCK + +/* Mouse Keys */ +#define X_MS_U X_MS_UP +#define X_MS_D X_MS_DOWN +#define X_MS_L X_MS_LEFT +#define X_MS_R X_MS_RIGHT +#define X_BTN1 X_MS_BTN1 +#define X_BTN2 X_MS_BTN2 +#define X_BTN3 X_MS_BTN3 +#define X_BTN4 X_MS_BTN4 +#define X_BTN5 X_MS_BTN5 +#define X_BTN6 X_MS_BTN6 +#define X_BTN7 X_MS_BTN7 +#define X_BTN8 X_MS_BTN8 +#define X_WH_U X_MS_WH_UP +#define X_WH_D X_MS_WH_DOWN +#define X_WH_L X_MS_WH_LEFT +#define X_WH_R X_MS_WH_RIGHT +#define X_ACL0 X_MS_ACCEL0 +#define X_ACL1 X_MS_ACCEL1 +#define X_ACL2 X_MS_ACCEL2 + +/* Keyboard/Keypad Page (0x07) */ +#define X_A 04 +#define X_B 05 +#define X_C 06 +#define X_D 07 +#define X_E 08 +#define X_F 09 +#define X_G 0a +#define X_H 0b +#define X_I 0c +#define X_J 0d +#define X_K 0e +#define X_L 0f +#define X_M 10 +#define X_N 11 +#define X_O 12 +#define X_P 13 +#define X_Q 14 +#define X_R 15 +#define X_S 16 +#define X_T 17 +#define X_U 18 +#define X_V 19 +#define X_W 1a +#define X_X 1b +#define X_Y 1c +#define X_Z 1d +#define X_1 1e +#define X_2 1f +#define X_3 20 +#define X_4 21 +#define X_5 22 +#define X_6 23 +#define X_7 24 +#define X_8 25 +#define X_9 26 +#define X_0 27 +#define X_ENTER 28 +#define X_ESCAPE 29 +#define X_BACKSPACE 2a +#define X_TAB 2b +#define X_SPACE 2c +#define X_MINUS 2d +#define X_EQUAL 2e +#define X_LEFT_BRACKET 2f +#define X_RIGHT_BRACKET 30 +#define X_BACKSLASH 31 +#define X_NONUS_HASH 32 +#define X_SEMICOLON 33 +#define X_QUOTE 34 +#define X_GRAVE 35 +#define X_COMMA 36 +#define X_DOT 37 +#define X_SLASH 38 +#define X_CAPS_LOCK 39 +#define X_F1 3a +#define X_F2 3b +#define X_F3 3c +#define X_F4 3d +#define X_F5 3e +#define X_F6 3f +#define X_F7 40 +#define X_F8 41 +#define X_F9 42 +#define X_F10 43 +#define X_F11 44 +#define X_F12 45 +#define X_PRINT_SCREEN 46 +#define X_SCROLL_LOCK 47 +#define X_PAUSE 48 +#define X_INSERT 49 +#define X_HOME 4a +#define X_PAGE_UP 4b +#define X_DELETE 4c +#define X_END 4d +#define X_PAGE_DOWN 4e +#define X_RIGHT 4f +#define X_LEFT 50 +#define X_DOWN 51 +#define X_UP 52 +#define X_NUM_LOCK 53 +#define X_KP_SLASH 54 +#define X_KP_ASTERISK 55 +#define X_KP_MINUS 56 +#define X_KP_PLUS 57 +#define X_KP_ENTER 58 +#define X_KP_1 59 +#define X_KP_2 5a +#define X_KP_3 5b +#define X_KP_4 5c +#define X_KP_5 5d +#define X_KP_6 5e +#define X_KP_7 5f +#define X_KP_8 60 +#define X_KP_9 61 +#define X_KP_0 62 +#define X_KP_DOT 63 +#define X_NONUS_BACKSLASH 64 +#define X_APPLICATION 65 +#define X_KB_POWER 66 +#define X_KP_EQUAL 67 +#define X_F13 68 +#define X_F14 69 +#define X_F15 6a +#define X_F16 6b +#define X_F17 6c +#define X_F18 6d +#define X_F19 6e +#define X_F20 6f +#define X_F21 70 +#define X_F22 71 +#define X_F23 72 +#define X_F24 73 +#define X_EXECUTE 74 +#define X_HELP 75 +#define X_MENU 76 +#define X_SELECT 77 +#define X_STOP 78 +#define X_AGAIN 79 +#define X_UNDO 7a +#define X_CUT 7b +#define X_COPY 7c +#define X_PASTE 7d +#define X_FIND 7e +#define X_KB_MUTE 7f +#define X_KB_VOLUME_UP 80 +#define X_KB_VOLUME_DOWN 81 +#define X_LOCKING_CAPS_LOCK 82 +#define X_LOCKING_NUM_LOCK 83 +#define X_LOCKING_SCROLL_LOCK 84 +#define X_KP_COMMA 85 +#define X_KP_EQUAL_AS400 86 +#define X_INTERNATIONAL_1 87 +#define X_INTERNATIONAL_2 88 +#define X_INTERNATIONAL_3 89 +#define X_INTERNATIONAL_4 8a +#define X_INTERNATIONAL_5 8b +#define X_INTERNATIONAL_6 8c +#define X_INTERNATIONAL_7 8d +#define X_INTERNATIONAL_8 8e +#define X_INTERNATIONAL_9 8f +#define X_LANGUAGE_1 90 +#define X_LANGUAGE_2 91 +#define X_LANGUAGE_3 92 +#define X_LANGUAGE_4 93 +#define X_LANGUAGE_5 94 +#define X_LANGUAGE_6 95 +#define X_LANGUAGE_7 96 +#define X_LANGUAGE_8 97 +#define X_LANGUAGE_9 98 +#define X_ALTERNATE_ERASE 99 +#define X_SYSTEM_REQUEST 9a +#define X_CANCEL 9b +#define X_CLEAR 9c +#define X_PRIOR 9d +#define X_RETURN 9e +#define X_SEPARATOR 9f +#define X_OUT a0 +#define X_OPER a1 +#define X_CLEAR_AGAIN a2 +#define X_CRSEL a3 +#define X_EXSEL a4 + +/* Modifiers */ +#define X_LEFT_CTRL e0 +#define X_LEFT_SHIFT e1 +#define X_LEFT_ALT e2 +#define X_LEFT_GUI e3 +#define X_RIGHT_CTRL e4 +#define X_RIGHT_SHIFT e5 +#define X_RIGHT_ALT e6 +#define X_RIGHT_GUI e7 + +/* Media and Function keys */ +/* Generic Desktop Page (0x01) */ +#define X_SYSTEM_POWER a5 +#define X_SYSTEM_SLEEP a6 +#define X_SYSTEM_WAKE a7 + +/* Consumer Page (0x0C) */ +#define X_AUDIO_MUTE a8 +#define X_AUDIO_VOL_UP a9 +#define X_AUDIO_VOL_DOWN aa +#define X_MEDIA_NEXT_TRACK ab +#define X_MEDIA_PREV_TRACK ac +#define X_MEDIA_STOP ad +#define X_MEDIA_PLAY_PAUSE ae +#define X_MEDIA_SELECT af +#define X_MEDIA_EJECT b0 +#define X_MAIL b1 +#define X_CALCULATOR b2 +#define X_MY_COMPUTER b3 +#define X_WWW_SEARCH b4 +#define X_WWW_HOME b5 +#define X_WWW_BACK b6 +#define X_WWW_FORWARD b7 +#define X_WWW_STOP b8 +#define X_WWW_REFRESH b9 +#define X_WWW_FAVORITES ba +#define X_MEDIA_FAST_FORWARD bb +#define X_MEDIA_REWIND bc +#define X_BRIGHTNESS_UP bd +#define X_BRIGHTNESS_DOWN be +#define X_CONTROL_PANEL bf +#define X_ASSISTANT c0 + +/* Mouse Buttons (unallocated range in HID spec) */ +#define X_MS_UP cd +#define X_MS_DOWN ce +#define X_MS_LEFT cf +#define X_MS_RIGHT d0 +#define X_MS_BTN1 d1 +#define X_MS_BTN2 d2 +#define X_MS_BTN3 d3 +#define X_MS_BTN4 d4 +#define X_MS_BTN5 d5 +#define X_MS_BTN6 d6 +#define X_MS_BTN7 d7 +#define X_MS_BTN8 d8 +#define X_MS_WH_UP d9 +#define X_MS_WH_DOWN da +#define X_MS_WH_LEFT db +#define X_MS_WH_RIGHT dc +#define X_MS_ACCEL0 dd +#define X_MS_ACCEL1 de +#define X_MS_ACCEL2 df + +// Send string macros +#define STRINGIZE(z) #z +#define ADD_SLASH_X(y) STRINGIZE(\x##y) +#define SYMBOL_STR(x) ADD_SLASH_X(x) + +#define SS_QMK_PREFIX 1 + +#define SS_TAP_CODE 1 +#define SS_DOWN_CODE 2 +#define SS_UP_CODE 3 +#define SS_DELAY_CODE 4 + +#define SS_TAP(keycode) "\1\1" SYMBOL_STR(keycode) +#define SS_DOWN(keycode) "\1\2" SYMBOL_STR(keycode) +#define SS_UP(keycode) "\1\3" SYMBOL_STR(keycode) +#define SS_DELAY(msecs) "\1\4" STRINGIZE(msecs) "|" + +// `string` arguments must not be parenthesized +#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL) +#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT) +#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT) +#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI) +#define SS_LOPT(string) SS_LALT(string) +#define SS_LCMD(string) SS_LGUI(string) +#define SS_LWIN(string) SS_LGUI(string) + +#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL) +#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT) +#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT) +#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI) +#define SS_ALGR(string) SS_RALT(string) +#define SS_ROPT(string) SS_RALT(string) +#define SS_RCMD(string) SS_RGUI(string) +#define SS_RWIN(string) SS_RGUI(string) diff --git a/app/src/launcher/sendstring_japanese.h b/app/src/launcher/sendstring_japanese.h new file mode 100644 index 00000000000..842f3541bb3 --- /dev/null +++ b/app/src/launcher/sendstring_japanese.h @@ -0,0 +1,81 @@ +/* Copyright 2016 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Sendstring lookup tables for JIS layouts + +#pragma once + +#include "send_string.h" +#include "keymap_japanese.h" + +// clang-format off +#define PROGMEM + +const uint8_t ascii_to_shift_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 1, 1, 1, 1), + KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 0, 1), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0) +}; + +const uint8_t ascii_to_keycode_lut[128] PROGMEM = { + // NUL SOH STX ETX EOT ENQ ACK BEL + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // BS TAB LF VT FF CR SO SI + KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // DLE DC1 DC2 DC3 DC4 NAK SYN ETB + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // CAN EM SUB ESC FS GS RS US + XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + + // ! " # $ % & ' + KC_SPC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + // ( ) * + , - . / + KC_8, KC_9, JP_COLN, JP_SCLN, JP_COMM, JP_MINS, JP_DOT, JP_SLSH, + // 0 1 2 3 4 5 6 7 + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + // 8 9 : ; < = > ? + KC_8, KC_9, JP_COLN, JP_SCLN, JP_COMM, JP_MINS, JP_DOT, JP_SLSH, + // @ A B C D E F G + JP_AT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + // H I J K L M N O + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + // P Q R S T U V W + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + // X Y Z [ \ ] ^ _ + KC_X, KC_Y, KC_Z, JP_LBRC, JP_BSLS, JP_RBRC, JP_CIRC, JP_BSLS, + // ` a b c d e f g + JP_AT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + // h i j k l m n o + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + // p q r s t u v w + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + // x y z { | } ~ DEL + KC_X, KC_Y, KC_Z, JP_LBRC, JP_YEN, JP_RBRC, JP_CIRC, KC_DEL +}; diff --git a/app/src/led_effect.h b/app/src/led_effect.h new file mode 100644 index 00000000000..3c45b16a129 --- /dev/null +++ b/app/src/led_effect.h @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2019-2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _LED_EFFECT_H_ +#define _LED_EFFECT_H_ + +/** + * @brief LED Effect + * @defgroup led_effect_CAF LED Effect + * @{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define _CAF_LED_COLOR_CHANNEL_COUNT 3 + +/** @brief Color of LED. + */ +struct led_color { + /** Values for color channels. */ + uint8_t c[_CAF_LED_COLOR_CHANNEL_COUNT]; +}; + +/** @brief Single step of a LED effect. + * + * During a single step, color of LED changes from the color before the step + * to the color defined in the step. The color update may be done in multiple + * substeps to achieve smooth, gradual change. + */ +struct led_effect_step { + /** LED color at the end of the step. */ + struct led_color color; + + /** Number of substeps. */ + uint16_t substep_count; + + /** Duration of a single substep. */ + uint16_t substep_time; +}; + +/** @brief Single LED effect. + */ +struct led_effect { + /** Sequence of LED color changes. It is defined by subsequent steps. */ + const struct led_effect_step *steps; + + /** Number of steps for the given effect. */ + uint16_t step_count; + + /** Flag that indicates if the sequence should start again after it finishes. */ + bool loop_forever; +}; + +/** Transform color brightness from 8-bit space to percentage representation. + * + * @param _val Color brightness in 0-255 range + * + * @return Color brightness in 0-100 range + */ +#define COLOR_BRIGHTNESS_TO_PCT(_val) ((_val * 100) / UINT8_MAX) + +/** + * @brief Pass a color value as a macro argument + * + * @ref LED_COLOR macro contains commas in its body. + * This means that after the argument is expanded, the macro is to be treated + * as multiple arguments. This also makes it impossible to pass an argument + * from macro level to another macro. + * The macro allows the usage of the color argument as an argument to + * another macro level. + * + * @param ... Any list of arguments that have to be treated as + * a single argument for the macro. + */ +#define LED_COLOR_ARG_PASS(...) __VA_ARGS__ + +/** Create LED color initializer for LED turned on. + * + * @note As arguments, pass the brightness levels for every color channel. + * + * @note The macro returns the structure initializer that once expanded + * contains commas not placed in brackets. + * This means that when passed as an argument, this argument + * cannot be passed simply to another macro. + * Use @ref LED_COLOR_ARG_PASS macro for the preprocessor + * to treat it as a single argument again. + */ +#define LED_COLOR(_r, _g, _b) { \ + .c = { \ + COLOR_BRIGHTNESS_TO_PCT(_r), \ + COLOR_BRIGHTNESS_TO_PCT(_g), \ + COLOR_BRIGHTNESS_TO_PCT(_b) \ + } \ +} + +/** Create LED color initializer for LED turned off. + */ +#define LED_NOCOLOR() { \ + .c = {0, 0, 0} \ +} + +/** Create LED turned on effect initializer. + * + * LED color remains constant. + * + * @param _color Selected LED color. + */ +#define LED_EFFECT_LED_ON(_color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = _color, \ + .substep_count = 1, \ + .substep_time = 0, \ + }, \ + }), \ + .step_count = 1, \ + .loop_forever = false, \ + } + + +/** Create LED turned off effect initializer. + */ +#define LED_EFFECT_LED_OFF() LED_EFFECT_LED_ON(LED_NOCOLOR()) + +/** Create LED turned on for a brief period effect initializer. + * + * LED color remains constant for a defined time, then goes off. + * + * @param _color Selected LED color. + * @param _on_time Time LED will remain on in milliseconds. + * @param _off_delay Time in which LED will gradually switch to off + * (in milliseconds). + */ +#define LED_EFFECT_LED_ON_GO_OFF(_color, _on_time, _off_delay) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = _color, \ + .substep_count = 1, \ + .substep_time = 0, \ + }, \ + { \ + .color = _color, \ + .substep_count = 1, \ + .substep_time = (_on_time), \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = (_off_delay)/10, \ + .substep_time = 10, \ + }, \ + }), \ + .step_count = 3, \ + .loop_forever = false, \ + } + +/** Create LED blinking effect initializer with two periods as arguments. + * + * LED color is periodically changed between the selected color and the LED + * turned off. + * This macro takes two periods: for on and off time. + * + * @param _period_on Period of time for which LED is on. + * @param _period_off Period of time for which LED is off. + * @param _color Selected LED color. + * + * @sa LED_EFFECT_LED_BLINK + */ +#define LED_EFFECT_LED_BLINK2(_period_on, _period_off, _color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = _color, \ + .substep_count = 1, \ + .substep_time = (_period_off), \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = (_period_on), \ + }, \ + }), \ + .step_count = 2, \ + .loop_forever = true, \ + } + + +/** Create LED blinking effect initializer with one period given + * + * LED color is periodically changed between the selected color and the LED + * turned off. + * The same time is used for both: on and off time. + * + * @param _period Period of time between LED color switches. + * @param _color Selected LED color. + * + * @sa LED_EFFECT_LED_BLINK + */ +#define LED_EFFECT_LED_BLINK(_period, _color) \ + LED_EFFECT_LED_BLINK2(_period, _period, LED_COLOR_ARG_PASS(_color)) + +/** @def _BREATH_SUBSTEPS + * + * @brief Substeps for color update for LED breathing effect. + */ +#define _BREATH_SUBSTEPS 15 + +/** Create LED breathing effect initializer. + * + * LED color is smoothly, gradually changed between the LED turned off + * and the selected color. + * + * @param _period Period of time for single substep. + * @param _color Selected LED color. + */ +#define LED_EFFECT_LED_BREATH(_period, _color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = _color, \ + .substep_count = _BREATH_SUBSTEPS, \ + .substep_time = ((_period + (_BREATH_SUBSTEPS - 1)) \ + / _BREATH_SUBSTEPS), \ + }, \ + { \ + .color = _color, \ + .substep_count = 1, \ + .substep_time = _period, \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = _BREATH_SUBSTEPS, \ + .substep_time = ((_period + (_BREATH_SUBSTEPS - 1)) \ + / _BREATH_SUBSTEPS), \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = _period, \ + }, \ + }), \ + .step_count = 4, \ + .loop_forever = true, \ + } + +/** @def LED_CLOCK_BLINK_PERIOD + * + * @brief Period of time between color changes while the LED is blinking + * (LED clock effect). + */ +#define LED_CLOCK_BLINK_PERIOD 100 + +/** @def LED_CLOCK_SLEEP_PERIOD + * + * @brief Period of time when the LED is turned off (LED clock effect). + */ +#define LED_CLOCK_SLEEP_PERIOD 1000 + +/** Create LED steps initializer for single clock tick. + * + * A single clock tick is a single LED blink with the defined color. + * This macro is used by UTIL_LISTIFY macro. + * + * @param i Tick number (required by UTIL_LISTIFY). + * @param ... Selected LED color. + */ +#define _LED_CLOCK_TIK(i, ...) \ + { \ + .color = __VA_ARGS__, \ + .substep_count = 1, \ + .substep_time = LED_CLOCK_BLINK_PERIOD, \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = LED_CLOCK_BLINK_PERIOD, \ + } + +/** Create LED clock effect initializer. + * + * LED blinks a defined number of times, then it is turned off for a defined + * period of time. The sequence is repeated periodically. + * + * @note You can pass only one additional argument to the UTIL_LISTIFY macro, + * which in this case is LED color. Period is defined separately. + * + * @param _ticks Number of ticks. + * @param _color Selected LED color. + */ +#define LED_EFFECT_LED_CLOCK(_ticks, _color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = LED_CLOCK_SLEEP_PERIOD, \ + }, \ + LISTIFY(_ticks, _LED_CLOCK_TIK, (,), _color) \ + }), \ + .step_count = (2 * _ticks + 1), \ + .loop_forever = true, \ + } +#define LED_EFFECT_LED_FLASH(_ticks,_period,_color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = _period, \ + }, \ + LISTIFY(_ticks, _LED_CLOCK_TIK, (,), _color) \ + }), \ + .step_count = (2 * _ticks + 1), \ + .loop_forever = false, \ + } + +#define _LED_FLASH_TIK(i, ...) \ + { \ + .color = __VA_ARGS__, \ + .substep_count = 1, \ + .substep_time = 400, \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = 400, \ + } +#define LED_EFFECT_LED_FLASH2(_ticks,_color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = 200, \ + }, \ + LISTIFY(_ticks, _LED_FLASH_TIK, (,), _color) \ + }), \ + .step_count = (2 * _ticks + 1), \ + .loop_forever = false, \ + } + +#define _LED_FLASH_TIK1(i, ...) \ + { \ + .color = __VA_ARGS__, \ + .substep_count = 1, \ + .substep_time = 500, \ + }, \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = 500, \ + } +#define LED_EFFECT_LED_FLASH3(_ticks,_color) \ + { \ + .steps = ((const struct led_effect_step[]) { \ + { \ + .color = LED_NOCOLOR(), \ + .substep_count = 1, \ + .substep_time = 200, \ + }, \ + LISTIFY(_ticks, _LED_FLASH_TIK1, (,),_color) \ + }), \ + .step_count = (2 * _ticks + 1), \ + .loop_forever = false, \ + } +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* _LED_EFFECT_H_ */ diff --git a/app/src/leds.c b/app/src/leds.c new file mode 100644 index 00000000000..18a7d130ad8 --- /dev/null +++ b/app/src/leds.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2018-2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include "led_effect.h" +#include +#include + + +// #include +// #include + +// #define MODULE leds +// #include + +#include +// LOG_MODULE_REGISTER(MODULE, CONFIG_CAF_LEDS_LOG_LEVEL); + +static const struct led_effect led_peer_state_effect[] = +{ + [LED_PEER_STATE_DISCONNECTED] = LED_EFFECT_LED_OFF(), + [LED_PEER_STATE_CONNECTED] = LED_EFFECT_LED_ON_GO_OFF(LED_COLOR(150, 0, 0),3000,100), + [LED_PEER_STATE_PAIR] = LED_EFFECT_LED_BLINK(1000, LED_COLOR(150, 0, 0)), + [LED_PEER_STATE_RECONN] = LED_EFFECT_LED_FLASH(3, 200,LED_COLOR(150, 0, 0)),// LED_EFFECT_LED_BLINK(200, LED_COLOR(150, 0, 0)), + [LED_PEER_STATE_FAILE] = LED_EFFECT_LED_FLASH(3, 300,LED_COLOR(150, 0, 0)), + [LED_PEER_STATE_POWER_ON] = LED_EFFECT_LED_ON_GO_OFF(LED_COLOR(150, 150, 150),2500,100), + [LED_PEER_STATE_ON_100MS] = LED_EFFECT_LED_ON_GO_OFF(LED_COLOR(100, 100,100),200,100), + [LED_PEER_STATE_BAT_LOW] = LED_EFFECT_LED_FLASH3(5, LED_COLOR(255, 0,0)), + [LED_PEER_STATE_BAT_CHARGING] = LED_EFFECT_LED_ON(LED_COLOR(255, 0,0)), + [LED_PEER_STATE_BAT_CHARGEDONE] = LED_EFFECT_LED_ON(LED_COLOR(0, 255,0)), + [LED_PEER_STATE_RECOVER] = LED_EFFECT_LED_FLASH2(3, LED_COLOR(0, 0,255)), + + +}; +LOG_MODULE_DECLARE(zmk,4); + +// K_SEM_DEFINE(power_on_sem,0,1); +void power_on_finish_cb(struct k_work * work); +K_WORK_DEFINE(power_on_finish,power_on_finish_cb); +static uint8_t led_power_on_status; + +#define LED_ID(led) ((led) - &leds[0]) + +struct led { + const struct device *dev; + uint8_t color_count; + + struct led_color color; + const struct led_effect *effect; + uint16_t effect_step; + uint16_t effect_substep; + + // struct k_work_delayable work; + struct k_timer timer; +}; + +#ifdef CONFIG_ZMK_LEDS_PWM + #define DT_DRV_COMPAT pwm_leds +#elif defined(CONFIG_ZMK_LEDS_GPIO) + #define DT_DRV_COMPAT gpio_leds +#else + #error "LED driver must be specified in configuration" +#endif + +#define _LED_COLOR_ID(_unused) 0, + +#define _LED_COLOR_COUNT(id) \ + static const uint8_t led_colors_##id[] = { \ + DT_INST_FOREACH_CHILD(id, _LED_COLOR_ID) \ + }; + +DT_INST_FOREACH_STATUS_OKAY(_LED_COLOR_COUNT) + +#define _LED_INSTANCE_DEF(id) \ + { \ + .dev = DEVICE_DT_GET(DT_DRV_INST(id)), \ + .color_count = ARRAY_SIZE(led_colors_##id), \ + }, +/**/ + +static struct led leds[] = { + DT_INST_FOREACH_STATUS_OKAY(_LED_INSTANCE_DEF) +}; +static void led_update(struct led *led); + +// void test_led_work_cb(struct k_work *work); +// K_WORK_DELAYABLE_DEFINE(test_led_work, test_led_work_cb); +// void test_led_work_cb(struct k_work *work) { +// leds[4].effect = &led_peer_state_effect[LED_PEER_STATE_ON_100MS]; +// led_update(&leds[4]); +// k_work_reschedule(&test_led_work, K_MSEC(3000)); +// } + +// uint8_t get_mode_status(void); +// static uint8_t last_mode; +// void mode_check_cb(struct k_timer *timer); +// K_TIMER_DEFINE(mode_check,mode_check_cb,NULL); +// void mode_check_cb(struct k_timer *timer) +// { +// uint8_t mode =get_mode_status(); +// if(mode!=last_mode) +// { +// k_sem_give(&power_on_sem); +// LOG_INF("mode change:%d",mode); +// for (size_t i = 0; i < ARRAY_SIZE(leds); i++) +// k_timer_stop(&leds[i].timer); +// } +// else +// k_timer_start(&mode_check,K_MSEC(100),K_FOREVER); +// } + + +static int set_color_one_channel(struct led *led, struct led_color *color) +{ + /* For a single color LED convert color to brightness. */ + unsigned int brightness = 0; + + for (size_t i = 0; i < ARRAY_SIZE(color->c); i++) { + brightness += color->c[i]; + } + brightness /= ARRAY_SIZE(color->c); + + return led_set_brightness(led->dev, 0, brightness); +} + +static int set_color_all_channels(struct led *led, struct led_color *color) +{ + int err = 0; + + for (size_t i = 0; (i < ARRAY_SIZE(color->c)) && !err; i++) { + err = led_set_brightness(led->dev, i, color->c[i]); + } + + return err; +} + +static void set_color(struct led *led, struct led_color *color) +{ + int err; + // LOG_INF("color:%d,%d,%d",color->c[0],color->c[1],color->c[1]); + if (led->color_count == ARRAY_SIZE(color->c)) { + err = set_color_all_channels(led, color); + } else { + err = set_color_one_channel(led, color); + } + + if (err) { + LOG_ERR("Cannot set LED brightness (err: %d)", err); + } +} + +static void set_off(struct led *led) +{ + struct led_color nocolor = {0}; + + set_color(led, &nocolor); +} + +// static void work_handler(struct k_work *work) +static void timer_handler(struct k_timer *timer) +{ + // struct led *led = CONTAINER_OF(work, struct led, work); + struct led *led = CONTAINER_OF(timer, struct led, timer); + // LOG_INF("led ptr:%x,time:%d,%d",led,led->effect->steps[0].substep_time,led->effect->steps[1].substep_time); + const struct led_effect_step *effect_step = + &led->effect->steps[led->effect_step]; + + __ASSERT_NO_MSG(effect_step->substep_count > 0); + int substeps_left = effect_step->substep_count - led->effect_substep; + + for (size_t i = 0; i < ARRAY_SIZE(led->color.c); i++) { + int diff = (effect_step->color.c[i] - led->color.c[i]) / + substeps_left; + led->color.c[i] += diff; + } + set_color(led, &led->color); + + led->effect_substep++; + if (led->effect_substep == effect_step->substep_count) { + led->effect_substep = 0; + led->effect_step++; + + if (led->effect_step == led->effect->step_count) { + if (led->effect->loop_forever) { + led->effect_step = 0; + } else { + LOG_INF("led:%p effect finish",led); + if((led == &leds[ARRAY_SIZE(leds)-1]) && (led->effect == &led_peer_state_effect[LED_PEER_STATE_POWER_ON])) + { + LOG_INF("power_on_finish"); + // k_sem_give(&power_on_sem); + // k_timer_stop(&mode_check); + led_power_on_status =0; + k_work_submit(&power_on_finish); + } + + } + } + } + + if (led->effect_step < led->effect->step_count) { + int32_t next_delay = + led->effect->steps[led->effect_step].substep_time; + // LOG_INF("led ptr:%x,led->effect_step:%d,next delay:%d",led,led->effect_step,next_delay); + // k_work_reschedule(&led->work, K_MSEC(next_delay)); + k_timer_start(&led->timer,K_MSEC(next_delay),K_FOREVER); + } +} + +static void led_update(struct led *led) +{ + // k_work_cancel_delayable(&led->work); + k_timer_stop(&led->timer); + + led->effect_step = 0; + led->effect_substep = 0; + + if (!led->effect) { + LOG_DBG("No effect set"); + return; + } + + __ASSERT_NO_MSG(led->effect->steps); + + if (led->effect->step_count > 0) { + int32_t next_delay = + led->effect->steps[led->effect_step].substep_time; + LOG_INF("next delay:%d",next_delay); + // k_work_reschedule(&led->work, K_MSEC(next_delay)); + k_timer_start(&led->timer,K_MSEC(next_delay),K_FOREVER); + } else { + LOG_WRN("LED effect with no effect"); + } +} +void print_led_info(const struct device *dev,uint32_t led); + int leds_init(const struct device *_arg) +{ + int err = 0; + + BUILD_ASSERT(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) > 0, "No LEDs defined"); + + for (size_t i = 0; (i < ARRAY_SIZE(leds)) && !err; i++) { + struct led *led = &leds[i]; + LOG_INF("led :%d,color count:%d",i,led->color_count); + // print_led_info(led->dev,i); + if(led->color_count>3) continue; + __ASSERT_NO_MSG((led->color_count == 1) || (led->color_count == 3)); + + if (!device_is_ready(led->dev)) { + LOG_ERR("Device %s is not ready", led->dev->name); + err = -ENODEV; + } else { + // k_work_init_delayable(&led->work, work_handler); + k_timer_init(&led->timer,timer_handler,NULL); + + // led_set_state(i,LED_PEER_STATE_POWER_ON); + // led->effect = &led_peer_state_effect[LED_PEER_STATE_POWER_ON]; + + led_update(led); + } + } + // k_work_reschedule(&test_led_work, K_MSEC(1000)); + return err; +} + + void leds_start(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(leds); i++) { +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_ZMK_LEDS_GPIO) + /* Zephyr power management API is not implemented for GPIO LEDs. + * LEDs are turned off by CAF LEDs module. + */ + int err = pm_device_action_run(leds[i].dev, PM_DEVICE_ACTION_RESUME); + + if (err) { + LOG_ERR("Failed to set LED driver into active state (err: %d)", err); + } +#endif + led_update(&leds[i]); + } +} + + void leds_stop(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(leds); i++) { + // k_work_cancel_delayable(&leds[i].work); + k_timer_stop(&leds[i].timer); + + set_off(&leds[i]); + +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_ZMK_LEDS_GPIO) + /* Zephyr power management API is not implemented for GPIO LEDs. + * LEDs are turned off by CAF LEDs module. + */ + int err = pm_device_action_run(leds[i].dev, PM_DEVICE_ACTION_SUSPEND); + + if (err) { + LOG_ERR("Failed to set LED driver into suspend state (err: %d)", err); + } +#endif + } +} + + + +void led_set_state(uint8_t index,uint8_t led_state) +{ + LOG_INF("led_set_state index:%d,state:%d",index,led_state); + if(index< ARRAY_SIZE(leds)) + { + //why leds in dts is enable? + for(int i=0;i +#include + +struct led_gpio_config { + size_t num_leds; + const struct gpio_dt_spec *led; +}; +void print_led_info(const struct device *dev,uint32_t led) +{ + const struct led_gpio_config *config = dev->config; + const struct gpio_dt_spec *led_gpio; + LOG_INF("LED NUM:%d,dev name:%s",config->num_leds,dev->name); + + for(int i=0;inum_leds;i++) + { + led_gpio = &config->led[i]; + LOG_INF("LED gpio pin:%d",led_gpio->pin); + } + // keyboard_led_init(); +} +static uint8_t keyboard_led_state; +static uint8_t charge_led_state; +void keyboad_led_set_onoff(uint8_t led_state) +{ + if(led_power_on_status) + { + keyboard_led_state =led_state; + return; + } + uint8_t num =led_state &0x01; + uint8_t caps= (led_state &0x02); + struct led_color color=LED_COLOR(0xff,0xff,0xff); + LOG_DBG("led state:%d,num:%d,caps:%d",led_state,num,caps); +#if !(CONFIG_SHIELD_KEYCHRON_B1) + num ? set_color(&leds[LED_NUMLOCK],&color):set_off(&leds[LED_NUMLOCK]); +#endif + caps ? set_color(&leds[LED_CAPSLOCK],&color):set_off(&leds[LED_CAPSLOCK]); + keyboard_led_state =led_state; + +} +uint8_t keyboard_get_led_state(void) +{ + return keyboard_led_state; +} +uint8_t get_charge_led_state(void) +{ + return charge_led_state; +} +void blue_led_set_state(uint8_t led_state) +{ + if(get_current_transport()!=ZMK_TRANSPORT_BLE) return; + LOG_DBG("set:%d",led_state); + + if((leds[LED_BLUE].effect !=&led_peer_state_effect[led_state]) || k_timer_remaining_get(&leds[LED_BLUE].timer)==0)// k_work_delayable_remaining_get(&leds[LED_BLUE].work)==0) + { + leds[LED_BLUE].effect = &led_peer_state_effect[led_state]; + led_update(&leds[LED_BLUE]); + } +} +void led_24G_set_state(uint8_t led_state) +{ + if(get_current_transport()!=ZMK_TRANSPORT_24G) return; + LOG_DBG("set:%d",led_state); + if((leds[LED_24G].effect !=&led_peer_state_effect[led_state]) || k_timer_remaining_get(&leds[LED_24G].timer)==0)//k_work_delayable_remaining_get(&leds[LED_24G].work)==0) + { + LOG_DBG("."); + leds[LED_24G].effect = &led_peer_state_effect[led_state]; + led_update(&leds[LED_24G]); + } +} +void led_charge_set_state(uint8_t led_state) +{ + if(led_power_on_status) + { + charge_led_state =led_state; + return; + } + if(led_state == LED_BAT_CHARGING) + { + leds[LED_BAT].effect = &led_peer_state_effect[LED_PEER_STATE_BAT_CHARGING]; + led_update(&leds[LED_BAT]); + } + else if(led_state == LED_BAT_CHARGE_DONE) + { + leds[LED_BAT].effect = &led_peer_state_effect[LED_PEER_STATE_BAT_CHARGEDONE]; + led_update(&leds[LED_BAT]); + } + else if(led_state == LED_BAT_LOW) + { + leds[LED_BAT].effect = &led_peer_state_effect[LED_PEER_STATE_BAT_LOW]; + led_update(&leds[LED_BAT]); + } + else if(led_state == LED_BAT_NONE) + { + leds[LED_BAT].effect = &led_peer_state_effect[LED_PEER_STATE_DISCONNECTED]; + led_update(&leds[LED_BAT]); + } + charge_led_state =led_state; +} +void led_recover(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(leds);i++) + { + #if (CONFIG_SHIELD_KEYCHRON_B1) + if(i== LED_NUMLOCK) continue; + #endif + leds[i].effect = &led_peer_state_effect[LED_PEER_STATE_RECOVER]; + led_update(&leds[i]); + } +} +void power_on_finish_cb(struct k_work * work) +{ + keyboad_led_set_onoff(keyboard_led_state); + led_charge_set_state(charge_led_state); +} +bool bat_is_shutdown(void); +void led_power_on(void) +{ + if(bat_is_shutdown()) return; + // k_sem_reset(&power_on_sem); + led_power_on_status =1; + + for (size_t i = 0; i < ARRAY_SIZE(leds);i++) + { + #if (CONFIG_SHIELD_KEYCHRON_B1) + if(i== LED_NUMLOCK) continue; + #endif + if(get_current_transport()==ZMK_TRANSPORT_BLE) + { + if(i==LED_24G) continue; + } + else if(get_current_transport()==ZMK_TRANSPORT_24G) + { + if(i==LED_BLUE) continue; + } + leds[i].effect = &led_peer_state_effect[LED_PEER_STATE_POWER_ON]; + + led_update(&leds[i]); + } + // last_mode = get_mode_status(); + // k_timer_start(&mode_check,K_MSEC(100),K_FOREVER); + // k_sem_take(&power_on_sem,K_MSEC(3000)); + // LOG_INF("power on finish"); + // led_charge_set_state(charge_led_state); +} +void reset_led_power_on(void) +{ + // k_sem_give(&power_on_sem); + led_power_on_status=0; + leds_stop(); +} + +static const struct led_effect * bat_bak_effect ; +extern uint8_t bt_bas_get_battery_level(void); +void led_bat_display(void) +{ + bat_bak_effect = leds[LED_BAT].effect; + LOG_DBG("."); + // led_charge_set_state(LED_BAT_NONE); + + // k_sem_take(&led_semi,K_MSEC(1000)); + + uint8_t level =bt_bas_get_battery_level(); + + if(level >=70) + { + struct led_color color=LED_COLOR(0,0xff,0); //green; + set_color(&leds[LED_BAT],&color); + LOG_DBG("green,level:%d",level); + + } + else if(level >=30) + { + struct led_color color=LED_COLOR(0,0,0xff); //blue; + set_color(&leds[LED_BAT],&color); + LOG_DBG("blue,level:%d",level); + } + else + { + struct led_color color=LED_COLOR(0xff,0,0); //red + set_color(&leds[LED_BAT],&color); + LOG_DBG("red,level:%d",level); + } +} +void led_bat_display_off(void) +{ + LOG_DBG("."); + // if(bat_bak_effect) + // { + // leds[LED_BAT].effect = bat_bak_effect; + // led_update(&leds[LED_BAT]); + // } + // else + if(charge_led_state !=LED_BAT_LOW) + { + led_charge_set_state(charge_led_state); + } + else + { + led_charge_set_state(LED_BAT_NONE); + } +} +void leds_turnoff(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(leds);i++) + { + set_off(&leds[i]); + } + led_charge_set_state(LED_BAT_NONE); + blue_led_set_state( LED_PEER_STATE_DISCONNECTED); + led_24G_set_state(LED_PEER_STATE_DISCONNECTED); +} + +SYS_INIT(leds_init, APPLICATION, CONFIG_ZMK_LED_INIT_PRIORITY); \ No newline at end of file diff --git a/app/src/main.c b/app/src/main.c index 0f77382addb..9b8a6ab880e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -12,7 +12,24 @@ #include LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); +<<<<<<< HEAD +#include +#include +#include +#include +#include +#include +#include +#include + +void f1_f13_fn_exchange_start_check(void); +bool bat_is_shutdown(void); +void clear_bat_shutdown(void); +int zmk_ble_init(const struct device *_arg); +void zmk_24g_init(void); +======= #if IS_ENABLED(CONFIG_ZMK_DISPLAY) +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #include #include @@ -21,11 +38,62 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); int main(void) { LOG_INF("Welcome to ZMK!\n"); + + +<<<<<<< HEAD + if (zmk_kscan_init(DEVICE_DT_GET(ZMK_MATRIX_NODE_ID)) != 0) { + return; + } + uint8_t exit_shutdown=0; + uint8_t bat_shutdown=0; + + while(1) + { + if(bat_is_shutdown()) + { + bat_shutdown =1; + if(zmk_usb_is_powered()) + { + exit_shutdown =1; + } + } + else + { + exit_shutdown =1; + } + if(exit_shutdown) + { + exit_shutdown =0; + LOG_ERR("Exit shutdown!"); + if(bat_shutdown) + { + LOG_ERR("bat low ,Exit shutdown!"); + bat_shutdown=0; + clear_bat_shutdown(); + if(get_current_transport()==ZMK_TRANSPORT_BLE) + { + zmk_ble_init(NULL); + } + else if(get_current_transport()==ZMK_TRANSPORT_24G) + { + zmk_24g_init(); + } + } + set_state(ZMK_ACTIVITY_ACTIVE); + break; + } + + LOG_ERR("shutdown now"); + k_msleep(100); + set_state(ZMK_ACTIVITY_SLEEP); + } +======= #if IS_ENABLED(CONFIG_SETTINGS) settings_subsys_init(); settings_load(); #endif +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 #ifdef CONFIG_ZMK_DISPLAY zmk_display_init(); @@ -41,5 +109,13 @@ int main(void) { #endif /* CONFIG_ZMK_DISPLAY */ +<<<<<<< HEAD + + k_msleep(20); + f1_f13_fn_exchange_start_check(); + + +======= return 0; +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 } diff --git a/app/src/usb.c b/app/src/usb.c index cf76341eee2..8510ba8eb1f 100644 --- a/app/src/usb.c +++ b/app/src/usb.c @@ -14,11 +14,19 @@ #include #include #include +#include "version.h" +#include +#include #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); - +void bt_24g_switch_reset(void); +void bt_24g_switch_pulldown(uint8_t current); +void zmk_usb_set_protocol_report(void); +void keyboad_led_set_onoff(uint8_t led_state); +uint8_t keyboard_get_led_state(void); +uint32_t usb_sof_count=0; static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; static bool is_configured; @@ -31,14 +39,24 @@ K_WORK_DEFINE(usb_status_notifier_work, raise_usb_status_changed_event); enum usb_dc_status_code zmk_usb_get_status(void) { return usb_status; } +<<<<<<< HEAD +enum zmk_usb_conn_state zmk_usb_get_conn_state() { + // LOG_DBG("state: %d", usb_status); +======= enum zmk_usb_conn_state zmk_usb_get_conn_state(void) { LOG_DBG("state: %d", usb_status); +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 switch (usb_status) { - case USB_DC_SUSPEND: + // case USB_DC_SUSPEND: + // LOG_DBG("USB_DC_SUSPEND"); case USB_DC_CONFIGURED: case USB_DC_RESUME: +<<<<<<< HEAD + case USB_DC_CLEAR_HALT: +======= case USB_DC_CLEAR_HALT: case USB_DC_SOF: +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 return ZMK_USB_CONN_HID; case USB_DC_DISCONNECTED: @@ -55,6 +73,54 @@ bool zmk_usb_is_hid_ready(void) { } void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) { +<<<<<<< HEAD + static uint8_t led_bak_state=0; + usb_status = status; + + switch(status) + { + case USB_DC_RESET: + + zmk_usb_set_protocol_report(); + led_bak_state =0; + usb_sof_count=0; + break; + case USB_DC_RESUME: + + if(get_current_transport()==ZMK_TRANSPORT_USB) + { + keyboad_led_set_onoff(led_bak_state); + } + usb_sof_count =0; + break; + case USB_DC_SUSPEND: + led_bak_state= keyboard_get_led_state(); + if(get_current_transport()==ZMK_TRANSPORT_USB) + { + keyboad_led_set_onoff(0); + } + break; + case USB_DC_DISCONNECTED: + + break; + default: + break; + } + LOG_ERR("status:%d,sof:%d",status,usb_sof_count); + k_work_submit(&usb_status_notifier_work); +}; +extern struct usb_desc_header __usb_descriptor_start[]; +static int zmk_usb_init(const struct device *_arg) { + + struct usb_device_descriptor *device_descriptor=(struct usb_device_descriptor *)__usb_descriptor_start; + if(device_descriptor) + { + LOG_ERR("usb bcd ver:%x",device_descriptor->bcdDevice); + device_descriptor->bcdDevice = sys_cpu_to_le16(USB_BCD_VER); + LOG_ERR("new usb bcd ver:%x,ver:%s",device_descriptor->bcdDevice,APP_VERSION_STRING); + } + +======= // Start-of-frame events are too frequent and noisy to notify, and they're // not used within ZMK if (status == USB_DC_SOF) { @@ -76,6 +142,7 @@ void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) { }; static int zmk_usb_init(void) { +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 int usb_enable_ret; usb_enable_ret = usb_enable(usb_status_cb); @@ -89,3 +156,8 @@ static int zmk_usb_init(void) { } SYS_INIT(zmk_usb_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); + +uint32_t get_usb_sof_count(void) +{ + return usb_sof_count; +} \ No newline at end of file diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c index 9adc7db8092..722110f422a 100644 --- a/app/src/usb_hid.c +++ b/app/src/usb_hid.c @@ -23,14 +23,52 @@ #endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS) #include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); +void keyboad_led_set_onoff(uint8_t led_state); +uint32_t get_usb_sof_count(void); + static const struct device *hid_dev; static K_SEM_DEFINE(hid_sem, 1, 1); +static uint8_t zmk_usb_protocol=HID_PROTOCOL_REPORT; +void zmk_usb_set_protocol_report(void) +{ + zmk_usb_protocol=HID_PROTOCOL_REPORT; +} +void zmk_usb_protocol_change(const struct device *dev, uint8_t protocol) +{ + zmk_usb_protocol =protocol; + LOG_DBG("usb protocol:%d",protocol); +} +static void out_ready_cb(const struct device *dev) +{ + uint8_t rev_buf[32]={0}; + uint32_t rev_bytes =0; + hid_int_ep_read(dev,rev_buf,sizeof(rev_buf),&rev_bytes); + LOG_HEXDUMP_DBG(rev_buf,rev_bytes,"rx"); + if(rev_buf[0]==ZMK_HID_REPORT_ID_KEYBOARD) + { + if(get_current_transport()==ZMK_TRANSPORT_USB) + keyboad_led_set_onoff(rev_buf[1]); + } +} static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); } +<<<<<<< HEAD +static int zmk_usb_hid_set_report(const struct device *dev, struct usb_setup_packet *setup, + int32_t *len, uint8_t **data) { + LOG_HEXDUMP_DBG(*data, *len, "set report"); + uint8_t *report=*data; + if(report[0]==ZMK_HID_REPORT_ID_KEYBOARD) + { + keyboad_led_set_onoff(report[1]); + } + return 0; +} +======= #define HID_GET_REPORT_TYPE_MASK 0xff00 #define HID_GET_REPORT_ID_MASK 0x00ff @@ -175,29 +213,61 @@ static int set_report_cb(const struct device *dev, struct usb_setup_packet *setu return 0; } +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 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, +<<<<<<< HEAD + .int_out_ready = out_ready_cb, + .set_report = zmk_usb_hid_set_report, + .protocol_change =zmk_usb_protocol_change +======= .get_report = get_report_cb, .set_report = set_report_cb, +>>>>>>> ead91ca094c6cd778574f73b9ae011ddab611c66 }; static int zmk_usb_hid_send_report(const uint8_t *report, size_t len) { switch (zmk_usb_get_status()) { - case USB_DC_SUSPEND: - return usb_wakeup_request(); + case USB_DC_ERROR: case USB_DC_RESET: case USB_DC_DISCONNECTED: case USB_DC_UNKNOWN: return -ENODEV; + case USB_DC_SUSPEND: + usb_wakeup_request(); + + for(int i=0;i<50;i++) + { + k_msleep(100); + if(!usb_get_remote_wakeup_status()|| get_usb_sof_count()>100) + { + LOG_ERR("i:%d,sof:%d",i,get_usb_sof_count()); + break; + } + } default: - k_sem_take(&hid_sem, K_MSEC(30)); - int err = hid_int_ep_write(hid_dev, report, len, NULL); + int sem_err=k_sem_take(&hid_sem, K_MSEC(100)); + if(sem_err) + { + LOG_ERR("sem err:%d",sem_err); + } + LOG_HEXDUMP_DBG(report,len,"usb"); + int err; + if(zmk_usb_protocol == HID_PROTOCOL_REPORT) + { + err = hid_int_ep_write(hid_dev, report, len, NULL); + } + else + { + err = hid_int_ep_write(hid_dev, &report[1], len-1, NULL); + } if (err) { + LOG_ERR("err:%d",err); k_sem_give(&hid_sem); } @@ -249,7 +319,7 @@ static int zmk_usb_hid_init(void) { #endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */ usb_hid_init(hid_dev); - + usb_hid_set_proto_code(hid_dev,1);//set boot keyboard! return 0; } diff --git a/app/src/version.h b/app/src/version.h new file mode 100644 index 00000000000..2258fe0d7b4 --- /dev/null +++ b/app/src/version.h @@ -0,0 +1,37 @@ +#ifndef __VERSION_H__ +#define __VERSION_H__ + +#if CONFIG_SHIELD_KEYCHRON_B1 +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define PATCHLEVEL 4 +#elif CONFIG_SHIELD_KEYCHRON_B2 +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define PATCHLEVEL 2 +#else +#define VERSION_MAJOR 1 +#define VERSION_MINOR 3 +#define PATCHLEVEL 3 +#endif +#define VERSION_TWEAK 0 +#define EXTRAVERSION "ZK" + +#define ZMK_VERSION (VERSION_MAJOR<<16| VERSION_MINOR<<8 | PATCHLEVEL)//0x00010209 +#define VIA_FIRMWARE_VERSION ZMK_VERSION + +#define USB_DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10)) + +/** USB Device release number (bcdDevice Descriptor field) */ +#define USB_BCD_VER (USB_DEC_TO_BCD(VERSION_MAJOR) << 8 | \ + USB_DEC_TO_BCD((VERSION_MINOR*10)+PATCHLEVEL)) +#define VER_STR1(a1,a2,a3,a4) "v"#a1"."#a2"."#a3"-"a4 +#define VER_STR(a1,a2,a3,a4) VER_STR1(a1,a2,a3,a4) + +#define APP_VERSION_STRING VER_STR(VERSION_MAJOR,VERSION_MINOR,PATCHLEVEL,EXTRAVERSION) + +//upate version.h 's timestamp in ps shell +//(Get-Item ".\src\version.h").LastWriteTime=$(Get-Date -format o) +//read version.h 's timestamp + //Get-Item .\src\version.h | Format-List CreationTime, LastAccessTime, LastWriteTime +#endif \ No newline at end of file