]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: uvcvideo: Introduce dev->meta_formats
authorRicardo Ribalda <ribalda@chromium.org>
Mon, 7 Jul 2025 18:34:03 +0000 (18:34 +0000)
committerHans Verkuil <hverkuil@xs4all.nl>
Fri, 11 Jul 2025 17:27:29 +0000 (19:27 +0200)
Right now, there driver supports devices with one or two metadata
formats. Prepare it to support more than two metadata formats.

This is achieved with the introduction of a new field `meta_formats`,
that contains the array of metadata formats supported by the device, in
the order expected by userspace.

Suggested-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Link: https://lore.kernel.org/r/20250707-uvc-meta-v8-3-ed17f8b1218b@chromium.org
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/usb/uvc/uvc_driver.c
drivers/media/usb/uvc/uvc_metadata.c
drivers/media/usb/uvc/uvcvideo.h

index accfb4ca3c72cb899185ddc8ecf4e29143d58fc6..b12c95fe8b0a77720fd0e6dfea7d6a89abab30e7 100644 (file)
@@ -2293,6 +2293,8 @@ static int uvc_probe(struct usb_interface *intf,
                goto error;
        }
 
+       uvc_meta_init(dev);
+
        if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME)
                udev->quirks &= ~USB_QUIRK_RESET_RESUME;
 
index d3aab22f91cea21aefc56409924dfa1451aec914..58691df60dd3771f45f14524a6f1593f1502bb30 100644 (file)
@@ -64,14 +64,20 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh,
        struct uvc_device *dev = stream->dev;
        struct v4l2_meta_format *fmt = &format->fmt.meta;
        u32 fmeta = fmt->dataformat;
+       u32 i;
 
        if (format->type != vfh->vdev->queue->type)
                return -EINVAL;
 
+       for (i = 0; (fmeta != dev->meta_formats[i]) && dev->meta_formats[i];
+            i++)
+               ;
+       if (!dev->meta_formats[i])
+               fmeta = V4L2_META_FMT_UVC;
+
        memset(fmt, 0, sizeof(*fmt));
 
-       fmt->dataformat = fmeta == dev->info->meta_format
-                       ? fmeta : V4L2_META_FMT_UVC;
+       fmt->dataformat = fmeta;
        fmt->buffersize = UVC_METADATA_BUF_SIZE;
 
        return 0;
@@ -112,17 +118,21 @@ static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh,
        struct v4l2_fh *vfh = file->private_data;
        struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
        struct uvc_device *dev = stream->dev;
-       u32 index = fdesc->index;
+       u32 i;
+
+       if (fdesc->type != vfh->vdev->queue->type)
+               return -EINVAL;
 
-       if (fdesc->type != vfh->vdev->queue->type ||
-           index > 1U || (index && !dev->info->meta_format))
+       for (i = 0; (i < fdesc->index) && dev->meta_formats[i]; i++)
+               ;
+       if (!dev->meta_formats[i])
                return -EINVAL;
 
        memset(fdesc, 0, sizeof(*fdesc));
 
        fdesc->type = vfh->vdev->queue->type;
-       fdesc->index = index;
-       fdesc->pixelformat = index ? dev->info->meta_format : V4L2_META_FMT_UVC;
+       fdesc->index = i;
+       fdesc->pixelformat = dev->meta_formats[i];
 
        return 0;
 }
@@ -168,3 +178,17 @@ int uvc_meta_register(struct uvc_streaming *stream)
                                         V4L2_BUF_TYPE_META_CAPTURE,
                                         &uvc_meta_fops, &uvc_meta_ioctl_ops);
 }
+
+void uvc_meta_init(struct uvc_device *dev)
+{
+       unsigned int i = 0;
+
+       dev->meta_formats[i++] = V4L2_META_FMT_UVC;
+
+       if (dev->info->meta_format &&
+           !WARN_ON(dev->info->meta_format == V4L2_META_FMT_UVC))
+               dev->meta_formats[i++] = dev->info->meta_format;
+
+        /* IMPORTANT: for new meta-formats update UVC_MAX_META_DATA_FORMATS. */
+       dev->meta_formats[i++] = 0;
+}
index 3e6d2d912f3a1cfcf63b2bc8edd3f86f3da305db..81ec171fdfde4e48f8694cc9b9df899fdecf6baf 100644 (file)
@@ -575,6 +575,8 @@ struct uvc_status {
        };
 } __packed;
 
+#define UVC_MAX_META_DATA_FORMATS 3
+
 struct uvc_device {
        struct usb_device *udev;
        struct usb_interface *intf;
@@ -585,6 +587,9 @@ struct uvc_device {
 
        const struct uvc_device_info *info;
 
+       /* Zero-ended list of meta formats */
+       u32 meta_formats[UVC_MAX_META_DATA_FORMATS + 1];
+
        atomic_t nmappings;
 
        /* Video control interface */
@@ -722,6 +727,7 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit,
 void uvc_video_clock_update(struct uvc_streaming *stream,
                            struct vb2_v4l2_buffer *vbuf,
                            struct uvc_buffer *buf);
+void uvc_meta_init(struct uvc_device *dev);
 int uvc_meta_register(struct uvc_streaming *stream);
 
 int uvc_register_video_device(struct uvc_device *dev,