This is an automatic generated email to let you know that the following patch were queued:
Subject: edid-decode: add Cable ID support Author: Hans Verkuil <hverkuil-ci...@xs4all.nl> Date: Tue Aug 20 11:54:09 2024 +0200 Add Cable ID support. Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl> ddc.cpp | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ edid-decode.cpp | 5 +++ edid-decode.h | 2 + 3 files changed, 134 insertions(+) --- diff --git a/ddc.cpp b/ddc.cpp index b9640d8c71f2..da65e177d337 100644 --- a/ddc.cpp +++ b/ddc.cpp @@ -552,3 +552,130 @@ int read_scdc(int adapter_fd, bool update_only) } return 0; } + +static __u8 checksum(const __u8 *hdr, const __u8 *data, unsigned len) +{ + __u8 sum = 0; + + for (int i = 0; i < 5; i++) + sum += hdr[i]; + while (len--) + sum += *data++; + return 256 - sum; +} + +static int idcc_read(int adapter_fd, __u8 cmd, __u8 *data, __u16 len) +{ + struct i2c_rdwr_ioctl_data i2c_data; + struct i2c_msg write_message; + struct i2c_msg read_message; + int err; + + write_message = { + .addr = EDID_ADDR, + .len = 1, + .buf = &cmd + }; + read_message = { + .addr = EDID_ADDR, + .flags = I2C_M_RD, + .len = len, + .buf = data + }; + + struct i2c_msg msgs[2] = { write_message, read_message }; + + i2c_data.msgs = msgs; + i2c_data.nmsgs = ARRAY_SIZE(msgs); + err = ioctl(adapter_fd, I2C_RDWR, &i2c_data); + + if (err >= 0) + err = err == 2 ? 0 : -EIO; + if (err < 0) + fprintf(stderr, "Unable to read IDCC: %s\n", strerror(errno)); + return err; +} + +#if 0 +static int idcc_write_block(int adapter_fd, const __u8 *data, unsigned len) +{ + __u8 dummy = 0; + int ret = 0; + + while (!ret && len--) + ret = idcc_read(adapter_fd, *data++, &dummy, 1); + + return ret; +} +#endif + +static int idcc_read_block(int adapter_fd, const __u8 *data, unsigned len, __u8 *res, unsigned len2) +{ + __u8 dummy = 0; + int ret = 0; + + while (!ret && len--) + ret = idcc_read(adapter_fd, *data++, len ? &dummy : res, len ? 1 : len2); + + return ret; +} + +int read_cable_id(int adapter_fd) +{ + const __u8 cable_id[] = { 0xae, 0x6e, 0x61, 0x00, 0x04, 0x01 }; + __u8 cable_man_id[] = { 0xae, 0x6e, 0x61, 0xd0, 0x04, 0x01 }; + __u8 data[49] = {}; + + //__u8 source_id[] = { 0xae, 0x6e, 0x60, 0x00, 0x01, 0xff, 0 }; + //source_id[6] = checksum(source_id, source_id + 5, 1); + //idcc_write_block(adapter_fd, source_id, 7); + + idcc_read_block(adapter_fd, cable_id, 6, data, 5); + if (data[4] == checksum(cable_id, data, 4)) { + printf("Cable ID:\n\tCat3: %c Cat2: %c Cat1: %c\n", + (data[0] & 4) ? 'n' : 'y', + (data[0] & 2) ? 'n' : 'y', + (data[0] & 1) ? 'n' : 'y'); + printf("\tPCA_ON: %c MonoDirErr: %c MonoDir: %c PCA_DEP: %c HEAC: %c\n", + (data[1] & 0x10) ? 'n' : 'y', + (data[1] & 0x08) ? 'n' : 'y', + (data[1] & 0x04) ? 'n' : 'y', + (data[1] & 0x02) ? 'n' : 'y', + (data[1] & 0x01) ? 'n' : 'y'); + printf("\tRND: 0x%04x\n", (data[3] << 8) | data[2]); + } + bool valid = true; + for (unsigned i = 0; i < sizeof(data) - 1; i += 4) { + cable_man_id[3] = 0xd0 + i; + idcc_read_block(adapter_fd, cable_man_id, 6, data + i, 5); + if (data[i + 4] != checksum(cable_man_id, data + i, 4)) { + valid = false; + break; + } + } + if (valid) { + bool all_ff = true; + + for (unsigned i = 0; i < sizeof(data) - 1; i++) { + if (data[i] != 0xff) { + all_ff = false; + break; + } + } + if (all_ff) { + printf("Cable ID - Manufacturer Specific: all values are 0xff\n"); + } else { + printf("Cable ID - Manufacturer Specific:\n"); + printf("\tManufacturer OUI: %02x-%02x-%02x\n", data[0], data[1], data[2]); + printf("\tDevice ID: %s\n", ""); + printf("\tHW Rev: %u.%u\n", data[11] >> 4, data[11] & 0xf); + printf("\tSW Rev: %u.%u\n", data[12], data[13]); + printf("\tManufacturer Specific:\n\t\t"); + for (unsigned i = 14; i < sizeof(data) - 1; i++) + printf(" %02x", data[i]); + printf("\n"); + } + } + + return 0; +} diff --git a/edid-decode.cpp b/edid-decode.cpp index dc019387801d..b696535b525b 100644 --- a/edid-decode.cpp +++ b/edid-decode.cpp @@ -68,6 +68,7 @@ enum Option { OptI2CSCDCUpdate, OptI2CHDCP, OptI2CHDCPRi, + OptI2CCableID, OptSTD, OptDMT, OptVIC, @@ -116,6 +117,7 @@ static struct option long_options[] = { { "i2c-scdc", no_argument, 0, OptI2CSCDC }, { "i2c-hdcp", no_argument, 0, OptI2CHDCP }, { "i2c-hdcp-ri", required_argument, 0, OptI2CHDCPRi }, + { "i2c-cable-id", no_argument, 0, OptI2CCableID }, #endif { "std", required_argument, 0, OptSTD }, { "dmt", required_argument, 0, OptDMT }, @@ -177,6 +179,7 @@ static void usage(void) " --i2c-scdc-update Read the SCDC Update information (bytes 0x10-0x11) from the DDC lines.\n" " --i2c-hdcp Read the HDCP from the DDC lines.\n" " --i2c-hdcp-ri=<t> Read and print the HDCP Ri information every <t> seconds.\n" + " --i2c-cable-id Read the Cable ID from the DDC lines.\n" #endif " --std <byte1>,<byte2> Show the standard timing represented by these two bytes.\n" " --dmt <dmt> Show the timings for the DMT with the given DMT ID.\n" @@ -2472,6 +2475,8 @@ int main(int argc, char **argv) ret = read_hdcp(adapter_fd); if (!ret && options[OptI2CHDCPRi]) ret = read_hdcp_ri(adapter_fd, hdcp_ri_sleep); + if (!ret && options[OptI2CCableID]) + ret = read_cable_id(adapter_fd); } else if (options[OptInfoFrame] && !options[OptGTF]) { ret = 0; } else { diff --git a/edid-decode.h b/edid-decode.h index 279f77186fa9..738d84cba3e4 100644 --- a/edid-decode.h +++ b/edid-decode.h @@ -622,6 +622,7 @@ int read_edid(int adapter_fd, unsigned char *edid); int read_hdcp(int adapter_fd); int read_hdcp_ri(int adapter_fd, double ri_time); int read_scdc(int adapter_fd, bool update_only); +int read_cable_id(int adapter_fd); #else @@ -629,6 +630,7 @@ static inline int read_edid(int adapter_fd, unsigned char *edid) { return -ENODE static inline int read_hdcp(int adapter_fd) { return -ENODEV; } static inline int read_hdcp_ri(int adapter_fd, double ri_time) { return -ENODEV; } static inline int read_scdc(int adapter_fd, bool update_only) { return -ENODEV; } +static inline int read_cable_id(int adapter_fd) { return -ENODEV; } #endif