aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2021-01-18 16:17:11 +0100
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2021-01-18 16:17:11 +0100
commit3abb9556eff581e3ba424972cc54a40611ead80b (patch)
tree3a2927a19173cd91e395af589e75df49893b0e47
parentfc89f67d9fe0cd9092d0609ffcc363508d544e50 (diff)
v4l2-compliance: add support for VIDIOC_SUBDEV_QUERYCAP
This ioctl was introduce some time ago, but support for this was never added to v4l2-compliance. Fix this. In particular add checks for read-only subdevices. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.cpp21
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.h2
-rw-r--r--utils/v4l2-compliance/v4l2-test-subdevs.cpp29
3 files changed, 47 insertions, 5 deletions
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index 9e7b14c7..3191e9c0 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -940,7 +940,8 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
unsigned frame_count, unsigned all_fmt_frame_count)
{
struct node node2;
- struct v4l2_capability vcap; /* list_cap */
+ struct v4l2_capability vcap = {};
+ struct v4l2_subdev_capability subdevcap = {};
std::string driver;
tests_total = tests_ok = warnings = 0;
@@ -958,6 +959,8 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
if (is_vivid)
node.bus_info = reinterpret_cast<const char *>(vcap.bus_info);
determine_codec_mask(node);
+ } else if (node.is_subdev()) {
+ doioctl(&node, VIDIOC_SUBDEV_QUERYCAP, &subdevcap);
} else {
memset(&vcap, 0, sizeof(vcap));
}
@@ -1038,6 +1041,9 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
printf("\tDetected Stateless Decoder\n");
break;
}
+ } else if (node.is_subdev()) {
+ printf("Driver Info:\n");
+ v4l2_info_subdev_capability(subdevcap);
}
__u32 ent_id = 0;
@@ -1076,10 +1082,16 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
if (node.is_v4l2())
printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&node)));
+ else if (node.is_subdev())
+ printf("\ttest VIDIOC_SUDBEV_QUERYCAP: %s\n", ok(testSubDevCap(&node)));
+
+ if (node.is_v4l2() || node.is_subdev())
+ printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, 'V')));
if (node.is_media()) {
printf("\ttest MEDIA_IOC_DEVICE_INFO: %s\n",
ok(testMediaDeviceInfo(&node)));
+ printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, '|')));
}
printf("\n");
@@ -1091,6 +1103,8 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
case MEDIA_TYPE_SUBDEV:
printf("\ttest second %s open: %s\n", node.device,
ok(node2.subdev_open(node.device, false) >= 0 ? 0 : errno));
+ if (node2.g_fd() >= 0)
+ printf("\ttest VIDIOC_SUBDEV_QUERYCAP: %s\n", ok(testSubDevCap(&node2)));
break;
case MEDIA_TYPE_MEDIA:
printf("\ttest second %s open: %s\n", node.device,
@@ -1113,8 +1127,8 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
printf("\ttest for unlimited opens: %s\n",
ok(testUnlimitedOpens(&node)));
- printf("\n");
+ printf("\n");
storeState(&node);
/* register signal handler for interrupt signal, to exit gracefully */
@@ -1137,13 +1151,10 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
node.topology->num_links);
printf("\ttest MEDIA_IOC_ENUM_ENTITIES/LINKS: %s\n", ok(testMediaEnum(&node)));
printf("\ttest MEDIA_IOC_SETUP_LINK: %s\n", ok(testMediaSetupLink(&node)));
- printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, '|')));
printf("\n");
goto show_total;
}
- printf("\ttest invalid ioctls: %s\n", ok(testInvalidIoctls(&node, 'V')));
-
/* Debug ioctls */
printf("Debug ioctls:\n");
diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
index 5fe3be8a..4d5c3a5c 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -97,6 +97,7 @@ struct base_node {
bool is_m2m;
bool is_io_mc;
bool is_planar;
+ bool is_ro_subdev;
bool can_capture;
bool can_output;
bool can_scale;
@@ -335,6 +336,7 @@ int testEncIndex(struct node *node);
int testDecoder(struct node *node);
// SubDev ioctl tests
+int testSubDevCap(struct node *node);
int testSubDevEnum(struct node *node, unsigned which, unsigned pad);
int testSubDevFormat(struct node *node, unsigned which, unsigned pad);
int testSubDevSelection(struct node *node, unsigned which, unsigned pad);
diff --git a/utils/v4l2-compliance/v4l2-test-subdevs.cpp b/utils/v4l2-compliance/v4l2-test-subdevs.cpp
index ec3ef169..68f97205 100644
--- a/utils/v4l2-compliance/v4l2-test-subdevs.cpp
+++ b/utils/v4l2-compliance/v4l2-test-subdevs.cpp
@@ -25,6 +25,23 @@
#include "v4l2-compliance.h"
+#define VALID_SUBDEV_CAPS (V4L2_SUBDEV_CAP_RO_SUBDEV)
+
+int testSubDevCap(struct node *node)
+{
+ v4l2_subdev_capability caps;
+
+ memset(&caps, 0xff, sizeof(caps));
+ // Must always be there
+ fail_on_test(doioctl(node, VIDIOC_SUBDEV_QUERYCAP, nullptr) != EFAULT);
+ fail_on_test(doioctl(node, VIDIOC_SUBDEV_QUERYCAP, &caps));
+ fail_on_test(check_0(caps.reserved, sizeof(caps.reserved)));
+ fail_on_test((caps.version >> 16) < 5);
+ fail_on_test(caps.capabilities & ~VALID_SUBDEV_CAPS);
+ node->is_ro_subdev = caps.capabilities & V4L2_SUBDEV_CAP_RO_SUBDEV;
+ return 0;
+}
+
static int testSubDevEnumFrameInterval(struct node *node, unsigned which,
unsigned pad, unsigned code,
unsigned width, unsigned height)
@@ -266,6 +283,10 @@ int testSubDevFrameInterval(struct node *node, unsigned pad)
fail_on_test(fival.interval.numerator == ~0U || fival.interval.denominator == ~0U);
ival = fival.interval;
memset(fival.reserved, 0xff, sizeof(fival.reserved));
+ if (node->is_ro_subdev) {
+ fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival) != EPERM);
+ return 0;
+ }
fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival));
fail_on_test(fival.pad != pad);
fail_on_test(ival.numerator != fival.interval.numerator);
@@ -350,6 +371,10 @@ int testSubDevFormat(struct node *node, unsigned which, unsigned pad)
memset(s_fmt.reserved, 0xff, sizeof(s_fmt.reserved));
memset(s_fmt.format.reserved, 0xff, sizeof(s_fmt.format.reserved));
ret = doioctl(node, VIDIOC_SUBDEV_S_FMT, &s_fmt);
+ if (node->is_ro_subdev && which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ fail_on_test(ret != EPERM);
+ return 0;
+ }
fail_on_test(ret && ret != ENOTTY);
fail_on_test(s_fmt.which != which);
fail_on_test(s_fmt.pad != pad);
@@ -460,6 +485,8 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
s_sel = sel;
memset(s_sel.reserved, 0xff, sizeof(s_sel.reserved));
ret = doioctl(node, VIDIOC_SUBDEV_S_SELECTION, &s_sel);
+ if (node->is_ro_subdev && which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ fail_on_test(ret != EPERM);
if (tgt == V4L2_SEL_TGT_CROP) {
crop.rect = sel.r;
memset(crop.reserved, 0xff, sizeof(crop.reserved));
@@ -471,6 +498,8 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
fail_on_test(memcmp(&crop.rect, &sel.r, sizeof(sel.r)));
}
}
+ if (node->is_ro_subdev && which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ continue;
fail_on_test(!ret && targets[tgt].readonly);
fail_on_test(s_sel.which != which);
fail_on_test(s_sel.pad != pad);

Privacy Policy