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/version.h>
17#include <linux/list.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/usb.h>
21#include <linux/videodev2.h>
22#include <linux/vmalloc.h>
23#include <linux/mm.h>
24#include <linux/wait.h>
25#include <linux/atomic.h>
26
27#include <media/v4l2-common.h>
28#include <media/v4l2-ioctl.h>
29
30#include "uvcvideo.h"
31
32
33
34
35static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
36 struct uvc_xu_control_mapping *xmap)
37{
38 struct uvc_control_mapping *map;
39 unsigned int size;
40 int ret;
41
42 map = kzalloc(sizeof *map, GFP_KERNEL);
43 if (map == NULL)
44 return -ENOMEM;
45
46 map->id = xmap->id;
47 memcpy(map->name, xmap->name, sizeof map->name);
48 memcpy(map->entity, xmap->entity, sizeof map->entity);
49 map->selector = xmap->selector;
50 map->size = xmap->size;
51 map->offset = xmap->offset;
52 map->v4l2_type = xmap->v4l2_type;
53 map->data_type = xmap->data_type;
54
55 switch (xmap->v4l2_type) {
56 case V4L2_CTRL_TYPE_INTEGER:
57 case V4L2_CTRL_TYPE_BOOLEAN:
58 case V4L2_CTRL_TYPE_BUTTON:
59 break;
60
61 case V4L2_CTRL_TYPE_MENU:
62
63
64
65 if (xmap->menu_count == 0 ||
66 xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
67 ret = -EINVAL;
68 goto done;
69 }
70
71 size = xmap->menu_count * sizeof(*map->menu_info);
72 map->menu_info = kmalloc(size, GFP_KERNEL);
73 if (map->menu_info == NULL) {
74 ret = -ENOMEM;
75 goto done;
76 }
77
78 if (copy_from_user(map->menu_info, xmap->menu_info, size)) {
79 ret = -EFAULT;
80 goto done;
81 }
82
83 map->menu_count = xmap->menu_count;
84 break;
85
86 default:
87 uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
88 "%u.\n", xmap->v4l2_type);
89 ret = -ENOTTY;
90 goto done;
91 }
92
93 ret = uvc_ctrl_add_mapping(chain, map);
94
95done:
96 kfree(map->menu_info);
97 kfree(map);
98
99 return ret;
100}
101
102
103
104
105
106
107
108
109
110
111
112static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
113{
114 unsigned int i;
115
116 if (frame->bFrameIntervalType) {
117 __u32 best = -1, dist;
118
119 for (i = 0; i < frame->bFrameIntervalType; ++i) {
120 dist = interval > frame->dwFrameInterval[i]
121 ? interval - frame->dwFrameInterval[i]
122 : frame->dwFrameInterval[i] - interval;
123
124 if (dist > best)
125 break;
126
127 best = dist;
128 }
129
130 interval = frame->dwFrameInterval[i-1];
131 } else {
132 const __u32 min = frame->dwFrameInterval[0];
133 const __u32 max = frame->dwFrameInterval[1];
134 const __u32 step = frame->dwFrameInterval[2];
135
136 interval = min + (interval - min + step/2) / step * step;
137 if (interval > max)
138 interval = max;
139 }
140
141 return interval;
142}
143
144static int uvc_v4l2_try_format(struct uvc_streaming *stream,
145 struct v4l2_format *fmt, struct uvc_streaming_control *probe,
146 struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
147{
148 struct uvc_format *format = NULL;
149 struct uvc_frame *frame = NULL;
150 __u16 rw, rh;
151 unsigned int d, maxd;
152 unsigned int i;
153 __u32 interval;
154 int ret = 0;
155 __u8 *fcc;
156
157 if (fmt->type != stream->type)
158 return -EINVAL;
159
160 fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
161 uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
162 fmt->fmt.pix.pixelformat,
163 fcc[0], fcc[1], fcc[2], fcc[3],
164 fmt->fmt.pix.width, fmt->fmt.pix.height);
165
166
167 for (i = 0; i < stream->nformats; ++i) {
168 format = &stream->format[i];
169 if (format->fcc == fmt->fmt.pix.pixelformat)
170 break;
171 }
172
173 if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
174 uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
175 fmt->fmt.pix.pixelformat);
176 return -EINVAL;
177 }
178
179
180
181
182
183 rw = fmt->fmt.pix.width;
184 rh = fmt->fmt.pix.height;
185 maxd = (unsigned int)-1;
186
187 for (i = 0; i < format->nframes; ++i) {
188 __u16 w = format->frame[i].wWidth;
189 __u16 h = format->frame[i].wHeight;
190
191 d = min(w, rw) * min(h, rh);
192 d = w*h + rw*rh - 2*d;
193 if (d < maxd) {
194 maxd = d;
195 frame = &format->frame[i];
196 }
197
198 if (maxd == 0)
199 break;
200 }
201
202 if (frame == NULL) {
203 uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
204 fmt->fmt.pix.width, fmt->fmt.pix.height);
205 return -EINVAL;
206 }
207
208
209 interval = frame->dwDefaultFrameInterval;
210 uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
211 "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
212 (100000000/interval)%10);
213
214
215 memset(probe, 0, sizeof *probe);
216 probe->bmHint = 1;
217 probe->bFormatIndex = format->index;
218 probe->bFrameIndex = frame->bFrameIndex;
219 probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
220
221
222
223
224
225
226
227
228
229
230
231
232 mutex_lock(&stream->mutex);
233 if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
234 probe->dwMaxVideoFrameSize =
235 stream->ctrl.dwMaxVideoFrameSize;
236
237
238 ret = uvc_probe_video(stream, probe);
239 mutex_unlock(&stream->mutex);
240 if (ret < 0)
241 goto done;
242
243 fmt->fmt.pix.width = frame->wWidth;
244 fmt->fmt.pix.height = frame->wHeight;
245 fmt->fmt.pix.field = V4L2_FIELD_NONE;
246 fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
247 fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
248 fmt->fmt.pix.colorspace = format->colorspace;
249 fmt->fmt.pix.priv = 0;
250
251 if (uvc_format != NULL)
252 *uvc_format = format;
253 if (uvc_frame != NULL)
254 *uvc_frame = frame;
255
256done:
257 return ret;
258}
259
260static int uvc_v4l2_get_format(struct uvc_streaming *stream,
261 struct v4l2_format *fmt)
262{
263 struct uvc_format *format;
264 struct uvc_frame *frame;
265 int ret = 0;
266
267 if (fmt->type != stream->type)
268 return -EINVAL;
269
270 mutex_lock(&stream->mutex);
271 format = stream->cur_format;
272 frame = stream->cur_frame;
273
274 if (format == NULL || frame == NULL) {
275 ret = -EINVAL;
276 goto done;
277 }
278
279 fmt->fmt.pix.pixelformat = format->fcc;
280 fmt->fmt.pix.width = frame->wWidth;
281 fmt->fmt.pix.height = frame->wHeight;
282 fmt->fmt.pix.field = V4L2_FIELD_NONE;
283 fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
284 fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
285 fmt->fmt.pix.colorspace = format->colorspace;
286 fmt->fmt.pix.priv = 0;
287
288done:
289 mutex_unlock(&stream->mutex);
290 return ret;
291}
292
293static int uvc_v4l2_set_format(struct uvc_streaming *stream,
294 struct v4l2_format *fmt)
295{
296 struct uvc_streaming_control probe;
297 struct uvc_format *format;
298 struct uvc_frame *frame;
299 int ret;
300
301 if (fmt->type != stream->type)
302 return -EINVAL;
303
304 ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
305 if (ret < 0)
306 return ret;
307
308 mutex_lock(&stream->mutex);
309
310 if (uvc_queue_allocated(&stream->queue)) {
311 ret = -EBUSY;
312 goto done;
313 }
314
315 memcpy(&stream->ctrl, &probe, sizeof probe);
316 stream->cur_format = format;
317 stream->cur_frame = frame;
318
319done:
320 mutex_unlock(&stream->mutex);
321 return ret;
322}
323
324static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
325 struct v4l2_streamparm *parm)
326{
327 uint32_t numerator, denominator;
328
329 if (parm->type != stream->type)
330 return -EINVAL;
331
332 mutex_lock(&stream->mutex);
333 numerator = stream->ctrl.dwFrameInterval;
334 mutex_unlock(&stream->mutex);
335
336 denominator = 10000000;
337 uvc_simplify_fraction(&numerator, &denominator, 8, 333);
338
339 memset(parm, 0, sizeof *parm);
340 parm->type = stream->type;
341
342 if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
343 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
344 parm->parm.capture.capturemode = 0;
345 parm->parm.capture.timeperframe.numerator = numerator;
346 parm->parm.capture.timeperframe.denominator = denominator;
347 parm->parm.capture.extendedmode = 0;
348 parm->parm.capture.readbuffers = 0;
349 } else {
350 parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
351 parm->parm.output.outputmode = 0;
352 parm->parm.output.timeperframe.numerator = numerator;
353 parm->parm.output.timeperframe.denominator = denominator;
354 }
355
356 return 0;
357}
358
359static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
360 struct v4l2_streamparm *parm)
361{
362 struct uvc_streaming_control probe;
363 struct v4l2_fract timeperframe;
364 uint32_t interval;
365 int ret;
366
367 if (parm->type != stream->type)
368 return -EINVAL;
369
370 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
371 timeperframe = parm->parm.capture.timeperframe;
372 else
373 timeperframe = parm->parm.output.timeperframe;
374
375 interval = uvc_fraction_to_interval(timeperframe.numerator,
376 timeperframe.denominator);
377 uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
378 timeperframe.numerator, timeperframe.denominator, interval);
379
380 mutex_lock(&stream->mutex);
381
382 if (uvc_queue_streaming(&stream->queue)) {
383 mutex_unlock(&stream->mutex);
384 return -EBUSY;
385 }
386
387 memcpy(&probe, &stream->ctrl, sizeof probe);
388 probe.dwFrameInterval =
389 uvc_try_frame_interval(stream->cur_frame, interval);
390
391
392 ret = uvc_probe_video(stream, &probe);
393 if (ret < 0) {
394 mutex_unlock(&stream->mutex);
395 return ret;
396 }
397
398 memcpy(&stream->ctrl, &probe, sizeof probe);
399 mutex_unlock(&stream->mutex);
400
401
402 timeperframe.numerator = probe.dwFrameInterval;
403 timeperframe.denominator = 10000000;
404 uvc_simplify_fraction(&timeperframe.numerator,
405 &timeperframe.denominator, 8, 333);
406
407 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
408 parm->parm.capture.timeperframe = timeperframe;
409 else
410 parm->parm.output.timeperframe = timeperframe;
411
412 return 0;
413}
414
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
442static int uvc_acquire_privileges(struct uvc_fh *handle)
443{
444
445 if (handle->state == UVC_HANDLE_ACTIVE)
446 return 0;
447
448
449 if (atomic_inc_return(&handle->stream->active) != 1) {
450 atomic_dec(&handle->stream->active);
451 return -EBUSY;
452 }
453
454 handle->state = UVC_HANDLE_ACTIVE;
455 return 0;
456}
457
458static void uvc_dismiss_privileges(struct uvc_fh *handle)
459{
460 if (handle->state == UVC_HANDLE_ACTIVE)
461 atomic_dec(&handle->stream->active);
462
463 handle->state = UVC_HANDLE_PASSIVE;
464}
465
466static int uvc_has_privileges(struct uvc_fh *handle)
467{
468 return handle->state == UVC_HANDLE_ACTIVE;
469}
470
471
472
473
474
475static int uvc_v4l2_open(struct file *file)
476{
477 struct uvc_streaming *stream;
478 struct uvc_fh *handle;
479 int ret = 0;
480
481 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
482 stream = video_drvdata(file);
483
484 if (stream->dev->state & UVC_DEV_DISCONNECTED)
485 return -ENODEV;
486
487 ret = usb_autopm_get_interface(stream->dev->intf);
488 if (ret < 0)
489 return ret;
490
491
492 handle = kzalloc(sizeof *handle, GFP_KERNEL);
493 if (handle == NULL) {
494 usb_autopm_put_interface(stream->dev->intf);
495 return -ENOMEM;
496 }
497
498 if (atomic_inc_return(&stream->dev->users) == 1) {
499 ret = uvc_status_start(stream->dev);
500 if (ret < 0) {
501 usb_autopm_put_interface(stream->dev->intf);
502 atomic_dec(&stream->dev->users);
503 kfree(handle);
504 return ret;
505 }
506 }
507
508 handle->chain = stream->chain;
509 handle->stream = stream;
510 handle->state = UVC_HANDLE_PASSIVE;
511 file->private_data = handle;
512
513 return 0;
514}
515
516static int uvc_v4l2_release(struct file *file)
517{
518 struct uvc_fh *handle = file->private_data;
519 struct uvc_streaming *stream = handle->stream;
520
521 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
522
523
524 if (uvc_has_privileges(handle)) {
525 uvc_video_enable(stream, 0);
526 uvc_free_buffers(&stream->queue);
527 }
528
529
530 uvc_dismiss_privileges(handle);
531 kfree(handle);
532 file->private_data = NULL;
533
534 if (atomic_dec_return(&stream->dev->users) == 0)
535 uvc_status_stop(stream->dev);
536
537 usb_autopm_put_interface(stream->dev->intf);
538 return 0;
539}
540
541static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
542{
543 struct video_device *vdev = video_devdata(file);
544 struct uvc_fh *handle = file->private_data;
545 struct uvc_video_chain *chain = handle->chain;
546 struct uvc_streaming *stream = handle->stream;
547 long ret = 0;
548
549 switch (cmd) {
550
551 case VIDIOC_QUERYCAP:
552 {
553 struct v4l2_capability *cap = arg;
554
555 memset(cap, 0, sizeof *cap);
556 strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
557 strlcpy(cap->card, vdev->name, sizeof cap->card);
558 usb_make_path(stream->dev->udev,
559 cap->bus_info, sizeof(cap->bus_info));
560 cap->version = LINUX_VERSION_CODE;
561 if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
562 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
563 | V4L2_CAP_STREAMING;
564 else
565 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
566 | V4L2_CAP_STREAMING;
567 break;
568 }
569
570
571 case VIDIOC_QUERYCTRL:
572 return uvc_query_v4l2_ctrl(chain, arg);
573
574 case VIDIOC_G_CTRL:
575 {
576 struct v4l2_control *ctrl = arg;
577 struct v4l2_ext_control xctrl;
578
579 memset(&xctrl, 0, sizeof xctrl);
580 xctrl.id = ctrl->id;
581
582 ret = uvc_ctrl_begin(chain);
583 if (ret < 0)
584 return ret;
585
586 ret = uvc_ctrl_get(chain, &xctrl);
587 uvc_ctrl_rollback(chain);
588 if (ret >= 0)
589 ctrl->value = xctrl.value;
590 break;
591 }
592
593 case VIDIOC_S_CTRL:
594 {
595 struct v4l2_control *ctrl = arg;
596 struct v4l2_ext_control xctrl;
597
598 memset(&xctrl, 0, sizeof xctrl);
599 xctrl.id = ctrl->id;
600 xctrl.value = ctrl->value;
601
602 ret = uvc_ctrl_begin(chain);
603 if (ret < 0)
604 return ret;
605
606 ret = uvc_ctrl_set(chain, &xctrl);
607 if (ret < 0) {
608 uvc_ctrl_rollback(chain);
609 return ret;
610 }
611 ret = uvc_ctrl_commit(chain);
612 if (ret == 0)
613 ctrl->value = xctrl.value;
614 break;
615 }
616
617 case VIDIOC_QUERYMENU:
618 return uvc_query_v4l2_menu(chain, arg);
619
620 case VIDIOC_G_EXT_CTRLS:
621 {
622 struct v4l2_ext_controls *ctrls = arg;
623 struct v4l2_ext_control *ctrl = ctrls->controls;
624 unsigned int i;
625
626 ret = uvc_ctrl_begin(chain);
627 if (ret < 0)
628 return ret;
629
630 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
631 ret = uvc_ctrl_get(chain, ctrl);
632 if (ret < 0) {
633 uvc_ctrl_rollback(chain);
634 ctrls->error_idx = i;
635 return ret;
636 }
637 }
638 ctrls->error_idx = 0;
639 ret = uvc_ctrl_rollback(chain);
640 break;
641 }
642
643 case VIDIOC_S_EXT_CTRLS:
644 case VIDIOC_TRY_EXT_CTRLS:
645 {
646 struct v4l2_ext_controls *ctrls = arg;
647 struct v4l2_ext_control *ctrl = ctrls->controls;
648 unsigned int i;
649
650 ret = uvc_ctrl_begin(chain);
651 if (ret < 0)
652 return ret;
653
654 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
655 ret = uvc_ctrl_set(chain, ctrl);
656 if (ret < 0) {
657 uvc_ctrl_rollback(chain);
658 ctrls->error_idx = i;
659 return ret;
660 }
661 }
662
663 ctrls->error_idx = 0;
664
665 if (cmd == VIDIOC_S_EXT_CTRLS)
666 ret = uvc_ctrl_commit(chain);
667 else
668 ret = uvc_ctrl_rollback(chain);
669 break;
670 }
671
672
673 case VIDIOC_ENUMINPUT:
674 {
675 const struct uvc_entity *selector = chain->selector;
676 struct v4l2_input *input = arg;
677 struct uvc_entity *iterm = NULL;
678 u32 index = input->index;
679 int pin = 0;
680
681 if (selector == NULL ||
682 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
683 if (index != 0)
684 return -EINVAL;
685 list_for_each_entry(iterm, &chain->entities, chain) {
686 if (UVC_ENTITY_IS_ITERM(iterm))
687 break;
688 }
689 pin = iterm->id;
690 } else if (pin < selector->bNrInPins) {
691 pin = selector->baSourceID[index];
692 list_for_each_entry(iterm, &chain->entities, chain) {
693 if (!UVC_ENTITY_IS_ITERM(iterm))
694 continue;
695 if (iterm->id == pin)
696 break;
697 }
698 }
699
700 if (iterm == NULL || iterm->id != pin)
701 return -EINVAL;
702
703 memset(input, 0, sizeof *input);
704 input->index = index;
705 strlcpy(input->name, iterm->name, sizeof input->name);
706 if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
707 input->type = V4L2_INPUT_TYPE_CAMERA;
708 break;
709 }
710
711 case VIDIOC_G_INPUT:
712 {
713 u8 input;
714
715 if (chain->selector == NULL ||
716 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
717 *(int *)arg = 0;
718 break;
719 }
720
721 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
722 chain->selector->id, chain->dev->intfnum,
723 UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
724 if (ret < 0)
725 return ret;
726
727 *(int *)arg = input - 1;
728 break;
729 }
730
731 case VIDIOC_S_INPUT:
732 {
733 u32 input = *(u32 *)arg + 1;
734
735 if ((ret = uvc_acquire_privileges(handle)) < 0)
736 return ret;
737
738 if (chain->selector == NULL ||
739 (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
740 if (input != 1)
741 return -EINVAL;
742 break;
743 }
744
745 if (input == 0 || input > chain->selector->bNrInPins)
746 return -EINVAL;
747
748 return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
749 chain->selector->id, chain->dev->intfnum,
750 UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
751 }
752
753
754 case VIDIOC_ENUM_FMT:
755 {
756 struct v4l2_fmtdesc *fmt = arg;
757 struct uvc_format *format;
758 enum v4l2_buf_type type = fmt->type;
759 __u32 index = fmt->index;
760
761 if (fmt->type != stream->type ||
762 fmt->index >= stream->nformats)
763 return -EINVAL;
764
765 memset(fmt, 0, sizeof(*fmt));
766 fmt->index = index;
767 fmt->type = type;
768
769 format = &stream->format[fmt->index];
770 fmt->flags = 0;
771 if (format->flags & UVC_FMT_FLAG_COMPRESSED)
772 fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
773 strlcpy(fmt->description, format->name,
774 sizeof fmt->description);
775 fmt->description[sizeof fmt->description - 1] = 0;
776 fmt->pixelformat = format->fcc;
777 break;
778 }
779
780 case VIDIOC_TRY_FMT:
781 {
782 struct uvc_streaming_control probe;
783
784 return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
785 }
786
787 case VIDIOC_S_FMT:
788 if ((ret = uvc_acquire_privileges(handle)) < 0)
789 return ret;
790
791 return uvc_v4l2_set_format(stream, arg);
792
793 case VIDIOC_G_FMT:
794 return uvc_v4l2_get_format(stream, arg);
795
796
797 case VIDIOC_ENUM_FRAMESIZES:
798 {
799 struct v4l2_frmsizeenum *fsize = arg;
800 struct uvc_format *format = NULL;
801 struct uvc_frame *frame;
802 int i;
803
804
805 for (i = 0; i < stream->nformats; i++) {
806 if (stream->format[i].fcc ==
807 fsize->pixel_format) {
808 format = &stream->format[i];
809 break;
810 }
811 }
812 if (format == NULL)
813 return -EINVAL;
814
815 if (fsize->index >= format->nframes)
816 return -EINVAL;
817
818 frame = &format->frame[fsize->index];
819 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
820 fsize->discrete.width = frame->wWidth;
821 fsize->discrete.height = frame->wHeight;
822 break;
823 }
824
825
826 case VIDIOC_ENUM_FRAMEINTERVALS:
827 {
828 struct v4l2_frmivalenum *fival = arg;
829 struct uvc_format *format = NULL;
830 struct uvc_frame *frame = NULL;
831 int i;
832
833
834 for (i = 0; i < stream->nformats; i++) {
835 if (stream->format[i].fcc ==
836 fival->pixel_format) {
837 format = &stream->format[i];
838 break;
839 }
840 }
841 if (format == NULL)
842 return -EINVAL;
843
844 for (i = 0; i < format->nframes; i++) {
845 if (format->frame[i].wWidth == fival->width &&
846 format->frame[i].wHeight == fival->height) {
847 frame = &format->frame[i];
848 break;
849 }
850 }
851 if (frame == NULL)
852 return -EINVAL;
853
854 if (frame->bFrameIntervalType) {
855 if (fival->index >= frame->bFrameIntervalType)
856 return -EINVAL;
857
858 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
859 fival->discrete.numerator =
860 frame->dwFrameInterval[fival->index];
861 fival->discrete.denominator = 10000000;
862 uvc_simplify_fraction(&fival->discrete.numerator,
863 &fival->discrete.denominator, 8, 333);
864 } else {
865 fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
866 fival->stepwise.min.numerator =
867 frame->dwFrameInterval[0];
868 fival->stepwise.min.denominator = 10000000;
869 fival->stepwise.max.numerator =
870 frame->dwFrameInterval[1];
871 fival->stepwise.max.denominator = 10000000;
872 fival->stepwise.step.numerator =
873 frame->dwFrameInterval[2];
874 fival->stepwise.step.denominator = 10000000;
875 uvc_simplify_fraction(&fival->stepwise.min.numerator,
876 &fival->stepwise.min.denominator, 8, 333);
877 uvc_simplify_fraction(&fival->stepwise.max.numerator,
878 &fival->stepwise.max.denominator, 8, 333);
879 uvc_simplify_fraction(&fival->stepwise.step.numerator,
880 &fival->stepwise.step.denominator, 8, 333);
881 }
882 break;
883 }
884
885
886 case VIDIOC_G_PARM:
887 return uvc_v4l2_get_streamparm(stream, arg);
888
889 case VIDIOC_S_PARM:
890 if ((ret = uvc_acquire_privileges(handle)) < 0)
891 return ret;
892
893 return uvc_v4l2_set_streamparm(stream, arg);
894
895
896 case VIDIOC_CROPCAP:
897 {
898 struct v4l2_cropcap *ccap = arg;
899
900 if (ccap->type != stream->type)
901 return -EINVAL;
902
903 ccap->bounds.left = 0;
904 ccap->bounds.top = 0;
905
906 mutex_lock(&stream->mutex);
907 ccap->bounds.width = stream->cur_frame->wWidth;
908 ccap->bounds.height = stream->cur_frame->wHeight;
909 mutex_unlock(&stream->mutex);
910
911 ccap->defrect = ccap->bounds;
912
913 ccap->pixelaspect.numerator = 1;
914 ccap->pixelaspect.denominator = 1;
915 break;
916 }
917
918 case VIDIOC_G_CROP:
919 case VIDIOC_S_CROP:
920 return -EINVAL;
921
922
923 case VIDIOC_REQBUFS:
924 if ((ret = uvc_acquire_privileges(handle)) < 0)
925 return ret;
926
927 mutex_lock(&stream->mutex);
928 ret = uvc_alloc_buffers(&stream->queue, arg);
929 mutex_unlock(&stream->mutex);
930 if (ret < 0)
931 return ret;
932
933 if (ret == 0)
934 uvc_dismiss_privileges(handle);
935
936 ret = 0;
937 break;
938
939 case VIDIOC_QUERYBUF:
940 {
941 struct v4l2_buffer *buf = arg;
942
943 if (!uvc_has_privileges(handle))
944 return -EBUSY;
945
946 return uvc_query_buffer(&stream->queue, buf);
947 }
948
949 case VIDIOC_QBUF:
950 if (!uvc_has_privileges(handle))
951 return -EBUSY;
952
953 return uvc_queue_buffer(&stream->queue, arg);
954
955 case VIDIOC_DQBUF:
956 if (!uvc_has_privileges(handle))
957 return -EBUSY;
958
959 return uvc_dequeue_buffer(&stream->queue, arg,
960 file->f_flags & O_NONBLOCK);
961
962 case VIDIOC_STREAMON:
963 {
964 int *type = arg;
965
966 if (*type != stream->type)
967 return -EINVAL;
968
969 if (!uvc_has_privileges(handle))
970 return -EBUSY;
971
972 mutex_lock(&stream->mutex);
973 ret = uvc_video_enable(stream, 1);
974 mutex_unlock(&stream->mutex);
975 if (ret < 0)
976 return ret;
977 break;
978 }
979
980 case VIDIOC_STREAMOFF:
981 {
982 int *type = arg;
983
984 if (*type != stream->type)
985 return -EINVAL;
986
987 if (!uvc_has_privileges(handle))
988 return -EBUSY;
989
990 return uvc_video_enable(stream, 0);
991 }
992
993
994 case VIDIOC_ENUMSTD:
995 case VIDIOC_QUERYSTD:
996 case VIDIOC_G_STD:
997 case VIDIOC_S_STD:
998
999 case VIDIOC_OVERLAY:
1000
1001 case VIDIOC_ENUMAUDIO:
1002 case VIDIOC_ENUMAUDOUT:
1003
1004 case VIDIOC_ENUMOUTPUT:
1005 uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
1006 return -EINVAL;
1007
1008 case UVCIOC_CTRL_MAP:
1009 return uvc_ioctl_ctrl_map(chain, arg);
1010
1011 case UVCIOC_CTRL_QUERY:
1012 return uvc_xu_ctrl_query(chain, arg);
1013
1014 default:
1015 uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
1016 return -ENOTTY;
1017 }
1018
1019 return ret;
1020}
1021
1022static long uvc_v4l2_ioctl(struct file *file,
1023 unsigned int cmd, unsigned long arg)
1024{
1025 if (uvc_trace_param & UVC_TRACE_IOCTL) {
1026 uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
1027 v4l_printk_ioctl(cmd);
1028 printk(")\n");
1029 }
1030
1031 return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
1032}
1033
1034#ifdef CONFIG_COMPAT
1035struct uvc_xu_control_mapping32 {
1036 __u32 id;
1037 __u8 name[32];
1038 __u8 entity[16];
1039 __u8 selector;
1040
1041 __u8 size;
1042 __u8 offset;
1043 __u32 v4l2_type;
1044 __u32 data_type;
1045
1046 compat_caddr_t menu_info;
1047 __u32 menu_count;
1048
1049 __u32 reserved[4];
1050};
1051
1052static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
1053 const struct uvc_xu_control_mapping32 __user *up)
1054{
1055 struct uvc_menu_info __user *umenus;
1056 struct uvc_menu_info __user *kmenus;
1057 compat_caddr_t p;
1058
1059 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
1060 __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) ||
1061 __get_user(kp->menu_count, &up->menu_count))
1062 return -EFAULT;
1063
1064 memset(kp->reserved, 0, sizeof(kp->reserved));
1065
1066 if (kp->menu_count == 0) {
1067 kp->menu_info = NULL;
1068 return 0;
1069 }
1070
1071 if (__get_user(p, &up->menu_info))
1072 return -EFAULT;
1073 umenus = compat_ptr(p);
1074 if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus)))
1075 return -EFAULT;
1076
1077 kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus));
1078 if (kmenus == NULL)
1079 return -EFAULT;
1080 kp->menu_info = kmenus;
1081
1082 if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus)))
1083 return -EFAULT;
1084
1085 return 0;
1086}
1087
1088static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
1089 struct uvc_xu_control_mapping32 __user *up)
1090{
1091 struct uvc_menu_info __user *umenus;
1092 struct uvc_menu_info __user *kmenus = kp->menu_info;
1093 compat_caddr_t p;
1094
1095 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
1096 __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
1097 __put_user(kp->menu_count, &up->menu_count))
1098 return -EFAULT;
1099
1100 __clear_user(up->reserved, sizeof(up->reserved));
1101
1102 if (kp->menu_count == 0)
1103 return 0;
1104
1105 if (get_user(p, &up->menu_info))
1106 return -EFAULT;
1107 umenus = compat_ptr(p);
1108 if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus)))
1109 return -EFAULT;
1110
1111 if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus)))
1112 return -EFAULT;
1113
1114 return 0;
1115}
1116
1117struct uvc_xu_control_query32 {
1118 __u8 unit;
1119 __u8 selector;
1120 __u8 query;
1121 __u16 size;
1122 compat_caddr_t data;
1123};
1124
1125static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
1126 const struct uvc_xu_control_query32 __user *up)
1127{
1128 u8 __user *udata;
1129 u8 __user *kdata;
1130 compat_caddr_t p;
1131
1132 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
1133 __copy_from_user(kp, up, offsetof(typeof(*up), data)))
1134 return -EFAULT;
1135
1136 if (kp->size == 0) {
1137 kp->data = NULL;
1138 return 0;
1139 }
1140
1141 if (__get_user(p, &up->data))
1142 return -EFAULT;
1143 udata = compat_ptr(p);
1144 if (!access_ok(VERIFY_READ, udata, kp->size))
1145 return -EFAULT;
1146
1147 kdata = compat_alloc_user_space(kp->size);
1148 if (kdata == NULL)
1149 return -EFAULT;
1150 kp->data = kdata;
1151
1152 if (copy_in_user(kdata, udata, kp->size))
1153 return -EFAULT;
1154
1155 return 0;
1156}
1157
1158static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
1159 struct uvc_xu_control_query32 __user *up)
1160{
1161 u8 __user *udata;
1162 u8 __user *kdata = kp->data;
1163 compat_caddr_t p;
1164
1165 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
1166 __copy_to_user(up, kp, offsetof(typeof(*up), data)))
1167 return -EFAULT;
1168
1169 if (kp->size == 0)
1170 return 0;
1171
1172 if (get_user(p, &up->data))
1173 return -EFAULT;
1174 udata = compat_ptr(p);
1175 if (!access_ok(VERIFY_READ, udata, kp->size))
1176 return -EFAULT;
1177
1178 if (copy_in_user(udata, kdata, kp->size))
1179 return -EFAULT;
1180
1181 return 0;
1182}
1183
1184#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32)
1185#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32)
1186
1187static long uvc_v4l2_compat_ioctl32(struct file *file,
1188 unsigned int cmd, unsigned long arg)
1189{
1190 union {
1191 struct uvc_xu_control_mapping xmap;
1192 struct uvc_xu_control_query xqry;
1193 } karg;
1194 void __user *up = compat_ptr(arg);
1195 mm_segment_t old_fs;
1196 long ret;
1197
1198 switch (cmd) {
1199 case UVCIOC_CTRL_MAP32:
1200 cmd = UVCIOC_CTRL_MAP;
1201 ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
1202 break;
1203
1204 case UVCIOC_CTRL_QUERY32:
1205 cmd = UVCIOC_CTRL_QUERY;
1206 ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
1207 break;
1208
1209 default:
1210 return -ENOIOCTLCMD;
1211 }
1212
1213 old_fs = get_fs();
1214 set_fs(KERNEL_DS);
1215 ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
1216 set_fs(old_fs);
1217
1218 if (ret < 0)
1219 return ret;
1220
1221 switch (cmd) {
1222 case UVCIOC_CTRL_MAP:
1223 ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
1224 break;
1225
1226 case UVCIOC_CTRL_QUERY:
1227 ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
1228 break;
1229 }
1230
1231 return ret;
1232}
1233#endif
1234
1235static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
1236 size_t count, loff_t *ppos)
1237{
1238 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
1239 return -EINVAL;
1240}
1241
1242static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
1243{
1244 struct uvc_fh *handle = file->private_data;
1245 struct uvc_streaming *stream = handle->stream;
1246
1247 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
1248
1249 return uvc_queue_mmap(&stream->queue, vma);
1250}
1251
1252static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
1253{
1254 struct uvc_fh *handle = file->private_data;
1255 struct uvc_streaming *stream = handle->stream;
1256
1257 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
1258
1259 return uvc_queue_poll(&stream->queue, file, wait);
1260}
1261
1262#ifndef CONFIG_MMU
1263static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
1264 unsigned long addr, unsigned long len, unsigned long pgoff,
1265 unsigned long flags)
1266{
1267 struct uvc_fh *handle = file->private_data;
1268 struct uvc_streaming *stream = handle->stream;
1269
1270 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
1271
1272 return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
1273}
1274#endif
1275
1276const struct v4l2_file_operations uvc_fops = {
1277 .owner = THIS_MODULE,
1278 .open = uvc_v4l2_open,
1279 .release = uvc_v4l2_release,
1280 .unlocked_ioctl = uvc_v4l2_ioctl,
1281#ifdef CONFIG_COMPAT
1282 .compat_ioctl32 = uvc_v4l2_compat_ioctl32,
1283#endif
1284 .read = uvc_v4l2_read,
1285 .mmap = uvc_v4l2_mmap,
1286 .poll = uvc_v4l2_poll,
1287#ifndef CONFIG_MMU
1288 .get_unmapped_area = uvc_v4l2_get_unmapped_area,
1289#endif
1290};
1291
1292