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/>.
22 #include <linux/input.h>
23 #include <sys/types.h>
25 #include <sys/ioctl.h>
35 #include "woptionpane.h"
37 #include "inputlinux.h"
39 static const char* TAG = "InputLinux";
41 #define test_bit(input,b) ((1 << ((b) % 8))&(input)[b / 8] )
43 bool InputLinux::init()
45 if (initted) return false;
48 InitHWCListwithDefaults();
51 for (int eventid = 0; eventid < 100; eventid++)
54 sprintf(buffer,"/dev/input/event%d", eventid);
57 if (stat(buffer, &test_buf) == 0)
59 LogNT::getInstance()->info(TAG, "Probe /dev/input/event{}", eventid);
61 unsigned long ev_type = 0;
62 int new_fd = open(buffer, O_RDONLY);
65 LogNT::getInstance()->info(TAG, "Can not open /dev/input/event{}", eventid);
69 if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0)
71 LogNT::getInstance()->info(TAG, "Ioctl failed /dev/input/event{} {}", eventid, errno);
75 //Now test if it generates keyboard presses
76 if (test_bit(reinterpret_cast<char*>(&ev_type), EV_KEY))
78 LogNT::getInstance()->info(TAG, "Add /dev/input/event{} to List", eventid);
79 devices.push_back(new_fd);
81 // Grab the device - make it exclusive to vomp. Fixes rubbish input going to console in background
82 ioctl(new_fd, EVIOCGRAB, 1);
93 void InputLinux::shutdown()
97 while (devices.size())
99 int cur_fd = devices.back();
101 ioctl(cur_fd, EVIOCGRAB, 0);
108 UCHAR InputLinux::TranslateHWCFixed(int code)
110 // Translate /dev/input codes to VOMP codes for the hard coded buttons
113 case KEY_DOWN: return DOWN;
114 case KEY_UP: return UP;
115 case KEY_LEFT: return LEFT;
116 case KEY_RIGHT: return RIGHT;
118 case KEY_MEDIA: return MENU;
120 case KEY_EXIT: return BACK;
123 case KEY_OK: return OK;
126 case KEY_ESC: return POWER;
127 case POWER: return POWER; // Where does this come from?
133 void InputLinux::InitHWCListwithDefaults()
135 LogNT::getInstance()->info(TAG, "InitHWCListwithDefaults");
137 // Processing VK_Messages
138 translist[KEY_9] = NINE;
139 translist[KEY_8] = EIGHT;
140 translist[KEY_7] = SEVEN;
141 translist[KEY_6] = SIX;
142 translist[KEY_5] = FIVE;
143 translist[KEY_4] = FOUR;
144 translist[KEY_3] = THREE;
145 translist[KEY_2] = TWO;
146 translist[KEY_1] = ONE;
147 translist[KEY_0] = ZERO;
148 translist[KEY_KPDOT] = STAR;
149 // translist[KEY_#] = HASH;
151 translist[KEY_KP9] = NINE;
152 translist[KEY_KP8] = EIGHT;
153 translist[KEY_KP7] = SEVEN;
154 translist[KEY_KP6] = SIX;
155 translist[KEY_KP5] = FIVE;
156 translist[KEY_KP4] = FOUR;
157 translist[KEY_KP3] = THREE;
158 translist[KEY_KP2] = TWO;
159 translist[KEY_KP1] = ONE;
160 translist[KEY_KP0] = ZERO;
162 translist[KEY_NUMERIC_9] = NINE;
163 translist[KEY_NUMERIC_8] = EIGHT;
164 translist[KEY_NUMERIC_7] = SEVEN;
165 translist[KEY_NUMERIC_6] = SIX;
166 translist[KEY_NUMERIC_5] = FIVE;
167 translist[KEY_NUMERIC_4] = FOUR;
168 translist[KEY_NUMERIC_3] = THREE;
169 translist[KEY_NUMERIC_2] = TWO;
170 translist[KEY_NUMERIC_1] = ONE;
171 translist[KEY_NUMERIC_0] = ZERO;
172 translist[KEY_NUMERIC_STAR] = STAR;
173 translist[KEY_NUMERIC_POUND] = HASH;
176 translist[KEY_J] = GO; //j for JUMP TO instead of go to
177 translist[KEY_R] = RED;
178 translist[KEY_G] = GREEN;
179 translist[KEY_Y] = YELLOW;
180 translist[KEY_B] = BLUE;
181 //Processing Remote Style Messages
182 translist[KEY_GREEN] = GREEN;
183 translist[KEY_RED] = RED;
184 translist[KEY_YELLOW] = YELLOW;
185 translist[KEY_BLUE] = BLUE;
186 translist[KEY_MENU] = MENU;
188 translist[KEY_RECORD] = RECORD;
189 translist[KEY_PLAY] = PLAY; //Playback Televison
190 translist[KEY_PAUSE] = PAUSE;
191 translist[KEY_STOP] = STOP;
192 translist[KEY_PLAYPAUSE] = PLAYPAUSE;
193 translist[KEY_P] = PLAYPAUSE;
194 translist[KEY_NEXT] = SKIPFORWARD;
195 translist[KEY_F2] = SKIPFORWARD;
196 translist[KEY_PREVIOUS] = SKIPBACK;
197 translist[KEY_F1] = SKIPBACK;
198 translist[KEY_FORWARD] = FORWARD;
199 translist[KEY_FASTFORWARD] = FORWARD;
200 translist[KEY_F] = FORWARD;
201 translist[KEY_BACK] = REVERSE;
202 translist[KEY_REWIND] = REVERSE;
203 translist[KEY_T] = REVERSE;
204 translist[KEY_MUTE] = MUTE;
205 translist[KEY_F8] = MUTE;
206 translist[KEY_F10] = VOLUMEUP;
207 translist[KEY_F9] = VOLUMEDOWN;
208 translist[KEY_VOLUMEUP] = VOLUMEUP;
209 translist[KEY_VOLUMEDOWN] = VOLUMEDOWN;
210 translist[KEY_CHANNELUP] = CHANNELUP;
211 translist[KEY_CHANNELDOWN] = CHANNELDOWN;
212 translist[KEY_PAGEUP] = CHANNELUP;
213 translist[KEY_PAGEDOWN] = CHANNELDOWN;
216 #define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
217 //extracte from linux/input.h
219 static const char * linux_keymap[KEY_MAX+1];
221 void InputLinux::InitKeymap()
223 for (int i=0;i<KEY_MAX+1;i++)
225 linux_keymap[i] = NULL;
228 NAMETRICK(KEY_,RESERVED);
240 NAMETRICK(KEY_,MINUS);
241 NAMETRICK(KEY_,EQUAL);
242 NAMETRICK(KEY_,BACKSPACE);
254 NAMETRICK(KEY_,LEFTBRACE);
255 NAMETRICK(KEY_,RIGHTBRACE);
256 NAMETRICK(KEY_,ENTER);
257 NAMETRICK(KEY_,LEFTCTRL);
267 NAMETRICK(KEY_,SEMICOLON);
268 NAMETRICK(KEY_,APOSTROPHE);
269 NAMETRICK(KEY_,GRAVE);
270 NAMETRICK(KEY_,LEFTSHIFT);
271 NAMETRICK(KEY_,BACKSLASH);
279 NAMETRICK(KEY_,COMMA);
281 NAMETRICK(KEY_,SLASH);
282 NAMETRICK(KEY_,RIGHTSHIFT);
283 NAMETRICK(KEY_,KPASTERISK);
284 NAMETRICK(KEY_,LEFTALT);
285 NAMETRICK(KEY_,SPACE);
286 NAMETRICK(KEY_,CAPSLOCK);
297 NAMETRICK(KEY_,NUMLOCK);
298 NAMETRICK(KEY_,SCROLLLOCK);
302 NAMETRICK(KEY_,KPMINUS);
306 NAMETRICK(KEY_,KPPLUS);
311 NAMETRICK(KEY_,KPDOT);
314 NAMETRICK(KEY_,KPENTER);
315 NAMETRICK(KEY_,RIGHTCTRL);
316 NAMETRICK(KEY_,KPSLASH);
317 NAMETRICK(KEY_,SYSRQ);
318 NAMETRICK(KEY_,RIGHTALT);
319 NAMETRICK(KEY_,LINEFEED);
320 NAMETRICK(KEY_,HOME);
322 NAMETRICK(KEY_,PAGEUP);
323 NAMETRICK(KEY_,LEFT);
324 NAMETRICK(KEY_,RIGHT);
326 NAMETRICK(KEY_,DOWN);
327 NAMETRICK(KEY_,PAGEDOWN);
328 NAMETRICK(KEY_,INSERT);
329 NAMETRICK(KEY_,DELETE);
330 NAMETRICK(KEY_,MACRO);
331 NAMETRICK(KEY_,MUTE);
332 NAMETRICK(KEY_,VOLUMEDOWN);
333 NAMETRICK(KEY_,VOLUMEUP);
334 NAMETRICK(KEY_,POWER);
335 NAMETRICK(KEY_,KPEQUAL);
336 NAMETRICK(KEY_,KPPLUSMINUS);
337 NAMETRICK(KEY_,PLAY);
338 NAMETRICK(KEY_,PAUSE);
339 NAMETRICK(KEY_,SCALE);
340 NAMETRICK(KEY_,KPCOMMA);
342 NAMETRICK(KEY_,LEFTMETA);
343 NAMETRICK(KEY_,RIGHTMETA);
344 NAMETRICK(KEY_,COMPOSE);
345 NAMETRICK(KEY_,STOP);
346 NAMETRICK(KEY_,AGAIN);
347 NAMETRICK(KEY_,PROPS);
348 NAMETRICK(KEY_,UNDO);
349 NAMETRICK(KEY_,FRONT);
350 NAMETRICK(KEY_,COPY);
351 NAMETRICK(KEY_,OPEN);
352 NAMETRICK(KEY_,PASTE);
353 NAMETRICK(KEY_,FIND);
355 NAMETRICK(KEY_,HELP);
356 NAMETRICK(KEY_,MENU);
357 NAMETRICK(KEY_,CALC);
358 NAMETRICK(KEY_,SETUP);
359 NAMETRICK(KEY_,SLEEP);
360 NAMETRICK(KEY_,WAKEUP);
361 NAMETRICK(KEY_,FILE);
362 NAMETRICK(KEY_,SENDFILE);
363 NAMETRICK(KEY_,DELETEFILE);
364 NAMETRICK(KEY_,XFER);
365 NAMETRICK(KEY_,PROG1);
366 NAMETRICK(KEY_,PROG2);
368 NAMETRICK(KEY_,MSDOS);
369 NAMETRICK(KEY_,COFFEE);
370 NAMETRICK(KEY_,DIRECTION);
371 NAMETRICK(KEY_,CYCLEWINDOWS);
372 NAMETRICK(KEY_,MAIL);
373 NAMETRICK(KEY_,BOOKMARKS);
374 NAMETRICK(KEY_,COMPUTER);
375 NAMETRICK(KEY_,BACK);
376 NAMETRICK(KEY_,FORWARD);
377 NAMETRICK(KEY_,FASTFORWARD);
378 NAMETRICK(KEY_,CLOSECD);
379 NAMETRICK(KEY_,EJECTCD);
380 NAMETRICK(KEY_,EJECTCLOSECD);
381 NAMETRICK(KEY_,NEXTSONG);
382 NAMETRICK(KEY_,PLAYPAUSE);
383 NAMETRICK(KEY_,PREVIOUSSONG);
384 NAMETRICK(KEY_,STOPCD);
385 NAMETRICK(KEY_,RECORD);
386 NAMETRICK(KEY_,REWIND);
387 NAMETRICK(KEY_,PHONE);
389 NAMETRICK(KEY_,CONFIG);
390 NAMETRICK(KEY_,HOMEPAGE);
391 NAMETRICK(KEY_,REFRESH);
392 NAMETRICK(KEY_,EXIT);
393 NAMETRICK(KEY_,MOVE);
394 NAMETRICK(KEY_,EDIT);
395 NAMETRICK(KEY_,SCROLLUP);
396 NAMETRICK(KEY_,SCROLLDOWN);
397 NAMETRICK(KEY_,KPLEFTPAREN);
398 NAMETRICK(KEY_,KPRIGHTPAREN);
400 NAMETRICK(KEY_,REDO);
402 NAMETRICK(KEY_,SELECT);
403 NAMETRICK(KEY_,GOTO);
404 NAMETRICK(KEY_,CLEAR);
405 NAMETRICK(KEY_,POWER2);
406 NAMETRICK(KEY_,OPTION);
407 NAMETRICK(KEY_,INFO);
408 NAMETRICK(KEY_,TIME);
409 NAMETRICK(KEY_,VENDOR);
410 NAMETRICK(KEY_,ARCHIVE);
411 NAMETRICK(KEY_,PROGRAM);
412 NAMETRICK(KEY_,CHANNEL);
413 NAMETRICK(KEY_,FAVORITES);
417 NAMETRICK(KEY_,LANGUAGE);
418 NAMETRICK(KEY_,TITLE);
419 NAMETRICK(KEY_,SUBTITLE);
420 NAMETRICK(KEY_,ANGLE);
421 NAMETRICK(KEY_,ZOOM);
422 NAMETRICK(KEY_,MODE);
423 NAMETRICK(KEY_,KEYBOARD);
424 NAMETRICK(KEY_,SCREEN);
426 NAMETRICK(KEY_,GREEN);
427 NAMETRICK(KEY_,YELLOW);
428 NAMETRICK(KEY_,BLUE);
429 NAMETRICK(KEY_,CHANNELUP);
430 NAMETRICK(KEY_,CHANNELDOWN);
431 NAMETRICK(KEY_,FIRST);
432 NAMETRICK(KEY_,LAST);
434 NAMETRICK(KEY_,NEXT);
435 NAMETRICK(KEY_,RESTART);
436 NAMETRICK(KEY_,SLOW);
437 NAMETRICK(KEY_,SHUFFLE);
438 NAMETRICK(KEY_,BREAK);
439 NAMETRICK(KEY_,PREVIOUS);
440 NAMETRICK(KEY_,DIGITS);
441 NAMETRICK(KEY_,TEEN);
442 NAMETRICK(KEY_,TWEN);
443 NAMETRICK(KEY_,VIDEOPHONE);
444 NAMETRICK(KEY_,GAMES);
445 NAMETRICK(KEY_,ZOOMIN);
446 NAMETRICK(KEY_,ZOOMOUT);
447 NAMETRICK(KEY_,ZOOMRESET);
448 NAMETRICK(KEY_,DOLLAR);
449 NAMETRICK(KEY_,EURO);
450 NAMETRICK(KEY_,MEDIA);
451 NAMETRICK(KEY_,FRAMEBACK);
452 NAMETRICK(KEY_,FRAMEFORWARD);
453 NAMETRICK(KEY_,CONTEXT_MENU);
454 NAMETRICK(KEY_,MEDIA_REPEAT);
455 NAMETRICK(KEY_,NUMERIC_0);
456 NAMETRICK(KEY_,NUMERIC_1);
457 NAMETRICK(KEY_,NUMERIC_2);
458 NAMETRICK(KEY_,NUMERIC_3);
459 NAMETRICK(KEY_,NUMERIC_4);
460 NAMETRICK(KEY_,NUMERIC_5);
461 NAMETRICK(KEY_,NUMERIC_6);
462 NAMETRICK(KEY_,NUMERIC_7);
463 NAMETRICK(KEY_,NUMERIC_8);
464 NAMETRICK(KEY_,NUMERIC_9);
465 NAMETRICK(KEY_,NUMERIC_STAR);
466 NAMETRICK(KEY_,NUMERIC_POUND);
469 const char* InputLinux::getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey)
484 return tr("Backspace, Back");
486 return tr("Return, Space");
492 std::string InputLinux::getHardwareKeyName(int hardwareKey)
494 const char* desc = linux_keymap[hardwareKey];
504 char* rt = new char[10];
505 sprintf(rt, "0x%x", hardwareKey);
512 void InputLinux::EnterLearningMode(UCHAR vompKey)
514 learnMode = vompKey; // Armed
517 bool InputLinux::start()
519 LogNT::getInstance()->info(TAG, "start called");
521 threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
522 listenThread = std::thread( [this]
524 threadStartProtect.lock();
525 threadStartProtect.unlock();
528 threadStartProtect.unlock();
532 void InputLinux::stop()
534 threadStartProtect.lock(); // Also use it to protect against starting while stopping
536 if (listenThread.joinable())
538 listenLoopStop = true;
539 write(pfds[1], "1", 1); // break the select in listenLoop
543 threadStartProtect.unlock();
546 void InputLinux::listenLoop()
551 if (pipe2(pfds, O_NONBLOCK) == -1)
553 LogNT::getInstance()->error(TAG, "pipe2() fail");
557 LogNT::getInstance()->info(TAG, "Listen loop");
561 if (listenLoopStop) break;
566 for (unsigned int i = 0; i < devices.size(); i++)
568 int cur_fd = devices[i];
569 maxfd = max(cur_fd, maxfd);
570 FD_SET(cur_fd, &readfds);
573 FD_SET(pfds[0], &readfds);
574 maxfd = max(pfds[0], maxfd);
576 // 0 = nothing happened and timeout expired
577 // >0 = num of descriptors that changed
579 if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
581 LogNT::getInstance()->error(TAG, "Select fail");
585 if (FD_ISSET(pfds[0], &readfds))
587 // assume quit signal
588 LogNT::getInstance()->info(TAG, "pfds quit");
591 // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
594 for (unsigned int i = 0; i < devices.size(); i++)
596 int cur_fd = devices[i];
597 if (FD_ISSET(cur_fd, &readfds))
599 struct input_event ev;
600 int count = read(cur_fd, &ev, sizeof(ev));
601 if (count == sizeof(ev))
603 if (ev.type == EV_KEY && ev.value == 1)
605 sendInputKey(TranslateHWC(ev.code));
616 // FIXME surely NA_SIGNAL can go