Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: uvcvideo: Use heuristic to find stream entity

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")
Cc: stable@vger.kernel.org
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Ricardo Ribalda and committed by
Hans Verkuil
758dbc75 7df699c2

+14 -1
+14 -1
drivers/media/usb/uvc/uvc_driver.c
··· 167 167 168 168 static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) 169 169 { 170 - struct uvc_streaming *stream; 170 + struct uvc_streaming *stream, *last_stream; 171 + unsigned int count = 0; 171 172 172 173 list_for_each_entry(stream, &dev->streams, list) { 174 + count += 1; 175 + last_stream = stream; 173 176 if (stream->header.bTerminalLink == id) 174 177 return stream; 178 + } 179 + 180 + /* 181 + * If the streaming entity is referenced by an invalid ID, notify the 182 + * user and use heuristics to guess the correct entity. 183 + */ 184 + if (count == 1 && id == UVC_INVALID_ENTITY_ID) { 185 + dev_warn(&dev->intf->dev, 186 + "UVC non compliance: Invalid USB header. The streaming entity has an invalid ID, guessing the correct one."); 187 + return last_stream; 175 188 } 176 189 177 190 return NULL;