vdr  2.0.4
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.5.1.1 2013/08/22 09:36:49 kls Exp $
10  */
11 
12 #include "lirc.h"
13 #include <netinet/in.h>
14 #include <sys/socket.h>
15 
16 #define RECONNECTDELAY 3000 // ms
17 
18 cLircRemote::cLircRemote(const char *DeviceName)
19 :cRemote("LIRC")
20 ,cThread("LIRC remote control")
21 {
22  addr.sun_family = AF_UNIX;
23  strcpy(addr.sun_path, DeviceName);
24  if (Connect()) {
25  Start();
26  return;
27  }
28  f = -1;
29 }
30 
32 {
33  int fh = f;
34  f = -1;
35  Cancel();
36  if (fh >= 0)
37  close(fh);
38 }
39 
41 {
42  if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
43  if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
44  return true;
45  LOG_ERROR_STR(addr.sun_path);
46  close(f);
47  f = -1;
48  }
49  else
50  LOG_ERROR_STR(addr.sun_path);
51  return false;
52 }
53 
55 {
56  return f >= 0;
57 }
58 
60 {
61  cTimeMs FirstTime;
62  cTimeMs LastTime;
63  cTimeMs ThisTime;
64  char buf[LIRC_BUFFER_SIZE];
65  char LastKeyName[LIRC_KEY_BUF] = "";
66  bool pressed = false;
67  bool repeat = false;
68  int timeout = -1;
69 
70  while (Running() && f >= 0) {
71 
72  bool ready = cFile::FileReady(f, timeout);
73  int ret = ready ? safe_read(f, buf, sizeof(buf)) : -1;
74 
75  if (ready && ret <= 0 ) {
76  esyslog("ERROR: lircd connection broken, trying to reconnect every %.1f seconds", float(RECONNECTDELAY) / 1000);
77  close(f);
78  f = -1;
79  while (Running() && f < 0) {
81  if (Connect()) {
82  isyslog("reconnected to lircd");
83  break;
84  }
85  }
86  }
87 
88  if (ready && ret > 0) {
89  buf[ret - 1] = 0;
90  int count;
91  char KeyName[LIRC_KEY_BUF];
92  if (sscanf(buf, "%*x %x %29s", &count, KeyName) != 2) { // '29' in '%29s' is LIRC_KEY_BUF-1!
93  esyslog("ERROR: unparseable lirc command: %s", buf);
94  continue;
95  }
96  int Delta = ThisTime.Elapsed(); // the time between two subsequent LIRC events
97  ThisTime.Set();
98  if (count == 0) {
99  if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < (uint)Setup.RcRepeatDelay)
100  continue; // skip keys coming in too fast
101  if (repeat)
102  Put(LastKeyName, false, true);
103  strcpy(LastKeyName, KeyName);
104  pressed = true;
105  repeat = false;
106  FirstTime.Set();
107  timeout = -1;
108  }
109  else if (FirstTime.Elapsed() < (uint)Setup.RcRepeatDelay)
110  continue; // repeat function kicks in after a short delay
111  else if (LastTime.Elapsed() < (uint)Setup.RcRepeatDelta)
112  continue; // skip same keys coming in too fast
113  else {
114  pressed = true;
115  repeat = true;
116  timeout = Delta * 10 / 9;
117  }
118  if (pressed) {
119  LastTime.Set();
120  Put(KeyName, repeat);
121  }
122  }
123  else if (pressed && repeat) { // the last one was a repeat, so let's generate a release
124  Put(LastKeyName, false, true);
125  pressed = false;
126  repeat = false;
127  *LastKeyName = 0;
128  timeout = -1;
129  }
130  else {
131  pressed = false;
132  repeat = false;
133  *LastKeyName = 0;
134  timeout = -1;
135  }
136  }
137 }
138