This document assumes at least some knowledge of how USB works. If you do not understand the different transfer modes, interfaces and endpoints described by the USB standard, it is recommended that you first spend some time understanding the details of that.
The Cooler Master bVendor
is 0x2516
, which is the same for all
keyboards. However, each keyboard has a different bDevice
, even
devices with the same name.
My own keyboard has a bDevice
value of 0x003b
. However, the USB
ID repository also reports
0x0047
as a bDevice
for the MasterKeys Pro L
.
Revisions and switches
Personally, I would guess that the differences in bDevice
values stem
from two things. First off, there are at least two revisions of the
MasterKeys Pro L
keyboard. The first revision was prone to having
some issues with specific keys.
The second revision (as I can attest to) does not have these issues.
Second, there might be different device ids for the keyboards with different layouts. There are two main layouts available (independent of QWERTY OR QWERTZ): US (ANSI) and ISO (EU). My device is ANSI.
Library Implementation
This library does not implement device detection by using the vendor
and device ids, but instead loops over a list of the devices and checks
if the descriptor strings (iManufacturer
and iProduct
) contain the
identifying marks of a MasterKeys
keyboard.
The MasterKeys keyboard present themselves to the system with three interfaces, each of them recognized as a HID device. These interfaces are:
- Interface 0: HID Device
EndPoint 1 IN, 8 byte packets, 0x81
- Interface 1: HID Device
EndPoint 3 IN, 64 byte packets, 0x83
EndPoint 4 OUT, 64 byte packets, 0x04
- Interface 2: HID Device
EndPoint 2 IN, 64 byte packets, 0x82
It is the second interface, numbered 1, with the endpoints 3 and 4 that is used for LED control. The commands should be written in 64 byte packets to EndPoint 4, return data is received on EndPoint 4. This data can be the data stored in the keyboard itself and confirmation messages.
All packets must be 64 bytes in size. The packets are created in the
library using the libmk_build_packet
function. At the top of libmk.c
is a list of packet headers (first byte) and opcodes (second byte).
There ought to be a pattern discoverable in the headers and opcodes,
but so far it is unclear what each and exact bit does. Further analysis
of the protocol with more instructions may yield more insight.
Disclaimer: Following is a list of packet descriptions. Note that
these were written based on the MasterKeys Pro L ANSI
, and that
different keyboards, particularly with only monochrome LEDs, may work
differently.
Enable keyboard LED control. Control is not automatically released. Sets the currently active LED profile to be altered.
41 02 00 ...
Release keyboard LED control. Automatically released (and then reclaimed) when a new Enable packet is received.
41 00 00 ...
Flush the keyboard color data that is in cache on the chip to the
actual LED controllers. Used in libmk_set_all_led_color
.
50 55 00 ...
Simple: An effect can simply be enabled based on the last given settings (generally default) using the 'simple' effect setting method.
41 01 00 ...
51 28 00 00 xx 00 ...
xx: Effect number (enum LibMK_Effect)
The first packet somehow puts the keyboard into a different mode. The exact purpose is currently unknown. The second packet sets the actual effect.
Detailed: Effects can take additional arguments through specific bytes.
51 28 00 00 nn ss dd aa FF FF fr fg fb br bg bb FF FF ...
nn: Effect number (enum LibMK_Effect)
ss: Effect speed
dd: Effect direction (00, 02, 04, 06, %8)
aa: Effect amount (purpose differs wildly)
f*: Foreground color r, g, b
b*: Background color r, g, b
The rest of the packet is filled with FF.
Effect LIBMK_EFF_CUSTOM
should be enabled before sending these
packets. The amount of packets (probably) depends on the size of the
keyboard. The offset conversion tables are used to build the packets.
Each packet contains the data for LIBMK_ALL_LED_PER_PCK
LEDs. For
a full keyboard, that is LIBMK_ALL_LED_PCK_NUM
packets.
51 A8 xx 00 00 yy yy yy ... 00 00 00
xx: Offset of this package: 2 * (key offset % LIBMK_ALL_PER_PCK)
00, 02, 04 ... etc.
yy: 3 element color values for 16 LEDs: rr gg bb rr gg bb ... etc.
The rest of the packet is filled up with zeros.
Currently lights only a single LED on the keyboard (so even if
libmk_set_single_led
is called multiple times, the previously lit
LEDs will turn off once a new one is turned on). There should be a way
to allow setting the color of multiple LEDs this way, but that it is
as of yet unclear how to achieve this.
C0 01 01 00 oo rr gg bb 00 00 ...
oo: Key offset
- Determine how to read effect profiles from the keyboard