2 Copyright 2004-2020 Chris Tallon; 2012 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
21 #include <linux/input.h>
22 #include <sys/types.h>
24 #include <sys/ioctl.h>
34 #include "woptionpane.h"
36 #include "inputlinux.h"
38 #define test_bit(input,b) ((1 << ((b) % 8))&(input)[b / 8] )
40 bool InputLinux::init()
42 if (initted) return false;
45 InitHWCListwithDefaults();
48 for (int eventid = 0; eventid < 100; eventid++)
51 sprintf(buffer,"/dev/input/event%d", eventid);
54 if (stat(buffer, &test_buf) == 0)
56 Log::getInstance()->log("InputLinux", Log::NOTICE, "Probe /dev/input/event%d", eventid);
58 unsigned long ev_type = 0;
59 int new_fd = open(buffer, O_RDONLY);
62 Log::getInstance()->log("InputLinux", Log::NOTICE, "Can not open /dev/input/event%d", eventid);
66 if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0)
68 Log::getInstance()->log("InputLinux", Log::NOTICE, "Ioctl failed /dev/input/event%d %d", eventid, errno);
72 //Now test if it generates keyboard presses
73 if (test_bit(reinterpret_cast<char*>(&ev_type), EV_KEY))
75 Log::getInstance()->log("InputLinux", Log::NOTICE, "Add /dev/input/event%d to List", eventid);
76 devices.push_back(new_fd);
78 // Grab the device - make it exclusive to vomp. Fixes rubbish input going to console in background
79 ioctl(new_fd, EVIOCGRAB, 1);
90 void InputLinux::shutdown()
94 while (devices.size())
96 int cur_fd = devices.back();
98 ioctl(cur_fd, EVIOCGRAB, 0);
105 UCHAR InputLinux::TranslateHWCFixed(int code)
107 // Translate /dev/input codes to VOMP codes for the hard coded buttons
110 case KEY_DOWN: return DOWN;
111 case KEY_UP: return UP;
112 case KEY_LEFT: return LEFT;
113 case KEY_RIGHT: return RIGHT;
115 case KEY_MEDIA: return MENU;
117 case KEY_EXIT: return BACK;
120 case KEY_OK: return OK;
123 case KEY_ESC: return POWER;
124 case POWER: return POWER; // Where does this come from?
130 void InputLinux::InitHWCListwithDefaults()
132 Log::getInstance()->log("InputLinux", Log::INFO, "InitHWCListwithDefaults");
134 // Processing VK_Messages
135 translist[KEY_9] = NINE;
136 translist[KEY_8] = EIGHT;
137 translist[KEY_7] = SEVEN;
138 translist[KEY_6] = SIX;
139 translist[KEY_5] = FIVE;
140 translist[KEY_4] = FOUR;
141 translist[KEY_3] = THREE;
142 translist[KEY_2] = TWO;
143 translist[KEY_1] = ONE;
144 translist[KEY_0] = ZERO;
145 translist[KEY_KPDOT] = STAR;
146 // translist[KEY_#] = HASH;
148 translist[KEY_KP9] = NINE;
149 translist[KEY_KP8] = EIGHT;
150 translist[KEY_KP7] = SEVEN;
151 translist[KEY_KP6] = SIX;
152 translist[KEY_KP5] = FIVE;
153 translist[KEY_KP4] = FOUR;
154 translist[KEY_KP3] = THREE;
155 translist[KEY_KP2] = TWO;
156 translist[KEY_KP1] = ONE;
157 translist[KEY_KP0] = ZERO;
159 translist[KEY_NUMERIC_9] = NINE;
160 translist[KEY_NUMERIC_8] = EIGHT;
161 translist[KEY_NUMERIC_7] = SEVEN;
162 translist[KEY_NUMERIC_6] = SIX;
163 translist[KEY_NUMERIC_5] = FIVE;
164 translist[KEY_NUMERIC_4] = FOUR;
165 translist[KEY_NUMERIC_3] = THREE;
166 translist[KEY_NUMERIC_2] = TWO;
167 translist[KEY_NUMERIC_1] = ONE;
168 translist[KEY_NUMERIC_0] = ZERO;
169 translist[KEY_NUMERIC_STAR] = STAR;
170 translist[KEY_NUMERIC_POUND] = HASH;
173 translist[KEY_J] = GO; //j for JUMP TO instead of go to
174 translist[KEY_R] = RED;
175 translist[KEY_G] = GREEN;
176 translist[KEY_Y] = YELLOW;
177 translist[KEY_B] = BLUE;
178 //Processing Remote Style Messages
179 translist[KEY_GREEN] = GREEN;
180 translist[KEY_RED] = RED;
181 translist[KEY_YELLOW] = YELLOW;
182 translist[KEY_BLUE] = BLUE;
183 translist[KEY_MENU] = MENU;
185 translist[KEY_RECORD] = RECORD;
186 translist[KEY_PLAY] = PLAY; //Playback Televison
187 translist[KEY_PAUSE] = PAUSE;
188 translist[KEY_STOP] = STOP;
189 translist[KEY_PLAYPAUSE] = PLAYPAUSE;
190 translist[KEY_P] = PLAYPAUSE;
191 translist[KEY_NEXT] = SKIPFORWARD;
192 translist[KEY_F2] = SKIPFORWARD;
193 translist[KEY_PREVIOUS] = SKIPBACK;
194 translist[KEY_F1] = SKIPBACK;
195 translist[KEY_FORWARD] = FORWARD;
196 translist[KEY_FASTFORWARD] = FORWARD;
197 translist[KEY_F] = FORWARD;
198 translist[KEY_BACK] = REVERSE;
199 translist[KEY_REWIND] = REVERSE;
200 translist[KEY_T] = REVERSE;
201 translist[KEY_MUTE] = MUTE;
202 translist[KEY_F8] = MUTE;
203 translist[KEY_F10] = VOLUMEUP;
204 translist[KEY_F9] = VOLUMEDOWN;
205 translist[KEY_VOLUMEUP] = VOLUMEUP;
206 translist[KEY_VOLUMEDOWN] = VOLUMEDOWN;
207 translist[KEY_CHANNELUP] = CHANNELUP;
208 translist[KEY_CHANNELDOWN] = CHANNELDOWN;
209 translist[KEY_PAGEUP] = CHANNELUP;
210 translist[KEY_PAGEDOWN] = CHANNELDOWN;
213 #define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
214 //extracte from linux/input.h
216 static const char * linux_keymap[KEY_MAX+1];
218 void InputLinux::InitKeymap()
220 for (int i=0;i<KEY_MAX+1;i++)
222 linux_keymap[i] = NULL;
225 NAMETRICK(KEY_,RESERVED);
237 NAMETRICK(KEY_,MINUS);
238 NAMETRICK(KEY_,EQUAL);
239 NAMETRICK(KEY_,BACKSPACE);
251 NAMETRICK(KEY_,LEFTBRACE);
252 NAMETRICK(KEY_,RIGHTBRACE);
253 NAMETRICK(KEY_,ENTER);
254 NAMETRICK(KEY_,LEFTCTRL);
264 NAMETRICK(KEY_,SEMICOLON);
265 NAMETRICK(KEY_,APOSTROPHE);
266 NAMETRICK(KEY_,GRAVE);
267 NAMETRICK(KEY_,LEFTSHIFT);
268 NAMETRICK(KEY_,BACKSLASH);
276 NAMETRICK(KEY_,COMMA);
278 NAMETRICK(KEY_,SLASH);
279 NAMETRICK(KEY_,RIGHTSHIFT);
280 NAMETRICK(KEY_,KPASTERISK);
281 NAMETRICK(KEY_,LEFTALT);
282 NAMETRICK(KEY_,SPACE);
283 NAMETRICK(KEY_,CAPSLOCK);
294 NAMETRICK(KEY_,NUMLOCK);
295 NAMETRICK(KEY_,SCROLLLOCK);
299 NAMETRICK(KEY_,KPMINUS);
303 NAMETRICK(KEY_,KPPLUS);
308 NAMETRICK(KEY_,KPDOT);
311 NAMETRICK(KEY_,KPENTER);
312 NAMETRICK(KEY_,RIGHTCTRL);
313 NAMETRICK(KEY_,KPSLASH);
314 NAMETRICK(KEY_,SYSRQ);
315 NAMETRICK(KEY_,RIGHTALT);
316 NAMETRICK(KEY_,LINEFEED);
317 NAMETRICK(KEY_,HOME);
319 NAMETRICK(KEY_,PAGEUP);
320 NAMETRICK(KEY_,LEFT);
321 NAMETRICK(KEY_,RIGHT);
323 NAMETRICK(KEY_,DOWN);
324 NAMETRICK(KEY_,PAGEDOWN);
325 NAMETRICK(KEY_,INSERT);
326 NAMETRICK(KEY_,DELETE);
327 NAMETRICK(KEY_,MACRO);
328 NAMETRICK(KEY_,MUTE);
329 NAMETRICK(KEY_,VOLUMEDOWN);
330 NAMETRICK(KEY_,VOLUMEUP);
331 NAMETRICK(KEY_,POWER);
332 NAMETRICK(KEY_,KPEQUAL);
333 NAMETRICK(KEY_,KPPLUSMINUS);
334 NAMETRICK(KEY_,PLAY);
335 NAMETRICK(KEY_,PAUSE);
336 NAMETRICK(KEY_,SCALE);
337 NAMETRICK(KEY_,KPCOMMA);
339 NAMETRICK(KEY_,LEFTMETA);
340 NAMETRICK(KEY_,RIGHTMETA);
341 NAMETRICK(KEY_,COMPOSE);
342 NAMETRICK(KEY_,STOP);
343 NAMETRICK(KEY_,AGAIN);
344 NAMETRICK(KEY_,PROPS);
345 NAMETRICK(KEY_,UNDO);
346 NAMETRICK(KEY_,FRONT);
347 NAMETRICK(KEY_,COPY);
348 NAMETRICK(KEY_,OPEN);
349 NAMETRICK(KEY_,PASTE);
350 NAMETRICK(KEY_,FIND);
352 NAMETRICK(KEY_,HELP);
353 NAMETRICK(KEY_,MENU);
354 NAMETRICK(KEY_,CALC);
355 NAMETRICK(KEY_,SETUP);
356 NAMETRICK(KEY_,SLEEP);
357 NAMETRICK(KEY_,WAKEUP);
358 NAMETRICK(KEY_,FILE);
359 NAMETRICK(KEY_,SENDFILE);
360 NAMETRICK(KEY_,DELETEFILE);
361 NAMETRICK(KEY_,XFER);
362 NAMETRICK(KEY_,PROG1);
363 NAMETRICK(KEY_,PROG2);
365 NAMETRICK(KEY_,MSDOS);
366 NAMETRICK(KEY_,COFFEE);
367 NAMETRICK(KEY_,DIRECTION);
368 NAMETRICK(KEY_,CYCLEWINDOWS);
369 NAMETRICK(KEY_,MAIL);
370 NAMETRICK(KEY_,BOOKMARKS);
371 NAMETRICK(KEY_,COMPUTER);
372 NAMETRICK(KEY_,BACK);
373 NAMETRICK(KEY_,FORWARD);
374 NAMETRICK(KEY_,FASTFORWARD);
375 NAMETRICK(KEY_,CLOSECD);
376 NAMETRICK(KEY_,EJECTCD);
377 NAMETRICK(KEY_,EJECTCLOSECD);
378 NAMETRICK(KEY_,NEXTSONG);
379 NAMETRICK(KEY_,PLAYPAUSE);
380 NAMETRICK(KEY_,PREVIOUSSONG);
381 NAMETRICK(KEY_,STOPCD);
382 NAMETRICK(KEY_,RECORD);
383 NAMETRICK(KEY_,REWIND);
384 NAMETRICK(KEY_,PHONE);
386 NAMETRICK(KEY_,CONFIG);
387 NAMETRICK(KEY_,HOMEPAGE);
388 NAMETRICK(KEY_,REFRESH);
389 NAMETRICK(KEY_,EXIT);
390 NAMETRICK(KEY_,MOVE);
391 NAMETRICK(KEY_,EDIT);
392 NAMETRICK(KEY_,SCROLLUP);
393 NAMETRICK(KEY_,SCROLLDOWN);
394 NAMETRICK(KEY_,KPLEFTPAREN);
395 NAMETRICK(KEY_,KPRIGHTPAREN);
397 NAMETRICK(KEY_,REDO);
399 NAMETRICK(KEY_,SELECT);
400 NAMETRICK(KEY_,GOTO);
401 NAMETRICK(KEY_,CLEAR);
402 NAMETRICK(KEY_,POWER2);
403 NAMETRICK(KEY_,OPTION);
404 NAMETRICK(KEY_,INFO);
405 NAMETRICK(KEY_,TIME);
406 NAMETRICK(KEY_,VENDOR);
407 NAMETRICK(KEY_,ARCHIVE);
408 NAMETRICK(KEY_,PROGRAM);
409 NAMETRICK(KEY_,CHANNEL);
410 NAMETRICK(KEY_,FAVORITES);
414 NAMETRICK(KEY_,LANGUAGE);
415 NAMETRICK(KEY_,TITLE);
416 NAMETRICK(KEY_,SUBTITLE);
417 NAMETRICK(KEY_,ANGLE);
418 NAMETRICK(KEY_,ZOOM);
419 NAMETRICK(KEY_,MODE);
420 NAMETRICK(KEY_,KEYBOARD);
421 NAMETRICK(KEY_,SCREEN);
423 NAMETRICK(KEY_,GREEN);
424 NAMETRICK(KEY_,YELLOW);
425 NAMETRICK(KEY_,BLUE);
426 NAMETRICK(KEY_,CHANNELUP);
427 NAMETRICK(KEY_,CHANNELDOWN);
428 NAMETRICK(KEY_,FIRST);
429 NAMETRICK(KEY_,LAST);
431 NAMETRICK(KEY_,NEXT);
432 NAMETRICK(KEY_,RESTART);
433 NAMETRICK(KEY_,SLOW);
434 NAMETRICK(KEY_,SHUFFLE);
435 NAMETRICK(KEY_,BREAK);
436 NAMETRICK(KEY_,PREVIOUS);
437 NAMETRICK(KEY_,DIGITS);
438 NAMETRICK(KEY_,TEEN);
439 NAMETRICK(KEY_,TWEN);
440 NAMETRICK(KEY_,VIDEOPHONE);
441 NAMETRICK(KEY_,GAMES);
442 NAMETRICK(KEY_,ZOOMIN);
443 NAMETRICK(KEY_,ZOOMOUT);
444 NAMETRICK(KEY_,ZOOMRESET);
445 NAMETRICK(KEY_,DOLLAR);
446 NAMETRICK(KEY_,EURO);
447 NAMETRICK(KEY_,MEDIA);
448 NAMETRICK(KEY_,FRAMEBACK);
449 NAMETRICK(KEY_,FRAMEFORWARD);
450 NAMETRICK(KEY_,CONTEXT_MENU);
451 NAMETRICK(KEY_,MEDIA_REPEAT);
452 NAMETRICK(KEY_,NUMERIC_0);
453 NAMETRICK(KEY_,NUMERIC_1);
454 NAMETRICK(KEY_,NUMERIC_2);
455 NAMETRICK(KEY_,NUMERIC_3);
456 NAMETRICK(KEY_,NUMERIC_4);
457 NAMETRICK(KEY_,NUMERIC_5);
458 NAMETRICK(KEY_,NUMERIC_6);
459 NAMETRICK(KEY_,NUMERIC_7);
460 NAMETRICK(KEY_,NUMERIC_8);
461 NAMETRICK(KEY_,NUMERIC_9);
462 NAMETRICK(KEY_,NUMERIC_STAR);
463 NAMETRICK(KEY_,NUMERIC_POUND);
466 const char* InputLinux::getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey)
481 return tr("Backspace, Back");
483 return tr("Return, Space");
489 std::string InputLinux::getHardwareKeyName(int hardwareKey)
491 const char* desc = linux_keymap[hardwareKey];
501 char* rt = new char[10];
502 sprintf(rt, "0x%x", hardwareKey);
509 void InputLinux::EnterLearningMode(UCHAR vompKey)
511 learnMode = vompKey; // Armed
514 bool InputLinux::start()
516 Log::getInstance()->log("Input", Log::INFO, "start called");
518 threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
519 listenThread = std::thread( [this]
521 threadStartProtect.lock();
522 threadStartProtect.unlock();
525 threadStartProtect.unlock();
529 void InputLinux::stop()
531 threadStartProtect.lock(); // Also use it to protect against starting while stopping
533 if (listenThread.joinable())
535 listenLoopStop = true;
536 write(pfds[1], "1", 1); // break the select in listenLoop
540 threadStartProtect.unlock();
543 void InputLinux::listenLoop()
548 if (pipe2(pfds, O_NONBLOCK) == -1)
550 Log::getInstance()->log("InputLinux", Log::ERR, "pipe2() fail");
554 Log::getInstance()->log("InputLinux", Log::INFO, "Listen loop");
558 if (listenLoopStop) break;
563 for (unsigned int i = 0; i < devices.size(); i++)
565 int cur_fd = devices[i];
566 maxfd = max(cur_fd, maxfd);
567 FD_SET(cur_fd, &readfds);
570 FD_SET(pfds[0], &readfds);
571 maxfd = max(pfds[0], maxfd);
573 // 0 = nothing happened and timeout expired
574 // >0 = num of descriptors that changed
576 if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
578 Log::getInstance()->log("InputLinux", Log::ERR, "Select fail");
582 if (FD_ISSET(pfds[0], &readfds))
584 // assume quit signal
585 Log::getInstance()->log("InputLinux", Log::NOTICE, "pfds quit");
588 // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
591 for (unsigned int i = 0; i < devices.size(); i++)
593 int cur_fd = devices[i];
594 if (FD_ISSET(cur_fd, &readfds))
596 struct input_event ev;
597 int count = read(cur_fd, &ev, sizeof(ev));
598 if (count == sizeof(ev))
600 if (ev.type == EV_KEY && ev.value == 1)
602 sendInputKey(TranslateHWC(ev.code));
613 // FIXME surely NA_SIGNAL can go