From 103eb041ef46f322b3c374da47feabab6c378004 Mon Sep 17 00:00:00 2001 From: Damien Fouilleul Date: Sat, 8 Feb 2014 11:41:55 +0000 Subject: [PATCH] return HDMI physical address using EDID data retrieved from X11 randr extension --- configure.ac | 14 +++ src/lib/Makefile.am | 4 + src/lib/platform/X11/randr-edid.cpp | 166 ++++++++++++++++++++++++++++ src/lib/platform/X11/randr-edid.h | 47 ++++++++ src/lib/platform/posix/os-edid.cpp | 5 + 5 files changed, 236 insertions(+) create mode 100644 src/lib/platform/X11/randr-edid.cpp create mode 100644 src/lib/platform/X11/randr-edid.h diff --git a/configure.ac b/configure.ac index 510d851..58bd607 100644 --- a/configure.ac +++ b/configure.ac @@ -206,6 +206,20 @@ 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_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)) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 9117d8e..3ac5577 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 diff --git a/src/lib/platform/X11/randr-edid.cpp b/src/lib/platform/X11/randr-edid.cpp new file mode 100644 index 0000000..42071b3 --- /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 >=2) + 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 } -- 2.34.1