This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/v4l-utils.git tree:
Subject: v4l2-compliance: add tests for VIDIOC_REQBUFS/CREATE_BUFS. Author: Hans Verkuil <[email protected]> Date: Thu Jun 7 00:16:12 2012 +0200 Signed-off-by: Hans Verkuil <[email protected]> (cherry picked from commit 2aff86ebeedf886c026f977463ba75bb689d90ef) Signed-off-by: Gregor Jasny <[email protected]> utils/v4l2-compliance/Makefile | 3 +- utils/v4l2-compliance/v4l2-compliance.cpp | 27 ++++- utils/v4l2-compliance/v4l2-compliance.h | 21 ++++ utils/v4l2-compliance/v4l2-test-buffers.cpp | 164 +++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 5 deletions(-) --- http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=5b08a8f2ce8783b26562ad30950dac3ebf562e7f diff --git a/utils/v4l2-compliance/Makefile b/utils/v4l2-compliance/Makefile index b65fc82..b267b3d 100644 --- a/utils/v4l2-compliance/Makefile +++ b/utils/v4l2-compliance/Makefile @@ -5,7 +5,8 @@ all: $(TARGETS) -include *.d v4l2-compliance: v4l2-compliance.o v4l2-test-debug.o v4l2-test-input-output.o \ - v4l2-test-controls.o v4l2-test-io-config.o v4l2-test-formats.o + v4l2-test-controls.o v4l2-test-io-config.o v4l2-test-formats.o \ + v4l2-test-buffers.o $(CXX) $(LDFLAGS) -o $@ $^ -lv4l2 -lv4lconvert -lrt install: $(TARGETS) diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp index 4869520..3ccd533 100644 --- a/utils/v4l2-compliance/v4l2-compliance.cpp +++ b/utils/v4l2-compliance/v4l2-compliance.cpp @@ -258,6 +258,7 @@ static int testCap(struct node *node) V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; + const __u32 io_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; // Must always be there fail_on_test(doioctl(node, VIDIOC_QUERYCAP, &vcap)); @@ -291,6 +292,10 @@ static int testCap(struct node *node) fail_on_test(dcaps & output_caps); if (dcaps & output_caps) fail_on_test(dcaps & input_caps); + if (node->can_capture || node->can_output) + fail_on_test(!(dcaps & io_caps)); + else + fail_on_test(dcaps & io_caps); return 0; } @@ -473,6 +478,7 @@ int main(int argc, char **argv) device = vbi_device; node.is_vbi = true; } + node.device = device; doioctl(&node, VIDIOC_QUERYCAP, &vcap); if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) @@ -487,6 +493,12 @@ int main(int argc, char **argv) V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_RDS_OUTPUT | V4L2_CAP_MODULATOR)) node.has_outputs = true; + if (node.caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_SLICED_VBI_CAPTURE)) + node.can_capture = true; + if (node.caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT | + V4L2_CAP_SLICED_VBI_OUTPUT)) + node.can_output = true; /* Information Opts */ @@ -528,7 +540,7 @@ int main(int argc, char **argv) printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&video_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&video_node, &video_node2))); - test_close(video_node2.fd); + node.node2 = &video_node2; } } if (radio_device) { @@ -539,7 +551,7 @@ int main(int argc, char **argv) printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&radio_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&radio_node, &radio_node2))); - test_close(radio_node2.fd); + node.node2 = &video_node2; } } if (vbi_device) { @@ -550,7 +562,7 @@ int main(int argc, char **argv) printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&vbi_node2))); printf("\ttest VIDIOC_G/S_PRIORITY: %s\n", ok(testPrio(&vbi_node, &vbi_node2))); - test_close(vbi_node2.fd); + node.node2 = &video_node2; } } printf("\n"); @@ -617,6 +629,12 @@ int main(int argc, char **argv) printf("\ttest VIDIOC_G_FMT: %s\n", ok(testFormats(&node))); printf("\ttest VIDIOC_G_SLICED_VBI_CAP: %s\n", ok(testSlicedVBICap(&node))); + /* Buffer ioctls */ + + printf("Buffer ioctls:\n"); + printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS: %s\n", ok(testReqBufs(&node))); + printf("\ttest read/write: %s\n", ok(testReadWrite(&node))); + /* TODO: VIDIOC_CROPCAP, VIDIOC_G/S_CROP, VIDIOC_G/S_SELECTION @@ -625,7 +643,7 @@ int main(int argc, char **argv) VIDIOC_(TRY_)ENCODER_CMD VIDIOC_(TRY_)DECODER_CMD VIDIOC_G_ENC_INDEX - VIDIOC_REQBUFS/QBUF/DQBUF/QUERYBUF/CREATE_BUFS/PREPARE_BUFS + VIDIOC_QBUF/DQBUF/QUERYBUF/PREPARE_BUFS VIDIOC_STREAMON/OFF */ @@ -633,6 +651,7 @@ int main(int argc, char **argv) /* Final test report */ test_close(node.fd); + test_close(node.node2->fd); printf("Total: %d Succeeded: %d Failed: %d Warnings: %d\n", tests_total, tests_ok, tests_total - tests_ok, warnings); exit(app_result); diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h index 18a91e4..0e50a63 100644 --- a/utils/v4l2-compliance/v4l2-compliance.h +++ b/utils/v4l2-compliance/v4l2-compliance.h @@ -40,12 +40,18 @@ struct test_queryctrl: v4l2_queryctrl { typedef std::list<test_queryctrl> qctrl_list; typedef std::set<__u32> pixfmt_set; +struct node; + struct node { int fd; bool is_video; bool is_radio; bool is_vbi; + bool can_capture; + bool can_output; + const char *device; unsigned caps; + struct node *node2; /* second open filehandle */ bool has_outputs; bool has_inputs; unsigned tuners; @@ -59,6 +65,7 @@ struct node { qctrl_list controls; __u32 fbuf_caps; pixfmt_set buftype_pixfmts[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE + 1]; + __u32 valid_buftype; }; #define info(fmt, args...) \ @@ -96,6 +103,16 @@ static inline int test_close(int fd) return wrapper ? v4l2_close(fd) : close(fd); } +static inline void reopen(struct node *node) +{ + test_close(node->fd); + if ((node->fd = test_open(node->device, O_RDWR)) < 0) { + fprintf(stderr, "Failed to open %s: %s\n", node->device, + strerror(errno)); + exit(1); + } +} + static inline int test_ioctl(int fd, int cmd, void *arg) { return wrapper ? v4l2_ioctl(fd, cmd, arg) : ioctl(fd, cmd, arg); @@ -167,4 +184,8 @@ int testFBuf(struct node *node); int testFormats(struct node *node); int testSlicedVBICap(struct node *node); +// Buffer ioctl tests +int testReqBufs(struct node *node); +int testReadWrite(struct node *node); + #endif diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp new file mode 100644 index 0000000..28b05ce --- /dev/null +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp @@ -0,0 +1,164 @@ +/* + V4L2 API compliance buffer ioctl tests. + + Copyright (C) 2012 Hans Verkuil <[email protected]> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <sys/ioctl.h> +#include "v4l2-compliance.h" + +int testReqBufs(struct node *node) +{ + struct v4l2_requestbuffers bufs; + struct v4l2_create_buffers cbufs; + struct v4l2_format fmt; + bool can_stream = node->caps & V4L2_CAP_STREAMING; + bool can_rw = node->caps & V4L2_CAP_READWRITE; + bool mmap_valid; + bool userptr_valid; + int ret; + unsigned i; + + memset(&bufs, 0, sizeof(bufs)); + memset(&cbufs, 0, sizeof(cbufs)); + ret = doioctl(node, VIDIOC_REQBUFS, &bufs); + if (ret == ENOTTY) { + fail_on_test(can_stream); + return ret; + } + fail_on_test(ret != EINVAL); + fail_on_test(node->node2 == NULL); + for (i = 1; i <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; i++) { + if (node->buftype_pixfmts[i].empty()) + continue; + info("test buftype %d\n", i); + if (node->valid_buftype == 0) + node->valid_buftype = i; + fmt.type = i; + fail_on_test(doioctl(node, VIDIOC_G_FMT, &fmt)); + bufs.type = fmt.type; + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs) != EINVAL); + bufs.memory = V4L2_MEMORY_MMAP; + ret = doioctl(node, VIDIOC_REQBUFS, &bufs); + fail_on_test(ret && ret != EINVAL); + mmap_valid = !ret; + bufs.memory = V4L2_MEMORY_USERPTR; + ret = doioctl(node, VIDIOC_REQBUFS, &bufs); + fail_on_test(ret && ret != EINVAL); + userptr_valid = !ret; + fail_on_test(can_stream && !mmap_valid && !userptr_valid); + fail_on_test(!can_stream && (mmap_valid || userptr_valid)); + if (!can_stream) + continue; + + if (mmap_valid) { + bufs.count = 1; + bufs.memory = V4L2_MEMORY_MMAP; + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + fail_on_test(bufs.count == 0); + fail_on_test(bufs.memory != V4L2_MEMORY_MMAP); + fail_on_test(bufs.type != i); + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + } + if (userptr_valid) { + bufs.count = 1; + bufs.memory = V4L2_MEMORY_USERPTR; + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + fail_on_test(bufs.count == 0); + fail_on_test(bufs.memory != V4L2_MEMORY_USERPTR); + fail_on_test(bufs.type != i); + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + } + + if (can_rw) { + char buf = 0; + + if (node->can_capture) + ret = read(node->fd, &buf, 1); + else + ret = write(node->fd, &buf, 1); + fail_on_test(ret != -1); + fail_on_test(errno != EBUSY); + } + bufs.count = 1; + fail_on_test(doioctl(node->node2, VIDIOC_REQBUFS, &bufs) != EBUSY); + bufs.count = 0; + fail_on_test(doioctl(node->node2, VIDIOC_REQBUFS, &bufs) != EBUSY); + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + bufs.count = 1; + fail_on_test(doioctl(node->node2, VIDIOC_REQBUFS, &bufs)); + bufs.count = 0; + fail_on_test(doioctl(node->node2, VIDIOC_REQBUFS, &bufs)); + cbufs.format = fmt; + cbufs.count = 1; + cbufs.memory = bufs.memory; + ret = doioctl(node, VIDIOC_CREATE_BUFS, &cbufs); + if (ret == ENOTTY) { + warn("VIDIOC_CREATE_BUFS not supported\n"); + continue; + } + fail_on_test(cbufs.count == 0); + fail_on_test(cbufs.memory != bufs.memory); + fail_on_test(cbufs.format.type != i); + cbufs.count = 1; + fail_on_test(doioctl(node, VIDIOC_CREATE_BUFS, &cbufs)); + bufs.count = 1; + fail_on_test(doioctl(node->node2, VIDIOC_REQBUFS, &bufs) != EBUSY); + bufs.count = 0; + fail_on_test(doioctl(node, VIDIOC_REQBUFS, &bufs)); + } + return 0; +} + +int testReadWrite(struct node *node) +{ + bool can_rw = node->caps & V4L2_CAP_READWRITE; + char buf = 0; + int ret; + + if (node->can_capture) + ret = read(node->fd, &buf, 1); + else + ret = write(node->fd, &buf, 1); + if (can_rw) + fail_on_test(ret != 1); + else + fail_on_test(ret < 0 && errno != EINVAL); + if (!can_rw) + return 0; + + reopen(node); + + /* check that the close cleared the busy flag */ + if (node->can_capture) + ret = read(node->fd, &buf, 1); + else + ret = write(node->fd, &buf, 1); + fail_on_test(ret != 1); + reopen(node); + return 0; +} _______________________________________________ linuxtv-commits mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits
