diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2020-09-08 17:11:47 +0200 |
---|---|---|
committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2020-09-08 17:11:47 +0200 |
commit | dedeb53218d1e6b8da584a3c1aaa404f424c3647 (patch) | |
tree | f9ac5526c9b7e41e61964866a87f15e78d3c3868 | |
parent | 364da216e3f8750b037fde0f83d64ced0f94a1aa (diff) |
cec-ctl: improve the --phys-addr-from-edid-poll option
When --phys-addr-from-edid-poll is specified, start a background
thread that does the polling. This avoids having to start one
cec-ctl instance to do EDID polling, and another to start a stress
test (--stress-test-power-cycle).
When all other requested actions are finished, then cec-ctl will just
wait for Ctrl-C when --phys-addr-from-edid-poll is specified, so this
effectively keeps the old behavior as well.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r-- | utils/cec-ctl/Makefile.am | 2 | ||||
-rw-r--r-- | utils/cec-ctl/cec-ctl.1.in | 8 | ||||
-rw-r--r-- | utils/cec-ctl/cec-ctl.cpp | 106 |
3 files changed, 69 insertions, 47 deletions
diff --git a/utils/cec-ctl/Makefile.am b/utils/cec-ctl/Makefile.am index 278fcc47..de04c4de 100644 --- a/utils/cec-ctl/Makefile.am +++ b/utils/cec-ctl/Makefile.am @@ -3,6 +3,6 @@ man_MANS = cec-ctl.1 cec_ctl_SOURCES = cec-ctl.cpp cec-pin.cpp cec-ctl.h cec_ctl_CPPFLAGS = -I$(top_srcdir)/utils/libcecutil $(GIT_COMMIT_CNT) -cec_ctl_LDADD = -lrt ../libcecutil/libcecutil.la +cec_ctl_LDADD = -lrt -lpthread ../libcecutil/libcecutil.la EXTRA_DIST = cec-ctl.1 diff --git a/utils/cec-ctl/cec-ctl.1.in b/utils/cec-ctl/cec-ctl.1.in index fac3a92e..aaa3157f 100644 --- a/utils/cec-ctl/cec-ctl.1.in +++ b/utils/cec-ctl/cec-ctl.1.in @@ -56,7 +56,7 @@ Turn on verbose reporting. Show version information. .TP \fB\-w\fR, \fB\-\-wall\-clock\fR -Show timestamps as wall-clock time. This also turns on verbose reporting. +Show timestamps as wall-clock time. This also turns on verbose reporting. .TP \fB\-h\fR, \fB\-\-help\fR Prints the help message. @@ -79,6 +79,10 @@ EDID file every 100 ms and, if changed, update the physical address. This provides a way for Pulse-Eight (or similar) USB CEC dongles to become aware of HDMI disconnect and reconnect events. + +Polling happens in the background while cec-ctl processes other requested +actions (i.e. transmitting messages, waiting for replies, etc.) and when that +is all done cec-ctl will keep polling until the user kills cec-ctl (Ctrl-C). .TP \fB\-o\fR, \fB\-\-osd\-name\fR \fI<name>\fR Use this OSD name. The maximum length is 14 characters. @@ -102,7 +106,7 @@ By default when sending a CEC message that expects a reply this utility will wait for that reply. With this option it will just send it without waiting for the reply. This option applies to the messages following this option. It acts as a toggle, so after you specify it a second time then the following -messages will wait for a reply again. +messages will wait for a reply again. .TP \fB\-N\fR, \fB\-\-non\-blocking\fR Transmit messages in non-blocking mode. diff --git a/utils/cec-ctl/cec-ctl.cpp b/utils/cec-ctl/cec-ctl.cpp index 0cdab383..672110ab 100644 --- a/utils/cec-ctl/cec-ctl.cpp +++ b/utils/cec-ctl/cec-ctl.cpp @@ -21,6 +21,7 @@ #include <stdarg.h> #include <ctime> #include <cerrno> +#include <pthread.h> #include <string> #include <vector> #include <map> @@ -42,6 +43,7 @@ static struct timespec start_monotonic; static struct timeval start_timeofday; static bool ignore_la[16]; +static const char *edid_path; #define POLL_FAKE_OPCODE 256 static unsigned short ignore_opcode[257]; @@ -1749,6 +1751,48 @@ static __u16 parse_phys_addr_from_edid(const char *edid_path) return pa; } +static void *thread_edid_poll(void *arg) +{ + struct node *node = static_cast<struct node *>(arg); + __u16 phys_addr; + bool has_edid; + char dummy; + int fd; + + fd = open(edid_path, O_RDONLY); + if (fd < 0) + std::exit(EXIT_FAILURE); + lseek(fd, 0, SEEK_SET); + has_edid = read(fd, &dummy, 1) > 0; + + if (!has_edid) + phys_addr = CEC_PHYS_ADDR_INVALID; + else + phys_addr = parse_phys_addr_from_edid(edid_path); + doioctl(node, CEC_ADAP_S_PHYS_ADDR, &phys_addr); + printf("Physical Address: %x.%x.%x.%x\n", cec_phys_addr_exp(phys_addr)); + + for (;;) { + bool edid; + + /* Poll every 100 ms */ + usleep(100000); + lseek(fd, 0, SEEK_SET); + edid = read(fd, &dummy, 1) > 0; + if (has_edid != edid) { + has_edid = edid; + if (!edid) + phys_addr = CEC_PHYS_ADDR_INVALID; + else + phys_addr = parse_phys_addr_from_edid(edid_path); + doioctl(node, CEC_ADAP_S_PHYS_ADDR, &phys_addr); + printf("Physical Address: %x.%x.%x.%x\n", + cec_phys_addr_exp(phys_addr)); + } + } + return NULL; +} + using dev_vec = std::vector<std::string>; using dev_map = std::map<std::string, std::string>; @@ -1763,7 +1807,7 @@ static void list_devices() dp = opendir("/dev"); if (dp == NULL) { - perror ("Couldn't open the directory"); + perror("Couldn't open the directory"); return; } while ((ep = readdir(dp))) @@ -1856,7 +1900,6 @@ int main(int argc, char **argv) __u8 rc_tv = 0; __u8 rc_src = 0; const char *osd_name = ""; - const char *edid_path = NULL; const char *store_pin = NULL; const char *analyze_pin = NULL; bool reply = true; @@ -2580,10 +2623,19 @@ int main(int argc, char **argv) cec_driver_info(caps, laddrs, phys_addr, conn_info); } + if (options[OptPhysAddrFromEDIDPoll]) { + pthread_t t; + int ret = pthread_create(&t, NULL, thread_edid_poll, &node); + if (ret) { + fprintf(stderr, "Failed to start EDID poll thread: %s\n", + strerror(errno)); + std::exit(EXIT_FAILURE); + } + } + if (node.num_log_addrs == 0) { if (options[OptMonitor] || options[OptMonitorAll] || - options[OptMonitorPin] || options[OptStorePin] || - options[OptPhysAddrFromEDIDPoll]) + options[OptMonitorPin] || options[OptStorePin]) goto skip_la; if (warn_if_unconfigured) fprintf(stderr, "\nAdapter is unconfigured, please configure it first.\n"); @@ -2672,49 +2724,15 @@ int main(int argc, char **argv) stress_test_pwr_cycle_sleep_before_off); skip_la: - if (options[OptPhysAddrFromEDIDPoll]) { - bool has_edid; - char dummy; - int fd; - - fd = open(edid_path, O_RDONLY); - if (fd < 0) - std::exit(EXIT_FAILURE); - lseek(fd, 0, SEEK_SET); - has_edid = read(fd, &dummy, 1) > 0; - - if (!has_edid) - phys_addr = CEC_PHYS_ADDR_INVALID; - else - phys_addr = parse_phys_addr_from_edid(edid_path); - doioctl(&node, CEC_ADAP_S_PHYS_ADDR, &phys_addr); - printf("Physical Address: %x.%x.%x.%x\n", cec_phys_addr_exp(phys_addr)); - - for (;;) { - bool edid; - - /* Poll every 100 ms */ - usleep(100000); - lseek(fd, 0, SEEK_SET); - edid = read(fd, &dummy, 1) > 0; - if (has_edid != edid) { - has_edid = edid; - if (!edid) - phys_addr = CEC_PHYS_ADDR_INVALID; - else - phys_addr = parse_phys_addr_from_edid(edid_path); - doioctl(&node, CEC_ADAP_S_PHYS_ADDR, &phys_addr); - printf("Physical Address: %x.%x.%x.%x\n", - cec_phys_addr_exp(phys_addr)); - } - } - } - if (options[OptMonitor] || options[OptMonitorAll] || - options[OptMonitorPin] || options[OptStorePin]) + options[OptMonitorPin] || options[OptStorePin]) { monitor(node, monitor_time, store_pin); - else if (options[OptWaitForMsgs]) + } else if (options[OptWaitForMsgs]) { wait_for_msgs(node, monitor_time); + } else if (options[OptPhysAddrFromEDIDPoll]) { + printf("Press Ctrl-C to stop EDID polling.\n"); + pause(); + } fflush(stdout); close(fd); return 0; |