Skip to content

Commit 6edf519

Browse files
committed
Extend device support
1 parent b3406ea commit 6edf519

File tree

4 files changed

+233
-68
lines changed

4 files changed

+233
-68
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,9 @@ GNU General Public License for more details.
9696
You should have received a copy of the GNU General Public License
9797
along with this program. If not, see <https://www.gnu.org/licenses/>.
9898
```
99+
100+
## Credits
101+
Part of the implementation of this library is based on the more
102+
extensive protocol description written by [`chmod222`](https://github.com/chmod222),
103+
available under the LGPLv3 license in [`libcmmk`](https://github.com/chmod222/libcmmk),
104+
which has the same goal as this project.

libmk/libmk.c

Lines changed: 176 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,11 @@
3535
static libusb_context* Context;
3636
static LibMK_Handle* DeviceHandle;
3737

38-
3938
typedef enum LibMK_Model LibMK_Model;
4039
typedef enum LibMK_Result LibMK_Result;
4140
typedef enum LibMK_Effect LibMK_Effect;
4241
typedef struct LibMK_Device LibMK_Device;
4342

44-
4543
/** Constants */
4644
const unsigned char HEADER_DEFAULT = 0x41; // 0100 0001
4745
const unsigned char HEADER_EFFECT = 0x50; // 0101 0000
@@ -67,38 +65,108 @@ const unsigned char LAYOUT_ISO = 1;
6765
* keyboard. The matrix is in [row][column] format. A value of 0xFF
6866
* indicates an unknown value.
6967
*/
70-
const unsigned char LIBMK_LAYOUT_ANSI[LIBMK_MAX_ROWS][LIBMK_MAX_COLS] =
71-
{{0x0b, 0x16, 0x1e, 0x19, 0x1b, 0xff, 0x07, 0x33, 0x39, 0x3e, 0xff, 0x56,
72-
0x57, 0x53, 0x55, 0x4f, 0x48, 0x00, 0x65, 0x6d, 0x75, 0x77, 0xff, 0xff},
73-
{0x0e, 0x0f, 0x17, 0x1f, 0x27, 0x26, 0x2e, 0x2f, 0x37, 0x3f, 0x47, 0x46,
74-
0x36, 0xff, 0x51, 0x03, 0x01, 0x02, 0x64, 0x6c, 0x74, 0x76, 0xff, 0xff},
75-
{0x09, 0x08, 0x10, 0x18, 0x20, 0x21, 0x29, 0x28, 0x30, 0x38, 0x40, 0x41,
76-
0x31, 0xff, 0x52, 0x5e, 0x5c, 0x58, 0x60, 0x68, 0x70, 0x6e, 0xff, 0xff},
77-
{0x11, 0x0a, 0x12, 0x1a, 0x22, 0x23, 0x2b, 0x2a, 0x32, 0x3a, 0x42, 0x43,
78-
0xff, 0xff, 0x54, 0xff, 0xff, 0xff, 0x61, 0x69, 0x71, 0xff, 0xff, 0xff},
79-
{0x49, 0xff, 0x0c, 0x14, 0x1c, 0x24, 0x25, 0x2d, 0x2c, 0x34, 0x3c, 0x45,
80-
0xff, 0xff, 0x4a, 0xff, 0x50, 0xff, 0x62, 0x6a, 0x72, 0x6f, 0xff, 0xff},
81-
{0x06, 0x5a, 0x4b, 0xff, 0xff, 0xff, 0x5b, 0xff, 0xff, 0xff, 0x4d, 0x4e,
82-
0x3d, 0xff, 0x04, 0x5f, 0x5d, 0x05, 0x6b, 0xff, 0x73, 0xff, 0xff, 0xff},
83-
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
85-
};
86-
87-
const unsigned char LIBMK_LAYOUT_ISO[LIBMK_MAX_ROWS][LIBMK_MAX_COLS] =
88-
{{0x0B, 0x16, 0x1E, 0x19, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
90-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
91-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
92-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
94-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
96-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
97-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
98-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
100-
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
101-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
68+
const unsigned char LIBMK_LAYOUT[2][3][LIBMK_MAX_ROWS][LIBMK_MAX_COLS] = {
69+
{ // ANSI Layouts
70+
// Layout size L
71+
{{0x0b, 0x16, 0x1e, 0x19, 0x1b, 0xff, 0x07, 0x33, 0x39, 0x3e, 0xff, 0x56,
72+
0x57, 0x53, 0x55, 0x4f, 0x48, 0x00, 0x65, 0x6d, 0x75, 0x77, 0xff, 0xff},
73+
{0x0e, 0x0f, 0x17, 0x1f, 0x27, 0x26, 0x2e, 0x2f, 0x37, 0x3f, 0x47, 0x46,
74+
0x36, 0xff, 0x51, 0x03, 0x01, 0x02, 0x64, 0x6c, 0x74, 0x76, 0xff, 0xff},
75+
{0x09, 0x08, 0x10, 0x18, 0x20, 0x21, 0x29, 0x28, 0x30, 0x38, 0x40, 0x41,
76+
0x31, 0xff, 0x52, 0x5e, 0x5c, 0x58, 0x60, 0x68, 0x70, 0x6e, 0xff, 0xff},
77+
{0x11, 0x0a, 0x12, 0x1a, 0x22, 0x23, 0x2b, 0x2a, 0x32, 0x3a, 0x42, 0x43,
78+
0xff, 0xff, 0x54, 0xff, 0xff, 0xff, 0x61, 0x69, 0x71, 0xff, 0xff, 0xff},
79+
{0x49, 0xff, 0x0c, 0x14, 0x1c, 0x24, 0x25, 0x2d, 0x2c, 0x34, 0x3c, 0x45,
80+
0xff, 0xff, 0x4a, 0xff, 0x50, 0xff, 0x62, 0x6a, 0x72, 0x6f, 0xff, 0xff},
81+
{0x06, 0x5a, 0x4b, 0xff, 0xff, 0xff, 0x5b, 0xff, 0xff, 0xff, 0x4d, 0x4e,
82+
0x3d, 0xff, 0x04, 0x5f, 0x5d, 0x05, 0x6b, 0xff, 0x73, 0xff, 0xff, 0xff},
83+
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
85+
// Layout size M
86+
// TODO: Find the key layout matrix of an ANSI M keyboard
87+
{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
89+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
90+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
91+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
92+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
93+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
95+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
96+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
97+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
98+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
99+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
100+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
101+
// Layout size S
102+
{{0x60, 0x61, 0x62, 0x63, 0x68, 0xFF, 0x69, 0x6A, 0x70, 0x71, 0xFF, 0x72,
103+
0x43, 0x44, 0x45, 0x66, 0x67, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
104+
{0x00, 0x01, 0x08, 0x09, 0x10, 0x11, 0x18, 0x19, 0x20, 0x21, 0x28, 0x29,
105+
0x30, 0xFF, 0x31, 0x38, 0x39, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
106+
{0x02, 0x03, 0x0A, 0x0B, 0x12, 0x13, 0x1A, 0x1B, 0x22, 0x23, 0x2A, 0x2B,
107+
0x32, 0xFF, 0x33, 0x3A, 0x3B, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
108+
{0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, 0x24, 0x25, 0x2C, 0x2D,
109+
0xFF, 0xFF, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
110+
{0x06, 0xFF, 0x07, 0x0E, 0x0F, 0x16, 0x17, 0x1E, 0x1F, 0x26, 0x27, 0x2E,
111+
0x01, 0xFF, 0x2F, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
112+
{0x5B, 0x5A, 0x5C, 0xFF, 0xFF, 0xFF, 0x5D, 0xFF, 0xFF, 0xFF, 0x5E, 0x3C,
113+
0x5F, 0xFF, 0x36, 0x3F, 0x3E, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
114+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
116+
}, { // ISO Layouts
117+
// Layout size L
118+
// This key layout matrix was copied from libcmmk, GNU GPLv3
119+
{{0x0B, 0x16, 0x1E, 0x19, 0x1B, 0xFF, 0x07, 0x33, 0x39, 0x3E, 0xFF, 0x56,
120+
0x57, 0x53, 0x55, 0x4F, 0x48, 0x00, 0x65, 0x6D, 0x75, 0x77, 0xFF, 0xFF},
121+
{0x0E, 0x0F, 0x17, 0x1F, 0x27, 0x26, 0x2E, 0x2F, 0x37, 0x3F, 0x47, 0x46,
122+
0x36, 0xFF, 0x51, 0x03, 0x01, 0x02, 0x64, 0x6C, 0x74, 0x76, 0xFF, 0xFF},
123+
{0x09, 0x08, 0x10, 0x18, 0x20, 0x21, 0x29, 0x28, 0x30, 0x38, 0x40, 0x41,
124+
0x31, 0xFF, 0x54, 0x5E, 0x5C, 0x58, 0x60, 0x68, 0x70, 0x6E, 0xFF, 0xFF},
125+
{0x11, 0x0A, 0x12, 0x1A, 0x22, 0x23, 0x2B, 0x2A, 0x32, 0x3A, 0x42, 0x43,
126+
0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x69, 0x71, 0xFF, 0xFF, 0xFF},
127+
{0x49, 0x13, 0x0C, 0x14, 0x1C, 0x24, 0x25, 0x2D, 0x2C, 0x34, 0x3C, 0x45,
128+
0xFF, 0xFF, 0x4A, 0xFF, 0x50, 0xFF, 0x62, 0x6A, 0x72, 0x6F, 0xFF, 0xFF},
129+
{0x06, 0x5A, 0x4B, 0xFF, 0xFF, 0xFF, 0x5B, 0xFF, 0xFF, 0xFF, 0x4D, 0x4E,
130+
0x3D, 0xFF, 0x04, 0x5F, 0x5D, 0x05, 0x6B, 0xFF, 0x73, 0xFF, 0xFF, 0xFF},
131+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
132+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
133+
// Layout size M
134+
// TODO: Find the key layout matrix of an ISO M keyboard
135+
{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
137+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
138+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
139+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
140+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
141+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
142+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
143+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
144+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
145+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
146+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
147+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
148+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
149+
// Layout size S
150+
// TODO: Find the key layout matrix of an ISO S keyboard
151+
{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
152+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
153+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
154+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
155+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
156+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
157+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
158+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
159+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
160+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
161+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
162+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
163+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}
165+
},
166+
// TODO: If required, Japanese layouts may be added at index 2 of this array
167+
// TODO: so that it remains compatible with the LibMK_Layout enum and the
168+
// TODO: firmware defined layout
169+
};
102170

103171

104172
bool libmk_init(void) {
@@ -289,16 +357,34 @@ int libmk_create_handle(LibMK_Handle** handle, LibMK_Device* device) {
289357
* A LibMK_Handle must be created from a LibMK_Device struct, as
290358
* the LibMK_Handle requires special attributes.
291359
*/
292-
unsigned char layout = libmk_get_layout(device->bDevice);
293360
*handle = (LibMK_Handle*) malloc(sizeof(LibMK_Handle));
361+
if (*handle == NULL)
362+
return LIBMK_ERR_DEV_OPEN_FAILED;
294363
int r = libusb_open(device->device, &(*handle)->handle);
295364
if (r != 0)
296365
return LIBMK_ERR_DEV_OPEN_FAILED;
297366
(*handle)->open = true;
298367
(*handle)->model = device->model;
299-
(*handle)->layout = layout;
300368
(*handle)->bDevice = device->bDevice;
301369
(*handle)->bVendor = device->bVendor;
370+
LibMK_Model model = device->model;
371+
if (model == DEV_RGB_L || model == DEV_WHITE_L)
372+
(*handle)->size = LIBMK_L;
373+
else if (model == DEV_RGB_M || model == DEV_WHITE_M)
374+
(*handle)->size = LIBMK_M;
375+
else if (model == DEV_RGB_S || model == DEV_WHITE_S)
376+
(*handle)->size = LIBMK_S;
377+
else {
378+
libusb_close((*handle)->handle);
379+
return LIBMK_ERR_UNKNOWN_LAYOUT;
380+
}
381+
LibMK_Firmware* fw;
382+
r = libmk_get_firmware_version(*handle, &fw);
383+
if (r != LIBMK_SUCCESS) {
384+
libusb_close((*handle)->handle);
385+
return r;
386+
}
387+
(*handle)->layout = fw->layout;
302388
return LIBMK_SUCCESS;
303389
}
304390

@@ -590,7 +676,7 @@ int libmk_send_packet(LibMK_Handle* handle, unsigned char* packet) {
590676
handle->handle, LIBMK_EP_IN | LIBUSB_ENDPOINT_IN,
591677
packet, LIBMK_PACKET_SIZE, &t, LIBMK_PACKET_TIMEOUT);
592678
if (r != LIBUSB_SUCCESS) {
593-
result = LIBMK_SUCCESS;
679+
result = LIBMK_ERR_TRANSFER;
594680
} else if (t != LIBMK_PACKET_SIZE) {
595681
result = LIBMK_ERR_TRANSFER;
596682
} else if (packet[0] == HEADER_ERROR) {
@@ -603,6 +689,30 @@ int libmk_send_packet(LibMK_Handle* handle, unsigned char* packet) {
603689
}
604690

605691

692+
int libmk_exch_packet(LibMK_Handle* handle, unsigned char* packet) {
693+
/** Send a single packet to the keyboard and receive the response
694+
*
695+
* The response is put in the memory allocated for the packet to be
696+
* sent. If the function encounters an error, the memory is freed
697+
* and no response is available (except for a return code).
698+
*/
699+
int t;
700+
int r = libusb_interrupt_transfer(
701+
handle->handle, LIBMK_EP_OUT | LIBUSB_ENDPOINT_OUT,
702+
packet, LIBMK_PACKET_SIZE, &t, LIBMK_PACKET_TIMEOUT);
703+
if (r != LIBUSB_SUCCESS || t != LIBMK_PACKET_SIZE) {
704+
free(packet);
705+
return LIBMK_ERR_TRANSFER;
706+
}
707+
r = libusb_interrupt_transfer(
708+
handle->handle, LIBMK_EP_IN | LIBUSB_ENDPOINT_IN,
709+
packet, LIBMK_PACKET_SIZE, &t, LIBMK_PACKET_TIMEOUT);
710+
if (r != LIBUSB_SUCCESS || t != LIBMK_PACKET_SIZE)
711+
return LIBMK_ERR_TRANSFER;
712+
return LIBMK_SUCCESS;
713+
}
714+
715+
606716
unsigned char* libmk_build_packet(unsigned char predef, ...) {
607717
/** Return a pointer to a packet filled with zeros */
608718
unsigned char* packet = (unsigned char*)
@@ -688,26 +798,7 @@ int libmk_set_all_led_color(
688798
}
689799

690800

691-
unsigned char libmk_get_layout(int bProduct) {
692-
short i = 0;
693-
while (true) {
694-
if (ANSI[i] == bProduct)
695-
return LAYOUT_ANSI;
696-
else if (ANSI[i] == 0)
697-
break;
698-
i++;
699-
}
700-
i = 0;
701-
while (ISO[i] != 0x0000) {
702-
if (ISO[i] == bProduct)
703-
return LAYOUT_ISO;
704-
i++;
705-
}
706-
return LIBMK_ERR_UNKNOWN_LAYOUT;
707-
}
708-
709-
710-
void libmk_print_packet(unsigned char* packet) {
801+
inline void libmk_print_packet(unsigned char* packet) {
711802
/** Pretty print a keyboard communication packet */
712803
#ifdef LIBMK_DEBUG
713804
printf("Packet:\n");
@@ -731,12 +822,9 @@ int libmk_get_offset(
731822
* keyboard. This function returns the hexadecimal offset for the
732823
* appropriate layout into the offset pointer.
733824
*/
734-
if (handle->layout == LAYOUT_ANSI)
735-
*offset = LIBMK_LAYOUT_ANSI[row][col];
736-
else if (handle->layout == LAYOUT_ISO)
737-
*offset = LIBMK_LAYOUT_ISO[row][col];
738-
else
825+
if (handle->layout != LAYOUT_ISO && handle->layout != LAYOUT_ANSI)
739826
return LIBMK_ERR_UNKNOWN_LAYOUT;
827+
*offset = LIBMK_LAYOUT[handle->layout - 1][handle->size][row][col];
740828
return LIBMK_SUCCESS;
741829
}
742830

@@ -795,3 +883,29 @@ int libmk_set_effect_details(
795883
return r;
796884
return libmk_send_packet(handle, packet);
797885
}
886+
887+
888+
int libmk_get_firmware_version(LibMK_Handle* handle, LibMK_Firmware** fw) {
889+
/** Return the firmware details
890+
*
891+
* TODO: Determine whether the version number encodes the layout
892+
* TODO: See libcmmk issue #10 for more information
893+
*/
894+
if (handle == NULL)
895+
handle = DeviceHandle;
896+
if (handle == NULL)
897+
return LIBMK_ERR_DEV_NOT_SET;
898+
unsigned char* p = libmk_build_packet(2, 0x01, 0x02);
899+
int r = libmk_exch_packet(handle, p);
900+
if (r != LIBMK_SUCCESS)
901+
return r;
902+
(*fw) = (LibMK_Firmware*) malloc(sizeof(LibMK_Firmware));
903+
for (unsigned char i=0; i<5; i++)
904+
(*fw)->string[i] = p[0x04 + i];
905+
(*fw)->string[5] = (char) NULL;
906+
(*fw)->major = p[0x04] & 0x0F;
907+
(*fw)->minor = p[0x06] & 0x0F;
908+
(*fw)->patch = p[0x08] & 0x0F;
909+
(*fw)->layout = p[0x04] & 0x0F;
910+
return LIBMK_SUCCESS;
911+
}

libmk/libmk.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,46 @@ typedef enum LibMK_Effect {
7878
} LibMK_Effect;
7979

8080

81+
typedef enum LibMK_ControlMode {
82+
/** Describes keyboard control modes */
83+
LIBMK_FIRMWARE_CTRL = 0x00,
84+
LIBMK_EFFECT_CTRL = 0x01,
85+
LIBMK_CUSTOM_CTRL = 0x02,
86+
LIBMK_PROFILE_CTRL = 0x03,
87+
} LibMK_ControlMode;
88+
89+
90+
typedef enum LibMK_Layout {
91+
LIBMK_LAYOUT_UNKNOWN = 0,
92+
LIBMK_LAYOUT_ANSI = 1,
93+
LIBMK_LAYOUT_ISO = 2,
94+
LIBMK_LAYOUT_JP = 3
95+
} LibMK_Layout;
96+
97+
98+
typedef struct LibMK_Firmware {
99+
/** Describes keyboard firmware details */
100+
unsigned char major;
101+
unsigned char minor;
102+
unsigned char patch;
103+
unsigned char layout;
104+
char string[6];
105+
} LibMK_Firmware;
106+
107+
108+
typedef enum LibMK_Size {
109+
LIBMK_L = 0,
110+
LIBMK_M = 1,
111+
LIBMK_S = 2
112+
} LibMK_Size;
113+
114+
81115
typedef enum LibMK_Model {
82116
/** Describes models available for use with this library
83117
*
84118
* The device indices are the same as the ones used in the official
85119
* Cooler Master (Windows-only) SDK. Not all these devices are
86-
* supported. For white devices, the
120+
* supported.
87121
*/
88122
DEV_RGB_L = 0,
89123
DEV_RGB_M = 5,
@@ -122,6 +156,7 @@ typedef struct LibMK_Handle {
122156
int bVendor;
123157
int bDevice;
124158
int layout;
159+
int size;
125160
libusb_device_handle* handle;
126161
bool open;
127162
} LibMK_Handle;
@@ -136,6 +171,7 @@ typedef struct LibMK_Effect_Details {
136171
unsigned char background[3];
137172
} LibMK_Effect_Details;
138173

174+
139175
/** Library management and initialization */
140176
bool libmk_init();
141177
int libmk_exit();
@@ -150,7 +186,6 @@ LibMK_Device* libmk_create_device(
150186
void libmk_free_device(LibMK_Device* device);
151187
LibMK_Device* libmk_append_device(LibMK_Device* first, LibMK_Device* device);
152188
LibMK_Model libmk_ident_model(char* product);
153-
unsigned char libmk_get_layout(int bProduct);
154189

155190

156191
/** Handle management */
@@ -166,6 +201,7 @@ int libmk_claim_interface(LibMK_Handle* handle);
166201
int libmk_send_control_packet(LibMK_Handle* handle);
167202
int libmk_reset(LibMK_Handle* handle);
168203
int libmk_get_device_ident(LibMK_Handle* handle);
204+
int libmk_get_firmware_version(LibMK_Handle* handle, LibMK_Firmware** fw);
169205

170206

171207
/** Communication */

0 commit comments

Comments
 (0)