vdr  2.4.1
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 4.1 2017/05/30 11:02:17 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  strn0cpy(addr.sun_path, DeviceName, sizeof(addr.sun_path));
24  if (!Connect())
25  f = -1;
26  Start();
27 }
28 
30 {
31  int fh = f;
32  f = -1;
33  Cancel();
34  if (fh >= 0)
35  close(fh);
36 }
37 
39 {
40  if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
41  if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
42  return true;
43  LOG_ERROR_STR(addr.sun_path);
44  close(f);
45  f = -1;
46  }
47  else
48  LOG_ERROR_STR(addr.sun_path);
49  return false;
50 }
51 
53 {
54  return f >= 0;
55 }
56 
58 {
59  cTimeMs FirstTime;
60  cTimeMs LastTime;
61  cTimeMs ThisTime;
62  char buf[LIRC_BUFFER_SIZE];
63  char LastKeyName[LIRC_KEY_BUF] = "";
64  bool pressed = false;
65  bool repeat = false;
66  int timeout = -1;
67 
68  while (Running()) {
69 
70  bool ready = f >= 0 && cFile::FileReady(f, timeout);
71  int ret = ready ? safe_read(f, buf, sizeof(buf)) : -1;
72 
73  if (f < 0 || ready && ret <= 0) {
74  esyslog("ERROR: lircd connection broken, trying to reconnect every %.1f seconds", float(RECONNECTDELAY) / 1000);
75  if (f >= 0)
76  close(f);
77  f = -1;
78  while (Running() && f < 0) {
80  if (Connect()) {
81  isyslog("reconnected to lircd");
82  break;
83  }
84  }
85  }
86 
87  if (ready && ret > 0) {
88  buf[ret - 1] = 0;
89  int count;
90  char KeyName[LIRC_KEY_BUF];
91  if (sscanf(buf, "%*x %x %29s", &count, KeyName) != 2) { // '29' in '%29s' is LIRC_KEY_BUF-1!
92  esyslog("ERROR: unparseable lirc command: %s", buf);
93  continue;
94  }
95  int Delta = ThisTime.Elapsed(); // the time between two subsequent LIRC events
96  ThisTime.Set();
97  if (count == 0) { // new key pressed
98  if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < (uint)Setup.RcRepeatDelay)
99  continue; // skip keys coming in too fast
100  if (repeat)
101  Put(LastKeyName, false, true); // generated release for previous repeated key
102  strn0cpy(LastKeyName, KeyName, sizeof(LastKeyName));
103  pressed = true;
104  repeat = false;
105  FirstTime.Set();
106  timeout = -1;
107  }
108  else if (FirstTime.Elapsed() < (uint)Setup.RcRepeatDelay)
109  continue; // repeat function kicks in after a short delay
110  else if (LastTime.Elapsed() < (uint)Setup.RcRepeatDelta)
111  continue; // skip same keys coming in too fast
112  else {
113  pressed = true;
114  repeat = true;
115  timeout = Delta * 3 / 2;
116  }
117  if (pressed) {
118  LastTime.Set();
119  Put(KeyName, repeat);
120  }
121  }
122  else {
123  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  }
131 }
cSetup::RcRepeatDelay
int RcRepeatDelay
Definition: config.h:300
cLircRemote::Ready
virtual bool Ready(void)
Definition: lirc.c:52
cFile::FileReady
static bool FileReady(int FileDes, int TimeoutMs=1000)
Definition: tools.c:1692
cLircRemote::cLircRemote
cLircRemote(const char *DeviceName)
Definition: lirc.c:18
cRemote::Put
bool Put(uint64_t Code, bool Repeat=false, bool Release=false)
Definition: remote.c:124
cThread::Cancel
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
Definition: thread.c:354
Setup
cSetup Setup
Definition: config.c:372
RECONNECTDELAY
#define RECONNECTDELAY
Definition: lirc.c:16
cLircRemote::LIRC_KEY_BUF
@ LIRC_KEY_BUF
Definition: lirc.h:19
cLircRemote::Action
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: lirc.c:57
cTimeMs::Set
void Set(int Ms=0)
Definition: tools.c:774
cLircRemote::addr
struct sockaddr_un addr
Definition: lirc.h:21
cTimeMs
Definition: tools.h:369
cSetup::RcRepeatDelta
int RcRepeatDelta
Definition: config.h:301
cRemote
Definition: remote.h:20
cLircRemote::LIRC_BUFFER_SIZE
@ LIRC_BUFFER_SIZE
Definition: lirc.h:19
cLircRemote::Connect
bool Connect(void)
Definition: lirc.c:38
cThread
Definition: thread.h:79
cCondWait::SleepMs
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:72
cLircRemote::~cLircRemote
virtual ~cLircRemote()
Definition: lirc.c:29
lirc.h
strn0cpy
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
safe_read
ssize_t safe_read(int filedes, void *buffer, size_t size)
Definition: tools.c:53
cThread::Start
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
Definition: thread.c:304
cLircRemote::f
int f
Definition: lirc.h:20
isyslog
#define isyslog(a...)
Definition: tools.h:36
esyslog
#define esyslog(a...)
Definition: tools.h:35
cTimeMs::Elapsed
uint64_t Elapsed(void) const
Definition: tools.c:784
LOG_ERROR_STR
#define LOG_ERROR_STR(s)
Definition: tools.h:40