aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 9f89c781e885..ef9066dcf535 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -405,8 +405,27 @@ static int uvc_parse_format(struct uvc_device *dev,
get_unaligned_le32(&buffer[17]);
frame->bFrameIntervalType = buffer[21];
}
+
+ /*
+ * Copy the frame intervals.
+ *
+ * Some bogus devices report dwMinFrameInterval equal to
+ * dwMaxFrameInterval and have dwFrameIntervalStep set to
+ * zero. Setting all null intervals to 1 fixes the problem and
+ * some other divisions by zero that could happen.
+ */
frame->dwFrameInterval = *intervals;
+ for (i = 0; i < n; ++i) {
+ interval = get_unaligned_le32(&buffer[26+4*i]);
+ *(*intervals)++ = interval ? interval : 1;
+ }
+
+ /*
+ * Apply more fixes, quirks and workarounds to handle incorrect
+ * or broken descriptors.
+ */
+
/*
* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
* completely. Observed behaviours range from setting the
@@ -420,27 +439,18 @@ static int uvc_parse_format(struct uvc_device *dev,
frame->dwMaxVideoFrameBufferSize = format->bpp
* frame->wWidth * frame->wHeight / 8;
- /*
- * Some bogus devices report dwMinFrameInterval equal to
- * dwMaxFrameInterval and have dwFrameIntervalStep set to
- * zero. Setting all null intervals to 1 fixes the problem and
- * some other divisions by zero that could happen.
- */
- for (i = 0; i < n; ++i) {
- interval = get_unaligned_le32(&buffer[26+4*i]);
- *(*intervals)++ = interval ? interval : 1;
- }
-
- /*
- * Make sure that the default frame interval stays between
- * the boundaries.
- */
+ /* Clamp the default frame interval to the boundaries. */
n -= frame->bFrameIntervalType ? 1 : 2;
frame->dwDefaultFrameInterval =
clamp(frame->dwDefaultFrameInterval,
frame->dwFrameInterval[0],
frame->dwFrameInterval[n]);
+ /*
+ * Some devices report frame intervals that are not functional.
+ * If the corresponding quirk is set, restrict operation to the
+ * first interval only.
+ */
if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
frame->bFrameIntervalType = 1;
frame->dwFrameInterval[0] =