#include <sys/stat.h>
#include <fcntl.h>
+#include <cstdio>
+#include <iostream>
+#include <ostream>
+
+#include <bcm_host.h>
+
+using namespace std;
+using namespace CEC;
+
+#include <libcec/cecloader.h>
+
RemoteLinux::RemoteLinux()
{
initted = 0;
- curevent=0;
- hascurevent=false;
+ curcec=0;
+ hascurcec=false;
signal=false;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
+ cec_adap=NULL;
+ num_loop=0;
}
}
+
+
+
+
}
+ // bcm_host_init(); //may be move to custom hardware init?
+// now init cec
+ Log::getInstance()->log("Remote", Log::NOTICE, "Init LibCEC");
+ cec_config.Clear();
+ cec_callbacks.Clear();
+ cec_callbacks.CBCecLogMessage = cecLogMessage;
+ cec_callbacks.CBCecKeyPress = cecKeyPress;
+ cec_callbacks.CBCecCommand = cecCommand;
+ cec_callbacks.CBCecConfigurationChanged = cecConfigurationChanged;
+ cec_config.clientVersion=LIBCEC_VERSION_CURRENT;
+ cec_config.bActivateSource=1;
+ cec_config.bUseTVMenuLanguage=1;
+ //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_TUNER);
+
+ strncpy(cec_config.strDeviceName,"vomp",sizeof(cec_config.strDeviceName));
+
+
+ cec_config.callbackParam = NULL; // I do not care
+ cec_config.callbacks = &cec_callbacks;
+
+ cec_adap = LibCecInitialise(&cec_config);
+ if (!cec_adap) {
+ Log::getInstance()->log("Remote", Log::ERR, "Init LibCEC failed");
+ return 1;
+ }
+ cec_adap->InitVideoStandalone();
+
+
+ cec_adapter cec_devices[10];
+ int adap_num=cec_adap->FindAdapters(cec_devices,10,NULL);
+ if (adap_num<0) {
+ Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed to find adapter");
+ return 1;
+
+ }
+ if (adap_num==0) {
+ Log::getInstance()->log("Remote", Log::NOTICE, "CEC: No adapter found");
+ return 1;
+
+ }
+ if (!cec_adap->Open(cec_devices[0].comm)) {
+ Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed to open adapter");
+ return 1;
+ }
+
+ if (!cec_adap->SetActiveSource(cec_config.deviceTypes[0])) {
+ Log::getInstance()->log("Remote", Log::ERR, "CEC:Failed set active source");
+ return 1;
+ }
+
int RemoteLinux::shutdown()
{
if (!initted) return 0;
+ if (cec_adap) {
+ cec_adap->SetInactiveView();
+ cec_adap->Close();
+ UnloadLibCec(cec_adap);
+ }
initted = 0;
return 1;
}
-UCHAR RemoteLinux::getButtonPress(int waitType)
-{
- /* how = 0 - block
- how = 1 - start new wait
- how = 2 - continue wait
- how = 3 - no wait
- */
-
-
- struct timeval* passToSelect = NULL;
- int retval;
- fd_set readfds;
-
- if (waitType == 0)
- {
- passToSelect = NULL;
- }
- else if (waitType == 1)
- {
- tv.tv_sec = 1;
- tv.tv_usec = 000000;
- passToSelect = &tv;
- }
- else if (waitType == 2)
- {
- if ((tv.tv_sec == 0) && (tv.tv_usec == 0)) // protection in case timer = 0
- {
- tv.tv_sec = 1;
- tv.tv_usec = 000000;
- }
- passToSelect = &tv;
- }
- else if (waitType == 3)
- {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- passToSelect = &tv;
- }
- FD_ZERO(&readfds);
-
- int maxfd=0;
- for (int i=0; i<devices.size();i++) {
- int cur_fd=devices[i];
- maxfd=max(cur_fd,maxfd);
- FD_SET(cur_fd, &readfds);
- }
-
-
-
- retval = select(maxfd + 1, &readfds, NULL, NULL, &tv);
- // 0 = nothing happened
- // 1 = data arrived (actually num of descriptors that changed)
- // other value = signal or error
- if (retval == 0) return NA_NONE;
- if (retval == -1) return NA_SIGNAL;
+UCHAR RemoteLinux::getButtonPress(int waitType) {
+ /* how = 0 - block
+ how = 1 - start new wait
+ how = 2 - continue wait
+ how = 3 - no wait
+ */
+
+ //in units of 40 ms
+
+ int retval;
+ fd_set readfds;
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 40000;
+ if (waitType == 0) {
+ num_loop = -1;
+ } else if (waitType == 1) {
+
+ num_loop = 25;
+ } else if (waitType == 2) {
+ if (num_loop<=0) num_loop = 25;
+ } else if (waitType == 3) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ num_loop = 0;
+ }
- for (int i=0; i<devices.size();i++) {
- int cur_fd=devices[i];
- if (FD_ISSET(cur_fd, &readfds)) {
- struct input_event ev;
- int count = read(cur_fd, &ev, sizeof(ev));
- if (count==sizeof(ev)) {
- if (ev.type==EV_KEY && ev.value==1) {
- return (UCHAR) TranslateHWC(W_G_HCW(W_HCW_KC,ev.code));
- }
- }
+ int ret = 0;
+ while (num_loop!=0) {
+ ret = NA_UNKNOWN;
+ FD_ZERO(&readfds);
+
+ int maxfd = 0;
+ for (int i = 0; i < devices.size(); i++) {
+ int cur_fd = devices[i];
+ maxfd = max(cur_fd, maxfd);
+ FD_SET(cur_fd, &readfds);
+ }
+
+ retval = select(maxfd + 1, &readfds, NULL, NULL, &tv);
+ tv.tv_sec = 0;
+ tv.tv_usec = 40000;
+ // 0 = nothing happened
+ // 1 = data arrived (actually num of descriptors that changed)
+ // other value = signal or error
+ if (retval == 0) {
+ if (hascurcec) {
+ hascurcec = false;
+ return (UCHAR) TranslateHWC(W_G_HCW(W_HCW_CEC,curcec));
+ }
+ ret = NA_NONE;
+ } else {
+ if (retval == -1) {
+ Log::getInstance()->log("Remote", Log::NOTICE, "na_signal");
+ return NA_SIGNAL;
+
+ }
+ for (int i = 0; i < devices.size(); i++) {
+ int cur_fd = devices[i];
+ if (FD_ISSET(cur_fd, &readfds)) {
+ struct input_event ev;
+ int count = read(cur_fd, &ev, sizeof(ev));
+ if (count == sizeof(ev)) {
+ if (ev.type == EV_KEY && ev.value == 1) {
+ UCHAR retty=(UCHAR) TranslateHWC(
+ W_G_HCW(W_HCW_KC,ev.code));
+ return retty;
+ }
+ }
+
+ }
+
+ }
+
+ }
+ //Log::getInstance()->log("Remote", Log::NOTICE, "numloop: %d %d",num_loop,retval);
+ if (num_loop > 0)
+ num_loop--;
+ }
+ if (ret != 0)
+ return ret;
- }
+ return NA_UNKNOWN;
- }
-
- return NA_UNKNOWN;
-
}
void RemoteLinux::clearBuffer()
case W_G_HCW(W_HCW_KC,KEY_SPACE):
case W_G_HCW(W_HCW_KC,KEY_OK):
return OK;
+ //CEC
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_DOWN):
+ return DOWN;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_UP):
+ return UP;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_LEFT):
+ return LEFT;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_RIGHT):
+ return RIGHT;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_ROOT_MENU):
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CONTENTS_MENU):
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_SETUP_MENU):
+ return MENU;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_EXIT ):
+ return BACK;
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_ENTER):
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_SELECT):
+ case W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_AN_RETURN):
+ return OK;
case POWER:
return POWER;
default:
translist[W_G_HCW(W_HCW_KC,KEY_PAGEDOWN)] = CHANNELDOWN;
+ //Processing CEC_Messages
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER9)] = NINE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER8)] = EIGHT;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER7)] = SEVEN;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER6)] = SIX;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER5)] = FIVE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER4)] = FOUR;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER3)] = THREE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER2)] = TWO;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER1)] = ONE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER0)] = ZERO;
+ translist[W_G_HCW(W_HCW_CEC,KEY_KPDOT)] = STAR;
+
+
+
+ //translist[W_G_HCW(W_HCW_CEC,KEY_J)] = GO; //j for JUMP TO instead of go to
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F2_RED)] = RED;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F3_GREEN)] = GREEN;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F4_YELLOW)] = YELLOW;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F1_BLUE)] = BLUE;
+ //Processing Remote Style Messages
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAVORITE_MENU)] = MENU;
+
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_RECORD)] = RECORD;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PLAY)] = PLAY; //Playback Televison
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE)] = PAUSE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_STOP)] = STOP;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION)] = PLAYPAUSE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FORWARD)] = SKIPFORWARD;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_BACKWARD)] = SKIPBACK;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAST_FORWARD )] = FORWARD;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_REWIND)] = REVERSE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_MUTE)] = MUTE;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_UP)] = VOLUMEUP;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_DOWN)] = VOLUMEDOWN;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_UP )] = CHANNELUP;
+ translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_DOWN)] = CHANNELDOWN;
+
+
+
}
#define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
+#define NAMETRICK2(pre, code) cec_keymap[pre ## code]= #code
//extracte from linux/input.h
static const char * linux_keymap[KEY_MAX+1];
+static const char * cec_keymap[CEC_USER_CONTROL_CODE_MAX+1];
void RemoteLinux::InitKeymap()
{
NAMETRICK(KEY_,NUMERIC_STAR);
NAMETRICK(KEY_,NUMERIC_POUND);
-
+ for (int i=0;i<CEC_USER_CONTROL_CODE_MAX+1;i++) {
+ cec_keymap[i]=NULL;
+ }
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ROOT_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SETUP_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CONTENTS_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FAVORITE_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,EXIT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER0);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER1);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER2);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER3);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER4);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER5);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER6);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER7);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER8);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER9);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DOT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ENTER);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CLEAR);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NEXT_FAVORITE);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PREVIOUS_CHANNEL);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SOUND_SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,INPUT_SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DISPLAY_INFORMATION);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,HELP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_UP );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_DOWN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,REWIND );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FAST_FORWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,EJECT );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FORWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,BACKWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ANGLE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SUB_PICTURE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VIDEO_ON_DEMAND );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ELECTRONIC_PROGRAM_GUIDE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,TIMER_PROGRAMMING );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,INITIAL_CONFIGURATION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_PLAY_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RESTORE_VOLUME_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,TUNE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_MEDIA_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AV_INPUT_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AUDIO_INPUT_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_TOGGLE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_OFF_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_ON_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F1_BLUE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F2_RED );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F3_GREEN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F4_YELLOW );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F5 );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DATA );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_RETURN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_CHANNELS_LIST );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MAX );
}
sprintf(rt,"0x%x",vk);
}
}break;
- //TODO
- /* case W_HCW_CEC:{
- ULONG ch=(ULONG)hcw;
- ULONG scancode=OemKeyScan(ch);
-
+ case W_HCW_CEC:{
+ unsigned int vk=(ULONG)hcw;
rt=new char[10];
- GetKeyNameText(scancode << 16,rt,10);
+ const char *desc=cec_keymap[vk];
+ if (desc) {
+ strncpy(rt,desc,9);
+ } else {
+ sprintf(rt,"0x%x",vk);
+ }
}break;
+ /*
case W_HCW_LIRC:{
ULONG ri=(ULONG)hcw;
rt=new char[10];
}
+int RemoteLinux::cecLogMessage(void *param, const cec_log_message &message)
+{
+ Log::getInstance()->log("Remote", Log::DEBUG, "CECLOG: %lld %d %s",message.time , message.level, message.message );
+ return 0;
+}
+int RemoteLinux::cecKeyPress(void*param, const cec_keypress &key)
+{
+ //Log::getInstance()->log("Remote", Log::DEBUG, "Incoming cec key %d %d", key.keycode,key.duration);
+ if (key.duration==0) ((RemoteLinux*)Remote::getInstance())->incomingCECkey(key.keycode);
+ return 1;
+}
+int RemoteLinux::cecCommand(void *param, const cec_command &command)
+{
+ //Log::getInstance()->log("Remote", Log::DEBUG, "CECCommand: %d",command.opcode);
+ return 1;
+}
+
+int RemoteLinux::cecConfigurationChanged(void *param, const libcec_configuration &config)
+{
+ //Log::getInstance()->log("Remote", Log::DEBUG, "CECConfig:"/*,config.string()*/);
+ return 1;
+}
+void RemoteLinux::incomingCECkey(int keys)
+{
+ curcec=keys;
+ hascurcec=true;
+}
/*
void RemoteLinux::Signal() {