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