From: Lars Op den Kamp Date: Wed, 31 Oct 2012 14:58:41 +0000 (+0100) Subject: Merge branch 'master' into release X-Git-Tag: upstream/2.2.0~1^2~13 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=75362c3c044a252f4d596ed8b28cad8069c2e781;hp=a9ac151c8265f1d241799f7d6beaf4e13d4066ca;p=deb_libcec.git Merge branch 'master' into release --- diff --git a/ChangeLog b/ChangeLog index 983d006..9b0d274 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +libcec (2.0.3-1) unstable; urgency=low + + * changed: + * log unhandled vendor remote keycodes in the log, so they get logged + without debugging enabled + * double tap timeout increased from 200ms to 250ms + * CuBox/NXP* renamed to TDA995x* + * fixed: + * handling of active route changes. github issue #56 and issue #58 + * new combo key handling broke samsung's vendor specific remote buttons. + github issue #54 + * don't try to set controlled mode when using firmware version 1 and crash. + github issue #76 + * fix for LG models that send a vendor key up after a normal key down. + github issue #71 + * some TVs send keypresses to us without making us the active source. mark + us as active source when this happens. github issue #71 + * LG doesn't send routing changes, and marks the TV as active source when + switching to another source that's not been selected in the simplink menu + instead. this change keeps libCEC marked as powered on and keep the deck + state set to CEC_DECK_INFO_OTHER_STATUS_LG. fixes keypresses not working + after switching to another source and back to libCEC's hdmi port via the + source select menu instead of the simplink menu. github issue #71 + * don't respond with an abort message when receiving a vendor remote button + command + * respond with CEC_ABORT_REASON_INVALID_OPERAND when receiving a keypress + without a parameter + * typo in stop+pause combo key that prevented one of the keys from working + * rpi: log what data we received exactly when we receive an response from + the pi's firmware that doesn't match any command that we sent. issue #77 + * cubox: added adapter ID interface + + -- Pulse-Eight Packaging Wed, 31 Oct 2012 15:57:00 +0100 + libcec (2.0.2-2) unstable; urgency=medium * fixed: diff --git a/README b/README index 9bf8786..f25c539 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ You can find a list of frequently asked questions on the following page: http://libcec.pulse-eight.com/faq =============================================================================== - === Linux === + === Linux & BSD === =============================================================================== libCEC needs the following dependencies in order to work correctly: @@ -25,7 +25,7 @@ be auto-detected. * udev development headers v151 or later To compile, execute the following commands: -# autoreconf -vif +# ./bootstrap # ./configure # make # sudo make install @@ -40,8 +40,8 @@ To compile libCEC on OS-X, you'll need the following dependencies: * pkg-config * xcode 3.2.6 or later -To compile, execute the following commands (TODO: please verify): -# autoreconf -vif +To compile, execute the following command: +# ./bootstrap # ./configure # make # sudo make install @@ -100,15 +100,15 @@ for 'configure': --with-rpi-lib-path="/path/to/libbcm_host.so" =============================================================================== - === CuBox === + === CuBox / TDA995x === =============================================================================== Solid-Run's CuBox uses a combined HDMI tranceiver / CEC controller by NXP. The device driver for it is based on an SDK by the chip vendor and is compiled into the Linux kernel. The following options for 'configure' have been introduced: -To enable support for the CuBox: ---enable-cubox +To enable support for the CuBox / TDA995x: +--enable-tda995x To specify the path to the SDK part of the kernel driver: --with-tda995x-toolkit-path='path/to/linux/drivers/video/dovefb/nxp_hdmi' @@ -120,6 +120,10 @@ If the toolkit path is not specified, it is assumed that a directory named === Debugging / Testing === =============================================================================== +To compile libCEC with extensive debugging output, pass the following argument +to configure on Linux/OS-X/BSD: +--enable-debug + We provide a test client, named cec-client, to debug the device. To check whether the device can be detected, execute the following command: * cec-client -l diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..b80eba2 --- /dev/null +++ b/bootstrap @@ -0,0 +1,4 @@ +#!/bin/sh + +autoreconf -vif + diff --git a/configure.ac b/configure.ac index df63c2d..45d969b 100644 --- a/configure.ac +++ b/configure.ac @@ -43,10 +43,10 @@ AC_ARG_ENABLE([optimisation], [use_optimisation=$enableval], [use_optimisation=yes]) -## CuBox support +## TDA995x support AC_ARG_ENABLE([cubox], - [AS_HELP_STRING([--enable-cubox], - [enable support for the CuBox (default is no)])], + [AS_HELP_STRING([--enable-tda995x], + [enable support for the TDA995x (default is no)])], [use_tda995x=$enableval], [use_tda995x=no]) @@ -250,16 +250,16 @@ else features="$features\n Raspberry Pi support :\t\tno" fi -## mark CuBox support as available +## mark TDA995x support as available if test "x$use_tda995x" != "xno"; then AC_DEFINE([HAVE_TDA995X_API],[1],[Define to 1 to include CuBox support]) AM_CONDITIONAL(USE_TDA995X_API, true) - features="$features\n CuBox support :\t\t\tyes" - LIB_INFO="$LIB_INFO 'CuBox'" + features="$features\n TDA995x support :\t\t\tyes" + LIB_INFO="$LIB_INFO 'TDA995x'" CPPFLAGS="$CPPFLAGS $TDA995X_CFLAGS" else AM_CONDITIONAL(USE_TDA995X_API, false) - features="$features\n CuBox support :\t\t\tno" + features="$features\n TDA995x support :\t\t\tno" fi ## check if our build system is complete diff --git a/debian/changelog b/debian/changelog index 983d006..9b0d274 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,37 @@ +libcec (2.0.3-1) unstable; urgency=low + + * changed: + * log unhandled vendor remote keycodes in the log, so they get logged + without debugging enabled + * double tap timeout increased from 200ms to 250ms + * CuBox/NXP* renamed to TDA995x* + * fixed: + * handling of active route changes. github issue #56 and issue #58 + * new combo key handling broke samsung's vendor specific remote buttons. + github issue #54 + * don't try to set controlled mode when using firmware version 1 and crash. + github issue #76 + * fix for LG models that send a vendor key up after a normal key down. + github issue #71 + * some TVs send keypresses to us without making us the active source. mark + us as active source when this happens. github issue #71 + * LG doesn't send routing changes, and marks the TV as active source when + switching to another source that's not been selected in the simplink menu + instead. this change keeps libCEC marked as powered on and keep the deck + state set to CEC_DECK_INFO_OTHER_STATUS_LG. fixes keypresses not working + after switching to another source and back to libCEC's hdmi port via the + source select menu instead of the simplink menu. github issue #71 + * don't respond with an abort message when receiving a vendor remote button + command + * respond with CEC_ABORT_REASON_INVALID_OPERAND when receiving a keypress + without a parameter + * typo in stop+pause combo key that prevented one of the keys from working + * rpi: log what data we received exactly when we receive an response from + the pi's firmware that doesn't match any command that we sent. issue #77 + * cubox: added adapter ID interface + + -- Pulse-Eight Packaging Wed, 31 Oct 2012 15:57:00 +0100 + libcec (2.0.2-2) unstable; urgency=medium * fixed: diff --git a/include/cec.h b/include/cec.h index ba12a87..7d14a47 100644 --- a/include/cec.h +++ b/include/cec.h @@ -36,7 +36,7 @@ #include "cectypes.h" -#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_2 +#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_3 namespace CEC { diff --git a/include/cectypes.h b/include/cectypes.h index 6b7f73c..48d1ab8 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -82,7 +82,7 @@ namespace CEC { /*! * don't send the same key twice within this timeout in milliseconds */ -#define CEC_DOUBLE_TAP_TIMEOUT_MS 200 +#define CEC_DOUBLE_TAP_TIMEOUT_MS 250 /*! * don't query the power state for the same device within this timeout in milliseconds @@ -1376,6 +1376,7 @@ typedef enum cec_client_version CEC_CLIENT_VERSION_2_0_0 = 0x2000, CEC_CLIENT_VERSION_2_0_1 = 0x2001, CEC_CLIENT_VERSION_2_0_2 = 0x2002, + CEC_CLIENT_VERSION_2_0_3 = 0x2003, } cec_client_version; typedef enum cec_server_version @@ -1400,6 +1401,7 @@ typedef enum cec_server_version CEC_SERVER_VERSION_2_0_0 = 0x2000, CEC_SERVER_VERSION_2_0_1 = 0x2001, CEC_SERVER_VERSION_2_0_2 = 0x2002, + CEC_SERVER_VERSION_2_0_3 = 0x2003, } cec_server_version; struct libcec_configuration diff --git a/project/cec-config.rc b/project/cec-config.rc index 7a9da22..def8b1f 100644 Binary files a/project/cec-config.rc and b/project/cec-config.rc differ diff --git a/project/libcec.rc b/project/libcec.rc index b925f41..c92cadc 100644 Binary files a/project/libcec.rc and b/project/libcec.rc differ diff --git a/project/testclient.rc b/project/testclient.rc index abb8ee4..0da16c6 100644 Binary files a/project/testclient.rc and b/project/testclient.rc differ diff --git a/src/CecSharpTester/CecSharpClient.cs b/src/CecSharpTester/CecSharpClient.cs index cd9b0e9..63a2e23 100644 --- a/src/CecSharpTester/CecSharpClient.cs +++ b/src/CecSharpTester/CecSharpClient.cs @@ -43,7 +43,7 @@ namespace CecSharpClient Config = new LibCECConfiguration(); Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice; Config.DeviceName = "CEC Tester"; - Config.ClientVersion = CecClientVersion.Version2_0_2; + Config.ClientVersion = CecClientVersion.Version2_0_3; Config.SetCallbacks(this); LogLevel = (int)CecLogLevel.All; diff --git a/src/CecSharpTester/Properties/AssemblyInfo.cs b/src/CecSharpTester/Properties/AssemblyInfo.cs index 23128fc..ad7143f 100644 --- a/src/CecSharpTester/Properties/AssemblyInfo.cs +++ b/src/CecSharpTester/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.2.0")] -[assembly: AssemblyFileVersion("2.0.2.0")] +[assembly: AssemblyVersion("2.0.3.0")] +[assembly: AssemblyFileVersion("2.0.3.0")] diff --git a/src/LibCecSharp/AssemblyInfo.cpp b/src/LibCecSharp/AssemblyInfo.cpp index fe944b5..fa6b40b 100644 --- a/src/LibCecSharp/AssemblyInfo.cpp +++ b/src/LibCecSharp/AssemblyInfo.cpp @@ -13,7 +13,7 @@ using namespace System::Security::Permissions; [assembly:AssemblyTrademarkAttribute("")]; [assembly:AssemblyCultureAttribute("")]; -[assembly:AssemblyVersionAttribute("2.0.2.0")]; +[assembly:AssemblyVersionAttribute("2.0.3.0")]; [assembly:ComVisible(false)]; [assembly:CLSCompliantAttribute(true)]; diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index e183be3..bf42996 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -1171,7 +1171,11 @@ namespace CecSharp /// /// v2.0.2 /// - Version2_0_2 = 0x2002 + Version2_0_2 = 0x2002, + /// + /// v2.0.3 + /// + Version2_0_3 = 0x2003 }; /// @@ -1258,7 +1262,11 @@ namespace CecSharp /// /// v2.0.2 /// - Version2_0_2 = 0x2002 + Version2_0_2 = 0x2002, + /// + /// v2.0.3 + /// + Version2_0_3 = 0x2003 }; /// diff --git a/src/LibCecTray/Properties/AssemblyInfo.cs b/src/LibCecTray/Properties/AssemblyInfo.cs index aad28dd..8bc2245 100644 --- a/src/LibCecTray/Properties/AssemblyInfo.cs +++ b/src/LibCecTray/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.2.0")] -[assembly: AssemblyFileVersion("2.0.2.0")] +[assembly: AssemblyVersion("2.0.3.0")] +[assembly: AssemblyFileVersion("2.0.3.0")] diff --git a/src/LibCecTray/controller/CECController.cs b/src/LibCecTray/controller/CECController.cs index ebce4ba..f4dc434 100644 --- a/src/LibCecTray/controller/CECController.cs +++ b/src/LibCecTray/controller/CECController.cs @@ -438,7 +438,7 @@ namespace LibCECTray.controller { if (_config == null) { - _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.Version2_0_2 }; + _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.Version2_0_3 }; _config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice; _config.SetCallbacks(this); diff --git a/src/lib/CECClient.cpp b/src/lib/CECClient.cpp index a5a960e..004d741 100644 --- a/src/lib/CECClient.cpp +++ b/src/lib/CECClient.cpp @@ -940,21 +940,21 @@ void CCECClient::AddKey(const cec_keypress &key) // send back the previous key if there is one AddKey(); + if (key.keycode > CEC_USER_CONTROL_CODE_MAX && + key.keycode < CEC_USER_CONTROL_CODE_SELECT) + return; + cec_keypress transmitKey(key); { CLockObject lock(m_mutex); - if (key.duration > 0 || key.keycode > CEC_USER_CONTROL_CODE_MAX) - { - transmitKey.keycode = CEC_USER_CONTROL_CODE_UNKNOWN; - } - else if (m_iCurrentButton == COMBO_KEY) + if (m_iCurrentButton == COMBO_KEY && key.duration == 0) { // stop + ok -> exit if (key.keycode == CEC_USER_CONTROL_CODE_SELECT) transmitKey.keycode = CEC_USER_CONTROL_CODE_EXIT; // stop + pause -> root menu - else if (key.keycode == CEC_USER_CONTROL_CODE_ROOT_MENU) + else if (key.keycode == CEC_USER_CONTROL_CODE_PAUSE) transmitKey.keycode = CEC_USER_CONTROL_CODE_ROOT_MENU; // stop + play -> dot (which is handled as context menu in xbmc) else if (key.keycode == CEC_USER_CONTROL_CODE_PLAY) @@ -968,8 +968,11 @@ void CCECClient::AddKey(const cec_keypress &key) m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs(); } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode); - CallbackAddKey(transmitKey); + if (key.keycode != COMBO_KEY || key.duration > 0) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode); + CallbackAddKey(transmitKey); + } } void CCECClient::SetCurrentButton(const cec_user_control_code iButtonCode) diff --git a/src/lib/CECTypeUtils.h b/src/lib/CECTypeUtils.h index 21a651d..ee3ddb3 100644 --- a/src/lib/CECTypeUtils.h +++ b/src/lib/CECTypeUtils.h @@ -561,6 +561,8 @@ namespace CEC return "2.0.1"; case CEC_CLIENT_VERSION_2_0_2: return "2.0.2"; + case CEC_CLIENT_VERSION_2_0_3: + return "2.0.3"; default: return "Unknown"; } @@ -610,6 +612,8 @@ namespace CEC return "2.0.1"; case CEC_SERVER_VERSION_2_0_2: return "2.0.2"; + case CEC_SERVER_VERSION_2_0_3: + return "2.0.3"; default: return "Unknown"; } @@ -819,5 +823,16 @@ namespace CEC return "unknown"; } } + + static bool PhysicalAddressIsIncluded(uint16_t iParent, uint16_t iChild) + { + for (int iPtr = 3; iPtr >= 0; iPtr--) + { + if (((iParent >> 4*iPtr) & 0xF) > 0 && + ((iParent >> 4*iPtr) & 0xF) != ((iChild >> 4*iPtr) & 0xF)) + return false; + } + return true; + } }; } diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index b88b02b..ab00f1b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -52,8 +52,8 @@ endif ## CuBox (NXP) support if USE_TDA995X_API -libcec_la_SOURCES += adapter/CuBox/NxpCECAdapterDetection.cpp \ - adapter/CuBox/NxpCECAdapterCommunication.cpp +libcec_la_SOURCES += adapter/TDA995x/TDA995xCECAdapterDetection.cpp \ + adapter/TDA995x/TDA995xCECAdapterCommunication.cpp endif diff --git a/src/lib/adapter/AdapterFactory.cpp b/src/lib/adapter/AdapterFactory.cpp index d1dae84..02b6200 100644 --- a/src/lib/adapter/AdapterFactory.cpp +++ b/src/lib/adapter/AdapterFactory.cpp @@ -48,8 +48,8 @@ #endif #if defined(HAVE_TDA995X_API) -#include "CuBox/NxpCECAdapterDetection.h" -#include "CuBox/NxpCECAdapterCommunication.h" +#include "TDA995x/TDA995xCECAdapterDetection.h" +#include "TDA995x/TDA995xCECAdapterCommunication.h" #endif using namespace std; @@ -81,7 +81,7 @@ int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, #endif #if defined(HAVE_TDA995X_API) - if (iAdaptersFound < iBufSize && CNxpCECAdapterDetection::FindAdapter() && + if (iAdaptersFound < iBufSize && CTDA995xCECAdapterDetection::FindAdapter() && (!strDevicePath || !strcmp(strDevicePath, CEC_TDA995x_VIRTUAL_COM))) { snprintf(deviceList[iAdaptersFound].path, 1024, CEC_TDA995x_PATH); @@ -100,7 +100,7 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ { #if defined(HAVE_TDA995X_API) if (!strcmp(strPort, CEC_TDA995x_VIRTUAL_COM)) - return new CNxpCECAdapterCommunication(m_lib->m_cec); + return new CTDA995xCECAdapterCommunication(m_lib->m_cec); #endif #if defined(HAVE_RPI_API) diff --git a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.cpp b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.cpp index 717e7d3..9448068 100644 --- a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.cpp +++ b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.cpp @@ -104,6 +104,10 @@ uint16_t CUSBCECAdapterCommands::RequestFirmwareVersion(void) m_persistedConfiguration.iFirmwareVersion = 1; } + // firmware versions < 2 don't have an autonomous mode + if (m_persistedConfiguration.iFirmwareVersion < 2) + m_bControlledMode = true; + return m_persistedConfiguration.iFirmwareVersion; } diff --git a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp index 656a25d..625b2e9 100644 --- a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp +++ b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp @@ -121,7 +121,7 @@ void CRPiCECAdapterMessageQueue::MessageReceived(cec_opcode opcode, cec_logical_ bHandled = it->second->MessageReceived(opcode, initiator, destination, response); if (!bHandled) - LIB_CEC->AddLog(CEC_LOG_WARNING, "unhandled response received"); + LIB_CEC->AddLog(CEC_LOG_WARNING, "unhandled response received: opcode=%x initiator=%x destination=%x response=%x", (int)opcode, (int)initiator, (int)destination, response); } bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply) diff --git a/src/lib/adapter/CuBox/AdapterMessageQueue.h b/src/lib/adapter/TDA995x/AdapterMessageQueue.h similarity index 100% rename from src/lib/adapter/CuBox/AdapterMessageQueue.h rename to src/lib/adapter/TDA995x/AdapterMessageQueue.h diff --git a/src/lib/adapter/CuBox/NxpCECAdapterCommunication.cpp b/src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.cpp similarity index 89% rename from src/lib/adapter/CuBox/NxpCECAdapterCommunication.cpp rename to src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.cpp index e46f94e..83df119 100644 --- a/src/lib/adapter/CuBox/NxpCECAdapterCommunication.cpp +++ b/src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.cpp @@ -33,7 +33,7 @@ #include "env.h" #if defined(HAVE_TDA995X_API) -#include "NxpCECAdapterCommunication.h" +#include "TDA995xCECAdapterCommunication.h" #include "lib/CECTypeUtils.h" #include "lib/LibCEC.h" @@ -66,7 +66,7 @@ using namespace PLATFORM; #define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/ -CNxpCECAdapterCommunication::CNxpCECAdapterCommunication(IAdapterCommunicationCallback *callback) : +CTDA995xCECAdapterCommunication::CTDA995xCECAdapterCommunication(IAdapterCommunicationCallback *callback) : IAdapterCommunication(callback), m_bLogicalAddressChanged(false) { @@ -78,7 +78,7 @@ CNxpCECAdapterCommunication::CNxpCECAdapterCommunication(IAdapterCommunicationCa } -CNxpCECAdapterCommunication::~CNxpCECAdapterCommunication(void) +CTDA995xCECAdapterCommunication::~CTDA995xCECAdapterCommunication(void) { Close(); @@ -88,13 +88,13 @@ CNxpCECAdapterCommunication::~CNxpCECAdapterCommunication(void) } -bool CNxpCECAdapterCommunication::IsOpen(void) +bool CTDA995xCECAdapterCommunication::IsOpen(void) { return IsInitialised() && m_dev->IsOpen(); } -bool CNxpCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening) +bool CTDA995xCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening) { if (m_dev->Open(iTimeoutMs)) { @@ -129,7 +129,7 @@ bool CNxpCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChe } -void CNxpCECAdapterCommunication::Close(void) +void CTDA995xCECAdapterCommunication::Close(void) { StopThread(0); @@ -140,14 +140,14 @@ void CNxpCECAdapterCommunication::Close(void) } -std::string CNxpCECAdapterCommunication::GetError(void) const +std::string CTDA995xCECAdapterCommunication::GetError(void) const { std::string strError(m_strError); return strError; } -cec_adapter_message_state CNxpCECAdapterCommunication::Write( +cec_adapter_message_state CTDA995xCECAdapterCommunication::Write( const cec_command &data, bool &UNUSED(bRetry), uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) { cec_frame frame; @@ -211,7 +211,7 @@ cec_adapter_message_state CNxpCECAdapterCommunication::Write( } -uint16_t CNxpCECAdapterCommunication::GetFirmwareVersion(void) +uint16_t CTDA995xCECAdapterCommunication::GetFirmwareVersion(void) { cec_sw_version vers = { 0 }; @@ -221,7 +221,7 @@ uint16_t CNxpCECAdapterCommunication::GetFirmwareVersion(void) } -cec_vendor_id CNxpCECAdapterCommunication::GetVendorId(void) +cec_vendor_id CTDA995xCECAdapterCommunication::GetVendorId(void) { cec_raw_info info; @@ -235,7 +235,7 @@ cec_vendor_id CNxpCECAdapterCommunication::GetVendorId(void) } -uint16_t CNxpCECAdapterCommunication::GetPhysicalAddress(void) +uint16_t CTDA995xCECAdapterCommunication::GetPhysicalAddress(void) { cec_raw_info info; @@ -249,7 +249,7 @@ uint16_t CNxpCECAdapterCommunication::GetPhysicalAddress(void) } -cec_logical_addresses CNxpCECAdapterCommunication::GetLogicalAddresses(void) +cec_logical_addresses CTDA995xCECAdapterCommunication::GetLogicalAddresses(void) { CLockObject lock(m_mutex); @@ -280,7 +280,7 @@ cec_logical_addresses CNxpCECAdapterCommunication::GetLogicalAddresses(void) } -bool CNxpCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) +bool CTDA995xCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) { unsigned char log_addr = addresses.primary; @@ -308,7 +308,7 @@ bool CNxpCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresse } -void CNxpCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) +void CTDA995xCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) { unsigned char log_addr = CECDEVICE_BROADCAST; @@ -319,7 +319,7 @@ void CNxpCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address U } -void *CNxpCECAdapterCommunication::Process(void) +void *CTDA995xCECAdapterCommunication::Process(void) { bool bHandled; cec_frame frame; diff --git a/src/lib/adapter/CuBox/NxpCECAdapterCommunication.h b/src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.h similarity index 88% rename from src/lib/adapter/CuBox/NxpCECAdapterCommunication.h rename to src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.h index 066c032..9476383 100644 --- a/src/lib/adapter/CuBox/NxpCECAdapterCommunication.h +++ b/src/lib/adapter/TDA995x/TDA995xCECAdapterCommunication.h @@ -39,6 +39,8 @@ #include "lib/adapter/AdapterCommunication.h" #include +#define TDA995X_ADAPTER_VID 0x0471 +#define TDA995X_ADAPTER_PID 0x1001 namespace PLATFORM { @@ -50,15 +52,15 @@ namespace CEC { class CAdapterMessageQueueEntry; - class CNxpCECAdapterCommunication : public IAdapterCommunication, public PLATFORM::CThread + class CTDA995xCECAdapterCommunication : public IAdapterCommunication, public PLATFORM::CThread { public: /*! * @brief Create a new USB-CEC communication handler. * @param callback The callback to use for incoming CEC commands. */ - CNxpCECAdapterCommunication(IAdapterCommunicationCallback *callback); - virtual ~CNxpCECAdapterCommunication(void); + CTDA995xCECAdapterCommunication(IAdapterCommunicationCallback *callback); + virtual ~CTDA995xCECAdapterCommunication(void); /** @name IAdapterCommunication implementation */ ///{ @@ -78,12 +80,14 @@ namespace CEC 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("NXP"); } + std::string GetPortName(void) { return std::string("TDA995X"); } uint16_t GetPhysicalAddress(void); bool SetControlledMode(bool UNUSED(controlled)) { return true; } cec_vendor_id GetVendorId(void); bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_TDA995x; } + uint16_t GetAdapterVendorId(void) const { return TDA995X_ADAPTER_VID; } + uint16_t GetAdapterProductId(void) const { return TDA995X_ADAPTER_PID; } void HandleLogicalAddressLost(cec_logical_address oldAddress); ///} diff --git a/src/lib/adapter/CuBox/NxpCECAdapterDetection.cpp b/src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.cpp similarity index 94% rename from src/lib/adapter/CuBox/NxpCECAdapterDetection.cpp rename to src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.cpp index b4b7495..a355f78 100644 --- a/src/lib/adapter/CuBox/NxpCECAdapterDetection.cpp +++ b/src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.cpp @@ -34,7 +34,7 @@ #include #if defined(HAVE_TDA995X_API) -#include "NxpCECAdapterDetection.h" +#include "TDA995xCECAdapterDetection.h" extern "C" { #define __cec_h__ @@ -44,7 +44,7 @@ extern "C" { using namespace CEC; -bool CNxpCECAdapterDetection::FindAdapter(void) +bool CTDA995xCECAdapterDetection::FindAdapter(void) { return access(CEC_TDA995x_PATH, 0) == 0; } diff --git a/src/lib/adapter/CuBox/NxpCECAdapterDetection.h b/src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.h similarity index 97% rename from src/lib/adapter/CuBox/NxpCECAdapterDetection.h rename to src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.h index dde82a2..5380663 100644 --- a/src/lib/adapter/CuBox/NxpCECAdapterDetection.h +++ b/src/lib/adapter/TDA995x/TDA995xCECAdapterDetection.h @@ -33,7 +33,7 @@ namespace CEC { - class CNxpCECAdapterDetection + class CTDA995xCECAdapterDetection { public: static bool FindAdapter(void); diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 5137cfb..5fe6d4d 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -1066,6 +1066,26 @@ bool CCECBusDevice::TransmitPendingActiveSourceCommands(void) return bReturn; } +void CCECBusDevice::SetActiveRoute(uint16_t iRoute) +{ + CCECDeviceMap* map = m_processor->GetDevices(); + if (!map) + return; + + CCECBusDevice* previouslyActive = map->GetActiveSource(); + if (!previouslyActive) + return; + + CECDEVICEVEC devices; + m_processor->GetDevices()->GetChildrenOf(devices, this); + + for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) + { + if (!CCECTypeUtils::PhysicalAddressIsIncluded(iRoute, (*it)->GetCurrentPhysicalAddress())) + (*it)->MarkAsInactiveSource(); + } +} + void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */) { CLockObject lock(m_mutex); diff --git a/src/lib/devices/CECBusDevice.h b/src/lib/devices/CECBusDevice.h index fad7191..6cba39f 100644 --- a/src/lib/devices/CECBusDevice.h +++ b/src/lib/devices/CECBusDevice.h @@ -224,6 +224,7 @@ namespace CEC virtual bool TransmitImageViewOn(void); virtual bool TransmitInactiveSource(void); virtual bool TransmitPendingActiveSourceCommands(void); + virtual void SetActiveRoute(uint16_t iRoute); virtual void SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress = CEC_INVALID_PHYSICAL_ADDRESS); virtual bool PowerOn(const cec_logical_address initiator); diff --git a/src/lib/devices/CECDeviceMap.cpp b/src/lib/devices/CECDeviceMap.cpp index a21b2b4..23e7a6f 100644 --- a/src/lib/devices/CECDeviceMap.cpp +++ b/src/lib/devices/CECDeviceMap.cpp @@ -39,6 +39,7 @@ #include "CECTuner.h" #include "CECTV.h" #include "lib/CECProcessor.h" +#include "lib/CECTypeUtils.h" using namespace std; using namespace CEC; @@ -266,3 +267,19 @@ cec_logical_addresses CCECDeviceMap::ToLogicalAddresses(const CECDEVICEVEC &devi addresses.Set((*it)->GetLogicalAddress()); return addresses; } + +void CCECDeviceMap::GetChildrenOf(CECDEVICEVEC& devices, CCECBusDevice* device) const +{ + devices.clear(); + if (!device) + return; + + uint16_t iPA = device->GetCurrentPhysicalAddress(); + + for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++) + { + uint16_t iCurrentPA = it->second->GetCurrentPhysicalAddress(); + if (CCECTypeUtils::PhysicalAddressIsIncluded(iPA, iCurrentPA)) + devices.push_back(it->second); + } +} diff --git a/src/lib/devices/CECDeviceMap.h b/src/lib/devices/CECDeviceMap.h index d4af816..c27a2dd 100644 --- a/src/lib/devices/CECDeviceMap.h +++ b/src/lib/devices/CECDeviceMap.h @@ -62,6 +62,7 @@ namespace CEC void GetByLogicalAddresses(CECDEVICEVEC &devices, const cec_logical_addresses &addresses); void GetActive(CECDEVICEVEC &devices) const; void GetByType(const cec_device_type type, CECDEVICEVEC &devices) const; + void GetChildrenOf(CECDEVICEVEC& devices, CCECBusDevice* device) const; void GetPowerOffDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const; void GetWakeDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const; diff --git a/src/lib/implementations/ANCommandHandler.cpp b/src/lib/implementations/ANCommandHandler.cpp index 648f4a0..92b4464 100644 --- a/src/lib/implementations/ANCommandHandler.cpp +++ b/src/lib/implementations/ANCommandHandler.cpp @@ -68,23 +68,9 @@ int CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command) cec_keypress key; key.duration = CEC_BUTTON_TIMEOUT; - key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN; + key.keycode = (cec_user_control_code)command.parameters[0]; - switch (command.parameters[0]) - { - case CEC_USER_CONTROL_CODE_AN_RETURN: - key.keycode = client && client->GetClientVersion() >= CEC_CLIENT_VERSION_1_5_0 ? - CEC_USER_CONTROL_CODE_AN_RETURN : - CEC_USER_CONTROL_CODE_EXIT; - break; - case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST: - key.keycode = CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST; - break; - default: - break; - } - - if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN && client) + if (client) client->AddKey(key); return COMMAND_HANDLED; diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 5398513..3b0187a 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -488,13 +488,11 @@ int CCECCommandHandler::HandleRoutingChange(const cec_command &command) { if (command.parameters.size == 4) { - uint16_t iOldAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); - uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]); - CCECBusDevice *device = GetDevice(command.initiator); if (device) { - device->SetStreamPath(iNewAddress, iOldAddress); + uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]); + device->SetActiveRoute(iNewAddress); return COMMAND_HANDLED; } } @@ -506,11 +504,11 @@ int CCECCommandHandler::HandleRoutingInformation(const cec_command &command) { if (command.parameters.size == 2) { - uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); - CCECBusDevice *device = m_processor->GetDeviceByPhysicalAddress(iNewAddress); + CCECBusDevice *device = GetDevice(command.initiator); if (device) { - device->MarkAsActiveSource(); + uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); + device->SetActiveRoute(iNewAddress); return COMMAND_HANDLED; } } @@ -570,9 +568,6 @@ int CCECCommandHandler::HandleSetStreamPath(const cec_command &command) uint16_t iStreamAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s (%x) sets stream path to physical address %04x", ToString(command.initiator), command.initiator, iStreamAddress); - // a device will only change the stream path when it's powered on - m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON); - /* one of the device handled by libCEC has been made active */ CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress); if (device && device->IsHandledByLibCEC()) @@ -678,13 +673,15 @@ int CCECCommandHandler::HandleUserControlPressed(const cec_command &command) client->SetCurrentButton((cec_user_control_code) command.parameters[0]); if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER || - command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION) + command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION|| + command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION) { bool bPowerOn(true); - // CEC_USER_CONTROL_CODE_POWER operates as a toggle + // CEC_USER_CONTROL_CODE_POWER and CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION operate as a toggle // assume CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION does not - if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER) + if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER || + command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION) { cec_power_status status = device->GetCurrentPowerStatus(); bPowerOn = !(status == CEC_POWER_STATUS_ON || status == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON); @@ -701,6 +698,12 @@ int CCECCommandHandler::HandleUserControlPressed(const cec_command &command) device->SetMenuState(CEC_MENU_STATE_DEACTIVATED); } } + else if (command.parameters[0] != CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION) + { + // we're not marked as active source, but the tv sends keypresses to us, so assume it forgot to activate us + if (!device->IsActiveSource() && command.initiator == CECDEVICE_TV) + device->ActivateSource(); + } return COMMAND_HANDLED; } @@ -723,6 +726,15 @@ int CCECCommandHandler::HandleVendorCommand(const cec_command & UNUSED(command)) return CEC_ABORT_REASON_INVALID_OPERAND; } +int CCECCommandHandler::HandleVendorRemoteButtonDown(const cec_command& command) +{ + if (command.parameters.size == 0) + return CEC_ABORT_REASON_INVALID_OPERAND; + + LIB_CEC->AddLog(CEC_LOG_NOTICE, "unhandled vendor remote button received with keycode %x", command.parameters[0]); + return COMMAND_HANDLED; +} + void CCECCommandHandler::UnhandledCommand(const cec_command &command, const cec_abort_reason reason) { if (m_processor->IsHandledByLibCEC(command.destination)) diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 1a6cd56..b09f9b3 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -135,8 +135,8 @@ namespace CEC virtual int HandleUserControlPressed(const cec_command &command); virtual int HandleUserControlRelease(const cec_command &command); virtual int HandleVendorCommand(const cec_command &command); - virtual int HandleVendorRemoteButtonDown(const cec_command & UNUSED(command)) { return CEC_ABORT_REASON_REFUSED; } - virtual int HandleVendorRemoteButtonUp(const cec_command & UNUSED(command)) { return CEC_ABORT_REASON_REFUSED; } + virtual int HandleVendorRemoteButtonDown(const cec_command& command); + virtual int HandleVendorRemoteButtonUp(const cec_command & UNUSED(command)) { return COMMAND_HANDLED; } virtual void UnhandledCommand(const cec_command &command, const cec_abort_reason reason); virtual void VendorPreActivateSourceHook(void) {}; diff --git a/src/lib/implementations/SLCommandHandler.cpp b/src/lib/implementations/SLCommandHandler.cpp index f495b8b..7c9579d 100644 --- a/src/lib/implementations/SLCommandHandler.cpp +++ b/src/lib/implementations/SLCommandHandler.cpp @@ -115,19 +115,13 @@ int CSLCommandHandler::HandleActiveSource(const cec_command &command) if (command.parameters.size == 2) { uint16_t iAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); - CCECBusDevice *primary = m_processor->GetPrimaryDevice(); - bool bSendPowerOffState(iAddress != primary->GetCurrentPhysicalAddress() && primary->IsActiveSource()); - CCECBusDevice *device = m_processor->GetDeviceByPhysicalAddress(iAddress); if (device) device->MarkAsActiveSource(); - if (bSendPowerOffState) + { - { - CLockObject lock(m_SLMutex); - m_bActiveSourceSent = false; - } - primary->TransmitPowerState(CECDEVICE_TV, false); + CLockObject lock(m_SLMutex); + m_bActiveSourceSent = false; } return COMMAND_HANDLED; @@ -273,7 +267,7 @@ int CSLCommandHandler::HandleGiveDeckStatus(const cec_command &command) if (!device || command.parameters.size == 0) return CEC_ABORT_REASON_INVALID_OPERAND; - device->SetDeckStatus(!device->IsActiveSource() ? CEC_DECK_INFO_OTHER_STATUS : CEC_DECK_INFO_OTHER_STATUS_LG); + device->SetDeckStatus(CEC_DECK_INFO_OTHER_STATUS_LG); if (command.parameters[0] == CEC_STATUS_REQUEST_ON) { device->TransmitDeckStatus(command.initiator, true); diff --git a/src/lib/implementations/SLCommandHandler.h b/src/lib/implementations/SLCommandHandler.h index 2cbef7b..ec2a4ae 100644 --- a/src/lib/implementations/SLCommandHandler.h +++ b/src/lib/implementations/SLCommandHandler.h @@ -68,6 +68,7 @@ namespace CEC int HandleStandby(const cec_command &command); bool TransmitMenuState(const cec_logical_address UNUSED(iInitiator), const cec_logical_address UNUSED(iDestination), cec_menu_state UNUSED(menuState), bool UNUSED(bIsReply)) { return true; } bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination); + int HandleVendorRemoteButtonUp(const cec_command& command) { return HandleUserControlRelease(command); } void ResetSLState(void); bool SLInitialised(void); diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp index 2050ee9..d73d4cb 100644 --- a/src/testclient/main.cpp +++ b/src/testclient/main.cpp @@ -48,7 +48,7 @@ using namespace CEC; using namespace std; using namespace PLATFORM; -#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_2; +#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_3; #include "../../include/cecloader.h"