All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Hans Verkuil <hverkuil+cisco@kernel.org>
Cc: linux-media@vger.kernel.org
Subject: Re: v4l2-compliance does not pick media device with -z and -u options
Date: Mon, 29 Jun 2026 16:15:55 +0300	[thread overview]
Message-ID: <20260629131555.GF3054459@killaraus.ideasonboard.com> (raw)
In-Reply-To: <160a57b9-9c06-43de-bab9-9e3d05656b1f@kernel.org>

Hi Hans,

On Thu, Jun 18, 2026 at 09:03:44AM +0200, Hans Verkuil wrote:
> Hi Laurent,
> 
> Here is a second attempt to fix this. Let me know if it works!
> 
> The reason is it so messy is that support for the media device and
> media bus info was added much later, and it really needs a cleanup.

I can't disagree :-) There are lots of opportunities to refactor the
code into classes with clear APIs.

> Anyway, fingers crossed...

It works better \o/

----------------------------------------
root@buildroot ~ # v4l2-compliance -z "platform:rkisp1" -u "imx219 1-0010"
v4l2-compliance 1.33.0-5476, 64 bits, 64-bit time_t
v4l2-compliance SHA: 1355f143676b 2026-06-18 06:31:21

Compliance test for rkisp1 device /dev/v4l-subdev3:

Driver Info:
        Driver version   : 7.1.0
        Capabilities     : 0x00000000
        Client Capabilities: 0x0000000000000003
streams interval-uses-which Media Driver Info:
        Driver name      : rkisp1
        Model            : rkisp1
        Serial           :
        Bus info         : platform:rkisp1
        Media version    : 7.1.0
        Hardware revision: 0x0000000e (14)
        Driver version   : 7.1.0
Interface Info:
        ID               : 0x0300002c
        Type             : V4L Sub-Device
Entity Info:
        ID               : 0x00000022 (34)
        Name             : imx219 1-0010
        Function         : Camera Sensor
        Pad 0x01000023   : 0: Source
          Link 0x02000024: to remote pad 0x100001e of entity 'csis-32e40000.csi' (Video Interface Bridge): Data

Required ioctls:
        test MC information (see 'Media Driver Info' above): OK
        test VIDIOC_SUDBEV_QUERYCAP: OK
        test invalid ioctls: OK

Allow for multiple opens:
        test second /dev/v4l-subdev3 open: OK
        test VIDIOC_SUBDEV_QUERYCAP: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Sub-Device ioctls (Source Pad 0):
        Try Stream 0
        test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
        test Try VIDIOC_SUBDEV_G/S_FMT: OK
                warn: v4l2-test-subdevs.cpp(566): VIDIOC_SUBDEV_G_SELECTION is supported for target 0 but not VIDIOC_SUBDEV_S_SELECTION
        test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
        Active Stream 0
        test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
        test Active VIDIOC_SUBDEV_G/S_FMT: OK
                warn: v4l2-test-subdevs.cpp(566): VIDIOC_SUBDEV_G_SELECTION is supported for target 0 but not VIDIOC_SUBDEV_S_SELECTION
        test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
        test Active VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)

Control ioctls:
        test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
        test VIDIOC_QUERYCTRL: OK
        test VIDIOC_G/S_CTRL: OK
        test VIDIOC_G/S/TRY_EXT_CTRLS: OK
        test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
        test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
        Standard Controls: 20 Private Controls: 0

Format ioctls:
        test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
        test VIDIOC_G/S_PARM: OK (Not Supported)
        test VIDIOC_G_FBUF: OK (Not Supported)
        test VIDIOC_G_FMT: OK (Not Supported)
        test VIDIOC_TRY_FMT: OK (Not Supported)
        test VIDIOC_S_FMT: OK (Not Supported)
        test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
        test Cropping: OK (Not Supported)
        test Composing: OK (Not Supported)
        test Scaling: OK (Not Supported)

Codec ioctls:
        test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
        test VIDIOC_G_ENC_INDEX: OK (Not Supported)
        test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

Buffer ioctls:
        test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
        test CREATE_BUFS maximum buffers: OK
        test VIDIOC_REMOVE_BUFS: OK
        test VIDIOC_EXPBUF: OK (Not Supported)
        test Requests: OK (Not Supported)
        test blocking wait: OK (Not Supported)

Total for rkisp1 device /dev/v4l-subdev3: 54, Succeeded: 54, Failed: 0, Warnings: 2
----------------------------------------

