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