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 // Processing VK_Messages
133 translist[KEY_9] = NINE;
134 translist[KEY_8] = EIGHT;
135 translist[KEY_7] = SEVEN;
136 translist[KEY_6] = SIX;
137 translist[KEY_5] = FIVE;
138 translist[KEY_4] = FOUR;
139 translist[KEY_3] = THREE;
140 translist[KEY_2] = TWO;
141 translist[KEY_1] = ONE;
142 translist[KEY_0] = ZERO;
143 translist[KEY_KPDOT] = STAR;
144 // translist[KEY_#] = HASH;
146 translist[KEY_KP9] = NINE;
147 translist[KEY_KP8] = EIGHT;
148 translist[KEY_KP7] = SEVEN;
149 translist[KEY_KP6] = SIX;
150 translist[KEY_KP5] = FIVE;
151 translist[KEY_KP4] = FOUR;
152 translist[KEY_KP3] = THREE;
153 translist[KEY_KP2] = TWO;
154 translist[KEY_KP1] = ONE;
155 translist[KEY_KP0] = ZERO;
157 translist[KEY_NUMERIC_9] = NINE;
158 translist[KEY_NUMERIC_8] = EIGHT;
159 translist[KEY_NUMERIC_7] = SEVEN;
160 translist[KEY_NUMERIC_6] = SIX;
161 translist[KEY_NUMERIC_5] = FIVE;
162 translist[KEY_NUMERIC_4] = FOUR;
163 translist[KEY_NUMERIC_3] = THREE;
164 translist[KEY_NUMERIC_2] = TWO;
165 translist[KEY_NUMERIC_1] = ONE;
166 translist[KEY_NUMERIC_0] = ZERO;
167 translist[KEY_NUMERIC_STAR] = STAR;
168 translist[KEY_NUMERIC_POUND] = HASH;
171 translist[KEY_J] = GO; //j for JUMP TO instead of go to
172 translist[KEY_R] = RED;
173 translist[KEY_G] = GREEN;
174 translist[KEY_Y] = YELLOW;
175 translist[KEY_B] = BLUE;
176 //Processing Remote Style Messages
177 translist[KEY_GREEN] = GREEN;
178 translist[KEY_RED] = RED;
179 translist[KEY_YELLOW] = YELLOW;
180 translist[KEY_BLUE] = BLUE;
181 translist[KEY_MENU] = MENU;
183 translist[KEY_RECORD] = RECORD;
184 translist[KEY_PLAY] = PLAY; //Playback Televison
185 translist[KEY_PAUSE] = PAUSE;
186 translist[KEY_STOP] = STOP;
187 translist[KEY_PLAYPAUSE] = PLAYPAUSE;
188 translist[KEY_P] = PLAYPAUSE;
189 translist[KEY_NEXT] = SKIPFORWARD;
190 translist[KEY_F2] = SKIPFORWARD;
191 translist[KEY_PREVIOUS] = SKIPBACK;
192 translist[KEY_F1] = SKIPBACK;
193 translist[KEY_FORWARD] = FORWARD;
194 translist[KEY_FASTFORWARD] = FORWARD;
195 translist[KEY_F] = FORWARD;
196 translist[KEY_BACK] = REVERSE;
197 translist[KEY_REWIND] = REVERSE;
198 translist[KEY_T] = REVERSE;
199 translist[KEY_MUTE] = MUTE;
200 translist[KEY_F8] = MUTE;
201 translist[KEY_F10] = VOLUMEUP;
202 translist[KEY_F9] = VOLUMEDOWN;
203 translist[KEY_VOLUMEUP] = VOLUMEUP;
204 translist[KEY_VOLUMEDOWN] = VOLUMEDOWN;
205 translist[KEY_CHANNELUP] = CHANNELUP;
206 translist[KEY_CHANNELDOWN] = CHANNELDOWN;
207 translist[KEY_PAGEUP] = CHANNELUP;
208 translist[KEY_PAGEDOWN] = CHANNELDOWN;
211 #define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
212 //extracte from linux/input.h
214 static const char * linux_keymap[KEY_MAX+1];
216 void InputLinux::InitKeymap()
218 for (int i=0;i<KEY_MAX+1;i++)
220 linux_keymap[i] = NULL;
223 NAMETRICK(KEY_,RESERVED);
235 NAMETRICK(KEY_,MINUS);
236 NAMETRICK(KEY_,EQUAL);
237 NAMETRICK(KEY_,BACKSPACE);
249 NAMETRICK(KEY_,LEFTBRACE);
250 NAMETRICK(KEY_,RIGHTBRACE);
251 NAMETRICK(KEY_,ENTER);
252 NAMETRICK(KEY_,LEFTCTRL);
262 NAMETRICK(KEY_,SEMICOLON);
263 NAMETRICK(KEY_,APOSTROPHE);
264 NAMETRICK(KEY_,GRAVE);
265 NAMETRICK(KEY_,LEFTSHIFT);
266 NAMETRICK(KEY_,BACKSLASH);
274 NAMETRICK(KEY_,COMMA);
276 NAMETRICK(KEY_,SLASH);
277 NAMETRICK(KEY_,RIGHTSHIFT);
278 NAMETRICK(KEY_,KPASTERISK);
279 NAMETRICK(KEY_,LEFTALT);
280 NAMETRICK(KEY_,SPACE);
281 NAMETRICK(KEY_,CAPSLOCK);
292 NAMETRICK(KEY_,NUMLOCK);
293 NAMETRICK(KEY_,SCROLLLOCK);
297 NAMETRICK(KEY_,KPMINUS);
301 NAMETRICK(KEY_,KPPLUS);
306 NAMETRICK(KEY_,KPDOT);
309 NAMETRICK(KEY_,KPENTER);
310 NAMETRICK(KEY_,RIGHTCTRL);
311 NAMETRICK(KEY_,KPSLASH);
312 NAMETRICK(KEY_,SYSRQ);
313 NAMETRICK(KEY_,RIGHTALT);
314 NAMETRICK(KEY_,LINEFEED);
315 NAMETRICK(KEY_,HOME);
317 NAMETRICK(KEY_,PAGEUP);
318 NAMETRICK(KEY_,LEFT);
319 NAMETRICK(KEY_,RIGHT);
321 NAMETRICK(KEY_,DOWN);
322 NAMETRICK(KEY_,PAGEDOWN);
323 NAMETRICK(KEY_,INSERT);
324 NAMETRICK(KEY_,DELETE);
325 NAMETRICK(KEY_,MACRO);
326 NAMETRICK(KEY_,MUTE);
327 NAMETRICK(KEY_,VOLUMEDOWN);
328 NAMETRICK(KEY_,VOLUMEUP);
329 NAMETRICK(KEY_,POWER);
330 NAMETRICK(KEY_,KPEQUAL);
331 NAMETRICK(KEY_,KPPLUSMINUS);
332 NAMETRICK(KEY_,PLAY);
333 NAMETRICK(KEY_,PAUSE);
334 NAMETRICK(KEY_,SCALE);
335 NAMETRICK(KEY_,KPCOMMA);
337 NAMETRICK(KEY_,LEFTMETA);
338 NAMETRICK(KEY_,RIGHTMETA);
339 NAMETRICK(KEY_,COMPOSE);
340 NAMETRICK(KEY_,STOP);
341 NAMETRICK(KEY_,AGAIN);
342 NAMETRICK(KEY_,PROPS);
343 NAMETRICK(KEY_,UNDO);
344 NAMETRICK(KEY_,FRONT);
345 NAMETRICK(KEY_,COPY);
346 NAMETRICK(KEY_,OPEN);
347 NAMETRICK(KEY_,PASTE);
348 NAMETRICK(KEY_,FIND);
350 NAMETRICK(KEY_,HELP);
351 NAMETRICK(KEY_,MENU);
352 NAMETRICK(KEY_,CALC);
353 NAMETRICK(KEY_,SETUP);
354 NAMETRICK(KEY_,SLEEP);
355 NAMETRICK(KEY_,WAKEUP);
356 NAMETRICK(KEY_,FILE);
357 NAMETRICK(KEY_,SENDFILE);
358 NAMETRICK(KEY_,DELETEFILE);
359 NAMETRICK(KEY_,XFER);
360 NAMETRICK(KEY_,PROG1);
361 NAMETRICK(KEY_,PROG2);
363 NAMETRICK(KEY_,MSDOS);
364 NAMETRICK(KEY_,COFFEE);
365 NAMETRICK(KEY_,DIRECTION);
366 NAMETRICK(KEY_,CYCLEWINDOWS);
367 NAMETRICK(KEY_,MAIL);
368 NAMETRICK(KEY_,BOOKMARKS);
369 NAMETRICK(KEY_,COMPUTER);
370 NAMETRICK(KEY_,BACK);
371 NAMETRICK(KEY_,FORWARD);
372 NAMETRICK(KEY_,FASTFORWARD);
373 NAMETRICK(KEY_,CLOSECD);
374 NAMETRICK(KEY_,EJECTCD);
375 NAMETRICK(KEY_,EJECTCLOSECD);
376 NAMETRICK(KEY_,NEXTSONG);
377 NAMETRICK(KEY_,PLAYPAUSE);
378 NAMETRICK(KEY_,PREVIOUSSONG);
379 NAMETRICK(KEY_,STOPCD);
380 NAMETRICK(KEY_,RECORD);
381 NAMETRICK(KEY_,REWIND);
382 NAMETRICK(KEY_,PHONE);
384 NAMETRICK(KEY_,CONFIG);
385 NAMETRICK(KEY_,HOMEPAGE);
386 NAMETRICK(KEY_,REFRESH);
387 NAMETRICK(KEY_,EXIT);
388 NAMETRICK(KEY_,MOVE);
389 NAMETRICK(KEY_,EDIT);
390 NAMETRICK(KEY_,SCROLLUP);
391 NAMETRICK(KEY_,SCROLLDOWN);
392 NAMETRICK(KEY_,KPLEFTPAREN);
393 NAMETRICK(KEY_,KPRIGHTPAREN);
395 NAMETRICK(KEY_,REDO);
397 NAMETRICK(KEY_,SELECT);
398 NAMETRICK(KEY_,GOTO);
399 NAMETRICK(KEY_,CLEAR);
400 NAMETRICK(KEY_,POWER2);
401 NAMETRICK(KEY_,OPTION);
402 NAMETRICK(KEY_,INFO);
403 NAMETRICK(KEY_,TIME);
404 NAMETRICK(KEY_,VENDOR);
405 NAMETRICK(KEY_,ARCHIVE);
406 NAMETRICK(KEY_,PROGRAM);
407 NAMETRICK(KEY_,CHANNEL);
408 NAMETRICK(KEY_,FAVORITES);
412 NAMETRICK(KEY_,LANGUAGE);
413 NAMETRICK(KEY_,TITLE);
414 NAMETRICK(KEY_,SUBTITLE);
415 NAMETRICK(KEY_,ANGLE);
416 NAMETRICK(KEY_,ZOOM);
417 NAMETRICK(KEY_,MODE);
418 NAMETRICK(KEY_,KEYBOARD);
419 NAMETRICK(KEY_,SCREEN);
421 NAMETRICK(KEY_,GREEN);
422 NAMETRICK(KEY_,YELLOW);
423 NAMETRICK(KEY_,BLUE);
424 NAMETRICK(KEY_,CHANNELUP);
425 NAMETRICK(KEY_,CHANNELDOWN);
426 NAMETRICK(KEY_,FIRST);
427 NAMETRICK(KEY_,LAST);
429 NAMETRICK(KEY_,NEXT);
430 NAMETRICK(KEY_,RESTART);
431 NAMETRICK(KEY_,SLOW);
432 NAMETRICK(KEY_,SHUFFLE);
433 NAMETRICK(KEY_,BREAK);
434 NAMETRICK(KEY_,PREVIOUS);
435 NAMETRICK(KEY_,DIGITS);
436 NAMETRICK(KEY_,TEEN);
437 NAMETRICK(KEY_,TWEN);
438 NAMETRICK(KEY_,VIDEOPHONE);
439 NAMETRICK(KEY_,GAMES);
440 NAMETRICK(KEY_,ZOOMIN);
441 NAMETRICK(KEY_,ZOOMOUT);
442 NAMETRICK(KEY_,ZOOMRESET);
443 NAMETRICK(KEY_,DOLLAR);
444 NAMETRICK(KEY_,EURO);
445 NAMETRICK(KEY_,MEDIA);
446 NAMETRICK(KEY_,FRAMEBACK);
447 NAMETRICK(KEY_,FRAMEFORWARD);
448 NAMETRICK(KEY_,CONTEXT_MENU);
449 NAMETRICK(KEY_,MEDIA_REPEAT);
450 NAMETRICK(KEY_,NUMERIC_0);
451 NAMETRICK(KEY_,NUMERIC_1);
452 NAMETRICK(KEY_,NUMERIC_2);
453 NAMETRICK(KEY_,NUMERIC_3);
454 NAMETRICK(KEY_,NUMERIC_4);
455 NAMETRICK(KEY_,NUMERIC_5);
456 NAMETRICK(KEY_,NUMERIC_6);
457 NAMETRICK(KEY_,NUMERIC_7);
458 NAMETRICK(KEY_,NUMERIC_8);
459 NAMETRICK(KEY_,NUMERIC_9);
460 NAMETRICK(KEY_,NUMERIC_STAR);
461 NAMETRICK(KEY_,NUMERIC_POUND);
464 const char* InputLinux::getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey)
479 return tr("Backspace, Back");
481 return tr("Return, Space");
487 std::string InputLinux::getHardwareKeyName(int hardwareKey)
489 const char* desc = linux_keymap[hardwareKey];
499 char* rt = new char[10];
500 sprintf(rt, "0x%x", hardwareKey);
507 bool InputLinux::start()
509 Log::getInstance()->log("Input", Log::INFO, "start called");
511 threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
512 listenThread = std::thread( [this]
514 threadStartProtect.lock();
515 threadStartProtect.unlock();
518 threadStartProtect.unlock();
522 void InputLinux::stop()
524 threadStartProtect.lock(); // Also use it to protect against starting while stopping
526 if (listenThread.joinable())
528 listenLoopStop = true;
529 write(pfds[1], "1", 1); // break the select in listenLoop
533 threadStartProtect.unlock();
536 void InputLinux::listenLoop()
541 if (pipe2(pfds, O_NONBLOCK) == -1)
543 Log::getInstance()->log("InputLinux", Log::ERR, "pipe2() fail");
547 Log::getInstance()->log("InputLinux", Log::INFO, "Listen loop");
551 if (listenLoopStop) break;
556 for (unsigned int i = 0; i < devices.size(); i++)
558 int cur_fd = devices[i];
559 maxfd = max(cur_fd, maxfd);
560 FD_SET(cur_fd, &readfds);
563 FD_SET(pfds[0], &readfds);
564 maxfd = max(pfds[0], maxfd);
566 // 0 = nothing happened and timeout expired
567 // >0 = num of descriptors that changed
569 if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
571 Log::getInstance()->log("InputLinux", Log::ERR, "Select fail");
575 if (FD_ISSET(pfds[0], &readfds))
577 // assume quit signal
578 Log::getInstance()->log("InputLinux", Log::NOTICE, "pfds quit");
581 // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
584 for (unsigned int i = 0; i < devices.size(); i++)
586 int cur_fd = devices[i];
587 if (FD_ISSET(cur_fd, &readfds))
589 struct input_event ev;
590 int count = read(cur_fd, &ev, sizeof(ev));
591 if (count == sizeof(ev))
593 if (ev.type == EV_KEY && ev.value == 1)
595 sendInputKey(TranslateHWC(ev.code));
606 // FIXME surely NA_SIGNAL can go