Move it to a new function displayid_block. Then we can simplify it later. This is mostly just a copy/paste. No output should change. The new function returns 0xff for len to signal a break from the loop in parse_displayid_block. That will be cleaned up later. first_data_block is replaced with dispid.block_number (similar to cta.block_number) Signed-off-by: Joe van Tunen <joevt@xxxxxxx> --- edid-decode.h | 3 ++ parse-displayid-block.cpp | 95 +++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/edid-decode.h b/edid-decode.h index dbc00c2..4636978 100644 --- a/edid-decode.h +++ b/edid-decode.h @@ -176,6 +176,7 @@ struct edid_state { dispid.is_display = dispid.has_product_identification = dispid.has_display_parameters = dispid.has_type_1_7 = dispid.has_display_interface_features = false; + dispid.block_number = 0; // Block Map block state block_map.saw_block_1 = false; @@ -283,6 +284,7 @@ struct edid_state { bool has_display_interface_features; vec_timings_ext preferred_timings; unsigned native_width, native_height; + unsigned block_number; // 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; @@ -393,6 +395,7 @@ struct edid_state { void parse_displayid_type_10_timing(const unsigned char *x, unsigned sz, bool is_cta = false); void preparse_displayid_block(const unsigned char *x); + unsigned displayid_block(const unsigned version, const unsigned char *x, unsigned offset, unsigned length); void parse_displayid_block(const unsigned char *x); void parse_displayid_vesa(const unsigned char *x); void parse_displayid_cta_data_block(const unsigned char *x); diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp index e4c3bff..0a996bd 100644 --- a/parse-displayid-block.cpp +++ b/parse-displayid-block.cpp @@ -1651,47 +1651,9 @@ void edid_state::preparse_displayid_block(const unsigned char *x) } } -void edid_state::parse_displayid_block(const unsigned char *x) +unsigned edid_state::displayid_block(const unsigned version, const unsigned char *x, unsigned offset, unsigned length) { - unsigned version = x[1]; - unsigned length = x[2]; - unsigned prod_type = x[3]; // future check: based on type, check for required data blocks - unsigned ext_count = x[4]; unsigned i; - - printf(" Version: %u.%u\n Extension Count: %u\n", - version >> 4, version & 0xf, ext_count); - - if (dispid.is_base_block) { - dispid.version = version; - printf(" %s: %s\n", product_type(prod_type, true).c_str(), - product_type(prod_type, false).c_str()); - if (!prod_type) - fail("DisplayID Base Block has no product type.\n"); - if (ext_count != dispid.preparsed_displayid_blocks - 1) - fail("Expected %u DisplayID Extension Block%s, but got %u.\n", - ext_count, - ext_count > 1 ? "s" : "", - dispid.preparsed_displayid_blocks - 1); - } else { - if (prod_type) - fail("Product Type should be 0 in extension block.\n"); - if (ext_count) - fail("Extension Count should be 0 in extension block.\n"); - if (version != dispid.version) - fail("Got version %u.%u, expected %u.%u.\n", - version >> 4, version & 0xf, - dispid.version >> 4, dispid.version & 0xf); - } - - if (length > 121) { - fail("DisplayID length %d is greater than 121.\n", length); - length = 121; - } - - unsigned offset = 5; - bool first_data_block = true; - while (length > 0) { unsigned tag = x[offset]; unsigned oui = 0; @@ -1773,7 +1735,7 @@ void edid_state::parse_displayid_block(const unsigned char *x) if (tag || x[offset + 1]) { fail("Not enough bytes remain (%d) for a DisplayID data block or the DisplayID filler is non-0.\n", length); } - break; + return 0xff; } unsigned block_rev = x[offset + 1] & 0x07; @@ -1781,7 +1743,7 @@ void edid_state::parse_displayid_block(const unsigned char *x) if (length < len + 3) { fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d).\n", len + 3, length); - break; + return 0xff; } if (!tag && !len) { @@ -1789,7 +1751,7 @@ void edid_state::parse_displayid_block(const unsigned char *x) if (!memchk(x + offset, length)) { fail("Non-0 filler bytes in the DisplayID block.\n"); } - break; + return 0xff; } printf(" %s:\n", data_block.c_str()); @@ -1925,12 +1887,57 @@ void edid_state::parse_displayid_block(const unsigned char *x) } if ((tag == 0x00 || tag == 0x20) && - (!dispid.is_base_block || !first_data_block)) + (!dispid.is_base_block || dispid.block_number > 0)) fail("%s is required to be the first DisplayID Data Block.\n", data_block.c_str()); + + dispid.block_number++; + return len; +} + +void edid_state::parse_displayid_block(const unsigned char *x) +{ + unsigned version = x[1]; + unsigned length = x[2]; + unsigned prod_type = x[3]; // future check: based on type, check for required data blocks + unsigned ext_count = x[4]; + + printf(" Version: %u.%u\n Extension Count: %u\n", + version >> 4, version & 0xf, ext_count); + + if (dispid.is_base_block) { + dispid.version = version; + printf(" %s: %s\n", product_type(prod_type, true).c_str(), + product_type(prod_type, false).c_str()); + if (!prod_type) + fail("DisplayID Base Block has no product type.\n"); + if (ext_count != dispid.preparsed_displayid_blocks - 1) + fail("Expected %u DisplayID Extension Block%s, but got %u.\n", + ext_count, + ext_count > 1 ? "s" : "", + dispid.preparsed_displayid_blocks - 1); + } else { + if (prod_type) + fail("Product Type should be 0 in extension block.\n"); + if (ext_count) + fail("Extension Count should be 0 in extension block.\n"); + if (version != dispid.version) + fail("Got version %u.%u, expected %u.%u.\n", + version >> 4, version & 0xf, + dispid.version >> 4, dispid.version & 0xf); + } + + if (length > 121) { + fail("DisplayID length %d is greater than 121.\n", length); + length = 121; + } + + unsigned offset = 5; + while (length > 0) { + unsigned len = displayid_block(version, x, offset, length); + if (len == 0xff) break; length -= len + 3; offset += len + 3; - first_data_block = false; } /* -- 2.24.3 (Apple Git-128)