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