* v4l2-compliance does not pick media device with -z and -u options
@ 2026-06-10 11:33 Laurent Pinchart
2026-06-12 11:37 ` Hans Verkuil
0 siblings, 1 reply; 5+ messages in thread
From: Laurent Pinchart @ 2026-06-10 11:33 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media
Hi Hans,
I've noticed yesterday that v4l2-compliance does not pick a media device
when run on a subdev with the -z and -u options.
The options are documented as
-u, --subdev-device <dev>
Use device <dev> as the v4l-subdev device.
If <dev> starts with a digit, then /dev/v4l-subdev<dev> is used.
[...]
Otherwise if -z was specified earlier, then <dev> is the entity name
or interface ID (if prefixed with 0x) as found in the topology of the
media device with the bus info string as specified by the -z option.
-z, --media-bus-info <bus-info>
Find the media device with the given bus info string. If set, then
the options above can use the entity name or interface ID to refer
to the device nodes.
I reproduced the issue on an i.MX8MP and a Raspberry Pi 5. On i.MX8MP, I
ran
$ v4l2-compliance -z "platform:rkisp1" -u "imx219 1-0010"
where "imx219 1-0010" is the sensor entity in the ISP media graph. This
resulted in the following output:
--------
v4l2-compliance 1.33.0-5474, 64 bits, 64-bit time_t
v4l2-compliance SHA: 73e05fa3c79b 2026-06-02 06:15:45
Compliance test for device /dev/v4l-subdev3:
Driver Info:
Driver version : 7.1.0
Capabilities : 0x00000000
Client Capabilities: 0x0000000000000003
streams interval-uses-which media_fd 4294967295 ent_id 0x00000000
Required ioctls:
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)
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 device /dev/v4l-subdev3: 46, Succeeded: 46, Failed: 0, Warnings: 0
--------
v4l2-compliance skipped pad-based ioctl tests, because it was unable to
count the number of pad of the entity. The root cause if
mi_get_media_fd() returning -1 in testNode(), because
/sys/dev/char/81:9/device/ does not contain any entry whose name starts
with "media".
I couldn't reproduce the issue with vimc running
$ v4l2-compliance -z platform:vimc.0 -u "Sensor A"
so I investigated further, and realized there's a major difference: the
"Sensor A" entity in vimc is created by the vimc driver that registers
the media device, while the sensor entity in the rkisp1 media graph is
created by a sensor driver.
Finding the media device through sysfs isn't guaranteed to work. We can
keep doing so as a last resort option when no -z option is specified,
but we should use the media device found by open_media_bus_info() when
running with -z.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: v4l2-compliance does not pick media device with -z and -u options
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
0 siblings, 1 reply; 5+ messages in thread
From: Hans Verkuil @ 2026-06-12 11:37 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linux-media
On 10/06/2026 13:33, Laurent Pinchart wrote:
> Hi Hans,
>
> I've noticed yesterday that v4l2-compliance does not pick a media device
> when run on a subdev with the -z and -u options.
>
> The options are documented as
>
> -u, --subdev-device <dev>
> Use device <dev> as the v4l-subdev device.
> If <dev> starts with a digit, then /dev/v4l-subdev<dev> is used.
> [...]
> Otherwise if -z was specified earlier, then <dev> is the entity name
> or interface ID (if prefixed with 0x) as found in the topology of the
> media device with the bus info string as specified by the -z option.
>
> -z, --media-bus-info <bus-info>
> Find the media device with the given bus info string. If set, then
> the options above can use the entity name or interface ID to refer
> to the device nodes.
>
>
> I reproduced the issue on an i.MX8MP and a Raspberry Pi 5. On i.MX8MP, I
> ran
>
> $ v4l2-compliance -z "platform:rkisp1" -u "imx219 1-0010"
>
> where "imx219 1-0010" is the sensor entity in the ISP media graph. This
> resulted in the following output:
>
> --------
> v4l2-compliance 1.33.0-5474, 64 bits, 64-bit time_t
> v4l2-compliance SHA: 73e05fa3c79b 2026-06-02 06:15:45
>
> Compliance test for device /dev/v4l-subdev3:
>
> Driver Info:
> Driver version : 7.1.0
> Capabilities : 0x00000000
> Client Capabilities: 0x0000000000000003
> streams interval-uses-which media_fd 4294967295 ent_id 0x00000000
>
> Required ioctls:
> 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)
>
> 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 device /dev/v4l-subdev3: 46, Succeeded: 46, Failed: 0, Warnings: 0
> --------
>
> v4l2-compliance skipped pad-based ioctl tests, because it was unable to
> count the number of pad of the entity. The root cause if
> mi_get_media_fd() returning -1 in testNode(), because
> /sys/dev/char/81:9/device/ does not contain any entry whose name starts
> with "media".
>
> I couldn't reproduce the issue with vimc running
>
> $ v4l2-compliance -z platform:vimc.0 -u "Sensor A"
>
> so I investigated further, and realized there's a major difference: the
> "Sensor A" entity in vimc is created by the vimc driver that registers
> the media device, while the sensor entity in the rkisp1 media graph is
> created by a sensor driver.
>
> Finding the media device through sysfs isn't guaranteed to work. We can
> keep doing so as a last resort option when no -z option is specified,
> but we should use the media device found by open_media_bus_info() when
> running with -z.
>
Please check this patch, I hope this fixes the issue.
Regards,
Hans
diff --git a/utils/common/media-info.cpp b/utils/common/media-info.cpp
index 95e4c74f..b9140727 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,6 +243,34 @@ int mi_get_media_fd(int fd, const char *bus_info)
devname += ep->d_name;
media_fd = open(devname.c_str(), O_RDWR);
+ 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;
+ 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 (bus_info &&
(ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo) ||
strcmp(mdinfo.bus_info, bus_info))) {
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..0108c8d4 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;
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);
+ 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;
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: v4l2-compliance does not pick media device with -z and -u options
2026-06-12 11:37 ` Hans Verkuil
@ 2026-06-12 15:16 ` Laurent Pinchart
2026-06-18 7:03 ` Hans Verkuil
0 siblings, 1 reply; 5+ messages in thread
From: Laurent Pinchart @ 2026-06-12 15:16 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media
Hi Hans,
On Fri, Jun 12, 2026 at 01:37:49PM +0200, Hans Verkuil wrote:
> On 10/06/2026 13:33, Laurent Pinchart wrote:
> > Hi Hans,
> >
> > I've noticed yesterday that v4l2-compliance does not pick a media device
> > when run on a subdev with the -z and -u options.
> >
> > The options are documented as
> >
> > -u, --subdev-device <dev>
> > Use device <dev> as the v4l-subdev device.
> > If <dev> starts with a digit, then /dev/v4l-subdev<dev> is used.
> > [...]
> > Otherwise if -z was specified earlier, then <dev> is the entity name
> > or interface ID (if prefixed with 0x) as found in the topology of the
> > media device with the bus info string as specified by the -z option.
> >
> > -z, --media-bus-info <bus-info>
> > Find the media device with the given bus info string. If set, then
> > the options above can use the entity name or interface ID to refer
> > to the device nodes.
> >
> >
> > I reproduced the issue on an i.MX8MP and a Raspberry Pi 5. On i.MX8MP, I
> > ran
> >
> > $ v4l2-compliance -z "platform:rkisp1" -u "imx219 1-0010"
> >
> > where "imx219 1-0010" is the sensor entity in the ISP media graph. This
> > resulted in the following output:
> >
> > --------
> > v4l2-compliance 1.33.0-5474, 64 bits, 64-bit time_t
> > v4l2-compliance SHA: 73e05fa3c79b 2026-06-02 06:15:45
> >
> > Compliance test for device /dev/v4l-subdev3:
> >
> > Driver Info:
> > Driver version : 7.1.0
> > Capabilities : 0x00000000
> > Client Capabilities: 0x0000000000000003
> > streams interval-uses-which media_fd 4294967295 ent_id 0x00000000
> >
> > Required ioctls:
> > 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)
> >
> > 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 device /dev/v4l-subdev3: 46, Succeeded: 46, Failed: 0, Warnings: 0
> > --------
> >
> > v4l2-compliance skipped pad-based ioctl tests, because it was unable to
> > count the number of pad of the entity. The root cause if
> > mi_get_media_fd() returning -1 in testNode(), because
> > /sys/dev/char/81:9/device/ does not contain any entry whose name starts
> > with "media".
> >
> > I couldn't reproduce the issue with vimc running
> >
> > $ v4l2-compliance -z platform:vimc.0 -u "Sensor A"
> >
> > so I investigated further, and realized there's a major difference: the
> > "Sensor A" entity in vimc is created by the vimc driver that registers
> > the media device, while the sensor entity in the rkisp1 media graph is
> > created by a sensor driver.
> >
> > Finding the media device through sysfs isn't guaranteed to work. We can
> > keep doing so as a last resort option when no -z option is specified,
> > but we should use the media device found by open_media_bus_info() when
> > running with -z.
>
> Please check this patch, I hope this fixes the issue.
Unfortunately it doesn't. Please read below for comments.
> diff --git a/utils/common/media-info.cpp b/utils/common/media-info.cpp
> index 95e4c74f..b9140727 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,6 +243,34 @@ int mi_get_media_fd(int fd, const char *bus_info)
> devname += ep->d_name;
> media_fd = open(devname.c_str(), O_RDWR);
>
> + 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)
> +{
Small improvement, you can return -1 here if bus_info is NULL.
> + int media_fd = -1;
> +
> + DIR *dp;
> + struct dirent *ep;
> + 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 (bus_info &&
And drop the bus_info check here.
> (ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo) ||
> strcmp(mdinfo.bus_info, bus_info))) {
> 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..0108c8d4 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);
This doesn't work, because node.bus_info is never set.
The node class has a bus_info field and a media_bus_info field. As
they're not documented, I'm not sure which one is supposed to be set
here. node.media_bus_info is set later in this function, retrieved from
the media_fd.
I'd fix this myself (I don't think it's a very difficult job), but all
this is lots of spaghetti code and I don't know how it's supposed to
look like :-/
> }
>
> int fd = node.is_media() ? node.g_fd() : media_fd;
> 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);
> + 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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: v4l2-compliance does not pick media device with -z and -u options
2026-06-12 15:16 ` Laurent Pinchart
@ 2026-06-18 7:03 ` Hans Verkuil
2026-06-29 13:15 ` Laurent Pinchart
0 siblings, 1 reply; 5+ messages in thread
From: Hans Verkuil @ 2026-06-18 7:03 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linux-media
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.
Anyway, fingers crossed...
Regards,
Hans
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);
+ 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;
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: v4l2-compliance does not pick media device with -z and -u options
2026-06-18 7:03 ` Hans Verkuil
@ 2026-06-29 13:15 ` Laurent Pinchart
0 siblings, 0 replies; 5+ messages in thread
From: Laurent Pinchart @ 2026-06-29 13:15 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media
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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-29 13:15 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox