@@ -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:
@@ -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
@@ -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;
@@ -906,6 +906,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;
If a process polls for an event (using select() or epoll), and the device is unregistered, then it should wake up. This is normally difficult to test, but the vivid driver has a Disconnect control that can emulate this. This patch adds a testVividDisconnect() function to verify that select and epoll behave correctly. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> ---