On Mon Sep 28 17:50:19 2026 -0400, Michael Jordan wrote:
> The flags fixup table is only applied to extension unit controls.
> Apply it to all controls, and skip GET_INFO when an entry matches.
>
> Suggested-by: Ricardo Ribalda <[email protected]>
> Reviewed-by: Ricardo Ribalda <[email protected]>
> Reviewed-by: Hans de Goede <[email protected]>
> Assisted-by: LLM
> Signed-off-by: Michael Jordan <[email protected]>
> Link: https://patch.msgid.link/[email protected]
> Signed-off-by: Hans de Goede <[email protected]>
> Signed-off-by: Laurent Pinchart <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/usb/uvc/uvc_ctrl.c | 91 ++++++++++++++++++++++------------------
1 file changed, 50 insertions(+), 41 deletions(-)
---
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index ea28c4e819bd..97f0fc48321e 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -2841,6 +2841,48 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct
v4l2_ext_control *xctrl)
* Dynamic controls
*/
+static bool uvc_ctrl_fixup_flags(struct uvc_device *dev,
+ const struct uvc_control *ctrl,
+ struct uvc_control_info *info)
+{
+ struct uvc_ctrl_fixup {
+ struct usb_device_id id;
+ u8 entity;
+ u8 selector;
+ u8 flags;
+ };
+
+ static const struct uvc_ctrl_fixup fixups[] = {
+ { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
+ UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+ UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+ UVC_CTRL_FLAG_AUTO_UPDATE },
+ { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
+ UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+ UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+ UVC_CTRL_FLAG_AUTO_UPDATE },
+ { { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
+ UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+ UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+ UVC_CTRL_FLAG_AUTO_UPDATE },
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
+ if (!usb_match_one_id(dev->intf, &fixups[i].id))
+ continue;
+
+ if (fixups[i].entity == ctrl->entity->id &&
+ fixups[i].selector == info->selector) {
+ info->flags = fixups[i].flags;
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* Retrieve flags for a given control
*/
@@ -2851,6 +2893,14 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev,
u8 *data;
int ret;
+ /*
+ * Some devices report bogus capabilities through GET_INFO. If the
+ * fixup table covers this control, take the flags from the table and
+ * skip the query altogether.
+ */
+ if (uvc_ctrl_fixup_flags(dev, ctrl, info))
+ return 0;
+
data = kmalloc(1, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -2882,45 +2932,6 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev,
return ret;
}
-static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
- const struct uvc_control *ctrl, struct uvc_control_info *info)
-{
- struct uvc_ctrl_fixup {
- struct usb_device_id id;
- u8 entity;
- u8 selector;
- u8 flags;
- };
-
- static const struct uvc_ctrl_fixup fixups[] = {
- { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
- UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
- UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
- UVC_CTRL_FLAG_AUTO_UPDATE },
- { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
- UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
- UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
- UVC_CTRL_FLAG_AUTO_UPDATE },
- { { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
- UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
- UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
- UVC_CTRL_FLAG_AUTO_UPDATE },
- };
-
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
- if (!usb_match_one_id(dev->intf, &fixups[i].id))
- continue;
-
- if (fixups[i].entity == ctrl->entity->id &&
- fixups[i].selector == info->selector) {
- info->flags = fixups[i].flags;
- return;
- }
- }
-}
-
/*
* Query control information (size and flags) for XU controls.
*/
@@ -2961,8 +2972,6 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
goto done;
}
- uvc_ctrl_fixup_xu_info(dev, ctrl, info);
-
uvc_dbg(dev, CONTROL,
"XU control %pUl/%u queried: len %u, flags { get %u set %u auto
%u }\n",
info->entity, info->selector, info->size,
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]