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-compliance: test polling and disconnecting
Author:  Hans Verkuil <[email protected]>
Date:    Wed Jan 6 09:21:53 2021 +0100

Test that disconnecting a device will wake up any processes
that are using select or poll.

This can only be tested with the vivid driver that enabled
the DISCONNECT control.

Signed-off-by: Hans Verkuil <[email protected]>

 utils/v4l2-compliance/v4l2-compliance.cpp    |  8 +++
 utils/v4l2-compliance/v4l2-compliance.h      |  5 ++
 utils/v4l2-compliance/v4l2-test-controls.cpp | 87 +++++++++++++++++++++++++++-
 3 files changed, 98 insertions(+), 2 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=4739a67dac10389559cffa6450a9ad88d37629ac
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp 
b/utils/v4l2-compliance/v4l2-compliance.cpp
index 2d4d10db1088..9e7b14c7ace8 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -1438,6 +1438,14 @@ void testNode(struct node &node, struct node 
&node_m2m_cap, struct node &expbuf_
         *       S_SELECTION flags tests
         */
 
+       if (is_vivid &&
+           node.controls.find(VIVID_CID_DISCONNECT) != node.controls.end()) {
+               if (node.node2)
+                       node.node2->close();
+               node.node2 = NULL;
+               printf("\ttest Disconnect: %s\n\n", 
ok(testVividDisconnect(&node)));
+       }
+
        restoreState();
 
 show_total:
diff --git a/utils/v4l2-compliance/v4l2-compliance.h 
b/utils/v4l2-compliance/v4l2-compliance.h
index 5cfe870b8b6e..c0cc57db153c 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -70,6 +70,10 @@ enum poll_mode {
 #define IS_ENCODER(node) ((node)->codec_mask & (JPEG_ENCODER | 
STATEFUL_ENCODER | STATELESS_ENCODER))
 #define IS_DECODER(node) ((node)->codec_mask & (JPEG_DECODER | 
STATEFUL_DECODER | STATELESS_DECODER))
 
+#define V4L2_CTRL_CLASS_VIVID 0x00f00000
+#define VIVID_CID_VIVID_BASE           (V4L2_CTRL_CLASS_VIVID | 0xf000)
+#define VIVID_CID_DISCONNECT            (VIVID_CID_VIVID_BASE + 65)
+
 struct test_query_ext_ctrl: v4l2_query_ext_ctrl {
        __u64 menu_mask;
 };
@@ -296,6 +300,7 @@ int testQueryControls(struct node *node);
 int testSimpleControls(struct node *node);
 int testExtendedControls(struct node *node);
 int testEvents(struct node *node);
+int testVividDisconnect(struct node *node);
 int testJpegComp(struct node *node);
 
 // I/O configuration ioctl tests
diff --git a/utils/v4l2-compliance/v4l2-test-controls.cpp 
b/utils/v4l2-compliance/v4l2-test-controls.cpp
index 839132b6f9c1..9a68b7e847b0 100644
--- a/utils/v4l2-compliance/v4l2-test-controls.cpp
+++ b/utils/v4l2-compliance/v4l2-test-controls.cpp
@@ -23,12 +23,12 @@
 #include <vector>
 
 #include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/epoll.h>
 
 #include "compiler.h"
 #include "v4l2-compliance.h"
 
-#define V4L2_CTRL_CLASS_VIVID 0x00f00000
-
 static int checkQCtrl(struct node *node, struct test_query_ext_ctrl &qctrl)
 {
        struct v4l2_querymenu qmenu;
@@ -901,6 +901,89 @@ int testEvents(struct node *node)
        return 0;
 }
 
+int testVividDisconnect(struct node *node)
+{
+       // Test that disconnecting a device will wake up any processes
+       // that are using select or poll.
+       //
+       // This can only be tested with the vivid driver that enabled
+       // the DISCONNECT control.
+
+       pid_t pid = fork();
+       if (pid == 0) {
+               struct timeval tv = { 5, 0 };
+               fd_set fds;
+
+               FD_ZERO(&fds);
+               FD_SET(node->g_fd(), &fds);
+               int res = select(node->g_fd() + 1, nullptr, nullptr, &fds, &tv);
+               // No POLLPRI seen
+               if (res != 1)
+                       exit(1);
+               // POLLPRI seen, but didn't wake up
+               if (!tv.tv_sec)
+                       exit(2);
+               v4l2_event ev = {};
+               // Woke up on POLLPRI, but VIDIOC_DQEVENT didn't return
+               // the ENODEV error.
+               if (doioctl(node, VIDIOC_DQEVENT, &ev) != ENODEV)
+                       exit(3);
+               exit(0);
+       }
+       v4l2_control ctrl = { VIVID_CID_DISCONNECT, 0 };
+       sleep(1);
+       fail_on_test(doioctl(node, VIDIOC_S_CTRL, &ctrl));
+       int wstatus;
+       fail_on_test(waitpid(pid, &wstatus, 0) != pid);
+       fail_on_test(!WIFEXITED(wstatus));
+       if (WEXITSTATUS(wstatus))
+               return fail("select child exited with status %d\n", 
WEXITSTATUS(wstatus));
+
+       node->reopen();
+
+       pid = fork();
+       if (pid == 0) {
+               struct epoll_event ep_ev;
+               int epollfd = epoll_create1(0);
+
+               if (epollfd < 0)
+                       exit(1);
+
+               ep_ev.events = 0;
+               if (epoll_ctl(epollfd, EPOLL_CTL_ADD, node->g_fd(), &ep_ev))
+                       exit(2);
+
+               ep_ev.events = EPOLLPRI;
+               ep_ev.data.fd = node->g_fd();
+               if (epoll_ctl(epollfd, EPOLL_CTL_MOD, node->g_fd(), &ep_ev))
+                       exit(3);
+               int ret = epoll_wait(epollfd, &ep_ev, 1, 5000);
+               if (ret == 0)
+                       exit(4);
+               if (ret < 0)
+                       exit(5);
+               if (ret != 1)
+                       exit(6);
+               if (!(ep_ev.events & EPOLLPRI))
+                       exit(7);
+               if (!(ep_ev.events & EPOLLERR))
+                       exit(8);
+               v4l2_event ev = {};
+               // Woke up on POLLPRI, but VIDIOC_DQEVENT didn't return
+               // the ENODEV error.
+               if (doioctl(node, VIDIOC_DQEVENT, &ev) != ENODEV)
+                       exit(9);
+               exit(0);
+       }
+       sleep(1);
+       fail_on_test(doioctl(node, VIDIOC_S_CTRL, &ctrl));
+       fail_on_test(waitpid(pid, &wstatus, 0) != pid);
+       fail_on_test(!WIFEXITED(wstatus));
+       if (WEXITSTATUS(wstatus))
+               return fail("epoll child exited with status %d\n", 
WEXITSTATUS(wstatus));
+       return 0;
+}
+
 int testJpegComp(struct node *node)
 {
        struct v4l2_jpegcompression jc;

_______________________________________________
linuxtv-commits mailing list
[email protected]
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to