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