aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2021-01-15 11:29:33 +0100
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2021-01-15 11:29:33 +0100
commit2174f43e3fae167e7ae53d182f654a0ccf2c2c69 (patch)
tree589d868bede939842bf38e6c8cc7638247c6e0cb
parentf48427bcd5d079d2ddea31bc26cc919ebabb2b8d (diff)
edid-decode: check for duplicate CTA data blocks
CTA-861-H explicitly stated which Data Blocks are allowed to have multiple instances. Fail if duplicate Data Blocks are found where only a single instance is allowed. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--edid-decode.h11
-rw-r--r--parse-cta-block.cpp41
-rw-r--r--parse-displayid-block.cpp13
3 files changed, 56 insertions, 9 deletions
diff --git a/edid-decode.h b/edid-decode.h
index 666080b..e24c300 100644
--- a/edid-decode.h
+++ b/edid-decode.h
@@ -12,6 +12,7 @@
#include <string>
#include <vector>
+#include <set>
#include <string.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@@ -205,6 +206,9 @@ struct edid_state {
vec_timings_ext vec_vtdbs;
vec_timings_ext preferred_timings;
bool preparsed_has_t8vtdb;
+ // Keep track of the found Tag/Extended Tag pairs.
+ // The unsigned value is equal to: (tag << 8) | ext_tag
+ std::set<unsigned> found_tags;
timings_ext t8vtdb;
vec_timings_ext native_timings;
bool has_vic_1;
@@ -242,6 +246,9 @@ struct edid_state {
bool has_type_1_7;
bool has_display_interface_features;
vec_timings_ext preferred_timings;
+ // Keep track of the found CTA-861 Tag/Extended Tag pairs.
+ // The unsigned value is equal to: (tag << 8) | ext_tag
+ std::set<unsigned> found_tags;
} dispid;
// Block Map block state
@@ -287,8 +294,8 @@ struct edid_state {
void cta_displayid_type_7(const unsigned char *x, unsigned length);
void cta_displayid_type_8(const unsigned char *x, unsigned length);
void cta_displayid_type_10(const unsigned char *x, unsigned length);
- void cta_ext_block(const unsigned char *x, unsigned length);
- void cta_block(const unsigned char *x);
+ void cta_ext_block(const unsigned char *x, unsigned length, bool duplicate);
+ void cta_block(const unsigned char *x, bool duplicate);
void preparse_cta_block(const unsigned char *x);
void parse_cta_block(const unsigned char *x);
void cta_resolve_svr(vec_timings_ext::iterator iter);
diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
index b6519c1..8f759eb 100644
--- a/parse-cta-block.cpp
+++ b/parse-cta-block.cpp
@@ -1855,7 +1855,8 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
}
}
-void edid_state::cta_ext_block(const unsigned char *x, unsigned length)
+void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
+ bool duplicate)
{
const char *name;
unsigned oui;
@@ -1905,6 +1906,23 @@ void edid_state::cta_ext_block(const unsigned char *x, unsigned length)
return;
}
+ switch (x[0]) {
+ case 0x00:
+ case 0x02:
+ case 0x05:
+ case 0x06:
+ case 0x0d:
+ case 0x0f:
+ case 0x12:
+ case 0x13:
+ case 0x78:
+ case 0x79:
+ if (duplicate)
+ 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");
@@ -2018,7 +2036,7 @@ void edid_state::cta_ext_block(const unsigned char *x, unsigned length)
hex_block(" ", x + 1, length);
}
-void edid_state::cta_block(const unsigned char *x)
+void edid_state::cta_block(const unsigned char *x, bool duplicate)
{
unsigned length = x[0] & 0x1f;
const char *name;
@@ -2090,14 +2108,18 @@ void edid_state::cta_block(const unsigned char *x)
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);
+ cta_ext_block(x + 1, length - 1, duplicate);
break;
default: {
unsigned tag = (*x & 0xe0) >> 5;
@@ -2260,8 +2282,17 @@ void edid_state::parse_cta_block(const unsigned char *x)
if (version >= 3) {
unsigned i;
- for (i = 4; i < offset; i += (x[i] & 0x1f) + 1)
- cta_block(x + 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);
+ }
data_block.clear();
if (i != offset)
diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
index 035e53d..93cd16f 100644
--- a/parse-displayid-block.cpp
+++ b/parse-displayid-block.cpp
@@ -1446,8 +1446,17 @@ void edid_state::parse_displayid_cta_data_block(const unsigned char *x)
}
x += 3;
- for (i = 0; i < len; i += (x[i] & 0x1f) + 1)
- cta_block(x + i);
+ for (i = 0; i < len; i += (x[i] & 0x1f) + 1) {
+ unsigned tag = (x[i] & 0xe0) << 3;
+
+ if (tag == 0x700)
+ tag |= x[i + 1];
+ bool duplicate = dispid.found_tags.find(tag) != dispid.found_tags.end();
+
+ cta_block(x + i, duplicate);
+ if (!duplicate)
+ dispid.found_tags.insert(tag);
+ }
if (i != len)
fail("Length is %u instead of %u.\n", len, i);

Privacy Policy