1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/compat.h>
15#include <linux/kernel.h>
16#include <linux/list.h>
17#include <linux/module.h>
18#include <linux/slab.h>
19#include <linux/usb.h>
20#include <linux/videodev2.h>
21#include <linux/vmalloc.h>
22#include <linux/mm.h>
23#include <linux/wait.h>
24#include <linux/atomic.h>
25
26#include <media/v4l2-common.h>
27#include <media/v4l2-ctrls.h>
28#include <media/v4l2-event.h>
29#include <media/v4l2-ioctl.h>
30
31#include "uvcvideo.h"
32
33
34
35
36static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
37 struct uvc_xu_control_mapping *xmap)
38{
39 struct uvc_control_mapping *map;
40 unsigned int size;
41 int ret;
42
43 map = kzalloc(sizeof *map, GFP_KERNEL);
44 if (map == NULL)
45 return -ENOMEM;
46
47 map->id = xmap->id;
48 memcpy(map->name, xmap->name, sizeof map->name);
49 memcpy(map->entity, xmap->entity, sizeof map->entity);
50 map->selector = xmap->selector;
51 map->size = xmap->size;
52 map->offset = xmap->offset;
53 map->v4l2_type = xmap->v4l2_type;
54 map->data_type = xmap->data_type;
55
56 switch (xmap->v4l2_type) {
57 case V4L2_CTRL_TYPE_INTEGER:
58 case V4L2_CTRL_TYPE_BOOLEAN:
59 case V4L2_CTRL_TYPE_BUTTON:
60 break;
61
62 case V4L2_CTRL_TYPE_MENU:
63
64
65
66 if (xmap->menu_count == 0 ||
67 xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
68 ret = -EINVAL;
69 goto free_map;
70 }
71
72 size = xmap->menu_count * sizeof(*map->menu_info);
73 map->menu_info = memdup_user(xmap->menu_info, size);
74 if (IS_ERR(map->menu_info)) {
75 ret = PTR_ERR(map->menu_info);
76 goto free_map;
77 }
78
79 map->menu_count = xmap->menu_count;
80 break;
81
82 default:
83 uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
84 "%u.\n", xmap->v4l2_type);
85 ret = -ENOTTY;
86 goto free_map;
87 }
88
89 ret = uvc_ctrl_add_mapping(chain, map);
90
91 kfree(map->menu_info);
92free_map:
93 kfree(map);
94
95 return ret;
96}
97
98
99
100
101
102
103
104
105
106
107
108static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
109{
110 unsigned int i;
111
112 if (frame->bFrameIntervalType) {
113 __u32 best = -1, dist;
114
115 for (i = 0; i < frame->bFrameIntervalType; ++i) {
116 dist = interval > frame->dwFrameInterval[i]
117 ? interval - frame->dwFrameInterval[i]
118 : frame->dwFrameInterval[i] - interval;
119
120 if (dist > best)
121 break;
122
123 best = dist;
124 }
125
126 interval = frame->dwFrameInterval[i-1];
127 } else {
128 const __u32 min = frame->dwFrameInterval[0];
129 const __u32 max = frame->dwFrameInterval[1];
130 const __u32 step = frame->dwFrameInterval[2];
131
132 interval = min + (interval - min + step/2) / step * step;
133 if (interval > max)
134 interval = max;
135 }
136
137 return interval;
138}
139
140static __u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format,
141 const struct uvc_frame *frame)
142{
143 switch (format->fcc) {
144 case V4L2_PIX_FMT_NV12:
145 case V4L2_PIX_FMT_YVU420:
146 case V4L2_PIX_FMT_YUV420:
147 case V4L2_PIX_FMT_M420:
148 return frame->wWidth;
149
150 default:
151 return format->bpp * frame->wWidth / 8;
152 }
153}
154
155static int uvc_v4l2_try_format(struct uvc_streaming *stream,
156 struct v4l2_format *fmt, struct uvc_streaming_control *probe,
157 struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
158{
159 struct uvc_format *format = NULL;
160 struct uvc_frame *frame = NULL;
161 __u16 rw, rh;
162 unsigned int d, maxd;
163 unsigned int i;
164 __u32 interval;
165 int ret = 0;
166 __u8 *fcc;
167
168 if (fmt->type != stream->type)
169 return -EINVAL;
170
171 fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
172 uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
173 fmt->fmt.pix.pixelformat,
174 fcc[0], fcc[1], fcc[2], fcc[3],
175 fmt->fmt.pix.width, fmt->fmt.pix.height);
176
177
178
179
180 for (i = 0; i < stream->nformats; ++i) {
181 format = &stream->format[i];
182 if (format->fcc == fmt->fmt.pix.pixelformat)
183 break;
184 }
185
186 if (i == stream->nformats) {
187 format = stream->def_format;
188 fmt->fmt.pix.pixelformat = format->fcc;
189 }
190
191
192
193
194
195 rw = fmt->fmt.pix.width;
196 rh = fmt->fmt.pix.height;
197 maxd = (unsigned int)-1;
198
199 for (i = 0; i < format->nframes; ++i) {
200 __u16 w = format->frame[i].wWidth;
201 __u16 h = format->frame[i].wHeight;
202
203 d = min(w, rw) * min(h, rh);
204 d = w*h + rw*rh - 2*d;
205 if (d < maxd) {
206 maxd = d;
207 frame = &format->frame[i];
208 }
209
210 if (maxd == 0)
211 break;
212 }
213
214 if (frame == NULL) {
215 uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
216 fmt->fmt.pix.width, fmt->fmt.pix.height);
217 return -EINVAL;
218 }
219
220
221 interval = frame->dwDefaultFrameInterval;
222 uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
223 "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
224 (100000000/interval)%10);
225
226
227 memset(probe, 0, sizeof *probe);
228 probe->bmHint = 1;
229 probe->bFormatIndex = format->index;
230 probe->bFrameIndex = frame->bFrameIndex;
231 probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
232
233
234
235
236
237
238
239
240
241
242
243
244 mutex_lock(&stream->mutex);
245 if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
246 probe->dwMaxVideoFrameSize =
247 stream->ctrl.dwMaxVideoFrameSize;
248
249
250 ret = uvc_probe_video(stream, probe);
251 mutex_unlock(&stream->mutex);
252 if (ret < 0)
253 goto done;
254
255 fmt->fmt.pix.width = frame->wWidth;
256 fmt->fmt.pix.height = frame->wHeight;
257 fmt->fmt.pix.field = V4L2_FIELD_NONE;
258 fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame);
259 fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
260 fmt->fmt.pix.colorspace = format->colorspace;
261 fmt->fmt.pix.priv = 0;
262
263 if (uvc_format != NULL)
264 *uvc_format = format;
265 if (uvc_frame != NULL)
266 *uvc_frame = frame;
267
268done:
269 return ret;
270}
271
272static int uvc_v4l2_get_format(struct uvc_streaming *stream,
273 struct v4l2_format *fmt)
274{
275 struct uvc_format *format;
276 struct uvc_frame *frame;
277 int ret = 0;
278
279 if (fmt->type != stream->type)
280 return -EINVAL;
281
282 mutex_lock(&stream->mutex);
283 format = stream->cur_format;
284 frame = stream->cur_frame;
285
286 if (format == NULL || frame == NULL) {
287 ret = -EINVAL;
288 goto done;
289 }
290
291 fmt->fmt.pix.pixelformat = format->fcc;
292 fmt->fmt.pix.width = frame->wWidth;
293 fmt->fmt.pix.height = frame->wHeight;
294 fmt->fmt.pix.field = V4L2_FIELD_NONE;
295 fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame);
296 fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
297 fmt->fmt.pix.colorspace = format->colorspace;
298 fmt->fmt.pix.priv = 0;
299
300done:
301 mutex_unlock(&stream->mutex);
302 return ret;
303}
304
305static int uvc_v4l2_set_format(struct uvc_streaming *stream,
306 struct v4l2_format *fmt)
307{
308 struct uvc_streaming_control probe;
309 struct uvc_format *format;
310 struct uvc_frame *frame;
311 int ret;
312
313 if (fmt->type != stream->type)
314 return -EINVAL;
315
316 ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
317 if (ret < 0)
318 return ret;
319
320 mutex_lock(&stream->mutex);
321
322 if (uvc_queue_allocated(&stream->queue)) {
323 ret = -EBUSY;
324 goto done;
325 }
326
327 stream->ctrl = probe;
328 stream->cur_format = format;
329 stream->cur_frame = frame;
330
331done:
332 mutex_unlock(&stream->mutex);
333 return ret;
334}
335
336static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
337 struct v4l2_streamparm *parm)
338{
339 uint32_t numerator, denominator;
340
341 if (parm->type != stream->type)
342 return -EINVAL;
343
344 mutex_lock(&stream->mutex);
345 numerator = stream->ctrl.dwFrameInterval;
346 mutex_unlock(&stream->mutex);
347
348 denominator = 10000000;
349 uvc_simplify_fraction(&numerator, &denominator, 8, 333);
350
351 memset(parm, 0, sizeof *parm);
352 parm->type = stream->type;
353
354 if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
355 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
356 parm->parm.capture.capturemode = 0;
357 parm->parm.capture.timeperframe.numerator = numerator;
358 parm->parm.capture.timeperframe.denominator = denominator;
359 parm->parm.capture.extendedmode = 0;
360 parm->parm.capture.readbuffers = 0;
361 } else {
362 parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
363 parm->parm.output.outputmode = 0;
364 parm->parm.output.timeperframe.numerator = numerator;
365 parm->parm.output.timeperframe.denominator = denominator;
366 }
367
368 return 0;
369}
370
371static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
372 struct v4l2_streamparm *parm)
373{
374 struct uvc_streaming_control probe;
375 struct v4l2_fract timeperframe;
376 uint32_t interval;
377 int ret;
378
379 if (parm->type != stream->type)
380 return -EINVAL;
381
382 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
383 timeperframe = parm->parm.capture.timeperframe;
384 else
385 timeperframe = parm->parm.output.timeperframe;
386
387 interval = uvc_fraction_to_interval(timeperframe.numerator,
388 timeperframe.denominator);
389 uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
390 timeperframe.numerator, timeperframe.denominator, interval);
391
392 mutex_lock(&stream->mutex);
393
394 if (uvc_queue_streaming(&stream->queue)) {
395 mutex_unlock(&stream->mutex);
396 return -EBUSY;
397 }
398
399 probe = stream->ctrl;
400 probe.dwFrameInterval =
401 uvc_try_frame_interval(stream->cur_frame, interval);
402
403
404 ret = uvc_probe_video(stream, &probe);
405 if (ret < 0) {
406 mutex_unlock(&stream->mutex);
407 return ret;
408 }
409
410 stream->ctrl = probe;
411 mutex_unlock(&stream->mutex);
412
413
414 timeperframe.numerator = probe.dwFrameInterval;
415 timeperframe.denominator = 10000000;
416 uvc_simplify_fraction(&timeperframe.numerator,
417 &timeperframe.denominator, 8, 333);
418
419 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
420 parm->parm.capture.timeperframe = timeperframe;
421 else
422 parm->parm.output.timeperframe = timeperframe;
423
424 return 0;
425}
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454static int uvc_acquire_privileges(struct uvc_fh *handle)
455{
456
457 if (handle->state == UVC_HANDLE_ACTIVE)
458 return 0;
459
460
461 if (atomic_inc_return(&handle->stream->active) != 1) {
462 atomic_dec(&handle->stream->active);
463 return -EBUSY;
464 }
465
466 handle->state = UVC_HANDLE_ACTIVE;
467 return 0;
468}
469
470static void uvc_dismiss_privileges(struct uvc_fh *handle)
471{
472 if (handle->state == UVC_HANDLE_ACTIVE)
473 atomic_dec(&handle->stream->active);
474
475 handle->state = UVC_HANDLE_PASSIVE;
476}
477
478static int uvc_has_privileges(struct uvc_fh *handle)
479{
480 return handle->state == UVC_HANDLE_ACTIVE;
481}
482
483
484
485
486
487static int uvc_v4l2_open(struct file *file)
488{
489 struct uvc_streaming *stream;
490 struct uvc_fh *handle;
491 int ret = 0;
492
493 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
494 stream = video_drvdata(file);
495
496 ret = usb_autopm_get_interface(stream->dev->intf);
497 if (ret < 0)
498 return ret;
499
500
501 handle = kzalloc(sizeof *handle, GFP_KERNEL);
502 if (handle == NULL) {
503 usb_autopm_put_interface(stream->dev->intf);
504 return -ENOMEM;
505 }
506
507 mutex_lock(&stream->dev->lock);
508 if (stream->dev->users == 0) {
509 ret = uvc_status_start(stream->dev, GFP_KERNEL);
510 if (ret < 0) {
511 mutex_unlock(&stream->dev->lock);
512 usb_autopm_put_interface(stream->dev->intf);
513 kfree(handle);
514 return ret;
515 }
516 }
517
518 stream->dev->users++;
519 mutex_unlock(&stream->dev->lock);
520
521 v4l2_fh_init(&handle->vfh, &stream->vdev);
522 v4l2_fh_add(&handle->vfh);
523 handle->chain = stream->chain;
524 handle->stream = stream;
525 handle->state = UVC_HANDLE_PASSIVE;
526 file->private_data = handle;
527
528 return 0;
529}
530
531static int uvc_v4l2_release(struct file *file)
532{
533 struct uvc_fh *handle = file->private_data;
534 struct uvc_streaming *stream = handle->stream;
535
536 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
537
538
539 if (uvc_has_privileges(handle))
540 uvc_queue_release(&stream->queue);
541
542
543 uvc_dismiss_privileges(handle);
544 v4l2_fh_del(&handle->vfh);
545 v4l2_fh_exit(&handle->vfh);
546 kfree(handle);
547 file->private_data = NULL;
548
549 mutex_lock(&stream->dev->lock);
550 if (--stream->dev->users == 0)
551 uvc_status_stop(stream->dev);
552 mutex_unlock(&stream->dev->lock);
553
554 usb_autopm_put_interface(stream->dev->intf);
555 return 0;
556}
557
558static int uvc_ioctl_querycap(struct file *file, void *fh,
559 struct v4l2_capability *cap)
560{
561 struct video_device *vdev = video_devdata(file);
562 struct uvc_fh *handle = file->private_data;
563 struct uvc_video_chain *chain = handle->chain;
564 struct uvc_streaming *stream = handle->stream;
565
566 strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
567 strlcpy(cap->card, vdev->name, sizeof(cap->card));
568 usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
569 cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
570 | chain->caps;
571 if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
572 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
573 else
574 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
575
576 return 0;
577}
578
579static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
580 struct v4l2_fmtdesc *fmt)
581{
582 struct uvc_format *format;
583 enum v4l2_buf_type type = fmt->type;
584 __u32 index = fmt->index;
585
586 if (fmt->type != stream->type || fmt->index >= stream->nformats)
587 return -EINVAL;
588
589 memset(fmt, 0, sizeof(*fmt));
590 fmt->index = index;
591 fmt->type = type;
592
593 format = &stream->format[fmt->index];
594 fmt->flags = 0;
595 if (format->flags & UVC_FMT_FLAG_COMPRESSED)
596 fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
597 strlcpy(fmt->description, format->name, sizeof(fmt->description));
598 fmt->description[sizeof(fmt->description) - 1] = 0;
599 fmt->pixelformat = format->fcc;
600 return 0;
601}
602
603static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,
604 struct v4l2_fmtdesc *fmt)
605{
606 struct uvc_fh *handle = fh;
607 struct uvc_streaming *stream = handle->stream;
608
609 return uvc_ioctl_enum_fmt(stream, fmt);
610}
611
612static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh,
613 struct v4l2_fmtdesc *fmt)
614{
615 struct uvc_fh *handle = fh;
616 struct uvc_streaming *stream = handle->stream;
617
618 return uvc_ioctl_enum_fmt(stream, fmt);
619}
620
621static int uvc_ioctl_g_fmt_vid_cap(struct file *file, void *fh,
622 struct v4l2_format *fmt)
623{
624 struct uvc_fh *handle = fh;
625 struct uvc_streaming *stream = handle->stream;
626
627 return uvc_v4l2_get_format(stream, fmt);
628}
629
630static int uvc_ioctl_g_fmt_vid_out(struct file *file, void *fh,
631 struct v4l2_format *fmt)
632{
633 struct uvc_fh *handle = fh;
634 struct uvc_streaming *stream = handle->stream;
635
636 return uvc_v4l2_get_format(stream, fmt);
637}
638
639static int uvc_ioctl_s_fmt_vid_cap(struct file *file, void *fh,
640 struct v4l2_format *fmt)
641{
642 struct uvc_fh *handle = fh;
643 struct uvc_streaming *stream = handle->stream;
644 int ret;
645
646 ret = uvc_acquire_privileges(handle);
647 if (ret < 0)
648 return ret;
649
650 return uvc_v4l2_set_format(stream, fmt);
651}
652
653static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh,
654 struct v4l2_format *fmt)
655{
656 struct uvc_fh *handle = fh;
657 struct uvc_streaming *stream = handle->stream;
658 int ret;
659
660 ret = uvc_acquire_privileges(handle);
661 if (ret < 0)
662 return ret;
663
664 return uvc_v4l2_set_format(stream, fmt);
665}
666
667static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh,
668 struct v4l2_format *fmt)
669{
670 struct uvc_fh *handle = fh;
671 struct uvc_streaming *stream = handle->stream;
672 struct uvc_streaming_control probe;
673
674 return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
675}
676
677static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh,
678 struct v4l2_format *fmt)
679{
680 struct uvc_fh *handle = fh;
681 struct uvc_streaming *stream = handle->stream;
682 struct uvc_streaming_control probe;
683
684 return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
685}
686
687static int uvc_ioctl_reqbufs(struct file *file, void *fh,
688 struct v4l2_requestbuffers *rb)
689{
690 struct uvc_fh *handle = fh;
691 struct uvc_streaming *stream = handle->stream;
692 int ret;
693
694 ret = uvc_acquire_privileges(handle);
695 if (ret < 0)
696 return ret;
697
698 mutex_lock(&stream->mutex);
699 ret = uvc_request_buffers(&stream->queue, rb);
700 mutex_unlock(&stream->mutex);
701 if (ret < 0)
702 return ret;
703
704 if (ret == 0)
705 uvc_dismiss_privileges(handle);
706
707 return 0;
708}
709
710static int uvc_ioctl_querybuf(struct file *file, void *fh,
711 struct v4l2_buffer *buf)
712{
713 struct uvc_fh *handle = fh;
714 struct uvc_streaming *stream = handle->stream;
715
716 if (!uvc_has_privileges(handle))
717 return -EBUSY;
718
719 return uvc_query_buffer(&stream->queue, buf);
720}
721
722static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
723{
724 struct uvc_fh *handle = fh;
725 struct uvc_streaming *stream = handle->stream;
726
727 if (!uvc_has_privileges(handle))
728 return -EBUSY;
729
730 return uvc_queue_buffer(&stream->queue, buf);
731}
732
733static int uvc_ioctl_expbuf(struct file *file, void *fh,
734 struct v4l2_exportbuffer *exp)
735{
736 struct uvc_fh *handle = fh;
737 struct uvc_streaming *stream = handle->stream;
738
739 if (!uvc_has_privileges(handle))
740 return -EBUSY;
741
742 return uvc_export_buffer(&stream->queue, exp);
743}
744
745static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
746{
747 struct uvc_fh *handle = fh;
748 struct uvc_streaming *stream = handle->stream;
749
750 if (!uvc_has_privileges(handle))
751 return -EBUSY;
752
753 return uvc_dequeue_buffer(&stream->queue, buf,
754 file->f_flags & O_NONBLOCK);
755}
756
757static int uvc_ioctl_create_bufs(struct file *file, void *fh,
758 struct v4l2_create_buffers *cb)
759{
760 struct uvc_fh *handle = fh;
761 struct uvc_streaming *stream = handle->stream;
762 int ret;
763
764 ret = uvc_acquire_privileges(handle);
765 if (ret < 0)
766 return ret;
767
768 return uvc_create_buffers(&stream->queue, cb);
769}
770
771static int uvc_ioctl_streamon(struct file *file, void *fh,
772 enum v4l2_buf_type type)
773{
774 struct uvc_fh *handle = fh;
775 struct uvc_streaming *stream = handle->stream;
776 int ret;
777
778 if (!uvc_has_privileges(handle))
779 return -EBUSY;
780
781 mutex_lock(&stream->mutex);
782 ret = uvc_queue_streamon(&stream->queue, type);
783 mutex_unlock(&stream->mutex);
784
785 return ret;
786}
787
788static int uvc_ioctl_streamoff(struct file *file, void *fh,
789 enum v4l2_buf_type type)
790{
791 struct uvc_fh *handle = fh;
792 struct uvc_streaming *stream = handle->stream;
793
794 if (!uvc_has_privileges(handle))
795 return -EBUSY;
796
797 mutex_lock(&stream->mutex);
798 uvc_queue_streamoff(&stream->queue, type);
799 mutex_unlock(&stream->mutex);
800
801 return 0;
802}
803
804static int uvc_ioctl_enum_input(struct file *file, void *fh,
805 struct v4l2_input *input)
806{
807 struct uvc_fh *handle = fh;
808 struct uvc_video_chain *chain = handle->chain;
809 const struct uvc_entity *selector = chain->selector;
810 struct uvc_entity *iterm = NULL;
811 u32 index = input->index;
812 int pin = 0;
813
814 if (selector == NULL ||
815 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
816 if (index != 0)
817 return -EINVAL;
818 list_for_each_entry(iterm, &chain->entities, chain) {
819 if (UVC_ENTITY_IS_ITERM(iterm))
820 break;
821 }
822 pin = iterm->id;
823 } else if (index < selector->bNrInPins) {
824 pin = selector->baSourceID[index];
825 list_for_each_entry(iterm, &chain->entities, chain) {
826 if (!UVC_ENTITY_IS_ITERM(iterm))
827 continue;
828 if (iterm->id == pin)
829 break;
830 }
831 }
832
833 if (iterm == NULL || iterm->id != pin)
834 return -EINVAL;
835
836 memset(input, 0, sizeof(*input));
837 input->index = index;
838 strlcpy(input->name, iterm->name, sizeof(input->name));
839 if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
840 input->type = V4L2_INPUT_TYPE_CAMERA;
841
842 return 0;
843}
844
845static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
846{
847 struct uvc_fh *handle = fh;
848 struct uvc_video_chain *chain = handle->chain;
849 int ret;
850 u8 i;
851
852 if (chain->selector == NULL ||
853 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
854 *input = 0;
855 return 0;
856 }
857
858 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
859 chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
860 &i, 1);
861 if (ret < 0)
862 return ret;
863
864 *input = i - 1;
865 return 0;
866}
867
868static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
869{
870 struct uvc_fh *handle = fh;
871 struct uvc_video_chain *chain = handle->chain;
872 int ret;
873 u32 i;
874
875 ret = uvc_acquire_privileges(handle);
876 if (ret < 0)
877 return ret;
878
879 if (chain->selector == NULL ||
880 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
881 if (input)
882 return -EINVAL;
883 return 0;
884 }
885
886 if (input >= chain->selector->bNrInPins)
887 return -EINVAL;
888
889 i = input + 1;
890 return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
891 chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
892 &i, 1);
893}
894
895static int uvc_ioctl_queryctrl(struct file *file, void *fh,
896 struct v4l2_queryctrl *qc)
897{
898 struct uvc_fh *handle = fh;
899 struct uvc_video_chain *chain = handle->chain;
900
901 return uvc_query_v4l2_ctrl(chain, qc);
902}
903
904static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh,
905 struct v4l2_query_ext_ctrl *qec)
906{
907 struct uvc_fh *handle = fh;
908 struct uvc_video_chain *chain = handle->chain;
909 struct v4l2_queryctrl qc = { qec->id };
910 int ret;
911
912 ret = uvc_query_v4l2_ctrl(chain, &qc);
913 if (ret)
914 return ret;
915
916 qec->id = qc.id;
917 qec->type = qc.type;
918 strlcpy(qec->name, qc.name, sizeof(qec->name));
919 qec->minimum = qc.minimum;
920 qec->maximum = qc.maximum;
921 qec->step = qc.step;
922 qec->default_value = qc.default_value;
923 qec->flags = qc.flags;
924 qec->elem_size = 4;
925 qec->elems = 1;
926 qec->nr_of_dims = 0;
927 memset(qec->dims, 0, sizeof(qec->dims));
928 memset(qec->reserved, 0, sizeof(qec->reserved));
929
930 return 0;
931}
932
933static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
934 struct v4l2_control *ctrl)
935{
936 struct uvc_fh *handle = fh;
937 struct uvc_video_chain *chain = handle->chain;
938 struct v4l2_ext_control xctrl;
939 int ret;
940
941 memset(&xctrl, 0, sizeof(xctrl));
942 xctrl.id = ctrl->id;
943
944 ret = uvc_ctrl_begin(chain);
945 if (ret < 0)
946 return ret;
947
948 ret = uvc_ctrl_get(chain, &xctrl);
949 uvc_ctrl_rollback(handle);
950 if (ret < 0)
951 return ret;
952
953 ctrl->value = xctrl.value;
954 return 0;
955}
956
957static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
958 struct v4l2_control *ctrl)
959{
960 struct uvc_fh *handle = fh;
961 struct uvc_video_chain *chain = handle->chain;
962 struct v4l2_ext_control xctrl;
963 int ret;
964
965 memset(&xctrl, 0, sizeof(xctrl));
966 xctrl.id = ctrl->id;
967 xctrl.value = ctrl->value;
968
969 ret = uvc_ctrl_begin(chain);
970 if (ret < 0)
971 return ret;
972
973 ret = uvc_ctrl_set(chain, &xctrl);
974 if (ret < 0) {
975 uvc_ctrl_rollback(handle);
976 return ret;
977 }
978
979 ret = uvc_ctrl_commit(handle, &xctrl, 1);
980 if (ret < 0)
981 return ret;
982
983 ctrl->value = xctrl.value;
984 return 0;
985}
986
987static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
988 struct v4l2_ext_controls *ctrls)
989{
990 struct uvc_fh *handle = fh;
991 struct uvc_video_chain *chain = handle->chain;
992 struct v4l2_ext_control *ctrl = ctrls->controls;
993 unsigned int i;
994 int ret;
995
996 if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
997 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
998 struct v4l2_queryctrl qc = { .id = ctrl->id };
999
1000 ret = uvc_query_v4l2_ctrl(chain, &qc);
1001 if (ret < 0) {
1002 ctrls->error_idx = i;
1003 return ret;
1004 }
1005
1006 ctrl->value = qc.default_value;
1007 }
1008
1009 return 0;
1010 }
1011
1012 ret = uvc_ctrl_begin(chain);
1013 if (ret < 0)
1014 return ret;
1015
1016 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
1017 ret = uvc_ctrl_get(chain, ctrl);
1018 if (ret < 0) {
1019 uvc_ctrl_rollback(handle);
1020 ctrls->error_idx = i;
1021 return ret;
1022 }
1023 }
1024
1025 ctrls->error_idx = 0;
1026
1027 return uvc_ctrl_rollback(handle);
1028}
1029
1030static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
1031 struct v4l2_ext_controls *ctrls,
1032 bool commit)
1033{
1034 struct v4l2_ext_control *ctrl = ctrls->controls;
1035 struct uvc_video_chain *chain = handle->chain;
1036 unsigned int i;
1037 int ret;
1038
1039
1040 if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL)
1041 return -EINVAL;
1042
1043 ret = uvc_ctrl_begin(chain);
1044 if (ret < 0)
1045 return ret;
1046
1047 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
1048 ret = uvc_ctrl_set(chain, ctrl);
1049 if (ret < 0) {
1050 uvc_ctrl_rollback(handle);
1051 ctrls->error_idx = commit ? ctrls->count : i;
1052 return ret;
1053 }
1054 }
1055
1056 ctrls->error_idx = 0;
1057
1058 if (commit)
1059 return uvc_ctrl_commit(handle, ctrls->controls, ctrls->count);
1060 else
1061 return uvc_ctrl_rollback(handle);
1062}
1063
1064static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh,
1065 struct v4l2_ext_controls *ctrls)
1066{
1067 struct uvc_fh *handle = fh;
1068
1069 return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, true);
1070}
1071
1072static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh,
1073 struct v4l2_ext_controls *ctrls)
1074{
1075 struct uvc_fh *handle = fh;
1076
1077 return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, false);
1078}
1079
1080static int uvc_ioctl_querymenu(struct file *file, void *fh,
1081 struct v4l2_querymenu *qm)
1082{
1083 struct uvc_fh *handle = fh;
1084 struct uvc_video_chain *chain = handle->chain;
1085
1086 return uvc_query_v4l2_menu(chain, qm);
1087}
1088
1089static int uvc_ioctl_g_selection(struct file *file, void *fh,
1090 struct v4l2_selection *sel)
1091{
1092 struct uvc_fh *handle = fh;
1093 struct uvc_streaming *stream = handle->stream;
1094
1095 if (sel->type != stream->type)
1096 return -EINVAL;
1097
1098 switch (sel->target) {
1099 case V4L2_SEL_TGT_CROP_DEFAULT:
1100 case V4L2_SEL_TGT_CROP_BOUNDS:
1101 if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1102 return -EINVAL;
1103 break;
1104 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1105 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1106 if (stream->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1107 return -EINVAL;
1108 break;
1109 default:
1110 return -EINVAL;
1111 }
1112
1113 sel->r.left = 0;
1114 sel->r.top = 0;
1115 mutex_lock(&stream->mutex);
1116 sel->r.width = stream->cur_frame->wWidth;
1117 sel->r.height = stream->cur_frame->wHeight;
1118 mutex_unlock(&stream->mutex);
1119
1120 return 0;
1121}
1122
1123static int uvc_ioctl_g_parm(struct file *file, void *fh,
1124 struct v4l2_streamparm *parm)
1125{
1126 struct uvc_fh *handle = fh;
1127 struct uvc_streaming *stream = handle->stream;
1128
1129 return uvc_v4l2_get_streamparm(stream, parm);
1130}
1131
1132static int uvc_ioctl_s_parm(struct file *file, void *fh,
1133 struct v4l2_streamparm *parm)
1134{
1135 struct uvc_fh *handle = fh;
1136 struct uvc_streaming *stream = handle->stream;
1137 int ret;
1138
1139 ret = uvc_acquire_privileges(handle);
1140 if (ret < 0)
1141 return ret;
1142
1143 return uvc_v4l2_set_streamparm(stream, parm);
1144}
1145
1146static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
1147 struct v4l2_frmsizeenum *fsize)
1148{
1149 struct uvc_fh *handle = fh;
1150 struct uvc_streaming *stream = handle->stream;
1151 struct uvc_format *format = NULL;
1152 struct uvc_frame *frame;
1153 int i;
1154
1155
1156 for (i = 0; i < stream->nformats; i++) {
1157 if (stream->format[i].fcc == fsize->pixel_format) {
1158 format = &stream->format[i];
1159 break;
1160 }
1161 }
1162 if (format == NULL)
1163 return -EINVAL;
1164
1165 if (fsize->index >= format->nframes)
1166 return -EINVAL;
1167
1168 frame = &format->frame[fsize->index];
1169 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1170 fsize->discrete.width = frame->wWidth;
1171 fsize->discrete.height = frame->wHeight;
1172 return 0;
1173}
1174
1175static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
1176 struct v4l2_frmivalenum *fival)
1177{
1178 struct uvc_fh *handle = fh;
1179 struct uvc_streaming *stream = handle->stream;
1180 struct uvc_format *format = NULL;
1181 struct uvc_frame *frame = NULL;
1182 int i;
1183
1184
1185 for (i = 0; i < stream->nformats; i++) {
1186 if (stream->format[i].fcc == fival->pixel_format) {
1187 format = &stream->format[i];
1188 break;
1189 }
1190 }
1191 if (format == NULL)
1192 return -EINVAL;
1193
1194 for (i = 0; i < format->nframes; i++) {
1195 if (format->frame[i].wWidth == fival->width &&
1196 format->frame[i].wHeight == fival->height) {
1197 frame = &format->frame[i];
1198 break;
1199 }
1200 }
1201 if (frame == NULL)
1202 return -EINVAL;
1203
1204 if (frame->bFrameIntervalType) {
1205 if (fival->index >= frame->bFrameIntervalType)
1206 return -EINVAL;
1207
1208 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1209 fival->discrete.numerator =
1210 frame->dwFrameInterval[fival->index];
1211 fival->discrete.denominator = 10000000;
1212 uvc_simplify_fraction(&fival->discrete.numerator,
1213 &fival->discrete.denominator, 8, 333);
1214 } else {
1215 if (fival->index)
1216 return -EINVAL;
1217
1218 fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1219 fival->stepwise.min.numerator = frame->dwFrameInterval[0];
1220 fival->stepwise.min.denominator = 10000000;
1221 fival->stepwise.max.numerator = frame->dwFrameInterval[1];
1222 fival->stepwise.max.denominator = 10000000;
1223 fival->stepwise.step.numerator = frame->dwFrameInterval[2];
1224 fival->stepwise.step.denominator = 10000000;
1225 uvc_simplify_fraction(&fival->stepwise.min.numerator,
1226 &fival->stepwise.min.denominator, 8, 333);
1227 uvc_simplify_fraction(&fival->stepwise.max.numerator,
1228 &fival->stepwise.max.denominator, 8, 333);
1229 uvc_simplify_fraction(&fival->stepwise.step.numerator,
1230 &fival->stepwise.step.denominator, 8, 333);
1231 }
1232
1233 return 0;
1234}
1235
1236static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
1237 const struct v4l2_event_subscription *sub)
1238{
1239 switch (sub->type) {
1240 case V4L2_EVENT_CTRL:
1241 return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
1242 default:
1243 return -EINVAL;
1244 }
1245}
1246
1247static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio,
1248 unsigned int cmd, void *arg)
1249{
1250 struct uvc_fh *handle = fh;
1251 struct uvc_video_chain *chain = handle->chain;
1252
1253 switch (cmd) {
1254
1255 case UVCIOC_CTRL_MAP:
1256 return uvc_ioctl_ctrl_map(chain, arg);
1257
1258 case UVCIOC_CTRL_QUERY:
1259 return uvc_xu_ctrl_query(chain, arg);
1260
1261 default:
1262 return -ENOTTY;
1263 }
1264}
1265
1266#ifdef CONFIG_COMPAT
1267struct uvc_xu_control_mapping32 {
1268 __u32 id;
1269 __u8 name[32];
1270 __u8 entity[16];
1271 __u8 selector;
1272
1273 __u8 size;
1274 __u8 offset;
1275 __u32 v4l2_type;
1276 __u32 data_type;
1277
1278 compat_caddr_t menu_info;
1279 __u32 menu_count;
1280
1281 __u32 reserved[4];
1282};
1283
1284static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
1285 const struct uvc_xu_control_mapping32 __user *up)
1286{
1287 compat_caddr_t p;
1288
1289 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
1290 __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) ||
1291 __get_user(kp->menu_count, &up->menu_count))
1292 return -EFAULT;
1293
1294 memset(kp->reserved, 0, sizeof(kp->reserved));
1295
1296 if (kp->menu_count == 0) {
1297 kp->menu_info = NULL;
1298 return 0;
1299 }
1300
1301 if (__get_user(p, &up->menu_info))
1302 return -EFAULT;
1303 kp->menu_info = compat_ptr(p);
1304
1305 return 0;
1306}
1307
1308static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
1309 struct uvc_xu_control_mapping32 __user *up)
1310{
1311 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
1312 __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
1313 __put_user(kp->menu_count, &up->menu_count))
1314 return -EFAULT;
1315
1316 if (__clear_user(up->reserved, sizeof(up->reserved)))
1317 return -EFAULT;
1318
1319 return 0;
1320}
1321
1322struct uvc_xu_control_query32 {
1323 __u8 unit;
1324 __u8 selector;
1325 __u8 query;
1326 __u16 size;
1327 compat_caddr_t data;
1328};
1329
1330static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
1331 const struct uvc_xu_control_query32 __user *up)
1332{
1333 compat_caddr_t p;
1334
1335 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
1336 __copy_from_user(kp, up, offsetof(typeof(*up), data)))
1337 return -EFAULT;
1338
1339 if (kp->size == 0) {
1340 kp->data = NULL;
1341 return 0;
1342 }
1343
1344 if (__get_user(p, &up->data))
1345 return -EFAULT;
1346 kp->data = compat_ptr(p);
1347
1348 return 0;
1349}
1350
1351static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
1352 struct uvc_xu_control_query32 __user *up)
1353{
1354 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
1355 __copy_to_user(up, kp, offsetof(typeof(*up), data)))
1356 return -EFAULT;
1357
1358 return 0;
1359}
1360
1361#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32)
1362#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32)
1363
1364static long uvc_v4l2_compat_ioctl32(struct file *file,
1365 unsigned int cmd, unsigned long arg)
1366{
1367 struct uvc_fh *handle = file->private_data;
1368 union {
1369 struct uvc_xu_control_mapping xmap;
1370 struct uvc_xu_control_query xqry;
1371 } karg;
1372 void __user *up = compat_ptr(arg);
1373 long ret;
1374
1375 switch (cmd) {
1376 case UVCIOC_CTRL_MAP32:
1377 ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
1378 if (ret)
1379 return ret;
1380 ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap);
1381 if (ret)
1382 return ret;
1383 ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
1384 if (ret)
1385 return ret;
1386
1387 break;
1388
1389 case UVCIOC_CTRL_QUERY32:
1390 ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
1391 if (ret)
1392 return ret;
1393 ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry);
1394 if (ret)
1395 return ret;
1396 ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
1397 if (ret)
1398 return ret;
1399 break;
1400
1401 default:
1402 return -ENOIOCTLCMD;
1403 }
1404
1405 return ret;
1406}
1407#endif
1408
1409static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
1410 size_t count, loff_t *ppos)
1411{
1412 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
1413 return -EINVAL;
1414}
1415
1416static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
1417{
1418 struct uvc_fh *handle = file->private_data;
1419 struct uvc_streaming *stream = handle->stream;
1420
1421 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
1422
1423 return uvc_queue_mmap(&stream->queue, vma);
1424}
1425
1426static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
1427{
1428 struct uvc_fh *handle = file->private_data;
1429 struct uvc_streaming *stream = handle->stream;
1430
1431 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
1432
1433 return uvc_queue_poll(&stream->queue, file, wait);
1434}
1435
1436#ifndef CONFIG_MMU
1437static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
1438 unsigned long addr, unsigned long len, unsigned long pgoff,
1439 unsigned long flags)
1440{
1441 struct uvc_fh *handle = file->private_data;
1442 struct uvc_streaming *stream = handle->stream;
1443
1444 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
1445
1446 return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
1447}
1448#endif
1449
1450const struct v4l2_ioctl_ops uvc_ioctl_ops = {
1451 .vidioc_querycap = uvc_ioctl_querycap,
1452 .vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
1453 .vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
1454 .vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap,
1455 .vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out,
1456 .vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap,
1457 .vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out,
1458 .vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap,
1459 .vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out,
1460 .vidioc_reqbufs = uvc_ioctl_reqbufs,
1461 .vidioc_querybuf = uvc_ioctl_querybuf,
1462 .vidioc_qbuf = uvc_ioctl_qbuf,
1463 .vidioc_expbuf = uvc_ioctl_expbuf,
1464 .vidioc_dqbuf = uvc_ioctl_dqbuf,
1465 .vidioc_create_bufs = uvc_ioctl_create_bufs,
1466 .vidioc_streamon = uvc_ioctl_streamon,
1467 .vidioc_streamoff = uvc_ioctl_streamoff,
1468 .vidioc_enum_input = uvc_ioctl_enum_input,
1469 .vidioc_g_input = uvc_ioctl_g_input,
1470 .vidioc_s_input = uvc_ioctl_s_input,
1471 .vidioc_queryctrl = uvc_ioctl_queryctrl,
1472 .vidioc_query_ext_ctrl = uvc_ioctl_query_ext_ctrl,
1473 .vidioc_g_ctrl = uvc_ioctl_g_ctrl,
1474 .vidioc_s_ctrl = uvc_ioctl_s_ctrl,
1475 .vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
1476 .vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
1477 .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
1478 .vidioc_querymenu = uvc_ioctl_querymenu,
1479 .vidioc_g_selection = uvc_ioctl_g_selection,
1480 .vidioc_g_parm = uvc_ioctl_g_parm,
1481 .vidioc_s_parm = uvc_ioctl_s_parm,
1482 .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
1483 .vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals,
1484 .vidioc_subscribe_event = uvc_ioctl_subscribe_event,
1485 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1486 .vidioc_default = uvc_ioctl_default,
1487};
1488
1489const struct v4l2_file_operations uvc_fops = {
1490 .owner = THIS_MODULE,
1491 .open = uvc_v4l2_open,
1492 .release = uvc_v4l2_release,
1493 .unlocked_ioctl = video_ioctl2,
1494#ifdef CONFIG_COMPAT
1495 .compat_ioctl32 = uvc_v4l2_compat_ioctl32,
1496#endif
1497 .read = uvc_v4l2_read,
1498 .mmap = uvc_v4l2_mmap,
1499 .poll = uvc_v4l2_poll,
1500#ifndef CONFIG_MMU
1501 .get_unmapped_area = uvc_v4l2_get_unmapped_area,
1502#endif
1503};
1504
1505