ckb-next  v0.2.8 at branch master
ckb-next driver for corsair devices
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends 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  clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {.tv_nsec = action->delay * 1000}, NULL);
107  } else if (kb->delay != UINT_MAX && kb->delay) {
108  clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {.tv_nsec = kb->delay * 1000}, NULL);
109  } else if (a < (macro->actioncount - 1)) {
110  if (a > 200) {
111  clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {.tv_nsec = action->delay * 100000}, NULL);
112  } else if (a > 20) {
113  clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {.tv_nsec = 30000}, NULL);
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) && !IS_K63(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  (void)dummy;
309 
310  if(keyindex >= N_KEYS_INPUT)
311  return;
312  // Find the key to bind to
313  int tocode = 0;
314  if(sscanf(to, "#x%ux", &tocode) != 1 && sscanf(to, "#%u", &tocode) == 1 && tocode < N_KEYS_INPUT){
315  pthread_mutex_lock(imutex(kb));
316  mode->bind.base[keyindex] = tocode;
317  pthread_mutex_unlock(imutex(kb));
318  return;
319  }
320  // If not numeric, look it up
321  for(int i = 0; i < N_KEYS_INPUT; i++){
322  if(keymap[i].name && !strcmp(to, keymap[i].name)){
323  pthread_mutex_lock(imutex(kb));
324  mode->bind.base[keyindex] = keymap[i].scan;
325  pthread_mutex_unlock(imutex(kb));
326  return;
327  }
328  }
329 }
330 
331 void cmd_unbind(usbdevice* kb, usbmode* mode, int dummy, int keyindex, const char* to){
332  (void)dummy;
333  (void)to;
334 
335  if(keyindex >= N_KEYS_INPUT)
336  return;
337  pthread_mutex_lock(imutex(kb));
338  mode->bind.base[keyindex] = KEY_UNBOUND;
339  pthread_mutex_unlock(imutex(kb));
340 }
341 
342 void cmd_rebind(usbdevice* kb, usbmode* mode, int dummy, int keyindex, const char* to){
343  (void)dummy;
344  (void)to;
345 
346  if(keyindex >= N_KEYS_INPUT)
347  return;
348  pthread_mutex_lock(imutex(kb));
349  mode->bind.base[keyindex] = keymap[keyindex].scan;
350  pthread_mutex_unlock(imutex(kb));
351 }
352 
353 static void _cmd_macro(usbmode* mode, const char* keys, const char* assignment){
354  binding* bind = &mode->bind;
355  if(!keys && !assignment){
356  // Null strings = "macro clear" -> erase the whole thing
357  for(int i = 0; i < bind->macrocount; i++)
358  free(bind->macros[i].actions);
359  bind->macrocount = 0;
360  return;
361  }
362  if(bind->macrocount >= MACRO_MAX)
363  return;
364  // Create a key macro
365  keymacro macro;
366  memset(&macro, 0, sizeof(macro));
367  // Scan the left side for key names, separated by +
368  int empty = 1;
369  int left = strlen(keys), right = strlen(assignment);
370  int position = 0, field = 0;
371  char keyname[24];
372  while(position < left && sscanf(keys + position, "%10[^+]%n", keyname, &field) == 1){
373  int keycode;
374  if((sscanf(keyname, "#%d", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)
375  || (sscanf(keyname, "#x%x", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)){
376  // Set a key numerically
377  SET_KEYBIT(macro.combo, keycode);
378  empty = 0;
379  } else {
380  // Find this key in the keymap
381  for(unsigned i = 0; i < N_KEYS_INPUT; i++){
382  if(keymap[i].name && !strcmp(keyname, keymap[i].name)){
383  macro.combo[i / 8] |= 1 << (i % 8);
384  empty = 0;
385  break;
386  }
387  }
388  }
389  if(keys[position += field] == '+')
390  position++;
391  }
392  if(empty)
393  return;
394  // Count the number of actions (comma separated)
395  int count = 1;
396  for(const char* c = assignment; *c != 0; c++){
397  if(*c == ',')
398  count++;
399  }
400  // Allocate a buffer for them
401  macro.actions = calloc(count, sizeof(macroaction));
402  macro.actioncount = 0;
403  // Scan the actions
404  position = 0;
405  field = 0;
406  // max action = old 11 chars plus 12 chars which is the max 32-bit int 4294967295 size
407  while(position < right && sscanf(assignment + position, "%23[^,]%n", keyname, &field) == 1){
408  if(!strcmp(keyname, "clear"))
409  break;
410 
411  // Check for local key delay of the form '[+-]<key>=<delay>'
412  long int long_delay; // scanned delay value, used to keep delay in range.
413  unsigned int delay = UINT_MAX; // computed delay value. UINT_MAX means use global delay value.
414  char real_keyname[12]; // temp to hold the left side (key) of the <key>=<delay>
415  int scan_matches = sscanf(keyname, "%11[^=]=%ld", real_keyname, &long_delay);
416  if (scan_matches == 2) {
417  if (0 <= long_delay && long_delay < UINT_MAX) {
418  delay = (unsigned int)long_delay;
419  strcpy(keyname, real_keyname); // keyname[24], real_keyname[12]
420  }
421  }
422 
423  int down = (keyname[0] == '+');
424  if(down || keyname[0] == '-'){
425  int keycode;
426  if((sscanf(keyname + 1, "#%d", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)
427  || (sscanf(keyname + 1, "#x%x", &keycode) && keycode >= 0 && keycode < N_KEYS_INPUT)){
428  // Set a key numerically
429  macro.actions[macro.actioncount].scan = keymap[keycode].scan;
430  macro.actions[macro.actioncount].down = down;
431  macro.actions[macro.actioncount].delay = delay;
432  macro.actioncount++;
433  } else {
434  // Find this key in the keymap
435  for(unsigned i = 0; i < N_KEYS_INPUT; i++){
436  if(keymap[i].name && !strcmp(keyname + 1, keymap[i].name)){
437  macro.actions[macro.actioncount].scan = keymap[i].scan;
438  macro.actions[macro.actioncount].down = down;
439  macro.actions[macro.actioncount].delay = delay;
440  macro.actioncount++;
441  break;
442  }
443  }
444  }
445  }
446  if(assignment[position += field] == ',')
447  position++;
448  }
449 
450  // See if there's already a macro with this trigger
451  keymacro* macros = bind->macros;
452  for(int i = 0; i < bind->macrocount; i++){
453  if(!memcmp(macros[i].combo, macro.combo, N_KEYBYTES_INPUT)){
454  free(macros[i].actions);
455  // If the new macro has no actions, erase the existing one
456  if(!macro.actioncount){
457  for(int j = i + 1; j < bind->macrocount; j++)
458  memcpy(macros + j - 1, macros + j, sizeof(keymacro));
459  bind->macrocount--;
460  } else
461  // If there are actions, replace the existing with the new
462  memcpy(macros + i, &macro, sizeof(keymacro));
463  return;
464  }
465  }
466 
467  // Add the macro to the device settings if not empty
468  if(macro.actioncount < 1)
469  return;
470  memcpy(bind->macros + (bind->macrocount++), &macro, sizeof(keymacro));
471  if(bind->macrocount >= bind->macrocap)
472  bind->macros = realloc(bind->macros, (bind->macrocap += 16) * sizeof(keymacro));
473 }
474 
475 void cmd_macro(usbdevice* kb, usbmode* mode, const int notifynumber, const char* keys, const char* assignment){
476  (void)notifynumber;
477 
478  pthread_mutex_lock(imutex(kb));
479  _cmd_macro(mode, keys, assignment);
480  pthread_mutex_unlock(imutex(kb));
481 }
short scan
Definition: structures.h:28
void initbind(binding *bind)
Definition: input.c:292
#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.
Definition: usb.h:178
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
#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
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
uchar prevkeys[((((152+22+12)+25)+7)/8)]
Definition: structures.h:131
#define SCAN_SILENT
Definition: keymap.h:56
Definition: keymap.h:49
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
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
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:331
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
uchar combo[((((152+22+12)+25)+7)/8)]
Definition: structures.h:38
static void _cmd_macro(usbmode *mode, const char *keys, const char *assignment)
Definition: input.c:353
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:475
double left
Definition: main.c:51
static QString right(const QString &left)
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
int base[((152+22+12)+25)]
Definition: structures.h:45
binding bind
Definition: structures.h:85
#define N_KEYS_INPUT
Definition: keymap.h:36
void freebind(binding *bind)
Definition: input.c:300
uchar inotify[10]
Definition: structures.h:95
uchar notify[10][((((152+22+12)+25)+7)/8)]
Definition: structures.h:91
uchar hw_ileds
Definition: structures.h:247
#define KEY_UNBOUND
Definition: keymap.h:9
void os_sendindicators(usbdevice *kb)
os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else...
Definition: usb_linux.c:214
keymacro * macros
Definition: structures.h:47
uchar keys[((((152+22+12)+25)+7)/8)]
Definition: structures.h:130
#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:342
#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
#define OUTFIFO_MAX
Definition: structures.h:24