From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Michael Jordan <jordan.mymail@gmail.com>
Cc: Hans de Goede <hansg@kernel.org>,
Ricardo Ribalda <ribalda@chromium.org>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Hans Verkuil <hverkuil+cisco@kernel.org>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/3] media: uvcvideo: generalise the XU flags fixup to all controls
Date: Mon, 28 Sep 2026 14:44:23 +0300 [thread overview]
Message-ID: <20260928114423.GB157191@killaraus.ideasonboard.com> (raw)
In-Reply-To: <20260902002553.34839-3-jordan.mymail@gmail.com>
On Tue, Sep 01, 2026 at 08:25:52PM -0400, Michael Jordan wrote:
> uvc_ctrl_fixup_xu_info() holds a per-device table of controls whose
> GET_INFO reply is wrong, and overrides the flags for them. It only runs
> from uvc_ctrl_fill_xu_info(), so it can only correct extension unit
> controls, but standard controls suffer from the same class of firmware
> bug: a device can report a wrong capability byte for a Camera Terminal
> or Processing Unit control just as easily.
>
> Rename it to uvc_ctrl_fixup_flags() and call it at the start of
> uvc_ctrl_get_flags(), where the flags are derived from GET_INFO for
> every control, standard and XU alike. The fixup replaces the flags
> wholesale, so when the table covers a control there is no point in
> querying a device we already know gives a wrong answer: return early
> and skip the GET_INFO request altogether. The call in
> uvc_ctrl_fill_xu_info() is dropped, as uvc_ctrl_get_flags() now handles
> the fixup for XU controls too.
>
> No functional change for the devices already in the table: their
> entries are XU controls, matched by entity and selector before as they
> are now, and their flags come from the table either way. The only
> difference is one GET_INFO request no longer issued per fixed-up
> control.
That's a long commit message for such a simple change. Is it
LLM-generated ? If so, you need an Assisted-by tag on this patch series.
> Suggested-by: Ricardo Ribalda <ribalda@chromium.org>
> Signed-off-by: Michael Jordan <jordan.mymail@gmail.com>
> ---
> 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 aceb26310..64c90c380 100644
> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> @@ -2852,6 +2852,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;
> + }
> + }
The O(n*m) complexity isn't nice, but it's not a new issue. It can be
addressed separately.
The code change looks fine.
> +
> + return false;
> +}
> +
> /*
> * Retrieve flags for a given control
> */
> @@ -2862,6 +2904,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;
> @@ -2893,45 +2943,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.
> */
> @@ -2972,8 +2983,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,
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2026-09-28 11:44 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 0:25 [PATCH v2 0/3] media: uvcvideo: live pan/tilt/zoom readback on the OBSBOT Tiny 2 Michael Jordan
2026-09-02 0:25 ` [PATCH v2 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan
2026-09-02 0:25 ` [PATCH v2 2/3] media: uvcvideo: generalise the XU flags fixup to all controls Michael Jordan
2026-09-02 6:38 ` Ricardo Ribalda
2026-09-28 11:44 ` Laurent Pinchart [this message]
2026-09-28 14:34 ` Michael Jordan
2026-09-02 0:25 ` [PATCH v2 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on the OBSBOT Tiny 2 Michael Jordan
2026-09-02 6:34 ` Ricardo Ribalda
2026-09-27 22:06 ` Michael Jordan
2026-09-28 6:57 ` Ricardo Ribalda
2026-09-28 11:18 ` Ricardo Ribalda
2026-09-28 14:34 ` Michael Jordan
2026-09-28 11:57 ` Laurent Pinchart
2026-09-28 14:34 ` Michael Jordan
2026-09-28 14:55 ` Hans de Goede
2026-09-28 18:53 ` Laurent Pinchart
2026-09-28 11:01 ` [PATCH v2 0/3] media: uvcvideo: live pan/tilt/zoom readback " Hans de Goede
2026-09-28 11:12 ` Ricardo Ribalda
2026-09-28 11:14 ` Hans de Goede
2026-09-28 11:49 ` Laurent Pinchart
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928114423.GB157191@killaraus.ideasonboard.com \
--to=laurent.pinchart@ideasonboard.com \
--cc=hansg@kernel.org \
--cc=hverkuil+cisco@kernel.org \
--cc=jordan.mymail@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=ribalda@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.