From: Ai Chao <aichao@xxxxxxxxxx> The Alcor Corp. Slave camera (1b17:6684 and 2017:0011) returns a wrong dwMaxPayloadTransferSize value for compressed formats. Valid values are typically up to 3072 bytes per interval (for high-speed, high-bandwidth devices), and those faulty devices request 2752512 bytes per interval. This is a firmware issue, but the manufacturer cannot provide a fixed firmware. Fix this by checking the dwMaxPayloadTransferSize field, and hardcoding a value of 1024 if it exceeds 3072 for compressed formats transferred over isochronous endpoints. While at it, document the other quirk that handles a bandwidth issue for uncompressed formats. Signed-off-by: Ai Chao <aichao@xxxxxxxxxx> Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> --- Changes since v5: - Print a warning message --- drivers/media/usb/uvc/uvc_video.c | 34 +++++++++++++++++++++++++++++++ drivers/media/usb/uvc/uvcvideo.h | 1 + 2 files changed, 35 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index d4b023d4de7c..9634596f3dc7 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -200,6 +200,20 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000) ctrl->dwMaxPayloadTransferSize &= ~0xffff0000; + /* + * Many devices report an incorrect dwMaxPayloadTransferSize value. The + * most common issue is devices requesting the maximum possible USB + * bandwidth (3072 bytes per interval for high-speed, high-bandwidth + * isochronous endpoints) while they actually require less, preventing + * multiple cameras from being used at the same time due to bandwidth + * overallocation. + * + * For those devices, replace the dwMaxPayloadTransferSize value based + * on an estimation calculated from the frame format and size. This is + * only possible for uncompressed formats, as not enough information is + * available to reliably estimate the bandwidth requirements for + * compressed formats. + */ if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) && stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && stream->intf->num_altsetting > 1) { @@ -236,6 +250,26 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, ctrl->dwMaxPayloadTransferSize = bandwidth; } + + /* + * Another issue is with devices that report a transfer size that + * greatly exceeds the maximum supported by any existing USB version + * for isochronous transfers. For instance, the "Slave camera" devices + * from Alcor Corp. (2017:0011 and 1b17:66B8) request 2752512 bytes per + * interval. + * + * For uncompressed formats, this can be addressed by the FIX_BANDWIDTH + * quirk, but for compressed format we can't meaningfully estimate the + * required bandwidth. Just hardcode it to 1024 bytes per interval, + * which should be large enough for compressed formats. + */ + if ((format->flags & UVC_FMT_FLAG_COMPRESSED) && + ctrl->dwMaxPayloadTransferSize > 3072 && + stream->intf->num_altsetting > 1) { + uvc_warn_once(stream->dev, UVC_WARN_PAYLOAD_SIZE, + "Device requested invalid bandwidth, lowering to 1024 bytes per interval\n"); + ctrl->dwMaxPayloadTransferSize = 1024; + } } static size_t uvc_video_ctrl_size(struct uvc_streaming *stream) diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9a596c8d894a..72189249719e 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -630,6 +630,7 @@ struct uvc_driver { #define UVC_WARN_MINMAX 0 #define UVC_WARN_PROBE_DEF 1 #define UVC_WARN_XU_GET_RES 2 +#define UVC_WARN_PAYLOAD_SIZE 3 extern unsigned int uvc_clock_param; extern unsigned int uvc_no_drop_param; -- Regards, Laurent Pinchart