return HDMI physical address using EDID data retrieved from X11 randr extension
authorDamien Fouilleul <damienf@nas.home>
Sat, 8 Feb 2014 11:41:55 +0000 (11:41 +0000)
committerDamien Fouilleul <damienf@nas.home>
Sat, 8 Feb 2014 11:41:55 +0000 (11:41 +0000)
configure.ac
src/lib/Makefile.am
src/lib/platform/X11/randr-edid.cpp [new file with mode: 0644]
src/lib/platform/X11/randr-edid.h [new file with mode: 0644]
src/lib/platform/posix/os-edid.cpp

index 510d851ccdac9d91d6bb6363944ff7e828ec39b4..58bd607e1c8b9ca652c21078050ce147b5a132dd 100644 (file)
@@ -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))
index 9117d8ebf3ce8fb7e9880b8b3497b4b8e3b946aa..3ac5577961c373ae22b2c79cb9fae2664e04f0ab 100644 (file)
@@ -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 (file)
index 0000000..42071b3
--- /dev/null
@@ -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       <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 >=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<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;
+}
diff --git a/src/lib/platform/X11/randr-edid.h b/src/lib/platform/X11/randr-edid.h
new file mode 100644 (file)
index 0000000..a648e7b
--- /dev/null
@@ -0,0 +1,47 @@
+#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);
+
+  };
+}
index 4347688ca5ac43fafabd53d8c614ebb6cebeefa7..51dc92fd76ffda551b12fb7bfe4324855c51978e 100644 (file)
 
 #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
 }