[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251022-uvc-grandstream-laurent-v2-1-8c5c20d6c571@chromium.org>
Date: Wed, 22 Oct 2025 13:12:09 +0000
From: Ricardo Ribalda <ribalda@...omium.org>
To: Laurent Pinchart <laurent.pinchart@...asonboard.com>,
Hans de Goede <hansg@...nel.org>,
Mauro Carvalho Chehab <mchehab@...nel.org>
Cc: linux-media@...r.kernel.org, linux-kernel@...r.kernel.org,
Ricardo Ribalda <ribalda@...omium.org>
Subject: [PATCH v2] media: uvcvideo: Create a specific id namespace for
output entities
Nothing can be connected to an output terminal. Which means that no
other entity can reference an output terminal as baSourceId.
Use this fact to move all the output streaming entities, which have no
controls, to a different namespace.
The output entities are usually named after the dev_name() of the usb
device, so there should not be any uAPI change from this change.
Although with this change we can handle some id collisions
automagically, change the logic of uvc_alloc_new_entity() to keep
showing a warning when a camera has invalid descriptors. Hopefully this
message will help vendors fix their invalid descriptors.
Suggested-by: Laurent Pinchart <laurent.pinchart@...asonboard.com>
Signed-off-by: Ricardo Ribalda <ribalda@...omium.org>
---
Hi, this patch fixes support for some devices with invalid USB
descriptor.
It is orthogonal to:
https://lore.kernel.org/linux-media/20251021184213.GC19043@pendragon.ideasonboard.com/T/#t
Some devices will be fixed by the other patch, other devices will be
fixed by this. In my opinion is worth to land both patches.
Tested with GRANDSTREAM GUV3100 in a 6.6 kernel.
---
Changes in v2:
- Change Macro name
- Apply quirk only to TT_STEAMING
- Add missing suggested by
- uvc_stream_for_terminal
- Note, v2 has not been tested yet in real hardware, only v1.
- Link to v1: https://lore.kernel.org/r/20251022-uvc-grandstream-laurent-v1-1-0925738a3484@chromium.org
---
drivers/media/usb/uvc/uvc_driver.c | 31 ++++++++++++++++++++++++-------
drivers/media/usb/uvc/uvcvideo.h | 3 ++-
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index fb6afb8e84f00961f86fd8f840fba48d706d7a9a..c0a2c05b0f13a8c3b14018c47dfb0be2614340ce 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -165,8 +165,10 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
return NULL;
}
-static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
+static struct uvc_streaming *uvc_stream_for_terminal(struct uvc_device *dev,
+ struct uvc_entity *term)
{
+ u16 id = UVC_HARDWARE_ENTITY_ID(term->id);
struct uvc_streaming *stream;
list_for_each_entry(stream, &dev->streams, list) {
@@ -810,10 +812,12 @@ static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type,
}
/* Per UVC 1.1+ spec 3.7.2, the ID is unique. */
- if (uvc_entity_by_id(dev, id)) {
- dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id);
+ if (uvc_entity_by_id(dev, UVC_HARDWARE_ENTITY_ID(id)))
+ dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n",
+ UVC_HARDWARE_ENTITY_ID(id));
+
+ if (uvc_entity_by_id(dev, id))
id = UVC_INVALID_ENTITY_ID;
- }
extra_size = roundup(extra_size, sizeof(*entity->pads));
if (num_pads)
@@ -969,6 +973,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
struct usb_host_interface *alts = dev->intf->cur_altsetting;
unsigned int i, n, p, len;
const char *type_name;
+ unsigned int id;
u16 type;
switch (buffer[2]) {
@@ -1107,8 +1112,20 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return 0;
}
+ id = buffer[3];
+
+ /*
+ * Nothing can be connected to an output terminal. To avoid
+ * entity-id's collisions in devices with invalid USB
+ * descriptors, move the output terminal id to its own
+ * namespace. Do this only for UVC_TT_STREAMING entities, to
+ * avoid changing the id of terminals with controls.
+ */
+ if (type & UVC_TT_STREAMING)
+ id |= UVC_TERM_OUTPUT;
+
term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT,
- buffer[3], 1, 0);
+ id, 1, 0);
if (IS_ERR(term))
return PTR_ERR(term);
@@ -2105,8 +2122,8 @@ static int uvc_register_terms(struct uvc_device *dev,
if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
continue;
- stream = uvc_stream_by_id(dev, term->id);
- if (stream == NULL) {
+ stream = uvc_stream_for_terminal(dev, term);
+ if (!stream) {
dev_info(&dev->intf->dev,
"No streaming interface found for terminal %u.",
term->id);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index ed7bad31f75ca474c1037d666d5310c78dd764df..3f2e832025e712585edc324afa6cad760d4edafc 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -41,7 +41,8 @@
#define UVC_EXT_GPIO_UNIT 0x7ffe
#define UVC_EXT_GPIO_UNIT_ID 0x100
-#define UVC_INVALID_ENTITY_ID 0xffff
+#define UVC_HARDWARE_ENTITY_ID(id) ((id) & 0xff)
+#define UVC_INVALID_ENTITY_ID 0xffff
/* ------------------------------------------------------------------------
* Driver specific constants.
---
base-commit: ea299a2164262ff787c9d33f46049acccd120672
change-id: 20251022-uvc-grandstream-laurent-3f9abb8a0d5b
Best regards,
--
Ricardo Ribalda <ribalda@...omium.org>
Powered by blists - more mailing lists