xref: /linux/drivers/media/usb/uvc/uvc_metadata.c (revision 55a42f78ffd386e01a5404419f8c5ded7db70a21)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *      uvc_metadata.c  --  USB Video Class driver - Metadata handling
4  *
5  *      Copyright (C) 2016
6  *          Guennadi Liakhovetski (guennadi.liakhovetski@intel.com)
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/list.h>
11 #include <linux/module.h>
12 #include <linux/usb.h>
13 #include <linux/usb/uvc.h>
14 #include <linux/videodev2.h>
15 
16 #include <media/v4l2-ioctl.h>
17 #include <media/videobuf2-v4l2.h>
18 #include <media/videobuf2-vmalloc.h>
19 
20 #include "uvcvideo.h"
21 
22 /* -----------------------------------------------------------------------------
23  * V4L2 ioctls
24  */
25 
26 static int uvc_meta_v4l2_querycap(struct file *file, void *priv,
27 				  struct v4l2_capability *cap)
28 {
29 	struct v4l2_fh *vfh = file_to_v4l2_fh(file);
30 	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
31 	struct uvc_video_chain *chain = stream->chain;
32 
33 	strscpy(cap->driver, "uvcvideo", sizeof(cap->driver));
34 	strscpy(cap->card, stream->dev->name, sizeof(cap->card));
35 	usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
36 	cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
37 			  | chain->caps;
38 
39 	return 0;
40 }
41 
42 static int uvc_meta_v4l2_get_format(struct file *file, void *priv,
43 				    struct v4l2_format *format)
44 {
45 	struct v4l2_fh *vfh = file_to_v4l2_fh(file);
46 	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
47 	struct v4l2_meta_format *fmt = &format->fmt.meta;
48 
49 	if (format->type != vfh->vdev->queue->type)
50 		return -EINVAL;
51 
52 	fmt->dataformat = stream->meta.format;
53 	fmt->buffersize = UVC_METADATA_BUF_SIZE;
54 
55 	return 0;
56 }
57 
58 static int uvc_meta_v4l2_try_format(struct file *file, void *priv,
59 				    struct v4l2_format *format)
60 {
61 	struct v4l2_fh *vfh = file_to_v4l2_fh(file);
62 	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
63 	struct uvc_device *dev = stream->dev;
64 	struct v4l2_meta_format *fmt = &format->fmt.meta;
65 	u32 fmeta = V4L2_META_FMT_UVC;
66 
67 	if (format->type != vfh->vdev->queue->type)
68 		return -EINVAL;
69 
70 	for (unsigned int i = 0; i < dev->nmeta_formats; i++) {
71 		if (dev->meta_formats[i] == fmt->dataformat) {
72 			fmeta = fmt->dataformat;
73 			break;
74 		}
75 	}
76 
77 	memset(fmt, 0, sizeof(*fmt));
78 
79 	fmt->dataformat = fmeta;
80 	fmt->buffersize = UVC_METADATA_BUF_SIZE;
81 
82 	return 0;
83 }
84 
85 static int uvc_meta_v4l2_set_format(struct file *file, void *priv,
86 				    struct v4l2_format *format)
87 {
88 	struct v4l2_fh *vfh = file_to_v4l2_fh(file);
89 	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
90 	struct v4l2_meta_format *fmt = &format->fmt.meta;
91 	int ret;
92 
93 	ret = uvc_meta_v4l2_try_format(file, priv, format);
94 	if (ret < 0)
95 		return ret;
96 
97 	/*
98 	 * We could in principle switch at any time, also during streaming.
99 	 * Metadata buffers would still be perfectly parseable, but it's more
100 	 * consistent and cleaner to disallow that.
101 	 */
102 	if (vb2_is_busy(&stream->meta.queue.queue))
103 		return -EBUSY;
104 
105 	stream->meta.format = fmt->dataformat;
106 
107 	return 0;
108 }
109 
110 static int uvc_meta_v4l2_enum_formats(struct file *file, void *priv,
111 				      struct v4l2_fmtdesc *fdesc)
112 {
113 	struct v4l2_fh *vfh = file_to_v4l2_fh(file);
114 	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
115 	struct uvc_device *dev = stream->dev;
116 
117 	if (fdesc->type != vfh->vdev->queue->type)
118 		return -EINVAL;
119 
120 	if (fdesc->index >= dev->nmeta_formats)
121 		return -EINVAL;
122 
123 	fdesc->pixelformat = dev->meta_formats[fdesc->index];
124 
125 	return 0;
126 }
127 
128 static const struct v4l2_ioctl_ops uvc_meta_ioctl_ops = {
129 	.vidioc_querycap		= uvc_meta_v4l2_querycap,
130 	.vidioc_g_fmt_meta_cap		= uvc_meta_v4l2_get_format,
131 	.vidioc_s_fmt_meta_cap		= uvc_meta_v4l2_set_format,
132 	.vidioc_try_fmt_meta_cap	= uvc_meta_v4l2_try_format,
133 	.vidioc_enum_fmt_meta_cap	= uvc_meta_v4l2_enum_formats,
134 	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
135 	.vidioc_querybuf		= vb2_ioctl_querybuf,
136 	.vidioc_qbuf			= vb2_ioctl_qbuf,
137 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
138 	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
139 	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
140 	.vidioc_streamon		= vb2_ioctl_streamon,
141 	.vidioc_streamoff		= vb2_ioctl_streamoff,
142 };
143 
144 /* -----------------------------------------------------------------------------
145  * V4L2 File Operations
146  */
147 
148 static const struct v4l2_file_operations uvc_meta_fops = {
149 	.owner = THIS_MODULE,
150 	.unlocked_ioctl = video_ioctl2,
151 	.open = v4l2_fh_open,
152 	.release = vb2_fop_release,
153 	.poll = vb2_fop_poll,
154 	.mmap = vb2_fop_mmap,
155 };
156 
157 static struct uvc_entity *uvc_meta_find_msxu(struct uvc_device *dev)
158 {
159 	static const u8 uvc_msxu_guid[16] = UVC_GUID_MSXU_1_5;
160 	struct uvc_entity *entity;
161 
162 	list_for_each_entry(entity, &dev->entities, list) {
163 		if (!memcmp(entity->guid, uvc_msxu_guid, sizeof(entity->guid)))
164 			return entity;
165 	}
166 
167 	return NULL;
168 }
169 
170 static int uvc_meta_detect_msxu(struct uvc_device *dev)
171 {
172 	u32 *data __free(kfree) = NULL;
173 	struct uvc_entity *entity;
174 	int ret;
175 
176 	entity = uvc_meta_find_msxu(dev);
177 	if (!entity)
178 		return 0;
179 
180 	/*
181 	 * USB requires buffers aligned in a special way, simplest way is to
182 	 * make sure that query_ctrl will work is to kmalloc() them.
183 	 */
184 	data = kmalloc(sizeof(*data), GFP_KERNEL);
185 	if (!data)
186 		return -ENOMEM;
187 
188 	/*
189 	 * Check if the metadata is already enabled, or if the device always
190 	 * returns metadata.
191 	 */
192 	ret = uvc_query_ctrl(dev, UVC_GET_CUR, entity->id, dev->intfnum,
193 			     UVC_MSXU_CONTROL_METADATA, data, sizeof(*data));
194 	if (ret)
195 		return 0;
196 
197 	if (*data) {
198 		dev->quirks |= UVC_QUIRK_MSXU_META;
199 		return 0;
200 	}
201 
202 	/*
203 	 * Set the value of UVC_MSXU_CONTROL_METADATA to the value reported by
204 	 * GET_MAX to enable production of MSXU metadata. The GET_MAX request
205 	 * reports the maximum size of the metadata, if its value is 0 then MSXU
206 	 * metadata is not supported. For more information, see
207 	 * https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#2229-metadata-control
208 	 */
209 	ret = uvc_query_ctrl(dev, UVC_GET_MAX, entity->id, dev->intfnum,
210 			     UVC_MSXU_CONTROL_METADATA, data, sizeof(*data));
211 	if (ret || !*data)
212 		return 0;
213 
214 	/*
215 	 * If we can set UVC_MSXU_CONTROL_METADATA, the device will report
216 	 * metadata.
217 	 */
218 	ret = uvc_query_ctrl(dev, UVC_SET_CUR, entity->id, dev->intfnum,
219 			     UVC_MSXU_CONTROL_METADATA, data, sizeof(*data));
220 	if (!ret)
221 		dev->quirks |= UVC_QUIRK_MSXU_META;
222 
223 	return 0;
224 }
225 
226 int uvc_meta_register(struct uvc_streaming *stream)
227 {
228 	struct uvc_device *dev = stream->dev;
229 	struct uvc_video_queue *queue = &stream->meta.queue;
230 
231 	stream->meta.format = V4L2_META_FMT_UVC;
232 
233 	return uvc_register_video_device(dev, stream, queue,
234 					 V4L2_BUF_TYPE_META_CAPTURE,
235 					 &uvc_meta_fops, &uvc_meta_ioctl_ops);
236 }
237 
238 int uvc_meta_init(struct uvc_device *dev)
239 {
240 	unsigned int i = 0;
241 	int ret;
242 
243 	ret = uvc_meta_detect_msxu(dev);
244 	if (ret)
245 		return ret;
246 
247 	dev->meta_formats[i++] = V4L2_META_FMT_UVC;
248 
249 	if (dev->info->meta_format &&
250 	    !WARN_ON(dev->info->meta_format == V4L2_META_FMT_UVC))
251 		dev->meta_formats[i++] = dev->info->meta_format;
252 
253 	if (dev->quirks & UVC_QUIRK_MSXU_META &&
254 	    !WARN_ON(dev->info->meta_format == V4L2_META_FMT_UVC_MSXU_1_5))
255 		dev->meta_formats[i++] = V4L2_META_FMT_UVC_MSXU_1_5;
256 
257 	 /* IMPORTANT: for new meta-formats update UVC_MAX_META_DATA_FORMATS. */
258 	dev->nmeta_formats = i;
259 
260 	return 0;
261 }
262