vdr  1.7.31
lirc.c
Go to the documentation of this file.
1 /*
2  * lirc.c: LIRC remote control
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
8  *
9  * $Id: lirc.c 2.1 2011/03/08 15:35:13 kls Exp $
10  */
11 
12 #include "lirc.h"
13 #include <netinet/in.h>
14 #include <sys/socket.h>
15 
16 #define REPEATDELAY 350 // ms
17 #define REPEATFREQ 100 // ms
18 #define REPEATTIMEOUT 500 // ms
19 #define RECONNECTDELAY 3000 // ms
20 
21 cLircRemote::cLircRemote(const char *DeviceName)
22 :cRemote("LIRC")
23 ,cThread("LIRC remote control")
24 {
25  addr.sun_family = AF_UNIX;
26  strcpy(addr.sun_path, DeviceName);
27  if (Connect()) {
28  Start();
29  return;
30  }
31  f = -1;
32 }
33 
35 {
36  int fh = f;
37  f = -1;
38  Cancel();
39  if (fh >= 0)
40  close(fh);
41 }
42 
44 {
45  if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
46  if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
47  return true;
48  LOG_ERROR_STR(addr.sun_path);
49  close(f);
50  f = -1;
51  }
52  else
53  LOG_ERROR_STR(addr.sun_path);
54  return false;
55 }
56 
58 {
59  return f >= 0;
60 }
61 
63 {
64  cTimeMs FirstTime;
65  cTimeMs LastTime;
66  char buf[LIRC_BUFFER_SIZE];
67  char LastKeyName[LIRC_KEY_BUF] = "";
68  bool repeat = false;
69  int timeout = -1;
70 
71  while (Running() && f >= 0) {
72 
73  bool ready = cFile::FileReady(f, timeout);
74  int ret = ready ? safe_read(f, buf, sizeof(buf)) : -1;
75 
76  if (ready && ret <= 0 ) {
77  esyslog("ERROR: lircd connection broken, trying to reconnect every %.1f seconds", float(RECONNECTDELAY) / 1000);
78  close(f);
79  f = -1;
80  while (Running() && f < 0) {
82  if (Connect()) {
83  isyslog("reconnected to lircd");
84  break;
85  }
86  }
87  }
88 
89  if (ready && ret > 0) {
90  buf[ret - 1] = 0;
91  int count;
92  char KeyName[LIRC_KEY_BUF];
93  if (sscanf(buf, "%*x %x %29s", &count, KeyName) != 2) { // '29' in '%29s' is LIRC_KEY_BUF-1!
94  esyslog("ERROR: unparseable lirc command: %s", buf);
95  continue;
96  }
97  if (count == 0) {
98  if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < REPEATDELAY)
99  continue; // skip keys coming in too fast
100  if (repeat)
101  Put(LastKeyName, false, true);
102  strcpy(LastKeyName, KeyName);
103  repeat = false;
104  FirstTime.Set();
105  timeout = -1;
106  }
107  else {
108  if (LastTime.Elapsed() < REPEATFREQ)
109  continue; // repeat function kicks in after a short delay (after last key instead of first key)
110  if (FirstTime.Elapsed() < REPEATDELAY)
111  continue; // skip keys coming in too fast (for count != 0 as well)
112  repeat = true;
113  timeout = REPEATDELAY;
114  }
115  LastTime.Set();
116  Put(KeyName, repeat);
117  }
118  else if (repeat) { // the last one was a repeat, so let's generate a release
119  if (LastTime.Elapsed() >= REPEATTIMEOUT) {
120  Put(LastKeyName, false, true);
121  repeat = false;
122  *LastKeyName = 0;
123  timeout = -1;
124  }
125  }
126  }
127 }