diff options
Diffstat (limited to 'deps')
| -rw-r--r-- | deps/sysobj_early/data/edid.ids | 1 | ||||
| -rw-r--r-- | deps/sysobj_early/data/vendor.ids | 189 | ||||
| -rw-r--r-- | deps/sysobj_early/include/util_edid.h | 56 | ||||
| -rw-r--r-- | deps/sysobj_early/src/util_edid.c | 379 | 
4 files changed, 518 insertions, 107 deletions
| diff --git a/deps/sysobj_early/data/edid.ids b/deps/sysobj_early/data/edid.ids index 575287b6..9f959804 100644 --- a/deps/sysobj_early/data/edid.ids +++ b/deps/sysobj_early/data/edid.ids @@ -28,6 +28,7 @@ BNQ BenQ  BOE BOE  CMN Chimei Innolux Corporation  CMO Chi Mei Optoelectronics +CNL Valve Corporation  CRO Extraordinary Technologies  CUK Calibre UK  DEL Dell diff --git a/deps/sysobj_early/data/vendor.ids b/deps/sysobj_early/data/vendor.ids index 8c7d8b6f..84524b3a 100644 --- a/deps/sysobj_early/data/vendor.ids +++ b/deps/sysobj_early/data/vendor.ids @@ -128,13 +128,89 @@ name Toshiba Corporation  name Vizio      name_short VIZIO      ansi_color 0;30;107 +    match_string Vizio      note EDID vendor: VIZ      match_string_exact VIZ +name AOC International +    name_short AOC +    url www.aoc.com +    wikipedia AOC International +    ansi_color 0;97;44 +    match_string_case AOC +    note formerly Admiral Overseas Corporation +    match_string Admiral Overseas Corporation +    match_string Admiral + +name Magewell +    url www.magewell.com +    ansi_color 0;34;107 +    match_string Magewell + +name Harman International +    name_short Harman +    url www.harman.com +    ansi_color 0;34;107 +    match_string Harman International +    match_string Harman + +name Oculus VR +    name_short Oculus +    url www.oculus.com +    ansi_color 0;97;100 +    wikipedia Oculus VR +    match_string Oculus VR +    match_string Oculus + +name Yamaha Corporation +    name_short Yamaha +    url www.yamaha.com +    wikipedia Yamaha Corporation +    ansi_color 0;35;107 +    match_string Yamaha + +name AU Optronics Corporation +    name_short AUO +    url www.auo.com +    wikipedia AU Optronics +    ansi_color 0;34;107 +    match_string AU Optronics +    match_string_case AUO + +name Planar +    name_short PLANAR +    url www.planar.com +    ansi_color 0;91;40 +    match_string Planar + +name Seiko Epson Corporation +    name_short EPSON +    url epson.com +    wikipedia Seiko Epson +    ansi_color 0;34;107 +    match_string Seiko Epson +    match_string Epson +    match_string Seiko + +# Company defunct, now brand name of Chinese company +name Eastman Kodak Company +    name_short Kodak +    wikipedia Kodak +    ansi_color 0;31;43 +    match_string Kodak + +# Company defunct, now brand name of Chinese company +name Westinghouse Electronics +    name_short W +    wikipedia Westinghouse Electronics +    ansi_color 0;97;44 +    match_string Westinghouse +  name ViewSonic Corporation      name_short ViewSonic      url www.viewsonic.com      ansi_color 0;35;103 +    match_string ViewSonic      note EDID vendor: VSC      match_string_exact VSC @@ -164,17 +240,14 @@ name Plextor      url www.plextor.be      match_string Plextor -name Western Digital -    name_short WD -    url www.wdc.com -    ansi_color 0;37;40 -    match_string_case WDC -  name LG Electronics      name_short LG      url www.lge.com      ansi_color 0;97;41 +    match_string LG Electronics [Lucky Goldstar Co. Ltd] +    match_string Lucky Goldstar      match_string Lucky-Goldstar +    match_string LG Semi      match_string_case LG  name LG Electronics (formerly Goldstar) @@ -269,9 +342,12 @@ name Qualcomm (formerly Atheros)      match_string Atheros  name Panasonic Industry Company +# AKA: Matsushita Electric Industrial      name_short Panasonic      url www.panasonic.com      ansi_color 0;30;107 +    match_string Panasonic +    match_string Matsushita      match_string MATSHITA      note EDID vendor: MEI      match_string_exact MEI @@ -299,6 +375,7 @@ name International Business Machines Corporation      name_short IBM      url www.ibm.com      ansi_color 0;94;107 +    match_string International Business Machines      match_string_case IBM  name Dell Computer @@ -322,6 +399,8 @@ name Fujitsu      url www.fujitsu.com      ansi_color 0;31;107      match_string FUJITSU +    name_short Fujitsu/Siemens +    match_string Fujitsu Siemens  name Sony      name_short SONY @@ -332,6 +411,14 @@ name Sony      note EDID vendor: SNY      match_string_exact SNY +name Sony Mobile +    name_short SONY +    url www.sony.com +    ansi_color 0;30;107 +    match_string Sony Mobile +    name_short SONY/Ericsson +    match_string Sony Ericsson +  name SanDisk      url www.sandisk.com      ansi_color 0;31;40 @@ -467,6 +554,13 @@ name BenQ      ansi_color 0;35;107      match_string BENQ +name BenQ (formerly Acer Peripherals) +    name_short BenQ/acer +    url www.benq.com +    ansi_color 0;35;107 +    match_string Acer Peripherals +    match_string Acer Peripherals Inc. (now BenQ Corp.) +  name Holtek Semiconductor      name_short Holtek      url www.holtek.com @@ -608,6 +702,7 @@ name Crucial (Micron)      url www.crucial.com      ansi_color 0;37;44      match_string Crucial +    match_string Micron/Crucial  name Toshiba Samsung Storage Technology      name_short TSST @@ -622,7 +717,7 @@ name Seagate Technology      url www.seagate.com      ansi_color 0;92;100      match_string Seagate -#    match_string_case ST +    match_string_num_prefix_case ST  name Silicon Integrated Systems Corporation      name_short SIS @@ -719,6 +814,7 @@ name Infineon Technologies      wikipedia Infineon Technologies      ansi_color 0;34;107      match_string Infineon +    match_string Infineon (former Siemens)  name Cypress Semiconductor      name_short Cypress @@ -744,6 +840,7 @@ name Victor Company of Japan      url www.victor.co.jp      ansi_color 0;91;107      match_string_case JVC +    match_string Victor  name ASRock      url www.asrock.com @@ -814,6 +911,51 @@ name SK Hynix      match_string Hynix      match_string Hyundai +name PNY Technologies +    name_short PNY +    url www.pny.com +    wikipedia PNY Technologies +    ansi_color 0;97;100 +    match_string_case PNY + +name Linaro +    url linaro.org +    wikipedia Linaro +    ansi_color 0;32;107 +    match_string Linaro + +name Longsys +    name_short longsys +    url longsys.com +    ansi_color 0;31;107 +    match_string Longsys + +name Longsys (formerly Micron Lexar) +    name_short longsys/Lexar +    url lexar.com +    wikipedia Lexar +    ansi_color 0;31;40 +    match_string Lexar + +name Angelbird Technologies +    name_short Angelbird +    url www.angelbird.com +    ansi_color 0;97;100 +    match_string Angelbird + +name Hoodman Corporation +    name_short Hoodman +    url www.hoodmanusa.com +    ansi_color 0;30;43 +    match_string Hoodman + +name Silicon Power +    name_short SP +    url www.silicon-power.com +    wikipedia Silicon Power +    ansi_color 0;97;40 +    match_string Silicon Power +  #  # BIOS manufacturers  # @@ -884,17 +1026,20 @@ name Red Hat      match_string Red Hat      match_string RedHat -name Sun Microsystems -    name_short Sun -    wikipedia Sun Microsystems -    match_string Sun Microsystems -  name Oracle Corporation      name_short Oracle      url www.oracle.com      ansi_color 0;97;41      match_string Oracle +name Oracle Corporation (formerly Sun Microsystems) +    name_short Oracle (Sun) +    url www.oracle.com +    wikipedia Sun Microsystems +    ansi_color 0;97;41 +    match_string Sun Microsystems +    match_string Oracle Corporation (former Sun Microsystems) +  name Oracle Corporation (formerly InnoTek Systemberatung)      name_short Oracle (InnoTek)      url www.virtualbox.org/wiki/innotek @@ -1008,7 +1153,17 @@ name Digital Equipment Corporation      note Dead; various parts to Intel, Compaq, HP      match_string_case DEC      match_string Digital Equipment -    match_string Digital +    match_string_exact Digital + +name Western Digital +    name_short WD +    url www.westerndigital.com +    wikipedia Western Digital +    ansi_color 0;37;40 +#   ansi_color 0;97;44 +    match_string Western Digital +    match_string_case WDC +    match_string_num_prefix_case WD  name Marvell Technology Group      name_short Marvell @@ -1067,6 +1222,14 @@ name MediaTek      ansi_color 0;97;43      match_string MediaTek +name Valve Corporation +    name_short VALVE +    url valvesoftware.com +    wikipedia Valve Corporation +    ansi_color 0;97;41 +    match_string Valve Corporation +    match_string Valve +  #  # x86 VM vendor strings  # diff --git a/deps/sysobj_early/include/util_edid.h b/deps/sysobj_early/include/util_edid.h index b50dcb33..6f1360b5 100644 --- a/deps/sysobj_early/include/util_edid.h +++ b/deps/sysobj_early/include/util_edid.h @@ -24,6 +24,38 @@  #include <stdint.h>  /* for *int*_t types */  typedef struct { +    uint8_t version; +    uint8_t extension_length; +    uint8_t primary_use_case; +    uint8_t extension_count; +    int blocks; +    int checksum_ok; +} DisplayIDMeta; + +typedef struct { +    uint8_t *ptr; +    union { +        uint8_t tag; +        uint8_t type; +    }; +    uint8_t revision; +    uint8_t len; +} DisplayIDBlock; + +/* order by rising priority */ +enum { +    OUTSRC_EDID, +    OUTSRC_ETB, +    OUTSRC_STD, +    OUTSRC_DTD, +    OUTSRC_CEA_DTD, +    OUTSRC_SVD, +    OUTSRC_DID_TYPE_I, +    OUTSRC_DID_TYPE_VI, +    OUTSRC_DID_TYPE_VII, +}; + +typedef struct {      float horiz_cm, vert_cm;      float diag_cm, diag_in;      int horiz_blanking, vert_blanking; @@ -31,8 +63,9 @@ typedef struct {      float vert_freq_hz;      int is_interlaced;      int stereo_mode; +    int is_preferred;      uint64_t pixel_clock_khz; -    int src; /* 0: edid, 1: etb, 2: std, 3: dtd, 4: cea-dtd, 5: svd ... */ +    int src; /* enum OUTSRC_* */      uint64_t pixels; /* h*v: easier to compare */      char class_inch[6];  } edid_output; @@ -71,6 +104,14 @@ struct edid_cea_block {      int reserved[8];  }; +enum { +    STD_EDID         = 0, +    STD_EEDID        = 1, +    STD_EIACEA861    = 2, +    STD_DISPLAYID    = 3, +    STD_DISPLAYID20  = 4, +}; +  typedef struct {      union {          void* data; @@ -80,10 +121,7 @@ typedef struct {      };      unsigned int len; -    /* 0 - EDID -     * 1 - EIA/CEA-861 -     * 2 - DisplayID -     */ +    /* enum STD_* */      int std;      int ver_major, ver_minor; @@ -128,6 +166,12 @@ typedef struct {      edid_output img_max;      int speaker_alloc_bits; +    DisplayIDMeta did; +    int did_block_count; +    DisplayIDBlock *did_blocks; + +    int didt_count; +    edid_output *didts;  } edid;  edid *edid_new(const char *data, unsigned int len);  edid *edid_new_from_hex(const char *hex_string); @@ -147,6 +191,8 @@ char *edid_dtd_describe(struct edid_dtd *dtd, int dump_bytes);  char *edid_cea_block_describe(struct edid_cea_block *blk);  char *edid_cea_audio_describe(struct edid_sad *sad);  char *edid_cea_speaker_allocation_describe(int bitfield, int short_version); +const char *edid_did_block_type(int type); +char *edid_did_block_describe(DisplayIDBlock *blk);  char *edid_dump2(edid *e); diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c index 2aa595fa..6d90f6ac 100644 --- a/deps/sysobj_early/src/util_edid.c +++ b/deps/sysobj_early/src/util_edid.c @@ -31,16 +31,19 @@  #include "util_edid_svd_table.c" -/* block must be 128 bytes */ -static int block_check(const void *edid_block_bytes) { +static int block_check_n(const void *edid_block_bytes, int len) {      if (!edid_block_bytes) return 0;      uint8_t sum = 0;      uint8_t *data = (uint8_t*)edid_block_bytes;      int i; -    for(i=0; i<128; i++) +    for(i=0; i<len; i++)          sum += data[i];      return sum == 0 ? 1 : 0;  } +static int block_check(const void *edid_block_bytes) { +    /* block must be 128 bytes */ +    return block_check_n(edid_block_bytes, 128); +}  char *hex_bytes(uint8_t *bytes, int count) {      char *buffer = malloc(count*3+1), *p = buffer; @@ -53,6 +56,51 @@ char *hex_bytes(uint8_t *bytes, int count) {      return buffer;  } +#define OUTPUT_CPY_SIZE(DEST, SRC)  \ +    (DEST).horiz_cm = (SRC).horiz_cm; \ +    (DEST).vert_cm = (SRC).vert_cm; \ +    (DEST).diag_cm = (SRC).diag_cm; \ +    (DEST).diag_in = (SRC).diag_in; \ +    edid_output_fill(&(DEST)); + +static void edid_output_fill(edid_output *out) { +    out->diag_cm = +        sqrt( (out->horiz_cm * out->horiz_cm) +         + (out->vert_cm * out->vert_cm) ); +    out->diag_in = out->diag_cm / 2.54; + +    if (out->is_interlaced) { +        if (out->vert_lines) +            out->vert_pixels = out->vert_lines * 2; +        else +            out->vert_lines = out->vert_pixels / 2; +    } else { +        if (out->vert_lines) +            out->vert_pixels = out->vert_lines; +        else +            out->vert_lines = out->vert_pixels; +    } + +    if (!out->vert_freq_hz && out->pixel_clock_khz) { +        uint64_t h = out->horiz_pixels + out->horiz_blanking; +        uint64_t v = out->vert_lines + out->vert_blanking; +        if (h && v) { +            uint64_t work = out->pixel_clock_khz * 1000; +            work /= (h*v); +            out->vert_freq_hz = work; +        } +    } + +    out->pixels = out->horiz_pixels; +    out->pixels *= out->vert_pixels; + +    if (out->diag_in) { +        static const char *inlbl = "\""; /* TODO: unicode */ +        sprintf(out->class_inch, "%0.1f%s", out->diag_in, inlbl); +        util_strchomp_float(out->class_inch); +    } +} +  static void cea_block_decode(struct edid_cea_block *blk, edid *e) {      int i;      if (blk) { @@ -90,45 +138,77 @@ static void cea_block_decode(struct edid_cea_block *blk, edid *e) {      }  } -static void edid_output_fill(edid_output *out) { -    out->diag_cm = -        sqrt( (out->horiz_cm * out->horiz_cm) -         + (out->vert_cm * out->vert_cm) ); -    out->diag_in = out->diag_cm / 2.54; - -    if (out->is_interlaced) { -        if (out->vert_lines) -            out->vert_pixels = out->vert_lines * 2; -        else -            out->vert_lines = out->vert_pixels / 2; -    } else { -        if (out->vert_lines) -            out->vert_pixels = out->vert_lines; -        else -            out->vert_lines = out->vert_pixels; -    } - -    if (!out->vert_freq_hz && out->pixel_clock_khz) { -        uint64_t h = out->horiz_pixels + out->horiz_blanking; -        uint64_t v = out->vert_lines + out->vert_blanking; -        if (h && v) { -            uint64_t work = out->pixel_clock_khz * 1000; -            work /= (h*v); -            out->vert_freq_hz = work; +static void did_block_decode(DisplayIDBlock *blk, edid *e) { +    int b = 3; +    uint8_t *u8 = blk->ptr; +    edid_output out = {}; +    if (blk) { +        switch(blk->type) { +            case 0x03: /* Type I Detailed timings */ +                out.pixel_clock_khz = u8[b+2] << 16; +                out.pixel_clock_khz += u8[b+1] << 8; +                out.pixel_clock_khz += u8[b]; +                out.pixel_clock_khz *= 10; +                out.horiz_pixels = (u8[b+5] << 8) + u8[b+4]; +                out.horiz_blanking = (u8[b+7] << 8) + u8[b+6]; +                out.vert_lines = (u8[b+13] << 8) + u8[b+12]; +                out.vert_blanking = (u8[b+15] << 8) + u8[b+14]; +                out.is_interlaced = (u8[b+3] >> 4) & 0x1; +                out.stereo_mode = (u8[b+3] >> 5) & 0x2; +                out.is_preferred = (u8[b+3] >> 7) & 0x1; +                out.src = OUTSRC_DID_TYPE_I; +                edid_output_fill(&out); +                e->didts[e->didt_count++] = out; +                break; +            case 0x13: /* Type VI Detailed timings (super 0x03) */ +                /* UNTESTED */ +                out.pixel_clock_khz = (u8[b+2] << 16) & 0xa0; +                out.pixel_clock_khz += u8[b+1] << 8; +                out.pixel_clock_khz += u8[b]; +                out.horiz_pixels = ((u8[b+5] << 8) + u8[b+3]) & 0x7fff; +                out.vert_lines = ((u8[b+6] << 8) + u8[b+5]) & 0x7fff; +                // TODO: blanking... +                out.is_interlaced = (u8[b+13] >> 7) & 0x1; +                out.stereo_mode = (u8[b+13] >> 5) & 0x2; +                out.src = OUTSRC_DID_TYPE_VI; +                edid_output_fill(&out); +                e->didts[e->didt_count++] = out; +                break; +            case 0x22: /* Type VII Detailed timings (super 0x13) */ +                /* UNTESTED */ +                out.pixel_clock_khz = u8[b+2] << 16; +                out.pixel_clock_khz += u8[b+1] << 8; +                out.pixel_clock_khz += u8[b]; +                out.horiz_pixels = (u8[b+5] << 8) + u8[b+4]; +                out.horiz_blanking = (u8[b+7] << 8) + u8[b+6]; +                out.vert_lines = (u8[b+13] << 8) + u8[b+12]; +                out.vert_blanking = (u8[b+15] << 8) + u8[b+14]; +                out.is_interlaced = (u8[b+3] >> 4) & 0x1; +                out.stereo_mode = (u8[b+3] >> 5) & 0x2; +                out.is_preferred = (u8[b+3] >> 7) & 0x1; +                out.src = OUTSRC_DID_TYPE_VII; +                edid_output_fill(&out); +                e->didts[e->didt_count++] = out; +                break; +            case 0x81: /* CTA DisplayID, ... Embedded CEA Blocks */ +                while(b < blk->len) { +                    int db_type = (u8[b] & 0xe0) >> 5; +                    int db_size = u8[b] & 0x1f; +                    e->cea_blocks[e->cea_block_count].header.ptr = &u8[b]; +                    e->cea_blocks[e->cea_block_count].header.type = db_type; +                    e->cea_blocks[e->cea_block_count].header.len = db_size; +                    cea_block_decode(&e->cea_blocks[e->cea_block_count], e); +                    e->cea_block_count++; +                    b += db_size + 1; +                } +                break; +            default: +                break;          }      } - -    out->pixels = out->horiz_pixels; -    out->pixels *= out->vert_pixels; - -    if (out->diag_in) { -        static const char *inlbl = "\""; /* TODO: unicode */ -        sprintf(out->class_inch, "%0.1f%s", out->diag_in, inlbl); -        util_strchomp_float(out->class_inch); -    }  } -edid_output edid_output_from_svd(uint8_t index) { +static edid_output edid_output_from_svd(uint8_t index) {      int i;      if (index >= 128 && index <= 192) index &= 0x7f; /* "native" flag for 0-64 */      for(i = 0; i < (int)G_N_ELEMENTS(cea_standard_timings); i++) { @@ -140,7 +220,7 @@ edid_output edid_output_from_svd(uint8_t index) {                  out.is_interlaced = 1;              out.pixel_clock_khz = cea_standard_timings[i].pixel_clock_mhz * 1000;              out.vert_freq_hz = cea_standard_timings[i].vert_freq_hz; -            out.src = 5; +            out.src = OUTSRC_SVD;              edid_output_fill(&out);              return out;          } @@ -160,14 +240,19 @@ edid *edid_new(const char *data, unsigned int len) {      e->ver_major = e->u8[18];      e->ver_minor = e->u8[19]; -    e->dtds = malloc(sizeof(struct edid_dtd) * 1000); -    e->cea_blocks = malloc(sizeof(struct edid_cea_block) * 1000); -    e->svds = malloc(sizeof(struct edid_svd) * 1000); -    e->sads = malloc(sizeof(struct edid_sad) * 1000); -    memset(e->dtds, 0, sizeof(struct edid_dtd) * 1000); -    memset(e->cea_blocks, 0, sizeof(struct edid_cea_block) * 1000); -    memset(e->svds, 0, sizeof(struct edid_svd) * 1000); -    memset(e->sads, 0, sizeof(struct edid_sad) * 1000); +#define RESERVE_COUNT 300 +    e->dtds = malloc(sizeof(struct edid_dtd) * RESERVE_COUNT); +    e->cea_blocks = malloc(sizeof(struct edid_cea_block) * RESERVE_COUNT); +    e->svds = malloc(sizeof(struct edid_svd) * RESERVE_COUNT); +    e->sads = malloc(sizeof(struct edid_sad) * RESERVE_COUNT); +    e->did_blocks = malloc(sizeof(DisplayIDBlock) * RESERVE_COUNT); +    e->didts = malloc(sizeof(edid_output) * RESERVE_COUNT); +    memset(e->dtds, 0, sizeof(struct edid_dtd) * RESERVE_COUNT); +    memset(e->cea_blocks, 0, sizeof(struct edid_cea_block) * RESERVE_COUNT); +    memset(e->svds, 0, sizeof(struct edid_svd) * RESERVE_COUNT); +    memset(e->sads, 0, sizeof(struct edid_sad) * RESERVE_COUNT); +    memset(e->did_blocks, 0, sizeof(DisplayIDBlock) * RESERVE_COUNT); +    memset(e->didts, 0, sizeof(edid_output) * RESERVE_COUNT);      uint16_t vid = be16toh(e->u16[4]); /* bytes 8-9 */      e->ven[2] = 64 + (vid & 0x1f); @@ -210,7 +295,7 @@ edid *edid_new(const char *data, unsigned int len) {          e->etbs[e->etb_count].vert_pixels = v;   \          e->etbs[e->etb_count].vert_freq_hz = f;  \          e->etbs[e->etb_count].is_interlaced = i; \ -        e->etbs[e->etb_count].src = 1;           \ +        e->etbs[e->etb_count].src = OUTSRC_ETB;  \          edid_output_fill(&e->etbs[e->etb_count]);\          e->etb_count++; };      ETB_CHECK(35, 7, 720, 400, 70, 0); //(VGA) @@ -262,7 +347,7 @@ edid *edid_new(const char *data, unsigned int len) {          e->stds[e->std_count].out.horiz_pixels = xres;          e->stds[e->std_count].out.vert_pixels = yres;          e->stds[e->std_count].out.vert_freq_hz = vf; -        e->stds[e->std_count].out.src = 2; +        e->stds[e->std_count].out.src = OUTSRC_STD;          edid_output_fill(&e->stds[e->std_count].out);          e->std_count++;      } @@ -299,13 +384,41 @@ edid *edid_new(const char *data, unsigned int len) {              else e->ext_blocks_fail++;              if (u8[0] == 0x70) { -                e->std = MAX(e->std, 2);                  /* DisplayID */ -                // TODO: ... +                e->did.version = u8[1]; +                if (e->did.version >= 0x20) +                    e->std = MAX(e->std, STD_DISPLAYID20); +                else e->std = MAX(e->std, STD_DISPLAYID); +                e->did.extension_length = u8[2]; +                e->did.primary_use_case = u8[3]; +                e->did.extension_count = u8[4]; +                int db_end = u8[2] + 5; +                int b = 5; +                while(b < db_end) { +                    int db_type = u8[b]; +                    int db_revision = u8[b+1] & 0x7; +                    int db_size = u8[b+2]; +                    e->did_blocks[e->did_block_count].ptr = &u8[b]; +                    e->did_blocks[e->did_block_count].type = db_type; +                    e->did_blocks[e->did_block_count].revision = db_revision; +                    e->did_blocks[e->did_block_count].len = db_size; +                    did_block_decode(&e->did_blocks[e->did_block_count], e); +                    e->did_block_count++; +                    e->did.blocks++; +                    b += db_size + 3; +                } +                if (b != db_end) { +                    // over or under-run ... +                } +                e->did.checksum_ok = block_check_n(u8, u8[2] + 5); +                //printf("DID: v:%02x el:%d uc:%d ec:%d, blocks:%d ok:%d\n", +                //    e->did.version, e->did.extension_length, +                //    e->did.primary_use_case, e->did.extension_count, +                //    e->did.blocks, e->checksum_ok);              }              if (u8[0] == 0x02) { -                e->std = MAX(e->std, 1); +                e->std = MAX(e->std, STD_EIACEA861);                  /* CEA extension */                  int db_end = u8[2];                  if (db_end) { @@ -334,6 +447,9 @@ edid *edid_new(const char *data, unsigned int len) {              }          }      } +    if (e->ext_blocks_ok) { +        e->std = MAX(e->std, STD_EEDID); +    }      /* strings */      for(i = 0; i < 4; i++) { @@ -389,8 +505,8 @@ edid *edid_new(const char *data, unsigned int len) {          uint8_t *u8 = e->dtds[i].ptr;          uint16_t *u16 = (uint16_t*)e->dtds[i].ptr;          edid_output *out = &e->dtds[i].out; -        if (e->dtds[i].cea_ext) out->src = 4; -        else out->src = 3; +        if (e->dtds[i].cea_ext) out->src = OUTSRC_CEA_DTD; +        else out->src = OUTSRC_DTD;          out->pixel_clock_khz = le16toh(u16[0]) * 10;          out->horiz_pixels =              ((u8[4] & 0xf0) << 4) + u8[2]; @@ -421,42 +537,51 @@ edid *edid_new(const char *data, unsigned int len) {      /* svds */      for(i = 0; i < e->svd_count; i++) { +        e->svds[i].out = edid_output_from_svd(e->svds[i].v);          if (e->svds[i].v >= 128 &&              e->svds[i].v <= 192) {              e->svds[i].is_native = 1; + +            edid_output tmp = e->img_max; +            /* native res is max real res, right? */ +            e->img_max = e->svds[i].out; +            e->img_max.is_preferred = 1; +            OUTPUT_CPY_SIZE(e->img_max, tmp);          } -        e->svds[i].out = edid_output_from_svd(e->svds[i].v);      } -    /* squeeze lists */ -    if (!e->dtd_count) { -        free(e->dtds); -        e->dtds = NULL; -    } else { -        e->dtds = realloc(e->dtds, sizeof(struct edid_dtd) * e->dtd_count); -    } -    if (!e->cea_block_count) { -        if (e->cea_blocks) -            free(e->cea_blocks); -        e->cea_blocks = NULL; -    } else { -        e->cea_blocks = realloc(e->cea_blocks, sizeof(struct edid_cea_block) * e->cea_block_count); -    } -    if (!e->svd_count) { -        if (e->svds) -            free(e->svds); -        e->svds = NULL; -    } else { -        e->svds = realloc(e->svds, sizeof(struct edid_svd) * e->svd_count); +    /* didts */ +    for(i = 0; i < e->didt_count; i++) { +        int pref = e->didts[i].is_preferred; +        int max_pref = e->img_max.is_preferred; +        int bigger = (e->didts[i].pixels > e->img_max.pixels); +        int better = (e->didts[i].src > e->img_max.src); +        if (bigger && !max_pref +            || pref && !max_pref +            || pref && better) { +            edid_output tmp = e->img_max; +            e->img_max = e->didts[i]; +            OUTPUT_CPY_SIZE(e->img_max, tmp); +        }      } -    if (!e->sad_count) { -        if (e->sads) -            free(e->sads); -        e->sads = NULL; -    } else { -        e->sads = realloc(e->sads, sizeof(struct edid_sad) * e->sad_count); + +    if (!e->speaker_alloc_bits && e->sad_count) { +        /* make an assumption */ +        if (e->sads[0].channels == 2) +            e->speaker_alloc_bits = 0x1;      } +    /* squeeze lists */ +#define SQUEEZE(C, L) \ +    if (!e->C) { free(e->L); e->L = NULL; } \ +    else { e->L = realloc(e->L, sizeof(e->L[0]) * (e->C)); } + +    SQUEEZE(dtd_count, dtds); +    SQUEEZE(cea_block_count, cea_blocks); +    SQUEEZE(svd_count, svds); +    SQUEEZE(sad_count, sads); +    SQUEEZE(did_block_count, did_blocks); +    SQUEEZE(didt_count, didts);      return e;  } @@ -528,20 +653,26 @@ edid_dump_hex_done:  const char *edid_standard(int std) {      switch(std) { -        case 0: return N_("VESA EDID"); -        case 1: return N_("EIA/CEA-861"); -        case 2: return N_("VESA DisplayID"); +        case STD_EDID: return N_("VESA EDID"); +        case STD_EEDID: return N_("VESA E-EDID"); +        case STD_EIACEA861: return N_("EIA/CEA-861"); +        case STD_DISPLAYID: return N_("VESA DisplayID"); +        case STD_DISPLAYID20: return N_("VESA DisplayID 2.0");      };      return N_("unknown");  }  const char *edid_output_src(int src) {      switch(src) { -        case 0: return N_("VESA EDID"); -        case 1: return N_("VESA EDID ETB"); -        case 2: return N_("VESA EDID STD"); -        case 3: return N_("VESA EDID DTD"); -        case 4: return N_("EIA/CEA-861 DTD"); +        case OUTSRC_EDID: return N_("VESA EDID"); +        case OUTSRC_ETB: return N_("VESA EDID ETB"); +        case OUTSRC_STD: return N_("VESA EDID STD"); +        case OUTSRC_DTD: return N_("VESA EDID DTD"); +        case OUTSRC_CEA_DTD: return N_("EIA/CEA-861 DTD"); +        case OUTSRC_SVD: return N_("EIA/CEA-861 SVD"); +        case OUTSRC_DID_TYPE_I: return N_("DisplayID Type I"); +        case OUTSRC_DID_TYPE_VI: return N_("DisplayID Type VI"); +        case OUTSRC_DID_TYPE_VII: return N_("DisplayID Type VII");      };      return N_("unknown");  } @@ -592,6 +723,46 @@ const char *edid_cea_block_type(int type) {      return N_("unknown type");  } +const char *edid_did_block_type(int type) { +    switch(type) { +        /* 1.x */ +        case 0x00: return N_("Product Identification (1.x)"); +        case 0x01: return N_("Display Parameters (1.x)"); +        case 0x02: return N_("Color Characteristics (1.x)"); +        case 0x03: return N_("Type I Timing - Detailed (1.x)"); +        case 0x04: return N_("Type II Timing - Detailed (1.x)"); +        case 0x05: return N_("Type III Timing - Short (1.x)"); +        case 0x06: return N_("Type IV Timing - DMT ID Code (1.x)"); +        case 0x07: return N_("VESA Timing Standard (1.x)"); +        case 0x08: return N_("CEA Timing Standard (1.x)"); +        case 0x09: return N_("Video Timing Range (1.x)"); +        case 0x0A: return N_("Product Serial Number (1.x)"); +        case 0x0B: return N_("General Purpose ASCII String (1.x)"); +        case 0x0C: return N_("Display Device Data (1.x)"); +        case 0x0D: return N_("Interface Power Sequencing (1.x)"); +        case 0x0E: return N_("Transfer Characteristics (1.x)"); +        case 0x0F: return N_("Display Interface Data (1.x)"); +        case 0x10: return N_("Stereo Display Interface (1.x)"); +        case 0x11: return N_("Type V Timing - Short (1.x)"); +        case 0x13: return N_("Type VI Timing - Detailed (1.x)"); +        case 0x7F: return N_("Vendor specific (1.x)"); +        /* 2.x */ +        case 0x20: return N_("Product Identification"); +        case 0x21: return N_("Display Parameters"); +        case 0x22: return N_("Type VII - Detailed Timing"); +        case 0x23: return N_("Type VIII - Enumerated Timing Code"); +        case 0x24: return N_("Type IX - Formula-based Timing"); +        case 0x25: return N_("Dynamic Video Timing Range Limits"); +        case 0x26: return N_("Display Interface Features"); +        case 0x27: return N_("Stereo Display Interface"); +        case 0x28: return N_("Tiled Display Topology"); +        case 0x29: return N_("ContainerID"); +        case 0x7E: return N_("Vendor specific"); +        case 0x81: return N_("CTA DisplayID"); +    } +    return N_("unknown type"); +} +  const char *edid_ext_block_type(int type) {      switch(type) {          case 0x00: @@ -735,6 +906,23 @@ char *edid_cea_block_describe(struct edid_cea_block *blk) {      return ret;  } +char *edid_did_block_describe(DisplayIDBlock *blk) { +    gchar *ret = NULL; +    if (blk) { +        char *hb = hex_bytes(blk->ptr, blk->len+3); +        switch(blk->type) { +            default: +                ret = g_strdup_printf("([%02x:r%02x] %s) len:%d -- %s", +                    blk->type, blk->revision, _(edid_did_block_type(blk->type)), +                    blk->len, +                    hb); +                break; +        } +        free(hb); +    } +    return ret; +} +  char *edid_output_describe(edid_output *out) {      gchar *ret = NULL;      if (out) { @@ -837,6 +1025,7 @@ char *edid_dump2(edid *e) {      for(i = 0; i < e->cea_block_count; i++) {          char *desc = edid_cea_block_describe(&e->cea_blocks[i]);          ret = appfnl(ret, "cea_block[%d] %s", i, desc); +        free(desc);      }      for(i = 0; i < e->svd_count; i++) { @@ -853,6 +1042,18 @@ char *edid_dump2(edid *e) {          free(desc);      } +    for(i = 0; i < e->did_block_count; i++) { +        char *desc = edid_did_block_describe(&e->did_blocks[i]); +        ret = appfnl(ret, "did_block[%d] %s", i, desc); +        free(desc); +    } + +    for(i = 0; i < e->didt_count; i++) { +        char *desc = edid_output_describe(&e->didts[i]); +        ret = appfnl(ret, "did_timing[%d]: %s", i, desc); +        g_free(desc); +    } +      return ret;  } | 
