LIRC libraries
LinuxInfraredRemoteControl
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups Pages
ir_remote.c
Go to the documentation of this file.
1 
2 /****************************************************************************
3  ** ir_remote.c *************************************************************
4  ****************************************************************************
5  *
6  * ir_remote.c - sends and decodes the signals from IR remotes
7  *
8  * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
9  * Copyright (C) 1998 Christoph Bartelmus (lirc@bartelmus.de)
10  *
11  */
12 
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 
31 #include <sys/ioctl.h>
32 
33 #include "include/media/lirc.h"
34 #include "lirc/ir_remote.h"
35 #include "lirc/driver.h"
36 #include "lirc/release.h"
37 #include "lirc/lirc_log.h"
38 
40 static struct ir_ncode NCODE_EOF =
41  {"__EOF", LIRC_EOF, 1, NULL, NULL, NULL, 0};
42 
44 static const char* const PACKET_EOF = "0000000008000000 00 __EOF lirc\n";
45 
47 static struct ir_remote lirc_internal_remote = {"lirc"};
48 
49 struct ir_remote* decoding = NULL;
50 
51 struct ir_remote* last_remote = NULL;
52 
53 struct ir_remote* repeat_remote = NULL;
54 
56 
57 static int dyncodes = 0;
58 
59 void ir_remote_init(int use_dyncodes)
60 {
61  dyncodes= use_dyncodes;
62 }
63 
64 static lirc_t time_left(struct timeval *current, struct timeval *last, lirc_t gap)
65 {
66  unsigned long secs, diff;
67 
68  secs = current->tv_sec - last->tv_sec;
69 
70  diff = 1000000 * secs + current->tv_usec - last->tv_usec;
71 
72  return ((lirc_t) (diff < gap ? gap - diff : 0));
73 }
74 
75 static int match_ir_code(struct ir_remote *remote, ir_code a, ir_code b)
76 {
77  return ((remote->ignore_mask | a) == (remote->ignore_mask | b)
78  || (remote->ignore_mask | a) == (remote->ignore_mask | (b ^ remote->toggle_bit_mask)));
79 }
80 
87 void get_frequency_range(const struct ir_remote *remotes, unsigned int *min_freq, unsigned int *max_freq)
88 {
89  const struct ir_remote *scan;
90 
91  /* use remotes carefully, it may be changed on SIGHUP */
92  scan = remotes;
93  if (scan == NULL) {
94  *min_freq = 0;
95  *max_freq = 0;
96  } else {
97  *min_freq = scan->freq;
98  *max_freq = scan->freq;
99  scan = scan->next;
100  }
101  while (scan) {
102  if (scan->freq != 0) {
103  if (scan->freq > *max_freq) {
104  *max_freq = scan->freq;
105  } else if (scan->freq < *min_freq) {
106  *min_freq = scan->freq;
107  }
108  }
109  scan = scan->next;
110  }
111 }
112 
122 void get_filter_parameters(const struct ir_remote *remotes, lirc_t * max_gap_lengthp, lirc_t * min_pulse_lengthp,
123  lirc_t * min_space_lengthp, lirc_t * max_pulse_lengthp, lirc_t * max_space_lengthp)
124 {
125  const struct ir_remote *scan = remotes;
126  lirc_t max_gap_length = 0;
127  lirc_t min_pulse_length = 0, min_space_length = 0;
128  lirc_t max_pulse_length = 0, max_space_length = 0;
129 
130  while (scan) {
131  lirc_t val;
132  val = upper_limit(scan, scan->max_gap_length);
133  if (val > max_gap_length) {
134  max_gap_length = val;
135  }
136  val = lower_limit(scan, scan->min_pulse_length);
137  if (min_pulse_length == 0 || val < min_pulse_length) {
138  min_pulse_length = val;
139  }
140  val = lower_limit(scan, scan->min_space_length);
141  if (min_space_length == 0 || val > min_space_length) {
142  min_space_length = val;
143  }
144  val = upper_limit(scan, scan->max_pulse_length);
145  if (val > max_pulse_length) {
146  max_pulse_length = val;
147  }
148  val = upper_limit(scan, scan->max_space_length);
149  if (val > max_space_length) {
150  max_space_length = val;
151  }
152  scan = scan->next;
153  }
154  *max_gap_lengthp = max_gap_length;
155  *min_pulse_lengthp = min_pulse_length;
156  *min_space_lengthp = min_space_length;
157  *max_pulse_lengthp = max_pulse_length;
158  *max_space_lengthp = max_space_length;
159 }
160 
167 const struct ir_remote *is_in_remotes(const struct ir_remote *remotes,
168  const struct ir_remote *remote)
169 {
170  while (remotes != NULL) {
171  if (remotes == remote) {
172  return remote;
173  }
174  remotes = remotes->next;
175  }
176  return NULL;
177 }
178 
185 struct ir_remote *get_ir_remote(const struct ir_remote *remotes,
186  const char *name)
187 {
188  const struct ir_remote *all;
189 
190  /* use remotes carefully, it may be changed on SIGHUP */
191  all = remotes;
192  if (strcmp(name, "lirc") == 0) {
193  return &lirc_internal_remote;
194  }
195  while (all) {
196  if (strcasecmp(all->name, name) == 0) {
197  return (struct ir_remote*) all;
198  }
199  all = all->next;
200  }
201  return (NULL);
202 }
203 
218 int map_code(const struct ir_remote* remote,
219  struct decode_ctx_t* ctx,
220  int pre_bits,
221  ir_code pre,
222  int bits,
223  ir_code code,
224  int post_bits,
225  ir_code post)
226 
227 {
228  ir_code all;
229 
230  if (pre_bits + bits + post_bits != remote->pre_data_bits + remote->bits + remote->post_data_bits) {
231  return (0);
232  }
233  all = (pre & gen_mask(pre_bits));
234  all <<= bits;
235  all |= (code & gen_mask(bits));
236  all <<= post_bits;
237  all |= (post & gen_mask(post_bits));
238 
239  ctx->post = (all & gen_mask(remote->post_data_bits));
240  all >>= remote->post_data_bits;
241  ctx->code = (all & gen_mask(remote->bits));
242  all >>= remote->bits;
243  ctx->pre = (all & gen_mask(remote->pre_data_bits));
244 
245  LOGPRINTF(1, "pre: %llx", (__u64) (ctx->pre));
246  LOGPRINTF(1, "code: %llx", (__u64) (ctx->code));
247  LOGPRINTF(1, "post: %llx", (__u64) (ctx->post));
248  LOGPRINTF(1, "code: %016llx\n", code);
249 
250  return (1);
251 }
252 
263 void map_gap(const struct ir_remote *remote,
264  struct decode_ctx_t* ctx,
265  const struct timeval *start,
266  const struct timeval *last,
267  lirc_t signal_length)
268 {
269  // Time gap (us) between a keypress on the remote control and
270  // the next one.
271  lirc_t gap;
272 
273  // Check the time gap between the last keypress and this one.
274  if (start->tv_sec - last->tv_sec >= 2) {
275  // Gap of 2 or more seconds: this is not a repeated keypress.
276  ctx->repeat_flag = 0;
277  gap = 0;
278  } else {
279  // Calculate the time gap in microseconds.
280  gap = time_elapsed(last, start);
281  if (expect_at_most(remote, gap, remote->max_remaining_gap)) {
282  // The gap is shorter than a standard gap
283  // (with relative or aboslute tolerance): this
284  // is a repeated keypress.
285  ctx->repeat_flag = 1;
286  } else {
287  // Standard gap: this is a new keypress.
288  ctx->repeat_flag = 0;
289  }
290  }
291 
292  // Calculate extimated time gap remaining for the next code.
293  if (is_const(remote)) {
294  // The sum (signal_length + gap) is always constant
295  // so the gap is shorter when the code is longer.
296  if (min_gap(remote) > signal_length) {
297  ctx->min_remaining_gap = min_gap(remote) - signal_length;
298  ctx->max_remaining_gap = max_gap(remote) - signal_length;
299  } else {
300  ctx->min_remaining_gap = 0;
301  if (max_gap(remote) > signal_length) {
302  ctx->max_remaining_gap = max_gap(remote) - signal_length;
303  } else {
304  ctx->max_remaining_gap = 0;
305  }
306  }
307  } else {
308  // The gap after the signal is always constant.
309  // This is the case of Kanam Accent serial remote.
310  ctx->min_remaining_gap = min_gap(remote);
311  ctx->max_remaining_gap = max_gap(remote);
312  }
313 
314  LOGPRINTF(1, "repeat_flagp: %d", (ctx->repeat_flag));
315  LOGPRINTF(1, "is_const(remote): %d", is_const(remote));
316  LOGPRINTF(1, "remote->gap range: %lu %lu", (__u32) min_gap(remote), (__u32) max_gap(remote));
317  LOGPRINTF(1, "remote->remaining_gap: %lu %lu", (__u32) remote->min_remaining_gap,
318  (__u32) remote->max_remaining_gap);
319  LOGPRINTF(1, "signal length: %lu", (__u32) signal_length);
320  LOGPRINTF(1, "gap: %lu", (__u32) gap);
321  LOGPRINTF(1, "extim. remaining_gap: %lu %lu", (__u32) (ctx->min_remaining_gap), (__u32)(ctx->max_remaining_gap));
322 
323 }
324 
331 struct ir_ncode *get_code_by_name(const struct ir_remote *remote, const char *name)
332 {
333  const struct ir_ncode *all;
334 
335  all = remote->codes;
336  if (strcmp(remote->name, "lirc") == 0) {
337  return strcmp(name, "__EOF") == 0 ? &NCODE_EOF : 0;
338  }
339  while (all->name != NULL) {
340  if (strcasecmp(all->name, name) == 0) {
341  return (struct ir_ncode*) all;
342  }
343  all++;
344  }
345  return (0);
346 }
347 
348 static struct ir_ncode *get_code(struct ir_remote *remote, ir_code pre, ir_code code, ir_code post,
349  int *repeat_flag, ir_code * toggle_bit_mask_statep)
350 {
351  ir_code pre_mask, code_mask, post_mask, toggle_bit_mask_state, all;
352  int found_code, have_code;
353  struct ir_ncode *codes, *found;
354 
355  pre_mask = code_mask = post_mask = 0;
356 
357  if (has_toggle_bit_mask(remote)) {
358  pre_mask = remote->toggle_bit_mask >> (remote->bits + remote->post_data_bits);
359  post_mask = remote->toggle_bit_mask & gen_mask(remote->post_data_bits);
360  }
361  if (has_ignore_mask(remote)) {
362  pre_mask |= remote->ignore_mask >> (remote->bits + remote->post_data_bits);
363  post_mask |= remote->ignore_mask & gen_mask(remote->post_data_bits);
364  }
365  if (has_toggle_mask(remote) && remote->toggle_mask_state % 2) {
366  ir_code *affected, mask, mask_bit;
367  int bit, current_bit;
368 
369  affected = &post;
370  mask = remote->toggle_mask;
371  for (bit = current_bit = 0; bit < bit_count(remote); bit++, current_bit++) {
372  if (bit == remote->post_data_bits) {
373  affected = &code;
374  current_bit = 0;
375  }
376  if (bit == remote->post_data_bits + remote->bits) {
377  affected = &pre;
378  current_bit = 0;
379  }
380  mask_bit = mask & 1;
381  (*affected) ^= (mask_bit << current_bit);
382  mask >>= 1;
383  }
384  }
385  if (has_pre(remote)) {
386  if ((pre | pre_mask) != (remote->pre_data | pre_mask)) {
387  LOGPRINTF(1, "bad pre data");
388  LOGPRINTF(2, "%llx %llx", pre, remote->pre_data);
389  return (0);
390  }
391  LOGPRINTF(1, "pre");
392  }
393 
394  if (has_post(remote)) {
395  if ((post | post_mask) != (remote->post_data | post_mask)) {
396  LOGPRINTF(1, "bad post data");
397  LOGPRINTF(2, "%llx %llx", post, remote->post_data);
398  return (0);
399  }
400  LOGPRINTF(1, "post");
401  }
402 
403  all = gen_ir_code(remote, pre, code, post);
404 
405  if(*repeat_flag && has_repeat_mask(remote)) {
406  all ^= remote->repeat_mask;
407  }
408 
409  toggle_bit_mask_state = all & remote->toggle_bit_mask;
410 
411  found = NULL;
412  found_code = 0;
413  have_code = 0;
414  codes = remote->codes;
415  if (codes != NULL) {
416  while (codes->name != NULL) {
417  ir_code next_all;
418 
419  next_all =
420  gen_ir_code(remote, remote->pre_data, get_ir_code(codes, codes->current),
421  remote->post_data);
422  if (match_ir_code(remote, next_all, all) ||
423  (*repeat_flag && has_repeat_mask(remote) &&
424  match_ir_code(remote, next_all, all ^ remote->repeat_mask))) {
425  found_code = 1;
426  if (codes->next != NULL) {
427  if (codes->current == NULL) {
428  codes->current = codes->next;
429  } else {
430  codes->current = codes->current->next;
431  }
432  }
433  if (!have_code) {
434  found = codes;
435  if (codes->current == NULL) {
436  have_code = 1;
437  }
438  }
439  } else {
440  /* find longest matching sequence */
441  struct ir_code_node *search;
442 
443  search = codes->next;
444  if (search == NULL || (codes->next != NULL && codes->current == NULL)) {
445  codes->current = NULL;
446  } else {
447  int sequence_match = 0;
448 
449  while (search != codes->current->next) {
450  struct ir_code_node *prev, *next;
451  int flag = 1;
452 
453  prev = NULL; /* means codes->code */
454  next = search;
455  while (next != codes->current) {
456  if (get_ir_code(codes, prev) != get_ir_code(codes, next)) {
457  flag = 0;
458  break;
459  }
460  prev = get_next_ir_code_node(codes, prev);
461  next = get_next_ir_code_node(codes, next);
462  }
463  if (flag == 1) {
464  next_all =
465  gen_ir_code(remote, remote->pre_data,
466  get_ir_code(codes, prev), remote->post_data);
467  if (match_ir_code(remote, next_all, all)) {
468  codes->current = get_next_ir_code_node(codes, prev);
469  sequence_match = 1;
470  found_code = 1;
471  if (!have_code) {
472  found = codes;
473  }
474  break;
475  }
476  }
477  search = search->next;
478  }
479  if (!sequence_match)
480  codes->current = NULL;
481  }
482  }
483  codes++;
484  }
485  }
486  if (!found_code && dyncodes) {
487  if (remote->dyncodes[remote->dyncode].code != code) {
488  remote->dyncode++;
489  remote->dyncode %= 2;
490  }
491  remote->dyncodes[remote->dyncode].code = code;
492  found = &(remote->dyncodes[remote->dyncode]);
493  found_code = 1;
494  }
495  if (found_code && found != NULL && has_toggle_mask(remote)) {
496  if (!(remote->toggle_mask_state % 2)) {
497  remote->toggle_code = found;
498  LOGPRINTF(1, "toggle_mask_start");
499  } else {
500  if (found != remote->toggle_code) {
501  remote->toggle_code = NULL;
502  return (NULL);
503  }
504  remote->toggle_code = NULL;
505  }
506  }
507  *toggle_bit_mask_statep = toggle_bit_mask_state;
508  return (found);
509 }
510 
511 static __u64 set_code(struct ir_remote * remote, struct ir_ncode * found, ir_code toggle_bit_mask_state, struct decode_ctx_t* ctx)
512 {
513  struct timeval current;
514  static struct ir_remote *last_decoded = NULL;
515 
516  LOGPRINTF(1, "found: %s", found->name);
517 
518  gettimeofday(&current, NULL);
519  LOGPRINTF(1, "%lx %lx %lx %d %d %d %d %d %d %d",
520  remote, last_remote, last_decoded,
521  remote == last_decoded,
522  found == remote->last_code, found->next != NULL, found->current != NULL, ctx->repeat_flag,
523  time_elapsed(&remote->last_send, &current) < 1000000, (!has_toggle_bit_mask(remote)
524  || toggle_bit_mask_state ==
525  remote->toggle_bit_mask_state));
526  if (remote->release_detected) {
527  remote->release_detected = 0;
528  if (ctx->repeat_flag) {
529  LOGPRINTF(0, "repeat indicated although release was detected before");
530  }
531  ctx->repeat_flag = 0;
532  }
533  if (remote == last_decoded &&
534  (found == remote->last_code || (found->next != NULL && found->current != NULL)) &&
535  ctx->repeat_flag && time_elapsed(&remote->last_send, &current) < 1000000 && (!has_toggle_bit_mask(remote)
536  || toggle_bit_mask_state ==
537  remote->toggle_bit_mask_state)) {
538  if (has_toggle_mask(remote)) {
539  remote->toggle_mask_state++;
540  if (remote->toggle_mask_state == 4) {
541  remote->reps++;
542  remote->toggle_mask_state = 2;
543  }
544  } else if (found->current == NULL) {
545  remote->reps++;
546  }
547  } else {
548  if (found->next != NULL && found->current == NULL) {
549  remote->reps = 1;
550  } else {
551  remote->reps = 0;
552  }
553  if (has_toggle_mask(remote)) {
554  remote->toggle_mask_state = 1;
555  remote->toggle_code = found;
556  }
557  if (has_toggle_bit_mask(remote)) {
558  remote->toggle_bit_mask_state = toggle_bit_mask_state;
559  }
560  }
561  last_remote = remote;
562  last_decoded = remote;
563  if (found->current == NULL)
564  remote->last_code = found;
565  remote->last_send = current;
566  remote->min_remaining_gap = ctx->min_remaining_gap;
567  remote->max_remaining_gap = ctx->max_remaining_gap;
568 
569  ctx->code = 0;
570  if (has_pre(remote)) {
571  ctx->code |= remote->pre_data;
572  ctx->code = ctx->code << remote->bits;
573  }
574  ctx->code |= found->code;
575  if (has_post(remote)) {
576  ctx->code = ctx->code << remote->post_data_bits;
577  ctx->code |= remote->post_data;
578  }
579  if (remote->flags & COMPAT_REVERSE) {
580  /* actually this is wrong: pre, code and post should
581  be rotated separately but we have to stay
582  compatible with older software
583  */
584  ctx->code = reverse(ctx->code, bit_count(remote));
585  }
586  return (ctx->code);
587 }
588 
601 int write_message(char *buffer, size_t size, const char *remote_name, const char *button_name,
602  const char *button_suffix, ir_code code, int reps)
603 {
604  int len;
605 
606  len = snprintf(buffer, size, "%016llx %02x %s%s %s\n",
607  (unsigned long long)code, reps, button_name, button_suffix, remote_name);
608 
609  return len;
610 }
611 
617 char *decode_all(struct ir_remote *remotes)
618 {
619  struct ir_remote *remote;
620  static char message[PACKET_SIZE + 1];
621  struct ir_ncode *ncode;
622  ir_code toggle_bit_mask_state;
623  struct ir_remote *scan;
624  struct ir_ncode *scan_ncode;
625  struct decode_ctx_t ctx;
626 
627  /* use remotes carefully, it may be changed on SIGHUP */
628  decoding = remote = remotes;
629  while (remote) {
630  LOGPRINTF(1, "trying \"%s\" remote", remote->name);
631  if (curr_driver->decode_func(remote, &ctx)
632  && (ncode = get_code(remote, ctx.pre, ctx.code, ctx.post, &ctx.repeat_flag, &toggle_bit_mask_state))) {
633  int len;
634  int reps;
635  if (ncode == &NCODE_EOF) {
636  logprintf(LIRC_DEBUG, "decode all: returning EOF");
637  strncpy(message, PACKET_EOF, sizeof(message));
638  return message;
639  }
640  ctx.code = set_code(remote, ncode, toggle_bit_mask_state, &ctx);
641  if ((has_toggle_mask(remote) && remote->toggle_mask_state % 2) || ncode->current != NULL) {
642  decoding = NULL;
643  return (NULL);
644  }
645 
646  for (scan = decoding; scan != NULL; scan = scan->next) {
647  for (scan_ncode = scan->codes; scan_ncode->name != NULL; scan_ncode++) {
648  scan_ncode->current = NULL;
649  }
650  }
651  if (is_xmp(remote)) {
652  remote->last_code->current = remote->last_code->next;
653  }
654  reps = remote->reps - (ncode->next ? 1 : 0);
655  if (reps > 0) {
656  if (reps <= remote->suppress_repeat) {
657  decoding = NULL;
658  return NULL;
659  } else {
660  reps -= remote->suppress_repeat;
661  }
662  }
663  register_button_press(remote, remote->last_code, ctx.code, reps);
664 
665  len =
666  write_message(message, PACKET_SIZE + 1, remote->name, remote->last_code->name, "", ctx.code,
667  reps);
668  decoding = NULL;
669  if (len >= PACKET_SIZE + 1) {
670  logprintf(LIRC_ERROR, "message buffer overflow");
671  return (NULL);
672  } else {
673  return (message);
674  }
675  } else {
676  LOGPRINTF(1, "failed \"%s\" remote", remote->name);
677  }
678  remote->toggle_mask_state = 0;
679  remote = remote->next;
680  }
681  decoding = NULL;
682  last_remote = NULL;
683  LOGPRINTF(1, "decoding failed for all remotes");
684  return (NULL);
685 }
686 
693 int send_ir_ncode(struct ir_remote *remote, struct ir_ncode *code, int delay)
694 {
695  int ret;
696 
697  if (delay) {
698  /* insert pause when needed: */
699  if (remote->last_code != NULL) {
700  struct timeval current;
701  unsigned long usecs;
702 
703  gettimeofday(&current, NULL);
704  usecs = time_left(&current,
705  &remote->last_send,
706  remote->min_remaining_gap * 2);
707  if (usecs > 0) {
708  if (repeat_remote == NULL || remote != repeat_remote
709  || remote->last_code != code)
710  {
711  usleep(usecs);
712  }
713  }
714  }
715  }
716 
717  ret = curr_driver->send_func(remote, code);
718 
719  if (ret) {
720  gettimeofday(&remote->last_send, NULL);
721  remote->last_code = code;
722  }
723 
724  return ret;
725 }
lirc_t min_remaining_gap
struct ir_remote * last_remote
Definition: ir_remote.c:51
struct ir_ncode * repeat_code
Definition: ir_remote.c:55
int(*const send_func)(struct ir_remote *remote, struct ir_ncode *code)
Definition: driver.h:134
unsigned int freq
lirc_t max_gap_length
void ir_remote_init(int use_dyncodes)
Definition: ir_remote.c:59
ir_code post_data
ir_code repeat_mask
struct ir_ncode * toggle_code
void get_filter_parameters(const struct ir_remote *remotes, lirc_t *max_gap_lengthp, lirc_t *min_pulse_lengthp, lirc_t *min_space_lengthp, lirc_t *max_pulse_lengthp, lirc_t *max_space_lengthp)
Definition: ir_remote.c:122
struct ir_code_node * next
const char * name
struct ir_ncode * get_code_by_name(const struct ir_remote *remote, const char *name)
Definition: ir_remote.c:331
#define COMPAT_REVERSE
struct ir_ncode * last_code
struct ir_remote * get_ir_remote(const struct ir_remote *remotes, const char *name)
Definition: ir_remote.c:185
#define LIRC_EOF
Definition: lirc_config.h:106
__u64 ir_code
int map_code(const struct ir_remote *remote, struct decode_ctx_t *ctx, int pre_bits, ir_code pre, int bits, ir_code code, int post_bits, ir_code post)
Definition: ir_remote.c:218
char * decode_all(struct ir_remote *remotes)
Definition: ir_remote.c:617
#define PACKET_SIZE
Definition: lirc_config.h:100
char * name
struct timeval last_send
struct ir_code_node * current
ir_code toggle_mask
ir_code pre_data
int write_message(char *buffer, size_t size, const char *remote_name, const char *button_name, const char *button_suffix, ir_code code, int reps)
Definition: ir_remote.c:601
const struct ir_remote * is_in_remotes(const struct ir_remote *remotes, const struct ir_remote *remote)
Definition: ir_remote.c:167
lirc_t max_remaining_gap
#define LOGPRINTF(level, fmt, args...)
Definition: lirc_log.h:76
void map_gap(const struct ir_remote *remote, struct decode_ctx_t *ctx, const struct timeval *start, const struct timeval *last, lirc_t signal_length)
Definition: ir_remote.c:263
int release_detected
lirc_t min_remaining_gap
lirc_t max_remaining_gap
void get_frequency_range(const struct ir_remote *remotes, unsigned int *min_freq, unsigned int *max_freq)
Definition: ir_remote.c:87
ir_code code
int(*const decode_func)(struct ir_remote *remote, struct decode_ctx_t *ctx)
Definition: driver.h:148
const struct driver const * curr_driver
Definition: driver.c:24
struct ir_ncode dyncodes[2]
struct ir_remote * repeat_remote
Definition: ir_remote.c:53
ir_code toggle_bit_mask
int send_ir_ncode(struct ir_remote *remote, struct ir_ncode *code, int delay)
Definition: ir_remote.c:693
ir_code ignore_mask