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