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 static const char* TAG = "InputLinux";
40 #define test_bit(input,b) ((1 << ((b) % 8))&(input)[b / 8] )
42 bool InputLinux::init()
44 if (initted) return false;
47 InitHWCListwithDefaults();
50 for (int eventid = 0; eventid < 100; eventid++)
53 sprintf(buffer,"/dev/input/event%d", eventid);
56 if (stat(buffer, &test_buf) == 0)
58 LogNT::getInstance()->info(TAG, "Probe /dev/input/event{}", eventid);
60 unsigned long ev_type = 0;
61 int new_fd = open(buffer, O_RDONLY);
64 LogNT::getInstance()->info(TAG, "Can not open /dev/input/event{}", eventid);
68 if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0)
70 LogNT::getInstance()->info(TAG, "Ioctl failed /dev/input/event{} {}", eventid, errno);
74 //Now test if it generates keyboard presses
75 if (test_bit(reinterpret_cast<char*>(&ev_type), EV_KEY))
77 LogNT::getInstance()->info(TAG, "Add /dev/input/event{} to List", eventid);
78 devices.push_back(new_fd);
80 // Grab the device - make it exclusive to vomp. Fixes rubbish input going to console in background
81 ioctl(new_fd, EVIOCGRAB, 1);
92 void InputLinux::shutdown()
96 while (devices.size())
98 int cur_fd = devices.back();
100 ioctl(cur_fd, EVIOCGRAB, 0);
107 UCHAR InputLinux::TranslateHWCFixed(int code)
109 // Translate /dev/input codes to VOMP codes for the hard coded buttons
112 case KEY_DOWN: return DOWN;
113 case KEY_UP: return UP;
114 case KEY_LEFT: return LEFT;
115 case KEY_RIGHT: return RIGHT;
117 case KEY_MEDIA: return MENU;
119 case KEY_EXIT: return BACK;
122 case KEY_OK: return OK;
125 case KEY_ESC: return POWER;
126 case POWER: return POWER; // Where does this come from?
132 void InputLinux::InitHWCListwithDefaults()
134 LogNT::getInstance()->info(TAG, "InitHWCListwithDefaults");
136 // Processing VK_Messages
137 translist[KEY_9] = NINE;
138 translist[KEY_8] = EIGHT;
139 translist[KEY_7] = SEVEN;
140 translist[KEY_6] = SIX;
141 translist[KEY_5] = FIVE;
142 translist[KEY_4] = FOUR;
143 translist[KEY_3] = THREE;
144 translist[KEY_2] = TWO;
145 translist[KEY_1] = ONE;
146 translist[KEY_0] = ZERO;
147 translist[KEY_KPDOT] = STAR;
148 // translist[KEY_#] = HASH;
150 translist[KEY_KP9] = NINE;
151 translist[KEY_KP8] = EIGHT;
152 translist[KEY_KP7] = SEVEN;
153 translist[KEY_KP6] = SIX;
154 translist[KEY_KP5] = FIVE;
155 translist[KEY_KP4] = FOUR;
156 translist[KEY_KP3] = THREE;
157 translist[KEY_KP2] = TWO;
158 translist[KEY_KP1] = ONE;
159 translist[KEY_KP0] = ZERO;
161 translist[KEY_NUMERIC_9] = NINE;
162 translist[KEY_NUMERIC_8] = EIGHT;
163 translist[KEY_NUMERIC_7] = SEVEN;
164 translist[KEY_NUMERIC_6] = SIX;
165 translist[KEY_NUMERIC_5] = FIVE;
166 translist[KEY_NUMERIC_4] = FOUR;
167 translist[KEY_NUMERIC_3] = THREE;
168 translist[KEY_NUMERIC_2] = TWO;
169 translist[KEY_NUMERIC_1] = ONE;
170 translist[KEY_NUMERIC_0] = ZERO;
171 translist[KEY_NUMERIC_STAR] = STAR;
172 translist[KEY_NUMERIC_POUND] = HASH;
175 translist[KEY_J] = GO; //j for JUMP TO instead of go to
176 translist[KEY_R] = RED;
177 translist[KEY_G] = GREEN;
178 translist[KEY_Y] = YELLOW;
179 translist[KEY_B] = BLUE;
180 //Processing Remote Style Messages
181 translist[KEY_GREEN] = GREEN;
182 translist[KEY_RED] = RED;
183 translist[KEY_YELLOW] = YELLOW;
184 translist[KEY_BLUE] = BLUE;
185 translist[KEY_MENU] = MENU;
187 translist[KEY_RECORD] = RECORD;
188 translist[KEY_PLAY] = PLAY; //Playback Televison
189 translist[KEY_PAUSE] = PAUSE;
190 translist[KEY_STOP] = STOP;
191 translist[KEY_PLAYPAUSE] = PLAYPAUSE;
192 translist[KEY_P] = PLAYPAUSE;
193 translist[KEY_NEXT] = SKIPFORWARD;
194 translist[KEY_F2] = SKIPFORWARD;
195 translist[KEY_PREVIOUS] = SKIPBACK;
196 translist[KEY_F1] = SKIPBACK;
197 translist[KEY_FORWARD] = FORWARD;
198 translist[KEY_FASTFORWARD] = FORWARD;
199 translist[KEY_F] = FORWARD;
200 translist[KEY_BACK] = REVERSE;
201 translist[KEY_REWIND] = REVERSE;
202 translist[KEY_T] = REVERSE;
203 translist[KEY_MUTE] = MUTE;
204 translist[KEY_F8] = MUTE;
205 translist[KEY_F10] = VOLUMEUP;
206 translist[KEY_F9] = VOLUMEDOWN;
207 translist[KEY_VOLUMEUP] = VOLUMEUP;
208 translist[KEY_VOLUMEDOWN] = VOLUMEDOWN;
209 translist[KEY_CHANNELUP] = CHANNELUP;
210 translist[KEY_CHANNELDOWN] = CHANNELDOWN;
211 translist[KEY_PAGEUP] = CHANNELUP;
212 translist[KEY_PAGEDOWN] = CHANNELDOWN;
215 #define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
216 //extracte from linux/input.h
218 static const char * linux_keymap[KEY_MAX+1];
220 void InputLinux::InitKeymap()
222 for (int i=0;i<KEY_MAX+1;i++)
224 linux_keymap[i] = NULL;
227 NAMETRICK(KEY_,RESERVED);
239 NAMETRICK(KEY_,MINUS);
240 NAMETRICK(KEY_,EQUAL);
241 NAMETRICK(KEY_,BACKSPACE);
253 NAMETRICK(KEY_,LEFTBRACE);
254 NAMETRICK(KEY_,RIGHTBRACE);
255 NAMETRICK(KEY_,ENTER);
256 NAMETRICK(KEY_,LEFTCTRL);
266 NAMETRICK(KEY_,SEMICOLON);
267 NAMETRICK(KEY_,APOSTROPHE);
268 NAMETRICK(KEY_,GRAVE);
269 NAMETRICK(KEY_,LEFTSHIFT);
270 NAMETRICK(KEY_,BACKSLASH);
278 NAMETRICK(KEY_,COMMA);
280 NAMETRICK(KEY_,SLASH);
281 NAMETRICK(KEY_,RIGHTSHIFT);
282 NAMETRICK(KEY_,KPASTERISK);
283 NAMETRICK(KEY_,LEFTALT);
284 NAMETRICK(KEY_,SPACE);
285 NAMETRICK(KEY_,CAPSLOCK);
296 NAMETRICK(KEY_,NUMLOCK);
297 NAMETRICK(KEY_,SCROLLLOCK);
301 NAMETRICK(KEY_,KPMINUS);
305 NAMETRICK(KEY_,KPPLUS);
310 NAMETRICK(KEY_,KPDOT);
313 NAMETRICK(KEY_,KPENTER);
314 NAMETRICK(KEY_,RIGHTCTRL);
315 NAMETRICK(KEY_,KPSLASH);
316 NAMETRICK(KEY_,SYSRQ);
317 NAMETRICK(KEY_,RIGHTALT);
318 NAMETRICK(KEY_,LINEFEED);
319 NAMETRICK(KEY_,HOME);
321 NAMETRICK(KEY_,PAGEUP);
322 NAMETRICK(KEY_,LEFT);
323 NAMETRICK(KEY_,RIGHT);
325 NAMETRICK(KEY_,DOWN);
326 NAMETRICK(KEY_,PAGEDOWN);
327 NAMETRICK(KEY_,INSERT);
328 NAMETRICK(KEY_,DELETE);
329 NAMETRICK(KEY_,MACRO);
330 NAMETRICK(KEY_,MUTE);
331 NAMETRICK(KEY_,VOLUMEDOWN);
332 NAMETRICK(KEY_,VOLUMEUP);
333 NAMETRICK(KEY_,POWER);
334 NAMETRICK(KEY_,KPEQUAL);
335 NAMETRICK(KEY_,KPPLUSMINUS);
336 NAMETRICK(KEY_,PLAY);
337 NAMETRICK(KEY_,PAUSE);
338 NAMETRICK(KEY_,SCALE);
339 NAMETRICK(KEY_,KPCOMMA);
341 NAMETRICK(KEY_,LEFTMETA);
342 NAMETRICK(KEY_,RIGHTMETA);
343 NAMETRICK(KEY_,COMPOSE);
344 NAMETRICK(KEY_,STOP);
345 NAMETRICK(KEY_,AGAIN);
346 NAMETRICK(KEY_,PROPS);
347 NAMETRICK(KEY_,UNDO);
348 NAMETRICK(KEY_,FRONT);
349 NAMETRICK(KEY_,COPY);
350 NAMETRICK(KEY_,OPEN);
351 NAMETRICK(KEY_,PASTE);
352 NAMETRICK(KEY_,FIND);
354 NAMETRICK(KEY_,HELP);
355 NAMETRICK(KEY_,MENU);
356 NAMETRICK(KEY_,CALC);
357 NAMETRICK(KEY_,SETUP);
358 NAMETRICK(KEY_,SLEEP);
359 NAMETRICK(KEY_,WAKEUP);
360 NAMETRICK(KEY_,FILE);
361 NAMETRICK(KEY_,SENDFILE);
362 NAMETRICK(KEY_,DELETEFILE);
363 NAMETRICK(KEY_,XFER);
364 NAMETRICK(KEY_,PROG1);
365 NAMETRICK(KEY_,PROG2);
367 NAMETRICK(KEY_,MSDOS);
368 NAMETRICK(KEY_,COFFEE);
369 NAMETRICK(KEY_,DIRECTION);
370 NAMETRICK(KEY_,CYCLEWINDOWS);
371 NAMETRICK(KEY_,MAIL);
372 NAMETRICK(KEY_,BOOKMARKS);
373 NAMETRICK(KEY_,COMPUTER);
374 NAMETRICK(KEY_,BACK);
375 NAMETRICK(KEY_,FORWARD);
376 NAMETRICK(KEY_,FASTFORWARD);
377 NAMETRICK(KEY_,CLOSECD);
378 NAMETRICK(KEY_,EJECTCD);
379 NAMETRICK(KEY_,EJECTCLOSECD);
380 NAMETRICK(KEY_,NEXTSONG);
381 NAMETRICK(KEY_,PLAYPAUSE);
382 NAMETRICK(KEY_,PREVIOUSSONG);
383 NAMETRICK(KEY_,STOPCD);
384 NAMETRICK(KEY_,RECORD);
385 NAMETRICK(KEY_,REWIND);
386 NAMETRICK(KEY_,PHONE);
388 NAMETRICK(KEY_,CONFIG);
389 NAMETRICK(KEY_,HOMEPAGE);
390 NAMETRICK(KEY_,REFRESH);
391 NAMETRICK(KEY_,EXIT);
392 NAMETRICK(KEY_,MOVE);
393 NAMETRICK(KEY_,EDIT);
394 NAMETRICK(KEY_,SCROLLUP);
395 NAMETRICK(KEY_,SCROLLDOWN);
396 NAMETRICK(KEY_,KPLEFTPAREN);
397 NAMETRICK(KEY_,KPRIGHTPAREN);
399 NAMETRICK(KEY_,REDO);
401 NAMETRICK(KEY_,SELECT);
402 NAMETRICK(KEY_,GOTO);
403 NAMETRICK(KEY_,CLEAR);
404 NAMETRICK(KEY_,POWER2);
405 NAMETRICK(KEY_,OPTION);
406 NAMETRICK(KEY_,INFO);
407 NAMETRICK(KEY_,TIME);
408 NAMETRICK(KEY_,VENDOR);
409 NAMETRICK(KEY_,ARCHIVE);
410 NAMETRICK(KEY_,PROGRAM);
411 NAMETRICK(KEY_,CHANNEL);
412 NAMETRICK(KEY_,FAVORITES);
416 NAMETRICK(KEY_,LANGUAGE);
417 NAMETRICK(KEY_,TITLE);
418 NAMETRICK(KEY_,SUBTITLE);
419 NAMETRICK(KEY_,ANGLE);
420 NAMETRICK(KEY_,ZOOM);
421 NAMETRICK(KEY_,MODE);
422 NAMETRICK(KEY_,KEYBOARD);
423 NAMETRICK(KEY_,SCREEN);
425 NAMETRICK(KEY_,GREEN);
426 NAMETRICK(KEY_,YELLOW);
427 NAMETRICK(KEY_,BLUE);
428 NAMETRICK(KEY_,CHANNELUP);
429 NAMETRICK(KEY_,CHANNELDOWN);
430 NAMETRICK(KEY_,FIRST);
431 NAMETRICK(KEY_,LAST);
433 NAMETRICK(KEY_,NEXT);
434 NAMETRICK(KEY_,RESTART);
435 NAMETRICK(KEY_,SLOW);
436 NAMETRICK(KEY_,SHUFFLE);
437 NAMETRICK(KEY_,BREAK);
438 NAMETRICK(KEY_,PREVIOUS);
439 NAMETRICK(KEY_,DIGITS);
440 NAMETRICK(KEY_,TEEN);
441 NAMETRICK(KEY_,TWEN);
442 NAMETRICK(KEY_,VIDEOPHONE);
443 NAMETRICK(KEY_,GAMES);
444 NAMETRICK(KEY_,ZOOMIN);
445 NAMETRICK(KEY_,ZOOMOUT);
446 NAMETRICK(KEY_,ZOOMRESET);
447 NAMETRICK(KEY_,DOLLAR);
448 NAMETRICK(KEY_,EURO);
449 NAMETRICK(KEY_,MEDIA);
450 NAMETRICK(KEY_,FRAMEBACK);
451 NAMETRICK(KEY_,FRAMEFORWARD);
452 NAMETRICK(KEY_,CONTEXT_MENU);
453 NAMETRICK(KEY_,MEDIA_REPEAT);
454 NAMETRICK(KEY_,NUMERIC_0);
455 NAMETRICK(KEY_,NUMERIC_1);
456 NAMETRICK(KEY_,NUMERIC_2);
457 NAMETRICK(KEY_,NUMERIC_3);
458 NAMETRICK(KEY_,NUMERIC_4);
459 NAMETRICK(KEY_,NUMERIC_5);
460 NAMETRICK(KEY_,NUMERIC_6);
461 NAMETRICK(KEY_,NUMERIC_7);
462 NAMETRICK(KEY_,NUMERIC_8);
463 NAMETRICK(KEY_,NUMERIC_9);
464 NAMETRICK(KEY_,NUMERIC_STAR);
465 NAMETRICK(KEY_,NUMERIC_POUND);
468 const char* InputLinux::getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey)
483 return tr("Backspace, Back");
485 return tr("Return, Space");
491 std::string InputLinux::getHardwareKeyName(int hardwareKey)
493 const char* desc = linux_keymap[hardwareKey];
503 char* rt = new char[10];
504 sprintf(rt, "0x%x", hardwareKey);
511 void InputLinux::EnterLearningMode(UCHAR vompKey)
513 learnMode = vompKey; // Armed
516 bool InputLinux::start()
518 LogNT::getInstance()->info(TAG, "start called");
520 threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
521 listenThread = std::thread( [this]
523 threadStartProtect.lock();
524 threadStartProtect.unlock();
527 threadStartProtect.unlock();
531 void InputLinux::stop()
533 threadStartProtect.lock(); // Also use it to protect against starting while stopping
535 if (listenThread.joinable())
537 listenLoopStop = true;
538 write(pfds[1], "1", 1); // break the select in listenLoop
542 threadStartProtect.unlock();
545 void InputLinux::listenLoop()
550 if (pipe2(pfds, O_NONBLOCK) == -1)
552 LogNT::getInstance()->error(TAG, "pipe2() fail");
556 LogNT::getInstance()->info(TAG, "Listen loop");
560 if (listenLoopStop) break;
565 for (unsigned int i = 0; i < devices.size(); i++)
567 int cur_fd = devices[i];
568 maxfd = max(cur_fd, maxfd);
569 FD_SET(cur_fd, &readfds);
572 FD_SET(pfds[0], &readfds);
573 maxfd = max(pfds[0], maxfd);
575 // 0 = nothing happened and timeout expired
576 // >0 = num of descriptors that changed
578 if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
580 LogNT::getInstance()->error(TAG, "Select fail");
584 if (FD_ISSET(pfds[0], &readfds))
586 // assume quit signal
587 LogNT::getInstance()->info(TAG, "pfds quit");
590 // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
593 for (unsigned int i = 0; i < devices.size(); i++)
595 int cur_fd = devices[i];
596 if (FD_ISSET(cur_fd, &readfds))
598 struct input_event ev;
599 int count = read(cur_fd, &ev, sizeof(ev));
600 if (count == sizeof(ev))
602 if (ev.type == EV_KEY && ev.value == 1)
604 sendInputKey(TranslateHWC(ev.code));
615 // FIXME surely NA_SIGNAL can go