1 /* $Id: config_file.c,v 5.34 2010/07/11 03:28:21 jarodwilson Exp $ */
2
3 /****************************************************************************
4 ** config_file.c ***********************************************************
5 ****************************************************************************
6 *
7 * config_file.c - parses the config file of lircd
8 *
9 * Copyright (C) 1998 Pablo d'Angelo <pablo@ag-trek.allgaeu.org>
10 *
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16
17 #include <errno.h>
18 #include <limits.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <libgen.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30
31 #include "lircd.h"
32 #include "ir_remote.h"
33 #include "config_file.h"
34 #include "transmit.h"
35
36 #define LINE_LEN 1024
37 #define MAX_INCLUDES 10
38
39 const char *whitespace = " \t";
40
41 static int line;
42 static int parse_error;
43
44 static struct ir_remote *read_config_recursive(FILE * f, const char *name, int depth);
45 static void calculate_signal_lengths(struct ir_remote *remote);
46
init_void_array(struct void_array * ar,size_t chunk_size,size_t item_size)47 void **init_void_array(struct void_array *ar, size_t chunk_size, size_t item_size)
48 {
49 ar->chunk_size = chunk_size;
50 ar->item_size = item_size;
51 ar->nr_items = 0;
52 if (!(ar->ptr = calloc(chunk_size, ar->item_size))) {
53 logprintf(LOG_ERR, "out of memory");
54 parse_error = 1;
55 return (NULL);
56 }
57 return (ar->ptr);
58 }
59
add_void_array(struct void_array * ar,void * dataptr)60 int add_void_array(struct void_array *ar, void *dataptr)
61 {
62 void *ptr;
63
64 if ((ar->nr_items % ar->chunk_size) == (ar->chunk_size) - 1) {
65 /* I hope this works with the right alignment,
66 if not we're screwed */
67 if (!(ptr = realloc(ar->ptr, ar->item_size * ((ar->nr_items) + (ar->chunk_size + 1))))) {
68 logprintf(LOG_ERR, "out of memory");
69 parse_error = 1;
70 return (0);
71 }
72 ar->ptr = ptr;
73 }
74 memcpy((ar->ptr) + (ar->item_size * ar->nr_items), dataptr, ar->item_size);
75 ar->nr_items = (ar->nr_items) + 1;
76 memset((ar->ptr) + (ar->item_size * ar->nr_items), 0, ar->item_size);
77 return (1);
78 }
79
get_void_array(struct void_array * ar)80 inline void *get_void_array(struct void_array *ar)
81 {
82 return (ar->ptr);
83 }
84
s_malloc(size_t size)85 void *s_malloc(size_t size)
86 {
87 void *ptr;
88 if ((ptr = malloc(size)) == NULL) {
89 logprintf(LOG_ERR, "out of memory");
90 parse_error = 1;
91 return (NULL);
92 }
93 memset(ptr, 0, size);
94 return (ptr);
95 }
96
s_strdup(char * string)97 inline char *s_strdup(char *string)
98 {
99 char *ptr;
100 if (!(ptr = strdup(string))) {
101 logprintf(LOG_ERR, "out of memory");
102 parse_error = 1;
103 return (NULL);
104 }
105 return (ptr);
106 }
107
s_strtocode(const char * val)108 inline ir_code s_strtocode(const char *val)
109 {
110 ir_code code = 0;
111 char *endptr;
112
113 errno = 0;
114 code = strtoull(val, &endptr, 0);
115 if ((code == (__u64) - 1 && errno == ERANGE) || strlen(endptr) != 0 || strlen(val) == 0) {
116 logprintf(LOG_ERR, "error in configfile line %d:", line);
117 logprintf(LOG_ERR, "\"%s\": must be a valid (__u64) number", val);
118 parse_error = 1;
119 return (0);
120 }
121 return (code);
122 }
123
s_strtou32(char * val)124 __u32 s_strtou32(char *val)
125 {
126 __u32 n;
127 char *endptr;
128
129 n = strtoul(val, &endptr, 0);
130 if (!*val || *endptr) {
131 logprintf(LOG_ERR, "error in configfile line %d:", line);
132 logprintf(LOG_ERR, "\"%s\": must be a valid (__u32) number", val);
133 parse_error = 1;
134 return (0);
135 }
136 return (n);
137 }
138
s_strtoi(char * val)139 int s_strtoi(char *val)
140 {
141 char *endptr;
142 long n;
143 int h;
144
145 n = strtol(val, &endptr, 0);
146 h = (int)n;
147 if (!*val || *endptr || n != ((long)h)) {
148 logprintf(LOG_ERR, "error in configfile line %d:", line);
149 logprintf(LOG_ERR, "\"%s\": must be a valid (int) number", val);
150 parse_error = 1;
151 return (0);
152 }
153 return (h);
154 }
155
s_strtoui(char * val)156 unsigned int s_strtoui(char *val)
157 {
158 char *endptr;
159 __u32 n;
160 unsigned int h;
161
162 n = strtoul(val, &endptr, 0);
163 h = (unsigned int)n;
164 if (!*val || *endptr || n != ((__u32) h)) {
165 logprintf(LOG_ERR, "error in configfile line %d:", line);
166 logprintf(LOG_ERR, "\"%s\": must be a valid (unsigned int) number", val);
167 parse_error = 1;
168 return (0);
169 }
170 return (h);
171 }
172
s_strtolirc_t(char * val)173 lirc_t s_strtolirc_t(char *val)
174 {
175 __u32 n;
176 lirc_t h;
177 char *endptr;
178
179 n = strtoul(val, &endptr, 0);
180 h = (lirc_t) n;
181 if (!*val || *endptr || n != ((__u32) h)) {
182 logprintf(LOG_ERR, "error in configfile line %d:", line);
183 logprintf(LOG_ERR, "\"%s\": must be a valid (lirc_t) number", val);
184 parse_error = 1;
185 return (0);
186 }
187 if (h < 0) {
188 logprintf(LOG_WARNING, "error in configfile line %d:", line);
189 logprintf(LOG_WARNING, "\"%s\" is out of range", val);
190 }
191 return (h);
192 }
193
checkMode(int is_mode,int c_mode,char * error)194 int checkMode(int is_mode, int c_mode, char *error)
195 {
196 if (is_mode != c_mode) {
197 logprintf(LOG_ERR, "fatal error in configfile line %d:", line);
198 logprintf(LOG_ERR, "\"%s\" isn't valid at this position", error);
199 parse_error = 1;
200 return (0);
201 }
202 return (1);
203 }
204
addSignal(struct void_array * signals,char * val)205 int addSignal(struct void_array *signals, char *val)
206 {
207 unsigned int t;
208
209 t = s_strtoui(val);
210 if (parse_error)
211 return 0;
212 if (!add_void_array(signals, &t))
213 return 0;
214
215 return 1;
216 }
217
defineCode(char * key,char * val,struct ir_ncode * code)218 struct ir_ncode *defineCode(char *key, char *val, struct ir_ncode *code)
219 {
220 memset(code, 0, sizeof(*code));
221 code->name = s_strdup(key);
222 code->code = s_strtocode(val);
223 LOGPRINTF(3, " %-20s 0x%016llX", code->name, code->code);
224 return (code);
225 }
226
defineNode(struct ir_ncode * code,const char * val)227 struct ir_code_node *defineNode(struct ir_ncode *code, const char *val)
228 {
229 struct ir_code_node *node;
230
231 node = s_malloc(sizeof(*node));
232 if (node == NULL)
233 return NULL;
234
235 node->code = s_strtocode(val);
236 node->next = NULL;
237
238 LOGPRINTF(3, " 0x%016llX", node->code);
239
240 if (code->current == NULL) {
241 code->next = node;
242 code->current = node;
243 } else {
244 code->current->next = node;
245 code->current = node;
246 }
247 return node;
248 }
249
parseFlags(char * val)250 int parseFlags(char *val)
251 {
252 struct flaglist *flaglptr;
253 int flags = 0;
254 char *flag, *help;
255
256 flag = help = val;
257 while (flag != NULL) {
258 while (*help != '|' && *help != 0)
259 help++;
260 if (*help == '|') {
261 *help = 0;
262 help++;
263 } else {
264 help = NULL;
265 }
266
267 flaglptr = all_flags;
268 while (flaglptr->name != NULL) {
269 if (strcasecmp(flaglptr->name, flag) == 0) {
270 if (flaglptr->flag & IR_PROTOCOL_MASK && flags & IR_PROTOCOL_MASK) {
271 logprintf(LOG_ERR, "error in configfile line %d:", line);
272 logprintf(LOG_ERR, "multiple protocols given in flags: \"%s\"", flag);
273 parse_error = 1;
274 return (0);
275 }
276 flags = flags | flaglptr->flag;
277 LOGPRINTF(3, "flag %s recognized", flaglptr->name);
278 break;
279 }
280 flaglptr++;
281 }
282 if (flaglptr->name == NULL) {
283 logprintf(LOG_ERR, "error in configfile line %d:", line);
284 logprintf(LOG_ERR, "unknown flag: \"%s\"", flag);
285 parse_error = 1;
286 return (0);
287 }
288 flag = help;
289 }
290 LOGPRINTF(2, "flags value: %d", flags);
291
292 return (flags);
293 }
294
defineRemote(char * key,char * val,char * val2,struct ir_remote * rem)295 int defineRemote(char *key, char *val, char *val2, struct ir_remote *rem)
296 {
297 if ((strcasecmp("name", key)) == 0) {
298 if (rem->name != NULL)
299 free(rem->name);
300 rem->name = s_strdup(val);
301 LOGPRINTF(1, "parsing %s remote", val);
302 return (1);
303 }
304 #ifdef DYNCODES
305 if ((strcasecmp("dyncodes_name", key)) == 0) {
306 if (rem->dyncodes_name != NULL) {
307 free(rem->dyncodes_name);
308 }
309 rem->dyncodes_name = s_strdup(val);
310 return (1);
311 }
312 #endif
313 else if ((strcasecmp("bits", key)) == 0) {
314 rem->bits = s_strtoi(val);
315 return (1);
316 } else if (strcasecmp("flags", key) == 0) {
317 rem->flags |= parseFlags(val);
318 return (1);
319 } else if (strcasecmp("eps", key) == 0) {
320 rem->eps = s_strtoi(val);
321 return (1);
322 } else if (strcasecmp("aeps", key) == 0) {
323 rem->aeps = s_strtoi(val);
324 return (1);
325 } else if (strcasecmp("plead", key) == 0) {
326 rem->plead = s_strtolirc_t(val);
327 return (1);
328 } else if (strcasecmp("ptrail", key) == 0) {
329 rem->ptrail = s_strtolirc_t(val);
330 return (1);
331 } else if (strcasecmp("pre_data_bits", key) == 0) {
332 rem->pre_data_bits = s_strtoi(val);
333 return (1);
334 } else if (strcasecmp("pre_data", key) == 0) {
335 rem->pre_data = s_strtocode(val);
336 return (1);
337 } else if (strcasecmp("post_data_bits", key) == 0) {
338 rem->post_data_bits = s_strtoi(val);
339 return (1);
340 } else if (strcasecmp("post_data", key) == 0) {
341 rem->post_data = s_strtocode(val);
342 return (1);
343 } else if (strcasecmp("gap", key) == 0) {
344 if (val2 != NULL) {
345 rem->gap2 = s_strtou32(val2);
346 }
347 rem->gap = s_strtou32(val);
348 return (val2 != NULL ? 2 : 1);
349 } else if (strcasecmp("repeat_gap", key) == 0) {
350 rem->repeat_gap = s_strtou32(val);
351 return (1);
352 }
353 /* obsolete: use toggle_bit_mask instead */
354 else if (strcasecmp("toggle_bit", key) == 0) {
355 rem->toggle_bit = s_strtoi(val);
356 return 1;
357 } else if (strcasecmp("toggle_bit_mask", key) == 0) {
358 rem->toggle_bit_mask = s_strtocode(val);
359 return 1;
360 } else if (strcasecmp("toggle_mask", key) == 0) {
361 rem->toggle_mask = s_strtocode(val);
362 return (1);
363 } else if (strcasecmp("rc6_mask", key) == 0) {
364 rem->rc6_mask = s_strtocode(val);
365 return (1);
366 } else if (strcasecmp("ignore_mask", key) == 0) {
367 rem->ignore_mask = s_strtocode(val);
368 return (1);
369 }
370 /* obsolete name */
371 else if (strcasecmp("repeat_bit", key) == 0) {
372 rem->toggle_bit = s_strtoi(val);
373 return (1);
374 } else if (strcasecmp("suppress_repeat", key) == 0) {
375 rem->suppress_repeat = s_strtoi(val);
376 return (1);
377 } else if (strcasecmp("min_repeat", key) == 0) {
378 rem->min_repeat = s_strtoi(val);
379 return (1);
380 } else if (strcasecmp("min_code_repeat", key) == 0) {
381 rem->min_code_repeat = s_strtoi(val);
382 return (1);
383 } else if (strcasecmp("frequency", key) == 0) {
384 rem->freq = s_strtoui(val);
385 return (1);
386 } else if (strcasecmp("duty_cycle", key) == 0) {
387 rem->duty_cycle = s_strtoui(val);
388 return (1);
389 } else if (strcasecmp("baud", key) == 0) {
390 rem->baud = s_strtoui(val);
391 return (1);
392 } else if (strcasecmp("serial_mode", key) == 0) {
393 if (val[0] < '5' || val[0] > '9') {
394 logprintf(LOG_ERR, "error in configfile line %d:", line);
395 logprintf(LOG_ERR, "bad bit count");
396 parse_error = 1;
397 return 0;
398 }
399 rem->bits_in_byte = val[0] - '0';
400 switch (toupper(val[1])) {
401 case 'N':
402 rem->parity = IR_PARITY_NONE;
403 break;
404 case 'E':
405 rem->parity = IR_PARITY_EVEN;
406 break;
407 case 'O':
408 rem->parity = IR_PARITY_ODD;
409 break;
410 default:
411 logprintf(LOG_ERR, "error in configfile line %d:", line);
412 logprintf(LOG_ERR, "unsupported parity mode");
413 parse_error = 1;
414 return 0;
415 }
416 if (strcmp(val + 2, "1.5") == 0) {
417 rem->stop_bits = 3;
418 } else {
419 rem->stop_bits = s_strtoui(val + 2) * 2;
420 }
421 return (1);
422 } else if (val2 != NULL) {
423 if (strcasecmp("header", key) == 0) {
424 rem->phead = s_strtolirc_t(val);
425 rem->shead = s_strtolirc_t(val2);
426 return (2);
427 } else if (strcasecmp("three", key) == 0) {
428 rem->pthree = s_strtolirc_t(val);
429 rem->sthree = s_strtolirc_t(val2);
430 return (2);
431 } else if (strcasecmp("two", key) == 0) {
432 rem->ptwo = s_strtolirc_t(val);
433 rem->stwo = s_strtolirc_t(val2);
434 return (2);
435 } else if (strcasecmp("one", key) == 0) {
436 rem->pone = s_strtolirc_t(val);
437 rem->sone = s_strtolirc_t(val2);
438 return (2);
439 } else if (strcasecmp("zero", key) == 0) {
440 rem->pzero = s_strtolirc_t(val);
441 rem->szero = s_strtolirc_t(val2);
442 return (2);
443 } else if (strcasecmp("foot", key) == 0) {
444 rem->pfoot = s_strtolirc_t(val);
445 rem->sfoot = s_strtolirc_t(val2);
446 return (2);
447 } else if (strcasecmp("repeat", key) == 0) {
448 rem->prepeat = s_strtolirc_t(val);
449 rem->srepeat = s_strtolirc_t(val2);
450 return (2);
451 } else if (strcasecmp("pre", key) == 0) {
452 rem->pre_p = s_strtolirc_t(val);
453 rem->pre_s = s_strtolirc_t(val2);
454 return (2);
455 } else if (strcasecmp("post", key) == 0) {
456 rem->post_p = s_strtolirc_t(val);
457 rem->post_s = s_strtolirc_t(val2);
458 return (2);
459 }
460 }
461 if (val2) {
462 logprintf(LOG_ERR, "error in configfile line %d:", line);
463 logprintf(LOG_ERR, "unknown definiton: \"%s %s %s\"", key, val, val2);
464 } else {
465 logprintf(LOG_ERR, "error in configfile line %d:", line);
466 logprintf(LOG_ERR, "unknown definiton or too few arguments: \"%s %s\"", key, val);
467 }
468 parse_error = 1;
469 return (0);
470 }
471
sanityChecks(struct ir_remote * rem)472 static int sanityChecks(struct ir_remote *rem)
473 {
474 struct ir_ncode *codes;
475 struct ir_code_node *node;
476
477 if (!rem->name) {
478 logprintf(LOG_ERR, "you must specify a remote name");
479 return 0;
480 }
481 if (rem->gap == 0) {
482 logprintf(LOG_WARNING, "you should specify a valid gap value");
483 }
484 if (has_repeat_gap(rem) && is_const(rem)) {
485 logprintf(LOG_WARNING, "repeat_gap will be ignored if CONST_LENGTH flag is set");
486 }
487
488 if (is_raw(rem))
489 return 1;
490
491 if ((rem->pre_data & gen_mask(rem->pre_data_bits)) != rem->pre_data) {
492 logprintf(LOG_WARNING, "invalid pre_data found for %s", rem->name);
493 rem->pre_data &= gen_mask(rem->pre_data_bits);
494 }
495 if ((rem->post_data & gen_mask(rem->post_data_bits)) != rem->post_data) {
496 logprintf(LOG_WARNING, "invalid post_data found for %s", rem->name);
497 rem->post_data &= gen_mask(rem->post_data_bits);
498 }
499 for (codes = rem->codes; codes->name != NULL; codes++) {
500 if ((codes->code & gen_mask(rem->bits)) != codes->code) {
501 logprintf(LOG_WARNING, "invalid code found for %s: %s", rem->name, codes->name);
502 codes->code &= gen_mask(rem->bits);
503 }
504 for (node = codes->next; node != NULL; node = node->next) {
505 if ((node->code & gen_mask(rem->bits)) != node->code) {
506 logprintf(LOG_WARNING, "invalid code found for %s: %s", rem->name, codes->name);
507 node->code &= gen_mask(rem->bits);
508 }
509 }
510 }
511
512 return 1;
513 }
514
sort_by_bit_count(struct ir_remote * remotes)515 struct ir_remote *sort_by_bit_count(struct ir_remote *remotes)
516 {
517 struct ir_remote *top, *rem, *next, *prev, *scan;
518
519 rem = remotes;
520 top = NULL;
521 while (rem != NULL) {
522 next = rem->next;
523
524 scan = top;
525 prev = NULL;
526 while (scan && bit_count(scan) <= bit_count(rem)) {
527 prev = scan;
528 scan = scan->next;
529 }
530 if (prev) {
531 prev->next = rem;
532 } else {
533 top = rem;
534 }
535 if (scan) {
536 rem->next = scan;
537 } else {
538 rem->next = NULL;
539 }
540
541 rem = next;
542 }
543
544 return top;
545 }
546
lirc_parse_include(char * s)547 static const char *lirc_parse_include(char *s)
548 {
549 char *last;
550 size_t len;
551
552 len = strlen(s);
553 if (len < 2) {
554 return NULL;
555 }
556 last = s + len - 1;
557 while (last > s && strchr(whitespace, *last) != NULL) {
558 last--;
559 }
560 if (last <= s) {
561 return NULL;
562 }
563 if (*s != '"' && *s != '<') {
564 return NULL;
565 }
566 if (*s == '"' && *last != '"') {
567 return NULL;
568 } else if (*s == '<' && *last != '>') {
569 return NULL;
570 }
571 *last = 0;
572 memmove(s, s + 1, len - 2 + 1); /* terminating 0 is copied, and
573 maybe more, but we don't care */
574 return s;
575 }
576
lirc_parse_relative(char * dst,size_t dst_size,const char * child,const char * current)577 static const char *lirc_parse_relative(char *dst, size_t dst_size, const char *child, const char *current)
578 {
579 char *dir;
580 size_t dirlen;
581
582 if (!current)
583 return child;
584
585 /* Not a relative path */
586 if (*child == '/')
587 return child;
588
589 if (strlen(current) >= dst_size) {
590 return NULL;
591 }
592 strcpy(dst, current);
593 dir = dirname(dst);
594 dirlen = strlen(dir);
595 if (dir != dst) {
596 memmove(dst, dir, dirlen + 1);
597 }
598
599 if (dirlen + 1 + strlen(child) + 1 > dst_size) {
600 return NULL;
601 }
602 strcat(dst, "/");
603 strcat(dst, child);
604
605 return dst;
606 }
607
read_config(FILE * f,const char * name)608 struct ir_remote *read_config(FILE * f, const char *name)
609 {
610 return read_config_recursive(f, name, 0);
611 }
612
read_config_recursive(FILE * f,const char * name,int depth)613 static struct ir_remote *read_config_recursive(FILE * f, const char *name, int depth)
614 {
615 char buf[LINE_LEN + 1], *key, *val, *val2;
616 int len, argc;
617 struct ir_remote *top_rem = NULL, *rem = NULL;
618 struct void_array codes_list, raw_codes, signals;
619 struct ir_ncode raw_code = { NULL, 0, 0, NULL };
620 struct ir_ncode name_code = { NULL, 0, 0, NULL };
621 struct ir_ncode *code;
622 int mode = ID_none;
623
624 line = 0;
625 parse_error = 0;
626 LOGPRINTF(2, "parsing '%s'", name);
627
628 while (fgets(buf, LINE_LEN, f) != NULL) {
629 line++;
630 len = strlen(buf);
631 if (len == LINE_LEN && buf[len - 1] != '\n') {
632 logprintf(LOG_ERR, "line %d too long in config file", line);
633 parse_error = 1;
634 break;
635 }
636
637 if (len > 0) {
638 len--;
639 if (buf[len] == '\n')
640 buf[len] = 0;
641 }
642 if (len > 0) {
643 len--;
644 if (buf[len] == '\r')
645 buf[len] = 0;
646 }
647 /* ignore comments */
648 if (buf[0] == '#') {
649 continue;
650 }
651 key = strtok(buf, whitespace);
652 /* ignore empty lines */
653 if (key == NULL)
654 continue;
655 val = strtok(NULL, whitespace);
656 if (val != NULL) {
657 val2 = strtok(NULL, whitespace);
658 LOGPRINTF(3, "\"%s\" \"%s\"", key, val);
659 if (strcasecmp("include", key) == 0) {
660 FILE *childFile;
661 const char *childName;
662 const char *fullPath;
663 char result[FILENAME_MAX + 1];
664
665 if (depth > MAX_INCLUDES) {
666 logprintf(LOG_ERR, "error opening child file defined at %s:%d", name, line);
667 logprintf(LOG_ERR, "too many files included");
668 parse_error = -1;
669 break;
670 }
671
672 childName = lirc_parse_include(val);
673 if (!childName) {
674 logprintf(LOG_ERR, "error parsing child file value defined at line %d:", line);
675 logprintf(LOG_ERR, "invalid quoting");
676 parse_error = -1;
677 break;
678 }
679
680 fullPath = lirc_parse_relative(result, sizeof(result), childName, name);
681 if (!fullPath) {
682 logprintf(LOG_ERR, "error composing relative file path defined at line %d:",
683 line);
684 logprintf(LOG_ERR, "resulting path too long");
685 parse_error = -1;
686 break;
687 }
688
689 childFile = fopen(fullPath, "r");
690 if (childFile == NULL) {
691 logprintf(LOG_ERR, "error opening child file '%s' defined at line %d:",
692 fullPath, line);
693 logprintf(LOG_ERR, "ignoring this child file for now.");
694 } else {
695 int save_line = line;
696
697 if (!top_rem) {
698 /* create first remote */
699 LOGPRINTF(2, "creating first remote");
700 rem = read_config_recursive(childFile, fullPath, depth + 1);
701 if (rem != (void *)-1 && rem != NULL) {
702 top_rem = rem;
703 } else {
704 rem = NULL;
705 }
706 } else {
707 /* create new remote */
708 LOGPRINTF(2, "creating next remote");
709 rem->next = read_config_recursive(childFile, fullPath, depth + 1);
710 if (rem->next != (void *)-1 && rem->next != NULL) {
711 rem = rem->next;
712 } else {
713 rem->next = NULL;
714 }
715 }
716 fclose(childFile);
717 line = save_line;
718 }
719 } else if (strcasecmp("begin", key) == 0) {
720 if (strcasecmp("codes", val) == 0) {
721 /* init codes mode */
722 LOGPRINTF(2, " begin codes");
723 if (!checkMode(mode, ID_remote, "begin codes"))
724 break;
725 if (rem->codes) {
726 logprintf(LOG_ERR, "error in configfile line %d:", line);
727 logprintf(LOG_ERR, "codes are already defined");
728 parse_error = 1;
729 break;
730 }
731
732 init_void_array(&codes_list, 30, sizeof(struct ir_ncode));
733 mode = ID_codes;
734 } else if (strcasecmp("raw_codes", val) == 0) {
735 /* init raw_codes mode */
736 LOGPRINTF(2, " begin raw_codes");
737 if (!checkMode(mode, ID_remote, "begin raw_codes"))
738 break;
739 if (rem->codes) {
740 logprintf(LOG_ERR, "error in configfile line %d:", line);
741 logprintf(LOG_ERR, "codes are already defined");
742 parse_error = 1;
743 break;
744 }
745 set_protocol(rem, RAW_CODES);
746 raw_code.code = 0;
747 init_void_array(&raw_codes, 30, sizeof(struct ir_ncode));
748 mode = ID_raw_codes;
749 } else if (strcasecmp("remote", val) == 0) {
750 /* create new remote */
751 LOGPRINTF(1, "parsing remote");
752 if (!checkMode(mode, ID_none, "begin remote"))
753 break;
754 mode = ID_remote;
755 if (!top_rem) {
756 /* create first remote */
757 LOGPRINTF(2, "creating first remote");
758 rem = top_rem = s_malloc(sizeof(struct ir_remote));
759 } else {
760 /* create new remote */
761 LOGPRINTF(2, "creating next remote");
762 rem->next = s_malloc(sizeof(struct ir_remote));;
763 rem = rem->next;
764 }
765 } else if (mode == ID_codes) {
766 code = defineCode(key, val, &name_code);
767 while (!parse_error && val2 != NULL) {
768 struct ir_code_node *node;
769
770 if (val2[0] == '#')
771 break; /* comment */
772 node = defineNode(code, val2);
773 val2 = strtok(NULL, whitespace);
774 }
775 code->current = NULL;
776 add_void_array(&codes_list, code);
777 } else {
778 logprintf(LOG_ERR, "error in configfile line %d:", line);
779 logprintf(LOG_ERR, "unknown section \"%s\"", val);
780 parse_error = 1;
781 }
782 if (!parse_error && val2 != NULL) {
783 logprintf(LOG_WARNING, "garbage after '%s' token in line %d ignored", val,
784 line);
785 }
786 } else if (strcasecmp("end", key) == 0) {
787
788 if (strcasecmp("codes", val) == 0) {
789 /* end Codes mode */
790 LOGPRINTF(2, " end codes");
791 if (!checkMode(mode, ID_codes, "end codes"))
792 break;
793 rem->codes = get_void_array(&codes_list);
794 mode = ID_remote; /* switch back */
795
796 } else if (strcasecmp("raw_codes", val) == 0) {
797 /* end raw codes mode */
798 LOGPRINTF(2, " end raw_codes");
799
800 if (mode == ID_raw_name) {
801 raw_code.signals = get_void_array(&signals);
802 raw_code.length = signals.nr_items;
803 if (raw_code.length % 2 == 0) {
804 logprintf(LOG_ERR, "error in configfile line %d:", line);
805 logprintf(LOG_ERR, "bad signal length");
806 parse_error = 1;
807 }
808 if (!add_void_array(&raw_codes, &raw_code))
809 break;
810 mode = ID_raw_codes;
811 }
812 if (!checkMode(mode, ID_raw_codes, "end raw_codes"))
813 break;
814 rem->codes = get_void_array(&raw_codes);
815 mode = ID_remote; /* switch back */
816 } else if (strcasecmp("remote", val) == 0) {
817 /* end remote mode */
818 LOGPRINTF(2, "end remote");
819 /* print_remote(rem); */
820 if (!checkMode(mode, ID_remote, "end remote"))
821 break;
822 if (!sanityChecks(rem)) {
823 parse_error = 1;
824 break;
825 }
826 # ifdef DYNCODES
827 if (rem->dyncodes_name == NULL) {
828 rem->dyncodes_name = s_strdup("unknown");
829 }
830 rem->dyncodes[0].name = rem->dyncodes_name;
831 rem->dyncodes[1].name = rem->dyncodes_name;
832 # endif
833 /* not really necessary because we
834 clear the alloced memory */
835 rem->next = NULL;
836 rem->last_code = NULL;
837 mode = ID_none; /* switch back */
838 } else if (mode == ID_codes) {
839 code = defineCode(key, val, &name_code);
840 while (!parse_error && val2 != NULL) {
841 struct ir_code_node *node;
842
843 if (val2[0] == '#')
844 break; /* comment */
845 node = defineNode(code, val2);
846 val2 = strtok(NULL, whitespace);
847 }
848 code->current = NULL;
849 add_void_array(&codes_list, code);
850 } else {
851 logprintf(LOG_ERR, "error in configfile line %d:", line);
852 logprintf(LOG_ERR, "unknown section %s", val);
853 parse_error = 1;
854 }
855 if (!parse_error && val2 != NULL) {
856 logprintf(LOG_WARNING, "garbage after '%s'" " token in line %d ignored", val,
857 line);
858 }
859 } else {
860 switch (mode) {
861 case ID_remote:
862 argc = defineRemote(key, val, val2, rem);
863 if (!parse_error
864 && ((argc == 1 && val2 != NULL)
865 || (argc == 2 && val2 != NULL && strtok(NULL, whitespace) != NULL))) {
866 logprintf(LOG_WARNING, "garbage after '%s'" " token in line %d ignored",
867 key, line);
868 }
869 break;
870 case ID_codes:
871 code = defineCode(key, val, &name_code);
872 while (!parse_error && val2 != NULL) {
873 struct ir_code_node *node;
874
875 if (val2[0] == '#')
876 break; /* comment */
877 node = defineNode(code, val2);
878 val2 = strtok(NULL, whitespace);
879 }
880 code->current = NULL;
881 add_void_array(&codes_list, code);
882 break;
883 case ID_raw_codes:
884 case ID_raw_name:
885 if (strcasecmp("name", key) == 0) {
886 LOGPRINTF(3, "Button: \"%s\"", val);
887 if (mode == ID_raw_name) {
888 raw_code.signals = get_void_array(&signals);
889 raw_code.length = signals.nr_items;
890 if (raw_code.length % 2 == 0) {
891 logprintf(LOG_ERR, "error in configfile line %d:",
892 line);
893 logprintf(LOG_ERR, "bad signal length");
894 parse_error = 1;
895 }
896 if (!add_void_array(&raw_codes, &raw_code))
897 break;
898 }
899 if (!(raw_code.name = s_strdup(val))) {
900 break;
901 }
902 raw_code.code++;
903 init_void_array(&signals, 50, sizeof(lirc_t));
904 mode = ID_raw_name;
905 if (!parse_error && val2 != NULL) {
906 logprintf(LOG_WARNING,
907 "garbage after '%s'" " token in line %d ignored", key,
908 line);
909 }
910 } else {
911 if (mode == ID_raw_codes) {
912 logprintf(LOG_ERR, "no name for signal defined at line %d",
913 line);
914 parse_error = 1;
915 break;
916 }
917 if (!addSignal(&signals, key))
918 break;
919 if (!addSignal(&signals, val))
920 break;
921 if (val2) {
922 if (!addSignal(&signals, val2)) {
923 break;
924 }
925 }
926 while ((val = strtok(NULL, whitespace))) {
927 if (!addSignal(&signals, val))
928 break;
929 }
930 }
931 break;
932 }
933 }
934 } else if (mode == ID_raw_name) {
935 if (!addSignal(&signals, key)) {
936 break;
937 }
938 } else {
939 logprintf(LOG_ERR, "error in configfile line %d", line);
940 parse_error = 1;
941 break;
942 }
943 if (parse_error) {
944 break;
945 }
946 }
947 if (mode != ID_none) {
948 switch (mode) {
949 case ID_raw_name:
950 if (raw_code.name != NULL) {
951 free(raw_code.name);
952 if (get_void_array(&signals) != NULL)
953 free(get_void_array(&signals));
954 }
955 case ID_raw_codes:
956 rem->codes = get_void_array(&raw_codes);
957 break;
958 case ID_codes:
959 rem->codes = get_void_array(&codes_list);
960 break;
961 }
962 if (!parse_error) {
963 logprintf(LOG_ERR, "unexpected end of file");
964 parse_error = 1;
965 }
966 }
967 if (parse_error) {
968 static int print_error = 1;
969
970 if (print_error) {
971 logprintf(LOG_ERR, "reading of file '%s' failed", name);
972 print_error = 0;
973 }
974 free_config(top_rem);
975 if (depth == 0)
976 print_error = 1;
977 return ((void *)-1);
978 }
979 /* kick reverse flag */
980 /* handle RC6 flag to be backwards compatible: previous RC-6
981 config files did not set rc6_mask */
982 rem = top_rem;
983 while (rem != NULL) {
984 if ((!is_raw(rem)) && rem->flags & REVERSE) {
985 struct ir_ncode *codes;
986
987 if (has_pre(rem)) {
988 rem->pre_data = reverse(rem->pre_data, rem->pre_data_bits);
989 }
990 if (has_post(rem)) {
991 rem->post_data = reverse(rem->post_data, rem->post_data_bits);
992 }
993 codes = rem->codes;
994 while (codes->name != NULL) {
995 codes->code = reverse(codes->code, rem->bits);
996 codes++;
997 }
998 rem->flags = rem->flags & (~REVERSE);
999 rem->flags = rem->flags | COMPAT_REVERSE;
1000 /* don't delete the flag because we still need
1001 it to remain compatible with older versions
1002 */
1003 }
1004 if (rem->flags & RC6 && rem->rc6_mask == 0 && rem->toggle_bit > 0) {
1005 int all_bits = bit_count(rem);
1006
1007 rem->rc6_mask = ((ir_code) 1) << (all_bits - rem->toggle_bit);
1008 }
1009 if (rem->toggle_bit > 0) {
1010 int all_bits = bit_count(rem);
1011
1012 if (has_toggle_bit_mask(rem)) {
1013 logprintf(LOG_WARNING, "%s uses both toggle_bit and toggle_bit_mask", rem->name);
1014 } else {
1015 rem->toggle_bit_mask = ((ir_code) 1) << (all_bits - rem->toggle_bit);
1016 }
1017 rem->toggle_bit = 0;
1018 }
1019 if (has_toggle_bit_mask(rem)) {
1020 if (!is_raw(rem) && rem->codes) {
1021 rem->toggle_bit_mask_state = (rem->codes->code & rem->toggle_bit_mask);
1022 if (rem->toggle_bit_mask_state) {
1023 /* start with state set to 0 for backwards compatibility */
1024 rem->toggle_bit_mask_state ^= rem->toggle_bit_mask;
1025 }
1026 }
1027 }
1028 if (is_serial(rem)) {
1029 lirc_t base;
1030
1031 if (rem->baud > 0) {
1032 base = 1000000 / rem->baud;
1033 if (rem->pzero == 0 && rem->szero == 0) {
1034 rem->pzero = base;
1035 }
1036 if (rem->pone == 0 && rem->sone == 0) {
1037 rem->sone = base;
1038 }
1039 }
1040 if (rem->bits_in_byte == 0) {
1041 rem->bits_in_byte = 8;
1042 }
1043 }
1044 if (rem->min_code_repeat > 0) {
1045 if (!has_repeat(rem) || rem->min_code_repeat > rem->min_repeat) {
1046 logprintf(LOG_WARNING, "invalid min_code_repeat value");
1047 rem->min_code_repeat = 0;
1048 }
1049 }
1050 calculate_signal_lengths(rem);
1051 rem = rem->next;
1052 }
1053
1054 top_rem = sort_by_bit_count(top_rem);
1055 # if defined(DEBUG) && !defined(DAEMONIZE)
1056 /*fprint_remotes(stderr, top_rem); */
1057 # endif
1058 return (top_rem);
1059 }
1060
calculate_signal_lengths(struct ir_remote * remote)1061 void calculate_signal_lengths(struct ir_remote *remote)
1062 {
1063 if (is_const(remote)) {
1064 remote->min_total_signal_length = min_gap(remote);
1065 remote->max_total_signal_length = max_gap(remote);
1066 } else {
1067 remote->min_gap_length = min_gap(remote);
1068 remote->max_gap_length = max_gap(remote);
1069 }
1070
1071 lirc_t min_signal_length = 0, max_signal_length = 0;
1072 lirc_t max_pulse = 0, max_space = 0;
1073 int first_sum = 1;
1074 struct ir_ncode *c = remote->codes;
1075 int i;
1076
1077 while (c->name) {
1078 struct ir_ncode code = *c;
1079 struct ir_code_node *next = code.next;
1080 int first = 1;
1081 int repeat = 0;
1082 do {
1083 if (first) {
1084 first = 0;
1085 } else {
1086 code.code = next->code;
1087 next = next->next;
1088 }
1089 for (repeat = 0; repeat < 2; repeat++) {
1090 if (init_sim(remote, &code, repeat)) {
1091 lirc_t sum = send_buffer.sum;
1092
1093 if (sum) {
1094 if (first_sum || sum < min_signal_length) {
1095 min_signal_length = sum;
1096 }
1097 if (first_sum || sum > max_signal_length) {
1098 max_signal_length = sum;
1099 }
1100 first_sum = 0;
1101 }
1102 for (i = 0; i < send_buffer.wptr; i++) {
1103 if (i & 1) { /* space */
1104 if (send_buffer.data[i] > max_space) {
1105 max_space = send_buffer.data[i];
1106 }
1107 } else { /* pulse */
1108
1109 if (send_buffer.data[i] > max_pulse) {
1110 max_pulse = send_buffer.data[i];
1111 }
1112 }
1113 }
1114 }
1115 }
1116 } while (next);
1117 c++;
1118 }
1119 if (first_sum) {
1120 /* no timing data, so assume gap is the actual total
1121 length */
1122 remote->min_total_signal_length = min_gap(remote);
1123 remote->max_total_signal_length = max_gap(remote);
1124 remote->min_gap_length = min_gap(remote);
1125 remote->max_gap_length = max_gap(remote);
1126 } else if (is_const(remote)) {
1127 if (remote->min_total_signal_length > max_signal_length) {
1128 remote->min_gap_length = remote->min_total_signal_length - max_signal_length;
1129 } else {
1130 logprintf(LOG_WARNING, "min_gap_length is 0 for '%s' remote", remote->name);
1131 remote->min_gap_length = 0;
1132 }
1133 if (remote->max_total_signal_length > min_signal_length) {
1134 remote->max_gap_length = remote->max_total_signal_length - min_signal_length;
1135 } else {
1136 logprintf(LOG_WARNING, "max_gap_length is 0 for '%s' remote", remote->name);
1137 remote->max_gap_length = 0;
1138 }
1139 } else {
1140 remote->min_total_signal_length = min_signal_length + remote->min_gap_length;
1141 remote->max_total_signal_length = max_signal_length + remote->max_gap_length;
1142 }
1143 LOGPRINTF(1, "lengths: %lu %lu %lu %lu", remote->min_total_signal_length, remote->max_total_signal_length,
1144 remote->min_gap_length, remote->max_gap_length);
1145 }
1146
free_config(struct ir_remote * remotes)1147 void free_config(struct ir_remote *remotes)
1148 {
1149 struct ir_remote *next;
1150 struct ir_ncode *codes;
1151
1152 while (remotes != NULL) {
1153 next = remotes->next;
1154
1155 # ifdef DYNCODES
1156 if (remotes->dyncodes_name != NULL)
1157 free(remotes->dyncodes_name);
1158 # endif
1159 if (remotes->name != NULL)
1160 free(remotes->name);
1161 if (remotes->codes != NULL) {
1162 codes = remotes->codes;
1163 while (codes->name != NULL) {
1164 struct ir_code_node *node, *next_node;
1165
1166 free(codes->name);
1167 if (codes->signals != NULL)
1168 free(codes->signals);
1169 node = codes->next;
1170 while (node) {
1171 next_node = node->next;
1172 free(node);
1173 node = next_node;
1174 }
1175 codes++;
1176 }
1177 free(remotes->codes);
1178 }
1179 free(remotes);
1180 remotes = next;
1181 }
1182 }
1183