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 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))
 

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))

Referenced by inputupdate_keys().

Function Documentation

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

Definition at line 345 of file input.c.

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

Referenced by cmd_macro().

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

+ 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  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 }
short scan
Definition: keymap.h:52
#define N_KEYS_INPUT
Definition: keymap.h:36
#define imutex(kb)
Definition: device.h:22
binding bind
Definition: structures.h:85
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
int base[((152+3+12)+25)]
Definition: structures.h:45
void cmd_macro ( usbdevice kb,
usbmode mode,
const int  notifynumber,
const char *  keys,
const char *  assignment 
)

Definition at line 467 of file input.c.

References _cmd_macro(), and imutex.

467  {
468  pthread_mutex_lock(imutex(kb));
469  _cmd_macro(mode, keys, assignment);
470  pthread_mutex_unlock(imutex(kb));
471 }
static void _cmd_macro(usbmode *mode, const char *keys, const char *assignment)
Definition: input.c:345
#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 337 of file input.c.

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

337  {
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 }
short scan
Definition: keymap.h:52
#define N_KEYS_INPUT
Definition: keymap.h:36
#define imutex(kb)
Definition: device.h:22
binding bind
Definition: structures.h:85
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
int base[((152+3+12)+25)]
Definition: structures.h:45
void cmd_unbind ( usbdevice kb,
usbmode mode,
int  dummy,
int  keyindex,
const char *  to 
)

Definition at line 329 of file input.c.

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

329  {
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 }
#define N_KEYS_INPUT
Definition: keymap.h:36
#define KEY_UNBOUND
Definition: keymap.h:9
#define imutex(kb)
Definition: device.h:22
binding bind
Definition: structures.h:85
int base[((152+3+12)+25)]
Definition: structures.h:45
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
#define N_KEYS_INPUT
Definition: keymap.h:36
int macrocap
Definition: structures.h:49
int macrocount
Definition: structures.h:48
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
keymacro * macros
Definition: structures.h:47
int base[((152+3+12)+25)]
Definition: structures.h:45

+ 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
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
short rel_x
Definition: structures.h:132
int uinput_mouse
Definition: structures.h:189
short rel_y
Definition: structures.h:132
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
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

+ 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))
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 }
uchar notify[10][((((152+3+12)+25)+7)/8)]
Definition: structures.h:91
short scan
Definition: keymap.h:52
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
#define IS_WHEEL(scan, kb)
#define IS_MOD(s)
Definition: input.h:34
uchar keys[((((152+3+12)+25)+7)/8)]
Definition: structures.h:130
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
#define N_KEYS_INPUT
Definition: keymap.h:36
char active
Definition: structures.h:231
keymacro * macro
Definition: input.h:56
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+3+12)+25)+7)/8)]
Definition: structures.h:38
#define N_KEYBYTES_INPUT
Definition: keymap.h:37
uchar prevkeys[((((152+3+12)+25)+7)/8)]
Definition: structures.h:131
usbdevice * kb
Definition: input.h:55
char triggered
Definition: structures.h:39
int macrocount
Definition: structures.h:48
binding bind
Definition: structures.h:85
#define SCAN_SILENT
Definition: keymap.h:56
const key keymap[(((152+3+12)+25)+11)]
Definition: keymap.c:5
keymacro * macros
Definition: structures.h:47
int base[((152+3+12)+25)]
Definition: structures.h:45
Definition: keymap.h:49
#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  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 }
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. The short delay is used before any send or receive.
Definition: usb.h:149
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:213
#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.