]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
media: uvcvideo: Use entity get_cur in uvc_ctrl_set
authorYunke Cao <yunkec@google.com>
Thu, 7 Jul 2022 08:53:31 +0000 (10:53 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Thu, 24 Nov 2022 13:24:33 +0000 (14:24 +0100)
BugLink: https://bugs.launchpad.net/bugs/1996825
[ Upstream commit 5f36851c36b30f713f588ed2b60aa7b4512e2c76 ]

Entity controls should get_cur using an entity-defined function
instead of via a query. Fix this in uvc_ctrl_set.

Fixes: 65900c581d01 ("media: uvcvideo: Allow entity-defined get_info and get_cur")
Signed-off-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/media/usb/uvc/uvc_ctrl.c

index b3dde98499f419a4f491974e73ab641e112c3bf6..5bb29fc49538ea7b7dee365c828fe8bd13096875 100644 (file)
@@ -988,36 +988,56 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
        return value;
 }
 
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
-       struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
-       s32 *value)
+static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
+                              struct uvc_control *ctrl)
 {
+       u8 *data;
        int ret;
 
-       if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
-               return -EACCES;
+       if (ctrl->loaded)
+               return 0;
 
-       if (!ctrl->loaded) {
-               if (ctrl->entity->get_cur) {
-                       ret = ctrl->entity->get_cur(chain->dev,
-                               ctrl->entity,
-                               ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-               } else {
-                       ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-                               ctrl->entity->id,
-                               chain->dev->intfnum,
-                               ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-               }
-               if (ret < 0)
-                       return ret;
+       data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
 
+       if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
+               memset(data, 0, ctrl->info.size);
                ctrl->loaded = 1;
+
+               return 0;
        }
 
+       if (ctrl->entity->get_cur)
+               ret = ctrl->entity->get_cur(chain->dev, ctrl->entity,
+                                           ctrl->info.selector, data,
+                                           ctrl->info.size);
+       else
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+                                    ctrl->entity->id, chain->dev->intfnum,
+                                    ctrl->info.selector, data,
+                                    ctrl->info.size);
+
+       if (ret < 0)
+               return ret;
+
+       ctrl->loaded = 1;
+
+       return ret;
+}
+
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+                         struct uvc_control *ctrl,
+                         struct uvc_control_mapping *mapping,
+                         s32 *value)
+{
+       int ret;
+
+       if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+               return -EACCES;
+
+       ret = __uvc_ctrl_load_cur(chain, ctrl);
+       if (ret < 0)
+               return ret;
+
        *value = __uvc_ctrl_get_value(mapping,
                                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
@@ -1667,21 +1687,10 @@ int uvc_ctrl_set(struct uvc_fh *handle,
         * needs to be loaded from the device to perform the read-modify-write
         * operation.
         */
-       if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
-               if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
-                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               0, ctrl->info.size);
-               } else {
-                       ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-                               ctrl->entity->id, chain->dev->intfnum,
-                               ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               ctrl->loaded = 1;
+       if ((ctrl->info.size * 8) != mapping->size) {
+               ret = __uvc_ctrl_load_cur(chain, ctrl);
+               if (ret < 0)
+                       return ret;
        }
 
        /* Backup the current value in case we need to rollback later. */