mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 23:12:44 +02:00
Merge branch 'mpx' of https://github.com/tuxbox-neutrino/library-stb-hal
Conflicts:
libarmbox/video.cpp
libeplayer3-arm/main/exteplayer.c
libeplayer3-arm/playback/playback.c
Origin commit data
------------------
Branch: master
Commit: d9d82406de
Author: vanhofen <vanhofen@gmx.de>
Date: 2018-10-12 (Fri, 12 Oct 2018)
------------------
This commit was generated by Migit
This commit is contained in:
@@ -70,10 +70,6 @@ static const char *devname[] = {
|
|||||||
"/dev/dvb/adapter0/demux0"
|
"/dev/dvb/adapter0/demux0"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_DEMUX 1
|
|
||||||
static int dmx_source[NUM_DEMUX] = { 0 };
|
|
||||||
// static bool init[NUM_DEMUXDEV] = { false };
|
|
||||||
|
|
||||||
/* uuuugly */
|
/* uuuugly */
|
||||||
static int dmx_tp_count = 0;
|
static int dmx_tp_count = 0;
|
||||||
#define MAX_TS_COUNT 8
|
#define MAX_TS_COUNT 8
|
||||||
|
@@ -20,7 +20,8 @@ libarmbox_la_SOURCES = \
|
|||||||
video.cpp \
|
video.cpp \
|
||||||
audio.cpp \
|
audio.cpp \
|
||||||
init.cpp \
|
init.cpp \
|
||||||
record.cpp
|
record.cpp \
|
||||||
|
hdmi_cec.cpp
|
||||||
|
|
||||||
if ENABLE_GSTREAMER_10
|
if ENABLE_GSTREAMER_10
|
||||||
libarmbox_la_SOURCES += \
|
libarmbox_la_SOURCES += \
|
||||||
|
607
libarmbox/hdmi_cec.cpp
Normal file
607
libarmbox/hdmi_cec.cpp
Normal file
@@ -0,0 +1,607 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018 TangoCash
|
||||||
|
|
||||||
|
License: GPLv2
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation;
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <utime.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#include "linux-uapi-cec.h"
|
||||||
|
#include "hdmi_cec.h"
|
||||||
|
#include "hdmi_cec_types.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
|
||||||
|
#define RED "\x1B[31m"
|
||||||
|
#define NORMAL "\x1B[0m"
|
||||||
|
|
||||||
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, this, args)
|
||||||
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, this, args)
|
||||||
|
#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
|
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
|
|
||||||
|
#define fop(cmd, args...) ({ \
|
||||||
|
int _r; \
|
||||||
|
if (fd >= 0) { \
|
||||||
|
if ((_r = ::cmd(fd, args)) < 0) \
|
||||||
|
lt_info(#cmd"(fd, "#args")\n"); \
|
||||||
|
else \
|
||||||
|
lt_debug(#cmd"(fd, "#args")\n");\
|
||||||
|
} \
|
||||||
|
else { _r = fd; } \
|
||||||
|
_r; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define CEC_DEVICE "/dev/cec0"
|
||||||
|
#define RC_DEVICE "/dev/input/event1"
|
||||||
|
|
||||||
|
hdmi_cec * hdmi_cec::hdmi_cec_instance = NULL;
|
||||||
|
|
||||||
|
//hack to get an instance before first call
|
||||||
|
hdmi_cec * CEC = hdmi_cec::getInstance();
|
||||||
|
|
||||||
|
hdmi_cec::hdmi_cec()
|
||||||
|
{
|
||||||
|
standby_cec_activ = autoview_cec_activ = standby = false;
|
||||||
|
hdmiFd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi_cec::~hdmi_cec()
|
||||||
|
{
|
||||||
|
if (hdmiFd >= 0)
|
||||||
|
{
|
||||||
|
close(hdmiFd);
|
||||||
|
hdmiFd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi_cec* hdmi_cec::getInstance()
|
||||||
|
{
|
||||||
|
if (hdmi_cec_instance == NULL)
|
||||||
|
{
|
||||||
|
hdmi_cec_instance = new hdmi_cec();
|
||||||
|
lt_debug_c("[CEC] new instance created \n");
|
||||||
|
}
|
||||||
|
return hdmi_cec_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
|
||||||
|
{
|
||||||
|
physicalAddress[0] = 0x10;
|
||||||
|
physicalAddress[1] = 0x00;
|
||||||
|
logicalAddress = 1;
|
||||||
|
|
||||||
|
if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
lt_debug("[CEC] switch off %s\n", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
deviceType = _deviceType;
|
||||||
|
|
||||||
|
lt_debug("[CEC] switch on %s\n", __func__);
|
||||||
|
|
||||||
|
if (hdmiFd == -1)
|
||||||
|
{
|
||||||
|
hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdmiFd >= 0)
|
||||||
|
{
|
||||||
|
__u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
|
||||||
|
struct cec_caps caps = {};
|
||||||
|
|
||||||
|
if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0)
|
||||||
|
lt_debug("[CEC] %s: get caps failed (%m)\n", __func__);
|
||||||
|
|
||||||
|
if (caps.capabilities & CEC_CAP_LOG_ADDRS)
|
||||||
|
{
|
||||||
|
struct cec_log_addrs laddrs = {};
|
||||||
|
|
||||||
|
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
|
||||||
|
lt_debug("[CEC] %s: reset log addr failed (%m)\n", __func__);
|
||||||
|
|
||||||
|
memset(&laddrs, 0, sizeof(laddrs));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: cec_version, osd_name and deviceType should be made configurable,
|
||||||
|
* CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
|
||||||
|
* (saves us some startup speed as well, polling for a free logical address
|
||||||
|
* takes some time)
|
||||||
|
*/
|
||||||
|
laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
|
||||||
|
strcpy(laddrs.osd_name, "neutrino");
|
||||||
|
laddrs.vendor_id = CEC_VENDOR_ID_NONE;
|
||||||
|
|
||||||
|
switch (deviceType)
|
||||||
|
{
|
||||||
|
case CEC_LOG_ADDR_TV:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_RECORD_1:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TUNER_1:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_PLAYBACK_1:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_AUDIOSYSTEM:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
|
||||||
|
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
|
||||||
|
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
laddrs.num_log_addrs++;
|
||||||
|
|
||||||
|
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
|
||||||
|
lt_debug("[CEC] %s: et log addr failed (%m)\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0)
|
||||||
|
lt_debug("[CEC] %s: monitor failed (%m)\n", __func__);
|
||||||
|
|
||||||
|
GetCECAddressInfo();
|
||||||
|
|
||||||
|
if(autoview_cec_activ)
|
||||||
|
SetCECState(false);
|
||||||
|
|
||||||
|
Start();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::GetCECAddressInfo()
|
||||||
|
{
|
||||||
|
if (hdmiFd >= 0)
|
||||||
|
{
|
||||||
|
struct addressinfo addressinfo;
|
||||||
|
|
||||||
|
__u16 phys_addr;
|
||||||
|
struct cec_log_addrs laddrs = {};
|
||||||
|
|
||||||
|
::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
|
||||||
|
addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
|
||||||
|
addressinfo.physical[1] = phys_addr & 0xff;
|
||||||
|
|
||||||
|
::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
|
||||||
|
addressinfo.logical = laddrs.log_addr[0];
|
||||||
|
|
||||||
|
switch (laddrs.log_addr_type[0])
|
||||||
|
{
|
||||||
|
case CEC_LOG_ADDR_TYPE_TV:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_TV;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TYPE_RECORD:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_RECORD_1;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TYPE_TUNER:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_TUNER_1;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TYPE_PLAYBACK:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
|
||||||
|
break;
|
||||||
|
case CEC_LOG_ADDR_TYPE_UNREGISTERED:
|
||||||
|
default:
|
||||||
|
addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceType = addressinfo.type;
|
||||||
|
logicalAddress = addressinfo.logical;
|
||||||
|
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
|
||||||
|
{
|
||||||
|
lt_info("[CEC] %s: detected physical address change: %02X%02X --> %02X%02X\n", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
|
||||||
|
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
|
||||||
|
ReportPhysicalAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::ReportPhysicalAddress()
|
||||||
|
{
|
||||||
|
struct cec_message txmessage;
|
||||||
|
txmessage.initiator = logicalAddress;
|
||||||
|
txmessage.destination = CEC_LOG_ADDR_BROADCAST;
|
||||||
|
txmessage.data[0] = CEC_MSG_REPORT_PHYSICAL_ADDR;
|
||||||
|
txmessage.data[1] = physicalAddress[0];
|
||||||
|
txmessage.data[2] = physicalAddress[1];
|
||||||
|
txmessage.data[3] = deviceType;
|
||||||
|
txmessage.length = 4;
|
||||||
|
SendCECMessage(txmessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::SendCECMessage(struct cec_message &txmessage)
|
||||||
|
{
|
||||||
|
if (hdmiFd >= 0)
|
||||||
|
{
|
||||||
|
char str[txmessage.length*6];
|
||||||
|
for (int i = 0; i < txmessage.length; i++)
|
||||||
|
{
|
||||||
|
sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]);
|
||||||
|
}
|
||||||
|
lt_info("[CEC] send message 0x%02X >> 0x%02X '%s' (%s)\n", txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
|
||||||
|
struct cec_msg msg;
|
||||||
|
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
|
||||||
|
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
|
||||||
|
msg.len = txmessage.length + 1;
|
||||||
|
ioctl(hdmiFd, CEC_TRANSMIT, &msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::SetCECAutoStandby(bool state)
|
||||||
|
{
|
||||||
|
standby_cec_activ = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::SetCECAutoView(bool state)
|
||||||
|
{
|
||||||
|
autoview_cec_activ = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::SetCECState(bool state)
|
||||||
|
{
|
||||||
|
struct cec_message message;
|
||||||
|
|
||||||
|
standby = state;
|
||||||
|
|
||||||
|
if ((standby_cec_activ) && state)
|
||||||
|
{
|
||||||
|
message.initiator = logicalAddress;
|
||||||
|
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
|
||||||
|
message.data[0] = CEC_MSG_STANDBY;
|
||||||
|
message.length = 1;
|
||||||
|
SendCECMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((autoview_cec_activ) && !state)
|
||||||
|
{
|
||||||
|
message.initiator = logicalAddress;
|
||||||
|
message.destination = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
|
||||||
|
message.data[0] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
|
||||||
|
message.length = 1;
|
||||||
|
SendCECMessage(message);
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
message.initiator = logicalAddress;
|
||||||
|
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
|
||||||
|
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
|
||||||
|
message.length = 1;
|
||||||
|
SendCECMessage(message);
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
message.initiator = logicalAddress;
|
||||||
|
message.destination = CEC_LOG_ADDR_BROADCAST;
|
||||||
|
message.data[0] = CEC_MSG_ACTIVE_SOURCE;
|
||||||
|
message.data[1] = physicalAddress[0];
|
||||||
|
message.data[2] = physicalAddress[1];
|
||||||
|
message.length = 3;
|
||||||
|
SendCECMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
long hdmi_cec::translateKey(unsigned char code)
|
||||||
|
{
|
||||||
|
long key = 0;
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL:
|
||||||
|
key = KEY_MENU;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER0:
|
||||||
|
key = KEY_0;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER1:
|
||||||
|
key = KEY_1;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER2:
|
||||||
|
key = KEY_2;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER3:
|
||||||
|
key = KEY_3;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER4:
|
||||||
|
key = KEY_4;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER5:
|
||||||
|
key = KEY_5;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER6:
|
||||||
|
key = KEY_6;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER7:
|
||||||
|
key = KEY_7;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER8:
|
||||||
|
key = KEY_8;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER9:
|
||||||
|
key = KEY_9;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_CHANNEL_UP:
|
||||||
|
key = KEY_CHANNELUP;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_CHANNEL_DOWN:
|
||||||
|
key = KEY_CHANNELDOWN;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_PLAY:
|
||||||
|
key = KEY_PLAY;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_STOP:
|
||||||
|
key = KEY_STOP;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE:
|
||||||
|
key = KEY_PAUSE;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_RECORD:
|
||||||
|
key = KEY_RECORD;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_REWIND:
|
||||||
|
key = KEY_REWIND;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_FAST_FORWARD:
|
||||||
|
key = KEY_FASTFORWARD;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE:
|
||||||
|
key = KEY_INFO;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING:
|
||||||
|
key = KEY_PROGRAM;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_PLAY_FUNCTION:
|
||||||
|
key = KEY_PLAY;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION:
|
||||||
|
key = KEY_PLAYPAUSE;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_RECORD_FUNCTION:
|
||||||
|
key = KEY_RECORD;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_STOP_FUNCTION:
|
||||||
|
key = KEY_STOP;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT:
|
||||||
|
key = KEY_OK;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_LEFT:
|
||||||
|
key = KEY_LEFT;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_RIGHT:
|
||||||
|
key = KEY_RIGHT;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_UP:
|
||||||
|
key = KEY_UP;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_DOWN:
|
||||||
|
key = KEY_DOWN;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_EXIT:
|
||||||
|
key = KEY_EXIT;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_F2_RED:
|
||||||
|
key = KEY_RED;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_F3_GREEN:
|
||||||
|
key = KEY_GREEN;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_F4_YELLOW:
|
||||||
|
key = KEY_YELLOW;
|
||||||
|
break;
|
||||||
|
case CEC_USER_CONTROL_CODE_F1_BLUE:
|
||||||
|
key = KEY_BLUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
key = KEY_MENU;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hdmi_cec::Start()
|
||||||
|
{
|
||||||
|
if (running)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hdmiFd == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
return (OpenThreads::Thread::start() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hdmi_cec::Stop()
|
||||||
|
{
|
||||||
|
if (!running)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
|
||||||
|
OpenThreads::Thread::cancel();
|
||||||
|
|
||||||
|
if (hdmiFd >= 0)
|
||||||
|
{
|
||||||
|
close(hdmiFd);
|
||||||
|
hdmiFd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (OpenThreads::Thread::join() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::run()
|
||||||
|
{
|
||||||
|
OpenThreads::Thread::setCancelModeAsynchronous();
|
||||||
|
struct pollfd pfd;
|
||||||
|
|
||||||
|
pfd.fd = hdmiFd;
|
||||||
|
pfd.events = (POLLIN | POLLPRI);
|
||||||
|
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
if (poll(&pfd, 1, 0) > 0)
|
||||||
|
Receive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::Receive()
|
||||||
|
{
|
||||||
|
bool hasdata = false;
|
||||||
|
struct cec_message rxmessage;
|
||||||
|
struct cec_message txmessage;
|
||||||
|
|
||||||
|
struct cec_msg msg;
|
||||||
|
if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0)
|
||||||
|
{
|
||||||
|
rxmessage.length = msg.len - 1;
|
||||||
|
rxmessage.initiator = cec_msg_initiator(&msg);
|
||||||
|
rxmessage.destination = cec_msg_destination(&msg);
|
||||||
|
rxmessage.opcode = cec_msg_opcode(&msg);
|
||||||
|
memcpy(&rxmessage.data, &msg.msg[1], rxmessage.length);
|
||||||
|
hasdata = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasdata)
|
||||||
|
{
|
||||||
|
bool keypressed = false;
|
||||||
|
static unsigned char pressedkey = 0;
|
||||||
|
|
||||||
|
char str[rxmessage.length*6];
|
||||||
|
for (int i = 0; i < rxmessage.length; i++)
|
||||||
|
{
|
||||||
|
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
|
||||||
|
}
|
||||||
|
lt_info("[CEC] received message 0x%02X << 0x%02X '%s' (%s)\n", rxmessage.destination, rxmessage.initiator, ToString((cec_opcode)rxmessage.opcode), str);
|
||||||
|
|
||||||
|
switch (rxmessage.opcode)
|
||||||
|
{
|
||||||
|
case CEC_OPCODE_DEVICE_VENDOR_ID:
|
||||||
|
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
|
||||||
|
{
|
||||||
|
uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) +
|
||||||
|
((uint64_t)rxmessage.data[2] << 8) +
|
||||||
|
(uint64_t)rxmessage.data[3];
|
||||||
|
lt_debug("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
|
||||||
|
{
|
||||||
|
txmessage.destination = rxmessage.initiator;
|
||||||
|
txmessage.initiator = rxmessage.destination;
|
||||||
|
txmessage.data[0] = GetResponseOpcode((cec_opcode)rxmessage.opcode);
|
||||||
|
txmessage.data[1] = standby ? CEC_POWER_STATUS_STANDBY : CEC_POWER_STATUS_ON;
|
||||||
|
txmessage.length = 2;
|
||||||
|
SendCECMessage(txmessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CEC_OPCODE_USER_CONTROL_PRESSED: /* key pressed */
|
||||||
|
keypressed = true;
|
||||||
|
pressedkey = rxmessage.data[1];
|
||||||
|
case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */
|
||||||
|
{
|
||||||
|
long code = translateKey(pressedkey);
|
||||||
|
lt_debug("[CEC] decoded key %s (%ld)\n",ToString((cec_user_control_code)pressedkey), code);
|
||||||
|
handleCode(code,keypressed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::handleCode(long code, bool keypressed)
|
||||||
|
{
|
||||||
|
int evd = open(RC_DEVICE, O_RDWR);
|
||||||
|
if (evd < 0)
|
||||||
|
{
|
||||||
|
lt_debug("[CEC] opening " RC_DEVICE " failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keypressed)
|
||||||
|
{
|
||||||
|
if (rc_send(evd, code, KEY_PRESSED) < 0)
|
||||||
|
{
|
||||||
|
lt_debug("[CEC] writing 'KEY_PRESSED' event failed");
|
||||||
|
close(evd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rc_sync(evd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rc_send(evd, code, KEY_RELEASED) < 0)
|
||||||
|
{
|
||||||
|
lt_debug("[CEC] writing 'KEY_RELEASED' event failed");
|
||||||
|
close(evd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rc_sync(evd);
|
||||||
|
}
|
||||||
|
close(evd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdmi_cec::rc_send(int fd, unsigned int code, unsigned int value)
|
||||||
|
{
|
||||||
|
struct input_event ev;
|
||||||
|
|
||||||
|
ev.type = EV_KEY;
|
||||||
|
ev.code = code;
|
||||||
|
ev.value = value;
|
||||||
|
return write(fd, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::rc_sync(int fd)
|
||||||
|
{
|
||||||
|
struct input_event ev;
|
||||||
|
|
||||||
|
gettimeofday(&ev.time, NULL);
|
||||||
|
ev.type = EV_SYN;
|
||||||
|
ev.code = SYN_REPORT;
|
||||||
|
ev.value = 0;
|
||||||
|
write(fd, &ev, sizeof(ev));
|
||||||
|
}
|
78
libarmbox/hdmi_cec.h
Normal file
78
libarmbox/hdmi_cec.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018 TangoCash
|
||||||
|
|
||||||
|
License: GPLv2
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation;
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
#include "video_lib.h"
|
||||||
|
|
||||||
|
struct cec_message
|
||||||
|
{
|
||||||
|
unsigned char initiator;
|
||||||
|
unsigned char destination;
|
||||||
|
unsigned char opcode;
|
||||||
|
unsigned char data[256];
|
||||||
|
unsigned char length;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct addressinfo
|
||||||
|
{
|
||||||
|
unsigned char logical;
|
||||||
|
unsigned char physical[2];
|
||||||
|
unsigned char type;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
KEY_RELEASED = 0,
|
||||||
|
KEY_PRESSED,
|
||||||
|
KEY_AUTOREPEAT
|
||||||
|
};
|
||||||
|
|
||||||
|
class hdmi_cec : public OpenThreads::Thread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
hdmi_cec();
|
||||||
|
static hdmi_cec *hdmi_cec_instance;
|
||||||
|
void run();
|
||||||
|
bool Start();
|
||||||
|
bool Stop();
|
||||||
|
void Receive();
|
||||||
|
unsigned char physicalAddress[2];
|
||||||
|
bool autoview_cec_activ;
|
||||||
|
unsigned char deviceType, logicalAddress;
|
||||||
|
int hdmiFd;
|
||||||
|
long translateKey(unsigned char code);
|
||||||
|
void handleCode(long code, bool keypressed);
|
||||||
|
int rc_send(int fd, unsigned int code, unsigned int value);
|
||||||
|
void rc_sync(int fd);
|
||||||
|
bool standby;
|
||||||
|
protected:
|
||||||
|
bool running;
|
||||||
|
public:
|
||||||
|
~hdmi_cec();
|
||||||
|
static hdmi_cec* getInstance();
|
||||||
|
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
|
||||||
|
void SetCECAutoView(bool);
|
||||||
|
void SetCECAutoStandby(bool);
|
||||||
|
void GetCECAddressInfo();
|
||||||
|
void SendCECMessage(struct cec_message &message);
|
||||||
|
void SetCECState(bool state);
|
||||||
|
void ReportPhysicalAddress();
|
||||||
|
bool standby_cec_activ;
|
||||||
|
};
|
668
libarmbox/hdmi_cec_types.h
Normal file
668
libarmbox/hdmi_cec_types.h
Normal file
@@ -0,0 +1,668 @@
|
|||||||
|
typedef enum cec_vendor_id
|
||||||
|
{
|
||||||
|
CEC_VENDOR_TOSHIBA = 0x000039,
|
||||||
|
CEC_VENDOR_SAMSUNG = 0x0000F0,
|
||||||
|
CEC_VENDOR_DENON = 0x0005CD,
|
||||||
|
CEC_VENDOR_MARANTZ = 0x000678,
|
||||||
|
CEC_VENDOR_LOEWE = 0x000982,
|
||||||
|
CEC_VENDOR_ONKYO = 0x0009B0,
|
||||||
|
CEC_VENDOR_MEDION = 0x000CB8,
|
||||||
|
CEC_VENDOR_TOSHIBA2 = 0x000CE7,
|
||||||
|
CEC_VENDOR_PULSE_EIGHT = 0x001582,
|
||||||
|
CEC_VENDOR_HARMAN_KARDON2 = 0x001950,
|
||||||
|
CEC_VENDOR_GOOGLE = 0x001A11,
|
||||||
|
CEC_VENDOR_AKAI = 0x0020C7,
|
||||||
|
CEC_VENDOR_AOC = 0x002467,
|
||||||
|
CEC_VENDOR_PANASONIC = 0x008045,
|
||||||
|
CEC_VENDOR_PHILIPS = 0x00903E,
|
||||||
|
CEC_VENDOR_DAEWOO = 0x009053,
|
||||||
|
CEC_VENDOR_YAMAHA = 0x00A0DE,
|
||||||
|
CEC_VENDOR_GRUNDIG = 0x00D0D5,
|
||||||
|
CEC_VENDOR_PIONEER = 0x00E036,
|
||||||
|
CEC_VENDOR_LG = 0x00E091,
|
||||||
|
CEC_VENDOR_SHARP = 0x08001F,
|
||||||
|
CEC_VENDOR_SONY = 0x080046,
|
||||||
|
CEC_VENDOR_BROADCOM = 0x18C086,
|
||||||
|
CEC_VENDOR_SHARP2 = 0x534850,
|
||||||
|
CEC_VENDOR_VIZIO = 0x6B746D,
|
||||||
|
CEC_VENDOR_BENQ = 0x8065E9,
|
||||||
|
CEC_VENDOR_HARMAN_KARDON = 0x9C645E,
|
||||||
|
CEC_VENDOR_UNKNOWN = 0
|
||||||
|
} cec_vendor_id;
|
||||||
|
|
||||||
|
typedef enum cec_user_control_code
|
||||||
|
{
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT = 0x00,
|
||||||
|
CEC_USER_CONTROL_CODE_UP = 0x01,
|
||||||
|
CEC_USER_CONTROL_CODE_DOWN = 0x02,
|
||||||
|
CEC_USER_CONTROL_CODE_LEFT = 0x03,
|
||||||
|
CEC_USER_CONTROL_CODE_RIGHT = 0x04,
|
||||||
|
CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05,
|
||||||
|
CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06,
|
||||||
|
CEC_USER_CONTROL_CODE_LEFT_UP = 0x07,
|
||||||
|
CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08,
|
||||||
|
CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09,
|
||||||
|
CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A,
|
||||||
|
CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B,
|
||||||
|
CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C,
|
||||||
|
CEC_USER_CONTROL_CODE_EXIT = 0x0D,
|
||||||
|
// reserved: 0x0E, 0x0F
|
||||||
|
CEC_USER_CONTROL_CODE_TOP_MENU = 0x10,
|
||||||
|
CEC_USER_CONTROL_CODE_DVD_MENU = 0x11,
|
||||||
|
// reserved: 0x12 ... 0x1C
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE = 0x1D,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER11 = 0x1E,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER12 = 0x1F,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER0 = 0x20,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER1 = 0x21,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER2 = 0x22,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER3 = 0x23,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER4 = 0x24,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER5 = 0x25,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER6 = 0x26,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER7 = 0x27,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER8 = 0x28,
|
||||||
|
CEC_USER_CONTROL_CODE_NUMBER9 = 0x29,
|
||||||
|
CEC_USER_CONTROL_CODE_DOT = 0x2A,
|
||||||
|
CEC_USER_CONTROL_CODE_ENTER = 0x2B,
|
||||||
|
CEC_USER_CONTROL_CODE_CLEAR = 0x2C,
|
||||||
|
CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F,
|
||||||
|
CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30,
|
||||||
|
CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31,
|
||||||
|
CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32,
|
||||||
|
CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33,
|
||||||
|
CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34,
|
||||||
|
CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35,
|
||||||
|
CEC_USER_CONTROL_CODE_HELP = 0x36,
|
||||||
|
CEC_USER_CONTROL_CODE_PAGE_UP = 0x37,
|
||||||
|
CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38,
|
||||||
|
// reserved: 0x39 ... 0x3F
|
||||||
|
CEC_USER_CONTROL_CODE_POWER = 0x40,
|
||||||
|
CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41,
|
||||||
|
CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42,
|
||||||
|
CEC_USER_CONTROL_CODE_MUTE = 0x43,
|
||||||
|
CEC_USER_CONTROL_CODE_PLAY = 0x44,
|
||||||
|
CEC_USER_CONTROL_CODE_STOP = 0x45,
|
||||||
|
CEC_USER_CONTROL_CODE_PAUSE = 0x46,
|
||||||
|
CEC_USER_CONTROL_CODE_RECORD = 0x47,
|
||||||
|
CEC_USER_CONTROL_CODE_REWIND = 0x48,
|
||||||
|
CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49,
|
||||||
|
CEC_USER_CONTROL_CODE_EJECT = 0x4A,
|
||||||
|
CEC_USER_CONTROL_CODE_FORWARD = 0x4B,
|
||||||
|
CEC_USER_CONTROL_CODE_BACKWARD = 0x4C,
|
||||||
|
CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D,
|
||||||
|
CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E,
|
||||||
|
// reserved: 0x4F
|
||||||
|
CEC_USER_CONTROL_CODE_ANGLE = 0x50,
|
||||||
|
CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51,
|
||||||
|
CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52,
|
||||||
|
CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53,
|
||||||
|
CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54,
|
||||||
|
CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55,
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE = 0x56,
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION = 0x57,
|
||||||
|
// reserved: 0x58 ... 0x5F
|
||||||
|
CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60,
|
||||||
|
CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61,
|
||||||
|
CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62,
|
||||||
|
CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63,
|
||||||
|
CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64,
|
||||||
|
CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65,
|
||||||
|
CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66,
|
||||||
|
CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67,
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68,
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69,
|
||||||
|
CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A,
|
||||||
|
CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B,
|
||||||
|
CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C,
|
||||||
|
CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D,
|
||||||
|
// reserved: 0x6E ... 0x70
|
||||||
|
CEC_USER_CONTROL_CODE_F1_BLUE = 0x71,
|
||||||
|
CEC_USER_CONTROL_CODE_F2_RED = 0X72,
|
||||||
|
CEC_USER_CONTROL_CODE_F3_GREEN = 0x73,
|
||||||
|
CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74,
|
||||||
|
CEC_USER_CONTROL_CODE_F5 = 0x75,
|
||||||
|
CEC_USER_CONTROL_CODE_DATA = 0x76,
|
||||||
|
// reserved: 0x77 ... 0xFF
|
||||||
|
CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, // return (Samsung)
|
||||||
|
CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, // channels list (Samsung)
|
||||||
|
CEC_USER_CONTROL_CODE_MAX = 0x96,
|
||||||
|
CEC_USER_CONTROL_CODE_UNKNOWN = 0xFF
|
||||||
|
} cec_user_control_code;
|
||||||
|
|
||||||
|
typedef enum cec_opcode
|
||||||
|
{
|
||||||
|
CEC_OPCODE_ACTIVE_SOURCE = 0x82,
|
||||||
|
CEC_OPCODE_IMAGE_VIEW_ON = 0x04,
|
||||||
|
CEC_OPCODE_TEXT_VIEW_ON = 0x0D,
|
||||||
|
CEC_OPCODE_INACTIVE_SOURCE = 0x9D,
|
||||||
|
CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85,
|
||||||
|
CEC_OPCODE_ROUTING_CHANGE = 0x80,
|
||||||
|
CEC_OPCODE_ROUTING_INFORMATION = 0x81,
|
||||||
|
CEC_OPCODE_SET_STREAM_PATH = 0x86,
|
||||||
|
CEC_OPCODE_STANDBY = 0x36,
|
||||||
|
CEC_OPCODE_RECORD_OFF = 0x0B,
|
||||||
|
CEC_OPCODE_RECORD_ON = 0x09,
|
||||||
|
CEC_OPCODE_RECORD_STATUS = 0x0A,
|
||||||
|
CEC_OPCODE_RECORD_TV_SCREEN = 0x0F,
|
||||||
|
CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33,
|
||||||
|
CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99,
|
||||||
|
CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1,
|
||||||
|
CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34,
|
||||||
|
CEC_OPCODE_SET_DIGITAL_TIMER = 0x97,
|
||||||
|
CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2,
|
||||||
|
CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67,
|
||||||
|
CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43,
|
||||||
|
CEC_OPCODE_TIMER_STATUS = 0x35,
|
||||||
|
CEC_OPCODE_CEC_VERSION = 0x9E,
|
||||||
|
CEC_OPCODE_GET_CEC_VERSION = 0x9F,
|
||||||
|
CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83,
|
||||||
|
CEC_OPCODE_GET_MENU_LANGUAGE = 0x91,
|
||||||
|
CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84,
|
||||||
|
CEC_OPCODE_SET_MENU_LANGUAGE = 0x32,
|
||||||
|
CEC_OPCODE_DECK_CONTROL = 0x42,
|
||||||
|
CEC_OPCODE_DECK_STATUS = 0x1B,
|
||||||
|
CEC_OPCODE_GIVE_DECK_STATUS = 0x1A,
|
||||||
|
CEC_OPCODE_PLAY = 0x41,
|
||||||
|
CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08,
|
||||||
|
CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92,
|
||||||
|
CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93,
|
||||||
|
CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07,
|
||||||
|
CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06,
|
||||||
|
CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05,
|
||||||
|
CEC_OPCODE_DEVICE_VENDOR_ID = 0x87,
|
||||||
|
CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C,
|
||||||
|
CEC_OPCODE_VENDOR_COMMAND = 0x89,
|
||||||
|
CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0,
|
||||||
|
CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
|
||||||
|
CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B,
|
||||||
|
CEC_OPCODE_SET_OSD_STRING = 0x64,
|
||||||
|
CEC_OPCODE_GIVE_OSD_NAME = 0x46,
|
||||||
|
CEC_OPCODE_SET_OSD_NAME = 0x47,
|
||||||
|
CEC_OPCODE_MENU_REQUEST = 0x8D,
|
||||||
|
CEC_OPCODE_MENU_STATUS = 0x8E,
|
||||||
|
CEC_OPCODE_USER_CONTROL_PRESSED = 0x44,
|
||||||
|
CEC_OPCODE_USER_CONTROL_RELEASE = 0x45,
|
||||||
|
CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F,
|
||||||
|
CEC_OPCODE_REPORT_POWER_STATUS = 0x90,
|
||||||
|
CEC_OPCODE_FEATURE_ABORT = 0x00,
|
||||||
|
CEC_OPCODE_ABORT = 0xFF,
|
||||||
|
CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71,
|
||||||
|
CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
|
||||||
|
CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A,
|
||||||
|
CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
|
||||||
|
CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
|
||||||
|
CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
|
||||||
|
CEC_OPCODE_SET_AUDIO_RATE = 0x9A,
|
||||||
|
|
||||||
|
/* CEC 1.4 */
|
||||||
|
CEC_OPCODE_START_ARC = 0xC0,
|
||||||
|
CEC_OPCODE_REPORT_ARC_STARTED = 0xC1,
|
||||||
|
CEC_OPCODE_REPORT_ARC_ENDED = 0xC2,
|
||||||
|
CEC_OPCODE_REQUEST_ARC_START = 0xC3,
|
||||||
|
CEC_OPCODE_REQUEST_ARC_END = 0xC4,
|
||||||
|
CEC_OPCODE_END_ARC = 0xC5,
|
||||||
|
CEC_OPCODE_CDC = 0xF8,
|
||||||
|
/* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
|
||||||
|
CEC_OPCODE_NONE = 0xFD
|
||||||
|
} cec_opcode;
|
||||||
|
|
||||||
|
typedef enum cec_logical_address
|
||||||
|
{
|
||||||
|
CECDEVICE_UNKNOWN = -1, //not a valid logical address
|
||||||
|
CECDEVICE_TV = 0,
|
||||||
|
CECDEVICE_RECORDINGDEVICE1 = 1,
|
||||||
|
CECDEVICE_RECORDINGDEVICE2 = 2,
|
||||||
|
CECDEVICE_TUNER1 = 3,
|
||||||
|
CECDEVICE_PLAYBACKDEVICE1 = 4,
|
||||||
|
CECDEVICE_AUDIOSYSTEM = 5,
|
||||||
|
CECDEVICE_TUNER2 = 6,
|
||||||
|
CECDEVICE_TUNER3 = 7,
|
||||||
|
CECDEVICE_PLAYBACKDEVICE2 = 8,
|
||||||
|
CECDEVICE_RECORDINGDEVICE3 = 9,
|
||||||
|
CECDEVICE_TUNER4 = 10,
|
||||||
|
CECDEVICE_PLAYBACKDEVICE3 = 11,
|
||||||
|
CECDEVICE_RESERVED1 = 12,
|
||||||
|
CECDEVICE_RESERVED2 = 13,
|
||||||
|
CECDEVICE_FREEUSE = 14,
|
||||||
|
CECDEVICE_UNREGISTERED = 15,
|
||||||
|
CECDEVICE_BROADCAST = 15
|
||||||
|
} cec_logical_address;
|
||||||
|
|
||||||
|
typedef enum cec_power_status
|
||||||
|
{
|
||||||
|
CEC_POWER_STATUS_ON = 0x00,
|
||||||
|
CEC_POWER_STATUS_STANDBY = 0x01,
|
||||||
|
CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON = 0x02,
|
||||||
|
CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY = 0x03,
|
||||||
|
CEC_POWER_STATUS_UNKNOWN = 0x99
|
||||||
|
} cec_power_status;
|
||||||
|
|
||||||
|
static const char *ToString(const cec_opcode opcode)
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case CEC_OPCODE_ACTIVE_SOURCE:
|
||||||
|
return "active source";
|
||||||
|
case CEC_OPCODE_IMAGE_VIEW_ON:
|
||||||
|
return "image view on";
|
||||||
|
case CEC_OPCODE_TEXT_VIEW_ON:
|
||||||
|
return "text view on";
|
||||||
|
case CEC_OPCODE_INACTIVE_SOURCE:
|
||||||
|
return "inactive source";
|
||||||
|
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
|
||||||
|
return "request active source";
|
||||||
|
case CEC_OPCODE_ROUTING_CHANGE:
|
||||||
|
return "routing change";
|
||||||
|
case CEC_OPCODE_ROUTING_INFORMATION:
|
||||||
|
return "routing information";
|
||||||
|
case CEC_OPCODE_SET_STREAM_PATH:
|
||||||
|
return "set stream path";
|
||||||
|
case CEC_OPCODE_STANDBY:
|
||||||
|
return "standby";
|
||||||
|
case CEC_OPCODE_RECORD_OFF:
|
||||||
|
return "record off";
|
||||||
|
case CEC_OPCODE_RECORD_ON:
|
||||||
|
return "record on";
|
||||||
|
case CEC_OPCODE_RECORD_STATUS:
|
||||||
|
return "record status";
|
||||||
|
case CEC_OPCODE_RECORD_TV_SCREEN:
|
||||||
|
return "record tv screen";
|
||||||
|
case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
|
||||||
|
return "clear analogue timer";
|
||||||
|
case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
|
||||||
|
return "clear digital timer";
|
||||||
|
case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
|
||||||
|
return "clear external timer";
|
||||||
|
case CEC_OPCODE_SET_ANALOGUE_TIMER:
|
||||||
|
return "set analogue timer";
|
||||||
|
case CEC_OPCODE_SET_DIGITAL_TIMER:
|
||||||
|
return "set digital timer";
|
||||||
|
case CEC_OPCODE_SET_EXTERNAL_TIMER:
|
||||||
|
return "set external timer";
|
||||||
|
case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
|
||||||
|
return "set timer program title";
|
||||||
|
case CEC_OPCODE_TIMER_CLEARED_STATUS:
|
||||||
|
return "timer cleared status";
|
||||||
|
case CEC_OPCODE_TIMER_STATUS:
|
||||||
|
return "timer status";
|
||||||
|
case CEC_OPCODE_CEC_VERSION:
|
||||||
|
return "cec version";
|
||||||
|
case CEC_OPCODE_GET_CEC_VERSION:
|
||||||
|
return "get cec version";
|
||||||
|
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
|
||||||
|
return "give physical address";
|
||||||
|
case CEC_OPCODE_GET_MENU_LANGUAGE:
|
||||||
|
return "get menu language";
|
||||||
|
case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
|
||||||
|
return "report physical address";
|
||||||
|
case CEC_OPCODE_SET_MENU_LANGUAGE:
|
||||||
|
return "set menu language";
|
||||||
|
case CEC_OPCODE_DECK_CONTROL:
|
||||||
|
return "deck control";
|
||||||
|
case CEC_OPCODE_DECK_STATUS:
|
||||||
|
return "deck status";
|
||||||
|
case CEC_OPCODE_GIVE_DECK_STATUS:
|
||||||
|
return "give deck status";
|
||||||
|
case CEC_OPCODE_PLAY:
|
||||||
|
return "play";
|
||||||
|
case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
|
||||||
|
return "give tuner status";
|
||||||
|
case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
|
||||||
|
return "select analogue service";
|
||||||
|
case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
|
||||||
|
return "set digital service";
|
||||||
|
case CEC_OPCODE_TUNER_DEVICE_STATUS:
|
||||||
|
return "tuner device status";
|
||||||
|
case CEC_OPCODE_TUNER_STEP_DECREMENT:
|
||||||
|
return "tuner step decrement";
|
||||||
|
case CEC_OPCODE_TUNER_STEP_INCREMENT:
|
||||||
|
return "tuner step increment";
|
||||||
|
case CEC_OPCODE_DEVICE_VENDOR_ID:
|
||||||
|
return "device vendor id";
|
||||||
|
case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
|
||||||
|
return "give device vendor id";
|
||||||
|
case CEC_OPCODE_VENDOR_COMMAND:
|
||||||
|
return "vendor command";
|
||||||
|
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
|
||||||
|
return "vendor command with id";
|
||||||
|
case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
|
||||||
|
return "vendor remote button down";
|
||||||
|
case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
|
||||||
|
return "vendor remote button up";
|
||||||
|
case CEC_OPCODE_SET_OSD_STRING:
|
||||||
|
return "set osd string";
|
||||||
|
case CEC_OPCODE_GIVE_OSD_NAME:
|
||||||
|
return "give osd name";
|
||||||
|
case CEC_OPCODE_SET_OSD_NAME:
|
||||||
|
return "set osd name";
|
||||||
|
case CEC_OPCODE_MENU_REQUEST:
|
||||||
|
return "menu request";
|
||||||
|
case CEC_OPCODE_MENU_STATUS:
|
||||||
|
return "menu status";
|
||||||
|
case CEC_OPCODE_USER_CONTROL_PRESSED:
|
||||||
|
return "user control pressed";
|
||||||
|
case CEC_OPCODE_USER_CONTROL_RELEASE:
|
||||||
|
return "user control release";
|
||||||
|
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
|
||||||
|
return "give device power status";
|
||||||
|
case CEC_OPCODE_REPORT_POWER_STATUS:
|
||||||
|
return "report power status";
|
||||||
|
case CEC_OPCODE_FEATURE_ABORT:
|
||||||
|
return "feature abort";
|
||||||
|
case CEC_OPCODE_ABORT:
|
||||||
|
return "abort";
|
||||||
|
case CEC_OPCODE_GIVE_AUDIO_STATUS:
|
||||||
|
return "give audio status";
|
||||||
|
case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
|
||||||
|
return "give audio mode status";
|
||||||
|
case CEC_OPCODE_REPORT_AUDIO_STATUS:
|
||||||
|
return "report audio status";
|
||||||
|
case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
|
||||||
|
return "set system audio mode";
|
||||||
|
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
|
||||||
|
return "system audio mode request";
|
||||||
|
case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
|
||||||
|
return "system audio mode status";
|
||||||
|
case CEC_OPCODE_SET_AUDIO_RATE:
|
||||||
|
return "set audio rate";
|
||||||
|
case CEC_OPCODE_START_ARC:
|
||||||
|
return "start ARC";
|
||||||
|
case CEC_OPCODE_REPORT_ARC_STARTED:
|
||||||
|
return "report ARC started";
|
||||||
|
case CEC_OPCODE_REPORT_ARC_ENDED:
|
||||||
|
return "report ARC ended";
|
||||||
|
case CEC_OPCODE_REQUEST_ARC_START:
|
||||||
|
return "request ARC start";
|
||||||
|
case CEC_OPCODE_REQUEST_ARC_END:
|
||||||
|
return "request ARC end";
|
||||||
|
case CEC_OPCODE_END_ARC:
|
||||||
|
return "end ARC";
|
||||||
|
case CEC_OPCODE_CDC:
|
||||||
|
return "CDC";
|
||||||
|
case CEC_OPCODE_NONE:
|
||||||
|
return "poll";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *ToString(const cec_vendor_id vendor)
|
||||||
|
{
|
||||||
|
switch (vendor)
|
||||||
|
{
|
||||||
|
case CEC_VENDOR_SAMSUNG:
|
||||||
|
return "Samsung";
|
||||||
|
case CEC_VENDOR_LG:
|
||||||
|
return "LG";
|
||||||
|
case CEC_VENDOR_PANASONIC:
|
||||||
|
return "Panasonic";
|
||||||
|
case CEC_VENDOR_PIONEER:
|
||||||
|
return "Pioneer";
|
||||||
|
case CEC_VENDOR_ONKYO:
|
||||||
|
return "Onkyo";
|
||||||
|
case CEC_VENDOR_YAMAHA:
|
||||||
|
return "Yamaha";
|
||||||
|
case CEC_VENDOR_PHILIPS:
|
||||||
|
return "Philips";
|
||||||
|
case CEC_VENDOR_SONY:
|
||||||
|
return "Sony";
|
||||||
|
case CEC_VENDOR_TOSHIBA:
|
||||||
|
case CEC_VENDOR_TOSHIBA2:
|
||||||
|
return "Toshiba";
|
||||||
|
case CEC_VENDOR_AKAI:
|
||||||
|
return "Akai";
|
||||||
|
case CEC_VENDOR_AOC:
|
||||||
|
return "AOC";
|
||||||
|
case CEC_VENDOR_BENQ:
|
||||||
|
return "Benq";
|
||||||
|
case CEC_VENDOR_DAEWOO:
|
||||||
|
return "Daewoo";
|
||||||
|
case CEC_VENDOR_GRUNDIG:
|
||||||
|
return "Grundig";
|
||||||
|
case CEC_VENDOR_MEDION:
|
||||||
|
return "Medion";
|
||||||
|
case CEC_VENDOR_SHARP:
|
||||||
|
case CEC_VENDOR_SHARP2:
|
||||||
|
return "Sharp";
|
||||||
|
case CEC_VENDOR_VIZIO:
|
||||||
|
return "Vizio";
|
||||||
|
case CEC_VENDOR_BROADCOM:
|
||||||
|
return "Broadcom";
|
||||||
|
case CEC_VENDOR_LOEWE:
|
||||||
|
return "Loewe";
|
||||||
|
case CEC_VENDOR_DENON:
|
||||||
|
return "Denon";
|
||||||
|
case CEC_VENDOR_MARANTZ:
|
||||||
|
return "Marantz";
|
||||||
|
case CEC_VENDOR_HARMAN_KARDON:
|
||||||
|
case CEC_VENDOR_HARMAN_KARDON2:
|
||||||
|
return "Harman/Kardon";
|
||||||
|
case CEC_VENDOR_PULSE_EIGHT:
|
||||||
|
return "Pulse Eight";
|
||||||
|
case CEC_VENDOR_GOOGLE:
|
||||||
|
return "Google";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *ToString(const cec_user_control_code key)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT:
|
||||||
|
return "select";
|
||||||
|
case CEC_USER_CONTROL_CODE_UP:
|
||||||
|
return "up";
|
||||||
|
case CEC_USER_CONTROL_CODE_DOWN:
|
||||||
|
return "down";
|
||||||
|
case CEC_USER_CONTROL_CODE_LEFT:
|
||||||
|
return "left";
|
||||||
|
case CEC_USER_CONTROL_CODE_RIGHT:
|
||||||
|
return "right";
|
||||||
|
case CEC_USER_CONTROL_CODE_RIGHT_UP:
|
||||||
|
return "right+up";
|
||||||
|
case CEC_USER_CONTROL_CODE_RIGHT_DOWN:
|
||||||
|
return "right+down";
|
||||||
|
case CEC_USER_CONTROL_CODE_LEFT_UP:
|
||||||
|
return "left+up";
|
||||||
|
case CEC_USER_CONTROL_CODE_LEFT_DOWN:
|
||||||
|
return "left+down";
|
||||||
|
case CEC_USER_CONTROL_CODE_ROOT_MENU:
|
||||||
|
return "root menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_SETUP_MENU:
|
||||||
|
return "setup menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_CONTENTS_MENU:
|
||||||
|
return "contents menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_FAVORITE_MENU:
|
||||||
|
return "favourite menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_EXIT:
|
||||||
|
return "exit";
|
||||||
|
case CEC_USER_CONTROL_CODE_TOP_MENU:
|
||||||
|
return "top menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_DVD_MENU:
|
||||||
|
return "dvd menu";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE:
|
||||||
|
return "number entry mode";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER11:
|
||||||
|
return "11";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER12:
|
||||||
|
return "12";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER0:
|
||||||
|
return "0";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER1:
|
||||||
|
return "1";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER2:
|
||||||
|
return "2";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER3:
|
||||||
|
return "3";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER4:
|
||||||
|
return "4";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER5:
|
||||||
|
return "5";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER6:
|
||||||
|
return "6";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER7:
|
||||||
|
return "7";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER8:
|
||||||
|
return "8";
|
||||||
|
case CEC_USER_CONTROL_CODE_NUMBER9:
|
||||||
|
return "9";
|
||||||
|
case CEC_USER_CONTROL_CODE_DOT:
|
||||||
|
return ".";
|
||||||
|
case CEC_USER_CONTROL_CODE_ENTER:
|
||||||
|
return "enter";
|
||||||
|
case CEC_USER_CONTROL_CODE_CLEAR:
|
||||||
|
return "clear";
|
||||||
|
case CEC_USER_CONTROL_CODE_NEXT_FAVORITE:
|
||||||
|
return "next favourite";
|
||||||
|
case CEC_USER_CONTROL_CODE_CHANNEL_UP:
|
||||||
|
return "channel up";
|
||||||
|
case CEC_USER_CONTROL_CODE_CHANNEL_DOWN:
|
||||||
|
return "channel down";
|
||||||
|
case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL:
|
||||||
|
return "previous channel";
|
||||||
|
case CEC_USER_CONTROL_CODE_SOUND_SELECT:
|
||||||
|
return "sound select";
|
||||||
|
case CEC_USER_CONTROL_CODE_INPUT_SELECT:
|
||||||
|
return "input select";
|
||||||
|
case CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION:
|
||||||
|
return "display information";
|
||||||
|
case CEC_USER_CONTROL_CODE_HELP:
|
||||||
|
return "help";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAGE_UP:
|
||||||
|
return "page up";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAGE_DOWN:
|
||||||
|
return "page down";
|
||||||
|
case CEC_USER_CONTROL_CODE_POWER:
|
||||||
|
return "power";
|
||||||
|
case CEC_USER_CONTROL_CODE_VOLUME_UP:
|
||||||
|
return "volume up";
|
||||||
|
case CEC_USER_CONTROL_CODE_VOLUME_DOWN:
|
||||||
|
return "volume down";
|
||||||
|
case CEC_USER_CONTROL_CODE_MUTE:
|
||||||
|
return "mute";
|
||||||
|
case CEC_USER_CONTROL_CODE_PLAY:
|
||||||
|
return "play";
|
||||||
|
case CEC_USER_CONTROL_CODE_STOP:
|
||||||
|
return "stop";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE:
|
||||||
|
return "pause";
|
||||||
|
case CEC_USER_CONTROL_CODE_RECORD:
|
||||||
|
return "record";
|
||||||
|
case CEC_USER_CONTROL_CODE_REWIND:
|
||||||
|
return "rewind";
|
||||||
|
case CEC_USER_CONTROL_CODE_FAST_FORWARD:
|
||||||
|
return "Fast forward";
|
||||||
|
case CEC_USER_CONTROL_CODE_EJECT:
|
||||||
|
return "eject";
|
||||||
|
case CEC_USER_CONTROL_CODE_FORWARD:
|
||||||
|
return "forward";
|
||||||
|
case CEC_USER_CONTROL_CODE_BACKWARD:
|
||||||
|
return "backward";
|
||||||
|
case CEC_USER_CONTROL_CODE_STOP_RECORD:
|
||||||
|
return "stop record";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE_RECORD:
|
||||||
|
return "pause record";
|
||||||
|
case CEC_USER_CONTROL_CODE_ANGLE:
|
||||||
|
return "angle";
|
||||||
|
case CEC_USER_CONTROL_CODE_SUB_PICTURE:
|
||||||
|
return "sub picture";
|
||||||
|
case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND:
|
||||||
|
return "video on demand";
|
||||||
|
case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE:
|
||||||
|
return "electronic program guide";
|
||||||
|
case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING:
|
||||||
|
return "timer programming";
|
||||||
|
case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION:
|
||||||
|
return "initial configuration";
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE:
|
||||||
|
return "select broadcast type";
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION:
|
||||||
|
return "select sound presentation";
|
||||||
|
case CEC_USER_CONTROL_CODE_PLAY_FUNCTION:
|
||||||
|
return "play (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION:
|
||||||
|
return "pause play (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_RECORD_FUNCTION:
|
||||||
|
return "record (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION:
|
||||||
|
return "pause record (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_STOP_FUNCTION:
|
||||||
|
return "stop (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_MUTE_FUNCTION:
|
||||||
|
return "mute (function)";
|
||||||
|
case CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION:
|
||||||
|
return "restore volume";
|
||||||
|
case CEC_USER_CONTROL_CODE_TUNE_FUNCTION:
|
||||||
|
return "tune";
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION:
|
||||||
|
return "select media";
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION:
|
||||||
|
return "select AV input";
|
||||||
|
case CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION:
|
||||||
|
return "select audio input";
|
||||||
|
case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION:
|
||||||
|
return "power toggle";
|
||||||
|
case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION:
|
||||||
|
return "power off";
|
||||||
|
case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION:
|
||||||
|
return "power on";
|
||||||
|
case CEC_USER_CONTROL_CODE_F1_BLUE:
|
||||||
|
return "F1 (blue)";
|
||||||
|
case CEC_USER_CONTROL_CODE_F2_RED:
|
||||||
|
return "F2 (red)";
|
||||||
|
case CEC_USER_CONTROL_CODE_F3_GREEN:
|
||||||
|
return "F3 (green)";
|
||||||
|
case CEC_USER_CONTROL_CODE_F4_YELLOW:
|
||||||
|
return "F4 (yellow)";
|
||||||
|
case CEC_USER_CONTROL_CODE_F5:
|
||||||
|
return "F5";
|
||||||
|
case CEC_USER_CONTROL_CODE_DATA:
|
||||||
|
return "data";
|
||||||
|
case CEC_USER_CONTROL_CODE_AN_RETURN:
|
||||||
|
return "return (Samsung)";
|
||||||
|
case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST:
|
||||||
|
return "channels list (Samsung)";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static cec_opcode GetResponseOpcode(cec_opcode opcode)
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
|
||||||
|
return CEC_OPCODE_ACTIVE_SOURCE;
|
||||||
|
case CEC_OPCODE_GET_CEC_VERSION:
|
||||||
|
return CEC_OPCODE_CEC_VERSION;
|
||||||
|
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
|
||||||
|
return CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
|
||||||
|
case CEC_OPCODE_GET_MENU_LANGUAGE:
|
||||||
|
return CEC_OPCODE_SET_MENU_LANGUAGE;
|
||||||
|
case CEC_OPCODE_GIVE_DECK_STATUS:
|
||||||
|
return CEC_OPCODE_DECK_STATUS;
|
||||||
|
case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
|
||||||
|
return CEC_OPCODE_TUNER_DEVICE_STATUS;
|
||||||
|
case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
|
||||||
|
return CEC_OPCODE_DEVICE_VENDOR_ID;
|
||||||
|
case CEC_OPCODE_GIVE_OSD_NAME:
|
||||||
|
return CEC_OPCODE_SET_OSD_NAME;
|
||||||
|
case CEC_OPCODE_MENU_REQUEST:
|
||||||
|
return CEC_OPCODE_MENU_STATUS;
|
||||||
|
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
|
||||||
|
return CEC_OPCODE_REPORT_POWER_STATUS;
|
||||||
|
case CEC_OPCODE_GIVE_AUDIO_STATUS:
|
||||||
|
return CEC_OPCODE_REPORT_AUDIO_STATUS;
|
||||||
|
case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
|
||||||
|
return CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS;
|
||||||
|
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
|
||||||
|
return CEC_OPCODE_SET_SYSTEM_AUDIO_MODE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CEC_OPCODE_NONE;
|
||||||
|
}
|
@@ -36,7 +36,7 @@
|
|||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include "video_lib.h"
|
#include "video_lib.h"
|
||||||
#include "lt_debug.h"
|
#include "lt_debug.h"
|
||||||
#include "linux-uapi-cec.h"
|
#include "hdmi_cec.h"
|
||||||
|
|
||||||
#include <proc_tools.h>
|
#include <proc_tools.h>
|
||||||
|
|
||||||
@@ -317,8 +317,6 @@ cVideo::cVideo(int, void *, void *, unsigned int unit)
|
|||||||
} else
|
} else
|
||||||
devnum = unit;
|
devnum = unit;
|
||||||
fd = -1;
|
fd = -1;
|
||||||
hdmiFd = -1;
|
|
||||||
standby_cec_activ = autoview_cec_activ = false;
|
|
||||||
openDevice();
|
openDevice();
|
||||||
setAVInput(ENCODER);
|
setAVInput(ENCODER);
|
||||||
}
|
}
|
||||||
@@ -327,8 +325,8 @@ cVideo::~cVideo(void)
|
|||||||
{
|
{
|
||||||
if(fd >= 0)
|
if(fd >= 0)
|
||||||
setAVInput(AUX);
|
setAVInput(AUX);
|
||||||
if (standby_cec_activ && fd >= 0)
|
if (hdmi_cec::getInstance()->standby_cec_activ && fd >= 0)
|
||||||
SetCECState(true);
|
hdmi_cec::getInstance()->SetCECState(true);
|
||||||
|
|
||||||
closeDevice();
|
closeDevice();
|
||||||
}
|
}
|
||||||
@@ -631,7 +629,7 @@ void cVideo::Standby(unsigned int bOn)
|
|||||||
setAVInput(ENCODER);
|
setAVInput(ENCODER);
|
||||||
}
|
}
|
||||||
video_standby = bOn;
|
video_standby = bOn;
|
||||||
SetCECState(video_standby);
|
hdmi_cec::getInstance()->SetCECState(video_standby);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::getBlank(void)
|
int cVideo::getBlank(void)
|
||||||
@@ -847,7 +845,7 @@ void cVideo::SetControl(int control, int value)
|
|||||||
if (p) {
|
if (p) {
|
||||||
char buf[20];
|
char buf[20];
|
||||||
int fix_value = value * 256;
|
int fix_value = value * 256;
|
||||||
int len = snprintf(buf, sizeof(buf), "%0.8X", fix_value);
|
int len = snprintf(buf, sizeof(buf), "%.8X", fix_value);
|
||||||
if (len < (int) sizeof(buf))
|
if (len < (int) sizeof(buf))
|
||||||
proc_put(p, buf, len);
|
proc_put(p, buf, len);
|
||||||
}
|
}
|
||||||
@@ -1149,220 +1147,15 @@ bool cVideo::GetScreenImage(unsigned char * &out_data, int &xres, int &yres, boo
|
|||||||
|
|
||||||
bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
|
bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
|
||||||
{
|
{
|
||||||
physicalAddress[0] = 0x10;
|
return hdmi_cec::getInstance()->SetCECMode(_deviceType);
|
||||||
physicalAddress[1] = 0x00;
|
|
||||||
logicalAddress = 1;
|
|
||||||
|
|
||||||
if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF)
|
|
||||||
{
|
|
||||||
if (hdmiFd >= 0) {
|
|
||||||
close(hdmiFd);
|
|
||||||
hdmiFd = -1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
deviceType = _deviceType;
|
|
||||||
|
|
||||||
if (hdmiFd == -1)
|
|
||||||
hdmiFd = open("/dev/cec0", O_RDWR | O_CLOEXEC);
|
|
||||||
|
|
||||||
if (hdmiFd >= 0)
|
|
||||||
{
|
|
||||||
__u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
|
|
||||||
struct cec_caps caps = {};
|
|
||||||
|
|
||||||
if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0)
|
|
||||||
lt_info("%s: CEC get caps failed (%m)\n", __func__);
|
|
||||||
|
|
||||||
if (caps.capabilities & CEC_CAP_LOG_ADDRS)
|
|
||||||
{
|
|
||||||
struct cec_log_addrs laddrs = {};
|
|
||||||
|
|
||||||
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
|
|
||||||
lt_info("%s: CEC reset log addr failed (%m)\n", __func__);
|
|
||||||
|
|
||||||
memset(&laddrs, 0, sizeof(laddrs));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: cec_version, osd_name and deviceType should be made configurable,
|
|
||||||
* CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
|
|
||||||
* (saves us some startup speed as well, polling for a free logical address
|
|
||||||
* takes some time)
|
|
||||||
*/
|
|
||||||
laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
|
|
||||||
strcpy(laddrs.osd_name, "neutrino");
|
|
||||||
laddrs.vendor_id = CEC_VENDOR_ID_NONE;
|
|
||||||
|
|
||||||
switch (deviceType)
|
|
||||||
{
|
|
||||||
case CEC_LOG_ADDR_TV:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_RECORD_1:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TUNER_1:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_PLAYBACK_1:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_AUDIOSYSTEM:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
|
|
||||||
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
|
|
||||||
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
laddrs.num_log_addrs++;
|
|
||||||
|
|
||||||
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
|
|
||||||
lt_info("%s: CEC set log addr failed (%m)\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0)
|
|
||||||
lt_info("%s: CEC monitor failed (%m)\n", __func__);
|
|
||||||
|
|
||||||
GetCECAddressInfo();
|
|
||||||
|
|
||||||
if(autoview_cec_activ)
|
|
||||||
SetCECState(false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cVideo::GetCECAddressInfo()
|
|
||||||
{
|
|
||||||
if (hdmiFd >= 0)
|
|
||||||
{
|
|
||||||
struct addressinfo addressinfo;
|
|
||||||
|
|
||||||
__u16 phys_addr;
|
|
||||||
struct cec_log_addrs laddrs = {};
|
|
||||||
|
|
||||||
::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
|
|
||||||
addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
|
|
||||||
addressinfo.physical[1] = phys_addr & 0xff;
|
|
||||||
|
|
||||||
::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
|
|
||||||
addressinfo.logical = laddrs.log_addr[0];
|
|
||||||
|
|
||||||
switch (laddrs.log_addr_type[0])
|
|
||||||
{
|
|
||||||
case CEC_LOG_ADDR_TYPE_TV:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_TV;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TYPE_RECORD:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_RECORD_1;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TYPE_TUNER:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_TUNER_1;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TYPE_PLAYBACK:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
|
|
||||||
break;
|
|
||||||
case CEC_LOG_ADDR_TYPE_UNREGISTERED:
|
|
||||||
default:
|
|
||||||
addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceType = addressinfo.type;
|
|
||||||
logicalAddress = addressinfo.logical;
|
|
||||||
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
|
|
||||||
{
|
|
||||||
lt_info("%s: detected physical address change: %02X%02X --> %02X%02X", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
|
|
||||||
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
|
|
||||||
ReportPhysicalAddress();
|
|
||||||
// addressChanged((physicalAddress[0] << 8) | physicalAddress[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cVideo::ReportPhysicalAddress()
|
|
||||||
{
|
|
||||||
struct cec_message txmessage;
|
|
||||||
txmessage.address = 0x0f; /* broadcast */
|
|
||||||
txmessage.data[0] = CEC_MSG_REPORT_PHYSICAL_ADDR;
|
|
||||||
txmessage.data[1] = physicalAddress[0];
|
|
||||||
txmessage.data[2] = physicalAddress[1];
|
|
||||||
txmessage.data[3] = deviceType;
|
|
||||||
txmessage.length = 4;
|
|
||||||
SendCECMessage(txmessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cVideo::SendCECMessage(struct cec_message &message)
|
|
||||||
{
|
|
||||||
if (hdmiFd >= 0)
|
|
||||||
{
|
|
||||||
lt_info("[CEC] send message");
|
|
||||||
for (int i = 0; i < message.length; i++)
|
|
||||||
{
|
|
||||||
lt_info(" %02X", message.data[i]);
|
|
||||||
}
|
|
||||||
lt_info("\n");
|
|
||||||
struct cec_msg msg;
|
|
||||||
cec_msg_init(&msg, logicalAddress, message.address);
|
|
||||||
memcpy(&msg.msg[1], message.data, message.length);
|
|
||||||
msg.len = message.length + 1;
|
|
||||||
ioctl(hdmiFd, CEC_TRANSMIT, &msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::SetCECAutoStandby(bool state)
|
void cVideo::SetCECAutoStandby(bool state)
|
||||||
{
|
{
|
||||||
standby_cec_activ = state;
|
hdmi_cec::getInstance()->SetCECAutoStandby(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::SetCECAutoView(bool state)
|
void cVideo::SetCECAutoView(bool state)
|
||||||
{
|
{
|
||||||
autoview_cec_activ = state;
|
hdmi_cec::getInstance()->SetCECAutoView(state);
|
||||||
}
|
|
||||||
|
|
||||||
void cVideo::SetCECState(bool state)
|
|
||||||
{
|
|
||||||
struct cec_message message;
|
|
||||||
|
|
||||||
if ((standby_cec_activ) && state){
|
|
||||||
message.address = CEC_OP_PRIM_DEVTYPE_TV;
|
|
||||||
message.data[0] = CEC_MSG_STANDBY;
|
|
||||||
message.length = 1;
|
|
||||||
SendCECMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((autoview_cec_activ) && !state){
|
|
||||||
message.address = CEC_OP_PRIM_DEVTYPE_TV;
|
|
||||||
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
|
|
||||||
message.length = 1;
|
|
||||||
SendCECMessage(message);
|
|
||||||
usleep(10000);
|
|
||||||
message.address = 0x0f; /* broadcast */
|
|
||||||
message.data[0] = CEC_MSG_ACTIVE_SOURCE;
|
|
||||||
//message.data[1] = ((((int)physicalAddress >> 12) & 0xf) << 4) + (((int)physicalAddress >> 8) & 0xf);
|
|
||||||
//message.data[2] = ((((int)physicalAddress >> 4) & 0xf) << 4) + (((int)physicalAddress >> 0) & 0xf);
|
|
||||||
message.data[1] = physicalAddress[0];
|
|
||||||
message.data[2] = physicalAddress[1];
|
|
||||||
message.length = 3;
|
|
||||||
SendCECMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -157,20 +157,6 @@ typedef enum
|
|||||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||||
} VIDEO_CONTROL;
|
} VIDEO_CONTROL;
|
||||||
|
|
||||||
struct cec_message
|
|
||||||
{
|
|
||||||
unsigned char address;
|
|
||||||
unsigned char length;
|
|
||||||
unsigned char data[256];
|
|
||||||
}__attribute__((packed));
|
|
||||||
#define cec_rx_message cec_message
|
|
||||||
struct addressinfo
|
|
||||||
{
|
|
||||||
unsigned char logical;
|
|
||||||
unsigned char physical[2];
|
|
||||||
unsigned char type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class cDemux;
|
class cDemux;
|
||||||
class cPlayback;
|
class cPlayback;
|
||||||
|
|
||||||
@@ -214,11 +200,6 @@ class cVideo
|
|||||||
/* used internally by dmx */
|
/* used internally by dmx */
|
||||||
int64_t GetPTS(void);
|
int64_t GetPTS(void);
|
||||||
|
|
||||||
unsigned char physicalAddress[2];
|
|
||||||
bool standby_cec_activ,autoview_cec_activ;
|
|
||||||
unsigned char deviceType, logicalAddress;
|
|
||||||
int hdmiFd;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* constructor & destructor */
|
/* constructor & destructor */
|
||||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||||
@@ -263,10 +244,6 @@ class cVideo
|
|||||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
|
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
|
||||||
void SetCECAutoView(bool);
|
void SetCECAutoView(bool);
|
||||||
void SetCECAutoStandby(bool);
|
void SetCECAutoStandby(bool);
|
||||||
void GetCECAddressInfo();
|
|
||||||
void SendCECMessage(struct cec_message &message);
|
|
||||||
void SetCECState(bool state);
|
|
||||||
void ReportPhysicalAddress();
|
|
||||||
void ShowPicture(const char * fname);
|
void ShowPicture(const char * fname);
|
||||||
void StopPicture();
|
void StopPicture();
|
||||||
void Standby(unsigned int bOn);
|
void Standby(unsigned int bOn);
|
||||||
|
@@ -399,10 +399,7 @@ static int32_t PlaybackContinue(Context_t *context)
|
|||||||
if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard)
|
if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard)
|
||||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||||
|
|
||||||
context->output->Command(context, OUTPUT_PAUSE, NULL);
|
if (context->playback->BackWard || context->playback->isForwarding)
|
||||||
context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
|
||||||
|
|
||||||
if (context->playback->BackWard)
|
|
||||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||||
|
|
||||||
context->playback->isPaused = 0;
|
context->playback->isPaused = 0;
|
||||||
@@ -411,6 +408,8 @@ static int32_t PlaybackContinue(Context_t *context)
|
|||||||
context->playback->BackWard = 0;
|
context->playback->BackWard = 0;
|
||||||
context->playback->SlowMotion = 0;
|
context->playback->SlowMotion = 0;
|
||||||
context->playback->Speed = 1;
|
context->playback->Speed = 1;
|
||||||
|
|
||||||
|
context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -540,7 +539,8 @@ static int PlaybackFastForward(Context_t *context, int *speed)
|
|||||||
context->playback->Speed = *speed;
|
context->playback->Speed = *speed;
|
||||||
playback_printf(20, "Speed: %d x {%d}\n", *speed, context->playback->Speed);
|
playback_printf(20, "Speed: %d x {%d}\n", *speed, context->playback->Speed);
|
||||||
context->output->Command(context, OUTPUT_FASTFORWARD, NULL);
|
context->output->Command(context, OUTPUT_FASTFORWARD, NULL);
|
||||||
//context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "1");
|
||||||
|
context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user