From: Lars Op den Kamp Date: Tue, 28 Oct 2014 15:19:42 +0000 (+0100) Subject: Release 2.2.0 X-Git-Tag: upstream/2.2.0~1^2~1 X-Git-Url: https://git.piment-noir.org/?p=deb_libcec.git;a=commitdiff_plain;h=b45bdacdeee5c96e0294717fbe2c47a49a110fd1;hp=81e38211724bc6e8bd7a60f484433053ed682635 Release 2.2.0 --- diff --git a/COPYING b/COPYING index c19af3b..b2a8590 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,6 @@ This file is part of the libCEC(R) library. -libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. +libCEC(R) is Copyright (C) 2011-2014 Pulse-Eight Limited. All rights reserved. libCEC(R) is a original work, containing original code. libCEC(R) is a trademark of Pulse-Eight Limited. diff --git a/ChangeLog b/ChangeLog index 8ef4b35..862c347 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +libcec (2.2.0-1) unstable; urgency=low + + * changed / added: + * read the physical address from X11 randr extension. credits: @smithereens + * support for Exynos HDMI. credits: @vamanea + * another vendor ID for Harman/Kardon. credits: @ksooo + * some 1.4 keycodes have been added. credits: @ksooo + * cec-client: fix typo prevent keycodes to be passed. credits: @popcornmix + + * fixed: + * various Raspberry Pi fixes. credits: @mk01 + * vendor specific handlers weren't used for Toshiba and Onkyo. + credits: @ksooo + * LibCecTray: keypress not sent when multiple instances of eshell.exe are + running. thanks @pvanbaren + * deadlock on exit in XBMC, because of CEC_ALERT_CONNECTION_LOST + + -- Pulse-Eight Packaging Tue, 28 Oct 2014 10:45:00 +0200 + libcec (2.1.4-2) unstable; urgency=low * fixed: diff --git a/configure.ac b/configure.ac index 510d851..2612d55 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,13 @@ AC_ARG_WITH([tda995x-toolkit-path], [TDA995X_CFLAGS="-I$withval/inc"], [TDA995X_CFLAGS="-I\$(abs_top_srcdir)/nxp_hdmi/inc"]) +## Exynos support +AC_ARG_ENABLE([exynos], + [AS_HELP_STRING([--enable-exynos], + [enable support for the Exynos (default is yes)])], + [use_exynos=$enableval], + [use_exynos=yes]) + ## Raspberry Pi support AC_ARG_ENABLE([rpi], [AS_HELP_STRING([--enable-rpi], @@ -206,6 +213,21 @@ case "${host}" in LIBS="$libs_pre_rpi" fi fi + ## search for X11/xrandr + libs_tmp="$LIBS" + use_x11_xrandr="yes" + AC_CHECK_HEADER(X11/Xlib.h,,[use_x11_xrandr="no"]) + AC_CHECK_HEADER(X11/Xatom.h,,[use_x11_xrandr="no"]) + AC_CHECK_HEADER(X11/extensions/Xrandr.h,,[use_x11_xrandr="no"]) + AC_CHECK_LIB(X11,XOpenDisplay,,[use_x11_xrandr="no"]) + AC_CHECK_LIB(Xrandr,XRRGetScreenResources,,[use_x11_xrandr="no"]) + if test "x$use_x11_xrandr" = "xyes"; then + AC_DEFINE([HAVE_RANDR],[1],[Define to 1 to include support for the X11 randr extension]) + AM_CONDITIONAL(USE_X11_RANDR, true) + else + AM_CONDITIONAL(USE_X11_RANDR, false) + LIBS="$libs_tmp" + fi ;; *-apple-darwin*) AC_CHECK_HEADER(mach/mach_time.h,,AC_MSG_ERROR($msg_required_header_missing)) @@ -270,6 +292,19 @@ else features="$features\n TDA995x support :\t\t\tno" fi +## mark Exynos support as available +if test "x$use_exynos" != "xno"; then + AC_DEFINE([HAVE_EXYNOS_API],[1],[Define to 1 to include Exynos support]) + AM_CONDITIONAL(USE_EXYNOS_API, true) + features="$features\n Exynos support :\t\t\tyes" + LIB_INFO="$LIB_INFO 'EXYNOS'" + CPPFLAGS="$CPPFLAGS $EXYNOS_CFLAGS" +else + AM_CONDITIONAL(USE_EXYNOS_API, false) + features="$features\n EXYNOS support :\t\t\tno" +fi + + ## check if our build system is complete AC_CHECK_HEADER(algorithm,,AC_MSG_ERROR($msg_required_header_missing)) AC_CHECK_HEADER(ctype.h,,AC_MSG_ERROR($msg_required_header_missing)) diff --git a/debian/changelog b/debian/changelog index 8ef4b35..862c347 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +libcec (2.2.0-1) unstable; urgency=low + + * changed / added: + * read the physical address from X11 randr extension. credits: @smithereens + * support for Exynos HDMI. credits: @vamanea + * another vendor ID for Harman/Kardon. credits: @ksooo + * some 1.4 keycodes have been added. credits: @ksooo + * cec-client: fix typo prevent keycodes to be passed. credits: @popcornmix + + * fixed: + * various Raspberry Pi fixes. credits: @mk01 + * vendor specific handlers weren't used for Toshiba and Onkyo. + credits: @ksooo + * LibCecTray: keypress not sent when multiple instances of eshell.exe are + running. thanks @pvanbaren + * deadlock on exit in XBMC, because of CEC_ALERT_CONNECTION_LOST + + -- Pulse-Eight Packaging Tue, 28 Oct 2014 10:45:00 +0200 + libcec (2.1.4-2) unstable; urgency=low * fixed: diff --git a/include/cectypes.h b/include/cectypes.h index 9f86253..0a90d0e 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -80,9 +80,11 @@ namespace CEC { #define CEC_BUTTON_TIMEOUT 500 /*! - * don't send the same key twice within this timeout in milliseconds + * don't send the same key twice within this timeout in units of 50 milliseconds + * 4 = 200ms */ -#define CEC_DOUBLE_TAP_TIMEOUT_MS 250 +#define CEC_DOUBLE_TAP_TIMEOUT_50_MS 4 +#define CEC_DOUBLE_TAP_TIMEOUT_MS_OLD 200 /*! * don't query the power state for the same device within this timeout in milliseconds @@ -294,6 +296,16 @@ namespace CEC { */ #define CEC_TDA995x_VIRTUAL_COM "CuBox" +/*! + * the path to use for the Exynos HDMI CEC device + */ +#define CEC_EXYNOS_PATH "/dev/CEC" + +/*! + * the name of the virtual COM port to use for the EXYNOS' CEC wire + */ +#define CEC_EXYNOS_VIRTUAL_COM "Exynos" + /*! * Mimimum client version */ @@ -312,13 +324,15 @@ namespace CEC { /*! * libCEC's minor version number */ -#define CEC_LIB_VERSION_MINOR 1 +#define CEC_LIB_VERSION_MINOR 2 #define MSGSTART 0xFF #define MSGEND 0xFE #define MSGESC 0xFD #define ESCOFFSET 3 +#define DOUBLE_TAP_TIMEOUT_UNIT_SIZE (50) + // defines to make compile time checks for certain features easy #define CEC_FEATURE_CONFIGURABLE_COMBO_KEY 1 @@ -636,6 +650,13 @@ typedef enum cec_user_control_code CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B, CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C, CEC_USER_CONTROL_CODE_EXIT = 0x0D, + // reserved: 0x0E, 0x0F + CEC_USER_CONTROL_CODE_TOP_MENU = 0x10, + CEC_USER_CONTROL_CODE_DVD_MENU = 0x11, + // reserved: 0x12 ... 0x1C + CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE = 0x1D, + CEC_USER_CONTROL_CODE_NUMBER11 = 0x1E, + CEC_USER_CONTROL_CODE_NUMBER12 = 0x1F, CEC_USER_CONTROL_CODE_NUMBER0 = 0x20, CEC_USER_CONTROL_CODE_NUMBER1 = 0x21, CEC_USER_CONTROL_CODE_NUMBER2 = 0x22, @@ -659,6 +680,7 @@ typedef enum cec_user_control_code CEC_USER_CONTROL_CODE_HELP = 0x36, CEC_USER_CONTROL_CODE_PAGE_UP = 0x37, CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38, + // reserved: 0x39 ... 0x3F CEC_USER_CONTROL_CODE_POWER = 0x40, CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41, CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42, @@ -674,12 +696,16 @@ typedef enum cec_user_control_code CEC_USER_CONTROL_CODE_BACKWARD = 0x4C, CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D, CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E, + // reserved: 0x4F CEC_USER_CONTROL_CODE_ANGLE = 0x50, CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51, CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52, CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53, CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54, CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55, + CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE = 0x56, + CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION = 0x57, + // reserved: 0x58 ... 0x5F CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60, CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61, CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62, @@ -694,14 +720,16 @@ typedef enum cec_user_control_code CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B, CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C, CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D, + // reserved: 0x6E ... 0x70 CEC_USER_CONTROL_CODE_F1_BLUE = 0x71, CEC_USER_CONTROL_CODE_F2_RED = 0X72, CEC_USER_CONTROL_CODE_F3_GREEN = 0x73, CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74, CEC_USER_CONTROL_CODE_F5 = 0x75, CEC_USER_CONTROL_CODE_DATA = 0x76, - CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, - CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, + // reserved: 0x77 ... 0xFF + CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, // return (Samsung) + CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, // channels list (Samsung) CEC_USER_CONTROL_CODE_MAX = 0x96, CEC_USER_CONTROL_CODE_UNKNOWN = 0xFF } cec_user_control_code; @@ -825,31 +853,32 @@ typedef enum cec_bus_device_status typedef enum cec_vendor_id { - CEC_VENDOR_TOSHIBA = 0x000039, - CEC_VENDOR_SAMSUNG = 0x0000F0, - CEC_VENDOR_DENON = 0x0005CD, - CEC_VENDOR_MARANTZ = 0x000678, - CEC_VENDOR_LOEWE = 0x000982, - CEC_VENDOR_ONKYO = 0x0009B0, - CEC_VENDOR_MEDION = 0x000CB8, - CEC_VENDOR_TOSHIBA2 = 0x000CE7, - CEC_VENDOR_PULSE_EIGHT = 0x001582, - CEC_VENDOR_AKAI = 0x0020C7, - CEC_VENDOR_AOC = 0x002467, - CEC_VENDOR_PANASONIC = 0x008045, - CEC_VENDOR_PHILIPS = 0x00903E, - CEC_VENDOR_DAEWOO = 0x009053, - CEC_VENDOR_YAMAHA = 0x00A0DE, - CEC_VENDOR_GRUNDIG = 0x00D0D5, - CEC_VENDOR_PIONEER = 0x00E036, - CEC_VENDOR_LG = 0x00E091, - CEC_VENDOR_SHARP = 0x08001F, - CEC_VENDOR_SONY = 0x080046, - CEC_VENDOR_BROADCOM = 0x18C086, - CEC_VENDOR_VIZIO = 0x6B746D, - CEC_VENDOR_BENQ = 0x8065E9, - CEC_VENDOR_HARMAN_KARDON = 0x9C645E, - CEC_VENDOR_UNKNOWN = 0 + CEC_VENDOR_TOSHIBA = 0x000039, + CEC_VENDOR_SAMSUNG = 0x0000F0, + CEC_VENDOR_DENON = 0x0005CD, + CEC_VENDOR_MARANTZ = 0x000678, + CEC_VENDOR_LOEWE = 0x000982, + CEC_VENDOR_ONKYO = 0x0009B0, + CEC_VENDOR_MEDION = 0x000CB8, + CEC_VENDOR_TOSHIBA2 = 0x000CE7, + CEC_VENDOR_PULSE_EIGHT = 0x001582, + CEC_VENDOR_HARMAN_KARDON2 = 0x001950, + CEC_VENDOR_AKAI = 0x0020C7, + CEC_VENDOR_AOC = 0x002467, + CEC_VENDOR_PANASONIC = 0x008045, + CEC_VENDOR_PHILIPS = 0x00903E, + CEC_VENDOR_DAEWOO = 0x009053, + CEC_VENDOR_YAMAHA = 0x00A0DE, + CEC_VENDOR_GRUNDIG = 0x00D0D5, + CEC_VENDOR_PIONEER = 0x00E036, + CEC_VENDOR_LG = 0x00E091, + CEC_VENDOR_SHARP = 0x08001F, + CEC_VENDOR_SONY = 0x080046, + CEC_VENDOR_BROADCOM = 0x18C086, + CEC_VENDOR_VIZIO = 0x6B746D, + CEC_VENDOR_BENQ = 0x8065E9, + CEC_VENDOR_HARMAN_KARDON = 0x9C645E, + CEC_VENDOR_UNKNOWN = 0 } cec_vendor_id; typedef enum cec_adapter_type @@ -858,7 +887,8 @@ typedef enum cec_adapter_type ADAPTERTYPE_P8_EXTERNAL = 0x1, ADAPTERTYPE_P8_DAUGHTERBOARD = 0x2, ADAPTERTYPE_RPI = 0x100, - ADAPTERTYPE_TDA995x = 0x200 + ADAPTERTYPE_TDA995x = 0x200, + ADAPTERTYPE_EXYNOS = 0x300 } cec_adapter_type; typedef struct cec_menu_language @@ -1424,7 +1454,8 @@ typedef enum cec_client_version CEC_CLIENT_VERSION_2_1_2 = 0x2102, CEC_CLIENT_VERSION_2_1_3 = 0x2103, CEC_CLIENT_VERSION_2_1_4 = 0x2104, - CEC_CLIENT_VERSION_CURRENT = 0x2104 + CEC_CLIENT_VERSION_2_2_0 = 0x2200, + CEC_CLIENT_VERSION_CURRENT = 0x2200 } cec_client_version; typedef enum cec_server_version @@ -1457,7 +1488,8 @@ typedef enum cec_server_version CEC_SERVER_VERSION_2_1_2 = 0x2102, CEC_SERVER_VERSION_2_1_3 = 0x2103, CEC_SERVER_VERSION_2_1_4 = 0x2104, - CEC_SERVER_VERSION_CURRENT = 0x2104 + CEC_SERVER_VERSION_2_2_0 = 0x2200, + CEC_SERVER_VERSION_CURRENT = 0x2200 } cec_server_version; struct libcec_configuration @@ -1496,7 +1528,8 @@ struct libcec_configuration uint8_t bMonitorOnly; /*!< won't allocate a CCECClient when starting the connection when set (same as monitor mode). added in 1.6.3 */ cec_version cecVersion; /*!< CEC spec version to use by libCEC. defaults to v1.4. added in 1.8.0 */ cec_adapter_type adapterType; /*!< type of the CEC adapter that we're connected to. added in 1.8.2 */ - uint8_t iDoubleTapTimeoutMs; /*!< prevent double taps withing this timeout. defaults to 200ms. added in 2.0.0 */ + uint8_t iDoubleTapTimeout50Ms; /*!< prevent double taps withing this timeout, in units of 50ms. defaults to 200ms (value: 4). added in 2.0.0, + XXX changed meaning in 2.2.0 to not break binary compatibility. next major (3.0) release will fix it in a nicer way */ cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_F1_BLUE. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */ uint32_t iComboKeyTimeoutMs; /*!< timeout until the combo key is sent as normal keypress */ @@ -1508,34 +1541,34 @@ struct libcec_configuration { return ( clientVersion == other.clientVersion && !strncmp(strDeviceName, other.strDeviceName, 13) && - deviceTypes == other.deviceTypes && - bAutodetectAddress == other.bAutodetectAddress && - iPhysicalAddress == other.iPhysicalAddress && - baseDevice == other.baseDevice && - iHDMIPort == other.iHDMIPort && - tvVendor == other.tvVendor && - wakeDevices == other.wakeDevices && - powerOffDevices == other.powerOffDevices && - serverVersion == other.serverVersion && - bGetSettingsFromROM == other.bGetSettingsFromROM && - bUseTVMenuLanguage == other.bUseTVMenuLanguage && - bActivateSource == other.bActivateSource && - bPowerOffScreensaver == other.bPowerOffScreensaver && - bPowerOffOnStandby == other.bPowerOffOnStandby && - bSendInactiveSource == other.bSendInactiveSource && - logicalAddresses == other.logicalAddresses && - iFirmwareVersion == other.iFirmwareVersion && - bPowerOffDevicesOnStandby == other.bPowerOffDevicesOnStandby && - bShutdownOnStandby == other.bShutdownOnStandby && + deviceTypes == other.deviceTypes && + bAutodetectAddress == other.bAutodetectAddress && + iPhysicalAddress == other.iPhysicalAddress && + baseDevice == other.baseDevice && + iHDMIPort == other.iHDMIPort && + tvVendor == other.tvVendor && + wakeDevices == other.wakeDevices && + powerOffDevices == other.powerOffDevices && + serverVersion == other.serverVersion && + bGetSettingsFromROM == other.bGetSettingsFromROM && + bUseTVMenuLanguage == other.bUseTVMenuLanguage && + bActivateSource == other.bActivateSource && + bPowerOffScreensaver == other.bPowerOffScreensaver && + bPowerOffOnStandby == other.bPowerOffOnStandby && + bSendInactiveSource == other.bSendInactiveSource && + logicalAddresses == other.logicalAddresses && + iFirmwareVersion == other.iFirmwareVersion && + bPowerOffDevicesOnStandby == other.bPowerOffDevicesOnStandby && + bShutdownOnStandby == other.bShutdownOnStandby && !strncmp(strDeviceLanguage, other.strDeviceLanguage, 3) && - iFirmwareBuildDate == other.iFirmwareBuildDate && - bMonitorOnly == other.bMonitorOnly && - cecVersion == other.cecVersion && - adapterType == other.adapterType && - iDoubleTapTimeoutMs == other.iDoubleTapTimeoutMs && - (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || comboKey == other.comboKey) && - (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || iComboKeyTimeoutMs == other.iComboKeyTimeoutMs) && - (other.clientVersion < CEC_CLIENT_VERSION_2_1_0 || bPowerOnScreensaver == other.bPowerOnScreensaver)); + iFirmwareBuildDate == other.iFirmwareBuildDate && + bMonitorOnly == other.bMonitorOnly && + cecVersion == other.cecVersion && + adapterType == other.adapterType && + iDoubleTapTimeout50Ms == other.iDoubleTapTimeout50Ms && + (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || comboKey == other.comboKey) && + (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || iComboKeyTimeoutMs == other.iComboKeyTimeoutMs) && + (other.clientVersion < CEC_CLIENT_VERSION_2_1_0 || bPowerOnScreensaver == other.bPowerOnScreensaver)); } bool operator!=(const libcec_configuration &other) const @@ -1570,7 +1603,7 @@ struct libcec_configuration bMonitorOnly = 0; cecVersion = (cec_version)CEC_DEFAULT_SETTING_CEC_VERSION; adapterType = ADAPTERTYPE_UNKNOWN; - iDoubleTapTimeoutMs = CEC_DOUBLE_TAP_TIMEOUT_MS; + iDoubleTapTimeout50Ms = CEC_DOUBLE_TAP_TIMEOUT_50_MS; comboKey = CEC_USER_CONTROL_CODE_STOP; iComboKeyTimeoutMs = CEC_DEFAULT_COMBO_TIMEOUT_MS; diff --git a/project/libcec/libcec.rc b/project/libcec/libcec.rc index a302d99..0505a8d 100644 Binary files a/project/libcec/libcec.rc and b/project/libcec/libcec.rc differ diff --git a/project/testclient/testclient.rc b/project/testclient/testclient.rc index 5990a9c..8d422ec 100644 Binary files a/project/testclient/testclient.rc and b/project/testclient/testclient.rc differ diff --git a/src/CecSharpTester/Properties/AssemblyInfo.cs b/src/CecSharpTester/Properties/AssemblyInfo.cs index cb4952f..4f52c1b 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.1.4.0")] -[assembly: AssemblyFileVersion("2.1.4.0")] +[assembly: AssemblyVersion("2.2.0.0")] +[assembly: AssemblyFileVersion("2.2.0.0")] diff --git a/src/LibCecSharp/AssemblyInfo.cpp b/src/LibCecSharp/AssemblyInfo.cpp index 19f1b43..386b69c 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.1.4.0")]; +[assembly:AssemblyVersionAttribute("2.2.0.0")]; [assembly:ComVisible(false)]; [assembly:CLSCompliantAttribute(true)]; diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index 2de94bf..74afce6 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -784,31 +784,32 @@ namespace CecSharp /// public enum class CecVendorId { - Toshiba = 0x000039, - Samsung = 0x0000F0, - Denon = 0x0005CD, - Marantz = 0x000678, - Loewe = 0x000982, - Onkyo = 0x0009B0, - Medion = 0x000CB8, - Toshiba2 = 0x000CE7, - PulseEight = 0x001582, - Akai = 0x0020C7, - AOC = 0x002467, - Panasonic = 0x008045, - Philips = 0x00903E, - Daewoo = 0x009053, - Yamaha = 0x00A0DE, - Grundig = 0x00D0D5, - Pioneer = 0x00E036, - LG = 0x00E091, - Sharp = 0x08001F, - Sony = 0x080046, - Broadcom = 0x18C086, - Vizio = 0x6B746D, - Benq = 0x8065E9, - HarmanKardon = 0x9C645E, - Unknown = 0 + Toshiba = 0x000039, + Samsung = 0x0000F0, + Denon = 0x0005CD, + Marantz = 0x000678, + Loewe = 0x000982, + Onkyo = 0x0009B0, + Medion = 0x000CB8, + Toshiba2 = 0x000CE7, + PulseEight = 0x001582, + HarmanKardon2 = 0x001950, + Akai = 0x0020C7, + AOC = 0x002467, + Panasonic = 0x008045, + Philips = 0x00903E, + Daewoo = 0x009053, + Yamaha = 0x00A0DE, + Grundig = 0x00D0D5, + Pioneer = 0x00E036, + LG = 0x00E091, + Sharp = 0x08001F, + Sony = 0x080046, + Broadcom = 0x18C086, + Vizio = 0x6B746D, + Benq = 0x8065E9, + HarmanKardon = 0x9C645E, + Unknown = 0 }; /// @@ -1232,10 +1233,14 @@ namespace CecSharp /// v2.1.4 /// Version2_1_4 = 0x2104, - /// + /// + /// v2.1.4 + /// + Version2_2_0 = 0x2200, + /// /// The current version /// - CurrentVersion = 0x2104 + CurrentVersion = 0x2200 }; /// @@ -1351,14 +1356,18 @@ namespace CecSharp /// v2.1.3 /// Version2_1_3 = 0x2103, - /// + /// /// v2.1.4 /// Version2_1_4 = 0x2104, /// + /// v2.2.0 + /// + Version2_2_0 = 0x2200, + /// /// The current version /// - CurrentVersion = 0x2104 + CurrentVersion = 0x2200 }; /// diff --git a/src/LibCecTray/Properties/AssemblyInfo.cs b/src/LibCecTray/Properties/AssemblyInfo.cs index 8d6e8ed..ed4ac9f 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.1.4.0")] -[assembly: AssemblyFileVersion("2.1.4.0")] +[assembly: AssemblyVersion("2.2.0.0")] +[assembly: AssemblyFileVersion("2.2.0.0")] diff --git a/src/LibCecTray/controller/applications/ApplicationController.cs b/src/LibCecTray/controller/applications/ApplicationController.cs index 3c7b83f..b4c6120 100644 --- a/src/LibCecTray/controller/applications/ApplicationController.cs +++ b/src/LibCecTray/controller/applications/ApplicationController.cs @@ -273,7 +273,12 @@ namespace LibCECTray.controller.applications protected virtual IntPtr FindInstance() { var processes = Process.GetProcessesByName(ProcessName); - return processes.Length > 0 ? processes[0].MainWindowHandle : IntPtr.Zero; + foreach (var process in processes) + { + if (process.MainWindowHandle != IntPtr.Zero) + return process.MainWindowHandle; + } + return IntPtr.Zero; } #endregion diff --git a/src/lib/CECClient.cpp b/src/lib/CECClient.cpp index 85df46d..0bc9705 100644 --- a/src/lib/CECClient.cpp +++ b/src/lib/CECClient.cpp @@ -876,7 +876,7 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) m_configuration.bMonitorOnly = configuration.bMonitorOnly; m_configuration.cecVersion = configuration.cecVersion; m_configuration.adapterType = configuration.adapterType; - m_configuration.iDoubleTapTimeoutMs = configuration.iDoubleTapTimeoutMs; + m_configuration.iDoubleTapTimeout50Ms = configuration.iDoubleTapTimeout50Ms; m_configuration.deviceTypes.Add(configuration.deviceTypes[0]); if (m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5) @@ -995,7 +995,7 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */) void CCECClient::AddKey(const cec_keypress &key) { - if (key.keycode > CEC_USER_CONTROL_CODE_MAX && + if (key.keycode > CEC_USER_CONTROL_CODE_MAX || key.keycode < CEC_USER_CONTROL_CODE_SELECT) { // send back the previous key if there is one @@ -1457,6 +1457,14 @@ void CCECClient::CallbackAddCommand(const cec_command &command) m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command); } +uint32_t CCECClient::DoubleTapTimeoutMS(void) +{ + CLockObject lock(m_cbMutex); + return m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_2_0 ? + m_configuration.iDoubleTapTimeout50Ms * DOUBLE_TAP_TIMEOUT_UNIT_SIZE : + m_configuration.iDoubleTapTimeout50Ms; +} + void CCECClient::CallbackAddKey(const cec_keypress &key) { CLockObject lock(m_cbMutex); @@ -1466,7 +1474,7 @@ void CCECClient::CallbackAddKey(const cec_keypress &key) int64_t now = GetTimeMs(); if (m_lastKeypress.keycode != key.keycode || key.duration > 0 || - now - m_iLastKeypressTime >= m_configuration.iDoubleTapTimeoutMs) + now - m_iLastKeypressTime >= DoubleTapTimeoutMS()) { // no double tap if (key.duration == 0) diff --git a/src/lib/CECClient.h b/src/lib/CECClient.h index ba76736..3ef0453 100644 --- a/src/lib/CECClient.h +++ b/src/lib/CECClient.h @@ -302,6 +302,8 @@ namespace CEC virtual int CallbackMenuStateChanged(const cec_menu_state newState); virtual void CallbackSourceActivated(bool bActivated, const cec_logical_address logicalAddress); + uint32_t DoubleTapTimeoutMS(void); + CCECProcessor * m_processor; /**< a pointer to the processor */ libcec_configuration m_configuration; /**< the configuration of this client */ bool m_bInitialised; /**< true when initialised, false otherwise */ diff --git a/src/lib/CECTypeUtils.h b/src/lib/CECTypeUtils.h index dc4e5f1..64f5c21 100644 --- a/src/lib/CECTypeUtils.h +++ b/src/lib/CECTypeUtils.h @@ -520,6 +520,7 @@ namespace CEC case CEC_VENDOR_MARANTZ: return "Marantz"; case CEC_VENDOR_HARMAN_KARDON: + case CEC_VENDOR_HARMAN_KARDON2: return "Harman/Kardon"; case CEC_VENDOR_PULSE_EIGHT: return "Pulse Eight"; @@ -588,6 +589,8 @@ namespace CEC return "2.1.3"; case CEC_CLIENT_VERSION_2_1_4: return "2.1.4"; + case CEC_CLIENT_VERSION_2_2_0: + return "2.2.0"; default: return "Unknown"; } @@ -653,6 +656,8 @@ namespace CEC return "2.1.3"; case CEC_SERVER_VERSION_2_1_4: return "2.1.4"; + case CEC_SERVER_VERSION_2_2_0: + return "2.2.0"; default: return "Unknown"; } @@ -709,6 +714,16 @@ namespace CEC return "favourite menu"; case CEC_USER_CONTROL_CODE_EXIT: return "exit"; + case CEC_USER_CONTROL_CODE_TOP_MENU: + return "top menu"; + case CEC_USER_CONTROL_CODE_DVD_MENU: + return "dvd menu"; + case CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE: + return "number entry mode"; + case CEC_USER_CONTROL_CODE_NUMBER11: + return "11"; + case CEC_USER_CONTROL_CODE_NUMBER12: + return "12"; case CEC_USER_CONTROL_CODE_NUMBER0: return "0"; case CEC_USER_CONTROL_CODE_NUMBER1: @@ -797,6 +812,10 @@ namespace CEC return "timer programming"; case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: return "initial configuration"; + case CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE: + return "select broadcast type"; + case CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION: + return "select sound presentation"; case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: return "play (function)"; case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: diff --git a/src/lib/LibCECC.cpp b/src/lib/LibCECC.cpp index fc5c9c2..ecf4565 100644 --- a/src/lib/LibCECC.cpp +++ b/src/lib/LibCECC.cpp @@ -346,7 +346,7 @@ int cec_persist_configuration(libcec_configuration *configuration) return cec_parser ? (cec_parser->PersistConfiguration(configuration) ? 1 : 0) : -1; } -int cec_set_configuration(libcec_configuration *configuration) +int cec_set_configuration(const libcec_configuration *configuration) { return cec_parser ? (cec_parser->SetConfiguration(configuration) ? 1 : 0) : -1; } diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 9117d8e..bd9598f 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -44,6 +44,10 @@ libcec_la_SOURCES += adapter/Pulse-Eight/USBCECAdapterMessage.cpp \ platform/posix/os-edid.cpp \ platform/adl/adl-edid.cpp \ platform/nvidia/nv-edid.cpp +if USE_X11_RANDR +libcec_la_SOURCES += platform/X11/randr-edid.cpp +endif + endif ## Raspberry Pi support @@ -59,5 +63,10 @@ libcec_la_SOURCES += adapter/TDA995x/TDA995xCECAdapterDetection.cpp \ adapter/TDA995x/TDA995xCECAdapterCommunication.cpp endif +## Exynos support +if USE_EXYNOS_API +libcec_la_SOURCES += adapter/Exynos/ExynosCECAdapterDetection.cpp \ + adapter/Exynos/ExynosCECAdapterCommunication.cpp +endif libcec_la_LDFLAGS = @LIBS_LIBCEC@ -version-info @VERSION@ diff --git a/src/lib/adapter/AdapterFactory.cpp b/src/lib/adapter/AdapterFactory.cpp index 42cdd0b..d585154 100644 --- a/src/lib/adapter/AdapterFactory.cpp +++ b/src/lib/adapter/AdapterFactory.cpp @@ -52,6 +52,11 @@ #include "TDA995x/TDA995xCECAdapterCommunication.h" #endif +#if defined(HAVE_EXYNOS_API) +#include "Exynos/ExynosCECAdapterDetection.h" +#include "Exynos/ExynosCECAdapterCommunication.h" +#endif + using namespace std; using namespace CEC; @@ -109,6 +114,19 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 } #endif +#if defined(HAVE_EXYNOS_API) + if (iAdaptersFound < iBufSize && CExynosCECAdapterDetection::FindAdapter()) + { + snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_EXYNOS_PATH); + snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_EXYNOS_VIRTUAL_COM); + deviceList[iAdaptersFound].iVendorId = 0; + deviceList[iAdaptersFound].iProductId = 0; + deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_EXYNOS; + iAdaptersFound++; + } +#endif + + #if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" #endif @@ -123,6 +141,11 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ return new CTDA995xCECAdapterCommunication(m_lib->m_cec); #endif +#if defined(HAVE_EXYNOS_API) + if (!strcmp(strPort, CEC_EXYNOS_VIRTUAL_COM)) + return new CExynosCECAdapterCommunication(m_lib->m_cec); +#endif + #if defined(HAVE_RPI_API) if (!strcmp(strPort, CEC_RPI_VIRTUAL_COM)) return new CRPiCECAdapterCommunication(m_lib->m_cec); @@ -132,7 +155,7 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); #endif -#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) +#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) return NULL; #endif } diff --git a/src/lib/adapter/Exynos/ExynosCEC.h b/src/lib/adapter/Exynos/ExynosCEC.h new file mode 100644 index 0000000..55e1eec --- /dev/null +++ b/src/lib/adapter/Exynos/ExynosCEC.h @@ -0,0 +1,39 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + + +#define CEC_DEFAULT_PADDR 0x1000 +#define CEC_PADDR_NAME "/sys/module/s5p_hdmi/parameters/source_phy_addr" +#define CEC_IOC_SETLADDR _IOW('c', 0, unsigned int) +#define CEC_MAX_FRAME_SIZE 16 diff --git a/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.cpp b/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.cpp new file mode 100644 index 0000000..86e306b --- /dev/null +++ b/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.cpp @@ -0,0 +1,256 @@ +/* + * This file is part of the libCEC(R) library. + * + * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "env.h" +#include +#include + + +#if defined(HAVE_EXYNOS_API) +#include "ExynosCEC.h" +#include "ExynosCECAdapterCommunication.h" + +#include "lib/CECTypeUtils.h" +#include "lib/LibCEC.h" +#include "lib/platform/util/StdString.h" +#include "lib/platform/util/buffer.h" + +using namespace std; +using namespace CEC; +using namespace PLATFORM; + +#define LIB_CEC m_callback->GetLib() + + +CExynosCECAdapterCommunication::CExynosCECAdapterCommunication(IAdapterCommunicationCallback *callback) : + IAdapterCommunication(callback), + m_bLogicalAddressChanged(false) +{ + CLockObject lock(m_mutex); + + m_logicalAddresses.Clear(); + m_fd = INVALID_SOCKET_VALUE; +} + + +CExynosCECAdapterCommunication::~CExynosCECAdapterCommunication(void) +{ + Close(); +} + + +bool CExynosCECAdapterCommunication::IsOpen(void) +{ + return IsInitialised() && m_fd != INVALID_SOCKET_VALUE; +} + + +bool CExynosCECAdapterCommunication::Open(uint32_t UNUSED(iTimeoutMs), bool UNUSED(bSkipChecks), bool bStartListening) +{ + if (m_fd != INVALID_SOCKET_VALUE) + close(m_fd); + + if ((m_fd = open(CEC_EXYNOS_PATH, O_RDWR)) > 0) + { + if (!bStartListening || CreateThread()) { + return true; + } + close(m_fd); + } + return false; +} + + +void CExynosCECAdapterCommunication::Close(void) +{ + StopThread(0); + + close(m_fd); + m_fd = INVALID_SOCKET_VALUE; +} + + +std::string CExynosCECAdapterCommunication::GetError(void) const +{ + std::string strError(m_strError); + return strError; +} + + +cec_adapter_message_state CExynosCECAdapterCommunication::Write( + const cec_command &data, bool &UNUSED(bRetry), uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) +{ + uint8_t buffer[CEC_MAX_FRAME_SIZE]; + int32_t size = 1; + cec_adapter_message_state rc = ADAPTER_MESSAGE_STATE_ERROR; + + if (!IsOpen()) + return rc; + + if ((size_t)data.parameters.size + data.opcode_set > sizeof(buffer)) + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: data size too large !", __func__); + return ADAPTER_MESSAGE_STATE_ERROR; + } + + buffer[0] = (data.initiator << 4) | (data.destination & 0x0f); + + if (data.opcode_set) + { + buffer[1] = data.opcode; + size++; + + memcpy(&buffer[size], data.parameters.data, data.parameters.size); + size += data.parameters.size; + } + + if (write(m_fd, (void *)buffer, size) == size) + { + rc = ADAPTER_MESSAGE_STATE_SENT_ACKED; + } + else + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: write failed !", __func__); + } + + return rc; +} + + +uint16_t CExynosCECAdapterCommunication::GetFirmwareVersion(void) +{ + return 0; +} + + +cec_vendor_id CExynosCECAdapterCommunication::GetVendorId(void) +{ + return cec_vendor_id(CEC_VENDOR_SAMSUNG); +} + + +uint16_t CExynosCECAdapterCommunication::GetPhysicalAddress(void) +{ + uint16_t phys_addr = CEC_DEFAULT_PADDR; + + FILE *f = fopen(CEC_PADDR_NAME, "r"); + if(f) { + if(fscanf(f, "%hu", &phys_addr) != 1) + phys_addr = CEC_DEFAULT_PADDR; + + fclose(f); + } + return phys_addr; +} + + +cec_logical_addresses CExynosCECAdapterCommunication::GetLogicalAddresses(void) +{ + return m_logicalAddresses; +} + + +bool CExynosCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) +{ + unsigned int log_addr = addresses.primary; + CLockObject lock(m_mutex); + + if (!IsOpen()) + return false; + + if (ioctl(m_fd, CEC_IOC_SETLADDR, &log_addr)) + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: IOCTL SetLogicalAddr failed !", __func__); + return false; + } + m_logicalAddresses = addresses; + m_bLogicalAddressChanged = true; + + return true; +} + + +void CExynosCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) +{ + unsigned int log_addr = CECDEVICE_BROADCAST; + if (ioctl(m_fd, CEC_IOC_SETLADDR, &log_addr)) + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: IOCTL SetLogicalAddr failed !", __func__); + } +} + + +void *CExynosCECAdapterCommunication::Process(void) +{ + uint8_t buffer[CEC_MAX_FRAME_SIZE]; + uint32_t size; + fd_set rfds; + cec_logical_address initiator, destination; + + if (!IsOpen()) + return 0; + + FD_ZERO(&rfds); + FD_SET(m_fd, &rfds); + + while (!IsStopped()) + { + if (select(m_fd + 1, &rfds, NULL, NULL, NULL) >= 0 ) + { + size = read(m_fd, buffer, CEC_MAX_FRAME_SIZE); + + if (size > 0) + { + initiator = cec_logical_address(buffer[0] >> 4); + destination = cec_logical_address(buffer[0] & 0x0f); + + cec_command cmd; + + cec_command::Format( + cmd, initiator, destination, + ( size > 1 ) ? cec_opcode(buffer[1]) : CEC_OPCODE_NONE); + + for( uint8_t i = 2; i < size; i++ ) + cmd.parameters.PushBack(buffer[i]); + + if (!IsStopped()) + m_callback->OnCommandReceived(cmd); + } + } + + } + + return 0; +} + +#endif // HAVE_EXYNOS_API diff --git a/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.h b/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.h new file mode 100644 index 0000000..e23487d --- /dev/null +++ b/src/lib/adapter/Exynos/ExynosCECAdapterCommunication.h @@ -0,0 +1,101 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#if defined(HAVE_EXYNOS_API) + +#include "lib/platform/threads/mutex.h" +#include "lib/platform/threads/threads.h" +#include "lib/adapter/AdapterCommunication.h" +#include + +namespace CEC +{ + class CExynosCECAdapterCommunication : public IAdapterCommunication, public PLATFORM::CThread + { + public: + /*! + * @brief Create a new Exynos HDMI CEC communication handler. + * @param callback The callback to use for incoming CEC commands. + */ + CExynosCECAdapterCommunication(IAdapterCommunicationCallback *callback); + virtual ~CExynosCECAdapterCommunication(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("EXYNOS"); } + 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_EXYNOS; } + uint16_t GetAdapterVendorId(void) const { return 1; } + uint16_t GetAdapterProductId(void) const { return 1; } + void HandleLogicalAddressLost(cec_logical_address oldAddress); + void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {} + ///} + + /** @name PLATFORM::CThread implementation */ + ///{ + void *Process(void); + ///} + + private: + bool IsInitialised(void) const { return 1; }; + + std::string m_strError; /**< current error message */ + + bool m_bLogicalAddressChanged; + cec_logical_addresses m_logicalAddresses; + + PLATFORM::CMutex m_mutex; + int m_fd; + }; +}; +#endif diff --git a/src/lib/adapter/Exynos/ExynosCECAdapterDetection.cpp b/src/lib/adapter/Exynos/ExynosCECAdapterDetection.cpp new file mode 100644 index 0000000..4daf191 --- /dev/null +++ b/src/lib/adapter/Exynos/ExynosCECAdapterDetection.cpp @@ -0,0 +1,48 @@ +/* + * This file is part of the libCEC(R) library. + * + * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "env.h" +#include + +#if defined(HAVE_EXYNOS_API) +#include "ExynosCECAdapterDetection.h" +#include "ExynosCEC.h" + +using namespace CEC; + +bool CExynosCECAdapterDetection::FindAdapter(void) +{ + return access(CEC_EXYNOS_PATH, 0) == 0; +} + +#endif diff --git a/src/lib/adapter/Exynos/ExynosCECAdapterDetection.h b/src/lib/adapter/Exynos/ExynosCECAdapterDetection.h new file mode 100644 index 0000000..901496b --- /dev/null +++ b/src/lib/adapter/Exynos/ExynosCECAdapterDetection.h @@ -0,0 +1,42 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +namespace CEC +{ + class CExynosCECAdapterDetection + { + public: + static bool FindAdapter(void); + }; +} diff --git a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp index 0373595..1be07c5 100644 --- a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp @@ -710,7 +710,7 @@ void *CAdapterPingThread::Process(void) /* send a ping to the adapter */ bool bPinged(false); int iFailedCounter(0); - while (!bPinged && iFailedCounter < 3) + while (!bPinged && iFailedCounter < 3 && !IsStopped()) { if (!m_com->PingAdapter()) { @@ -724,7 +724,7 @@ void *CAdapterPingThread::Process(void) } } - if (iFailedCounter == 3) + if (iFailedCounter == 3 && !IsStopped()) { /* failed to ping the adapter 3 times in a row. something must be wrong with the connection */ m_com->LIB_CEC->AddLog(CEC_LOG_ERROR, "failed to ping the adapter 3 times in a row. closing the connection."); diff --git a/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp b/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp index 76c61b3..9af5357 100644 --- a/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp +++ b/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp @@ -78,7 +78,9 @@ CRPiCECAdapterCommunication::CRPiCECAdapterCommunication(IAdapterCommunicationCa CRPiCECAdapterCommunication::~CRPiCECAdapterCommunication(void) { delete(m_queue); + UnregisterLogicalAddress(); Close(); + vc_cec_set_passive(false); } const char *ToString(const VC_CEC_ERROR_T error) @@ -212,6 +214,7 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u { m_bLogicalAddressChanged = true; m_logicalAddress = (cec_logical_address)(p0 & 0xF); + m_bLogicalAddressRegistered = true; LIB_CEC->AddLog(CEC_LOG_DEBUG, "logical address changed to %s (%x)", LIB_CEC->ToString(m_logicalAddress), m_logicalAddress); } else @@ -224,8 +227,9 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u break; case VC_CEC_LOGICAL_ADDR_LOST: { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "logical %s (%x) address lost", LIB_CEC->ToString(m_logicalAddress), m_logicalAddress); // the logical address was taken by another device - cec_logical_address previousAddress = m_logicalAddress == CECDEVICE_BROADCAST ? m_previousLogicalAddress : m_logicalAddress; + cec_logical_address previousAddress = m_logicalAddress == CECDEVICE_FREEUSE ? m_previousLogicalAddress : m_logicalAddress; m_logicalAddress = CECDEVICE_UNKNOWN; // notify libCEC that we lost our LA when the connection was initialised @@ -305,23 +309,18 @@ bool CRPiCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONN vc_cec_register_callback(rpi_cec_callback, (void*)this); vc_tv_register_callback(rpi_tv_callback, (void*)this); - // release previous LA - vc_cec_release_logical_address(); - if (!m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged, iTimeoutMs)) - { - LIB_CEC->AddLog(CEC_LOG_ERROR, "failed to release the previous LA"); - return false; - } - // register LA "freeuse" - if (RegisterLogicalAddress(CECDEVICE_FREEUSE)) + if (RegisterLogicalAddress(CECDEVICE_FREEUSE, iTimeoutMs)) { LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - vc_cec initialised", __FUNCTION__); CLockObject lock(m_mutex); m_bInitialised = true; } else + { LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - vc_cec could not be initialised", __FUNCTION__); + return false; + } } return true; @@ -346,19 +345,10 @@ uint16_t CRPiCECAdapterCommunication::GetPhysicalAddress(void) void CRPiCECAdapterCommunication::Close(void) { - { - CLockObject lock(m_mutex); - if (m_bInitialised) - m_bInitialised = false; - else - return; + if (m_bInitialised) { + vc_tv_unregister_callback(rpi_tv_callback); + m_bInitialised = false; } - vc_tv_unregister_callback(rpi_tv_callback); - - UnregisterLogicalAddress(); - - // disable passive mode - vc_cec_set_passive(false); if (!g_bHostInited) { @@ -373,22 +363,16 @@ std::string CRPiCECAdapterCommunication::GetError(void) const return strError; } -cec_adapter_message_state CRPiCECAdapterCommunication::Write(const cec_command &data, bool &UNUSED(bRetry), uint8_t UNUSED(iLineTimeout), bool bIsReply) +cec_adapter_message_state CRPiCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply) { - // ensure that the source LA is registered - if (!RegisterLogicalAddress(data.initiator)) - { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to register logical address %s (%X)", CCECTypeUtils::ToString(data.initiator), data.initiator); - return (data.initiator == data.destination) ? ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED : ADAPTER_MESSAGE_STATE_ERROR; - } - - if (!data.opcode_set && data.initiator == data.destination) - { - // registration of the logical address would have failed - return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; - } + VC_CEC_ERROR_T vcAnswer; + uint32_t iTimeout = (data.transmit_timeout ? data.transmit_timeout : iLineTimeout*1000); - return m_queue->Write(data, bIsReply) ? ADAPTER_MESSAGE_STATE_SENT_ACKED : ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; + cec_adapter_message_state rc = m_queue->Write(data, bRetry, iTimeout, bIsReply, vcAnswer); +#ifdef CEC_DEBUGGING + LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: result %s", ToString(vcAnswer)); +#endif + return rc; } uint16_t CRPiCECAdapterCommunication::GetFirmwareVersion(void) @@ -398,22 +382,15 @@ uint16_t CRPiCECAdapterCommunication::GetFirmwareVersion(void) cec_logical_address CRPiCECAdapterCommunication::GetLogicalAddress(void) { - { - CLockObject lock(m_mutex); - if (m_logicalAddress != CECDEVICE_UNKNOWN) - return m_logicalAddress; - } + CLockObject lock(m_mutex); - CEC_AllDevices_T address; - return (vc_cec_get_logical_address(&address) == VCHIQ_SUCCESS) ? - (cec_logical_address)address : CECDEVICE_UNKNOWN; + return m_logicalAddress; } bool CRPiCECAdapterCommunication::UnregisterLogicalAddress(void) { CLockObject lock(m_mutex); - if (m_logicalAddress == CECDEVICE_UNKNOWN || - m_logicalAddress == CECDEVICE_BROADCAST) + if (!m_bInitialised) return true; LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - releasing previous logical address", __FUNCTION__); @@ -428,34 +405,25 @@ bool CRPiCECAdapterCommunication::UnregisterLogicalAddress(void) return m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged); } -bool CRPiCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address) +bool CRPiCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address, uint32_t iTimeoutMs) { { CLockObject lock(m_mutex); - if (m_logicalAddress == address) + if ((m_logicalAddress == address) && m_bLogicalAddressRegistered) return true; } - if (!UnregisterLogicalAddress()) - return false; - - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - registering address %x", __FUNCTION__, address); - - CLockObject lock(m_mutex); m_bLogicalAddressChanged = false; - vc_cec_poll_address((CEC_AllDevices_T)address); // register the new LA int iRetval = vc_cec_set_logical_address((CEC_AllDevices_T)address, (CEC_DEVICE_TYPE_T)CCECTypeUtils::GetType(address), CEC_VENDOR_ID_BROADCOM); if (iRetval != VCHIQ_SUCCESS) { LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - vc_cec_set_logical_address(%X) returned %s (%d)", __FUNCTION__, address, ToString((VC_CEC_ERROR_T)iRetval), iRetval); - return false; + UnregisterLogicalAddress(); } - - if (m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged)) + else if (m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged, iTimeoutMs)) { - m_bLogicalAddressRegistered = true; return true; } return false; @@ -464,9 +432,8 @@ bool CRPiCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_addre cec_logical_addresses CRPiCECAdapterCommunication::GetLogicalAddresses(void) { cec_logical_addresses addresses; addresses.Clear(); - cec_logical_address current = GetLogicalAddress(); - if (current != CECDEVICE_UNKNOWN) - addresses.Set(current); + if (m_bLogicalAddressRegistered) + addresses.primary = GetLogicalAddress(); return addresses; } diff --git a/src/lib/adapter/RPi/RPiCECAdapterCommunication.h b/src/lib/adapter/RPi/RPiCECAdapterCommunication.h index 7fbc105..e6a6446 100644 --- a/src/lib/adapter/RPi/RPiCECAdapterCommunication.h +++ b/src/lib/adapter/RPi/RPiCECAdapterCommunication.h @@ -97,7 +97,7 @@ namespace CEC private: cec_logical_address GetLogicalAddress(void); bool UnregisterLogicalAddress(void); - bool RegisterLogicalAddress(const cec_logical_address address); + bool RegisterLogicalAddress(const cec_logical_address address, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT); int InitHostCEC(void); bool m_bInitialised; /**< true when the connection is initialised, false otherwise */ diff --git a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp index aa9701d..cb9fed0 100644 --- a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp +++ b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp @@ -71,9 +71,12 @@ void CRPiCECAdapterMessageQueueEntry::Broadcast(void) bool CRPiCECAdapterMessageQueueEntry::MessageReceived(cec_opcode opcode, cec_logical_address initiator, cec_logical_address destination, uint32_t response) { - if ((!m_command.opcode_set || m_command.opcode == opcode) && - m_command.initiator == initiator && - m_command.destination == destination) + if ((m_command.opcode_set && m_command.opcode == opcode && + m_command.initiator == initiator && + m_command.destination == destination) + || + (!m_command.opcode_set && + m_command.destination == destination)) { CLockObject lock(m_mutex); m_retval = response; @@ -93,9 +96,6 @@ bool CRPiCECAdapterMessageQueueEntry::Wait(uint32_t iTimeout) CLockObject lock(m_mutex); bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout); m_bWaiting = false; - - if (bReturn) - bReturn = m_retval == VCHIQ_SUCCESS; } return bReturn; } @@ -124,7 +124,12 @@ void CRPiCECAdapterMessageQueue::MessageReceived(cec_opcode opcode, cec_logical_ 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) +uint32_t CRPiCECAdapterMessageQueueEntry::Result() const +{ + return m_retval; +} + +cec_adapter_message_state CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool &bRetry, uint32_t iLineTimeout, bool bIsReply, VC_CEC_ERROR_T &vcReply) { CRPiCECAdapterMessageQueueEntry *entry = new CRPiCECAdapterMessageQueueEntry(this, command); uint64_t iEntryId(0); @@ -182,24 +187,43 @@ bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str()); #endif - int iReturn = vc_cec_send_message((uint32_t)command.destination, (uint8_t*)&payload, iLength, bIsReply); + int iReturn = vc_cec_send_message((uint32_t)command.destination, command.opcode_set ? (uint8_t*)&payload : NULL, iLength, bIsReply); #endif + bRetry = false; if (iReturn != VCHIQ_SUCCESS) { LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending command '%s' failed (%d)", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL", iReturn); delete (entry); - return false; + return ADAPTER_MESSAGE_STATE_ERROR; } - bool bReturn(true); + cec_adapter_message_state bReturn(ADAPTER_MESSAGE_STATE_ERROR); if (entry) { - if (!entry->Wait(CEC_DEFAULT_TRANSMIT_WAIT)) + if (entry->Wait(iLineTimeout)) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' was not acked by the controller", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL"); - bReturn = false; + int status = entry->Result(); + + if (status == VC_CEC_ERROR_NO_ACK) + bReturn = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; + else if (status == VC_CEC_SUCCESS) + bReturn = ADAPTER_MESSAGE_STATE_SENT_ACKED; + else + bReturn = ADAPTER_MESSAGE_STATE_SENT; } + else + { + if (command.opcode_set) + { + bRetry = true; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' timeout", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL"); + sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); + } + bReturn = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT; + } + + vcReply = (VC_CEC_ERROR_T)entry->Result(); CLockObject lock(m_mutex); m_messages.erase(iEntryId); diff --git a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.h b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.h index af5756b..a6f4d7e 100644 --- a/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.h +++ b/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.h @@ -33,6 +33,12 @@ #include "lib/platform/util/buffer.h" #include +#include "lib/adapter/AdapterCommunication.h" + +extern "C" { +#include +#include +} namespace CEC { @@ -64,6 +70,11 @@ namespace CEC */ bool IsWaiting(void); + /*! + * @brief Query result from worker thread + */ + uint32_t Result() const; + /*! * @return The command that was sent in human readable form. */ @@ -106,7 +117,7 @@ namespace CEC void MessageReceived(cec_opcode opcode, cec_logical_address initiator, cec_logical_address destination, uint32_t response); - bool Write(const cec_command &command, bool bIsReply); + cec_adapter_message_state Write(const cec_command &command, bool &bRetry, uint32_t iLineTimeout, bool bIsReply, VC_CEC_ERROR_T &vcReply); private: CRPiCECAdapterCommunication * m_com; /**< the communication handler */ diff --git a/src/lib/implementations/ANCommandHandler.cpp b/src/lib/implementations/ANCommandHandler.cpp index 7e0e9b9..93e8c92 100644 --- a/src/lib/implementations/ANCommandHandler.cpp +++ b/src/lib/implementations/ANCommandHandler.cpp @@ -116,3 +116,13 @@ int CANCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comman } return CEC_ABORT_REASON_INVALID_OPERAND; } + +int CANCommandHandler::HandleSetMenuLanguage(const cec_command &command) +{ + if (m_processor->CECInitialised() && command.initiator == CECDEVICE_TV && command.destination == CECDEVICE_BROADCAST) + { + m_processor->GetDevice(command.initiator)->SetPowerStatus(CEC_POWER_STATUS_ON); + } + + return CCECCommandHandler::HandleSetMenuLanguage(command); +} diff --git a/src/lib/implementations/ANCommandHandler.h b/src/lib/implementations/ANCommandHandler.h index 595170a..73d3cae 100644 --- a/src/lib/implementations/ANCommandHandler.h +++ b/src/lib/implementations/ANCommandHandler.h @@ -47,6 +47,7 @@ namespace CEC int HandleVendorRemoteButtonDown(const cec_command &command); int HandleDeviceVendorCommandWithId(const cec_command &command); + int HandleSetMenuLanguage(const cec_command &command); protected: bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination); diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 29d1ffb..a89ebe6 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -592,12 +592,15 @@ int CCECCommandHandler::HandleSetStreamPath(const cec_command &command) CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress); if (device) { - if (device->IsHandledByLibCEC() && !device->IsActiveSource()) - device->ActivateSource(); - else + if (device->IsHandledByLibCEC()) { - device->MarkAsActiveSource(); - device->TransmitActiveSource(true); + if (!device->IsActiveSource()) + device->ActivateSource(); + else + { + device->MarkAsActiveSource(); + device->TransmitActiveSource(true); + } } return COMMAND_HANDLED; } diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index aeace02..e94851e 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -58,7 +58,7 @@ 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;} + 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_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO;} virtual bool InitHandler(void) { return true; } virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false); diff --git a/src/lib/implementations/RLCommandHandler.cpp b/src/lib/implementations/RLCommandHandler.cpp index 208b504..cb6cd31 100644 --- a/src/lib/implementations/RLCommandHandler.cpp +++ b/src/lib/implementations/RLCommandHandler.cpp @@ -111,13 +111,13 @@ int CRLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comman bHandled = true; switch (command.parameters[4]) { - // top menu -> root menu + // top menu case RL_KEY_TOP_MENU: - client->SetCurrentButton(CEC_USER_CONTROL_CODE_ROOT_MENU); + client->SetCurrentButton(CEC_USER_CONTROL_CODE_TOP_MENU); break; - // dvd menu -> contents menu + // dvd menu case RL_KEY_DVD_MENU: - client->SetCurrentButton(CEC_USER_CONTROL_CODE_CONTENTS_MENU); + client->SetCurrentButton(CEC_USER_CONTROL_CODE_DVD_MENU); break; default: bHandled = false; diff --git a/src/lib/implementations/VLCommandHandler.cpp b/src/lib/implementations/VLCommandHandler.cpp index 0e74a06..12a36e6 100644 --- a/src/lib/implementations/VLCommandHandler.cpp +++ b/src/lib/implementations/VLCommandHandler.cpp @@ -78,9 +78,9 @@ bool CVLCommandHandler::InitHandler(void) { libcec_configuration config; m_processor->GetPrimaryClient()->GetCurrentConfiguration(config); - if (config.iDoubleTapTimeoutMs == 0) + if (config.iDoubleTapTimeout50Ms == 0) { - config.iDoubleTapTimeoutMs = CEC_DOUBLE_TAP_TIMEOUT_MS; + config.iDoubleTapTimeout50Ms = config.clientVersion >= CEC_CLIENT_VERSION_2_2_0 ? CEC_DOUBLE_TAP_TIMEOUT_50_MS : CEC_DOUBLE_TAP_TIMEOUT_MS_OLD; m_processor->GetPrimaryClient()->SetConfiguration(config); } diff --git a/src/lib/platform/X11/randr-edid.cpp b/src/lib/platform/X11/randr-edid.cpp new file mode 100644 index 0000000..4de17e4 --- /dev/null +++ b/src/lib/platform/X11/randr-edid.cpp @@ -0,0 +1,166 @@ +/* + * 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 + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "env.h" + +#include "lib/platform/os.h" +#include "randr-edid.h" + +#include +#include +#include + +#include + +using namespace PLATFORM; + +static const char * const edid_names[] = +{ +#if (RANDR_MAJOR > 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >2) + RR_PROPERTY_RANDR_EDID, +#else + "EDID", +#endif + "EDID_DATA", + "XFree86_DDC_EDID1_RAWDATA" +}; + +#define EDID_NAME_COUNT (sizeof(edid_names)/sizeof(*edid_names)) + +uint16_t CRandrEdidParser::GetPhysicalAddress(void) +{ + uint16_t physical_address = 0; + + /* open default X11 DISPLAY */ + Display *disp = XOpenDisplay(NULL); + if( disp ) + { + int event_base, error_base; + int maj, min; + + if( XRRQueryExtension(disp, &event_base, &error_base) + && XRRQueryVersion(disp, &maj, &min) ) + { + int version = (maj << 8) | min; + + if( version >= 0x0102 ) + { + size_t atom_avail = 0; + Atom edid_atoms[EDID_NAME_COUNT]; + + if( XInternAtoms(disp, (char **)edid_names, EDID_NAME_COUNT, True, edid_atoms) ) + { + /* remove missing some atoms */ + atom_avail = 0; + for(size_t atom_count=0; atom_count 0 ) + { + int scr_count = ScreenCount(disp); + int screen; + + for(screen=0; screen 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >=3) + if( version >= 0x0103 ) + { + /* get cached resources if they are available */ + rsrc = XRRGetScreenResourcesCurrent(disp, root); + } + + if( NULL == rsrc ) +#endif + rsrc = XRRGetScreenResources(disp, root); + + if( NULL != rsrc ) + { + int output_id; + for( output_id=0; 0 == physical_address && output_id < rsrc->noutput; ++output_id ) + { + RROutput rr_output_id = rsrc->outputs[output_id]; + XRROutputInfo *output_info = XRRGetOutputInfo(disp, rsrc, rr_output_id); + if( NULL != output_info ) + { + if( RR_Connected == output_info->connection ) + { + for(size_t atom_count=0; 0 == physical_address && atom_count + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "lib/platform/util/edid.h" + +namespace PLATFORM +{ + class CRandrEdidParser + { + public: + CRandrEdidParser(void) {}; + virtual ~CRandrEdidParser(void) {}; + + uint16_t GetPhysicalAddress(void); + }; +} diff --git a/src/lib/platform/posix/os-edid.cpp b/src/lib/platform/posix/os-edid.cpp index 4347688..51dc92f 100644 --- a/src/lib/platform/posix/os-edid.cpp +++ b/src/lib/platform/posix/os-edid.cpp @@ -32,11 +32,16 @@ #include "env.h" #include "lib/platform/util/edid.h" +#include "lib/platform/X11/randr-edid.h" using namespace PLATFORM; uint16_t CEDIDParser::GetPhysicalAddress(void) { +#if HAVE_RANDR + return CRandrEdidParser().GetPhysicalAddress(); +#else // TODO return 0; +#endif }