LIRC libraries
LinuxInfraredRemoteControl
 All Classes Files Functions Variables Typedefs Enumerations Macros Modules Pages
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 }
One remote as represented in the configuration file.
int bits
bits (length of code)
const lirc_t * send_buffer_data(void)
Definition: transmit.c:379
lirc_t min_total_signal_length
how long is the shortest signal including gap
#define NO_FOOT_REP
no foot for key repeats
#define RC6
IR data follows RC6 protocol.
An ir_code for entering into (singly) linked lists, i.e.
unsigned int freq
modulation frequency
lirc_t max_gap_length
how long is the longest gap
#define GOLDSTAR
encoding found on Goldstar remote
lirc_t max_total_signal_length
how long is the longest signal including gap
ir_code post_data
data which the remote sends after actual keycode
lirc_t post_s
signal between keycode and post_code
lirc_t plead
leading pulse
ir_code repeat_mask
mask defines which bits are inverted for repeats
struct ir_code_node * next
Linked list of the subsequent ir_code's, after the first one.
unsigned int baud
can be overridden by [p|s]zero, [p|s]one
const char * name
name of remote control
#define SPACE_ENC
IR data is space encoded.
void free_config(struct ir_remote *remotes)
Free() an ir_remote instance obtained using read_config().
Definition: config_file.c:1409
lirc_t * signals
(private)
#define COMPAT_REVERSE
compatibility mode for REVERSE flag
int eps
eps (relative tolerance)
struct ir_ncode * last_code
code received or sent last
unsigned int parity
currently unsupported
#define log_warn(fmt,...)
Log a warning message.
Definition: lirc_log.h:109
lirc_t sfoot
foot
lirc_t ptrail
trailing pulse
int pre_data_bits
length of pre_data
lirc_t min_gap_length
how long is the shortest gap
int manual_sort
If set in any remote, disables automatic sorting.
logchannel_t
Log channels used to filter messages.
Definition: lirc_log.h:53
Description of flag to print.
Definition: config_flags.h:16
char * name
Name of command.
#define log_trace2(fmt,...)
Log a trace2 message.
Definition: lirc_log.h:139
struct ir_code_node * current
Should point at the ir_code currently being transmitted, or NULL if none.
unsigned int duty_cycle
int post_data_bits
length of post_data
lirc_t sthree
3 (only used for RC-MM)
#define RCMM
IR data follows RC-MM protocol.
ir_code toggle_mask
Sharp (?) error detection scheme.
#define log_trace1(fmt,...)
Log a trace1 message.
Definition: lirc_log.h:134
#define log_error(fmt,...)
Log an error message.
Definition: lirc_log.h:104
ir_code pre_data
data which the remote sends before actual keycode
lirc_t send_buffer_sum(void)
Definition: transmit.c:384
uint32_t gap
time between signals in usecs
#define log_trace(fmt,...)
Log a trace message.
Definition: lirc_log.h:129
lirc_t sone
1
#define RC5
IR data follows RC5 protocol.
char * dyncodes_name
name for unknown buttons
uint32_t repeat_gap
time between two repeat codes if different from gap
lirc_t shead
header
#define REPEAT_HEADER
header is also sent before repeat code
#define SPACE_FIRST
bits are encoded as space+pulse
#define CONST_LENGTH
signal length+gap is always constant
uint32_t gap2
time between signals in usecs
#define NO_HEAD_REP
no header for key repeats
unsigned int stop_bits
mapping: 1->2 1.5->3 2->4
lirc_t pre_s
signal between pre_data and keycode
#define GRUNDIG
encoding found on Grundig remote
lirc_t szero
0
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
void *(* array_guest_func)(void *item, void *arg)
foreach_void_array argument.
Definition: config_file.c:71
IR Command, corresponding to one (command defining) line of the configuration file.
lirc_t stwo
2 (only used for RC-MM)
int flags
flags
unsigned int aeps
detecting very short pulses is difficult with relative tolerance for some remotes, this is an absolute tolerance to solve this problem usually you can say 0 here.
lirc_t srepeat
indicate repeating
#define SERIAL
serial protocol
#define SHIFT_ENC
IR data is shift encoded (name obsolete)
#define BO
encoding found on Bang & Olufsen remote
int suppress_repeat
suppress unwanted repeats
ir_code code
The first code of the command.
int toggle_bit
obsolete
const char * driver
Name of driver for LIRCCODE cases.
unsigned int min_code_repeat
meaningful only if remote sends a repeat code: in this case this value indicates how often the real c...
const struct flaglist all_flags[]
All flags i config file: Their name and mask.
Definition: config_file.c:99
struct ir_ncode dyncodes[2]
helper structs for unknown buttons
char * name
Name of flag.
Definition: config_flags.h:17
ir_code rc6_mask
RC-6 doubles signal length of some bits.
int flag
Flag bitmask.
Definition: config_flags.h:18
int send_buffer_length(void)
Do not document this function.
Definition: transmit.c:373
#define log_info(fmt,...)
Log an info message.
Definition: lirc_log.h:114
ir_code toggle_bit_mask
previously only one bit called toggle_bit
int min_repeat
code is repeated at least x times code sent once -> min_repeat=0
#define RAW_CODES
for internal use only
struct ir_remote * read_config(FILE *f, const char *name)
Parse a lircd.conf config file.
Definition: config_file.c:838
#define log_notice(fmt,...)
Log a notice message.
Definition: lirc_log.h:119
ir_code ignore_mask
mask defines which bits can be ignored when matching a code
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
#define XMP
XMP protocol.
unsigned int bits_in_byte
default: 8
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
int length
(private)