Skip to content

Commit 69b99aa

Browse files
committed
Initial library version
Original history squashed together into a single commit with a working copy of the library with working CI
0 parents  commit 69b99aa

File tree

22 files changed

+3032
-0
lines changed

22 files changed

+3032
-0
lines changed

.gitignore

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Object files
5+
*.o
6+
*.ko
7+
*.obj
8+
*.elf
9+
10+
# Linker output
11+
*.ilk
12+
*.map
13+
*.exp
14+
15+
# Precompiled Headers
16+
*.gch
17+
*.pch
18+
19+
# Libraries
20+
*.lib
21+
*.a
22+
*.la
23+
*.lo
24+
25+
# Shared objects (inc. Windows DLLs)
26+
*.dll
27+
*.so
28+
*.so.*
29+
*.dylib
30+
31+
# Executables
32+
*.exe
33+
*.out
34+
*.app
35+
*.i*86
36+
*.x86_64
37+
*.hex
38+
39+
# Debug files
40+
*.dSYM/
41+
*.su
42+
*.idb
43+
*.pdb
44+
45+
# Kernel Module Compile Results
46+
*.mod*
47+
*.cmd
48+
.tmp_versions/
49+
modules.order
50+
Module.symvers
51+
Mkfile.old
52+
dkms.conf
53+
54+
# CLion
55+
/.idea
56+
57+
# CMake
58+
/CMakeFiles
59+
/cmake-build*
60+
61+
# Code::Blocks
62+
*.layout
63+
*.cbp
64+
*.depend
65+
66+
# Project Files
67+
Makefile
68+
main-*
69+
layout.*
70+
/_skbuild
71+
72+
# CMake
73+
*.cmake
74+
CMakeCache.txt
75+
/CMakeTmp
76+
*CMakeTmp*
77+
*CMakeFiles*
78+
*CMakeCache.txt
79+
80+
# Python packages
81+
/*.egg-info
82+
/build
83+
/dist
84+
*.pyc
85+
86+
# Executables
87+
record
88+
main

.travis.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
language: c
2+
sudo: required
3+
dist: trusty
4+
compiler: gcc
5+
matrix:
6+
include:
7+
- os: linux
8+
python: '2.7'
9+
- os: linux
10+
python: '3.6'
11+
addons:
12+
apt:
13+
packages:
14+
- libusb-1.0.0-dev
15+
- python-dev
16+
- python3-dev
17+
install:
18+
- sudo python -m pip install -U pip scikit-build enum
19+
before_script:
20+
- mkdir cmake-build
21+
script:
22+
- cd cmake-build
23+
- cmake ..
24+
- make
25+
- sudo make install
26+
- cd ..
27+
- sudo env "PATH=$PATH" python setup.py install
28+
- cd ..
29+
- python -c 'import masterkeys'

CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Author: RedFantom
2+
# License: GNU GPLv3
3+
# Copyright (c) 2018 RedFantom
4+
cmake_minimum_required(VERSION 3.9)
5+
set(CMAKE_C_FLAGS "-std=c99")
6+
include(libmk/CMakeLists.txt)
7+
if (SKBUILD) # The masterkeys package can only be built with scikit-build
8+
include(masterkeys/CMakeLists.txt)
9+
else()
10+
include(examples/CMakeLists.txt)
11+
include(utils/CMakeLists.txt)
12+
endif()
13+
include(GNUInstallDirs)

FindLibUSB.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Author: RedFantom
2+
# License: GNU GPLv3
3+
# Copyright (c) 2018 RedFantom
4+
5+
# LibUSB include directory on Linux
6+
set(LIBUSB_INCLUDE_DIR /usr/include/libusb-1.0)
7+
8+
# Path finding for libusb
9+
FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
10+
HINTS $ENV{LIBUSB_ROOT}
11+
PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}
12+
PATH_SUFFIXES include)
13+
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0
14+
HINTS $ENV{LIBUSB_ROOT}
15+
PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}
16+
PATH_SUFFIXES lib)

INTERFACE.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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

Comments
 (0)