[PATCH] media: uvcvideo: Use heuristic to find stream entity

Ricardo Ribalda posted 1 patch 3 months, 2 weeks ago
There is a newer version of this series
drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
[PATCH] media: uvcvideo: Use heuristic to find stream entity
Posted by Ricardo Ribalda 3 months, 2 weeks ago
Some devices, like the Grandstream GUV3100 webcam, have an invalid UVC
descriptor where multiple entities share the same ID, this is invalid
and makes it impossible to make a proper entity tree without heuristics.

We have recently introduced a change in the way that we handle invalid
entities that has caused a regression on broken devices.

Implement a new heuristic to handle these devices properly.

Reported-by: Angel4005 <ooara1337@gmail.com>
Closes: https://lore.kernel.org/linux-media/CAOzBiVuS7ygUjjhCbyWg-KiNx+HFTYnqH5+GJhd6cYsNLT=DaA@mail.gmail.com/
Fixes: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID")
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
---
I have managed to get my hands into a Grandstream GUV3100 and
implemented a new heuristics. (Thanks Yunke and Hidenori!).

With this heuristics we can use this camera again (see the /dev/video0
in the topology).

I have tested this change in a 6.6 kernel. Because the notebook that I
used for testing has some issues running master. But for the purpose of
this change this test should work.

~ # media-ctl --print-topology
Media controller API version 6.6.99

Media device information
------------------------
driver          uvcvideo
model           GRANDSTREAM GUV3100: GRANDSTREA
serial
bus info        usb-0000:00:14.0-9
hw revision     0x409
driver version  6.6.99

Device topology
- entity 1: GRANDSTREAM GUV3100: GRANDSTREA (1 pad, 1 link)
            type Node subtype V4L flags 1
            device node name /dev/video0
        pad0: SINK
                <- "Extension 3":1 [ENABLED,IMMUTABLE]

- entity 4: GRANDSTREAM GUV3100: GRANDSTREA (0 pad, 0 link)
            type Node subtype V4L flags 0
            device node name /dev/video1

- entity 8: Extension 3 (2 pads, 2 links, 0 routes)
            type V4L2 subdev subtype Unknown flags 0
        pad0: SINK
                <- "Processing 2":1 [ENABLED,IMMUTABLE]
        pad1: SOURCE
                -> "GRANDSTREAM GUV3100: GRANDSTREA":0 [ENABLED,IMMUTABLE]

- entity 11: Processing 2 (2 pads, 3 links, 0 routes)
             type V4L2 subdev subtype Unknown flags 0
        pad0: SINK
                <- "Camera 1":0 [ENABLED,IMMUTABLE]
        pad1: SOURCE
                -> "Extension 3":0 [ENABLED,IMMUTABLE]
                -> "Extension 4":0 [ENABLED,IMMUTABLE]

- entity 14: Extension 4 (2 pads, 1 link, 0 routes)
             type V4L2 subdev subtype Unknown flags 0
        pad0: SINK
                <- "Processing 2":1 [ENABLED,IMMUTABLE]
        pad1: SOURCE

- entity 17: Camera 1 (1 pad, 1 link, 0 routes)
             type V4L2 subdev subtype Sensor flags 0
        pad0: SOURCE
                -> "Processing 2":0 [ENABLED,IMMUTABLE]
---
 drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index fb6afb8e84f00961f86fd8f840fba48d706d7a9a..4a8712d2d663ab0c31a1586ed7da6fd42f3ad3cc 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -168,12 +168,24 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
 static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
 {
 	struct uvc_streaming *stream;
+	unsigned int count = 0;
 
 	list_for_each_entry(stream, &dev->streams, list) {
+		count += 1;
 		if (stream->header.bTerminalLink == id)
 			return stream;
 	}
 
+	/*
+	 * If the streaming entity is referenced by an invalid ID, notify the
+	 * user and use heuristics to guess the correct entity.
+	 */
+	if (count == 1 && id == UVC_INVALID_ENTITY_ID) {
+		dev_warn(&dev->intf->dev,
+			 "UVC non compliance: Invalid USB header. The streaming entity has an invalid ID, guessing the correct one.");
+		return stream;
+	}
+
 	return NULL;
 }
 

---
base-commit: ea299a2164262ff787c9d33f46049acccd120672
change-id: 20251021-uvc-grandstream-05ecf0288f62

Best regards,
-- 
Ricardo Ribalda <ribalda@chromium.org>