ckb-next  beta-v0.2.8 at branch testing
ckb-next driver for corsair devices
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
keymap.c
Go to the documentation of this file.
1 #include "device.h"
2 #include "includes.h"
3 #include "keymap.h"
4 
6  // Keyboard keys
7  { "esc", 0x00, KEY_ESC },
8  { "f1", 0x0c, KEY_F1 },
9  { "f2", 0x18, KEY_F2 },
10  { "f3", 0x24, KEY_F3 },
11  { "f4", 0x30, KEY_F4 },
12  { "f5", 0x3c, KEY_F5 },
13  { "f6", 0x48, KEY_F6 },
14  { "f7", 0x54, KEY_F7 },
15  { "f8", 0x60, KEY_F8 },
16  { "f9", 0x6c, KEY_F9 },
17  { "f10", 0x78, KEY_F10 },
18  { "f11", 0x84, KEY_F11 },
19  { "grave", 0x01, KEY_GRAVE },
20  { "1", 0x0d, KEY_1 },
21  { "2", 0x19, KEY_2 },
22  { "3", 0x25, KEY_3 },
23  { "4", 0x31, KEY_4 },
24  { "5", 0x3d, KEY_5 },
25  { "6", 0x49, KEY_6 },
26  { "7", 0x55, KEY_7 },
27  { "8", 0x61, KEY_8 },
28  { "9", 0x6d, KEY_9 },
29  { "0", 0x79, KEY_0 },
30  { "minus", 0x85, KEY_MINUS },
31  { "tab", 0x02, KEY_TAB },
32  { "q", 0x0e, KEY_Q },
33  { "w", 0x1a, KEY_W },
34  { "e", 0x26, KEY_E },
35  { "r", 0x32, KEY_R },
36  { "t", 0x3e, KEY_T },
37  { "y", 0x4a, KEY_Y },
38  { "u", 0x56, KEY_U },
39  { "i", 0x62, KEY_I },
40  { "o", 0x6e, KEY_O },
41  { "p", 0x7a, KEY_P },
42  { "lbrace", 0x86, KEY_LEFTBRACE },
43  { "caps", 0x03, KEY_CAPSLOCK },
44  { "a", 0x0f, KEY_A },
45  { "s", 0x1b, KEY_S },
46  { "d", 0x27, KEY_D },
47  { "f", 0x33, KEY_F },
48  { "g", 0x3f, KEY_G },
49  { "h", 0x4b, KEY_H },
50  { "j", 0x57, KEY_J },
51  { "k", 0x63, KEY_K },
52  { "l", 0x6f, KEY_L },
53  { "colon", 0x7b, KEY_SEMICOLON },
54  { "quote", 0x87, KEY_APOSTROPHE },
55  { "lshift", 0x04, KEY_LEFTSHIFT },
56  { "bslash_iso", 0x10, KEY_102ND },
57  { "z", 0x1c, KEY_Z },
58  { "x", 0x28, KEY_X },
59  { "c", 0x34, KEY_C },
60  { "v", 0x40, KEY_V },
61  { "b", 0x4c, KEY_B },
62  { "n", 0x58, KEY_N },
63  { "m", 0x64, KEY_M },
64  { "comma", 0x70, KEY_COMMA },
65  { "dot", 0x7c, KEY_DOT },
66  { "slash", 0x88, KEY_SLASH },
67  { "lctrl", 0x05, KEY_LEFTCTRL },
68  { "lwin", 0x11, KEY_LEFTMETA },
69  { "lalt", 0x1d, KEY_LEFTALT },
70  { 0, -1, KEY_NONE },
71  { "space", 0x35, KEY_SPACE },
72  { 0, -1, KEY_NONE },
73  { 0, -1, KEY_NONE },
74  { "ralt", 0x59, KEY_RIGHTALT },
75  { "rwin", 0x65, KEY_RIGHTMETA },
76  { "rmenu", 0x71, KEY_COMPOSE },
77  { 0, -1, KEY_NONE },
78  { "light", 0x89, KEY_CORSAIR },
79  { "f12", 0x06, KEY_F12 },
80  { "prtscn", 0x12, KEY_SYSRQ },
81  { "scroll", 0x1e, KEY_SCROLLLOCK },
82  { "pause", 0x2a, KEY_PAUSE },
83  { "ins", 0x36, KEY_INSERT },
84  { "home", 0x42, KEY_HOME },
85  { "pgup", 0x4e, KEY_PAGEUP },
86  { "rbrace", 0x5a, KEY_RIGHTBRACE },
87  { "bslash", 0x66, KEY_BACKSLASH },
88  { "hash", 0x72, KEY_BACKSLASH_ISO },
89  { "enter", 0x7e, KEY_ENTER },
90  { 0, -1, KEY_NONE },
91  { "equal", 0x07, KEY_EQUAL },
92  { 0, -1, KEY_NONE },
93  { "bspace", 0x1f, KEY_BACKSPACE },
94  { "del", 0x2b, KEY_DELETE },
95  { "end", 0x37, KEY_END },
96  { "pgdn", 0x43, KEY_PAGEDOWN },
97  { "rshift", 0x4f, KEY_RIGHTSHIFT },
98  { "rctrl", 0x5b, KEY_RIGHTCTRL },
99  { "up", 0x67, KEY_UP },
100  { "left", 0x73, KEY_LEFT },
101  { "down", 0x7f, KEY_DOWN },
102  { "right", 0x8b, KEY_RIGHT },
103  { "lock", 0x08, KEY_CORSAIR },
104  { "mute", 0x14, KEY_MUTE },
105  { "stop", 0x20, KEY_STOPCD },
106  { "prev", 0x2c, KEY_PREVIOUSSONG },
107  { "play", 0x38, KEY_PLAYPAUSE },
108  { "next", 0x44, KEY_NEXTSONG },
109  { "numlock", 0x50, KEY_NUMLOCK },
110  { "numslash", 0x5c, KEY_KPSLASH },
111  { "numstar", 0x68, KEY_KPASTERISK },
112  { "numminus", 0x74, KEY_KPMINUS },
113  { "numplus", 0x80, KEY_KPPLUS },
114  { "numenter", 0x8c, KEY_KPENTER },
115  { "num7", 0x09, KEY_KP7 },
116  { "num8", 0x15, KEY_KP8 },
117  { "num9", 0x21, KEY_KP9 },
118  { 0, -1, KEY_NONE },
119  { "num4", 0x39, KEY_KP4 },
120  { "num5", 0x45, KEY_KP5 },
121  { "num6", 0x51, KEY_KP6 },
122  { "num1", 0x5d, KEY_KP1 },
123  { "num2", 0x69, KEY_KP2 },
124  { "num3", 0x75, KEY_KP3 },
125  { "num0", 0x81, KEY_KP0 },
126  { "numdot", 0x8d, KEY_KPDOT },
127  { "g1", 0x0a, KEY_CORSAIR },
128  { "g2", 0x16, KEY_CORSAIR },
129  { "g3", 0x22, KEY_CORSAIR },
130  { "g4", 0x2e, KEY_CORSAIR },
131  { "g5", 0x3a, KEY_CORSAIR },
132  { "g6", 0x46, KEY_CORSAIR },
133  { "g7", 0x52, KEY_CORSAIR },
134  { "g8", 0x5e, KEY_CORSAIR },
135  { "g9", 0x6a, KEY_CORSAIR },
136  { "g10", 0x76, KEY_CORSAIR },
137  { "volup", 0x20, KEY_VOLUMEUP },
138  { "voldn", 0x2c, KEY_VOLUMEDOWN },
139  { "mr", 0x0b, KEY_CORSAIR },
140  { "m1", 0x17, KEY_CORSAIR },
141  { "m2", 0x23, KEY_CORSAIR },
142  { "m3", 0x2f, KEY_CORSAIR },
143  { "g11", 0x3b, KEY_CORSAIR },
144  { "g12", 0x47, KEY_CORSAIR },
145  { "g13", 0x53, KEY_CORSAIR },
146  { "g14", 0x5f, KEY_CORSAIR },
147  { "g15", 0x6b, KEY_CORSAIR },
148  { "g16", 0x77, KEY_CORSAIR },
149  { "g17", 0x83, KEY_CORSAIR },
150  { "g18", 0x8f, KEY_CORSAIR },
151  { 0, -1, KEY_NONE },
152  { 0, -1, KEY_NONE },
153  { "fn", 0x65, KEY_FN }, // STRAFE Fn - rwin on other keyboards
154  { 0, -1, KEY_NONE },
155  { 0, -1, KEY_NONE },
156  { 0, -1, KEY_NONE },
157  { 0, -1, KEY_NONE },
158  { 0, -1, KEY_NONE },
159 
160  // Strafe specific side leds, that are set via a special command
161  { "lsidel", -2, KEY_CORSAIR },
162  { "rsidel", -2, KEY_CORSAIR },
163  // Strafe logo backlight
164  { "logo", 0x7d, KEY_CORSAIR },
165 
166  // Keys not present on any device
167  { "lightup", -1, KEY_BRIGHTNESSUP },
168  { "lightdn", -1, KEY_BRIGHTNESSDOWN },
169  { "eject", -1, KEY_EJECTCD },
170  { "power", -1, KEY_POWER },
171  { "f13", -1, KEY_F13 },
172  { "f14", -1, KEY_F14 },
173  { "f15", -1, KEY_F15 },
174  { "f16", -1, KEY_F16 },
175  { "f17", -1, KEY_F17 },
176  { "f18", -1, KEY_F18 },
177  { "f19", -1, KEY_F19 },
178  { "f20", -1, KEY_F20 },
179 
180  // Mouse buttons
181  { "mouse1", -1, SCAN_MOUSE | BTN_LEFT },
182  { "mouse2", -1, SCAN_MOUSE | BTN_RIGHT },
183  { "mouse3", -1, SCAN_MOUSE | BTN_MIDDLE },
184  { "mouse4", -1, SCAN_MOUSE | BTN_SIDE },
185  { "mouse5", -1, SCAN_MOUSE | BTN_EXTRA },
186  { "dpiup", -1, KEY_CORSAIR },
187  { "dpidn", -1, KEY_CORSAIR },
188  { "sniper", -1, KEY_CORSAIR },
189  { "thumb1", -1, KEY_CORSAIR },
190  { "thumb2", -1, KEY_CORSAIR },
191  { "thumb3", -1, KEY_CORSAIR },
192  { "thumb4", -1, KEY_CORSAIR },
193  { "thumb5", -1, KEY_CORSAIR },
194  { "thumb6", -1, KEY_CORSAIR },
195  { "thumb7", -1, KEY_CORSAIR },
196  { "thumb8", -1, KEY_CORSAIR },
197  { "thumb9", -1, KEY_CORSAIR },
198  { "thumb10", -1, KEY_CORSAIR },
199  { "thumb11", -1, KEY_CORSAIR },
200  { "thumb12", -1, KEY_CORSAIR },
201 
202  // Extended mouse buttons (wheel is an axis in HW, 6-8 are recognized by the OS but not present in HW)
203  { "wheelup", -1, SCAN_MOUSE | BTN_WHEELUP },
204  { "wheeldn", -1, SCAN_MOUSE | BTN_WHEELDOWN },
205  { "mouse6", -1, SCAN_MOUSE | BTN_FORWARD },
206  { "mouse7", -1, SCAN_MOUSE | BTN_BACK },
207  { "mouse8", -1, SCAN_MOUSE | BTN_TASK },
208 
209  // RGB mouse zones
210  { "front", LED_MOUSE, KEY_NONE },
211  { "back", LED_MOUSE + 1, KEY_NONE },
212  { "dpi", LED_MOUSE + 2, KEY_NONE }, // SW DPI light
213  { "wheel", LED_MOUSE + 3, KEY_NONE },
214  { "thumb", LED_MOUSE + 4, KEY_NONE },
215  { "dpi0", LED_MOUSE + 5, KEY_NONE }, // HW DPI light levels (0 = sniper, 1..5 = modes)
216  { "dpi1", LED_MOUSE + 6, KEY_NONE },
217  { "dpi2", LED_MOUSE + 7, KEY_NONE },
218  { "dpi3", LED_MOUSE + 8, KEY_NONE },
219  { "dpi4", LED_MOUSE + 9, KEY_NONE },
220  { "dpi5", LED_MOUSE + 10, KEY_NONE },
221 };
222 
223 void hid_kb_translate(unsigned char* kbinput, int endpoint, int length, const unsigned char* urbinput){
224  if(length < 1)
225  return;
226  // LUT for HID -> Corsair scancodes (-1 for no scan code, -2 for currently unsupported)
227  // Modified from Linux drivers/hid/usbhid/usbkbd.c, key codes replaced with array indices and K95 keys added
228  static const short hid_codes[256] = {
229  -1, -1, -1, -1, 37, 54, 52, 39, 27, 40, 41, 42, 32, 43, 44, 45,
230  56, 55, 33, 34, 25, 28, 38, 29, 31, 53, 26, 51, 30, 50, 13, 14,
231  15, 16, 17, 18, 19, 20, 21, 22, 82, 0, 86, 24, 64, 23, 84, 35,
232  79, 80, 81, 46, 47, 12, 57, 58, 59, 36, 1, 2, 3, 4, 5, 6,
233  7, 8, 9, 10, 11, 72, 73, 74, 75, 76, 77, 78, 87, 88, 89, 95,
234  93, 94, 92, 102, 103, 104, 105, 106, 107, 115, 116, 117, 112, 113, 114, 108,
235  109, 110, 118, 119, 49, 69, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
236  -2, -2, -2, -2, -2, -2, -2, -2, 98, -2, -2, -2, -2, -2, -2, 97,
237  130, 131, -1, -1, -1, -2, -1, -2, -2, -2, -2, -2, -2, -1, -1, -1,
238  -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
239  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
240  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
241  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, -1, -1, -1, // <- -3 = non-RGB program key
242  120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 136, 137, 138, 139, 140, 141,
243  60, 48, 62, 61, 91, 90, 67, 68, 142, 143, 99, 101, -2, 130, 131, 97,
244  -2, 133, 134, 135, -2, 96, -2, 132, -2, -2, 71, 71, 71, 71, -1, -1,
245  };
246  switch(endpoint){
247  case 1:
248  case -1:
249  // EP 1: 6KRO input (RGB and non-RGB)
250  // Clear previous input
251  for(int i = 0; i < 256; i++){
252  if(hid_codes[i] >= 0)
253  CLEAR_KEYBIT(kbinput, hid_codes[i]);
254  }
255  // Set new input
256  for(int i = 0; i < 8; i++){
257  if((urbinput[0] >> i) & 1)
258  SET_KEYBIT(kbinput, hid_codes[i + 224]);
259  }
260  for(int i = 2; i < length; i++){
261  if(urbinput[i] > 3){
262  int scan = hid_codes[urbinput[i]];
263  if(scan >= 0)
264  SET_KEYBIT(kbinput, scan);
265  else
266  ckb_warn("Got unknown key press %d on EP 1\n", urbinput[i]);
267  }
268  }
269  break;
270  case -2:
271  // EP 2 RGB: NKRO input
272  if(urbinput[0] == 1){
273  // Type 1: standard key
274  if(length != 21)
275  return;
276  for(int bit = 0; bit < 8; bit++){
277  if((urbinput[1] >> bit) & 1)
278  SET_KEYBIT(kbinput, hid_codes[bit + 224]);
279  else
280  CLEAR_KEYBIT(kbinput, hid_codes[bit + 224]);
281  }
282  for(int byte = 0; byte < 19; byte++){
283  char input = urbinput[byte + 2];
284  for(int bit = 0; bit < 8; bit++){
285  int keybit = byte * 8 + bit;
286  int scan = hid_codes[keybit];
287  if((input >> bit) & 1){
288  if(scan >= 0)
289  SET_KEYBIT(kbinput, hid_codes[keybit]);
290  else
291  ckb_warn("Got unknown key press %d on EP 2\n", keybit);
292  } else if(scan >= 0)
293  CLEAR_KEYBIT(kbinput, hid_codes[keybit]);
294  }
295  }
296  break;
297  } else if(urbinput[0] == 2)
298  ; // Type 2: media key (fall through)
299  else
300  break; // No other known types
301  case 2:
302  // EP 2 Non-RGB: media keys
303  CLEAR_KEYBIT(kbinput, 97); // mute
304  CLEAR_KEYBIT(kbinput, 98); // stop
305  CLEAR_KEYBIT(kbinput, 99); // prev
306  CLEAR_KEYBIT(kbinput, 100); // play
307  CLEAR_KEYBIT(kbinput, 101); // next
308  CLEAR_KEYBIT(kbinput, 130); // volup
309  CLEAR_KEYBIT(kbinput, 131); // voldn
310  for(int i = 0; i < length; i++){
311  switch(urbinput[i]){
312  case 181:
313  SET_KEYBIT(kbinput, 101); // next
314  break;
315  case 182:
316  SET_KEYBIT(kbinput, 99); // prev
317  break;
318  case 183:
319  SET_KEYBIT(kbinput, 98); // stop
320  break;
321  case 205:
322  SET_KEYBIT(kbinput, 100); // play
323  break;
324  case 226:
325  SET_KEYBIT(kbinput, 97); // mute
326  break;
327  case 233:
328  SET_KEYBIT(kbinput, 130); // volup
329  break;
330  case 234:
331  SET_KEYBIT(kbinput, 131); // voldn
332  break;
333  }
334  }
335  break;
336  case 3:
337  // EP 3 non-RGB: NKRO input
338  if(length != 15)
339  return;
340  for(int bit = 0; bit < 8; bit++){
341  if((urbinput[0] >> bit) & 1)
342  SET_KEYBIT(kbinput, hid_codes[bit + 224]);
343  else
344  CLEAR_KEYBIT(kbinput, hid_codes[bit + 224]);
345  }
346  for(int byte = 0; byte < 14; byte++){
347  char input = urbinput[byte + 1];
348  for(int bit = 0; bit < 8; bit++){
349  int keybit = byte * 8 + bit;
350  int scan = hid_codes[keybit];
351  if((input >> bit) & 1){
352  if(scan >= 0)
353  SET_KEYBIT(kbinput, hid_codes[keybit]);
354  else
355  ckb_warn("Got unknown key press %d on EP 3\n", keybit);
356  } else if(scan >= 0)
357  CLEAR_KEYBIT(kbinput, hid_codes[keybit]);
358  }
359  }
360  break;
361  }
362 }
363 
364 #define BUTTON_HID_COUNT 5
365 
366 void hid_mouse_translate(unsigned char* kbinput, short* xaxis, short* yaxis, int endpoint, int length, const unsigned char* urbinput){
367  if((endpoint != 2 && endpoint != -2) || length < 10)
368  return;
369  // EP 2: mouse input
370  if(urbinput[0] != 1)
371  return;
372  // Byte 1 = mouse buttons (bitfield)
373  for(int bit = 0; bit < BUTTON_HID_COUNT; bit++){
374  if(urbinput[1] & (1 << bit))
375  SET_KEYBIT(kbinput, MOUSE_BUTTON_FIRST + bit);
376  else
377  CLEAR_KEYBIT(kbinput, MOUSE_BUTTON_FIRST + bit);
378  }
379  // Bytes 5 - 8: movement
380  *xaxis += *(short*)(urbinput + 5);
381  *yaxis += *(short*)(urbinput + 7);
382  // Byte 9: wheel
383  char wheel = urbinput[9];
384  if(wheel > 0)
385  SET_KEYBIT(kbinput, MOUSE_EXTRA_FIRST); // wheelup
386  else
388  if(wheel < 0)
389  SET_KEYBIT(kbinput, MOUSE_EXTRA_FIRST + 1); // wheeldn
390  else
391  CLEAR_KEYBIT(kbinput, MOUSE_EXTRA_FIRST + 1);
392 }
393 
394 void corsair_kbcopy(unsigned char* kbinput, int endpoint, const unsigned char* urbinput){
395  if(endpoint == 2 || endpoint == -2){
396  if(urbinput[0] != 3)
397  return;
398  urbinput++;
399  }
400  memcpy(kbinput, urbinput, N_KEYBYTES_HW);
401 }
402 
403 void corsair_mousecopy(unsigned char* kbinput, int endpoint, const unsigned char* urbinput){
404  if(endpoint == 2 || endpoint == -2){
405  if(urbinput[0] != 3)
406  return;
407  urbinput++;
408  }
409  for(int bit = BUTTON_HID_COUNT; bit < N_BUTTONS_HW; bit++){
410  int byte = bit / 8;
411  uchar test = 1 << (bit % 8);
412  if(urbinput[byte] & test)
413  SET_KEYBIT(kbinput, MOUSE_BUTTON_FIRST + bit);
414  else
415  CLEAR_KEYBIT(kbinput, MOUSE_BUTTON_FIRST + bit);
416  }
417 }
#define N_KEYS_EXTENDED
Definition: keymap.h:45
#define CLEAR_KEYBIT(array, index)
Definition: structures.h:16
#define KEY_NONE
Definition: keymap.h:7
#define BTN_WHEELUP
Definition: keymap.h:12
#define MOUSE_BUTTON_FIRST
Definition: keymap.h:33
#define BUTTON_HID_COUNT
Definition: keymap.c:364
#define SET_KEYBIT(array, index)
Definition: structures.h:15
#define SCAN_MOUSE
Definition: keymap.h:58
unsigned char uchar
Definition: includes.h:24
#define KEY_BACKSLASH_ISO
Definition: keymap.h:20
void hid_mouse_translate(unsigned char *kbinput, short *xaxis, short *yaxis, int endpoint, int length, const unsigned char *urbinput)
Definition: keymap.c:366
#define ckb_warn(fmt, args...)
Definition: includes.h:52
void corsair_mousecopy(unsigned char *kbinput, int endpoint, const unsigned char *urbinput)
Definition: keymap.c:403
#define N_BUTTONS_HW
Definition: keymap.h:31
#define BTN_WHEELDOWN
Definition: keymap.h:13
void hid_kb_translate(unsigned char *kbinput, int endpoint, int length, const unsigned char *urbinput)
Definition: keymap.c:223
#define MOUSE_EXTRA_FIRST
Definition: keymap.h:34
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
void corsair_kbcopy(unsigned char *kbinput, int endpoint, const unsigned char *urbinput)
Definition: keymap.c:394
#define N_KEYBYTES_HW
Definition: keymap.h:25
#define KEY_CORSAIR
Definition: keymap.h:8
#define LED_MOUSE
Definition: keymap.h:39
Definition: keymap.h:49