Imported Upstream version 2.2.0
[deb_libcec.git] / src / lib / platform / X11 / randr-edid.cpp
CommitLineData
cbbe90dd
JB
1/*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
6 *
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
8 *
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 *
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
26 *
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
31 */
32
33#include "env.h"
34
35#include "lib/platform/os.h"
36#include "randr-edid.h"
37
38#include <X11/Xlib.h>
39#include <X11/Xatom.h>
40#include <X11/extensions/Xrandr.h>
41
42#include <stdlib.h>
43
44using namespace PLATFORM;
45
46static const char * const edid_names[] =
47{
48#if (RANDR_MAJOR > 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >2)
49 RR_PROPERTY_RANDR_EDID,
50#else
51 "EDID",
52#endif
53 "EDID_DATA",
54 "XFree86_DDC_EDID1_RAWDATA"
55};
56
57#define EDID_NAME_COUNT (sizeof(edid_names)/sizeof(*edid_names))
58
59uint16_t CRandrEdidParser::GetPhysicalAddress(void)
60{
61 uint16_t physical_address = 0;
62
63 /* open default X11 DISPLAY */
64 Display *disp = XOpenDisplay(NULL);
65 if( disp )
66 {
67 int event_base, error_base;
68 int maj, min;
69
70 if( XRRQueryExtension(disp, &event_base, &error_base)
71 && XRRQueryVersion(disp, &maj, &min) )
72 {
73 int version = (maj << 8) | min;
74
75 if( version >= 0x0102 )
76 {
77 size_t atom_avail = 0;
78 Atom edid_atoms[EDID_NAME_COUNT];
79
80 if( XInternAtoms(disp, (char **)edid_names, EDID_NAME_COUNT, True, edid_atoms) )
81 {
82 /* remove missing some atoms */
83 atom_avail = 0;
84 for(size_t atom_count=0; atom_count<EDID_NAME_COUNT; ++atom_count)
85 {
86 Atom edid_atom = edid_atoms[atom_count];
87 if( None != edid_atom )
88 {
89 if( atom_avail < atom_count )
90 {
91 edid_atoms[atom_avail] = edid_atom;
92 }
93 ++atom_avail;
94 }
95 }
96 }
97
98 if( atom_avail > 0 )
99 {
100 int scr_count = ScreenCount(disp);
101 int screen;
102
103 for(screen=0; screen<scr_count; ++screen)
104 {
105 XRRScreenResources *rsrc = NULL;
106 Window root = RootWindow(disp, screen);
107
108#if (RANDR_MAJOR > 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >=3)
109 if( version >= 0x0103 )
110 {
111 /* get cached resources if they are available */
112 rsrc = XRRGetScreenResourcesCurrent(disp, root);
113 }
114
115 if( NULL == rsrc )
116#endif
117 rsrc = XRRGetScreenResources(disp, root);
118
119 if( NULL != rsrc )
120 {
121 int output_id;
122 for( output_id=0; 0 == physical_address && output_id < rsrc->noutput; ++output_id )
123 {
124 RROutput rr_output_id = rsrc->outputs[output_id];
125 XRROutputInfo *output_info = XRRGetOutputInfo(disp, rsrc, rr_output_id);
126 if( NULL != output_info )
127 {
128 if( RR_Connected == output_info->connection )
129 {
130 for(size_t atom_count=0; 0 == physical_address && atom_count<atom_avail; ++atom_count)
131 {
132 Atom actual_type;
133 int actual_format;
134 unsigned long nitems;
135 unsigned long bytes_after;
136 unsigned char *data;
137 int status;
138
139 status = XRRGetOutputProperty(disp, rr_output_id, edid_atoms[atom_count], 0, 128, False, False,
140 AnyPropertyType, &actual_type, &actual_format,
141 &nitems, &bytes_after, &data);
142 if( Success == status )
143 {
144 if((actual_type == XA_INTEGER) && (actual_format == 8) )
145 {
146 physical_address = CEDIDParser::GetPhysicalAddressFromEDID(data, nitems);
147 }
148 XFree(data);
149 }
150 }
151 }
152 XRRFreeOutputInfo(output_info);
153 }
154 else
155 break; /* problem ? */
156 }
157 XRRFreeScreenResources(rsrc);
158 }
159 }
160 }
161 }
162 }
163 XCloseDisplay(disp);
164 }
165 return physical_address;
166}