On 07/06/2023 13:48, Hans Verkuil wrote: > On 07/06/2023 13:35, Hans Verkuil wrote: >> On 29/05/2023 10:50, Tomi Valkeinen wrote: >>> Add a very simple test for >>> VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING. >>> >>> We can't (at least at the moment) really know here what kind of routings >>> the driver would accept, but we can test a VIDIOC_SUBDEV_G_ROUTING call, >>> followed by a VIDIOC_SUBDEV_S_ROUTING call with the routing we >>> received. >>> >>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxxxxxxxxx> >>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx> >>> --- >>> utils/v4l2-compliance/v4l2-compliance.cpp | 12 ++++++++++++ >>> utils/v4l2-compliance/v4l2-compliance.h | 1 + >>> utils/v4l2-compliance/v4l2-test-subdevs.cpp | 16 ++++++++++++++++ >>> 3 files changed, 29 insertions(+) >>> >>> diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp >>> index d7c10482..f082f569 100644 >>> --- a/utils/v4l2-compliance/v4l2-compliance.cpp >>> +++ b/utils/v4l2-compliance/v4l2-compliance.cpp >>> @@ -1249,6 +1249,18 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_ >>> node.is_passthrough_subdev = has_source && has_sink; >>> >>> if (has_routes) { >>> + printf("Sub-Device routing ioctls:\n"); >>> + >>> + for (unsigned which = V4L2_SUBDEV_FORMAT_TRY; >>> + which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) { >>> + >>> + printf("\ttest %s VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: %s\n", >>> + which ? "Active" : "Try", >>> + ok(testSubDevRouting(&node, which))); >>> + } >>> + >>> + printf("\n"); >>> + >>> for (unsigned which = V4L2_SUBDEV_FORMAT_TRY; >>> which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) { >>> >>> diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h >>> index 0cd43980..35b2274b 100644 >>> --- a/utils/v4l2-compliance/v4l2-compliance.h >>> +++ b/utils/v4l2-compliance/v4l2-compliance.h >>> @@ -375,6 +375,7 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad, unsigned str >>> int testSubDevFormat(struct node *node, unsigned which, unsigned pad, unsigned stream); >>> int testSubDevSelection(struct node *node, unsigned which, unsigned pad, unsigned stream); >>> int testSubDevFrameInterval(struct node *node, unsigned pad, unsigned stream); >>> +int testSubDevRouting(struct node *node, unsigned which); >>> >>> // Buffer ioctl tests >>> int testReqBufs(struct node *node); >>> diff --git a/utils/v4l2-compliance/v4l2-test-subdevs.cpp b/utils/v4l2-compliance/v4l2-test-subdevs.cpp >>> index 07192bda..962d9244 100644 >>> --- a/utils/v4l2-compliance/v4l2-test-subdevs.cpp >>> +++ b/utils/v4l2-compliance/v4l2-test-subdevs.cpp >>> @@ -551,3 +551,19 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad, unsigne >>> >>> return have_sel ? 0 : ENOTTY; >>> } >>> + >>> +int testSubDevRouting(struct node *node, unsigned which) >>> +{ >>> + struct v4l2_subdev_routing routing = {}; >>> + struct v4l2_subdev_route routes[256] = {}; >> >> NUM_ROUTES_MAX >> >>> + >>> + routing.which = which; >>> + routing.routes = (__u64)&routes; >>> + routing.num_routes = 256; >> >> NUM_ROUTES_MAX > > Actually, you should also test the corner cases of NUM_ROUTES_MAX + 1 > (that should fail, right?) and setting num_routes to 0 and check that > ENOSPC is returned and num_routes is updated. > > Also verify that 'reserved' is zeroed (i.e. set it to 0xff here, then > check for 0 after the ioctl). I assume also that if num_routes is set to 256, then G_ROUTING is called, num_routes is updated to the actual number of routes? The spec does not actually state that. And what should happen when num_routes is set to 0 and S_ROUTING is called? Would that clear all routes? Or is that an error? And can G_ROUTING actually return num_routes == 0 as well if there are no routes defined? Additional checks you can do is to verify that all sink/source pads are valid and that 'flags' is valid. Another test is setting a pad or stream to an invalid value and verify that EINVAL is returned. Note that the spec says that E2BIG is returned for S_ROUTING, but it is returned for G_ROUTING as well, that should be updated. Regards, Hans > > Regards, > > Hans > >> >> Regards, >> >> Hans >> >>> + >>> + fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_ROUTING, &routing)); >>> + >>> + fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_ROUTING, &routing)); >>> + >>> + return 0; >>> +} >> >