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