From dd35cb8cbfeb37481cceb4bb1bbf90311074ae2a Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Tue, 1 Sep 2026 22:51:10 -0500 Subject: [PATCH] Update Keychron QMK controller to pull keyboard's real firmware version when connected over wireless dongle, display both dongle and keyboard version --- .../QMKKeychronController.cpp | 89 ++++++++++++++++--- .../QMKKeychronController.h | 5 +- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/Controllers/QMKController/QMKKeychronController/QMKKeychronController.cpp b/Controllers/QMKController/QMKKeychronController/QMKKeychronController.cpp index ba4b39c61..925392490 100644 --- a/Controllers/QMKController/QMKKeychronController/QMKKeychronController.cpp +++ b/Controllers/QMKController/QMKKeychronController/QMKKeychronController.cpp @@ -26,15 +26,17 @@ QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char /*-----------------------------------------------------*\ | Initialize controller fields | \*-----------------------------------------------------*/ - dev = dev_handle; - location = path; - kc_protocol_version = 0; - kc_rgb_protocol_version = 0; - number_leds = 0; - supported_features = 0; - via_protocol_version = 0; - wireless_device_pid = 0; - wireless_device_vid = 0; + dev = dev_handle; + location = path; + kc_dongle_firmware_version = ""; + kc_firmware_version = ""; + kc_protocol_version = 0; + kc_rgb_protocol_version = 0; + number_leds = 0; + supported_features = 0; + via_protocol_version = 0; + wireless_device_pid = 0; + wireless_device_vid = 0; /*-----------------------------------------------------*\ | Read product string | @@ -113,7 +115,27 @@ QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char /*-----------------------------------------------------*\ | Get Keychron firmware version | \*-----------------------------------------------------*/ - kc_firmware_version = CmdGetKeychronFirmwareVersion(); + std::string initial_firmware = CmdGetKeychronFirmwareVersion(); + + if(wireless_device_vid != 0 && wireless_device_pid != 0) + { + /*-------------------------------------------------*\ + | For wireless connections: | + | - The initial firmware is the dongle's version | + | - Query the keyboard's firmware via wireless | + \*-------------------------------------------------*/ + kc_dongle_firmware_version = initial_firmware; + kc_firmware_version = CmdGetWirelessKeyboardFirmwareVersion(); + } + else + { + /*-------------------------------------------------*\ + | For wired connections: | + | - Use the firmware version directly | + | - No dongle firmware to display | + \*-------------------------------------------------*/ + kc_firmware_version = initial_firmware; + } /*-----------------------------------------------------*\ | Get supported Keychron features | @@ -238,10 +260,27 @@ std::string QMKKeychronController::GetVersion() /*-----------------------------------------------------*\ | Format multi-line version text | \*-----------------------------------------------------*/ - return("VIA: " + std::to_string(via_protocol_version) + "\r\n" + - "Keychron: " + std::to_string(kc_protocol_version) + "\r\n" + - "Keychron RGB: " + std::to_string(kc_rgb_protocol_version) + "\r\n" + - "Keychron FW: " + kc_firmware_version); + std::string result = "VIA: " + std::to_string(via_protocol_version) + "\r\n" + + "Keychron: " + std::to_string(kc_protocol_version) + "\r\n" + + "Keychron RGB: " + std::to_string(kc_rgb_protocol_version) + "\r\n"; + + if(!kc_dongle_firmware_version.empty()) + { + /*-------------------------------------------------*\ + | Wireless - show both dongle and keyboard | + \*-------------------------------------------------*/ + result += "Dongle FW: " + kc_dongle_firmware_version + "\r\n" + + "Keyboard FW: " + kc_firmware_version; + } + else + { + /*-------------------------------------------------*\ + | Wired - show keyboard only | + \*-------------------------------------------------*/ + result += "Keychron FW: " + kc_firmware_version; + } + + return(result); } bool QMKKeychronController::GetSupported() @@ -498,6 +537,28 @@ void QMKKeychronController::CmdGetWirelessDeviceInfo *wireless_pid = response[3] | (response[4] << 8); } +std::string QMKKeychronController::CmdGetWirelessKeyboardFirmwareVersion() +{ + /*-----------------------------------------------------*\ + | Query wireless keyboard firmware version via dongle | + | Similar to CmdGetKeychronFirmwareVersion but for | + | the connected wireless keyboard instead of the dongle | + \*-----------------------------------------------------*/ + char response[30] = { 0 }; + + if(ViaSendCommand(KC_WIRELESS_FIRMWARE_VERSION, NULL, 0, (unsigned char*)response, sizeof(response)) <= 0) + { + return(""); + } + + /*-----------------------------------------------------*\ + | Ensure response null termination | + \*-----------------------------------------------------*/ + response[29] = 0; + + return(std::string(response)); +} + void QMKKeychronController::CmdSaveMode() { ViaSendCommandSub(KC_KEYCHRON_RGB, KEYCHRON_RGB_SAVE, NULL, 0, NULL, 0); diff --git a/Controllers/QMKController/QMKKeychronController/QMKKeychronController.h b/Controllers/QMKController/QMKKeychronController/QMKKeychronController.h index d7ff05385..c94047d9e 100644 --- a/Controllers/QMKController/QMKKeychronController/QMKKeychronController.h +++ b/Controllers/QMKController/QMKKeychronController/QMKKeychronController.h @@ -48,7 +48,8 @@ enum KC_ANALOG_MATRIX = 0xA9, KC_WIRELESS_DFU = 0xAA, KC_FACTORY_TEST = 0xAB, - KC_WIRELESS_DEVICE_INFO = 0xB2 + KC_WIRELESS_DEVICE_INFO = 0xB2, + KC_WIRELESS_FIRMWARE_VERSION = 0xB3 }; enum KeychronKCRGBCommand @@ -152,6 +153,7 @@ public: private: hid_device* dev; + std::string kc_dongle_firmware_version; std::string kc_firmware_version; unsigned char kc_protocol_version; unsigned short kc_rgb_protocol_version; @@ -176,6 +178,7 @@ private: void CmdGetSupportFeature(unsigned short* supported_features); void CmdGetViaProtocolVersion(unsigned short* via_protocol_version); void CmdGetWirelessDeviceInfo(unsigned short* wireless_vid, unsigned short* wireless_pid); + std::string CmdGetWirelessKeyboardFirmwareVersion(); void CmdSaveMode(); void CmdSendLEDs(unsigned char start_index, unsigned char number_leds, RGBColor* color_data); void CmdSetBrightness(unsigned char brightness);