mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
armbox: start implementing cec support
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include <linux/fb.h>
|
||||
#include "video_lib.h"
|
||||
#include "lt_debug.h"
|
||||
#include "linux-uapi-cec.h"
|
||||
|
||||
#include <proc_tools.h>
|
||||
|
||||
@@ -160,6 +161,7 @@ cVideo::cVideo(int, void *, void *, unsigned int unit)
|
||||
} else
|
||||
devnum = unit;
|
||||
fd = -1;
|
||||
standby_cec_activ = autoview_cec_activ = false;
|
||||
openDevice();
|
||||
}
|
||||
|
||||
@@ -519,6 +521,7 @@ void cVideo::Standby(unsigned int bOn)
|
||||
openDevice();
|
||||
}
|
||||
video_standby = bOn;
|
||||
SetCECState(video_standby);
|
||||
}
|
||||
|
||||
int cVideo::getBlank(void)
|
||||
@@ -773,3 +776,192 @@ bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool g
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
|
||||
{
|
||||
physicalAddress[0] = 0x10;
|
||||
physicalAddress[1] = 0x00;
|
||||
logicalAddress = 1;
|
||||
deviceType = 1; /* default: recorder */
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
void cVideo::getCECAddressInfo()
|
||||
{
|
||||
if (hdmiFd >= 0)
|
||||
{
|
||||
bool hasdata = false;
|
||||
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;
|
||||
}
|
||||
hasdata = true;
|
||||
|
||||
if (hasdata)
|
||||
{
|
||||
deviceType = addressinfo.type;
|
||||
logicalAddress = addressinfo.logical;
|
||||
if (!fixedAddress)
|
||||
{
|
||||
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::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)
|
||||
{
|
||||
standby_cec_activ = state;
|
||||
}
|
||||
|
||||
void cVideo::SetCECAutoView(bool state)
|
||||
{
|
||||
autoview_cec_activ = state;
|
||||
}
|
||||
|
||||
void cVideo::SetCECState(bool state)
|
||||
{
|
||||
struct cec_message message;
|
||||
message.address = 0x0f;
|
||||
message.length = 2;
|
||||
|
||||
if ((standby_cec_activ) && state){
|
||||
message.data[0] = CEC_MSG_STANDBY;
|
||||
message.data[1] = 1;
|
||||
}
|
||||
|
||||
if ((autoview_cec_activ) && !state){
|
||||
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
|
||||
message.data[1] = 1;
|
||||
}
|
||||
|
||||
sendCECMessage(message);
|
||||
}
|
||||
|
@@ -135,6 +135,19 @@ typedef enum
|
||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||
} 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 cVideo
|
||||
{
|
||||
@@ -167,6 +180,11 @@ class cVideo
|
||||
/* used internally by dmx */
|
||||
int64_t GetPTS(void);
|
||||
|
||||
unsigned char physicalAddress[2];
|
||||
bool fixedAddress,standby_cec_activ,autoview_cec_activ;
|
||||
unsigned char deviceType, logicalAddress;
|
||||
int hdmiFd;
|
||||
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||
@@ -208,9 +226,12 @@ class cVideo
|
||||
int SetVideoSystem(int video_system, bool remember = true);
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
|
||||
void SetCECAutoView(bool) { return; };
|
||||
void SetCECAutoStandby(bool) { return; };
|
||||
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 ShowPicture(const char * fname, const char *_destname = NULL);
|
||||
void StopPicture();
|
||||
void Standby(unsigned int bOn);
|
||||
|
Reference in New Issue
Block a user