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]

Reply via email to