28 #include <X11/Xatom.h>
32 return (in & (1 << bit)) >> bit;
35 static int get_bits(
int in,
int begin,
int end) {
36 int mask = (1 << (end - begin + 1)) - 1;
38 return (in >> begin) & mask;
42 if (
memcmp(edid,
"\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
64 info->
serial_number = edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
67 bool is_model_year =
false;
105 static const int bit_depth[8] = { -1, 6, 8, 10, 12, 14, 16, -1 };
108 int bits =
get_bits(edid[0x14], 4, 6);
109 info->
connector.digital.bits_per_primary = bit_depth[bits];
113 info->
connector.digital.interface = interfaces[bits];
117 int bits =
get_bits(edid[0x14], 5, 6);
118 static const double levels[][3] = {
120 { 0.714, 0.286, 1.0 },
125 info->
connector.analog.video_signal_level = levels[bits][0];
126 info->
connector.analog.sync_signal_level = levels[bits][1];
127 info->
connector.analog.total_signal_level = levels[bits][2];
136 if (edid[0x15] == 0 && edid[0x16] == 0) {
140 }
else if (edid[0x16] == 0) {
144 }
else if (edid[0x15] == 0) {
155 if (edid[0x17] == 0xFF)
158 info->
gamma = (edid[0x17] + 100.0) / 100.0;
172 int bits =
get_bits(edid[0x18], 3, 4);
175 info->
connector.analog.color_type = color_type[bits];
190 high = (high << 2) | low;
191 for (
int i = 0; i < 10; ++i)
192 result +=
get_bit(high, i) * pow(2, i - 10);
210 static const Timing established[][8] = {
211 { { 800, 600, 60 }, { 800, 600, 56 },
212 { 640, 480, 75 }, { 640, 480, 72 },
213 { 640, 480, 67 }, { 640, 480, 60 },
214 { 720, 400, 88 }, { 720, 400, 70 } },
215 { { 1280, 1024, 75 }, { 1024, 768, 75 },
216 { 1024, 768, 70 }, { 1024, 768, 60 },
217 { 1024, 768, 87 }, { 832, 624, 75 },
218 { 800, 600, 75 }, { 800, 600, 72 } },
219 { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
220 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1152, 870, 75 } },
224 for (
int i = 0; i < 3; ++i) {
225 for (
int j = 0; j < 8; ++j) {
226 int byte = edid[0x23 + i];
228 if (
get_bit(byte, j) && established[i][j].frequency != 0)
238 for (i = 0; i < 8; i++) {
239 int first = edid[0x26 + 2 * i];
240 int second = edid[0x27 + 2 * i];
242 if (first != 0x01 && second != 0x01) {
243 int w = 8 * (first + 31);
272 for (i = 0; i < n_chars; ++i) {
276 }
else if (s[i] == 0x00) {
286 switch (desc[0x03]) {
329 detailed->
pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
330 detailed->
h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
331 detailed->
h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
332 detailed->
v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
333 detailed->
v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
335 detailed->
h_sync = timing[0x09] |
get_bits(timing[0x0b], 4, 5) << 8;
346 detailed->
stereo = stereo[bits];
354 if (detailed->
connector.digital.composite) {
356 detailed->
connector.digital.negative_vsync = 0;
358 detailed->
connector.digital.serrations = 0;
371 for (
int i = 0; i < 4; ++i) {
372 int index = 0x36 + i * 18;
373 if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00) {
385 for (
int i = 0; i < 128; ++i)
408 static uint8_t *
get_property(Display *dpy, RROutput output, Atom atom,
int *len) {
411 unsigned long nitems, bytes_after;
413 uint8_t *result =
NULL;
415 XRRGetOutputProperty(dpy, output, atom, 0, 100, False, False,
416 AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
418 if (actual_type == XA_INTEGER && actual_format == 8) {
419 result =
new uint8_t[nitems];
420 memcpy(result, prop, nitems);
430 Atom edid_atom = XInternAtom(disp,
"EDID",
false);
431 uint8_t *edid =
get_property(disp,
id, edid_atom, &len);
433 edid_atom = XInternAtom(disp,
"EDID_DATA",
false);
439 if (len % 128 == 0) {
static bool decode_established_timings(const uint8_t *edid, MonitorInfo *info)
MonitorInfo * decode_edid(const uint8_t *edid)
DetailedTiming detailed_timings[4]
char dsc_product_name[14]
static int get_bit(int in, int bit)
__BEGIN_NAMESPACE_STD void * memcpy(void *__restrict __dest, const void *__restrict __src, size_t __n) __THROW __nonnull((1
static bool decode_header(const uint8_t *edid)
static void decode_check_sum(const uint8_t *edid, MonitorInfo *info)
static uint8_t * get_property(Display *dpy, RROutput output, Atom atom, int *len)
static bool decode_edid_version(const uint8_t *edid, MonitorInfo *info)
static bool decode_standard_timings(const uint8_t *edid, MonitorInfo *info)
union DetailedTiming::@69 connector
int memcmp(const void *__s1, const void *__s2, size_t __n) __THROW __attribute_pure__ __nonnull((1
unsigned int serial_number
union MonitorInfo::@72 connector
static void decode_display_descriptor(const uint8_t *desc, MonitorInfo *info)
static void decode_detailed_timing(const uint8_t *timing, DetailedTiming *detailed)
static double decode_fraction(int high, int low)
static void decode_lf_string(const uint8_t *s, int n_chars, char *result)
int preferred_timing_includes_native
static bool decode_color_characteristics(const uint8_t *edid, MonitorInfo *info)
MonitorInfo * read_edid_data(Display *disp, RROutput id)
char manufacturer_code[4]
int char * index(const char *__s, int __c) __THROW __attribute_pure__ __nonnull((1))
char dsc_serial_number[14]
static int get_bits(int in, int begin, int end)
static int decode_vendor_and_product_identification(const uint8_t *edid, MonitorInfo *info)
static bool decode_descriptors(const uint8_t *edid, MonitorInfo *info)
static bool decode_display_parameters(const uint8_t *edid, MonitorInfo *info)