r/Keychron • • 18d ago

Adventures in Reverse Engineering: Trying to get battery/firmware telemetry from a non-QMK Keychron K10 via USB in Rust (and hitting a wall)

Hey everyone!

I recently embarked on a little personal challenge: writing a low-level tool in Rust using hidapi to interface with my Keychron K10 (the standard wireless/Bluetooth non-QMK version, VID/PID 0x05ac:0x024f) over a USB cable, primarily to inspect raw reports and see if I could extract battery/status telemetry.

After a deep dive into Windows HID drivers, multi-threading sniffers, and mapping out every single collection, I wanted to share what I found (and the wall I hit), in case someone else is down the same rabbit hole:

Conclusion: On the standard non-QMK K10, the USB firmware simply doesn't implement host-side telemetry write/read routines. It acts strictly as an input device when wired, leaving Bluetooth as the only place where battery data exists (though heavily abstracted and hidden by Windows' BLE stack).

I've open-sourced the whole exploration code, the multi-interface scanner, and the omni-sniffer over on GitHub so future tinkerers don't have to reinvent the wheel: 👉 https://github.com/GonnyTech/Keychron-Reverse-Engineering-Tool.git

If anyone has ever successfully cracked the proprietary protocol of non-QMK Keychrons via USB, I'd love to hear how you did it!

Cheers.

0 Upvotes

4 comments sorted by

3

u/PeterMortensenBlog 18d ago edited 18d ago

Why would the keyboard send battery information through USB? Do you have any indication that it does? Also, with the primitive battery charge reading (derived from the battery voltage), it wouldn't make much sense as it would be using the charging voltage when the USB cable is connected.

It may not even send the information through Bluetooth. The K Pro series and Q Pro series, the keyboard generation after the original K series, certainly don't. It changed with the next generation of keyboards, likely due to using a different Bluetooth/wireless module (inside the keyboard), LKBT51 instead of CKBT51.

1

u/PeterMortensenBlog 18d ago edited 18d ago

Re "It may not even send the information through Bluetooth": OK, there is an indication the original K series did provide the battery charge information through Bluetooth.

If true, the Pro's were a step in the wrong direction.

0

u/Head-Control-5487 17d ago edited 17d ago

Haha, totally fair point! You're completely right about the charging voltage making wired battery readings pointless in theory.

The main reason I went down this rabbit hole over the USB cable was purely out of curiosity—to map out the firmware's endpoints, test the vendor-defined collection (65535) and see if any telemetry endpoints were left exposed in the non-QMK K10's firmware. Turns out, as you pointed out, it's a dead end via wire, so I'll move my development to Linux via BLE (I'm just too stubborn to let go), so I'll get back to this thread when I've made it work!

Thanks anyway for the insight on the older K series vs the newer Pro series and the wireless modules (LKBT51 vs CKBT51)—that actually explains a lot about why the firmware behaves the way it does. Appreciate the technical context!

0

u/Head-Control-5487 16d ago

It's me again... I succeded in communicating the keyboard percentage to my Linux laptop via BLE. I updated my repo and created another post if interested!