xref: /aosp_15_r20/external/virtio-media/driver/virtio_media_ioctls.c (revision 1b4853f54772485c5dd4001ae33a7a958bcc97a1)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+
2 
3 /*
4  * Ioctls implementations for the virtio-media driver.
5  *
6  * Copyright (c) 2023-2024 Google LLC.
7  */
8 
9 #include <linux/virtio_config.h>
10 #include <linux/vmalloc.h>
11 #include <media/v4l2-event.h>
12 #include <media/v4l2-ioctl.h>
13 
14 #include "scatterlist_filler.h"
15 #include "virtio_media.h"
16 
17 /**
18  * Send an ioctl that has no driver payload, but expects a reponse from the host (i.e. an
19  * ioctl specified with _IOR).
20  *
21  * Returns 0 in case of success, or a negative error code.
22  */
virtio_media_send_r_ioctl(struct v4l2_fh * fh,u32 ioctl,void * ioctl_data,size_t ioctl_data_len)23 static int virtio_media_send_r_ioctl(struct v4l2_fh *fh, u32 ioctl,
24 				     void *ioctl_data, size_t ioctl_data_len)
25 {
26 	struct video_device *video_dev = fh->vdev;
27 	struct virtio_media *vv = to_virtio_media(video_dev);
28 	struct virtio_media_session *session = fh_to_session(fh);
29 	struct scatterlist *sgs[3];
30 	struct scatterlist_filler filler = {
31 		.descs = session->command_sgs.sgl,
32 		.num_descs = DESC_CHAIN_MAX_LEN,
33 		.cur_desc = 0,
34 		.shadow_buffer = session->shadow_buf,
35 		.shadow_buffer_size = VIRTIO_SHADOW_BUF_SIZE,
36 		.shadow_buffer_pos = 0,
37 		.sgs = sgs,
38 		.num_sgs = ARRAY_SIZE(sgs),
39 		.cur_sg = 0,
40 	};
41 	int ret;
42 
43 	/* Command descriptor */
44 	ret = scatterlist_filler_add_ioctl_cmd(&filler, session, ioctl);
45 	if (ret)
46 		return ret;
47 
48 	/* Response descriptor */
49 	ret = scatterlist_filler_add_ioctl_resp(&filler, session);
50 	if (ret)
51 		return ret;
52 
53 	/* Response payload */
54 	ret = scatterlist_filler_add_data(&filler, ioctl_data, ioctl_data_len);
55 	if (ret) {
56 		v4l2_err(&vv->v4l2_dev,
57 			 "failed to prepare command descriptor chain\n");
58 		return ret;
59 	}
60 
61 	ret = virtio_media_send_command(
62 		vv, sgs, 1, 2,
63 		sizeof(struct virtio_media_resp_ioctl) + ioctl_data_len, NULL);
64 	if (ret < 0)
65 		return ret;
66 
67 	ret = scatterlist_filler_retrieve_data(session, filler.sgs[2],
68 					       ioctl_data, ioctl_data_len);
69 	if (ret) {
70 		v4l2_err(&vv->v4l2_dev,
71 			 "failed to retrieve response descriptor chain\n");
72 		return ret;
73 	}
74 
75 	return 0;
76 }
77 /**
78  * Send an ioctl that does not expect a reply beyond an error status (i.e. an
79  * ioctl specified with _IOW) to the host.
80  *
81  * Returns 0 in case of success, or a negative error code.
82  */
virtio_media_send_w_ioctl(struct v4l2_fh * fh,u32 ioctl,const void * ioctl_data,size_t ioctl_data_len)83 static int virtio_media_send_w_ioctl(struct v4l2_fh *fh, u32 ioctl,
84 				     const void *ioctl_data,
85 				     size_t ioctl_data_len)
86 {
87 	struct video_device *video_dev = fh->vdev;
88 	struct virtio_media *vv = to_virtio_media(video_dev);
89 	struct virtio_media_session *session = fh_to_session(fh);
90 	struct scatterlist *sgs[3];
91 	struct scatterlist_filler filler = {
92 		.descs = session->command_sgs.sgl,
93 		.num_descs = DESC_CHAIN_MAX_LEN,
94 		.cur_desc = 0,
95 		.shadow_buffer = session->shadow_buf,
96 		.shadow_buffer_size = VIRTIO_SHADOW_BUF_SIZE,
97 		.shadow_buffer_pos = 0,
98 		.sgs = sgs,
99 		.num_sgs = ARRAY_SIZE(sgs),
100 		.cur_sg = 0,
101 	};
102 	int ret;
103 
104 	/* Command descriptor */
105 	ret = scatterlist_filler_add_ioctl_cmd(&filler, session, ioctl);
106 	if (ret)
107 		return ret;
108 
109 	/* Command payload */
110 	ret = scatterlist_filler_add_data(&filler, (void *)ioctl_data,
111 					  ioctl_data_len);
112 	if (ret) {
113 		v4l2_err(&vv->v4l2_dev,
114 			 "failed to prepare command descriptor chain\n");
115 		return ret;
116 	}
117 
118 	/* Response descriptor */
119 	ret = scatterlist_filler_add_ioctl_resp(&filler, session);
120 	if (ret)
121 		return ret;
122 
123 	ret = virtio_media_send_command(
124 		vv, sgs, 2, 1, sizeof(struct virtio_media_resp_ioctl), NULL);
125 	if (ret < 0)
126 		return ret;
127 
128 	return 0;
129 }
130 
131 /**
132  * Sends an ioctl that expects a response of exactly the same size as the
133  * input (i.e. an ioctl specified with _IOWR) to the host.
134  *
135  * This corresponds to what most V4L2 ioctls do. For instance VIDIOC_ENUM_FMT
136  * takes a partially-initialized struct v4l2_fmtdesc and returns its filled
137  * version.
138  *
139  * Ioctls specified with _IOR can also use this, since the host will simply
140  * ignore the extra input data provided.
141  *
142  * Returns 0 in case of success, or a negative error code.
143  */
virtio_media_send_wr_ioctl(struct v4l2_fh * fh,u32 ioctl,void * ioctl_data,size_t ioctl_data_len,size_t min_resp_payload)144 static int virtio_media_send_wr_ioctl(struct v4l2_fh *fh, u32 ioctl,
145 				      void *ioctl_data, size_t ioctl_data_len,
146 				      size_t min_resp_payload)
147 {
148 	struct video_device *video_dev = fh->vdev;
149 	struct virtio_media *vv = to_virtio_media(video_dev);
150 	struct virtio_media_session *session = fh_to_session(fh);
151 	struct scatterlist *sgs[4];
152 	struct scatterlist_filler filler = {
153 		.descs = session->command_sgs.sgl,
154 		.num_descs = DESC_CHAIN_MAX_LEN,
155 		.cur_desc = 0,
156 		.shadow_buffer = session->shadow_buf,
157 		.shadow_buffer_size = VIRTIO_SHADOW_BUF_SIZE,
158 		.shadow_buffer_pos = 0,
159 		.sgs = sgs,
160 		.num_sgs = ARRAY_SIZE(sgs),
161 		.cur_sg = 0,
162 	};
163 	int ret;
164 
165 	/* Command descriptor */
166 	ret = scatterlist_filler_add_ioctl_cmd(&filler, session, ioctl);
167 	if (ret)
168 		return ret;
169 
170 	/* Command payload */
171 	ret = scatterlist_filler_add_data(&filler, ioctl_data, ioctl_data_len);
172 	if (ret) {
173 		v4l2_err(&vv->v4l2_dev,
174 			 "failed to prepare command descriptor chain\n");
175 		return ret;
176 	}
177 
178 	/* Response descriptor */
179 	ret = scatterlist_filler_add_ioctl_resp(&filler, session);
180 	if (ret)
181 		return ret;
182 
183 	/* Response payload, same as command */
184 	ret = scatterlist_filler_add_sg(&filler, filler.sgs[1]);
185 	if (ret)
186 		return ret;
187 
188 	ret = virtio_media_send_command(vv, sgs, 2, 2,
189 					sizeof(struct virtio_media_resp_ioctl) +
190 						min_resp_payload,
191 					NULL);
192 	if (ret < 0)
193 		return ret;
194 
195 	ret = scatterlist_filler_retrieve_data(session, filler.sgs[3],
196 					       ioctl_data, ioctl_data_len);
197 	if (ret) {
198 		v4l2_err(&vv->v4l2_dev,
199 			 "failed to retrieve response descriptor chain\n");
200 		return ret;
201 	}
202 
203 	return 0;
204 }
205 
virtio_media_send_buffer_ioctl(struct v4l2_fh * fh,u32 ioctl_code,struct v4l2_buffer * b)206 static int virtio_media_send_buffer_ioctl(struct v4l2_fh *fh, u32 ioctl_code,
207 					  struct v4l2_buffer *b)
208 {
209 	struct video_device *video_dev = fh->vdev;
210 	struct virtio_media *vv = to_virtio_media(video_dev);
211 	struct virtio_media_session *session = fh_to_session(fh);
212 	struct v4l2_plane *planes_backup = NULL;
213 	u32 length_backup = 0;
214 	struct scatterlist *sgs[64];
215 	/* End of the device-readable buffer SGs, to reuse in device-writable section. */
216 	size_t num_cmd_sgs;
217 	size_t end_buf_sg;
218 	struct scatterlist_filler filler = {
219 		.descs = session->command_sgs.sgl,
220 		.num_descs = DESC_CHAIN_MAX_LEN,
221 		.cur_desc = 0,
222 		.shadow_buffer = session->shadow_buf,
223 		.shadow_buffer_size = VIRTIO_SHADOW_BUF_SIZE,
224 		.shadow_buffer_pos = 0,
225 		.sgs = sgs,
226 		.num_sgs = ARRAY_SIZE(sgs),
227 		.cur_sg = 0,
228 	};
229 	size_t resp_len;
230 	int ret;
231 	int i;
232 
233 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE)
234 		return -EINVAL;
235 
236 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
237 		planes_backup = b->m.planes;
238 		length_backup = b->length;
239 	}
240 
241 	/* Command descriptor */
242 	ret = scatterlist_filler_add_ioctl_cmd(&filler, session, ioctl_code);
243 	if (ret)
244 		return ret;
245 
246 	/* Command payload (struct v4l2_buffer) */
247 	ret = scatterlist_filler_add_buffer(&filler, b);
248 	if (ret < 0)
249 		return ret;
250 
251 	end_buf_sg = filler.cur_sg;
252 
253 	/* Payload of USERPTR buffers, if relevant */
254 	ret = scatterlist_filler_add_buffer_userptr(&filler, b);
255 	if (ret < 0)
256 		return ret;
257 
258 	num_cmd_sgs = filler.cur_sg;
259 
260 	/* Response descriptor */
261 	ret = scatterlist_filler_add_ioctl_resp(&filler, session);
262 	if (ret)
263 		return ret;
264 
265 	/* Response payload (same as input, but no userptr mapping) */
266 	for (i = 1; i < end_buf_sg; i++) {
267 		ret = scatterlist_filler_add_sg(&filler, filler.sgs[i]);
268 		if (ret < 0)
269 			return ret;
270 	}
271 
272 	ret = virtio_media_send_command(
273 		vv, filler.sgs, num_cmd_sgs, filler.cur_sg - num_cmd_sgs,
274 		sizeof(struct virtio_media_resp_ioctl) + sizeof(*b), &resp_len);
275 
276 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
277 		b->m.planes = planes_backup;
278 		if (b->length > length_backup)
279 			return -ENOSPC;
280 	}
281 
282 	if (ret < 0)
283 		return ret;
284 
285 	resp_len -= sizeof(struct virtio_media_resp_ioctl);
286 
287 	/* Make sure that the reply's length covers our v4l2_buffer */
288 	if (resp_len < sizeof(*b))
289 		return -EINVAL;
290 
291 	ret = scatterlist_filler_retrieve_buffer(session, &sgs[num_cmd_sgs + 1],
292 						 b, length_backup);
293 	if (ret) {
294 		v4l2_err(&vv->v4l2_dev,
295 			 "failed to retrieve response descriptor chain\n");
296 		return ret;
297 	}
298 
299 	/* TODO ideally we should not be doing this twice, but the scatterlist may screw us up here? */
300 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
301 		b->m.planes = planes_backup;
302 		if (b->length > length_backup)
303 			return -ENOSPC;
304 	}
305 
306 	return 0;
307 }
308 
309 /**
310  * Queues an ioctl that sends a v4l2_ext_controls to the host and receives an updated version.
311  *
312  * v4l2_ext_controls has a pointer to an array of v4l2_ext_control, and also
313  * potentially pointers to user-space memory that we need to map properly,
314  * hence the dedicated function.
315  *
316  */
virtio_media_send_ext_controls_ioctl(struct v4l2_fh * fh,u32 ioctl_code,struct v4l2_ext_controls * ctrls)317 static int virtio_media_send_ext_controls_ioctl(struct v4l2_fh *fh,
318 						u32 ioctl_code,
319 						struct v4l2_ext_controls *ctrls)
320 {
321 	struct video_device *video_dev = fh->vdev;
322 	struct virtio_media *vv = to_virtio_media(video_dev);
323 	struct virtio_media_session *session = fh_to_session(fh);
324 	size_t num_cmd_sgs;
325 	struct v4l2_ext_control *controls_backup = ctrls->controls;
326 	const u32 num_ctrls = ctrls->count;
327 	struct scatterlist *sgs[64];
328 	struct scatterlist_filler filler = {
329 		.descs = session->command_sgs.sgl,
330 		.num_descs = DESC_CHAIN_MAX_LEN,
331 		.cur_desc = 0,
332 		.shadow_buffer = session->shadow_buf,
333 		.shadow_buffer_size = VIRTIO_SHADOW_BUF_SIZE,
334 		.shadow_buffer_pos = 0,
335 		.sgs = sgs,
336 		.num_sgs = ARRAY_SIZE(sgs),
337 		.cur_sg = 0,
338 	};
339 	size_t resp_len = 0;
340 	int ret;
341 
342 	/* Command descriptor */
343 	ret = scatterlist_filler_add_ioctl_cmd(&filler, session, ioctl_code);
344 	if (ret)
345 		return ret;
346 
347 	/* v4l2_controls and its pointees */
348 	ret = scatterlist_filler_add_ext_ctrls(&filler, ctrls, true);
349 	if (ret)
350 		return ret;
351 
352 	num_cmd_sgs = filler.cur_sg;
353 
354 	/* Response descriptor */
355 	ret = scatterlist_filler_add_ioctl_resp(&filler, session);
356 	if (ret)
357 		return ret;
358 
359 	/*
360 	 * Response payload (same as input but without userptrs)
361 	 */
362 	ret = scatterlist_filler_add_ext_ctrls(&filler, ctrls, false);
363 	if (ret)
364 		return ret;
365 
366 	ret = virtio_media_send_command(
367 		vv, filler.sgs, num_cmd_sgs, filler.cur_sg - num_cmd_sgs,
368 		sizeof(struct virtio_media_resp_ioctl) + sizeof(*ctrls),
369 		&resp_len);
370 
371 	/* Just in case the host touched these. */
372 	ctrls->controls = controls_backup;
373 	if (ctrls->count != num_ctrls) {
374 		v4l2_err(
375 			&vv->v4l2_dev,
376 			"device returned a number of extended controls different than submitted\n");
377 	}
378 	if (ctrls->count > num_ctrls)
379 		return -ENOSPC;
380 
381 	/* Event if we have received an error, we may need to read our payload back */
382 	if (ret < 0 && resp_len >= sizeof(struct virtio_media_resp_ioctl) +
383 					   sizeof(*ctrls)) {
384 		/* Deliberately ignore the error here as we want to return the previous one */
385 		scatterlist_filler_retrieve_ext_ctrls(
386 			session, &sgs[num_cmd_sgs + 1],
387 			filler.cur_sg - (num_cmd_sgs + 1), ctrls);
388 		return ret;
389 	}
390 
391 	resp_len -= sizeof(struct virtio_media_resp_ioctl);
392 
393 	/* Make sure that the reply's length covers our v4l2_ext_controls */
394 	if (resp_len < sizeof(*ctrls))
395 		return -EINVAL;
396 
397 	ret = scatterlist_filler_retrieve_ext_ctrls(
398 		session, &sgs[num_cmd_sgs + 1],
399 		filler.cur_sg - (num_cmd_sgs + 1), ctrls);
400 	if (ret)
401 		return ret;
402 
403 	return 0;
404 }
405 
406 /**
407  * Helper function to clear the list of buffers waiting to be dequeued on a
408  * queue that has just been streamed off.
409  */
virtio_media_clear_queue(struct virtio_media * vv,struct virtio_media_session * session,struct virtio_media_queue_state * queue)410 static void virtio_media_clear_queue(struct virtio_media *vv,
411 				     struct virtio_media_session *session,
412 				     struct virtio_media_queue_state *queue)
413 {
414 	struct list_head *p, *n;
415 	int i;
416 
417 	mutex_lock(&session->dqbufs_lock);
418 
419 	list_for_each_safe(p, n, &queue->pending_dqbufs) {
420 		struct virtio_media_buffer *dqbuf =
421 			list_entry(p, struct virtio_media_buffer, list);
422 
423 		list_del(&dqbuf->list);
424 	}
425 
426 	mutex_unlock(&session->dqbufs_lock);
427 
428 	/* All buffers are now dequeued. */
429 	for (i = 0; i < queue->allocated_bufs; i++) {
430 		queue->buffers[i].buffer.flags = 0;
431 	}
432 
433 	queue->queued_bufs = 0;
434 	queue->streaming = false;
435 	queue->is_capture_last = false;
436 }
437 
438 /*
439  * Macros suitable for defining ioctls with a constant size payload.
440  */
441 
442 #define SIMPLE_WR_IOCTL(name, ioctl, type)                            \
443 	static int virtio_media_##name(struct file *file, void *fh,   \
444 				       type *payload)                 \
445 	{                                                             \
446 		return virtio_media_send_wr_ioctl(fh, ioctl, payload, \
447 						  sizeof(*payload),   \
448 						  sizeof(*payload));  \
449 	}
450 #define SIMPLE_R_IOCTL(name, ioctl, type)                            \
451 	static int virtio_media_##name(struct file *file, void *fh,  \
452 				       type *payload)                \
453 	{                                                            \
454 		return virtio_media_send_r_ioctl(fh, ioctl, payload, \
455 						 sizeof(*payload));  \
456 	}
457 #define SIMPLE_W_IOCTL(name, ioctl, type)                            \
458 	static int virtio_media_##name(struct file *file, void *fh,  \
459 				       type *payload)                \
460 	{                                                            \
461 		return virtio_media_send_w_ioctl(fh, ioctl, payload, \
462 						 sizeof(*payload));  \
463 	}
464 
465 /*
466  * V4L2 ioctl handlers.
467  *
468  * Most of these functions just forward the ioctl to the host, for these we can
469  * use one of the SIMPLE_*_IOCTL macros. Exceptions that have their own
470  * standalone function follow.
471  */
472 
SIMPLE_WR_IOCTL(enum_fmt,VIDIOC_ENUM_FMT,struct v4l2_fmtdesc)473 SIMPLE_WR_IOCTL(enum_fmt, VIDIOC_ENUM_FMT, struct v4l2_fmtdesc)
474 SIMPLE_WR_IOCTL(g_fmt, VIDIOC_G_FMT, struct v4l2_format)
475 SIMPLE_WR_IOCTL(s_fmt, VIDIOC_S_FMT, struct v4l2_format)
476 SIMPLE_WR_IOCTL(try_fmt, VIDIOC_TRY_FMT, struct v4l2_format)
477 SIMPLE_WR_IOCTL(enum_framesizes, VIDIOC_ENUM_FRAMESIZES,
478 		struct v4l2_frmsizeenum)
479 SIMPLE_WR_IOCTL(enum_frameintervals, VIDIOC_ENUM_FRAMEINTERVALS,
480 		struct v4l2_frmivalenum)
481 SIMPLE_WR_IOCTL(queryctrl, VIDIOC_QUERYCTRL, struct v4l2_queryctrl)
482 SIMPLE_WR_IOCTL(g_ctrl, VIDIOC_G_CTRL, struct v4l2_control)
483 SIMPLE_WR_IOCTL(s_ctrl, VIDIOC_S_CTRL, struct v4l2_control)
484 SIMPLE_WR_IOCTL(query_ext_ctrl, VIDIOC_QUERY_EXT_CTRL,
485 		struct v4l2_query_ext_ctrl)
486 SIMPLE_WR_IOCTL(s_dv_timings, VIDIOC_S_DV_TIMINGS, struct v4l2_dv_timings)
487 SIMPLE_WR_IOCTL(g_dv_timings, VIDIOC_G_DV_TIMINGS, struct v4l2_dv_timings)
488 SIMPLE_R_IOCTL(query_dv_timings, VIDIOC_QUERY_DV_TIMINGS,
489 	       struct v4l2_dv_timings)
490 SIMPLE_WR_IOCTL(enum_dv_timings, VIDIOC_ENUM_DV_TIMINGS,
491 		struct v4l2_enum_dv_timings)
492 SIMPLE_WR_IOCTL(dv_timings_cap, VIDIOC_DV_TIMINGS_CAP,
493 		struct v4l2_dv_timings_cap)
494 SIMPLE_WR_IOCTL(enuminput, VIDIOC_ENUMINPUT, struct v4l2_input)
495 SIMPLE_WR_IOCTL(querymenu, VIDIOC_QUERYMENU, struct v4l2_querymenu)
496 SIMPLE_WR_IOCTL(enumoutput, VIDIOC_ENUMOUTPUT, struct v4l2_output)
497 SIMPLE_WR_IOCTL(enumaudio, VIDIOC_ENUMAUDIO, struct v4l2_audio)
498 SIMPLE_R_IOCTL(g_audio, VIDIOC_G_AUDIO, struct v4l2_audio)
499 SIMPLE_W_IOCTL(s_audio, VIDIOC_S_AUDIO, const struct v4l2_audio)
500 SIMPLE_WR_IOCTL(enumaudout, VIDIOC_ENUMAUDOUT, struct v4l2_audioout)
501 SIMPLE_R_IOCTL(g_audout, VIDIOC_G_AUDOUT, struct v4l2_audioout)
502 SIMPLE_W_IOCTL(s_audout, VIDIOC_S_AUDOUT, const struct v4l2_audioout)
503 SIMPLE_WR_IOCTL(g_modulator, VIDIOC_G_MODULATOR, struct v4l2_modulator)
504 SIMPLE_W_IOCTL(s_modulator, VIDIOC_S_MODULATOR, const struct v4l2_modulator)
505 SIMPLE_WR_IOCTL(g_selection, VIDIOC_G_SELECTION, struct v4l2_selection)
506 SIMPLE_WR_IOCTL(s_selection, VIDIOC_S_SELECTION, struct v4l2_selection)
507 SIMPLE_R_IOCTL(g_enc_index, VIDIOC_G_ENC_INDEX, struct v4l2_enc_idx)
508 SIMPLE_WR_IOCTL(encoder_cmd, VIDIOC_ENCODER_CMD, struct v4l2_encoder_cmd)
509 SIMPLE_WR_IOCTL(try_encoder_cmd, VIDIOC_TRY_ENCODER_CMD,
510 		struct v4l2_encoder_cmd)
511 SIMPLE_WR_IOCTL(try_decoder_cmd, VIDIOC_TRY_DECODER_CMD,
512 		struct v4l2_decoder_cmd)
513 SIMPLE_WR_IOCTL(g_parm, VIDIOC_G_PARM, struct v4l2_streamparm)
514 SIMPLE_WR_IOCTL(s_parm, VIDIOC_S_PARM, struct v4l2_streamparm)
515 SIMPLE_R_IOCTL(g_std, VIDIOC_G_STD, v4l2_std_id)
516 SIMPLE_R_IOCTL(querystd, VIDIOC_QUERYSTD, v4l2_std_id)
517 SIMPLE_WR_IOCTL(enumstd, VIDIOC_ENUMSTD, struct v4l2_standard)
518 SIMPLE_WR_IOCTL(g_tuner, VIDIOC_G_TUNER, struct v4l2_tuner)
519 SIMPLE_W_IOCTL(s_tuner, VIDIOC_S_TUNER, const struct v4l2_tuner)
520 SIMPLE_WR_IOCTL(g_frequency, VIDIOC_G_FREQUENCY, struct v4l2_frequency)
521 SIMPLE_W_IOCTL(s_frequency, VIDIOC_S_FREQUENCY, const struct v4l2_frequency)
522 SIMPLE_WR_IOCTL(enum_freq_bands, VIDIOC_ENUM_FREQ_BANDS,
523 		struct v4l2_frequency_band)
524 SIMPLE_WR_IOCTL(g_sliced_vbi_cap, VIDIOC_G_SLICED_VBI_CAP,
525 		struct v4l2_sliced_vbi_cap)
526 SIMPLE_W_IOCTL(s_hw_freq_seek, VIDIOC_S_HW_FREQ_SEEK,
527 	       const struct v4l2_hw_freq_seek)
528 
529 /*
530  * QUERYCAP is handled by reading the configuration area.
531  *
532  */
533 
534 static int virtio_media_querycap(struct file *file, void *fh,
535 				 struct v4l2_capability *cap)
536 {
537 	struct video_device *video_dev = video_devdata(file);
538 	struct virtio_media *vv = to_virtio_media(video_dev);
539 
540 	/* TODO add proper number? */
541 	strncpy(cap->bus_info, "platform:virtio-media0", sizeof(cap->bus_info));
542 
543 	if (!driver_name) {
544 		strncpy(cap->driver, VIRTIO_MEDIA_DEFAULT_DRIVER_NAME,
545 			sizeof(cap->driver));
546 	} else {
547 		strncpy(cap->driver, driver_name, sizeof(cap->driver));
548 	}
549 	virtio_cread_bytes(vv->virtio_dev, 8, cap->card, sizeof(cap->card));
550 
551 	cap->capabilities = video_dev->device_caps | V4L2_CAP_DEVICE_CAPS;
552 	cap->device_caps = video_dev->device_caps;
553 
554 	return 0;
555 }
556 
557 /*
558  * Extended control ioctls are handled mostly identically.
559  */
560 
virtio_media_g_ext_ctrls(struct file * file,void * fh,struct v4l2_ext_controls * ctrls)561 static int virtio_media_g_ext_ctrls(struct file *file, void *fh,
562 				    struct v4l2_ext_controls *ctrls)
563 {
564 	return virtio_media_send_ext_controls_ioctl(fh, VIDIOC_G_EXT_CTRLS,
565 						    ctrls);
566 }
567 
virtio_media_s_ext_ctrls(struct file * file,void * fh,struct v4l2_ext_controls * ctrls)568 static int virtio_media_s_ext_ctrls(struct file *file, void *fh,
569 				    struct v4l2_ext_controls *ctrls)
570 {
571 	return virtio_media_send_ext_controls_ioctl(fh, VIDIOC_S_EXT_CTRLS,
572 						    ctrls);
573 }
574 
virtio_media_try_ext_ctrls(struct file * file,void * fh,struct v4l2_ext_controls * ctrls)575 static int virtio_media_try_ext_ctrls(struct file *file, void *fh,
576 				      struct v4l2_ext_controls *ctrls)
577 {
578 	return virtio_media_send_ext_controls_ioctl(fh, VIDIOC_TRY_EXT_CTRLS,
579 						    ctrls);
580 }
581 
582 /*
583  * Subscribe/unsubscribe from an event.
584  */
585 
586 static int
virtio_media_subscribe_event(struct v4l2_fh * fh,const struct v4l2_event_subscription * sub)587 virtio_media_subscribe_event(struct v4l2_fh *fh,
588 			     const struct v4l2_event_subscription *sub)
589 {
590 	struct video_device *video_dev = fh->vdev;
591 	struct virtio_media *vv = to_virtio_media(video_dev);
592 	int ret;
593 
594 	/* First subscribe to the event in the guest. */
595 	switch (sub->type) {
596 	case V4L2_EVENT_SOURCE_CHANGE:
597 		ret = v4l2_src_change_event_subscribe(fh, sub);
598 		break;
599 	default:
600 		ret = v4l2_event_subscribe(fh, sub, 1, NULL);
601 		break;
602 	}
603 	if (ret)
604 		return ret;
605 
606 	/* Then ask the host to signal us these events. */
607 	ret = virtio_media_send_w_ioctl(fh, VIDIOC_SUBSCRIBE_EVENT, sub,
608 					sizeof(*sub));
609 	if (ret < 0) {
610 		v4l2_event_unsubscribe(fh, sub);
611 		return ret;
612 	}
613 
614 	/*
615 	 * Subscribing to an event may result in that event being signaled
616 	 * immediately. Process all pending events to make sure we don't miss it.
617 	 */
618 	if (sub->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
619 		virtio_media_process_events(vv);
620 	}
621 
622 	return 0;
623 }
624 
625 static int
virtio_media_unsubscribe_event(struct v4l2_fh * fh,const struct v4l2_event_subscription * sub)626 virtio_media_unsubscribe_event(struct v4l2_fh *fh,
627 			       const struct v4l2_event_subscription *sub)
628 {
629 	int ret;
630 
631 	ret = virtio_media_send_w_ioctl(fh, VIDIOC_UNSUBSCRIBE_EVENT, sub,
632 					sizeof(*sub));
633 	if (ret < 0)
634 		return ret;
635 
636 	ret = v4l2_event_unsubscribe(fh, sub);
637 	if (ret)
638 		return ret;
639 
640 	return 0;
641 }
642 
643 /*
644  * Streamon/off affect the local queue state.
645  */
646 
virtio_media_streamon(struct file * file,void * fh,enum v4l2_buf_type i)647 static int virtio_media_streamon(struct file *file, void *fh,
648 				 enum v4l2_buf_type i)
649 {
650 	struct virtio_media_session *session = fh_to_session(fh);
651 	int ret;
652 
653 	if (i > VIRTIO_MEDIA_LAST_QUEUE)
654 		return -EINVAL;
655 
656 	ret = virtio_media_send_w_ioctl(fh, VIDIOC_STREAMON, &i, sizeof(i));
657 	if (ret < 0)
658 		return ret;
659 
660 	session->queues[i].streaming = true;
661 
662 	return 0;
663 }
664 
virtio_media_streamoff(struct file * file,void * fh,enum v4l2_buf_type i)665 static int virtio_media_streamoff(struct file *file, void *fh,
666 				  enum v4l2_buf_type i)
667 {
668 	struct video_device *video_dev = video_devdata(file);
669 	struct virtio_media *vv = to_virtio_media(video_dev);
670 	struct virtio_media_session *session = fh_to_session(fh);
671 	int ret;
672 
673 	if (i > VIRTIO_MEDIA_LAST_QUEUE) {
674 		return -EINVAL;
675 	}
676 
677 	ret = virtio_media_send_w_ioctl(fh, VIDIOC_STREAMOFF, &i, sizeof(i));
678 	if (ret < 0)
679 		return ret;
680 
681 	virtio_media_clear_queue(vv, session, &session->queues[i]);
682 
683 	return 0;
684 }
685 
686 /*
687  * Buffer creation/queuing functions deal with the local driver state.
688  */
689 
virtio_media_reqbufs(struct file * file,void * fh,struct v4l2_requestbuffers * b)690 static int virtio_media_reqbufs(struct file *file, void *fh,
691 				struct v4l2_requestbuffers *b)
692 {
693 	struct video_device *video_dev = video_devdata(file);
694 	struct virtio_media *vv = to_virtio_media(video_dev);
695 	struct virtio_media_session *session = fh_to_session(fh);
696 	struct virtio_media_queue_state *queue;
697 	int ret;
698 
699 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE)
700 		return -EINVAL;
701 
702 	ret = virtio_media_send_wr_ioctl(fh, VIDIOC_REQBUFS, b, sizeof(*b),
703 					 sizeof(*b));
704 	if (ret)
705 		return ret;
706 
707 	queue = &session->queues[b->type];
708 
709 	/* REQBUFS(0) is an implicit STREAMOFF. */
710 	if (b->count == 0) {
711 		virtio_media_clear_queue(vv, session, queue);
712 	}
713 
714 	vfree(queue->buffers);
715 	queue->buffers = NULL;
716 
717 	if (b->count > 0) {
718 		queue->buffers =
719 			vzalloc(sizeof(struct virtio_media_buffer) * b->count);
720 		if (!queue->buffers) {
721 			return -ENOMEM;
722 		}
723 	}
724 
725 	queue->allocated_bufs = b->count;
726 
727 	/*
728 	 * If a multiplanar queue is successfully used here, this means
729 	 * we are using the multiplanar interface.
730 	 */
731 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
732 		session->uses_mplane = true;
733 	}
734 
735 	/* TODO remove once we support DMABUFs */
736 	b->capabilities &= ~V4L2_BUF_CAP_SUPPORTS_DMABUF;
737 
738 	return 0;
739 }
740 
virtio_media_querybuf(struct file * file,void * fh,struct v4l2_buffer * b)741 static int virtio_media_querybuf(struct file *file, void *fh,
742 				 struct v4l2_buffer *b)
743 {
744 	struct virtio_media_session *session = fh_to_session(fh);
745 	struct virtio_media_queue_state *queue;
746 	struct virtio_media_buffer *buffer;
747 	int ret;
748 
749 	ret = virtio_media_send_buffer_ioctl(fh, VIDIOC_QUERYBUF, b);
750 	if (ret)
751 		return ret;
752 
753 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE) {
754 		return -EINVAL;
755 	}
756 	queue = &session->queues[b->type];
757 	if (b->index >= queue->allocated_bufs) {
758 		return -EINVAL;
759 	}
760 	buffer = &queue->buffers[b->index];
761 	/* Set the DONE flag if the buffer is waiting in our own dequeue queue. */
762 	b->flags |= (buffer->buffer.flags & V4L2_BUF_FLAG_DONE);
763 
764 	return 0;
765 }
766 
virtio_media_create_bufs(struct file * file,void * fh,struct v4l2_create_buffers * b)767 static int virtio_media_create_bufs(struct file *file, void *fh,
768 				    struct v4l2_create_buffers *b)
769 {
770 	struct virtio_media_session *session = fh_to_session(fh);
771 	struct virtio_media_queue_state *queue;
772 	struct virtio_media_buffer *buffers;
773 	u32 type = b->format.type;
774 	int ret;
775 
776 	if (type > VIRTIO_MEDIA_LAST_QUEUE)
777 		return -EINVAL;
778 
779 	queue = &session->queues[type];
780 
781 	ret = virtio_media_send_wr_ioctl(fh, VIDIOC_CREATE_BUFS, b, sizeof(*b),
782 					 sizeof(*b));
783 	if (ret)
784 		return ret;
785 
786 	/* If count is zero, we were just checking for format. */
787 	if (b->count == 0)
788 		return 0;
789 
790 	buffers = queue->buffers;
791 
792 	queue->buffers = vzalloc(sizeof(struct virtio_media_buffer) *
793 				 (b->index + b->count));
794 	if (!queue->buffers) {
795 		queue->buffers = buffers;
796 		return -ENOMEM;
797 	}
798 
799 	memcpy(queue->buffers, buffers,
800 	       sizeof(*buffers) * queue->allocated_bufs);
801 	vfree(buffers);
802 
803 	queue->allocated_bufs = b->index + b->count;
804 
805 	return 0;
806 }
807 
virtio_media_prepare_buf(struct file * file,void * fh,struct v4l2_buffer * b)808 static int virtio_media_prepare_buf(struct file *file, void *fh,
809 				    struct v4l2_buffer *b)
810 {
811 	struct virtio_media_session *session = fh_to_session(fh);
812 	struct virtio_media_queue_state *queue;
813 	struct virtio_media_buffer *buffer;
814 	int i, ret;
815 
816 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE)
817 		return -EINVAL;
818 	queue = &session->queues[b->type];
819 	if (b->index >= queue->allocated_bufs)
820 		return -EINVAL;
821 	buffer = &queue->buffers[b->index];
822 
823 	buffer->buffer.m = b->m;
824 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
825 		if (b->length > VIDEO_MAX_PLANES)
826 			return -EINVAL;
827 		for (i = 0; i < b->length; i++)
828 			buffer->planes[i].m = b->m.planes[i].m;
829 	}
830 
831 	ret = virtio_media_send_buffer_ioctl(fh, VIDIOC_PREPARE_BUF, b);
832 	if (ret)
833 		return ret;
834 
835 	buffer->buffer.flags = V4L2_BUF_FLAG_PREPARED;
836 
837 	return 0;
838 }
839 
virtio_media_qbuf(struct file * file,void * fh,struct v4l2_buffer * b)840 static int virtio_media_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
841 {
842 	struct virtio_media_session *session = fh_to_session(fh);
843 	struct virtio_media_queue_state *queue;
844 	struct virtio_media_buffer *buffer;
845 	bool prepared;
846 	u32 old_flags;
847 	int i, ret;
848 
849 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE)
850 		return -EINVAL;
851 	queue = &session->queues[b->type];
852 	if (b->index >= queue->allocated_bufs)
853 		return -EINVAL;
854 	buffer = &queue->buffers[b->index];
855 	prepared = buffer->buffer.flags & V4L2_BUF_FLAG_PREPARED;
856 
857 	/*
858 	 * Store the buffer and plane `m` information so we can retrieve it again
859 	 * when DQBUF occurs.
860 	 */
861 	if (!prepared) {
862 		buffer->buffer.m = b->m;
863 		if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
864 			if (b->length > VIDEO_MAX_PLANES)
865 				return -EINVAL;
866 			for (i = 0; i < b->length; i++)
867 				buffer->planes[i].m = b->m.planes[i].m;
868 		}
869 	}
870 	old_flags = buffer->buffer.flags;
871 	buffer->buffer.flags = V4L2_BUF_FLAG_QUEUED;
872 
873 	ret = virtio_media_send_buffer_ioctl(fh, VIDIOC_QBUF, b);
874 	if (ret) {
875 		/* Rollback the previous flags as the buffer is not queued. */
876 		buffer->buffer.flags = old_flags;
877 		return ret;
878 	}
879 
880 	queue->queued_bufs += 1;
881 
882 	return 0;
883 }
884 
virtio_media_dqbuf(struct file * file,void * fh,struct v4l2_buffer * b)885 static int virtio_media_dqbuf(struct file *file, void *fh,
886 			      struct v4l2_buffer *b)
887 {
888 	struct virtio_media_session *session =
889 		fh_to_session(file->private_data);
890 	struct video_device *video_dev = video_devdata(file);
891 	struct virtio_media *vv = to_virtio_media(video_dev);
892 	struct virtio_media_buffer *dqbuf;
893 	struct virtio_media_queue_state *queue;
894 	struct list_head *buffer_queue;
895 	struct v4l2_plane *planes_backup = NULL;
896 	const bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(b->type);
897 	int ret;
898 
899 	if (b->type > VIRTIO_MEDIA_LAST_QUEUE)
900 		return -EINVAL;
901 
902 	queue = &session->queues[b->type];
903 
904 	/*
905 	 * If a buffer with the LAST flag has been returned, subsequent calls to DQBUF
906 	 * must return -EPIPE until the queue is cleared.
907 	 */
908 	if (queue->is_capture_last)
909 		return -EPIPE;
910 
911 	buffer_queue = &queue->pending_dqbufs;
912 
913 	if (session->nonblocking_dequeue) {
914 		if (list_empty(buffer_queue))
915 			return -EAGAIN;
916 	} else if (queue->allocated_bufs == 0) {
917 		return -EINVAL;
918 	} else if (!queue->streaming) {
919 		return -EINVAL;
920 	} else {
921 		mutex_unlock(&vv->vlock);
922 		ret = wait_event_interruptible(session->dqbufs_wait,
923 					       !list_empty(buffer_queue));
924 		mutex_lock(&vv->vlock);
925 		if (ret)
926 			return -EINTR;
927 	}
928 
929 	mutex_lock(&session->dqbufs_lock);
930 	dqbuf = list_first_entry(buffer_queue, struct virtio_media_buffer,
931 				 list);
932 	list_del(&dqbuf->list);
933 	mutex_unlock(&session->dqbufs_lock);
934 
935 	/* Clear the DONE flag as the buffer is now being dequeued. */
936 	dqbuf->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
937 
938 	if (is_multiplanar) {
939 		size_t nb_planes = min(b->length, (u32)VIDEO_MAX_PLANES);
940 		memcpy(b->m.planes, dqbuf->planes,
941 		       nb_planes * sizeof(struct v4l2_plane));
942 		planes_backup = b->m.planes;
943 	}
944 
945 	memcpy(b, &dqbuf->buffer, sizeof(*b));
946 
947 	if (is_multiplanar) {
948 		b->m.planes = planes_backup;
949 	}
950 
951 	if (V4L2_TYPE_IS_CAPTURE(b->type) && b->flags & V4L2_BUF_FLAG_LAST) {
952 		queue->is_capture_last = true;
953 	}
954 
955 	return 0;
956 }
957 
958 /*
959  * s/g_input/output work with an unsigned int - recast this to a u32 so the
960  * size is unambiguous.
961  */
962 
virtio_media_g_input(struct file * file,void * fh,unsigned int * i)963 static int virtio_media_g_input(struct file *file, void *fh, unsigned int *i)
964 {
965 	u32 input;
966 	int ret;
967 
968 	ret = virtio_media_send_wr_ioctl(fh, VIDIOC_G_INPUT, &input,
969 					 sizeof(input), sizeof(input));
970 	if (ret)
971 		return ret;
972 
973 	*i = input;
974 
975 	return 0;
976 }
977 
virtio_media_s_input(struct file * file,void * fh,unsigned int i)978 static int virtio_media_s_input(struct file *file, void *fh, unsigned int i)
979 {
980 	u32 input = i;
981 
982 	return virtio_media_send_wr_ioctl(fh, VIDIOC_S_INPUT, &input,
983 					  sizeof(input), sizeof(input));
984 }
985 
virtio_media_g_output(struct file * file,void * fh,unsigned int * o)986 static int virtio_media_g_output(struct file *file, void *fh, unsigned int *o)
987 {
988 	u32 output;
989 	int ret;
990 
991 	ret = virtio_media_send_wr_ioctl(fh, VIDIOC_G_OUTPUT, &output,
992 					 sizeof(output), sizeof(output));
993 	if (ret)
994 		return ret;
995 
996 	*o = output;
997 
998 	return 0;
999 }
1000 
virtio_media_s_output(struct file * file,void * fh,unsigned int o)1001 static int virtio_media_s_output(struct file *file, void *fh, unsigned int o)
1002 {
1003 	u32 output = o;
1004 
1005 	return virtio_media_send_wr_ioctl(fh, VIDIOC_S_OUTPUT, &output,
1006 					  sizeof(output), sizeof(output));
1007 }
1008 
1009 /*
1010  * decoder_cmd can affect the state of the CAPTURE queue.
1011  */
1012 
virtio_media_decoder_cmd(struct file * file,void * fh,struct v4l2_decoder_cmd * cmd)1013 static int virtio_media_decoder_cmd(struct file *file, void *fh,
1014 				    struct v4l2_decoder_cmd *cmd)
1015 {
1016 	struct virtio_media_session *session = fh_to_session(fh);
1017 	int ret;
1018 
1019 	ret = virtio_media_send_wr_ioctl(fh, VIDIOC_DECODER_CMD, cmd,
1020 					 sizeof(*cmd), sizeof(*cmd));
1021 	if (ret)
1022 		return ret;
1023 
1024 	/* A START command makes the CAPTURE queue able to dequeue again. */
1025 	if (cmd->cmd == V4L2_DEC_CMD_START) {
1026 		session->queues[V4L2_BUF_TYPE_VIDEO_CAPTURE].is_capture_last =
1027 			false;
1028 		session->queues[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE]
1029 			.is_capture_last = false;
1030 	}
1031 
1032 	return 0;
1033 }
1034 
1035 /*
1036  * s_std doesn't work with a pointer, so we cannot use SIMPLE_W_IOCTL.
1037  */
1038 
virtio_media_s_std(struct file * file,void * fh,v4l2_std_id s)1039 static int virtio_media_s_std(struct file *file, void *fh, v4l2_std_id s)
1040 {
1041 	int ret;
1042 
1043 	ret = virtio_media_send_w_ioctl(fh, VIDIOC_S_STD, &s, sizeof(s));
1044 	if (ret)
1045 		return ret;
1046 
1047 	return 0;
1048 }
1049 
1050 const struct v4l2_ioctl_ops virtio_media_ioctl_ops = {
1051 	/* VIDIOC_QUERYCAP handler */
1052 	.vidioc_querycap = virtio_media_querycap,
1053 
1054 	/* VIDIOC_ENUM_FMT handlers */
1055 	.vidioc_enum_fmt_vid_cap = virtio_media_enum_fmt,
1056 	.vidioc_enum_fmt_vid_overlay = virtio_media_enum_fmt,
1057 	.vidioc_enum_fmt_vid_out = virtio_media_enum_fmt,
1058 	.vidioc_enum_fmt_sdr_cap = virtio_media_enum_fmt,
1059 	.vidioc_enum_fmt_sdr_out = virtio_media_enum_fmt,
1060 	.vidioc_enum_fmt_meta_cap = virtio_media_enum_fmt,
1061 	.vidioc_enum_fmt_meta_out = virtio_media_enum_fmt,
1062 
1063 	/* VIDIOC_G_FMT handlers */
1064 	.vidioc_g_fmt_vid_cap = virtio_media_g_fmt,
1065 	.vidioc_g_fmt_vid_overlay = virtio_media_g_fmt,
1066 	.vidioc_g_fmt_vid_out = virtio_media_g_fmt,
1067 	.vidioc_g_fmt_vid_out_overlay = virtio_media_g_fmt,
1068 	.vidioc_g_fmt_vbi_cap = virtio_media_g_fmt,
1069 	.vidioc_g_fmt_vbi_out = virtio_media_g_fmt,
1070 	.vidioc_g_fmt_sliced_vbi_cap = virtio_media_g_fmt,
1071 	.vidioc_g_fmt_sliced_vbi_out = virtio_media_g_fmt,
1072 	.vidioc_g_fmt_vid_cap_mplane = virtio_media_g_fmt,
1073 	.vidioc_g_fmt_vid_out_mplane = virtio_media_g_fmt,
1074 	.vidioc_g_fmt_sdr_cap = virtio_media_g_fmt,
1075 	.vidioc_g_fmt_sdr_out = virtio_media_g_fmt,
1076 	.vidioc_g_fmt_meta_cap = virtio_media_g_fmt,
1077 	.vidioc_g_fmt_meta_out = virtio_media_g_fmt,
1078 
1079 	/* VIDIOC_S_FMT handlers */
1080 	.vidioc_s_fmt_vid_cap = virtio_media_s_fmt,
1081 	.vidioc_s_fmt_vid_overlay = virtio_media_s_fmt,
1082 	.vidioc_s_fmt_vid_out = virtio_media_s_fmt,
1083 	.vidioc_s_fmt_vid_out_overlay = virtio_media_s_fmt,
1084 	.vidioc_s_fmt_vbi_cap = virtio_media_s_fmt,
1085 	.vidioc_s_fmt_vbi_out = virtio_media_s_fmt,
1086 	.vidioc_s_fmt_sliced_vbi_cap = virtio_media_s_fmt,
1087 	.vidioc_s_fmt_sliced_vbi_out = virtio_media_s_fmt,
1088 	.vidioc_s_fmt_vid_cap_mplane = virtio_media_s_fmt,
1089 	.vidioc_s_fmt_vid_out_mplane = virtio_media_s_fmt,
1090 	.vidioc_s_fmt_sdr_cap = virtio_media_s_fmt,
1091 	.vidioc_s_fmt_sdr_out = virtio_media_s_fmt,
1092 	.vidioc_s_fmt_meta_cap = virtio_media_s_fmt,
1093 	.vidioc_s_fmt_meta_out = virtio_media_s_fmt,
1094 
1095 	/* VIDIOC_TRY_FMT handlers */
1096 	.vidioc_try_fmt_vid_cap = virtio_media_try_fmt,
1097 	.vidioc_try_fmt_vid_overlay = virtio_media_try_fmt,
1098 	.vidioc_try_fmt_vid_out = virtio_media_try_fmt,
1099 	.vidioc_try_fmt_vid_out_overlay = virtio_media_try_fmt,
1100 	.vidioc_try_fmt_vbi_cap = virtio_media_try_fmt,
1101 	.vidioc_try_fmt_vbi_out = virtio_media_try_fmt,
1102 	.vidioc_try_fmt_sliced_vbi_cap = virtio_media_try_fmt,
1103 	.vidioc_try_fmt_sliced_vbi_out = virtio_media_try_fmt,
1104 	.vidioc_try_fmt_vid_cap_mplane = virtio_media_try_fmt,
1105 	.vidioc_try_fmt_vid_out_mplane = virtio_media_try_fmt,
1106 	.vidioc_try_fmt_sdr_cap = virtio_media_try_fmt,
1107 	.vidioc_try_fmt_sdr_out = virtio_media_try_fmt,
1108 	.vidioc_try_fmt_meta_cap = virtio_media_try_fmt,
1109 	.vidioc_try_fmt_meta_out = virtio_media_try_fmt,
1110 
1111 	/* Buffer handlers */
1112 	.vidioc_reqbufs = virtio_media_reqbufs,
1113 	.vidioc_querybuf = virtio_media_querybuf,
1114 	.vidioc_qbuf = virtio_media_qbuf,
1115 	.vidioc_expbuf = NULL,
1116 	.vidioc_dqbuf = virtio_media_dqbuf,
1117 	.vidioc_create_bufs = virtio_media_create_bufs,
1118 	.vidioc_prepare_buf = virtio_media_prepare_buf,
1119 	/* Overlay interface not supported yet */
1120 	.vidioc_overlay = NULL,
1121 	/* Overlay interface not supported yet */
1122 	.vidioc_g_fbuf = NULL,
1123 	/* Overlay interface not supported yet */
1124 	.vidioc_s_fbuf = NULL,
1125 
1126 	/* Stream on/off */
1127 	.vidioc_streamon = virtio_media_streamon,
1128 	.vidioc_streamoff = virtio_media_streamoff,
1129 
1130 	/* Standard handling */
1131 	.vidioc_g_std = virtio_media_g_std,
1132 	.vidioc_s_std = virtio_media_s_std,
1133 	.vidioc_querystd = virtio_media_querystd,
1134 
1135 	/* Input handling */
1136 	.vidioc_enum_input = virtio_media_enuminput,
1137 	.vidioc_g_input = virtio_media_g_input,
1138 	.vidioc_s_input = virtio_media_s_input,
1139 
1140 	/* Output handling */
1141 	.vidioc_enum_output = virtio_media_enumoutput,
1142 	.vidioc_g_output = virtio_media_g_output,
1143 	.vidioc_s_output = virtio_media_s_output,
1144 
1145 	/* Control handling */
1146 	.vidioc_queryctrl = virtio_media_queryctrl,
1147 	.vidioc_query_ext_ctrl = virtio_media_query_ext_ctrl,
1148 	.vidioc_g_ctrl = virtio_media_g_ctrl,
1149 	.vidioc_s_ctrl = virtio_media_s_ctrl,
1150 	.vidioc_g_ext_ctrls = virtio_media_g_ext_ctrls,
1151 	.vidioc_s_ext_ctrls = virtio_media_s_ext_ctrls,
1152 	.vidioc_try_ext_ctrls = virtio_media_try_ext_ctrls,
1153 	.vidioc_querymenu = virtio_media_querymenu,
1154 
1155 	/* Audio ioctls */
1156 	.vidioc_enumaudio = virtio_media_enumaudio,
1157 	.vidioc_g_audio = virtio_media_g_audio,
1158 	.vidioc_s_audio = virtio_media_s_audio,
1159 
1160 	/* Audio out ioctls */
1161 	.vidioc_enumaudout = virtio_media_enumaudout,
1162 	.vidioc_g_audout = virtio_media_g_audout,
1163 	.vidioc_s_audout = virtio_media_s_audout,
1164 	.vidioc_g_modulator = virtio_media_g_modulator,
1165 	.vidioc_s_modulator = virtio_media_s_modulator,
1166 
1167 	/* Crop ioctls */
1168 	/* Not directly an ioctl (part of VIDIOC_CROPCAP), so no need to implement */
1169 	.vidioc_g_pixelaspect = NULL,
1170 	.vidioc_g_selection = virtio_media_g_selection,
1171 	.vidioc_s_selection = virtio_media_s_selection,
1172 
1173 	/* Compression ioctls */
1174 	/* Deprecated in V4L2. */
1175 	.vidioc_g_jpegcomp = NULL,
1176 	/* Deprecated in V4L2. */
1177 	.vidioc_s_jpegcomp = NULL,
1178 	.vidioc_g_enc_index = virtio_media_g_enc_index,
1179 	.vidioc_encoder_cmd = virtio_media_encoder_cmd,
1180 	.vidioc_try_encoder_cmd = virtio_media_try_encoder_cmd,
1181 	.vidioc_decoder_cmd = virtio_media_decoder_cmd,
1182 	.vidioc_try_decoder_cmd = virtio_media_try_decoder_cmd,
1183 
1184 	/* Stream type-dependent parameter ioctls */
1185 	.vidioc_g_parm = virtio_media_g_parm,
1186 	.vidioc_s_parm = virtio_media_s_parm,
1187 
1188 	/* Tuner ioctls */
1189 	.vidioc_g_tuner = virtio_media_g_tuner,
1190 	.vidioc_s_tuner = virtio_media_s_tuner,
1191 	.vidioc_g_frequency = virtio_media_g_frequency,
1192 	.vidioc_s_frequency = virtio_media_s_frequency,
1193 	.vidioc_enum_freq_bands = virtio_media_enum_freq_bands,
1194 
1195 	/* Sliced VBI cap */
1196 	.vidioc_g_sliced_vbi_cap = virtio_media_g_sliced_vbi_cap,
1197 
1198 	/* Log status ioctl */
1199 	/* Guest-only operation */
1200 	.vidioc_log_status = NULL,
1201 
1202 	.vidioc_s_hw_freq_seek = virtio_media_s_hw_freq_seek,
1203 
1204 	.vidioc_enum_framesizes = virtio_media_enum_framesizes,
1205 	.vidioc_enum_frameintervals = virtio_media_enum_frameintervals,
1206 
1207 	/* DV Timings IOCTLs */
1208 	.vidioc_s_dv_timings = virtio_media_s_dv_timings,
1209 	.vidioc_g_dv_timings = virtio_media_g_dv_timings,
1210 	.vidioc_query_dv_timings = virtio_media_query_dv_timings,
1211 	.vidioc_enum_dv_timings = virtio_media_enum_dv_timings,
1212 	.vidioc_dv_timings_cap = virtio_media_dv_timings_cap,
1213 	.vidioc_g_edid = NULL,
1214 	.vidioc_s_edid = NULL,
1215 
1216 	.vidioc_subscribe_event = virtio_media_subscribe_event,
1217 	.vidioc_unsubscribe_event = virtio_media_unsubscribe_event,
1218 
1219 	/* For other private ioctls */
1220 	.vidioc_default = NULL,
1221 };
1222 
virtio_media_device_ioctl(struct file * file,unsigned int cmd,unsigned long arg)1223 long virtio_media_device_ioctl(struct file *file, unsigned int cmd,
1224 			       unsigned long arg)
1225 {
1226 	struct video_device *video_dev = video_devdata(file);
1227 	struct virtio_media *vv = to_virtio_media(video_dev);
1228 	struct v4l2_fh *vfh = NULL;
1229 	struct v4l2_standard standard;
1230 	v4l2_std_id std_id = 0;
1231 	int ret;
1232 
1233 	if (test_bit(V4L2_FL_USES_V4L2_FH, &video_dev->flags))
1234 		vfh = file->private_data;
1235 
1236 	mutex_lock(&vv->vlock);
1237 
1238 	/*
1239 	 * We need to handle a few ioctls manually because their result rely on
1240 	 * vfd->tvnorms, which is normally updated by the driver as S_INPUT is
1241 	 * called. Since we want to just pass these ioctls through, we have to hijack
1242 	 * them from here.
1243 	 */
1244 	switch (cmd) {
1245 	case VIDIOC_S_STD:
1246 		ret = copy_from_user(&std_id, (void __user *)arg,
1247 				     sizeof(std_id));
1248 		if (ret) {
1249 			ret = -EINVAL;
1250 			break;
1251 		}
1252 		ret = virtio_media_s_std(file, vfh, std_id);
1253 		break;
1254 	case VIDIOC_ENUMSTD:
1255 		ret = copy_from_user(&standard, (void __user *)arg,
1256 				     sizeof(standard));
1257 		if (ret) {
1258 			ret = -EINVAL;
1259 			break;
1260 		}
1261 		ret = virtio_media_enumstd(file, vfh, &standard);
1262 		if (ret)
1263 			break;
1264 		ret = copy_to_user((void __user *)arg, &standard,
1265 				   sizeof(standard));
1266 		if (ret)
1267 			ret = -EINVAL;
1268 		break;
1269 	case VIDIOC_QUERYSTD:
1270 		ret = virtio_media_querystd(file, vfh, &std_id);
1271 		if (ret)
1272 			break;
1273 		ret = copy_to_user((void __user *)arg, &std_id, sizeof(std_id));
1274 		if (ret)
1275 			ret = -EINVAL;
1276 		break;
1277 	default:
1278 		ret = video_ioctl2(file, cmd, arg);
1279 		break;
1280 	}
1281 
1282 	mutex_unlock(&vv->vlock);
1283 
1284 	return ret;
1285 }
1286