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: v4l2-ctl: allow waiting/polling for multiple events Author: Hans Verkuil <hverkuil-ci...@xs4all.nl> Date: Thu Mar 17 10:35:27 2022 +0100 Currently there can be only one --wait/poll/epoll-for-event option, so waiting or polling is for a single event only. Add support for more than one of these options to make it possible to wait/poll for multiple events. Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl> utils/v4l2-ctl/v4l2-ctl.cpp | 167 ++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 91 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=52b4b9f26e1f4ee606a4885c117c088d681887fe diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index 1c433355c17b..6bf0a1c7d201 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -21,6 +21,7 @@ */ #include <cctype> +#include <vector> #include <dirent.h> #include <getopt.h> @@ -1106,6 +1107,12 @@ err: int main(int argc, char **argv) { + struct event { + int type; + __u32 ev; + __u32 id; + std::string name; + }; int i; cv4l_fd c_fd; cv4l_fd c_out_fd; @@ -1124,12 +1131,7 @@ int main(int argc, char **argv) const char *export_device = nullptr; struct v4l2_capability vcap = {}; struct v4l2_subdev_capability subdevcap = {}; - __u32 wait_for_event = 0; /* wait for this event */ - const char *wait_event_id = nullptr; - __u32 poll_for_event = 0; /* poll for this event */ - const char *poll_event_id = nullptr; - __u32 epoll_for_event = 0; /* epoll for this event */ - const char *epoll_event_id = nullptr; + std::vector<event> events; unsigned secs = 0; char short_options[26 * 2 * 3 + 1]; int idx = 0; @@ -1151,6 +1153,8 @@ int main(int argc, char **argv) } while (true) { int option_index = 0; + const char *name; + event new_ev; short_options[idx] = 0; ch = getopt_long(argc, argv, short_options, @@ -1233,19 +1237,18 @@ int main(int argc, char **argv) media_bus_info = optarg; break; case OptWaitForEvent: - wait_for_event = parse_event(optarg, &wait_event_id); - if (wait_for_event == 0) - return 1; - break; case OptPollForEvent: - poll_for_event = parse_event(optarg, &poll_event_id); - if (poll_for_event == 0) - return 1; - break; case OptEPollForEvent: - epoll_for_event = parse_event(optarg, &epoll_event_id); - if (epoll_for_event == 0) + new_ev.type = ch; + new_ev.ev = parse_event(optarg, &name); + new_ev.id = 0; + if (new_ev.ev == 0) return 1; + if (new_ev.ev == V4L2_EVENT_SOURCE_CHANGE) + new_ev.id = strtoul(name, nullptr, 0); + else if (new_ev.ev == V4L2_EVENT_CTRL) + new_ev.name = name; + events.push_back(new_ev); break; case OptSleep: secs = strtoul(optarg, nullptr, 0); @@ -1399,21 +1402,15 @@ int main(int argc, char **argv) common_process_controls(c_fd); - if (wait_for_event == V4L2_EVENT_CTRL && wait_event_id) - if (!common_find_ctrl_id(wait_event_id)) { - fprintf(stderr, "unknown control '%s'\n", wait_event_id); - std::exit(EXIT_FAILURE); - } - if (poll_for_event == V4L2_EVENT_CTRL && poll_event_id) - if (!common_find_ctrl_id(poll_event_id)) { - fprintf(stderr, "unknown control '%s'\n", poll_event_id); - std::exit(EXIT_FAILURE); - } - if (epoll_for_event == V4L2_EVENT_CTRL && epoll_event_id) - if (!common_find_ctrl_id(epoll_event_id)) { - fprintf(stderr, "unknown control '%s'\n", epoll_event_id); + for (auto &e : events) { + if (e.ev != V4L2_EVENT_CTRL) + continue; + e.id = common_find_ctrl_id(e.name.c_str()); + if (!e.id) { + fprintf(stderr, "unknown control '%s'\n", e.name.c_str()); std::exit(EXIT_FAILURE); } + } if (options[OptAll]) { options[OptGetVideoFormat] = 1; @@ -1516,92 +1513,80 @@ int main(int argc, char **argv) streaming_set(c_fd, c_out_fd, c_exp_fd); - if (options[OptWaitForEvent]) { + for (const auto &e : events) { struct v4l2_event_subscription sub; struct v4l2_event ev; + if (e.type != OptWaitForEvent) + continue; memset(&sub, 0, sizeof(sub)); - sub.type = wait_for_event; - if (wait_for_event == V4L2_EVENT_CTRL) - sub.id = common_find_ctrl_id(wait_event_id); - else if (wait_for_event == V4L2_EVENT_SOURCE_CHANGE) - sub.id = strtoul(wait_event_id, nullptr, 0); + sub.type = e.ev; + sub.id = e.id; if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub)) if (!doioctl(fd, VIDIOC_DQEVENT, &ev)) print_event(&ev); + doioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); } - if (options[OptPollForEvent]) { + for (const auto &e : events) { struct v4l2_event_subscription sub; - struct v4l2_event ev; + if (e.type == OptWaitForEvent) + continue; memset(&sub, 0, sizeof(sub)); sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL; - sub.type = poll_for_event; - if (poll_for_event == V4L2_EVENT_CTRL) - sub.id = common_find_ctrl_id(poll_event_id); - else if (poll_for_event == V4L2_EVENT_SOURCE_CHANGE) - sub.id = strtoul(poll_event_id, nullptr, 0); - if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub)) { - fd_set fds; - __u32 seq = 0; - - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - while (true) { - int res; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - res = select(fd + 1, nullptr, nullptr, &fds, nullptr); - if (res <= 0) - break; - if (doioctl(fd, VIDIOC_DQEVENT, &ev)) - break; - print_event(&ev); - if (ev.sequence > seq) - printf("\tMissed %d events\n", - ev.sequence - seq); - seq = ev.sequence + 1; - } + sub.type = e.ev; + sub.id = e.id; + doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); + } + + if (options[OptPollForEvent]) { + fd_set fds; + __u32 seq = 0; + + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + while (true) { + struct v4l2_event ev; + int res; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + res = select(fd + 1, nullptr, nullptr, &fds, nullptr); + if (res <= 0) + break; + if (doioctl(fd, VIDIOC_DQEVENT, &ev)) + break; + print_event(&ev); + if (ev.sequence > seq) + printf("\tMissed %d events\n", ev.sequence - seq); + seq = ev.sequence + 1; } } if (options[OptEPollForEvent]) { struct epoll_event epoll_ev; int epollfd = -1; - struct v4l2_event_subscription sub; - struct v4l2_event ev; + __u32 seq = 0; epollfd = epoll_create1(0); epoll_ev.events = EPOLLPRI; epoll_ev.data.fd = fd; - memset(&sub, 0, sizeof(sub)); - sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL; - sub.type = epoll_for_event; - if (epoll_for_event == V4L2_EVENT_CTRL) - sub.id = common_find_ctrl_id(epoll_event_id); - else if (epoll_for_event == V4L2_EVENT_SOURCE_CHANGE) - sub.id = strtoul(epoll_event_id, nullptr, 0); - if (!doioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub)) { - __u32 seq = 0; - - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &epoll_ev); - while (true) { - int res; - - res = epoll_wait(epollfd, &epoll_ev, 1, -1); - if (res <= 0) - break; - if (doioctl(fd, VIDIOC_DQEVENT, &ev)) - break; - print_event(&ev); - if (ev.sequence > seq) - printf("\tMissed %d events\n", - ev.sequence - seq); - seq = ev.sequence + 1; - } + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &epoll_ev); + while (true) { + struct v4l2_event ev; + int res; + + res = epoll_wait(epollfd, &epoll_ev, 1, -1); + if (res <= 0) + break; + if (doioctl(fd, VIDIOC_DQEVENT, &ev)) + break; + print_event(&ev); + if (ev.sequence > seq) + printf("\tMissed %d events\n", ev.sequence - seq); + seq = ev.sequence + 1; } close(epollfd); } _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits