From 8c98c7a8d8502aed076409d75451bde89dfdf18f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 29 Jul 2011 15:02:38 +0200 Subject: [PATCH] v4l2-compliance: test for ENOTTY compliance. Unsupported ioctls used to return -EINVAL, but now they return -ENOTTY. This patch changes the compliance tests to take this into account. Signed-off-by: Hans Verkuil --- utils/v4l2-compliance/v4l2-compliance.cpp | 3 +- utils/v4l2-compliance/v4l2-test-controls.cpp | 10 ++-- utils/v4l2-compliance/v4l2-test-debug.cpp | 12 ++-- utils/v4l2-compliance/v4l2-test-formats.cpp | 71 +++++++++++++----------- utils/v4l2-compliance/v4l2-test-input-output.cpp | 59 ++++++++++---------- utils/v4l2-compliance/v4l2-test-io-config.cpp | 8 +-- 6 files changed, 85 insertions(+), 78 deletions(-) diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp index f865a76..7704364 100644 --- a/utils/v4l2-compliance/v4l2-compliance.cpp +++ b/utils/v4l2-compliance/v4l2-compliance.cpp @@ -193,7 +193,7 @@ const char *ok(int res) { static char buf[100]; - if (res == -ENOSYS) { + if (res == ENOTTY) { strcpy(buf, "Not Supported"); res = 0; } else { @@ -248,6 +248,7 @@ static int testCap(struct node *node) fail_on_test(vcap.bus_info[0]); warn("VIDIOC_QUERYCAP: empty bus_info\n"); } + fail_on_test((vcap.version >> 16) < 3); fail_on_test(check_0(vcap.reserved, sizeof(vcap.reserved))); caps = vcap.capabilities; fail_on_test(vcap.capabilities == 0); diff --git a/utils/v4l2-compliance/v4l2-test-controls.cpp b/utils/v4l2-compliance/v4l2-test-controls.cpp index 5f1b5a0..4a0712d 100644 --- a/utils/v4l2-compliance/v4l2-test-controls.cpp +++ b/utils/v4l2-compliance/v4l2-test-controls.cpp @@ -188,6 +188,8 @@ int testQueryControls(struct node *node) memset(&qctrl, 0xff, sizeof(qctrl)); qctrl.id = id | V4L2_CTRL_FLAG_NEXT_CTRL; ret = doioctl(node, VIDIOC_QUERYCTRL, &qctrl); + if (ret == ENOTTY) + return ret; if (ret && ret != EINVAL) return fail("invalid queryctrl return code\n"); if (ret) @@ -493,12 +495,10 @@ int testExtendedControls(struct node *node) memset(&ctrls, 0, sizeof(ctrls)); ret = doioctl(node, VIDIOC_G_EXT_CTRLS, &ctrls); - if (ret && !node->controls.empty()) - return fail("g_ext_ctrls does not support count == 0\n"); - if (ret && ret != EINVAL) - return fail("g_ext_ctrls with count == 0 did not return EINVAL\n"); + if (ret == ENOTTY && node->controls.empty()) + return ret; if (ret) - return -ENOSYS; + return fail("g_ext_ctrls does not support count == 0\n"); if (node->controls.empty()) return fail("g_ext_ctrls worked even when no controls are present\n"); if (ctrls.ctrl_class) diff --git a/utils/v4l2-compliance/v4l2-test-debug.cpp b/utils/v4l2-compliance/v4l2-test-debug.cpp index d624e81..074b975 100644 --- a/utils/v4l2-compliance/v4l2-test-debug.cpp +++ b/utils/v4l2-compliance/v4l2-test-debug.cpp @@ -61,7 +61,7 @@ int testChipIdent(struct node *node) fail_on_test(memcmp(&orig, &chip, sizeof(chip))); return 0; } - return ret == EINVAL ? -ENOSYS : ret; + return ret; } int testRegister(struct node *node) @@ -75,8 +75,8 @@ int testRegister(struct node *node) reg.match.addr = 0; reg.reg = 0; ret = doioctl(node, VIDIOC_DBG_G_REGISTER, ®); - if (ret == EINVAL) - return -ENOSYS; + if (ret == ENOTTY) + return ret; // Not allowed to call VIDIOC_DBG_G_REGISTER unless root fail_on_test(uid && ret != EPERM); fail_on_test(uid == 0 && ret); @@ -88,14 +88,12 @@ int testRegister(struct node *node) // messing with registers in the compliance test. reg.reg = reg.val = 0; ret = doioctl(node, VIDIOC_DBG_S_REGISTER, ®); - fail_on_test(ret != EINVAL && ret != EPERM); + fail_on_test(ret != ENOTTY && ret != EINVAL && ret != EPERM); } return 0; } int testLogStatus(struct node *node) { - int ret = doioctl(node, VIDIOC_LOG_STATUS, NULL); - - return (ret == EINVAL) ? -ENOSYS : ret; + return doioctl(node, VIDIOC_LOG_STATUS, NULL); } diff --git a/utils/v4l2-compliance/v4l2-test-formats.cpp b/utils/v4l2-compliance/v4l2-test-formats.cpp index db9245c..5b56a65 100644 --- a/utils/v4l2-compliance/v4l2-test-formats.cpp +++ b/utils/v4l2-compliance/v4l2-test-formats.cpp @@ -63,10 +63,12 @@ static int testEnumFrameIntervals(struct node *node, __u32 pixfmt, __u32 w, __u3 frmival.height = h; ret = doioctl(node, VIDIOC_ENUM_FRAMEINTERVALS, &frmival); + if (ret == ENOTTY) + return ret; if (f == 0 && ret == EINVAL) { if (valid) warn("found framesize %dx%d, but no frame intervals\n", w, h); - return -ENOSYS; + return ENOTTY; } if (ret == EINVAL) break; @@ -130,8 +132,10 @@ static int testEnumFrameSizes(struct node *node, __u32 pixfmt) frmsize.pixel_format = pixfmt; ret = doioctl(node, VIDIOC_ENUM_FRAMESIZES, &frmsize); + if (ret == ENOTTY) + return ret; if (f == 0 && ret == EINVAL) - return -ENOSYS; + return fail("got EINVAL enumerating first framesize\n"); if (ret == EINVAL) break; if (ret) @@ -149,11 +153,11 @@ static int testEnumFrameSizes(struct node *node, __u32 pixfmt) return fail("mixing discrete and stepwise is not allowed\n"); ret = testEnumFrameIntervals(node, pixfmt, frmsize.discrete.width, frmsize.discrete.height, true); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; ret = testEnumFrameIntervals(node, pixfmt, frmsize.discrete.width + 1, frmsize.discrete.height, false); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: @@ -173,19 +177,19 @@ static int testEnumFrameSizes(struct node *node, __u32 pixfmt) return fail("step > max - min for width or height\n"); ret = testEnumFrameIntervals(node, pixfmt, sw->min_width, sw->min_height, true); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; ret = testEnumFrameIntervals(node, pixfmt, sw->max_width, sw->max_height, true); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; ret = testEnumFrameIntervals(node, pixfmt, sw->min_width - 1, sw->min_height, false); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; ret = testEnumFrameIntervals(node, pixfmt, sw->max_width, sw->max_height + 1, false); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; break; default: @@ -211,8 +215,10 @@ static int testEnumFormatsType(struct node *node, enum v4l2_buf_type type) fmtdesc.index = f; ret = doioctl(node, VIDIOC_ENUM_FMT, &fmtdesc); + if (ret == ENOTTY) + return ret; if (f == 0 && ret == EINVAL) - return -ENOSYS; + return ENOTTY; if (ret == EINVAL) break; if (ret) @@ -234,7 +240,7 @@ static int testEnumFormatsType(struct node *node, enum v4l2_buf_type type) if (fmtdesc.flags & ~(V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_EMULATED)) return fail("unknown flag %08x returned\n", fmtdesc.flags); ret = testEnumFrameSizes(node, fmtdesc.pixelformat); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; if (ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE))) return fail("found framesizes when no video capture is supported\n"); @@ -271,7 +277,7 @@ int testEnumFormats(struct node *node) for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) { ret = testEnumFormatsType(node, (enum v4l2_buf_type)type); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -279,7 +285,7 @@ int testEnumFormats(struct node *node) case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (ret < 0 && (node->caps & buftype2cap[type])) + if (ret && (node->caps & buftype2cap[type])) return fail("%s cap set, but no %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); if (!ret && !(node->caps & buftype2cap[type])) @@ -294,16 +300,16 @@ int testEnumFormats(struct node *node) } ret = testEnumFormatsType(node, V4L2_BUF_TYPE_PRIVATE); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; if (!ret) warn("Buffer type PRIVATE allowed!\n"); ret = testEnumFrameSizes(node, 0x20202020); - if (ret >= 0) + if (ret != ENOTTY) return fail("Accepted framesize for invalid format\n"); ret = testEnumFrameIntervals(node, 0x20202020, 640, 480, false); - if (ret >= 0) + if (ret != ENOTTY) return fail("Accepted frameinterval for invalid format\n"); return 0; } @@ -320,10 +326,10 @@ int testFBuf(struct node *node) fbuf.fmt.priv = 0; ret = doioctl(node, VIDIOC_G_FBUF, &fbuf); fail_on_test(ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); - fail_on_test(ret == EINVAL && (node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); - if (ret == EINVAL) - return -ENOSYS; - if (ret) + fail_on_test(ret == ENOTTY && (node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY))); + if (ret == ENOTTY) + return ret; + if (ret != EINVAL) return fail("expected EINVAL, but got %d when getting framebuffer format\n", ret); node->fbuf_caps = caps = fbuf.capability; flags = fbuf.flags; @@ -371,11 +377,15 @@ static int testFormatsType(struct node *node, enum v4l2_buf_type type) memset(&fmt, 0xff, sizeof(fmt)); fmt.type = type; ret = doioctl(node, VIDIOC_G_FMT, &fmt); + if (ret == ENOTTY) + return ret; if (ret == EINVAL) - return -ENOSYS; + return ENOTTY; if (ret) return fail("expected EINVAL, but got %d when getting format for buftype %d\n", ret, type); fail_on_test(fmt.type != type); + if (ret) + return 0; switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -474,7 +484,7 @@ int testFormats(struct node *node) for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) { ret = testFormatsType(node, (enum v4l2_buf_type)type); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; if (ret && (node->caps & buftype2cap[type])) return fail("%s cap set, but no %s formats defined\n", @@ -485,7 +495,7 @@ int testFormats(struct node *node) } ret = testFormatsType(node, V4L2_BUF_TYPE_PRIVATE); - if (ret > 0) + if (ret && ret != ENOTTY) return ret; if (!ret) warn("Buffer type PRIVATE allowed!\n"); @@ -504,18 +514,17 @@ static int testSlicedVBICapType(struct node *node, enum v4l2_buf_type type) memset(&cap.reserved, 0, sizeof(cap.reserved)); cap.type = type; ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap); - fail_on_test(check_0(cap.reserved, sizeof(cap.reserved))); - fail_on_test(cap.type != type); - fail_on_test(ret && ret != EINVAL && sliced_type); - if (ret == EINVAL) { + if (ret == ENOTTY) { fail_on_test(sliced_type && (node->caps & buftype2cap[type])); - if (node->caps & (V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT)) - return 0; - return -ENOSYS; + return ret; } + fail_on_test(check_0(cap.reserved, sizeof(cap.reserved))); + fail_on_test(cap.type != type); + fail_on_test(ret && ret != EINVAL); + fail_on_test(ret && sliced_type && (node->caps & buftype2cap[type])); + fail_on_test(!ret && (!sliced_type || !(node->caps & buftype2cap[type]))); if (ret) - return fail("expected EINVAL, but got %d when getting sliced VBI caps buftype %d\n", ret, type); - fail_on_test(!(node->caps & buftype2cap[type])); + return 0; for (int f = 0; f < 2; f++) for (int i = 0; i < 24; i++) diff --git a/utils/v4l2-compliance/v4l2-test-input-output.cpp b/utils/v4l2-compliance/v4l2-test-input-output.cpp index 31364fd..44d2253 100644 --- a/utils/v4l2-compliance/v4l2-test-input-output.cpp +++ b/utils/v4l2-compliance/v4l2-test-input-output.cpp @@ -125,8 +125,8 @@ int testTuner(struct node *node) memset(tuner.reserved, 0, sizeof(tuner.reserved)); tuner.index = t; ret = doioctl(node, VIDIOC_G_TUNER, &tuner); - if (ret == EINVAL && t == 0) - return -ENOSYS; + if (ret == ENOTTY) + return ret; if (ret == EINVAL) break; if (ret) @@ -224,16 +224,16 @@ int testTunerFreq(struct node *node) freq.tuner = t; ret = doioctl(node, VIDIOC_G_FREQUENCY, &freq); - if (ret != EINVAL) + if (ret != EINVAL && ret != ENOTTY) return fail("could get frequency for invalid tuner %d\n", t); freq.tuner = t; freq.type = last_type; // TV: 400 Mhz Radio: 100 MHz freq.frequency = last_type == V4L2_TUNER_ANALOG_TV ? 6400 : 1600000; ret = doioctl(node, VIDIOC_S_FREQUENCY, &freq); - if (ret != EINVAL) + if (ret != EINVAL && ret != ENOTTY) return fail("could set frequency for invalid tuner %d\n", t); - return node->tuners ? 0 : -ENOSYS; + return node->tuners ? 0 : ENOTTY; } static int checkInput(struct node *node, const struct v4l2_input &descr, unsigned i) @@ -275,16 +275,16 @@ int testInput(struct node *node) int ret = doioctl(node, VIDIOC_G_INPUT, &cur_input); int i = 0; - if (ret == EINVAL) { + if (ret == ENOTTY) { descr.index = 0; ret = doioctl(node, VIDIOC_ENUMINPUT, &descr); - if (ret != EINVAL) + if (ret != ENOTTY) return fail("G_INPUT not supported, but ENUMINPUT is\n"); cur_input = 0; ret = doioctl(node, VIDIOC_S_INPUT, &cur_input); - if (ret != EINVAL) + if (ret != ENOTTY) return fail("G_INPUT not supported, but S_INPUT is\n"); - return -ENOSYS; + return ENOTTY; } if (ret) return fail("could not get current input\n"); @@ -350,8 +350,8 @@ int testEnumInputAudio(struct node *node) input.index = i; ret = doioctl(node, VIDIOC_ENUMAUDIO, &input); - if (i == 0 && ret == EINVAL) - return -ENOSYS; + if (ret == ENOTTY) + return ret; if (ret == EINVAL) break; if (ret) @@ -373,8 +373,8 @@ static int checkInputAudioSet(struct node *node, __u32 audioset) int ret; ret = doioctl(node, VIDIOC_G_AUDIO, &input); - if (audioset == 0 && ret != EINVAL) - return fail("No audio inputs, but G_AUDIO did not return EINVAL\n"); + if (audioset == 0 && ret != ENOTTY && ret != EINVAL) + return fail("No audio inputs, but G_AUDIO did not return ENOTTY or EINVAL\n"); if (audioset) { if (ret) return fail("Audio inputs, but G_AUDIO returned an error\n"); @@ -392,7 +392,7 @@ static int checkInputAudioSet(struct node *node, __u32 audioset) input.index = i; input.mode = 0; ret = doioctl(node, VIDIOC_S_AUDIO, &input); - if (!valid && ret != EINVAL) + if (!valid && ret != EINVAL && ret != ENOTTY) return fail("can set invalid audio input %d\n", i); if (valid && ret) return fail("can't set valid audio input %d\n", i); @@ -420,7 +420,7 @@ int testInputAudio(struct node *node) if (checkInputAudioSet(node, vinput.audioset)) return fail("invalid audioset for input %d\n", i); } - return node->audio_inputs ? 0 : -ENOSYS; + return node->audio_inputs ? 0 : ENOTTY; } static int checkModulator(struct node *node, const struct v4l2_modulator &mod, unsigned m) @@ -471,8 +471,8 @@ int testModulator(struct node *node) memset(mod.reserved, 0, sizeof(mod.reserved)); mod.index = m; ret = doioctl(node, VIDIOC_G_MODULATOR, &mod); - if (ret == EINVAL && m == 0) - return -ENOSYS; + if (ret == ENOTTY) + return ret; if (ret == EINVAL) break; if (ret) @@ -559,15 +559,15 @@ int testModulatorFreq(struct node *node) freq.tuner = m; ret = doioctl(node, VIDIOC_G_FREQUENCY, &freq); - if (ret != EINVAL) + if (ret != EINVAL && ret != ENOTTY) return fail("could get frequency for invalid modulator %d\n", m); freq.tuner = m; // Radio: 100 MHz freq.frequency = 1600000; ret = doioctl(node, VIDIOC_S_FREQUENCY, &freq); - if (ret != EINVAL) + if (ret != EINVAL && ret != ENOTTY) return fail("could set frequency for invalid modulator %d\n", m); - return node->modulators ? 0 : -ENOSYS; + return node->modulators ? 0 : ENOTTY; } static int checkOutput(struct node *node, const struct v4l2_output &descr, unsigned o) @@ -605,16 +605,15 @@ int testOutput(struct node *node) int ret = doioctl(node, VIDIOC_G_OUTPUT, &cur_output); int o = 0; - if (ret == EINVAL) { + if (ret == ENOTTY) { descr.index = 0; ret = doioctl(node, VIDIOC_ENUMOUTPUT, &descr); - if (ret != EINVAL) + if (ret != ENOTTY) return fail("G_OUTPUT not supported, but ENUMOUTPUT is\n"); output = 0; ret = doioctl(node, VIDIOC_S_OUTPUT, &output); - if (ret != EINVAL) + if (ret != ENOTTY) return fail("G_OUTPUT not supported, but S_OUTPUT is\n"); - return -ENOSYS; } if (ret) return ret; @@ -674,8 +673,8 @@ int testEnumOutputAudio(struct node *node) output.index = o; ret = doioctl(node, VIDIOC_ENUMAUDOUT, &output); - if (o == 0 && ret == EINVAL) - return -ENOSYS; + if (ret == ENOTTY) + return ENOTTY; if (ret == EINVAL) break; if (ret) @@ -698,8 +697,8 @@ static int checkOutputAudioSet(struct node *node, __u32 audioset) int ret; ret = doioctl(node, VIDIOC_G_AUDOUT, &output); - if (audioset == 0 && ret != EINVAL) - return fail("No audio outputs, but G_AUDOUT did not return EINVAL\n"); + if (audioset == 0 && ret != EINVAL && ret != ENOTTY) + return fail("No audio outputs, but G_AUDOUT did not return EINVAL or ENOTTY\n"); if (audioset) { if (ret) return fail("Audio outputs, but G_AUDOUT returned an error\n"); @@ -717,7 +716,7 @@ static int checkOutputAudioSet(struct node *node, __u32 audioset) output.index = i; output.mode = 0; ret = doioctl(node, VIDIOC_S_AUDOUT, &output); - if (!valid && ret != EINVAL) + if (!valid && ret != EINVAL && ret != ENOTTY) return fail("can set invalid audio output %d\n", i); if (valid && ret) return fail("can't set valid audio output %d\n", i); @@ -748,5 +747,5 @@ int testOutputAudio(struct node *node) if (node->audio_outputs == 0 && node->audio_inputs && (caps & V4L2_CAP_AUDIO)) return fail("no audio inputs or outputs reported, but CAP_AUDIO set\n"); - return node->audio_outputs ? 0 : -ENOSYS; + return node->audio_outputs ? 0 : ENOTTY; } diff --git a/utils/v4l2-compliance/v4l2-test-io-config.cpp b/utils/v4l2-compliance/v4l2-test-io-config.cpp index d2e89c3..35a17ef 100644 --- a/utils/v4l2-compliance/v4l2-test-io-config.cpp +++ b/utils/v4l2-compliance/v4l2-test-io-config.cpp @@ -136,7 +136,7 @@ int testStd(struct node *node) if (checkStd(node, output.capabilities & V4L2_OUT_CAP_STD, output.std)) return fail("STD failed for output %d.\n", o); } - return has_std ? 0 : -ENOSYS; + return has_std ? 0 : ENOTTY; } static int checkPresets(struct node *node, bool has_presets) @@ -163,7 +163,7 @@ static int checkPresets(struct node *node, bool has_presets) } preset.preset = V4L2_DV_INVALID; ret = doioctl(node, VIDIOC_S_DV_PRESET, &preset); - if (ret != EINVAL) + if (ret != EINVAL && ret != ENOTTY) return fail("could set preset V4L2_DV_INVALID\n"); for (i = 0; ; i++) { @@ -231,7 +231,7 @@ int testPresets(struct node *node) if (checkPresets(node, output.capabilities & V4L2_OUT_CAP_PRESETS)) return fail("Presets check failed for output %d.\n", o); } - return has_presets ? 0 : -ENOSYS; + return has_presets ? 0 : ENOTTY; } static int checkTimings(struct node *node, bool has_timings) @@ -290,5 +290,5 @@ int testCustomTimings(struct node *node) if (checkTimings(node, output.capabilities & V4L2_OUT_CAP_CUSTOM_TIMINGS)) return fail("Custom timings check failed for output %d.\n", o); } - return has_timings ? 0 : -ENOSYS; + return has_timings ? 0 : ENOTTY; } -- 2.7.4