LIRC libraries
Linux Infrared Remote Control
Loading...
Searching...
No Matches
receive.c
Go to the documentation of this file.
1/****************************************************************************
2 * receive.c ***************************************************************
3 ****************************************************************************
4 *
5 * functions that decode IR codes
6 *
7 * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
8 *
9 */
10
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20
21#include <errno.h>
22#include <limits.h>
23#include <poll.h>
24#include <stdint.h>
25
26#include "media/lirc.h"
27
28#include "lirc/driver.h"
29#include "lirc/lirc_log.h"
30#include "lirc/receive.h"
31#include "lirc/ir_remote.h"
32
33#define RBUF_SIZE 512
34
35#define REC_SYNC 8
36
37static const logchannel_t logchannel = LOG_LIB;
38
42struct rbuf {
43 lirc_t data[RBUF_SIZE];
44 ir_code decoded;
45 int rptr;
46 int wptr;
47 int too_long;
48 int is_biphase;
49 lirc_t pendingp;
50 lirc_t pendings;
51 lirc_t sum;
52 struct timeval last_signal_time;
53 int at_eof;
54 FILE* input_log;
55};
56
57
61static struct rbuf rec_buffer;
62static int update_mode = 0;
63
64
65void rec_set_update_mode(int mode)
66{
67 update_mode = mode;
68}
69
70int (*lircd_waitfordata)(uint32_t timeout) = NULL;
71
72
73static lirc_t readdata(lirc_t timeout)
74{
75 lirc_t data;
76
77 data = curr_driver->readdata(timeout);
78 rec_buffer.at_eof = data & LIRC_EOF ? 1 : 0;
79 if (rec_buffer.at_eof)
80 log_debug("receive: Got EOF");
81 return data;
82}
83
84
85static lirc_t lirc_t_max(lirc_t a, lirc_t b)
86{
87 return a > b ? a : b;
88}
89
90static void set_pending_pulse(lirc_t deltap)
91{
92 log_trace2("pending pulse: %lu", deltap);
93 rec_buffer.pendingp = deltap;
94}
95
96static void set_pending_space(lirc_t deltas)
97{
98 log_trace2("pending space: %lu", deltas);
99 rec_buffer.pendings = deltas;
100}
101
102
103static void log_input(lirc_t data)
104{
105 fprintf(rec_buffer.input_log, "%s %u\n",
106 data & PULSE_BIT ? "pulse" : "space", data & PULSE_MASK);
107 fflush(rec_buffer.input_log);
108}
109
110
111static lirc_t get_next_rec_buffer_internal(lirc_t maxusec)
112{
113 if (rec_buffer.rptr < rec_buffer.wptr) {
114 log_trace2("<%c%lu", rec_buffer.data[rec_buffer.rptr] & PULSE_BIT ? 'p' : 's', (uint32_t)
115 rec_buffer.data[rec_buffer.rptr] & (PULSE_MASK));
116 rec_buffer.sum += rec_buffer.data[rec_buffer.rptr] & (PULSE_MASK);
117 return rec_buffer.data[rec_buffer.rptr++];
118 }
119 if (rec_buffer.wptr < RBUF_SIZE) {
120 lirc_t data = 0;
121 unsigned long elapsed = 0;
122
123 if (timerisset(&rec_buffer.last_signal_time)) {
124 struct timeval current;
125
126 gettimeofday(&current, NULL);
127 elapsed = time_elapsed(&rec_buffer.last_signal_time, &current);
128 }
129 if (elapsed < maxusec)
130 data = readdata(maxusec - elapsed);
131 if (!data) {
132 log_trace2("timeout: %u", maxusec);
133 return 0;
134 }
135 if (data & LIRC_EOF) {
136 log_debug("Receive: returning EOF");
137 return data;
138 }
139 if (LIRC_IS_TIMEOUT(data)) {
140 log_trace("timeout received: %lu", (uint32_t)LIRC_VALUE(data));
141 if (LIRC_VALUE(data) < maxusec)
142 return get_next_rec_buffer_internal(maxusec - LIRC_VALUE(data));
143 return 0;
144 }
145
146 rec_buffer.data[rec_buffer.wptr] = data;
147 if (rec_buffer.input_log != NULL)
148 log_input(data);
149 if (rec_buffer.data[rec_buffer.wptr] == 0)
150 return 0;
151 rec_buffer.sum += rec_buffer.data[rec_buffer.rptr]
152 & (PULSE_MASK);
153 rec_buffer.wptr++;
154 rec_buffer.rptr++;
155 log_trace2("+%c%lu", rec_buffer.data[rec_buffer.rptr - 1] & PULSE_BIT ? 'p' : 's', (uint32_t)
156 rec_buffer.data[rec_buffer.rptr - 1]
157 & (PULSE_MASK));
158 return rec_buffer.data[rec_buffer.rptr - 1];
159 }
160 rec_buffer.too_long = 1;
161 return 0;
162}
163
164
165void set_waitfordata_func(int(*func)(uint32_t maxusec))
166{
167 lircd_waitfordata = func;
168}
169
170
171int waitfordata(uint32_t maxusec)
172{
173 int ret;
174 struct pollfd pfd = {
175 .fd = curr_driver->fd, .events = POLLIN, .revents = 0 };
176
177 if (lircd_waitfordata != NULL)
178 return lircd_waitfordata(maxusec);
179
180 while (1) {
181 do {
182 do {
183 ret = curl_poll(&pfd, 1, (maxusec > 0) ? (maxusec / 1000) : -1);
184 if (maxusec > 0 && ret == 0)
185 return 0;
186 } while (ret == -1 && errno == EINTR);
187 if (ret == -1) {
188 log_perror_err("curl_poll() failed");
189 continue;
190 }
191 } while (ret == -1);
192
193 if (pfd.revents & POLLIN)
194 /* we will read later */
195 return 1;
196 }
197}
198
199
201{
202 if (rec_buffer.input_log != NULL)
203 fclose(rec_buffer.input_log);
204 rec_buffer.input_log = f;
205}
206
207
208static lirc_t get_next_rec_buffer(lirc_t maxusec)
209{
210 return get_next_rec_buffer_internal(receive_timeout(maxusec));
211}
212
214{
215 memset(&rec_buffer, 0, sizeof(rec_buffer));
216}
217
219{
220 rec_buffer.rptr = 0;
221 rec_buffer.too_long = 0;
222 set_pending_pulse(0);
223 set_pending_space(0);
224 rec_buffer.sum = 0;
225 rec_buffer.at_eof = 0;
226}
227
229{
230 rec_buffer.wptr = 0;
231}
232
234{
235 int move, i;
236
237 timerclear(&rec_buffer.last_signal_time);
238 if (curr_driver->rec_mode == LIRC_MODE_LIRCCODE) {
239 unsigned char buffer[curr_driver->code_length/CHAR_BIT + 1];
240 size_t count;
241
242 count = curr_driver->code_length / CHAR_BIT;
243 if (curr_driver->code_length % CHAR_BIT)
244 count++;
245
246 if (read(curr_driver->fd, buffer, count) != count) {
247 log_error("reading in mode LIRC_MODE_LIRCCODE failed");
248 return 0;
249 }
250 for (i = 0, rec_buffer.decoded = 0; i < count; i++)
251 rec_buffer.decoded = (rec_buffer.decoded << CHAR_BIT) + ((ir_code)buffer[i]);
252 } else {
253 lirc_t data;
254
255 move = rec_buffer.wptr - rec_buffer.rptr;
256 if (move > 0 && rec_buffer.rptr > 0) {
257 memmove(&rec_buffer.data[0], &rec_buffer.data[rec_buffer.rptr],
258 sizeof(rec_buffer.data[0]) * move);
259 rec_buffer.wptr -= rec_buffer.rptr;
260 } else {
261 rec_buffer.wptr = 0;
262 data = readdata(0);
263
264 log_trace2("c%lu", (uint32_t)data & (PULSE_MASK));
265
266 rec_buffer.data[rec_buffer.wptr] = data;
267 rec_buffer.wptr++;
268 }
269 }
270
272 rec_buffer.is_biphase = 0;
273
274 return 1;
275}
276
277static void unget_rec_buffer(int count)
278{
279 log_trace2("unget: %d", count);
280 if (count == 1 || count == 2) {
281 rec_buffer.rptr -= count;
282 rec_buffer.sum -= rec_buffer.data[rec_buffer.rptr] & (PULSE_MASK);
283 if (count == 2)
284 rec_buffer.sum -= rec_buffer.data[rec_buffer.rptr + 1]
285 & (PULSE_MASK);
286 }
287}
288
289static void unget_rec_buffer_delta(lirc_t delta)
290{
291 rec_buffer.rptr--;
292 rec_buffer.sum -= delta & (PULSE_MASK);
293 rec_buffer.data[rec_buffer.rptr] = delta;
294}
295
296static lirc_t get_next_pulse(lirc_t maxusec)
297{
298 lirc_t data;
299
300 data = get_next_rec_buffer(maxusec);
301 if (data == 0)
302 return 0;
303 if (!is_pulse(data)) {
304 log_trace1("pulse expected");
305 return 0;
306 }
307 return data & (PULSE_MASK);
308}
309
310static lirc_t get_next_space(lirc_t maxusec)
311{
312 lirc_t data;
313
314 data = get_next_rec_buffer(maxusec);
315 if (data == 0)
316 return 0;
317 if (!is_space(data)) {
318 log_trace1("space expected");
319 return 0;
320 }
321 return data;
322}
323
324static int sync_pending_pulse(struct ir_remote* remote)
325{
326 if (rec_buffer.pendingp > 0) {
327 lirc_t deltap;
328
329 deltap = get_next_pulse(rec_buffer.pendingp);
330 if (deltap == 0)
331 return 0;
332 if (!expect(remote, deltap, rec_buffer.pendingp))
333 return 0;
334 set_pending_pulse(0);
335 }
336 return 1;
337}
338
339static int sync_pending_space(struct ir_remote* remote)
340{
341 if (rec_buffer.pendings > 0) {
342 lirc_t deltas;
343
344 deltas = get_next_space(rec_buffer.pendings);
345 if (deltas == 0)
346 return 0;
347 if (!expect(remote, deltas, rec_buffer.pendings))
348 return 0;
349 set_pending_space(0);
350 }
351 return 1;
352}
353
354static int expectpulse(struct ir_remote* remote, int exdelta)
355{
356 lirc_t deltap;
357 int retval;
358
359 log_trace2("expecting pulse: %lu", exdelta);
360 if (!sync_pending_space(remote))
361 return 0;
362
363 deltap = get_next_pulse(rec_buffer.pendingp + exdelta);
364 if (deltap == 0)
365 return 0;
366 if (rec_buffer.pendingp > 0) {
367 if (rec_buffer.pendingp > deltap)
368 return 0;
369 retval = expect(remote, deltap - rec_buffer.pendingp, exdelta);
370 if (!retval)
371 return 0;
372 set_pending_pulse(0);
373 } else {
374 retval = expect(remote, deltap, exdelta);
375 }
376 return retval;
377}
378
379static int expectspace(struct ir_remote* remote, int exdelta)
380{
381 lirc_t deltas;
382 int retval;
383
384 log_trace2("expecting space: %lu", exdelta);
385 if (!sync_pending_pulse(remote))
386 return 0;
387
388 deltas = get_next_space(rec_buffer.pendings + exdelta);
389 if (deltas == 0)
390 return 0;
391 if (rec_buffer.pendings > 0) {
392 if (rec_buffer.pendings > deltas)
393 return 0;
394 retval = expect(remote, deltas - rec_buffer.pendings, exdelta);
395 if (!retval)
396 return 0;
397 set_pending_space(0);
398 } else {
399 retval = expect(remote, deltas, exdelta);
400 }
401 return retval;
402}
403
404static int expectone(struct ir_remote* remote, int bit)
405{
406 if (is_biphase(remote)) {
407 int all_bits = bit_count(remote);
408 ir_code mask;
409
410 mask = ((ir_code)1) << (all_bits - 1 - bit);
411 if (mask & remote->rc6_mask) {
412 if (remote->sone > 0 && !expectspace(remote, 2 * remote->sone)) {
413 unget_rec_buffer(1);
414 return 0;
415 }
416 set_pending_pulse(2 * remote->pone);
417 } else {
418 if (remote->sone > 0 && !expectspace(remote, remote->sone)) {
419 unget_rec_buffer(1);
420 return 0;
421 }
422 set_pending_pulse(remote->pone);
423 }
424 } else if (is_space_first(remote)) {
425 if (remote->sone > 0 && !expectspace(remote, remote->sone)) {
426 unget_rec_buffer(1);
427 return 0;
428 }
429 if (remote->pone > 0 && !expectpulse(remote, remote->pone)) {
430 unget_rec_buffer(2);
431 return 0;
432 }
433 } else {
434 if (remote->pone > 0 && !expectpulse(remote, remote->pone)) {
435 unget_rec_buffer(1);
436 return 0;
437 }
438 if (remote->ptrail > 0) {
439 if (remote->sone > 0 && !expectspace(remote, remote->sone)) {
440 unget_rec_buffer(2);
441 return 0;
442 }
443 } else {
444 set_pending_space(remote->sone);
445 }
446 }
447 return 1;
448}
449
450static int expectzero(struct ir_remote* remote, int bit)
451{
452 if (is_biphase(remote)) {
453 int all_bits = bit_count(remote);
454 ir_code mask;
455
456 mask = ((ir_code)1) << (all_bits - 1 - bit);
457 if (mask & remote->rc6_mask) {
458 if (!expectpulse(remote, 2 * remote->pzero)) {
459 unget_rec_buffer(1);
460 return 0;
461 }
462 set_pending_space(2 * remote->szero);
463 } else {
464 if (!expectpulse(remote, remote->pzero)) {
465 unget_rec_buffer(1);
466 return 0;
467 }
468 set_pending_space(remote->szero);
469 }
470 } else if (is_space_first(remote)) {
471 if (remote->szero > 0 && !expectspace(remote, remote->szero)) {
472 unget_rec_buffer(1);
473 return 0;
474 }
475 if (remote->pzero > 0 && !expectpulse(remote, remote->pzero)) {
476 unget_rec_buffer(2);
477 return 0;
478 }
479 } else {
480 if (!expectpulse(remote, remote->pzero)) {
481 unget_rec_buffer(1);
482 return 0;
483 }
484 if (remote->ptrail > 0) {
485 if (!expectspace(remote, remote->szero)) {
486 unget_rec_buffer(2);
487 return 0;
488 }
489 } else {
490 set_pending_space(remote->szero);
491 }
492 }
493 return 1;
494}
495
496static lirc_t sync_rec_buffer(struct ir_remote* remote)
497{
498 int count;
499 lirc_t deltas, deltap;
500
501 count = 0;
502 deltas = get_next_space(1000000);
503 if (deltas == 0)
504 return 0;
505
506 if (last_remote != NULL && !is_rcmm(remote)) {
507 while (!expect_at_least(last_remote, deltas, last_remote->min_remaining_gap)) {
508 deltap = get_next_pulse(1000000);
509 if (deltap == 0)
510 return 0;
511 deltas = get_next_space(1000000);
512 if (deltas == 0)
513 return 0;
514 count++;
515 if (count > REC_SYNC) /* no sync found,
516 * let's try a diffrent remote */
517 return 0;
518 }
519 if (has_toggle_mask(remote)) {
520 if (!expect_at_most(last_remote, deltas, last_remote->max_remaining_gap)) {
521 remote->toggle_mask_state = 0;
522 remote->toggle_code = NULL;
523 }
524 }
525 }
526 rec_buffer.sum = 0;
527 return deltas;
528}
529
530static int get_header(struct ir_remote* remote)
531{
532 if (is_rcmm(remote)) {
533 lirc_t deltap, deltas, sum;
534
535 deltap = get_next_pulse(remote->phead);
536 if (deltap == 0) {
537 unget_rec_buffer(1);
538 return 0;
539 }
540 deltas = get_next_space(remote->shead);
541 if (deltas == 0) {
542 unget_rec_buffer(2);
543 return 0;
544 }
545 sum = deltap + deltas;
546 if (expect(remote, sum, remote->phead + remote->shead))
547 return 1;
548 unget_rec_buffer(2);
549 return 0;
550 } else if (is_bo(remote)) {
551 if (expectpulse(remote, remote->pone) && expectspace(remote, remote->sone)
552 && expectpulse(remote, remote->pone) && expectspace(remote, remote->sone)
553 && expectpulse(remote, remote->phead) && expectspace(remote, remote->shead))
554 return 1;
555 return 0;
556 }
557 if (remote->shead == 0) {
558 if (!sync_pending_space(remote))
559 return 0;
560 set_pending_pulse(remote->phead);
561 return 1;
562 }
563 if (!expectpulse(remote, remote->phead)) {
564 unget_rec_buffer(1);
565 return 0;
566 }
567 /* if this flag is set I need a decision now if this is really
568 * a header */
569 if (remote->flags & NO_HEAD_REP) {
570 lirc_t deltas;
571
572 deltas = get_next_space(remote->shead);
573 if (deltas != 0) {
574 if (expect(remote, remote->shead, deltas))
575 return 1;
576 unget_rec_buffer(2);
577 return 0;
578 }
579 }
580
581 set_pending_space(remote->shead);
582 return 1;
583}
584
585static int get_foot(struct ir_remote* remote)
586{
587 if (!expectspace(remote, remote->sfoot))
588 return 0;
589 if (!expectpulse(remote, remote->pfoot))
590 return 0;
591 return 1;
592}
593
594static int get_lead(struct ir_remote* remote)
595{
596 if (remote->plead == 0)
597 return 1;
598 if (!sync_pending_space(remote))
599 return 0;
600 set_pending_pulse(remote->plead);
601 return 1;
602}
603
604static int get_trail(struct ir_remote* remote)
605{
606 if (remote->ptrail != 0)
607 if (!expectpulse(remote, remote->ptrail))
608 return 0;
609 if (rec_buffer.pendingp > 0)
610 if (!sync_pending_pulse(remote))
611 return 0;
612 return 1;
613}
614
615static int get_gap(struct ir_remote* remote, lirc_t gap)
616{
617 lirc_t data;
618
619 log_trace1("sum: %d", rec_buffer.sum);
620 data = get_next_rec_buffer(gap - gap * remote->eps / 100);
621 if (data == 0)
622 return 1;
623 if (!is_space(data)) {
624 log_trace1("space expected");
625 return 0;
626 }
627 unget_rec_buffer(1);
628 if (!expect_at_least(remote, data, gap)) {
629 log_trace("end of signal not found");
630 return 0;
631 }
632 return 1;
633}
634
635static int get_repeat(struct ir_remote* remote)
636{
637 if (!get_lead(remote))
638 return 0;
639 if (is_biphase(remote)) {
640 if (!expectspace(remote, remote->srepeat))
641 return 0;
642 if (!expectpulse(remote, remote->prepeat))
643 return 0;
644 } else {
645 if (!expectpulse(remote, remote->prepeat))
646 return 0;
647 set_pending_space(remote->srepeat);
648 }
649 if (!get_trail(remote))
650 return 0;
651 if (!get_gap
652 (remote,
653 is_const(remote) ? (min_gap(remote) >
654 rec_buffer.sum ?
655 min_gap(remote) - rec_buffer.sum : 0) :
656 (has_repeat_gap(remote) ? remote->repeat_gap : min_gap(remote))
657 ))
658 return 0;
659 return 1;
660}
661
662static ir_code get_data(struct ir_remote* remote, int bits, int done)
663{
664 ir_code code;
665 int i;
666
667 code = 0;
668
669 if (is_rcmm(remote)) {
670 lirc_t deltap, deltas, sum;
671
672 if (bits % 2 || done % 2) {
673 log_error("invalid bit number.");
674 return (ir_code) -1;
675 }
676 if (!sync_pending_space(remote))
677 return 0;
678 for (i = 0; i < bits; i += 2) {
679 code <<= 2;
680 deltap = get_next_pulse(remote->pzero + remote->pone + remote->ptwo + remote->pthree);
681 deltas = get_next_space(remote->szero + remote->sone + remote->stwo + remote->sthree);
682 if (deltap == 0 || deltas == 0) {
683 log_error("failed on bit %d", done + i + 1);
684 return (ir_code) -1;
685 }
686 sum = deltap + deltas;
687 log_trace2("rcmm: sum %ld", (uint32_t)sum);
688 if (expect(remote, sum, remote->pzero + remote->szero)) {
689 code |= 0;
690 log_trace1("00");
691 } else if (expect(remote, sum, remote->pone + remote->sone)) {
692 code |= 1;
693 log_trace1("01");
694 } else if (expect(remote, sum, remote->ptwo + remote->stwo)) {
695 code |= 2;
696 log_trace1("10");
697 } else if (expect(remote, sum, remote->pthree + remote->sthree)) {
698 code |= 3;
699 log_trace1("11");
700 } else {
701 log_trace1("no match for %d+%d=%d", deltap, deltas, sum);
702 return (ir_code) -1;
703 }
704 }
705 return code;
706 } else if (is_grundig(remote)) {
707 lirc_t deltap, deltas, sum;
708 int state, laststate;
709
710 if (bits % 2 || done % 2) {
711 log_error("invalid bit number.");
712 return (ir_code) -1;
713 }
714 if (!sync_pending_pulse(remote))
715 return (ir_code) -1;
716 for (laststate = state = -1, i = 0; i < bits; ) {
717 deltas = get_next_space(remote->szero + remote->sone + remote->stwo + remote->sthree);
718 deltap = get_next_pulse(remote->pzero + remote->pone + remote->ptwo + remote->pthree);
719 if (deltas == 0 || deltap == 0) {
720 log_error("failed on bit %d", done + i + 1);
721 return (ir_code) -1;
722 }
723 sum = deltas + deltap;
724 log_trace2("grundig: sum %ld", (uint32_t)sum);
725 if (expect(remote, sum, remote->szero + remote->pzero)) {
726 state = 0;
727 log_trace1("2T");
728 } else if (expect(remote, sum, remote->sone + remote->pone)) {
729 state = 1;
730 log_trace1("3T");
731 } else if (expect(remote, sum, remote->stwo + remote->ptwo)) {
732 state = 2;
733 log_trace1("4T");
734 } else if (expect(remote, sum, remote->sthree + remote->pthree)) {
735 state = 3;
736 log_trace2("6T");
737 } else {
738 log_trace1("no match for %d+%d=%d", deltas, deltap, sum);
739 return (ir_code) -1;
740 }
741 if (state == 3) { /* 6T */
742 i += 2;
743 code <<= 2;
744 state = -1;
745 code |= 0;
746 } else if (laststate == 2 && state == 0) { /* 4T2T */
747 i += 2;
748 code <<= 2;
749 state = -1;
750 code |= 1;
751 } else if (laststate == 1 && state == 1) { /* 3T3T */
752 i += 2;
753 code <<= 2;
754 state = -1;
755 code |= 2;
756 } else if (laststate == 0 && state == 2) { /* 2T4T */
757 i += 2;
758 code <<= 2;
759 state = -1;
760 code |= 3;
761 } else if (laststate == -1) {
762 /* 1st bit */
763 } else {
764 log_error("invalid state %d:%d", laststate, state);
765 return (ir_code) -1;
766 }
767 laststate = state;
768 }
769 return code;
770 } else if (is_serial(remote)) {
771 int received;
772 int space, stop_bit, parity_bit;
773 int parity;
774 lirc_t delta, origdelta, pending, expecting, gap_delta;
775 lirc_t base, stop;
776 lirc_t max_space, max_pulse;
777
778 base = 1000000 / remote->baud;
779
780 /* start bit */
781 set_pending_pulse(base);
782
783 received = 0;
784 space = (rec_buffer.pendingp == 0); /* expecting space ? */
785 stop_bit = 0;
786 parity_bit = 0;
787 delta = origdelta = 0;
788 stop = base * remote->stop_bits / 2;
789 parity = 0;
790 gap_delta = 0;
791
792 max_space = remote->sone * remote->bits_in_byte + stop;
793 max_pulse = remote->pzero * (1 + remote->bits_in_byte);
794 if (remote->parity != IR_PARITY_NONE) {
795 parity_bit = 1;
796 max_space += remote->sone;
797 max_pulse += remote->pzero;
798 bits += bits / remote->bits_in_byte;
799 }
800
801 while (received < bits || stop_bit) {
802 if (delta == 0) {
803 delta = space ? get_next_space(max_space) : get_next_pulse(max_pulse);
804 if (delta == 0 && space && received + remote->bits_in_byte + parity_bit >= bits)
805 /* open end */
806 delta = max_space;
807 origdelta = delta;
808 }
809 if (delta == 0) {
810 log_trace("failed before bit %d", received + 1);
811 return (ir_code) -1;
812 }
813 pending = (space ? rec_buffer.pendings : rec_buffer.pendingp);
814 if (expect(remote, delta, pending)) {
815 delta = 0;
816 } else if (delta > pending) {
817 delta -= pending;
818 } else {
819 log_trace("failed before bit %d", received + 1);
820 return (ir_code) -1;
821 }
822 if (pending > 0) {
823 if (stop_bit) {
824 log_trace2("delta: %lu", delta);
825 gap_delta = delta;
826 delta = 0;
827 set_pending_pulse(base);
828 set_pending_space(0);
829 stop_bit = 0;
830 space = 0;
831 log_trace2("stop bit found");
832 } else {
833 log_trace2("pending bit found");
834 set_pending_pulse(0);
835 set_pending_space(0);
836 if (delta == 0)
837 space = (space ? 0 : 1);
838 }
839 continue;
840 }
841 expecting = (space ? remote->sone : remote->pzero);
842 if (delta > expecting || expect(remote, delta, expecting)) {
843 delta -= (expecting > delta ? delta : expecting);
844 received++;
845 code <<= 1;
846 code |= space;
847 parity ^= space;
848 log_trace1("adding %d", space);
849 if (received % (remote->bits_in_byte + parity_bit) == 0) {
850 ir_code temp;
851
852 if ((remote->parity == IR_PARITY_EVEN && parity)
853 || (remote->parity == IR_PARITY_ODD && !parity)) {
854 log_trace("parity error after %d bits", received + 1);
855 return (ir_code) -1;
856 }
857 parity = 0;
858
859 /* parity bit is filtered out */
860 temp = code >> (remote->bits_in_byte + parity_bit);
861 code =
862 temp << remote->bits_in_byte | reverse(code >> parity_bit,
863 remote->bits_in_byte);
864
865 if (space && delta == 0) {
866 log_trace("failed at stop bit after %d bits", received + 1);
867 return (ir_code) -1;
868 }
869 log_trace2("awaiting stop bit");
870 set_pending_space(stop);
871 stop_bit = 1;
872 }
873 } else {
874 if (delta == origdelta) {
875 log_trace("framing error after %d bits", received + 1);
876 return (ir_code) -1;
877 }
878 delta = 0;
879 }
880 if (delta == 0)
881 space = (space ? 0 : 1);
882 }
883 if (gap_delta)
884 unget_rec_buffer_delta(gap_delta);
885 set_pending_pulse(0);
886 set_pending_space(0);
887 return code;
888 } else if (is_bo(remote)) {
889 int lastbit = 1;
890 lirc_t deltap, deltas;
891 lirc_t pzero, szero;
892 lirc_t pone, sone;
893
894 for (i = 0; i < bits; i++) {
895 code <<= 1;
896 deltap = get_next_pulse(remote->pzero + remote->pone + remote->ptwo + remote->pthree);
897 deltas = get_next_space(remote->szero + remote->sone + remote->stwo + remote->sthree);
898 if (deltap == 0 || deltas == 0) {
899 log_error("failed on bit %d", done + i + 1);
900 return (ir_code) -1;
901 }
902 if (lastbit == 1) {
903 pzero = remote->pone;
904 szero = remote->sone;
905 pone = remote->ptwo;
906 sone = remote->stwo;
907 } else {
908 pzero = remote->ptwo;
909 szero = remote->stwo;
910 pone = remote->pthree;
911 sone = remote->sthree;
912 }
913 log_trace2("%lu %lu %lu %lu", pzero, szero, pone, sone);
914 if (expect(remote, deltap, pzero)) {
915 if (expect(remote, deltas, szero)) {
916 code |= 0;
917 lastbit = 0;
918 log_trace1("0");
919 continue;
920 }
921 }
922
923 if (expect(remote, deltap, pone)) {
924 if (expect(remote, deltas, sone)) {
925 code |= 1;
926 lastbit = 1;
927 log_trace1("1");
928 continue;
929 }
930 }
931 log_error("failed on bit %d", done + i + 1);
932 return (ir_code) -1;
933 }
934 return code;
935 } else if (is_xmp(remote)) {
936 lirc_t deltap, deltas, sum;
937 ir_code n;
938
939 if (bits % 4 || done % 4) {
940 log_error("invalid bit number.");
941 return (ir_code) -1;
942 }
943 if (!sync_pending_space(remote))
944 return 0;
945 for (i = 0; i < bits; i += 4) {
946 code <<= 4;
947 deltap = get_next_pulse(remote->pzero);
948 deltas = get_next_space(remote->szero + 16 * remote->sone);
949 if (deltap == 0 || deltas == 0) {
950 log_error("failed on bit %d", done + i + 1);
951 return (ir_code) -1;
952 }
953 sum = deltap + deltas;
954
955 sum -= remote->pzero + remote->szero;
956 n = (sum + remote->sone / 2) / remote->sone;
957 if (n >= 16) {
958 log_error("failed on bit %d", done + i + 1);
959 return (ir_code) -1;
960 }
961 log_trace("%d: %lx", i, n);
962 code |= n;
963 }
964 return code;
965 }
966
967 for (i = 0; i < bits; i++) {
968 code = code << 1;
969 if (expectone(remote, done + i)) {
970 log_trace1("1");
971 code |= 1;
972 } else if (expectzero(remote, done + i)) {
973 log_trace1("0");
974 code |= 0;
975 } else {
976 log_trace("failed on bit %d", done + i + 1);
977 return (ir_code) -1;
978 }
979 }
980 return code;
981}
982
983static ir_code get_pre(struct ir_remote* remote)
984{
985 ir_code pre;
986 ir_code remote_pre;
987 ir_code match_pre;
988 ir_code toggle_mask;
989
990 pre = get_data(remote, remote->pre_data_bits, 0);
991
992 if (pre == (ir_code) -1) {
993 log_trace("Failed on pre_data: cannot get it");
994 return (ir_code) -1;
995 }
996 if (update_mode) {
997 /*
998 * toggle_bit_mask is applied to the concatenated
999 * pre_data - data - post_data. We dont check post data, but
1000 * adjusts for the length.
1001 */
1002 toggle_mask =
1003 remote->toggle_bit_mask >> remote->post_data_bits;
1004 remote_pre = remote->pre_data & ~toggle_mask;
1005 match_pre = pre & ~toggle_mask;
1006 if (remote->pre_data != 0 && remote_pre != match_pre) {
1007 log_trace("Failed on pre_data: bad data: %x", pre);
1008 return (ir_code) -1;
1009 }
1010 }
1011 if (remote->pre_p > 0 && remote->pre_s > 0) {
1012 if (!expectpulse(remote, remote->pre_p))
1013 return (ir_code) -1;
1014 set_pending_space(remote->pre_s);
1015 }
1016 return pre;
1017}
1018
1019static ir_code get_post(struct ir_remote* remote)
1020{
1021 ir_code post;
1022
1023 if (remote->post_p > 0 && remote->post_s > 0) {
1024 if (!expectpulse(remote, remote->post_p))
1025 return (ir_code) -1;
1026 set_pending_space(remote->post_s);
1027 }
1028
1029 post = get_data(remote, remote->post_data_bits, remote->pre_data_bits + remote->bits);
1030
1031 if (post == (ir_code) -1) {
1032 log_trace("failed on post_data");
1033 return (ir_code) -1;
1034 }
1035 return post;
1036}
1037
1038int receive_decode(struct ir_remote* remote, struct decode_ctx_t* ctx)
1039{
1040 lirc_t sync;
1041 int header;
1042 struct timeval current;
1043
1044 sync = 0; /* make compiler happy */
1045 memset(ctx, 0, sizeof(struct decode_ctx_t));
1046 ctx->code = ctx->pre = ctx->post = 0;
1047 header = 0;
1048
1049 if (rec_buffer.at_eof && rec_buffer.wptr - rec_buffer.rptr <= 1) {
1050 log_debug("Decode: found EOF");
1051 ctx->code = LIRC_EOF;
1052 rec_buffer.at_eof = 0;
1053 return 1;
1054 }
1055 if (curr_driver->rec_mode == LIRC_MODE_MODE2 ||
1056 curr_driver->rec_mode == LIRC_MODE_PULSE ||
1057 curr_driver->rec_mode == LIRC_MODE_RAW) {
1059 rec_buffer.is_biphase = is_biphase(remote) ? 1 : 0;
1060
1061 /* we should get a long space first */
1062 sync = sync_rec_buffer(remote);
1063 if (!sync) {
1064 log_trace("failed on sync");
1065 return 0;
1066 }
1067 log_trace("sync");
1068
1069 if (has_repeat(remote) && last_remote == remote) {
1070 if (remote->flags & REPEAT_HEADER && has_header(remote)) {
1071 if (!get_header(remote)) {
1072 log_trace("failed on repeat header");
1073 return 0;
1074 }
1075 log_trace("repeat header");
1076 }
1077 if (get_repeat(remote)) {
1078 if (remote->last_code == NULL) {
1079 log_notice("repeat code without last_code received");
1080 return 0;
1081 }
1082
1083 ctx->pre = remote->pre_data;
1084 ctx->code = remote->last_code->code;
1085 ctx->post = remote->post_data;
1086 ctx->repeat_flag = 1;
1087
1088 ctx->min_remaining_gap =
1089 is_const(remote) ? (min_gap(remote) >
1090 rec_buffer.sum ? min_gap(remote) -
1091 rec_buffer.sum : 0) : (has_repeat_gap(remote) ? remote->
1092 repeat_gap : min_gap(remote));
1093 ctx->max_remaining_gap =
1094 is_const(remote) ? (max_gap(remote) >
1095 rec_buffer.sum ? max_gap(remote) -
1096 rec_buffer.sum : 0) : (has_repeat_gap(remote) ? remote->
1097 repeat_gap : max_gap(remote));
1098 return 1;
1099 }
1100 log_trace("no repeat");
1102 sync_rec_buffer(remote);
1103 }
1104
1105 if (has_header(remote)) {
1106 header = 1;
1107 if (!get_header(remote)) {
1108 header = 0;
1109 if (!(remote->flags & NO_HEAD_REP && expect_at_most(remote, sync, max_gap(remote)))) {
1110 log_trace("failed on header");
1111 return 0;
1112 }
1113 }
1114 log_trace("header");
1115 }
1116 }
1117
1118 if (is_raw(remote)) {
1119 struct ir_ncode* codes;
1120 struct ir_ncode* found;
1121 int i;
1122
1123 if (curr_driver->rec_mode == LIRC_MODE_LIRCCODE)
1124 return 0;
1125
1126 codes = remote->codes;
1127 found = NULL;
1128 while (codes->name != NULL && found == NULL) {
1129 found = codes;
1130 for (i = 0; i < codes->length; ) {
1131 if (!expectpulse(remote, codes->signals[i++])) {
1132 found = NULL;
1134 sync_rec_buffer(remote);
1135 break;
1136 }
1137 if (i < codes->length && !expectspace(remote, codes->signals[i++])) {
1138 found = NULL;
1140 sync_rec_buffer(remote);
1141 break;
1142 }
1143 }
1144 codes++;
1145 if (found != NULL) {
1146 if (!get_gap
1147 (remote, is_const(remote) ?
1148 min_gap(remote) - rec_buffer.sum :
1149 min_gap(remote)))
1150 found = NULL;
1151 }
1152 }
1153 if (found == NULL)
1154 return 0;
1155 ctx->code = found->code;
1156 } else {
1157 if (curr_driver->rec_mode == LIRC_MODE_LIRCCODE) {
1158 lirc_t sum;
1159 ir_code decoded = rec_buffer.decoded;
1160
1161 log_trace("decoded: %llx", decoded);
1162 if (curr_driver->rec_mode == LIRC_MODE_LIRCCODE
1163 && curr_driver->code_length != bit_count(remote))
1164 return 0;
1165
1166 ctx->post = decoded & gen_mask(remote->post_data_bits);
1167 decoded >>= remote->post_data_bits;
1168 ctx->code = decoded & gen_mask(remote->bits);
1169 ctx->pre = decoded >> remote->bits;
1170
1171 gettimeofday(&current, NULL);
1172 sum = remote->phead + remote->shead +
1173 lirc_t_max(remote->pone + remote->sone,
1174 remote->pzero + remote->szero) * bit_count(remote) + remote->plead +
1175 remote->ptrail + remote->pfoot + remote->sfoot + remote->pre_p + remote->pre_s +
1176 remote->post_p + remote->post_s;
1177
1178 rec_buffer.sum = sum >= remote->gap ? remote->gap - 1 : sum;
1179 sync = time_elapsed(&remote->last_send, &current) - rec_buffer.sum;
1180 } else {
1181 if (!get_lead(remote)) {
1182 log_trace("failed on leading pulse");
1183 return 0;
1184 }
1185
1186 if (has_pre(remote)) {
1187 ctx->pre = get_pre(remote);
1188 if (ctx->pre == (ir_code) -1) {
1189 log_trace("failed on pre");
1190 return 0;
1191 }
1192 log_trace("pre: %llx", ctx->pre);
1193 }
1194
1195 ctx->code = get_data(remote, remote->bits, remote->pre_data_bits);
1196 if (ctx->code == (ir_code) -1) {
1197 log_trace("failed on code");
1198 return 0;
1199 }
1200 log_trace("code: %llx", ctx->code);
1201
1202 if (has_post(remote)) {
1203 ctx->post = get_post(remote);
1204 if (ctx->post == (ir_code) -1) {
1205 log_trace("failed on post");
1206 return 0;
1207 }
1208 log_trace("post: %llx", ctx->post);
1209 }
1210 if (!get_trail(remote)) {
1211 log_trace("failed on trailing pulse");
1212 return 0;
1213 }
1214 if (has_foot(remote)) {
1215 if (!get_foot(remote)) {
1216 log_trace("failed on foot");
1217 return 0;
1218 }
1219 }
1220 if (header == 1 && is_const(remote) && (remote->flags & NO_HEAD_REP))
1221 rec_buffer.sum -= remote->phead + remote->shead;
1222 if (is_rcmm(remote)) {
1223 if (!get_gap(remote, 1000))
1224 return 0;
1225 } else if (is_const(remote)) {
1226 if (!get_gap(remote, min_gap(remote) > rec_buffer.sum ?
1227 min_gap(remote) - rec_buffer.sum :
1228 0))
1229 return 0;
1230 } else {
1231 if (!get_gap(remote, min_gap(remote)))
1232 return 0;
1233 }
1234 } /* end of mode specific code */
1235 }
1236 if ((!has_repeat(remote) || remote->reps < remote->min_code_repeat)
1237 && expect_at_most(remote, sync, remote->max_remaining_gap))
1238 ctx->repeat_flag = 1;
1239 else
1240 ctx->repeat_flag = 0;
1241 if (curr_driver->rec_mode == LIRC_MODE_LIRCCODE) {
1242 /* Most TV cards don't pass each signal to the
1243 * driver. This heuristic should fix repeat in such
1244 * cases. */
1245 if (time_elapsed(&remote->last_send, &current) < 325000)
1246 ctx->repeat_flag = 1;
1247 }
1248 if (is_const(remote)) {
1249 ctx->min_remaining_gap = min_gap(remote) > rec_buffer.sum ? min_gap(remote) - rec_buffer.sum : 0;
1250 ctx->max_remaining_gap = max_gap(remote) > rec_buffer.sum ? max_gap(remote) - rec_buffer.sum : 0;
1251 } else {
1252 ctx->min_remaining_gap = min_gap(remote);
1253 ctx->max_remaining_gap = max_gap(remote);
1254 }
1255 return 1;
1256}
const struct driver *const curr_driver
Read-only access to drv for client code.
Definition driver.c:34
void rec_buffer_set_logfile(FILE *f)
Set a file logging input from driver in same format as mode2(1).
Definition receive.c:200
int waitfordata(uint32_t maxusec)
If set_waitfordata(func) is called, invoke and return function set this way.
Definition receive.c:171
void set_waitfordata_func(int(*func)(uint32_t maxusec))
Set the function used by waitfordata().
Definition receive.c:165
void rec_buffer_rewind(void)
Reset the modules's internal fifo's read state to initial values where the nothing is read.
Definition receive.c:218
struct ir_remote * last_remote
TODO.
Definition ir_remote.c:55
void rec_buffer_reset_wptr(void)
Reset internal fifo's write pointer.
Definition receive.c:228
void rec_set_update_mode(int mode)
Set update mode, where recorded pre_data is verified to match the template pre_data.
Definition receive.c:65
void rec_buffer_init(void)
Clear internal buffer to pristine state.
Definition receive.c:213
int receive_decode(struct ir_remote *remote, struct decode_ctx_t *ctx)
Decode data from remote.
Definition receive.c:1038
int rec_buffer_clear(void)
Flush the internal fifo and store a single code read from the driver in it.
Definition receive.c:233
#define REPEAT_HEADER
header is also sent before repeat code
uint64_t ir_code
Denotes an internal coded representation for an IR transmission.
#define NO_HEAD_REP
no header for key repeats
#define LIRC_EOF
Bit manipulator in lirc_t, see lirc.h .
Definition lirc_config.h:90
#define log_trace(fmt,...)
Log a trace message.
Definition lirc_log.h:129
#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_trace2(fmt,...)
Log a trace2 message.
Definition lirc_log.h:139
#define log_error(fmt,...)
Log an error message.
Definition lirc_log.h:104
#define log_trace1(fmt,...)
Log a trace1 message.
Definition lirc_log.h:134
logchannel_t
Log channels used to filter messages.
Definition lirc_log.h:53
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.
ir_code post
post data, sent after code.
lirc_t min_remaining_gap
Estimated min time of trailing gap.
lirc_t max_remaining_gap
Estimated max time of trailing gap.
ir_code pre
pre data, before code.
int fd
Set by the driver after init().
Definition driver.h:142
const uint32_t code_length
Length in bits of the code.
Definition driver.h:160
lirc_t(*const readdata)(lirc_t timeout)
Get length of next pulse/space from hardware.
Definition driver.h:218
uint32_t rec_mode
Possible values are: LIRC_MODE_RAW, LIRC_MODE_PULSE, LIRC_MODE_MODE2, LIRC_MODE_LIRCCODE.
Definition driver.h:157
IR Command, corresponding to one (command defining) line of the configuration file.
ir_code code
The first code of the command.
int length
(private)
lirc_t * signals
(private)
struct ir_code_node * current
Should point at the ir_code currently being transmitted, or NULL if none.
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
lirc_t stwo
2 (only used for RC-MM)
unsigned int stop_bits
mapping: 1->2 1.5->3 2->4
unsigned int bits_in_byte
default: 8
lirc_t sfoot
foot
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 sthree
3 (only used for RC-MM)
lirc_t shead
header
struct timeval last_send
time last_code was received or sent
ir_code post_data
data which the remote sends after actual keycode
int flags
flags
unsigned int baud
can be overridden by [p|s]zero, [p|s]one
lirc_t post_s
signal between keycode and post_code
lirc_t pre_s
signal between pre_data and keycode
uint32_t gap
time between signals in usecs
int eps
eps (relative tolerance)
struct ir_ncode * last_code
code received or sent last
struct ir_ncode * toggle_code
toggle code received or sent last
unsigned int min_code_repeat
meaningful only if remote sends a repeat code: in this case this value indicates how often the real c...
ir_code toggle_bit_mask
previously only one bit called toggle_bit
unsigned int parity
currently unsupported
int pre_data_bits
length of pre_data
lirc_t min_remaining_gap
remember gap for CONST_LENGTH remotes