Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: uvcvideo: Fix support for V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX

The VIDIOC_G_EXT_CTRLS with which V4L2_CTRL_WHICH_(MIN|MAX)_VAL can only
work for controls that have previously announced support for it.

This patch fixes the following v4l2-compliance error:

info: checking extended control 'User Controls' (0x00980001)
fail: v4l2-test-controls.cpp(980): ret != EINVAL (got 13)
test VIDIOC_G/S/TRY_EXT_CTRLS: FAIL

Fixes: 39d2c891c96e ("media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL")
Cc: stable@vger.kernel.org
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Ricardo Ribalda and committed by
Hans Verkuil
4238bd6d 85883141

+19 -7
+12 -2
drivers/media/usb/uvc/uvc_ctrl.c
··· 1432 1432 * auto_exposure=1, exposure_time_absolute=251. 1433 1433 */ 1434 1434 int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, 1435 - const struct v4l2_ext_controls *ctrls, 1435 + const struct v4l2_ext_controls *ctrls, u32 which, 1436 1436 unsigned long ioctl) 1437 1437 { 1438 1438 struct uvc_control_mapping *master_map = NULL; ··· 1442 1442 s32 val; 1443 1443 int ret; 1444 1444 int i; 1445 + /* 1446 + * There is no need to check the ioctl, all the ioctls except 1447 + * VIDIOC_G_EXT_CTRLS use which=V4L2_CTRL_WHICH_CUR_VAL. 1448 + */ 1449 + bool is_which_min_max = which == V4L2_CTRL_WHICH_MIN_VAL || 1450 + which == V4L2_CTRL_WHICH_MAX_VAL; 1445 1451 1446 1452 if (__uvc_query_v4l2_class(chain, v4l2_id, 0) >= 0) 1447 - return -EACCES; 1453 + return is_which_min_max ? -EINVAL : -EACCES; 1448 1454 1449 1455 ctrl = uvc_find_control(chain, v4l2_id, &mapping); 1450 1456 if (!ctrl) 1457 + return -EINVAL; 1458 + 1459 + if ((!(ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) || 1460 + !(ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)) && is_which_min_max) 1451 1461 return -EINVAL; 1452 1462 1453 1463 if (ioctl == VIDIOC_G_EXT_CTRLS)
+6 -4
drivers/media/usb/uvc/uvc_v4l2.c
··· 765 765 766 766 static int uvc_ctrl_check_access(struct uvc_video_chain *chain, 767 767 struct v4l2_ext_controls *ctrls, 768 - unsigned long ioctl) 768 + u32 which, unsigned long ioctl) 769 769 { 770 770 struct v4l2_ext_control *ctrl = ctrls->controls; 771 771 unsigned int i; 772 772 int ret = 0; 773 773 774 774 for (i = 0; i < ctrls->count; ++ctrl, ++i) { 775 - ret = uvc_ctrl_is_accessible(chain, ctrl->id, ctrls, ioctl); 775 + ret = uvc_ctrl_is_accessible(chain, ctrl->id, ctrls, which, 776 + ioctl); 776 777 if (ret) 777 778 break; 778 779 } ··· 807 806 which = V4L2_CTRL_WHICH_CUR_VAL; 808 807 } 809 808 810 - ret = uvc_ctrl_check_access(chain, ctrls, VIDIOC_G_EXT_CTRLS); 809 + ret = uvc_ctrl_check_access(chain, ctrls, which, VIDIOC_G_EXT_CTRLS); 811 810 if (ret < 0) 812 811 return ret; 813 812 ··· 841 840 if (!ctrls->count) 842 841 return 0; 843 842 844 - ret = uvc_ctrl_check_access(chain, ctrls, ioctl); 843 + ret = uvc_ctrl_check_access(chain, ctrls, V4L2_CTRL_WHICH_CUR_VAL, 844 + ioctl); 845 845 if (ret < 0) 846 846 return ret; 847 847
+1 -1
drivers/media/usb/uvc/uvcvideo.h
··· 786 786 struct v4l2_ext_control *xctrl); 787 787 int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl); 788 788 int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, 789 - const struct v4l2_ext_controls *ctrls, 789 + const struct v4l2_ext_controls *ctrls, u32 which, 790 790 unsigned long ioctl); 791 791 792 792 int uvc_xu_ctrl_query(struct uvc_video_chain *chain,