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 queryctrl/querymenu tests.
Author:  Hans Verkuil <[email protected]>
Date:    Sun Jan 9 22:58:32 2011 +0100

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

 utils/v4l2-compliance/Makefile               |    3 +-
 utils/v4l2-compliance/v4l2-compliance.cpp    |   91 ++++++-----
 utils/v4l2-compliance/v4l2-compliance.h      |    7 +
 utils/v4l2-compliance/v4l2-test-controls.cpp |  231 ++++++++++++++++++++++++++
 4 files changed, 289 insertions(+), 43 deletions(-)

---

http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=e4377f0f9bdb5538c5ee46db325e8b7b683f7dad

diff --git a/utils/v4l2-compliance/Makefile b/utils/v4l2-compliance/Makefile
index 816a371..b8aa16e 100644
--- a/utils/v4l2-compliance/Makefile
+++ b/utils/v4l2-compliance/Makefile
@@ -4,7 +4,8 @@ all: $(TARGETS)
 
 -include *.d
 
-v4l2-compliance: v4l2-compliance.o v4l2-test-debug.o v4l2-test-input-output.o
+v4l2-compliance: v4l2-compliance.o v4l2-test-debug.o v4l2-test-input-output.o \
+       v4l2-test-controls.o
        $(CXX) $(LDFLAGS) -o $@ $^
 
 install: $(TARGETS)
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp 
b/utils/v4l2-compliance/v4l2-compliance.cpp
index dc2e245..5dc39d8 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -45,22 +45,22 @@
    case is used to retrieve a setting. */
 enum Option {
        OptSetDevice = 'd',
-       OptSetRadioDevice = 'r',
-       OptSetVbiDevice = 'V',
        OptHelp = 'h',
+       OptSetRadioDevice = 'r',
        OptTest = 't',
-       OptVerbose = 'v',
        OptTrace = 'T',
+       OptVerbose = 'v',
+       OptSetVbiDevice = 'V',
        OptLast = 256
 };
 
 enum Test {
-       TestCap = 0,
-       TestChipIdent,
-       TestRegister,
-       TestLogStatus,
+       TestRequired = 0,
+       TestMultipleOpen,
+       TestDebug,
        TestInput,
        TestOutput,
+       TestControls,
        TestMax
 };
 
@@ -73,6 +73,7 @@ static int tests_total, tests_ok;
 
 // Globals
 int verbose;
+int ignore_failure;
 unsigned caps;
 
 static struct option long_options[] = {
@@ -435,8 +436,8 @@ int main(int argc, char **argv)
 
        printf("\nCompliance test for device %s:\n\n", device);
 
-       printf("Required ioctls:\n");
-       if (test[TestCap]) {
+       if (test[TestRequired]) {
+               printf("Required ioctls:\n");
                if (video_device)
                        printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&video_node)));
                if (radio_device)
@@ -445,60 +446,66 @@ int main(int argc, char **argv)
                        printf("\ttest VIDIOC_QUERYCAP for vbi: %s\n", 
ok(testCap(&vbi_node)));
        }
 
-       printf("Allow for multiple opens:\n");
-       if (video_device) {
-               printf("\ttest second video open: %s\n",
-                               ok((video_node2.fd = open(video_device, 
O_RDWR)) < 0));
-               if (video_node2.fd >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&video_node2)));
-                       printf("\ttest VIDIOC_S_PRIORITY: %s\n",
-                                       ok(testPrio(&video_node, 
&video_node2)));
-                       close(video_node2.fd);
+       if (test[TestMultipleOpen]) {
+               printf("Allow for multiple opens:\n");
+               if (video_device) {
+                       printf("\ttest second video open: %s\n",
+                                       ok((video_node2.fd = open(video_device, 
O_RDWR)) < 0));
+                       if (video_node2.fd >= 0) {
+                               printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&video_node2)));
+                               printf("\ttest VIDIOC_S_PRIORITY: %s\n",
+                                               ok(testPrio(&video_node, 
&video_node2)));
+                               close(video_node2.fd);
+                       }
                }
