~ubuntu-branches/ubuntu/utopic/unity-settings-daemon/utopic-proposed

« back to all changes in this revision

Viewing changes to gnome-settings-daemon/edid-parse.c

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Robert Ancell, Rui Matos, Bastien Nocera, Tim Lunn
  • Date: 2014-09-22 11:29:11 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20140922112911-jcq0tddp30t7btep
Tags: 14.04.0+14.10.20140922-0ubuntu1
[ Robert Ancell ]
* Move libgnome-desktop RandR code into u-s-d since newer versions
  remove this unstable API (LP: #1372240)

[ Rui Matos ]
* Apply git patch that pulls in code removed from gnome-desktop3 3.12

[ Bastien Nocera ]
* common: Check the exit status of hotplug scripts correctly

[ Tim Lunn ]
* Apply git patch that pulls in code removed from gnome-desktop3 3.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007 Red Hat, Inc.
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 
8
 * license, and/or sell copies of the Software, and to permit persons to whom
 
9
 * the Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 
19
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 */
 
22
 
 
23
/* Author: Soren Sandmann <sandmann@redhat.com> */
 
24
 
 
25
#include "edid.h"
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include <math.h>
 
29
#include <glib.h>
 
30
 
 
31
static int
 
32
get_bit (int in, int bit)
 
33
{
 
34
    return (in & (1 << bit)) >> bit;
 
35
}
 
36
 
 
37
static int
 
38
get_bits (int in, int begin, int end)
 
39
{
 
40
    int mask = (1 << (end - begin + 1)) - 1;
 
41
    
 
42
    return (in >> begin) & mask;
 
43
}
 
44
 
 
45
static int
 
46
decode_header (const uchar *edid)
 
47
{
 
48
    if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
 
49
        return TRUE;
 
50
    return FALSE;
 
51
}
 
52
 
 
53
static int
 
54
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
 
55
{
 
56
    int is_model_year;
 
57
    
 
58
    /* Manufacturer Code */
 
59
    info->manufacturer_code[0]  = get_bits (edid[0x08], 2, 6);
 
60
    info->manufacturer_code[1]  = get_bits (edid[0x08], 0, 1) << 3;
 
61
    info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
 
62
    info->manufacturer_code[2]  = get_bits (edid[0x09], 0, 4);
 
63
    info->manufacturer_code[3]  = '\0';
 
64
    
 
65
    info->manufacturer_code[0] += 'A' - 1;
 
66
    info->manufacturer_code[1] += 'A' - 1;
 
67
    info->manufacturer_code[2] += 'A' - 1;
 
68
 
 
69
    /* Product Code */
 
70
    info->product_code = edid[0x0b] << 8 | edid[0x0a];
 
71
 
 
72
    /* Serial Number */
 
73
    info->serial_number =
 
74
        edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
 
75
 
 
76
    /* Week and Year */
 
77
    is_model_year = FALSE;
 
78
    switch (edid[0x10])
 
79
    {
 
80
    case 0x00:
 
81
        info->production_week = -1;
 
82
        break;
 
83
 
 
84
    case 0xff:
 
85
        info->production_week = -1;
 
86
        is_model_year = TRUE;
 
87
        break;
 
88
 
 
89
    default:
 
90
        info->production_week = edid[0x10];
 
91
        break;
 
92
    }
 
93
 
 
94
    if (is_model_year)
 
95
    {
 
96
        info->production_year = -1;
 
97
        info->model_year = 1990 + edid[0x11];
 
98
    }
 
99
    else
 
100
    {
 
101
        info->production_year = 1990 + edid[0x11];
 
102
        info->model_year = -1;
 
103
    }
 
104
 
 
105
    return TRUE;
 
106
}
 
107
 
 
108
static int
 
109
decode_edid_version (const uchar *edid, MonitorInfo *info)
 
110
{
 
111
    info->major_version = edid[0x12];
 
112
    info->minor_version = edid[0x13];
 
113
 
 
114
    return TRUE;
 
115
}
 
116
 
 
117
static int
 
118
decode_display_parameters (const uchar *edid, MonitorInfo *info)
 
119
{
 
120
    /* Digital vs Analog */
 
121
    info->is_digital = get_bit (edid[0x14], 7);
 
122
 
 
123
    if (info->is_digital)
 
124
    {
 
125
        int bits;
 
126
        
 
127
        static const int bit_depth[8] =
 
128
        {
 
129
            -1, 6, 8, 10, 12, 14, 16, -1
 
130
        };
 
131
 
 
132
        static const Interface interfaces[6] =
 
133
        {
 
134
            UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
 
135
        };
 
136
 
 
137
        bits = get_bits (edid[0x14], 4, 6);
 
138
        info->connector.digital.bits_per_primary = bit_depth[bits];
 
139
 
 
140
        bits = get_bits (edid[0x14], 0, 3);
 
141
        
 
142
        if (bits <= 5)
 
143
            info->connector.digital.interface = interfaces[bits];
 
144
        else
 
145
            info->connector.digital.interface = UNDEFINED;
 
146
    }
 
147
    else
 
148
    {
 
149
        int bits = get_bits (edid[0x14], 5, 6);
 
150
        
 
151
        static const double levels[][3] =
 
152
        {
 
153
            { 0.7,   0.3,    1.0 },
 
154
            { 0.714, 0.286,  1.0 },
 
155
            { 1.0,   0.4,    1.4 },
 
156
            { 0.7,   0.0,    0.7 },
 
157
        };
 
158
 
 
159
        info->connector.analog.video_signal_level = levels[bits][0];
 
160
        info->connector.analog.sync_signal_level = levels[bits][1];
 
161
        info->connector.analog.total_signal_level = levels[bits][2];
 
162
 
 
163
        info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
 
164
 
 
165
        info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
 
166
        info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
 
167
        info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
 
168
 
 
169
        info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
 
170
    }
 
171
 
 
172
    /* Screen Size / Aspect Ratio */
 
173
    if (edid[0x15] == 0 && edid[0x16] == 0)
 
174
    {
 
175
        info->width_mm = -1;
 
176
        info->height_mm = -1;
 
177
        info->aspect_ratio = -1.0;
 
178
    }
 
179
    else if (edid[0x16] == 0)
 
180
    {
 
181
        info->width_mm = -1;
 
182
        info->height_mm = -1; 
 
183
        info->aspect_ratio = 100.0 / (edid[0x15] + 99);
 
184
    }
 
185
    else if (edid[0x15] == 0)
 
186
    {
 
187
        info->width_mm = -1;
 
188
        info->height_mm = -1;
 
189
        info->aspect_ratio = 100.0 / (edid[0x16] + 99);
 
190
        info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
 
191
    }
 
192
    else
 
193
    {
 
194
        info->width_mm = 10 * edid[0x15];
 
195
        info->height_mm = 10 * edid[0x16];
 
196
    }
 
197
 
 
198
    /* Gamma */
 
199
    if (edid[0x17] == 0xFF)
 
200
        info->gamma = -1.0;
 
201
    else
 
202
        info->gamma = (edid[0x17] + 100.0) / 100.0;
 
203
 
 
204
    /* Features */
 
205
    info->standby = get_bit (edid[0x18], 7);
 
206
    info->suspend = get_bit (edid[0x18], 6);
 
207
    info->active_off = get_bit (edid[0x18], 5);
 
208
 
 
209
    if (info->is_digital)
 
210
    {
 
211
        info->connector.digital.rgb444 = TRUE;
 
212
        if (get_bit (edid[0x18], 3))
 
213
            info->connector.digital.ycrcb444 = 1;
 
214
        if (get_bit (edid[0x18], 4))
 
215
            info->connector.digital.ycrcb422 = 1;
 
216
    }
 
217
    else
 
218
    {
 
219
        int bits = get_bits (edid[0x18], 3, 4);
 
220
        ColorType color_type[4] =
 
221
        {
 
222
            MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
 
223
        };
 
224
 
 
225
        info->connector.analog.color_type = color_type[bits];
 
226
    }
 
227
 
 
228
    info->srgb_is_standard = get_bit (edid[0x18], 2);
 
229
 
 
230
    /* In 1.3 this is called "has preferred timing" */
 
231
    info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
 
232
 
 
233
    /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
 
234
    info->continuous_frequency = get_bit (edid[0x18], 0);
 
235
    return TRUE;
 
236
}
 
237
 
 
238
static double
 
239
decode_fraction (int high, int low)
 
240
{
 
241
    double result = 0.0;
 
242
    int i;
 
243
 
 
244
    high = (high << 2) | low;
 
245
 
 
246
    for (i = 0; i < 10; ++i)
 
247
        result += get_bit (high, i) * pow (2, i - 10);
 
248
 
 
249
    return result;
 
250
}
 
251
 
 
252
static int
 
253
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
 
254
{
 
255
    info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
 
256
    info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
 
257
    info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
 
258
    info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
 
259
    info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
 
260
    info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
 
261
    info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
 
262
    info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
 
263
 
 
264
    return TRUE;
 
265
}
 
266
 
 
267
static int
 
268
decode_established_timings (const uchar *edid, MonitorInfo *info)
 
269
{
 
270
    static const Timing established[][8] = 
 
271
    {
 
272
        {
 
273
            { 800, 600, 60 },
 
274
            { 800, 600, 56 },
 
275
            { 640, 480, 75 },
 
276
            { 640, 480, 72 },
 
277
            { 640, 480, 67 },
 
278
            { 640, 480, 60 },
 
279
            { 720, 400, 88 },
 
280
            { 720, 400, 70 }
 
281
        },
 
282
        {
 
283
            { 1280, 1024, 75 },
 
284
            { 1024, 768, 75 },
 
285
            { 1024, 768, 70 },
 
286
            { 1024, 768, 60 },
 
287
            { 1024, 768, 87 },
 
288
            { 832, 624, 75 },
 
289
            { 800, 600, 75 },
 
290
            { 800, 600, 72 }
 
291
        },
 
292
        {
 
293
            { 0, 0, 0 },
 
294
            { 0, 0, 0 },
 
295
            { 0, 0, 0 },
 
296
            { 0, 0, 0 },
 
297
            { 0, 0, 0 },
 
298
            { 0, 0, 0 },
 
299
            { 0, 0, 0 },
 
300
            { 1152, 870, 75 }
 
301
        },
 
302
    };
 
303
 
 
304
    int i, j, idx;
 
305
 
 
306
    idx = 0;
 
307
    for (i = 0; i < 3; ++i)
 
308
    {
 
309
        for (j = 0; j < 8; ++j)
 
310
        {
 
311
            int byte = edid[0x23 + i];
 
312
 
 
313
            if (get_bit (byte, j) && established[i][j].frequency != 0)
 
314
                info->established[idx++] = established[i][j];
 
315
        }
 
316
    }
 
317
    return TRUE;
 
318
}
 
319
 
 
320
static int
 
321
decode_standard_timings (const uchar *edid, MonitorInfo *info)
 
322
{
 
323
    int i;
 
324
    
 
325
    for (i = 0; i < 8; i++)
 
326
    {
 
327
        int first = edid[0x26 + 2 * i];
 
328
        int second = edid[0x27 + 2 * i];
 
329
 
 
330
        if (first != 0x01 && second != 0x01)
 
331
        {
 
332
            int w = 8 * (first + 31);
 
333
            int h = 0;
 
334
 
 
335
            switch (get_bits (second, 6, 7))
 
336
            {
 
337
            case 0x00: h = (w / 16) * 10; break;
 
338
            case 0x01: h = (w / 4) * 3; break;
 
339
            case 0x02: h = (w / 5) * 4; break;
 
340
            case 0x03: h = (w / 16) * 9; break;
 
341
            }
 
342
 
 
343
            info->standard[i].width = w;
 
344
            info->standard[i].height = h;
 
345
            info->standard[i].frequency = get_bits (second, 0, 5) + 60;
 
346
        }
 
347
    }
 
348
    
 
349
    return TRUE;
 
350
}
 
351
 
 
352
static void
 
353
decode_lf_string (const uchar *s, int n_chars, char *result)
 
354
{
 
355
    int i;
 
356
    for (i = 0; i < n_chars; ++i)
 
357
    {
 
358
        if (s[i] == 0x0a)
 
359
        {
 
360
            *result++ = '\0';
 
361
            break;
 
362
        }
 
363
        else if (s[i] == 0x00)
 
364
        {
 
365
            /* Convert embedded 0's to spaces */
 
366
            *result++ = ' ';
 
367
        }
 
368
        else
 
369
        {
 
370
            *result++ = s[i];
 
371
        }
 
372
    }
 
373
}
 
374
 
 
375
static void
 
376
decode_display_descriptor (const uchar *desc,
 
377
                           MonitorInfo *info)
 
378
{
 
379
    switch (desc[0x03])
 
380
    {
 
381
    case 0xFC:
 
382
        decode_lf_string (desc + 5, 13, info->dsc_product_name);
 
383
        break;
 
384
    case 0xFF:
 
385
        decode_lf_string (desc + 5, 13, info->dsc_serial_number);
 
386
        break;
 
387
    case 0xFE:
 
388
        decode_lf_string (desc + 5, 13, info->dsc_string);
 
389
        break;
 
390
    case 0xFD:
 
391
        /* Range Limits */
 
392
        break;
 
393
    case 0xFB:
 
394
        /* Color Point */
 
395
        break;
 
396
    case 0xFA:
 
397
        /* Timing Identifications */
 
398
        break;
 
399
    case 0xF9:
 
400
        /* Color Management */
 
401
        break;
 
402
    case 0xF8:
 
403
        /* Timing Codes */
 
404
        break;
 
405
    case 0xF7:
 
406
        /* Established Timings */
 
407
        break;
 
408
    case 0x10:
 
409
        break;
 
410
    }
 
411
}
 
412
 
 
413
static void
 
414
decode_detailed_timing (const uchar *timing,
 
415
                        DetailedTiming *detailed)
 
416
{
 
417
    int bits;
 
418
    StereoType stereo[] =
 
419
    {
 
420
        NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
 
421
        TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
 
422
        FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
 
423
    };
 
424
    
 
425
    detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
 
426
    detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
 
427
    detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
 
428
    detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
 
429
    detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
 
430
    detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
 
431
    detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
 
432
    detailed->v_front_porch =
 
433
        get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
 
434
    detailed->v_sync =
 
435
        get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
 
436
    detailed->width_mm =  timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
 
437
    detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
 
438
    detailed->right_border = timing[0x0f];
 
439
    detailed->top_border = timing[0x10];
 
440
 
 
441
    detailed->interlaced = get_bit (timing[0x11], 7);
 
442
 
 
443
    /* Stereo */
 
444
    bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
 
445
    detailed->stereo = stereo[bits];
 
446
 
 
447
    /* Sync */
 
448
    bits = timing[0x11];
 
449
 
 
450
    detailed->digital_sync = get_bit (bits, 4);
 
451
    if (detailed->digital_sync)
 
452
    {
 
453
        detailed->connector.digital.composite = !get_bit (bits, 3);
 
454
 
 
455
        if (detailed->connector.digital.composite)
 
456
        {
 
457
            detailed->connector.digital.serrations = get_bit (bits, 2);
 
458
            detailed->connector.digital.negative_vsync = FALSE;
 
459
        }
 
460
        else
 
461
        {
 
462
            detailed->connector.digital.serrations = FALSE;
 
463
            detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
 
464
        }
 
465
 
 
466
        detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
 
467
    }
 
468
    else
 
469
    {
 
470
        detailed->connector.analog.bipolar = get_bit (bits, 3);
 
471
        detailed->connector.analog.serrations = get_bit (bits, 2);
 
472
        detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
 
473
    }
 
474
}
 
475
 
 
476
static int
 
477
decode_descriptors (const uchar *edid, MonitorInfo *info)
 
478
{
 
479
    int i;
 
480
    int timing_idx;
 
481
    
 
482
    timing_idx = 0;
 
483
    
 
484
    for (i = 0; i < 4; ++i)
 
485
    {
 
486
        int index = 0x36 + i * 18;
 
487
 
 
488
        if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
 
489
        {
 
490
            decode_display_descriptor (edid + index, info);
 
491
        }
 
492
        else
 
493
        {
 
494
            decode_detailed_timing (
 
495
                edid + index, &(info->detailed_timings[timing_idx++]));
 
496
        }
 
497
    }
 
498
 
 
499
    info->n_detailed_timings = timing_idx;
 
500
 
 
501
    return TRUE;
 
502
}
 
503
 
 
504
static void
 
505
decode_check_sum (const uchar *edid,
 
506
                  MonitorInfo *info)
 
507
{
 
508
    int i;
 
509
    uchar check = 0;
 
510
 
 
511
    for (i = 0; i < 128; ++i)
 
512
        check += edid[i];
 
513
 
 
514
    info->checksum = check;
 
515
}
 
516
 
 
517
MonitorInfo *
 
518
decode_edid (const uchar *edid)
 
519
{
 
520
    MonitorInfo *info = g_new0 (MonitorInfo, 1);
 
521
 
 
522
    decode_check_sum (edid, info);
 
523
    
 
524
    if (decode_header (edid)
 
525
        && decode_vendor_and_product_identification (edid, info)
 
526
        && decode_edid_version (edid, info)
 
527
        && decode_display_parameters (edid, info)
 
528
        && decode_color_characteristics (edid, info)
 
529
        && decode_established_timings (edid, info)
 
530
        && decode_standard_timings (edid, info)
 
531
        && decode_descriptors (edid, info))
 
532
    {
 
533
        return info;
 
534
    }
 
535
    else
 
536
    {
 
537
        g_free (info);
 
538
        return NULL;
 
539
    }
 
540
}