From ec6667461cb1ac8bf051f19248611940f86848d2 Mon Sep 17 00:00:00 2001 From: Thilo Graf Date: Fri, 5 Oct 2018 13:58:11 +0200 Subject: [PATCH 01/14] libarmbox/video.cpp: fix possible broken build possible error: "error: '0' flag ignored with precision and '%X' gnu_printf format [-Werror=format=]" Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/cffb2dc8e35b0a7e4fe023a5ecf3ab287cd9fac4 Author: Thilo Graf Date: 2018-10-05 (Fri, 05 Oct 2018) ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index a7422de..ab5d7ff 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -847,7 +847,7 @@ void cVideo::SetControl(int control, int value) if (p) { char buf[20]; 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)) proc_put(p, buf, len); } From 7531eaff031fde1436ca473fdb03a93cb24ed5db Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 6 Oct 2018 18:43:59 +0200 Subject: [PATCH 02/14] arm another fix fastforward Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/8b46d8192e46660f0f72ecaee1c260da4624744b Author: TangoCash Date: 2018-10-06 (Sat, 06 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libeplayer3-arm/playback/playback.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index 4ec98be..b8fe5bb 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -399,9 +399,6 @@ static int32_t PlaybackContinue(Context_t *context) if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard) context->output->Command(context, OUTPUT_CLEAR, NULL); - context->output->Command(context, OUTPUT_PAUSE, NULL); - context->output->Command(context, OUTPUT_CONTINUE, NULL); - if (context->playback->BackWard) context->output->Command(context, OUTPUT_AUDIOMUTE, "0"); @@ -411,6 +408,8 @@ static int32_t PlaybackContinue(Context_t *context) context->playback->BackWard = 0; context->playback->SlowMotion = 0; context->playback->Speed = 1; + + context->output->Command(context, OUTPUT_CONTINUE, NULL); } else { @@ -540,7 +539,7 @@ static int PlaybackFastForward(Context_t *context, int *speed) context->playback->Speed = *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_CONTINUE, NULL); + context->output->Command(context, OUTPUT_CONTINUE, NULL); } else { From 47c1b0b58cf3196b745b09ed3075a94884896410 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 6 Oct 2018 18:53:42 +0200 Subject: [PATCH 03/14] Revert "update video streamtype" This reverts commit ebda3bf0417182ce9b0859ba66fcf7a5b28300a5. Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/144d9990660c47e338a2220a0649b01103b67baf Author: TangoCash Date: 2018-10-06 (Sat, 06 Oct 2018) ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 56 ++++++++++++++++++++++++++++++------------- libarmbox/video_lib.h | 25 +++++++------------ 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index ab5d7ff..73fc02a 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -140,6 +140,15 @@ static const char *vid_modes[] = { "720p50" // VIDEO_STD_AUTO }; +#define VIDEO_STREAMTYPE_MPEG2 0 +#define VIDEO_STREAMTYPE_MPEG4_H264 1 +#define VIDEO_STREAMTYPE_VC1 3 +#define VIDEO_STREAMTYPE_MPEG4_Part2 4 +#define VIDEO_STREAMTYPE_VC1_SM 5 +#define VIDEO_STREAMTYPE_MPEG1 6 +#define VIDEO_STREAMTYPE_H265_HEVC 7 +#define VIDEO_STREAMTYPE_AVS 16 + ssize_t write_all(int fd, const void *buf, size_t count) { int retval; @@ -751,26 +760,39 @@ void cVideo::SetSyncMode(AVSYNC_TYPE mode) int cVideo::SetStreamType(VIDEO_FORMAT type) { - const char *VF[] = { - "VIDEO_STREAMTYPE_MPEG2", - "VIDEO_STREAMTYPE_MPEG4_H264", - "VIDEO_STREAMTYPE_MPEG4_H263", - "VIDEO_STREAMTYPE_VC1", - "VIDEO_STREAMTYPE_MPEG4_Part2", - "VIDEO_STREAMTYPE_VC1_SM", - "VIDEO_STREAMTYPE_MPEG1", - "VIDEO_STREAMTYPE_DIVX311" - "VIDEO_STREAMTYPE_H265_HEVC", - "VIDEO_STREAMTYPE_AVS" + static const char *VF[] = { + "VIDEO_FORMAT_MPEG2", + "VIDEO_FORMAT_MPEG4", + "VIDEO_FORMAT_VC1", + "VIDEO_FORMAT_JPEG", + "VIDEO_FORMAT_GIF", + "VIDEO_FORMAT_PNG" }; + int t; + lt_debug("#%d: %s type=%s\n", devnum, __func__, VF[type]); - lt_info("%s - type=%s\n", __FUNCTION__, VF[type]); - - if (ioctl( fd, VIDEO_SET_STREAMTYPE, type) < 0) - perror("VIDEO_SET_STREAMTYPE"); - - StreamType = type; + switch (type) + { + case VIDEO_FORMAT_MPEG4_H264: + t = VIDEO_STREAMTYPE_MPEG4_H264; + break; + case VIDEO_FORMAT_MPEG4_H265: + t = VIDEO_STREAMTYPE_H265_HEVC; + break; + case VIDEO_FORMAT_AVS: + t = VIDEO_STREAMTYPE_AVS; + break; + case VIDEO_FORMAT_VC1: + t = VIDEO_STREAMTYPE_VC1; + break; + case VIDEO_FORMAT_MPEG2: + default: + t = VIDEO_STREAMTYPE_MPEG2; + break; + } + if (ioctl(fd, VIDEO_SET_STREAMTYPE, t) < 0) + lt_info("%s VIDEO_SET_STREAMTYPE(%d) failed: %m\n", __func__, t); return 0; } diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index f8c665e..adbb5fb 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -35,23 +35,14 @@ typedef enum { } COLOR_FORMAT; typedef enum { - VIDEO_STREAMTYPE_UNKNOWN = -1, - VIDEO_STREAMTYPE_MPEG2 = 0, - VIDEO_STREAMTYPE_MPEG4_H264 = 1, - VIDEO_STREAMTYPE_H263 = 2, - VIDEO_STREAMTYPE_VC1 = 3, - VIDEO_STREAMTYPE_MPEG4_Part2 = 4, - VIDEO_STREAMTYPE_VC1_SM = 5, - VIDEO_STREAMTYPE_MPEG1 = 6, - VIDEO_STREAMTYPE_MPEG4_H265 = 7, - VIDEO_STREAMTYPE_VB8 = 8, - VIDEO_STREAMTYPE_VB9 = 9, - VIDEO_STREAMTYPE_XVID = 10, - VIDEO_STREAMTYPE_DIVX311 = 13, - VIDEO_STREAMTYPE_DIVX4 = 14, - VIDEO_STREAMTYPE_DIVX5 = 15, - VIDEO_STREAMTYPE_VB6 = 18, - VIDEO_STREAMTYPE_SPARK = 21 + VIDEO_FORMAT_MPEG2 = 0, + VIDEO_FORMAT_MPEG4_H264, + VIDEO_FORMAT_VC1, + VIDEO_FORMAT_JPEG, + VIDEO_FORMAT_GIF, + VIDEO_FORMAT_PNG, + VIDEO_FORMAT_MPEG4_H265, + VIDEO_FORMAT_AVS = 16 } VIDEO_FORMAT; typedef enum { From b52f7380abc084af7c89b3e8bc8fdb828d137383 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 6 Oct 2018 18:53:49 +0200 Subject: [PATCH 04/14] Revert "update audio streamtype" This reverts commit b95524d059dfaec36034e23592f7c7236067c2d2. Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/b4c9228ff653653658d01c134e1e2818d470faab Author: TangoCash Date: 2018-10-06 (Sat, 06 Oct 2018) ------------------ This commit was generated by Migit --- libarmbox/audio.cpp | 57 +++++++++++++++++++++++-------------------- libarmbox/audio_lib.h | 29 +++++++++++----------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index d6af373..809b594 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -150,36 +150,41 @@ void cAudio::SetSyncMode(AVSYNC_TYPE Mode) ioctl(fd, AUDIO_SET_AV_SYNC, Mode); } +#define AUDIO_STREAMTYPE_AC3 0 +#define AUDIO_STREAMTYPE_MPEG 1 +#define AUDIO_STREAMTYPE_DTS 2 +#define AUDIO_STREAMTYPE_AAC 8 +#define AUDIO_STREAMTYPE_AACHE 9 + void cAudio::SetStreamType(AUDIO_FORMAT type) { - const char *AF[] = { - "AUDIO_STREAMTYPE_AC3", - "AUDIO_STREAMTYPE_MPEG", - "AUDIO_STREAMTYPE_DTS", - "AUDIO_STREAMTYPE_LPCM", - "AUDIO_STREAMTYPE_AAC", - "AUDIO_STREAMTYPE_AAC_HE", - "AUDIO_STREAMTYPE_MP3", - "AUDIO_STREAMTYPE_AAC_PLUS", - "AUDIO_STREAMTYPE_DTS_HD", - "AUDIO_STREAMTYPE_WMA", - "AUDIO_STREAMTYPE_WMA_PRO", - "AUDIO_STREAMTYPE_AC3_PLUS", - "AUDIO_STREAMTYPE_AMR", - "AUDIO_STREAMTYPE_RAW" - }; - - lt_info("%s - type=%s\n", __FUNCTION__, AF[type]); - - if (ioctl(fd, AUDIO_SET_BYPASS_MODE, type) < 0) - { - perror("AUDIO_SET_BYPASS_MODE"); - return; - } - + int bypass = AUDIO_STREAMTYPE_MPEG; + lt_debug("%s %d\n", __FUNCTION__, type); StreamType = type; - return; + switch (type) + { + case AUDIO_FMT_DD_PLUS: + case AUDIO_FMT_DOLBY_DIGITAL: + bypass = AUDIO_STREAMTYPE_AC3; + break; + case AUDIO_FMT_AAC: + bypass = AUDIO_STREAMTYPE_AAC; + break; + case AUDIO_FMT_AAC_PLUS: + bypass = AUDIO_STREAMTYPE_AACHE; + break; + case AUDIO_FMT_DTS: + bypass = AUDIO_STREAMTYPE_DTS; + break; + default: + break; + } + + // Normaly the encoding should be set using AUDIO_SET_ENCODING + // But as we implemented the behavior to bypass (cause of e2) this is correct here + if (ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass) < 0) + lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__); } int cAudio::setChannel(int channel) diff --git a/libarmbox/audio_lib.h b/libarmbox/audio_lib.h index 2bcd073..1fb896f 100644 --- a/libarmbox/audio_lib.h +++ b/libarmbox/audio_lib.h @@ -20,21 +20,20 @@ typedef enum { typedef enum { - AUDIO_FMT_UNKNOWN = -1, - AUDIO_FMT_DOLBY_DIGITAL = 0, - AUDIO_FMT_MPEG = 1, - AUDIO_FMT_DTS = 2, - AUDIO_FMT_LPCM = 6, - AUDIO_FMT_AAC = 8, - AUDIO_FMT_AAC_HE = 9, - AUDIO_FMT_MP3 = 0xa, - AUDIO_FMT_AAC_PLUS = 0xb, - AUDIO_FMT_DTS_HD = 0x10, - AUDIO_FMT_WMA = 0x20, - AUDIO_FMT_WMA_PRO = 0x21, - AUDIO_FMT_DD_PLUS = 0x22, - AUDIO_FMT_AMR = 0x23, - AUDIO_FMT_RAW = 0xf + AUDIO_FMT_AUTO = 0, + AUDIO_FMT_MPEG, + AUDIO_FMT_MP3, + AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_AAC, + AUDIO_FMT_AAC_PLUS, + AUDIO_FMT_DD_PLUS, + AUDIO_FMT_DTS, + AUDIO_FMT_AVS, + AUDIO_FMT_MLP, + AUDIO_FMT_WMA, + AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback + AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP } AUDIO_FORMAT; class mixerVolume; From 6887c787e816f255653c9b069b154a894be5fbff Mon Sep 17 00:00:00 2001 From: Frankenstone Date: Sun, 7 Oct 2018 09:57:38 +0200 Subject: [PATCH 05/14] arm hardware: fast forward, mute audio when passthrough AC3 / DTS -thx DboxOldie Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/53c28f7fb96550a43594ee4795b71d34be75f5b6 Author: Frankenstone Date: 2018-10-07 (Sun, 07 Oct 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/playback/playback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index b8fe5bb..781bf4f 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -399,7 +399,7 @@ static int32_t PlaybackContinue(Context_t *context) if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard) context->output->Command(context, OUTPUT_CLEAR, NULL); - if (context->playback->BackWard) + if (context->playback->BackWard || context->playback->isForwarding) context->output->Command(context, OUTPUT_AUDIOMUTE, "0"); context->playback->isPaused = 0; @@ -539,6 +539,7 @@ static int PlaybackFastForward(Context_t *context, int *speed) context->playback->Speed = *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_AUDIOMUTE, "1"); context->output->Command(context, OUTPUT_CONTINUE, NULL); } else From 1f6c9f15546f08d518dec9d15235965be88dfba9 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 7 Oct 2018 12:00:41 +0200 Subject: [PATCH 06/14] libarmbox: move hdmi_cec to own class, add basic cec-remote support cec-remote will print received commands in log for now Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/eca390a5748dadf2c38ad13aa6bb97f4fa326fb4 Author: TangoCash Date: 2018-10-07 (Sun, 07 Oct 2018) ------------------ This commit was generated by Migit --- libarmbox/Makefile.am | 3 +- libarmbox/hdmi_cec.cpp | 495 +++++++++++++++++++++++++++++++++++++++++ libarmbox/hdmi_cec.h | 66 ++++++ libarmbox/video.cpp | 221 +----------------- libarmbox/video_lib.h | 23 -- 5 files changed, 570 insertions(+), 238 deletions(-) create mode 100644 libarmbox/hdmi_cec.cpp create mode 100644 libarmbox/hdmi_cec.h diff --git a/libarmbox/Makefile.am b/libarmbox/Makefile.am index 4d5c162..d8453df 100644 --- a/libarmbox/Makefile.am +++ b/libarmbox/Makefile.am @@ -20,7 +20,8 @@ libarmbox_la_SOURCES = \ video.cpp \ audio.cpp \ init.cpp \ - record.cpp + record.cpp \ + hdmi_cec.cpp if ENABLE_GSTREAMER_10 libarmbox_la_SOURCES += \ diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp new file mode 100644 index 0000000..5edf404 --- /dev/null +++ b/libarmbox/hdmi_cec.cpp @@ -0,0 +1,495 @@ +/* + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "linux-uapi-cec.h" +#include "hdmi_cec.h" +#include "lt_debug.h" + +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) +#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) +#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, 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" + +hdmi_cec * hdmi_cec::hdmi_cec_instance = NULL; + +hdmi_cec::hdmi_cec() +{ + standby_cec_activ = autoview_cec_activ = false; + hdmiFd = -1; + if (hdmiFd == -1) + hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC); + Start(); +} + +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(); + 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) + { + if (hdmiFd >= 0) + { + close(hdmiFd); + hdmiFd = -1; + Stop(); + } + return false; + } + else + deviceType = _deviceType; + + if (hdmiFd == -1) + { + hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC); + Start(); + } + + 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 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("%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.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 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 %s\n",str); + struct cec_msg msg; + cec_msg_init(&msg, logicalAddress, txmessage.address); + 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; + + 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] = 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 0x32: + key = 0x8b; + break; + case 0x20: + key = 0x0b; + break; + case 0x21: + key = 0x02; + break; + case 0x22: + key = 0x03; + break; + case 0x23: + key = 0x04; + break; + case 0x24: + key = 0x05; + break; + case 0x25: + key = 0x06; + break; + case 0x26: + key = 0x07; + break; + case 0x27: + key = 0x08; + break; + case 0x28: + key = 0x09; + break; + case 0x29: + key = 0x0a; + break; + case 0x30: + key = 0x192; + break; + case 0x31: + key = 0x193; + break; + case 0x44: + key = 0xcf; + break; + case 0x45: + key = 0x80; + break; + case 0x46: + key = 0x77; + break; + case 0x47: + key = 0xa7; + break; + case 0x48: + key = 0xa8; + break; + case 0x49: + key = 0xd0; + break; + case 0x53: + key = 0x166; + break; + case 0x54: + key = 0x16a; + break; + case 0x60: + key = 0xcf; + break; + case 0x61: + key = 0xa4; + break; + case 0x62: + key = 0xa7; + break; + case 0x64: + key = 0x80; + break; + case 0x00: + key = 0x160; + break; + case 0x03: + key = 0x69; + break; + case 0x04: + key = 0x6a; + break; + case 0x01: + key = 0x67; + break; + case 0x02: + key = 0x6c; + break; + case 0x0d: + key = 0xae; + break; + case 0x72: + key = 0x18e; + break; + case 0x71: + key = 0x191; + break; + case 0x73: + key = 0x18f; + break; + case 0x74: + key = 0x190; + break; + default: + key = 0x8b; + 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; + + return (OpenThreads::Thread::join() == 0); +} + +void hdmi_cec::run() +{ + while (running) + { + Receive(); + } +} + +void hdmi_cec::Receive() +{ + bool hasdata = false; + struct cec_message rxmessage; + + struct cec_msg msg; + if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0) + { + rxmessage.length = msg.len - 1; + 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 %s\n", str); + + switch (rxmessage.data[0]) + { + case 0x44: /* key pressed */ + keypressed = true; + pressedkey = rxmessage.data[1]; + case 0x45: /* key released */ + { + long code = translateKey(pressedkey); + if (keypressed) + code |= 0x80000000; + lt_info("[CEC] received key %ld\n",code); + break; + } + } + } +} diff --git a/libarmbox/hdmi_cec.h b/libarmbox/hdmi_cec.h new file mode 100644 index 0000000..0dc97cb --- /dev/null +++ b/libarmbox/hdmi_cec.h @@ -0,0 +1,66 @@ +/* + 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 +#include + +#include "video_lib.h" + +struct cec_message +{ + unsigned char address; + unsigned char length; + unsigned char data[256]; +} __attribute__((packed)); + +struct addressinfo +{ + unsigned char logical; + unsigned char physical[2]; + unsigned char type; +}; + +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); +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; +}; diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 73fc02a..e05f3c3 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -36,7 +36,7 @@ #include #include "video_lib.h" #include "lt_debug.h" -#include "linux-uapi-cec.h" +#include "hdmi_cec.h" #include @@ -326,8 +326,6 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) } else devnum = unit; fd = -1; - hdmiFd = -1; - standby_cec_activ = autoview_cec_activ = false; openDevice(); setAVInput(ENCODER); } @@ -336,8 +334,8 @@ cVideo::~cVideo(void) { if(fd >= 0) setAVInput(AUX); - if (standby_cec_activ && fd >= 0) - SetCECState(true); + if (hdmi_cec::getInstance()->standby_cec_activ && fd >= 0) + hdmi_cec::getInstance()->SetCECState(true); closeDevice(); } @@ -640,7 +638,7 @@ void cVideo::Standby(unsigned int bOn) setAVInput(ENCODER); } video_standby = bOn; - SetCECState(video_standby); + hdmi_cec::getInstance()->SetCECState(video_standby); } int cVideo::getBlank(void) @@ -1171,220 +1169,15 @@ bool cVideo::GetScreenImage(unsigned char * &out_data, int &xres, int &yres, boo bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) { - physicalAddress[0] = 0x10; - 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); - } + return hdmi_cec::getInstance()->SetCECMode(_deviceType); } void cVideo::SetCECAutoStandby(bool state) { - standby_cec_activ = state; + hdmi_cec::getInstance()->SetCECAutoStandby(state); } void cVideo::SetCECAutoView(bool state) { - autoview_cec_activ = 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); - } - + hdmi_cec::getInstance()->SetCECAutoView(state); } diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index adbb5fb..86bbd24 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -144,20 +144,6 @@ 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 cDemux; class cPlayback; @@ -201,11 +187,6 @@ class cVideo /* used internally by dmx */ int64_t GetPTS(void); - unsigned char physicalAddress[2]; - bool standby_cec_activ,autoview_cec_activ; - unsigned char deviceType, logicalAddress; - int hdmiFd; - public: /* constructor & destructor */ cVideo(int mode, void *, void *, unsigned int unit = 0); @@ -250,10 +231,6 @@ class cVideo 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(); void ShowPicture(const char * fname); void StopPicture(); void Standby(unsigned int bOn); From 43be595ff63325434b7866eb1da86870faedc24f Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 7 Oct 2018 18:43:31 +0200 Subject: [PATCH 07/14] libarmbox: fix hdmi_cec handling Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/06856841d55cc60a3fa9794c20d247aea1032643 Author: TangoCash Date: 2018-10-07 (Sun, 07 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index 5edf404..ddea9b6 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -60,9 +60,6 @@ hdmi_cec::hdmi_cec() { standby_cec_activ = autoview_cec_activ = false; hdmiFd = -1; - if (hdmiFd == -1) - hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC); - Start(); } hdmi_cec::~hdmi_cec() @@ -89,21 +86,18 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF) { - if (hdmiFd >= 0) - { - close(hdmiFd); - hdmiFd = -1; - Stop(); - } + Stop(); + lt_debug("CEC OFF %s\n", __func__); return false; } else deviceType = _deviceType; + lt_debug("CEC ON %s\n", __func__); + if (hdmiFd == -1) { - hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC); - Start(); + hdmiFd = open(CEC_DEVICE, O_RDWR | O_NONBLOCK); } if (hdmiFd >= 0) @@ -180,6 +174,7 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if(autoview_cec_activ) SetCECState(false); + Start(); return true; } @@ -441,12 +436,18 @@ bool hdmi_cec::Stop() running = false; + if (hdmiFd >= 0) + { + close(hdmiFd); + hdmiFd = -1; + } + return (OpenThreads::Thread::join() == 0); } void hdmi_cec::run() { - while (running) + while (running && (hdmiFd >= 0)) { Receive(); } From ca25b72ba61036d5b3cd0528a963c3a62918f27d Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 7 Oct 2018 22:21:38 +0200 Subject: [PATCH 08/14] libarmbox: hdmi_cec add some more output Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/73a8a5078657531c135de4657fc3134a758acc28 Author: TangoCash Date: 2018-10-07 (Sun, 07 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 26 +- libarmbox/hdmi_cec_types.h | 600 +++++++++++++++++++++++++++++++++++++ 2 files changed, 619 insertions(+), 7 deletions(-) create mode 100644 libarmbox/hdmi_cec_types.h diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index ddea9b6..a45597d 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -33,8 +33,12 @@ #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_VIDEO, this, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) #define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) @@ -250,9 +254,9 @@ void hdmi_cec::SendCECMessage(struct cec_message &txmessage) char str[txmessage.length*6]; for (int i = 0; i < txmessage.length; i++) { - sprintf(str+(i*6),"(0x%02X)", txmessage.data[i]); + sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]); } - lt_info("[CEC] send message %s\n",str); + lt_info("[CEC] send message '%s' (%s)\n", ToString((cec_opcode)txmessage.data[0]), str); struct cec_msg msg; cec_msg_init(&msg, logicalAddress, txmessage.address); memcpy(&msg.msg[1], txmessage.data, txmessage.length); @@ -474,21 +478,29 @@ void hdmi_cec::Receive() char str[rxmessage.length*6]; for (int i = 0; i < rxmessage.length; i++) { - sprintf(str+(i*6),"(0x%02X)", rxmessage.data[i]); + sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]); } - lt_info("[CEC] received message %s\n", str); + lt_info("[CEC] received message '%s' (%s)\n", ToString((cec_opcode)rxmessage.data[0]), str); switch (rxmessage.data[0]) { - case 0x44: /* key pressed */ + case CEC_MSG_DEVICE_VENDOR_ID: + { + uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) + + ((uint64_t)rxmessage.data[2] << 8) + + (uint64_t)rxmessage.data[3]; + lt_info("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.data[0]), ToString((cec_vendor_id)iVendorId)); + break; + } + case CEC_MSG_USER_CONTROL_PRESSED: /* key pressed */ keypressed = true; pressedkey = rxmessage.data[1]; - case 0x45: /* key released */ + case CEC_MSG_USER_CONTROL_RELEASED: /* key released */ { long code = translateKey(pressedkey); if (keypressed) code |= 0x80000000; - lt_info("[CEC] received key %ld\n",code); + lt_info("[CEC] decoded key %s (%ld)\n",ToString((cec_user_control_code)pressedkey), code); break; } } diff --git a/libarmbox/hdmi_cec_types.h b/libarmbox/hdmi_cec_types.h new file mode 100644 index 0000000..f5808af --- /dev/null +++ b/libarmbox/hdmi_cec_types.h @@ -0,0 +1,600 @@ +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; + +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"; + } +} From e0811c89bd1e9aa566e3c218af23e34517170272 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 7 Oct 2018 23:00:29 +0200 Subject: [PATCH 09/14] libarmbox: hdmi_cec better readability Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/2658572c2ad11b75e6e39d9ba6386c352a78c9ee Author: TangoCash Date: 2018-10-07 (Sun, 07 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 144 +++++++++++++++++++++-------------------- libarmbox/hdmi_cec.h | 20 ++++++ 2 files changed, 93 insertions(+), 71 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index a45597d..195887e 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include "linux-uapi-cec.h" #include "hdmi_cec.h" #include "hdmi_cec_types.h" @@ -309,113 +311,113 @@ long hdmi_cec::translateKey(unsigned char code) long key = 0; switch (code) { - case 0x32: - key = 0x8b; + case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: + key = KEY_MENU; break; - case 0x20: - key = 0x0b; + case CEC_USER_CONTROL_CODE_NUMBER0: + key = KEY_0; break; - case 0x21: - key = 0x02; + case CEC_USER_CONTROL_CODE_NUMBER1: + key = KEY_1; break; - case 0x22: - key = 0x03; + case CEC_USER_CONTROL_CODE_NUMBER2: + key = KEY_2; break; - case 0x23: - key = 0x04; + case CEC_USER_CONTROL_CODE_NUMBER3: + key = KEY_3; break; - case 0x24: - key = 0x05; + case CEC_USER_CONTROL_CODE_NUMBER4: + key = KEY_4; break; - case 0x25: - key = 0x06; + case CEC_USER_CONTROL_CODE_NUMBER5: + key = KEY_5; break; - case 0x26: - key = 0x07; + case CEC_USER_CONTROL_CODE_NUMBER6: + key = KEY_6; break; - case 0x27: - key = 0x08; + case CEC_USER_CONTROL_CODE_NUMBER7: + key = KEY_7; break; - case 0x28: - key = 0x09; + case CEC_USER_CONTROL_CODE_NUMBER8: + key = KEY_8; break; - case 0x29: - key = 0x0a; + case CEC_USER_CONTROL_CODE_NUMBER9: + key = KEY_9; break; - case 0x30: - key = 0x192; + case CEC_USER_CONTROL_CODE_CHANNEL_UP: + key = KEY_CHANNELUP; break; - case 0x31: - key = 0x193; + case CEC_USER_CONTROL_CODE_CHANNEL_DOWN: + key = KEY_CHANNELDOWN; break; - case 0x44: - key = 0xcf; + case CEC_USER_CONTROL_CODE_PLAY: + key = KEY_PLAY; break; - case 0x45: - key = 0x80; + case CEC_USER_CONTROL_CODE_STOP: + key = KEY_STOP; break; - case 0x46: - key = 0x77; + case CEC_USER_CONTROL_CODE_PAUSE: + key = KEY_PAUSE; break; - case 0x47: - key = 0xa7; + case CEC_USER_CONTROL_CODE_RECORD: + key = KEY_RECORD; break; - case 0x48: - key = 0xa8; + case CEC_USER_CONTROL_CODE_REWIND: + key = KEY_REWIND; break; - case 0x49: - key = 0xd0; + case CEC_USER_CONTROL_CODE_FAST_FORWARD: + key = KEY_FASTFORWARD; break; - case 0x53: - key = 0x166; + case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: + key = KEY_INFO; break; - case 0x54: - key = 0x16a; + case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: + key = KEY_PROGRAM; break; - case 0x60: - key = 0xcf; + case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: + key = KEY_PLAY; break; - case 0x61: - key = 0xa4; + case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: + key = KEY_PLAYPAUSE; break; - case 0x62: - key = 0xa7; + case CEC_USER_CONTROL_CODE_RECORD_FUNCTION: + key = KEY_RECORD; break; - case 0x64: - key = 0x80; + case CEC_USER_CONTROL_CODE_STOP_FUNCTION: + key = KEY_STOP; break; - case 0x00: - key = 0x160; + case CEC_USER_CONTROL_CODE_SELECT: + key = KEY_OK; break; - case 0x03: - key = 0x69; + case CEC_USER_CONTROL_CODE_LEFT: + key = KEY_LEFT; break; - case 0x04: - key = 0x6a; + case CEC_USER_CONTROL_CODE_RIGHT: + key = KEY_RIGHT; break; - case 0x01: - key = 0x67; + case CEC_USER_CONTROL_CODE_UP: + key = KEY_UP; break; - case 0x02: - key = 0x6c; + case CEC_USER_CONTROL_CODE_DOWN: + key = KEY_DOWN; break; - case 0x0d: - key = 0xae; + case CEC_USER_CONTROL_CODE_EXIT: + key = KEY_EXIT; break; - case 0x72: - key = 0x18e; + case CEC_USER_CONTROL_CODE_F2_RED: + key = KEY_RED; break; - case 0x71: - key = 0x191; + case CEC_USER_CONTROL_CODE_F3_GREEN: + key = KEY_GREEN; break; - case 0x73: - key = 0x18f; + case CEC_USER_CONTROL_CODE_F4_YELLOW: + key = KEY_YELLOW; break; - case 0x74: - key = 0x190; + case CEC_USER_CONTROL_CODE_F1_BLUE: + key = KEY_BLUE; break; default: - key = 0x8b; + key = KEY_MENU; break; } return key; diff --git a/libarmbox/hdmi_cec.h b/libarmbox/hdmi_cec.h index 0dc97cb..9654e73 100644 --- a/libarmbox/hdmi_cec.h +++ b/libarmbox/hdmi_cec.h @@ -22,6 +22,26 @@ #include "video_lib.h" +#ifndef KEY_OK +#define KEY_OK 0x160 +#endif + +#ifndef KEY_RED +#define KEY_RED 0x18e +#endif + +#ifndef KEY_GREEN +#define KEY_GREEN 0x18f +#endif + +#ifndef KEY_YELLOW +#define KEY_YELLOW 0x190 +#endif + +#ifndef KEY_BLUE +#define KEY_BLUE 0x191 +#endif + struct cec_message { unsigned char address; From 043eb80d33efae292a804bb00f161790bf4d3392 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Mon, 8 Oct 2018 16:23:15 +0200 Subject: [PATCH 10/14] libarmbox: hdmi_cec fixx segfault on DDT, align log Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/58089348e6435134a1bcbac2b5d2bf3a347f84bb Author: TangoCash Date: 2018-10-08 (Mon, 08 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index 195887e..ef279f3 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -62,6 +62,9 @@ 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 = false; @@ -80,7 +83,10 @@ hdmi_cec::~hdmi_cec() hdmi_cec* hdmi_cec::getInstance() { if (hdmi_cec_instance == NULL) + { hdmi_cec_instance = new hdmi_cec(); + lt_debug("[CEC] new instance created \n"); + } return hdmi_cec_instance; } @@ -93,13 +99,13 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF) { Stop(); - lt_debug("CEC OFF %s\n", __func__); + lt_debug("[CEC] switch off %s\n", __func__); return false; } else deviceType = _deviceType; - lt_debug("CEC ON %s\n", __func__); + lt_debug("[CEC] switch on %s\n", __func__); if (hdmiFd == -1) { @@ -112,14 +118,14 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) struct cec_caps caps = {}; if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0) - lt_info("%s: CEC get caps failed (%m)\n", __func__); + lt_info("[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_info("%s: CEC reset log addr failed (%m)\n", __func__); + lt_info("[CEC] %s: reset log addr failed (%m)\n", __func__); memset(&laddrs, 0, sizeof(laddrs)); @@ -169,11 +175,11 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) 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__); + lt_info("[CEC] %s: et log addr failed (%m)\n", __func__); } if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0) - lt_info("%s: CEC monitor failed (%m)\n", __func__); + lt_info("[CEC] %s: monitor failed (%m)\n", __func__); GetCECAddressInfo(); @@ -230,7 +236,7 @@ void hdmi_cec::GetCECAddressInfo() logicalAddress = addressinfo.logical; if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress))) { - lt_info("%s: detected physical address change: %02X%02X --> %02X%02X\n", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]); + 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(); } From f2314e1dddcb5112cc9e4d2ce815e8511fc4a437 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Mon, 8 Oct 2018 16:27:52 +0200 Subject: [PATCH 11/14] libarmbox: hdmi_cec typo Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/9bf2bce32e9e772047d7e6fc5df6080ffb7dbfe3 Author: TangoCash Date: 2018-10-08 (Mon, 08 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index ef279f3..cc4db35 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -85,7 +85,7 @@ hdmi_cec* hdmi_cec::getInstance() if (hdmi_cec_instance == NULL) { hdmi_cec_instance = new hdmi_cec(); - lt_debug("[CEC] new instance created \n"); + lt_debug_c("[CEC] new instance created \n"); } return hdmi_cec_instance; } From 16e732d1e4ffdd8eada1d82d6cd2c980c002c61e Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 9 Oct 2018 22:11:01 +0200 Subject: [PATCH 12/14] libarmbox: hmdi_cec emit received keys, report power status Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/fa700036193dd1e7b2766f50096a7cf5cecd80c1 Author: TangoCash Date: 2018-10-09 (Tue, 09 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 115 +++++++++++++++++++++++++++++++------ libarmbox/hdmi_cec.h | 36 +++++------- libarmbox/hdmi_cec_types.h | 68 ++++++++++++++++++++++ 3 files changed, 180 insertions(+), 39 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index cc4db35..a30e115 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -59,6 +59,7 @@ }) #define CEC_DEVICE "/dev/cec0" +#define RC_DEVICE "/dev/input/event1" hdmi_cec * hdmi_cec::hdmi_cec_instance = NULL; @@ -67,7 +68,7 @@ hdmi_cec * CEC = hdmi_cec::getInstance(); hdmi_cec::hdmi_cec() { - standby_cec_activ = autoview_cec_activ = false; + standby_cec_activ = autoview_cec_activ = standby = false; hdmiFd = -1; } @@ -246,7 +247,8 @@ void hdmi_cec::GetCECAddressInfo() void hdmi_cec::ReportPhysicalAddress() { struct cec_message txmessage; - txmessage.address = 0x0f; /* broadcast */ + 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]; @@ -264,9 +266,9 @@ void hdmi_cec::SendCECMessage(struct cec_message &txmessage) { sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]); } - lt_info("[CEC] send message '%s' (%s)\n", ToString((cec_opcode)txmessage.data[0]), str); + 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, logicalAddress, txmessage.address); + 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); @@ -287,9 +289,12 @@ void hdmi_cec::SetCECState(bool state) { struct cec_message message; + standby = state; + if ((standby_cec_activ) && state) { - message.address = CEC_OP_PRIM_DEVTYPE_TV; + message.initiator = logicalAddress; + message.destination = CEC_OP_PRIM_DEVTYPE_TV; message.data[0] = CEC_MSG_STANDBY; message.length = 1; SendCECMessage(message); @@ -297,12 +302,22 @@ void hdmi_cec::SetCECState(bool state) if ((autoview_cec_activ) && !state) { - message.address = CEC_OP_PRIM_DEVTYPE_TV; + 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.address = 0x0f; /* broadcast */ + + 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]; @@ -469,11 +484,15 @@ 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; } @@ -488,29 +507,91 @@ void hdmi_cec::Receive() { sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]); } - lt_info("[CEC] received message '%s' (%s)\n", ToString((cec_opcode)rxmessage.data[0]), str); + lt_info("[CEC] received message 0x%02X << 0x%02X '%s' (%s)\n", rxmessage.destination, rxmessage.initiator, ToString((cec_opcode)rxmessage.opcode), str); - switch (rxmessage.data[0]) + switch (rxmessage.opcode) { - case CEC_MSG_DEVICE_VENDOR_ID: + 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_info("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.data[0]), ToString((cec_vendor_id)iVendorId)); + ((uint64_t)rxmessage.data[2] << 8) + + (uint64_t)rxmessage.data[3]; + lt_info("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId)); break; } - case CEC_MSG_USER_CONTROL_PRESSED: /* key pressed */ + 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_MSG_USER_CONTROL_RELEASED: /* key released */ + case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */ { long code = translateKey(pressedkey); - if (keypressed) - code |= 0x80000000; lt_info("[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) + { + perror("opening " RC_DEVICE " failed"); + return; + } + if (keypressed) + { + if (rc_send(evd, code, KEY_PRESSED) < 0) + { + perror("writing 'KEY_PRESSED' event failed"); + close(evd); + return; + } + rc_sync(evd); + } + else + { + if (rc_send(evd, code, KEY_RELEASED) < 0) + { + perror("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)); +} diff --git a/libarmbox/hdmi_cec.h b/libarmbox/hdmi_cec.h index 9654e73..65604d7 100644 --- a/libarmbox/hdmi_cec.h +++ b/libarmbox/hdmi_cec.h @@ -22,31 +22,13 @@ #include "video_lib.h" -#ifndef KEY_OK -#define KEY_OK 0x160 -#endif - -#ifndef KEY_RED -#define KEY_RED 0x18e -#endif - -#ifndef KEY_GREEN -#define KEY_GREEN 0x18f -#endif - -#ifndef KEY_YELLOW -#define KEY_YELLOW 0x190 -#endif - -#ifndef KEY_BLUE -#define KEY_BLUE 0x191 -#endif - struct cec_message { - unsigned char address; - unsigned char length; + unsigned char initiator; + unsigned char destination; + unsigned char opcode; unsigned char data[256]; + unsigned char length; } __attribute__((packed)); struct addressinfo @@ -56,6 +38,12 @@ struct addressinfo unsigned char type; }; +enum { + KEY_RELEASED = 0, + KEY_PRESSED, + KEY_AUTOREPEAT +}; + class hdmi_cec : public OpenThreads::Thread { private: @@ -70,6 +58,10 @@ private: 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: diff --git a/libarmbox/hdmi_cec_types.h b/libarmbox/hdmi_cec_types.h index f5808af..beb3e4f 100644 --- a/libarmbox/hdmi_cec_types.h +++ b/libarmbox/hdmi_cec_types.h @@ -207,6 +207,37 @@ typedef enum cec_opcode 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) @@ -598,3 +629,40 @@ static const char *ToString(const cec_user_control_code key) 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; +} From 4eff4a571352803e2b19799daed5115a088802d8 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 9 Oct 2018 23:10:21 +0200 Subject: [PATCH 13/14] libarmbox: hdmi_cec fix device Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/95f96c8c354549a1918311db508feba83c884fcd Author: TangoCash Date: 2018-10-09 (Tue, 09 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index a30e115..5d45bc9 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,7 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if (hdmiFd == -1) { - hdmiFd = open(CEC_DEVICE, O_RDWR | O_NONBLOCK); + hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC); } if (hdmiFd >= 0) @@ -462,6 +463,8 @@ bool hdmi_cec::Stop() return false; running = false; + + OpenThreads::Thread::cancel(); if (hdmiFd >= 0) { @@ -474,9 +477,16 @@ bool hdmi_cec::Stop() void hdmi_cec::run() { - while (running && (hdmiFd >= 0)) + OpenThreads::Thread::setCancelModeAsynchronous(); + struct pollfd pfd; + + pfd.fd = hdmiFd; + pfd.events = (POLLIN | POLLPRI); + + while (running) { - Receive(); + if (poll(&pfd, 1, 0) > 0) + Receive(); } } From 2cc58e098191d8eb480d708a3ad72797fee34ac3 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 10 Oct 2018 23:45:51 +0200 Subject: [PATCH 14/14] libarmbox: hdmi_cec switch debug log to INIT (not used by armbox elsewhere), to debug hdmi_cec separatly from video Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/cf5d5d373f6436190552df1291c32b98a54803e5 Author: TangoCash Date: 2018-10-10 (Wed, 10 Oct 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/hdmi_cec.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libarmbox/hdmi_cec.cpp b/libarmbox/hdmi_cec.cpp index 5d45bc9..0eed4ab 100644 --- a/libarmbox/hdmi_cec.cpp +++ b/libarmbox/hdmi_cec.cpp @@ -42,10 +42,10 @@ #define RED "\x1B[31m" #define NORMAL "\x1B[0m" -#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) -#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) -#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) -#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args) +#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; \ @@ -120,14 +120,14 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) struct cec_caps caps = {}; if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0) - lt_info("[CEC] %s: get caps failed (%m)\n", __func__); + 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_info("[CEC] %s: reset log addr failed (%m)\n", __func__); + lt_debug("[CEC] %s: reset log addr failed (%m)\n", __func__); memset(&laddrs, 0, sizeof(laddrs)); @@ -177,11 +177,11 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) laddrs.num_log_addrs++; if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0) - lt_info("[CEC] %s: et log addr failed (%m)\n", __func__); + lt_debug("[CEC] %s: et log addr failed (%m)\n", __func__); } if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0) - lt_info("[CEC] %s: monitor failed (%m)\n", __func__); + lt_debug("[CEC] %s: monitor failed (%m)\n", __func__); GetCECAddressInfo(); @@ -527,7 +527,7 @@ void hdmi_cec::Receive() uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) + ((uint64_t)rxmessage.data[2] << 8) + (uint64_t)rxmessage.data[3]; - lt_info("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId)); + 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: @@ -546,7 +546,7 @@ void hdmi_cec::Receive() case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */ { long code = translateKey(pressedkey); - lt_info("[CEC] decoded key %s (%ld)\n",ToString((cec_user_control_code)pressedkey), code); + lt_debug("[CEC] decoded key %s (%ld)\n",ToString((cec_user_control_code)pressedkey), code); handleCode(code,keypressed); break; } @@ -559,14 +559,14 @@ void hdmi_cec::handleCode(long code, bool keypressed) int evd = open(RC_DEVICE, O_RDWR); if (evd < 0) { - perror("opening " RC_DEVICE " failed"); + lt_debug("[CEC] opening " RC_DEVICE " failed"); return; } if (keypressed) { if (rc_send(evd, code, KEY_PRESSED) < 0) { - perror("writing 'KEY_PRESSED' event failed"); + lt_debug("[CEC] writing 'KEY_PRESSED' event failed"); close(evd); return; } @@ -576,7 +576,7 @@ void hdmi_cec::handleCode(long code, bool keypressed) { if (rc_send(evd, code, KEY_RELEASED) < 0) { - perror("writing 'KEY_RELEASED' event failed"); + lt_debug("[CEC] writing 'KEY_RELEASED' event failed"); close(evd); return; }