[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],
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
+ LIBS="$libs_tmp"
+ fi
;;
*-apple-darwin*)
AC_CHECK_HEADER(mach/mach_time.h,,AC_MSG_ERROR($msg_required_header_missing))
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))
*/
#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
*/
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
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
/// </summary>
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
};
/// <summary>
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";
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
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@
#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;
}
#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
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);
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
}
--- /dev/null
+#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 <license@pulse-eight.com>
+ * 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
--- /dev/null
+/*
+ * 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 <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+
+#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
--- /dev/null
+#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 <license@pulse-eight.com>
+ * 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 <map>
+
+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
--- /dev/null
+/*
+ * 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 <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include <stdio.h>
+
+#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
--- /dev/null
+#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 <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+namespace CEC
+{
+ class CExynosCECAdapterDetection
+ {
+ public:
+ static bool FindAdapter(void);
+ };
+}
CRPiCECAdapterCommunication::~CRPiCECAdapterCommunication(void)
{
delete(m_queue);
+ UnregisterLogicalAddress();
Close();
+ vc_cec_set_passive(false);
}
const char *ToString(const VC_CEC_ERROR_T error)
{
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
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
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;
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)
{
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)
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__);
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;
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;
}
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 */
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;
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;
}
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);
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);
#include "lib/platform/util/buffer.h"
#include <map>
+#include "lib/adapter/AdapterCommunication.h"
+
+extern "C" {
+#include <interface/vmcs_host/vc_cecservice.h>
+#include <interface/vchiq_arm/vchiq_if.h>
+}
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.
*/
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 */
}
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);
+}
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);
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;
}
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);
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+
+#include "lib/platform/os.h"
+#include "randr-edid.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+
+#include <stdlib.h>
+
+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<EDID_NAME_COUNT; ++atom_count)
+ {
+ Atom edid_atom = edid_atoms[atom_count];
+ if( None != edid_atom )
+ {
+ if( atom_avail < atom_count )
+ {
+ edid_atoms[atom_avail] = edid_atom;
+ }
+ ++atom_avail;
+ }
+ }
+ }
+
+ if( atom_avail > 0 )
+ {
+ int scr_count = ScreenCount(disp);
+ int screen;
+
+ for(screen=0; screen<scr_count; ++screen)
+ {
+ XRRScreenResources *rsrc = NULL;
+ Window root = RootWindow(disp, screen);
+
+#if (RANDR_MAJOR > 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<atom_avail; ++atom_count)
+ {
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long bytes_after;
+ unsigned char *data;
+ int status;
+
+ status = XRRGetOutputProperty(disp, rr_output_id, edid_atoms[atom_count], 0, 128, False, False,
+ AnyPropertyType, &actual_type, &actual_format,
+ &nitems, &bytes_after, &data);
+ if( Success == status )
+ {
+ if((actual_type == XA_INTEGER) && (actual_format == 8) )
+ {
+ physical_address = CEDIDParser::GetPhysicalAddressFromEDID(data, nitems);
+ }
+ XFree(data);
+ }
+ }
+ }
+ XRRFreeOutputInfo(output_info);
+ }
+ else
+ break; /* problem ? */
+ }
+ XRRFreeScreenResources(rsrc);
+ }
+ }
+ }
+ }
+ }
+ XCloseDisplay(disp);
+ }
+ return physical_address;
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "lib/platform/util/edid.h"
+
+namespace PLATFORM
+{
+ class CRandrEdidParser
+ {
+ public:
+ CRandrEdidParser(void) {};
+ virtual ~CRandrEdidParser(void) {};
+
+ uint16_t GetPhysicalAddress(void);
+ };
+}
#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
}