This is an automatic generated email to let you know that the following patch were queued:
Subject: edid-decode: add --replace-serial-numbers option Author: Hans Verkuil <hverkuil-ci...@xs4all.nl> Date: Wed Jun 15 16:50:41 2022 +0200 This replaces any serial numbers by '123456' in the EDID itself. It differs from the --hide-serial-numbers option that just shows them as '...' in the human readable output, but leaves them in the EDID hex dump. Replacing the serial numbers will also update the checksums, so incorrect checksums in the original EDID will no longer be detected when using this option. Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl> edid-decode.1 | 11 ++++++- edid-decode.cpp | 40 ++++++++++++++++------ edid-decode.h | 15 ++++++--- parse-base-block.cpp | 84 ++++++++++++++++++++++++++++++----------------- parse-cta-block.cpp | 2 +- parse-displayid-block.cpp | 42 ++++++++++++++++++++---- parse-ls-ext-block.cpp | 23 +++++++++++++ 7 files changed, 164 insertions(+), 53 deletions(-) --- diff --git a/edid-decode.1 b/edid-decode.1 index 2a63818d2ff5..85d0fc399dc4 100644 --- a/edid-decode.1 +++ b/edid-decode.1 @@ -251,10 +251,19 @@ in the git repository, even if nothing else changed in the edid-decode output. Use this option to avoid including the SHA in the edid-decode output. .TP \fB\-\-hide\-serial\-numbers\fR -Replace any serial numbers in the human readable output by '...'. +Hide any serial numbers in the human readable output by '...'. Note that they are still easily extracted from the EDID hex dump at the start. .TP +\fB\-\-replace\-serial\-numbers\fR +Replaces any serial numbers in the EDID by '123456'. This will +also update any checksums in the EDID and update the EDID hex dump at +the start of the output. Note that since this will update checksums, any +checksum errors present in the original EDID will no longer be detected. + +Serial numbers appear in the Base Block, DisplayID Extension Blocks and +Localized String Extension Blocks. +.TP \fB\-\-version\fR Show the SHA hash and the last commit date. diff --git a/edid-decode.cpp b/edid-decode.cpp index b3c6c088f4cb..c8baacc04376 100644 --- a/edid-decode.cpp +++ b/edid-decode.cpp @@ -57,6 +57,7 @@ enum Option { OptXModeLineTimings = 'X', OptSkipSHA = 128, OptHideSerialNumbers, + OptReplaceSerialNumbers, OptVersion, OptDiag, OptSTD, @@ -88,6 +89,7 @@ static struct option long_options[] = { { "only-hex-dump", no_argument, 0, OptOnlyHexDump }, { "skip-sha", no_argument, 0, OptSkipSHA }, { "hide-serial-numbers", no_argument, 0, OptHideSerialNumbers }, + { "replace-serial-numbers", no_argument, 0, OptReplaceSerialNumbers }, { "version", no_argument, 0, OptVersion }, { "check-inline", no_argument, 0, OptCheckInline }, { "check", no_argument, 0, OptCheck }, @@ -145,7 +147,8 @@ static void usage(void) " -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" " --skip-sha Skip the SHA report.\n" - " --hide-serial-numbers Replace serial numbers with '...'.\n" + " --hide-serial-numbers Hide serial numbers with '...'.\n" + " --replace-serial-numbers Replace serial numbers in EDID with 123456.\n" " --version Show the edid-decode version (SHA).\n" " --diagonal <inches> Set the display's diagonal in inches.\n" " --std <byte1>,<byte2> Show the standard timing represented by these two bytes.\n" @@ -236,17 +239,26 @@ static void show_msgs(bool is_warn) } +void replace_checksum(unsigned char *x, size_t len) +{ + unsigned char sum = 0; + unsigned i; + + for (i = 0; i < len - 1; i++) + sum += x[i]; + x[len - 1] = -sum & 0xff; +} + void do_checksum(const char *prefix, const unsigned char *x, size_t len, unsigned unused_bytes) { unsigned char check = x[len - 1]; unsigned char sum = 0; unsigned i; - printf("%sChecksum: 0x%02hhx", prefix, check); - - for (i = 0; i < len-1; i++) + for (i = 0; i < len - 1; i++) sum += x[i]; + printf("%sChecksum: 0x%02hhx", prefix, check); if ((unsigned char)(check + sum) != 0) { printf(" (should be 0x%02x)", -sum & 0xff); fail("Invalid checksum 0x%02x (should be 0x%02x).\n", @@ -1140,16 +1152,23 @@ void edid_state::parse_block_map(const unsigned char *x) } } -void edid_state::preparse_extension(const unsigned char *x) +void edid_state::preparse_extension(unsigned char *x) { switch (x[0]) { case 0x02: has_cta = true; preparse_cta_block(x); break; + case 0x50: + preparse_ls_ext_block(x); + if (replace_serial_numbers) + replace_checksum(x, EDID_PAGE_SIZE); + break; case 0x70: has_dispid = true; preparse_displayid_block(x); + if (replace_serial_numbers) + replace_checksum(x, EDID_PAGE_SIZE); break; } } @@ -1404,6 +1423,11 @@ void edid_state::print_native_res() int edid_state::parse_edid() { hide_serial_numbers = options[OptHideSerialNumbers]; + replace_serial_numbers = options[OptReplaceSerialNumbers]; + + preparse_base_block(edid); + if (replace_serial_numbers) + replace_checksum(edid, EDID_PAGE_SIZE); for (unsigned i = 1; i < num_blocks; i++) preparse_extension(edid + i * EDID_PAGE_SIZE); @@ -2128,11 +2152,7 @@ int main(int argc, char **argv) if (options[OptGTF]) { timings t; - // Find the Secondary Curve - state.preparse_detailed_block(edid + 0x36); - state.preparse_detailed_block(edid + 0x48); - state.preparse_detailed_block(edid + 0x5a); - state.preparse_detailed_block(edid + 0x6c); + state.preparse_base_block(edid); t = state.calc_gtf_mode(gtf_data.w, gtf_data.h, gtf_data.freq, gtf_data.interlaced, gtf_data.ip_parm, diff --git a/edid-decode.h b/edid-decode.h index e075c83d7220..6f37e4522b36 100644 --- a/edid-decode.h +++ b/edid-decode.h @@ -145,6 +145,7 @@ struct edid_state { warnings = failures = 0; has_cta = has_dispid = false; hide_serial_numbers = false; + replace_serial_numbers = false; image_width = image_height = diagonal = 0; // Base block state @@ -215,6 +216,7 @@ struct edid_state { bool has_cta; bool has_dispid; bool hide_serial_numbers; + bool replace_serial_numbers; unsigned min_hor_freq_hz; unsigned max_hor_freq_hz; @@ -369,7 +371,8 @@ struct edid_state { void detailed_epi(const unsigned char *x); void detailed_timings(const char *prefix, const unsigned char *x, bool base_or_cta = true); - void preparse_detailed_block(const unsigned char *x); + void preparse_detailed_block(unsigned char *x); + void preparse_base_block(unsigned char *x); void detailed_block(const unsigned char *x); void parse_base_block(const unsigned char *x); void check_base_block(); @@ -398,7 +401,7 @@ struct edid_state { void cta_displayid_type_8(const unsigned char *x, unsigned length); void cta_displayid_type_10(const unsigned char *x, unsigned length); void cta_block(const unsigned char *x, std::vector<unsigned> &found_tags); - void preparse_cta_block(const unsigned char *x); + void preparse_cta_block(unsigned char *x); void parse_cta_block(const unsigned char *x); void cta_resolve_svr(timings_ext &t_ext); void cta_resolve_svrs(); @@ -445,7 +448,7 @@ struct edid_state { void parse_displayid_adaptive_sync(const unsigned char *x); void parse_displayid_type_10_timing(const unsigned char *x, unsigned sz, bool is_cta = false); - void preparse_displayid_block(const unsigned char *x); + void preparse_displayid_block(unsigned char *x); unsigned displayid_block(const unsigned version, const unsigned char *x, unsigned length); void parse_displayid_block(const unsigned char *x); void parse_displayid_vesa(const unsigned char *x); @@ -456,11 +459,12 @@ struct edid_state { void parse_vtb_ext_block(const unsigned char *x); void parse_string_table(const unsigned char *x); + void preparse_ls_ext_block(unsigned char *x); void parse_ls_ext_block(const unsigned char *x); void parse_block_map(const unsigned char *x); - void preparse_extension(const unsigned char *x); + void preparse_extension(unsigned char *x); void parse_extension(const unsigned char *x); void print_preferred_timings(); void print_native_res(); @@ -505,7 +509,6 @@ void msg(bool is_warn, const char *fmt, ...); #endif -void do_checksum(const char *prefix, const unsigned char *x, size_t len, unsigned unused_bytes = 0); std::string utohex(unsigned char x); std::string ouitohex(unsigned oui); std::string containerid2s(const unsigned char *x); @@ -513,6 +516,8 @@ bool memchk(const unsigned char *x, unsigned len, unsigned char v = 0); void hex_block(const char *prefix, const unsigned char *x, unsigned length, bool show_ascii = true, unsigned step = 16); std::string block_name(unsigned char block); +void do_checksum(const char *prefix, const unsigned char *x, size_t len, unsigned unused_bytes = 0); +void replace_checksum(unsigned char *x, size_t len); void calc_ratio(struct timings *t); const char *oui_name(unsigned oui, unsigned *ouinum = NULL); unsigned gcd(unsigned a, unsigned b); diff --git a/parse-base-block.cpp b/parse-base-block.cpp index f65cd9c21342..56583c150f69 100644 --- a/parse-base-block.cpp +++ b/parse-base-block.cpp @@ -1089,31 +1089,43 @@ void edid_state::detailed_timings(const char *prefix, const unsigned char *x, } } -void edid_state::preparse_detailed_block(const unsigned char *x) +void edid_state::preparse_detailed_block(unsigned char *x) { if (x[0] || x[1]) return; - if (x[3] != 0xfd) - return; - switch (x[10]) { - case 0x00: /* default gtf */ - base.supports_gtf = true; - break; - case 0x02: /* secondary gtf curve */ - base.supports_gtf = true; - base.supports_sec_gtf = !memchk(x + 12, 6); - base.sec_gtf_start_freq = x[12] * 2; - base.C = x[13] / 2.0; - base.M = (x[15] << 8) | x[14]; - base.K = x[16]; - base.J = x[17] / 2.0; - break; - case 0x04: /* cvt */ - if (base.edid_minor >= 4) { - /* GTF is implied if CVT is signaled */ + switch (x[3]) { + case 0xfd: + switch (x[10]) { + case 0x00: /* default gtf */ base.supports_gtf = true; - base.supports_cvt = true; + break; + case 0x02: /* secondary gtf curve */ + base.supports_gtf = true; + base.supports_sec_gtf = !memchk(x + 12, 6); + base.sec_gtf_start_freq = x[12] * 2; + base.C = x[13] / 2.0; + base.M = (x[15] << 8) | x[14]; + base.K = x[16]; + base.J = x[17] / 2.0; + break; + case 0x04: /* cvt */ + if (base.edid_minor >= 4) { + /* GTF is implied if CVT is signaled */ + base.supports_gtf = true; + base.supports_cvt = true; + } + break; + } + break; + case 0xff: + if (replace_serial_numbers) { + // Replace with 123456 + static const unsigned char sernum[13] = { + '1', '2', '3', '4', '5', '6', + '\n', ' ', ' ', ' ', ' ', ' ', ' ' + }; + memcpy(x + 5, sernum, sizeof(sernum)); } break; } @@ -1316,6 +1328,28 @@ static const unsigned char srgb_chromaticity[10] = { 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54 }; +void edid_state::preparse_base_block(unsigned char *x) +{ + base.has_serial_number = x[0x0c] || x[0x0d] || x[0x0e] || x[0x0f]; + + if (base.has_serial_number && replace_serial_numbers) { + // Replace by 123456 + x[0x0c] = 0x40; + x[0x0d] = 0xe2; + x[0x0e] = 0x01; + x[0x0f] = 0x00; + } + + /* + * Need to find the Display Range Limit info before reading + * the standard timings. + */ + preparse_detailed_block(x + 0x36); + preparse_detailed_block(x + 0x48); + preparse_detailed_block(x + 0x5a); + preparse_detailed_block(x + 0x6c); +} + void edid_state::parse_base_block(const unsigned char *x) { time_t the_time; @@ -1341,7 +1375,6 @@ void edid_state::parse_base_block(const unsigned char *x) printf(" Manufacturer: %s\n Model: %u\n", manufacturer_name(x + 0x08), (unsigned short)(x[0x0a] + (x[0x0b] << 8))); - base.has_serial_number = x[0x0c] || x[0x0d] || x[0x0e] || x[0x0f]; if (base.has_serial_number) { if (hide_serial_numbers) printf(" Serial Number: ...\n"); @@ -1576,15 +1609,6 @@ void edid_state::parse_base_block(const unsigned char *x) } base.has_640x480p60_est_timing = x[0x23] & 0x20; - /* - * Need to find the Display Range Limit info before reading - * the standard timings. - */ - preparse_detailed_block(x + 0x36); - preparse_detailed_block(x + 0x48); - preparse_detailed_block(x + 0x5a); - preparse_detailed_block(x + 0x6c); - data_block = "Standard Timings"; bool found = false; for (unsigned i = 0; i < 8; i++) { diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp index 83171f190c42..2e163dc019f6 100644 --- a/parse-cta-block.cpp +++ b/parse-cta-block.cpp @@ -2531,7 +2531,7 @@ dodefault: found_tags.push_back(tag); } -void edid_state::preparse_cta_block(const unsigned char *x) +void edid_state::preparse_cta_block(unsigned char *x) { unsigned version = x[1]; unsigned offset = x[2]; diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp index a5c33c65a75c..dd8afb8b7d52 100644 --- a/parse-displayid-block.cpp +++ b/parse-displayid-block.cpp @@ -1050,11 +1050,15 @@ void edid_state::parse_displayid_tiled_display_topology(const unsigned char *x, x[0x10], x[0x11], x[0x12]); printf(" Tiled Display Product ID Code: %u\n", x[0x13] | (x[0x14] << 8)); - if (hide_serial_numbers) - printf(" Tiled Display Serial Number: ...\n"); - else - printf(" Tiled Display Serial Number: %u\n", - x[0x15] | (x[0x16] << 8) | (x[0x17] << 16)| (x[0x18] << 24)); + unsigned int sn = x[0x15] | (x[0x16] << 8) | (x[0x17] << 16)| (x[0x18] << 24); + if (sn) { + if (hide_serial_numbers) + printf(" Tiled Display Serial Number: ...\n"); + else + printf(" Tiled Display Serial Number: %u\n", sn); + } else { + fail("Tiled Display Serial Number must be non-zero.\n"); + } } // tag 0x13 @@ -1678,7 +1682,7 @@ std::string edid_state::product_type(unsigned char x, bool heading) return std::string("Unknown " + headingstr + " (") + utohex(x) + ")"; } -void edid_state::preparse_displayid_block(const unsigned char *x) +void edid_state::preparse_displayid_block(unsigned char *x) { unsigned length = x[2]; @@ -1693,6 +1697,32 @@ void edid_state::preparse_displayid_block(const unsigned char *x) unsigned len = x[offset + 2]; switch (tag) { + case 0x00: + case 0x20: + if (replace_serial_numbers && + (x[offset + 0x08] || x[offset + 0x09] || + x[offset + 0x0a] || x[offset + 0x0b])) { + // Replace by 123456 + x[offset + 0x08] = 0x40; + x[offset + 0x09] = 0xe2; + x[offset + 0x0a] = 0x01; + x[offset + 0x0b] = 0x00; + replace_checksum(x + 1, x[2] + 5); + } + break; + case 0x12: + case 0x28: + if (replace_serial_numbers && + (x[offset + 0x15] || x[offset + 0x16] || + x[offset + 0x17] || x[offset + 0x18])) { + // Replace by 123456 + x[offset + 0x15] = 0x40; + x[offset + 0x16] = 0xe2; + x[offset + 0x17] = 0x01; + x[offset + 0x18] = 0x00; + replace_checksum(x + 1, x[2] + 5); + } + break; case 0x02: dispid.preparsed_color_ids |= 1 << ((x[offset + 1] >> 3) & 0x0f); break; diff --git a/parse-ls-ext-block.cpp b/parse-ls-ext-block.cpp index 3c991dc56ab4..9152eb175934 100644 --- a/parse-ls-ext-block.cpp +++ b/parse-ls-ext-block.cpp @@ -15,6 +15,9 @@ static void parse_string(const char *name, const unsigned char *x) hex_block("", x + 1, *x, true, *x); } +// Note that support for UTF 16BE and 32BE is missing. +// I have never seen LS-EXT support in real EDIDs, so that +// shouldn't be a problem. void edid_state::parse_string_table(const unsigned char *x) { printf(" UTF Type: "); @@ -52,6 +55,26 @@ void edid_state::parse_string_table(const unsigned char *x) parse_string("Serial Number", x); } +void edid_state::preparse_ls_ext_block(unsigned char *x) +{ + unsigned char *orig = x; + + if (!replace_serial_numbers) + return; + + x += 5; + + while (x[0] && x + x[0] < orig + 127) { + unsigned char *s = x + 6; + + s += s[0] + 1; + s += s[0] + 1; + for (unsigned i = 1; i <= s[0]; i++) + s[i] = i <= 6 ? '0' + i : ' '; + x += x[0]; + } +} + void edid_state::parse_ls_ext_block(const unsigned char *x) { const unsigned char *orig = x; _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits