1 /* $Id: slinke.c,v 5.6 2010/04/11 18:50:38 lirc Exp $ */
2
3 /****************************************************************************
4 ** slinke.c ****************************************************************
5 ****************************************************************************
6 *
7 * slinke - simple hack to convert Nirvis Systems Device Files to LIRC
8 + config files
9 *
10 * Copyright (C) 2000 Christoph Bartelmus <lirc@bartelmus.de>
11 *
12 */
13
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <getopt.h>
21 #include <stdarg.h>
22 #include <ctype.h>
23 #include <limits.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27
28 #include "ir_remote.h"
29 #include "config_file.h"
30 #include "dump_config.h"
31
32 const char *usage = "Usage: %s --help | --version | [options] file\n";
33 char *progname;
34 struct hardware hw = {
35 "/dev/null", /* default device */
36 -1, /* fd */
37 0, /* features */
38 0, /* send_mode */
39 0, /* rec_mode */
40 0, /* code_length */
41 NULL, /* init_func */
42 NULL, /* deinit_func */
43 NULL, /* send_func */
44 NULL, /* rec_func */
45 NULL, /* decode_func */
46 NULL, /* ioctl_func */
47 NULL, /* readdata */
48 "slinke", /* name */
49 };
50
51 #define MAX_LINE_WIDTH 300
52 #define MAX_CODES 100
53
54 int debug = 0;
55
logprintf(int prio,const char * format_str,...)56 void logprintf(int prio, const char *format_str, ...)
57 {
58 }
59
logperror(int prio,const char * s)60 void logperror(int prio, const char *s)
61 {
62 }
63
get_val(char * buffer,...)64 int get_val(char *buffer, ...)
65 {
66 va_list ap;
67 char *next;
68 int count, flag;
69 int *n;
70
71 va_start(ap, buffer);
72 count = 0;
73 flag = 1;
74
75 next = strtok(buffer, " \t");
76 while (next != NULL) {
77 if (flag) {
78 n = va_arg(ap, int *);
79 if (n != NULL) {
80 *n = atoi(next);
81 } else {
82 flag = 0;
83 }
84 }
85 next = strtok(NULL, " \t");
86 count++;
87 }
88 return (count);
89 }
90
get_data(char * s,ir_code * data,int * bits)91 int get_data(char *s, ir_code * data, int *bits)
92 {
93 *data = 0;
94 *bits = 0;
95 while (*s) {
96 *data <<= 1;
97 if (*s == '1') {
98 *data |= 1;
99 } else if (*s != '0' && !isspace(*s)) {
100 return (0);
101 }
102 s++;
103 (*bits)++;
104 }
105 return (1);
106 }
107
strtoupper(char * s)108 void strtoupper(char *s)
109 {
110 while (*s) {
111 *s = toupper(*s);
112 s++;
113 }
114 }
115
append_code(struct ir_remote * r,ir_code code,char * name)116 int append_code(struct ir_remote *r, ir_code code, char *name)
117 {
118 struct ir_ncode *codes;
119 int count;
120
121 count = 0;
122 codes = r->codes;
123 while (codes->name != NULL) {
124 count++;
125 codes++;
126 }
127 if (count > MAX_CODES)
128 return (0);
129
130 codes->name = strdup(name);
131 strtoupper(codes->name);
132 codes->code = code;
133 return (1);
134 }
135
trim(char * s)136 char *trim(char *s)
137 {
138 char *end;
139
140 while (isspace(*s))
141 s++;
142 end = s + strlen(s) - 1;
143 while (end >= s) {
144 if (!isspace(*end)) {
145 end++;
146 *end = 0;
147 break;
148 }
149 end--;
150 }
151 return (s);
152 }
153
fill_struct(struct ir_remote * r,FILE * f,char ** desc)154 int fill_struct(struct ir_remote *r, FILE * f, char **desc)
155 {
156 char buffer[MAX_LINE_WIDTH], backup[MAX_LINE_WIDTH];
157 char *eq, *dp, *cr, *s;
158
159 while ((s = fgets(buffer, MAX_LINE_WIDTH, f)) != NULL) {
160 cr = strrchr(buffer, '\r');
161 if (cr != NULL)
162 *cr = 0;
163 cr = strrchr(buffer, '\n');
164 if (cr != NULL)
165 *cr = 0;
166 printf("%s\n", buffer);
167 cr = strchr(buffer, '#');
168 if (cr != NULL)
169 *cr = 0;
170
171 strcpy(backup, buffer);
172 eq = strchr(buffer, '=');
173 if (eq != NULL) {
174 *eq = 0;
175 eq++;
176 eq = trim(eq);
177 if (strcasecmp(buffer, "desc") == 0) {
178 /* todo */
179 if (*desc != NULL) {
180 fprintf(stderr, "%s: mulitple descriptions\n", progname);
181 break;
182 }
183 *desc = strdup(eq);
184 continue;
185 } else if (strcasecmp(buffer, "name") == 0) {
186 if (r->name != NULL) {
187 fprintf(stderr, "%s: multiple names\n", progname);
188 break;
189 }
190 if (strlen(eq) == 0)
191 continue;
192 r->name = strdup(eq);
193 if (r->name == NULL) {
194 fprintf(stderr, "%s: out of memory\n", progname);
195 }
196 strtoupper(r->name);
197 continue;
198 } else if (strcasecmp(buffer, "type") == 0) {
199 continue;
200 } else if (strcasecmp(buffer, "group") == 0) {
201 continue;
202 } else if (strcasecmp(buffer, "carrier") == 0) {
203 r->freq = (__u32) atof(eq);
204 continue;
205 } else if (strcasecmp(buffer, "repeat") == 0) {
206 r->min_repeat = atoi(eq);
207 continue;
208 } else if (strcasecmp(buffer, "pause") == 0) {
209 int n, gap;
210
211 n = get_val(eq, &gap, 0);
212 if (n > 1)
213 break;
214 if (n == 0)
215 continue;
216 /* may be zero for now, but we have to
217 check at the end */
218 if (gap > 0) {
219 break;
220 }
221 r->gap = abs(gap);
222 continue;
223 } else if (strcasecmp(buffer, "sleep") == 0) {
224 int n, gap;
225
226 /* no equivalent in LIRC */
227 if (r->gap == 0) {
228 n = get_val(eq, &gap, 0);
229 if (n == 1 && gap < 0) {
230 r->gap = (lirc_t) abs(gap);
231 }
232 }
233 continue;
234 } else if (strcasecmp(buffer, "zero") == 0) {
235 int a, b;
236
237 if (get_val(eq, &a, &b, 0) != 2 || a <= 0 || b >= 0) {
238 break;
239 }
240 r->pzero = (lirc_t) a;
241 r->szero = (lirc_t) abs(b);
242 continue;
243 } else if (strcasecmp(buffer, "one") == 0) {
244 int a, b;
245
246 if (get_val(eq, &a, &b, 0) != 2) {
247 break;
248 }
249 if (a < 0 && b > 0) {
250 r->pone = (lirc_t) b;
251 r->sone = (lirc_t) abs(a);
252 set_protocol(r, RC5);
253 continue;
254 }
255 r->pone = (lirc_t) a;
256 r->sone = (lirc_t) abs(b);
257 continue;
258 } else if (strcasecmp(buffer, "start") == 0) {
259 int a, b, n;
260
261 n = get_val(eq, &a, &b, 0);
262 if (is_rc5(r) && n == 1) {
263 if (a <= 0) {
264 break;
265 }
266 r->plead = (lirc_t) a;
267 continue;
268 }
269 if (n == 0) {
270 continue;
271 }
272 if (n != 2 || a <= 0 || b >= 0) {
273 break;
274 }
275 r->phead = (lirc_t) a;
276 r->shead = (lirc_t) abs(b);
277 continue;
278 } else if (strcasecmp(buffer, "stop") == 0) {
279 int n;
280 int a, b, c, d, e;
281
282 n = get_val(eq, &a, &b, &c, &d, &e, 0);
283 if (n == 5) {
284
285 if (a > 0 && c > 0 && e > 0 && b < 0 && d < 0 && a == e) {
286 r->ptrail = (lirc_t) a;
287 r->gap = (lirc_t) abs(b);
288 r->prepeat = (lirc_t) c;
289 r->srepeat = (lirc_t) abs(d);
290 if (e != a) {
291 break;
292 }
293 continue;
294 }
295 }
296 if (n == 0) {
297 r->ptrail = (lirc_t) 0;
298 continue;
299 }
300 if (n > 2 || a <= 0) {
301 break;
302 }
303 if (n == 2 && b < 0) {
304 if (r->gap == 0)
305 r->gap = abs(b);
306 }
307 r->ptrail = (lirc_t) a;
308 continue;
309 } else if (strcasecmp(buffer, "prefix") == 0) {
310 if (has_pre(r)) {
311 fprintf(stderr, "warning: multiple prefix tokens\n");
312 continue;
313 }
314 if (!get_data(eq, &r->pre_data, &r->pre_data_bits)) {
315 break;
316 }
317 continue;
318 } else if (strcasecmp(buffer, "suffix") == 0) {
319 if (has_post(r)) {
320 fprintf(stderr, "warning: multiple suffix tokens\n");
321 continue;
322 }
323 if (!get_data(eq, &r->post_data, &r->post_data_bits)) {
324 break;
325 }
326 continue;
327 } else if (strcasecmp(buffer, "include") == 0) {
328 FILE *nf;
329
330 nf = fopen(eq, "r");
331 if (nf == NULL) {
332 fprintf(stderr, "%s: could not open file %s\n", progname, eq);
333 perror(progname);
334 break;
335 }
336 if (!fill_struct(r, nf, desc)) {
337 fclose(nf);
338 return (0);
339 }
340 fclose(nf);
341 continue;
342 }
343 }
344 dp = strchr(buffer, ':');
345 if (dp != NULL) {
346 int bits;
347 ir_code code;
348
349 *dp = 0;
350 dp++;
351 dp = trim(dp);
352 get_data(buffer, &code, &bits);
353 if (r->bits == 0)
354 r->bits = bits;
355 else if (r->bits != bits) {
356 fprintf(stderr, "%s: variable bit length!\n", progname);
357 break;
358 }
359 if (!append_code(r, code, dp)) {
360 break;
361 }
362 continue;
363
364 }
365 if (strtok(buffer, " \t") == NULL) {
366 continue;
367 }
368 printf("%s\n", buffer);
369 }
370 if (s == NULL) {
371 if (r->gap == 0) {
372 if (r->repeat_gap != 0) {
373 r->gap = r->repeat_gap;
374 r->repeat_gap = 0;
375 } else {
376 fprintf(stderr, "%s: no gap!\n", progname);
377 return (0);
378 }
379 }
380 return (1);
381 }
382
383 fprintf(stderr, "%s: can't convert \"%s\"\n", progname, backup);
384 free_config(r);
385 return (0);
386 }
387
read_slinke(char * filename,char ** desc)388 struct ir_remote *read_slinke(char *filename, char **desc)
389 {
390 struct ir_remote *r;
391 FILE *f;
392
393 r = malloc(sizeof(*r));
394 if (r == NULL) {
395 fprintf(stderr, "%s: out of memory\n", progname);
396 return (NULL);
397 }
398 /* set defaults */
399 memset(r, 0, sizeof(*r));
400 set_protocol(r, SPACE_ENC);
401 r->eps = 20;
402 r->aeps = 200;
403
404 r->codes = malloc(sizeof(struct ir_ncode) * (MAX_CODES + 1));
405 if (r->codes == NULL) {
406 fprintf(stderr, "%s: out of memory\n", progname);
407 free(r);
408 return (NULL);
409 }
410 memset(r->codes, 0, sizeof(struct ir_ncode) * (MAX_CODES + 1));
411 f = fopen(filename, "r");
412 if (f == NULL) {
413 fprintf(stderr, "%s: could not open file %s\n", progname, filename);
414 perror(progname);
415 free(r->codes);
416 free(r);
417 return (NULL);
418 }
419 if (!fill_struct(r, f, desc)) {
420 fclose(f);
421 return (NULL);
422 }
423 fclose(f);
424 return (r);
425 }
426
get_pre_data(struct ir_remote * remote)427 void get_pre_data(struct ir_remote *remote)
428 {
429 struct ir_ncode *codes;
430 ir_code mask, last;
431 int count, i;
432
433 if (remote->bits == 0)
434 return;
435
436 mask = (-1);
437 codes = remote->codes;
438 if (codes->name != NULL) {
439 last = codes->code;
440 codes++;
441 }
442 if (codes->name == NULL)
443 return; /* at least 2 codes needed */
444 while (codes->name != NULL) {
445 mask &= ~(last ^ codes->code);
446 last = codes->code;
447 codes++;
448 }
449 count = 0;
450 while (mask & 0x8000000000000000LL) {
451 count++;
452 mask = mask << 1;
453 }
454 count -= sizeof(ir_code) * CHAR_BIT - remote->bits;
455 if (count > 0) {
456 mask = 0;
457 for (i = 0; i < count; i++) {
458 mask = mask << 1;
459 mask |= 1;
460 }
461 remote->bits -= count;
462 mask = mask << (remote->bits);
463 remote->pre_data_bits = count;
464 remote->pre_data = (last & mask) >> (remote->bits);
465
466 codes = remote->codes;
467 while (codes->name != NULL) {
468 codes->code &= ~mask;
469 codes++;
470 }
471 }
472 }
473
get_post_data(struct ir_remote * remote)474 void get_post_data(struct ir_remote *remote)
475 {
476 struct ir_ncode *codes;
477 ir_code mask, last;
478 int count, i;
479
480 if (remote->bits == 0)
481 return;
482
483 mask = (-1);
484 codes = remote->codes;
485 if (codes->name != NULL) {
486 last = codes->code;
487 codes++;
488 }
489 if (codes->name == NULL)
490 return; /* at least 2 codes needed */
491 while (codes->name != NULL) {
492 mask &= ~(last ^ codes->code);
493 last = codes->code;
494 codes++;
495 }
496 count = 0;
497 while (mask & 0x1) {
498 count++;
499 mask = mask >> 1;
500 }
501 if (count > 0) {
502 mask = 0;
503 for (i = 0; i < count; i++) {
504 mask = mask << 1;
505 mask |= 1;
506 }
507 remote->bits -= count;
508 remote->post_data_bits = count;
509 remote->post_data = last & mask;
510
511 codes = remote->codes;
512 while (codes->name != NULL) {
513 codes->code = codes->code >> count;
514 codes++;
515 }
516 }
517 }
518
main(int argc,char ** argv)519 int main(int argc, char **argv)
520 {
521 char *filename, *model, *brand, *description, *path, cwd[PATH_MAX + 1];
522 struct ir_remote *remote;
523 int fd;
524 FILE *fout;
525 int pre, post;
526
527 progname = argv[0];
528 model = brand = NULL;
529 pre = post = 0;
530 while (1) {
531 int c;
532 static struct option long_options[] = {
533 {"help", no_argument, NULL, 'h'},
534 {"version", no_argument, NULL, 'v'},
535 {"brand", required_argument, NULL, 'b'},
536 {"model", required_argument, NULL, 'm'},
537 {"pre", no_argument, NULL, 'p'},
538 {"post", no_argument, NULL, 'P'},
539 {0, 0, 0, 0}
540 };
541 c = getopt_long(argc, argv, "hvb:m:pP", long_options, NULL);
542 if (c == -1)
543 break;
544 switch (c) {
545 case 'h':
546 printf(usage, progname);
547 printf("\t -h --help\t\tdisplay this message\n");
548 printf("\t -v --version\t\tdisplay version\n\n");
549 printf("\t -b --brand\t\tremote control manufacturer\n");
550 printf("\t -m --model\t\tremote control model = name of new file\n");
551 exit(EXIT_SUCCESS);
552 case 'v':
553 printf("slinke-%s\n", VERSION);
554 exit(EXIT_SUCCESS);
555 case 'b':
556 brand = optarg;
557 break;
558 case 'm':
559 model = optarg;
560 break;
561 case 'p':
562 pre = 1;
563 break;
564 case 'P':
565 post = 1;
566 break;
567 default:
568 printf("Try %s -h for help!\n", progname);
569 exit(EXIT_FAILURE);
570 }
571 }
572 if (argc == 1) {
573 printf(usage, progname);
574 }
575 if (optind + 1 != argc) {
576 fprintf(stderr, "%s: invalid argument count\n", progname);
577 exit(EXIT_FAILURE);
578 }
579 filename = argv[optind];
580
581 path = strrchr(filename, '/');
582 if (path != NULL) {
583 char *help;
584
585 *path = 0;
586 help = path + 1;
587 path = filename;
588 filename = help;
589 if (getcwd(cwd, PATH_MAX) == NULL) {
590 fprintf(stderr, "%s: can't get current work directory\n", progname);
591 perror(progname);
592 return (EXIT_FAILURE);
593 }
594 chdir(path);
595 }
596 description = NULL;
597 remote = read_slinke(filename, &description);
598 if (remote == NULL) {
599 exit(EXIT_FAILURE);
600 }
601 if (model != NULL) {
602 if (remote->name != NULL)
603 free(remote->name);
604 remote->name = strdup(model);
605 if (remote->name == NULL) {
606 free_config(remote);
607 exit(EXIT_FAILURE);
608 }
609 }
610 if (pre)
611 get_pre_data(remote);
612 if (post)
613 get_post_data(remote);
614
615 if (remote->name == NULL) {
616 char newname[100];
617 char *cr;
618
619 if (description != NULL) {
620 printf("Description: %s\n", description);
621 }
622 printf("Please enter name: ");
623 fflush(stdout);
624 if (fgets(newname, 100, stdin) == NULL) {
625 free_config(remote);
626 exit(EXIT_FAILURE);
627 }
628 cr = strrchr(newname, '\n');
629 if (cr != NULL)
630 *cr = 0;
631 cr = strrchr(newname, '\r');
632 if (cr != NULL)
633 *cr = 0;
634
635 remote->name = strdup(newname);
636 if (remote->name == NULL) {
637 fprintf(stderr, "%s: out of memory\n", progname);
638 free_config(remote);
639 exit(EXIT_FAILURE);
640 }
641
642 }
643 if (path != NULL) {
644 chdir(cwd);
645 }
646 fd = open(remote->name, O_CREAT | O_EXCL | O_RDWR, 0644);
647 if (fd == -1) {
648 fprintf(stderr, "%s: could not open output file\n", progname);
649 perror(progname);
650 free_config(remote);
651 if (description != NULL)
652 free(description);
653 exit(EXIT_FAILURE);
654 }
655 fout = fdopen(fd, "w");
656 if (fout == NULL) {
657 fprintf(stderr, "%s: could not reopen output file\n", progname);
658 perror(progname);
659 free_config(remote);
660 if (description != NULL)
661 free(description);
662 exit(EXIT_FAILURE);
663 }
664 fprintf(fout,
665 "#\n"
666 "# This config file has been automatically converted from a device file\n"
667 "# found in the 06/26/00 release of the Windows Slink-e software\n"
668 "# package.\n" "#\n" "# Many thanks to Colby Boles of Nirvis Systems Inc. for allowing us to\n"
669 "# use these files.\n" "#\n" "# The original filename was: \"%s\"\n", filename);
670 if (description != NULL) {
671 fprintf(fout, "#\n" "# The original description for this device was:\n" "#\n" "# %s\n" "#\n",
672 description);
673 free(description);
674 }
675 fprintf(fout, "\n\n");
676 fprint_remote_head(fout, remote);
677 fprint_remote_signals(fout, remote);
678 fprint_remote_foot(fout, remote);
679 fclose(fout);
680
681 free_config(remote);
682 exit(EXIT_SUCCESS);
683 }
684