LIRC libraries
LinuxInfraredRemoteControl
config_file.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** config_file.c ***********************************************************
3 ****************************************************************************
4 *
5 *
6 * Copyright (C) 1998 Pablo d'Angelo <pablo@ag-trek.allgaeu.org>
7 *
8 */
9 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 
21 #include <dirent.h>
22 #include <errno.h>
23 #include <glob.h>
24 #include <limits.h>
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <libgen.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <fcntl.h>
36 #include <ctype.h>
37 
38 #ifdef HAVE_KERNEL_LIRC_H
39 #include <linux/lirc.h>
40 #else
41 #include "media/lirc.h"
42 #endif
43 
44 #include "lirc/lirc_log.h"
45 #include "lirc/lirc_options.h"
46 #include "lirc/ir_remote.h"
47 #include "lirc/config_file.h"
48 #include "lirc/transmit.h"
49 #include "lirc/config_flags.h"
50 
51 
52 static const logchannel_t logchannel = LOG_LIB;
53 
54 enum directive { ID_none, ID_remote, ID_codes, ID_raw_codes, ID_raw_name };
55 
56 struct ptr_array {
57  void** ptr;
58  size_t nr_items;
59  size_t chunk_size;
60 };
61 
62 struct void_array {
63  void* ptr;
64  size_t item_size;
65  size_t nr_items;
66  size_t chunk_size;
67 };
68 
69 
71 typedef void* (*array_guest_func)(void* item, void* arg);
72 
73 
74 #define LINE_LEN 1024
75 #define MAX_INCLUDES 10
76 
77 const char* whitespace = " \t";
78 
79 static int line;
80 static int parse_error;
81 
82 static struct ir_remote* read_config_recursive(FILE* f, const char* name, int depth);
83 static void calculate_signal_lengths(struct ir_remote* remote);
84 
85 void** init_void_array(struct void_array* ar, size_t chunk_size, size_t item_size)
86 {
87  ar->chunk_size = chunk_size;
88  ar->item_size = item_size;
89  ar->nr_items = 0;
90  ar->ptr = calloc(chunk_size, ar->item_size);
91  if (!ar->ptr) {
92  log_error("out of memory");
93  parse_error = 1;
94  return NULL;
95  }
96  return ar->ptr;
97 }
98 
99 const struct flaglist all_flags[] = {
100  { "RAW_CODES", RAW_CODES },
101  { "RC5", RC5 },
102  { "SHIFT_ENC", SHIFT_ENC }, /* obsolete */
103  { "RC6", RC6 },
104  { "RCMM", RCMM },
105  { "SPACE_ENC", SPACE_ENC },
106  { "SPACE_FIRST", SPACE_FIRST },
107  { "GOLDSTAR", GOLDSTAR },
108  { "GRUNDIG", GRUNDIG },
109  { "BO", BO },
110  { "SERIAL", SERIAL },
111  { "XMP", XMP },
112 
113  { "REVERSE", REVERSE },
114  { "NO_HEAD_REP", NO_HEAD_REP },
115  { "NO_FOOT_REP", NO_FOOT_REP },
116  { "CONST_LENGTH", CONST_LENGTH }, /* remember to adapt warning
117  * message when changing this */
118  { "REPEAT_HEADER", REPEAT_HEADER },
119  { NULL, 0 },
120 };
121 
122 
124 int add_void_array(struct void_array* ar, void* dataptr)
125 {
126  void* ptr;
127 
128  if ((ar->nr_items % ar->chunk_size) == (ar->chunk_size) - 1) {
129  /* I hope this works with the right alignment,
130  * if not we're screwed */
131  ptr = realloc(ar->ptr,
132  ar->item_size *
133  (ar->nr_items + ar->chunk_size + 1));
134  if (!ptr) {
135  log_error("out of memory");
136  parse_error = 1;
137  return 0;
138  }
139  ar->ptr = ptr;
140  }
141  memcpy((ar->ptr) + (ar->item_size * ar->nr_items), dataptr, ar->item_size);
142  ar->nr_items = (ar->nr_items) + 1;
143  memset((ar->ptr) + (ar->item_size * ar->nr_items), 0, ar->item_size);
144  return 1;
145 }
146 
147 
149 void* get_void_array(struct void_array* ar)
150 {
151  return ar->ptr;
152 }
153 
154 
159 static void*
160 foreach_void_array(struct void_array* ar, array_guest_func func, void* arg)
161 {
162  void* r;
163  int i;
164 
165  for (i = 0; i < ar->nr_items; i += 1) {
166  r = func(ar->ptr + (i * ar->item_size), arg);
167  if (r != NULL)
168  return r;
169  }
170  return NULL;
171 }
172 
173 
174 static int
175 ir_code_node_equals(struct ir_code_node* node1, struct ir_code_node* node2)
176 {
177  if (node1 == NULL || node2 == NULL)
178  return node1 == node2;
179  return node1->code == node2->code;
180 }
181 
182 
187 static void* array_guest_code_equals(void* arg1, void* arg2)
188 {
189 
190  struct ir_ncode* code1 = (struct ir_ncode*) arg1;
191  struct ir_ncode* code2 = (struct ir_ncode*) arg2;
192  struct ir_code_node* next1;
193  struct ir_code_node* next2;
194 
195  if (code1 == NULL || code2 == NULL)
196  return NULL;
197  if (code1->code != code2->code)
198  return NULL;
199  next1 = code1->next;
200  next2 = code2->next;
201  while (next1 != NULL) {
202  if (!ir_code_node_equals(next1, next2))
203  return NULL;
204  next1 = next1->next;
205  next2 = next2->next;
206  }
207  return next2 == NULL ? arg1 : NULL;
208 }
209 
210 
215 static void* array_guest_ncode_cmp(void* item, void* arg)
216 {
217 
218  struct ir_ncode* code1 = (struct ir_ncode*) item;
219  struct ir_ncode* code2 = (struct ir_ncode*) arg;
220 
221  if (strcmp(code1->name, code2->name) == 0)
222  return item;
223  return NULL;
224 }
225 
226 
227 void* s_malloc(size_t size)
228 {
229  void* ptr;
230 
231  ptr = malloc(size);
232  if (ptr == NULL) {
233  log_error("out of memory");
234  parse_error = 1;
235  return NULL;
236  }
237  memset(ptr, 0, size);
238  return ptr;
239 }
240 
241 char* s_strdup(char* string)
242 {
243  char* ptr;
244 
245  ptr = strdup(string);
246  if (!ptr) {
247  log_error("out of memory");
248  parse_error = 1;
249  return NULL;
250  }
251  return ptr;
252 }
253 
254 ir_code s_strtocode(const char* val)
255 {
256  ir_code code = 0;
257  char* endptr;
258 
259  errno = 0;
260  code = strtoull(val, &endptr, 0);
261  if ((code == (uint64_t) -1 && errno == ERANGE) || strlen(endptr) != 0 || strlen(val) == 0) {
262  log_error("error in configfile line %d:", line);
263  log_error("\"%s\": must be a valid (uint64_t) number", val);
264  parse_error = 1;
265  return 0;
266  }
267  return code;
268 }
269 
270 uint32_t s_strtou32(char* val)
271 {
272  uint32_t n;
273  char* endptr;
274 
275  n = strtoul(val, &endptr, 0);
276  if (!*val || *endptr) {
277  log_error("error in configfile line %d:", line);
278  log_error("\"%s\": must be a valid (uint32_t) number", val);
279  parse_error = 1;
280  return 0;
281  }
282  return n;
283 }
284 
285 int s_strtoi(char* val)
286 {
287  char* endptr;
288  long n;
289  int h;
290 
291  n = strtol(val, &endptr, 0);
292  h = (int)n;
293  if (!*val || *endptr || n != ((long)h)) {
294  log_error("error in configfile line %d:", line);
295  log_error("\"%s\": must be a valid (int) number", val);
296  parse_error = 1;
297  return 0;
298  }
299  return h;
300 }
301 
302 unsigned int s_strtoui(char* val)
303 {
304  char* endptr;
305  uint32_t n;
306  unsigned int h;
307 
308  n = strtoul(val, &endptr, 0);
309  h = (unsigned int)n;
310  if (!*val || *endptr || n != ((uint32_t)h)) {
311  log_error("error in configfile line %d:", line);
312  log_error("\"%s\": must be a valid (unsigned int) number", val);
313  parse_error = 1;
314  return 0;
315  }
316  return h;
317 }
318 
319 lirc_t s_strtolirc_t(char* val)
320 {
321  uint32_t n;
322  lirc_t h;
323  char* endptr;
324 
325  n = strtoul(val, &endptr, 0);
326  h = (lirc_t)n;
327  if (!*val || *endptr || n != ((uint32_t)h)) {
328  log_error("error in configfile line %d:", line);
329  log_error("\"%s\": must be a valid (lirc_t) number", val);
330  parse_error = 1;
331  return 0;
332  }
333  if (h < 0) {
334  log_warn("error in configfile line %d:", line);
335  log_warn("\"%s\" is out of range", val);
336  }
337  return h;
338 }
339 
340 int checkMode(int is_mode, int c_mode, char* error)
341 {
342  if (is_mode != c_mode) {
343  log_error("fatal error in configfile line %d:", line);
344  log_error("\"%s\" isn't valid at this position", error);
345  parse_error = 1;
346  return 0;
347  }
348  return 1;
349 }
350 
351 int addSignal(struct void_array* signals, char* val)
352 {
353  unsigned int t;
354 
355  t = s_strtoui(val);
356  if (parse_error)
357  return 0;
358  if (!add_void_array(signals, &t))
359  return 0;
360 
361  return 1;
362 }
363 
364 struct ir_ncode* defineCode(char* key, char* val, struct ir_ncode* code)
365 {
366  memset(code, 0, sizeof(*code));
367  code->name = s_strdup(key);
368  code->code = s_strtocode(val);
369  log_trace2(" %-20s 0x%016llX", code->name, code->code);
370  return code;
371 }
372 
373 struct ir_code_node* defineNode(struct ir_ncode* code, const char* val)
374 {
375  struct ir_code_node* node;
376 
377  node = s_malloc(sizeof(*node));
378  if (node == NULL)
379  return NULL;
380 
381  node->code = s_strtocode(val);
382  node->next = NULL;
383 
384  log_trace2(" 0x%016llX", node->code);
385 
386  if (code->current == NULL) {
387  code->next = node;
388  code->current = node;
389  } else {
390  code->current->next = node;
391  code->current = node;
392  }
393  return node;
394 }
395 
396 int parseFlags(char* val)
397 {
398  const struct flaglist* flaglptr;
399  int flags = 0;
400  char* flag;
401  char* help;
402 
403  flag = help = val;
404  while (flag != NULL) {
405  while (*help != '|' && *help != 0)
406  help++;
407  if (*help == '|') {
408  *help = 0;
409  help++;
410  } else {
411  help = NULL;
412  }
413 
414  flaglptr = all_flags;
415  while (flaglptr->name != NULL) {
416  if (strcasecmp(flaglptr->name, flag) == 0) {
417  if (flaglptr->flag & IR_PROTOCOL_MASK && flags & IR_PROTOCOL_MASK) {
418  log_error("error in configfile line %d:", line);
419  log_error("multiple protocols given in flags: \"%s\"", flag);
420  parse_error = 1;
421  return 0;
422  }
423  flags = flags | flaglptr->flag;
424  log_trace2("flag %s recognized", flaglptr->name);
425  break;
426  }
427  flaglptr++;
428  }
429  if (flaglptr->name == NULL) {
430  log_error("error in configfile line %d:", line);
431  log_error("unknown flag: \"%s\"", flag);
432  parse_error = 1;
433  return 0;
434  }
435  flag = help;
436  }
437  log_trace1("flags value: %d", flags);
438 
439  return flags;
440 }
441 
442 int defineRemote(char* key, char* val, char* val2, struct ir_remote* rem)
443 {
444  if ((strcasecmp("name", key)) == 0) {
445  if (rem->name != NULL)
446  free((void*)(rem->name));
447  rem->name = s_strdup(val);
448  log_info("Using remote: %s.", val);
449  return 1;
450  }
451  if (options_getboolean("lircd:dynamic-codes")) {
452  if ((strcasecmp("dyncodes_name", key)) == 0) {
453  if (rem->dyncodes_name != NULL)
454  free(rem->dyncodes_name);
455  rem->dyncodes_name = s_strdup(val);
456  return 1;
457  }
458  } else if (strcasecmp("driver", key) == 0) {
459  if (rem->driver != NULL)
460  free((void*)(rem->driver));
461  rem->driver = s_strdup(val);
462  return 1;
463  } else if ((strcasecmp("bits", key)) == 0) {
464  rem->bits = s_strtoi(val);
465  return 1;
466  } else if (strcasecmp("flags", key) == 0) {
467  rem->flags |= parseFlags(val);
468  return 1;
469  } else if (strcasecmp("eps", key) == 0) {
470  rem->eps = s_strtoi(val);
471  return 1;
472  } else if (strcasecmp("aeps", key) == 0) {
473  rem->aeps = s_strtoi(val);
474  return 1;
475  } else if (strcasecmp("plead", key) == 0) {
476  rem->plead = s_strtolirc_t(val);
477  return 1;
478  } else if (strcasecmp("ptrail", key) == 0) {
479  rem->ptrail = s_strtolirc_t(val);
480  return 1;
481  } else if (strcasecmp("pre_data_bits", key) == 0) {
482  rem->pre_data_bits = s_strtoi(val);
483  return 1;
484  } else if (strcasecmp("pre_data", key) == 0) {
485  rem->pre_data = s_strtocode(val);
486  return 1;
487  } else if (strcasecmp("post_data_bits", key) == 0) {
488  rem->post_data_bits = s_strtoi(val);
489  return 1;
490  } else if (strcasecmp("post_data", key) == 0) {
491  rem->post_data = s_strtocode(val);
492  return 1;
493  } else if (strcasecmp("gap", key) == 0) {
494  if (val2 != NULL)
495  rem->gap2 = s_strtou32(val2);
496  rem->gap = s_strtou32(val);
497  return val2 != NULL ? 2 : 1;
498  } else if (strcasecmp("repeat_gap", key) == 0) {
499  rem->repeat_gap = s_strtou32(val);
500  return 1;
501  } else if (strcasecmp("repeat_mask", key) == 0) {
502  rem->repeat_mask = s_strtocode(val);
503  return 1;
504  }
505  /* obsolete: use toggle_bit_mask instead */
506  else if (strcasecmp("toggle_bit", key) == 0) {
507  rem->toggle_bit = s_strtoi(val);
508  return 1;
509  } else if (strcasecmp("toggle_bit_mask", key) == 0) {
510  rem->toggle_bit_mask = s_strtocode(val);
511  return 1;
512  } else if (strcasecmp("toggle_mask", key) == 0) {
513  rem->toggle_mask = s_strtocode(val);
514  return 1;
515  } else if (strcasecmp("rc6_mask", key) == 0) {
516  rem->rc6_mask = s_strtocode(val);
517  return 1;
518  } else if (strcasecmp("ignore_mask", key) == 0) {
519  rem->ignore_mask = s_strtocode(val);
520  return 1;
521  } else if (strcasecmp("manual_sort", key) == 0) {
522  rem->manual_sort = s_strtoi(val);
523  return 1;
524  }
525  /* obsolete name */
526  else if (strcasecmp("repeat_bit", key) == 0) {
527  rem->toggle_bit = s_strtoi(val);
528  return 1;
529  } else if (strcasecmp("suppress_repeat", key) == 0) {
530  rem->suppress_repeat = s_strtoi(val);
531  return 1;
532  } else if (strcasecmp("min_repeat", key) == 0) {
533  rem->min_repeat = s_strtoi(val);
534  return 1;
535  } else if (strcasecmp("min_code_repeat", key) == 0) {
536  rem->min_code_repeat = s_strtoi(val);
537  return 1;
538  } else if (strcasecmp("frequency", key) == 0) {
539  rem->freq = s_strtoui(val);
540  return 1;
541  } else if (strcasecmp("duty_cycle", key) == 0) {
542  rem->duty_cycle = s_strtoui(val);
543  return 1;
544  } else if (strcasecmp("baud", key) == 0) {
545  rem->baud = s_strtoui(val);
546  return 1;
547  } else if (strcasecmp("serial_mode", key) == 0) {
548  if (val[0] < '5' || val[0] > '9') {
549  log_error("error in configfile line %d:", line);
550  log_error("bad bit count");
551  parse_error = 1;
552  return 0;
553  }
554  rem->bits_in_byte = val[0] - '0';
555  switch (toupper(val[1])) {
556  case 'N':
557  rem->parity = IR_PARITY_NONE;
558  break;
559  case 'E':
560  rem->parity = IR_PARITY_EVEN;
561  break;
562  case 'O':
563  rem->parity = IR_PARITY_ODD;
564  break;
565  default:
566  log_error("error in configfile line %d:", line);
567  log_error("unsupported parity mode");
568  parse_error = 1;
569  return 0;
570  }
571  if (strcmp(val + 2, "1.5") == 0)
572  rem->stop_bits = 3;
573  else
574  rem->stop_bits = s_strtoui(val + 2) * 2;
575  return 1;
576  } else if (val2 != NULL) {
577  if (strcasecmp("header", key) == 0) {
578  rem->phead = s_strtolirc_t(val);
579  rem->shead = s_strtolirc_t(val2);
580  return 2;
581  } else if (strcasecmp("three", key) == 0) {
582  rem->pthree = s_strtolirc_t(val);
583  rem->sthree = s_strtolirc_t(val2);
584  return 2;
585  } else if (strcasecmp("two", key) == 0) {
586  rem->ptwo = s_strtolirc_t(val);
587  rem->stwo = s_strtolirc_t(val2);
588  return 2;
589  } else if (strcasecmp("one", key) == 0) {
590  rem->pone = s_strtolirc_t(val);
591  rem->sone = s_strtolirc_t(val2);
592  return 2;
593  } else if (strcasecmp("zero", key) == 0) {
594  rem->pzero = s_strtolirc_t(val);
595  rem->szero = s_strtolirc_t(val2);
596  return 2;
597  } else if (strcasecmp("foot", key) == 0) {
598  rem->pfoot = s_strtolirc_t(val);
599  rem->sfoot = s_strtolirc_t(val2);
600  return 2;
601  } else if (strcasecmp("repeat", key) == 0) {
602  rem->prepeat = s_strtolirc_t(val);
603  rem->srepeat = s_strtolirc_t(val2);
604  return 2;
605  } else if (strcasecmp("pre", key) == 0) {
606  rem->pre_p = s_strtolirc_t(val);
607  rem->pre_s = s_strtolirc_t(val2);
608  return 2;
609  } else if (strcasecmp("post", key) == 0) {
610  rem->post_p = s_strtolirc_t(val);
611  rem->post_s = s_strtolirc_t(val2);
612  return 2;
613  }
614  }
615  if (val2) {
616  log_error("error in configfile line %d:", line);
617  log_error("unknown definiton: \"%s %s %s\"", key, val, val2);
618  } else {
619  log_error("error in configfile line %d:", line);
620  log_error("unknown definiton or too few arguments: \"%s %s\"", key, val);
621  }
622  parse_error = 1;
623  return 0;
624 }
625 
626 static int sanityChecks(struct ir_remote* rem, const char* path)
627 {
628  struct ir_ncode* codes;
629  struct ir_code_node* node;
630 
631  path = path != NULL ? path : "unknown file";
632 
633  if (!rem->name) {
634  log_error("%s: Missing remote name", path);
635  return 0;
636  }
637  if (rem->gap == 0) {
638  log_warn("%s: %s: Gap value missing or invalid",
639  path, rem->name);
640  }
641  if (has_repeat_gap(rem) && is_const(rem)) {
642  log_warn("%s: %s: Repeat_gap ignored (CONST_LENGTH is set)",
643  path, rem->name);
644  }
645 
646  if (is_raw(rem))
647  return 1;
648 
649  if ((rem->pre_data & gen_mask(rem->pre_data_bits)) != rem->pre_data) {
650  log_warn(
651  "%s: %s: Invalid pre_data", path, rem->name);
652  rem->pre_data &= gen_mask(rem->pre_data_bits);
653  }
654  if ((rem->post_data & gen_mask(rem->post_data_bits)) != rem->post_data) {
655  log_warn("%s: %s: Invalid post_data",
656  path, rem->name);
657  rem->post_data &= gen_mask(rem->post_data_bits);
658  }
659  if (!rem->codes) {
660  log_error("%s: %s: No codes", path, rem->name);
661  return 0;
662  }
663  for (codes = rem->codes; codes->name != NULL; codes++) {
664  if ((codes->code & gen_mask(rem->bits)) != codes->code) {
665  log_warn("%s: %s: Invalid code : %s",
666  path, rem->name, codes->name);
667  codes->code &= gen_mask(rem->bits);
668  }
669  for (node = codes->next; node != NULL; node = node->next) {
670  if ((node->code & gen_mask(rem->bits)) != node->code) {
671  log_warn("%s: %s: Invalid code %s: %s",
672  path, rem->name, codes->name);
673  node->code &= gen_mask(rem->bits);
674  }
675  }
676  }
677  return 1;
678 }
679 
686 static int remote_bits_cmp(struct ir_remote* r1, struct ir_remote* r2)
687 {
688  int r1_size;
689  int r2_size;
690  struct ir_ncode* c;
691 
692  int r1_is_raw = is_raw(r1);
693  int r2_is_raw = is_raw(r2);
694 
695  if (!r1_is_raw && r2_is_raw)
696  return -1;
697  if (r1_is_raw && !r2_is_raw)
698  return 1;
699 
700  if (r1_is_raw && r2_is_raw) {
701  for (c = r1->codes, r1_size = 0; c->name != NULL; c++)
702  r1_size += 1;
703  for (c = r2->codes, r2_size = 0; c->name != NULL; c++)
704  r2_size += 1;
705  } else {
706  r1_size = bit_count(r1);
707  r2_size = bit_count(r2);
708  }
709  if (r1_size == r2_size)
710  return 0;
711  return r1_size < r2_size ? -1 : 1;
712 }
713 
714 
719 static struct ir_remote* sort_by_bit_count(struct ir_remote* remotes)
720 {
721  struct ir_remote* top;
722  struct ir_remote* rem;
723  struct ir_remote* next;
724  struct ir_remote* prev;
725  struct ir_remote* scan;
726  struct ir_remote* r;
727 
728  for (r = remotes; r != NULL && r != (void*)-1; r = r->next)
729  if (r->manual_sort)
730  return remotes;
731  rem = remotes;
732  top = NULL;
733  while (rem != NULL && rem != (void*)-1) {
734  next = rem->next;
735 
736  scan = top;
737  prev = NULL;
738  while (scan && remote_bits_cmp(scan, rem) <= 0) {
739  prev = scan;
740  scan = scan->next;
741  }
742  if (prev)
743  prev->next = rem;
744  else
745  top = rem;
746  if (scan)
747  rem->next = scan;
748  else
749  rem->next = NULL;
750 
751  rem = next;
752  }
753 
754  return top;
755 }
756 
757 static const char* lirc_parse_include(char* s)
758 {
759  char* last;
760  size_t len;
761 
762  len = strlen(s);
763  if (len < 2)
764  return NULL;
765  last = s + len - 1;
766  while (last > s && strchr(whitespace, *last) != NULL)
767  last--;
768  if (last <= s)
769  return NULL;
770  if (*s != '"' && *s != '<')
771  return NULL;
772  if (*s == '"' && *last != '"')
773  return NULL;
774  else if (*s == '<' && *last != '>')
775  return NULL;
776  *last = 0;
777  memmove(s, s + 1, len - 2 + 1); /* terminating 0 is copied, and
778  * maybe more, but we don't care */
779  return s;
780 }
781 
782 
784 static const char* lirc_parse_relative(char* dst,
785  size_t dst_size,
786  const char* child,
787  const char* current)
788 {
789  char* dir;
790  size_t dirlen;
791 
792  if (!current)
793  return child;
794 
795  /* Already an absolute path */
796  if (*child == '/') {
797  snprintf(dst, dst_size, "%s", child);
798  return dst;
799  }
800  if (strlen(current) >= dst_size)
801  return NULL;
802  strcpy(dst, current);
803  dir = dirname(dst);
804  dirlen = strlen(dir);
805  if (dir != dst)
806  memmove(dst, dir, dirlen + 1);
807 
808  if (dirlen + 1 + strlen(child) + 1 > dst_size)
809  return NULL;
810  strcat(dst, "/");
811  strcat(dst, child);
812 
813  return dst;
814 }
815 
816 
818 static struct ir_remote*
819 ir_remotes_append(struct ir_remote* root, struct ir_remote* what)
820 {
821  struct ir_remote* r;
822 
823  if (root == (struct ir_remote*)-1)
824  root = NULL;
825  if (what == (struct ir_remote*)-1)
826  what = NULL;
827  if (root == NULL && what != NULL)
828  return what;
829  if (what == NULL)
830  return root;
831  for (r = root; r->next != NULL; r = r->next)
832  ;
833  r->next = what;
834  return root;
835 }
836 
837 
838 struct ir_remote* read_config(FILE* f, const char* name)
839 {
840  struct ir_remote* head;
841 
842  head = read_config_recursive(f, name, 0);
843  head = sort_by_bit_count(head);
844  return head;
845 }
846 
847 
858 static struct ir_remote*
859 read_included(const char* name, int depth, char* val, struct ir_remote* top_rem)
860 {
861  FILE* childFile;
862  const char* childName;
863  struct ir_remote* rem = NULL;
864 
865  if (depth > MAX_INCLUDES) {
866  log_error("error opening child file defined at %s:%d", name, line);
867  log_error("too many files included");
868  return top_rem;
869  }
870  childName = lirc_parse_include(val);
871  if (!childName) {
872  log_error("error parsing child file value defined at line %d:", line);
873  log_error("invalid quoting");
874  return top_rem;
875  }
876  childFile = fopen(childName, "r");
877  if (childFile == NULL) {
878  log_error("error opening child file '%s' defined at line %d:",
879  childName, line);
880  log_error("ignoring this child file for now.");
881  return NULL;
882  }
883  rem = read_config_recursive(childFile, childName, depth + 1);
884  top_rem = ir_remotes_append(top_rem, rem);
885  fclose(childFile);
886  return top_rem;
887 }
888 
889 
900 static struct ir_remote* read_all_included(const char* name,
901  int depth,
902  char* val,
903  struct ir_remote* top_rem)
904 {
905  int i;
906  glob_t globbuf;
907  char buff[256] = { '\0' };
908 
909  memset(&globbuf, 0, sizeof(globbuf));
910  val = val + 1; // Strip quotes
911  val[strlen(val) - 1] = '\0';
912  lirc_parse_relative(buff, sizeof(buff), val, name);
913  glob(buff, 0, NULL, &globbuf);
914  for (i = 0; i < globbuf.gl_pathc; i += 1) {
915  snprintf(buff, sizeof(buff), "\"%s\"", globbuf.gl_pathv[i]);
916  top_rem = read_included(name, depth, buff, top_rem);
917  }
918  globfree(&globbuf);
919  return top_rem;
920 }
921 
922 
923 static void check_ncode_dups(const char* path,
924  const char* name,
925  struct void_array* ar,
926  struct ir_ncode* code)
927 {
928  if (foreach_void_array(ar, array_guest_ncode_cmp, code) != NULL) {
929  log_notice("%s: %s: Multiple definitions of: %s",
930  path, name, code->name);
931  }
932  if (foreach_void_array(ar, array_guest_code_equals, code) != NULL) {
933  log_notice("%s: %s: Multiple values for same code: %s",
934  path, name, code->name);
935  }
936 }
937 
938 
939 static struct ir_remote*
940 read_config_recursive(FILE* f, const char* name, int depth)
941 {
942  char buf[LINE_LEN + 1];
943  char* key;
944  char* val;
945  char* val2;
946  int len, argc;
947  struct ir_remote* top_rem = NULL;
948  struct ir_remote* rem = NULL;
949  struct void_array codes_list, raw_codes, signals;
950  struct ir_ncode raw_code = { NULL, 0, 0, NULL };
951  struct ir_ncode name_code = { NULL, 0, 0, NULL };
952  struct ir_ncode* code;
953  int mode = ID_none;
954 
955  line = 0;
956  parse_error = 0;
957  log_trace1("parsing '%s'", name);
958 
959  while (fgets(buf, LINE_LEN, f) != NULL) {
960  line++;
961  len = strlen(buf);
962  if (len == LINE_LEN && buf[len - 1] != '\n') {
963  log_error("line %d too long in config file", line);
964  parse_error = 1;
965  break;
966  }
967 
968  if (len > 0) {
969  len--;
970  if (buf[len] == '\n')
971  buf[len] = 0;
972  }
973  if (len > 0) {
974  len--;
975  if (buf[len] == '\r')
976  buf[len] = 0;
977  }
978  /* ignore comments */
979  if (buf[0] == '#')
980  continue;
981  key = strtok(buf, whitespace);
982  /* ignore empty lines */
983  if (key == NULL)
984  continue;
985  val = strtok(NULL, whitespace);
986  if (val != NULL) {
987  val2 = strtok(NULL, whitespace);
988  log_trace2("Tokens: \"%s\" \"%s\" \"%s\"", key, val, (val2 == NULL ? "(null)" : val));
989  if (strcasecmp("include", key) == 0) {
990  int save_line = line;
991 
992  top_rem = read_all_included(name,
993  depth,
994  val,
995  top_rem);
996  line = save_line;
997  } else if (strcasecmp("begin", key) == 0) {
998  if (strcasecmp("codes", val) == 0) {
999  /* init codes mode */
1000  log_trace1(" begin codes");
1001  if (!checkMode(mode, ID_remote, "begin codes"))
1002  break;
1003  if (rem->codes) {
1004  log_error("error in configfile line %d:", line);
1005  log_error("codes are already defined");
1006  parse_error = 1;
1007  break;
1008  }
1009 
1010  init_void_array(&codes_list, 30, sizeof(struct ir_ncode));
1011  mode = ID_codes;
1012  } else if (strcasecmp("raw_codes", val) == 0) {
1013  /* init raw_codes mode */
1014  log_trace1(" begin raw_codes");
1015  if (!checkMode(mode, ID_remote, "begin raw_codes"))
1016  break;
1017  if (rem->codes) {
1018  log_error("error in configfile line %d:", line);
1019  log_error("codes are already defined");
1020  parse_error = 1;
1021  break;
1022  }
1023  set_protocol(rem, RAW_CODES);
1024  raw_code.code = 0;
1025  init_void_array(&raw_codes, 30, sizeof(struct ir_ncode));
1026  mode = ID_raw_codes;
1027  } else if (strcasecmp("remote", val) == 0) {
1028  /* create new remote */
1029  log_trace("parsing remote");
1030  if (!checkMode(mode, ID_none, "begin remote"))
1031  break;
1032  mode = ID_remote;
1033  if (!top_rem) {
1034  /* create first remote */
1035  log_trace1("creating first remote");
1036  rem = top_rem = s_malloc(sizeof(struct ir_remote));
1037  rem->freq = DEFAULT_FREQ;
1038  } else {
1039  /* create new remote */
1040  log_trace1("creating next remote");
1041  rem = s_malloc(sizeof(struct ir_remote));
1042  rem->freq = DEFAULT_FREQ;
1043  ir_remotes_append(top_rem, rem);
1044  }
1045  } else if (mode == ID_codes) {
1046  code = defineCode(key, val, &name_code);
1047  while (!parse_error && val2 != NULL) {
1048  if (val2[0] == '#')
1049  break; /* comment */
1050  defineNode(code, val2);
1051  val2 = strtok(NULL, whitespace);
1052  }
1053  code->current = NULL;
1054  check_ncode_dups(name, rem->name, &codes_list, code);
1055  add_void_array(&codes_list, code);
1056  } else {
1057  log_error("error in configfile line %d:", line);
1058  log_error("unknown section \"%s\"", val);
1059  parse_error = 1;
1060  }
1061  if (!parse_error && val2 != NULL) {
1062  log_warn("%s: garbage after '%s' token "
1063  "in line %d ignored",
1064  rem->name, val, line);
1065  }
1066  } else if (strcasecmp("end", key) == 0) {
1067  if (strcasecmp("codes", val) == 0) {
1068  /* end Codes mode */
1069  log_trace1(" end codes");
1070  if (!checkMode(mode, ID_codes, "end codes"))
1071  break;
1072  rem->codes = get_void_array(&codes_list);
1073  mode = ID_remote; /* switch back */
1074  } else if (strcasecmp("raw_codes", val) == 0) {
1075  /* end raw codes mode */
1076  log_trace1(" end raw_codes");
1077 
1078  if (mode == ID_raw_name) {
1079  raw_code.signals = get_void_array(&signals);
1080  raw_code.length = signals.nr_items;
1081  if (raw_code.length % 2 == 0) {
1082  log_error("error in configfile line %d:", line);
1083  log_error("bad signal length");
1084  parse_error = 1;
1085  }
1086  if (!add_void_array(&raw_codes, &raw_code))
1087  break;
1088  mode = ID_raw_codes;
1089  }
1090  if (!checkMode(mode, ID_raw_codes, "end raw_codes"))
1091  break;
1092  rem->codes = get_void_array(&raw_codes);
1093  mode = ID_remote; /* switch back */
1094  } else if (strcasecmp("remote", val) == 0) {
1095  /* end remote mode */
1096  log_trace1("end remote");
1097  /* print_remote(rem); */
1098  if (!checkMode(mode, ID_remote, "end remote"))
1099  break;
1100  if (!sanityChecks(rem, name)) {
1101  parse_error = 1;
1102  break;
1103  }
1104  if (options_getboolean("lircd:dynamic-codes")) {
1105  if (rem->dyncodes_name == NULL)
1106  rem->dyncodes_name = s_strdup("unknown");
1107  rem->dyncodes[0].name = rem->dyncodes_name;
1108  rem->dyncodes[1].name = rem->dyncodes_name;
1109  }
1110  /* not really necessary because we
1111  * clear the alloced memory */
1112  rem->next = NULL;
1113  rem->last_code = NULL;
1114  mode = ID_none; /* switch back */
1115  } else if (mode == ID_codes) {
1116  code = defineCode(key, val, &name_code);
1117  while (!parse_error && val2 != NULL) {
1118  if (val2[0] == '#')
1119  break; /* comment */
1120  defineNode(code, val2);
1121  val2 = strtok(NULL, whitespace);
1122  }
1123  code->current = NULL;
1124  add_void_array(&codes_list, code);
1125  } else {
1126  log_error("error in configfile line %d:", line);
1127  log_error("unknown section %s", val);
1128  parse_error = 1;
1129  }
1130  if (!parse_error && val2 != NULL) {
1131  log_warn(
1132  "%s: garbage after '%s'"
1133  " token in line %d ignored",
1134  rem->name, val, line);
1135  }
1136  } else {
1137  switch (mode) {
1138  case ID_remote:
1139  argc = defineRemote(key, val, val2, rem);
1140  if (!parse_error
1141  && ((argc == 1 && val2 != NULL)
1142  || (argc == 2 && val2 != NULL && strtok(NULL, whitespace) != NULL))) {
1143  log_warn("%s: garbage after '%s'"
1144  " token in line %d ignored",
1145  rem->name, key, line);
1146  }
1147  break;
1148  case ID_codes:
1149  code = defineCode(key, val, &name_code);
1150  while (!parse_error && val2 != NULL) {
1151  if (val2[0] == '#')
1152  break; /* comment */
1153  defineNode(code, val2);
1154  val2 = strtok(NULL, whitespace);
1155  }
1156  code->current = NULL;
1157  check_ncode_dups(name,
1158  rem->name,
1159  &codes_list,
1160  code);
1161  add_void_array(&codes_list, code);
1162  break;
1163  case ID_raw_codes:
1164  case ID_raw_name:
1165  if (strcasecmp("name", key) == 0) {
1166  log_trace2("Button: \"%s\"", val);
1167  if (mode == ID_raw_name) {
1168  raw_code.signals = get_void_array(&signals);
1169  raw_code.length = signals.nr_items;
1170  if (raw_code.length % 2 == 0) {
1171  log_error("error in configfile line %d:",
1172  line);
1173  log_error("bad signal length");
1174  parse_error = 1;
1175  }
1176  if (!add_void_array(&raw_codes, &raw_code))
1177  break;
1178  }
1179  raw_code.name = s_strdup(val);
1180  if (!raw_code.name)
1181  break;
1182  raw_code.code++;
1183  init_void_array(&signals, 50, sizeof(lirc_t));
1184  mode = ID_raw_name;
1185  if (!parse_error && val2 != NULL) {
1186  log_warn("%s: garbage after '%s'"
1187  " token in line %d ignored",
1188  rem->name, key, line);
1189  }
1190  } else {
1191  if (mode == ID_raw_codes) {
1192  log_error("no name for signal defined at line %d",
1193  line);
1194  parse_error = 1;
1195  break;
1196  }
1197  if (!addSignal(&signals, key))
1198  break;
1199  if (!addSignal(&signals, val))
1200  break;
1201  if (val2)
1202  if (!addSignal(&signals, val2))
1203  break;
1204  while ((val = strtok(NULL, whitespace)))
1205  if (!addSignal(&signals, val))
1206  break;
1207  }
1208  break;
1209  }
1210  }
1211  } else if (mode == ID_raw_name) {
1212  if (!addSignal(&signals, key))
1213  break;
1214  } else {
1215  log_error("error in configfile line %d", line);
1216  parse_error = 1;
1217  break;
1218  }
1219  if (parse_error)
1220  break;
1221  }
1222  if (mode != ID_none) {
1223  switch (mode) {
1224  case ID_raw_name:
1225  if (raw_code.name != NULL) {
1226  free(raw_code.name);
1227  if (get_void_array(&signals) != NULL)
1228  free(get_void_array(&signals));
1229  }
1230  case ID_raw_codes:
1231  rem->codes = get_void_array(&raw_codes);
1232  break;
1233  case ID_codes:
1234  rem->codes = get_void_array(&codes_list);
1235  break;
1236  }
1237  if (!parse_error) {
1238  log_error("unexpected end of file");
1239  parse_error = 1;
1240  }
1241  }
1242  if (parse_error) {
1243  static int print_error = 1;
1244 
1245  if (print_error) {
1246  log_error("reading of file '%s' failed", name);
1247  print_error = 0;
1248  }
1249  free_config(top_rem);
1250  if (depth == 0)
1251  print_error = 1;
1252  return (void*)-1;
1253  }
1254  /* kick reverse flag */
1255  /* handle RC6 flag to be backwards compatible: previous RC-6
1256  * config files did not set rc6_mask */
1257  rem = top_rem;
1258  while (rem != NULL) {
1259  if ((!is_raw(rem)) && rem->flags & REVERSE) {
1260  struct ir_ncode* codes;
1261 
1262  if (has_pre(rem))
1263  rem->pre_data = reverse(rem->pre_data, rem->pre_data_bits);
1264  if (has_post(rem))
1265  rem->post_data = reverse(rem->post_data, rem->post_data_bits);
1266  codes = rem->codes;
1267  while (codes->name != NULL) {
1268  codes->code = reverse(codes->code, rem->bits);
1269  codes++;
1270  }
1271  rem->flags = rem->flags & (~REVERSE);
1272  rem->flags = rem->flags | COMPAT_REVERSE;
1273  /* don't delete the flag because we still need
1274  * it to remain compatible with older versions
1275  */
1276  }
1277  if (rem->flags & RC6 && rem->rc6_mask == 0 && rem->toggle_bit > 0) {
1278  int all_bits = bit_count(rem);
1279 
1280  rem->rc6_mask = ((ir_code)1) << (all_bits - rem->toggle_bit);
1281  }
1282  if (rem->toggle_bit > 0) {
1283  int all_bits = bit_count(rem);
1284 
1285  if (has_toggle_bit_mask(rem)) {
1286  log_warn("%s uses both toggle_bit and toggle_bit_mask", rem->name);
1287  } else {
1288  rem->toggle_bit_mask = ((ir_code)1) << (all_bits - rem->toggle_bit);
1289  }
1290  rem->toggle_bit = 0;
1291  }
1292  if (has_toggle_bit_mask(rem)) {
1293  if (!is_raw(rem) && rem->codes) {
1294  rem->toggle_bit_mask_state = (rem->codes->code & rem->toggle_bit_mask);
1295  if (rem->toggle_bit_mask_state)
1296  /* start with state set to 0 for backwards compatibility */
1297  rem->toggle_bit_mask_state ^= rem->toggle_bit_mask;
1298  }
1299  }
1300  if (is_serial(rem)) {
1301  lirc_t base;
1302 
1303  if (rem->baud > 0) {
1304  base = 1000000 / rem->baud;
1305  if (rem->pzero == 0 && rem->szero == 0)
1306  rem->pzero = base;
1307  if (rem->pone == 0 && rem->sone == 0)
1308  rem->sone = base;
1309  }
1310  if (rem->bits_in_byte == 0)
1311  rem->bits_in_byte = 8;
1312  }
1313  if (rem->min_code_repeat > 0) {
1314  if (!has_repeat(rem) || rem->min_code_repeat > rem->min_repeat) {
1315  log_warn("invalid min_code_repeat value");
1316  rem->min_code_repeat = 0;
1317  }
1318  }
1319  calculate_signal_lengths(rem);
1320  rem = rem->next;
1321  }
1322 
1323  return top_rem;
1324 }
1325 
1326 void calculate_signal_lengths(struct ir_remote* remote)
1327 {
1328  if (is_const(remote)) {
1329  remote->min_total_signal_length = min_gap(remote);
1330  remote->max_total_signal_length = max_gap(remote);
1331  } else {
1332  remote->min_gap_length = min_gap(remote);
1333  remote->max_gap_length = max_gap(remote);
1334  }
1335 
1336  lirc_t min_signal_length = 0, max_signal_length = 0;
1337  lirc_t max_pulse = 0, max_space = 0;
1338  int first_sum = 1;
1339  struct ir_ncode* c = remote->codes;
1340  int i;
1341 
1342  while (c->name) {
1343  struct ir_ncode code = *c;
1344  struct ir_code_node* next = code.next;
1345  int first = 1;
1346  int repeat = 0;
1347 
1348  do {
1349  if (first) {
1350  first = 0;
1351  } else {
1352  code.code = next->code;
1353  next = next->next;
1354  }
1355  for (repeat = 0; repeat < 2; repeat++) {
1356  if (init_sim(remote, &code, repeat)) {
1357  lirc_t sum = send_buffer_sum();
1358 
1359  if (sum) {
1360  if (first_sum || sum < min_signal_length)
1361  min_signal_length = sum;
1362  if (first_sum || sum > max_signal_length)
1363  max_signal_length = sum;
1364  first_sum = 0;
1365  }
1366  for (i = 0; i < send_buffer_length(); i++) {
1367  if (i & 1) { /* space */
1368  if (send_buffer_data()[i] > max_space)
1369  max_space = send_buffer_data()[i];
1370  } else { /* pulse */
1371  if (send_buffer_data()[i] > max_pulse)
1372  max_pulse = send_buffer_data()[i];
1373  }
1374  }
1375  }
1376  }
1377  } while (next);
1378  c++;
1379  }
1380  if (first_sum) {
1381  /* no timing data, so assume gap is the actual total
1382  * length */
1383  remote->min_total_signal_length = min_gap(remote);
1384  remote->max_total_signal_length = max_gap(remote);
1385  remote->min_gap_length = min_gap(remote);
1386  remote->max_gap_length = max_gap(remote);
1387  } else if (is_const(remote)) {
1388  if (remote->min_total_signal_length > max_signal_length) {
1389  remote->min_gap_length = remote->min_total_signal_length - max_signal_length;
1390  } else {
1391  log_warn("min_gap_length is 0 for '%s' remote",
1392  remote->name);
1393  remote->min_gap_length = 0;
1394  }
1395  if (remote->max_total_signal_length > min_signal_length) {
1396  remote->max_gap_length = remote->max_total_signal_length - min_signal_length;
1397  } else {
1398  log_warn("max_gap_length is 0 for '%s' remote", remote->name);
1399  remote->max_gap_length = 0;
1400  }
1401  } else {
1402  remote->min_total_signal_length = min_signal_length + remote->min_gap_length;
1403  remote->max_total_signal_length = max_signal_length + remote->max_gap_length;
1404  }
1405  log_trace("lengths: %lu %lu %lu %lu", remote->min_total_signal_length, remote->max_total_signal_length,
1406  remote->min_gap_length, remote->max_gap_length);
1407 }
1408 
1409 void free_config(struct ir_remote* remotes)
1410 {
1411  struct ir_remote* next;
1412  struct ir_ncode* codes;
1413 
1414  while (remotes != NULL) {
1415  next = remotes->next;
1416 
1417  if (remotes->dyncodes_name != NULL)
1418  free(remotes->dyncodes_name);
1419  if (remotes->name != NULL)
1420  free((void*)(remotes->name));
1421  if (remotes->codes != NULL) {
1422  codes = remotes->codes;
1423  while (codes->name != NULL) {
1424  struct ir_code_node* node;
1425  struct ir_code_node* next_node;
1426 
1427  free(codes->name);
1428  if (codes->signals != NULL)
1429  free(codes->signals);
1430  node = codes->next;
1431  while (node) {
1432  next_node = node->next;
1433  free(node);
1434  node = next_node;
1435  }
1436  codes++;
1437  }
1438  free(remotes->codes);
1439  }
1440  free(remotes);
1441  remotes = next;
1442  }
1443 }
ir_code_node
An ir_code for entering into (singly) linked lists, i.e.
Definition: ir_remote_types.h:53
log_error
#define log_error(fmt,...)
Log an error message.
Definition: lirc_log.h:104
ir_remote::repeat_mask
ir_code repeat_mask
mask defines which bits are inverted for repeats
Definition: ir_remote_types.h:222
log_trace2
#define log_trace2(fmt,...)
Log a trace2 message.
Definition: lirc_log.h:139
read_config
struct ir_remote * read_config(FILE *f, const char *name)
Parse a lircd.conf config file.
Definition: config_file.c:838
ir_remote::post_data
ir_code post_data
data which the remote sends after actual keycode
Definition: ir_remote_types.h:187
all_flags
const struct flaglist all_flags[]
All flags i config file: Their name and mask.
Definition: config_file.c:99
send_buffer_sum
lirc_t send_buffer_sum(void)
Definition: transmit.c:384
NO_FOOT_REP
#define NO_FOOT_REP
no foot for key repeats
Definition: ir_remote_types.h:124
ir_remote::post_s
lirc_t post_s
signal between keycode and post_code
Definition: ir_remote_types.h:189
ir_remote::toggle_bit_mask
ir_code toggle_bit_mask
previously only one bit called toggle_bit
Definition: ir_remote_types.h:195
ir_remote::baud
unsigned int baud
can be overridden by [p|s]zero, [p|s]one
Definition: ir_remote_types.h:214
RC5
#define RC5
IR data follows RC5 protocol.
Definition: ir_remote_types.h:105
ir_remote::ignore_mask
ir_code ignore_mask
mask defines which bits can be ignored when matching a code
Definition: ir_remote_types.h:221
send_buffer_length
int send_buffer_length(void)
Do not document this function.
Definition: transmit.c:373
ir_remote::min_gap_length
lirc_t min_gap_length
how long is the shortest gap
Definition: ir_remote_types.h:237
free_config
void free_config(struct ir_remote *remotes)
Free() an ir_remote instance obtained using read_config().
Definition: config_file.c:1409
RAW_CODES
#define RAW_CODES
for internal use only
Definition: ir_remote_types.h:104
add_void_array
int add_void_array(struct void_array *ar, void *dataptr)
Add *dataptr to end of ar, re-allocating as necessary.
Definition: config_file.c:124
ir_remote::max_gap_length
lirc_t max_gap_length
how long is the longest gap
Definition: ir_remote_types.h:238
ir_ncode
IR Command, corresponding to one (command defining) line of the configuration file.
Definition: ir_remote_types.h:64
log_trace1
#define log_trace1(fmt,...)
Log a trace1 message.
Definition: lirc_log.h:134
flaglist::name
char * name
Name of flag.
Definition: config_flags.h:17
log_warn
#define log_warn(fmt,...)
Log a warning message.
Definition: lirc_log.h:109
ir_remote::toggle_mask
ir_code toggle_mask
Sharp (?) error detection scheme.
Definition: ir_remote_types.h:210
ir_remote::manual_sort
int manual_sort
If set in any remote, disables automatic sorting.
Definition: ir_remote_types.h:242
ir_remote::pre_data_bits
int pre_data_bits
length of pre_data
Definition: ir_remote_types.h:184
CONST_LENGTH
#define CONST_LENGTH
signal length+gap is always constant
Definition: ir_remote_types.h:125
ir_code
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
Definition: ir_remote_types.h:47
ir_remote::max_total_signal_length
lirc_t max_total_signal_length
how long is the longest signal including gap
Definition: ir_remote_types.h:236
get_void_array
void * get_void_array(struct void_array *ar)
Return the array dataptr, an array[nr_items] of item_size elements.
Definition: config_file.c:149
GRUNDIG
#define GRUNDIG
encoding found on Grundig remote
Definition: ir_remote_types.h:116
ir_remote::eps
int eps
eps (relative tolerance)
Definition: ir_remote_types.h:161
ir_remote::post_data_bits
int post_data_bits
length of post_data
Definition: ir_remote_types.h:186
RC6
#define RC6
IR data follows RC6 protocol.
Definition: ir_remote_types.h:111
ir_remote::name
const char * name
name of remote control
Definition: ir_remote_types.h:156
array_guest_func
void *(* array_guest_func)(void *item, void *arg)
foreach_void_array argument.
Definition: config_file.c:71
ir_remote::last_code
struct ir_ncode * last_code
code received or sent last
Definition: ir_remote_types.h:228
ir_remote::repeat_gap
uint32_t repeat_gap
time between two repeat codes if different from gap
Definition: ir_remote_types.h:193
flaglist
Description of flag to print.
Definition: config_flags.h:16
ir_remote::pre_data
ir_code pre_data
data which the remote sends before actual keycode
Definition: ir_remote_types.h:185
ir_remote::parity
unsigned int parity
currently unsupported
Definition: ir_remote_types.h:216
NO_HEAD_REP
#define NO_HEAD_REP
no header for key repeats
Definition: ir_remote_types.h:123
ir_remote::dyncodes_name
char * dyncodes_name
name for unknown buttons
Definition: ir_remote_types.h:168
ir_ncode::code
ir_code code
The first code of the command.
Definition: ir_remote_types.h:69
ir_remote::sfoot
lirc_t sfoot
foot
Definition: ir_remote_types.h:181
ir_remote::sone
lirc_t sone
1
Definition: ir_remote_types.h:177
RCMM
#define RCMM
IR data follows RC-MM protocol.
Definition: ir_remote_types.h:112
ir_remote::ptrail
lirc_t ptrail
trailing pulse
Definition: ir_remote_types.h:180
BO
#define BO
encoding found on Bang & Olufsen remote
Definition: ir_remote_types.h:117
ir_remote::gap2
uint32_t gap2
time between signals in usecs
Definition: ir_remote_types.h:192
SERIAL
#define SERIAL
serial protocol
Definition: ir_remote_types.h:118
ir_remote
One remote as represented in the configuration file.
Definition: ir_remote_types.h:155
log_info
#define log_info(fmt,...)
Log an info message.
Definition: lirc_log.h:114
ir_remote::pre_s
lirc_t pre_s
signal between pre_data and keycode
Definition: ir_remote_types.h:188
ir_remote::duty_cycle
unsigned int duty_cycle
0<duty cycle<=100 default: 50
Definition: ir_remote_types.h:209
ir_remote::sthree
lirc_t sthree
3 (only used for RC-MM)
Definition: ir_remote_types.h:175
ir_ncode::length
int length
(private)
Definition: ir_remote_types.h:72
REPEAT_HEADER
#define REPEAT_HEADER
header is also sent before repeat code
Definition: ir_remote_types.h:126
ir_remote::srepeat
lirc_t srepeat
indicate repeating
Definition: ir_remote_types.h:182
SPACE_ENC
#define SPACE_ENC
IR data is space encoded.
Definition: ir_remote_types.h:113
SPACE_FIRST
#define SPACE_FIRST
bits are encoded as space+pulse
Definition: ir_remote_types.h:114
flaglist::flag
int flag
Flag bitmask.
Definition: config_flags.h:18
ir_remote::gap
uint32_t gap
time between signals in usecs
Definition: ir_remote_types.h:191
ir_ncode::signals
lirc_t * signals
(private)
Definition: ir_remote_types.h:75
ir_remote::shead
lirc_t shead
header
Definition: ir_remote_types.h:174
ir_remote::stwo
lirc_t stwo
2 (only used for RC-MM)
Definition: ir_remote_types.h:176
ir_ncode::next
struct ir_code_node * next
Linked list of the subsequent ir_code's, after the first one.
Definition: ir_remote_types.h:79
ir_remote::szero
lirc_t szero
0
Definition: ir_remote_types.h:178
ir_remote::min_code_repeat
unsigned int min_code_repeat
meaningful only if remote sends a repeat code: in this case this value indicates how often the real c...
Definition: ir_remote_types.h:207
ir_remote::rc6_mask
ir_code rc6_mask
RC-6 doubles signal length of some bits.
Definition: ir_remote_types.h:211
log_notice
#define log_notice(fmt,...)
Log a notice message.
Definition: lirc_log.h:119
ir_remote::aeps
unsigned int aeps
detecting very short pulses is difficult with relative tolerance for some remotes,...
Definition: ir_remote_types.h:162
ir_remote::driver
const char * driver
Name of driver for LIRCCODE cases.
Definition: ir_remote_types.h:157
ir_remote::min_repeat
int min_repeat
code is repeated at least x times code sent once -> min_repeat=0
Definition: ir_remote_types.h:199
ir_remote::stop_bits
unsigned int stop_bits
mapping: 1->2 1.5->3 2->4
Definition: ir_remote_types.h:217
ir_remote::suppress_repeat
int suppress_repeat
suppress unwanted repeats
Definition: ir_remote_types.h:196
XMP
#define XMP
XMP protocol.
Definition: ir_remote_types.h:119
ir_remote::flags
int flags
flags
Definition: ir_remote_types.h:160
SHIFT_ENC
#define SHIFT_ENC
IR data is shift encoded (name obsolete)
Definition: ir_remote_types.h:106
ir_remote::toggle_bit
int toggle_bit
obsolete
Definition: ir_remote_types.h:194
ir_remote::dyncodes
struct ir_ncode dyncodes[2]
helper structs for unknown buttons
Definition: ir_remote_types.h:170
ir_remote::min_total_signal_length
lirc_t min_total_signal_length
how long is the shortest signal including gap
Definition: ir_remote_types.h:235
ir_remote::bits
int bits
bits (length of code)
Definition: ir_remote_types.h:159
log_trace
#define log_trace(fmt,...)
Log a trace message.
Definition: lirc_log.h:129
ir_ncode::name
char * name
Name of command.
Definition: ir_remote_types.h:66
ir_remote::freq
unsigned int freq
modulation frequency
Definition: ir_remote_types.h:208
ir_remote::bits_in_byte
unsigned int bits_in_byte
default: 8
Definition: ir_remote_types.h:215
logchannel_t
logchannel_t
Log channels used to filter messages.
Definition: lirc_log.h:53
send_buffer_data
const lirc_t * send_buffer_data(void)
Definition: transmit.c:379
COMPAT_REVERSE
#define COMPAT_REVERSE
compatibility mode for REVERSE flag
Definition: ir_remote_types.h:128
GOLDSTAR
#define GOLDSTAR
encoding found on Goldstar remote
Definition: ir_remote_types.h:115
ir_remote::plead
lirc_t plead
leading pulse
Definition: ir_remote_types.h:179