reverse engineering my keyboard

screen sync working — keyboard matching screen colors

the final result — keyboard colors matching the screen

so i bought this Redragon K617 Fizz in my first year. a nice little 60% keyboard, nothing too fancy. but the one thing i always wanted was screen sync — like what Razer keyboards have, where the keyboard colors match whatever is on the screen. or even a volume visualizer kind of thing. that was always in the back of my head.

i was dual booting Arch and Windows back then. mainly used Arch for everything but some software only worked on Windows and running a VM consumed too many resources, so i just kept a dual boot. the Redragon RGB software was Windows-only though, and even on Windows it was pretty basic. no screen sync, no API, no way to control it programmatically.

redragon oem software

the Redragon OEM software — Windows only, no API

fast forward about a year and three months. i was studying the AArch64 architecture (ARMv8) and for some reason i randomly got the idea that maybe i could reverse engineer this keyboard's protocol myself. no idea why that thought came up while reading about ARM, but it did. so that saturday morning i just went for it.

finding the device

first step was figuring out what this keyboard actually is on USB. opened Device Manager on Windows, found the HID device, and grabbed the vendor and product IDs.

hid device properties showing vid and pid

HID device properties — VID/PID identification

field value
keyboard Redragon K617 Fizz (60%, wired)
controller Sinowealth SH68F83
USB VID 0x258A
USB PID 0x0049
HID interface Interface 1, usage page 0xFF00 (vendor-defined)
report size 1032 bytes per packet

the Sinowealth SH68F83 is a pretty common chip in budget keyboards. no public documentation, no SDK. everything about how it handles RGB is proprietary.

capturing USB traffic

the plan was simple — set a color in the OEM software, capture whatever it sends over USB, and replay it from Linux. installed USBPcap on Windows, opened Wireshark, and started recording.

wireshark usb capture

Wireshark capture of the RGB protocol

this is where i got stuck for a while. i was using a host-only filter on Wireshark, which meant i was filtering out device-to-host traffic. turns out there is one critical packet in that direction — a GET_REPORT handshake — and without it, every single write to the keyboard gets silently ignored. no error, no feedback, just nothing happens. it took me hours to figure out that my filter was hiding the one packet that makes the whole thing work.

once i removed that filter, i could see the full sequence. the protocol turned out to be exactly 5 packets, always in this order:

step type size purpose
1 SET_REPORT (id=0x05) 6 bytes INIT — tells firmware "i want to write colors"
2 GET_REPORT (id=0x06) 1032 bytes mandatory handshake — read and discard
3 SET_REPORT (id=0x06) 1032 bytes P1 — the RGB color canvas
4 SET_REPORT (id=0x06) 1032 bytes P2 — key routing (never modify)
5 SET_REPORT (id=0x06) 1032 bytes EXEC — flash commit with 5AA5 marker

cracking the P1 canvas

the P1 packet is where all the actual color data lives. it's a 1032-byte blob, but the interesting part is how colors are encoded. it's not RGB triplets per key like you would expect. instead it uses a split-plane architecture — one region for all blue values, one for all green values, one for all red values.

channel base offset byte range
blue 8 bytes 5–126
green 134 bytes 127–252
red 260 bytes 281–378

the formula to set any key to any color:

p1[8   + led_index] = blue_value   (0-255)
p1[134 + led_index] = green_value  (0-255)
p1[260 + led_index] = red_value    (0-255)

i figured this out by flooding regions with 0xFF and watching which keys lit up and what color. start with a range, see what happens, narrow it down. the data follows a stride-21 layout — each keyboard row takes 14 bytes of actual data followed by a 7-byte gap. once i saw that pattern, mapping individual keys became straightforward.

probe bytes written result conclusion
probe4 test0 281–378 = 0xFF all keys red red plane confirmed
probe5 test1 5–65 = 0xFF rows 1–2 blue blue rows 1–2 at bytes 5–65
probe5 test2 127–187 = 0xFF rows 1–2 green green channel starts at 127
probe5 test5 127–280 = 0xFF all keys green full green range confirmed
probe5 test16 281–287 = 0xFF esc, 1, 2, 3, 4, 5, 6 red red row 0 map + stride-21 confirmed

i also tried opening the Redragon application in Ghidra to understand the protocol better. i could open the binary but couldn't really find references to the byte values i was looking for — couldn't trace where the app constructs those USB packets. but while digging through the software's directory, i found a file called Cfg.ini that had the complete LED index mapping for all 61 keys. that saved a lot of time, although by that point i had already figured out most of it manually through probing.

things that didn't work

not everything went smoothly.

P2 corruption. any modification to the P2 (routing) packet caused the firmware to crash. the keyboard would just restart. i learned pretty quickly to treat P2 as read-only — copy it exactly from a known-good capture and never touch it.

flash writes every time. every EXEC packet contains a 5AA5 magic marker that triggers a flash write. there is no RAM-only path — i tried skipping EXEC, zeroing out the 5AA5 marker, skipping P2, and even the OEM software's preview mode still flashes. the keyboard commits to flash on every single color change. flash endurance on these Sinowealth chips is around 100,000 cycles.

that killed the real-time screen sync dream, at least with this approach.

what works

keyboard with single red esc key

per-key control working — only esc set to red

per-key RGB control works perfectly. i can set any of the 61 keys to any color independently. and i built a screen sync tool on top of that — it captures a screenshot using maim, samples the color at each key's physical position on the screen, maps those colors to the keyboard, and applies them in one shot.

it's not real-time, but running it manually when you want your keyboard to match your screen is still pretty satisfying. the script needs sudo to access the HID device, but then maim can't access the X11 display because it's running as root. had to handle DISPLAY and XAUTHORITY environment variables and run maim as the original user to work around that.

what's next

one interesting direction for the future would be writing completely custom firmware. the SH68F83 is an 8051-based microcontroller, and if i could figure out how the LED matrix is wired to the board — like which rows and columns connect to which GPIO pins — i could flash my own firmware and have full control over everything. that's a much bigger project though.

what i learned

USB HID is surprisingly approachable once you get past the initial confusion. feature reports, output reports, usage pages — it sounds intimidating but Wireshark makes it very visual. the hardest part wasn't the protocol itself, it was figuring out that one missing GET_REPORT handshake.

also learned that cheap keyboard controllers are surprisingly capable chips. the SH68F83 has a full 8051 core, handles USB, drives the LED matrix, scans the key matrix — all on one chip. reverse engineering it was a good intro to embedded systems without needing any extra hardware.

github.com/orignalbox/k617-fizz
Published on: April 5, 2026