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/>.
20 #include <linux/input.h>
21 #include <sys/types.h>
32 #include <libcec/cec.h>
33 #include <libcec/cecloader.h>
38 #include "woptionpane.h"
40 #include "messagequeue.h"
41 #include "command.h" // FIXME - get rid after predefined message targets
43 #include "remotelinux.h"
45 #define W_G_HCW(type,code) ((static_cast<ULLONG>(type) << 32) | code)
47 #define W_HCW_KC 1 /* key code as defined by kernel for keyboard and remotes through /dev/input */
48 #define W_HCW_CEC 2 /* HDMI_CEC */
49 #define W_HCW_LIRC 3 /* remote control LIRC*/
52 RemoteLinux::RemoteLinux()
56 RemoteLinux::~RemoteLinux()
58 for (unsigned int i = 0; i < devices.size(); i++)
64 #define test_bit(input,b) ((1 << ((b) % 8))&(input)[b / 8] )
66 int RemoteLinux::init(const char*)
68 if (initted) return 0;
73 for (int eventid = 0; eventid < 100; eventid++)
76 sprintf(buffer,"/dev/input/event%d", eventid);
79 if (stat(buffer, &test_buf) == 0)
81 Log::getInstance()->log("Remote", Log::NOTICE, "Probe /dev/input/event%d", eventid);
83 unsigned long ev_type = 0;
84 int new_fd = open(buffer, O_RDONLY);
87 Log::getInstance()->log("Remote", Log::NOTICE, "Can not open /dev/input/event%d", eventid);
91 if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0)
93 Log::getInstance()->log("Remote", Log::NOTICE, "Ioctl failed /dev/input/event%d %d", eventid, errno);
97 //Now test if it generates keyboard presses
98 if (test_bit(reinterpret_cast<char*>(&ev_type), EV_KEY))
100 Log::getInstance()->log("Remote", Log::NOTICE, "Add /dev/input/event%d to List", eventid);
101 devices.push_back(new_fd);
112 int RemoteLinux::initCec() {
114 // bcm_host_init(); //may be move to custom hardware init?
116 Log::getInstance()->log("Remote", Log::NOTICE, "Init LibCEC");
118 cec_callbacks.Clear();
119 #if CEC_LIB_VERSION_MAJOR >= 4
120 cec_callbacks.logMessage = cecLogMessage;
121 cec_callbacks.keyPress = cecKeyPress;
122 cec_callbacks.commandReceived = cecCommand;
123 cec_callbacks.configurationChanged = cecConfigurationChanged;
124 cec_callbacks.sourceActivated = cecSourceActivated;
126 cec_callbacks.CBCecLogMessage = cecLogMessage;
127 cec_callbacks.CBCecKeyPress = cecKeyPress;
128 cec_callbacks.CBCecCommand = cecCommand;
129 cec_callbacks.CBCecConfigurationChanged = cecConfigurationChanged;
130 cec_callbacks.CBCecSourceActivated = cecSourceActivated;
131 cec_config.bUseTVMenuLanguage=1;
133 cec_config.clientVersion=LIBCEC_VERSION_CURRENT;
134 cec_config.bActivateSource=1;
135 //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
136 cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
137 //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_TUNER);
139 strncpy(cec_config.strDeviceName,"vomp",sizeof(cec_config.strDeviceName));
142 cec_config.callbackParam = NULL; // I do not care
143 cec_config.callbacks = &cec_callbacks;
145 cec_adap = LibCecInitialise(&cec_config);
147 Log::getInstance()->log("Remote", Log::ERR, "Init LibCEC failed");
150 cec_adap->InitVideoStandalone();
153 #if CEC_LIB_VERSION_MAJOR >= 4
154 cec_adapter_descriptor cec_adapter_descriptors[10];
155 int adap_num=cec_adap->DetectAdapters(cec_adapter_descriptors, 10);
157 cec_adapter cec_devices[10];
158 int adap_num=cec_adap->FindAdapters(cec_devices,10,NULL);
161 Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed to find adapter");
166 Log::getInstance()->log("Remote", Log::NOTICE, "CEC: No adapter found");
170 #if CEC_LIB_VERSION_MAJOR >= 4
171 if (!cec_adap->Open(cec_adapter_descriptors[0].strComName)) {
173 if (!cec_adap->Open(cec_devices[0].comm)) {
175 Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed to open adapter");
179 if (!cec_adap->SetActiveSource(cec_config.deviceTypes[0])) {
180 Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed set active source");
190 int RemoteLinux::shutdown()
192 if (!initted) return 0;
194 while (devices.size()) {
195 int cur_fd = devices.back();
204 void RemoteLinux::deinitCec()
207 Log::getInstance()->log("Remote", Log::NOTICE, "Shutdown libcec begin");
208 cec_adap->SetInactiveView();
210 vc_cec_register_callback(NULL, NULL);//deactivate callback!
211 UnloadLibCec(cec_adap);
213 Log::getInstance()->log("Remote", Log::NOTICE, "Shutdown libcec end");
218 UCHAR RemoteLinux::getButtonPress(int waitType) {
220 how = 1 - start new wait
221 how = 2 - continue wait
226 Log::getInstance()->log("Remote", Log::NOTICE, "get button press");
236 } else if (waitType == 1) {
239 } else if (waitType == 2) {
240 if (num_loop<=0) num_loop = 25;
241 } else if (waitType == 3) {
249 while (num_loop!=0) {
254 for (unsigned int i = 0; i < devices.size(); i++) {
255 int cur_fd = devices[i];
256 maxfd = max(cur_fd, maxfd);
257 FD_SET(cur_fd, &readfds);
260 FD_SET(pfds[0], &readfds);
261 maxfd = max(pfds[0], maxfd);
263 retval = select(maxfd + 1, &readfds, NULL, NULL, &tv);
266 // 0 = nothing happened
267 // 1 = data arrived (actually num of descriptors that changed)
268 // other value = signal or error
272 return (UCHAR) TranslateHWC(W_G_HCW(W_HCW_CEC,curcec));
281 Log::getInstance()->log("Remote", Log::NOTICE, "na_signal");
285 if (FD_ISSET(pfds[0], &readfds))
288 Log::getInstance()->log("Remote", Log::NOTICE, "pfds quit");
289 return NA_SIGNAL; // use NA_SIGNAL for now
292 for (unsigned int i = 0; i < devices.size(); i++) {
293 int cur_fd = devices[i];
294 if (FD_ISSET(cur_fd, &readfds)) {
295 struct input_event ev;
296 int count = read(cur_fd, &ev, sizeof(ev));
297 if (count == sizeof(ev)) {
298 if (ev.type == EV_KEY && ev.value == 1) {
299 UCHAR retty=(UCHAR) TranslateHWC(
300 W_G_HCW(W_HCW_KC,ev.code));
310 //Log::getInstance()->log("Remote", Log::NOTICE, "numloop: %d %d",num_loop,retval);
322 UCHAR RemoteLinux::TranslateHWCFixed(ULLONG code)
326 case W_G_HCW(W_HCW_KC, KEY_DOWN):
328 case W_G_HCW(W_HCW_KC, KEY_UP):
330 case W_G_HCW(W_HCW_KC, KEY_LEFT):
332 case W_G_HCW(W_HCW_KC, KEY_RIGHT):
334 case W_G_HCW(W_HCW_KC, KEY_M):
335 case W_G_HCW(W_HCW_KC, KEY_MEDIA):
337 case W_G_HCW(W_HCW_KC, KEY_BACKSPACE):
338 case W_G_HCW(W_HCW_KC, KEY_EXIT):
340 case W_G_HCW(W_HCW_KC, KEY_ENTER):
341 case W_G_HCW(W_HCW_KC, KEY_SPACE):
342 case W_G_HCW(W_HCW_KC, KEY_OK):
346 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_DOWN):
348 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_UP):
350 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_LEFT):
352 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_RIGHT):
354 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ROOT_MENU):
355 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_CONTENTS_MENU):
356 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SETUP_MENU):
358 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_EXIT ):
360 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ENTER):
361 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SELECT):
362 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_AN_RETURN):
364 case W_G_HCW(W_HCW_KC, KEY_SLEEP):
365 case W_G_HCW(W_HCW_KC, KEY_POWER):
366 case W_G_HCW(W_HCW_KC, KEY_ESC):
367 case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_POWER):
375 const char*RemoteLinux::HardcodedTranslateStr(UCHAR command)
390 return tr("Backspace, Back");
392 return tr("Return, Space");
399 void RemoteLinux::InitHWCListwithDefaults()
401 // Processing VK_Messages
402 translist[W_G_HCW(W_HCW_KC,KEY_9)] = NINE;
403 translist[W_G_HCW(W_HCW_KC,KEY_8)] = EIGHT;
404 translist[W_G_HCW(W_HCW_KC,KEY_7)] = SEVEN;
405 translist[W_G_HCW(W_HCW_KC,KEY_6)] = SIX;
406 translist[W_G_HCW(W_HCW_KC,KEY_5)] = FIVE;
407 translist[W_G_HCW(W_HCW_KC,KEY_4)] = FOUR;
408 translist[W_G_HCW(W_HCW_KC,KEY_3)] = THREE;
409 translist[W_G_HCW(W_HCW_KC,KEY_2)] = TWO;
410 translist[W_G_HCW(W_HCW_KC,KEY_1)] = ONE;
411 translist[W_G_HCW(W_HCW_KC,KEY_0)] = ZERO;
412 translist[W_G_HCW(W_HCW_KC,KEY_KPDOT)] = STAR;
413 // translist[W_G_HCW(W_HCW_KC,KEY_#)] = HASH;
415 translist[W_G_HCW(W_HCW_KC,KEY_KP9)] = NINE;
416 translist[W_G_HCW(W_HCW_KC,KEY_KP8)] = EIGHT;
417 translist[W_G_HCW(W_HCW_KC,KEY_KP7)] = SEVEN;
418 translist[W_G_HCW(W_HCW_KC,KEY_KP6)] = SIX;
419 translist[W_G_HCW(W_HCW_KC,KEY_KP5)] = FIVE;
420 translist[W_G_HCW(W_HCW_KC,KEY_KP4)] = FOUR;
421 translist[W_G_HCW(W_HCW_KC,KEY_KP3)] = THREE;
422 translist[W_G_HCW(W_HCW_KC,KEY_KP2)] = TWO;
423 translist[W_G_HCW(W_HCW_KC,KEY_KP1)] = ONE;
424 translist[W_G_HCW(W_HCW_KC,KEY_KP0)] = ZERO;
426 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_9)] = NINE;
427 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_8)] = EIGHT;
428 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_7)] = SEVEN;
429 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_6)] = SIX;
430 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_5)] = FIVE;
431 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_4)] = FOUR;
432 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_3)] = THREE;
433 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_2)] = TWO;
434 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_1)] = ONE;
435 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_0)] = ZERO;
436 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_STAR)] = STAR;
437 translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_POUND)] = HASH;
440 translist[W_G_HCW(W_HCW_KC,KEY_J)] = GO; //j for JUMP TO instead of go to
441 translist[W_G_HCW(W_HCW_KC,KEY_R)] = RED;
442 translist[W_G_HCW(W_HCW_KC,KEY_G)] = GREEN;
443 translist[W_G_HCW(W_HCW_KC,KEY_Y)] = YELLOW;
444 translist[W_G_HCW(W_HCW_KC,KEY_B)] = BLUE;
445 //Processing Remote Style Messages
446 translist[W_G_HCW(W_HCW_KC,KEY_GREEN)] = GREEN;
447 translist[W_G_HCW(W_HCW_KC,KEY_RED)] = RED;
448 translist[W_G_HCW(W_HCW_KC,KEY_YELLOW)] = YELLOW;
449 translist[W_G_HCW(W_HCW_KC,KEY_BLUE)] = BLUE;
450 translist[W_G_HCW(W_HCW_KC,KEY_MENU)] = MENU;
452 translist[W_G_HCW(W_HCW_KC,KEY_RECORD)] = RECORD;
453 translist[W_G_HCW(W_HCW_KC,KEY_PLAY)] = PLAY; //Playback Televison
454 translist[W_G_HCW(W_HCW_KC,KEY_PAUSE)] = PAUSE;
455 translist[W_G_HCW(W_HCW_KC,KEY_STOP)] = STOP;
456 translist[W_G_HCW(W_HCW_KC,KEY_PLAYPAUSE)] = PLAYPAUSE;
457 translist[W_G_HCW(W_HCW_KC,KEY_P)] = PLAYPAUSE;
458 translist[W_G_HCW(W_HCW_KC,KEY_NEXT)] = SKIPFORWARD;
459 translist[W_G_HCW(W_HCW_KC,KEY_F2)] = SKIPFORWARD;
460 translist[W_G_HCW(W_HCW_KC,KEY_PREVIOUS)] = SKIPBACK;
461 translist[W_G_HCW(W_HCW_KC,KEY_F1)] = SKIPBACK;
462 translist[W_G_HCW(W_HCW_KC,KEY_FORWARD)] = FORWARD;
463 translist[W_G_HCW(W_HCW_KC,KEY_FASTFORWARD)] = FORWARD;
464 translist[W_G_HCW(W_HCW_KC,KEY_F)] = FORWARD;
465 translist[W_G_HCW(W_HCW_KC,KEY_BACK)] = REVERSE;
466 translist[W_G_HCW(W_HCW_KC,KEY_REWIND)] = REVERSE;
467 translist[W_G_HCW(W_HCW_KC,KEY_T)] = REVERSE;
468 translist[W_G_HCW(W_HCW_KC,KEY_MUTE)] = MUTE;
469 translist[W_G_HCW(W_HCW_KC,KEY_F8)] = MUTE;
470 translist[W_G_HCW(W_HCW_KC,KEY_F10)] = VOLUMEUP;
471 translist[W_G_HCW(W_HCW_KC,KEY_F9)] = VOLUMEDOWN;
472 translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEUP)] = VOLUMEUP;
473 translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEDOWN)] = VOLUMEDOWN;
474 translist[W_G_HCW(W_HCW_KC,KEY_CHANNELUP)] = CHANNELUP;
475 translist[W_G_HCW(W_HCW_KC,KEY_CHANNELDOWN)] = CHANNELDOWN;
476 translist[W_G_HCW(W_HCW_KC,KEY_PAGEUP)] = CHANNELUP;
477 translist[W_G_HCW(W_HCW_KC,KEY_PAGEDOWN)] = CHANNELDOWN;
480 //Processing CEC_Messages
481 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER9)] = NINE;
482 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER8)] = EIGHT;
483 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER7)] = SEVEN;
484 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER6)] = SIX;
485 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER5)] = FIVE;
486 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER4)] = FOUR;
487 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER3)] = THREE;
488 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER2)] = TWO;
489 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER1)] = ONE;
490 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER0)] = ZERO;
491 //translist[W_G_HCW(W_HCW_CEC,KEY_KPDOT)] = STAR;
495 //translist[W_G_HCW(W_HCW_CEC,KEY_J)] = GO; //j for JUMP TO instead of go to
496 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F2_RED)] = RED;
497 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F3_GREEN)] = GREEN;
498 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F4_YELLOW)] = YELLOW;
499 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F1_BLUE)] = BLUE;
500 //Processing Remote Style Messages
501 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAVORITE_MENU)] = MENU;
503 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_RECORD)] = RECORD;
504 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PLAY)] = PLAY; //Playback Televison
505 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE)] = PAUSE;
506 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_STOP)] = STOP;
507 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION)] = PLAYPAUSE;
508 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FORWARD)] = SKIPFORWARD;
509 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_BACKWARD)] = SKIPBACK;
510 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAST_FORWARD )] = FORWARD;
511 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_REWIND)] = REVERSE;
512 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_MUTE)] = MUTE;
513 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_UP)] = VOLUMEUP;
514 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_DOWN)] = VOLUMEDOWN;
515 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_UP )] = CHANNELUP;
516 translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_DOWN)] = CHANNELDOWN;
519 #define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
520 #define NAMETRICK2(pre, code) cec_keymap[pre ## code]= #code
521 //extracte from linux/input.h
523 static const char * linux_keymap[KEY_MAX+1];
524 static const char * cec_keymap[CEC_USER_CONTROL_CODE_MAX+1];
526 void RemoteLinux::InitKeymap()
528 for (int i=0;i<KEY_MAX+1;i++)
530 linux_keymap[i] = NULL;
533 NAMETRICK(KEY_,RESERVED);
545 NAMETRICK(KEY_,MINUS);
546 NAMETRICK(KEY_,EQUAL);
547 NAMETRICK(KEY_,BACKSPACE);
559 NAMETRICK(KEY_,LEFTBRACE);
560 NAMETRICK(KEY_,RIGHTBRACE);
561 NAMETRICK(KEY_,ENTER);
562 NAMETRICK(KEY_,LEFTCTRL);
572 NAMETRICK(KEY_,SEMICOLON);
573 NAMETRICK(KEY_,APOSTROPHE);
574 NAMETRICK(KEY_,GRAVE);
575 NAMETRICK(KEY_,LEFTSHIFT);
576 NAMETRICK(KEY_,BACKSLASH);
584 NAMETRICK(KEY_,COMMA);
586 NAMETRICK(KEY_,SLASH);
587 NAMETRICK(KEY_,RIGHTSHIFT);
588 NAMETRICK(KEY_,KPASTERISK);
589 NAMETRICK(KEY_,LEFTALT);
590 NAMETRICK(KEY_,SPACE);
591 NAMETRICK(KEY_,CAPSLOCK);
602 NAMETRICK(KEY_,NUMLOCK);
603 NAMETRICK(KEY_,SCROLLLOCK);
607 NAMETRICK(KEY_,KPMINUS);
611 NAMETRICK(KEY_,KPPLUS);
616 NAMETRICK(KEY_,KPDOT);
619 NAMETRICK(KEY_,KPENTER);
620 NAMETRICK(KEY_,RIGHTCTRL);
621 NAMETRICK(KEY_,KPSLASH);
622 NAMETRICK(KEY_,SYSRQ);
623 NAMETRICK(KEY_,RIGHTALT);
624 NAMETRICK(KEY_,LINEFEED);
625 NAMETRICK(KEY_,HOME);
627 NAMETRICK(KEY_,PAGEUP);
628 NAMETRICK(KEY_,LEFT);
629 NAMETRICK(KEY_,RIGHT);
631 NAMETRICK(KEY_,DOWN);
632 NAMETRICK(KEY_,PAGEDOWN);
633 NAMETRICK(KEY_,INSERT);
634 NAMETRICK(KEY_,DELETE);
635 NAMETRICK(KEY_,MACRO);
636 NAMETRICK(KEY_,MUTE);
637 NAMETRICK(KEY_,VOLUMEDOWN);
638 NAMETRICK(KEY_,VOLUMEUP);
639 NAMETRICK(KEY_,POWER);
640 NAMETRICK(KEY_,KPEQUAL);
641 NAMETRICK(KEY_,KPPLUSMINUS);
642 NAMETRICK(KEY_,PLAY);
643 NAMETRICK(KEY_,PAUSE);
644 NAMETRICK(KEY_,SCALE);
645 NAMETRICK(KEY_,KPCOMMA);
647 NAMETRICK(KEY_,LEFTMETA);
648 NAMETRICK(KEY_,RIGHTMETA);
649 NAMETRICK(KEY_,COMPOSE);
650 NAMETRICK(KEY_,STOP);
651 NAMETRICK(KEY_,AGAIN);
652 NAMETRICK(KEY_,PROPS);
653 NAMETRICK(KEY_,UNDO);
654 NAMETRICK(KEY_,FRONT);
655 NAMETRICK(KEY_,COPY);
656 NAMETRICK(KEY_,OPEN);
657 NAMETRICK(KEY_,PASTE);
658 NAMETRICK(KEY_,FIND);
660 NAMETRICK(KEY_,HELP);
661 NAMETRICK(KEY_,MENU);
662 NAMETRICK(KEY_,CALC);
663 NAMETRICK(KEY_,SETUP);
664 NAMETRICK(KEY_,SLEEP);
665 NAMETRICK(KEY_,WAKEUP);
666 NAMETRICK(KEY_,FILE);
667 NAMETRICK(KEY_,SENDFILE);
668 NAMETRICK(KEY_,DELETEFILE);
669 NAMETRICK(KEY_,XFER);
670 NAMETRICK(KEY_,PROG1);
671 NAMETRICK(KEY_,PROG2);
673 NAMETRICK(KEY_,MSDOS);
674 NAMETRICK(KEY_,COFFEE);
675 NAMETRICK(KEY_,DIRECTION);
676 NAMETRICK(KEY_,CYCLEWINDOWS);
677 NAMETRICK(KEY_,MAIL);
678 NAMETRICK(KEY_,BOOKMARKS);
679 NAMETRICK(KEY_,COMPUTER);
680 NAMETRICK(KEY_,BACK);
681 NAMETRICK(KEY_,FORWARD);
682 NAMETRICK(KEY_,FASTFORWARD);
683 NAMETRICK(KEY_,CLOSECD);
684 NAMETRICK(KEY_,EJECTCD);
685 NAMETRICK(KEY_,EJECTCLOSECD);
686 NAMETRICK(KEY_,NEXTSONG);
687 NAMETRICK(KEY_,PLAYPAUSE);
688 NAMETRICK(KEY_,PREVIOUSSONG);
689 NAMETRICK(KEY_,STOPCD);
690 NAMETRICK(KEY_,RECORD);
691 NAMETRICK(KEY_,REWIND);
692 NAMETRICK(KEY_,PHONE);
694 NAMETRICK(KEY_,CONFIG);
695 NAMETRICK(KEY_,HOMEPAGE);
696 NAMETRICK(KEY_,REFRESH);
697 NAMETRICK(KEY_,EXIT);
698 NAMETRICK(KEY_,MOVE);
699 NAMETRICK(KEY_,EDIT);
700 NAMETRICK(KEY_,SCROLLUP);
701 NAMETRICK(KEY_,SCROLLDOWN);
702 NAMETRICK(KEY_,KPLEFTPAREN);
703 NAMETRICK(KEY_,KPRIGHTPAREN);
705 NAMETRICK(KEY_,REDO);
707 NAMETRICK(KEY_,SELECT);
708 NAMETRICK(KEY_,GOTO);
709 NAMETRICK(KEY_,CLEAR);
710 NAMETRICK(KEY_,POWER2);
711 NAMETRICK(KEY_,OPTION);
712 NAMETRICK(KEY_,INFO);
713 NAMETRICK(KEY_,TIME);
714 NAMETRICK(KEY_,VENDOR);
715 NAMETRICK(KEY_,ARCHIVE);
716 NAMETRICK(KEY_,PROGRAM);
717 NAMETRICK(KEY_,CHANNEL);
718 NAMETRICK(KEY_,FAVORITES);
722 NAMETRICK(KEY_,LANGUAGE);
723 NAMETRICK(KEY_,TITLE);
724 NAMETRICK(KEY_,SUBTITLE);
725 NAMETRICK(KEY_,ANGLE);
726 NAMETRICK(KEY_,ZOOM);
727 NAMETRICK(KEY_,MODE);
728 NAMETRICK(KEY_,KEYBOARD);
729 NAMETRICK(KEY_,SCREEN);
731 NAMETRICK(KEY_,GREEN);
732 NAMETRICK(KEY_,YELLOW);
733 NAMETRICK(KEY_,BLUE);
734 NAMETRICK(KEY_,CHANNELUP);
735 NAMETRICK(KEY_,CHANNELDOWN);
736 NAMETRICK(KEY_,FIRST);
737 NAMETRICK(KEY_,LAST);
739 NAMETRICK(KEY_,NEXT);
740 NAMETRICK(KEY_,RESTART);
741 NAMETRICK(KEY_,SLOW);
742 NAMETRICK(KEY_,SHUFFLE);
743 NAMETRICK(KEY_,BREAK);
744 NAMETRICK(KEY_,PREVIOUS);
745 NAMETRICK(KEY_,DIGITS);
746 NAMETRICK(KEY_,TEEN);
747 NAMETRICK(KEY_,TWEN);
748 NAMETRICK(KEY_,VIDEOPHONE);
749 NAMETRICK(KEY_,GAMES);
750 NAMETRICK(KEY_,ZOOMIN);
751 NAMETRICK(KEY_,ZOOMOUT);
752 NAMETRICK(KEY_,ZOOMRESET);
753 NAMETRICK(KEY_,DOLLAR);
754 NAMETRICK(KEY_,EURO);
755 NAMETRICK(KEY_,MEDIA);
756 NAMETRICK(KEY_,FRAMEBACK);
757 NAMETRICK(KEY_,FRAMEFORWARD);
758 NAMETRICK(KEY_,CONTEXT_MENU);
759 NAMETRICK(KEY_,MEDIA_REPEAT);
760 NAMETRICK(KEY_,NUMERIC_0);
761 NAMETRICK(KEY_,NUMERIC_1);
762 NAMETRICK(KEY_,NUMERIC_2);
763 NAMETRICK(KEY_,NUMERIC_3);
764 NAMETRICK(KEY_,NUMERIC_4);
765 NAMETRICK(KEY_,NUMERIC_5);
766 NAMETRICK(KEY_,NUMERIC_6);
767 NAMETRICK(KEY_,NUMERIC_7);
768 NAMETRICK(KEY_,NUMERIC_8);
769 NAMETRICK(KEY_,NUMERIC_9);
770 NAMETRICK(KEY_,NUMERIC_STAR);
771 NAMETRICK(KEY_,NUMERIC_POUND);
773 for (int i=0; i < CEC_USER_CONTROL_CODE_MAX + 1; i++)
775 cec_keymap[i] = NULL;
778 NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT);
779 NAMETRICK2(CEC_USER_CONTROL_CODE_,UP);
780 NAMETRICK2(CEC_USER_CONTROL_CODE_,DOWN);
781 NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT);
782 NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT);
783 NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_UP);
784 NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_DOWN);
785 NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_UP);
786 NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_DOWN);
787 NAMETRICK2(CEC_USER_CONTROL_CODE_,ROOT_MENU);
788 NAMETRICK2(CEC_USER_CONTROL_CODE_,SETUP_MENU);
789 NAMETRICK2(CEC_USER_CONTROL_CODE_,CONTENTS_MENU);
790 NAMETRICK2(CEC_USER_CONTROL_CODE_,FAVORITE_MENU);
791 NAMETRICK2(CEC_USER_CONTROL_CODE_,EXIT);
792 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER0);
793 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER1);
794 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER2);
795 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER3);
796 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER4);
797 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER5);
798 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER6);
799 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER7);
800 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER8);
801 NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER9);
802 NAMETRICK2(CEC_USER_CONTROL_CODE_,DOT);
803 NAMETRICK2(CEC_USER_CONTROL_CODE_,ENTER);
804 NAMETRICK2(CEC_USER_CONTROL_CODE_,CLEAR);
805 NAMETRICK2(CEC_USER_CONTROL_CODE_,NEXT_FAVORITE);
806 NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_UP);
807 NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_DOWN);
808 NAMETRICK2(CEC_USER_CONTROL_CODE_,PREVIOUS_CHANNEL);
809 NAMETRICK2(CEC_USER_CONTROL_CODE_,SOUND_SELECT);
810 NAMETRICK2(CEC_USER_CONTROL_CODE_,INPUT_SELECT);
811 NAMETRICK2(CEC_USER_CONTROL_CODE_,DISPLAY_INFORMATION);
812 NAMETRICK2(CEC_USER_CONTROL_CODE_,HELP);
813 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_UP);
814 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_DOWN);
815 NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER );
816 NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_UP );
817 NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_DOWN );
818 NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE );
819 NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY );
820 NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP );
821 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE );
822 NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD );
823 NAMETRICK2(CEC_USER_CONTROL_CODE_,REWIND );
824 NAMETRICK2(CEC_USER_CONTROL_CODE_,FAST_FORWARD );
825 NAMETRICK2(CEC_USER_CONTROL_CODE_,EJECT );
826 NAMETRICK2(CEC_USER_CONTROL_CODE_,FORWARD );
827 NAMETRICK2(CEC_USER_CONTROL_CODE_,BACKWARD );
828 NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_RECORD );
829 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD );
830 NAMETRICK2(CEC_USER_CONTROL_CODE_,ANGLE );
831 NAMETRICK2(CEC_USER_CONTROL_CODE_,SUB_PICTURE );
832 NAMETRICK2(CEC_USER_CONTROL_CODE_,VIDEO_ON_DEMAND );
833 NAMETRICK2(CEC_USER_CONTROL_CODE_,ELECTRONIC_PROGRAM_GUIDE );
834 NAMETRICK2(CEC_USER_CONTROL_CODE_,TIMER_PROGRAMMING );
835 NAMETRICK2(CEC_USER_CONTROL_CODE_,INITIAL_CONFIGURATION );
836 NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY_FUNCTION );
837 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_PLAY_FUNCTION );
838 NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD_FUNCTION );
839 NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD_FUNCTION );
840 NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_FUNCTION );
841 NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE_FUNCTION );
842 NAMETRICK2(CEC_USER_CONTROL_CODE_,RESTORE_VOLUME_FUNCTION );
843 NAMETRICK2(CEC_USER_CONTROL_CODE_,TUNE_FUNCTION );
844 NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_MEDIA_FUNCTION );
845 NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AV_INPUT_FUNCTION );
846 NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AUDIO_INPUT_FUNCTION );
847 NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_TOGGLE_FUNCTION );
848 NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_OFF_FUNCTION );
849 NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_ON_FUNCTION );
850 NAMETRICK2(CEC_USER_CONTROL_CODE_,F1_BLUE );
851 NAMETRICK2(CEC_USER_CONTROL_CODE_,F2_RED );
852 NAMETRICK2(CEC_USER_CONTROL_CODE_,F3_GREEN );
853 NAMETRICK2(CEC_USER_CONTROL_CODE_,F4_YELLOW );
854 NAMETRICK2(CEC_USER_CONTROL_CODE_,F5 );
855 NAMETRICK2(CEC_USER_CONTROL_CODE_,DATA );
856 NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_RETURN );
857 NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_CHANNELS_LIST );
858 NAMETRICK2(CEC_USER_CONTROL_CODE_,MAX );
863 char* RemoteLinux::HCWDesc(unsigned long long hcw)
866 unsigned int type = static_cast<unsigned int>(hcw >> 32);
867 unsigned int vk = static_cast<ULONG>(hcw);
875 const char *desc=linux_keymap[vk];
877 strncpy(rt, desc, 9);
879 sprintf(rt, "0x%x", vk);
885 const char* desc = cec_keymap[vk];
887 strncpy(rt, desc, 9);
889 sprintf(rt, "0x%x", vk);
896 sprintf(rt,"R: %X",ri);
903 void RemoteLinux::changePowerState(bool poweron)
909 //Log::getInstance()->log("Remote", Log::DEBUG, "CEC set active source");
910 cec_adap->SetActiveSource(cec_config.deviceTypes[0]);
914 //Log::getInstance()->log("Remote", Log::DEBUG, "CEC set inactive view");
915 cec_adap->SetInactiveView();
920 #if CEC_LIB_VERSION_MAJOR >= 4
922 // libcec4 API changed these params to pointers rather than copies, and the returns to void
923 // Otherwise, these two blocks of code are the same
925 void RemoteLinux::cecLogMessage(void* /* param */, const cec_log_message* message)
927 Log::getInstance()->log("Remote", Log::DEBUG, "CECLOG: %lld %d %s", message->time, message->level, message->message);
930 void RemoteLinux::cecKeyPress(void* /* param */, const cec_keypress* key)
932 //Log::getInstance()->log("Remote", Log::DEBUG, "Incoming cec key %d %d", key->keycode,key->duration);
933 if (key->duration == 0) static_cast<RemoteLinux*>(Remote::getInstance())->incomingCECkey(key->keycode);
936 void RemoteLinux::cecCommand(void* /* param */, const cec_command* command)
938 Log::getInstance()->log("Remote", Log::DEBUG, "CECCommand: %d",command->opcode);
939 switch (command->opcode) {
940 case CEC_OPCODE_STANDBY: {
941 if (command->initiator==CECDEVICE_TV) {
942 static_cast<RemoteLinux*>(Remote::getInstance())->incomingPowerkey(POWEROFF);
945 case CEC_OPCODE_DECK_CONTROL: {
946 if (command->initiator==CECDEVICE_TV && command->parameters.size == 1
947 && command->parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
948 static_cast<RemoteLinux*>(Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
953 case CEC_OPCODE_PLAY: {
954 if (command->initiator==CECDEVICE_TV && command->parameters.size == 1) {
955 if (command->parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
956 static_cast<RemoteLinux*>(Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
957 } else if (command->parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
958 static_cast<RemoteLinux*>(Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
969 void RemoteLinux::cecConfigurationChanged(void* /* param */, const libcec_configuration*)
971 Log::getInstance()->log("Remote", Log::DEBUG, "CECConfig:"/*,config->string()*/);
976 int RemoteLinux::cecLogMessage(void *param, const cec_log_message message)
978 Log::getInstance()->log("Remote", Log::DEBUG, "CECLOG: %lld %d %s", message.time, message.level, message.message);
982 int RemoteLinux::cecKeyPress(void*param, const cec_keypress key)
984 //Log::getInstance()->log("Remote", Log::DEBUG, "Incoming cec key %d %d", key.keycode,key.duration);
985 if (key.duration == 0) ((RemoteLinux*)Remote::getInstance())->incomingCECkey(key.keycode);
989 int RemoteLinux::cecCommand(void *param, const cec_command command)
991 Log::getInstance()->log("Remote", Log::DEBUG, "CECCommand: %d",command.opcode);
992 switch (command.opcode) {
993 case CEC_OPCODE_STANDBY: {
994 if (command.initiator==CECDEVICE_TV) {
995 ((RemoteLinux*)Remote::getInstance())->incomingPowerkey(POWEROFF);
998 case CEC_OPCODE_DECK_CONTROL: {
999 if (command.initiator==CECDEVICE_TV && command.parameters.size == 1
1000 && command.parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
1001 ((RemoteLinux*)Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
1006 case CEC_OPCODE_PLAY: {
1007 if (command.initiator==CECDEVICE_TV && command.parameters.size == 1) {
1008 if (command.parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
1009 ((RemoteLinux*)Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
1010 } else if (command.parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
1011 ((RemoteLinux*)Remote::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
1023 int RemoteLinux::cecConfigurationChanged(void *param, const libcec_configuration config)
1025 Log::getInstance()->log("Remote", Log::DEBUG, "CECConfig:"/*,config.string()*/);
1032 void RemoteLinux::cecSourceActivated(void* /* param */, const cec_logical_address address, const uint8_t activated)
1034 Log::getInstance()->log("Remote", Log::DEBUG, "CECSourceActivated: %d %d", address, activated);
1037 static_cast<RemoteLinux*>(Remote::getInstance())->incomingPowerkey(POWERON);
1041 void RemoteLinux::incomingCECkey(int keys)
1043 // Send INPUT message
1044 Message* m = new Message();
1045 m->message = Message::INPUT_EVENT;
1046 m->to = Command::getInstance();
1048 m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_CEC, keys)));
1049 MessageQueue::getInstance()->postMessage(m);
1052 void RemoteLinux::incomingPowerkey(UCHAR key)
1054 // Send INPUT message
1055 Message* m = new Message();
1056 m->message = Message::INPUT_EVENT;
1057 m->to = Command::getInstance();
1060 MessageQueue::getInstance()->postMessage(m);
1063 bool RemoteLinux::loadOptionsfromServer(VDR* vdr)
1067 name = vdr->configLoad("RemoteLinux", "HandleVolume");
1071 if (STRCASECMP(name, "Vomp") == 0) cechandlesvolume = false;
1072 else if (STRCASECMP(name, "Cec") == 0) cechandlesvolume = true;
1075 return Remote::loadOptionsfromServer(vdr);
1078 bool RemoteLinux::saveOptionstoServer()
1080 if (cechandlesvolume) VDR::getInstance()->configSave("RemoteLinux", "HandleVolume","Cec");
1081 else VDR::getInstance()->configSave("RemoteLinux", "HandleVolume","Vomp");
1083 return Remote::saveOptionstoServer();
1086 bool RemoteLinux::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
1088 if (!Remote::addOptionsToPanes(panenumber, options, pane)) return false;
1091 if (panenumber == 2)
1093 static const char* volumeopts[]={"Vomp","Cec"};
1094 option = new Option(100,tr("Volume handled by"), "RemoteLinux","HandleVolume",Option::TYPE_TEXT,/*4,2*/2,0,0,volumeopts,NULL,false,this);
1095 options->push_back(option);
1096 pane->addOptionLine(option);
1102 bool RemoteLinux::handleOptionChanges(Option* option)
1104 if (Remote::handleOptionChanges(option))
1106 switch (option->id) {
1108 if (STRCASECMP(option->options[option->userSetChoice], "Vomp") == 0) {
1109 cechandlesvolume=false;
1110 } else if (STRCASECMP(option->options[option->userSetChoice], "Cec")
1112 cechandlesvolume=true;
1114 Log::getInstance()->log("Remote", Log::DEBUG, "Set volume handling to to %s %d",option->options[option->userSetChoice],cechandlesvolume);
1123 void RemoteLinux::volumeUp()
1125 cec_adap->VolumeUp();
1128 void RemoteLinux::volumeDown()
1130 cec_adap->VolumeDown();
1133 void RemoteLinux::volumeMute()
1135 #if CEC_LIB_VERSION_MAJOR >= 4
1136 cec_adap->AudioToggleMute();
1138 cec_adap->MuteAudio();
1142 void RemoteLinux::informStopEventLoop()
1144 listenLoopStop = true;
1145 write(pfds[1], "1", 1); // break the select in getButtonPress
1148 void RemoteLinux::eventLoop()
1153 if (pipe2(pfds, O_NONBLOCK) == -1)
1155 Log::getInstance()->log("RemoteLinux", Log::ERR, "pipe2() fail");
1159 Log::getInstance()->log("RemoteLinux", Log::INFO, "Listen loop");
1163 if (listenLoopStop) break;
1168 for (unsigned int i = 0; i < devices.size(); i++)
1170 int cur_fd = devices[i];
1171 maxfd = max(cur_fd, maxfd);
1172 FD_SET(cur_fd, &readfds);
1175 FD_SET(pfds[0], &readfds);
1176 maxfd = max(pfds[0], maxfd);
1178 // 0 = nothing happened and timeout expired
1179 // >0 = num of descriptors that changed
1181 if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
1183 Log::getInstance()->log("RemoteLinux", Log::ERR, "Select fail");
1187 if (FD_ISSET(pfds[0], &readfds))
1189 // assume quit signal
1190 Log::getInstance()->log("Remote", Log::NOTICE, "pfds quit");
1193 // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
1196 for (unsigned int i = 0; i < devices.size(); i++)
1198 int cur_fd = devices[i];
1199 if (FD_ISSET(cur_fd, &readfds))
1201 struct input_event ev;
1202 int count = read(cur_fd, &ev, sizeof(ev));
1203 if (count == sizeof(ev))
1205 if (ev.type == EV_KEY && ev.value == 1)
1207 // Send INPUT message
1208 Message* m = new Message();
1209 m->message = Message::INPUT_EVENT;
1210 m->to = Command::getInstance();
1212 m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_KC,ev.code)));
1213 MessageQueue::getInstance()->postMessage(m);
1224 // FIXME surely NA_SIGNAL can go