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 File Reference
#include <limits.h>
#include "device.h"
#include "input.h"
#include "notify.h"
+ Include dependency graph for input.c:

Go to the source code of this file.

Macros

#define IS_WHEEL(scan, kb)   (((scan) == KEY_VOLUMEUP || (scan) == KEY_VOLUMEDOWN || (scan) == BTN_WHEELUP || (scan) == BTN_WHEELDOWN) && (!IS_K65(kb) && !IS_K63(kb)))
 

Functions

int macromask (const uchar *key1, const uchar *key2)
 
static void macro_pt_enqueue ()
 macro_pt_enqueue Save the new thread in the single linked list (FIFO). More...
 
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. More...
 
static pthread_t macro_pt_first ()
 macro_pt_first returns the first pthread_id but does not remove the first entry. More...
 
static void * play_macro (void *param)
 play_macro is the code for all threads started to play a macro. More...
 
static void inputupdate_keys (usbdevice *kb)
 inputupdate_keys Handle input from Keyboard or mouse; start Macrof if detected. More...
 
void inputupdate (usbdevice *kb)
 
void updateindicators_kb (usbdevice *kb, int force)
 
void initbind (binding *bind)
 
void freebind (binding *bind)
 
void cmd_bind (usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
 
void cmd_unbind (usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
 
void cmd_rebind (usbdevice *kb, usbmode *mode, int dummy, int keyindex, const char *to)
 
static void _cmd_macro (usbmode *mode, const char *keys, const char *assignment)
 
void cmd_macro (usbdevice *kb, usbmode *mode, const int notifynumber, const char *keys, const char *assignment)
 

Variables

static ptlist_tpt_head = 0
 pt_head is the head pointer for the single linked thread list managed by macro_pt_en/dequeue(). More...
 
static ptlist_tpt_tail = 0
 pt_tail is the tail pointer for the single linked thread list managed by macro_pt_en/dequeue(). More...
 

Macro Definition Documentation

#define IS_WHEEL (   scan,
  kb 
)    (((scan) == KEY_VOLUMEUP || (scan) == KEY_VOLUMEDOWN || (scan) == BTN_WHEELUP || (scan) == BTN_WHEELDOWN) && (!IS_K65(kb) && !IS_K63(kb)))

Referenced by inputupdate_keys().

Function Documentation

static void _cmd_macro ( usbmode mode,
const char *  keys,
const char *  assignment 
)
static

Definition at line 353 of file input.c.

References keymacro::actioncount, keymacro::actions, usbmode::bind, keymacro::combo, macroaction::delay, macroaction::down, keymap, left, MACRO_MAX, binding::macrocap, binding::macrocount, binding::macros, N_KEYBYTES_INPUT, N_KEYS_INPUT, right(), macroaction::scan, key::scan, and SET_KEYBIT.

Referenced by cmd_macro().

353  {
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 }
short scan
Definition: structures.h:28
#define MACRO_MAX
Definition: structures.h:51
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
int actioncount
Definition: structures.h:37
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
#define SET_KEYBIT(array, index)
Definition: structures.h:15
uint delay
Definition: structures.h:31
uchar combo[((((152+22+12)+25)+7)/8)]
Definition: structures.h:38
double left
Definition: main.c:51
static QString right(const QString &left)
int macrocap
Definition: structures.h:49
int macrocount
Definition: structures.h:48
binding bind
Definition: structures.h:85
#define N_KEYS_INPUT
Definition: keymap.h:36
keymacro * macros
Definition: structures.h:47
macroaction * actions
Definition: structures.h:36

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void cmd_bind ( usbdevice kb,
usbmode mode,
int  dummy,
int  keyindex,
const char *  to 
)

Definition at line 307 of file input.c.

References binding::base, usbmode::bind, imutex, keymap, N_KEYS_INPUT, and key::scan.

307  {
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 }
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
#define imutex(kb)
Definition: device.h:22
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 cmd_macro ( usbdevice kb,
usbmode mode,
const int  notifynumber,
const char *  keys,
const char *  assignment 
)

Definition at line 475 of file input.c.

References _cmd_macro(), and imutex.

475  {
476  (void)notifynumber;
477 
478  pthread_mutex_lock(imutex(kb));
479  _cmd_macro(mode, keys, assignment);
480  pthread_mutex_unlock(imutex(kb));
481 }
static void _cmd_macro(usbmode *mode, const char *keys, const char *assignment)
Definition: input.c:353
#define imutex(kb)
Definition: device.h:22

+ Here is the call graph for this function:

void cmd_rebind ( usbdevice kb,
usbmode mode,
int  dummy,
int  keyindex,
const char *  to 
)

Definition at line 342 of file input.c.

References binding::base, usbmode::bind, imutex, keymap, N_KEYS_INPUT, and key::scan.

342  {
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 }
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
#define imutex(kb)
Definition: device.h:22
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 cmd_unbind ( usbdevice kb,
usbmode mode,
int  dummy,
int  keyindex,
const char *  to 
)

Definition at line 331 of file input.c.

References binding::base, usbmode::bind, imutex, KEY_UNBOUND, and N_KEYS_INPUT.

331  {
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 }
#define imutex(kb)
Definition: device.h:22
int base[((152+22+12)+25)]
Definition: structures.h:45
binding bind
Definition: structures.h:85
#define N_KEYS_INPUT
Definition: keymap.h:36
#define KEY_UNBOUND
Definition: keymap.h:9
void freebind ( binding bind)

Definition at line 300 of file input.c.

References keymacro::actions, binding::macrocount, and binding::macros.

Referenced by freemode().

300  {
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 }
int macrocount
Definition: structures.h:48
keymacro * macros
Definition: structures.h:47
macroaction * actions
Definition: structures.h:36

+ Here is the caller graph for this function:

void initbind ( binding bind)

Definition at line 292 of file input.c.

References binding::base, keymap, binding::macrocap, binding::macrocount, binding::macros, N_KEYS_INPUT, and key::scan.

Referenced by initmode().

292  {
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 }
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
int macrocap
Definition: structures.h:49
int macrocount
Definition: structures.h:48
int base[((152+22+12)+25)]
Definition: structures.h:45
#define N_KEYS_INPUT
Definition: keymap.h:36
keymacro * macros
Definition: structures.h:47

+ Here is the caller graph for this function:

void inputupdate ( usbdevice kb)

Definition at line 241 of file input.c.

References usbdevice::input, inputupdate_keys(), os_mousemove(), usbdevice::profile, usbinput::rel_x, usbinput::rel_y, usbdevice::uinput_kb, and usbdevice::uinput_mouse.

Referenced by os_inputmain(), setactive_kb(), and setactive_mouse().

241  {
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 }
usbprofile * profile
Definition: structures.h:221
int uinput_kb
Definition: structures.h:189
usbinput input
Definition: structures.h:245
void os_mousemove(usbdevice *kb, int x, int y)
Definition: input_linux.c:143
uchar prevkeys[((((152+22+12)+25)+7)/8)]
Definition: structures.h:131
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
short rel_x
Definition: structures.h:132
int uinput_mouse
Definition: structures.h:189
short rel_y
Definition: structures.h:132
static void inputupdate_keys(usbdevice *kb)
inputupdate_keys Handle input from Keyboard or mouse; start Macrof if detected.
Definition: input.c:134
uchar keys[((((152+22+12)+25)+7)/8)]
Definition: structures.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void inputupdate_keys ( usbdevice kb)
static
Parameters
kb

Process all queued keypresses if no macro is running yet.

Todo:
If we want to get all keys typed while a macro is played, add the code for it here.

Definition at line 134 of file input.c.

References usbdevice::active, binding::base, usbmode::bind, keymacro::combo, usbprofile::currentmode, usbdevice::input, IS_MOD, IS_WHEEL, parameter::kb, keymap, usbinput::keys, parameter::macro, macro_pt_first(), binding::macrocount, macromask(), binding::macros, N_KEYBYTES_INPUT, N_KEYS_INPUT, usbmode::notify, nprintkey(), os_keypress(), OUTFIFO_MAX, play_macro(), usbinput::prevkeys, usbdevice::profile, key::scan, SCAN_SILENT, and keymacro::triggered.

Referenced by inputupdate().

134  {
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 }
static void * play_macro(void *param)
play_macro is the code for all threads started to play a macro.
Definition: input.c:79
usbprofile * profile
Definition: structures.h:221
usbinput input
Definition: structures.h:245
usbmode * currentmode
Definition: structures.h:105
short scan
Definition: keymap.h:52
const key keymap[(((152+22+12)+25)+12)]
Definition: keymap.c:5
#define IS_WHEEL(scan, kb)
#define IS_MOD(s)
Definition: input.h:34
struct parameter contains the values for a fresh started macro_play thread. parameter_t is the typede...
Definition: input.h:54
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
char active
Definition: structures.h:231
keymacro * macro
Definition: input.h:56
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
void os_keypress(usbdevice *kb, int scancode, int down)
Definition: input_linux.c:118
void nprintkey(usbdevice *kb, int nnumber, int keyindex, int down)
Definition: notify.c:35
int macromask(const uchar *key1, const uchar *key2)
Definition: input.c:6
uchar combo[((((152+22+12)+25)+7)/8)]
Definition: structures.h:38
usbdevice * kb
Definition: input.h:55
char triggered
Definition: structures.h:39
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
uchar notify[10][((((152+22+12)+25)+7)/8)]
Definition: structures.h:91
keymacro * macros
Definition: structures.h:47
uchar keys[((((152+22+12)+25)+7)/8)]
Definition: structures.h:130
#define OUTFIFO_MAX
Definition: structures.h:24

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static pthread_t macro_pt_dequeue ( )
static
Returns
the ptread_id of the first element. If list is empty, return 0.
Attention
Becuase multiple threads may use this function in parallel, save the critical section with a mutex.

< why are we called?

< Was last element in the list, so clear tail.

< save the return value before deleting element

Definition at line 49 of file input.c.

References ckb_err, ptlist::next, pt_head, and ptlist::thread_id.

Referenced by play_macro().

49  {
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 }
struct ptlist is one element in the single linked list to store macro_play threads waiting for their ...
Definition: input.h:62
#define ckb_err(fmt, args...)
Definition: includes.h:49
struct ptlist * next
Definition: input.h:63
pthread_t thread_id
Definition: input.h:64
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
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

+ Here is the caller graph for this function:

static void macro_pt_enqueue ( )
static
Attention
Becuase multiple threads may use this function in parallel, save the critical section with a mutex.

< exit on critical situation;

Todo:
find a better exit strategy if no more mem available.

< The element knows its ID byself

< new list, first element

< existing list, append on last element (FIFO)

Definition at line 27 of file input.c.

References ptlist::next, and ptlist::thread_id.

Referenced by play_macro().

27  {
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 }
struct ptlist is one element in the single linked list to store macro_play threads waiting for their ...
Definition: input.h:62
struct ptlist * next
Definition: input.h:63
pthread_t thread_id
Definition: input.h:64
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
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

+ Here is the caller graph for this function:

static pthread_t macro_pt_first ( )
static
Returns
the pthread_id of the first element in the list or 0 if list is empty.
Attention
Becuase multiple threads may use this function in parallel, save the critical section with a mutex (avoid NIL-ptr)

Definition at line 70 of file input.c.

References ptlist::thread_id.

Referenced by inputupdate_keys(), and play_macro().

70  {
71  return pt_head? pt_head->thread_id : 0;
72 }
pthread_t thread_id
Definition: input.h:64
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

+ Here is the caller graph for this function:

int macromask ( const uchar key1,
const uchar key2 
)

Definition at line 6 of file input.c.

References N_KEYBYTES_INPUT.

Referenced by inputupdate_keys().

6  {
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 }
#define N_KEYBYTES_INPUT
Definition: keymap.h:37

+ Here is the caller graph for this function:

static void* play_macro ( void *  param)
static
Parameters
paramparameter_t to store Kb-ptr and macro-ptr (thread may get only one user-parameter)
Returns
0 on success, -1 else (no one is interested in it except the kernel...)

First have a look if we are the first and only macro-thread to run. If not, wait. So enqueue our thread first, so it is remembered for us and can be seen by all others.

< If the first thread in the list is not our, another one is running

< Give all new threads the chance to enter the block.

Send events for each keypress in the macro

< Synchonization between macro output and color information

< use this unlock / relock for enablling the parallel running colorization

< local delay set

< use default global delay

< use delays depending on macro length

< protect the linked list and the mvar

< Wake up all waiting threads

< for the linked list and the mvar

< Sync keyboard input/output and colorization

Definition at line 79 of file input.c.

References keymacro::actioncount, keymacro::actions, macroaction::delay, usbdevice::delay, macroaction::down, parameter::kb, parameter::macro, macro_pt_dequeue(), macro_pt_enqueue(), macro_pt_first(), mmutex, mmutex2, mvar, os_keypress(), os_mousemove(), macroaction::rel_x, macroaction::rel_y, and macroaction::scan.

Referenced by inputupdate_keys().

79  {
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 }
short scan
Definition: structures.h:28
#define mmutex(kb)
Definition: device.h:26
#define mmutex2(kb)
Definition: device.h:28
uint delay
Definition: structures.h:251
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
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
int actioncount
Definition: structures.h:37
#define mvar(kb)
Definition: device.h:30
keymacro * macro
Definition: input.h:56
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
uint delay
Definition: structures.h:31
void os_keypress(usbdevice *kb, int scancode, int down)
Definition: input_linux.c:118
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
usbdevice * kb
Definition: input.h:55
macroaction * actions
Definition: structures.h:36

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void updateindicators_kb ( usbdevice kb,
int  force 
)

Definition at line 261 of file input.c.

References usbdevice::active, usbprofile::currentmode, DELAY_SHORT, usbdevice::hw_ileds, usbdevice::hw_ileds_old, I_CAPS, I_NUM, I_SCROLL, usbdevice::ileds, usbmode::inotify, usbmode::ioff, usbmode::ion, nprintind(), os_sendindicators(), OUTFIFO_MAX, and usbdevice::profile.

261  {
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 }
usbprofile * profile
Definition: structures.h:221
uchar ion
Definition: structures.h:93
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
uchar hw_ileds_old
Definition: structures.h:247
uchar ileds
Definition: structures.h:247
char active
Definition: structures.h:231
uchar ioff
Definition: structures.h:93
unsigned char uchar
Definition: includes.h:24
void nprintind(usbdevice *kb, int nnumber, int led, int on)
Definition: notify.c:43
#define I_NUM
Definition: structures.h:19
uchar inotify[10]
Definition: structures.h:95
uchar hw_ileds
Definition: structures.h:247
void os_sendindicators(usbdevice *kb)
os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else...
Definition: usb_linux.c:214
#define I_CAPS
Definition: structures.h:20
#define I_SCROLL
Definition: structures.h:21
#define OUTFIFO_MAX
Definition: structures.h:24

+ Here is the call graph for this function:

Variable Documentation

ptlist_t* pt_head = 0
static

Definition at line 18 of file input.c.

Referenced by macro_pt_dequeue().

ptlist_t* pt_tail = 0
static

Definition at line 20 of file input.c.