summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/tools/remote/lirchandler.cpp166
-rw-r--r--noncore/tools/remote/lirchandler.h8
2 files changed, 174 insertions, 0 deletions
diff --git a/noncore/tools/remote/lirchandler.cpp b/noncore/tools/remote/lirchandler.cpp
index ec1e275..6022573 100644
--- a/noncore/tools/remote/lirchandler.cpp
+++ b/noncore/tools/remote/lirchandler.cpp
@@ -1,144 +1,149 @@
1/* 1/*
2Opie-Remote. emulates remote controls on an iPaq (and maybe a Zaurus) in Opie. 2Opie-Remote. emulates remote controls on an iPaq (and maybe a Zaurus) in Opie.
3Copyright (C) 2007 Paul Eggleton & Thomas Stephens 3Copyright (C) 2007 Paul Eggleton & Thomas Stephens
4 4
5This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public 5This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
6License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later 6License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
7version. 7version.
8 8
9This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 9This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
10implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 10implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11Public License for more details. 11Public License for more details.
12 12
13You should have received a copy of the GNU General Public License along with this program; if not, write to the Free 13You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
14Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15*/ 15*/
16 16
17#include <stdio.h> 17#include <stdio.h>
18#include <stdlib.h> 18#include <stdlib.h>
19#include <string.h> 19#include <string.h>
20#include <sys/socket.h> 20#include <sys/socket.h>
21#include <sys/types.h> 21#include <sys/types.h>
22#include <unistd.h> 22#include <unistd.h>
23#include <errno.h> 23#include <errno.h>
24 24
25#include <qstring.h> 25#include <qstring.h>
26#include <qmessagebox.h> 26#include <qmessagebox.h>
27#include <qobject.h> 27#include <qobject.h>
28#include <qtextstream.h>
28#include <opie2/oprocess.h> 29#include <opie2/oprocess.h>
29#include <qpe/qcopenvelope_qws.h> 30#include <qpe/qcopenvelope_qws.h>
30 31
31#include "lirchandler.h" 32#include "lirchandler.h"
32 33
33#define PACKET_SIZE 256 34#define PACKET_SIZE 256
34#define TIMEOUT 3 35#define TIMEOUT 3
35#define LIRCD_SOCKET "/dev/lircd" 36#define LIRCD_SOCKET "/dev/lircd"
36#define LIRCD_SERVICECMD "/etc/init.d/lircd" 37#define LIRCD_SERVICECMD "/etc/init.d/lircd"
38#define LIRCD_CONF "/etc/lircd.conf"
37 39
38using namespace Opie::Core; 40using namespace Opie::Core;
39 41
40LircHandler::LircHandler(void) 42LircHandler::LircHandler(void)
41{ 43{
42 fd = 0; 44 fd = 0;
43 addr.sun_family=AF_UNIX; 45 addr.sun_family=AF_UNIX;
44 strcpy(addr.sun_path, LIRCD_SOCKET); 46 strcpy(addr.sun_path, LIRCD_SOCKET);
45} 47}
46 48
47bool LircHandler::connectLirc(void) 49bool LircHandler::connectLirc(void)
48{ 50{
51 if(!checkLircdConfValid(false))
52 return false;
53
49 fd = socket(AF_UNIX, SOCK_STREAM, 0); 54 fd = socket(AF_UNIX, SOCK_STREAM, 0);
50 if(fd == -1) 55 if(fd == -1)
51 { 56 {
52 QMessageBox mb(QObject::tr("Error"), 57 QMessageBox mb(QObject::tr("Error"),
53 QObject::tr("Unable to create socket"), 58 QObject::tr("Unable to create socket"),
54 QMessageBox::Critical, 59 QMessageBox::Critical,
55 QMessageBox::Ok, 60 QMessageBox::Ok,
56 QMessageBox::NoButton, 61 QMessageBox::NoButton,
57 QMessageBox::NoButton); 62 QMessageBox::NoButton);
58 mb.exec(); 63 mb.exec();
59 perror("LircHandler::connectLirc"); 64 perror("LircHandler::connectLirc");
60 return false; 65 return false;
61 } 66 }
62 67
63 if(::connect(fd,(struct sockaddr *) &addr, sizeof(addr) ) == -1) 68 if(::connect(fd,(struct sockaddr *) &addr, sizeof(addr) ) == -1)
64 { 69 {
65 QMessageBox mb(QObject::tr("Error"), 70 QMessageBox mb(QObject::tr("Error"),
66 QObject::tr("Could not connect to lircd"), 71 QObject::tr("Could not connect to lircd"),
67 QMessageBox::Critical, 72 QMessageBox::Critical,
68 QMessageBox::Ok, 73 QMessageBox::Ok,
69 QMessageBox::NoButton, 74 QMessageBox::NoButton,
70 QMessageBox::NoButton); 75 QMessageBox::NoButton);
71 mb.exec(); 76 mb.exec();
72 perror("LircHandler::connectLirc"); 77 perror("LircHandler::connectLirc");
73 return false; 78 return false;
74 } 79 }
75 80
76 return true; 81 return true;
77} 82}
78 83
79//this function was ripped for rc.c in xrc, it is available here: http://www.lirc.org/software.html 84//this function was ripped for rc.c in xrc, it is available here: http://www.lirc.org/software.html
80const char *LircHandler::readPacket() 85const char *LircHandler::readPacket()
81{ 86{
82 static char buffer[PACKET_SIZE+1]=""; 87 static char buffer[PACKET_SIZE+1]="";
83 char *end; 88 char *end;
84 static int ptr=0; 89 static int ptr=0;
85 ssize_t ret; 90 ssize_t ret;
86 int timeout = 0; 91 int timeout = 0;
87 92
88 if(ptr>0) 93 if(ptr>0)
89 { 94 {
90 memmove(buffer,buffer+ptr,strlen(buffer+ptr)+1); 95 memmove(buffer,buffer+ptr,strlen(buffer+ptr)+1);
91 ptr=strlen(buffer); 96 ptr=strlen(buffer);
92 end=strchr(buffer,'\n'); 97 end=strchr(buffer,'\n');
93 } 98 }
94 else 99 else
95 { 100 {
96 end=NULL; 101 end=NULL;
97 } 102 }
98 alarm(TIMEOUT); 103 alarm(TIMEOUT);
99 while(end==NULL) 104 while(end==NULL)
100 { 105 {
101 if(PACKET_SIZE<=ptr) 106 if(PACKET_SIZE<=ptr)
102 { 107 {
103 fprintf(stderr,"readPacket: bad packet\n"); 108 fprintf(stderr,"readPacket: bad packet\n");
104 ptr=0; 109 ptr=0;
105 return(NULL); 110 return(NULL);
106 } 111 }
107 ret=read(fd,buffer+ptr,PACKET_SIZE-ptr); 112 ret=read(fd,buffer+ptr,PACKET_SIZE-ptr);
108 113
109 if(ret<=0 || timeout) 114 if(ret<=0 || timeout)
110 { 115 {
111 if(timeout) 116 if(timeout)
112 { 117 {
113 fprintf(stderr,"readPacket: timeout\n"); 118 fprintf(stderr,"readPacket: timeout\n");
114 } 119 }
115 else 120 else
116 { 121 {
117 alarm(0); 122 alarm(0);
118 } 123 }
119 ptr=0; 124 ptr=0;
120 return(NULL); 125 return(NULL);
121 } 126 }
122 buffer[ptr+ret]=0; 127 buffer[ptr+ret]=0;
123 ptr=strlen(buffer); 128 ptr=strlen(buffer);
124 end=strchr(buffer,'\n'); 129 end=strchr(buffer,'\n');
125 } 130 }
126 alarm(0); 131 alarm(0);
127 132
128 end[0]=0; 133 end[0]=0;
129 ptr=strlen(buffer)+1; 134 ptr=strlen(buffer)+1;
130//# ifdef DEBUG 135//# ifdef DEBUG
131 //printf("buffer: -%s-\n",buffer); 136 //printf("buffer: -%s-\n",buffer);
132//# endif 137//# endif
133 return(buffer); 138 return(buffer);
134} 139}
135 140
136QStringList LircHandler::getRemotes(void) 141QStringList LircHandler::getRemotes(void)
137{ 142{
138 const char write_buffer[] = "LIST\n"; 143 const char write_buffer[] = "LIST\n";
139 const char *readbuffer; 144 const char *readbuffer;
140 int i, numlines; 145 int i, numlines;
141 QStringList list; 146 QStringList list;
142 147
143 if(connectLirc()) { 148 if(connectLirc()) {
144 write(fd, write_buffer, strlen(write_buffer) ); 149 write(fd, write_buffer, strlen(write_buffer) );
@@ -176,118 +181,279 @@ QStringList LircHandler::getRemotes(void)
176 181
177QStringList LircHandler::getButtons(const char *remoteName) 182QStringList LircHandler::getButtons(const char *remoteName)
178{ 183{
179 QString write_buffer = "LIST "; 184 QString write_buffer = "LIST ";
180 const char *readbuffer; 185 const char *readbuffer;
181 int i, j, numlines; 186 int i, j, numlines;
182 QStringList list; 187 QStringList list;
183 QString string; 188 QString string;
184 189
185 write_buffer += remoteName; 190 write_buffer += remoteName;
186 write_buffer += '\n'; 191 write_buffer += '\n';
187 192
188 if(connectLirc()) { 193 if(connectLirc()) {
189 write(fd, write_buffer.latin1(), strlen(write_buffer) ); 194 write(fd, write_buffer.latin1(), strlen(write_buffer) );
190 195
191 for(i=0; i<5; i++) 196 for(i=0; i<5; i++)
192 { 197 {
193 readbuffer = readPacket(); 198 readbuffer = readPacket();
194 } 199 }
195 200
196 numlines = atoi(readbuffer); 201 numlines = atoi(readbuffer);
197 202
198 for(i=0; i<numlines; i++) 203 for(i=0; i<numlines; i++)
199 { 204 {
200 list+=readPacket(); 205 list+=readPacket();
201 for(j=0; j<list[i].length(); j++) 206 for(j=0; j<list[i].length(); j++)
202 { 207 {
203 if(list[i][j] == ' ') 208 if(list[i][j] == ' ')
204 break; 209 break;
205 } 210 }
206 list[i].remove(0, j+1); 211 list[i].remove(0, j+1);
207 } 212 }
208 213
209 if(strcasecmp(readPacket(), "END") != 0) 214 if(strcasecmp(readPacket(), "END") != 0)
210 { 215 {
211 QMessageBox mb(QObject::tr("Error"), 216 QMessageBox mb(QObject::tr("Error"),
212 QObject::tr("Bad packet while communicating with lircd"), 217 QObject::tr("Bad packet while communicating with lircd"),
213 QMessageBox::Critical, 218 QMessageBox::Critical,
214 QMessageBox::Ok, 219 QMessageBox::Ok,
215 QMessageBox::NoButton, 220 QMessageBox::NoButton,
216 QMessageBox::NoButton); 221 QMessageBox::NoButton);
217 mb.exec(); 222 mb.exec();
218 perror("LircHandler::getRemotes"); 223 perror("LircHandler::getRemotes");
219 return NULL; 224 return NULL;
220 } 225 }
221 226
222 ::close(fd); 227 ::close(fd);
223 } 228 }
224 229
225 return list; 230 return list;
226} 231}
227 232
228int LircHandler::sendIR(const char *lircaction) 233int LircHandler::sendIR(const char *lircaction)
229{ 234{
230 const char *read_buffer; 235 const char *read_buffer;
231 bool done=false; 236 bool done=false;
232 237
233 if(connectLirc()) { 238 if(connectLirc()) {
234 printf("fd2: %d\n", fd); 239 printf("fd2: %d\n", fd);
235 printf("%s", lircaction); 240 printf("%s", lircaction);
236 241
237 printf("1\n"); 242 printf("1\n");
238 printf("%d\n", write(fd, lircaction, strlen(lircaction) ) ); 243 printf("%d\n", write(fd, lircaction, strlen(lircaction) ) );
239 printf("2\n"); 244 printf("2\n");
240 while(!done) 245 while(!done)
241 { 246 {
242 read_buffer=readPacket(); 247 read_buffer=readPacket();
243 printf("%s\n", read_buffer); 248 printf("%s\n", read_buffer);
244 if(strcasecmp(read_buffer, "END") == 0) 249 if(strcasecmp(read_buffer, "END") == 0)
245 { 250 {
246 printf("done reading packet\n"); 251 printf("done reading packet\n");
247 done=true; 252 done=true;
248 } 253 }
249 } 254 }
250 ::close(fd); 255 ::close(fd);
251 return 1; 256 return 1;
252 } 257 }
253 else 258 else
254 return 0; 259 return 0;
255} 260}
256 261
257bool LircHandler::startLircd(void) 262bool LircHandler::startLircd(void)
258{ 263{
259 return (system(LIRCD_SERVICECMD " start") == 0); 264 return (system(LIRCD_SERVICECMD " start") == 0);
260} 265}
261 266
262bool LircHandler::stopLircd(void) 267bool LircHandler::stopLircd(void)
263{ 268{
264 return (system(LIRCD_SERVICECMD " stop") == 0); 269 return (system(LIRCD_SERVICECMD " stop") == 0);
265} 270}
266 271
267bool LircHandler::isLircdRunning(void) 272bool LircHandler::isLircdRunning(void)
268{ 273{
269 return (OProcess::processPID("lircd") != 0); 274 return (OProcess::processPID("lircd") != 0);
270} 275}
271 276
277void LircHandler::reloadLircdConf(void)
278{
279 int pid = OProcess::processPID("lircd");
280 if(pid > -1)
281 kill(pid, SIGHUP);
282 else
283 startLircd();
284}
285
272bool LircHandler::setupModules(void) 286bool LircHandler::setupModules(void)
273{ 287{
274 // Remove IrDA modules which get in the way 288 // Remove IrDA modules which get in the way
275 system("rmmod ircomm-tty ircomm"); 289 system("rmmod ircomm-tty ircomm");
276 // Load LIRC device driver 290 // Load LIRC device driver
277 system("modprobe lirc_sir"); 291 system("modprobe lirc_sir");
278 return true; 292 return true;
279} 293}
280 294
281bool LircHandler::cleanupModules(void) 295bool LircHandler::cleanupModules(void)
282{ 296{
283 // Unload LIRC device driver 297 // Unload LIRC device driver
284 system("rmmod lirc_sir"); 298 system("rmmod lirc_sir");
285 // Load IrDA drivers back in 299 // Load IrDA drivers back in
286 system("modprobe ircomm-tty"); 300 system("modprobe ircomm-tty");
287 return true; 301 return true;
288} 302}
289 303
290void LircHandler::disableIrDA(void) 304void LircHandler::disableIrDA(void)
291{ 305{
292 QCopEnvelope e("QPE/IrDaApplet", "disableIrda()"); 306 QCopEnvelope e("QPE/IrDaApplet", "disableIrda()");
293} 307}
308
309void LircHandler::mergeRemoteConfig(const QString &newconfig)
310{
311 QStringList contents;
312 QStringList newcontents;
313 QFile conf(LIRCD_CONF);
314 QFile newconf(newconfig);
315
316 readFromFile(conf, contents);
317 readFromFile(newconf, newcontents);
318 contents += newcontents;
319
320 writeToFile(conf, contents);
321}
322
323void LircHandler::removeRemote(const QString &remotetodelete)
324{
325 QStringList contents;
326 QFile conf(LIRCD_CONF);
327 bool found = false;
328 bool inremote = false;
329 QString remotename("");
330 int lineidx = 0;
331 int startidx = 0;
332 int lastendidx = 0;
333
334 readFromFile(conf, contents);
335
336 for (QStringList::Iterator it = contents.begin(); it != contents.end(); ++it ) {
337 QString line = (*it).stripWhiteSpace();
338 if(line == "begin remote") {
339 startidx = lastendidx;
340 inremote = true;
341 }
342 else if(line == "end remote") {
343 lastendidx = lineidx + 1;
344 if(remotename == remotetodelete) {
345 found = true;
346 break;
347 }
348 inremote = false;
349 }
350 else if(inremote && line.left(4) == "name") {
351 remotename = line.mid(4).stripWhiteSpace();
352 }
353 lineidx++;
354 }
355
356 if(found) {
357 // Remove the remote and any preceding lines (most likely associated comments)
358 int linecount = lastendidx - startidx;
359 QStringList::Iterator it = contents.at(startidx);
360 for (int i = 0; i < linecount; i++ ) {
361 it = contents.remove(it);
362 }
363
364 // Check if there is at least one remote still defined
365 found = false;
366 for (it = contents.begin(); it != contents.end(); ++it ) {
367 QString line = (*it).stripWhiteSpace();
368 if(line == "begin remote") {
369 found = true;
370 break;
371 }
372 }
373
374 if(found)
375 writeToFile(conf, contents);
376 else
377 conf.remove();
378 }
379}
380
381bool LircHandler::checkRemoteExists(const QString &remote)
382{
383 QStringList contents;
384 QFile conf(LIRCD_CONF);
385 bool inremote = false;
386
387 readFromFile(conf, contents);
388
389 for (QStringList::Iterator it = contents.begin(); it != contents.end(); ++it ) {
390 QString line = (*it).stripWhiteSpace();
391 if(line == "begin remote") {
392 inremote = true;
393 }
394 else if(line == "end remote") {
395 inremote = false;
396 }
397 else if(inremote && line.left(4) == "name") {
398 QString rname = line.mid(4).stripWhiteSpace();
399 if(rname == remote)
400 return true;
401 }
402 }
403 return false;
404}
405
406bool LircHandler::checkLircdConfValid(bool silent)
407{
408 QStringList contents;
409 QFile conf(LIRCD_CONF);
410 bool inremote = false;
411
412 if(conf.exists()) {
413 readFromFile(conf, contents);
414
415 for (QStringList::Iterator it = contents.begin(); it != contents.end(); ++it ) {
416 QString line = (*it).stripWhiteSpace();
417 if(line == "begin remote") {
418 inremote = true;
419 }
420 else if(line == "end remote") {
421 if(inremote)
422 return true;
423 }
424 }
425 }
426
427 if(!silent) {
428 QMessageBox::information(NULL, QObject::tr("No remote"),
429 QObject::tr("No remotes have been learned.\nPlease go to the Learn tab\nand learn a remote."),
430 QMessageBox::Ok, QMessageBox::NoButton);
431 }
432
433 return false;
434}
435
436bool LircHandler::readFromFile(QFile &file, QStringList &strlist)
437{
438 if(file.open(IO_ReadOnly)) {
439 QTextStream in(&file);
440
441 strlist = QStringList::split('\n', in.read(), true);
442 file.close();
443 if(strlist.count() > 0)
444 strlist.remove(strlist.at(strlist.count() - 1)); // remove extra blank line
445 }
446 return true;
447}
448
449bool LircHandler::writeToFile(QFile &file, QStringList &strlist)
450{
451 if(file.open(IO_WriteOnly | IO_Truncate)) {
452 QTextStream out(&file);
453 for (QStringList::Iterator it = strlist.begin(); it != strlist.end(); ++it ) {
454 out << (*it) << "\n";
455 }
456 file.close();
457 }
458 return true;
459}
diff --git a/noncore/tools/remote/lirchandler.h b/noncore/tools/remote/lirchandler.h
index 4e56b6b..5ba14b7 100644
--- a/noncore/tools/remote/lirchandler.h
+++ b/noncore/tools/remote/lirchandler.h
@@ -1,43 +1,51 @@
1/* 1/*
2Opie-Remote. emulates remote controls on an iPaq (and maybe a Zaurus) in Opie. 2Opie-Remote. emulates remote controls on an iPaq (and maybe a Zaurus) in Opie.
3Copyright (C) 2007 Paul Eggleton & Thomas Stephens 3Copyright (C) 2007 Paul Eggleton & Thomas Stephens
4 4
5This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public 5This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
6License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later 6License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
7version. 7version.
8 8
9This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 9This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
10implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 10implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11Public License for more details. 11Public License for more details.
12 12
13You should have received a copy of the GNU General Public License along with this program; if not, write to the Free 13You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
14Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15*/ 15*/
16 16
17#ifndef LIRCHANDLER_H 17#ifndef LIRCHANDLER_H
18#define LIRCHANDLER_H 18#define LIRCHANDLER_H
19 19
20#include <sys/un.h> 20#include <sys/un.h>
21#include <qfile.h>
21 22
22class LircHandler 23class LircHandler
23{ 24{
24private: 25private:
25 bool connectLirc(void); 26 bool connectLirc(void);
26 const char *readPacket(); 27 const char *readPacket();
28 bool readFromFile(QFile &file, QStringList &strlist);
29 bool writeToFile(QFile &file, QStringList &strlist);
27 30
28 struct sockaddr_un addr; 31 struct sockaddr_un addr;
29 int fd; 32 int fd;
30public: 33public:
31 LircHandler(void); 34 LircHandler(void);
32 QStringList getRemotes(void); 35 QStringList getRemotes(void);
33 QStringList getButtons(const char *remoteName); 36 QStringList getButtons(const char *remoteName);
34 int sendIR(const char *lircaction); 37 int sendIR(const char *lircaction);
35 bool startLircd(void); 38 bool startLircd(void);
36 bool stopLircd(void); 39 bool stopLircd(void);
37 bool isLircdRunning(void); 40 bool isLircdRunning(void);
41 void reloadLircdConf(void);
38 bool setupModules(void); 42 bool setupModules(void);
39 bool cleanupModules(void); 43 bool cleanupModules(void);
40 void disableIrDA(void); 44 void disableIrDA(void);
45 void mergeRemoteConfig(const QString &newconfig);
46 void removeRemote(const QString &remotetodelete);
47 bool checkRemoteExists(const QString &remote);
48 bool checkLircdConfValid(bool silent);
41}; 49};
42 50
43#endif 51#endif