From 3bf1ecd9b1a13b4442e05ab182fe1012e257df06 Mon Sep 17 00:00:00 2001 From: lokher Date: Fri, 31 Oct 2025 11:18:35 +0800 Subject: [PATCH] Add NKRO command support for raw HID --- keyboards/keychron/common/keychron_common.mk | 3 +- keyboards/keychron/common/keychron_raw_hid.c | 13 ++++- keyboards/keychron/common/keychron_raw_hid.h | 15 +++++- keyboards/keychron/common/nkro.c | 56 ++++++++++++++++++++ 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 keyboards/keychron/common/nkro.c diff --git a/keyboards/keychron/common/keychron_common.mk b/keyboards/keychron/common/keychron_common.mk index 504e6885be..6da9bf21a0 100644 --- a/keyboards/keychron/common/keychron_common.mk +++ b/keyboards/keychron/common/keychron_common.mk @@ -8,7 +8,8 @@ SRC += \ $(KEYCHRON_COMMON_DIR)/factory_test.c \ $(KEYCHRON_COMMON_DIR)/backlit_indicator.c \ $(KEYCHRON_COMMON_DIR)/eeconfig_kb.c \ - $(KEYCHRON_COMMON_DIR)/dfu_info.c + $(KEYCHRON_COMMON_DIR)/dfu_info.c \ + $(KEYCHRON_COMMON_DIR)/nkro.c VPATH += $(KEYCHRON_COMMON_DIR) diff --git a/keyboards/keychron/common/keychron_raw_hid.c b/keyboards/keychron/common/keychron_raw_hid.c index f9277d25ca..a505207dee 100644 --- a/keyboards/keychron/common/keychron_raw_hid.c +++ b/keyboards/keychron/common/keychron_raw_hid.c @@ -43,6 +43,7 @@ #ifdef RAW_ENABLE extern void dfu_info_rx(uint8_t *data, uint8_t length); +extern void nkro_rx(uint8_t *data, uint8_t length); void get_support_feature(uint8_t *data) { data[0] = 0; @@ -70,7 +71,7 @@ void get_support_feature(uint8_t *data) { # endif ; - data[2] = (FEATURE_QUICK_START >> 8); + data[2] = (FEATURE_QUICK_START >> 8) | (FEATURE_NKRO >> 8); } void get_firmware_version(uint8_t *data) { @@ -153,7 +154,11 @@ bool kc_raw_hid_rx(uint8_t src, uint8_t *data, uint8_t length) { # ifdef USB_REPORT_INTERVAL_ENABLE | MISC_REPORT_REATE # endif - | MISC_QUICK_START; + | MISC_QUICK_START +# ifdef NKRO_ENABLE + | MISC_NKRO +# endif + ; break; case DFU_INFO_GET: @@ -185,6 +190,10 @@ bool kc_raw_hid_rx(uint8_t src, uint8_t *data, uint8_t length) { report_rate_hid_rx(data, length); } break; # endif + case NKRO_GET ... NKRO_SET: + nkro_rx(data, length); + break; + default: data[0] = 0xFF; data[1] = 0x00; diff --git a/keyboards/keychron/common/keychron_raw_hid.h b/keyboards/keychron/common/keychron_raw_hid.h index e04754a9ac..580cfad8cd 100644 --- a/keyboards/keychron/common/keychron_raw_hid.h +++ b/keyboards/keychron/common/keychron_raw_hid.h @@ -42,7 +42,8 @@ enum { FEATURE_SNAP_CLICK = 0x01U << 6, FEATURE_KEYCHRON_RGB = 0x01U << 7, - FEATURE_QUICK_START = 0x01 << 8 + FEATURE_QUICK_START = 0x01 << 8, + FEATURE_NKRO = 0x01 << 9, }; enum { @@ -52,7 +53,8 @@ enum { MISC_SNAP_CLICK = 0x01 << 3, MISC_WIRELESS_LPM = 0x01 << 4, MISC_REPORT_REATE = 0x01 << 5, - MISC_QUICK_START = 0x01 << 6 + MISC_QUICK_START = 0x01 << 6, + MISC_NKRO = 0x01 << 7, }; enum { @@ -70,7 +72,16 @@ enum { WIRELESS_LPM_SET, REPORT_RATE_GET, REPORT_RATE_SET, + DIP_SWITCH_GET, + DIP_SWITCH_SET, // 0x10 FACTORY_RESET, + NKRO_GET, + NKRO_SET, +}; + +enum { + KC_SUCCESS = 0, + KC_FAIL, }; void kc_raw_hid_send(uint8_t src, uint8_t *data, uint8_t len); diff --git a/keyboards/keychron/common/nkro.c b/keyboards/keychron/common/nkro.c new file mode 100644 index 0000000000..1ec65a5f9e --- /dev/null +++ b/keyboards/keychron/common/nkro.c @@ -0,0 +1,56 @@ +/* Copyright 2024 @ Keychron (https://www.keychron.com) + * + * 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 "quantum.h" +#include "keychron_raw_hid.h" + +void nkro_rx(uint8_t *data, uint8_t length) { + if (data[0] != KC_MISC_CMD_GROUP) return; + + uint8_t cmd = data[1]; + switch (cmd) { + case NKRO_GET: + data[2] = KC_SUCCESS; + data[3] = ((keymap_config.nkro ? 0x01 : 0x00) << 0) +#if defined(NKRO_ENABLE) && !defined(APDAPTIVE_NKRO_ENABLE) + | (0x01 << 1) +#endif +#ifdef APDAPTIVE_NKRO_ENABLE + | (0x01 << 2) +#endif + ; + break; + + case NKRO_SET: + if (data[2] > 1) { + data[2] = KC_FAIL; + } else { +#if defined(NKRO_ENABLE) && !defined(APDAPTIVE_NKRO_ENABLE) + keymap_config.nkro = data[2]; + eeconfig_update_keymap(keymap_config.raw); + data[2] = KC_SUCCESS; +#else + data[2] = KC_FAIL; +#endif + } + break; + + default: + data[0] = 0xFF; + break; + } +}