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
572 return 0;
573}
574
575static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
576 struct v4l2_fmtdesc *fmt)
577{
578 struct uvc_format *format;
579 enum v4l2_buf_type type = fmt->type;
580 __u32 index = fmt->index;
581
582 if (fmt->type != stream->type || fmt->index >= stream->nformats)
583 return -EINVAL;
584
585 memset(fmt, 0, sizeof(*fmt));
586 fmt->index = index;
587 fmt->type = type;
588
589 format = &stream->format[fmt->index];
590 fmt->flags = 0;
591 if (format->flags & UVC_FMT_FLAG_COMPRESSED)
592 fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
593 strlcpy(fmt->description, format->name, sizeof(fmt->description));
594 fmt->description[sizeof(fmt->description) - 1] = 0;
595 fmt->pixelformat = format->fcc;
596 return 0;
597}
598
599static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,
600 struct v4l2_fmtdesc *fmt)
601{
602 struct uvc_fh *handle = fh;
603 struct uvc_streaming *stream = handle->stream;
604
605 return uvc_ioctl_enum_fmt(stream, fmt);
606}
607
608static int uvc_ioctl_enum_fmt_vid_out(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_g_fmt_vid_cap(struct file *file, void *fh,
618 struct v4l2_format *fmt)
619{
620 struct uvc_fh *handle = fh;
621 struct uvc_streaming *stream = handle->stream;
622
623 return uvc_v4l2_get_format(stream, fmt);
624}
625
626static int uvc_ioctl_g_fmt_vid_out(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_s_fmt_vid_cap(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 int ret;
641
642 ret = uvc_acquire_privileges(handle);
643 if (ret < 0)
644 return ret;
645
646 return uvc_v4l2_set_format(stream, fmt);
647}
648
649static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh,
650 struct v4l2_format *fmt)
651{
652 struct uvc_fh *handle = fh;
653 struct uvc_streaming *stream = handle->stream;
654 int ret;
655
656 ret = uvc_acquire_privileges(handle);
657 if (ret < 0)
658 return ret;
659
660 return uvc_v4l2_set_format(stream, fmt);
661}
662
663static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh,
664 struct v4l2_format *fmt)
665{
666 struct uvc_fh *handle = fh;
667 struct uvc_streaming *stream = handle->stream;
668 struct uvc_streaming_control probe;
669
670 return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
671}
672
673static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh,
674 struct v4l2_format *fmt)
675{
676 struct uvc_fh *handle = fh;
677 struct uvc_streaming *stream = handle->stream;
678 struct uvc_streaming_control probe;
679
680 return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
681}
682
683static int uvc_ioctl_reqbufs(struct file *file, void *fh,
684 struct v4l2_requestbuffers *rb)
685{
686 struct uvc_fh *handle = fh;
687 struct uvc_streaming *stream = handle->stream;
688 int ret;
689
690 ret = uvc_acquire_privileges(handle);
691 if (ret < 0)
692 return ret;
693
694 mutex_lock(&stream->mutex);
695 ret = uvc_request_buffers(&stream->queue, rb);
696 mutex_unlock(&stream->mutex);
697 if (ret < 0)
698 return ret;
699
700 if (ret == 0)
701 uvc_dismiss_privileges(handle);
702
703 return 0;
704}
705
706static int uvc_ioctl_querybuf(struct file *file, void *fh,
707 struct v4l2_buffer *buf)
708{
709 struct uvc_fh *handle = fh;
710 struct uvc_streaming *stream = handle->stream;
711
712 if (!uvc_has_privileges(handle))
713 return -EBUSY;
714
715 return uvc_query_buffer(&stream->queue, buf);
716}
717
718static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
719{
720 struct uvc_fh *handle = fh;
721 struct uvc_streaming *stream = handle->stream;
722
723 if (!uvc_has_privileges(handle))
724 return -EBUSY;
725
726 return uvc_queue_buffer(&stream->queue, buf);
727}
728
729static int uvc_ioctl_expbuf(struct file *file, void *fh,
730 struct v4l2_exportbuffer *exp)
731{
732 struct uvc_fh *handle = fh;
733 struct uvc_streaming *stream = handle->stream;
734
735 if (!uvc_has_privileges(handle))
736 return -EBUSY;
737
738 return uvc_export_buffer(&stream->queue, exp);
739}
740
741static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
742{
743 struct uvc_fh *handle = fh;
744 struct uvc_streaming *stream = handle->stream;
745
746 if (!uvc_has_privileges(handle))
747 return -EBUSY;
748
749 return uvc_dequeue_buffer(&stream->queue, buf,
750 file->f_flags & O_NONBLOCK);
751}
752
753static int uvc_ioctl_create_bufs(struct file *file, void *fh,
754 struct v4l2_create_buffers *cb)
755{
756 struct uvc_fh *handle = fh;
757 struct uvc_streaming *stream = handle->stream;
758 int ret;
759
760 ret = uvc_acquire_privileges(handle);
761 if (ret < 0)
762 return ret;
763
764 return uvc_create_buffers(&stream->queue, cb);
765}
766
767static int uvc_ioctl_streamon(struct file *file, void *fh,
768 enum v4l2_buf_type type)
769{
770 struct uvc_fh *handle = fh;
771 struct uvc_streaming *stream = handle->stream;
772 int ret;
773
774 if (!uvc_has_privileges(handle))
775 return -EBUSY;
776
777 mutex_lock(&stream->mutex);
778 ret = uvc_queue_streamon(&stream->queue, type);
779 mutex_unlock(&stream->mutex);
780
781 return ret;
782}
783
784static int uvc_ioctl_streamoff(struct file *file, void *fh,
785 enum v4l2_buf_type type)
786{
787 struct uvc_fh *handle = fh;
788 struct uvc_streaming *stream = handle->stream;
789
790 if (!uvc_has_privileges(handle))
791 return -EBUSY;
792
793 mutex_lock(&stream->mutex);
794 uvc_queue_streamoff(&stream->queue, type);
795 mutex_unlock(&stream->mutex);
796
797 return 0;
798}
799
800static int uvc_ioctl_enum_input(struct file *file, void *fh,
801 struct v4l2_input *input)
802{
803 struct uvc_fh *handle = fh;
804 struct uvc_video_chain *chain = handle->chain;
805 const struct uvc_entity *selector = chain->selector;
806 struct uvc_entity *iterm = NULL;
807 u32 index = input->index;
808 int pin = 0;
809
810 if (selector == NULL ||
811 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
812 if (index != 0)
813 return -EINVAL;
814 list_for_each_entry(iterm, &chain->entities, chain) {
815 if (UVC_ENTITY_IS_ITERM(iterm))
816 break;
817 }
818 pin = iterm->id;
819 } else if (index < selector->bNrInPins) {
820 pin = selector->baSourceID[index];
821 list_for_each_entry(iterm, &chain->entities, chain) {
822 if (!UVC_ENTITY_IS_ITERM(iterm))
823 continue;
824 if (iterm->id == pin)
825 break;
826 }
827 }
828
829 if (iterm == NULL || iterm->id != pin)
830 return -EINVAL;
831
832 memset(input, 0, sizeof(*input));
833 input->index = index;
834 strlcpy(input->name, iterm->name, sizeof(input->name));
835 if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
836 input->type = V4L2_INPUT_TYPE_CAMERA;
837
838 return 0;
839}
840
841static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
842{
843 struct uvc_fh *handle = fh;
844 struct uvc_video_chain *chain = handle->chain;
845 int ret;
846 u8 i;
847
848 if (chain->selector == NULL ||
849 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
850 *input = 0;
851 return 0;
852 }
853
854 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
855 chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
856 &i, 1);
857 if (ret < 0)
858 return ret;
859
860 *input = i - 1;
861 return 0;
862}
863
864static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
865{
866 struct uvc_fh *handle = fh;
867 struct uvc_video_chain *chain = handle->chain;
868 int ret;
869 u32 i;
870
871 ret = uvc_acquire_privileges(handle);
872 if (ret < 0)
873 return ret;
874
875 if (chain->selector == NULL ||
876 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
877 if (input)
878 return -EINVAL;
879 return 0;
880 }
881
882 if (input >= chain->selector->bNrInPins)
883 return -EINVAL;
884
885 i = input + 1;
886 return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
887 chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
888 &i, 1);
889}
890
891static int uvc_ioctl_queryctrl(struct file *file, void *fh,
892 struct v4l2_queryctrl *qc)
893{
894 struct uvc_fh *handle = fh;
895 struct uvc_video_chain *chain = handle->chain;
896
897 return uvc_query_v4l2_ctrl(chain, qc);
898}
899
900static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh,
901 struct v4l2_query_ext_ctrl *qec)
902{
903 struct uvc_fh *handle = fh;
904 struct uvc_video_chain *chain = handle->chain;
905 struct v4l2_queryctrl qc = { qec->id };
906 int ret;
907
908 ret = uvc_query_v4l2_ctrl(chain, &qc);
909 if (ret)
910 return ret;
911
912 qec->id = qc.id;
913 qec->type = qc.type;
914 strlcpy(qec->name, qc.name, sizeof(qec->name));
915 qec->minimum = qc.minimum;
916 qec->maximum = qc.maximum;
917 qec->step = qc.step;
918 qec->default_value = qc.default_value;
919 qec->flags = qc.flags;
920 qec->elem_size = 4;
921 qec->elems = 1;
922 qec->nr_of_dims = 0;
923 memset(qec->dims, 0, sizeof(qec->dims));
924 memset(qec->reserved, 0, sizeof(qec->reserved));
925
926 return 0;
927}
928
929static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
930 struct v4l2_control *ctrl)
931{
932 struct uvc_fh *handle = fh;
933 struct uvc_video_chain *chain = handle->chain;
934 struct v4l2_ext_control xctrl;
935 int ret;
936
937 memset(&xctrl, 0, sizeof(xctrl));
938 xctrl.id = ctrl->id;
939
940 ret = uvc_ctrl_begin(chain);
941 if (ret < 0)
942 return ret;
943
944 ret = uvc_ctrl_get(chain, &xctrl);
945 uvc_ctrl_rollback(handle);
946 if (ret < 0)
947 return ret;
948
949 ctrl->value = xctrl.value;
950 return 0;
951}
952
953static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
954 struct v4l2_control *ctrl)
955{
956 struct uvc_fh *handle = fh;
957 struct uvc_video_chain *chain = handle->chain;
958 struct v4l2_ext_control xctrl;
959 int ret;
960
961 memset(&xctrl, 0, sizeof(xctrl));
962 xctrl.id = ctrl->id;
963 xctrl.value = ctrl->value;
964
965 ret = uvc_ctrl_begin(chain);
966 if (ret < 0)
967 return ret;
968
969 ret = uvc_ctrl_set(chain, &xctrl);
970 if (ret < 0) {
971 uvc_ctrl_rollback(handle);
972 return ret;
973 }
974
975 ret = uvc_ctrl_commit(handle, &xctrl, 1);
976 if (ret < 0)
977 return ret;
978
979 ctrl->value = xctrl.value;
980 return 0;
981}
982
983static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
984 struct v4l2_ext_controls *ctrls)
985{
986 struct uvc_fh *handle = fh;
987 struct uvc_video_chain *chain = handle->chain;
988 struct v4l2_ext_control *ctrl = ctrls->controls;
989 unsigned int i;
990 int ret;
991
992 if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
993 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
994 struct v4l2_queryctrl qc = { .id = ctrl->id };
995
996 ret = uvc_query_v4l2_ctrl(chain, &qc);
997 if (ret < 0) {
998 ctrls->error_idx = i;
999 return ret;
1000 }
1001
1002 ctrl->value = qc.default_value;
1003 }
1004
1005 return 0;
1006 }
1007
1008 ret = uvc_ctrl_begin(chain);
1009 if (ret < 0)
1010 return ret;
1011
1012 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
1013 ret = uvc_ctrl_get(chain, ctrl);
1014 if (ret < 0) {
1015 uvc_ctrl_rollback(handle);
1016 ctrls->error_idx = i;
1017 return ret;
1018 }
1019 }
1020
1021 ctrls->error_idx = 0;
1022
1023 return uvc_ctrl_rollback(handle);
1024}
1025
1026static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
1027 struct v4l2_ext_controls *ctrls,
1028 bool commit)
1029{
1030 struct v4l2_ext_control *ctrl = ctrls->controls;
1031 struct uvc_video_chain *chain = handle->chain;
1032 unsigned int i;
1033 int ret;
1034
1035
1036 if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL)
1037 return -EINVAL;
1038
1039 ret = uvc_ctrl_begin(chain);
1040 if (ret < 0)
1041 return ret;
1042
1043 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
1044 ret = uvc_ctrl_set(chain, ctrl);
1045 if (ret < 0) {
1046 uvc_ctrl_rollback(handle);
1047 ctrls->error_idx = commit ? ctrls->count : i;
1048 return ret;
1049 }
1050 }
1051
1052 ctrls->error_idx = 0;
1053
1054 if (commit)
1055 return uvc_ctrl_commit(handle, ctrls->controls, ctrls->count);
1056 else
1057 return uvc_ctrl_rollback(handle);
1058}
1059
1060static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh,
1061 struct v4l2_ext_controls *ctrls)
1062{
1063 struct uvc_fh *handle = fh;
1064
1065 return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, true);
1066}
1067
1068static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh,
1069 struct v4l2_ext_controls *ctrls)
1070{
1071 struct uvc_fh *handle = fh;
1072
1073 return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, false);
1074}
1075
1076static int uvc_ioctl_querymenu(struct file *file, void *fh,
1077 struct v4l2_querymenu *qm)
1078{
1079 struct uvc_fh *handle = fh;
1080 struct uvc_video_chain *chain = handle->chain;
1081
1082 return uvc_query_v4l2_menu(chain, qm);
1083}
1084
1085static int uvc_ioctl_g_selection(struct file *file, void *fh,
1086 struct v4l2_selection *sel)
1087{
1088 struct uvc_fh *handle = fh;
1089 struct uvc_streaming *stream = handle->stream;
1090
1091 if (sel->type != stream->type)
1092 return -EINVAL;
1093
1094 switch (sel->target) {
1095 case V4L2_SEL_TGT_CROP_DEFAULT:
1096 case V4L2_SEL_TGT_CROP_BOUNDS:
1097 if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1098 return -EINVAL;
1099 break;
1100 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1101 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1102 if (stream->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1103 return -EINVAL;
1104 break;
1105 default:
1106 return -EINVAL;
1107 }
1108
1109 sel->r.left = 0;
1110 sel->r.top = 0;
1111 mutex_lock(&stream->mutex);
1112 sel->r.width = stream->cur_frame->wWidth;
1113 sel->r.height = stream->cur_frame->wHeight;
1114 mutex_unlock(&stream->mutex);
1115
1116 return 0;
1117}
1118
1119static int uvc_ioctl_g_parm(struct file *file, void *fh,
1120 struct v4l2_streamparm *parm)
1121{
1122 struct uvc_fh *handle = fh;
1123 struct uvc_streaming *stream = handle->stream;
1124
1125 return uvc_v4l2_get_streamparm(stream, parm);
1126}
1127
1128static int uvc_ioctl_s_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 int ret;
1134
1135 ret = uvc_acquire_privileges(handle);
1136 if (ret < 0)
1137 return ret;
1138
1139 return uvc_v4l2_set_streamparm(stream, parm);
1140}
1141
1142static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
1143 struct v4l2_frmsizeenum *fsize)
1144{
1145 struct uvc_fh *handle = fh;
1146 struct uvc_streaming *stream = handle->stream;
1147 struct uvc_format *format = NULL;
1148 struct uvc_frame *frame;
1149 int i;
1150
1151
1152 for (i = 0; i < stream->nformats; i++) {
1153 if (stream->format[i].fcc == fsize->pixel_format) {
1154 format = &stream->format[i];
1155 break;
1156 }
1157 }
1158 if (format == NULL)
1159 return -EINVAL;
1160
1161 if (fsize->index >= format->nframes)
1162 return -EINVAL;
1163
1164 frame = &format->frame[fsize->index];
1165 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1166 fsize->discrete.width = frame->wWidth;
1167 fsize->discrete.height = frame->wHeight;
1168 return 0;
1169}
1170
1171static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
1172 struct v4l2_frmivalenum *fival)
1173{
1174 struct uvc_fh *handle = fh;
1175 struct uvc_streaming *stream = handle->stream;
1176 struct uvc_format *format = NULL;
1177 struct uvc_frame *frame = NULL;
1178 int i;
1179
1180
1181 for (i = 0; i < stream->nformats; i++) {
1182 if (stream->format[i].fcc == fival->pixel_format) {
1183 format = &stream->format[i];
1184 break;
1185 }
1186 }
1187 if (format == NULL)
1188 return -EINVAL;
1189
1190 for (i = 0; i < format->nframes; i++) {
1191 if (format->frame[i].wWidth == fival->width &&
1192 format->frame[i].wHeight == fival->height) {
1193 frame = &format->frame[i];
1194 break;
1195 }
1196 }
1197 if (frame == NULL)
1198 return -EINVAL;
1199
1200 if (frame->bFrameIntervalType) {
1201 if (fival->index >= frame->bFrameIntervalType)
1202 return -EINVAL;
1203
1204 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1205 fival->discrete.numerator =
1206 frame->dwFrameInterval[fival->index];
1207 fival->discrete.denominator = 10000000;
1208 uvc_simplify_fraction(&fival->discrete.numerator,
1209 &fival->discrete.denominator, 8, 333);
1210 } else {
1211 if (fival->index)
1212 return -EINVAL;
1213
1214 fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1215 fival->stepwise.min.numerator = frame->dwFrameInterval[0];
1216 fival->stepwise.min.denominator = 10000000;
1217 fival->stepwise.max.numerator = frame->dwFrameInterval[1];
1218 fival->stepwise.max.denominator = 10000000;
1219 fival->stepwise.step.numerator = frame->dwFrameInterval[2];
1220 fival->stepwise.step.denominator = 10000000;
1221 uvc_simplify_fraction(&fival->stepwise.min.numerator,
1222 &fival->stepwise.min.denominator, 8, 333);
1223 uvc_simplify_fraction(&fival->stepwise.max.numerator,
1224 &fival->stepwise.max.denominator, 8, 333);
1225 uvc_simplify_fraction(&fival->stepwise.step.numerator,
1226 &fival->stepwise.step.denominator, 8, 333);
1227 }
1228
1229 return 0;
1230}
1231
1232static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
1233 const struct v4l2_event_subscription *sub)
1234{
1235 switch (sub->type) {
1236 case V4L2_EVENT_CTRL:
1237 return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
1238 default:
1239 return -EINVAL;
1240 }
1241}
1242
1243static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio,
1244 unsigned int cmd, void *arg)
1245{
1246 struct uvc_fh *handle = fh;
1247 struct uvc_video_chain *chain = handle->chain;
1248
1249 switch (cmd) {
1250
1251 case UVCIOC_CTRL_MAP:
1252 return uvc_ioctl_ctrl_map(chain, arg);
1253
1254 case UVCIOC_CTRL_QUERY:
1255 return uvc_xu_ctrl_query(chain, arg);
1256
1257 default:
1258 return -ENOTTY;
1259 }
1260}
1261
1262#ifdef CONFIG_COMPAT
1263struct uvc_xu_control_mapping32 {
1264 __u32 id;
1265 __u8 name[32];
1266 __u8 entity[16];
1267 __u8 selector;
1268
1269 __u8 size;
1270 __u8 offset;
1271 __u32 v4l2_type;
1272 __u32 data_type;
1273
1274 compat_caddr_t menu_info;
1275 __u32 menu_count;
1276
1277 __u32 reserved[4];
1278};
1279
1280static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
1281 const struct uvc_xu_control_mapping32 __user *up)
1282{
1283 struct uvc_xu_control_mapping32 *p = (void *)kp;
1284 compat_caddr_t info;
1285 u32 count;
1286
1287 if (copy_from_user(p, up, sizeof(*p)))
1288 return -EFAULT;
1289
1290 count = p->menu_count;
1291 info = p->menu_info;
1292
1293 memset(kp->reserved, 0, sizeof(kp->reserved));
1294 kp->menu_info = count ? compat_ptr(info) : NULL;
1295 kp->menu_count = count;
1296 return 0;
1297}
1298
1299static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
1300 struct uvc_xu_control_mapping32 __user *up)
1301{
1302 if (copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
1303 put_user(kp->menu_count, &up->menu_count))
1304 return -EFAULT;
1305
1306 if (clear_user(up->reserved, sizeof(up->reserved)))
1307 return -EFAULT;
1308
1309 return 0;
1310}
1311
1312struct uvc_xu_control_query32 {
1313 __u8 unit;
1314 __u8 selector;
1315 __u8 query;
1316 __u16 size;
1317 compat_caddr_t data;
1318};
1319
1320static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
1321 const struct uvc_xu_control_query32 __user *up)
1322{
1323 struct uvc_xu_control_query32 v;
1324
1325 if (copy_from_user(&v, up, sizeof(v)))
1326 return -EFAULT;
1327
1328 *kp = (struct uvc_xu_control_query){
1329 .unit = v.unit,
1330 .selector = v.selector,
1331 .query = v.query,
1332 .size = v.size,
1333 .data = v.size ? compat_ptr(v.data) : NULL
1334 };
1335 return 0;
1336}
1337
1338static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
1339 struct uvc_xu_control_query32 __user *up)
1340{
1341 if (copy_to_user(up, kp, offsetof(typeof(*up), data)))
1342 return -EFAULT;
1343 return 0;
1344}
1345
1346#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32)
1347#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32)
1348
1349static long uvc_v4l2_compat_ioctl32(struct file *file,
1350 unsigned int cmd, unsigned long arg)
1351{
1352 struct uvc_fh *handle = file->private_data;
1353 union {
1354 struct uvc_xu_control_mapping xmap;
1355 struct uvc_xu_control_query xqry;
1356 } karg;
1357 void __user *up = compat_ptr(arg);
1358 long ret;
1359
1360 switch (cmd) {
1361 case UVCIOC_CTRL_MAP32:
1362 ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
1363 if (ret)
1364 return ret;
1365 ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap);
1366 if (ret)
1367 return ret;
1368 ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
1369 if (ret)
1370 return ret;
1371
1372 break;
1373
1374 case UVCIOC_CTRL_QUERY32:
1375 ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
1376 if (ret)
1377 return ret;
1378 ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry);
1379 if (ret)
1380 return ret;
1381 ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
1382 if (ret)
1383 return ret;
1384 break;
1385
1386 default:
1387 return -ENOIOCTLCMD;
1388 }
1389
1390 return ret;
1391}
1392#endif
1393
1394static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
1395 size_t count, loff_t *ppos)
1396{
1397 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
1398 return -EINVAL;
1399}
1400
1401static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
1402{
1403 struct uvc_fh *handle = file->private_data;
1404 struct uvc_streaming *stream = handle->stream;
1405
1406 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
1407
1408 return uvc_queue_mmap(&stream->queue, vma);
1409}
1410
1411static __poll_t uvc_v4l2_poll(struct file *file, poll_table *wait)
1412{
1413 struct uvc_fh *handle = file->private_data;
1414 struct uvc_streaming *stream = handle->stream;
1415
1416 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
1417
1418 return uvc_queue_poll(&stream->queue, file, wait);
1419}
1420
1421#ifndef CONFIG_MMU
1422static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
1423 unsigned long addr, unsigned long len, unsigned long pgoff,
1424 unsigned long flags)
1425{
1426 struct uvc_fh *handle = file->private_data;
1427 struct uvc_streaming *stream = handle->stream;
1428
1429 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
1430
1431 return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
1432}
1433#endif
1434
1435const struct v4l2_ioctl_ops uvc_ioctl_ops = {
1436 .vidioc_querycap = uvc_ioctl_querycap,
1437 .vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
1438 .vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
1439 .vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap,
1440 .vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out,
1441 .vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap,
1442 .vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out,
1443 .vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap,
1444 .vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out,
1445 .vidioc_reqbufs = uvc_ioctl_reqbufs,
1446 .vidioc_querybuf = uvc_ioctl_querybuf,
1447 .vidioc_qbuf = uvc_ioctl_qbuf,
1448 .vidioc_expbuf = uvc_ioctl_expbuf,
1449 .vidioc_dqbuf = uvc_ioctl_dqbuf,
1450 .vidioc_create_bufs = uvc_ioctl_create_bufs,
1451 .vidioc_streamon = uvc_ioctl_streamon,
1452 .vidioc_streamoff = uvc_ioctl_streamoff,
1453 .vidioc_enum_input = uvc_ioctl_enum_input,
1454 .vidioc_g_input = uvc_ioctl_g_input,
1455 .vidioc_s_input = uvc_ioctl_s_input,
1456 .vidioc_queryctrl = uvc_ioctl_queryctrl,
1457 .vidioc_query_ext_ctrl = uvc_ioctl_query_ext_ctrl,
1458 .vidioc_g_ctrl = uvc_ioctl_g_ctrl,
1459 .vidioc_s_ctrl = uvc_ioctl_s_ctrl,
1460 .vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
1461 .vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
1462 .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
1463 .vidioc_querymenu = uvc_ioctl_querymenu,
1464 .vidioc_g_selection = uvc_ioctl_g_selection,
1465 .vidioc_g_parm = uvc_ioctl_g_parm,
1466 .vidioc_s_parm = uvc_ioctl_s_parm,
1467 .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
1468 .vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals,
1469 .vidioc_subscribe_event = uvc_ioctl_subscribe_event,
1470 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1471 .vidioc_default = uvc_ioctl_default,
1472};
1473
1474const struct v4l2_file_operations uvc_fops = {
1475 .owner = THIS_MODULE,
1476 .open = uvc_v4l2_open,
1477 .release = uvc_v4l2_release,
1478 .unlocked_ioctl = video_ioctl2,
1479#ifdef CONFIG_COMPAT
1480 .compat_ioctl32 = uvc_v4l2_compat_ioctl32,
1481#endif
1482 .read = uvc_v4l2_read,
1483 .mmap = uvc_v4l2_mmap,
1484 .poll = uvc_v4l2_poll,
1485#ifndef CONFIG_MMU
1486 .get_unmapped_area = uvc_v4l2_get_unmapped_area,
1487#endif
1488};
1489
1490