I think we should skip quite a few of the bove tests for subdevs (the
"Format ioctls" and "Buffer ioctls" tests for instance), but that's a
separate issue.

Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> diff --git a/utils/common/media-info.cpp b/utils/common/media-info.cpp
> index 95e4c74f..6d6d7904 100644
> --- a/utils/common/media-info.cpp
> +++ b/utils/common/media-info.cpp
> @@ -216,7 +216,7 @@ std::string mi_get_devpath_from_dev_t(dev_t dev)
>  	return devpath;
>  }
> 
> -int mi_get_media_fd(int fd, const char *bus_info)
> +int mi_get_media_fd(int fd)
>  {
>  	int media_fd = -1;
>  	dev_t dev;
> @@ -243,9 +243,39 @@ int mi_get_media_fd(int fd, const char *bus_info)
>  			devname += ep->d_name;
>  			media_fd = open(devname.c_str(), O_RDWR);
> 
> -			if (bus_info &&
> -			    (ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo) ||
> -			     strcmp(mdinfo.bus_info, bus_info))) {
> +			if (ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo)) {
> +				close(media_fd);
> +				continue;
> +			}
> +			break;
> +		}
> +	}
> +	closedir(dp);
> +	return media_fd;
> +}
> +
> +int mi_get_media_bus_info(const char *bus_info)
> +{
> +	int media_fd = -1;
> +	DIR *dp;
> +	struct dirent *ep;
> +
> +	if (!bus_info)
> +		return -1;
> +
> +	dp = opendir("/dev");
> +	if (dp == nullptr)
> +		return -1;
> +	while ((ep = readdir(dp))) {
> +		if (!memcmp(ep->d_name, "media", 5) && isdigit(ep->d_name[5])) {
> +			struct media_device_info mdinfo;
> +			std::string devname("/dev/");
> +
> +			devname += ep->d_name;
> +			media_fd = open(devname.c_str(), O_RDWR);
> +
> +			if (ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo) ||
> +			    strcmp(mdinfo.bus_info, bus_info)) {
>  				close(media_fd);
>  				continue;
>  			}
> diff --git a/utils/common/media-info.h b/utils/common/media-info.h
> index c0dd6304..75eb29b4 100644
> --- a/utils/common/media-info.h
> +++ b/utils/common/media-info.h
> @@ -51,12 +51,15 @@ std::string mi_get_devpath_from_dev_t(dev_t dev);
> 
>  /*
>   * For a given device fd return the corresponding media device
> - * or -1 if there is none.
> - *
> - * If bus_info is not NULL, then find the media device that
> - * matches the given bus_info.
> + * or -1 if there is none. This only works if the media device
> + * is discoverable from where fd sits in /sys.
>   */
> -int mi_get_media_fd(int fd, const char *bus_info = NULL);
> +int mi_get_media_fd(int fd);
> +
> +/*
> + * Find the media device that matches the given bus_info.
> + */
> +int mi_get_media_bus_info(const char *bus_info);
> 
>  /* Return entity flags description */
>  std::string mi_entflags2s(__u32 flags);
> diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
> index 4e5c9d00..a04e4e84 100644
> --- a/utils/v4l2-compliance/v4l2-compliance.cpp
> +++ b/utils/v4l2-compliance/v4l2-compliance.cpp
> @@ -1007,7 +1007,7 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
>  		if (parent_media_fd >= 0)
>  			media_fd = parent_media_fd;
>  		else
> -			media_fd = mi_get_media_fd(node.g_fd(), node.bus_info);
> +			media_fd = mi_get_media_bus_info(node.bus_info);
>  	}
> 
>  	int fd = node.is_media() ? node.g_fd() : media_fd;
> @@ -1658,6 +1658,7 @@ int main(int argc, char **argv)
>  	media_type type = MEDIA_TYPE_UNKNOWN;
>  	struct node expbuf_node;
>  	std::string media_bus_info;
> +	int media_fd = -1;
>  	const char *env_media_apps_color = getenv("MEDIA_APPS_COLOR");
> 
>  	/* command args */
> @@ -1903,6 +1904,16 @@ int main(int argc, char **argv)
>  			strerror(errno));
>  		std::exit(EXIT_FAILURE);
>  	}
> +	if (type != MEDIA_TYPE_MEDIA && !media_bus_info.empty()) {
> +		std::string media_devname;
> +
> +		media_fd = open_media_bus_info(media_bus_info, media_devname);
> +		if (media_fd < 0) {
> +			fprintf(stderr, "Failed to find media device for %s: %s\n",
> +				media_bus_info.c_str(), strerror(errno));
> +			std::exit(EXIT_FAILURE);
> +		}
> +	}
> 
>  	if (!expbuf_device.empty()) {
>  		expbuf_node.s_trace(options[OptTrace]);
> @@ -1915,7 +1926,7 @@ int main(int argc, char **argv)
>  		}
>  	}
> 
> -	testNode(node, node, expbuf_node, type, frame_count, all_fmt_frame_count);
> +	testNode(node, node, expbuf_node, type, frame_count, all_fmt_frame_count, media_fd);
> 
>  	if (!expbuf_device.empty())
>  		expbuf_node.close();
> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
> index 7e08668b..233cf03f 100644
> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
> @@ -2296,7 +2296,7 @@ int testDmaBuf(struct node *expbuf_node, struct node *node, struct node *node_m2
>  int testRequests(struct node *node, bool test_streaming)
>  {
>  	filehandles fhs;
> -	int media_fd = fhs.add(mi_get_media_fd(node->g_fd(), node->bus_info));
> +	int media_fd = fhs.add(mi_get_media_bus_info(node->bus_info));
>  	int req_fd;
>  	struct test_query_ext_ctrl valid_qctrl;
>  	v4l2_ext_controls ctrls;
> @@ -2432,7 +2432,7 @@ int testRequests(struct node *node, bool test_streaming)
>  	fail_on_test(doioctl_fd(req_fd, MEDIA_REQUEST_IOC_REINIT, nullptr) != EBADF);
> 
>  	// Open media_fd and alloc a request again
> -	media_fd = fhs.add(mi_get_media_fd(node->g_fd(), node->bus_info));
> +	media_fd = fhs.add(mi_get_media_bus_info(node->bus_info));
>  	fail_on_test(doioctl_fd(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd));
>  	fhs.add(req_fd);
>  	ctrls.count = 1;
> @@ -2507,7 +2507,7 @@ int testRequests(struct node *node, bool test_streaming)
>  	unsigned num_requests = 2 * num_bufs;
>  	last_seq.init();
> 
> -	media_fd = fhs.add(mi_get_media_fd(node->g_fd(), node->bus_info));
> +	media_fd = fhs.add(mi_get_media_bus_info(node->bus_info));
> 
>  	// Allocate the requests
>  	for (unsigned i = 0; i < num_requests; i++) {
> diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> index 517fc7f2..fe5d0dfe 100644
> --- a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> +++ b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> @@ -1346,10 +1346,10 @@ static int do_setup_out_buffers(cv4l_fd &fd, cv4l_queue &q, FILE *fin, bool qbuf
>  		if (fmt.g_pixelformat() == V4L2_PIX_FMT_FWHT_STATELESS) {
>  			struct v4l2_capability vcap = {};
>  			fd.querycap(vcap);
> -			int media_fd = mi_get_media_fd(fd.g_fd(), (const char *)vcap.bus_info);
> +			int media_fd = mi_get_media_bus_info((const char *)vcap.bus_info);
> 
>  			if (media_fd < 0) {
> -				fprintf(stderr, "%s: mi_get_media_fd failed\n", __func__);
> +				fprintf(stderr, "%s: mi_get_media_bus_info failed\n", __func__);
>  				return media_fd;
>  			}
> 
> diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
> index 842e22fd..14f5c51f 100644
> --- a/utils/v4l2-ctl/v4l2-ctl.cpp
> +++ b/utils/v4l2-ctl/v4l2-ctl.cpp
> @@ -1382,7 +1382,10 @@ int main(int argc, char **argv)
>  			capabilities = vcap.device_caps;
>  	}
> 
> -	media_fd = mi_get_media_fd(fd, is_subdev ? 0 : (const char *)vcap.bus_info);
> +	if (is_subdev)
> +		media_fd = mi_get_media_fd(fd);

This won't work correctly on subdevs that are not direct children of the
device registering the media device, but it's fine, it's not a
regression. media_fd is only used to print the media info anyway, it
won't prevent anything else from working.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +	else
> +		media_fd = mi_get_media_bus_info((const char *)vcap.bus_info);
> 
>  	priv_magic = (capabilities & V4L2_CAP_EXT_PIX_FORMAT) ?
>  			V4L2_PIX_FMT_PRIV_MAGIC : 0;
> 

-- 
Regards,

Laurent Pinchart

      reply	other threads:[~2026-06-29 13:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-10 11:33 v4l2-compliance does not pick media device with -z and -u options Laurent Pinchart
2026-06-12 11:37 ` Hans Verkuil
2026-06-12 15:16   ` Laurent Pinchart
2026-06-18  7:03     ` Hans Verkuil
2026-06-29 13:15       ` Laurent Pinchart [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260629131555.GF3054459@killaraus.ideasonboard.com \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=hverkuil+cisco@kernel.org \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.