On 23/03/2021 16:29, Ricardo Ribalda Delgado wrote: > Hi Hans > > On Mon, Mar 22, 2021 at 1:06 PM Hans Verkuil <hverkuil@xxxxxxxxx> wrote: >> >> Check for inactive controls in uvc_ctrl_is_accessible(). >> Use the new value for the master_id controls if present, >> otherwise use the existing value to determine if it is OK >> to set the control. Doing this here avoids attempting to >> set an inactive control, which will return an error from the >> USB device. > > Dont you think that this patch is not needed if this is used: > https://patchwork.linuxtv.org/project/linux-media/patch/20210319170906.278238-17-ribalda@xxxxxxxxxxxx/ > ? That might well be the case :-) I haven't really looked at that. > > > Also Maybe it is wrong. (Maybe it is the keyword here ;). > I think the initial assumption was that uvc_ctrl_is_accessible shall > not access the hardware, but with this patch it is accessing it. It's only accessing it if master_ctrl->loaded is 0 (see __uvc_ctrl_get()). If loaded is 0, and __uvc_ctrl_get() returns an error, then that error is ignored and the code will assume that the control is accessible. Note that what we try to avoid is *setting* an inactive control. In this case we're reading the master control, which should be safe except for USB hardware problems that can return an error. Regards, Hans >> >> Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> >> --- >> Ricardo: this can be added to your uvc series. It avoids attempts to set >> inactive controls. >> --- >> drivers/media/usb/uvc/uvc_ctrl.c | 28 +++++++++++++++++++++++++++- >> drivers/media/usb/uvc/uvc_v4l2.c | 4 ++-- >> drivers/media/usb/uvc/uvcvideo.h | 3 ++- >> 3 files changed, 31 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c >> index d9d4add1e813..6e7b904bc33d 100644 >> --- a/drivers/media/usb/uvc/uvc_ctrl.c >> +++ b/drivers/media/usb/uvc/uvc_ctrl.c >> @@ -1047,10 +1047,18 @@ static int uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id, >> } >> >> int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, >> - bool read) >> + const struct v4l2_ext_controls *ctrls, >> + unsigned long ioctl) >> { >> + struct uvc_control_mapping *master_map = NULL; >> + struct uvc_control *master_ctrl = NULL; >> struct uvc_control_mapping *mapping; >> struct uvc_control *ctrl; >> + bool read = ioctl == VIDIOC_G_EXT_CTRLS; >> + bool try = ioctl == VIDIOC_TRY_EXT_CTRLS; >> + s32 val; >> + int ret; >> + int i; >> >> if (__uvc_query_v4l2_class(chain, v4l2_id, 0) >= 0) >> return -EACCES; >> @@ -1065,6 +1073,24 @@ int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, >> if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read) >> return -EACCES; >> >> + if (read || try || !mapping->master_id) >> + return 0; >> + >> + for (i = ctrls->count - 1; i >= 0; i--) >> + if (ctrls->controls[i].id == mapping->master_id) >> + return ctrls->controls[i].value == >> + mapping->master_manual ? 0 : -EACCES; >> + >> + __uvc_find_control(ctrl->entity, mapping->master_id, &master_map, >> + &master_ctrl, 0); >> + >> + if (!master_ctrl || !(master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) >> + return 0; >> + >> + ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val); >> + if (ret >= 0 && val != mapping->master_manual) >> + return -EACCES; >> + >> return 0; >> } >> >> diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c >> index 12362e0f9870..e40db7ae18b1 100644 >> --- a/drivers/media/usb/uvc/uvc_v4l2.c >> +++ b/drivers/media/usb/uvc/uvc_v4l2.c >> @@ -803,8 +803,8 @@ static int uvc_ctrl_check_access(struct uvc_video_chain *chain, >> int ret = 0; >> >> for (i = 0; i < ctrls->count; ++ctrl, ++i) { >> - ret = uvc_ctrl_is_accessible(chain, ctrl->id, >> - ioctl == VIDIOC_G_EXT_CTRLS); >> + ret = uvc_ctrl_is_accessible(chain, ctrl->id, ctrls, >> + ioctl); >> if (ret) >> break; >> } >> diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h >> index aedb4d3d4db9..8849d7953767 100644 >> --- a/drivers/media/usb/uvc/uvcvideo.h >> +++ b/drivers/media/usb/uvc/uvcvideo.h >> @@ -869,7 +869,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle) >> int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); >> int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl); >> int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, >> - bool read); >> + const struct v4l2_ext_controls *ctrls, >> + unsigned long ioctl); >> >> int uvc_xu_ctrl_query(struct uvc_video_chain *chain, >> struct uvc_xu_control_query *xqry); >> -- >> 2.30.0 >> >> > >