This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: edid-decode: add --block-hex-dump option Author: Hans Verkuil <[email protected]> Date: Tue Mar 10 11:22:04 2026 +0100 This option shows the offset and hex dump of each data block inside the EDID. Useful if you want to manually edit an EDID. Signed-off-by: Hans Verkuil <[email protected]> utils/edid-decode/edid-decode.1.in | 4 ++++ utils/edid-decode/edid-decode.cpp | 16 ++++++++++++++++ utils/edid-decode/edid-decode.h | 3 +++ utils/edid-decode/parse-base-block.cpp | 24 ++++++++++++++++++++++++ utils/edid-decode/parse-cta-block.cpp | 4 ++++ utils/edid-decode/parse-di-ext-block.cpp | 4 ++++ utils/edid-decode/parse-displayid-block.cpp | 4 +++- 7 files changed, 58 insertions(+), 1 deletion(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=d2dc17e57f34a57fa50ba85159361f47f3b99fe4 diff --git a/utils/edid-decode/edid-decode.1.in b/utils/edid-decode/edid-decode.1.in index 869ef53f72d6..5f5361d69497 100644 --- a/utils/edid-decode/edid-decode.1.in +++ b/utils/edid-decode/edid-decode.1.in @@ -280,6 +280,10 @@ Skip the initial hex dump of the EDID. \fB\-H\fR, \fB\-\-only\-hex\-dump\fR Only show the hex dump of the EDID, then exit. .TP +\fB\-b\fR, \fB\-\-block\-hex\-dump\fR +Show the offset and hex dump of each data block inside the EDID. That can be +helpful if you want to manually modify an EDID. +.TP \fB\-\-skip\-sha\fR Don't show the SHA hash. Normally edid-decode will show the SHA, i.e. the hash of the git commit used to compile edid-decode. This uniquely identifies diff --git a/utils/edid-decode/edid-decode.cpp b/utils/edid-decode/edid-decode.cpp index 530d6bc9e4a5..ad373c8d427f 100644 --- a/utils/edid-decode/edid-decode.cpp +++ b/utils/edid-decode/edid-decode.cpp @@ -41,6 +41,7 @@ enum output_format { */ enum Option { OptI2CAdapter = 'a', + OptBlockHexDump = 'b', OptCheck = 'c', OptCheckInline = 'C', OptEld = 'E', @@ -93,6 +94,7 @@ static struct option long_options[] = { { "native-resolution", no_argument, 0, OptNativeResolution }, { "preferred-timings", no_argument, 0, OptPreferredTimings }, { "physical-address", no_argument, 0, OptPhysicalAddress }, + { "block-hex-dump", no_argument, 0, OptBlockHexDump }, { "skip-hex-dump", no_argument, 0, OptSkipHexDump }, { "only-hex-dump", no_argument, 0, OptOnlyHexDump }, { "skip-sha", no_argument, 0, OptSkipSHA }, @@ -165,6 +167,7 @@ static void usage(void) " -V, --v4l2-timings Report all long video timings in v4l2-dv-timings.h format.\n" " -s, --skip-hex-dump Skip the initial hex dump of the EDID.\n" " -H, --only-hex-dump Only output the hex dump of the EDID.\n" + " -b, --block-hex-dump Output hex dump for each block in the EDID.\n" " --skip-sha Skip the SHA report.\n" " --hide-serial-numbers Hide serial numbers with '...'.\n" " --replace-unique-ids Replace unique IDs (serial numbers, dates, Container IDs) with fixed values.\n" @@ -1234,6 +1237,17 @@ std::string block_name(unsigned char block) } } +void edid_state::block_hex_dump(const char *prefix, const unsigned char *start, unsigned length) +{ + if (!options[OptBlockHexDump]) + return; + + printf("%sHex: Offset: 0x%02x Data:", prefix, int(start - start_block)); + for (unsigned i = 0; i < length; i++) + printf(" %02x", start[i]); + printf("\n"); +} + void edid_state::parse_block_map(const unsigned char *x) { unsigned last_valid_block_tag = 0; @@ -1598,11 +1612,13 @@ int edid_state::parse_edid() block = block_name(0x00); printf("Block %u, %s:\n", block_nr, block.c_str()); + start_block = edid; parse_base_block(edid); for (unsigned i = 1; i < num_blocks; i++) { block_nr++; printf("\n----------------\n"); + start_block = edid + i * EDID_PAGE_SIZE; parse_extension(edid + i * EDID_PAGE_SIZE); } diff --git a/utils/edid-decode/edid-decode.h b/utils/edid-decode/edid-decode.h index 2f1a9ec43634..0ff00e907ee4 100644 --- a/utils/edid-decode/edid-decode.h +++ b/utils/edid-decode/edid-decode.h @@ -145,6 +145,7 @@ struct edid_state { { // Global state edid_size = num_blocks = block_nr = 0; + start_block = NULL; max_hor_freq_hz = max_vert_freq_hz = max_pixclk_khz = 0; min_hor_freq_hz = 0xffffff; min_vert_freq_hz = 0xffffffff; @@ -244,6 +245,7 @@ struct edid_state { unsigned edid_size; unsigned num_blocks; unsigned block_nr; + const unsigned char *start_block; std::string block; std::string data_block; unsigned unused_bytes; @@ -444,6 +446,7 @@ struct edid_state { void data_block_oui(std::string block_name, const unsigned char *x, unsigned length, unsigned *ouinum, bool ignorezeros = false, bool do_ascii = false, bool big_endian = false, bool silent = false); + void block_hex_dump(const char *prefix, const unsigned char *start, unsigned length); void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false); void hdmi_latency(unsigned char vid_lat, unsigned char aud_lat, bool is_ilaced); diff --git a/utils/edid-decode/parse-base-block.cpp b/utils/edid-decode/parse-base-block.cpp index 267f3d5597a2..6f6e92bf4a7c 100644 --- a/utils/edid-decode/parse-base-block.cpp +++ b/utils/edid-decode/parse-base-block.cpp @@ -688,6 +688,7 @@ void edid_state::detailed_display_range_limits(const unsigned char *x) data_block = "Display Range Limits"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); base.has_display_range_descriptor = 1; if (base.edid_minor >= 4) { @@ -888,6 +889,7 @@ void edid_state::detailed_epi(const unsigned char *x) { data_block = "EPI Descriptor"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); unsigned v = x[5] & 0x07; @@ -1130,6 +1132,8 @@ void edid_state::detailed_timings(const char *prefix, const unsigned char *x, std::string s_type = base_or_cta ? dtd_type() : "DTD"; bool ok = print_timings(prefix, &t, s_type.c_str(), s_flags.c_str(), true); + if (ok) + block_hex_dump((std::string(prefix) + " ").c_str(), x, 18); timings_ext te(t, s_type, s_flags); if (block_nr == 0 && base.dtd_cnt == 1) { @@ -1240,6 +1244,7 @@ void edid_state::detailed_block(const unsigned char *x) if (!memcmp(x, zero_descr, sizeof(zero_descr))) { data_block = "Empty Descriptor"; printf(" %s\n", data_block.c_str()); + block_hex_dump(" ", x, 18); fail("Use Dummy Descriptor instead of all zeroes.\n"); return; } @@ -1251,6 +1256,7 @@ void edid_state::detailed_block(const unsigned char *x) case 0x10: data_block = "Dummy Descriptor"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); for (i = 5; i < 18; i++) { if (x[i]) { fail("Dummy block filled with garbage.\n"); @@ -1261,6 +1267,7 @@ void edid_state::detailed_block(const unsigned char *x) case 0xf7: data_block = "Established timings III"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); for (i = 0; i < ARRAY_SIZE(established_timings3_dmt_ids); i++) if (x[6 + i / 8] & (1 << (7 - i % 8))) { unsigned char dmt_id = established_timings3_dmt_ids[i]; @@ -1275,6 +1282,7 @@ void edid_state::detailed_block(const unsigned char *x) case 0xf8: data_block = "CVT 3 Byte Timing Codes"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); if (x[5] != 0x01) { fail("Invalid version number %u.\n", x[5]); return; @@ -1287,6 +1295,7 @@ void edid_state::detailed_block(const unsigned char *x) case 0xf9: data_block = "Display Color Management Data"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); printf(" Version : %d\n", x[5]); printf(" Red a3 : %.2f\n", (short)(x[6] | (x[7] << 8)) / 100.0); printf(" Red a2 : %.2f\n", (short)(x[8] | (x[9] << 8)) / 100.0); @@ -1298,6 +1307,7 @@ void edid_state::detailed_block(const unsigned char *x) case 0xfa: data_block = "Standard Timing Identifications"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); for (cnt = i = 0; i < 6; i++) { if (x[5 + i * 2] != 0x01 || x[5 + i * 2 + 1] != 0x01) cnt++; @@ -1312,6 +1322,7 @@ void edid_state::detailed_block(const unsigned char *x) data_block = "Color Point Data"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); w_x = (x[7] << 2) | ((x[6] >> 2) & 3); w_y = (x[8] << 2) | (x[6] & 3); gamma = x[9]; @@ -1340,6 +1351,7 @@ void edid_state::detailed_block(const unsigned char *x) data_block = "Display Product Name"; base.has_name_descriptor = 1; printf(" %s: '%s'\n", data_block.c_str(), extract_string(x + 5, 13, true)); + block_hex_dump(" ", x, 18); return; case 0xfd: detailed_display_range_limits(x); @@ -1349,6 +1361,7 @@ void edid_state::detailed_block(const unsigned char *x) data_block = "Alphanumeric Data String"; printf(" %s: '%s'\n", data_block.c_str(), extract_string(x + 5, 13, true)); + block_hex_dump(" ", x, 18); return; } if (base.detailed_block_cnt == 3) { @@ -1356,6 +1369,7 @@ void edid_state::detailed_block(const unsigned char *x) data_block = "SPWG Descriptor #3"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); memcpy(buf, x + 5, 5); if (strlen(buf) != 5) fail("Invalid PC Maker P/N length.\n"); @@ -1365,6 +1379,7 @@ void edid_state::detailed_block(const unsigned char *x) } else { data_block = "SPWG Descriptor #4"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 18); printf(" SMBUS Values: 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx" " 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n", x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12]); @@ -1399,6 +1414,7 @@ void edid_state::detailed_block(const unsigned char *x) printf(" %s: '123456'\n", data_block.c_str()); else printf(" %s: '%s'\n", data_block.c_str(), sn); + block_hex_dump(" ", x, 18); bool dummy = true; // Any serial numbers consisting only of spaces, 0, and/or 1 // characters are always considered dummy values. @@ -1487,6 +1503,7 @@ void edid_state::parse_base_block(const unsigned char *x) data_block = "EDID Structure Version & Revision"; printf(" %s: %hhu.%hhu\n", data_block.c_str(), x[0x12], x[0x13]); + block_hex_dump(" ", x + 0x12, 2); if (x[0x12] == 1) { base.edid_minor = x[0x13]; if (base.edid_minor > 4) @@ -1500,6 +1517,7 @@ void edid_state::parse_base_block(const unsigned char *x) data_block = "Vendor & Product Identification"; manufacturer = manufacturer_name(x + 0x08); printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x + 0x08, 10); printf(" Manufacturer: %s\n Model: %u\n", manufacturer, (unsigned short)(x[0x0a] + (x[0x0b] << 8))); @@ -1564,6 +1582,7 @@ void edid_state::parse_base_block(const unsigned char *x) data_block = "Basic Display Parameters & Features"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x + 0x14, 5); if (x[0x14] & 0x80) { base.is_analog = false; printf(" Digital display\n"); @@ -1724,6 +1743,7 @@ void edid_state::parse_base_block(const unsigned char *x) data_block = "Color Characteristics"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x + 0x19, 10); col_x = (x[0x1b] << 2) | (x[0x19] >> 6); col_y = (x[0x1c] << 2) | ((x[0x19] >> 4) & 3); printf(" Red : 0.%04u, 0.%04u\n", @@ -1744,6 +1764,7 @@ void edid_state::parse_base_block(const unsigned char *x) data_block = "Established Timings I & II"; if (x[0x23] || x[0x24] || x[0x25]) { printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x + 0x23, 3); for (unsigned i = 0; i < ARRAY_SIZE(established_timings12); i++) { if (x[0x23 + i / 8] & (1 << (7 - i % 8))) { unsigned char dmt_id = established_timings12[i].dmt_id; @@ -1762,6 +1783,7 @@ void edid_state::parse_base_block(const unsigned char *x) } } else { printf(" %s: none\n", data_block.c_str()); + block_hex_dump(" ", x + 0x23, 3); } base.has_640x480p60_est_timing = x[0x23] & 0x20; @@ -1775,10 +1797,12 @@ void edid_state::parse_base_block(const unsigned char *x) } if (found) { printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x + 0x26, 16); for (unsigned i = 0; i < 8; i++) print_standard_timing(" ", x[0x26 + i * 2], x[0x26 + i * 2 + 1]); } else { printf(" %s: none\n", data_block.c_str()); + block_hex_dump(" ", x + 0x26, 16); } /* 18 byte descriptors */ diff --git a/utils/edid-decode/parse-cta-block.cpp b/utils/edid-decode/parse-cta-block.cpp index 24f91c65bf3c..3241d2dcbc2e 100644 --- a/utils/edid-decode/parse-cta-block.cpp +++ b/utils/edid-decode/parse-cta-block.cpp @@ -2783,6 +2783,7 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length) void edid_state::cta_block(const unsigned char *x, std::vector<unsigned> &found_tags) { + const unsigned char *start = x; unsigned length = x[0] & 0x1f; unsigned tag = (x[0] & 0xe0) >> 5; unsigned extended = (tag == 0x07) ? 1 : 0; @@ -2870,6 +2871,8 @@ void edid_state::cta_block(const unsigned char *x, std::vector<unsigned> &found_ if (dooutputname && data_block.length()) printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", start, 1 + (start[0] & 0x1f)); + switch (tag) { case 0x04: case 0x05: @@ -3129,6 +3132,7 @@ void edid_state::parse_cta_block(const unsigned char *x) // See Table 52 of CTA-861-G for a description of Byte 3 + block_hex_dump(" ", x, 4); printf(" Revision: %u\n", version); if (version == 0) fail("Invalid CTA-861 Extension revision 0.\n"); diff --git a/utils/edid-decode/parse-di-ext-block.cpp b/utils/edid-decode/parse-di-ext-block.cpp index 058f6b8e01bd..28cfae8a01f5 100644 --- a/utils/edid-decode/parse-di-ext-block.cpp +++ b/utils/edid-decode/parse-di-ext-block.cpp @@ -11,6 +11,7 @@ void edid_state::parse_digital_interface(const unsigned char *x) { data_block = "Digital Interface"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 12); printf(" Supported Digital Interface: "); unsigned short v = x[2]; @@ -131,6 +132,7 @@ void edid_state::parse_display_device(const unsigned char *x) { data_block = "Display Device"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 6); printf(" Sub-Pixel Layout: "); unsigned char v = x[0x0e]; @@ -207,6 +209,7 @@ void edid_state::parse_display_caps(const unsigned char *x) { data_block = "Display Capabities & Feature Support Set"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 35); unsigned short v = x[0x14]; @@ -434,6 +437,7 @@ void edid_state::parse_display_xfer(const unsigned char *x) { data_block = "Display Transfer Characteristics - Gamma"; printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, 46); unsigned char v = x[0x51]; unsigned num_entries = v & 0x3f; diff --git a/utils/edid-decode/parse-displayid-block.cpp b/utils/edid-decode/parse-displayid-block.cpp index 2fa8fde7418e..1df812902200 100644 --- a/utils/edid-decode/parse-displayid-block.cpp +++ b/utils/edid-decode/parse-displayid-block.cpp @@ -2551,8 +2551,10 @@ unsigned edid_state::displayid_block(const unsigned version, const unsigned char return length; } - if (dooutputname && data_block.length()) + if (dooutputname && data_block.length()) { printf(" %s:\n", data_block.c_str()); + block_hex_dump(" ", x, len + 1); + } if (version >= 0x20 && tag_version == 1) fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n", _______________________________________________ linuxtv-commits mailing list -- [email protected] To unsubscribe send an email to [email protected]
