* [PATCH 0/3] media: uvcvideo: live pan/tilt position on the OBSBOT Tiny 2
@ 2026-08-28 15:25 Michael Jordan
2026-08-28 15:25 ` [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Michael Jordan @ 2026-08-28 15:25 UTC (permalink / raw)
To: Laurent Pinchart, Hans de Goede, Ricardo Ribalda
Cc: Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
Michael Jordan
This replaces "[PATCH] media: uvcvideo: query pan/tilt position from the
device on every read" [1], following the review there. The approach in
that patch (a driver-side VOLATILE flag with a separate live buffer) is
dropped: as Ricardo pointed out, a control that carries AUTO_UPDATE
already gets re-read from the device on every VIDIOC_G_EXT_CTRLS, so the
problem on this camera reduces to its firmware clearing the AUTOUPDATE
bit in GET_INFO, and the fix reduces to a flags fixup for the device.
Patch 1 reports V4L2_CTRL_FLAG_VOLATILE (with EXECUTE_ON_WRITE for
writable controls) for AUTO_UPDATE controls, which the driver never did.
Patch 2 renames uvc_ctrl_fixup_xu_info() to uvc_ctrl_fixup_flags() and
calls it from uvc_ctrl_get_flags(), so the per-device flags table can
correct standard controls as well as XU ones. No functional change for
the devices already listed.
Patch 3 adds the OBSBOT Tiny 2 entry, restoring AUTO_UPDATE on its
CT_PANTILT_ABSOLUTE control.
Tested on an OBSBOT Tiny 2 (3564:fef8): pan_absolute and tilt_absolute
now report volatile/execute-on-write, and polling VIDIOC_G_CTRL during
a commanded 60 degree pan returns 0, 21600, 46800, 90000, 115200,
158400, 183600, 216000 -- the live position -- where a stock module
returns the commanded value from the first read. Reads also follow the
gimbal when it is moved by hand. The vendor was asked to fix the
firmware on 2026-08-04 (ticket #8220); no fix so far.
[1] https://lore.kernel.org/linux-media/20260725212332.64927-1-jordan.mymail@gmail.com/
Michael Jordan (3):
media: uvcvideo: report AUTO_UPDATE controls as volatile
media: uvcvideo: generalise the XU flags fixup to all controls
media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt
drivers/media/usb/uvc/uvc_ctrl.c | 107 +++++++++++++++++++------------
1 file changed, 66 insertions(+), 41 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile 2026-08-28 15:25 [PATCH 0/3] media: uvcvideo: live pan/tilt position on the OBSBOT Tiny 2 Michael Jordan @ 2026-08-28 15:25 ` Michael Jordan 2026-08-31 9:36 ` Ricardo Ribalda 2026-08-28 15:25 ` [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls Michael Jordan 2026-08-28 15:25 ` [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt Michael Jordan 2 siblings, 1 reply; 9+ messages in thread From: Michael Jordan @ 2026-08-28 15:25 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Ricardo Ribalda Cc: Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel, Michael Jordan A control with UVC_CTRL_FLAG_AUTO_UPDATE is one whose value the device changes on its own: the driver never trusts its cached value for it, re-reading the device on every VIDIOC_G_EXT_CTRLS (the rollback at the end of the ioctl runs uvc_ctrl_commit_entity(), which clears ctrl->loaded for these controls) and re-reading it after each write. That is exactly what V4L2_CTRL_FLAG_VOLATILE describes to userspace, but the driver never reported it, so applications had no way to know that the value they read can change under them and that a fresh read is worth issuing. Report V4L2_CTRL_FLAG_VOLATILE for AUTO_UPDATE controls. The uAPI documents writes to a volatile control as ignored unless V4L2_CTRL_FLAG_EXECUTE_ON_WRITE is also set, and this driver sends every write of a writable control to the device, so report EXECUTE_ON_WRITE alongside it whenever the control is settable. Suggested-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> --- drivers/media/usb/uvc/uvc_ctrl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 3ca108b83..aceb26310 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1840,6 +1840,17 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) && (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)) v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX; + if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE) { + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; + /* + * Writes to a volatile control are documented to be ignored + * unless EXECUTE_ON_WRITE is also reported. The driver sends + * every write of a writable control to the device, so report + * the flag accordingly. + */ + if (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; + } if (mapping->master_id) __uvc_find_control(ctrl->entity, mapping->master_id, -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile 2026-08-28 15:25 ` [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan @ 2026-08-31 9:36 ` Ricardo Ribalda 0 siblings, 0 replies; 9+ messages in thread From: Ricardo Ribalda @ 2026-08-31 9:36 UTC (permalink / raw) To: Michael Jordan Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel Hi Michael On Fri, 28 Aug 2026 at 17:26, Michael Jordan <jordan.mymail@gmail.com> wrote: > > A control with UVC_CTRL_FLAG_AUTO_UPDATE is one whose value the device > changes on its own: the driver never trusts its cached value for it, > re-reading the device on every VIDIOC_G_EXT_CTRLS (the rollback at the > end of the ioctl runs uvc_ctrl_commit_entity(), which clears ctrl->loaded > for these controls) and re-reading it after each write. That is exactly > what V4L2_CTRL_FLAG_VOLATILE describes to userspace, but the driver never > reported it, so applications had no way to know that the value they read > can change under them and that a fresh read is worth issuing. > > Report V4L2_CTRL_FLAG_VOLATILE for AUTO_UPDATE controls. The uAPI > documents writes to a volatile control as ignored unless > V4L2_CTRL_FLAG_EXECUTE_ON_WRITE is also set, and this driver sends every > write of a writable control to the device, so report EXECUTE_ON_WRITE > alongside it whenever the control is settable. > > Suggested-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> > Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index 3ca108b83..aceb26310 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -1840,6 +1840,17 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, > if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) && > (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)) > v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX; > + if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE) { > + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; > + /* > + * Writes to a volatile control are documented to be ignored > + * unless EXECUTE_ON_WRITE is also reported. The driver sends > + * every write of a writable control to the device, so report > + * the flag accordingly. > + */ > + if (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) > + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; > + } > > if (mapping->master_id) > __uvc_find_control(ctrl->entity, mapping->master_id, > -- > 2.43.0 > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls 2026-08-28 15:25 [PATCH 0/3] media: uvcvideo: live pan/tilt position on the OBSBOT Tiny 2 Michael Jordan 2026-08-28 15:25 ` [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan @ 2026-08-28 15:25 ` Michael Jordan 2026-08-31 9:35 ` Ricardo Ribalda 2026-08-28 15:25 ` [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt Michael Jordan 2 siblings, 1 reply; 9+ messages in thread From: Michael Jordan @ 2026-08-28 15:25 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Ricardo Ribalda Cc: Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel, Michael Jordan 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 from uvc_ctrl_get_flags(), where the flags are derived from GET_INFO for every control, standard and XU alike. Call it whether or not the GET_INFO request succeeded, so the table has the last word in both cases. The call in uvc_ctrl_fill_xu_info() is dropped, as it now runs from uvc_ctrl_get_flags() which that function calls. No functional change for the devices already in the table: their entries are XU controls, and were matched by entity and selector before as they are now. Suggested-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> --- drivers/media/usb/uvc/uvc_ctrl.c | 87 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index aceb26310..b16a5cc0d 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -2852,6 +2852,46 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl) * Dynamic controls */ +static void 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; + } + } +} + /* * Retrieve flags for a given control */ @@ -2889,49 +2929,16 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev, UVC_CTRL_FLAG_ASYNCHRONOUS : 0); } + /* + * Some devices report bogus capabilities through GET_INFO. Let the + * fixup table have the last word, whether or not GET_INFO succeeded. + */ + uvc_ctrl_fixup_flags(dev, ctrl, info); + kfree(data); 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 +2979,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, -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls 2026-08-28 15:25 ` [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls Michael Jordan @ 2026-08-31 9:35 ` Ricardo Ribalda 0 siblings, 0 replies; 9+ messages in thread From: Ricardo Ribalda @ 2026-08-31 9:35 UTC (permalink / raw) To: Michael Jordan Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel Hi Michael Thanks for your patch On Fri, 28 Aug 2026 at 17:26, Michael Jordan <jordan.mymail@gmail.com> 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 from > uvc_ctrl_get_flags(), where the flags are derived from GET_INFO for every > control, standard and XU alike. Call it whether or not the GET_INFO > request succeeded, so the table has the last word in both cases. The > call in uvc_ctrl_fill_xu_info() is dropped, as it now runs from > uvc_ctrl_get_flags() which that function calls. > > No functional change for the devices already in the table: their > entries are XU controls, and were matched by entity and selector before > as they are now. > > Suggested-by: Ricardo Ribalda <ribalda@chromium.org> > Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 87 +++++++++++++++++--------------- > 1 file changed, 46 insertions(+), 41 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index aceb26310..b16a5cc0d 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -2852,6 +2852,46 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl) > * Dynamic controls > */ > What about making uvc_ctrl_fixup_flags return bool: true if it applied a patch. That way we can move it to the beggining of uvc_ctrl_flags, even before the kmalloc and return early. > +static void 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; > + } > + } > +} > + > /* > * Retrieve flags for a given control > */ > @@ -2889,49 +2929,16 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev, > UVC_CTRL_FLAG_ASYNCHRONOUS : 0); > } > > + /* > + * Some devices report bogus capabilities through GET_INFO. Let the > + * fixup table have the last word, whether or not GET_INFO succeeded. > + */ > + uvc_ctrl_fixup_flags(dev, ctrl, info); > + > kfree(data); > 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 +2979,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, > -- > 2.43.0 > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt 2026-08-28 15:25 [PATCH 0/3] media: uvcvideo: live pan/tilt position on the OBSBOT Tiny 2 Michael Jordan 2026-08-28 15:25 ` [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan 2026-08-28 15:25 ` [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls Michael Jordan @ 2026-08-28 15:25 ` Michael Jordan 2026-08-31 9:40 ` Ricardo Ribalda 2 siblings, 1 reply; 9+ messages in thread From: Michael Jordan @ 2026-08-28 15:25 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Ricardo Ribalda Cc: Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel, Michael Jordan The OBSBOT Tiny 2 (3564:fef8) answers GET_INFO for CT_PANTILT_ABSOLUTE (entity 1, selector 0x0d) with 0x03 -- GET and SET capable, but with the AUTOUPDATE bit clear. It returns the same 0x03 for every Camera Terminal control queried, so the firmware is not computing the byte per control. uvc_ctrl_get_flags() takes the flags from that byte, so it clears the UVC_CTRL_FLAG_AUTO_UPDATE that the static uvc_ctrls[] entry sets for this control. Without AUTO_UPDATE nothing clears ctrl->loaded after the first read, so uvcvideo serves the control from its cache indefinitely: VIDIOC_G_CTRL returns the last value the host commanded, never the actuator's live position. On a motorised PTZ camera the position keeps changing during a move, and changes on its own under the camera's autonomous subject tracking, so userspace cannot observe it at all. Add a flags fixup entry restoring AUTO_UPDATE, alongside the flags the control already has, for this camera's pan/tilt control. With AUTO_UPDATE restored, the rollback at the end of every VIDIOC_G_EXT_CTRLS runs uvc_ctrl_commit_entity(), which clears ctrl->loaded, so the next read re-queries the device and reports the live position. The fixup replaces info->flags wholesale rather than OR-ing, so the entry spells out the full flag set for the control. Tested on an OBSBOT Tiny 2: without this, a read taken while the gimbal is moving (or after the gimbal is moved by hand) returns a stale value; with it, VIDIOC_G_EXT_CTRLS tracks the physical position on both axes. The vendor has been asked to fix the firmware (support ticket #8220, 2026-08-04); no fix is available at the time of writing. lsusb -v (device descriptor and the Camera Terminal): Bus 003 Device 006: ID 3564:fef8 Remo Tech Co., Ltd. OBSBOT Tiny 2 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.10 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 [unknown] bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x3564 Remo Tech Co., Ltd. idProduct 0xfef8 OBSBOT Tiny 2 bcdDevice 4.09 iManufacturer 1 Remo Tech Co., Ltd. iProduct 2 OBSBOT Tiny 2 iSerial 0 bNumConfigurations 1 [...] VideoControl Interface Descriptor: bLength 18 bDescriptorType 36 bDescriptorSubtype 2 (INPUT_TERMINAL) bTerminalID 1 wTerminalType 0x0201 Camera Sensor bAssocTerminal 0 iTerminal 0 wObjectiveFocalLengthMin 0 wObjectiveFocalLengthMax 0 wOcularFocalLength 0 bControlSize 3 bmControls 0x00023e3e Auto-Exposure Mode Auto-Exposure Priority Exposure Time (Absolute) Exposure Time (Relative) Focus (Absolute) Zoom (Absolute) Zoom (Relative) PanTilt (Absolute) PanTilt (Relative) Roll (Absolute) Focus, Auto Suggested-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> --- drivers/media/usb/uvc/uvc_ctrl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index b16a5cc0d..379ee51bd 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -2876,6 +2876,15 @@ static void uvc_ctrl_fixup_flags(struct uvc_device *dev, 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 }, + /* + * OBSBOT Tiny 2: GET_INFO on CT_PANTILT_ABSOLUTE_CONTROL is a + * stub that reports GET|SET only, clearing the AUTO_UPDATE the + * driver's own control table sets for this control. + */ + { { USB_DEVICE(0x3564, 0xfef8) }, 1, + UVC_CT_PANTILT_ABSOLUTE_CONTROL, + UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_RANGE | + UVC_CTRL_FLAG_RESTORE | UVC_CTRL_FLAG_AUTO_UPDATE }, }; unsigned int i; -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt 2026-08-28 15:25 ` [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt Michael Jordan @ 2026-08-31 9:40 ` Ricardo Ribalda 2026-08-31 9:42 ` Ricardo Ribalda 0 siblings, 1 reply; 9+ messages in thread From: Ricardo Ribalda @ 2026-08-31 9:40 UTC (permalink / raw) To: Michael Jordan Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel Hi Michael Thanks for the patch, and for contacting the vendor. Could you reply to this patch with the full output of lsusb -v instead of a cropped one? We keep that info for future reference. Thanks! On Fri, 28 Aug 2026 at 17:26, Michael Jordan <jordan.mymail@gmail.com> wrote: > > The OBSBOT Tiny 2 (3564:fef8) answers GET_INFO for CT_PANTILT_ABSOLUTE > (entity 1, selector 0x0d) with 0x03 -- GET and SET capable, but with the > AUTOUPDATE bit clear. It returns the same 0x03 for every Camera Terminal > control queried, so the firmware is not computing the byte per control. > uvc_ctrl_get_flags() takes the flags from that byte, so it clears the > UVC_CTRL_FLAG_AUTO_UPDATE that the static uvc_ctrls[] entry sets for > this control. Without AUTO_UPDATE nothing clears ctrl->loaded after the > first read, so uvcvideo serves the control from its cache indefinitely: > VIDIOC_G_CTRL returns the last value the host commanded, never the > actuator's live position. On a motorised PTZ camera the position keeps > changing during a move, and changes on its own under the camera's > autonomous subject tracking, so userspace cannot observe it at all. > > Add a flags fixup entry restoring AUTO_UPDATE, alongside the flags the > control already has, for this camera's pan/tilt control. With > AUTO_UPDATE restored, the rollback at the end of every > VIDIOC_G_EXT_CTRLS runs uvc_ctrl_commit_entity(), which clears > ctrl->loaded, so the next read re-queries the device and reports the > live position. The fixup replaces info->flags wholesale rather than > OR-ing, so the entry spells out the full flag set for the control. > > Tested on an OBSBOT Tiny 2: without this, a read taken while the gimbal > is moving (or after the gimbal is moved by hand) returns a stale value; > with it, VIDIOC_G_EXT_CTRLS tracks the physical position on both axes. > > The vendor has been asked to fix the firmware (support ticket #8220, > 2026-08-04); no fix is available at the time of writing. > > lsusb -v (device descriptor and the Camera Terminal): > > Bus 003 Device 006: ID 3564:fef8 Remo Tech Co., Ltd. OBSBOT Tiny 2 > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 2.10 > bDeviceClass 239 Miscellaneous Device > bDeviceSubClass 2 [unknown] > bDeviceProtocol 1 Interface Association > bMaxPacketSize0 64 > idVendor 0x3564 Remo Tech Co., Ltd. > idProduct 0xfef8 OBSBOT Tiny 2 > bcdDevice 4.09 > iManufacturer 1 Remo Tech Co., Ltd. > iProduct 2 OBSBOT Tiny 2 > iSerial 0 > bNumConfigurations 1 > [...] > VideoControl Interface Descriptor: > bLength 18 > bDescriptorType 36 > bDescriptorSubtype 2 (INPUT_TERMINAL) > bTerminalID 1 > wTerminalType 0x0201 Camera Sensor > bAssocTerminal 0 > iTerminal 0 > wObjectiveFocalLengthMin 0 > wObjectiveFocalLengthMax 0 > wOcularFocalLength 0 > bControlSize 3 > bmControls 0x00023e3e > Auto-Exposure Mode > Auto-Exposure Priority > Exposure Time (Absolute) > Exposure Time (Relative) > Focus (Absolute) > Zoom (Absolute) > Zoom (Relative) > PanTilt (Absolute) > PanTilt (Relative) > Roll (Absolute) > Focus, Auto > Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> > Suggested-by: Ricardo Ribalda <ribalda@chromium.org> > Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index b16a5cc0d..379ee51bd 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -2876,6 +2876,15 @@ static void uvc_ctrl_fixup_flags(struct uvc_device *dev, > 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 }, > + /* > + * OBSBOT Tiny 2: GET_INFO on CT_PANTILT_ABSOLUTE_CONTROL is a > + * stub that reports GET|SET only, clearing the AUTO_UPDATE the > + * driver's own control table sets for this control. > + */ > + { { USB_DEVICE(0x3564, 0xfef8) }, 1, > + UVC_CT_PANTILT_ABSOLUTE_CONTROL, > + UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_RANGE | > + UVC_CTRL_FLAG_RESTORE | UVC_CTRL_FLAG_AUTO_UPDATE }, > }; > > unsigned int i; > -- > 2.43.0 > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt 2026-08-31 9:40 ` Ricardo Ribalda @ 2026-08-31 9:42 ` Ricardo Ribalda 2026-09-02 0:25 ` Michael Jordan 0 siblings, 1 reply; 9+ messages in thread From: Ricardo Ribalda @ 2026-08-31 9:42 UTC (permalink / raw) To: Michael Jordan Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel Hi again. Sashiko [1] has pointed out that there might be other controls that will benefit from the UVC_CTRL_FLAG_AUTO_UPDATE. Can you double check if that is the case? Feel free to add is a v2 or as a follow-up patch. Thanks! [1] https://sashiko.dev/#/patchset/20260828152557.653475-1-jordan.mymail%40gmail.com On Mon, 31 Aug 2026 at 11:40, Ricardo Ribalda <ribalda@chromium.org> wrote: > > Hi Michael > > Thanks for the patch, and for contacting the vendor. > Could you reply to this patch with the full output of lsusb -v instead > of a cropped one? > > We keep that info for future reference. > > Thanks! > > On Fri, 28 Aug 2026 at 17:26, Michael Jordan <jordan.mymail@gmail.com> wrote: > > > > The OBSBOT Tiny 2 (3564:fef8) answers GET_INFO for CT_PANTILT_ABSOLUTE > > (entity 1, selector 0x0d) with 0x03 -- GET and SET capable, but with the > > AUTOUPDATE bit clear. It returns the same 0x03 for every Camera Terminal > > control queried, so the firmware is not computing the byte per control. > > uvc_ctrl_get_flags() takes the flags from that byte, so it clears the > > UVC_CTRL_FLAG_AUTO_UPDATE that the static uvc_ctrls[] entry sets for > > this control. Without AUTO_UPDATE nothing clears ctrl->loaded after the > > first read, so uvcvideo serves the control from its cache indefinitely: > > VIDIOC_G_CTRL returns the last value the host commanded, never the > > actuator's live position. On a motorised PTZ camera the position keeps > > changing during a move, and changes on its own under the camera's > > autonomous subject tracking, so userspace cannot observe it at all. > > > > Add a flags fixup entry restoring AUTO_UPDATE, alongside the flags the > > control already has, for this camera's pan/tilt control. With > > AUTO_UPDATE restored, the rollback at the end of every > > VIDIOC_G_EXT_CTRLS runs uvc_ctrl_commit_entity(), which clears > > ctrl->loaded, so the next read re-queries the device and reports the > > live position. The fixup replaces info->flags wholesale rather than > > OR-ing, so the entry spells out the full flag set for the control. > > > > Tested on an OBSBOT Tiny 2: without this, a read taken while the gimbal > > is moving (or after the gimbal is moved by hand) returns a stale value; > > with it, VIDIOC_G_EXT_CTRLS tracks the physical position on both axes. > > > > The vendor has been asked to fix the firmware (support ticket #8220, > > 2026-08-04); no fix is available at the time of writing. > > > > lsusb -v (device descriptor and the Camera Terminal): > > > > Bus 003 Device 006: ID 3564:fef8 Remo Tech Co., Ltd. OBSBOT Tiny 2 > > Device Descriptor: > > bLength 18 > > bDescriptorType 1 > > bcdUSB 2.10 > > bDeviceClass 239 Miscellaneous Device > > bDeviceSubClass 2 [unknown] > > bDeviceProtocol 1 Interface Association > > bMaxPacketSize0 64 > > idVendor 0x3564 Remo Tech Co., Ltd. > > idProduct 0xfef8 OBSBOT Tiny 2 > > bcdDevice 4.09 > > iManufacturer 1 Remo Tech Co., Ltd. > > iProduct 2 OBSBOT Tiny 2 > > iSerial 0 > > bNumConfigurations 1 > > [...] > > VideoControl Interface Descriptor: > > bLength 18 > > bDescriptorType 36 > > bDescriptorSubtype 2 (INPUT_TERMINAL) > > bTerminalID 1 > > wTerminalType 0x0201 Camera Sensor > > bAssocTerminal 0 > > iTerminal 0 > > wObjectiveFocalLengthMin 0 > > wObjectiveFocalLengthMax 0 > > wOcularFocalLength 0 > > bControlSize 3 > > bmControls 0x00023e3e > > Auto-Exposure Mode > > Auto-Exposure Priority > > Exposure Time (Absolute) > > Exposure Time (Relative) > > Focus (Absolute) > > Zoom (Absolute) > > Zoom (Relative) > > PanTilt (Absolute) > > PanTilt (Relative) > > Roll (Absolute) > > Focus, Auto > > > Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> > > Suggested-by: Ricardo Ribalda <ribalda@chromium.org> > > Signed-off-by: Michael Jordan <jordan.mymail@gmail.com> > > --- > > drivers/media/usb/uvc/uvc_ctrl.c | 9 +++++++++ > > 1 file changed, 9 insertions(+) > > > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > > index b16a5cc0d..379ee51bd 100644 > > --- a/drivers/media/usb/uvc/uvc_ctrl.c > > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > > @@ -2876,6 +2876,15 @@ static void uvc_ctrl_fixup_flags(struct uvc_device *dev, > > 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 }, > > + /* > > + * OBSBOT Tiny 2: GET_INFO on CT_PANTILT_ABSOLUTE_CONTROL is a > > + * stub that reports GET|SET only, clearing the AUTO_UPDATE the > > + * driver's own control table sets for this control. > > + */ > > + { { USB_DEVICE(0x3564, 0xfef8) }, 1, > > + UVC_CT_PANTILT_ABSOLUTE_CONTROL, > > + UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_RANGE | > > + UVC_CTRL_FLAG_RESTORE | UVC_CTRL_FLAG_AUTO_UPDATE }, > > }; > > > > unsigned int i; > > -- > > 2.43.0 > > > > > -- > Ricardo Ribalda -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt 2026-08-31 9:42 ` Ricardo Ribalda @ 2026-09-02 0:25 ` Michael Jordan 0 siblings, 0 replies; 9+ messages in thread From: Michael Jordan @ 2026-09-02 0:25 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel, Michael Jordan Hi Ricardo, On Mon, 31 Aug 2026 11:42:12 +0200, Ricardo Ribalda <ribalda@chromium.org> wrote: > > Could you reply to this patch with the full output of lsusb -v instead > > of a cropped one? Full output at the end of this mail. > Sashiko [1] has pointed out that there might be other controls that > will benefit from the UVC_CTRL_FLAG_AUTO_UPDATE. > > Can you double check if that is the case? Feel free to add is a v2 or > as a follow-up patch. I checked every control the camera exposes, in two steps: dumped the GET_INFO capability byte for each control, then tested on the hardware which values the firmware actually changes on its own and reports through GET_CUR. Two more controls need the fixup, both verified live: - CT_ZOOM_ABSOLUTE (GET_INFO 0x03): the camera's AI subject framing zooms autonomously, and GET_CUR reports it live -- I watched it move 0..71% with the host issuing no zoom request, matching the zoom value the vendor's own status protocol reports. - CT_PANTILT_RELATIVE (GET_INFO 0x03): GET_CUR reports the actual current speed during a relative move: a commanded 80 reads back as 78, then the deceleration ramp as the gimbal approaches the end stop, then 0 once stopped. (It reports the magnitude only, for either direction of travel.) Without AUTO_UPDATE the cache reports the last written speed forever. The camera's other AUTO_UPDATE-flagged controls turned out not to benefit: - Exposure, white balance and focus: the autos work (verified by forcing a wrong manual value and watching the image correct itself once auto is re-enabled), but GET_CUR just echoes the last SET_CUR; this firmware never reports the auto-chosen value, so AUTO_UPDATE would add USB traffic for no benefit. - Hue: the camera has no auto-hue, so nothing updates it. - CT_ZOOM_RELATIVE: the firmware gets this one right (GET_INFO 0x0f, AUTOUPDATE set). - CT_ROLL_ABSOLUTE: GET_INFO 0x01, read-only, and not mapped. This also corrects my own commit message: the capability byte is not the same 0x03 for every control (zoom relative reports 0x0f, roll 0x01), so the firmware does compute it per control -- it is just wrong for the PTZ controls that need AUTOUPDATE most. v2 follows with the wording fixed and the two entries added. lsusb -v: Bus 003 Device 006: ID 3564:fef8 Remo Tech Co., Ltd. OBSBOT Tiny 2 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.10 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 [unknown] bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x3564 Remo Tech Co., Ltd. idProduct 0xfef8 OBSBOT Tiny 2 bcdDevice 4.09 iManufacturer 1 Remo Tech Co., Ltd. iProduct 2 OBSBOT Tiny 2 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x03d2 bNumInterfaces 4 bConfigurationValue 1 iConfiguration 4 OBSBOT Multifunction bmAttributes 0xc0 Self Powered MaxPower 2mA Interface Association: bLength 8 bDescriptorType 11 bFirstInterface 0 bInterfaceCount 2 bFunctionClass 14 Video bFunctionSubClass 3 Video Interface Collection bFunctionProtocol 0 iFunction 5 OBSBOT Tiny 2 StreamCamera Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 14 Video bInterfaceSubClass 1 Video Control bInterfaceProtocol 0 iInterface 5 OBSBOT Tiny 2 StreamCamera VideoControl Interface Descriptor: bLength 13 bDescriptorType 36 bDescriptorSubtype 1 (HEADER) bcdUVC 1.00 wTotalLength 0x0050 dwClockFrequency 48.000000MHz bInCollection 1 baInterfaceNr( 0) 1 VideoControl Interface Descriptor: bLength 18 bDescriptorType 36 bDescriptorSubtype 2 (INPUT_TERMINAL) bTerminalID 1 wTerminalType 0x0201 Camera Sensor bAssocTerminal 0 iTerminal 0 wObjectiveFocalLengthMin 0 wObjectiveFocalLengthMax 0 wOcularFocalLength 0 bControlSize 3 bmControls 0x00023e3e Auto-Exposure Mode Auto-Exposure Priority Exposure Time (Absolute) Exposure Time (Relative) Focus (Absolute) Zoom (Absolute) Zoom (Relative) PanTilt (Absolute) PanTilt (Relative) Roll (Absolute) Focus, Auto VideoControl Interface Descriptor: bLength 11 bDescriptorType 36 bDescriptorSubtype 5 (PROCESSING_UNIT) Warning: Descriptor too short bUnitID 3 bSourceID 1 wMaxMultiplier 400 bControlSize 2 bmControls 0x0000f7df Brightness Contrast Hue Saturation Sharpness White Balance Temperature White Balance Component Backlight Compensation Gain Power Line Frequency White Balance Temperature, Auto White Balance Component, Auto Digital Multiplier Digital Multiplier Limit iProcessing 0 bmVideoStandards 0x1d None PAL - 625/50 SECAM - 625/50 NTSC - 625/50 VideoControl Interface Descriptor: bLength 29 bDescriptorType 36 bDescriptorSubtype 6 (EXTENSION_UNIT) bUnitID 2 guidExtensionCode {9a1e7291-6843-4683-6d92-39bc7906ee49} bNumControls 19 bNrInPins 1 baSourceID( 0) 3 bControlSize 4 bmControls( 0) 0xff bmControls( 1) 0xff bmControls( 2) 0x04 bmControls( 3) 0x00 iExtension 0 VideoControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 3 (OUTPUT_TERMINAL) bTerminalID 7 wTerminalType 0x0101 USB Streaming bAssocTerminal 0 bSourceID 2 iTerminal 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0010 1x 16 bytes bInterval 8 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 14 Video bInterfaceSubClass 2 Video Streaming bInterfaceProtocol 0 iInterface 6 Video Streaming VideoStreaming Interface Descriptor: bLength 16 bDescriptorType 36 bDescriptorSubtype 1 (INPUT_HEADER) bNumFormats 3 wTotalLength 0x02e0 bEndpointAddress 0x81 EP 1 IN bmInfo 0 bTerminalLink 7 bStillCaptureMethod 0 bTriggerSupport 0 bTriggerUsage 0 bControlSize 1 bmaControls( 0) 4 bmaControls( 1) 0 bmaControls( 2) 4 VideoStreaming Interface Descriptor: bLength 11 bDescriptorType 36 bDescriptorSubtype 6 (FORMAT_MJPEG) bFormatIndex 1 bNumFrameDescriptors 5 bFlags 0 Fixed-size samples: No bDefaultFrameIndex 1 bAspectRatioX 0 bAspectRatioY 0 bmInterlaceFlags 0x00 Interlaced stream or variable: No Fields per frame: 1 fields Field 1 first: No Field pattern: Field 1 only bCopyProtect 0 VideoStreaming Interface Descriptor: bLength 62 bDescriptorType 36 bDescriptorSubtype 7 (FRAME_MJPEG) bFrameIndex 1 bmCapabilities 0x00 Still image unsupported wWidth 1920 wHeight 1080 dwMinBitRate 995328000 dwMaxBitRate 1990656000 dwMaxVideoFrameBufferSize 4147200 dwDefaultFrameInterval 333333 bFrameIntervalType 9 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 166833 dwFrameInterval( 2) 200000 dwFrameInterval( 3) 333333 dwFrameInterval( 4) 333666 dwFrameInterval( 5) 400000 dwFrameInterval( 6) 416666 dwFrameInterval( 7) 500000 dwFrameInterval( 8) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 7 (FRAME_MJPEG) bFrameIndex 2 bmCapabilities 0x00 Still image unsupported wWidth 3840 wHeight 2160 dwMinBitRate 1327104000 dwMaxBitRate 1327104000 dwMaxVideoFrameBufferSize 16588800 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwFrameInterval( 0) 333333 dwFrameInterval( 1) 333666 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 62 bDescriptorType 36 bDescriptorSubtype 7 (FRAME_MJPEG) bFrameIndex 3 bmCapabilities 0x00 Still image unsupported wWidth 1280 wHeight 720 dwMinBitRate 221184000 dwMaxBitRate 884736000 dwMaxVideoFrameBufferSize 1843200 dwDefaultFrameInterval 333333 bFrameIntervalType 9 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 166833 dwFrameInterval( 2) 200000 dwFrameInterval( 3) 333333 dwFrameInterval( 4) 333666 dwFrameInterval( 5) 400000 dwFrameInterval( 6) 416666 dwFrameInterval( 7) 500000 dwFrameInterval( 8) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 7 (FRAME_MJPEG) bFrameIndex 4 bmCapabilities 0x00 Still image unsupported wWidth 1280 wHeight 960 dwMinBitRate 294912000 dwMaxBitRate 1179648000 dwMaxVideoFrameBufferSize 2457600 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 333333 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 7 (FRAME_MJPEG) bFrameIndex 5 bmCapabilities 0x00 Still image unsupported wWidth 1920 wHeight 1440 dwMinBitRate 663552000 dwMaxBitRate 1327104000 dwMaxVideoFrameBufferSize 5529600 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 333333 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 6 bDescriptorType 36 bDescriptorSubtype 13 (COLORFORMAT) bColorPrimaries 1 (BT.709,sRGB) bTransferCharacteristics 1 (BT.709) bMatrixCoefficients 4 (SMPTE 170M (BT.601)) VideoStreaming Interface Descriptor: bLength 27 bDescriptorType 36 bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) bFormatIndex 2 bNumFrameDescriptors 2 guidFormat {32595559-0000-0010-8000-00aa00389b71} bBitsPerPixel 16 bDefaultFrameIndex 1 bAspectRatioX 0 bAspectRatioY 0 bmInterlaceFlags 0x00 Interlaced stream or variable: No Fields per frame: 2 fields Field 1 first: No Field pattern: Field 1 only bCopyProtect 0 VideoStreaming Interface Descriptor: bLength 46 bDescriptorType 36 bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) bFrameIndex 1 bmCapabilities 0x00 Still image unsupported wWidth 640 wHeight 360 dwMinBitRate 55296000 dwMaxBitRate 110592000 dwMaxVideoFrameBufferSize 460800 dwDefaultFrameInterval 333333 bFrameIntervalType 5 dwFrameInterval( 0) 333333 dwFrameInterval( 1) 400000 dwFrameInterval( 2) 416666 dwFrameInterval( 3) 500000 dwFrameInterval( 4) 666666 VideoStreaming Interface Descriptor: bLength 42 bDescriptorType 36 bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) bFrameIndex 2 bmCapabilities 0x00 Still image unsupported wWidth 640 wHeight 480 dwMinBitRate 73728000 dwMaxBitRate 122880000 dwMaxVideoFrameBufferSize 614400 dwDefaultFrameInterval 400000 bFrameIntervalType 4 dwFrameInterval( 0) 400000 dwFrameInterval( 1) 416666 dwFrameInterval( 2) 500000 dwFrameInterval( 3) 666666 VideoStreaming Interface Descriptor: bLength 6 bDescriptorType 36 bDescriptorSubtype 13 (COLORFORMAT) bColorPrimaries 1 (BT.709,sRGB) bTransferCharacteristics 1 (BT.709) bMatrixCoefficients 4 (SMPTE 170M (BT.601)) VideoStreaming Interface Descriptor: bLength 28 bDescriptorType 36 bDescriptorSubtype 16 (FORMAT_FRAME_BASED) bFormatIndex 3 bNumFrameDescriptors 5 guidFormat {34363248-0000-0010-8000-00aa00389b71} bBitsPerPixel 16 bDefaultFrameIndex 1 bAspectRatioX 0 bAspectRatioY 0 bmInterlaceFlags 0x00 Interlaced stream or variable: No Fields per frame: 2 fields Field 1 first: No Field pattern: Field 1 only bCopyProtect 0 bVariableSize 1 VideoStreaming Interface Descriptor: bLength 62 bDescriptorType 36 bDescriptorSubtype 17 (FRAME_FRAME_BASED) bFrameIndex 1 bmCapabilities 0x00 Still image unsupported wWidth 1920 wHeight 1080 dwMinBitRate 497664000 dwMaxBitRate 1990656000 dwDefaultFrameInterval 333333 bFrameIntervalType 9 dwBytesPerLine 0 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 166833 dwFrameInterval( 2) 200000 dwFrameInterval( 3) 333333 dwFrameInterval( 4) 333666 dwFrameInterval( 5) 400000 dwFrameInterval( 6) 416666 dwFrameInterval( 7) 500000 dwFrameInterval( 8) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 17 (FRAME_FRAME_BASED) bFrameIndex 2 bmCapabilities 0x00 Still image unsupported wWidth 3840 wHeight 2160 dwMinBitRate 1327104000 dwMaxBitRate 1327104000 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwBytesPerLine 0 dwFrameInterval( 0) 333333 dwFrameInterval( 1) 333666 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 62 bDescriptorType 36 bDescriptorSubtype 17 (FRAME_FRAME_BASED) bFrameIndex 4 bmCapabilities 0x00 Still image unsupported wWidth 1280 wHeight 720 dwMinBitRate 221184000 dwMaxBitRate 884736000 dwDefaultFrameInterval 333333 bFrameIntervalType 9 dwBytesPerLine 0 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 166833 dwFrameInterval( 2) 200000 dwFrameInterval( 3) 333333 dwFrameInterval( 4) 333666 dwFrameInterval( 5) 400000 dwFrameInterval( 6) 416666 dwFrameInterval( 7) 500000 dwFrameInterval( 8) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 17 (FRAME_FRAME_BASED) bFrameIndex 5 bmCapabilities 0x00 Still image unsupported wWidth 1280 wHeight 960 dwMinBitRate 294912000 dwMaxBitRate 1179648000 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwBytesPerLine 0 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 333333 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 50 bDescriptorType 36 bDescriptorSubtype 17 (FRAME_FRAME_BASED) bFrameIndex 6 bmCapabilities 0x00 Still image unsupported wWidth 1920 wHeight 1440 dwMinBitRate 663552000 dwMaxBitRate 1327104000 dwDefaultFrameInterval 333333 bFrameIntervalType 6 dwBytesPerLine 0 dwFrameInterval( 0) 166666 dwFrameInterval( 1) 333333 dwFrameInterval( 2) 400000 dwFrameInterval( 3) 416666 dwFrameInterval( 4) 500000 dwFrameInterval( 5) 666666 VideoStreaming Interface Descriptor: bLength 6 bDescriptorType 36 bDescriptorSubtype 13 (COLORFORMAT) bColorPrimaries 1 (BT.709,sRGB) bTransferCharacteristics 1 (BT.709) bMatrixCoefficients 4 (SMPTE 170M (BT.601)) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Interface Association: bLength 8 bDescriptorType 11 bFirstInterface 2 bInterfaceCount 2 bFunctionClass 1 Audio bFunctionSubClass 0 [unknown] bFunctionProtocol 0 iFunction 8 OBSBOT Tiny2 Audio Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 2 bAlternateSetting 0 bNumEndpoints 0 bInterfaceClass 1 Audio bInterfaceSubClass 1 Control Device bInterfaceProtocol 0 iInterface 8 OBSBOT Tiny2 Audio AudioControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 1 (HEADER) bcdADC 1.00 wTotalLength 0x0027 bInCollection 1 baInterfaceNr(0) 3 AudioControl Interface Descriptor: bLength 12 bDescriptorType 36 bDescriptorSubtype 2 (INPUT_TERMINAL) bTerminalID 3 wTerminalType 0x0201 Microphone bAssocTerminal 0 bNrChannels 2 wChannelConfig 0x0003 Left Front (L) Right Front (R) iChannelNames 13 Capture Channels iTerminal 12 OBSBOT Tiny2 Microphone AudioControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 3 (OUTPUT_TERMINAL) bTerminalID 4 wTerminalType 0x0101 USB Streaming bAssocTerminal 0 bSourceID 5 iTerminal 14 Capture Output terminal AudioControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 6 (FEATURE_UNIT) bUnitID 5 bSourceID 3 bControlSize 2 bmaControls(0) 0x0003 Mute Control Volume Control iFeature 0 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 3 bAlternateSetting 0 bNumEndpoints 0 bInterfaceClass 1 Audio bInterfaceSubClass 2 Streaming bInterfaceProtocol 0 iInterface 17 OBSBOT Tiny2 Microphone Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 3 bAlternateSetting 1 bNumEndpoints 1 bInterfaceClass 1 Audio bInterfaceSubClass 2 Streaming bInterfaceProtocol 0 iInterface 18 Capture Active AudioStreaming Interface Descriptor: bLength 7 bDescriptorType 36 bDescriptorSubtype 1 (AS_GENERAL) bTerminalLink 4 bDelay 1 frames wFormatTag 0x0001 PCM AudioStreaming Interface Descriptor: bLength 11 bDescriptorType 36 bDescriptorSubtype 2 (FORMAT_TYPE) bFormatType 1 (FORMAT_TYPE_I) bNrChannels 2 bSubframeSize 2 bBitResolution 16 bSamFreqType 1 Discrete tSamFreq[ 0] 48000 Endpoint Descriptor: bLength 9 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 5 Transfer Type Isochronous Synch Type Asynchronous Usage Type Data wMaxPacketSize 0x00c0 1x 192 bytes bInterval 4 bRefresh 0 bSynchAddress 0 AudioStreaming Endpoint Descriptor: bLength 7 bDescriptorType 37 bDescriptorSubtype 1 (EP_GENERAL) bmAttributes 0x01 Sampling Frequency bLockDelayUnits 0 Undefined wLockDelay 0x0000 Binary Object Store Descriptor: bLength 5 bDescriptorType 15 wTotalLength 0x0016 bNumDeviceCaps 2 USB 2.0 Extension Device Capability: bLength 7 bDescriptorType 16 bDevCapabilityType 2 bmAttributes 0x00000006 BESL Link Power Management (LPM) Supported SuperSpeed USB Device Capability: bLength 10 bDescriptorType 16 bDevCapabilityType 3 bmAttributes 0x00 wSpeedsSupported 0x000f Device can operate at Low Speed (1Mbps) Device can operate at Full Speed (12Mbps) Device can operate at High Speed (480Mbps) Device can operate at SuperSpeed (5Gbps) bFunctionalitySupport 1 Lowest fully-functional device speed is Full Speed (12Mbps) bU1DevExitLat 1 micro seconds bU2DevExitLat 500 micro seconds Device Status: 0x0001 Self Powered Best regards, Michael ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-02 0:25 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-28 15:25 [PATCH 0/3] media: uvcvideo: live pan/tilt position on the OBSBOT Tiny 2 Michael Jordan 2026-08-28 15:25 ` [PATCH 1/3] media: uvcvideo: report AUTO_UPDATE controls as volatile Michael Jordan 2026-08-31 9:36 ` Ricardo Ribalda 2026-08-28 15:25 ` [PATCH 2/3] media: uvcvideo: generalise the XU flags fixup to all controls Michael Jordan 2026-08-31 9:35 ` Ricardo Ribalda 2026-08-28 15:25 ` [PATCH 3/3] media: uvcvideo: fix up missing AUTO_UPDATE on OBSBOT Tiny 2 pan/tilt Michael Jordan 2026-08-31 9:40 ` Ricardo Ribalda 2026-08-31 9:42 ` Ricardo Ribalda 2026-09-02 0:25 ` Michael Jordan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox