aboutsummaryrefslogtreecommitdiffstats
path: root/parse-cta-block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parse-cta-block.cpp')
-rw-r--r--parse-cta-block.cpp587
1 files changed, 239 insertions, 348 deletions
diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
index ee0b01d..9a2ef8a 100644
--- a/parse-cta-block.cpp
+++ b/parse-cta-block.cpp
@@ -7,6 +7,7 @@
* Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
*/
+#include <algorithm>
#include <stdio.h>
#include <math.h>
@@ -546,6 +547,55 @@ void edid_state::cta_y420cmdb(const unsigned char *x, unsigned length)
max_idx + 1, cta.preparsed_svds[0].size());
}
+void edid_state::cta_print_svr(unsigned char svr, vec_timings_ext &vec_tim)
+{
+ char suffix[16];
+
+ if ((svr > 0 && svr < 128) || (svr > 192 && svr < 254)) {
+ const struct timings *t;
+ unsigned char vic = svr;
+
+ sprintf(suffix, "VIC %3u", vic);
+
+ t = find_vic_id(vic);
+ if (t) {
+ print_timings(" ", t, suffix);
+ vec_tim.push_back(timings_ext(*t, suffix, ""));
+ } else {
+ printf(" %s: Unknown\n", suffix);
+ fail("Unknown VIC %u.\n", vic);
+ }
+
+ } else if (svr >= 129 && svr <= 144) {
+ sprintf(suffix, "DTD %3u", svr - 128);
+ if (svr >= cta.preparsed_total_dtds + 129) {
+ printf(" %s: Invalid\n", suffix);
+ fail("Invalid DTD %u.\n", svr - 128);
+ } else {
+ printf(" %s\n", suffix);
+ vec_tim.push_back(timings_ext(svr, suffix));
+ }
+ } else if (svr >= 145 && svr <= 160) {
+ sprintf(suffix, "VTDB %3u", svr - 144);
+ if (svr >= cta.preparsed_total_vtdbs + 145) {
+ printf(" %s: Invalid\n", suffix);
+ fail("Invalid VTDB %u.\n", svr - 144);
+ } else {
+ printf(" %s\n", suffix);
+ vec_tim.push_back(timings_ext(svr, suffix));
+ }
+ } else if (svr == 254) {
+ sprintf(suffix, "T8VTDB");
+ if (!cta.preparsed_has_t8vtdb) {
+ printf(" %s: Invalid\n", suffix);
+ fail("Invalid T8VTDB.\n");
+ } else {
+ printf(" %s\n", suffix);
+ vec_tim.push_back(timings_ext(svr, suffix));
+ }
+ }
+}
+
void edid_state::cta_vfpdb(const unsigned char *x, unsigned length)
{
unsigned i;
@@ -555,54 +605,8 @@ void edid_state::cta_vfpdb(const unsigned char *x, unsigned length)
return;
}
cta.preferred_timings.clear();
- for (i = 0; i < length; i++) {
- unsigned char svr = x[i];
- char suffix[16];
-
- if ((svr > 0 && svr < 128) || (svr > 192 && svr < 254)) {
- const struct timings *t;
- unsigned char vic = svr;
-
- sprintf(suffix, "VIC %3u", vic);
-
- t = find_vic_id(vic);
- if (t) {
- print_timings(" ", t, suffix);
- cta.preferred_timings.push_back(timings_ext(*t, suffix, ""));
- } else {
- printf(" %s: Unknown\n", suffix);
- fail("Unknown VIC %u.\n", vic);
- }
-
- } else if (svr >= 129 && svr <= 144) {
- sprintf(suffix, "DTD %3u", svr - 128);
- if (svr >= cta.preparsed_total_dtds + 129) {
- printf(" %s: Invalid\n", suffix);
- fail("Invalid DTD %u.\n", svr - 128);
- } else {
- printf(" %s\n", suffix);
- cta.preferred_timings.push_back(timings_ext(svr, suffix));
- }
- } else if (svr >= 145 && svr <= 160) {
- sprintf(suffix, "VTDB %3u", svr - 144);
- if (svr >= cta.preparsed_total_vtdbs + 145) {
- printf(" %s: Invalid\n", suffix);
- fail("Invalid VTDB %u.\n", svr - 144);
- } else {
- printf(" %s\n", suffix);
- cta.preferred_timings.push_back(timings_ext(svr, suffix));
- }
- } else if (svr == 254) {
- sprintf(suffix, "T8VTDB");
- if (!cta.preparsed_has_t8vtdb) {
- printf(" %s: Invalid\n", suffix);
- fail("Invalid T8VTDB.\n");
- } else {
- printf(" %s\n", suffix);
- cta.preferred_timings.push_back(timings_ext(svr, suffix));
- }
- }
- }
+ for (i = 0; i < length; i++)
+ cta_print_svr(x[i], cta.preferred_timings);
}
static std::string hdmi_latency2s(unsigned char l, bool is_video)
@@ -652,57 +656,57 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
{
unsigned len_vic, len_3d;
- if (length < 4) {
+ if (length < 1) {
fail("Empty Data Block with length %u.\n", length);
return;
}
- printf(" Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
- x[4] >> 4, x[4] & 0x0f);
+ printf(" Source physical address: %x.%x.%x.%x\n", x[0] >> 4, x[0] & 0x0f,
+ x[1] >> 4, x[1] & 0x0f);
- if (length < 6)
+ if (length < 3)
return;
- if (x[5] & 0x80)
+ if (x[2] & 0x80)
printf(" Supports_AI\n");
- if (x[5] & 0x40)
+ if (x[2] & 0x40)
printf(" DC_48bit\n");
- if (x[5] & 0x20)
+ if (x[2] & 0x20)
printf(" DC_36bit\n");
- if (x[5] & 0x10)
+ if (x[2] & 0x10)
printf(" DC_30bit\n");
- if (x[5] & 0x08)
+ if (x[2] & 0x08)
printf(" DC_Y444\n");
/* two reserved bits */
- if (x[5] & 0x01)
+ if (x[2] & 0x01)
printf(" DVI_Dual\n");
- if (length < 7)
+ if (length < 4)
return;
- printf(" Maximum TMDS clock: %u MHz\n", x[6] * 5);
- if (x[6] * 5 > 340)
+ printf(" Maximum TMDS clock: %u MHz\n", x[3] * 5);
+ if (x[3] * 5 > 340)
fail("HDMI VSDB Max TMDS rate is > 340.\n");
- if (length < 8)
+ if (length < 5)
return;
- if (x[7] & 0x0f) {
+ if (x[4] & 0x0f) {
printf(" Supported Content Types:\n");
- if (x[7] & 0x01)
+ if (x[4] & 0x01)
printf(" Graphics\n");
- if (x[7] & 0x02)
+ if (x[4] & 0x02)
printf(" Photo\n");
- if (x[7] & 0x04)
+ if (x[4] & 0x04)
printf(" Cinema\n");
- if (x[7] & 0x08)
+ if (x[4] & 0x08)
printf(" Game\n");
}
- unsigned b = 8;
- if (x[7] & 0x80) {
+ unsigned b = 5;
+ if (x[4] & 0x80) {
hdmi_latency(x[b], x[b + 1], false);
- if (x[7] & 0x40) {
+ if (x[4] & 0x40) {
if (x[b] == x[b + 2] &&
x[b + 1] == x[b + 3])
warn("Progressive and Interlaced latency values are identical, no need for both.\n");
@@ -712,7 +716,7 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
b += 2;
}
- if (!(x[7] & 0x20))
+ if (!(x[4] & 0x20))
return;
bool mask = false;
@@ -1133,11 +1137,12 @@ static void cta_microsoft(const unsigned char *x, unsigned length)
static void cta_hdr10plus(const unsigned char *x, unsigned length)
{
- printf(" Application Version: %u", x[0]);
- if (length > 1)
- hex_block(" ", x + 1, length - 1);
- else
- printf("\n");
+ if (length == 0) {
+ fail("Empty Data Block with length %u.\n", length);
+ return;
+ }
+ printf(" Application Version: %u\n", x[0]);
+ hex_block(" ", x + 1, length - 1);
}
// Convert a PQ value (0-1) to cd/m^2 aka nits (0-10000)
@@ -2026,293 +2031,187 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
}
}
-void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
- bool duplicate)
+void edid_state::cta_block(const unsigned char *x, std::vector<unsigned> &found_tags)
{
- const char *name;
- unsigned oui;
- bool reverse = false;
+ unsigned length = x[0] & 0x1f;
+ unsigned tag = (x[0] & 0xe0) >> 5;
+ unsigned extended = (tag == 0x07) ? 1 : 0;
+
+ x++;
+ if (extended && length) {
+ tag <<= 8;
+ tag |= x[0];
+ length--;
+ x++;
+ }
+
+ bool dooutputname = true;
bool audio_block = false;
+ data_block.clear();
+
+ switch (tag) {
+ case 0x01: data_block = "Audio Data Block"; audio_block = true; break;
+ case 0x02: data_block = "Video Data Block"; break;
+ case 0x03: data_block = "Vendor-Specific Data Block"; break;
+ case 0x04: data_block = "Speaker Allocation Data Block"; audio_block = true; break;
+ case 0x05: data_block = "VESA Display Transfer Characteristics Data Block"; break;
+
+ case 0x07: data_block = "Unknown CTA-861 Data Block (extended tag truncated)"; break;
+
+ case 0x700: data_block = "Video Capability Data Block"; break;
+ case 0x701: data_block = "Vendor-Specific Video Data Block"; break;
+ case 0x702: data_block = "VESA Video Display Device Data Block"; break;
+ case 0x703: data_block = "VESA Video Timing Block Extension"; break;
+ case 0x704: data_block = "Reserved for HDMI Video Data Block"; break;
+ case 0x705: data_block = "Colorimetry Data Block"; break;
+ case 0x706: data_block = "HDR Static Metadata Data Block"; break;
+ case 0x707: data_block = "HDR Dynamic Metadata Data Block"; break;
+
+ case 0x70d: data_block = "Video Format Preference Data Block"; break;
+ case 0x70e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
+ case 0x70f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
+ case 0x710: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
+ case 0x711: data_block = "Vendor-Specific Audio Data Block"; audio_block = true; break;
+ case 0x712: data_block = "HDMI Audio Data Block"; audio_block = true; break;
+ case 0x713: data_block = "Room Configuration Data Block"; audio_block = true; break;
+ case 0x714: data_block = "Speaker Location Data Block"; audio_block = true; break;
+
+ case 0x720: data_block = "InfoFrame Data Block"; break;
+
+ case 0x722: data_block = "DisplayID Type VII Video Timing Data Block"; break;
+ case 0x723: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
+ case 0x72a: data_block = "DisplayID Type X Video Timing Data Block"; break;
+
+ case 0x778: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
+ case 0x779: data_block = "HDMI Forum Sink Capability Data Block"; break;
- switch (x[0]) {
- case 0x00: data_block = "Video Capability Data Block"; break;
- case 0x01: data_block.clear(); break;
- case 0x02: data_block = "VESA Video Display Device Data Block"; break;
- case 0x03: data_block = "VESA Video Timing Block Extension"; break;
- case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
- case 0x05: data_block = "Colorimetry Data Block"; break;
- case 0x06: data_block = "HDR Static Metadata Data Block"; break;
- case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
-
- case 0x0d: data_block = "Video Format Preference Data Block"; break;
- case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
- case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
- case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
- case 0x11: data_block.clear(); audio_block = true; break;
- case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
- case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
- case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
-
- case 0x20: data_block = "InfoFrame Data Block"; break;
-
- case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
- case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
- case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
-
- case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
- case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
default:
- if (x[0] <= 12)
- printf(" Unknown CTA-861 Video-Related");
- else if (x[0] <= 31)
- printf(" Unknown CTA-861 Audio-Related");
- else if (x[0] >= 120 && x[0] <= 127)
- printf(" Unknown CTA-861 HDMI-Related");
- else
- printf(" Unknown CTA-861");
- printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
- hex_block(" ", x + 1, length);
- data_block.clear();
- warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
- return;
+ std::string unknown_name;
+ if (tag < 0x700) unknown_name = "Unknown CTA-861 Data Block";
+ else if (tag < 0x70d) unknown_name = "Unknown CTA-861 Video-Related Data Block";
+ else if (tag < 0x720) unknown_name = "Unknown CTA-861 Audio-Related Data Block";
+ else if (tag < 0x778) unknown_name = "Unknown CTA-861 Data Block";
+ else if (tag < 0x780) unknown_name = "Unknown CTA-861 HDMI-Related Data Block";
+ else unknown_name = "Unknown CTA-861 Data Block";
+ unknown_name += std::string(" (") + (extended ? "extended " : "") + "tag " + utohex(tag & 0xff) + ", length " + std::to_string(length) + ")";
+ printf(" %s:\n", unknown_name.c_str());
+ warn("%s.\n", unknown_name.c_str());
+ break;
+ }
+
+ switch (tag) {
+ case 0x03:
+ case 0x701:
+ case 0x711: {
+ unsigned ouinum;
+
+ data_block_oui(data_block, x, length, &ouinum);
+ x += (length < 3) ? length : 3;
+ length -= (length < 3) ? length : 3;
+ dooutputname = false;
+ tag |= ouinum;
+ break;
}
+ }
+
+ if (dooutputname && data_block.length())
+ printf(" %s:\n", data_block.c_str());
- switch (x[0]) {
- case 0x00:
- case 0x02:
+ switch (tag) {
+ case 0x04:
case 0x05:
- case 0x06:
- case 0x0d:
- case 0x0f:
- case 0x12:
- case 0x13:
- case 0x78:
- case 0x79:
- if (duplicate)
+ case 0x700:
+ case 0x702:
+ case 0x705:
+ case 0x706:
+ case 0x70d:
+ case 0x70f:
+ case 0x712:
+ case 0x713:
+ case 0x778:
+ case 0x779:
+ if (std::find(found_tags.begin(), found_tags.end(), tag) != found_tags.end())
fail("Only one instance of this Data Block is allowed.\n");
break;
}
-
// See Table 52 of CTA-861-G for a description of Byte 3
if (audio_block && !(cta.byte3 & 0x40))
- fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
-
- if (data_block.length())
- printf(" %s:\n", data_block.c_str());
-
- switch (x[0]) {
- case 0x00: cta_vcdb(x + 1, length); return;
- case 0x01:
- if (length < 3) {
- data_block = std::string("Vendor-Specific Video Data Block");
- fail("Invalid length %u < 3.\n", length);
- return;
- }
- oui = (x[3] << 16) + (x[2] << 8) + x[1];
- name = oui_name(oui);
- if (!name) {
- name = oui_name(oui, true);
- if (name)
- reverse = true;
- }
- if (!name) {
- printf(" Vendor-Specific Video Data Block, OUI %s:\n",
- ouitohex(oui).c_str());
- hex_block(" ", x + 4, length - 3);
- data_block.clear();
- warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
- ouitohex(oui).c_str());
- return;
- }
- data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
- if (reverse)
- fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
- printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
- if (oui == 0x90848b)
- cta_hdr10plus(x + 4, length - 3);
- else if (oui == 0x00d046)
- cta_dolby_video(x + 4, length - 3);
- else
- hex_block(" ", x + 4, length - 3);
- return;
- case 0x02: cta_vesa_vdddb(x + 1, length); return;
- case 0x05: cta_colorimetry_block(x + 1, length); return;
- case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
- case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
- case 0x0d: cta_vfpdb(x + 1, length); return;
- case 0x0e: cta_svd(x + 1, length, true); return;
- case 0x0f: cta_y420cmdb(x + 1, length); return;
- case 0x11:
- if (length < 3) {
- data_block = std::string("Vendor-Specific Audio Data Block");
- fail("Invalid length %u < 3.\n", length);
- return;
- }
- oui = (x[3] << 16) + (x[2] << 8) + x[1];
- name = oui_name(oui);
- if (!name) {
- name = oui_name(oui, true);
- if (name)
- reverse = true;
- }
- if (!name) {
- printf(" Vendor-Specific Audio Data Block, OUI %s:\n",
- ouitohex(oui).c_str());
- hex_block(" ", x + 4, length - 3);
- data_block.clear();
- warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
- ouitohex(oui).c_str());
- return;
- }
- data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
- if (reverse)
- fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
- printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
- if (oui == 0x00d046)
- cta_dolby_audio(x + 4, length - 3);
- else
- hex_block(" ", x + 4, length - 3);
- return;
- case 0x12: cta_hdmi_audio_block(x + 1, length); return;
- case 0x13: cta_rcdb(x + 1, length); return;
- case 0x14: cta_sldb(x + 1, length); return;
- case 0x20: cta_ifdb(x + 1, length); return;
- case 0x34: cta_displayid_type_7(x + 1, length); return;
- case 0x35: cta_displayid_type_8(x + 1, length); return;
- case 0x42: cta_displayid_type_10(x + 1, length); return;
- case 0x78:
- cta_hf_eeodb(x + 1, length);
+ fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
+
+ switch (tag) {
+ case 0x01: cta_audio_block(x, length); break;
+ case 0x02: cta_svd(x, length, false); break;
+ case 0x03|kOUI_HDMI:
+ cta_hdmi_block(x, length);
+ // The HDMI OUI is present, so this EDID represents an HDMI
+ // interface. And HDMI interfaces must use EDID version 1.3
+ // according to the HDMI Specification, so check for this.
+ if (base.edid_minor != 3)
+ fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
+ base.edid_minor);
+ break;
+ case 0x03|kOUI_HDMIForum:
+ if (cta.previous_cta_tag != (0x03|kOUI_HDMI))
+ fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
+ if (cta.have_hf_scdb || cta.have_hf_vsdb)
+ fail("Duplicate HDMI Forum VSDB/SCDB.\n");
+ cta_hf_scdb(x, length);
+ cta.have_hf_vsdb = true;
+ break;
+ case 0x03|kOUI_AMD: cta_amd(x, length); break;
+ case 0x03|kOUI_Microsoft: if (length != 0x12) goto dodefault; cta_microsoft(x, length); break;
+ case 0x04: cta_sadb(x, length); break;
+ case 0x05: cta_vesa_dtcdb(x, length); break;
+ case 0x07: fail("Extended tag cannot have zero length.\n"); break;
+ case 0x700: cta_vcdb(x, length); break;
+ case 0x701|kOUI_HDR10: cta_hdr10plus(x, length); break;
+ case 0x701|kOUI_Dolby: cta_dolby_video(x, length); break;
+ case 0x702: cta_vesa_vdddb(x, length); break;
+ case 0x705: cta_colorimetry_block(x, length); break;
+ case 0x706: cta_hdr_static_metadata_block(x, length); break;
+ case 0x707: cta_hdr_dyn_metadata_block(x, length); break;
+ case 0x70d: cta_vfpdb(x, length); break;
+ case 0x70e: cta_svd(x, length, true); break;
+ case 0x70f: cta_y420cmdb(x, length); break;
+ case 0x711|kOUI_Dolby: cta_dolby_audio(x, length); break;
+ case 0x712: cta_hdmi_audio_block(x, length); break;
+ case 0x713: cta_rcdb(x, length); break;
+ case 0x714: cta_sldb(x, length); break;
+ case 0x720: cta_ifdb(x, length); break;
+ case 0x722: cta_displayid_type_7(x, length); break;
+ case 0x723: cta_displayid_type_8(x, length); break;
+ case 0x72a: cta_displayid_type_10(x, length); break;
+ case 0x778:
+ cta_hf_eeodb(x, length);
// This must be the first CTA-861 block
- if (!cta.first_block)
+ if (cta.block_number > 0)
fail("Block starts at a wrong offset.\n");
- return;
- case 0x79:
- if (!cta.last_block_was_hdmi_vsdb)
+ break;
+ case 0x779:
+ if (cta.previous_cta_tag != (0x03|kOUI_HDMI))
fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
if (cta.have_hf_scdb || cta.have_hf_vsdb)
fail("Duplicate HDMI Forum VSDB/SCDB.\n");
if (length < 2) {
data_block = std::string("HDMI Forum SCDB");
fail("Invalid length %u < 2.\n", length);
- return;
- }
- if (x[1] || x[2])
- printf(" Non-zero SCDB reserved fields!\n");
- cta_hf_scdb(x + 3, length - 2);
- cta.have_hf_scdb = 1;
- return;
- }
-
- hex_block(" ", x + 1, length);
-}
-
-void edid_state::cta_block(const unsigned char *x, bool duplicate)
-{
- unsigned length = x[0] & 0x1f;
- const char *name;
- unsigned oui;
- bool reverse = false;
- bool audio_block = false;
-
- switch ((x[0] & 0xe0) >> 5) {
- case 0x01:
- data_block = "Audio Data Block";
- printf(" %s:\n", data_block.c_str());
- cta_audio_block(x + 1, length);
- audio_block = true;
- break;
- case 0x02:
- data_block = "Video Data Block";
- printf(" %s:\n", data_block.c_str());
- cta_svd(x + 1, length, false);
- break;
- case 0x03:
- oui = (x[3] << 16) + (x[2] << 8) + x[1];
- name = oui_name(oui);
- if (!name) {
- name = oui_name(oui, true);
- if (name)
- reverse = true;
- }
- if (!name) {
- printf(" Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
- hex_block(" ", x + 4, length - 3);
- data_block.clear();
- warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
- ouitohex(oui).c_str());
- return;
- }
- data_block = std::string("Vendor-Specific Data Block (") + name + ")";
- if (reverse)
- fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
- printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
- if (oui == 0x000c03) {
- cta_hdmi_block(x + 1, length);
- cta.last_block_was_hdmi_vsdb = 1;
- cta.first_block = 0;
- // The HDMI OUI is present, so this EDID represents an HDMI
- // interface. And HDMI interfaces must use EDID version 1.3
- // according to the HDMI Specification, so check for this.
- if (base.edid_minor != 3)
- fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
- base.edid_minor);
- return;
- }
- if (oui == 0xc45dd8) {
- if (!cta.last_block_was_hdmi_vsdb)
- fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
- if (cta.have_hf_scdb || cta.have_hf_vsdb)
- fail("Duplicate HDMI Forum VSDB/SCDB.\n");
- cta_hf_scdb(x + 4, length - 3);
- cta.have_hf_vsdb = 1;
- break;
- }
- if (oui == 0x00001a) {
- cta_amd(x + 4, length - 3);
- break;
- }
- if (oui == 0xca125c && length == 0x15) {
- cta_microsoft(x + 4, length - 3);
break;
}
- hex_block(" ", x + 4, length - 3);
- break;
- case 0x04:
- data_block = "Speaker Allocation Data Block";
- printf(" %s:\n", data_block.c_str());
- cta_sadb(x + 1, length);
- audio_block = true;
- if (duplicate)
- fail("Only one instance of this Data Block is allowed.\n");
- break;
- case 0x05:
- data_block = "VESA Display Transfer Characteristics Data Block";
- printf(" %s:\n", data_block.c_str());
- cta_vesa_dtcdb(x + 1, length);
- if (duplicate)
- fail("Only one instance of this Data Block is allowed.\n");
- break;
- case 0x07:
- cta_ext_block(x + 1, length - 1, duplicate);
+ if (x[0] || x[1])
+ printf(" Non-zero SCDB reserved fields!\n");
+ cta_hf_scdb(x + 2, length - 2);
+ cta.have_hf_scdb = true;
break;
- default: {
- unsigned tag = (*x & 0xe0) >> 5;
- unsigned length = *x & 0x1f;
-
- printf(" Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
- hex_block(" ", x + 1, length);
- data_block.clear();
- warn("Unknown CTA-861 Data Block %u.\n", tag);
+dodefault:
+ default:
+ hex_block(" ", x, length);
break;
}
- }
- // See Table 52 of CTA-861-G for a description of Byte 3
- if (audio_block && !(cta.byte3 & 0x40))
- fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
- cta.first_block = 0;
- cta.last_block_was_hdmi_vsdb = 0;
+ cta.block_number++;
+ cta.previous_cta_tag = tag;
+ found_tags.push_back(tag);
}
void edid_state::preparse_cta_block(const unsigned char *x)
@@ -2359,7 +2258,7 @@ void edid_state::preparse_cta_block(const unsigned char *x)
cta.preparsed_total_vtdbs++;
if (x[i + 1] == 0x23)
cta.preparsed_has_t8vtdb = true;
- if (x[i + 1] == 0x32)
+ if (x[i + 1] == 0x2a)
cta.preparsed_total_vtdbs +=
((x[i] & 0x1f) - 2) / (6 + ((x[i + 2] & 0x70) >> 4));
if (x[i + 1] != 0x0e)
@@ -2428,11 +2327,11 @@ void edid_state::parse_cta_block(const unsigned char *x)
// msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
// cta.has_hdmi ? "shall" : "should");
printf(" Native detailed modes: %u\n", x[3] & 0x0f);
- if (cta.first_block)
+ if (cta.block_number == 0)
cta.byte3 = x[3];
else if (x[3] != cta.byte3)
fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
- if (cta.first_block) {
+ if (cta.block_number == 0) {
unsigned native_dtds = x[3] & 0x0f;
cta.native_timings.clear();
@@ -2458,15 +2357,7 @@ void edid_state::parse_cta_block(const unsigned char *x)
unsigned i;
for (i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
- unsigned tag = (x[i] & 0xe0) << 3;
-
- if (tag == 0x700)
- tag |= x[i + 1];
- bool duplicate = cta.found_tags.find(tag) != cta.found_tags.end();
-
- cta_block(x + i, duplicate);
- if (!duplicate)
- cta.found_tags.insert(tag);
+ cta_block(x + i, cta.found_tags);
}
data_block.clear();

Privacy Policy