diff options
Diffstat (limited to 'drivers/media/video/pwc/pwc-v4l.c')
-rw-r--r-- | drivers/media/video/pwc/pwc-v4l.c | 145 |
1 files changed, 71 insertions, 74 deletions
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 2834e3e65b39..c691e29cc36e 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -464,26 +464,24 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | |||
464 | struct pwc_device *pdev = video_drvdata(file); | 464 | struct pwc_device *pdev = video_drvdata(file); |
465 | int ret, pixelformat, compression = 0; | 465 | int ret, pixelformat, compression = 0; |
466 | 466 | ||
467 | if (pwc_test_n_set_capt_file(pdev, file)) | ||
468 | return -EBUSY; | ||
469 | |||
470 | ret = pwc_vidioc_try_fmt(pdev, f); | 467 | ret = pwc_vidioc_try_fmt(pdev, f); |
471 | if (ret < 0) | 468 | if (ret < 0) |
472 | return ret; | 469 | return ret; |
473 | 470 | ||
474 | pixelformat = f->fmt.pix.pixelformat; | 471 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
472 | return -ERESTARTSYS; | ||
475 | 473 | ||
476 | mutex_lock(&pdev->udevlock); | 474 | ret = pwc_test_n_set_capt_file(pdev, file); |
477 | if (!pdev->udev) { | 475 | if (ret) |
478 | ret = -ENODEV; | ||
479 | goto leave; | 476 | goto leave; |
480 | } | ||
481 | 477 | ||
482 | if (pdev->iso_init) { | 478 | if (pdev->vb_queue.streaming) { |
483 | ret = -EBUSY; | 479 | ret = -EBUSY; |
484 | goto leave; | 480 | goto leave; |
485 | } | 481 | } |
486 | 482 | ||
483 | pixelformat = f->fmt.pix.pixelformat; | ||
484 | |||
487 | PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " | 485 | PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " |
488 | "format=%c%c%c%c\n", | 486 | "format=%c%c%c%c\n", |
489 | f->fmt.pix.width, f->fmt.pix.height, pdev->vframes, | 487 | f->fmt.pix.width, f->fmt.pix.height, pdev->vframes, |
@@ -499,7 +497,7 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | |||
499 | 497 | ||
500 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); | 498 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); |
501 | leave: | 499 | leave: |
502 | mutex_unlock(&pdev->udevlock); | 500 | mutex_unlock(&pdev->vb_queue_lock); |
503 | return ret; | 501 | return ret; |
504 | } | 502 | } |
505 | 503 | ||
@@ -507,9 +505,6 @@ static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap | |||
507 | { | 505 | { |
508 | struct pwc_device *pdev = video_drvdata(file); | 506 | struct pwc_device *pdev = video_drvdata(file); |
509 | 507 | ||
510 | if (!pdev->udev) | ||
511 | return -ENODEV; | ||
512 | |||
513 | strcpy(cap->driver, PWC_NAME); | 508 | strcpy(cap->driver, PWC_NAME); |
514 | strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); | 509 | strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); |
515 | usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); | 510 | usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); |
@@ -540,15 +535,12 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i) | |||
540 | return i ? -EINVAL : 0; | 535 | return i ? -EINVAL : 0; |
541 | } | 536 | } |
542 | 537 | ||
543 | static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl) | 538 | static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
544 | { | 539 | { |
545 | struct pwc_device *pdev = | 540 | struct pwc_device *pdev = |
546 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 541 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
547 | int ret = 0; | 542 | int ret = 0; |
548 | 543 | ||
549 | if (!pdev->udev) | ||
550 | return -ENODEV; | ||
551 | |||
552 | switch (ctrl->id) { | 544 | switch (ctrl->id) { |
553 | case V4L2_CID_AUTO_WHITE_BALANCE: | 545 | case V4L2_CID_AUTO_WHITE_BALANCE: |
554 | if (pdev->color_bal_valid && | 546 | if (pdev->color_bal_valid && |
@@ -615,18 +607,6 @@ static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl) | |||
615 | return ret; | 607 | return ret; |
616 | } | 608 | } |
617 | 609 | ||
618 | static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | ||
619 | { | ||
620 | struct pwc_device *pdev = | ||
621 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | ||
622 | int ret; | ||
623 | |||
624 | mutex_lock(&pdev->udevlock); | ||
625 | ret = pwc_g_volatile_ctrl_unlocked(ctrl); | ||
626 | mutex_unlock(&pdev->udevlock); | ||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | static int pwc_set_awb(struct pwc_device *pdev) | 610 | static int pwc_set_awb(struct pwc_device *pdev) |
631 | { | 611 | { |
632 | int ret; | 612 | int ret; |
@@ -648,7 +628,7 @@ static int pwc_set_awb(struct pwc_device *pdev) | |||
648 | if (pdev->auto_white_balance->val == awb_indoor || | 628 | if (pdev->auto_white_balance->val == awb_indoor || |
649 | pdev->auto_white_balance->val == awb_outdoor || | 629 | pdev->auto_white_balance->val == awb_outdoor || |
650 | pdev->auto_white_balance->val == awb_fl) | 630 | pdev->auto_white_balance->val == awb_fl) |
651 | pwc_g_volatile_ctrl_unlocked(pdev->auto_white_balance); | 631 | pwc_g_volatile_ctrl(pdev->auto_white_balance); |
652 | } | 632 | } |
653 | if (pdev->auto_white_balance->val != awb_manual) | 633 | if (pdev->auto_white_balance->val != awb_manual) |
654 | return 0; | 634 | return 0; |
@@ -812,13 +792,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
812 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 792 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
813 | int ret = 0; | 793 | int ret = 0; |
814 | 794 | ||
815 | mutex_lock(&pdev->udevlock); | ||
816 | |||
817 | if (!pdev->udev) { | ||
818 | ret = -ENODEV; | ||
819 | goto leave; | ||
820 | } | ||
821 | |||
822 | switch (ctrl->id) { | 795 | switch (ctrl->id) { |
823 | case V4L2_CID_BRIGHTNESS: | 796 | case V4L2_CID_BRIGHTNESS: |
824 | ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, | 797 | ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, |
@@ -915,8 +888,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
915 | if (ret) | 888 | if (ret) |
916 | PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); | 889 | PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); |
917 | 890 | ||
918 | leave: | ||
919 | mutex_unlock(&pdev->udevlock); | ||
920 | return ret; | 891 | return ret; |
921 | } | 892 | } |
922 | 893 | ||
@@ -949,11 +920,9 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | |||
949 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 920 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
950 | return -EINVAL; | 921 | return -EINVAL; |
951 | 922 | ||
952 | mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */ | ||
953 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", | 923 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", |
954 | pdev->width, pdev->height); | 924 | pdev->width, pdev->height); |
955 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); | 925 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); |
956 | mutex_unlock(&pdev->udevlock); | ||
957 | return 0; | 926 | return 0; |
958 | } | 927 | } |
959 | 928 | ||
@@ -968,70 +937,98 @@ static int pwc_reqbufs(struct file *file, void *fh, | |||
968 | struct v4l2_requestbuffers *rb) | 937 | struct v4l2_requestbuffers *rb) |
969 | { | 938 | { |
970 | struct pwc_device *pdev = video_drvdata(file); | 939 | struct pwc_device *pdev = video_drvdata(file); |
940 | int ret; | ||
971 | 941 | ||
972 | if (pwc_test_n_set_capt_file(pdev, file)) | 942 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
973 | return -EBUSY; | 943 | return -ERESTARTSYS; |
974 | 944 | ||
975 | return vb2_reqbufs(&pdev->vb_queue, rb); | 945 | ret = pwc_test_n_set_capt_file(pdev, file); |
946 | if (ret == 0) | ||
947 | ret = vb2_reqbufs(&pdev->vb_queue, rb); | ||
948 | |||
949 | mutex_unlock(&pdev->vb_queue_lock); | ||
950 | return ret; | ||
976 | } | 951 | } |
977 | 952 | ||
978 | static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) | 953 | static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) |
979 | { | 954 | { |
980 | struct pwc_device *pdev = video_drvdata(file); | 955 | struct pwc_device *pdev = video_drvdata(file); |
956 | int ret; | ||
981 | 957 | ||
982 | return vb2_querybuf(&pdev->vb_queue, buf); | 958 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
959 | return -ERESTARTSYS; | ||
960 | |||
961 | ret = pwc_test_n_set_capt_file(pdev, file); | ||
962 | if (ret == 0) | ||
963 | ret = vb2_querybuf(&pdev->vb_queue, buf); | ||
964 | |||
965 | mutex_unlock(&pdev->vb_queue_lock); | ||
966 | return ret; | ||
983 | } | 967 | } |
984 | 968 | ||
985 | static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | 969 | static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) |
986 | { | 970 | { |
987 | struct pwc_device *pdev = video_drvdata(file); | 971 | struct pwc_device *pdev = video_drvdata(file); |
972 | int ret; | ||
988 | 973 | ||
989 | if (!pdev->udev) | 974 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
990 | return -ENODEV; | 975 | return -ERESTARTSYS; |
991 | 976 | ||
992 | if (pdev->capt_file != file) | 977 | ret = pwc_test_n_set_capt_file(pdev, file); |
993 | return -EBUSY; | 978 | if (ret == 0) |
979 | ret = vb2_qbuf(&pdev->vb_queue, buf); | ||
994 | 980 | ||
995 | return vb2_qbuf(&pdev->vb_queue, buf); | 981 | mutex_unlock(&pdev->vb_queue_lock); |
982 | return ret; | ||
996 | } | 983 | } |
997 | 984 | ||
998 | static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | 985 | static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) |
999 | { | 986 | { |
1000 | struct pwc_device *pdev = video_drvdata(file); | 987 | struct pwc_device *pdev = video_drvdata(file); |
988 | int ret; | ||
1001 | 989 | ||
1002 | if (!pdev->udev) | 990 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
1003 | return -ENODEV; | 991 | return -ERESTARTSYS; |
1004 | 992 | ||
1005 | if (pdev->capt_file != file) | 993 | ret = pwc_test_n_set_capt_file(pdev, file); |
1006 | return -EBUSY; | 994 | if (ret == 0) |
995 | ret = vb2_dqbuf(&pdev->vb_queue, buf, | ||
996 | file->f_flags & O_NONBLOCK); | ||
1007 | 997 | ||
1008 | return vb2_dqbuf(&pdev->vb_queue, buf, file->f_flags & O_NONBLOCK); | 998 | mutex_unlock(&pdev->vb_queue_lock); |
999 | return ret; | ||
1009 | } | 1000 | } |
1010 | 1001 | ||
1011 | static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) | 1002 | static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) |
1012 | { | 1003 | { |
1013 | struct pwc_device *pdev = video_drvdata(file); | 1004 | struct pwc_device *pdev = video_drvdata(file); |
1005 | int ret; | ||
1014 | 1006 | ||
1015 | if (!pdev->udev) | 1007 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
1016 | return -ENODEV; | 1008 | return -ERESTARTSYS; |
1017 | 1009 | ||
1018 | if (pdev->capt_file != file) | 1010 | ret = pwc_test_n_set_capt_file(pdev, file); |
1019 | return -EBUSY; | 1011 | if (ret == 0) |
1012 | ret = vb2_streamon(&pdev->vb_queue, i); | ||
1020 | 1013 | ||
1021 | return vb2_streamon(&pdev->vb_queue, i); | 1014 | mutex_unlock(&pdev->vb_queue_lock); |
1015 | return ret; | ||
1022 | } | 1016 | } |
1023 | 1017 | ||
1024 | static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) | 1018 | static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) |
1025 | { | 1019 | { |
1026 | struct pwc_device *pdev = video_drvdata(file); | 1020 | struct pwc_device *pdev = video_drvdata(file); |
1021 | int ret; | ||
1027 | 1022 | ||
1028 | if (!pdev->udev) | 1023 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
1029 | return -ENODEV; | 1024 | return -ERESTARTSYS; |
1030 | 1025 | ||
1031 | if (pdev->capt_file != file) | 1026 | ret = pwc_test_n_set_capt_file(pdev, file); |
1032 | return -EBUSY; | 1027 | if (ret == 0) |
1028 | ret = vb2_streamoff(&pdev->vb_queue, i); | ||
1033 | 1029 | ||
1034 | return vb2_streamoff(&pdev->vb_queue, i); | 1030 | mutex_unlock(&pdev->vb_queue_lock); |
1031 | return ret; | ||
1035 | } | 1032 | } |
1036 | 1033 | ||
1037 | static int pwc_enum_framesizes(struct file *file, void *fh, | 1034 | static int pwc_enum_framesizes(struct file *file, void *fh, |
@@ -1119,19 +1116,17 @@ static int pwc_s_parm(struct file *file, void *fh, | |||
1119 | parm->parm.capture.timeperframe.numerator == 0) | 1116 | parm->parm.capture.timeperframe.numerator == 0) |
1120 | return -EINVAL; | 1117 | return -EINVAL; |
1121 | 1118 | ||
1122 | if (pwc_test_n_set_capt_file(pdev, file)) | ||
1123 | return -EBUSY; | ||
1124 | |||
1125 | fps = parm->parm.capture.timeperframe.denominator / | 1119 | fps = parm->parm.capture.timeperframe.denominator / |
1126 | parm->parm.capture.timeperframe.numerator; | 1120 | parm->parm.capture.timeperframe.numerator; |
1127 | 1121 | ||
1128 | mutex_lock(&pdev->udevlock); | 1122 | if (mutex_lock_interruptible(&pdev->vb_queue_lock)) |
1129 | if (!pdev->udev) { | 1123 | return -ERESTARTSYS; |
1130 | ret = -ENODEV; | 1124 | |
1125 | ret = pwc_test_n_set_capt_file(pdev, file); | ||
1126 | if (ret) | ||
1131 | goto leave; | 1127 | goto leave; |
1132 | } | ||
1133 | 1128 | ||
1134 | if (pdev->iso_init) { | 1129 | if (pdev->vb_queue.streaming) { |
1135 | ret = -EBUSY; | 1130 | ret = -EBUSY; |
1136 | goto leave; | 1131 | goto leave; |
1137 | } | 1132 | } |
@@ -1142,7 +1137,7 @@ static int pwc_s_parm(struct file *file, void *fh, | |||
1142 | pwc_g_parm(file, fh, parm); | 1137 | pwc_g_parm(file, fh, parm); |
1143 | 1138 | ||
1144 | leave: | 1139 | leave: |
1145 | mutex_unlock(&pdev->udevlock); | 1140 | mutex_unlock(&pdev->vb_queue_lock); |
1146 | return ret; | 1141 | return ret; |
1147 | } | 1142 | } |
1148 | 1143 | ||
@@ -1166,4 +1161,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { | |||
1166 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, | 1161 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, |
1167 | .vidioc_g_parm = pwc_g_parm, | 1162 | .vidioc_g_parm = pwc_g_parm, |
1168 | .vidioc_s_parm = pwc_s_parm, | 1163 | .vidioc_s_parm = pwc_s_parm, |
1164 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
1165 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
1169 | }; | 1166 | }; |