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 A/V input/output ioctls.
Author:  Hans Verkuil <hverk...@xs4all.nl>
Date:    Sat Jan 8 18:34:11 2011 +0100

Also did a major reorganization of the way failures are reported. This should
make it much easier to track down the cause of failures.

Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>

 utils/v4l2-compliance/Makefile                   |    2 +-
 utils/v4l2-compliance/v4l2-compliance.cpp        |  230 ++++++++--------
 utils/v4l2-compliance/v4l2-compliance.h          |   38 +++-
 utils/v4l2-compliance/v4l2-test-debug.cpp        |   60 ++---
 utils/v4l2-compliance/v4l2-test-input-output.cpp |  306 ++++++++++++++++++++++
 5 files changed, 476 insertions(+), 160 deletions(-)

---

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

diff --git a/utils/v4l2-compliance/Makefile b/utils/v4l2-compliance/Makefile
index d85be49..816a371 100644
--- a/utils/v4l2-compliance/Makefile
+++ b/utils/v4l2-compliance/Makefile
@@ -4,7 +4,7 @@ all: $(TARGETS)
 
 -include *.d
 
-v4l2-compliance: v4l2-compliance.o v4l2-test-debug.o
+v4l2-compliance: v4l2-compliance.o v4l2-test-debug.o v4l2-test-input-output.o
        $(CXX) $(LDFLAGS) -o $@ $^
 
 install: $(TARGETS)
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp 
b/utils/v4l2-compliance/v4l2-compliance.cpp
index ef77662..07dd7c1 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -50,6 +50,7 @@ enum Option {
        OptHelp = 'h',
        OptTest = 't',
        OptVerbose = 'v',
+       OptTrace = 'T',
        OptLast = 256
 };
 
@@ -58,6 +59,8 @@ enum Test {
        TestChipIdent,
        TestRegister,
        TestLogStatus,
+       TestInput,
+       TestOutput,
        TestMax
 };
 
@@ -78,6 +81,7 @@ static struct option long_options[] = {
        {"vbi-device", required_argument, 0, OptSetVbiDevice},
        {"help", no_argument, 0, OptHelp},
        {"verbose", no_argument, 0, OptVerbose},
+       {"trace", no_argument, 0, OptTrace},
        {"test", required_argument, 0, OptTest},
        {0, 0, 0, 0}
 };
@@ -97,26 +101,28 @@ static void usage(void)
        printf("  -t, --test=<num>   run specified test.\n");
        printf("                     By default all tests are run.\n");
        printf("                     0 = test VIDIOC_QUERYCAP\n");
-       printf("  -v, --verbose      turn on verbose ioctl error reporting.\n");
+       printf("  -v, --verbose      turn on verbose error reporting.\n");
+       printf("  -T, --trace        trace all called ioctls.\n");
        exit(0);
 }
 
