Commit | Line | Data |
---|---|---|
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 | ||
44 | using namespace PLATFORM; | |
45 | ||
46 | static 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 | ||
59 | uint16_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 | } |