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