diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-04-08 11:59:51 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-07 15:35:05 -0400 |
commit | b4012002f3a3983ba2797fde1613691d7f287048 (patch) | |
tree | 149ff2a22013fb77efd8bb374b9069083f4d5cd5 /drivers/media/video/uvc/uvc_v4l2.c | |
parent | cb74d482f81bf6a3ef3e29cb228c917e371773f2 (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.c | 43 |
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: |