Merge tag 'selinux-pr-20210629' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / media / usb / uvc / uvc_video.c
index a777b389a66ec4b503c177a0a3ffd416775f517c..e16464606b1405a5846eb7b2aff501cc184dae43 100644 (file)
@@ -127,10 +127,37 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit,
 static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
        struct uvc_streaming_control *ctrl)
 {
+       static const struct usb_device_id elgato_cam_link_4k = {
+               USB_DEVICE(0x0fd9, 0x0066)
+       };
        struct uvc_format *format = NULL;
        struct uvc_frame *frame = NULL;
        unsigned int i;
 
+       /*
+        * The response of the Elgato Cam Link 4K is incorrect: The second byte
+        * contains bFormatIndex (instead of being the second byte of bmHint).
+        * The first byte is always zero. The third byte is always 1.
+        *
+        * The UVC 1.5 class specification defines the first five bits in the
+        * bmHint bitfield. The remaining bits are reserved and should be zero.
+        * Therefore a valid bmHint will be less than 32.
+        *
+        * Latest Elgato Cam Link 4K firmware as of 2021-03-23 needs this fix.
+        * MCU: 20.02.19, FPGA: 67
+        */
+       if (usb_match_one_id(stream->dev->intf, &elgato_cam_link_4k) &&
+           ctrl->bmHint > 255) {
+               u8 corrected_format_index = ctrl->bmHint >> 8;
+
+               uvc_dbg(stream->dev, VIDEO,
+                       "Correct USB video probe response from {bmHint: 0x%04x, bFormatIndex: %u} to {bmHint: 0x%04x, bFormatIndex: %u}\n",
+                       ctrl->bmHint, ctrl->bFormatIndex,
+                       1, corrected_format_index);
+               ctrl->bmHint = 1;
+               ctrl->bFormatIndex = corrected_format_index;
+       }
+
        for (i = 0; i < stream->nformats; ++i) {
                if (stream->format[i].index == ctrl->bFormatIndex) {
                        format = &stream->format[i];