|
| 1 | +# MasterKeys Pro Interface Description |
| 2 | +This document assumes at least some knowledge of how USB works. If you |
| 3 | +do not understand the different transfer modes, interfaces and endpoints |
| 4 | +described by the USB standard, it is recommended that you first spend |
| 5 | +some time understanding the details of that. |
| 6 | + |
| 7 | +## Device Descriptors |
| 8 | +The Cooler Master `bVendor` is `0x2516`, which is the same for all |
| 9 | +keyboards. However, each keyboard has a different `bDevice`, even |
| 10 | +devices with the same name. |
| 11 | + |
| 12 | +My own keyboard has a `bDevice` value of `0x003b`. However, the [USB |
| 13 | +ID repository](https://usb-ids.gowdy.us/read/UD/2516) also reports |
| 14 | +`0x0047` as a `bDevice` for the `MasterKeys Pro L`. |
| 15 | + |
| 16 | +**Revisions and switches** |
| 17 | + |
| 18 | +Personally, I would guess that the differences in `bDevice` values stem |
| 19 | +from two things. First off, there are at least two revisions of the |
| 20 | +`MasterKeys Pro L` keyboard. The first revision was prone to [having |
| 21 | +some issues with specific keys](https://www.reddit.com/r/MechanicalKeyboards/comments/4ui8v9/help_cooler_master_masterkeys_pro_l_nonresponsive/). |
| 22 | +The second revision (as I can attest to) does not have these issues. |
| 23 | + |
| 24 | +Second, there might be different device ids for the keyboards with |
| 25 | +different layouts. There are two main layouts available (independent of |
| 26 | +QWERTY OR QWERTZ): US (ANSI) and ISO (EU). My device is ANSI. |
| 27 | + |
| 28 | +**Library Implementation** |
| 29 | + |
| 30 | +This library does not implement device detection by using the vendor |
| 31 | +and device ids, but instead loops over a list of the devices and checks |
| 32 | +if the descriptor strings (`iManufacturer` and `iProduct`) contain the |
| 33 | +identifying marks of a `MasterKeys` keyboard. |
| 34 | + |
| 35 | +## Connection |
| 36 | +The MasterKeys keyboard present themselves to the system with three |
| 37 | +interfaces, each of them recognized as a HID device. These interfaces |
| 38 | +are: |
| 39 | +```markdown |
| 40 | +- Interface 0: HID Device |
| 41 | + EndPoint 1 IN, 8 byte packets, 0x81 |
| 42 | +- Interface 1: HID Device |
| 43 | + EndPoint 3 IN, 64 byte packets, 0x83 |
| 44 | + EndPoint 4 OUT, 64 byte packets, 0x04 |
| 45 | +- Interface 2: HID Device |
| 46 | + EndPoint 2 IN, 64 byte packets, 0x82 |
| 47 | +``` |
| 48 | + |
| 49 | +It is the second interface, numbered 1, with the endpoints 3 and 4 that |
| 50 | +is used for LED control. The commands should be written in 64 byte |
| 51 | +packets to EndPoint 4, return data is received on EndPoint 4. This data |
| 52 | +can be the data stored in the keyboard itself and confirmation messages. |
| 53 | + |
| 54 | +## Packets |
| 55 | +All packets must be 64 bytes in size. The packets are created in the |
| 56 | +library using the `libmk_build_packet` function. At the top of `libmk.c` |
| 57 | +is a list of packet headers (first byte) and opcodes (second byte). |
| 58 | +There ought to be a pattern discoverable in the headers and opcodes, |
| 59 | +but so far it is unclear what each and exact bit does. Further analysis |
| 60 | +of the protocol with more instructions may yield more insight. |
| 61 | + |
| 62 | +**Disclaimer**: Following is a list of packet descriptions. Note that |
| 63 | +these were written based on the `MasterKeys Pro L ANSI`, and that |
| 64 | +different keyboards, particularly with only monochrome LEDs, may work |
| 65 | +differently. |
| 66 | + |
| 67 | +#### Enable |
| 68 | +Enable keyboard LED control. Control is not automatically released. Sets |
| 69 | +the currently active LED profile to be altered. |
| 70 | +```hex |
| 71 | +41 02 00 ... |
| 72 | +``` |
| 73 | + |
| 74 | +#### Disable |
| 75 | +Release keyboard LED control. Automatically released (and then |
| 76 | +reclaimed) when a new Enable packet is received. |
| 77 | +```hex |
| 78 | +41 00 00 ... |
| 79 | +``` |
| 80 | + |
| 81 | +#### Flush |
| 82 | +Flush the keyboard color data that is in cache on the chip to the |
| 83 | +actual LED controllers. Used in `libmk_set_all_led_color`. |
| 84 | +```hex |
| 85 | +50 55 00 ... |
| 86 | +``` |
| 87 | + |
| 88 | +#### Effects |
| 89 | +**Simple**: |
| 90 | +An effect can simply be enabled based on the last given settings |
| 91 | +(generally default) using the 'simple' effect setting method. |
| 92 | +```hex |
| 93 | +41 01 00 ... |
| 94 | +
|
| 95 | +51 28 00 00 xx 00 ... |
| 96 | +xx: Effect number (enum LibMK_Effect) |
| 97 | +``` |
| 98 | +The first packet somehow puts the keyboard into a different mode. The |
| 99 | +exact purpose is currently unknown. The second packet sets the actual |
| 100 | +effect. |
| 101 | + |
| 102 | +**Detailed**: |
| 103 | +Effects can take additional arguments through specific bytes. |
| 104 | +```hex |
| 105 | +51 28 00 00 nn ss dd aa FF FF fr fg fb br bg bb FF FF ... |
| 106 | +nn: Effect number (enum LibMK_Effect) |
| 107 | +ss: Effect speed |
| 108 | +dd: Effect direction (00, 02, 04, 06, %8) |
| 109 | +aa: Effect amount (purpose differs wildly) |
| 110 | +f*: Foreground color r, g, b |
| 111 | +b*: Background color r, g, b |
| 112 | +The rest of the packet is filled with FF. |
| 113 | +``` |
| 114 | + |
| 115 | +#### All LED colors |
| 116 | +Effect `LIBMK_EFF_CUSTOM` should be enabled before sending these |
| 117 | +packets. The amount of packets (probably) depends on the size of the |
| 118 | +keyboard. The offset conversion tables are used to build the packets. |
| 119 | +Each packet contains the data for `LIBMK_ALL_LED_PER_PCK` LEDs. For |
| 120 | +a full keyboard, that is `LIBMK_ALL_LED_PCK_NUM` packets. |
| 121 | +```hex |
| 122 | +51 A8 xx 00 00 yy yy yy ... 00 00 00 |
| 123 | +
|
| 124 | +xx: Offset of this package: 2 * (key offset % LIBMK_ALL_PER_PCK) |
| 125 | + 00, 02, 04 ... etc. |
| 126 | +yy: 3 element color values for 16 LEDs: rr gg bb rr gg bb ... etc. |
| 127 | +The rest of the packet is filled up with zeros. |
| 128 | +``` |
| 129 | + |
| 130 | +#### Single LED color |
| 131 | +Currently lights only a single LED on the keyboard (so even if |
| 132 | +`libmk_set_single_led` is called multiple times, the previously lit |
| 133 | +LEDs will turn off once a new one is turned on). There should be a way |
| 134 | +to allow setting the color of multiple LEDs this way, but that it is |
| 135 | +as of yet unclear how to achieve this. |
| 136 | +```hex |
| 137 | +C0 01 01 00 oo rr gg bb 00 00 ... |
| 138 | +oo: Key offset |
| 139 | +``` |
| 140 | + |
| 141 | +## TODO-list |
| 142 | +- Determine how to read effect profiles from the keyboard |
0 commit comments