Files
LibreELEC.tv/projects/imx6/patches/libcec/4.4-xbian/libcec-100-from-xbian.patch

1767 lines
63 KiB
Diff

From 714ce8ee2ba07fe88249b8033d875f58ed21a4ab Mon Sep 17 00:00:00 2001
From: Peter Vicman <peter.vicman@gmail.com>
Date: Thu, 12 Jan 2017 09:36:24 +0100
Subject: [PATCH] patch for libcec from xbian
libcec base: libcec-2fc92b5
libcec xbian:
https://github.com/xbianonpi/xbian-sources-libcec/tree/masterv4 e12f92586ccda4fe20814c93d5830ed3a33f3a4e
---
CMakeLists.txt | 6 +
debian/control | 7 +-
debian/libcec4-dev.install | 1 +
debian/libcec4.install | 2 +
include/cec.h | 2 +
include/cectypes.h | 47 ++-
src/cec-client/CMakeLists.txt | 4 +-
src/cecc-client/cecc-client.c | 2 +-
src/libcec/CECClient.cpp | 12 +-
src/libcec/CECClient.h | 1 +
src/libcec/CECProcessor.cpp | 6 +
src/libcec/CECProcessor.h | 1 +
src/libcec/CECTypeUtils.h | 2 +
src/libcec/CMakeLists.txt | 22 +-
src/libcec/LibCEC.cpp | 5 +
src/libcec/LibCEC.h | 1 +
src/libcec/adapter/AdapterFactory.cpp | 27 +-
.../adapter/IMX/IMXCECAdapterCommunication.cpp | 381 +++++++++++++++++++++
.../adapter/IMX/IMXCECAdapterCommunication.h | 139 ++++++++
src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp | 42 +++
src/libcec/adapter/IMX/IMXCECAdapterDetection.h | 36 ++
src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h | 118 +++++++
src/libcec/adapter/IMX/mxc_hdmi-cec.h | 47 +++
src/libcec/cmake/CheckPlatformSupport.cmake | 49 ++-
src/libcec/cmake/DisplayPlatformSupport.cmake | 10 +-
src/libcec/cmake/LinkPlatformSupport.cmake | 7 +-
src/libcec/cmake/git-rev.sh | 2 +-
src/libcec/devices/CECBusDevice.cpp | 11 +-
src/libcec/devices/CECBusDevice.h | 2 +
src/libcec/env.h.in | 3 +
src/libcec/implementations/CECCommandHandler.cpp | 16 +-
src/libcec/implementations/CECCommandHandler.h | 7 +-
src/libcec/implementations/GRCommandHandler.cpp | 92 +++++
src/libcec/implementations/GRCommandHandler.h | 53 +++
34 files changed, 1102 insertions(+), 61 deletions(-)
create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp
create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.h
create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp
create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.h
create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h
create mode 100644 src/libcec/adapter/IMX/mxc_hdmi-cec.h
create mode 100644 src/libcec/implementations/GRCommandHandler.cpp
create mode 100644 src/libcec/implementations/GRCommandHandler.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4f01662..7c19dd5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,6 +5,12 @@ set(LIBCEC_VERSION_MAJOR 4)
set(LIBCEC_VERSION_MINOR 0)
set(LIBCEC_VERSION_PATCH 1)
+find_program(CCACHE_FOUND ccache)
+if(CCACHE_FOUND)
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
+endif(CCACHE_FOUND)
+
# cec-client
add_subdirectory(src/cec-client)
add_dependencies(cec-client cec)
diff --git a/debian/control b/debian/control
index e05a063..1675c1b 100644
--- a/debian/control
+++ b/debian/control
@@ -20,6 +20,7 @@ Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/libcec.git
Package: libcec4-dev
Architecture: any
Section: libdevel
+Replaces: libcec-dev
Depends: libcec4 (= ${binary:Version}),
${misc:Depends}
Description: libCEC communication Library (development files)
@@ -30,6 +31,7 @@ Description: libCEC communication Library (development files)
Package: libcec4
Architecture: any
Multi-Arch: same
+Replaces: libcec3
Pre-Depends: ${misc:Pre-Depends}
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: libCEC communication Library (shared library)
@@ -40,6 +42,7 @@ Description: libCEC communication Library (shared library)
Package: cec-utils
Architecture: any
Section: utils
+Replaces: xbian-package-cec
Depends: libcec4 (= ${binary:Version}),
${shlibs:Depends},
${misc:Depends}
@@ -60,6 +63,8 @@ Description: Python bindings for libCEC
Package: libcec
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libcec4 (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, libcec4 (= ${binary:Version}), python-libcec, cec-utils, libcec4-dev
+Provides: xbian-package-cec
+Breaks: xbian-package-cec (<<10.0)
Description: Meta package libCEC.
diff --git a/debian/libcec4-dev.install b/debian/libcec4-dev.install
index e5bbd96..15a3585 100644
--- a/debian/libcec4-dev.install
+++ b/debian/libcec4-dev.install
@@ -1,3 +1,4 @@
usr/include
usr/lib/pkgconfig
usr/lib/*/*.so
+usr/lib/p8-platform
diff --git a/debian/libcec4.install b/debian/libcec4.install
index ca5ebe3..ac5e50a 100644
--- a/debian/libcec4.install
+++ b/debian/libcec4.install
@@ -1 +1,3 @@
usr/lib/*/libcec.so.*
+usr/lib/libp*.a
+
diff --git a/include/cec.h b/include/cec.h
index 71450ae..b4a7d78 100644
--- a/include/cec.h
+++ b/include/cec.h
@@ -389,6 +389,8 @@ namespace CEC
*/
virtual uint16_t GetAdapterProductId(void) const = 0;
+ virtual bool TransmitSystemAudioModeRequest(void) = 0;
+
virtual const char* ToString(const cec_menu_state state) = 0;
virtual const char* ToString(const cec_version version) = 0;
virtual const char* ToString(const cec_power_status status) = 0;
diff --git a/include/cectypes.h b/include/cectypes.h
index 9c91842..9fa69fc 100644
--- a/include/cectypes.h
+++ b/include/cectypes.h
@@ -267,9 +267,19 @@ namespace CEC {
#define CEC_TDA995x_VIRTUAL_COM "CuBox"
/*!
+ * the path to use for the i.MX CEC wire
+ */
+#define CEC_IMX_PATH "/dev/mxc_hdmi_cec"
+
+/*!
+ * the name of the virtual COM port to use for the i.MX CEC wire
+ */
+#define CEC_IMX_VIRTUAL_COM "i.MX"
+
+/*!
* the path to use for the Exynos HDMI CEC device
*/
-#define CEC_EXYNOS_PATH "/dev/CEC"
+#define CEC_EXYNOS_PATH "/dev/CEC"
/*!
* the name of the virtual COM port to use for the EXYNOS' CEC wire
@@ -296,6 +306,8 @@ namespace CEC {
*/
#define CEC_MIN_LIB_VERSION 4
+#define CEC_LIB_VERSION_MAJOR 4
+
#define MSGSTART 0xFF
#define MSGEND 0xFE
#define MSGESC 0xFD
@@ -861,6 +873,7 @@ typedef enum cec_adapter_type
ADAPTERTYPE_RPI = 0x100,
ADAPTERTYPE_TDA995x = 0x200,
ADAPTERTYPE_EXYNOS = 0x300,
+ ADAPTERTYPE_IMX = 0x400,
ADAPTERTYPE_AOCEC = 0x500
} cec_adapter_type;
@@ -1245,7 +1258,7 @@ typedef struct cec_device_type_list
typedef struct cec_logical_addresses
{
cec_logical_address primary; /**< the primary logical address to use */
- int addresses[16]; /**< the list of addresses */
+ uint16_t addresses; /**< the list of addresses */
#ifdef __cplusplus
/*!
@@ -1254,8 +1267,7 @@ typedef struct cec_logical_addresses
void Clear(void)
{
primary = CECDEVICE_UNREGISTERED;
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
- addresses[iPtr] = 0;
+ addresses = 0;
}
/*!
@@ -1263,7 +1275,7 @@ typedef struct cec_logical_addresses
*/
bool IsEmpty(void) const
{
- return primary == CECDEVICE_UNREGISTERED;
+ return primary == CECDEVICE_UNREGISTERED && addresses == 0;
}
/*!
@@ -1272,11 +1284,7 @@ typedef struct cec_logical_addresses
*/
uint16_t AckMask(void) const
{
- uint16_t mask = 0;
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
- if (addresses[iPtr] == 1)
- mask |= 0x1 << iPtr;
- return mask;
+ return addresses;
}
/*!
@@ -1288,7 +1296,7 @@ typedef struct cec_logical_addresses
if (primary == CECDEVICE_UNREGISTERED)
primary = address;
- addresses[(int) address] = 1;
+ addresses |= (1 << (int) address);
}
/*!
@@ -1300,7 +1308,7 @@ typedef struct cec_logical_addresses
if (primary == address)
primary = CECDEVICE_UNREGISTERED;
- addresses[(int) address] = 0;
+ addresses &= ~(uint16_t)(1 << (int) address);
}
/*!
@@ -1308,7 +1316,7 @@ typedef struct cec_logical_addresses
* @param address The address to check.
* @return True when set, false otherwise.
*/
- bool IsSet(cec_logical_address address) const { return addresses[(int) address] == 1; }
+ bool IsSet(cec_logical_address address) const { return (addresses & (1 << (int) address)); }
/*!
* @brief Check whether an address is set in this list.
@@ -1317,18 +1325,9 @@ typedef struct cec_logical_addresses
*/
bool operator[](uint8_t pos) const { return pos < 16 ? IsSet((cec_logical_address) pos) : false; }
- bool operator==(const cec_logical_addresses &other) const
- {
- bool bEqual(true);
- for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
- bEqual &= ((addresses[(int)iPtr] == 1) == other[iPtr]);
- return bEqual;
- }
+ bool operator==(const cec_logical_addresses &other) const { return addresses == other.addresses; }
- bool operator!=(const cec_logical_addresses &other) const
- {
- return !(*this == other);
- }
+ bool operator!=(const cec_logical_addresses &other) const { return !(*this == other); }
#endif
} cec_logical_addresses;
diff --git a/src/cec-client/CMakeLists.txt b/src/cec-client/CMakeLists.txt
index 2cb42bb..c708fdb 100644
--- a/src/cec-client/CMakeLists.txt
+++ b/src/cec-client/CMakeLists.txt
@@ -13,9 +13,9 @@ include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckCXXCompilerFlag)
-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11)
+check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11)
if (SUPPORTS_CXX11)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif()
find_package(p8-platform REQUIRED)
diff --git a/src/cecc-client/cecc-client.c b/src/cecc-client/cecc-client.c
index 3373109..914d4d4 100644
--- a/src/cecc-client/cecc-client.c
+++ b/src/cecc-client/cecc-client.c
@@ -337,7 +337,7 @@ static int cec_process_command_scan(const char* data)
activeSource = g_iface.get_active_source(g_iface.connection);
for (iPtr = 0; iPtr < 16; iPtr++)
{
- if (addresses.addresses[iPtr])
+ if (addresses.addresses & (1 << iPtr))
{
cec_menu_language lang;
cec_osd_name osdName;
diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp
index b777faa..9f6e7c5 100644
--- a/src/libcec/CECClient.cpp
+++ b/src/libcec/CECClient.cpp
@@ -139,10 +139,6 @@ bool CCECClient::OnRegister(void)
// set the physical address
SetPhysicalAddress(m_configuration);
- // make the primary device the active source if the option is set
- if (m_configuration.bActivateSource == 1)
- GetPrimaryDevice()->ActivateSource(500);
-
return true;
}
@@ -350,12 +346,13 @@ bool CCECClient::AllocateLogicalAddresses(void)
if (address == CECDEVICE_UNKNOWN)
{
LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - failed to allocate device '%d', type '%s'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr]));
- return false;
+ continue;
}
// display the registered LA
LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - device '%d', type '%s', LA '%X'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr]), address);
m_configuration.logicalAddresses.Set(address);
+ break;
}
// persist the new configuration
@@ -1540,6 +1537,11 @@ bool CCECClient::IsLibCECActiveSource(void)
return bReturn;
}
+bool CCECClient::TransmitSystemAudioModeRequest(void)
+{
+ return m_processor ? m_processor->TransmitSystemAudioModeRequest(m_configuration.logicalAddresses.primary) : false;
+}
+
void CCECClient::SourceActivated(const cec_logical_address logicalAddress)
{
LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress);
diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h
index 49528ee..f02775c 100644
--- a/src/libcec/CECClient.h
+++ b/src/libcec/CECClient.h
@@ -298,6 +298,7 @@ namespace CEC
virtual void RescanActiveDevices(void);
virtual bool IsLibCECActiveSource(void);
bool AudioEnable(bool enable);
+ virtual bool TransmitSystemAudioModeRequest(void);
// configuration
virtual bool GetCurrentConfiguration(libcec_configuration &configuration);
diff --git a/src/libcec/CECProcessor.cpp b/src/libcec/CECProcessor.cpp
index 8ce46c5..e31e24a 100644
--- a/src/libcec/CECProcessor.cpp
+++ b/src/libcec/CECProcessor.cpp
@@ -712,6 +712,12 @@ bool CCECProcessor::TransmitPendingActiveSourceCommands(void)
return bReturn;
}
+bool CCECProcessor::TransmitSystemAudioModeRequest(cec_logical_address initiator)
+{
+ CCECBusDevice *device = m_busDevices->At(initiator);
+ return device && device->TransmitSystemAudioModeRequest(initiator);
+}
+
CCECTV *CCECProcessor::GetTV(void) const
{
return CCECBusDevice::AsTV(m_busDevices->At(CECDEVICE_TV));
diff --git a/src/libcec/CECProcessor.h b/src/libcec/CECProcessor.h
index 08917b9..1971dee 100644
--- a/src/libcec/CECProcessor.h
+++ b/src/libcec/CECProcessor.h
@@ -149,6 +149,7 @@ namespace CEC
bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT);
bool TransmitPendingActiveSourceCommands(void);
+ bool TransmitSystemAudioModeRequest(cec_logical_address initiator);
CCECDeviceMap *GetDevices(void) const { return m_busDevices; }
CLibCEC *GetLib(void) const { return m_libcec; }
diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h
index 0d0cf17..f6c818a 100644
--- a/src/libcec/CECTypeUtils.h
+++ b/src/libcec/CECTypeUtils.h
@@ -766,6 +766,8 @@ namespace CEC
return "Raspberry Pi";
case ADAPTERTYPE_TDA995x:
return "TDA995x";
+ case ADAPTERTYPE_IMX:
+ return "i.MX";
default:
return "unknown";
}
diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt
index d3eefa3..6a33abf 100644
--- a/src/libcec/CMakeLists.txt
+++ b/src/libcec/CMakeLists.txt
@@ -13,9 +13,9 @@ include(CheckIncludeFiles)
include(CheckCXXCompilerFlag)
include(../../cmake/UseMultiArch.cmake)
-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11)
+check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11)
if (SUPPORTS_CXX11)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif()
find_package(p8-platform REQUIRED)
@@ -64,7 +64,8 @@ set(CEC_SOURCES_IMPLEMENTATIONS implementations/ANCommandHandler.cpp
implementations/RLCommandHandler.cpp
implementations/PHCommandHandler.cpp
implementations/RHCommandHandler.cpp
- implementations/AQCommandHandler.cpp)
+ implementations/AQCommandHandler.cpp
+ implementations/GRCommandHandler.cpp)
# /platform/*
set(CEC_SOURCES_PLATFORM platform/adl/adl-edid.cpp
@@ -124,6 +125,7 @@ set(CEC_HEADERS devices/CECRecordingDevice.h
implementations/RHCommandHandler.h
implementations/PHCommandHandler.h
implementations/AQCommandHandler.h
+ implementations/GRCommandHandler.h
CECProcessor.h)
source_group("Header Files" FILES ${CEC_HEADERS})
@@ -176,13 +178,17 @@ install(FILES ${PROJECT_SOURCE_DIR}/../../include/cec.h
DESTINATION include/libcec)
# libCEC target
-add_library(cec SHARED ${CEC_SOURCES})
-install(TARGETS cec
+add_library(cecobj OBJECT ${CEC_SOURCES})
+set_property(TARGET ${cecobj} PROPERTY POSITION_INDEPENDENT_CODE 1)
+add_library(cec SHARED $<TARGET_OBJECTS:cecobj>)
+add_library(cecstatic STATIC $<TARGET_OBJECTS:cecobj>)
+set_target_properties(cecstatic PROPERTIES OUTPUT_NAME cec)
+install(TARGETS cec cecstatic
DESTINATION ${LIB_DESTINATION})
-set_target_properties(cec PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH}
+set_target_properties(cec cecstatic PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH}
SOVERSION ${LIBCEC_VERSION_MAJOR})
-target_link_libraries(cec ${p8-platform_LIBRARIES})
-target_link_libraries(cec ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(cec cecstatic ${p8-platform_LIBRARIES})
+target_link_libraries(cec cecstatic ${CMAKE_THREAD_LIBS_INIT})
include(cmake/LinkPlatformSupport.cmake)
include(cmake/DisplayPlatformSupport.cmake)
diff --git a/src/libcec/LibCEC.cpp b/src/libcec/LibCEC.cpp
index 8eedaa7..9562e06 100644
--- a/src/libcec/LibCEC.cpp
+++ b/src/libcec/LibCEC.cpp
@@ -624,3 +624,8 @@ bool CLibCEC::AudioEnable(bool enable)
m_client->AudioEnable(enable) :
false;
}
+
+bool CLibCEC::TransmitSystemAudioModeRequest(void)
+{
+ return m_client ? m_client->TransmitSystemAudioModeRequest() : false;
+}
diff --git a/src/libcec/LibCEC.h b/src/libcec/LibCEC.h
index 7155926..b9e393b 100644
--- a/src/libcec/LibCEC.h
+++ b/src/libcec/LibCEC.h
@@ -109,6 +109,7 @@ namespace CEC
bool PersistConfiguration(libcec_configuration *configuration);
void RescanActiveDevices(void);
bool IsLibCECActiveSource(void);
+ bool TransmitSystemAudioModeRequest(void);
const char* ToString(const cec_menu_state state) { return CCECTypeUtils::ToString(state); }
const char* ToString(const cec_version version) { return CCECTypeUtils::ToString(version); }
diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp
index 91195ea..e2460ad 100644
--- a/src/libcec/adapter/AdapterFactory.cpp
+++ b/src/libcec/adapter/AdapterFactory.cpp
@@ -63,6 +63,11 @@
#include "AOCEC/AOCECAdapterCommunication.h"
#endif
+#if defined(HAVE_IMX_API)
+#include "IMX/IMXCECAdapterDetection.h"
+#include "IMX/IMXCECAdapterCommunication.h"
+#endif
+
using namespace CEC;
int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
@@ -143,8 +148,21 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8
}
#endif
+#if defined(HAVE_IMX_API)
+ if (iAdaptersFound < iBufSize && CIMXCECAdapterDetection::FindAdapter() &&
+ (!strDevicePath || !strcmp(strDevicePath, CEC_IMX_VIRTUAL_COM)))
+ {
+ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_IMX_PATH);
+ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_IMX_VIRTUAL_COM);
+ deviceList[iAdaptersFound].iVendorId = IMX_ADAPTER_VID;
+ deviceList[iAdaptersFound].iProductId = IMX_ADAPTER_PID;
+ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_IMX;
+ iAdaptersFound++;
+ }
+#endif
+
-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API)
+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) && !defined(HAVE_IMX_API)
#error "libCEC doesn't have support for any type of adapter. please check your build system or configuration"
#endif
@@ -173,11 +191,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_
return new CRPiCECAdapterCommunication(m_lib->m_cec);
#endif
+#if defined(HAVE_IMX_API)
+ if (!strcmp(strPort, CEC_IMX_VIRTUAL_COM))
+ return new CIMXCECAdapterCommunication(m_lib->m_cec);
+#endif
+
#if defined(HAVE_P8_USB)
return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate);
#endif
-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_AOCEC_API)
+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_AOCEC_API) && !defined(HAVE_IMX_API)
return NULL;
#endif
}
diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp
new file mode 100644
index 0000000..212dd75
--- /dev/null
+++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp
@@ -0,0 +1,381 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin
+ * Copyright (C) 2014 by Matus Kral
+ *
+ * You can redistribute this file and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#include "env.h"
+
+#if defined(HAVE_IMX_API)
+#include "IMXCECAdapterCommunication.h"
+
+#include "CECTypeUtils.h"
+#include "LibCEC.h"
+#include <p8-platform/sockets/cdevsocket.h>
+#include <p8-platform/util/StdString.h>
+#include <p8-platform/util/util.h>
+
+using namespace std;
+using namespace CEC;
+using namespace P8PLATFORM;
+
+#include "IMXCECAdapterMessageQueue.h"
+
+#define LIB_CEC m_callback->GetLib()
+
+// these are defined in nxp private header file
+#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/
+#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/
+#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/
+#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/
+#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/
+#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/
+#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/
+#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/
+
+CIMXCECAdapterCommunication::CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback) :
+ IAdapterCommunication(callback),
+ m_PAReporter(NULL)
+{
+ CLockObject lock(m_mutex);
+
+ m_iNextMessage = 0;
+ m_logicalAddress = CECDEVICE_UNKNOWN;
+ m_bLogicalAddressRegistered = false;
+ m_bInitialised = false;
+ m_dev = new CCDevSocket(CEC_IMX_PATH);
+ m_physicalAddress = -1;
+}
+
+CIMXCECAdapterCommunication::~CIMXCECAdapterCommunication(void)
+{
+ Close();
+ SAFE_DELETE(m_PAReporter);
+ delete m_dev;
+ m_dev = 0;
+}
+
+bool CIMXCECAdapterCommunication::IsOpen(void)
+{
+ return IsInitialised() && m_dev->IsOpen();
+}
+
+bool CIMXCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening)
+{
+ if (m_dev->Open(iTimeoutMs))
+ {
+ if (!bStartListening || CreateThread()) {
+ if (m_dev->Ioctl(HDMICEC_IOC_STARTDEVICE, NULL) == 0) {
+ m_bInitialised = true;
+ RegisterLogicalAddress(CECDEVICE_BROADCAST);
+ return true;
+ }
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to start device\n", __func__);
+ }
+ m_dev->Close();
+ }
+
+ return false;
+}
+
+
+void CIMXCECAdapterCommunication::Close(void)
+{
+ m_bInitialised = false;
+ if (m_dev->Ioctl(HDMICEC_IOC_STOPDEVICE, NULL) != 0)
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to stop device\n", __func__);
+ }
+ StopThread(false);
+ m_dev->Close();
+}
+
+
+std::string CIMXCECAdapterCommunication::GetError(void) const
+{
+ std::string strError(m_strError);
+ return strError;
+}
+
+
+cec_adapter_message_state CIMXCECAdapterCommunication::Write(
+ const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool UNUSED(bIsReply))
+{
+ unsigned char message[MAX_MESSAGE_LEN];
+ CIMXCECAdapterMessageQueueEntry *entry;
+ int msg_len = 1;
+ cec_adapter_message_state rc = ADAPTER_MESSAGE_STATE_ERROR;
+
+ bRetry = true;
+ if ((size_t)data.parameters.size + data.opcode_set + 1 > sizeof(message))
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: data size too large !", __func__);
+ bRetry = false;
+ return rc;
+ }
+
+ message[0] = (data.initiator << 4) | (data.destination & 0x0f);
+ if (data.opcode_set)
+ {
+ message[1] = data.opcode;
+ msg_len++;
+ memcpy(&message[2], data.parameters.data, data.parameters.size);
+ msg_len+=data.parameters.size;
+ }
+
+ entry = new CIMXCECAdapterMessageQueueEntry(message[0], data.opcode);
+ m_messageMutex.Lock();
+ uint32_t msgKey = ++m_iNextMessage;
+ m_messages.insert(make_pair(msgKey, entry));
+ m_messageMutex.Unlock();
+
+ if (m_dev->Write(message, msg_len) > 0)
+ {
+ if (entry->Wait(data.transmit_timeout ? data.transmit_timeout : iLineTimeout *1000))
+ {
+ int status = entry->Result();
+
+ if (status == MESSAGE_TYPE_NOACK)
+ rc = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
+ else if (status == MESSAGE_TYPE_SEND_SUCCESS)
+ rc = ADAPTER_MESSAGE_STATE_SENT_ACKED;
+
+ bRetry = false;
+ }
+ else
+ {
+ rc = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: command timed out !", __func__);
+#endif
+ }
+ }
+ else
+ {
+ Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: write failed !", __func__);
+#endif
+ }
+
+ m_messageMutex.Lock();
+ m_messages.erase(msgKey);
+ m_messageMutex.Unlock();
+
+ delete entry;
+
+ return rc;
+}
+
+
+uint16_t CIMXCECAdapterCommunication::GetFirmwareVersion(void)
+{
+ /* FIXME add ioctl ? */
+ return 0;
+}
+
+
+cec_vendor_id CIMXCECAdapterCommunication::GetVendorId(void)
+{
+ return CEC_VENDOR_UNKNOWN;
+}
+
+
+uint16_t CIMXCECAdapterCommunication::GetPhysicalAddress(void)
+{
+ uint8_t phy_addr[4];
+ uint16_t pa_tmp;
+
+ if (m_dev->Ioctl(HDMICEC_IOC_GETPHYADDRESS, &phy_addr) != 0)
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_GETPHYADDRESS failed !", __func__);
+ return CEC_INVALID_PHYSICAL_ADDRESS;
+ }
+
+ if ((pa_tmp = ((phy_addr[0] << 4 | phy_addr[1]) << 8) | (phy_addr[2] << 4 | phy_addr[3])))
+ m_physicalAddress = pa_tmp;
+
+ return m_physicalAddress;
+}
+
+
+cec_logical_addresses CIMXCECAdapterCommunication::GetLogicalAddresses(void)
+{
+ cec_logical_addresses addresses;
+ addresses.Clear();
+
+ CLockObject lock(m_mutex);
+ if (m_bLogicalAddressRegistered)
+ addresses.Set(m_logicalAddress);
+
+ return addresses;
+}
+
+void CIMXCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress))
+{
+ UnregisterLogicalAddress();
+}
+
+bool CIMXCECAdapterCommunication::UnregisterLogicalAddress(void)
+{
+ {
+ CLockObject lock(m_mutex);
+ if (!m_bLogicalAddressRegistered)
+ return true;
+ }
+
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - releasing previous logical address", __func__);
+#endif
+ return RegisterLogicalAddress(CECDEVICE_BROADCAST);
+}
+
+bool CIMXCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address)
+{
+ {
+ CLockObject lock(m_mutex);
+ if ((m_logicalAddress == address && m_bLogicalAddressRegistered) ||
+ (m_logicalAddress == address && address == CECDEVICE_BROADCAST))
+ {
+ return true;
+ }
+ }
+
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: %x to %x", __func__, m_logicalAddress, address);
+#endif
+
+ if (m_dev->Ioctl(HDMICEC_IOC_SETLOGICALADDRESS, (void *)address) != 0)
+ {
+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_SETLOGICALADDRESS failed !", __func__);
+ return false;
+ }
+
+ CLockObject lock(m_mutex);
+
+ m_logicalAddress = address;
+ m_bLogicalAddressRegistered = (address != CECDEVICE_BROADCAST) ? true : false;
+ return true;
+}
+
+bool CIMXCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses)
+{
+ int log_addr = addresses.primary;
+
+ return RegisterLogicalAddress((cec_logical_address)log_addr);
+}
+
+
+void *CIMXCECAdapterCommunication::Process(void)
+{
+ bool bHandled;
+ hdmi_cec_event event;
+ int ret;
+
+ cec_logical_address initiator, destination;
+
+ while (!IsStopped())
+ {
+ if (IsInitialised() && (ret = m_dev->Read((char *)&event, sizeof(event), 0)) > 0)
+ {
+
+ initiator = cec_logical_address(event.msg[0] >> 4);
+ destination = cec_logical_address(event.msg[0] & 0x0f);
+
+ if (event.event_type == MESSAGE_TYPE_RECEIVE_SUCCESS)
+ {
+ cec_command cmd;
+
+ cec_command::Format(
+ cmd, initiator, destination,
+ ( event.msg_len > 1 ) ? cec_opcode(event.msg[1]) : CEC_OPCODE_NONE);
+
+ for( uint8_t i = 2; i < event.msg_len; i++ )
+ cmd.parameters.PushBack(event.msg[i]);
+
+ if (!IsStopped()) {
+ m_callback->OnCommandReceived(cmd);
+ }
+ }
+ else if (event.event_type == MESSAGE_TYPE_SEND_SUCCESS
+ || event.event_type == MESSAGE_TYPE_NOACK)
+ {
+ bHandled = false;
+
+ m_messageMutex.Lock();
+ for (map<uint32_t, CIMXCECAdapterMessageQueueEntry *>::iterator it = m_messages.begin();
+ !bHandled && it != m_messages.end(); it++)
+ {
+ bHandled = it->second->Received(event.event_type, event.msg[0], (cec_opcode)event.msg[1]);
+ }
+ m_messageMutex.Unlock();
+
+ if (!bHandled)
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: response not matched !", __func__);
+ }
+ else if (event.event_type == MESSAGE_TYPE_DISCONNECTED)
+ {
+ /* HDMI Hotplug event - disconnect */
+ }
+ else if (event.event_type == MESSAGE_TYPE_CONNECTED)
+ {
+ if (m_physicalAddress == 0xffff)
+ continue;
+ /* HDMI Hotplug event - connect */
+ uint16_t oldAddress = m_physicalAddress;
+
+ if (oldAddress != GetPhysicalAddress()) {
+ if (m_PAReporter)
+ while (m_PAReporter->IsRunning()) Sleep(5);
+ delete m_PAReporter;
+
+ m_PAReporter = new CCECPAChangedReporter(m_callback, m_physicalAddress);
+ m_PAReporter->CreateThread(false);
+ }
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: plugin event received", __func__);
+#endif
+ }
+ else
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: unhandled response received %d!", __func__, event.event_type);
+ }
+ }
+
+ return 0;
+}
+
+CCECPAChangedReporter::CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA) :
+ m_callback(callback),
+ m_newPA(newPA)
+{
+}
+
+void* CCECPAChangedReporter::Process(void)
+{
+ m_callback->HandlePhysicalAddressChanged(m_newPA);
+ return NULL;
+}
+
+#endif // HAVE_IMX_API
diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h
new file mode 100644
index 0000000..2da38c1
--- /dev/null
+++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h
@@ -0,0 +1,139 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin
+ * Copyright (C) 2014 by Matus Kral
+ *
+ * You can redistribute this file and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#if defined(HAVE_IMX_API)
+
+#include "adapter/AdapterCommunication.h"
+#include <p8-platform/threads/mutex.h>
+#include <p8-platform/threads/threads.h>
+#include <p8-platform/sockets/socket.h>
+#include "adapter/IMX/mxc_hdmi-cec.h"
+#include <map>
+
+#define IMX_ADAPTER_VID 0x0471 /*FIXME TBD*/
+#define IMX_ADAPTER_PID 0x1001
+
+typedef struct hdmi_cec_event{
+ uint8_t event_type;
+ uint8_t msg_len;
+ uint8_t msg[MAX_MESSAGE_LEN];
+}hdmi_cec_event;
+
+
+namespace P8PLATFORM
+{
+ class CCDevSocket;
+};
+
+namespace CEC
+{
+ class CIMXCECAdapterMessageQueueEntry;
+
+ class CCECPAChangedReporter : public P8PLATFORM::CThread
+ {
+ public:
+ CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA);
+ void* Process(void);
+
+ private:
+ IAdapterCommunicationCallback *m_callback;
+ uint16_t m_newPA;
+ };
+
+ class CIMXCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread
+ {
+ public:
+ /*!
+ * @brief Create a new USB-CEC communication handler.
+ * @param callback The callback to use for incoming CEC commands.
+ */
+ CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback);
+ virtual ~CIMXCECAdapterCommunication(void);
+
+ /** @name IAdapterCommunication implementation */
+ ///{
+ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true);
+ void Close(void);
+ bool IsOpen(void);
+ std::string GetError(void) const;
+ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply);
+
+ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) { return true; }
+ bool StartBootloader(void) { return false; }
+ bool SetLogicalAddresses(const cec_logical_addresses &addresses);
+ cec_logical_addresses GetLogicalAddresses(void);
+ bool PingAdapter(void) { return IsInitialised(); }
+ uint16_t GetFirmwareVersion(void);
+ uint32_t GetFirmwareBuildDate(void) { return 0; }
+ bool IsRunningLatestFirmware(void) { return true; }
+ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; }
+ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; }
+ std::string GetPortName(void) { return std::string("IMX"); }
+ uint16_t GetPhysicalAddress(void);
+ bool SetControlledMode(bool UNUSED(controlled)) { return true; }
+ cec_vendor_id GetVendorId(void);
+ void HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress));
+ bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; }
+ cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_IMX; }
+ uint16_t GetAdapterVendorId(void) const { return IMX_ADAPTER_VID; }
+ uint16_t GetAdapterProductId(void) const { return IMX_ADAPTER_PID; }
+ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
+ ///}
+
+ /** @name PLATFORM::CThread implementation */
+ ///{
+ void *Process(void);
+ ///}
+
+ private:
+ bool IsInitialised(void) { return m_bInitialised; };
+ bool RegisterLogicalAddress(const cec_logical_address address);
+ bool UnregisterLogicalAddress(void);
+
+ std::string m_strError; /**< current error message */
+
+ cec_logical_address m_logicalAddress;
+ uint16_t m_physicalAddress;
+
+ P8PLATFORM::CMutex m_mutex;
+ P8PLATFORM::CCDevSocket *m_dev; /**< the device connection */
+
+ P8PLATFORM::CMutex m_messageMutex;
+ uint32_t m_iNextMessage;
+ std::map<uint32_t, CIMXCECAdapterMessageQueueEntry *> m_messages;
+
+ bool m_bLogicalAddressRegistered;
+ bool m_bInitialised;
+
+ CCECPAChangedReporter *m_PAReporter;
+ };
+
+};
+
+#endif
diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp
new file mode 100644
index 0000000..6c93c45
--- /dev/null
+++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin
+ *
+ * You can redistribute this file and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#include "env.h"
+#include <stdio.h>
+
+#if defined(HAVE_IMX_API)
+#include "IMXCECAdapterDetection.h"
+
+
+using namespace CEC;
+
+bool CIMXCECAdapterDetection::FindAdapter(void)
+{
+ return access(CEC_IMX_PATH, 0) == 0;
+}
+
+#endif
diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.h b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h
new file mode 100644
index 0000000..d54891d
--- /dev/null
+++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h
@@ -0,0 +1,36 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin
+ *
+ * You can redistribute this file and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+namespace CEC
+{
+ class CIMXCECAdapterDetection
+ {
+ public:
+ static bool FindAdapter(void);
+ };
+}
diff --git a/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h
new file mode 100644
index 0000000..e54c192
--- /dev/null
+++ b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h
@@ -0,0 +1,118 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include <p8-platform/threads/mutex.h>
+
+namespace CEC
+{
+ using namespace P8PLATFORM;
+
+ class CIMXCECAdapterMessageQueueEntry
+ {
+ public:
+ CIMXCECAdapterMessageQueueEntry(uint8_t addrs, cec_opcode opcode)
+ : m_bWaiting(true), m_retval((uint32_t)-1), m_bSucceeded(false)
+ {
+ m_opcode = opcode;
+ m_addrs = addrs;
+ }
+
+ virtual ~CIMXCECAdapterMessageQueueEntry(void) {}
+
+ /*!
+ * @brief Query result from worker thread
+ */
+ uint32_t Result() const
+ {
+ return m_retval;
+ }
+
+ /*!
+ * @brief Signal waiting threads
+ */
+ void Broadcast(void)
+ {
+ CLockObject lock(m_mutex);
+ m_condition.Broadcast();
+ }
+
+ /*!
+ * @brief Signal waiting thread(s) when message matches this entry
+ */
+ bool Received(int response, uint8_t addrs, cec_opcode opcode)
+ {
+ CLockObject lock(m_mutex);
+
+ if (!(m_addrs == addrs && m_opcode == opcode))
+ return false;
+
+ m_retval = response;
+ m_bSucceeded = true;
+ m_condition.Signal();
+ return true;
+ }
+
+ /*!
+ * @brief Wait for a response to this command.
+ * @param iTimeout The timeout to use while waiting.
+ * @return True when a response was received before the timeout passed, false otherwise.
+ */
+ bool Wait(uint32_t iTimeout)
+ {
+ CLockObject lock(m_mutex);
+
+ bool bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout);
+ m_bWaiting = false;
+ return bReturn;
+ }
+
+ /*!
+ * @return True while a thread is waiting for a signal or isn't waiting yet, false otherwise.
+ */
+ bool IsWaiting(void)
+ {
+ CLockObject lock(m_mutex);
+ return m_bWaiting;
+ }
+
+ private:
+ bool m_bWaiting; /**< true while a thread is waiting or when it hasn't started waiting yet */
+ P8PLATFORM::CCondition<bool> m_condition; /**< the condition to wait on */
+ P8PLATFORM::CMutex m_mutex; /**< mutex for changes to this class */
+ int m_retval;
+ bool m_bSucceeded;
+ uint8_t m_addrs;
+ cec_opcode m_opcode;
+ };
+
+};
diff --git a/src/libcec/adapter/IMX/mxc_hdmi-cec.h b/src/libcec/adapter/IMX/mxc_hdmi-cec.h
new file mode 100644
index 0000000..bc5bbce
--- /dev/null
+++ b/src/libcec/adapter/IMX/mxc_hdmi-cec.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef _HDMICEC_H_
+#define _HDMICEC_H_
+#include <linux/ioctl.h>
+
+/*
+ * Ioctl definitions
+ */
+
+/* Use 'k' as magic number */
+#define HDMICEC_IOC_MAGIC 'H'
+/*
+ * S means "Set" through a ptr,
+ * T means "Tell" directly with the argument value
+ * G means "Get": reply by setting through a pointer
+ * Q means "Query": response is on the return value
+ * X means "eXchange": G and S atomically
+ * H means "sHift": T and Q atomically
+ */
+#define HDMICEC_IOC_SETLOGICALADDRESS \
+ _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char)
+#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2)
+#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3)
+#define HDMICEC_IOC_GETPHYADDRESS \
+ _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4])
+
+#define MAX_MESSAGE_LEN 16
+
+#define MESSAGE_TYPE_RECEIVE_SUCCESS 1
+#define MESSAGE_TYPE_NOACK 2
+#define MESSAGE_TYPE_DISCONNECTED 3
+#define MESSAGE_TYPE_CONNECTED 4
+#define MESSAGE_TYPE_SEND_SUCCESS 5
+
+#endif /* !_HDMICEC_H_ */
+
diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake
index 532f213..a89e404 100644
--- a/src/libcec/cmake/CheckPlatformSupport.cmake
+++ b/src/libcec/cmake/CheckPlatformSupport.cmake
@@ -91,24 +91,49 @@ else()
endif()
# xrandr
- check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS)
- check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB)
- if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB)
- set(LIB_INFO "${LIB_INFO}, randr")
- list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp)
- SET(HAVE_RANDR ON CACHE BOOL "xrandr supported" FORCE)
+ if (${HAVE_RANDR_API})
+ check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS)
+ check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB)
+ if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB)
+ set(LIB_INFO "${LIB_INFO}, randr")
+ list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp)
+ set(HAVE_RANDR 1)
+ else()
+ set(HAVE_RANDR 0)
+ endif()
+ else()
+ set(HAVE_RANDR 0)
endif()
+ # iMX6
+ if (${HAVE_IMX_API})
+ set(LIB_INFO "${LIB_INFO}, iMX6")
+ set(HAVE_IMX_API 1)
+ set(CEC_SOURCES_ADAPTER_IMX adapter/IMX/IMXCECAdapterDetection.cpp
+ adapter/IMX/IMXCECAdapterCommunication.cpp)
+ source_group("Source Files\\adapter\\iMX6" FILES ${CEC_SOURCES_ADAPTER_IMX})
+ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_IMX})
+ set(HAVE_RPI_API 0)
+ else()
+ set(HAVE_IMX_API 0)
+ set(HAVE_RPI_API 1)
+ endif()
+
# raspberry pi
- find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}")
- check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_LIB)
- if (HAVE_RPI_LIB)
- SET(HAVE_RPI_API ON CACHE BOOL "raspberry pi supported" FORCE)
+ if (HAVE_RPI_API)
+ find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}")
+ check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_API)
+ endif()
+ if (HAVE_RPI_API)
find_library(RPI_VCOS vcos "${RPI_LIB_DIR}")
find_library(RPI_VCHIQ_ARM vchiq_arm "${RPI_LIB_DIR}")
include_directories(${RPI_INCLUDE_DIR} ${RPI_INCLUDE_DIR}/interface/vcos/pthreads ${RPI_INCLUDE_DIR}/interface/vmcs_host/linux)
- set(LIB_INFO "${LIB_INFO}, RPi")
+ set(LIB_INFO "${LIB_INFO}, 'RPi'")
+ # find includes files on Raspberry Pi
+ include_directories(/opt/vc/include /opt/vc/include/interface/vcos/pthreads /opt/vc/include/interface/vmcs_host/linux)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "vcos")
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "vchiq_arm")
set(CEC_SOURCES_ADAPTER_RPI adapter/RPi/RPiCECAdapterDetection.cpp
adapter/RPi/RPiCECAdapterCommunication.cpp
adapter/RPi/RPiCECAdapterMessageQueue.cpp)
@@ -148,6 +173,8 @@ else()
else()
set(HAVE_AOCEC_API 0)
endif()
+
+
endif()
# rt
diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake
index 7ec10f5..2262638 100644
--- a/src/libcec/cmake/DisplayPlatformSupport.cmake
+++ b/src/libcec/cmake/DisplayPlatformSupport.cmake
@@ -45,9 +45,15 @@ else()
endif()
if (HAVE_AOCEC_API)
- message(STATUS "AOCEC support: yes")
+ message(STATUS "AOCEC support: yes")
else()
- message(STATUS "AOCEC support: no")
+ message(STATUS "AOCEC support: no")
+endif()
+
+if (HAVE_IMX_API)
+ message(STATUS "i.MX6 support: yes")
+else()
+ message(STATUS "i.MX6 support: no")
endif()
if (HAVE_PYTHON)
diff --git a/src/libcec/cmake/LinkPlatformSupport.cmake b/src/libcec/cmake/LinkPlatformSupport.cmake
index fc27353..b203f6f 100644
--- a/src/libcec/cmake/LinkPlatformSupport.cmake
+++ b/src/libcec/cmake/LinkPlatformSupport.cmake
@@ -28,7 +28,12 @@ endif()
# raspberry pi
if (HAVE_RPI_API)
- target_link_libraries(cec ${RPI_VCOS} ${RPI_VCHIQ_ARM} ${RPI_BCM_HOST})
+ find_library (VCOS vcos)
+ target_link_libraries(cec ${VCOS})
+ find_library (VCHIQ_ARM vchiq_arm)
+ target_link_libraries(cec ${VCHIP_ARM})
+ find_library (BCM_HOST bcm_host)
+ target_link_libraries(cec ${BCM_HOST})
endif()
# Apple
diff --git a/src/libcec/cmake/git-rev.sh b/src/libcec/cmake/git-rev.sh
index db682c1..15b6a23 100755
--- a/src/libcec/cmake/git-rev.sh
+++ b/src/libcec/cmake/git-rev.sh
@@ -2,7 +2,7 @@
## cmake doesn't read the variable when it doesn't end with a newline, and I haven't figured out how to have it add a newline directly...
if git rev-parse --git-dir > /dev/null 2>&1; then
- last_tag=`git describe --tags --abbrev=0`
+ last_tag=`git describe --tags --abbrev=0 --all`
last_hash=`git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h"`
commits_since_tag=`git log ${last_tag}..HEAD --oneline | wc -l`
git_dirty=`git diff HEAD | wc -l`
diff --git a/src/libcec/devices/CECBusDevice.cpp b/src/libcec/devices/CECBusDevice.cpp
index 99f762c..be72b05 100644
--- a/src/libcec/devices/CECBusDevice.cpp
+++ b/src/libcec/devices/CECBusDevice.cpp
@@ -44,6 +44,7 @@
#include "implementations/RLCommandHandler.h"
#include "implementations/RHCommandHandler.h"
#include "implementations/AQCommandHandler.h"
+#include "implementations/GRCommandHandler.h"
#include "LibCEC.h"
#include "CECTypeUtils.h"
#include <p8-platform/util/timeutils.h>
@@ -217,6 +218,9 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */)
case CEC_VENDOR_SHARP2:
m_handler = new CAQCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
break;
+ case CEC_VENDOR_GRUNDIG:
+ m_handler = new CGRCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
+ break;
default:
m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
break;
@@ -1263,7 +1267,7 @@ bool CCECBusDevice::PowerOn(const cec_logical_address initiator)
MarkBusy();
cec_power_status currentStatus;
- if (m_iLogicalAddress == CECDEVICE_TV ||
+ if ((m_iLogicalAddress == CECDEVICE_TV && !ImageViewOnSent()) ||
((currentStatus = GetPowerStatus(initiator, false)) != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON &&
currentStatus != CEC_POWER_STATUS_ON))
{
@@ -1498,3 +1502,8 @@ bool CCECBusDevice::TransmitMuteAudio(const cec_logical_address source)
return TransmitKeypress(source, CEC_USER_CONTROL_CODE_MUTE) &&
TransmitKeyRelease(source);
}
+
+bool CCECBusDevice::TransmitSystemAudioModeRequest(const cec_logical_address initiator)
+{
+ return m_handler->TransmitSystemAudioModeRequest(initiator, m_iPhysicalAddress, false);
+}
diff --git a/src/libcec/devices/CECBusDevice.h b/src/libcec/devices/CECBusDevice.h
index b8255aa..8493d48 100644
--- a/src/libcec/devices/CECBusDevice.h
+++ b/src/libcec/devices/CECBusDevice.h
@@ -199,6 +199,8 @@ namespace CEC
void SignalOpcode(cec_opcode opcode);
bool WaitForOpcode(cec_opcode opcode);
+ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address initiator);
+
CCECAudioSystem * AsAudioSystem(void);
static CCECAudioSystem * AsAudioSystem(CCECBusDevice *device);
CCECPlaybackDevice * AsPlaybackDevice(void);
diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in
index 0774a1c..14c7704 100644
--- a/src/libcec/env.h.in
+++ b/src/libcec/env.h.in
@@ -70,6 +70,9 @@
/* Define to 1 for Raspberry Pi support */
#cmakedefine HAVE_RPI_API @HAVE_RPI_API@
+/* Define to 1 for iMX6 support */
+#cmakedefine HAVE_IMX_API @HAVE_IMX_API@
+
/* Define to 1 for TDA995x support */
#cmakedefine HAVE_TDA995X_API @HAVE_TDA995X_API@
diff --git a/src/libcec/implementations/CECCommandHandler.cpp b/src/libcec/implementations/CECCommandHandler.cpp
index 71c2230..5a1e7a0 100644
--- a/src/libcec/implementations/CECCommandHandler.cpp
+++ b/src/libcec/implementations/CECCommandHandler.cpp
@@ -62,6 +62,7 @@ CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice,
m_iTransmitRetries(iTransmitRetries),
m_bHandlerInited(false),
m_bOPTSendDeckStatusUpdateOnActiveSource(false),
+ m_bOPTSendMenuStatusUpdateOnActiveSource(true),
m_vendorId(CEC_VENDOR_UNKNOWN),
m_iActiveSourcePending(iActiveSourcePending),
m_iPowerStatusRequested(0)
@@ -1133,6 +1134,19 @@ bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiato
return Transmit(command, false, bIsReply);
}
+bool CCECCommandHandler::TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, CECDEVICE_AUDIOSYSTEM, CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST);
+ command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
+ command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));
+
+ if (Transmit(command, true, bIsReply))
+ return true;
+
+ return false;
+}
+
bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply)
{
cec_command command;
@@ -1307,7 +1321,7 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f
if (!bActiveSourceFailed && bSourceSwitchAllowed)
{
bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false);
- if (bTvPresent && !bActiveSourceFailed)
+ if (bTvPresent && !bActiveSourceFailed && SendMenuStatusUpdateOnActiveSource())
m_busDevice->TransmitMenuState(CECDEVICE_TV, false);
// update the deck status for playback devices
diff --git a/src/libcec/implementations/CECCommandHandler.h b/src/libcec/implementations/CECCommandHandler.h
index 8ff9a1e..eb52ed3 100644
--- a/src/libcec/implementations/CECCommandHandler.h
+++ b/src/libcec/implementations/CECCommandHandler.h
@@ -60,7 +60,9 @@ namespace CEC
virtual bool HandleCommand(const cec_command &command);
virtual cec_vendor_id GetVendorId(void) { return m_vendorId; };
virtual void SetVendorId(cec_vendor_id vendorId) { m_vendorId = vendorId; }
- static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO;}
+ static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS
+ || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO
+ || vendorId == CEC_VENDOR_GRUNDIG; }
virtual bool InitHandler(void) { return true; }
virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false);
@@ -89,6 +91,7 @@ namespace CEC
virtual bool TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state, bool bIsReply);
virtual bool TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t iVendorId, bool bIsReply);
virtual bool TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state, bool bIsReply);
+ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply);
virtual bool TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply);
virtual bool TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply);
virtual bool TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state, bool bIsReply);
@@ -97,6 +100,7 @@ namespace CEC
virtual bool TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
virtual bool TransmitSetStreamPath(uint16_t iStreamPath, bool bIsReply);
virtual bool SendDeckStatusUpdateOnActiveSource(void) const { return m_bOPTSendDeckStatusUpdateOnActiveSource; };
+ virtual bool SendMenuStatusUpdateOnActiveSource(void) const { return m_bOPTSendMenuStatusUpdateOnActiveSource; };
virtual void ScheduleActivateSource(uint64_t iDelay);
@@ -165,6 +169,7 @@ namespace CEC
int8_t m_iTransmitRetries;
bool m_bHandlerInited;
bool m_bOPTSendDeckStatusUpdateOnActiveSource;
+ bool m_bOPTSendMenuStatusUpdateOnActiveSource;
cec_vendor_id m_vendorId;
int64_t m_iActiveSourcePending;
P8PLATFORM::CMutex m_mutex;
diff --git a/src/libcec/implementations/GRCommandHandler.cpp b/src/libcec/implementations/GRCommandHandler.cpp
new file mode 100644
index 0000000..af49af9
--- /dev/null
+++ b/src/libcec/implementations/GRCommandHandler.cpp
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include "GRCommandHandler.h"
+
+#include "devices/CECBusDevice.h"
+#include "CECProcessor.h"
+#include "LibCEC.h"
+#include "CECClient.h"
+
+using namespace CEC;
+
+#define LIB_CEC m_busDevice->GetProcessor()->GetLib()
+#define ToString(p) LIB_CEC->ToString(p)
+
+CGRCommandHandler::CGRCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
+ int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
+ int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
+ int64_t iActiveSourcePending /* = 0 */) :
+ CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending)
+{
+ m_vendorId = CEC_VENDOR_GRUNDIG;
+ m_bOPTSendMenuStatusUpdateOnActiveSource = false;
+
+ m_busDevice->SetCecVersion(CEC_VERSION_1_3A);
+
+ /* Grundig devices return "" as language */
+ cec_menu_language lang;
+ snprintf(lang, 4, "eng");
+ m_busDevice->SetMenuLanguage(lang);
+}
+
+bool CGRCommandHandler::InitHandler(void)
+{
+ if (m_bHandlerInited)
+ return true;
+ m_bHandlerInited = true;
+
+ if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
+ return true;
+
+ CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+ if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
+ {
+ /* imitate Toshiba devices */
+ if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+ {
+ primary->SetVendorId(CEC_VENDOR_GRUNDIG);
+ primary->ReplaceHandler(false);
+ }
+
+ if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+ {
+ /* send the vendor id */
+ primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
+ }
+ }
+
+ return true;
+}
diff --git a/src/libcec/implementations/GRCommandHandler.h b/src/libcec/implementations/GRCommandHandler.h
new file mode 100644
index 0000000..e01c7fc
--- /dev/null
+++ b/src/libcec/implementations/GRCommandHandler.h
@@ -0,0 +1,53 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include "CECCommandHandler.h"
+#include "p8-platform/threads/threads.h"
+
+namespace CEC
+{
+ class CGRCommandHandler : public CCECCommandHandler
+ {
+ public:
+ CGRCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT,
+ int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT,
+ int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES,
+ int64_t iActiveSourcePending = 0);
+
+ bool InitHandler(void);
+ virtual ~CGRCommandHandler(void) {};
+ };
+};
--
2.7.4