-       }
-       if (radio_device) {
-               printf("\ttest second radio open: %s\n",
-                               ok((radio_node2.fd = open(radio_device, 
O_RDWR)) < 0));
-               if (radio_node2.fd >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&radio_node2)));
-                       printf("\ttest VIDIOC_S_PRIORITY: %s\n",
-                                       ok(testPrio(&radio_node, 
&radio_node2)));
-                       close(radio_node2.fd);
+               if (radio_device) {
+                       printf("\ttest second radio open: %s\n",
+                                       ok((radio_node2.fd = open(radio_device, 
O_RDWR)) < 0));
+                       if (radio_node2.fd >= 0) {
+                               printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&radio_node2)));
+                               printf("\ttest VIDIOC_S_PRIORITY: %s\n",
+                                               ok(testPrio(&radio_node, 
&radio_node2)));
+                               close(radio_node2.fd);
+                       }
                }
-       }
-       if (vbi_device) {
-               printf("\ttest second vbi open: %s\n",
-                               ok((vbi_node2.fd = open(vbi_device, O_RDWR)) < 
0));
-               if (vbi_node2.fd >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&vbi_node2)));
-                       printf("\ttest VIDIOC_S_PRIORITY: %s\n",
-                                       ok(testPrio(&vbi_node, &vbi_node2)));
-                       close(vbi_node2.fd);
+               if (vbi_device) {
+                       printf("\ttest second vbi open: %s\n",
+                                       ok((vbi_node2.fd = open(vbi_device, 
O_RDWR)) < 0));
+                       if (vbi_node2.fd >= 0) {
+                               printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&vbi_node2)));
+                               printf("\ttest VIDIOC_S_PRIORITY: %s\n",
+                                               ok(testPrio(&vbi_node, 
&vbi_node2)));
+                               close(vbi_node2.fd);
+                       }
                }
        }
 
-       printf("Debug ioctls:\n");
-       if (test[TestChipIdent])
+       if (test[TestDebug]) {
+               printf("Debug ioctls:\n");
                printf("\ttest VIDIOC_DBG_G_CHIP_IDENT: %s\n", 
ok(testChipIdent(&node)));
-       if (test[TestRegister])
                printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", 
ok(testRegister(&node)));
-       if (test[TestLogStatus])
                printf("\ttest VIDIOC_LOG_STATUS: %s\n", 
ok(testLogStatus(&node)));
+       }
 
-       printf("Input ioctls:\n");
        if (test[TestInput]) {
+               printf("Input ioctls:\n");
                printf("\ttest VIDIOC_S/G_TUNER: %s\n", ok(testTuner(&node)));
                printf("\ttest VIDIOC_S/G/ENUMAUDIO: %s\n", 
ok(testInputAudio(&node)));
                printf("\ttest VIDIOC_G/S/ENUMINPUT: %s\n", 
ok(testInput(&node)));
        }
 
-       printf("Output ioctls:\n");
        if (test[TestOutput]) {
+               printf("Output ioctls:\n");
                printf("\ttest VIDIOC_S/G_MODULATOR: %s\n", 
ok(testModulator(&node)));
                printf("\ttest VIDIOC_S/G/ENUMAUDOUT: %s\n", 
ok(testOutputAudio(&node)));
                printf("\ttest VIDIOC_G/S/ENUMOUTPUT: %s\n", 
ok(testOutput(&node)));
        }
 
+       if (test[TestControls]) {
+               printf("Control ioctls:\n");
+               printf("\ttest VIDIOC_QUERYCTRL/MENU: %s\n", 
ok(testQueryControls(&node)));
+       }
+
        close(node.fd);
        printf("Total: %d Succeeded: %d Failed: %d\n",
                        tests_total, tests_ok, tests_total - tests_ok);
diff --git a/utils/v4l2-compliance/v4l2-compliance.h 
b/utils/v4l2-compliance/v4l2-compliance.h
index 9a17c1b..e503ac6 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -35,6 +35,10 @@ struct node {
        unsigned modulators;
        unsigned audio_inputs;
        unsigned audio_outputs;
+       unsigned user_controls;
+       unsigned priv_user_controls;
+       unsigned user_controls_check;
+       unsigned priv_user_controls_check;
 };
 
 #define fail(fmt, args...)                     \
@@ -68,4 +72,7 @@ int testModulator(struct node *node);
 int testOutput(struct node *node);
 int testOutputAudio(struct node *node);
 
+// Control ioctl tests
+int testQueryControls(struct node *node);
+
 #endif
