diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2020-03-19 10:19:09 +0100 |
---|---|---|
committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2020-10-07 14:15:43 +0200 |
commit | 05000a380b2995e2fbbf89f4342330c719b777ea (patch) | |
tree | bd426099cb98a77fe8bbf5c241055b86f0f958c9 | |
parent | 28df3d403be3d7769d7b10cda3e372a0dbbfa410 (diff) |
cec: add support to list/set connectorscec-conn
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r-- | include/linux/cec.h | 15 | ||||
-rw-r--r-- | utils/cec-ctl/cec-ctl.cpp | 82 |
2 files changed, 91 insertions, 6 deletions
diff --git a/include/linux/cec.h b/include/linux/cec.h index 16d96133..2d3bac54 100644 --- a/include/linux/cec.h +++ b/include/linux/cec.h @@ -405,6 +405,17 @@ struct cec_connector_info { }; }; +/** + * struct cec_enum_connector_info - enumerate connector info + * @conn_info: connector info + * @index: get connector info at index @index + */ +struct cec_enum_connector_info { + struct cec_connector_info conn_info; + __u32 index; + char name[32]; +}; + /* Events */ /* Event that occurs when the adapter state changes */ @@ -513,8 +524,10 @@ struct cec_event { #define CEC_G_MODE _IOR('a', 8, __u32) #define CEC_S_MODE _IOW('a', 9, __u32) -/* Get the connector info */ +/* Get and set the connector info */ #define CEC_ADAP_G_CONNECTOR_INFO _IOR('a', 10, struct cec_connector_info) +#define CEC_ADAP_S_CONNECTOR_INFO _IOW('a', 11, struct cec_connector_info) +#define CEC_ADAP_ENUM_CONNECTOR_INFO _IOWR('a', 12, struct cec_enum_connector_info) /* * The remainder of this header defines all CEC messages and operands. diff --git a/utils/cec-ctl/cec-ctl.cpp b/utils/cec-ctl/cec-ctl.cpp index 2ee88ec9..5586a4de 100644 --- a/utils/cec-ctl/cec-ctl.cpp +++ b/utils/cec-ctl/cec-ctl.cpp @@ -62,6 +62,7 @@ static char options[512]; case is used to retrieve a setting. */ enum Option { OptSetAdapter = 'a', + OptSetConnInfo = 'c', OptClear = 'C', OptSetDevice = 'd', OptSetDriver = 'D', @@ -103,6 +104,7 @@ enum Option { OptReplyToFollowers, OptRawMsg, OptListDevices, + OptListConnectors, OptTimeout, OptMonitorTime, OptMonitorPin, @@ -162,6 +164,7 @@ static struct option long_options[] = { { "phys-addr-from-edid-poll", required_argument, 0, OptPhysAddrFromEDIDPoll }, { "phys-addr-from-edid", required_argument, 0, OptPhysAddrFromEDID }, { "phys-addr", required_argument, 0, OptPhysAddr }, + { "set-conn-info", required_argument, 0, OptSetConnInfo }, { "vendor-id", required_argument, 0, OptVendorID }, { "cec-version-1.4", no_argument, 0, OptCECVersion1_4 }, { "allow-unreg-fallback", no_argument, 0, OptAllowUnregFallback }, @@ -188,6 +191,7 @@ static struct option long_options[] = { { "show-raw", no_argument, 0, OptShowRaw }, { "show-topology", no_argument, 0, OptShowTopology }, { "list-devices", no_argument, 0, OptListDevices }, + { "list-connectors", no_argument, 0, OptListConnectors }, { "poll", no_argument, 0, OptPoll }, { "rc-tv-profile-1", no_argument, 0, OptRcTVProfile1 }, { "rc-tv-profile-2", no_argument, 0, OptRcTVProfile2 }, @@ -251,6 +255,12 @@ static void usage() " -E, --phys-addr-from-edid-poll <path>\n" " Continuously poll the EDID file for changes, and update the\n" " physical address whenever there is a change\n" + " -c, --set-conn-info none | card-no=<card>,conn-id=<id>\n" + " Associate the CEC adapter with the given connector.\n" + " Only valid if CEC_CAP_PHYS_ADDR is set.\n" + " none: disassociate the CEC adapter.\n" + " card-no,conn-id: associate the CEC adapter with the DRM\n" + " device with this card number and connector ID.\n" " -o, --osd-name <name> Use this OSD name\n" " -V, --vendor-id <id> Use this vendor ID\n" " -l, --logical-address Show first configured logical address\n" @@ -279,6 +289,7 @@ static void usage() " --raw-msg Transmit the message without validating it (must be root)\n" " --timeout <ms> Set the reply timeout in milliseconds (default is 1000 ms)\n" " --list-devices List all cec devices\n" + " --list-connectors List all connectors that can be used with -c\n" "\n" " --tv This is a TV\n" " --record This is a recording and playback device\n" @@ -1867,6 +1878,7 @@ int main(int argc, char **argv) const char *driver = NULL; const char *adapter = NULL; const struct cec_msg_args *opt; + struct cec_connector_info conn_info = {}; msg_vec msgs; char short_options[26 * 2 * 2 + 1]; __u32 timeout = 1000; @@ -1957,6 +1969,39 @@ int main(int argc, char **argv) case OptMonitorTime: monitor_time = strtoul(optarg, NULL, 0); break; + case OptSetConnInfo: { + static const char *arg_names[] = { + "card-no", + "conn-id", + NULL + }; + char *value, *subs = optarg; + + if (!optarg) + break; + + while (*subs != '\0') { + if (!strcmp(subs, "none")) { + conn_info.type = CEC_CONNECTOR_TYPE_NO_CONNECTOR; + break; + } + + switch (cec_parse_subopt(&subs, arg_names, &value)) { + case 0: + conn_info.type = CEC_CONNECTOR_TYPE_DRM; + conn_info.drm.card_no = strtoul(value, NULL, 0); + break; + case 1: + conn_info.type = CEC_CONNECTOR_TYPE_DRM; + conn_info.drm.connector_id = strtoul(value, NULL, 0); + break; + default: + usage(); + exit(1); + } + } + break; + } case OptIgnore: { bool all_la = !strncmp(optarg, "all", 3); bool all_opcodes = true; @@ -2453,7 +2498,7 @@ int main(int argc, char **argv) node.available_log_addrs = caps.available_log_addrs; bool set_phys_addr = options[OptPhysAddr] || options[OptPhysAddrFromEDID] || - options[OptPhysAddrFromEDIDPoll]; + options[OptPhysAddrFromEDIDPoll] || options[OptSetConnInfo]; if (set_phys_addr && !(node.caps & CEC_CAP_PHYS_ADDR)) fprintf(stderr, "The CEC adapter doesn't allow setting the physical address manually, ignore this option.\n\n"); @@ -2510,9 +2555,14 @@ int main(int argc, char **argv) doioctl(&node, CEC_ADAP_S_LOG_ADDRS, &laddrs); } - if (set_phys_addr) + if (options[OptSetConnInfo]) + doioctl(&node, CEC_ADAP_S_CONNECTOR_INFO, &conn_info); + else if (set_phys_addr) doioctl(&node, CEC_ADAP_S_PHYS_ADDR, &phys_addr); + doioctl(&node, CEC_ADAP_G_CAPS, &caps); + node.caps = caps.capabilities; + doioctl(&node, CEC_ADAP_G_PHYS_ADDR, &phys_addr); if (set_log_addrs) { @@ -2605,12 +2655,36 @@ int main(int argc, char **argv) phys_addrs[la] = (phys_addr << 8) | la; } + if (options[OptListConnectors]) { + struct cec_enum_connector_info c = {}; + bool first = true; + + while (!doioctl(&node, CEC_ADAP_ENUM_CONNECTOR_INFO, &c)) { + if (first) { + printf("Available connectors:\n"); + first = false; + } + switch (c.conn_info.type) { + case CEC_CONNECTOR_TYPE_DRM: + printf("\tDRM: card-no=%u,conn-id=%u (%s)\n", + c.conn_info.drm.card_no, + c.conn_info.drm.connector_id, + c.name); + break; + } + c.index++; + } + if (!first) + printf("\n"); + } + if (!options[OptSkipInfo]) { struct cec_connector_info conn_info = {}; doioctl(&node, CEC_ADAP_G_CONNECTOR_INFO, &conn_info); cec_driver_info(caps, laddrs, phys_addr, conn_info); + printf("\n"); } if (options[OptPhysAddrFromEDIDPoll]) { @@ -2628,11 +2702,9 @@ int main(int argc, char **argv) options[OptMonitorPin] || options[OptStorePin]) goto skip_la; if (warn_if_unconfigured) - fprintf(stderr, "\nAdapter is unconfigured, please configure it first.\n"); + fprintf(stderr, "Adapter is unconfigured, please configure it first.\n"); return 0; } - if (!options[OptSkipInfo]) - printf("\n"); if (!options[OptFrom]) from = laddrs.log_addr[0] & 0xf; |