-int doioctl(int fd, unsigned long int request, void *parm, const char *name)
+int doioctl(struct node *node, unsigned long int request, void *parm, const 
char *name)
 {
-       int retVal;
+       int retval;
        int e;
 
        errno = 0;
-       retVal = ioctl(fd, request, parm);
+       retval = ioctl(node->fd, request, parm);
        e = errno;
-       if (verbose)
-               printf("\t\t%s returned %d (%s)\n", name, retVal, strerror(e));
-       if (retVal == 0) return retVal;
-       if (retVal != -1) {
+       if (options[OptTrace])
+               printf("\t\t%s returned %d (%s)\n", name, retval, strerror(e));
+       if (retval == 0)
+               return 0;
+       if (retval != -1) {
+               fail("%s returned %d instead of 0 or -1\n", name, retval);
                return -1;
        }
-       retVal = e;
-       return retVal;
+       return e;
 }
 
 std::string cap2s(unsigned cap)
@@ -164,7 +170,7 @@ const char *ok(int res)
 {
        static char buf[100];
 
-       if (res == ENOSYS) {
+       if (res == -ENOSYS) {
                strcpy(buf, "Not Supported");
                res = 0;
        } else {
@@ -173,118 +179,100 @@ const char *ok(int res)
        tests_total++;
        if (res) {
                app_result = res;
-               sprintf(buf, "FAIL (%d)\n", res);
+               sprintf(buf, "FAIL");
        } else {
                tests_ok++;
        }
        return buf;
 }
 
-int check_string(const char *s, size_t len, const char *fld)
+int check_string(const char *s, size_t len)
 {
-       if (strlen(s) == 0) {
-               if (verbose)
-                       printf("%s field empty\n", fld);
-               return -1;
-       }
-       if (strlen(s) >= len) {
-               if (verbose)
-                       printf("%s field not 0-terminated\n", fld);
-               return -2;
-       }
+       size_t sz = strnlen(s, len);
+
+       if (sz == 0)
+               return fail("string empty\n");
+       if (sz == len)
+               return fail("string not 0-terminated\n");
        return 0;
 }
 
-int check_ustring(const __u8 *s, int len, const char *fld)
+int check_ustring(const __u8 *s, int len)
 {
-       return check_string((const char *)s, len, fld);
+       return check_string((const char *)s, len);
 }
 
-int check_0(void *p, int len)
+int check_0(const void *p, int len)
 {
-       __u8 *q = (__u8 *)p;
+       const __u8 *q = (const __u8 *)p;
 
        while (len--)
-               if (*q++) {
-                       if (verbose)
-                               printf("array not zeroed by driver\n");
-                       return -1;
-               }
+               if (*q++)
+                       return 1;
        return 0;
 }
 
-static int testCap(int fd)
+static int testCap(struct node *node)
 {
        struct v4l2_capability vcap;
        __u32 caps;
 
-       if (doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"))
-               return -1;
-       if (check_ustring(vcap.driver, sizeof(vcap.driver), "driver"))
-               return -2;
-       if (check_ustring(vcap.card, sizeof(vcap.card), "card"))
-               return -3;
+       if (doioctl(node, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"))
+               return fail("VIDIOC_QUERYCAP not implemented\n");
+       if (check_ustring(vcap.driver, sizeof(vcap.driver)))
+               return fail("invalid driver name\n");
+       if (check_ustring(vcap.card, sizeof(vcap.card)))
+               return fail("invalid card name\n");
        if (check_0(vcap.reserved, sizeof(vcap.reserved)))
-               return -4;
+               return fail("non-zero reserved fields\n");
        caps = vcap.capabilities;
-       if (caps == 0) {
-               if (verbose) printf("no capabilities set\n");
-               return -6;
-       }
+       if (caps == 0)
+               return fail("no capabilities set\n");
        return 0;
 }
 
-static int check_prio(int fd, int fd2, enum v4l2_priority match)
+static int check_prio(struct node *node, struct node *node2, enum 
v4l2_priority match)
 {
        enum v4l2_priority prio;
        int err;
 
-       err = doioctl(fd, VIDIOC_G_PRIORITY, &prio, "VIDIOC_G_PRIORITY");
+       err = doioctl(node, VIDIOC_G_PRIORITY, &prio, "VIDIOC_G_PRIORITY");
        if (err == EINVAL)
-               return ENOSYS;
+               return -ENOSYS;
        if (err)
-               return -1;
-       if (prio != match) {
-               if (verbose) printf("wrong priority returned (%d, expected 
%d)\n", prio, match);
-               return -2;
-       }
-       if (doioctl(fd2, VIDIOC_G_PRIORITY, &prio, "VIDIOC_G_PRIORITY"))
-               return -3;
-       if (prio != match) {
-               if (verbose) printf("wrong priority returned on second fh (%d, 
expected %d)\n", prio, match);
-               return -4;
-       }
+               return fail("VIDIOC_G_PRIORITY failed\n");
+       if (prio != match)
+               return fail("wrong priority returned (%d, expected %d)\n", 
prio, match);
+       if (doioctl(node2, VIDIOC_G_PRIORITY, &prio, "VIDIOC_G_PRIORITY"))
+               return fail("second VIDIOC_G_PRIORITY failed\n");
+       if (prio != match)
+               return fail("wrong priority returned on second fh (%d, expected 
%d)\n", prio, match);
        return 0;
 }
 
-static int testPrio(int fd, int fd2)
+static int testPrio(struct node *node, struct node *node2)
 {
        enum v4l2_priority prio;
        int err;
 
-       err = check_prio(fd, fd2, V4L2_PRIORITY_DEFAULT);
+       err = check_prio(node, node2, V4L2_PRIORITY_DEFAULT);
        if (err)
                return err;
 
        prio = V4L2_PRIORITY_RECORD;
-       if (doioctl(fd, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY"))
-               return -10;
-       if (check_prio(fd, fd2, V4L2_PRIORITY_RECORD))
-               return -11;
+       if (doioctl(node, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY"))
+               return fail("VIDIOC_S_PRIORITY RECORD failed\n");
+       if (check_prio(node, node2, V4L2_PRIORITY_RECORD))
+               return fail("expected priority RECORD");
 
        prio = V4L2_PRIORITY_INTERACTIVE;
-       if (!doioctl(fd2, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY")) {
-               if (verbose) printf("Can lower prio on second filehandle\n");
-               return -12;
-       }
+       if (!doioctl(node2, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY"))
+               return fail("Can lower prio on second filehandle\n");
        prio = V4L2_PRIORITY_INTERACTIVE;
-       if (doioctl(fd, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY")) {
-               if (verbose) printf("Could not lower prio\n");
-               return -13;
-       }
-       
-       if (check_prio(fd, fd2, V4L2_PRIORITY_INTERACTIVE))
-               return -14;
+       if (doioctl(node, VIDIOC_S_PRIORITY, &prio, "VIDIOC_S_PRIORITY"))
+               return fail("Could not lower prio\n");
+       if (check_prio(node, node2, V4L2_PRIORITY_INTERACTIVE))
+               return fail("expected priority INTERACTIVE");
        return 0;
 }
 
@@ -292,13 +280,13 @@ int main(int argc, char **argv)
 {
        int i;
        unsigned t;
-       int fd = -1;
-       int video_fd = -1;
-       int video_fd2 = -1;
-       int radio_fd = -1;
-       int radio_fd2 = -1;
-       int vbi_fd = -1;
-       int vbi_fd2 = -1;
+       struct node node = { -1 };
+       struct node video_node = { -1 };
+       struct node video_node2 = { -1 };
+       struct node radio_node = { -1 };
+       struct node radio_node2 = { -1 };
+       struct node vbi_node = { -1 };
+       struct node vbi_node2 = { -1 };
 
        /* command args */
        int ch;
@@ -402,37 +390,37 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       if (video_device && (video_fd = open(video_device, O_RDWR)) < 0) {
+       if (video_device && (video_node.fd = open(video_device, O_RDWR)) < 0) {
                fprintf(stderr, "Failed to open %s: %s\n", video_device,
                        strerror(errno));
                exit(1);
        }
 
-       if (radio_device && (radio_fd = open(radio_device, O_RDWR)) < 0) {
+       if (radio_device && (radio_node.fd = open(radio_device, O_RDWR)) < 0) {
                fprintf(stderr, "Failed to open %s: %s\n", radio_device,
                        strerror(errno));
                exit(1);
        }
 
-       if (vbi_device && (vbi_fd = open(vbi_device, O_RDWR)) < 0) {
+       if (vbi_device && (vbi_node.fd = open(vbi_device, O_RDWR)) < 0) {
                fprintf(stderr, "Failed to open %s: %s\n", vbi_device,
                        strerror(errno));
                exit(1);
        }
 
-       if (video_fd >= 0) {
-               fd = video_fd;
+       if (video_node.fd >= 0) {
+               node.fd = video_node.fd;
                device = video_device;
-       } else if (radio_fd >= 0) {
-               fd = radio_fd;
+       } else if (radio_node.fd >= 0) {
+               node.fd = radio_node.fd;
                device = radio_device;
-       } else if (vbi_fd >= 0) {
-               fd = vbi_fd;
+       } else if (vbi_node.fd >= 0) {
+               node.fd = vbi_node.fd;
                device = vbi_device;
        }
 
-       ioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
-       caps = vcap.capabilities;
+       ioctl(node.fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
+       node.caps = vcap.capabilities;
 
        /* Information Opts */
 
@@ -449,54 +437,66 @@ int main(int argc, char **argv)
        printf("Required ioctls:\n");
        if (test[TestCap]) {
                if (video_device)
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(video_fd)));
+                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&video_node)));
                if (radio_device)
-                       printf("\ttest VIDIOC_QUERYCAP for radio: %s\n", 
ok(testCap(radio_fd)));
+                       printf("\ttest VIDIOC_QUERYCAP for radio: %s\n", 
ok(testCap(&radio_node)));
                if (vbi_device)
-                       printf("\ttest VIDIOC_QUERYCAP for vbi: %s\n", 
ok(testCap(vbi_fd)));
+                       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_fd2 = open(video_device, O_RDWR)) < 
0));
-               if (video_fd2 >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(video_fd2)));
+                               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_fd, video_fd2)));
-                       close(video_fd2);
+                                       ok(testPrio(&video_node, 
&video_node2)));
+                       close(video_node2.fd);
                }
        }
        if (radio_device) {
                printf("\ttest second radio open: %s\n",
-                               ok((radio_fd2 = open(radio_device, O_RDWR)) < 
0));
-               if (radio_fd2 >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(radio_fd2)));
+                               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_fd, radio_fd2)));
-                       close(radio_fd2);
+                                       ok(testPrio(&radio_node, 
&radio_node2)));
+                       close(radio_node2.fd);
                }
        }
        if (vbi_device) {
                printf("\ttest second vbi open: %s\n",
-                               ok((vbi_fd2 = open(vbi_device, O_RDWR)) < 0));
-               if (vbi_fd2 >= 0) {
-                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(vbi_fd2)));
+                               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_fd, vbi_fd2)));
-                       close(vbi_fd2);
+                                       ok(testPrio(&vbi_node, &vbi_node2)));
+                       close(vbi_node2.fd);
                }
        }
 
        printf("Debug ioctls:\n");
        if (test[TestChipIdent])
