[PATCH] media: uvcvideo: Pick first best alternate setting insteed of last

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When selecting an alternate setting, the driver loops over all available
alternate settings to find the one with the lowest bandwidth high enough
for the selected format and resolution. While all alternate settings
should have different packet sizes, some buggy devices report multiple
alternate settings with the same size. The driver happens to pick the
last one in this case.

In theory this should work fine, but in real life we have device bugs.
The Ali Corp. Newmine Camera (0402:8841) exposes four alternate
settings with the same packet size. The first three seem to work fine,
while selecting the last one results in lots of transmission errors.

Switch to using the first best alternate setting when multiple are
present. This should be safe (last famous words), as sniffing USB
traffic with the faulty device shows that Windows 10 picks the first
alternate setting, and devices are typically tested on Windows.

Reported-by: Karel Janda <karel1@xxxxxxxxxxxx>
Closes: https://lore.kernel.org/linux-media/Nh6D0WI--3-9@xxxxxxxxxxxx/
Suggested-by: Karel Janda <karel1@xxxxxxxxxxxx>
Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
Karel, could you please test this patch ? Please also let me know if you
are fine having your name recorded in the kernel git history with the
Reported-by and Suggested-by tags above. If not, I will drop them.
---
 drivers/media/usb/uvc/uvc_video.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 28dde08ec6c5..7cbf4692bd87 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1954,7 +1954,7 @@ static int uvc_video_start_transfer(struct uvc_streaming *stream,
 
 			/* Check if the bandwidth is high enough. */
 			psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
-			if (psize >= bandwidth && psize <= best_psize) {
+			if (psize >= bandwidth && psize < best_psize) {
 				altsetting = alts->desc.bAlternateSetting;
 				best_psize = psize;
 				best_ep = ep;
-- 
Regards,

Laurent Pinchart




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux