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
input.c
Go to the documentation of this file.
1 #include <limits.h>
2 #include "device.h"
3 #include "input.h"
4 #include "notify.h"
5 
6 int macromask(const uchar* key1, const uchar* key2){
7  // Scan a macro against key input. Return 0 if any of them don't match
8  for(int i = 0; i < N_KEYBYTES_INPUT; i++){
9  // if((key1[i] & key2[i]) != key2[i])
10  if(key1[i] != key2[i]) // Changed to detect G-keys + modifiers
11  return 0;
12  }
13  return 1;
14 }
15 
18 static ptlist_t* pt_head = 0;
20 static ptlist_t* pt_tail = 0;
21 
27 static void macro_pt_enqueue() {
28  ptlist_t* new_elem = malloc(sizeof(ptlist_t));
29  if (!new_elem) {
30  perror("macro_pt_enqueue: ");
31  exit (-1);
32  }
33  new_elem->next = 0;
34  new_elem->thread_id = pthread_self();
35  if (pt_head == 0) {
36  pt_head = pt_tail = new_elem;
37  } else {
38  pt_tail->next = new_elem;
39  pt_tail = new_elem;
40  }
41 }
42 
49 static pthread_t macro_pt_dequeue() {
50  pthread_t retval = 0;
51  ptlist_t* elem = 0;
52  if (pt_head == 0 && pt_tail == 0) {
53  ckb_err("macro_pt_dequeue: called on empty list.\n");
54  return 0;
55  }
56  elem = pt_head;
57  pt_head = pt_head->next;
58  if (pt_head == 0) pt_tail = 0;
59  retval = elem->thread_id;
60  free(elem);
61  return retval;
62 }
63 
70 static pthread_t macro_pt_first() {
71  return pt_head? pt_head->thread_id : 0;
72 }
73 
79 static void* play_macro(void* param) {
80  parameter_t* ptr = (parameter_t*) param;
81  usbdevice* kb = ptr->kb;
82  keymacro* macro = ptr->macro;
83 
86  pthread_mutex_lock(mmutex2(kb));
88  // ckb_info("Entering critical section with 0x%lx. Queue head is 0x%lx\n", (unsigned long int)pthread_self(), (unsigned long int)macro_pt_first());
89  while (macro_pt_first() != pthread_self()) {
90  // ckb_info("Now waiting with 0x%lx because of 0x%lx\n", (unsigned long int)pthread_self(), (unsigned long int)macro_pt_first());
91  pthread_cond_wait(mvar(kb), mmutex2(kb));
92  // ckb_info("Waking up with 0x%lx\n", (unsigned long int)pthread_self());
93  }
94  pthread_mutex_unlock(mmutex2(kb));
95 
97  pthread_mutex_lock(mmutex(kb));
98  for (int a = 0; a < macro->actioncount; a++) {
99  macroaction* action = macro->actions + a;
100  if (action->rel_x != 0 || action->rel_y != 0)
101  os_mousemove(kb, action->rel_x, action->rel_y);
102  else {
103  os_keypress(kb, action->scan, action->down);
104  pthread_mutex_unlock(mmutex(kb));
105  if (action->delay != UINT_MAX && action->delay) {
106  usleep(action->delay);
107  } else if (kb->delay != UINT_MAX && kb->delay) {
108  usleep(kb->delay);
109  } else if (a < (macro->actioncount - 1)) {
110  if (a > 200) {
111  usleep (100);
112  } else if (a > 20) {
113  usleep(30);
114  }
115  }
116  pthread_mutex_lock(mmutex(kb));
117  }
118  }
119 
120  pthread_mutex_lock(mmutex2(kb));
121  // ckb_info("Now leaving 0x%lx and waking up all others\n", (unsigned long int)pthread_self());
123  pthread_cond_broadcast(mvar(kb));
124  pthread_mutex_unlock(mmutex2(kb));
125 
126  pthread_mutex_unlock(mmutex(kb));
127  return 0;
128 }
129 
134 static void inputupdate_keys(usbdevice* kb){
135  usbmode* mode = kb->profile->currentmode;
136  binding* bind = &mode->bind;
137  usbinput* input = &kb->input;
138 
139  // Don't do anything if the state hasn't changed
140  if(!memcmp(input->prevkeys, input->keys, N_KEYBYTES_INPUT))
141  return;
142  // Look for macros matching the current state
143  if (kb->active) {
144  for (int i = 0; i < bind->macrocount; i++) {
145  keymacro* macro = &bind->macros[i];
146  if (macromask(input->keys, macro->combo)) {
147  if (!macro->triggered) {
148  parameter_t* params = malloc(sizeof(parameter_t));
149  if (params == 0) {
150  perror("inputupdate_keys got no more mem:");
151  } else {
152  pthread_t thread = 0;
153  params->kb = kb;
154  params->macro = macro;
155  int retval = pthread_create(&thread, 0, play_macro, (void*)params);
156  if (retval) {
157  perror("inputupdate_keys: Creating thread returned not null");
158  } else {
159  macro->triggered = 1;
160  }
161  }
162  }
163  } else macro->triggered = 0;
164  }
165  }
166  // Make a list of keycodes to send. Rearrange them so that modifier keydowns always come first
167  // and modifier keyups always come last. This ensures that shortcut keys will register properly
168  // even if both keydown events happen at once.
169  // N_KEYS + 4 is used because the volume wheel generates keydowns and keyups at the same time
170  // (it's currently impossible to press all four at once, but safety first)
171  int events[N_KEYS_INPUT + 4];
172  int modcount = 0, keycount = 0, rmodcount = 0;
173  for(int byte = 0; byte < N_KEYBYTES_INPUT; byte++){
174  char oldb = input->prevkeys[byte], newb = input->keys[byte];
175  if(oldb == newb)
176  continue;
177  for(int bit = 0; bit < 8; bit++){
178  int keyindex = byte * 8 + bit;
179  if(keyindex >= N_KEYS_INPUT)
180  break;
181  const key* map = keymap + keyindex;
182  int scancode = (kb->active) ? bind->base[keyindex] : map->scan;
183  char mask = 1 << bit;
184  char old = oldb & mask, new = newb & mask;
185  // If the key state changed, send it to the input device
186  if(old != new){
187  // Don't echo a key press if there's no scancode associated
188  if(!(scancode & SCAN_SILENT)){
189  if(IS_MOD(scancode)){
190  if(new){
191  // Modifier down: Add to the end of modifier keys
192  for(int i = keycount + rmodcount; i > 0; i--)
193  events[modcount + i] = events[modcount + i - 1];
194  // Add 1 to the scancode because A is zero on OSX
195  // Positive code = keydown, negative code = keyup
196  events[modcount++] = scancode + 1;
197  } else {
198  // Modifier up: Add to the end of everything
199  events[modcount + keycount + rmodcount++] = -(scancode + 1);
200  }
201  } else {
202  // Regular keypress: add to the end of regular keys
203  for(int i = rmodcount; i > 0; i--)
204  events[modcount + keycount + i] = events[modcount + keycount + i - 1];
205  events[modcount + keycount++] = new ? (scancode + 1) : -(scancode + 1);
206  // The volume wheel and the mouse wheel don't generate keyups, so create them automatically
207 #define IS_WHEEL(scan, kb) (((scan) == KEY_VOLUMEUP || (scan) == KEY_VOLUMEDOWN || (scan) == BTN_WHEELUP || (scan) == BTN_WHEELDOWN) && !IS_K65(kb))
208  if(new && IS_WHEEL(map->scan, kb)){
209  for(int i = rmodcount; i > 0; i--)
210  events[modcount + keycount + i] = events[modcount + keycount + i - 1];
211  events[modcount + keycount++] = -(scancode + 1);
212  input->keys[byte] &= ~mask;
213  }
214  }
215  }
216  // Print notifications if desired
217  if(kb->active){
218  for(int notify = 0; notify < OUTFIFO_MAX; notify++){
219  if(mode->notify[notify][byte] & mask){
220  nprintkey(kb, notify, keyindex, new);
221  // Wheels doesn't generate keyups
222  if(new && IS_WHEEL(map->scan, kb))
223  nprintkey(kb, notify, keyindex, 0);
224  }
225  }
226  }
227  }
228  }
229  }
232  if (!macro_pt_first()) {
233  int totalkeys = modcount + keycount + rmodcount;
234  for(int i = 0; i < totalkeys; i++){
235  int scancode = events[i];
236  os_keypress(kb, (scancode < 0 ? -scancode : scancode) - 1, scancode > 0);
237  }
238  }
239 }
240 
242 #ifdef OS_LINUX
243  if((!kb->uinput_kb || !kb->uinput_mouse)
244 #else
245  if(!kb->event
246 #endif
247  || !kb->profile)
248  return;
249  // Process key/button input
250  inputupdate_keys(kb);
251  // Process mouse movement
252  usbinput* input = &kb->input;
253  if(input->rel_x != 0 || input->rel_y != 0){
254  os_mousemove(kb, input->rel_x, input->rel_y);
255  input->rel_x = input->rel_y = 0;
256  }
257  // Finish up
258  memcpy(input->prevkeys, input->keys, N_KEYBYTES_INPUT);
259 }
260 
261 void updateindicators_kb(usbdevice* kb, int force){
262  // Read current hardware indicator state (set externally)
263  uchar old = kb->ileds, hw_old = kb->hw_ileds_old;
264  uchar new = kb->hw_ileds, hw_new = new;
265  // Update them if needed
266  if(kb->active){
267  usbmode* mode = kb->profile->currentmode;
268  new = (new & ~mode->ioff) | mode->ion;
269  }
270  kb->ileds = new;
271  kb->hw_ileds_old = hw_new;
272  if(old != new || force){
273  DELAY_SHORT(kb);
274  os_sendindicators(kb);
275  }
276  // Print notifications if desired
277  if(!kb->active)
278  return;
279  usbmode* mode = kb->profile->currentmode;
280  uchar indicators[] = { I_NUM, I_CAPS, I_SCROLL };
281  for(unsigned i = 0; i < sizeof(indicators) / sizeof(uchar); i++){
282  uchar mask = indicators[i];
283  if((hw_old & mask) == (hw_new & mask))
284  continue;
285  for(int notify = 0; notify < OUTFIFO_MAX; notify++){
286  if(mode->inotify[notify] & mask)
287  nprintind(kb, notify, mask, hw_new & mask);
288  }
289  }
290 }
291 
292 void initbind(binding* bind){
293  for(int i = 0; i < N_KEYS_INPUT; i++)
294  bind->base[i] = keymap[i].scan;
295  bind->macros = calloc(32, sizeof(keymacro));
296  bind->macrocap = 32;
297  bind->macrocount = 0;
298 }
299 
300 void freebind(binding* bind){
301  for(int i = 0; i < bind->macrocount; i++)
302  free(bind->macros[i].actions);
303  free(bind->macros);
304  memset(bind, 0, sizeof(*bind));
305 }
306 
307 void cmd_bind(usbdevice* kb, usbmode* mode, int dummy, int keyindex, const char* to){
308  if(keyindex >= N_KEYS_INPUT)
309  return;
310  // Find the key to bind to
311  int tocode = 0;
312  if(sscanf(to, "#x%ux", &tocode) != 1 && sscanf(to, "#%u", &tocode) == 1 && tocode < N_KEYS_INPUT){
313  pthread_mutex_lock(imutex(kb));
314  mode->bind.base[keyindex] = tocode;
315  pthread_mutex_unlock(imutex(kb));
316  return;
317  }
318  // If not numeric, look it up
319  for(int i = 0; i < N_KEYS_INPUT; i++){
320  if(keymap[i].name && !strcmp(to, keymap[i].name)){
321  pthread_mutex_lock(imutex(kb));
322  mode->bind.base[keyindex] = keymap[i].scan;
323  pthread_mutex_unlock(imutex(kb));
324  return;
325  }
326  }
327 }
328 
329 void cmd_unbind(usbdevice* kb, usbmode* mode, int dummy, int keyindex, const char* to){
330  if(keyindex >= N_KEYS_INPUT)
331  return;
332  pthread_mutex_lock(imutex(kb));
333  mode->bind.base[keyindex] = KEY_UNBOUND;
334  pthread_mutex_unlock(imutex(kb));
335 }
336 
337 void cmd_rebind(usbdevice* kb, usbmode* mode, int dummy, int keyindex, const char* to){
338  if(keyindex >= N_KEYS_INPUT)
339  return;
340  pthread_mutex_lock(imutex(kb));
341  mode->bind.base[keyindex] = keymap[keyindex].scan;
342  pthread_mutex_unlock(imutex(kb));
343 }
344 
345 static void _cmd_macro(usbmode* mode, const char* keys, const char* assignment){
346  binding* bind = &mode->bind;
347  if(!keys && !assignment){
348  // Null strings = "macro clear" -> erase the whole thing
349  for(int i = 0; i < bind->macrocount; i++)
350  free(bind->macros[i].actions);
351  bind->macrocount = 0;
352  return;
353  }
354  if(bind->macrocount >= MACRO_MAX)
355  return;
356  // Create a key macro
357  keymacro macro;
358  memset(&macro, 0, sizeof(macro));
359  // Scan the left side for key names, separated by +
360  int empty = 1;
361  int left = strlen(keys), right = strlen(assignment);
362  int position = 0, field = 0;
363  char keyname[24];
364  while(position < left && sscanf(keys + position, "%10[^+]%n", keyname, &field) == 1){
365  int keycode;
366  if((sscanf(keyname, "#%d", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)
367  || (sscanf(keyname, "#x%x", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)){
368  // Set a key numerically
369  SET_KEYBIT(macro.combo, keycode);
370  empty = 0;
371  } else {
372  // Find this key in the keymap
373  for(unsigned i = 0; i < N_KEYS_INPUT; i++){
374  if(keymap[i].name && !strcmp(keyname, keymap[i].name)){
375  macro.combo[i / 8] |= 1 << (i % 8);
376  empty = 0;
377  break;
378  }
379  }
380  }
381  if(keys[position += field] == '+')
382  position++;
383  }
384  if(empty)
385  return;
386  // Count the number of actions (comma separated)
387  int count = 1;
388  for(const char* c = assignment; *c != 0; c++){
389  if(*c == ',')
390  count++;
391  }
392  // Allocate a buffer for them
393  macro.actions = calloc(count, sizeof(macroaction));
394  macro.actioncount = 0;
395  // Scan the actions
396  position = 0;
397  field = 0;
398  // max action = old 11 chars plus 12 chars which is the max 32-bit int 4294967295 size
399  while(position < right && sscanf(assignment + position, "%23[^,]%n", keyname, &field) == 1){
400  if(!strcmp(keyname, "clear"))
401  break;
402 
403  // Check for local key delay of the form '[+-]<key>=<delay>'
404  long int long_delay; // scanned delay value, used to keep delay in range.
405  unsigned int delay = UINT_MAX; // computed delay value. UINT_MAX means use global delay value.
406  char real_keyname[12]; // temp to hold the left side (key) of the <key>=<delay>
407  int scan_matches = sscanf(keyname, "%11[^=]=%ld", real_keyname, &long_delay);
408  if (scan_matches == 2) {
409  if (0 <= long_delay && long_delay < UINT_MAX) {
410  delay = (unsigned int)long_delay;
411  strcpy(keyname, real_keyname); // keyname[24], real_keyname[12]
412  }
413  }
414 
415  int down = (keyname[0] == '+');
416  if(down || keyname[0] == '-'){
417  int keycode;
418  if((sscanf(keyname + 1, "#%d", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)
419  || (sscanf(keyname + 1, "#x%x", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)){
420  // Set a key numerically
421  macro.actions[macro.actioncount].scan = keymap[keycode].scan;
422  macro.actions[macro.actioncount].down = down;
423  macro.actions[macro.actioncount].delay = delay;
424  macro.actioncount++;
425  } else {
426  // Find this key in the keymap
427  for(unsigned i = 0; i < N_KEYS_INPUT; i++){
428  if(keymap[i].name && !strcmp(keyname + 1, keymap[i].name)){
429  macro.actions[macro.actioncount].scan = keymap[i].scan;
430  macro.actions[macro.actioncount].down = down;
431  macro.actions[macro.actioncount].delay = delay;
432  macro.actioncount++;
433  break;
434  }
435  }
436  }
437  }
438  if(assignment[position += field] == ',')
439  position++;
440  }
441 
442  // See if there's already a macro with this trigger
443  keymacro* macros = bind->macros;
444  for(int i = 0; i < bind->macrocount; i++){
445  if(!memcmp(macros[i].combo, macro.combo, N_KEYBYTES_INPUT)){
446  free(macros[i].actions);
447  // If the new macro has no actions, erase the existing one
448  if(!macro.actioncount){
449  for(int j = i + 1; j < bind->macrocount; j++)
450  memcpy(macros + j - 1, macros + j, sizeof(keymacro));
451  bind->macrocount--;
452  } else
453  // If there are actions, replace the existing with the new
454  memcpy(macros + i, &macro, sizeof(keymacro));
455  return;
456  }
457  }
458 
459  // Add the macro to the device settings if not empty
460  if(macro.actioncount < 1)
461  return;
462  memcpy(bind->macros + (bind->macrocount++), &macro, sizeof(keymacro));
463  if(bind->macrocount >= bind->macrocap)
464  bind->macros = realloc(bind->macros, (bind->macrocap += 16) * sizeof(keymacro));
465 }
466 
467 void cmd_macro(usbdevice* kb, usbmode* mode, const int notifynumber, const char* keys, const char* assignment){
468  pthread_mutex_lock(imutex(kb));
469  _cmd_macro(mode, keys, assignment);
470  pthread_mutex_unlock(imutex(kb));
471 }
short scan
Definition: structures.h:28
void initbind(binding *bind)
Definition: input.c:292
uchar notify[10][((((152+3+12)+25)+7)/8)]
Definition: structures.h:91
short scan
Definition: keymap.h:52
#define mmutex(kb)
Definition: device.h:26
#define MACRO_MAX
Definition: structures.h:51
#define mmutex2(kb)
Definition: device.h:28
static void * play_macro(void *param)
play_macro is the code for all threads started to play a macro.
Definition: input.c:79
uint delay
Definition: structures.h:251
usbprofile * profile
Definition: structures.h:221
void updateindicators_kb(usbdevice *kb, int force)
Definition: input.c:261
uchar ion
Definition: structures.h:93
int uinput_kb
Definition: structures.h:189
usbinput input
Definition: structures.h:245
struct ptlist is one element in the single linked list to store macro_play threads waiting for their ...
Definition: input.h:62
usbmode * currentmode
Definition: structures.h:105
#define DELAY_SHORT(kb)
USB delays for when the keyboards get picky about timing That was the original comment, but it is used anytime. The short delay is used before any send or receive.
Definition: usb.h:149
#define ckb_err(fmt, args...)
Definition: includes.h:49
#define IS_WHEEL(scan, kb)
#define IS_MOD(s)
Definition: input.h:34
short rel_y
Definition: structures.h:29
uchar keys[((((152+3+12)+25)+7)/8)]
Definition: structures.h:130
void os_mousemove(usbdevice *kb, int x, int y)
Definition: input_linux.c:143
struct parameter contains the values for a fresh started macro_play thread. parameter_t is the typede...
Definition: input.h:54
uchar hw_ileds_old
Definition: structures.h:247
static pthread_t macro_pt_first()
macro_pt_first returns the first pthread_id but does not remove the first entry.
Definition: input.c:70
#define N_KEYS_INPUT
Definition: keymap.h:36
uchar ileds
Definition: structures.h:247
char active
Definition: structures.h:231
int actioncount
Definition: structures.h:37
#define mvar(kb)
Definition: device.h:30
keymacro * macro
Definition: input.h:56
void inputupdate(usbdevice *kb)
Definition: input.c:241
static pthread_t macro_pt_dequeue()
macro_pt_dequeue gets the first thread id of the list and returns the thread_id stored in it...
Definition: input.c:49
#define SET_KEYBIT(array, index)
Definition: structures.h:15
uint delay
Definition: structures.h:31
void os_keypress(usbdevice *kb, int scancode, int down)
Definition: input_linux.c:118
struct ptlist * next
Definition: input.h:63
uchar ioff
Definition: structures.h:93
unsigned char uchar
Definition: includes.h:24
void cmd_unbind(usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
Definition: input.c:329
void nprintkey(usbdevice *kb, int nnumber, int keyindex, int down)
Definition: notify.c:35
short rel_x
Definition: structures.h:132
int uinput_mouse
Definition: structures.h:189
int macromask(const uchar *key1, const uchar *key2)
Definition: input.c:6
void nprintind(usbdevice *kb, int nnumber, int led, int on)
Definition: notify.c:43
static void macro_pt_enqueue()
macro_pt_enqueue Save the new thread in the single linked list (FIFO).
Definition: input.c:27
short rel_x
Definition: structures.h:29
static void _cmd_macro(usbmode *mode, const char *keys, const char *assignment)
Definition: input.c:345
uchar combo[((((152+3+12)+25)+7)/8)]
Definition: structures.h:38
short rel_y
Definition: structures.h:132
void cmd_macro(usbdevice *kb, usbmode *mode, const int notifynumber, const char *keys, const char *assignment)
Definition: input.c:467
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
#define KEY_UNBOUND
Definition: keymap.h:9
uchar prevkeys[((((152+3+12)+25)+7)/8)]
Definition: structures.h:131
static void inputupdate_keys(usbdevice *kb)
inputupdate_keys Handle input from Keyboard or mouse; start Macrof if detected.
Definition: input.c:134
usbdevice * kb
Definition: input.h:55
pthread_t thread_id
Definition: input.h:64
void cmd_bind(usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
Definition: input.c:307
int macrocap
Definition: structures.h:49
#define I_NUM
Definition: structures.h:19
char triggered
Definition: structures.h:39
#define imutex(kb)
Definition: device.h:22
int macrocount
Definition: structures.h:48
binding bind
Definition: structures.h:85
void freebind(binding *bind)
Definition: input.c:300
uchar inotify[10]
Definition: structures.h:95
#define SCAN_SILENT
Definition: keymap.h:56
uchar hw_ileds
Definition: structures.h:247
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
void os_sendindicators(usbdevice *kb)
os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else...
Definition: usb_linux.c:213
keymacro * macros
Definition: structures.h:47
#define I_CAPS
Definition: structures.h:20
static ptlist_t * pt_tail
pt_tail is the tail pointer for the single linked thread list managed by macro_pt_en/dequeue().
Definition: input.c:20
void cmd_rebind(usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
Definition: input.c:337
#define I_SCROLL
Definition: structures.h:21
static ptlist_t * pt_head
pt_head is the head pointer for the single linked thread list managed by macro_pt_en/dequeue().
Definition: input.c:18
macroaction * actions
Definition: structures.h:36
int base[((152+3+12)+25)]
Definition: structures.h:45
Definition: keymap.h:49
#define OUTFIFO_MAX
Definition: structures.h:24