LIRC libraries
Linux Infrared Remote Control
Loading...
Searching...
No Matches
irrecord.c
Go to the documentation of this file.
1/***************************************************************************
2** irrecord.c **************************************************************
3****************************************************************************
4*
5* irrecord - library for recording IR-codes for usage with lircd
6*
7* Copyright (C) 1998,99 Christoph Bartelmus <lirc@bartelmus.de>
8*
9*/
10
16#define _GNU_SOURCE
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <stdint.h>
23#include <unistd.h>
24#include <poll.h>
25
26#include "lirc_private.h"
27#include "irrecord.h"
28
29/* -------------------------- C file -------------------------------- */
30
31static const logchannel_t logchannel = LOG_LIB;
32
33// forwards
34static lirc_t emulation_readdata(lirc_t timeout);
35
36// Constants
37static const struct driver hw_emulation = {
38 .name = "emulation",
39 .device = "/dev/null",
40 .features = LIRC_CAN_REC_MODE2,
41 .send_mode = 0,
42 .rec_mode = LIRC_MODE_MODE2,
43 .code_length = 0,
44 .init_func = NULL,
45 .deinit_func = NULL,
46 .send_func = NULL,
47 .rec_func = NULL,
48 .decode_func = NULL,
49 .drvctl_func = NULL,
50 .readdata = emulation_readdata,
51 .open_func = default_open,
52 .close_func = default_close,
53 .api_version = 2,
54 .driver_version = "0.9.2"
55};
56
57static const int IR_CODE_NODE_SIZE = sizeof(struct ir_code_node);
58
59// Globals
60
61struct ir_remote remote;
62unsigned int eps = 30;
63lirc_t aeps = 100;
64
65// Static data
66
67static lirc_t signals[MAX_SIGNALS];
68static struct ir_remote* emulation_data;
69static struct ir_ncode* next_code = NULL;
70static struct ir_ncode* current_code = NULL;
71static int current_index = 0;
72static int current_rep = 0;
73
74static struct lengths* first_space = NULL;
75static struct lengths* first_pulse = NULL;
76static struct lengths* first_sum = NULL;
77static struct lengths* first_gap = NULL;
78static struct lengths* first_repeat_gap = NULL;
79static struct lengths* first_signal_length = NULL;
80static struct lengths* first_headerp = NULL;
81static struct lengths* first_headers = NULL;
82static struct lengths* first_1lead = NULL;
83static struct lengths* first_3lead = NULL;
84static struct lengths* first_trail = NULL;
85static struct lengths* first_repeatp = NULL;
86static struct lengths* first_repeats = NULL;
87
88static uint32_t lengths[MAX_SIGNALS];
89static uint32_t first_length, first_lengths, second_lengths;
90static unsigned int count, count_spaces, count_signals;
91static unsigned int count_3repeats, count_5repeats;
92
93
94// Functions
95
97void btn_state_set_message(struct button_state* state, const char* fmt, ...)
98{
99 va_list ap;
100
101 va_start(ap, fmt);
102 vsnprintf(state->message, sizeof(state->message), fmt, ap);
103 va_end(ap);
104}
105
106
107static void fprint_copyright(FILE* fout)
108{
109 fprintf(fout, "\n"
110 "# Please take the time to finish this file as described in\n"
111 "# https://sourceforge.net/p/lirc-remotes/wiki/Checklist/\n"
112 "# and make it available to others by sending it to\n"
113 "# <lirc@bartelmus.de>\n");
114}
115
116
119{
120 struct pollfd pfd = {
121 .fd = curr_driver->fd, .events = POLLIN, .revents = 0};
122 int ret;
123
124 do {
125 do {
126 ret = curl_poll(&pfd, 1, 0);
127 } while (ret == -1 && errno == EINTR);
128 if (ret == -1) {
129 log_perror_err("availabledata: curl_poll() failed");
130 continue;
131 }
132 } while (ret == -1);
133
134 return pfd.revents & POLLIN ? 1 : 0;
135}
136
137
139void flushhw(void)
140{
141 size_t size = 1;
142 char buffer[PACKET_SIZE];
143
144 switch (curr_driver->rec_mode) {
145 case LIRC_MODE_MODE2:
146 while (availabledata())
148 return;
149 case LIRC_MODE_LIRCCODE:
150 size = curr_driver->code_length / CHAR_BIT;
151 if (curr_driver->code_length % CHAR_BIT)
152 size++;
153 break;
154 }
155 while (read(curr_driver->fd, buffer, size) == size)
156 ;
157}
158
159
161int resethw(int started_as_root)
162{
163 int flags;
164
165 if (started_as_root)
166 if (seteuid(0) == -1)
167 log_error("Cannot reset root uid");
170 if (curr_driver->init_func) {
171 if (!curr_driver->init_func()) {
172 drop_sudo_root(seteuid);
173 return 0;
174 }
175 }
176 flags = fcntl(curr_driver->fd, F_GETFL, 0);
177 if (flags == -1 ||
178 fcntl(curr_driver->fd, F_SETFL, flags | O_NONBLOCK) == -1) {
181 drop_sudo_root(seteuid);
182 return 0;
183 }
184 drop_sudo_root(seteuid);
185 return 1;
186}
187
188
189void gap_state_init(struct gap_state* state)
190{
191 memset(state, 0, sizeof(struct gap_state));
192}
193
194
196{
197 count = 0;
198 count_spaces = 0;
199 count_3repeats = 0;
200 count_5repeats = 0;
201 count_signals = 0;
202 first_length = 0;
203 first_lengths = 0;
204 second_lengths = 0;
205 memset(state, 0, sizeof(struct lengths_state));
206 state->first_signal = -1;
207 state->retval = 1;
208}
209
210
212{
213 memset(state, 0, sizeof(struct toggle_state));
214 state->retries = 30;
215 state->retval = EXIT_SUCCESS;
216}
217
218
219void button_state_init(struct button_state* state, int started_as_root)
220{
221 memset(state, 0, sizeof(struct button_state));
222 state->started_as_root = started_as_root;
223 state->retval = EXIT_SUCCESS;
224}
225
226
227static lirc_t calc_signal(struct lengths* len)
228{
229 if (len->count == 0)
230 return 0;
231 return (lirc_t)(len->sum / len->count);
232}
233
234
235static void set_toggle_bit_mask(struct ir_remote* remote, ir_code xor)
236{
237 ir_code mask;
238 struct ir_ncode* codes;
239 int bits;
240
241 if (!remote->codes)
242 return;
243
244 bits = bit_count(remote);
245 mask = ((ir_code)1) << (bits - 1);
246 while (mask) {
247 if (mask == xor)
248 break;
249 mask = mask >> 1;
250 }
251 if (mask) {
252 remote->toggle_bit_mask = xor;
253
254 codes = remote->codes;
255 while (codes->name != NULL) {
256 codes->code &= ~xor;
257 codes++;
258 }
259 }
260 /* Sharp, Denon and some others use a toggle_mask */
261 else if (bits == 15 && xor == 0x3ff) {
262 remote->toggle_mask = xor;
263 } else {
264 remote->toggle_bit_mask = xor;
265 }
266}
267
268
269void get_pre_data(struct ir_remote* remote)
270{
271 struct ir_ncode* codes;
272 ir_code mask, last;
273 int count, i;
274 struct ir_code_node* n;
275
276 if (remote->bits == 0)
277 return;
278 mask = (-1);
279 codes = remote->codes;
280 if (codes->name == NULL)
281 return; /* at least 2 codes needed */
282 last = codes->code;
283 codes++;
284 if (codes->name == NULL)
285 return; /* at least 2 codes needed */
286 while (codes->name != NULL) {
287 mask &= ~(last ^ codes->code);
288 last = codes->code;
289 for (n = codes->next; n != NULL; n = n->next) {
290 mask &= ~(last ^ n->code);
291 last = n->code;
292 }
293 codes++;
294 }
295 count = 0;
296 while (mask & 0x8000000000000000LL) {
297 count++;
298 mask = mask << 1;
299 }
300 count -= sizeof(ir_code) * CHAR_BIT - remote->bits;
301
302 /* only "even" numbers should go to pre/post data */
303 if (count % 8 && (remote->bits - count) % 8)
304 count -= count % 8;
305 if (count > 0) {
306 mask = 0;
307 for (i = 0; i < count; i++) {
308 mask = mask << 1;
309 mask |= 1;
310 }
311 remote->bits -= count;
312 mask = mask << (remote->bits);
313 remote->pre_data_bits = count;
314 remote->pre_data = (last & mask) >> (remote->bits);
315
316 codes = remote->codes;
317 while (codes->name != NULL) {
318 codes->code &= ~mask;
319 for (n = codes->next; n != NULL; n = n->next)
320 n->code &= ~mask;
321 codes++;
322 }
323 }
324}
325
326
327void get_post_data(struct ir_remote* remote)
328{
329 struct ir_ncode* codes;
330 ir_code mask, last;
331 int count, i;
332 struct ir_code_node* n;
333
334 if (remote->bits == 0)
335 return;
336
337 mask = (-1);
338 codes = remote->codes;
339 if (codes->name == NULL)
340 return; /* at least 2 codes needed */
341 last = codes->code;
342 codes++;
343 if (codes->name == NULL)
344 return; /* at least 2 codes needed */
345 while (codes->name != NULL) {
346 mask &= ~(last ^ codes->code);
347 last = codes->code;
348 for (n = codes->next; n != NULL; n = n->next) {
349 mask &= ~(last ^ n->code);
350 last = n->code;
351 }
352 codes++;
353 }
354 count = 0;
355 while (mask & 0x1) {
356 count++;
357 mask = mask >> 1;
358 }
359 /* only "even" numbers should go to pre/post data */
360 if (count % 8 && (remote->bits - count) % 8)
361 count -= count % 8;
362 if (count > 0) {
363 mask = 0;
364 for (i = 0; i < count; i++) {
365 mask = mask << 1;
366 mask |= 1;
367 }
368 remote->bits -= count;
369 remote->post_data_bits = count;
370 remote->post_data = last & mask;
371
372 codes = remote->codes;
373 while (codes->name != NULL) {
374 codes->code = codes->code >> count;
375 for (n = codes->next; n != NULL; n = n->next)
376 n->code = n->code >> count;
377 codes++;
378 }
379 }
380}
381
382
383void remove_pre_data(struct ir_remote* remote)
384{
385 struct ir_ncode* codes;
386 struct ir_code_node* n;
387
388 if (remote->pre_data_bits == 0
389 || remote->pre_p != 0
390 || remote->pre_s != 0)
391 return;
392 for (codes = remote->codes; codes->name != NULL; codes++) {
393 codes->code |= remote->pre_data << remote->bits;
394 for (n = codes->next; n != NULL; n = n->next)
395 n->code |= remote->pre_data << remote->bits;
396 }
397 remote->bits += remote->pre_data_bits;
398 remote->pre_data = 0;
399 remote->pre_data_bits = 0;
400}
401
402
403void remove_post_data(struct ir_remote* remote)
404{
405 struct ir_ncode* codes;
406 struct ir_code_node* n;
407
408 if (remote->post_data_bits == 0)
409 return;
410 for (codes = remote->codes; codes->name != NULL; codes++) {
411 codes->code <<= remote->post_data_bits;
412 codes->code |= remote->post_data;
413 for (n = codes->next; n != NULL; n = n->next) {
414 n->code <<= remote->post_data_bits;
415 n->code |= remote->post_data;
416 }
417 }
418 remote->bits += remote->post_data_bits;
419 remote->post_data = 0;
420 remote->post_data_bits = 0;
421}
422
423
424void invert_data(struct ir_remote* remote)
425{
426 struct ir_ncode* codes;
427 ir_code mask;
428 lirc_t p, s;
429 struct ir_code_node* n;
430
431 /* swap one, zero */
432 p = remote->pone;
433 s = remote->sone;
434 remote->pone = remote->pzero;
435 remote->sone = remote->szero;
436 remote->pzero = p;
437 remote->szero = s;
438
439 /* invert pre_data */
440 if (has_pre(remote)) {
441 mask = gen_mask(remote->pre_data_bits);
442 remote->pre_data ^= mask;
443 }
444 /* invert post_data */
445 if (has_post(remote)) {
446 mask = gen_mask(remote->post_data_bits);
447 remote->post_data ^= mask;
448 }
449
450 if (remote->bits == 0)
451 return;
452
453 /* invert codes */
454 mask = gen_mask(remote->bits);
455 for (codes = remote->codes; codes->name != NULL; codes++) {
456 codes->code ^= mask;
457 for (n = codes->next; n != NULL; n = n->next)
458 n->code ^= mask;
459 }
460}
461
462
463void remove_trail(struct ir_remote* remote)
464{
465 int extra_bit;
466
467 if (!is_space_enc(remote))
468 return;
469 if (remote->ptrail == 0)
470 return;
471 if (expect(remote, remote->pone, remote->pzero)
472 || expect(remote, remote->pzero, remote->pone))
473 return;
474 if (!(expect(remote, remote->sone, remote->szero)
475 && expect(remote, remote->szero, remote->sone)))
476 return;
477 if (expect(remote, remote->ptrail, remote->pone))
478 extra_bit = 1;
479 else if (expect(remote, remote->ptrail, remote->pzero))
480 extra_bit = 0;
481 else
482 return;
483
484 remote->post_data_bits++;
485 remote->post_data <<= 1;
486 remote->post_data |= extra_bit;
487 remote->ptrail = 0;
488}
489
490
491void for_each_remote(struct ir_remote* remotes, remote_func func)
492{
493 struct ir_remote* remote;
494
495 remote = remotes;
496 while (remote != NULL) {
497 func(remote);
498 remote = remote->next;
499 }
500}
501
502
503static int mywaitfordata(uint32_t maxusec)
504{
505 int ret;
506 struct pollfd pfd = {
507 .fd = curr_driver->fd, .events = POLLIN, .revents = 0};
508
509 do {
510 ret = curl_poll(&pfd, 1, maxusec / 1000);
511 } while (ret == -1 && errno == EINTR);
512
513 if (ret == -1 && errno != EINTR)
514 log_perror_err("mywaitfordata: curl_poll() failed");
515 return (pfd.revents & POLLIN) != 0;
516}
517
518
519static lirc_t emulation_readdata(lirc_t timeout)
520{
521 static lirc_t sum = 0;
522 lirc_t data = 0;
523
524 if (current_code == NULL) {
525 data = 1000000;
526 if (next_code)
527 current_code = next_code;
528 else
529 current_code = emulation_data->codes;
530 current_rep = 0;
531 sum = 0;
532 } else {
533 if (current_code->name == NULL) {
534 log_warn("%s: no data found", emulation_data->name);
535 data = 0;
536 }
537 if (current_index >= current_code->length) {
538 if (next_code) {
539 current_code = next_code;
540 } else {
541 current_rep++;
542 if (current_rep > 2) {
543 current_code++;
544 current_rep = 0;
545 data = 1000000;
546 }
547 }
548 current_index = 0;
549 if (current_code->name == NULL) {
550 current_code = NULL;
551 return emulation_readdata(timeout);
552 }
553 if (data == 0) {
554 if (is_const(emulation_data))
555 data = emulation_data->gap - sum;
556 else
557 data = emulation_data->gap;
558 }
559
560 sum = 0;
561 } else {
562 data = current_code->signals[current_index];
563 if ((current_index % 2) == 0)
564 data |= PULSE_BIT;
565 current_index++;
566 sum += data & PULSE_MASK;
567 }
568 }
569 log_debug("delivering: %c%u\n",
570 data & PULSE_BIT ? 'p':'s', data & PULSE_MASK);
571 return data;
572}
573
574
575static struct lengths* new_length(lirc_t length)
576{
577 struct lengths* l;
578
579 l = malloc(sizeof(struct lengths));
580 if (l == NULL)
581 return NULL;
582 l->count = 1;
583 l->sum = length;
584 l->lower_bound = length / 100 * 100;
585 l->upper_bound = length / 100 * 100 + 99;
586 l->min = l->max = length;
587 l->next = NULL;
588 return l;
589}
590
591
592void unlink_length(struct lengths** first, struct lengths* remove)
593{
594 struct lengths* last;
595 struct lengths* scan;
596
597 if (remove == *first) {
598 *first = remove->next;
599 remove->next = NULL;
600 return;
601 }
602 scan = (*first)->next;
603 last = *first;
604 while (scan) {
605 if (scan == remove) {
606 last->next = remove->next;
607 remove->next = NULL;
608 return;
609 }
610 last = scan;
611 scan = scan->next;
612 }
613 log_error("unlink_length(): report this bug!");
614}
615
616
617int add_length(struct lengths** first, lirc_t length)
618{
619 struct lengths* l;
620 struct lengths* last;
621
622 if (*first == NULL) {
623 *first = new_length(length);
624 if (*first == NULL)
625 return 0;
626 return 1;
627 }
628 l = *first;
629 while (l != NULL) {
630 if (l->lower_bound <= length && length <= l->upper_bound) {
631 l->count++;
632 l->sum += length;
633 l->min = min(l->min, length);
634 l->max = max(l->max, length);
635 return 1;
636 }
637 last = l;
638 l = l->next;
639 }
640 last->next = new_length(length);
641 if (last->next == NULL)
642 return 0;
643 return 1;
644}
645
646
647void free_lengths(struct lengths** firstp)
648{
649 struct lengths* first;
650 struct lengths* next;
651
652 first = *firstp;
653 if (first == NULL)
654 return;
655 while (first != NULL) {
656 next = first->next;
657 free(first);
658 first = next;
659 }
660 *firstp = NULL;
661}
662
663
665{
666 free_lengths(&first_space);
667 free_lengths(&first_pulse);
668 free_lengths(&first_sum);
669 free_lengths(&first_gap);
670 free_lengths(&first_repeat_gap);
671 free_lengths(&first_signal_length);
672 free_lengths(&first_headerp);
673 free_lengths(&first_headers);
674 free_lengths(&first_1lead);
675 free_lengths(&first_3lead);
676 free_lengths(&first_trail);
677 free_lengths(&first_repeatp);
678 free_lengths(&first_repeats);
679}
680
681
682static void merge_lengths(struct lengths* first)
683{
684 struct lengths* l;
685 struct lengths* inner;
686 struct lengths* last;
687 uint32_t new_sum;
688 int new_count;
689
690 l = first;
691 while (l != NULL) {
692 last = l;
693 inner = l->next;
694 while (inner != NULL) {
695 new_sum = l->sum + inner->sum;
696 new_count = l->count + inner->count;
697
698 if ((l->max <= new_sum / new_count + aeps
699 && l->min + aeps >= new_sum / new_count
700 && inner->max <= new_sum / new_count + aeps
701 && inner->min + aeps >= new_sum / new_count)
702 || (l->max <= new_sum / new_count * (100 + eps)
703 && l->min >= new_sum / new_count * (100 - eps)
704 && inner->max <= new_sum / new_count *
705 (100 + eps)
706 && inner->min >= new_sum / new_count *
707 (100 - eps))) {
708 l->sum = new_sum;
709 l->count = new_count;
710 l->upper_bound = max(l->upper_bound,
711 inner->upper_bound);
712 l->lower_bound = min(l->lower_bound,
713 inner->lower_bound);
714 l->min = min(l->min, inner->min);
715 l->max = max(l->max, inner->max);
716
717 last->next = inner->next;
718 free(inner);
719 inner = last;
720 }
721 last = inner;
722 inner = inner->next;
723 }
724 l = l->next;
725 }
726 for (l = first; l != NULL; l = l->next) {
727 log_debug("%d x %u [%u,%u]",
728 l->count, (uint32_t)calc_signal(l),
729 (uint32_t)l->min, (uint32_t)l->max);
730 }
731}
732
733
739static struct lengths* get_max_length(struct lengths* first,
740 unsigned int* sump)
741{
742 unsigned int sum;
743 struct lengths* scan;
744 struct lengths* max_length;
745
746 if (first == NULL)
747 return NULL;
748 max_length = first;
749 sum = first->count;
750
751 if (first->count > 0)
752 log_debug("%u x %u", first->count,
753 (uint32_t)calc_signal(first));
754 scan = first->next;
755 while (scan) {
756 if (scan->count > max_length->count)
757 max_length = scan;
758 sum += scan->count;
759 log_debug(
760 "%u x %u",
761 scan->count,
762 (uint32_t)calc_signal(scan));
763 scan = scan->next;
764 }
765 if (sump != NULL)
766 *sump = sum;
767 return max_length;
768}
769
770
771int get_trail_length(struct ir_remote* remote, int interactive)
772{
773 unsigned int sum = 0, max_count;
774 struct lengths* max_length;
775
776 if (is_biphase(remote))
777 return 1;
778
779 max_length = get_max_length(first_trail, &sum);
780 max_count = max_length->count;
781 log_debug(
782 "get_trail_length(): sum: %u, max_count %u",
783 sum, max_count);
784 if (max_count >= sum * TH_TRAIL / 100) {
785 log_debug("Found trail pulse: %lu",
786 (uint32_t)calc_signal(max_length));
787 remote->ptrail = calc_signal(max_length);
788 return 1;
789 }
790 log_debug("No trail pulse found.");
791 return 1;
792}
793
794
795int get_lead_length(struct ir_remote* remote, int interactive)
796{
797 unsigned int sum = 0, max_count;
798 struct lengths* first_lead;
799 struct lengths* max_length;
800 struct lengths* max2_length;
801 lirc_t a, b, swap;
802
803 if (!is_biphase(remote) || has_header(remote))
804 return 1;
805 if (is_rc6(remote))
806 return 1;
807
808 first_lead = has_header(remote) ? first_3lead : first_1lead;
809 max_length = get_max_length(first_lead, &sum);
810 max_count = max_length->count;
811 log_debug(
812 "get_lead_length(): sum: %u, max_count %u",
813 sum, max_count);
814 if (max_count >= sum * TH_LEAD / 100) {
815 log_debug(
816 "Found lead pulse: %lu",
817 (uint32_t)calc_signal(max_length));
818 remote->plead = calc_signal(max_length);
819 return 1;
820 }
821 unlink_length(&first_lead, max_length);
822 max2_length = get_max_length(first_lead, &sum);
823 max_length->next = first_lead;
824 first_lead = max_length;
825
826 a = calc_signal(max_length);
827 b = calc_signal(max2_length);
828 if (a > b) {
829 swap = a;
830 a = b;
831 b = swap;
832 }
833 if (abs(2 * a - b) < b * eps / 100 || abs(2 * a - b) < aeps) {
834 log_debug(
835 "Found hidden lead pulse: %lu",
836 (uint32_t)a);
837 remote->plead = a;
838 return 1;
839 }
840 log_debug("No lead pulse found.");
841 return 1;
842}
843
844
845int get_header_length(struct ir_remote* remote, int interactive)
846{
847 unsigned int sum, max_count;
848 lirc_t headerp, headers;
849 struct lengths* max_plength;
850 struct lengths* max_slength;
851
852 if (first_headerp != NULL) {
853 max_plength = get_max_length(first_headerp, &sum);
854 max_count = max_plength->count;
855 } else {
856 log_debug("No header data.");
857 return 1;
858 }
859 log_debug(
860 "get_header_length(): sum: %u, max_count %u",
861 sum, max_count);
862
863 if (max_count >= sum * TH_HEADER / 100) {
864 max_slength = get_max_length(first_headers, &sum);
865 max_count = max_slength->count;
866 log_debug(
867 "get_header_length(): sum: %u, max_count %u",
868 sum, max_count);
869 if (max_count >= sum * TH_HEADER / 100) {
870 headerp = calc_signal(max_plength);
871 headers = calc_signal(max_slength);
872
873 log_debug(
874 "Found possible header: %lu %lu",
875 (uint32_t)headerp,
876 (uint32_t)headers);
877 remote->phead = headerp;
878 remote->shead = headers;
879 if (first_lengths < second_lengths) {
880 log_debug(
881 "Header is not being repeated.");
882 remote->flags |= NO_HEAD_REP;
883 }
884 return 1;
885 }
886 }
887 log_debug("No header found.");
888 return 1;
889}
890
891
892int get_repeat_length(struct ir_remote* remote, int interactive)
893{
894 unsigned int sum = 0, max_count;
895 lirc_t repeatp, repeats, repeat_gap;
896 struct lengths* max_plength;
897 struct lengths* max_slength;
898
899 if (!((count_3repeats > SAMPLES / 2 ? 1 : 0) ^
900 (count_5repeats > SAMPLES / 2 ? 1 : 0))) {
901 if (count_3repeats > SAMPLES / 2
902 || count_5repeats > SAMPLES / 2) {
903 log_warn("Repeat inconsistency.");
904 return 0;
905 }
906 log_debug("No repeat code found.");
907 return 1;
908 }
909
910 max_plength = get_max_length(first_repeatp, &sum);
911 max_count = max_plength->count;
912 log_debug(
913 "get_repeat_length(): sum: %u, max_count %u",
914 sum, max_count);
915 if (max_count >= sum * TH_REPEAT / 100) {
916 max_slength = get_max_length(first_repeats, &sum);
917 max_count = max_slength->count;
918 log_debug(
919 "get_repeat_length(): sum: %u, max_count %u",
920 sum, max_count);
921 if (max_count >= sum * TH_REPEAT / 100) {
922 if (count_5repeats > count_3repeats
923 && !has_header(remote)) {
924 log_warn(
925 "Repeat code has header,"
926 " but no header found!");
927 return 0;
928 }
929 if (count_5repeats > count_3repeats
930 && has_header(remote))
931 remote->flags |= REPEAT_HEADER;
932 repeatp = calc_signal(max_plength);
933 repeats = calc_signal(max_slength);
934
935 log_debug(
936 "Found repeat code: %lu %lu",
937 (uint32_t)repeatp,
938 (uint32_t)repeats);
939 remote->prepeat = repeatp;
940 remote->srepeat = repeats;
941 if (!(remote->flags & CONST_LENGTH)) {
942 max_slength = get_max_length(first_repeat_gap,
943 NULL);
944 repeat_gap = calc_signal(max_slength);
945 log_debug(
946 "Found repeat gap: %lu",
947 (uint32_t)repeat_gap);
948 remote->repeat_gap = repeat_gap;
949 }
950 return 1;
951 }
952 }
953 log_debug("No repeat header found.");
954 return 1;
955}
956
957
958void get_scheme(struct ir_remote* remote, int interactive)
959{
960 unsigned int i, length = 0, sum = 0;
961 struct lengths* maxp;
962 struct lengths* max2p;
963 struct lengths* maxs;
964 struct lengths* max2s;
965
966 for (i = 1; i < MAX_SIGNALS; i++) {
967 if (lengths[i] > lengths[length])
968 length = i;
969 sum += lengths[i];
970 if (lengths[i] > 0)
971 log_debug("%u: %u", i, lengths[i]);
972 }
973 log_debug("get_scheme(): sum: %u length: %u signals: %u"
974 " first_lengths: %u second_lengths: %u\n",
975 sum, length + 1, lengths[length],
976 first_lengths, second_lengths);
977 /* FIXME !!! this heuristic is too bad */
978 if (lengths[length] >= TH_SPACE_ENC * sum / 100) {
979 length++;
980 log_debug(
981 "Space/pulse encoded remote control found.");
982 log_debug("Signal length is %u.", length);
983 /* this is not yet the number of bits */
984 remote->bits = length;
985 set_protocol(remote, SPACE_ENC);
986 return;
987 }
988 maxp = get_max_length(first_pulse, NULL);
989 unlink_length(&first_pulse, maxp);
990 if (first_pulse == NULL)
991 first_pulse = maxp;
992 max2p = get_max_length(first_pulse, NULL);
993 maxp->next = first_pulse;
994 first_pulse = maxp;
995
996 maxs = get_max_length(first_space, NULL);
997 unlink_length(&first_space, maxs);
998 if (first_space == NULL) {
999 first_space = maxs;
1000 } else {
1001 max2s = get_max_length(first_space, NULL);
1002 maxs->next = first_space;
1003 first_space = maxs;
1004
1005 maxs = get_max_length(first_space, NULL);
1006
1007 if (length > 20
1008 && (calc_signal(maxp) < TH_RC6_SIGNAL
1009 || calc_signal(max2p) < TH_RC6_SIGNAL)
1010 && (calc_signal(maxs) < TH_RC6_SIGNAL
1011 || calc_signal(max2s) < TH_RC6_SIGNAL)) {
1012 log_debug("RC-6 remote control found.");
1013 set_protocol(remote, RC6);
1014 } else {
1015 log_debug("RC-5 remote control found.");
1016 set_protocol(remote, RC5);
1017 }
1018 return;
1019 }
1020 length++;
1021 log_debug("Suspicious data length: %u.", length);
1022 /* this is not yet the number of bits */
1023 remote->bits = length;
1024 set_protocol(remote, SPACE_ENC);
1025}
1026
1027
1028int get_data_length(struct ir_remote* remote, int interactive)
1029{
1030 unsigned int sum = 0, max_count;
1031 lirc_t p1, p2, s1, s2;
1032 struct lengths* max_plength;
1033 struct lengths* max_slength;
1034 struct lengths* max2_plength;
1035 struct lengths* max2_slength;
1036
1037 max_plength = get_max_length(first_pulse, &sum);
1038 max_count = max_plength->count;
1039 log_debug("get_data_length(): sum: %u, max_count %u",
1040 sum, max_count);
1041
1042 if (max_count >= sum * TH_IS_BIT / 100) {
1043 unlink_length(&first_pulse, max_plength);
1044
1045 max2_plength = get_max_length(first_pulse, NULL);
1046 if (max2_plength != NULL)
1047 if (max2_plength->count < max_count * TH_IS_BIT / 100)
1048 max2_plength = NULL;
1049 log_debug("Pulse candidates: ");
1050 log_debug("%u x %u", max_plength->count,
1051 (uint32_t)calc_signal(max_plength));
1052 if (max2_plength)
1053 log_debug(", %u x %u",
1054 max2_plength->count,
1055 (uint32_t)calc_signal(max2_plength));
1056
1057 max_slength = get_max_length(first_space, &sum);
1058 max_count = max_slength->count;
1059 log_debug(
1060 "get_data_length(): sum: %u, max_count %u",
1061 sum, max_count);
1062 if (max_count >= sum * TH_IS_BIT / 100) {
1063 unlink_length(&first_space, max_slength);
1064
1065 max2_slength = get_max_length(first_space, NULL);
1066 if (max2_slength != NULL)
1067 if (max2_slength->count <
1068 max_count * TH_IS_BIT / 100)
1069 max2_slength = NULL;
1070 if (max_count >= sum * TH_IS_BIT / 100) {
1071 log_debug("Space candidates: ");
1072 log_debug(
1073 "%u x %u",
1074 max_slength->count,
1075 (uint32_t)calc_signal(max_slength));
1076 if (max2_slength) {
1077 log_debug(
1078 "%u x %u",
1079 max2_slength->count,
1080 (uint32_t)calc_signal(max2_slength));
1081 }
1082 }
1083 remote->eps = eps;
1084 remote->aeps = aeps;
1085 if (is_biphase(remote)) {
1086 if (max2_plength == NULL
1087 || max2_slength == NULL) {
1088 log_notice(
1089 "Unknown encoding found.");
1090 return 0;
1091 }
1092 log_debug(
1093 "Signals are biphase encoded.");
1094 p1 = calc_signal(max_plength);
1095 p2 = calc_signal(max2_plength);
1096 s1 = calc_signal(max_slength);
1097 s2 = calc_signal(max2_slength);
1098
1099 remote->pone =
1100 (min(p1, p2) + max(p1, p2) / 2) / 2;
1101 remote->sone =
1102 (min(s1, s2) + max(s1, s2) / 2) / 2;
1103 remote->pzero = remote->pone;
1104 remote->szero = remote->sone;
1105 } else {
1106 if (max2_plength == NULL
1107 && max2_slength == NULL) {
1108 log_notice(
1109 "No encoding found");
1110 return 0;
1111 }
1112 if (max2_plength && max2_slength) {
1113 log_notice(
1114 "Unknown encoding found.");
1115 return 0;
1116 }
1117 p1 = calc_signal(max_plength);
1118 s1 = calc_signal(max_slength);
1119 if (max2_plength) {
1120 p2 = calc_signal(max2_plength);
1121 log_debug("Signals are pulse encoded.");
1122 remote->pone = max(p1, p2);
1123 remote->sone = s1;
1124 remote->pzero = min(p1, p2);
1125 remote->szero = s1;
1126 if (expect(remote, remote->ptrail, p1)
1127 || expect(remote, remote->ptrail,
1128 p2))
1129 remote->ptrail = 0;
1130 } else {
1131 s2 = calc_signal(max2_slength);
1132 log_debug("Signals are space encoded.");
1133 remote->pone = p1;
1134 remote->sone = max(s1, s2);
1135 remote->pzero = p1;
1136 remote->szero = min(s1, s2);
1137 }
1138 }
1139 if (has_header(remote)
1140 && (!has_repeat(remote)
1141 || remote->flags & NO_HEAD_REP)) {
1142 if (!is_biphase(remote)
1143 && ((expect(remote, remote->phead,
1144 remote->pone)
1145 && expect(remote,
1146 remote->shead,
1147 remote->sone))
1148 || (expect(remote,
1149 remote->phead,
1150 remote->pzero)
1151 && expect(remote,
1152 remote->shead,
1153 remote->szero)))) {
1154 remote->phead = remote->shead = 0;
1155 remote->flags &= ~NO_HEAD_REP;
1156 log_debug(
1157 "Removed header.");
1158 }
1159 if (is_biphase(remote)
1160 && expect(remote,
1161 remote->shead,
1162 remote->sone)) {
1163 remote->plead = remote->phead;
1164 remote->phead = remote->shead = 0;
1165 remote->flags &= ~NO_HEAD_REP;
1166 log_debug(
1167 "Removed header.");
1168 }
1169 }
1170 if (is_biphase(remote)) {
1171 struct lengths* signal_length;
1172 lirc_t data_length;
1173
1174 signal_length =
1175 get_max_length(first_signal_length,
1176 NULL);
1177 data_length =
1178 calc_signal(signal_length) -
1179 remote->plead - remote->phead -
1180 remote->shead +
1181 /* + 1/2 bit */
1182 (remote->pone + remote->sone) / 2;
1183 remote->bits = data_length / (remote->pone +
1184 remote->sone);
1185 if (is_rc6(remote))
1186 remote->bits--;
1187 } else {
1188 remote->bits =
1189 (remote->bits -
1190 (has_header(remote) ? 2 : 0) + 1 -
1191 (remote->ptrail > 0 ? 2 : 0)) / 2;
1192 }
1193 log_debug(
1194 "Signal length is %d",
1195 remote->bits);
1196 free_lengths(&max_plength);
1197 free_lengths(&max_slength);
1198 return 1;
1199 }
1200 free_lengths(&max_plength);
1201 }
1202 log_notice("Could not find data lengths.");
1203 return 0;
1204}
1205
1206
1208 struct ir_remote* remote)
1209{
1210 while (availabledata())
1211 curr_driver->rec_func(NULL);
1212 if (!mywaitfordata(10000000)) {
1213 free_lengths(&(state->gaps));
1214 return STS_GAP_TIMEOUT;
1215 }
1216 gettimeofday(&(state->start), NULL);
1217 while (availabledata())
1218 curr_driver->rec_func(NULL);
1219 gettimeofday(&(state->end), NULL);
1220 if (state->flag) {
1221 state->gap = time_elapsed(&(state->last), &(state->start));
1222 add_length(&(state->gaps), state->gap);
1223 merge_lengths(state->gaps);
1224 state->maxcount = 0;
1225 state->scan = state->gaps;
1226 while (state->scan) {
1227 state->maxcount = max(state->maxcount,
1228 state->scan->count);
1229 if (state->scan->count > SAMPLES) {
1230 remote->gap = calc_signal(state->scan);
1231 free_lengths(&(state->gaps));
1232 return STS_GAP_FOUND;
1233 }
1234 state->scan = state->scan->next;
1235 }
1236 if (state->maxcount > state->lastmaxcount) {
1237 state->lastmaxcount = state->maxcount;
1238 return STS_GAP_GOT_ONE_PRESS;
1239 }
1240 } else {
1241 state->flag = 1;
1242 }
1243 state->last = state->end;
1244 return STS_GAP_AGAIN;
1245}
1246
1247
1249int needs_toggle_mask(struct ir_remote* remote)
1250{
1251 struct ir_ncode* codes;
1252
1253 if (!is_rc6(remote))
1254 return 0;
1255 if (remote->codes) {
1256 codes = remote->codes;
1257 while (codes->name != NULL) {
1258 if (codes->next)
1259 /* asume no toggle bit mask when key
1260 * sequences are used */
1261 return 0;
1262 codes++;
1263 }
1264 }
1265 return 1;
1266}
1267
1268
1269/* Compute lengths from four recorded signals. */
1270static void compute_lengths_4_signals(void)
1271{
1272 add_length(&first_repeatp, signals[0]);
1273 merge_lengths(first_repeatp);
1274 add_length(&first_repeats, signals[1]);
1275 merge_lengths(first_repeats);
1276 add_length(&first_trail, signals[2]);
1277 merge_lengths(first_trail);
1278 add_length(&first_repeat_gap, signals[3]);
1279 merge_lengths(first_repeat_gap);
1280}
1281
1282
1283/* Compute lengths from six recorded signals. */
1284static void compute_lengths_6_signals(void)
1285{
1286 add_length(&first_headerp, signals[0]);
1287 merge_lengths(first_headerp);
1288 add_length(&first_headers, signals[1]);
1289 merge_lengths(first_headers);
1290 add_length(&first_repeatp, signals[2]);
1291 merge_lengths(first_repeatp);
1292 add_length(&first_repeats, signals[3]);
1293 merge_lengths(first_repeats);
1294 add_length(&first_trail, signals[4]);
1295 merge_lengths(first_trail);
1296 add_length(&first_repeat_gap, signals[5]);
1297 merge_lengths(first_repeat_gap);
1298}
1299
1300/* Compute lengths from more than six recorded signals. */
1301static void compute_lengths_many_signals(struct lengths_state* state)
1302{
1303 int i;
1304
1305 add_length(&first_1lead, signals[0]);
1306 merge_lengths(first_1lead);
1307 for (i = 2; i < state->count - 2; i++) {
1308 if (i % 2) {
1309 add_length(&first_space, signals[i]);
1310 merge_lengths(first_space);
1311 } else {
1312 add_length(&first_pulse, signals[i]);
1313 merge_lengths(first_pulse);
1314 }
1315 }
1316 add_length(&first_trail, signals[state->count - 2]);
1317 merge_lengths(first_trail);
1318 lengths[state->count - 2]++;
1319 add_length(&first_signal_length, state->sum - state->data);
1320 merge_lengths(first_signal_length);
1321 if (state->first_signal == 1
1322 || (first_length > 2
1323 && first_length - 2 != state->count - 2)) {
1324 add_length(&first_3lead, signals[2]);
1325 merge_lengths(first_3lead);
1326 add_length(&first_headerp, signals[0]);
1327 merge_lengths(first_headerp);
1328 add_length(&first_headers, signals[1]);
1329 merge_lengths(first_headers);
1330 }
1331 if (state->first_signal == 1) {
1332 first_lengths++;
1333 first_length = state->count - 2;
1334 state->header = signals[0] + signals[1];
1335 } else if (state->first_signal == 0
1336 && first_length - 2 == state->count - 2) {
1337 lengths[state->count - 2]--;
1338 lengths[state->count - 2 + 2]++;
1339 second_lengths++;
1340 }
1341}
1342
1343
1344static struct lengths* scan_gap1(struct lengths_state* state,
1345 struct ir_remote* remote,
1346 int* maxcount,
1347 enum lengths_status* again)
1348{
1349 struct lengths* scan;
1350
1351 for (scan = first_sum; scan; scan = scan->next) {
1352 *maxcount = max(*maxcount, scan->count);
1353 if (scan->count > SAMPLES) {
1354 remote->gap = calc_signal(scan);
1355 remote->flags |= CONST_LENGTH;
1356 state->mode = MODE_HAVE_GAP;
1357 log_debug("Found gap: %u", remote->gap);
1358 *again = STS_LEN_AGAIN_INFO;
1359 break;
1360 }
1361 }
1362 return scan;
1363}
1364
1365
1366static struct lengths* scan_gap2(struct lengths_state* state,
1367 struct ir_remote* remote,
1368 int* maxcount,
1369 enum lengths_status* again)
1370{
1371 struct lengths* scan;
1372
1373 for (scan = first_gap; scan; scan = scan->next) {
1374 *maxcount = max(*maxcount, scan->count);
1375 if (scan->count > SAMPLES) {
1376 remote->gap = calc_signal(scan);
1377 state->mode = MODE_HAVE_GAP;
1378 log_debug("Found gap: %u", remote->gap);
1379 *again = STS_LEN_AGAIN_INFO;
1380 break;
1381 }
1382 }
1383 return scan;
1384}
1385
1386
1388 struct ir_remote* remote,
1389 int force, int interactive)
1390{
1391 struct lengths* scan;
1392 int maxcount = 0;
1393 static int lastmaxcount = 0;
1394 enum lengths_status again = STS_LEN_AGAIN;
1395
1396 state->data = curr_driver->readdata(10000000);
1397 if (!state->data) {
1398 state->retval = 0;
1399 return STS_LEN_TIMEOUT;
1400 }
1401 state->count++;
1402 if (state->mode == MODE_GET_GAP) {
1403 state->sum += state->data & PULSE_MASK;
1404 if (state->average == 0 && is_space(state->data)) {
1405 if (state->data > 100000) {
1406 state->sum = 0;
1407 return STS_LEN_AGAIN;
1408 }
1409 state->average = state->data;
1410 state->maxspace = state->data;
1411 } else if (is_space(state->data)) {
1412 if (state->data > MIN_GAP
1413 || state->data > 100 * state->average
1414 /* this MUST be a gap */
1415 || (state->data >= 5000 && count_spaces > 10
1416 && state->data > 5 * state->average)
1417 || (state->data < 5000 && count_spaces > 10
1418 && state->data > 5 * state->maxspace / 2)) {
1419 add_length(&first_sum, state->sum);
1420 merge_lengths(first_sum);
1421 add_length(&first_gap, state->data);
1422 merge_lengths(first_gap);
1423 state->sum = 0;
1424 count_spaces = 0;
1425 state->average = 0;
1426 state->maxspace = 0;
1427
1428 maxcount = 0;
1429 scan = scan_gap1(state,
1430 remote,
1431 &maxcount,
1432 &again);
1433 if (scan == NULL) {
1434 scan = scan_gap2(state,
1435 remote,
1436 &maxcount,
1437 &again);
1438 }
1439 if (scan != NULL) {
1440 state->mode = MODE_HAVE_GAP;
1441 state->sum = 0;
1442 state->count = 0;
1443 state->remaining_gap =
1444 is_const(remote) ?
1445 (remote->gap >
1446 state->data ?
1447 remote->gap - state->data : 0)
1448 : (has_repeat_gap(remote) ?
1449 remote->
1450 repeat_gap : remote->gap);
1451 if (force) {
1452 state->retval = 0;
1453 return STS_LEN_RAW_OK;
1454 }
1455 return STS_LEN_AGAIN_INFO;
1456 }
1457 lastmaxcount = maxcount;
1458 state->keypresses = lastmaxcount;
1459 return again;
1460 }
1461 state->average =
1462 (state->average * count_spaces + state->data)
1463 / (count_spaces + 1);
1464 count_spaces++;
1465 if (state->data > state->maxspace)
1466 state->maxspace = state->data;
1467 }
1468 if (state->count > SAMPLES * MAX_SIGNALS * 2) {
1469 state->retval = 0;
1470 return STS_LEN_NO_GAP_FOUND;
1471 }
1472 state->keypresses = lastmaxcount;
1473 return STS_LEN_AGAIN;
1474 } else if (state->mode == MODE_HAVE_GAP) {
1475 if (state->count <= MAX_SIGNALS) {
1476 signals[state->count - 1] = state->data & PULSE_MASK;
1477 } else {
1478 state->retval = 0;
1479 return STS_LEN_TOO_LONG;
1480 }
1481 if (is_const(remote))
1482 state->remaining_gap =
1483 remote->gap > state->sum ?
1484 remote->gap - state->sum : 0;
1485 else
1486 state->remaining_gap = remote->gap;
1487 state->sum += state->data & PULSE_MASK;
1488
1489 if (state->count > 2
1490 && ((state->data & PULSE_MASK) >=
1491 state->remaining_gap * (100 - eps) / 100
1492 || (state->data & PULSE_MASK) >=
1493 state->remaining_gap - aeps)) {
1494 if (is_space(state->data)) {
1495 /* signal complete */
1496 state->keypresses += 1;
1497 if (state->count == 4) {
1498 count_3repeats++;
1499 compute_lengths_4_signals();
1500 } else if (state->count == 6) {
1501 count_5repeats++;
1502 compute_lengths_6_signals();
1503 } else if (state->count > 6) {
1504 count_signals++;
1505 compute_lengths_many_signals(state);
1506 }
1507 state->count = 0;
1508 state->sum = 0;
1509 }
1510 /* such long pulses may appear with
1511 * crappy hardware (receiver? / remote?)
1512 */
1513 else {
1514 remote->gap = 0;
1515 return STS_LEN_NO_GAP_FOUND;
1516 }
1517
1518 if (count_signals >= SAMPLES) {
1519 get_scheme(remote, interactive);
1520 if (!get_header_length(remote, interactive)
1521 || !get_trail_length(remote, interactive)
1522 || !get_lead_length(remote, interactive)
1523 || !get_repeat_length(remote, interactive)
1524 || !get_data_length(remote, interactive))
1525 state->retval = 0;
1526 return state->retval ==
1527 0 ? STS_LEN_FAIL : STS_LEN_OK;
1528 }
1529 if ((state->data & PULSE_MASK) <=
1530 (state->remaining_gap + state->header) *
1531 (100 + eps) / 100
1532 || (state->data & PULSE_MASK) <=
1533 (state->remaining_gap + state->header) + aeps) {
1534 state->first_signal = 0;
1535 state->header = 0;
1536 } else {
1537 state->first_signal = 1;
1538 }
1539 }
1540 }
1541 return STS_LEN_AGAIN;
1542}
1543
1544
1546 struct ir_remote* remote)
1547{
1548 struct decode_ctx_t decode_ctx = { 0 };
1549 int i;
1550 ir_code mask;
1551
1552 if (!state->inited) {
1553 sleep(1);
1554 while (availabledata())
1555 curr_driver->rec_func(NULL);
1556 state->inited = 1;
1557 }
1558 if (state->retries <= 0) {
1559 if (!state->found)
1560 return STS_TGL_NOT_FOUND;
1561 if (state->seq > 0) {
1562 remote->min_repeat = state->repeats / state->seq;
1563 log_debug("min_repeat=%d",
1564 remote->min_repeat);
1565 }
1566 return STS_TGL_FOUND;
1567 }
1568 if (!mywaitfordata(10000000))
1569 return STS_TGL_TIMEOUT;
1570 curr_driver->rec_func(remote);
1571 if (is_rc6(remote) && remote->rc6_mask == 0) {
1572 for (i = 0, mask = 1; i < remote->bits; i++, mask <<= 1) {
1573 remote->rc6_mask = mask;
1574 state->success =
1575 curr_driver->decode_func(remote, &decode_ctx);
1576 if (state->success) {
1577 remote->min_remaining_gap =
1578 decode_ctx.min_remaining_gap;
1579 remote->max_remaining_gap =
1580 decode_ctx.max_remaining_gap;
1581 break;
1582 }
1583 }
1584 if (!state->success)
1585 remote->rc6_mask = 0;
1586 } else {
1587 state->success =
1588 curr_driver->decode_func(remote, &decode_ctx);
1589 if (state->success) {
1590 remote->min_remaining_gap =
1591 decode_ctx.min_remaining_gap;
1592 remote->max_remaining_gap =
1593 decode_ctx.max_remaining_gap;
1594 }
1595 }
1596 if (state->success) {
1597 if (state->flag == 0) {
1598 state->flag = 1;
1599 state->first = decode_ctx.code;
1600 } else if (!decode_ctx.repeat_flag
1601 || decode_ctx.code != state->last) {
1602 state->seq++;
1603 mask = state->first ^ decode_ctx.code;
1604 if (!state->found && mask) {
1605 set_toggle_bit_mask(remote, mask);
1606 state->found = 1;
1607 if (state->seq > 0)
1608 remote->min_repeat =
1609 state->repeats / state->seq;
1610 }
1611 state->retries--;
1612 state->last = decode_ctx.code;
1613 return STS_TGL_GOT_ONE_PRESS;
1614 }
1615 state->repeats++;
1616 state->last = decode_ctx.code;
1617 } else {
1618 state->retries--;
1619 while (availabledata())
1620 curr_driver->rec_func(NULL);
1621 }
1622 return STS_TGL_AGAIN;
1623}
1624
1625
1628{
1629 enum lengths_status status = STS_LEN_AGAIN;
1630
1631 while (status == STS_LEN_AGAIN) {
1632 status = get_lengths(lengths_state, &remote, 0, 0);
1633 switch (status) {
1634 case STS_LEN_AGAIN_INFO:
1635 status = STS_LEN_AGAIN;
1636 break;
1637 case STS_LEN_AGAIN:
1638 break;
1639 case STS_LEN_OK:
1640 break;
1641 case STS_LEN_FAIL:
1642 log_error("get_lengths() failure");
1643 return 0;
1644 case STS_LEN_RAW_OK:
1645 log_error("raw analyse result?!");
1646 return 0;
1647 case STS_LEN_TIMEOUT:
1648 log_error("analyse timeout?!");
1649 return 0;
1650 case STS_LEN_NO_GAP_FOUND:
1651 log_error("analyse, no gap?!");
1652 return 0;
1653 case STS_LEN_TOO_LONG:
1654 log_error("analyse, signal too long?!");
1655 return 0;
1656 default:
1657 log_error("Cannot read raw data (%d)",
1658 status);
1659 return 0;
1660 }
1661 }
1662 return 1;
1663}
1664
1665
1667int analyse_remote(struct ir_remote* raw_data, const struct opts* opts)
1668{
1669 struct ir_ncode* codes;
1670 struct decode_ctx_t decode_ctx;
1672 int code;
1673 int code2;
1674 struct ir_ncode* new_codes;
1675 size_t new_codes_count = 100;
1676 int new_index = 0;
1677 int ret;
1678
1679 if (!is_raw(raw_data)) {
1680 log_error("remote %s not in raw mode, ignoring",
1681 raw_data->name);
1682 return 0;
1683 }
1684 flushhw();
1685 aeps = raw_data->aeps;
1686 eps = raw_data->eps;
1687 emulation_data = raw_data;
1688 next_code = NULL;
1689 current_code = NULL;
1690 current_index = 0;
1691 memset(&remote, 0, sizeof(remote));
1694 return 0;
1695
1696 if (is_rc6(&remote) && remote.bits >= 5)
1697 /* have to assume something as it's very difficult to
1698 * extract the rc6_mask from the data that we have */
1699 remote.rc6_mask = ((ir_code)0x1ll) << (remote.bits - 5);
1700
1701 remote.name = raw_data->name;
1702 remote.freq = raw_data->freq;
1703
1704 new_codes = malloc(new_codes_count * sizeof(*new_codes));
1705 if (new_codes == NULL) {
1706 log_error("Out of memory");
1707 return 0;
1708 }
1709 memset(new_codes, 0, new_codes_count * sizeof(*new_codes));
1710 codes = raw_data->codes;
1711 while (codes->name != NULL) {
1712 // printf("decoding %s\n", codes->name);
1713 current_code = NULL;
1714 current_index = 0;
1715 next_code = codes;
1716
1718
1719 ret = receive_decode(&remote, &decode_ctx);
1720 if (!ret) {
1721 log_warn(
1722 "Decoding of %s failed", codes->name);
1723 } else {
1724 if (new_index + 1 >= new_codes_count) {
1725 struct ir_ncode* renew_codes;
1726
1727 new_codes_count *= 2;
1728 renew_codes =
1729 realloc(new_codes,
1730 new_codes_count *
1731 sizeof(*new_codes));
1732 if (renew_codes == NULL) {
1733 log_error("Out of memory");
1734 free(new_codes);
1735 return 0;
1736 }
1737 memset(&new_codes[new_codes_count / 2],
1738 0,
1739 new_codes_count / 2 *
1740 sizeof(*new_codes));
1741 new_codes = renew_codes;
1742 }
1743
1745 code = decode_ctx.code;
1746 ret = receive_decode(&remote, &decode_ctx);
1747 code2 = decode_ctx.code;
1748 decode_ctx.code = code;
1749 if (ret && code2 != decode_ctx.code) {
1750 new_codes[new_index].next =
1751 malloc(IR_CODE_NODE_SIZE);
1752 if (new_codes[new_index].next) {
1753 memset(new_codes[new_index].next,
1754 0,
1755 IR_CODE_NODE_SIZE);
1756 new_codes[new_index].next->code =
1757 code2;
1758 }
1759 }
1760 new_codes[new_index].name = codes->name;
1761 new_codes[new_index].code = decode_ctx.code;
1762 new_index++;
1763 }
1764 codes++;
1765 }
1766 new_codes[new_index].name = NULL;
1767 remote.codes = new_codes;
1768 fprint_remotes(stdout, &remote, opts->commandline);
1769 remote.codes = NULL;
1770 free(new_codes);
1771 return 1;
1772}
1773
1774
1776int do_analyse(const struct opts* opts, struct main_state* state)
1777{
1778 FILE* f;
1779 struct ir_remote* r;
1780
1781 memcpy((void*)curr_driver, &hw_emulation, sizeof(struct driver));
1782 f = fopen(opts->filename, "r");
1783 if (f == NULL) {
1784 fprintf(stderr, "Cannot open file: %s\n", opts->filename);
1785 return 0;
1786 }
1787 r = read_config(f, opts->filename);
1788 if (r == NULL) {
1789 fprintf(stderr, "Cannot parse file: %s\n", opts->filename);
1790 return 0;
1791 }
1792 for (; r != NULL; r = r->next) {
1793 if (!is_raw(r)) {
1794 log_error("remote %s not in raw mode, ignoring",
1795 r->name);
1796 continue;
1797 }
1798 analyse_remote(r, opts);
1799 }
1800 return 1;
1801}
1802
1803
1804ssize_t raw_read(void* buffer, size_t size, unsigned int timeout_us)
1805{
1806 if (!mywaitfordata(timeout_us))
1807 return 0;
1808 return read(curr_driver->fd, buffer, size);
1809}
1810
1811
1812static int raw_data_ok(struct button_state* btn_state)
1813{
1814 int r;
1815 int ref;
1816
1817 if (!is_space(btn_state->data)) {
1818 r = 0;
1819 } else if (is_const(&remote)) {
1820 if (remote.gap > btn_state->sum) {
1821 ref = (remote.gap - btn_state->sum);
1822 ref *= (100 - remote.eps);
1823 ref /= 100;
1824 } else {
1825 ref = 0;
1826 }
1827 r = btn_state->data > ref;
1828 } else {
1829 r = btn_state->data > (remote.gap * (100 - remote.eps)) / 100;
1830 }
1831 return r;
1832}
1833
1834
1836 enum button_status last_status,
1837 struct main_state* state,
1838 const struct opts* opts)
1839{
1840 const char* const MSG_BAD_LENGTH =
1841 "Signal length is %d\n"
1842 "That's weird because the signal length must be odd!\n";
1843 ir_code code2;
1844 int decode_ok;
1845 uint32_t timeout;
1846 int retries;
1847 struct ir_remote* my_remote;
1848 FILE* f;
1849 enum button_status sts;
1850
1851 if (btn_state->no_data) {
1852 btn_state->no_data = 0;
1853 return STS_BTN_TIMEOUT;
1854 }
1855 switch (last_status) {
1856 case STS_BTN_INIT:
1857 return STS_BTN_GET_NAME;
1858 case STS_BTN_GET_NAME:
1859 if (strchr(btn_state->buffer, ' ') != NULL) {
1861 btn_state,
1862 "The name must not contain any whitespace.");
1863 return STS_BTN_SOFT_ERROR;
1864 }
1865 if (strchr(btn_state->buffer, '\t') != NULL) {
1867 btn_state,
1868 "The name must not contain any whitespace.");
1869 return STS_BTN_SOFT_ERROR;
1870 }
1871 if (strcasecmp(btn_state->buffer, "begin") == 0) {
1873 btn_state,
1874 "'%s' is not allowed as button name\n",
1875 btn_state->buffer);
1876 return STS_BTN_SOFT_ERROR;
1877 }
1878 if (strcasecmp(btn_state->buffer, "end") == 0) {
1880 btn_state,
1881 "'%s' is not allowed as button name\n",
1882 btn_state->buffer);
1883 return STS_BTN_SOFT_ERROR;
1884 }
1885 if (strlen(btn_state->buffer) == 0)
1886 return STS_BTN_RECORD_DONE;
1887 if (!opts->disable_namespace
1888 && !is_in_namespace(btn_state->buffer)) {
1890 btn_state,
1891 "'%s' is not in name space"
1892 " (use --disable-namespace to override)\n",
1893 btn_state->buffer);
1894 return STS_BTN_SOFT_ERROR;
1895 }
1896 return STS_BTN_INIT_DATA;
1897 case STS_BTN_INIT_DATA:
1898 if (opts->force)
1899 flushhw();
1900 else
1901 while (availabledata())
1902 curr_driver->rec_func(NULL);
1903 if (curr_driver->fd == -1)
1905 return opts->force ? STS_BTN_GET_RAW_DATA : STS_BTN_GET_DATA;
1906 case STS_BTN_GET_DATA:
1907 for (retries = RETRIES; retries > 0; ) {
1908 if (!mywaitfordata(10000000)) {
1909 btn_state->no_data = 1;
1910 return STS_BTN_TIMEOUT;
1911 }
1912 decode_ok = 0;
1913 last_remote = NULL;
1914 sleep(1);
1915 while (availabledata()) {
1916 curr_driver->rec_func(NULL);
1918 &remote,
1919 &(state->decode_ctx))) {
1920 decode_ok = 1;
1921 break;
1922 }
1923 }
1924 if (!decode_ok) {
1925 if (!resethw(btn_state->started_as_root)) {
1927 btn_state,
1928 "Could not reset hardware.\n");
1929 return STS_BTN_HARD_ERROR;
1930 }
1931 btn_state_set_message(btn_state,
1932 "Cannot decode data\n");
1933 flushhw();
1934 return STS_BTN_SOFT_ERROR;
1935 }
1936 btn_state->ncode.name = btn_state->buffer;
1937 btn_state->ncode.code = state->decode_ctx.code;
1938 curr_driver->rec_func(NULL);
1939 if (!curr_driver->decode_func(&remote,
1940 &(state->decode_ctx))) {
1941 code2 = state->decode_ctx.code;
1942 state->decode_ctx.code = btn_state->ncode.code;
1943 if (state->decode_ctx.code != code2) {
1944 btn_state->ncode.next =
1945 malloc(IR_CODE_NODE_SIZE);
1946 if (btn_state->ncode.next) {
1947 memset(btn_state->ncode.next,
1948 0,
1949 IR_CODE_NODE_SIZE);
1950 btn_state->ncode.next->code =
1951 code2;
1952 }
1953 }
1954 }
1955 break;
1956 }
1957 return STS_BTN_BUTTON_DONE;
1958 case STS_BTN_GET_RAW_DATA:
1959 btn_state->count = 0;
1960 btn_state->sum = 0;
1961 while (btn_state->count < MAX_SIGNALS) {
1962 if (btn_state->count == 0)
1963 timeout = 10000000;
1964 else
1965 timeout = remote.gap * 5;
1966 btn_state->data = curr_driver->readdata(timeout);
1967 if (!btn_state->data) {
1968 if (btn_state->count == 0)
1969 return STS_BTN_TIMEOUT;
1970 btn_state->data = remote.gap;
1971 }
1972 if (btn_state->count == 0) {
1973 if (!is_space(btn_state->data)
1974 || btn_state->data <
1975 remote.gap - remote.gap * remote.eps /
1976 100) {
1977 sleep(3);
1978 flushhw();
1979 btn_state->count = 0;
1981 btn_state,
1982 "Something went wrong.");
1983 return STS_BTN_SOFT_ERROR;
1984 }
1985 } else {
1986 if (raw_data_ok(btn_state)) {
1987 log_info("Got it.\n");
1988 log_info("Signal length is %d\n",
1989 btn_state->count - 1);
1990 if (btn_state->count % 2) {
1992 btn_state,
1993 MSG_BAD_LENGTH,
1994 btn_state->count - 1);
1995 sleep(3);
1996 flushhw();
1997 btn_state->count = 0;
1998 return STS_BTN_SOFT_ERROR;
1999 }
2000 btn_state->ncode.name =
2001 btn_state->buffer;
2002 btn_state->ncode.length =
2003 btn_state->count - 1;
2004 btn_state->ncode.signals = signals;
2005 break;
2006 }
2007 signals[btn_state->count - 1] =
2008 btn_state->data & PULSE_MASK;
2009 btn_state->sum +=
2010 btn_state->data & PULSE_MASK;
2011 }
2012 btn_state->count++;
2013 }
2014 if (btn_state->count == MAX_SIGNALS) {
2015 btn_state_set_message(btn_state,
2016 "Signal is too long.\n");
2017 return STS_BTN_SOFT_ERROR;
2018 }
2019 return STS_BTN_BUTTON_DONE;
2020 case STS_BTN_RECORD_DONE:
2021 if (is_raw(&remote))
2022 return STS_BTN_ALL_DONE;
2023 if (!resethw(btn_state->started_as_root)) {
2024 btn_state_set_message(btn_state,
2025 "Could not reset hardware.");
2026 return STS_BTN_HARD_ERROR;
2027 }
2028 return STS_BTN_BUTTONS_DONE;
2029 case STS_BTN_BUTTONS_DONE:
2030 f = fopen(opts->tmpfile, "r");
2031 if (f == NULL) {
2032 btn_state_set_message(btn_state,
2033 "Could not reopen config file");
2034 return STS_BTN_HARD_ERROR;
2035 }
2036 my_remote = read_config(f, opts->filename);
2037 fclose(f);
2038 if (my_remote == NULL) {
2040 btn_state,
2041 "Internal error: "
2042 "config file contains no valid remote");
2043 return STS_BTN_HARD_ERROR;
2044 }
2045 if (my_remote == (void*)-1) {
2047 btn_state,
2048 "Internal error: "
2049 "Reading of config file failed");
2050 return STS_BTN_HARD_ERROR;
2051 }
2052 sts = STS_BTN_ALL_DONE;
2053 if (opts->force) {
2054 remote = *my_remote;
2055 return sts;
2056 }
2057 if (!has_toggle_bit_mask(my_remote)) {
2058 if (!opts->using_template
2059 && strcmp(curr_driver->name, "devinput") != 0) {
2060 remote = *(my_remote);
2061 sts = STS_BTN_GET_TOGGLE_BITS;
2062 }
2063 } else {
2064 set_toggle_bit_mask(my_remote,
2065 my_remote->toggle_bit_mask);
2068 }
2069 if (!opts->update) {
2070 get_pre_data(my_remote);
2071 get_post_data(my_remote);
2072 }
2073 remote = *my_remote;
2074 return sts;
2075 case STS_BTN_BUTTON_DONE:
2076 return STS_BTN_BUTTON_DONE;
2077 case STS_BTN_HARD_ERROR:
2078 return STS_BTN_HARD_ERROR;
2079 default:
2080 btn_state_set_message(btn_state,
2081 "record_buttons(): bad state: %d\n",
2082 last_status);
2083 return STS_BTN_HARD_ERROR;
2084 }
2085}
2086
2087
2089void config_file_setup(struct main_state* state, const struct opts* opts)
2090{
2091 state->fout = fopen(opts->tmpfile, "w");
2092 if (state->fout == NULL) {
2093 log_error("Could not open new config file %s", tmpfile);
2094 log_perror_err("While opening temporary file for write");
2095 return;
2096 }
2097 fprint_copyright(state->fout);
2098 fprint_comment(state->fout, &remote, opts->commandline);
2099 fprint_remote_head(state->fout, &remote);
2100 fprint_remote_signal_head(state->fout, &remote);
2101}
2102
2103
2104
2106int config_file_finish(struct main_state* state, const struct opts* opts)
2107{
2108 state->fout = fopen(opts->filename, "w");
2109 if (state->fout == NULL) {
2110 log_perror_err("While opening \"%s\" for write",
2111 opts->filename);
2112 return 0;
2113 }
2114 fprint_copyright(state->fout);
2115 fprint_remotes(state->fout, &remote, opts->commandline);
2116 return 1;
2117}
const struct driver *const curr_driver
Read-only access to drv for client code.
Definition driver.c:34
struct ir_remote * last_remote
TODO.
Definition ir_remote.c:59
int default_close(void)
For now, a placeholder.
Definition driver.c:52
void rec_buffer_init(void)
Clear internal buffer to pristine state.
Definition receive.c:217
int default_open(const char *path)
Stores path in drv.device if non-null.
Definition driver.c:37
int receive_decode(struct ir_remote *remote, struct decode_ctx_t *ctx)
Decode data from remote.
Definition receive.c:1054
int rec_buffer_clear(void)
Flush the internal fifo and store a single code read from the driver in it.
Definition receive.c:237
struct ir_remote * read_config(FILE *f, const char *name)
Parse a lircd.conf config file.
const char * drop_sudo_root(int(*set_some_uid)(uid_t))
Try to drop possible root privileges, returning new user or "" on error.
Definition lirc-utils.c:28
#define RC6
IR data follows RC6 protocol.
#define REPEAT_HEADER
header is also sent before repeat code
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
#define SPACE_ENC
IR data is space encoded.
#define RC5
IR data follows RC5 protocol.
#define NO_HEAD_REP
no header for key repeats
#define CONST_LENGTH
signal length+gap is always constant
int resethw(int started_as_root)
Reset the hardware.
Definition irrecord.c:161
unsigned int eps
Shared list of remotes.
Definition irrecord.c:62
void flushhw(void)
Clear the driver input buffers.
Definition irrecord.c:139
int analyse_remote(struct ir_remote *raw_data, const struct opts *opts)
Implement the analyse task, return 1 for ok, 0 for errors.
Definition irrecord.c:1667
enum lengths_status get_lengths(struct lengths_state *state, struct ir_remote *remote, int force, int interactive)
Try to find out pre/post etc.
Definition irrecord.c:1387
int analyse_get_lengths(struct lengths_state *lengths_state)
analyse non-interactive get_lengths, returns boolean ok/fail.
Definition irrecord.c:1627
enum button_status record_buttons(struct button_state *btn_state, enum button_status last_status, struct main_state *state, const struct opts *opts)
Try to record one button, returning button_status.
Definition irrecord.c:1835
int config_file_finish(struct main_state *state, const struct opts *opts)
Write the final config file.
Definition irrecord.c:2106
int needs_toggle_mask(struct ir_remote *remote)
Return true if a given remote needs to compute toggle_mask.
Definition irrecord.c:1249
enum toggle_status get_toggle_bit_mask(struct toggle_state *state, struct ir_remote *remote)
Try to find out toggle_bit_mask, returning toggle_status.
Definition irrecord.c:1545
void config_file_setup(struct main_state *state, const struct opts *opts)
Write the provisionary config file.
Definition irrecord.c:2089
void button_state_init(struct button_state *state, int started_as_root)
Initiate a pristine button_state.
Definition irrecord.c:219
ssize_t raw_read(void *buffer, size_t size, unsigned int timeout_us)
Absolute error tolerance (us).
Definition irrecord.c:1804
void remove_pre_data(struct ir_remote *remote)
Test hook: Move remote->pre_data into remote->bits.
Definition irrecord.c:383
int availabledata(void)
Return 1 if there is available after running poll(2), else 0.
Definition irrecord.c:118
void remove_post_data(struct ir_remote *remote)
Test hook: Move remote->post_data into remote->bits.
Definition irrecord.c:403
void invert_data(struct ir_remote *remote)
Test hook: Invert all data items in remote.
Definition irrecord.c:424
enum get_gap_status get_gap_length(struct gap_state *state, struct ir_remote *remote)
Try to find out gap length, returning gap_status.
Definition irrecord.c:1207
void free_all_lengths(void)
Free heap data allocated by get_lengths().
Definition irrecord.c:664
void gap_state_init(struct gap_state *state)
Initiate a pristine gap_state.
Definition irrecord.c:189
void remove_trail(struct ir_remote *remote)
Test hook: Move remote->trail into remote->bits.
Definition irrecord.c:463
int do_analyse(const struct opts *opts, struct main_state *state)
The –analyse wrapper.
Definition irrecord.c:1776
void get_post_data(struct ir_remote *remote)
Test hook: Extract remote->post_data and post_data_bits from bits.
Definition irrecord.c:327
lirc_t aeps
Error tolerance in per cent.
Definition irrecord.c:63
void btn_state_set_message(struct button_state *state, const char *fmt,...)
snprintf-style message formatting into state->message.
Definition irrecord.c:97
void lengths_state_init(struct lengths_state *state)
Initiate a pristine lengths_state.
Definition irrecord.c:195
void toggle_state_init(struct toggle_state *state)
Initiate a pristine toggle_state.
Definition irrecord.c:211
void for_each_remote(struct ir_remote *remotes, remote_func func)
Unconditionally apply func(remote) for all items in remotes list.
Definition irrecord.c:491
void get_pre_data(struct ir_remote *remote)
Test hook: Extract remote->pre_data from remote->bits.
Definition irrecord.c:269
Library part of irrecord, functions to identify unknown remotes.
button_status
Return from one pass in record_buttons().
Definition irrecord.h:124
lengths_status
Return from one attempt to determine lengths in get_lengths().
Definition irrecord.h:91
get_gap_status
Return form one attempt to get gap in get_gap().
Definition irrecord.h:104
toggle_status
Return from one attempt in get_toggle_bit_mask().
Definition irrecord.h:114
#define PACKET_SIZE
IR transmission packet size.
Definition lirc_config.h:84
#define log_notice(fmt,...)
Log a notice message.
Definition lirc_log.h:119
#define log_debug(fmt,...)
Log a debug message.
Definition lirc_log.h:124
#define log_perror_err(fmt,...)
perror wrapper logging with level LIRC_ERROR.
Definition lirc_log.h:89
#define log_info(fmt,...)
Log an info message.
Definition lirc_log.h:114
#define log_error(fmt,...)
Log an error message.
Definition lirc_log.h:104
logchannel_t
Log channels used to filter messages.
Definition lirc_log.h:53
#define log_warn(fmt,...)
Log a warning message.
Definition lirc_log.h:109
Main include file for lirc applications.
State while recording buttons, privates besides commented.
Definition irrecord.h:236
char message[128]
Error message, valid on STS_BTN_*_ERROR.
Definition irrecord.h:240
struct ir_ncode ncode
Recorded button, valid on STS_BTN_BUTTON_DONE.
Definition irrecord.h:238
State describing code, pre, post + gap and repeat state.
ir_code code
Code part, matched to code defintion.
int repeat_flag
True if code is a repeated one.
lirc_t min_remaining_gap
Estimated min time of trailing gap.
lirc_t max_remaining_gap
Estimated max time of trailing gap.
The data the driver exports i.
Definition driver.h:136
int fd
Set by the driver after init().
Definition driver.h:146
const char * name
Driver name, as listed by -H help and used as argument to i –driver.
Definition driver.h:228
const uint32_t code_length
Length in bits of the code.
Definition driver.h:164
int(*const decode_func)(struct ir_remote *remote, struct decode_ctx_t *ctx)
TODO.
Definition driver.h:206
char *(*const rec_func)(struct ir_remote *remotes)
Receive data from remote.
Definition driver.h:201
lirc_t(*const readdata)(lirc_t timeout)
Get length of next pulse/space from hardware.
Definition driver.h:222
int(*const deinit_func)(void)
Function called when transmitting/receiving stops.
Definition driver.h:184
int(*const init_func)(void)
Function called for initializing the driver and the hardware.
Definition driver.h:178
uint32_t rec_mode
Possible values are: LIRC_MODE_RAW, LIRC_MODE_PULSE, LIRC_MODE_MODE2, LIRC_MODE_LIRCCODE.
Definition driver.h:161
Private state in get_gap_length().
Definition irrecord.h:185
An ir_code for entering into (singly) linked lists, i.e.
IR Command, corresponding to one (command defining) line of the configuration file.
struct ir_code_node * next
Linked list of the subsequent ir_code's, after the first one.
ir_code code
The first code of the command.
int length
(private)
lirc_t * signals
(private)
char * name
Name of command.
One remote as represented in the configuration file.
uint32_t repeat_gap
time between two repeat codes if different from gap
unsigned int freq
modulation frequency
unsigned int aeps
detecting very short pulses is difficult with relative tolerance for some remotes,...
ir_code rc6_mask
RC-6 doubles signal length of some bits.
lirc_t max_remaining_gap
gap range
lirc_t ptrail
trailing pulse
lirc_t srepeat
indicate repeating
ir_code pre_data
data which the remote sends before actual keycode
int bits
bits (length of code)
int post_data_bits
length of post_data
lirc_t plead
leading pulse
lirc_t shead
header
ir_code post_data
data which the remote sends after actual keycode
ir_code toggle_mask
Sharp (?) error detection scheme.
int flags
flags
int min_repeat
code is repeated at least x times code sent once -> min_repeat=0
lirc_t pre_s
signal between pre_data and keycode
uint32_t gap
time between signals in usecs
int eps
eps (relative tolerance)
const char * name
name of remote control
ir_code toggle_bit_mask
previously only one bit called toggle_bit
int pre_data_bits
length of pre_data
lirc_t min_remaining_gap
remember gap for CONST_LENGTH remotes
State in get_lengths(), private besides commented.
Definition irrecord.h:199
int count
Number of processed data items.
Definition irrecord.h:206
int keypresses
Number of counted button presses.
Definition irrecord.h:203
lirc_t sum
Number of bits accounted for in signal.
Definition irrecord.h:211
Overall state in main.
Definition irrecord.h:177
Parsed run-time options, reflects long_options and the command line, mostly a const object.
Definition irrecord.h:153
Private state in get_togggle_bit_mask().
Definition irrecord.h:220