The control mechanism seems to be an 8-byte USB HID feature reports.
Below is the structure of the 8-byte feature report:
Byte | Purpose | Example | Notes |
---|---|---|---|
0 | Instruction? | 0x08 |
Only 0x08 appears to issue commands |
1 | Unknown? | 0x00 |
Values appear to make no difference. |
2 | Program | 0x01 |
See below |
3 | Speed | 0x06 |
See below |
4 | Brightness | 0x32 |
See below |
5 | Colour | 0x02 |
See below |
6 | Unknown? | 0x01 |
Values appear to make no difference. |
7 | Checksum | 0xbb |
255 - sum(b0-b6) |
Byte Value | Program | Notes |
---|---|---|
0x01 |
Static | |
0x02 |
Breathing | |
0x03 |
Wave | |
0x04 |
Fade on Keypress | |
0x05 |
Marquee | Does not support random colour - value ignored |
0x06 |
Ripple | |
0x07 |
Flash on Keypress | |
0x08 |
Neon | |
0x09 |
Rainbow Marquee | Only supports random colour - other values ignored |
0x0a |
Raindrop | |
0x0b |
Circle Marquee | |
0x0c |
Hedge | |
0x0d |
Rotate | |
0x33 |
Custom 1 | |
0x34 |
Custom 2 | |
0x35 |
Custom 3 | |
0x36 |
Custom 4 | |
0x37 |
Custom 5 |
Stored in code: here.
Byte Value | Speed |
---|---|
0x0a |
Slowest |
0x09 |
|
0x08 |
|
0x07 |
|
0x06 |
|
0x05 |
|
0x04 |
|
0x03 |
|
0x02 |
|
0x01 |
Fastest |
Byte Value | Colour |
---|---|
0x01 |
Red |
0x02 |
Green |
0x03 |
Yellow |
0x04 |
Blue |
0x05 |
Orange |
0x06 |
Purple |
0x07 |
White |
0x08 |
Rainbow / Random |
Stored in code: here.
Note: All other values inc 0x00
result in 0x08
- Rainbow/Random
A few examples below, with checksums.
Static, Green, Slowest, Full Brightness:
[0x08, 0x00, 0x01, 0x0A, 0x64, 0x02, 0x01, 0x85]
Fade on Press, Green, Slowest, Full Brightness:
[0x08, 0x00, 0x04, 0x0A, 0x64, 0x02, 0x01, 0x82]
Fade on Press, Yellow, Slowest, Full Brightness:
[0x08, 0x00, 0x04, 0x0A, 0x64, 0x03, 0x01, 0x81]
Fade on Press, Random, Slowest, Full Brightness:
[0x08, 0x00, 0x04, 0x0A, 0x64, 0x08, 0x01, 0x7C]
Marquee, Purple, Slowest, Full Brightness:
[0x08, 0x00, 0x05, 0x0A, 0x64, 0x06, 0x01, 0x7D]
Custom 1:
[0x08, 0x00, 0x33, 0x0A, 0x64, 0x00, 0x01, 0x55]
They keyboard supports 5 static custom layouts which are essentially an array of keys.
Programming requires the selection of the custom layout (as above), issuing a 'start programming' command, sending the data then selecting the layout again.
The data is sent as an array of [key_index, red, green, blue]
in batches of 16 values (64 bytes each). There are about 120 key indexes, though not all are used on all keyboards.
It appears best to send them in order, even when some values are not used (such as key indicies less than 6, for example:
[0x01, red, grn, blu, 0x02, red, grn, blu,
0x03, red, grn, blu, 0x04, red, grn, blu,
0x05, red, grn, blu, 0x06, red, grn, blu,
0x07, red, grn, blu, 0x08, red, grn, blu,
0x09, red, grn, blu, 0x0a, red, grn, blu,
0x0b, red, grn, blu, 0x0c, red, grn, blu,
0x0d, red, grn, blu, 0x0e, red, grn, blu,
0x0f, red, grn, blu, 0x10, red, grn, blu]
Select Custom 1 (as above):
[0x08, 0x00, 0x33, 0x0A, 0x64, 0x00, 0x01, 0x55]
Send 'start programming':
[0x12, 0x00, cidx, 0x08, 0x00, 0x00, 0x00, chks]
cidx
represents the custom profile index, but zero based, so Custom 1 is 0, Custom 2 is 1, etc.
chks
is the usual checksum.
Send the data (this example is the data from the group-based mapping described below).
There are 8 packets sent, each is 64 bytes, the start reference below is the offset in the overall keyboard colouring array
# Packet 1/8, len: 64 bytes, start element: 0
#ix1, reg, grn, blu, ix2, red, grn, blu
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x07, 0x40, 0xFF, 0x7F, 0x08, 0x40, 0xFF, 0x7F,
0x09, 0x40, 0xFF, 0x7F, 0x0A, 0x40, 0xFF, 0x7F,
0x0B, 0x7F, 0xFF, 0xFF, 0x0C, 0x7F, 0xFF, 0xFF,
0x0D, 0x40, 0xFF, 0x7F, 0x0E, 0x7F, 0x7F, 0xFF,
0x0F, 0xFF, 0xFF, 0x7F, 0x10, 0xFF, 0xFF, 0x7F
# Packet 2/8, len: 64 bytes, start element: 16
#i17, red, grn, blu, etc...
0x11, 0xFF, 0x7F, 0x7F, 0x12, 0x7F, 0x40, 0xFF,
0x13, 0x40, 0xFF, 0x7F, 0x14, 0xFF, 0xFF, 0x7F,
0x15, 0xFF, 0xFF, 0x7F, 0x16, 0xFF, 0xFF, 0x7F,
0x17, 0xFF, 0x7F, 0x7F, 0x18, 0x7F, 0x40, 0xFF,
0x19, 0x40, 0xFF, 0x7F, 0x1A, 0xFF, 0xFF, 0x7F,
0x1B, 0xFF, 0xFF, 0x7F, 0x1C, 0xFF, 0xFF, 0x7F,
0x1D, 0xFF, 0x7F, 0x7F, 0x1E, 0x7F, 0x40, 0xFF,
0x1F, 0x00, 0x00, 0x00, 0x20, 0xFF, 0xFF, 0x7F
# Packet 3/8, len: 64 bytes, start element: 32
0x21, 0xFF, 0xFF, 0x7F, 0x22, 0xFF, 0xFF, 0x7F,
0x23, 0xFF, 0x7F, 0x7F, 0x24, 0x7F, 0x40, 0xFF,
0x25, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFF, 0x7F,
0x27, 0xFF, 0xFF, 0x7F, 0x28, 0xFF, 0xFF, 0x7F,
0x29, 0xFF, 0x7F, 0x7F, 0x2A, 0x7F, 0x40, 0xFF,
0x2B, 0x64, 0x64, 0xFF, 0x2C, 0xFF, 0xFF, 0x7F,
0x2D, 0xFF, 0xFF, 0x7F, 0x2E, 0xFF, 0xFF, 0x7F,
0x2F, 0xFF, 0x7F, 0x7F, 0x30, 0x7F, 0x40, 0xFF
# Packet 4/8, len: 64 bytes, start element: 48
0x31, 0x00, 0x00, 0x00, 0x32, 0xFF, 0xFF, 0x7F,
0x33, 0xFF, 0xFF, 0x7F, 0x34, 0xFF, 0xFF, 0x7F,
0x35, 0xFF, 0x7F, 0x7F, 0x36, 0x7F, 0x40, 0xFF,
0x37, 0x00, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0x7F,
0x39, 0xFF, 0xFF, 0x7F, 0x3A, 0xFF, 0xFF, 0x7F,
0x3B, 0xFF, 0x7F, 0x7F, 0x3C, 0x7F, 0x40, 0xFF,
0x3D, 0x40, 0xFF, 0x7F, 0x3E, 0x7F, 0x7F, 0xFF,
0x3F, 0xFF, 0xFF, 0x7F, 0x40, 0xFF, 0xFF, 0x7F
# Packet 5/8, len: 64 bytes, start element: 64
0x41, 0xFF, 0x7F, 0x7F, 0x42, 0x7F, 0x40, 0xFF,
0x43, 0x40, 0xFF, 0x7F, 0x44, 0x7F, 0x7F, 0xFF,
0x45, 0x7F, 0x7F, 0xFF, 0x46, 0xFF, 0xFF, 0x7F,
0x47, 0xFF, 0x7F, 0x7F, 0x48, 0x7F, 0x40, 0xFF,
0x49, 0x40, 0xFF, 0x7F, 0x4A, 0x7F, 0x7F, 0xFF,
0x4B, 0x7F, 0x7F, 0xFF, 0x4C, 0x7F, 0x7F, 0xFF,
0x4D, 0x7F, 0xFF, 0xFF, 0x4E, 0x7F, 0x40, 0xFF,
0x4F, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00
# Packet 6/8, len: 64 bytes, startelement: 80
0x51, 0x00, 0x00, 0x00, 0x52, 0x7F, 0x7F, 0xFF,
0x53, 0x7F, 0xFF, 0xFF, 0x54, 0x7F, 0x40, 0xFF,
0x55, 0xFF, 0x7F, 0xFF, 0x56, 0x40, 0xFF, 0x7F,
0x57, 0x7F, 0x7F, 0xFF, 0x58, 0x00, 0x00, 0x00,
0x59, 0x00, 0x00, 0x00, 0x5A, 0x7F, 0xFF, 0xFF,
0x5B, 0xFF, 0x7F, 0xFF, 0x5C, 0xFF, 0x7F, 0xFF,
0x5D, 0xFF, 0xFF, 0xFF, 0x5E, 0x00, 0x00, 0x00,
0x5F, 0x7F, 0xFF, 0xFF, 0x60, 0x7F, 0xFF, 0xFF
# Packet 7/8, len: 64 bytes, start element: 96
0x61, 0xFF, 0x7F, 0xFF, 0x62, 0x7F, 0xFF, 0x7F,
0x63, 0x7F, 0xFF, 0x7F, 0x64, 0x7F, 0xFF, 0x7F,
0x65, 0x7F, 0xFF, 0x7F, 0x66, 0xFF, 0xFF, 0x7F,
0x67, 0x7F, 0xFF, 0x7F, 0x68, 0x7F, 0xFF, 0x7F,
0x69, 0x7F, 0xFF, 0x7F, 0x6A, 0x7F, 0xFF, 0x7F,
0x6B, 0x7F, 0xFF, 0x7F, 0x6C, 0xFF, 0xFF, 0x7F,
0x6D, 0x7F, 0xFF, 0x7F, 0x6E, 0x7F, 0xFF, 0x7F,
0x6F, 0x7F, 0xFF, 0x7F, 0x70, 0x7F, 0xFF, 0x7F
# Packet 8/8, len: 64 bytes, start element: 112
0x71, 0x7F, 0xFF, 0x7F, 0x72, 0xFF, 0xFF, 0x7F,
0x73, 0x7F, 0xFF, 0x7F, 0x74, 0x00, 0x00, 0x00,
0x75, 0x7F, 0xFF, 0x7F, 0x76, 0x00, 0x00, 0x00,
0x77, 0x7F, 0xFF, 0x7F, 0x78, 0xFF, 0xFF, 0x7F,
0x79, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00,
0x7B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00,
0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
Finally, select Custom 1 again:
[0x08, 0x00, 0x33, 0x0A, 0x64, 0x00, 0x01, 0x55]
The Key index mappings for the UK keyboard can be found here.
There are also a number of groups defined here for convenience.