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 --hdcp option to parse an HDCP hex dump Author: Hans Verkuil <[email protected]> Date: Mon May 11 08:13:14 2026 +0200 With the --i2c-hdcp option you can read the HDCP data. If that is saved to a file, then it can be parsed later with the --hdcp option. Signed-off-by: Hans Verkuil <[email protected]> utils/edid-decode/ddc.cpp | 20 +++--- utils/edid-decode/edid-decode.1.in | 3 + utils/edid-decode/edid-decode.cpp | 124 +++++++++++++++++++++++++++++++++++-- utils/edid-decode/edid-decode.h | 8 +-- utils/edid-decode/parse-hdcp.cpp | 22 ++----- 5 files changed, 138 insertions(+), 39 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=4a416ee511b710833e5ce759ba71c7d9b4b0e4fb diff --git a/utils/edid-decode/ddc.cpp b/utils/edid-decode/ddc.cpp index 209ef6aef230..a74e884a4706 100644 --- a/utils/edid-decode/ddc.cpp +++ b/utils/edid-decode/ddc.cpp @@ -41,9 +41,6 @@ #define EDID_ADDR 0x50 #define SEGMENT_POINTER_ADDR 0x30 -// i2c address for SCDC -#define SCDC_ADDR 0x54 - // i2c addresses for HDCP #define HDCP_PRIM_ADDR 0x3a #define HDCP_SEC_ADDR 0x3b @@ -285,8 +282,7 @@ static int read_hdcp_registers(int adapter_fd, __u8 *hdcp_prim, __u8 *hdcp_sec, msgs[1].buf = hdcp_prim + 129; err = ioctl(adapter_fd, I2C_RDWR, &data); } - - if (err < 0) { + if (err != 2) { fprintf(stderr, "Unable to read Primary Link HDCP: %s\n", strerror(errno)); return -1; @@ -310,7 +306,7 @@ static int read_hdcp_registers(int adapter_fd, __u8 *hdcp_prim, __u8 *hdcp_sec, data.msgs = ksv_fifo_msgs; data.nmsgs = ARRAY_SIZE(msgs); err = ioctl(adapter_fd, I2C_RDWR, &data); - if (err < 0) { + if (err != 2) { fprintf(stderr, "Unable to read KSV FIFO: %s\n", strerror(errno)); return -1; @@ -344,17 +340,15 @@ static int read_hdcp_registers(int adapter_fd, __u8 *hdcp_prim, __u8 *hdcp_sec, return 0; } -int edid_state::read_hdcp(int adapter_fd) +int read_hdcp(int adapter_fd, parse_data &pdata) { - __u8 hdcp_prim[256] = {}; - __u8 hdcp_sec[256] = {}; - __u8 ksv_fifo[128 * 5] = {}; + __u8 *hdcp_prim = &pdata.buf[0]; + __u8 *ksv_fifo = hdcp_prim + 256; + __u8 *hdcp_sec = ksv_fifo + 128 * 5; - hdcp_prim[5] = 0xdd; - hdcp_sec[5] = 0xdd; if (read_hdcp_registers(adapter_fd, hdcp_prim, hdcp_sec, ksv_fifo)) return -1; - parse_hdcp_data(hdcp_prim, hdcp_sec, ksv_fifo); + pdata.buf_size = pdata.buf_max_size; return 0; } diff --git a/utils/edid-decode/edid-decode.1.in b/utils/edid-decode/edid-decode.1.in index 5f5361d69497..9b93b1a8f3a1 100644 --- a/utils/edid-decode/edid-decode.1.in +++ b/utils/edid-decode/edid-decode.1.in @@ -238,6 +238,9 @@ On Linux systems ELD can be extracted via the amixer command (copy all hex after 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.TP +\fB\-J\fR, \fB\-\-hdcp\fR \fI<file>\fR +Parse the given HDCP file. Read data from stdin if '-' was passed as argument. .TP \fB\-\-diagonal\fR \fI<inches>\fR Specify the diagonal of the display in inches. This will enable additional checks diff --git a/utils/edid-decode/edid-decode.cpp b/utils/edid-decode/edid-decode.cpp index dcb0c88cba21..00092f2108b0 100644 --- a/utils/edid-decode/edid-decode.cpp +++ b/utils/edid-decode/edid-decode.cpp @@ -49,6 +49,7 @@ enum Option { OptHelp = 'h', OptOnlyHexDump = 'H', OptInfoFrame = 'I', + OptHDCP = 'J', OptLongTimings = 'L', OptNativeResolution = 'n', OptNTSC = 'N', @@ -133,6 +134,7 @@ static struct option long_options[] = { { "list-rids", no_argument, 0, OptListRIDs }, { "infoframe", required_argument, 0, OptInfoFrame }, { "eld", required_argument, 0, OptEld }, + { "hdcp", required_argument, 0, OptHDCP }, { 0, 0, 0, 0 } }; @@ -233,6 +235,7 @@ static void usage(void) " This option can be specified multiple times for different InfoFrame files.\n" " -E, --eld <file> Parse the EDID-Like Data, ELD from <file> (or stdin if '-' was specified).\n" " This option can be specified multiple times for different ELD files.\n" + " -J, --hdcp <file> Parse the HDCP data from <file> (or stdin if '-' was specified).\n" " -h, --help Display this help message.\n"); } #endif @@ -1660,7 +1663,7 @@ int edid_state::parse_edid() return failures ? -2 : 0; } -/* InfoFrame/ELD parsing */ +/* InfoFrame/HDCP/ELD parsing */ static unsigned char infoframe[32]; @@ -1680,6 +1683,16 @@ static struct parse_data eld_pdata = { 0 }; +// primary data, KSV FIFO data, and secondary data +static unsigned char hdcp[256 + 128 * 5 + 256]; + +static struct parse_data hdcp_pdata = { + "HDCP", + hdcp, + sizeof(hdcp), + 0 +}; + static bool data_add_byte(parse_data &pdata, const char *s) { char buf[3]; @@ -1975,6 +1988,82 @@ int edid_state::parse_eld_file(const std::string &fname) return failures ? -2 : 0; } +static int hdcp_from_file(parse_data &pdata, const char *from_file) +{ + int ret = data_from_file(pdata, from_file); + + if (ret < 0) + return ret; + + unsigned char *hdcp_prim = &pdata.buf[0]; + unsigned char *ksv_fifo = hdcp_prim + 256; + unsigned char *hdcp_sec = ksv_fifo + 128 * 5; + unsigned kvs_fifo_sz = hdcp_prim[0x41] & 0x7f; + memcpy(hdcp_sec, ksv_fifo + kvs_fifo_sz * 5, 256); + memset(ksv_fifo + kvs_fifo_sz * 5, 0, (128 - kvs_fifo_sz) * 5); + return 0; +} + +int edid_state::parse_hdcp_pdata(parse_data &pdata) +{ + state.block_nr = 0; + state.data_block.clear(); + + if (!options[OptSkipHexDump]) { + printf("edid-decode %s (hex):\n\n", pdata.name); + // Primary HDCP data + hex_block("", pdata.buf, 128, false); + printf("\n"); + hex_block("", pdata.buf + 128, 128, false); + printf("\n"); + // KSV FIFO + for (unsigned i = 0; i < (pdata.buf[0x41] & 0x7f); i++) { + hex_block("", pdata.buf + 256 + i * 5, 5, false); + printf("\n"); + } + // Secondary HDCP data if present + if (!memchk(pdata.buf + 256 + 128 * 5, 256)) { + hex_block("", pdata.buf + 256 + 128 * 5, 128, false); + printf("\n"); + hex_block("", pdata.buf + 256 + 128 * 5 + 128, 128, false); + printf("\n"); + } + if (options[OptOnlyHexDump]) + return 0; + printf("----------------\n\n"); + } + + if (pdata.buf_size < 128) { + fail("%s is too small to parse.\n", pdata.name); + return -1; + } + + parse_hdcp(pdata.buf, pdata.buf_size); + + if (!options[OptCheck] && !options[OptCheckInline]) + return 0; + + printf("\n----------------\n"); + + if (!options[OptSkipSHA] && strlen(STRING(SHA))) { + options[OptSkipSHA] = 1; + printf("\n"); + print_version(); + } + + if (options[OptCheck]) { + if (warnings) + show_data_msgs(pdata.name, true); + if (failures) + show_data_msgs(pdata.name, false); + } + + printf("\n%s conformity: %s\n", + state.data_block.empty() ? pdata.name : state.data_block.c_str(), + failures ? "FAIL" : "PASS"); + return failures ? -2 : 0; +} + #ifndef __EMSCRIPTEN__ static unsigned char crc_calc(const unsigned char *b) @@ -2530,6 +2619,7 @@ int main(int argc, char **argv) double hdcp_ri_sleep = 0; std::vector<std::string> if_names; std::vector<std::string> eld_names; + std::string hdcp_name; unsigned test_rel_duration = 0; unsigned test_rel_msleep = 50; unsigned idx = 0; @@ -2683,6 +2773,9 @@ int main(int argc, char **argv) case OptInfoFrame: if_names.push_back(optarg); break; + case OptHDCP: + hdcp_name = optarg; + break; case OptEld: eld_names.push_back(optarg); break; @@ -2740,13 +2833,14 @@ int main(int argc, char **argv) ret = 0; } } else if (adapter_fd >= 0) { - if (options[OptI2CHDCP]) - ret = state.read_hdcp(adapter_fd); - if (options[OptI2CHDCPRi]) + if (!ret && options[OptI2CHDCP]) + ret = read_hdcp(adapter_fd, hdcp_pdata); + if (!ret && options[OptI2CHDCPRi]) ret = read_hdcp_ri(adapter_fd, hdcp_ri_sleep); if (options[OptI2CTestReliability]) ret = test_reliability(adapter_fd, test_rel_duration, test_rel_msleep); - } else if ((options[OptInfoFrame] || options[OptEld]) && !options[OptGTF]) { + } else if ((options[OptInfoFrame] || options[OptEld] || + options[OptHDCP]) && !options[OptGTF]) { ret = 0; } else { ret = edid_from_file("-", stdout); @@ -2795,6 +2889,26 @@ int main(int argc, char **argv) bool show_line = state.edid_size; + if (hdcp_name.length()) { + int r = hdcp_from_file(hdcp_pdata, hdcp_name.c_str()); + if (r && !ret) + ret = r; + } + if (hdcp_pdata.buf_size) { + if (show_line) + printf("\n================\n\n"); + show_line = true; + + state.warnings = state.failures = 0; + for (unsigned i = 0; i < EDID_MAX_BLOCKS + 1; i++) { + s_msgs[i][0].clear(); + s_msgs[i][1].clear(); + } + int r = state.parse_hdcp_pdata(hdcp_pdata); + if (r && !ret) + ret = r; + } + for (const auto &n : if_names) { if (show_line) printf("\n================\n\n"); diff --git a/utils/edid-decode/edid-decode.h b/utils/edid-decode/edid-decode.h index 39b5dfbf3c5e..8ecd44f312fd 100644 --- a/utils/edid-decode/edid-decode.h +++ b/utils/edid-decode/edid-decode.h @@ -565,10 +565,8 @@ struct edid_state { int parse_eld_file(const std::string &fname); void parse_eld_baseline(const unsigned char *x, unsigned size); - int read_hdcp(int adapter_fd); - void parse_hdcp_data(const unsigned char hdcp_prim[256], - const unsigned char hdcp_sec[256], - const unsigned char ksv_fifo[128 * 5]); + int parse_hdcp_pdata(parse_data &pdata); + void parse_hdcp(const unsigned char *hdcp, unsigned size); }; static inline void add_str(std::string &s, const std::string &add) @@ -657,7 +655,7 @@ char *extract_string(const unsigned char *x, unsigned len, bool is_cp437); int request_i2c_adapter(const char *device); int read_edid(int adapter_fd, unsigned char *edid, bool silent = false); int test_reliability(int adapter_fd, unsigned secs, unsigned msleep); -int read_hdcp(int adapter_fd); +int read_hdcp(int adapter_fd, parse_data &pdata); int read_hdcp_ri(int adapter_fd, double ri_time); #else diff --git a/utils/edid-decode/parse-hdcp.cpp b/utils/edid-decode/parse-hdcp.cpp index 3359e1accd99..ded77ea6c2ce 100644 --- a/utils/edid-decode/parse-hdcp.cpp +++ b/utils/edid-decode/parse-hdcp.cpp @@ -9,22 +9,12 @@ #include "edid-decode.h" -void edid_state::parse_hdcp_data(const unsigned char hdcp_prim[256], - const unsigned char hdcp_sec[256], - const unsigned char ksv_fifo[128 * 5]) +void edid_state::parse_hdcp(const unsigned char *hdcp, unsigned size) { - printf("HDCP Primary Link Hex Dump:\n\n"); - hex_block("", hdcp_prim, 128, false); - printf("\n"); - hex_block("", hdcp_prim + 128, 128, false); - printf("\n"); - if (hdcp_sec[5] != 0xdd) { - printf("HDCP Secondary Link Hex Dump:\n\n"); - hex_block("", hdcp_sec, 128, false); - printf("\n"); - hex_block("", hdcp_sec + 128, 128, false); - printf("\n"); - } + const unsigned char *hdcp_prim = hdcp; + const unsigned char *ksv_fifo = hdcp + 256; + const unsigned char *hdcp_sec = hdcp + 256 + 128 * 5; + printf("HDCP Primary Link:\n\n"); printf("Bksv: %02x %02x %02x %02x %02x\n", hdcp_prim[0], hdcp_prim[1], hdcp_prim[2], hdcp_prim[3], hdcp_prim[4]); @@ -89,7 +79,7 @@ void edid_state::parse_hdcp_data(const unsigned char hdcp_prim[256], if (vv & 0x800) printf("\tREAUTH_REQ\n"); - if (hdcp_sec[5] == 0xdd) + if (memchk(hdcp_sec, 256)) return; printf("HDCP Secondary Link:\n\n"); _______________________________________________ linuxtv-commits mailing list -- [email protected] To unsubscribe send an email to [email protected]
