aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc/uvc_v4l2.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-04-08 11:59:51 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-07 15:35:05 -0400
commitb4012002f3a3983ba2797fde1613691d7f287048 (patch)
tree149ff2a22013fb77efd8bb374b9069083f4d5cd5 /drivers/media/video/uvc/uvc_v4l2.c
parentcb74d482f81bf6a3ef3e29cb228c917e371773f2 (diff)
[media] uvcvideo: Add support for control events
Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc/uvc_v4l2.c')
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 4ef21e9cb28c..a3322ed81e39 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -25,6 +25,8 @@
25#include <linux/atomic.h> 25#include <linux/atomic.h>
26 26
27#include <media/v4l2-common.h> 27#include <media/v4l2-common.h>
28#include <media/v4l2-ctrls.h>
29#include <media/v4l2-event.h>
28#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
29 31
30#include "uvcvideo.h" 32#include "uvcvideo.h"
@@ -505,6 +507,8 @@ static int uvc_v4l2_open(struct file *file)
505 } 507 }
506 } 508 }
507 509
510 v4l2_fh_init(&handle->vfh, stream->vdev);
511 v4l2_fh_add(&handle->vfh);
508 handle->chain = stream->chain; 512 handle->chain = stream->chain;
509 handle->stream = stream; 513 handle->stream = stream;
510 handle->state = UVC_HANDLE_PASSIVE; 514 handle->state = UVC_HANDLE_PASSIVE;
@@ -528,6 +532,8 @@ static int uvc_v4l2_release(struct file *file)
528 532
529 /* Release the file handle. */ 533 /* Release the file handle. */
530 uvc_dismiss_privileges(handle); 534 uvc_dismiss_privileges(handle);
535 v4l2_fh_del(&handle->vfh);
536 v4l2_fh_exit(&handle->vfh);
531 kfree(handle); 537 kfree(handle);
532 file->private_data = NULL; 538 file->private_data = NULL;
533 539
@@ -584,7 +590,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
584 return ret; 590 return ret;
585 591
586 ret = uvc_ctrl_get(chain, &xctrl); 592 ret = uvc_ctrl_get(chain, &xctrl);
587 uvc_ctrl_rollback(chain); 593 uvc_ctrl_rollback(handle);
588 if (ret >= 0) 594 if (ret >= 0)
589 ctrl->value = xctrl.value; 595 ctrl->value = xctrl.value;
590 break; 596 break;
@@ -605,10 +611,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
605 611
606 ret = uvc_ctrl_set(chain, &xctrl); 612 ret = uvc_ctrl_set(chain, &xctrl);
607 if (ret < 0) { 613 if (ret < 0) {
608 uvc_ctrl_rollback(chain); 614 uvc_ctrl_rollback(handle);
609 return ret; 615 return ret;
610 } 616 }
611 ret = uvc_ctrl_commit(chain); 617 ret = uvc_ctrl_commit(handle, &xctrl, 1);
612 if (ret == 0) 618 if (ret == 0)
613 ctrl->value = xctrl.value; 619 ctrl->value = xctrl.value;
614 break; 620 break;
@@ -630,13 +636,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
630 for (i = 0; i < ctrls->count; ++ctrl, ++i) { 636 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
631 ret = uvc_ctrl_get(chain, ctrl); 637 ret = uvc_ctrl_get(chain, ctrl);
632 if (ret < 0) { 638 if (ret < 0) {
633 uvc_ctrl_rollback(chain); 639 uvc_ctrl_rollback(handle);
634 ctrls->error_idx = i; 640 ctrls->error_idx = i;
635 return ret; 641 return ret;
636 } 642 }
637 } 643 }
638 ctrls->error_idx = 0; 644 ctrls->error_idx = 0;
639 ret = uvc_ctrl_rollback(chain); 645 ret = uvc_ctrl_rollback(handle);
640 break; 646 break;
641 } 647 }
642 648
@@ -654,7 +660,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
654 for (i = 0; i < ctrls->count; ++ctrl, ++i) { 660 for (i = 0; i < ctrls->count; ++ctrl, ++i) {
655 ret = uvc_ctrl_set(chain, ctrl); 661 ret = uvc_ctrl_set(chain, ctrl);
656 if (ret < 0) { 662 if (ret < 0) {
657 uvc_ctrl_rollback(chain); 663 uvc_ctrl_rollback(handle);
658 ctrls->error_idx = i; 664 ctrls->error_idx = i;
659 return ret; 665 return ret;
660 } 666 }
@@ -663,9 +669,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
663 ctrls->error_idx = 0; 669 ctrls->error_idx = 0;
664 670
665 if (cmd == VIDIOC_S_EXT_CTRLS) 671 if (cmd == VIDIOC_S_EXT_CTRLS)
666 ret = uvc_ctrl_commit(chain); 672 ret = uvc_ctrl_commit(handle,
673 ctrls->controls, ctrls->count);
667 else 674 else
668 ret = uvc_ctrl_rollback(chain); 675 ret = uvc_ctrl_rollback(handle);
669 break; 676 break;
670 } 677 }
671 678
@@ -990,6 +997,26 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
990 return uvc_video_enable(stream, 0); 997 return uvc_video_enable(stream, 0);
991 } 998 }
992 999
1000 case VIDIOC_SUBSCRIBE_EVENT:
1001 {
1002 struct v4l2_event_subscription *sub = arg;
1003
1004 switch (sub->type) {
1005 case V4L2_EVENT_CTRL:
1006 return v4l2_event_subscribe(&handle->vfh, sub, 0,
1007 &uvc_ctrl_sub_ev_ops);
1008 default:
1009 return -EINVAL;
1010 }
1011 }
1012
1013 case VIDIOC_UNSUBSCRIBE_EVENT:
1014 return v4l2_event_unsubscribe(&handle->vfh, arg);
1015
1016 case VIDIOC_DQEVENT:
1017 return v4l2_event_dequeue(&handle->vfh, arg,
1018 file->f_flags & O_NONBLOCK);
1019
993 /* Analog video standards make no sense for digital cameras. */ 1020 /* Analog video standards make no sense for digital cameras. */
994 case VIDIOC_ENUMSTD: 1021 case VIDIOC_ENUMSTD:
995 case VIDIOC_QUERYSTD: 1022 case VIDIOC_QUERYSTD: