1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * uvc_metadata.c -- USB Video Class driver - Metadata handling
6 * Guennadi Liakhovetski (guennadi.liakhovetski@intel.com)
9 #include <linux/kernel.h>
10 #include <linux/list.h>
11 #include <linux/module.h>
12 #include <linux/usb.h>
13 #include <linux/videodev2.h>
15 #include <media/v4l2-ioctl.h>
16 #include <media/videobuf2-v4l2.h>
17 #include <media/videobuf2-vmalloc.h>
21 /* -----------------------------------------------------------------------------
25 static int uvc_meta_v4l2_querycap(struct file
*file
, void *fh
,
26 struct v4l2_capability
*cap
)
28 struct v4l2_fh
*vfh
= file
->private_data
;
29 struct uvc_streaming
*stream
= video_get_drvdata(vfh
->vdev
);
30 struct uvc_video_chain
*chain
= stream
->chain
;
32 strscpy(cap
->driver
, "uvcvideo", sizeof(cap
->driver
));
33 strscpy(cap
->card
, vfh
->vdev
->name
, sizeof(cap
->card
));
34 usb_make_path(stream
->dev
->udev
, cap
->bus_info
, sizeof(cap
->bus_info
));
35 cap
->capabilities
= V4L2_CAP_DEVICE_CAPS
| V4L2_CAP_STREAMING
41 static int uvc_meta_v4l2_get_format(struct file
*file
, void *fh
,
42 struct v4l2_format
*format
)
44 struct v4l2_fh
*vfh
= file
->private_data
;
45 struct uvc_streaming
*stream
= video_get_drvdata(vfh
->vdev
);
46 struct v4l2_meta_format
*fmt
= &format
->fmt
.meta
;
48 if (format
->type
!= vfh
->vdev
->queue
->type
)
51 memset(fmt
, 0, sizeof(*fmt
));
53 fmt
->dataformat
= stream
->meta
.format
;
54 fmt
->buffersize
= UVC_METADATA_BUF_SIZE
;
59 static int uvc_meta_v4l2_try_format(struct file
*file
, void *fh
,
60 struct v4l2_format
*format
)
62 struct v4l2_fh
*vfh
= file
->private_data
;
63 struct uvc_streaming
*stream
= video_get_drvdata(vfh
->vdev
);
64 struct uvc_device
*dev
= stream
->dev
;
65 struct v4l2_meta_format
*fmt
= &format
->fmt
.meta
;
66 u32 fmeta
= fmt
->dataformat
;
68 if (format
->type
!= vfh
->vdev
->queue
->type
)
71 memset(fmt
, 0, sizeof(*fmt
));
73 fmt
->dataformat
= fmeta
== dev
->info
->meta_format
74 ? fmeta
: V4L2_META_FMT_UVC
;
75 fmt
->buffersize
= UVC_METADATA_BUF_SIZE
;
80 static int uvc_meta_v4l2_set_format(struct file
*file
, void *fh
,
81 struct v4l2_format
*format
)
83 struct v4l2_fh
*vfh
= file
->private_data
;
84 struct uvc_streaming
*stream
= video_get_drvdata(vfh
->vdev
);
85 struct v4l2_meta_format
*fmt
= &format
->fmt
.meta
;
88 ret
= uvc_meta_v4l2_try_format(file
, fh
, format
);
93 * We could in principle switch at any time, also during streaming.
94 * Metadata buffers would still be perfectly parseable, but it's more
95 * consistent and cleaner to disallow that.
97 mutex_lock(&stream
->mutex
);
99 if (uvc_queue_allocated(&stream
->queue
))
102 stream
->meta
.format
= fmt
->dataformat
;
104 mutex_unlock(&stream
->mutex
);
109 static int uvc_meta_v4l2_enum_formats(struct file
*file
, void *fh
,
110 struct v4l2_fmtdesc
*fdesc
)
112 struct v4l2_fh
*vfh
= file
->private_data
;
113 struct uvc_streaming
*stream
= video_get_drvdata(vfh
->vdev
);
114 struct uvc_device
*dev
= stream
->dev
;
115 u32 index
= fdesc
->index
;
117 if (fdesc
->type
!= vfh
->vdev
->queue
->type
||
118 index
> 1U || (index
&& !dev
->info
->meta_format
))
121 memset(fdesc
, 0, sizeof(*fdesc
));
123 fdesc
->type
= vfh
->vdev
->queue
->type
;
124 fdesc
->index
= index
;
125 fdesc
->pixelformat
= index
? dev
->info
->meta_format
: V4L2_META_FMT_UVC
;
130 static const struct v4l2_ioctl_ops uvc_meta_ioctl_ops
= {
131 .vidioc_querycap
= uvc_meta_v4l2_querycap
,
132 .vidioc_g_fmt_meta_cap
= uvc_meta_v4l2_get_format
,
133 .vidioc_s_fmt_meta_cap
= uvc_meta_v4l2_set_format
,
134 .vidioc_try_fmt_meta_cap
= uvc_meta_v4l2_try_format
,
135 .vidioc_enum_fmt_meta_cap
= uvc_meta_v4l2_enum_formats
,
136 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
137 .vidioc_querybuf
= vb2_ioctl_querybuf
,
138 .vidioc_qbuf
= vb2_ioctl_qbuf
,
139 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
140 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
141 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
142 .vidioc_streamon
= vb2_ioctl_streamon
,
143 .vidioc_streamoff
= vb2_ioctl_streamoff
,
146 /* -----------------------------------------------------------------------------
147 * V4L2 File Operations
150 static const struct v4l2_file_operations uvc_meta_fops
= {
151 .owner
= THIS_MODULE
,
152 .unlocked_ioctl
= video_ioctl2
,
153 .open
= v4l2_fh_open
,
154 .release
= vb2_fop_release
,
155 .poll
= vb2_fop_poll
,
156 .mmap
= vb2_fop_mmap
,
159 int uvc_meta_register(struct uvc_streaming
*stream
)
161 struct uvc_device
*dev
= stream
->dev
;
162 struct video_device
*vdev
= &stream
->meta
.vdev
;
163 struct uvc_video_queue
*queue
= &stream
->meta
.queue
;
165 stream
->meta
.format
= V4L2_META_FMT_UVC
;
168 * The video interface queue uses manual locking and thus does not set
169 * the queue pointer. Set it manually here.
171 vdev
->queue
= &queue
->queue
;
173 return uvc_register_video_device(dev
, stream
, vdev
, queue
,
174 V4L2_BUF_TYPE_META_CAPTURE
,
175 &uvc_meta_fops
, &uvc_meta_ioctl_ops
);