[PATCH v5 4/4] v4l2-compliance: Add a test for DELETE_BUFS ioctl

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add new test for DELETE_BUFS ioctl.
It create buffers and check if they could be removed from queue.
It also check that removing non existing buffer or a queued
buffer failed.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@xxxxxxxxxxxxx>
---
version 5:
- add V4L2_BUF_CAP_SUPPORTS_DELETE_BUFS in bufcap_def array.

 utils/common/cv4l-helpers.h                 |   4 +
 utils/common/v4l-helpers.h                  |  17 +++
 utils/common/v4l2-info.cpp                  |   1 +
 utils/v4l2-compliance/v4l2-compliance.cpp   |   1 +
 utils/v4l2-compliance/v4l2-compliance.h     |   1 +
 utils/v4l2-compliance/v4l2-test-buffers.cpp | 121 ++++++++++++++++----
 6 files changed, 125 insertions(+), 20 deletions(-)

diff --git a/utils/common/cv4l-helpers.h b/utils/common/cv4l-helpers.h
index 199aca36..5fe23cc6 100644
--- a/utils/common/cv4l-helpers.h
+++ b/utils/common/cv4l-helpers.h
@@ -760,6 +760,10 @@ public:
 	{
 		return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count, flags);
 	}
+	int delete_bufs(cv4l_fd *fd, unsigned index = 0, unsigned count = 0)
+	{
+		return v4l_queue_delete_bufs(fd->g_v4l_fd(), this, index, count);
+	}
 	bool has_create_bufs(cv4l_fd *fd) const
 	{
 		return v4l_queue_has_create_bufs(fd->g_v4l_fd(), this);
diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
index cf0e92df..dca11e2d 100644
--- a/utils/common/v4l-helpers.h
+++ b/utils/common/v4l-helpers.h
@@ -1510,6 +1510,23 @@ static inline void *v4l_queue_g_dataptr(const struct v4l_queue *q, unsigned inde
 	return v4l_queue_g_mmapping(q, index, plane);
 }
 
+static inline int v4l_queue_delete_bufs(struct v4l_fd *f, struct v4l_queue *q, unsigned index, unsigned count)
+{
+	struct v4l2_delete_buffers deletebufs;
+	int ret;
+
+	memset(&deletebufs, 0, sizeof(deletebufs));
+	deletebufs.type = q->type;
+	deletebufs.index = index;
+	deletebufs.count = count;
+
+	ret = v4l_ioctl(f, VIDIOC_DELETE_BUFS, &deletebufs);
+	if (!ret)
+		q->buffers -= deletebufs.count;
+
+	return ret;
+}
+
 static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from)
 {
 	unsigned b, p;
diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp
index 5fc92005..9ff107d9 100644
--- a/utils/common/v4l2-info.cpp
+++ b/utils/common/v4l2-info.cpp
@@ -207,6 +207,7 @@ static constexpr flag_def bufcap_def[] = {
 	{ V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
 	{ V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" },
 	{ V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS, "set-max-num-buffers" },
+	{ V4L2_BUF_CAP_SUPPORTS_DELETE_BUFS, "delete-bufs" },
 	{ 0, nullptr }
 };
 
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index a165ef5a..c1e519ea 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -1454,6 +1454,7 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
 		printf("Buffer ioctls%s:\n", suffix);
 		printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: %s\n", ok(testReqBufs(&node)));
 		printf("\ttest CREATE_BUFS maximum buffers: %s\n", ok(testCreateBufsMax(&node)));
+		printf("\ttest VIDIOC_DELETE_BUFS: %s\n", ok(testDeleteBufs(&node)));
 		// Reopen after each streaming test to reset the streaming state
 		// in case of any errors in the preceeding test.
 		node.reopen();
diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
index 4f9aa17e..9ec07494 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -384,6 +384,7 @@ int testReadWrite(struct node *node);
 int testExpBuf(struct node *node);
 int testBlockingWait(struct node *node);
 int testCreateBufsMax(struct node *node);
+int testDeleteBufs(struct node *node);
 
 // 32-bit architecture, 32/64-bit time_t tests
 int testTime32_64(struct node *node);
diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
index e3c3db46..4eb2d8f4 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -529,6 +529,97 @@ static int testCanSetSameTimings(struct node *node)
 	return 0;
 }
 
+int testDeleteBufs(struct node *node)
+{
+	int ret;
+	unsigned i;
+
+	node->reopen();
+
+	for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) {
+		struct v4l2_delete_buffers delbufs = { };
+
+		if (!(node->valid_buftypes & (1 << i)))
+			continue;
+
+		cv4l_queue q(i, V4L2_MEMORY_MMAP);
+
+		if (testSetupVbi(node, i))
+			continue;
+
+		q.init(i, V4L2_MEMORY_MMAP);
+		ret = q.create_bufs(node, 0);
+		fail_on_test_val(ret && ret != EINVAL, ret);
+		if (!(q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_DELETE_BUFS))
+			continue;
+
+		memset(&delbufs, 0xff, sizeof(delbufs));
+		delbufs.index = 0;
+		delbufs.count = 0;
+		delbufs.type = q.g_type();
+		fail_on_test(doioctl(node, VIDIOC_DELETE_BUFS, &delbufs));
+        	fail_on_test(check_0(delbufs.reserved, sizeof(delbufs.reserved)));
+
+		if (!ret) {
+			unsigned buffers;
+			buffer buf(q);
+
+			/* Create only 1 buffer */
+			fail_on_test(q.create_bufs(node, 1));
+			buffers = q.g_buffers();
+			fail_on_test(buffers == 0);
+			/* Delete buffer index 1 must fail */
+			fail_on_test(q.delete_bufs(node, 1, buffers) != EINVAL);
+			/* Delete buffer index 0 is valid */
+			fail_on_test(q.delete_bufs(node, 0, buffers));
+			/* Delete buffer index 0 again must fail */
+			fail_on_test(q.delete_bufs(node, 0, 1) != EINVAL);
+			/* Create 3 buffers indexes 0 to 2 */
+			fail_on_test(q.create_bufs(node, 3));
+			/* Delete them one by one */
+			fail_on_test(q.delete_bufs(node, 2, 1));
+			fail_on_test(q.delete_bufs(node, 0, 1));
+			fail_on_test(q.delete_bufs(node, 1, 1));
+			/* Delete buffer index 0 again must fail */
+			fail_on_test(q.delete_bufs(node, 0, 1) != EINVAL);
+
+			/* Create 5 buffers indexes 0 to 4*/
+			fail_on_test(q.create_bufs(node, 5));
+			/* Delete buffers index 1 and 2 */
+			fail_on_test(q.delete_bufs(node, 1, 2));
+			/* Add 3 more buffers should be indexes 5 to 7*/
+			fail_on_test(q.create_bufs(node, 3));
+			/* Query buffers: 
+			 * 1 and 2 have been deleted they must fail 
+			 * 5 to 7 must exist*/
+			fail_on_test(buf.querybuf(node, 1) != EINVAL);
+			fail_on_test(buf.querybuf(node, 2) != EINVAL);
+			fail_on_test(buf.querybuf(node, 5));
+			fail_on_test(buf.querybuf(node, 6));
+			fail_on_test(buf.querybuf(node, 7));
+			/* Delete existing buffer index 7 with bad type must fail */
+			memset(&delbufs, 0xff, sizeof(delbufs));
+			delbufs.index = 7;
+			delbufs.count = 1;
+			delbufs.type = 0;
+			fail_on_test(doioctl(node, VIDIOC_DELETE_BUFS, &delbufs) != EINVAL);
+
+			/* Delete crossing max allowed buffers boundary must fail */
+			fail_on_test(q.delete_bufs(node, q.g_max_num_buffers() - 2, 8) != EINVAL);
+		
+			/* Delete overflow must fail */
+			fail_on_test(q.delete_bufs(node, 3, 0xfffffff) != EINVAL);
+
+			/* Create 2 buffers, that must fill the hole */
+			fail_on_test(q.create_bufs(node, 2));
+			/* Remove all buffers */
+			fail_on_test(q.delete_bufs(node, 0, 8));
+		}
+	}
+
+	return 0;
+}
+
 int testReqBufs(struct node *node)
 {
 	struct v4l2_create_buffers crbufs = { };
@@ -773,29 +864,19 @@ int testCreateBufsMax(struct node *node)
 	for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) {
 		if (!(node->valid_buftypes & (1 << i)))
 			continue;
-
-		q.init(i, V4L2_MEMORY_USERPTR);
-		ret = q.create_bufs(node, 1);
-		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
-			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
-			ret = q.create_bufs(node, 1);
-			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
-		}
-
+	
 		q.init(i, V4L2_MEMORY_MMAP);
-		ret = q.create_bufs(node, 1);
-		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
-			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
-			ret = q.create_bufs(node, 1);
-			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
-		}
-
-		q.init(i, V4L2_MEMORY_DMABUF);
-		ret = q.create_bufs(node, 1);
+		ret = q.create_bufs(node, 0);
 		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
-			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
+			fail_on_test(q.create_bufs(node, q.g_max_num_buffers()));
+			/* Some drivers may not have allocated all the requested buffers
+			 * because of memory limitation, that is OK but make the next test
+			 * failed so skip it
+			 */
+			if (q.g_max_num_buffers() != q.g_buffers())
+				continue;
 			ret = q.create_bufs(node, 1);
-			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
+			fail_on_test(ret != ENOBUFS);
 		}
 	}
 
-- 
2.39.2




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux