@@ -2315,6 +2315,13 @@ static int uvc_probe(struct usb_interface *intf,
goto error;
}
+ ret = uvc_meta_init(dev);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev,
+ "Error initializing the metadata formats (%d)\n", ret);
+ goto error;
+ }
+
if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME)
udev->quirks &= ~USB_QUIRK_RESET_RESUME;
@@ -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;
}
@@ -174,3 +184,25 @@ int uvc_meta_register(struct uvc_streaming *stream)
V4L2_BUF_TYPE_META_CAPTURE,
&uvc_meta_fops, &uvc_meta_ioctl_ops);
}
+
+int uvc_meta_init(struct uvc_device *dev)
+{
+ static const u32 uvch_only[] = {V4L2_META_FMT_UVC, 0};
+ static const u32 d4xx_format[] = {V4L2_META_FMT_UVC, V4L2_META_FMT_D4XX,
+ 0};
+
+ switch (dev->info->meta_format) {
+ case V4L2_META_FMT_D4XX:
+ dev->meta_formats = d4xx_format;
+ break;
+ case 0:
+ dev->meta_formats = uvch_only;
+ break;
+ default:
+ dev_err(&dev->udev->dev, "Unknown metadata format 0x%x\n",
+ dev->info->meta_format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
@@ -581,6 +581,7 @@ struct uvc_device {
char name[32];
const struct uvc_device_info *info;
+ const u32 *meta_formats; /* Zero-ended list of meta formats */
atomic_t nmappings;
@@ -751,6 +752,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);
+int uvc_meta_init(struct uvc_device *dev);
int uvc_meta_register(struct uvc_streaming *stream);
int uvc_register_video_device(struct uvc_device *dev,
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. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_driver.c | 7 ++++++ drivers/media/usb/uvc/uvc_metadata.c | 46 ++++++++++++++++++++++++++++++------ drivers/media/usb/uvc/uvcvideo.h | 2 ++ 3 files changed, 48 insertions(+), 7 deletions(-)