-               printf("\ttest VIDIOC_DBG_G_CHIP_IDENT: %s\n", 
ok(testChipIdent(fd)));
+               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(fd)));
+               printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", 
ok(testRegister(&node)));
        if (test[TestLogStatus])
-               printf("\ttest VIDIOC_LOG_STATUS: %s\n", ok(testLogStatus(fd)));
+               printf("\ttest VIDIOC_LOG_STATUS: %s\n", 
ok(testLogStatus(&node)));
+
+       printf("Input ioctls:\n");
+       if (test[TestInput]) {
+               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("\ttest VIDIOC_S/G/ENUMAUDOUT: %s\n", 
ok(testOutputAudio(&node)));
+               printf("\ttest VIDIOC_G/S/ENUMOUTPUT: %s\n", 
ok(testOutput(&node)));
+       }
 
-       close(fd);
+       close(node.fd);
        printf("Total: %d Succeeded: %d Failed: %d\n",
                        tests_total, tests_ok, tests_total - tests_ok);
        exit(app_result);
diff --git a/utils/v4l2-compliance/v4l2-compliance.h 
b/utils/v4l2-compliance/v4l2-compliance.h
index cac3583..0e95877 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -27,16 +27,40 @@
 extern int verbose;
 extern unsigned caps;
 