diff --git a/utils/v4l2-compliance/v4l2-test-controls.cpp 
b/utils/v4l2-compliance/v4l2-test-controls.cpp
new file mode 100644
index 0000000..7feef2d
--- /dev/null
+++ b/utils/v4l2-compliance/v4l2-test-controls.cpp
@@ -0,0 +1,231 @@
+/*
+    V4L2 API compliance control ioctl tests.
+
+    Copyright (C) 2011  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 validQCtrl(struct node *node, const struct v4l2_queryctrl &qctrl)
+{
+       struct v4l2_querymenu qmenu;
+       __u32 fl = qctrl.flags;
+       __u32 rw_mask = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
+       unsigned menus = 0;
+       int ret;
+       int i;
+
+       if (qctrl.id & V4L2_CTRL_FLAG_NEXT_CTRL)
+               return fail("V4L2_CTRL_FLAG_NEXT_CTRL not cleared\n");
+       if (check_0(qctrl.reserved, sizeof(qctrl.reserved)))
+               return fail("non-zero reserved fields\n");
+       if (check_ustring(qctrl.name, sizeof(qctrl.name)))
+               return fail("invalid name\n");
+       switch (qctrl.type) {
+       case V4L2_CTRL_TYPE_BOOLEAN:
+               if (qctrl.maximum > 1)
+                       return fail("invalid boolean max value\n");
+               /* fall through */
+       case V4L2_CTRL_TYPE_MENU:
+               if (qctrl.step != 1)
+                       return fail("invalid step value %d\n", qctrl.step);
+               if (qctrl.minimum < 0)
+                       return fail("min < 0\n");
+               /* fall through */
+       case V4L2_CTRL_TYPE_INTEGER:
+               if (qctrl.default_value < qctrl.minimum ||
+                   qctrl.default_value > qctrl.maximum)
+                       return fail("def < min || def > max\n");
+               /* fall through */
+       case V4L2_CTRL_TYPE_STRING:
+               if (qctrl.minimum > qctrl.maximum)
+                       return fail("min > max\n");
+               if (qctrl.step == 0)
+                       return fail("step == 0\n");
+               if (qctrl.step < 0)
+                       return fail("step < 0\n");
+               if (qctrl.step > qctrl.maximum - qctrl.minimum)
+                       return fail("step > max - min\n");
+               break;
+       case V4L2_CTRL_TYPE_CTRL_CLASS:
+       case V4L2_CTRL_TYPE_INTEGER64:
+       case V4L2_CTRL_TYPE_BUTTON:
+               if (qctrl.minimum || qctrl.maximum || qctrl.step || 
qctrl.default_value)
+                       return fail("non-zero min/max/step/def\n");
+               break;
+       default:
+               return fail("unknown control type\n");
+       }
+       if (qctrl.type == V4L2_CTRL_TYPE_STRING && qctrl.default_value)
+               return fail("non-zero default value for string\n");
+       switch (qctrl.type) {
+       case V4L2_CTRL_TYPE_BUTTON:
+               if ((fl & rw_mask) != V4L2_CTRL_FLAG_WRITE_ONLY)
+                       return fail("button control not write only\n");
+               /* fall through */
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_MENU:
+       case V4L2_CTRL_TYPE_STRING:
+               if (fl & V4L2_CTRL_FLAG_SLIDER)
+                       return fail("slider makes only sense for integer 
controls\n");
+               /* fall through */
+       case V4L2_CTRL_TYPE_INTEGER64:
+       case V4L2_CTRL_TYPE_INTEGER:
+               if ((fl & rw_mask) == rw_mask)
+                       return fail("can't read nor write this control\n");
+               break;
+       case V4L2_CTRL_TYPE_CTRL_CLASS:
+               if (fl != (V4L2_CTRL_FLAG_READ_ONLY | 
V4L2_CTRL_FLAG_WRITE_ONLY))
+                       return fail("invalid flags for control class\n");
+               break;
+       }
+       if (qctrl.type != V4L2_CTRL_TYPE_MENU) {
+               memset(&qmenu, 0xff, sizeof(qmenu));
+               qmenu.id = qctrl.id;
+               qmenu.index = qctrl.minimum;
+               ret = doioctl(node, VIDIOC_QUERYMENU, &qmenu);
+               if (ret != EINVAL)
+                       return fail("can do querymenu on a non-menu control\n");
+               return 0;
+       }
+       for (i = 0; i <= qctrl.maximum + 1; i++) {
+               memset(&qmenu, 0xff, sizeof(qmenu));
+               qmenu.id = qctrl.id;
+               qmenu.index = i;
+               ret = doioctl(node, VIDIOC_QUERYMENU, &qmenu);
+               if (ret && ret != EINVAL)
+                       return fail("invalid QUERYMENU return code\n");
+               if (ret)
+                       continue;
+               if (i < qctrl.minimum || i > qctrl.maximum)
+                       return fail("can get menu for out-of-range index\n");
+               if (qmenu.index != (__u32)i || qmenu.id != qctrl.id)
+                       return fail("id or index changed\n");
+               if (check_ustring(qmenu.name, sizeof(qmenu.name)))
+                       return fail("invalid menu name\n");
+               if (qmenu.reserved)
+                       return fail("reserved is non-zero\n");
+               menus++;
+               return 0;
+       }
+       if (menus == 0)
+               return fail("no menu items found\n");
+       return 0;
+}
+
+int testQueryControls(struct node *node)
+{
+       struct v4l2_queryctrl qctrl;
+       __u32 id = 0;
+       int ret;
+       __u32 ctrl_class = 0;
+       bool found_ctrl_class = false;
+       unsigned class_count = 0;
+
+       for (;;) {
+               memset(&qctrl, 0xff, sizeof(qctrl));
+               qctrl.id = id | V4L2_CTRL_FLAG_NEXT_CTRL;
+               ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
+               if (ret && ret != EINVAL)
+                       return fail("invalid queryctrl return code\n");
+               if (ret && id == 0)
+                       return fail("does not support 
V4L2_CTRL_FLAG_NEXT_CTRL\n");
+               if (ret)
+                       break;
+               if (validQCtrl(node, qctrl))
+                       return fail("invalid control %08x\n", qctrl.id);
+               if (qctrl.id <= id)
+                       return fail("id did not increase!\n");
+               id = qctrl.id;
+               if (V4L2_CTRL_ID2CLASS(id) != ctrl_class) {
+                       if (ctrl_class && !found_ctrl_class)
+                               return fail("missing control class for class 
%08x\n", ctrl_class);
+                       if (ctrl_class && !class_count)
+                               return fail("no controls in class %08x\n", 
ctrl_class);
+                       ctrl_class = V4L2_CTRL_ID2CLASS(id);
+                       found_ctrl_class = false;
+                       class_count = 0;
+               }
+               if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
+                       found_ctrl_class = true;
+               else
+                       class_count++;
+
+               if (ctrl_class == V4L2_CTRL_CLASS_USER &&
+                   qctrl.type != V4L2_CTRL_TYPE_INTEGER64 &&
+                   qctrl.type != V4L2_CTRL_TYPE_STRING &&
+                   qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS) {
+                       if (V4L2_CTRL_DRIVER_PRIV(id))
+                               node->priv_user_controls_check++;
+                       else if (id < V4L2_CID_LASTP1)
+                               node->user_controls_check++;
+               }
+       }
+       if (ctrl_class && !found_ctrl_class)
+               return fail("missing control class for class %08x\n", 
ctrl_class);
+       if (ctrl_class && !class_count)
+               return fail("no controls in class %08x\n", ctrl_class);
+
+       for (id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; id++) {
+               memset(&qctrl, 0xff, sizeof(qctrl));
+               qctrl.id = id;
+               ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
+               if (ret && ret != EINVAL)
+                       return fail("invalid queryctrl return code\n");
+               if (ret)
+                       continue;
+               if (qctrl.id != id)
+                       return fail("qctrl.id != id\n");
+               if (validQCtrl(node, qctrl))
+                       return fail("invalid control %08x\n", qctrl.id);
+               node->user_controls++;
+       }
+
+       for (id = V4L2_CID_PRIVATE_BASE; ; id++) {
+               memset(&qctrl, 0xff, sizeof(qctrl));
+               qctrl.id = id;
+               ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl);
+               if (ret && ret != EINVAL)
+                       return fail("invalid queryctrl return code\n");
+               if (ret)
+                       break;
+               if (qctrl.id != id)
+                       return fail("qctrl.id != id\n");
+               if (validQCtrl(node, qctrl))
+                       return fail("invalid control %08x\n", qctrl.id);
+               node->priv_user_controls++;
+       }
+
+       if (node->user_controls != node->user_controls_check)
+               return fail("expected %d user controls, got %d\n",
+                       node->user_controls_check, node->user_controls);
+       if (node->priv_user_controls != node->priv_user_controls_check)
+               return fail("expected %d private controls, got %d\n",
+                       node->priv_user_controls_check, 
node->priv_user_controls);
+       return 0;
+}

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

Reply via email to