-int doioctl(int fd, unsigned long int request, void *parm, const char *name);
+struct node {
+       int fd;
+       unsigned caps;
+       unsigned tuners;
+       unsigned modulators;
+       unsigned audio_inputs;
+       unsigned audio_outputs;
+};
+
+#define fail(fmt, args...)                     \
+({                                             \
+       if (verbose)                            \
+               printf("\t\tfail: " fmt, ##args);       \
+       1;                                      \
+})
+
+int doioctl(struct node *node, unsigned long int request, void *parm, const 
char *name);
 std::string cap2s(unsigned cap);
 const char *ok(int res);
-int check_string(const char *s, size_t len, const char *fld);
-int check_ustring(const __u8 *s, int len, const char *fld);
-int check_0(void *p, int len);
+int check_string(const char *s, size_t len);
+int check_ustring(const __u8 *s, int len);
+int check_0(const void *p, int len);
 
 // Debug ioctl tests
-int testChipIdent(int fd);
-int testRegister(int fd);
-int testLogStatus(int fd);
+int testChipIdent(struct node *node);
+int testRegister(struct node *node);
+int testLogStatus(struct node *node);
+
+// Input ioctl tests
+int testInput(struct node *node);
+int testInputAudio(struct node *node);
+
+// Output ioctl tests
+int testOutput(struct node *node);
+int testOutputAudio(struct node *node);
 
 #endif
diff --git a/utils/v4l2-compliance/v4l2-test-debug.cpp 
b/utils/v4l2-compliance/v4l2-test-debug.cpp
index fe357b8..8a14dab 100644
--- a/utils/v4l2-compliance/v4l2-test-debug.cpp
+++ b/utils/v4l2-compliance/v4l2-test-debug.cpp
@@ -35,7 +35,7 @@
 #include <sys/klog.h>
 #include "v4l2-compliance.h"
 
-int testChipIdent(int fd)
+int testChipIdent(struct node *node)
 {
        struct v4l2_dbg_chip_ident chip;
        int ret;
@@ -43,7 +43,7 @@ int testChipIdent(int fd)
        memset(&chip, 0, sizeof(chip));
        chip.match.type = V4L2_CHIP_MATCH_HOST;
        chip.match.addr = 0;
-       ret = doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT");
+       ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT");
        // Must return either 0 (OK) or EINVAL (not supported)
        if (ret == 0) {
                struct v4l2_dbg_chip_ident orig;
@@ -55,23 +55,17 @@ int testChipIdent(int fd)
                chip.ident = 0xdeadbeef;
                chip.revision = 0xdeadbeef;
                orig = chip;
-               ret = doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT");
-               if (ret != EINVAL) {
-                       if (verbose)
-                               printf("Invalid match_type accepted\n");
-                       return -1;
-               }
-               if (memcmp(&orig, &chip, sizeof(chip))) {
-                       if (verbose)
-                               printf("Error, but struct modified\n");
-                       return -2;
-               }
+               ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT");
+               if (ret != EINVAL)
+                       return fail("Invalid match_type accepted\n");
+               if (memcmp(&orig, &chip, sizeof(chip)))
+                       return fail("Error, but struct modified\n");
                return 0;
        }
-       return ret == EINVAL ? ENOSYS : ret;
+       return ret == EINVAL ? -ENOSYS : ret;
 }
 
-int testRegister(int fd)
+int testRegister(struct node *node)
 {
        struct v4l2_dbg_register reg;
        struct v4l2_dbg_chip_ident chip;
@@ -81,39 +75,31 @@ int testRegister(int fd)
        reg.match.type = V4L2_CHIP_MATCH_HOST;
        reg.match.addr = 0;
        reg.reg = 0;
-       ret = doioctl(fd, VIDIOC_DBG_G_REGISTER, &reg, "VIDIOC_DBG_G_REGISTER");
+       ret = doioctl(node, VIDIOC_DBG_G_REGISTER, &reg, 
"VIDIOC_DBG_G_REGISTER");
        if (ret == EINVAL)
-               return ENOSYS;
-       if (uid && ret != EPERM) {
-               printf("Not allowed to call VIDIOC_DBG_G_REGISTER unless 
root\n");
-               return -1;
-       }
-       if (uid == 0 && ret) {
-               printf("Not allowed to call VIDIOC_DBG_G_REGISTER even though 
we are root\n");
-               return -2;
-       }
+               return -ENOSYS;
+       if (uid && ret != EPERM)
+               return fail("Not allowed to call VIDIOC_DBG_G_REGISTER unless 
root\n");
+       if (uid == 0 && ret)
+               return fail("Not allowed to call VIDIOC_DBG_G_REGISTER even 
though we are root\n");
        chip.match.type = V4L2_CHIP_MATCH_HOST;
        chip.match.addr = 0;
-       if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT")) {
-               printf("Must support VIDIOC_DBG_G_CHIP_IDENT\n");
-               return -3;
-       }
+       if (doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip, 
"VIDIOC_DBG_G_CHIP_IDENT"))
+               return fail("Must support VIDIOC_DBG_G_CHIP_IDENT\n");
        if (uid) {
                // Don't test S_REGISTER as root, don't want to risk
                // messing with registers in the compliance test.
                reg.reg = reg.val = 0;
-               ret = doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg, 
"VIDIOC_DBG_S_REGISTER");
-               if (ret != EINVAL && ret != EPERM) {
-                       printf("Invalid error calling VIDIOC_DBG_S_REGISTER as 
non-root\n");
-                       return -4;
-               }
+               ret = doioctl(node, VIDIOC_DBG_S_REGISTER, &reg, 
"VIDIOC_DBG_S_REGISTER");
+               if (ret != EINVAL && ret != EPERM)
+                       return fail("Invalid error calling 
VIDIOC_DBG_S_REGISTER as non-root\n");
        }
        return 0;
 }
 
-int testLogStatus(int fd)
+int testLogStatus(struct node *node)
 {
-       int ret = doioctl(fd, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS");
+       int ret = doioctl(node, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS");
 
-       return (ret == EINVAL) ? ENOSYS : ret;
+       return (ret == EINVAL) ? -ENOSYS : ret;
 }
diff --git a/utils/v4l2-compliance/v4l2-test-input-output.cpp 
b/utils/v4l2-compliance/v4l2-test-input-output.cpp
new file mode 100644
index 0000000..d42af58
--- /dev/null
+++ b/utils/v4l2-compliance/v4l2-test-input-output.cpp
@@ -0,0 +1,306 @@
+/*
+    V4L2 API compliance input/output ioctl tests.
+
+    Copyright (C) 2011  Hans Verkuil <hverk...@xs4all.nl>
+
+    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"
+
+#define MAGIC 0x1eadbeef
+
+static int validInput(const struct v4l2_input *descr, unsigned i, unsigned 
max_audio)
+{
+       __u32 mask = (1 << max_audio) - 1;
+
+       if (descr->index != i)
+               return fail("invalid index\n");
+       if (check_ustring(descr->name, sizeof(descr->name)))
+               return fail("invalid name\n");
+       if (descr->type != V4L2_INPUT_TYPE_TUNER && descr->type != 
V4L2_INPUT_TYPE_CAMERA)
+               return fail("invalid type\n");
+       if (descr->type == V4L2_INPUT_TYPE_CAMERA && descr->tuner)
+               return fail("invalid tuner\n");
+       if (!(descr->capabilities & V4L2_IN_CAP_STD) && descr->std)
+               return fail("invalid std\n");
+       if ((descr->capabilities & V4L2_IN_CAP_STD) && !descr->std)
+               return fail("std == 0\n");
+       if (descr->capabilities & ~0x7)
+               return fail("invalid capabilities\n");
+       if (check_0(descr->reserved, sizeof(descr->reserved)))
+               return fail("non-zero reserved fields\n");
+       if (descr->status & ~0x07070337)
+               return fail("invalid status\n");
+       if (descr->status & 0x02070000)
+               return fail("use of deprecated digital video status\n");
+       if (descr->audioset & ~mask)
+               return fail("invalid audioset\n");
+       return 0;
+}
+
+int testInput(struct node *node)
+{
+       struct v4l2_input descr;
+       struct v4l2_audio audio;
+       int cur_input = MAGIC;
+       int input;
+       int ret = doioctl(node, VIDIOC_G_INPUT, &cur_input, "VIDIOC_G_INPUT");
+       int i = 0;
+       unsigned a;
+
+       if (ret == EINVAL)
+               return -ENOSYS;
+       if (ret)
+               return ret;
+       if (cur_input == MAGIC)
+               return fail("VIDIOC_G_INPUT didn't fill in the input\n");
+       for (;;) {
+               memset(&descr, 0xff, sizeof(descr));
+               descr.index = i;
+               ret = doioctl(node, VIDIOC_ENUMINPUT, &descr, 
"VIDIOC_ENUMINPUT");
+               if (ret == EINVAL)
+                       break;
+               if (ret)
+                       return fail("could not enumerate input %d\n", i);
+               input = i;
+               if (doioctl(node, VIDIOC_S_INPUT, &input, "VIDIOC_S_INPUT"))
+                       return fail("could not set input to %d\n", i);
+               if (input != i)
+                       return fail("input set to %d, but becomes %d?!\n", i, 
input);
+               if (validInput(&descr, i, node->audio_inputs))
+                       return fail("invalid attributes for input %d\n", i);
+               for (a = 0; a <= node->audio_inputs; a++) {
+                       memset(&audio, 0, sizeof(audio));
+                       audio.index = a;
+                       ret = doioctl(node, VIDIOC_S_AUDIO, &audio, 
"VIDIOC_S_AUDIO");
+                       if (ret && (descr.audioset & (1 << a)))
+                               return fail("could not set audio input to %d 
for video input %d\n", a, i);
+                       if (ret != EINVAL && !(descr.audioset & (1 << a)))
+                               return fail("could set invalid audio input %d 
for video input %d\n", a, i);
+               }
+               i++;
+       }
+       input = i;
+       if (doioctl(node, VIDIOC_S_INPUT, &input, "VIDIOC_S_INPUT") != EINVAL)
+               return fail("could set input to invalid input %d\n", i);
+       if (doioctl(node, VIDIOC_S_INPUT, &cur_input, "VIDIOC_S_INPUT"))
+               return fail("couldn't set input to the original input %d\n", 
cur_input);
+       return 0;
+}
+
+static int validInputAudio(const struct v4l2_audio *descr, unsigned i)
+{
+       if (descr->index != i)
+               return fail("invalid index\n");
+       if (check_ustring(descr->name, sizeof(descr->name)))
+               return fail("invalid name\n");
+       if (descr->capability & ~0x3)
+               return fail("invalid capabilities\n");
+       if (descr->mode != 0 && descr->mode != V4L2_AUDMODE_AVL)
+               return fail("invalid mode\n");
+       if (!(descr->capability & V4L2_AUDCAP_AVL) && descr->mode)
+               return fail("mode != 0\n");
+       if (check_0(descr->reserved, sizeof(descr->reserved)))
+               return fail("non-zero reserved fields\n");
+       return 0;
+}
+
+int testInputAudio(struct node *node)
+{
+       struct v4l2_audio input;
+       int i = 0;
+       int ret;
+
+       for (;;) {
+               memset(&input, 0xff, sizeof(input));
+               input.index = i;
+
+               ret = doioctl(node, VIDIOC_ENUMAUDIO, &input, 
"VIDIOC_ENUMAUDIO");
+               if (i == 0 && ret == EINVAL)
+                       return -ENOSYS;
+               if (ret == EINVAL)
+                       break;
+               if (ret)
+                       return fail("could not enumerate audio input %d\n", i);
+               if (validInputAudio(&input, i))
+                       return fail("invalid attributes for audio input %d\n", 
i);
+               node->audio_inputs++;
+               i++;
+       }
+       memset(&input, 0xff, sizeof(input));
+       memset(input.reserved, 0, sizeof(input.reserved));
+       input.index = i;
+       input.mode = 0;
+       if (doioctl(node, VIDIOC_S_AUDIO, &input, "VIDIOC_S_AUDIO") != EINVAL)
+               return fail("can set invalid audio input\n");
+       memset(&input, 0xff, sizeof(input));
+       ret = doioctl(node, VIDIOC_G_AUDIO, &input, "VIDIOC_G_AUDIO");
+       if (i == 0) {
+               if (ret != EINVAL)
+                       return fail("can get current audio input, but no inputs 
enumerated\n");
+               return 0;
+       }
+       if (ret)
+               return fail("cannot get current audio input\n");
+       if (input.index >= node->audio_inputs)
+               return fail("invalid current audio input %d\n", input.index);
+       if (validInputAudio(&input, input.index))
+               return fail("invalid attributes for audio input %d\n", 
input.index);
+       return 0;
+}
+
+static int validOutput(const struct v4l2_output *descr, unsigned o, unsigned 
max_audio)
+{
+       __u32 mask = (1 << max_audio) - 1;
+
+       if (descr->index != o)
+               return fail("invalid index\n");
+       if (check_ustring(descr->name, sizeof(descr->name)))
+               return fail("invalid name\n");
+       if (descr->type != V4L2_OUTPUT_TYPE_MODULATOR && descr->type != 
V4L2_OUTPUT_TYPE_ANALOG)
+               return fail("invalid type\n");
+       if (descr->type == V4L2_OUTPUT_TYPE_ANALOG && descr->modulator)
+               return fail("invalid modulator\n");
+       if (!(descr->capabilities & V4L2_OUT_CAP_STD) && descr->std)
+               return fail("invalid std\n");
+       if ((descr->capabilities & V4L2_OUT_CAP_STD) && !descr->std)
+               return fail("std == 0\n");
+       if (descr->capabilities & ~0x7)
+               return fail("invalid capabilities\n");
+       if (check_0(descr->reserved, sizeof(descr->reserved)))
+               return fail("non-zero reserved fields\n");
+       if (descr->audioset & ~mask)
+               return fail("invalid audioset\n");
+       return 0;
+}
+
+int testOutput(struct node *node)
+{
+       struct v4l2_output descr;
+       struct v4l2_audioout audio;
+       int cur_output = MAGIC;
+       int output;
+       int ret = doioctl(node, VIDIOC_G_OUTPUT, &cur_output, 
"VIDIOC_G_OUTPUT");
+       int o = 0;
+       unsigned a;
+
+       if (ret == EINVAL)
+               return -ENOSYS;
+       if (ret)
+               return ret;
+       if (cur_output == MAGIC)
+               return fail("VIDIOC_G_OUTPUT didn't fill in the output\n");
+       for (;;) {
+               memset(&descr, 0xff, sizeof(descr));
+               descr.index = o;
+               ret = doioctl(node, VIDIOC_ENUMOUTPUT, &descr, 
"VIDIOC_ENUMOUTPUT");
+               if (ret)
+                       break;
+               output = o;
+               if (doioctl(node, VIDIOC_S_OUTPUT, &output, "VIDIOC_S_OUTPUT"))
+                       return fail("could not set output to %d\n", o);
+               if (output != o)
+                       return fail("output set to %d, but becomes %d?!\n", o, 
output);
+               if (validOutput(&descr, o, node->audio_outputs))
+                       return fail("invalid attributes for output %d\n", o);
+               for (a = 0; a <= node->audio_outputs; a++) {
+                       memset(&audio, 0, sizeof(audio));
+                       audio.index = a;
+                       ret = doioctl(node, VIDIOC_S_AUDOUT, &audio, 
"VIDIOC_S_AUDOUT");
+                       if (ret && (descr.audioset & (1 << a)))
+                               return fail("could not set audio output to %d 
for video output %d\n", a, o);
+                       if (ret != EINVAL && !(descr.audioset & (1 << a)))
+                               return fail("could set invalid audio output %d 
for video output %d\n", a, o);
+               }
+               o++;
+       }
+       output = o;
+       if (doioctl(node, VIDIOC_S_OUTPUT, &output, "VIDIOC_S_OUTPUT") != 
EINVAL)
+               return fail("could set output to invalid output %d\n", o);
+       if (doioctl(node, VIDIOC_S_OUTPUT, &cur_output, "VIDIOC_S_OUTPUT"))
+               return fail("couldn't set output to the original output %d\n", 
cur_output);
+       return 0;
+}
+
+static int validOutputAudio(const struct v4l2_audioout *descr, unsigned o)
+{
+       if (descr->index != o)
+               return fail("invalid index\n");
+       if (check_ustring(descr->name, sizeof(descr->name)))
+               return fail("invalid name\n");
+       if (descr->capability)
+               return fail("invalid capabilities\n");
+       if (descr->mode)
+               return fail("invalid mode\n");
+       if (check_0(descr->reserved, sizeof(descr->reserved)))
+               return fail("non-zero reserved fields\n");
+       return 0;
+}
+
+int testOutputAudio(struct node *node)
+{
+       struct v4l2_audioout output;
+       int o = 0;
+       int ret;
+
+       for (;;) {
+               memset(&output, 0xff, sizeof(output));
+               output.index = o;
+
+               ret = doioctl(node, VIDIOC_ENUMAUDOUT, &output, 
"VIDIOC_ENUMAUDOUT");
+               if (o == 0 && ret == EINVAL)
+                       return -ENOSYS;
+               if (ret == EINVAL)
+                       break;
+               if (ret)
+                       return fail("could not enumerate audio output %d\n", o);
+               if (validOutputAudio(&output, o))
+                       return fail("invalid attributes for audio output %d\n", 
o);
+               node->audio_outputs++;
+               o++;
+       }
+       memset(&output, 0xff, sizeof(output));
+       memset(output.reserved, 0, sizeof(output.reserved));
+       output.index = o;
+       output.mode = 0;
+       if (doioctl(node, VIDIOC_S_AUDOUT, &output, "VIDIOC_S_AUDOUT") != 
EINVAL)
+               return fail("can set invalid audio output\n");
+       memset(&output, 0xff, sizeof(output));
+       ret = doioctl(node, VIDIOC_G_AUDOUT, &output, "VIDIOC_G_AUDOUT");
+       if (o == 0) {
+               if (ret != EINVAL)
+                       return fail("can get current audio output, but no 
outputs enumerated\n");
+               return 0;
+       }
+       if (ret)
+               return fail("cannot get current audio output\n");
+       if (output.index >= node->audio_outputs)
+               return fail("invalid current audio output %d\n", output.index);
+       if (validOutputAudio(&output, output.index))
+               return fail("invalid attributes for audio output %d\n", 
output.index);
+       return 0;
+}

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to