18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * uvc_video.c -- USB Video Class driver - Video handling 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2010 68c2ecf20Sopenharmony_ci * Laurent Pinchart (laurent.pinchart@ideasonboard.com) 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/list.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/usb.h> 148c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 158c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 168c2ecf20Sopenharmony_ci#include <linux/wait.h> 178c2ecf20Sopenharmony_ci#include <linux/atomic.h> 188c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <media/v4l2-common.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "uvcvideo.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 258c2ecf20Sopenharmony_ci * UVC Controls 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int __uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, 298c2ecf20Sopenharmony_ci u8 intfnum, u8 cs, void *data, u16 size, 308c2ecf20Sopenharmony_ci int timeout) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; 338c2ecf20Sopenharmony_ci unsigned int pipe; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) 368c2ecf20Sopenharmony_ci : usb_sndctrlpipe(dev->udev, 0); 378c2ecf20Sopenharmony_ci type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci return usb_control_msg(dev->udev, pipe, query, type, cs << 8, 408c2ecf20Sopenharmony_ci unit << 8 | intfnum, data, size, timeout); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic const char *uvc_query_name(u8 query) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci switch (query) { 468c2ecf20Sopenharmony_ci case UVC_SET_CUR: 478c2ecf20Sopenharmony_ci return "SET_CUR"; 488c2ecf20Sopenharmony_ci case UVC_GET_CUR: 498c2ecf20Sopenharmony_ci return "GET_CUR"; 508c2ecf20Sopenharmony_ci case UVC_GET_MIN: 518c2ecf20Sopenharmony_ci return "GET_MIN"; 528c2ecf20Sopenharmony_ci case UVC_GET_MAX: 538c2ecf20Sopenharmony_ci return "GET_MAX"; 548c2ecf20Sopenharmony_ci case UVC_GET_RES: 558c2ecf20Sopenharmony_ci return "GET_RES"; 568c2ecf20Sopenharmony_ci case UVC_GET_LEN: 578c2ecf20Sopenharmony_ci return "GET_LEN"; 588c2ecf20Sopenharmony_ci case UVC_GET_INFO: 598c2ecf20Sopenharmony_ci return "GET_INFO"; 608c2ecf20Sopenharmony_ci case UVC_GET_DEF: 618c2ecf20Sopenharmony_ci return "GET_DEF"; 628c2ecf20Sopenharmony_ci default: 638c2ecf20Sopenharmony_ci return "<invalid>"; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciint uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, 688c2ecf20Sopenharmony_ci u8 intfnum, u8 cs, void *data, u16 size) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci int ret; 718c2ecf20Sopenharmony_ci u8 error; 728c2ecf20Sopenharmony_ci u8 tmp; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, 758c2ecf20Sopenharmony_ci UVC_CTRL_CONTROL_TIMEOUT); 768c2ecf20Sopenharmony_ci if (likely(ret == size)) 778c2ecf20Sopenharmony_ci return 0; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, 808c2ecf20Sopenharmony_ci "Failed to query (%s) UVC control %u on unit %u: %d (exp. %u).\n", 818c2ecf20Sopenharmony_ci uvc_query_name(query), cs, unit, ret, size); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (ret != -EPIPE) 848c2ecf20Sopenharmony_ci return ret; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci tmp = *(u8 *)data; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci ret = __uvc_query_ctrl(dev, UVC_GET_CUR, 0, intfnum, 898c2ecf20Sopenharmony_ci UVC_VC_REQUEST_ERROR_CODE_CONTROL, data, 1, 908c2ecf20Sopenharmony_ci UVC_CTRL_CONTROL_TIMEOUT); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci error = *(u8 *)data; 938c2ecf20Sopenharmony_ci *(u8 *)data = tmp; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (ret != 1) 968c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EPIPE; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_CONTROL, "Control error %u\n", error); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci switch (error) { 1018c2ecf20Sopenharmony_ci case 0: 1028c2ecf20Sopenharmony_ci /* Cannot happen - we received a STALL */ 1038c2ecf20Sopenharmony_ci return -EPIPE; 1048c2ecf20Sopenharmony_ci case 1: /* Not ready */ 1058c2ecf20Sopenharmony_ci return -EBUSY; 1068c2ecf20Sopenharmony_ci case 2: /* Wrong state */ 1078c2ecf20Sopenharmony_ci return -EILSEQ; 1088c2ecf20Sopenharmony_ci case 3: /* Power */ 1098c2ecf20Sopenharmony_ci return -EREMOTE; 1108c2ecf20Sopenharmony_ci case 4: /* Out of range */ 1118c2ecf20Sopenharmony_ci return -ERANGE; 1128c2ecf20Sopenharmony_ci case 5: /* Invalid unit */ 1138c2ecf20Sopenharmony_ci case 6: /* Invalid control */ 1148c2ecf20Sopenharmony_ci case 7: /* Invalid Request */ 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci * The firmware has not properly implemented 1178c2ecf20Sopenharmony_ci * the control or there has been a HW error. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci return -EIO; 1208c2ecf20Sopenharmony_ci case 8: /* Invalid value within range */ 1218c2ecf20Sopenharmony_ci return -EINVAL; 1228c2ecf20Sopenharmony_ci default: /* reserved or unknown */ 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return -EPIPE; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic void uvc_fixup_video_ctrl(struct uvc_streaming *stream, 1308c2ecf20Sopenharmony_ci struct uvc_streaming_control *ctrl) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci static const struct usb_device_id elgato_cam_link_4k = { 1338c2ecf20Sopenharmony_ci USB_DEVICE(0x0fd9, 0x0066) 1348c2ecf20Sopenharmony_ci }; 1358c2ecf20Sopenharmony_ci struct uvc_format *format = NULL; 1368c2ecf20Sopenharmony_ci struct uvc_frame *frame = NULL; 1378c2ecf20Sopenharmony_ci unsigned int i; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* 1408c2ecf20Sopenharmony_ci * The response of the Elgato Cam Link 4K is incorrect: The second byte 1418c2ecf20Sopenharmony_ci * contains bFormatIndex (instead of being the second byte of bmHint). 1428c2ecf20Sopenharmony_ci * The first byte is always zero. The third byte is always 1. 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * The UVC 1.5 class specification defines the first five bits in the 1458c2ecf20Sopenharmony_ci * bmHint bitfield. The remaining bits are reserved and should be zero. 1468c2ecf20Sopenharmony_ci * Therefore a valid bmHint will be less than 32. 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Latest Elgato Cam Link 4K firmware as of 2021-03-23 needs this fix. 1498c2ecf20Sopenharmony_ci * MCU: 20.02.19, FPGA: 67 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci if (usb_match_one_id(stream->dev->intf, &elgato_cam_link_4k) && 1528c2ecf20Sopenharmony_ci ctrl->bmHint > 255) { 1538c2ecf20Sopenharmony_ci u8 corrected_format_index = ctrl->bmHint >> 8; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* uvc_dbg(stream->dev, VIDEO, 1568c2ecf20Sopenharmony_ci "Correct USB video probe response from {bmHint: 0x%04x, bFormatIndex: %u} to {bmHint: 0x%04x, bFormatIndex: %u}\n", 1578c2ecf20Sopenharmony_ci ctrl->bmHint, ctrl->bFormatIndex, 1588c2ecf20Sopenharmony_ci 1, corrected_format_index); */ 1598c2ecf20Sopenharmony_ci ctrl->bmHint = 1; 1608c2ecf20Sopenharmony_ci ctrl->bFormatIndex = corrected_format_index; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci for (i = 0; i < stream->nformats; ++i) { 1648c2ecf20Sopenharmony_ci if (stream->format[i].index == ctrl->bFormatIndex) { 1658c2ecf20Sopenharmony_ci format = &stream->format[i]; 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (format == NULL) 1718c2ecf20Sopenharmony_ci return; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci for (i = 0; i < format->nframes; ++i) { 1748c2ecf20Sopenharmony_ci if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { 1758c2ecf20Sopenharmony_ci frame = &format->frame[i]; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (frame == NULL) 1818c2ecf20Sopenharmony_ci return; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || 1848c2ecf20Sopenharmony_ci (ctrl->dwMaxVideoFrameSize == 0 && 1858c2ecf20Sopenharmony_ci stream->dev->uvc_version < 0x0110)) 1868c2ecf20Sopenharmony_ci ctrl->dwMaxVideoFrameSize = 1878c2ecf20Sopenharmony_ci frame->dwMaxVideoFrameBufferSize; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* The "TOSHIBA Web Camera - 5M" Chicony device (04f2:b50b) seems to 1908c2ecf20Sopenharmony_ci * compute the bandwidth on 16 bits and erroneously sign-extend it to 1918c2ecf20Sopenharmony_ci * 32 bits, resulting in a huge bandwidth value. Detect and fix that 1928c2ecf20Sopenharmony_ci * condition by setting the 16 MSBs to 0 when they're all equal to 1. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ci if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000) 1958c2ecf20Sopenharmony_ci ctrl->dwMaxPayloadTransferSize &= ~0xffff0000; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) && 1988c2ecf20Sopenharmony_ci stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && 1998c2ecf20Sopenharmony_ci stream->intf->num_altsetting > 1) { 2008c2ecf20Sopenharmony_ci u32 interval; 2018c2ecf20Sopenharmony_ci u32 bandwidth; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci interval = (ctrl->dwFrameInterval > 100000) 2048c2ecf20Sopenharmony_ci ? ctrl->dwFrameInterval 2058c2ecf20Sopenharmony_ci : frame->dwFrameInterval[0]; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Compute a bandwidth estimation by multiplying the frame 2088c2ecf20Sopenharmony_ci * size by the number of video frames per second, divide the 2098c2ecf20Sopenharmony_ci * result by the number of USB frames (or micro-frames for 2108c2ecf20Sopenharmony_ci * high-speed devices) per second and add the UVC header size 2118c2ecf20Sopenharmony_ci * (assumed to be 12 bytes long). 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_ci bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; 2148c2ecf20Sopenharmony_ci bandwidth *= 10000000 / interval + 1; 2158c2ecf20Sopenharmony_ci bandwidth /= 1000; 2168c2ecf20Sopenharmony_ci if (stream->dev->udev->speed == USB_SPEED_HIGH) 2178c2ecf20Sopenharmony_ci bandwidth /= 8; 2188c2ecf20Sopenharmony_ci bandwidth += 12; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* The bandwidth estimate is too low for many cameras. Don't use 2218c2ecf20Sopenharmony_ci * maximum packet sizes lower than 1024 bytes to try and work 2228c2ecf20Sopenharmony_ci * around the problem. According to measurements done on two 2238c2ecf20Sopenharmony_ci * different camera models, the value is high enough to get most 2248c2ecf20Sopenharmony_ci * resolutions working while not preventing two simultaneous 2258c2ecf20Sopenharmony_ci * VGA streams at 15 fps. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci bandwidth = max_t(u32, bandwidth, 1024); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci ctrl->dwMaxPayloadTransferSize = bandwidth; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic size_t uvc_video_ctrl_size(struct uvc_streaming *stream) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci /* 2368c2ecf20Sopenharmony_ci * Return the size of the video probe and commit controls, which depends 2378c2ecf20Sopenharmony_ci * on the protocol version. 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_ci if (stream->dev->uvc_version < 0x0110) 2408c2ecf20Sopenharmony_ci return 26; 2418c2ecf20Sopenharmony_ci else if (stream->dev->uvc_version < 0x0150) 2428c2ecf20Sopenharmony_ci return 34; 2438c2ecf20Sopenharmony_ci else 2448c2ecf20Sopenharmony_ci return 48; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic int uvc_get_video_ctrl(struct uvc_streaming *stream, 2488c2ecf20Sopenharmony_ci struct uvc_streaming_control *ctrl, int probe, u8 query) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci u16 size = uvc_video_ctrl_size(stream); 2518c2ecf20Sopenharmony_ci u8 *data; 2528c2ecf20Sopenharmony_ci int ret; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && 2558c2ecf20Sopenharmony_ci query == UVC_GET_DEF) 2568c2ecf20Sopenharmony_ci return -EIO; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci data = kmalloc(size, GFP_KERNEL); 2598c2ecf20Sopenharmony_ci if (data == NULL) 2608c2ecf20Sopenharmony_ci return -ENOMEM; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, 2638c2ecf20Sopenharmony_ci probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, 2648c2ecf20Sopenharmony_ci size, uvc_timeout_param); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { 2678c2ecf20Sopenharmony_ci /* Some cameras, mostly based on Bison Electronics chipsets, 2688c2ecf20Sopenharmony_ci * answer a GET_MIN or GET_MAX request with the wCompQuality 2698c2ecf20Sopenharmony_ci * field only. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " 2728c2ecf20Sopenharmony_ci "compliance - GET_MIN/MAX(PROBE) incorrectly " 2738c2ecf20Sopenharmony_ci "supported. Enabling workaround.\n"); 2748c2ecf20Sopenharmony_ci memset(ctrl, 0, sizeof(*ctrl)); 2758c2ecf20Sopenharmony_ci ctrl->wCompQuality = le16_to_cpup((__le16 *)data); 2768c2ecf20Sopenharmony_ci ret = 0; 2778c2ecf20Sopenharmony_ci goto out; 2788c2ecf20Sopenharmony_ci } else if (query == UVC_GET_DEF && probe == 1 && ret != size) { 2798c2ecf20Sopenharmony_ci /* Many cameras don't support the GET_DEF request on their 2808c2ecf20Sopenharmony_ci * video probe control. Warn once and return, the caller will 2818c2ecf20Sopenharmony_ci * fall back to GET_CUR. 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_ci uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non " 2848c2ecf20Sopenharmony_ci "compliance - GET_DEF(PROBE) not supported. " 2858c2ecf20Sopenharmony_ci "Enabling workaround.\n"); 2868c2ecf20Sopenharmony_ci ret = -EIO; 2878c2ecf20Sopenharmony_ci goto out; 2888c2ecf20Sopenharmony_ci } else if (ret != size) { 2898c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : " 2908c2ecf20Sopenharmony_ci "%d (exp. %u).\n", query, probe ? "probe" : "commit", 2918c2ecf20Sopenharmony_ci ret, size); 2928c2ecf20Sopenharmony_ci ret = -EIO; 2938c2ecf20Sopenharmony_ci goto out; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); 2978c2ecf20Sopenharmony_ci ctrl->bFormatIndex = data[2]; 2988c2ecf20Sopenharmony_ci ctrl->bFrameIndex = data[3]; 2998c2ecf20Sopenharmony_ci ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]); 3008c2ecf20Sopenharmony_ci ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]); 3018c2ecf20Sopenharmony_ci ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]); 3028c2ecf20Sopenharmony_ci ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]); 3038c2ecf20Sopenharmony_ci ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]); 3048c2ecf20Sopenharmony_ci ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]); 3058c2ecf20Sopenharmony_ci ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]); 3068c2ecf20Sopenharmony_ci ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (size >= 34) { 3098c2ecf20Sopenharmony_ci ctrl->dwClockFrequency = get_unaligned_le32(&data[26]); 3108c2ecf20Sopenharmony_ci ctrl->bmFramingInfo = data[30]; 3118c2ecf20Sopenharmony_ci ctrl->bPreferedVersion = data[31]; 3128c2ecf20Sopenharmony_ci ctrl->bMinVersion = data[32]; 3138c2ecf20Sopenharmony_ci ctrl->bMaxVersion = data[33]; 3148c2ecf20Sopenharmony_ci } else { 3158c2ecf20Sopenharmony_ci ctrl->dwClockFrequency = stream->dev->clock_frequency; 3168c2ecf20Sopenharmony_ci ctrl->bmFramingInfo = 0; 3178c2ecf20Sopenharmony_ci ctrl->bPreferedVersion = 0; 3188c2ecf20Sopenharmony_ci ctrl->bMinVersion = 0; 3198c2ecf20Sopenharmony_ci ctrl->bMaxVersion = 0; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Some broken devices return null or wrong dwMaxVideoFrameSize and 3238c2ecf20Sopenharmony_ci * dwMaxPayloadTransferSize fields. Try to get the value from the 3248c2ecf20Sopenharmony_ci * format and frame descriptors. 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_ci uvc_fixup_video_ctrl(stream, ctrl); 3278c2ecf20Sopenharmony_ci ret = 0; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ciout: 3308c2ecf20Sopenharmony_ci kfree(data); 3318c2ecf20Sopenharmony_ci return ret; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic int uvc_set_video_ctrl(struct uvc_streaming *stream, 3358c2ecf20Sopenharmony_ci struct uvc_streaming_control *ctrl, int probe) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci u16 size = uvc_video_ctrl_size(stream); 3388c2ecf20Sopenharmony_ci u8 *data; 3398c2ecf20Sopenharmony_ci int ret; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci data = kzalloc(size, GFP_KERNEL); 3428c2ecf20Sopenharmony_ci if (data == NULL) 3438c2ecf20Sopenharmony_ci return -ENOMEM; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); 3468c2ecf20Sopenharmony_ci data[2] = ctrl->bFormatIndex; 3478c2ecf20Sopenharmony_ci data[3] = ctrl->bFrameIndex; 3488c2ecf20Sopenharmony_ci *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval); 3498c2ecf20Sopenharmony_ci *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate); 3508c2ecf20Sopenharmony_ci *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate); 3518c2ecf20Sopenharmony_ci *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); 3528c2ecf20Sopenharmony_ci *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); 3538c2ecf20Sopenharmony_ci *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); 3548c2ecf20Sopenharmony_ci put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); 3558c2ecf20Sopenharmony_ci put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (size >= 34) { 3588c2ecf20Sopenharmony_ci put_unaligned_le32(ctrl->dwClockFrequency, &data[26]); 3598c2ecf20Sopenharmony_ci data[30] = ctrl->bmFramingInfo; 3608c2ecf20Sopenharmony_ci data[31] = ctrl->bPreferedVersion; 3618c2ecf20Sopenharmony_ci data[32] = ctrl->bMinVersion; 3628c2ecf20Sopenharmony_ci data[33] = ctrl->bMaxVersion; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, 3668c2ecf20Sopenharmony_ci probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, 3678c2ecf20Sopenharmony_ci size, uvc_timeout_param); 3688c2ecf20Sopenharmony_ci if (ret != size) { 3698c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, "Failed to set UVC %s control : " 3708c2ecf20Sopenharmony_ci "%d (exp. %u).\n", probe ? "probe" : "commit", 3718c2ecf20Sopenharmony_ci ret, size); 3728c2ecf20Sopenharmony_ci ret = -EIO; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci kfree(data); 3768c2ecf20Sopenharmony_ci return ret; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ciint uvc_probe_video(struct uvc_streaming *stream, 3808c2ecf20Sopenharmony_ci struct uvc_streaming_control *probe) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci struct uvc_streaming_control probe_min, probe_max; 3838c2ecf20Sopenharmony_ci u16 bandwidth; 3848c2ecf20Sopenharmony_ci unsigned int i; 3858c2ecf20Sopenharmony_ci int ret; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* Perform probing. The device should adjust the requested values 3888c2ecf20Sopenharmony_ci * according to its capabilities. However, some devices, namely the 3898c2ecf20Sopenharmony_ci * first generation UVC Logitech webcams, don't implement the Video 3908c2ecf20Sopenharmony_ci * Probe control properly, and just return the needed bandwidth. For 3918c2ecf20Sopenharmony_ci * that reason, if the needed bandwidth exceeds the maximum available 3928c2ecf20Sopenharmony_ci * bandwidth, try to lower the quality. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_ci ret = uvc_set_video_ctrl(stream, probe, 1); 3958c2ecf20Sopenharmony_ci if (ret < 0) 3968c2ecf20Sopenharmony_ci goto done; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* Get the minimum and maximum values for compression settings. */ 3998c2ecf20Sopenharmony_ci if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { 4008c2ecf20Sopenharmony_ci ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN); 4018c2ecf20Sopenharmony_ci if (ret < 0) 4028c2ecf20Sopenharmony_ci goto done; 4038c2ecf20Sopenharmony_ci ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX); 4048c2ecf20Sopenharmony_ci if (ret < 0) 4058c2ecf20Sopenharmony_ci goto done; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci probe->wCompQuality = probe_max.wCompQuality; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci for (i = 0; i < 2; ++i) { 4118c2ecf20Sopenharmony_ci ret = uvc_set_video_ctrl(stream, probe, 1); 4128c2ecf20Sopenharmony_ci if (ret < 0) 4138c2ecf20Sopenharmony_ci goto done; 4148c2ecf20Sopenharmony_ci ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); 4158c2ecf20Sopenharmony_ci if (ret < 0) 4168c2ecf20Sopenharmony_ci goto done; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (stream->intf->num_altsetting == 1) 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci bandwidth = probe->dwMaxPayloadTransferSize; 4228c2ecf20Sopenharmony_ci if (bandwidth <= stream->maxpsize) 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { 4268c2ecf20Sopenharmony_ci ret = -ENOSPC; 4278c2ecf20Sopenharmony_ci goto done; 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* TODO: negotiate compression parameters */ 4318c2ecf20Sopenharmony_ci probe->wKeyFrameRate = probe_min.wKeyFrameRate; 4328c2ecf20Sopenharmony_ci probe->wPFrameRate = probe_min.wPFrameRate; 4338c2ecf20Sopenharmony_ci probe->wCompQuality = probe_max.wCompQuality; 4348c2ecf20Sopenharmony_ci probe->wCompWindowSize = probe_min.wCompWindowSize; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cidone: 4388c2ecf20Sopenharmony_ci return ret; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic int uvc_commit_video(struct uvc_streaming *stream, 4428c2ecf20Sopenharmony_ci struct uvc_streaming_control *probe) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci return uvc_set_video_ctrl(stream, probe, 0); 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 4488c2ecf20Sopenharmony_ci * Clocks and timestamps 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic inline ktime_t uvc_video_get_time(void) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci if (uvc_clock_param == CLOCK_MONOTONIC) 4548c2ecf20Sopenharmony_ci return ktime_get(); 4558c2ecf20Sopenharmony_ci else 4568c2ecf20Sopenharmony_ci return ktime_get_real(); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistatic void 4608c2ecf20Sopenharmony_ciuvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, 4618c2ecf20Sopenharmony_ci const u8 *data, int len) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci struct uvc_clock_sample *sample; 4648c2ecf20Sopenharmony_ci unsigned int header_size; 4658c2ecf20Sopenharmony_ci bool has_pts = false; 4668c2ecf20Sopenharmony_ci bool has_scr = false; 4678c2ecf20Sopenharmony_ci unsigned long flags; 4688c2ecf20Sopenharmony_ci ktime_t time; 4698c2ecf20Sopenharmony_ci u16 host_sof; 4708c2ecf20Sopenharmony_ci u16 dev_sof; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { 4738c2ecf20Sopenharmony_ci case UVC_STREAM_PTS | UVC_STREAM_SCR: 4748c2ecf20Sopenharmony_ci header_size = 12; 4758c2ecf20Sopenharmony_ci has_pts = true; 4768c2ecf20Sopenharmony_ci has_scr = true; 4778c2ecf20Sopenharmony_ci break; 4788c2ecf20Sopenharmony_ci case UVC_STREAM_PTS: 4798c2ecf20Sopenharmony_ci header_size = 6; 4808c2ecf20Sopenharmony_ci has_pts = true; 4818c2ecf20Sopenharmony_ci break; 4828c2ecf20Sopenharmony_ci case UVC_STREAM_SCR: 4838c2ecf20Sopenharmony_ci header_size = 8; 4848c2ecf20Sopenharmony_ci has_scr = true; 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci default: 4878c2ecf20Sopenharmony_ci header_size = 2; 4888c2ecf20Sopenharmony_ci break; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci /* Check for invalid headers. */ 4928c2ecf20Sopenharmony_ci if (len < header_size) 4938c2ecf20Sopenharmony_ci return; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* Extract the timestamps: 4968c2ecf20Sopenharmony_ci * 4978c2ecf20Sopenharmony_ci * - store the frame PTS in the buffer structure 4988c2ecf20Sopenharmony_ci * - if the SCR field is present, retrieve the host SOF counter and 4998c2ecf20Sopenharmony_ci * kernel timestamps and store them with the SCR STC and SOF fields 5008c2ecf20Sopenharmony_ci * in the ring buffer 5018c2ecf20Sopenharmony_ci */ 5028c2ecf20Sopenharmony_ci if (has_pts && buf != NULL) 5038c2ecf20Sopenharmony_ci buf->pts = get_unaligned_le32(&data[2]); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (!has_scr) 5068c2ecf20Sopenharmony_ci return; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* To limit the amount of data, drop SCRs with an SOF identical to the 5098c2ecf20Sopenharmony_ci * previous one. 5108c2ecf20Sopenharmony_ci */ 5118c2ecf20Sopenharmony_ci dev_sof = get_unaligned_le16(&data[header_size - 2]); 5128c2ecf20Sopenharmony_ci if (dev_sof == stream->clock.last_sof) 5138c2ecf20Sopenharmony_ci return; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci stream->clock.last_sof = dev_sof; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci host_sof = usb_get_current_frame_number(stream->dev->udev); 5188c2ecf20Sopenharmony_ci time = uvc_video_get_time(); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* The UVC specification allows device implementations that can't obtain 5218c2ecf20Sopenharmony_ci * the USB frame number to keep their own frame counters as long as they 5228c2ecf20Sopenharmony_ci * match the size and frequency of the frame number associated with USB 5238c2ecf20Sopenharmony_ci * SOF tokens. The SOF values sent by such devices differ from the USB 5248c2ecf20Sopenharmony_ci * SOF tokens by a fixed offset that needs to be estimated and accounted 5258c2ecf20Sopenharmony_ci * for to make timestamp recovery as accurate as possible. 5268c2ecf20Sopenharmony_ci * 5278c2ecf20Sopenharmony_ci * The offset is estimated the first time a device SOF value is received 5288c2ecf20Sopenharmony_ci * as the difference between the host and device SOF values. As the two 5298c2ecf20Sopenharmony_ci * SOF values can differ slightly due to transmission delays, consider 5308c2ecf20Sopenharmony_ci * that the offset is null if the difference is not higher than 10 ms 5318c2ecf20Sopenharmony_ci * (negative differences can not happen and are thus considered as an 5328c2ecf20Sopenharmony_ci * offset). The video commit control wDelay field should be used to 5338c2ecf20Sopenharmony_ci * compute a dynamic threshold instead of using a fixed 10 ms value, but 5348c2ecf20Sopenharmony_ci * devices don't report reliable wDelay values. 5358c2ecf20Sopenharmony_ci * 5368c2ecf20Sopenharmony_ci * See uvc_video_clock_host_sof() for an explanation regarding why only 5378c2ecf20Sopenharmony_ci * the 8 LSBs of the delta are kept. 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_ci if (stream->clock.sof_offset == (u16)-1) { 5408c2ecf20Sopenharmony_ci u16 delta_sof = (host_sof - dev_sof) & 255; 5418c2ecf20Sopenharmony_ci if (delta_sof >= 10) 5428c2ecf20Sopenharmony_ci stream->clock.sof_offset = delta_sof; 5438c2ecf20Sopenharmony_ci else 5448c2ecf20Sopenharmony_ci stream->clock.sof_offset = 0; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci dev_sof = (dev_sof + stream->clock.sof_offset) & 2047; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci spin_lock_irqsave(&stream->clock.lock, flags); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci sample = &stream->clock.samples[stream->clock.head]; 5528c2ecf20Sopenharmony_ci sample->dev_stc = get_unaligned_le32(&data[header_size - 6]); 5538c2ecf20Sopenharmony_ci sample->dev_sof = dev_sof; 5548c2ecf20Sopenharmony_ci sample->host_sof = host_sof; 5558c2ecf20Sopenharmony_ci sample->host_time = time; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /* Update the sliding window head and count. */ 5588c2ecf20Sopenharmony_ci stream->clock.head = (stream->clock.head + 1) % stream->clock.size; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (stream->clock.count < stream->clock.size) 5618c2ecf20Sopenharmony_ci stream->clock.count++; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&stream->clock.lock, flags); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic void uvc_video_clock_reset(struct uvc_streaming *stream) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct uvc_clock *clock = &stream->clock; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci clock->head = 0; 5718c2ecf20Sopenharmony_ci clock->count = 0; 5728c2ecf20Sopenharmony_ci clock->last_sof = -1; 5738c2ecf20Sopenharmony_ci clock->sof_offset = -1; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic int uvc_video_clock_init(struct uvc_streaming *stream) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct uvc_clock *clock = &stream->clock; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci spin_lock_init(&clock->lock); 5818c2ecf20Sopenharmony_ci clock->size = 32; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci clock->samples = kmalloc_array(clock->size, sizeof(*clock->samples), 5848c2ecf20Sopenharmony_ci GFP_KERNEL); 5858c2ecf20Sopenharmony_ci if (clock->samples == NULL) 5868c2ecf20Sopenharmony_ci return -ENOMEM; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci uvc_video_clock_reset(stream); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return 0; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic void uvc_video_clock_cleanup(struct uvc_streaming *stream) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci kfree(stream->clock.samples); 5968c2ecf20Sopenharmony_ci stream->clock.samples = NULL; 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci/* 6008c2ecf20Sopenharmony_ci * uvc_video_clock_host_sof - Return the host SOF value for a clock sample 6018c2ecf20Sopenharmony_ci * 6028c2ecf20Sopenharmony_ci * Host SOF counters reported by usb_get_current_frame_number() usually don't 6038c2ecf20Sopenharmony_ci * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame 6048c2ecf20Sopenharmony_ci * schedule window. They can be limited to 8, 9 or 10 bits depending on the host 6058c2ecf20Sopenharmony_ci * controller and its configuration. 6068c2ecf20Sopenharmony_ci * 6078c2ecf20Sopenharmony_ci * We thus need to recover the SOF value corresponding to the host frame number. 6088c2ecf20Sopenharmony_ci * As the device and host frame numbers are sampled in a short interval, the 6098c2ecf20Sopenharmony_ci * difference between their values should be equal to a small delta plus an 6108c2ecf20Sopenharmony_ci * integer multiple of 256 caused by the host frame number limited precision. 6118c2ecf20Sopenharmony_ci * 6128c2ecf20Sopenharmony_ci * To obtain the recovered host SOF value, compute the small delta by masking 6138c2ecf20Sopenharmony_ci * the high bits of the host frame counter and device SOF difference and add it 6148c2ecf20Sopenharmony_ci * to the device SOF value. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_cistatic u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci /* The delta value can be negative. */ 6198c2ecf20Sopenharmony_ci s8 delta_sof; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci delta_sof = (sample->host_sof - sample->dev_sof) & 255; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci return (sample->dev_sof + delta_sof) & 2047; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci/* 6278c2ecf20Sopenharmony_ci * uvc_video_clock_update - Update the buffer timestamp 6288c2ecf20Sopenharmony_ci * 6298c2ecf20Sopenharmony_ci * This function converts the buffer PTS timestamp to the host clock domain by 6308c2ecf20Sopenharmony_ci * going through the USB SOF clock domain and stores the result in the V4L2 6318c2ecf20Sopenharmony_ci * buffer timestamp field. 6328c2ecf20Sopenharmony_ci * 6338c2ecf20Sopenharmony_ci * The relationship between the device clock and the host clock isn't known. 6348c2ecf20Sopenharmony_ci * However, the device and the host share the common USB SOF clock which can be 6358c2ecf20Sopenharmony_ci * used to recover that relationship. 6368c2ecf20Sopenharmony_ci * 6378c2ecf20Sopenharmony_ci * The relationship between the device clock and the USB SOF clock is considered 6388c2ecf20Sopenharmony_ci * to be linear over the clock samples sliding window and is given by 6398c2ecf20Sopenharmony_ci * 6408c2ecf20Sopenharmony_ci * SOF = m * PTS + p 6418c2ecf20Sopenharmony_ci * 6428c2ecf20Sopenharmony_ci * Several methods to compute the slope (m) and intercept (p) can be used. As 6438c2ecf20Sopenharmony_ci * the clock drift should be small compared to the sliding window size, we 6448c2ecf20Sopenharmony_ci * assume that the line that goes through the points at both ends of the window 6458c2ecf20Sopenharmony_ci * is a good approximation. Naming those points P1 and P2, we get 6468c2ecf20Sopenharmony_ci * 6478c2ecf20Sopenharmony_ci * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS 6488c2ecf20Sopenharmony_ci * + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) 6498c2ecf20Sopenharmony_ci * 6508c2ecf20Sopenharmony_ci * or 6518c2ecf20Sopenharmony_ci * 6528c2ecf20Sopenharmony_ci * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1) 6538c2ecf20Sopenharmony_ci * 6548c2ecf20Sopenharmony_ci * to avoid losing precision in the division. Similarly, the host timestamp is 6558c2ecf20Sopenharmony_ci * computed with 6568c2ecf20Sopenharmony_ci * 6578c2ecf20Sopenharmony_ci * TS = ((TS2 - TS1) * SOF + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) 6588c2ecf20Sopenharmony_ci * 6598c2ecf20Sopenharmony_ci * SOF values are coded on 11 bits by USB. We extend their precision with 16 6608c2ecf20Sopenharmony_ci * decimal bits, leading to a 11.16 coding. 6618c2ecf20Sopenharmony_ci * 6628c2ecf20Sopenharmony_ci * TODO: To avoid surprises with device clock values, PTS/STC timestamps should 6638c2ecf20Sopenharmony_ci * be normalized using the nominal device clock frequency reported through the 6648c2ecf20Sopenharmony_ci * UVC descriptors. 6658c2ecf20Sopenharmony_ci * 6668c2ecf20Sopenharmony_ci * Both the PTS/STC and SOF counters roll over, after a fixed but device 6678c2ecf20Sopenharmony_ci * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the 6688c2ecf20Sopenharmony_ci * sliding window size is smaller than the rollover period, differences computed 6698c2ecf20Sopenharmony_ci * on unsigned integers will produce the correct result. However, the p term in 6708c2ecf20Sopenharmony_ci * the linear relations will be miscomputed. 6718c2ecf20Sopenharmony_ci * 6728c2ecf20Sopenharmony_ci * To fix the issue, we subtract a constant from the PTS and STC values to bring 6738c2ecf20Sopenharmony_ci * PTS to half the 32 bit STC range. The sliding window STC values then fit into 6748c2ecf20Sopenharmony_ci * the 32 bit range without any rollover. 6758c2ecf20Sopenharmony_ci * 6768c2ecf20Sopenharmony_ci * Similarly, we add 2048 to the device SOF values to make sure that the SOF 6778c2ecf20Sopenharmony_ci * computed by (1) will never be smaller than 0. This offset is then compensated 6788c2ecf20Sopenharmony_ci * by adding 2048 to the SOF values used in (2). However, this doesn't prevent 6798c2ecf20Sopenharmony_ci * rollovers between (1) and (2): the SOF value computed by (1) can be slightly 6808c2ecf20Sopenharmony_ci * lower than 4096, and the host SOF counters can have rolled over to 2048. This 6818c2ecf20Sopenharmony_ci * case is handled by subtracting 2048 from the SOF value if it exceeds the host 6828c2ecf20Sopenharmony_ci * SOF value at the end of the sliding window. 6838c2ecf20Sopenharmony_ci * 6848c2ecf20Sopenharmony_ci * Finally we subtract a constant from the host timestamps to bring the first 6858c2ecf20Sopenharmony_ci * timestamp of the sliding window to 1s. 6868c2ecf20Sopenharmony_ci */ 6878c2ecf20Sopenharmony_civoid uvc_video_clock_update(struct uvc_streaming *stream, 6888c2ecf20Sopenharmony_ci struct vb2_v4l2_buffer *vbuf, 6898c2ecf20Sopenharmony_ci struct uvc_buffer *buf) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci struct uvc_clock *clock = &stream->clock; 6928c2ecf20Sopenharmony_ci struct uvc_clock_sample *first; 6938c2ecf20Sopenharmony_ci struct uvc_clock_sample *last; 6948c2ecf20Sopenharmony_ci unsigned long flags; 6958c2ecf20Sopenharmony_ci u64 timestamp; 6968c2ecf20Sopenharmony_ci u32 delta_stc; 6978c2ecf20Sopenharmony_ci u32 y1; 6988c2ecf20Sopenharmony_ci u32 x1, x2; 6998c2ecf20Sopenharmony_ci u32 mean; 7008c2ecf20Sopenharmony_ci u32 sof; 7018c2ecf20Sopenharmony_ci u64 y, y2; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (!uvc_hw_timestamps_param) 7048c2ecf20Sopenharmony_ci return; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci /* 7078c2ecf20Sopenharmony_ci * We will get called from __vb2_queue_cancel() if there are buffers 7088c2ecf20Sopenharmony_ci * done but not dequeued by the user, but the sample array has already 7098c2ecf20Sopenharmony_ci * been released at that time. Just bail out in that case. 7108c2ecf20Sopenharmony_ci */ 7118c2ecf20Sopenharmony_ci if (!clock->samples) 7128c2ecf20Sopenharmony_ci return; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci spin_lock_irqsave(&clock->lock, flags); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci if (clock->count < clock->size) 7178c2ecf20Sopenharmony_ci goto done; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci first = &clock->samples[clock->head]; 7208c2ecf20Sopenharmony_ci last = &clock->samples[(clock->head - 1) % clock->size]; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* First step, PTS to SOF conversion. */ 7238c2ecf20Sopenharmony_ci delta_stc = buf->pts - (1UL << 31); 7248c2ecf20Sopenharmony_ci x1 = first->dev_stc - delta_stc; 7258c2ecf20Sopenharmony_ci x2 = last->dev_stc - delta_stc; 7268c2ecf20Sopenharmony_ci if (x1 == x2) 7278c2ecf20Sopenharmony_ci goto done; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci y1 = (first->dev_sof + 2048) << 16; 7308c2ecf20Sopenharmony_ci y2 = (last->dev_sof + 2048) << 16; 7318c2ecf20Sopenharmony_ci if (y2 < y1) 7328c2ecf20Sopenharmony_ci y2 += 2048 << 16; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2 7358c2ecf20Sopenharmony_ci - (u64)y2 * (u64)x1; 7368c2ecf20Sopenharmony_ci y = div_u64(y, x2 - x1); 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci sof = y; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu " 7418c2ecf20Sopenharmony_ci "(x1 %u x2 %u y1 %u y2 %llu SOF offset %u)\n", 7428c2ecf20Sopenharmony_ci stream->dev->name, buf->pts, 7438c2ecf20Sopenharmony_ci y >> 16, div_u64((y & 0xffff) * 1000000, 65536), 7448c2ecf20Sopenharmony_ci sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), 7458c2ecf20Sopenharmony_ci x1, x2, y1, y2, clock->sof_offset); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci /* Second step, SOF to host clock conversion. */ 7488c2ecf20Sopenharmony_ci x1 = (uvc_video_clock_host_sof(first) + 2048) << 16; 7498c2ecf20Sopenharmony_ci x2 = (uvc_video_clock_host_sof(last) + 2048) << 16; 7508c2ecf20Sopenharmony_ci if (x2 < x1) 7518c2ecf20Sopenharmony_ci x2 += 2048 << 16; 7528c2ecf20Sopenharmony_ci if (x1 == x2) 7538c2ecf20Sopenharmony_ci goto done; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci y1 = NSEC_PER_SEC; 7568c2ecf20Sopenharmony_ci y2 = ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* Interpolated and host SOF timestamps can wrap around at slightly 7598c2ecf20Sopenharmony_ci * different times. Handle this by adding or removing 2048 to or from 7608c2ecf20Sopenharmony_ci * the computed SOF value to keep it close to the SOF samples mean 7618c2ecf20Sopenharmony_ci * value. 7628c2ecf20Sopenharmony_ci */ 7638c2ecf20Sopenharmony_ci mean = (x1 + x2) / 2; 7648c2ecf20Sopenharmony_ci if (mean - (1024 << 16) > sof) 7658c2ecf20Sopenharmony_ci sof += 2048 << 16; 7668c2ecf20Sopenharmony_ci else if (sof > mean + (1024 << 16)) 7678c2ecf20Sopenharmony_ci sof -= 2048 << 16; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2 7708c2ecf20Sopenharmony_ci - (u64)y2 * (u64)x1; 7718c2ecf20Sopenharmony_ci y = div_u64(y, x2 - x1); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci timestamp = ktime_to_ns(first->host_time) + y - y1; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu " 7768c2ecf20Sopenharmony_ci "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %llu)\n", 7778c2ecf20Sopenharmony_ci stream->dev->name, 7788c2ecf20Sopenharmony_ci sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), 7798c2ecf20Sopenharmony_ci y, timestamp, vbuf->vb2_buf.timestamp, 7808c2ecf20Sopenharmony_ci x1, first->host_sof, first->dev_sof, 7818c2ecf20Sopenharmony_ci x2, last->host_sof, last->dev_sof, y1, y2); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* Update the V4L2 buffer. */ 7848c2ecf20Sopenharmony_ci vbuf->vb2_buf.timestamp = timestamp; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cidone: 7878c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&clock->lock, flags); 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 7918c2ecf20Sopenharmony_ci * Stream statistics 7928c2ecf20Sopenharmony_ci */ 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic void uvc_video_stats_decode(struct uvc_streaming *stream, 7958c2ecf20Sopenharmony_ci const u8 *data, int len) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci unsigned int header_size; 7988c2ecf20Sopenharmony_ci bool has_pts = false; 7998c2ecf20Sopenharmony_ci bool has_scr = false; 8008c2ecf20Sopenharmony_ci u16 scr_sof; 8018c2ecf20Sopenharmony_ci u32 scr_stc; 8028c2ecf20Sopenharmony_ci u32 pts; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (stream->stats.stream.nb_frames == 0 && 8058c2ecf20Sopenharmony_ci stream->stats.frame.nb_packets == 0) 8068c2ecf20Sopenharmony_ci stream->stats.stream.start_ts = ktime_get(); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { 8098c2ecf20Sopenharmony_ci case UVC_STREAM_PTS | UVC_STREAM_SCR: 8108c2ecf20Sopenharmony_ci header_size = 12; 8118c2ecf20Sopenharmony_ci has_pts = true; 8128c2ecf20Sopenharmony_ci has_scr = true; 8138c2ecf20Sopenharmony_ci break; 8148c2ecf20Sopenharmony_ci case UVC_STREAM_PTS: 8158c2ecf20Sopenharmony_ci header_size = 6; 8168c2ecf20Sopenharmony_ci has_pts = true; 8178c2ecf20Sopenharmony_ci break; 8188c2ecf20Sopenharmony_ci case UVC_STREAM_SCR: 8198c2ecf20Sopenharmony_ci header_size = 8; 8208c2ecf20Sopenharmony_ci has_scr = true; 8218c2ecf20Sopenharmony_ci break; 8228c2ecf20Sopenharmony_ci default: 8238c2ecf20Sopenharmony_ci header_size = 2; 8248c2ecf20Sopenharmony_ci break; 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci /* Check for invalid headers. */ 8288c2ecf20Sopenharmony_ci if (len < header_size || data[0] < header_size) { 8298c2ecf20Sopenharmony_ci stream->stats.frame.nb_invalid++; 8308c2ecf20Sopenharmony_ci return; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci /* Extract the timestamps. */ 8348c2ecf20Sopenharmony_ci if (has_pts) 8358c2ecf20Sopenharmony_ci pts = get_unaligned_le32(&data[2]); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (has_scr) { 8388c2ecf20Sopenharmony_ci scr_stc = get_unaligned_le32(&data[header_size - 6]); 8398c2ecf20Sopenharmony_ci scr_sof = get_unaligned_le16(&data[header_size - 2]); 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci /* Is PTS constant through the whole frame ? */ 8438c2ecf20Sopenharmony_ci if (has_pts && stream->stats.frame.nb_pts) { 8448c2ecf20Sopenharmony_ci if (stream->stats.frame.pts != pts) { 8458c2ecf20Sopenharmony_ci stream->stats.frame.nb_pts_diffs++; 8468c2ecf20Sopenharmony_ci stream->stats.frame.last_pts_diff = 8478c2ecf20Sopenharmony_ci stream->stats.frame.nb_packets; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci if (has_pts) { 8528c2ecf20Sopenharmony_ci stream->stats.frame.nb_pts++; 8538c2ecf20Sopenharmony_ci stream->stats.frame.pts = pts; 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci /* Do all frames have a PTS in their first non-empty packet, or before 8578c2ecf20Sopenharmony_ci * their first empty packet ? 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci if (stream->stats.frame.size == 0) { 8608c2ecf20Sopenharmony_ci if (len > header_size) 8618c2ecf20Sopenharmony_ci stream->stats.frame.has_initial_pts = has_pts; 8628c2ecf20Sopenharmony_ci if (len == header_size && has_pts) 8638c2ecf20Sopenharmony_ci stream->stats.frame.has_early_pts = true; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */ 8678c2ecf20Sopenharmony_ci if (has_scr && stream->stats.frame.nb_scr) { 8688c2ecf20Sopenharmony_ci if (stream->stats.frame.scr_stc != scr_stc) 8698c2ecf20Sopenharmony_ci stream->stats.frame.nb_scr_diffs++; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (has_scr) { 8738c2ecf20Sopenharmony_ci /* Expand the SOF counter to 32 bits and store its value. */ 8748c2ecf20Sopenharmony_ci if (stream->stats.stream.nb_frames > 0 || 8758c2ecf20Sopenharmony_ci stream->stats.frame.nb_scr > 0) 8768c2ecf20Sopenharmony_ci stream->stats.stream.scr_sof_count += 8778c2ecf20Sopenharmony_ci (scr_sof - stream->stats.stream.scr_sof) % 2048; 8788c2ecf20Sopenharmony_ci stream->stats.stream.scr_sof = scr_sof; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci stream->stats.frame.nb_scr++; 8818c2ecf20Sopenharmony_ci stream->stats.frame.scr_stc = scr_stc; 8828c2ecf20Sopenharmony_ci stream->stats.frame.scr_sof = scr_sof; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (scr_sof < stream->stats.stream.min_sof) 8858c2ecf20Sopenharmony_ci stream->stats.stream.min_sof = scr_sof; 8868c2ecf20Sopenharmony_ci if (scr_sof > stream->stats.stream.max_sof) 8878c2ecf20Sopenharmony_ci stream->stats.stream.max_sof = scr_sof; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* Record the first non-empty packet number. */ 8918c2ecf20Sopenharmony_ci if (stream->stats.frame.size == 0 && len > header_size) 8928c2ecf20Sopenharmony_ci stream->stats.frame.first_data = stream->stats.frame.nb_packets; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci /* Update the frame size. */ 8958c2ecf20Sopenharmony_ci stream->stats.frame.size += len - header_size; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* Update the packets counters. */ 8988c2ecf20Sopenharmony_ci stream->stats.frame.nb_packets++; 8998c2ecf20Sopenharmony_ci if (len <= header_size) 9008c2ecf20Sopenharmony_ci stream->stats.frame.nb_empty++; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci if (data[1] & UVC_STREAM_ERR) 9038c2ecf20Sopenharmony_ci stream->stats.frame.nb_errors++; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic void uvc_video_stats_update(struct uvc_streaming *stream) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci struct uvc_stats_frame *frame = &stream->stats.frame; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, " 9118c2ecf20Sopenharmony_ci "%u/%u/%u pts (%searly %sinitial), %u/%u scr, " 9128c2ecf20Sopenharmony_ci "last pts/stc/sof %u/%u/%u\n", 9138c2ecf20Sopenharmony_ci stream->sequence, frame->first_data, 9148c2ecf20Sopenharmony_ci frame->nb_packets - frame->nb_empty, frame->nb_packets, 9158c2ecf20Sopenharmony_ci frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts, 9168c2ecf20Sopenharmony_ci frame->has_early_pts ? "" : "!", 9178c2ecf20Sopenharmony_ci frame->has_initial_pts ? "" : "!", 9188c2ecf20Sopenharmony_ci frame->nb_scr_diffs, frame->nb_scr, 9198c2ecf20Sopenharmony_ci frame->pts, frame->scr_stc, frame->scr_sof); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci stream->stats.stream.nb_frames++; 9228c2ecf20Sopenharmony_ci stream->stats.stream.nb_packets += stream->stats.frame.nb_packets; 9238c2ecf20Sopenharmony_ci stream->stats.stream.nb_empty += stream->stats.frame.nb_empty; 9248c2ecf20Sopenharmony_ci stream->stats.stream.nb_errors += stream->stats.frame.nb_errors; 9258c2ecf20Sopenharmony_ci stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (frame->has_early_pts) 9288c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_early++; 9298c2ecf20Sopenharmony_ci if (frame->has_initial_pts) 9308c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_initial++; 9318c2ecf20Sopenharmony_ci if (frame->last_pts_diff <= frame->first_data) 9328c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_constant++; 9338c2ecf20Sopenharmony_ci if (frame->nb_scr >= frame->nb_packets - frame->nb_empty) 9348c2ecf20Sopenharmony_ci stream->stats.stream.nb_scr_count_ok++; 9358c2ecf20Sopenharmony_ci if (frame->nb_scr_diffs + 1 == frame->nb_scr) 9368c2ecf20Sopenharmony_ci stream->stats.stream.nb_scr_diffs_ok++; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci memset(&stream->stats.frame, 0, sizeof(stream->stats.frame)); 9398c2ecf20Sopenharmony_ci} 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_cisize_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, 9428c2ecf20Sopenharmony_ci size_t size) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci unsigned int scr_sof_freq; 9458c2ecf20Sopenharmony_ci unsigned int duration; 9468c2ecf20Sopenharmony_ci size_t count = 0; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF 9498c2ecf20Sopenharmony_ci * frequency this will not overflow before more than 1h. 9508c2ecf20Sopenharmony_ci */ 9518c2ecf20Sopenharmony_ci duration = ktime_ms_delta(stream->stats.stream.stop_ts, 9528c2ecf20Sopenharmony_ci stream->stats.stream.start_ts); 9538c2ecf20Sopenharmony_ci if (duration != 0) 9548c2ecf20Sopenharmony_ci scr_sof_freq = stream->stats.stream.scr_sof_count * 1000 9558c2ecf20Sopenharmony_ci / duration; 9568c2ecf20Sopenharmony_ci else 9578c2ecf20Sopenharmony_ci scr_sof_freq = 0; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci count += scnprintf(buf + count, size - count, 9608c2ecf20Sopenharmony_ci "frames: %u\npackets: %u\nempty: %u\n" 9618c2ecf20Sopenharmony_ci "errors: %u\ninvalid: %u\n", 9628c2ecf20Sopenharmony_ci stream->stats.stream.nb_frames, 9638c2ecf20Sopenharmony_ci stream->stats.stream.nb_packets, 9648c2ecf20Sopenharmony_ci stream->stats.stream.nb_empty, 9658c2ecf20Sopenharmony_ci stream->stats.stream.nb_errors, 9668c2ecf20Sopenharmony_ci stream->stats.stream.nb_invalid); 9678c2ecf20Sopenharmony_ci count += scnprintf(buf + count, size - count, 9688c2ecf20Sopenharmony_ci "pts: %u early, %u initial, %u ok\n", 9698c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_early, 9708c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_initial, 9718c2ecf20Sopenharmony_ci stream->stats.stream.nb_pts_constant); 9728c2ecf20Sopenharmony_ci count += scnprintf(buf + count, size - count, 9738c2ecf20Sopenharmony_ci "scr: %u count ok, %u diff ok\n", 9748c2ecf20Sopenharmony_ci stream->stats.stream.nb_scr_count_ok, 9758c2ecf20Sopenharmony_ci stream->stats.stream.nb_scr_diffs_ok); 9768c2ecf20Sopenharmony_ci count += scnprintf(buf + count, size - count, 9778c2ecf20Sopenharmony_ci "sof: %u <= sof <= %u, freq %u.%03u kHz\n", 9788c2ecf20Sopenharmony_ci stream->stats.stream.min_sof, 9798c2ecf20Sopenharmony_ci stream->stats.stream.max_sof, 9808c2ecf20Sopenharmony_ci scr_sof_freq / 1000, scr_sof_freq % 1000); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci return count; 9838c2ecf20Sopenharmony_ci} 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_cistatic void uvc_video_stats_start(struct uvc_streaming *stream) 9868c2ecf20Sopenharmony_ci{ 9878c2ecf20Sopenharmony_ci memset(&stream->stats, 0, sizeof(stream->stats)); 9888c2ecf20Sopenharmony_ci stream->stats.stream.min_sof = 2048; 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_cistatic void uvc_video_stats_stop(struct uvc_streaming *stream) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci stream->stats.stream.stop_ts = ktime_get(); 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 9978c2ecf20Sopenharmony_ci * Video codecs 9988c2ecf20Sopenharmony_ci */ 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci/* Video payload decoding is handled by uvc_video_decode_start(), 10018c2ecf20Sopenharmony_ci * uvc_video_decode_data() and uvc_video_decode_end(). 10028c2ecf20Sopenharmony_ci * 10038c2ecf20Sopenharmony_ci * uvc_video_decode_start is called with URB data at the start of a bulk or 10048c2ecf20Sopenharmony_ci * isochronous payload. It processes header data and returns the header size 10058c2ecf20Sopenharmony_ci * in bytes if successful. If an error occurs, it returns a negative error 10068c2ecf20Sopenharmony_ci * code. The following error codes have special meanings. 10078c2ecf20Sopenharmony_ci * 10088c2ecf20Sopenharmony_ci * - EAGAIN informs the caller that the current video buffer should be marked 10098c2ecf20Sopenharmony_ci * as done, and that the function should be called again with the same data 10108c2ecf20Sopenharmony_ci * and a new video buffer. This is used when end of frame conditions can be 10118c2ecf20Sopenharmony_ci * reliably detected at the beginning of the next frame only. 10128c2ecf20Sopenharmony_ci * 10138c2ecf20Sopenharmony_ci * If an error other than -EAGAIN is returned, the caller will drop the current 10148c2ecf20Sopenharmony_ci * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be 10158c2ecf20Sopenharmony_ci * made until the next payload. -ENODATA can be used to drop the current 10168c2ecf20Sopenharmony_ci * payload if no other error code is appropriate. 10178c2ecf20Sopenharmony_ci * 10188c2ecf20Sopenharmony_ci * uvc_video_decode_data is called for every URB with URB data. It copies the 10198c2ecf20Sopenharmony_ci * data to the video buffer. 10208c2ecf20Sopenharmony_ci * 10218c2ecf20Sopenharmony_ci * uvc_video_decode_end is called with header data at the end of a bulk or 10228c2ecf20Sopenharmony_ci * isochronous payload. It performs any additional header data processing and 10238c2ecf20Sopenharmony_ci * returns 0 or a negative error code if an error occurred. As header data have 10248c2ecf20Sopenharmony_ci * already been processed by uvc_video_decode_start, this functions isn't 10258c2ecf20Sopenharmony_ci * required to perform sanity checks a second time. 10268c2ecf20Sopenharmony_ci * 10278c2ecf20Sopenharmony_ci * For isochronous transfers where a payload is always transferred in a single 10288c2ecf20Sopenharmony_ci * URB, the three functions will be called in a row. 10298c2ecf20Sopenharmony_ci * 10308c2ecf20Sopenharmony_ci * To let the decoder process header data and update its internal state even 10318c2ecf20Sopenharmony_ci * when no video buffer is available, uvc_video_decode_start must be prepared 10328c2ecf20Sopenharmony_ci * to be called with a NULL buf parameter. uvc_video_decode_data and 10338c2ecf20Sopenharmony_ci * uvc_video_decode_end will never be called with a NULL buffer. 10348c2ecf20Sopenharmony_ci */ 10358c2ecf20Sopenharmony_cistatic int uvc_video_decode_start(struct uvc_streaming *stream, 10368c2ecf20Sopenharmony_ci struct uvc_buffer *buf, const u8 *data, int len) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci u8 fid; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci /* Sanity checks: 10418c2ecf20Sopenharmony_ci * - packet must be at least 2 bytes long 10428c2ecf20Sopenharmony_ci * - bHeaderLength value must be at least 2 bytes (see above) 10438c2ecf20Sopenharmony_ci * - bHeaderLength value can't be larger than the packet size. 10448c2ecf20Sopenharmony_ci */ 10458c2ecf20Sopenharmony_ci if (len < 2 || data[0] < 2 || data[0] > len) { 10468c2ecf20Sopenharmony_ci stream->stats.frame.nb_invalid++; 10478c2ecf20Sopenharmony_ci return -EINVAL; 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci fid = data[1] & UVC_STREAM_FID; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci /* Increase the sequence number regardless of any buffer states, so 10538c2ecf20Sopenharmony_ci * that discontinuous sequence numbers always indicate lost frames. 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci if (stream->last_fid != fid) { 10568c2ecf20Sopenharmony_ci stream->sequence++; 10578c2ecf20Sopenharmony_ci if (stream->sequence) 10588c2ecf20Sopenharmony_ci uvc_video_stats_update(stream); 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci uvc_video_clock_decode(stream, buf, data, len); 10628c2ecf20Sopenharmony_ci uvc_video_stats_decode(stream, data, len); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci /* Store the payload FID bit and return immediately when the buffer is 10658c2ecf20Sopenharmony_ci * NULL. 10668c2ecf20Sopenharmony_ci */ 10678c2ecf20Sopenharmony_ci if (buf == NULL) { 10688c2ecf20Sopenharmony_ci stream->last_fid = fid; 10698c2ecf20Sopenharmony_ci return -ENODATA; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci /* Mark the buffer as bad if the error bit is set. */ 10738c2ecf20Sopenharmony_ci if (data[1] & UVC_STREAM_ERR) { 10748c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit " 10758c2ecf20Sopenharmony_ci "set).\n"); 10768c2ecf20Sopenharmony_ci buf->error = 1; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* Synchronize to the input stream by waiting for the FID bit to be 10808c2ecf20Sopenharmony_ci * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. 10818c2ecf20Sopenharmony_ci * stream->last_fid is initialized to -1, so the first isochronous 10828c2ecf20Sopenharmony_ci * frame will always be in sync. 10838c2ecf20Sopenharmony_ci * 10848c2ecf20Sopenharmony_ci * If the device doesn't toggle the FID bit, invert stream->last_fid 10858c2ecf20Sopenharmony_ci * when the EOF bit is set to force synchronisation on the next packet. 10868c2ecf20Sopenharmony_ci */ 10878c2ecf20Sopenharmony_ci if (buf->state != UVC_BUF_STATE_ACTIVE) { 10888c2ecf20Sopenharmony_ci if (fid == stream->last_fid) { 10898c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " 10908c2ecf20Sopenharmony_ci "sync).\n"); 10918c2ecf20Sopenharmony_ci if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && 10928c2ecf20Sopenharmony_ci (data[1] & UVC_STREAM_EOF)) 10938c2ecf20Sopenharmony_ci stream->last_fid ^= UVC_STREAM_FID; 10948c2ecf20Sopenharmony_ci return -ENODATA; 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci buf->buf.field = V4L2_FIELD_NONE; 10988c2ecf20Sopenharmony_ci buf->buf.sequence = stream->sequence; 10998c2ecf20Sopenharmony_ci buf->buf.vb2_buf.timestamp = ktime_to_ns(uvc_video_get_time()); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci /* TODO: Handle PTS and SCR. */ 11028c2ecf20Sopenharmony_ci buf->state = UVC_BUF_STATE_ACTIVE; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci /* Mark the buffer as done if we're at the beginning of a new frame. 11068c2ecf20Sopenharmony_ci * End of frame detection is better implemented by checking the EOF 11078c2ecf20Sopenharmony_ci * bit (FID bit toggling is delayed by one frame compared to the EOF 11088c2ecf20Sopenharmony_ci * bit), but some devices don't set the bit at end of frame (and the 11098c2ecf20Sopenharmony_ci * last payload can be lost anyway). We thus must check if the FID has 11108c2ecf20Sopenharmony_ci * been toggled. 11118c2ecf20Sopenharmony_ci * 11128c2ecf20Sopenharmony_ci * stream->last_fid is initialized to -1, so the first isochronous 11138c2ecf20Sopenharmony_ci * frame will never trigger an end of frame detection. 11148c2ecf20Sopenharmony_ci * 11158c2ecf20Sopenharmony_ci * Empty buffers (bytesused == 0) don't trigger end of frame detection 11168c2ecf20Sopenharmony_ci * as it doesn't make sense to return an empty buffer. This also 11178c2ecf20Sopenharmony_ci * avoids detecting end of frame conditions at FID toggling if the 11188c2ecf20Sopenharmony_ci * previous payload had the EOF bit set. 11198c2ecf20Sopenharmony_ci */ 11208c2ecf20Sopenharmony_ci if (fid != stream->last_fid && buf->bytesused != 0) { 11218c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " 11228c2ecf20Sopenharmony_ci "toggled).\n"); 11238c2ecf20Sopenharmony_ci buf->state = UVC_BUF_STATE_READY; 11248c2ecf20Sopenharmony_ci return -EAGAIN; 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci stream->last_fid = fid; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci return data[0]; 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci/* 11338c2ecf20Sopenharmony_ci * uvc_video_decode_data_work: Asynchronous memcpy processing 11348c2ecf20Sopenharmony_ci * 11358c2ecf20Sopenharmony_ci * Copy URB data to video buffers in process context, releasing buffer 11368c2ecf20Sopenharmony_ci * references and requeuing the URB when done. 11378c2ecf20Sopenharmony_ci */ 11388c2ecf20Sopenharmony_cistatic void uvc_video_copy_data_work(struct work_struct *work) 11398c2ecf20Sopenharmony_ci{ 11408c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb = container_of(work, struct uvc_urb, work); 11418c2ecf20Sopenharmony_ci unsigned int i; 11428c2ecf20Sopenharmony_ci int ret; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci for (i = 0; i < uvc_urb->async_operations; i++) { 11458c2ecf20Sopenharmony_ci struct uvc_copy_op *op = &uvc_urb->copy_operations[i]; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci memcpy(op->dst, op->src, op->len); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci /* Release reference taken on this buffer. */ 11508c2ecf20Sopenharmony_ci uvc_queue_buffer_release(op->buf); 11518c2ecf20Sopenharmony_ci } 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci ret = usb_submit_urb(uvc_urb->urb, GFP_KERNEL); 11548c2ecf20Sopenharmony_ci if (ret < 0) 11558c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", 11568c2ecf20Sopenharmony_ci ret); 11578c2ecf20Sopenharmony_ci} 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_cistatic void uvc_video_decode_data(struct uvc_urb *uvc_urb, 11608c2ecf20Sopenharmony_ci struct uvc_buffer *buf, const u8 *data, int len) 11618c2ecf20Sopenharmony_ci{ 11628c2ecf20Sopenharmony_ci unsigned int active_op = uvc_urb->async_operations; 11638c2ecf20Sopenharmony_ci struct uvc_copy_op *op = &uvc_urb->copy_operations[active_op]; 11648c2ecf20Sopenharmony_ci unsigned int maxlen; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (len <= 0) 11678c2ecf20Sopenharmony_ci return; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci maxlen = buf->length - buf->bytesused; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci /* Take a buffer reference for async work. */ 11728c2ecf20Sopenharmony_ci kref_get(&buf->ref); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci op->buf = buf; 11758c2ecf20Sopenharmony_ci op->src = data; 11768c2ecf20Sopenharmony_ci op->dst = buf->mem + buf->bytesused; 11778c2ecf20Sopenharmony_ci op->len = min_t(unsigned int, len, maxlen); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci buf->bytesused += op->len; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci /* Complete the current frame if the buffer size was exceeded. */ 11828c2ecf20Sopenharmony_ci if (len > maxlen) { 11838c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); 11848c2ecf20Sopenharmony_ci buf->error = 1; 11858c2ecf20Sopenharmony_ci buf->state = UVC_BUF_STATE_READY; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci uvc_urb->async_operations++; 11898c2ecf20Sopenharmony_ci} 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_cistatic void uvc_video_decode_end(struct uvc_streaming *stream, 11928c2ecf20Sopenharmony_ci struct uvc_buffer *buf, const u8 *data, int len) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci /* Mark the buffer as done if the EOF marker is set. */ 11958c2ecf20Sopenharmony_ci if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { 11968c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); 11978c2ecf20Sopenharmony_ci if (data[0] == len) 11988c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); 11998c2ecf20Sopenharmony_ci buf->state = UVC_BUF_STATE_READY; 12008c2ecf20Sopenharmony_ci if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) 12018c2ecf20Sopenharmony_ci stream->last_fid ^= UVC_STREAM_FID; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci} 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci/* Video payload encoding is handled by uvc_video_encode_header() and 12068c2ecf20Sopenharmony_ci * uvc_video_encode_data(). Only bulk transfers are currently supported. 12078c2ecf20Sopenharmony_ci * 12088c2ecf20Sopenharmony_ci * uvc_video_encode_header is called at the start of a payload. It adds header 12098c2ecf20Sopenharmony_ci * data to the transfer buffer and returns the header size. As the only known 12108c2ecf20Sopenharmony_ci * UVC output device transfers a whole frame in a single payload, the EOF bit 12118c2ecf20Sopenharmony_ci * is always set in the header. 12128c2ecf20Sopenharmony_ci * 12138c2ecf20Sopenharmony_ci * uvc_video_encode_data is called for every URB and copies the data from the 12148c2ecf20Sopenharmony_ci * video buffer to the transfer buffer. 12158c2ecf20Sopenharmony_ci */ 12168c2ecf20Sopenharmony_cistatic int uvc_video_encode_header(struct uvc_streaming *stream, 12178c2ecf20Sopenharmony_ci struct uvc_buffer *buf, u8 *data, int len) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci data[0] = 2; /* Header length */ 12208c2ecf20Sopenharmony_ci data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF 12218c2ecf20Sopenharmony_ci | (stream->last_fid & UVC_STREAM_FID); 12228c2ecf20Sopenharmony_ci return 2; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic int uvc_video_encode_data(struct uvc_streaming *stream, 12268c2ecf20Sopenharmony_ci struct uvc_buffer *buf, u8 *data, int len) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci struct uvc_video_queue *queue = &stream->queue; 12298c2ecf20Sopenharmony_ci unsigned int nbytes; 12308c2ecf20Sopenharmony_ci void *mem; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci /* Copy video data to the URB buffer. */ 12338c2ecf20Sopenharmony_ci mem = buf->mem + queue->buf_used; 12348c2ecf20Sopenharmony_ci nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used); 12358c2ecf20Sopenharmony_ci nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, 12368c2ecf20Sopenharmony_ci nbytes); 12378c2ecf20Sopenharmony_ci memcpy(data, mem, nbytes); 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci queue->buf_used += nbytes; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci return nbytes; 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 12458c2ecf20Sopenharmony_ci * Metadata 12468c2ecf20Sopenharmony_ci */ 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci/* 12498c2ecf20Sopenharmony_ci * Additionally to the payload headers we also want to provide the user with USB 12508c2ecf20Sopenharmony_ci * Frame Numbers and system time values. The resulting buffer is thus composed 12518c2ecf20Sopenharmony_ci * of blocks, containing a 64-bit timestamp in nanoseconds, a 16-bit USB Frame 12528c2ecf20Sopenharmony_ci * Number, and a copy of the payload header. 12538c2ecf20Sopenharmony_ci * 12548c2ecf20Sopenharmony_ci * Ideally we want to capture all payload headers for each frame. However, their 12558c2ecf20Sopenharmony_ci * number is unknown and unbound. We thus drop headers that contain no vendor 12568c2ecf20Sopenharmony_ci * data and that either contain no SCR value or an SCR value identical to the 12578c2ecf20Sopenharmony_ci * previous header. 12588c2ecf20Sopenharmony_ci */ 12598c2ecf20Sopenharmony_cistatic void uvc_video_decode_meta(struct uvc_streaming *stream, 12608c2ecf20Sopenharmony_ci struct uvc_buffer *meta_buf, 12618c2ecf20Sopenharmony_ci const u8 *mem, unsigned int length) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci struct uvc_meta_buf *meta; 12648c2ecf20Sopenharmony_ci size_t len_std = 2; 12658c2ecf20Sopenharmony_ci bool has_pts, has_scr; 12668c2ecf20Sopenharmony_ci unsigned long flags; 12678c2ecf20Sopenharmony_ci unsigned int sof; 12688c2ecf20Sopenharmony_ci ktime_t time; 12698c2ecf20Sopenharmony_ci const u8 *scr; 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci if (!meta_buf || length == 2) 12728c2ecf20Sopenharmony_ci return; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci if (meta_buf->length - meta_buf->bytesused < 12758c2ecf20Sopenharmony_ci length + sizeof(meta->ns) + sizeof(meta->sof)) { 12768c2ecf20Sopenharmony_ci meta_buf->error = 1; 12778c2ecf20Sopenharmony_ci return; 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci has_pts = mem[1] & UVC_STREAM_PTS; 12818c2ecf20Sopenharmony_ci has_scr = mem[1] & UVC_STREAM_SCR; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (has_pts) { 12848c2ecf20Sopenharmony_ci len_std += 4; 12858c2ecf20Sopenharmony_ci scr = mem + 6; 12868c2ecf20Sopenharmony_ci } else { 12878c2ecf20Sopenharmony_ci scr = mem + 2; 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci if (has_scr) 12918c2ecf20Sopenharmony_ci len_std += 6; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci if (stream->meta.format == V4L2_META_FMT_UVC) 12948c2ecf20Sopenharmony_ci length = len_std; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci if (length == len_std && (!has_scr || 12978c2ecf20Sopenharmony_ci !memcmp(scr, stream->clock.last_scr, 6))) 12988c2ecf20Sopenharmony_ci return; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci meta = (struct uvc_meta_buf *)((u8 *)meta_buf->mem + meta_buf->bytesused); 13018c2ecf20Sopenharmony_ci local_irq_save(flags); 13028c2ecf20Sopenharmony_ci time = uvc_video_get_time(); 13038c2ecf20Sopenharmony_ci sof = usb_get_current_frame_number(stream->dev->udev); 13048c2ecf20Sopenharmony_ci local_irq_restore(flags); 13058c2ecf20Sopenharmony_ci put_unaligned(ktime_to_ns(time), &meta->ns); 13068c2ecf20Sopenharmony_ci put_unaligned(sof, &meta->sof); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (has_scr) 13098c2ecf20Sopenharmony_ci memcpy(stream->clock.last_scr, scr, 6); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci meta->length = mem[0]; 13128c2ecf20Sopenharmony_ci meta->flags = mem[1]; 13138c2ecf20Sopenharmony_ci memcpy(meta->buf, &mem[2], length - 2); 13148c2ecf20Sopenharmony_ci meta_buf->bytesused += length + sizeof(meta->ns) + sizeof(meta->sof); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, 13178c2ecf20Sopenharmony_ci "%s(): t-sys %lluns, SOF %u, len %u, flags 0x%x, PTS %u, STC %u frame SOF %u\n", 13188c2ecf20Sopenharmony_ci __func__, ktime_to_ns(time), meta->sof, meta->length, 13198c2ecf20Sopenharmony_ci meta->flags, 13208c2ecf20Sopenharmony_ci has_pts ? *(u32 *)meta->buf : 0, 13218c2ecf20Sopenharmony_ci has_scr ? *(u32 *)scr : 0, 13228c2ecf20Sopenharmony_ci has_scr ? *(u32 *)(scr + 4) & 0x7ff : 0); 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 13268c2ecf20Sopenharmony_ci * URB handling 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci/* 13308c2ecf20Sopenharmony_ci * Set error flag for incomplete buffer. 13318c2ecf20Sopenharmony_ci */ 13328c2ecf20Sopenharmony_cistatic void uvc_video_validate_buffer(const struct uvc_streaming *stream, 13338c2ecf20Sopenharmony_ci struct uvc_buffer *buf) 13348c2ecf20Sopenharmony_ci{ 13358c2ecf20Sopenharmony_ci if (stream->ctrl.dwMaxVideoFrameSize != buf->bytesused && 13368c2ecf20Sopenharmony_ci !(stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED)) 13378c2ecf20Sopenharmony_ci buf->error = 1; 13388c2ecf20Sopenharmony_ci} 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci/* 13418c2ecf20Sopenharmony_ci * Completion handler for video URBs. 13428c2ecf20Sopenharmony_ci */ 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic void uvc_video_next_buffers(struct uvc_streaming *stream, 13458c2ecf20Sopenharmony_ci struct uvc_buffer **video_buf, struct uvc_buffer **meta_buf) 13468c2ecf20Sopenharmony_ci{ 13478c2ecf20Sopenharmony_ci uvc_video_validate_buffer(stream, *video_buf); 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci if (*meta_buf) { 13508c2ecf20Sopenharmony_ci struct vb2_v4l2_buffer *vb2_meta = &(*meta_buf)->buf; 13518c2ecf20Sopenharmony_ci const struct vb2_v4l2_buffer *vb2_video = &(*video_buf)->buf; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci vb2_meta->sequence = vb2_video->sequence; 13548c2ecf20Sopenharmony_ci vb2_meta->field = vb2_video->field; 13558c2ecf20Sopenharmony_ci vb2_meta->vb2_buf.timestamp = vb2_video->vb2_buf.timestamp; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci (*meta_buf)->state = UVC_BUF_STATE_READY; 13588c2ecf20Sopenharmony_ci if (!(*meta_buf)->error) 13598c2ecf20Sopenharmony_ci (*meta_buf)->error = (*video_buf)->error; 13608c2ecf20Sopenharmony_ci *meta_buf = uvc_queue_next_buffer(&stream->meta.queue, 13618c2ecf20Sopenharmony_ci *meta_buf); 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci *video_buf = uvc_queue_next_buffer(&stream->queue, *video_buf); 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cistatic void uvc_video_decode_isoc(struct uvc_urb *uvc_urb, 13678c2ecf20Sopenharmony_ci struct uvc_buffer *buf, struct uvc_buffer *meta_buf) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci struct urb *urb = uvc_urb->urb; 13708c2ecf20Sopenharmony_ci struct uvc_streaming *stream = uvc_urb->stream; 13718c2ecf20Sopenharmony_ci u8 *mem; 13728c2ecf20Sopenharmony_ci int ret, i; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci for (i = 0; i < urb->number_of_packets; ++i) { 13758c2ecf20Sopenharmony_ci if (urb->iso_frame_desc[i].status < 0) { 13768c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " 13778c2ecf20Sopenharmony_ci "lost (%d).\n", urb->iso_frame_desc[i].status); 13788c2ecf20Sopenharmony_ci /* Mark the buffer as faulty. */ 13798c2ecf20Sopenharmony_ci if (buf != NULL) 13808c2ecf20Sopenharmony_ci buf->error = 1; 13818c2ecf20Sopenharmony_ci continue; 13828c2ecf20Sopenharmony_ci } 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci /* Decode the payload header. */ 13858c2ecf20Sopenharmony_ci mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; 13868c2ecf20Sopenharmony_ci do { 13878c2ecf20Sopenharmony_ci ret = uvc_video_decode_start(stream, buf, mem, 13888c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length); 13898c2ecf20Sopenharmony_ci if (ret == -EAGAIN) 13908c2ecf20Sopenharmony_ci uvc_video_next_buffers(stream, &buf, &meta_buf); 13918c2ecf20Sopenharmony_ci } while (ret == -EAGAIN); 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci if (ret < 0) 13948c2ecf20Sopenharmony_ci continue; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci uvc_video_decode_meta(stream, meta_buf, mem, ret); 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci /* Decode the payload data. */ 13998c2ecf20Sopenharmony_ci uvc_video_decode_data(uvc_urb, buf, mem + ret, 14008c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length - ret); 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci /* Process the header again. */ 14038c2ecf20Sopenharmony_ci uvc_video_decode_end(stream, buf, mem, 14048c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length); 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci if (buf->state == UVC_BUF_STATE_READY) 14078c2ecf20Sopenharmony_ci uvc_video_next_buffers(stream, &buf, &meta_buf); 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci} 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_cistatic void uvc_video_decode_bulk(struct uvc_urb *uvc_urb, 14128c2ecf20Sopenharmony_ci struct uvc_buffer *buf, struct uvc_buffer *meta_buf) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci struct urb *urb = uvc_urb->urb; 14158c2ecf20Sopenharmony_ci struct uvc_streaming *stream = uvc_urb->stream; 14168c2ecf20Sopenharmony_ci u8 *mem; 14178c2ecf20Sopenharmony_ci int len, ret; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci /* 14208c2ecf20Sopenharmony_ci * Ignore ZLPs if they're not part of a frame, otherwise process them 14218c2ecf20Sopenharmony_ci * to trigger the end of payload detection. 14228c2ecf20Sopenharmony_ci */ 14238c2ecf20Sopenharmony_ci if (urb->actual_length == 0 && stream->bulk.header_size == 0) 14248c2ecf20Sopenharmony_ci return; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci mem = urb->transfer_buffer; 14278c2ecf20Sopenharmony_ci len = urb->actual_length; 14288c2ecf20Sopenharmony_ci stream->bulk.payload_size += len; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* If the URB is the first of its payload, decode and save the 14318c2ecf20Sopenharmony_ci * header. 14328c2ecf20Sopenharmony_ci */ 14338c2ecf20Sopenharmony_ci if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) { 14348c2ecf20Sopenharmony_ci do { 14358c2ecf20Sopenharmony_ci ret = uvc_video_decode_start(stream, buf, mem, len); 14368c2ecf20Sopenharmony_ci if (ret == -EAGAIN) 14378c2ecf20Sopenharmony_ci uvc_video_next_buffers(stream, &buf, &meta_buf); 14388c2ecf20Sopenharmony_ci } while (ret == -EAGAIN); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* If an error occurred skip the rest of the payload. */ 14418c2ecf20Sopenharmony_ci if (ret < 0 || buf == NULL) { 14428c2ecf20Sopenharmony_ci stream->bulk.skip_payload = 1; 14438c2ecf20Sopenharmony_ci } else { 14448c2ecf20Sopenharmony_ci memcpy(stream->bulk.header, mem, ret); 14458c2ecf20Sopenharmony_ci stream->bulk.header_size = ret; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci uvc_video_decode_meta(stream, meta_buf, mem, ret); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci mem += ret; 14508c2ecf20Sopenharmony_ci len -= ret; 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci } 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* The buffer queue might have been cancelled while a bulk transfer 14558c2ecf20Sopenharmony_ci * was in progress, so we can reach here with buf equal to NULL. Make 14568c2ecf20Sopenharmony_ci * sure buf is never dereferenced if NULL. 14578c2ecf20Sopenharmony_ci */ 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci /* Prepare video data for processing. */ 14608c2ecf20Sopenharmony_ci if (!stream->bulk.skip_payload && buf != NULL) 14618c2ecf20Sopenharmony_ci uvc_video_decode_data(uvc_urb, buf, mem, len); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* Detect the payload end by a URB smaller than the maximum size (or 14648c2ecf20Sopenharmony_ci * a payload size equal to the maximum) and process the header again. 14658c2ecf20Sopenharmony_ci */ 14668c2ecf20Sopenharmony_ci if (urb->actual_length < urb->transfer_buffer_length || 14678c2ecf20Sopenharmony_ci stream->bulk.payload_size >= stream->bulk.max_payload_size) { 14688c2ecf20Sopenharmony_ci if (!stream->bulk.skip_payload && buf != NULL) { 14698c2ecf20Sopenharmony_ci uvc_video_decode_end(stream, buf, stream->bulk.header, 14708c2ecf20Sopenharmony_ci stream->bulk.payload_size); 14718c2ecf20Sopenharmony_ci if (buf->state == UVC_BUF_STATE_READY) 14728c2ecf20Sopenharmony_ci uvc_video_next_buffers(stream, &buf, &meta_buf); 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci stream->bulk.header_size = 0; 14768c2ecf20Sopenharmony_ci stream->bulk.skip_payload = 0; 14778c2ecf20Sopenharmony_ci stream->bulk.payload_size = 0; 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci} 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_cistatic void uvc_video_encode_bulk(struct uvc_urb *uvc_urb, 14828c2ecf20Sopenharmony_ci struct uvc_buffer *buf, struct uvc_buffer *meta_buf) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci struct urb *urb = uvc_urb->urb; 14858c2ecf20Sopenharmony_ci struct uvc_streaming *stream = uvc_urb->stream; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci u8 *mem = urb->transfer_buffer; 14888c2ecf20Sopenharmony_ci int len = stream->urb_size, ret; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci if (buf == NULL) { 14918c2ecf20Sopenharmony_ci urb->transfer_buffer_length = 0; 14928c2ecf20Sopenharmony_ci return; 14938c2ecf20Sopenharmony_ci } 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci /* If the URB is the first of its payload, add the header. */ 14968c2ecf20Sopenharmony_ci if (stream->bulk.header_size == 0) { 14978c2ecf20Sopenharmony_ci ret = uvc_video_encode_header(stream, buf, mem, len); 14988c2ecf20Sopenharmony_ci stream->bulk.header_size = ret; 14998c2ecf20Sopenharmony_ci stream->bulk.payload_size += ret; 15008c2ecf20Sopenharmony_ci mem += ret; 15018c2ecf20Sopenharmony_ci len -= ret; 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci /* Process video data. */ 15058c2ecf20Sopenharmony_ci ret = uvc_video_encode_data(stream, buf, mem, len); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci stream->bulk.payload_size += ret; 15088c2ecf20Sopenharmony_ci len -= ret; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (buf->bytesused == stream->queue.buf_used || 15118c2ecf20Sopenharmony_ci stream->bulk.payload_size == stream->bulk.max_payload_size) { 15128c2ecf20Sopenharmony_ci if (buf->bytesused == stream->queue.buf_used) { 15138c2ecf20Sopenharmony_ci stream->queue.buf_used = 0; 15148c2ecf20Sopenharmony_ci buf->state = UVC_BUF_STATE_READY; 15158c2ecf20Sopenharmony_ci buf->buf.sequence = ++stream->sequence; 15168c2ecf20Sopenharmony_ci uvc_queue_next_buffer(&stream->queue, buf); 15178c2ecf20Sopenharmony_ci stream->last_fid ^= UVC_STREAM_FID; 15188c2ecf20Sopenharmony_ci } 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci stream->bulk.header_size = 0; 15218c2ecf20Sopenharmony_ci stream->bulk.payload_size = 0; 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci urb->transfer_buffer_length = stream->urb_size - len; 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_cistatic void uvc_video_complete(struct urb *urb) 15288c2ecf20Sopenharmony_ci{ 15298c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb = urb->context; 15308c2ecf20Sopenharmony_ci struct uvc_streaming *stream = uvc_urb->stream; 15318c2ecf20Sopenharmony_ci struct uvc_video_queue *queue = &stream->queue; 15328c2ecf20Sopenharmony_ci struct uvc_video_queue *qmeta = &stream->meta.queue; 15338c2ecf20Sopenharmony_ci struct vb2_queue *vb2_qmeta = stream->meta.vdev.queue; 15348c2ecf20Sopenharmony_ci struct uvc_buffer *buf = NULL; 15358c2ecf20Sopenharmony_ci struct uvc_buffer *buf_meta = NULL; 15368c2ecf20Sopenharmony_ci unsigned long flags; 15378c2ecf20Sopenharmony_ci int ret; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci switch (urb->status) { 15408c2ecf20Sopenharmony_ci case 0: 15418c2ecf20Sopenharmony_ci break; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci default: 15448c2ecf20Sopenharmony_ci uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " 15458c2ecf20Sopenharmony_ci "completion handler.\n", urb->status); 15468c2ecf20Sopenharmony_ci fallthrough; 15478c2ecf20Sopenharmony_ci case -ENOENT: /* usb_poison_urb() called. */ 15488c2ecf20Sopenharmony_ci if (stream->frozen) 15498c2ecf20Sopenharmony_ci return; 15508c2ecf20Sopenharmony_ci fallthrough; 15518c2ecf20Sopenharmony_ci case -ECONNRESET: /* usb_unlink_urb() called. */ 15528c2ecf20Sopenharmony_ci case -ESHUTDOWN: /* The endpoint is being disabled. */ 15538c2ecf20Sopenharmony_ci uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); 15548c2ecf20Sopenharmony_ci if (vb2_qmeta) 15558c2ecf20Sopenharmony_ci uvc_queue_cancel(qmeta, urb->status == -ESHUTDOWN); 15568c2ecf20Sopenharmony_ci return; 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci buf = uvc_queue_get_current_buffer(queue); 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci if (vb2_qmeta) { 15628c2ecf20Sopenharmony_ci spin_lock_irqsave(&qmeta->irqlock, flags); 15638c2ecf20Sopenharmony_ci if (!list_empty(&qmeta->irqqueue)) 15648c2ecf20Sopenharmony_ci buf_meta = list_first_entry(&qmeta->irqqueue, 15658c2ecf20Sopenharmony_ci struct uvc_buffer, queue); 15668c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qmeta->irqlock, flags); 15678c2ecf20Sopenharmony_ci } 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci /* Re-initialise the URB async work. */ 15708c2ecf20Sopenharmony_ci uvc_urb->async_operations = 0; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci /* 15738c2ecf20Sopenharmony_ci * Process the URB headers, and optionally queue expensive memcpy tasks 15748c2ecf20Sopenharmony_ci * to be deferred to a work queue. 15758c2ecf20Sopenharmony_ci */ 15768c2ecf20Sopenharmony_ci stream->decode(uvc_urb, buf, buf_meta); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* If no async work is needed, resubmit the URB immediately. */ 15798c2ecf20Sopenharmony_ci if (!uvc_urb->async_operations) { 15808c2ecf20Sopenharmony_ci ret = usb_submit_urb(uvc_urb->urb, GFP_ATOMIC); 15818c2ecf20Sopenharmony_ci if (ret < 0) 15828c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, 15838c2ecf20Sopenharmony_ci "Failed to resubmit video URB (%d).\n", 15848c2ecf20Sopenharmony_ci ret); 15858c2ecf20Sopenharmony_ci return; 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci queue_work(stream->async_wq, &uvc_urb->work); 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci/* 15928c2ecf20Sopenharmony_ci * Free transfer buffers. 15938c2ecf20Sopenharmony_ci */ 15948c2ecf20Sopenharmony_cistatic void uvc_free_urb_buffers(struct uvc_streaming *stream) 15958c2ecf20Sopenharmony_ci{ 15968c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) { 15998c2ecf20Sopenharmony_ci if (!uvc_urb->buffer) 16008c2ecf20Sopenharmony_ci continue; 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 16038c2ecf20Sopenharmony_ci usb_free_coherent(stream->dev->udev, stream->urb_size, 16048c2ecf20Sopenharmony_ci uvc_urb->buffer, uvc_urb->dma); 16058c2ecf20Sopenharmony_ci#else 16068c2ecf20Sopenharmony_ci kfree(uvc_urb->buffer); 16078c2ecf20Sopenharmony_ci#endif 16088c2ecf20Sopenharmony_ci uvc_urb->buffer = NULL; 16098c2ecf20Sopenharmony_ci } 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci stream->urb_size = 0; 16128c2ecf20Sopenharmony_ci} 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci/* 16158c2ecf20Sopenharmony_ci * Allocate transfer buffers. This function can be called with buffers 16168c2ecf20Sopenharmony_ci * already allocated when resuming from suspend, in which case it will 16178c2ecf20Sopenharmony_ci * return without touching the buffers. 16188c2ecf20Sopenharmony_ci * 16198c2ecf20Sopenharmony_ci * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the 16208c2ecf20Sopenharmony_ci * system is too low on memory try successively smaller numbers of packets 16218c2ecf20Sopenharmony_ci * until allocation succeeds. 16228c2ecf20Sopenharmony_ci * 16238c2ecf20Sopenharmony_ci * Return the number of allocated packets on success or 0 when out of memory. 16248c2ecf20Sopenharmony_ci */ 16258c2ecf20Sopenharmony_cistatic int uvc_alloc_urb_buffers(struct uvc_streaming *stream, 16268c2ecf20Sopenharmony_ci unsigned int size, unsigned int psize, gfp_t gfp_flags) 16278c2ecf20Sopenharmony_ci{ 16288c2ecf20Sopenharmony_ci unsigned int npackets; 16298c2ecf20Sopenharmony_ci unsigned int i; 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci /* Buffers are already allocated, bail out. */ 16328c2ecf20Sopenharmony_ci if (stream->urb_size) 16338c2ecf20Sopenharmony_ci return stream->urb_size / psize; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci /* Compute the number of packets. Bulk endpoints might transfer UVC 16368c2ecf20Sopenharmony_ci * payloads across multiple URBs. 16378c2ecf20Sopenharmony_ci */ 16388c2ecf20Sopenharmony_ci npackets = DIV_ROUND_UP(size, psize); 16398c2ecf20Sopenharmony_ci if (npackets > UVC_MAX_PACKETS) 16408c2ecf20Sopenharmony_ci npackets = UVC_MAX_PACKETS; 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* Retry allocations until one succeed. */ 16438c2ecf20Sopenharmony_ci for (; npackets > 1; npackets /= 2) { 16448c2ecf20Sopenharmony_ci for (i = 0; i < UVC_URBS; ++i) { 16458c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci stream->urb_size = psize * npackets; 16488c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 16498c2ecf20Sopenharmony_ci uvc_urb->buffer = usb_alloc_coherent( 16508c2ecf20Sopenharmony_ci stream->dev->udev, stream->urb_size, 16518c2ecf20Sopenharmony_ci gfp_flags | __GFP_NOWARN, &uvc_urb->dma); 16528c2ecf20Sopenharmony_ci#else 16538c2ecf20Sopenharmony_ci uvc_urb->buffer = 16548c2ecf20Sopenharmony_ci kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN); 16558c2ecf20Sopenharmony_ci#endif 16568c2ecf20Sopenharmony_ci if (!uvc_urb->buffer) { 16578c2ecf20Sopenharmony_ci uvc_free_urb_buffers(stream); 16588c2ecf20Sopenharmony_ci break; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci uvc_urb->stream = stream; 16628c2ecf20Sopenharmony_ci } 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci if (i == UVC_URBS) { 16658c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " 16668c2ecf20Sopenharmony_ci "of %ux%u bytes each.\n", UVC_URBS, npackets, 16678c2ecf20Sopenharmony_ci psize); 16688c2ecf20Sopenharmony_ci return npackets; 16698c2ecf20Sopenharmony_ci } 16708c2ecf20Sopenharmony_ci } 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes " 16738c2ecf20Sopenharmony_ci "per packet).\n", psize); 16748c2ecf20Sopenharmony_ci return 0; 16758c2ecf20Sopenharmony_ci} 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci/* 16788c2ecf20Sopenharmony_ci * Uninitialize isochronous/bulk URBs and free transfer buffers. 16798c2ecf20Sopenharmony_ci */ 16808c2ecf20Sopenharmony_cistatic void uvc_video_stop_transfer(struct uvc_streaming *stream, 16818c2ecf20Sopenharmony_ci int free_buffers) 16828c2ecf20Sopenharmony_ci{ 16838c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci uvc_video_stats_stop(stream); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci /* 16888c2ecf20Sopenharmony_ci * We must poison the URBs rather than kill them to ensure that even 16898c2ecf20Sopenharmony_ci * after the completion handler returns, any asynchronous workqueues 16908c2ecf20Sopenharmony_ci * will be prevented from resubmitting the URBs. 16918c2ecf20Sopenharmony_ci */ 16928c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) 16938c2ecf20Sopenharmony_ci usb_poison_urb(uvc_urb->urb); 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci flush_workqueue(stream->async_wq); 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) { 16988c2ecf20Sopenharmony_ci usb_free_urb(uvc_urb->urb); 16998c2ecf20Sopenharmony_ci uvc_urb->urb = NULL; 17008c2ecf20Sopenharmony_ci } 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci if (free_buffers) 17038c2ecf20Sopenharmony_ci uvc_free_urb_buffers(stream); 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci/* 17078c2ecf20Sopenharmony_ci * Compute the maximum number of bytes per interval for an endpoint. 17088c2ecf20Sopenharmony_ci */ 17098c2ecf20Sopenharmony_cistatic unsigned int uvc_endpoint_max_bpi(struct usb_device *dev, 17108c2ecf20Sopenharmony_ci struct usb_host_endpoint *ep) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci u16 psize; 17138c2ecf20Sopenharmony_ci u16 mult; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci switch (dev->speed) { 17168c2ecf20Sopenharmony_ci case USB_SPEED_SUPER: 17178c2ecf20Sopenharmony_ci case USB_SPEED_SUPER_PLUS: 17188c2ecf20Sopenharmony_ci return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); 17198c2ecf20Sopenharmony_ci case USB_SPEED_HIGH: 17208c2ecf20Sopenharmony_ci psize = usb_endpoint_maxp(&ep->desc); 17218c2ecf20Sopenharmony_ci mult = usb_endpoint_maxp_mult(&ep->desc); 17228c2ecf20Sopenharmony_ci return psize * mult; 17238c2ecf20Sopenharmony_ci case USB_SPEED_WIRELESS: 17248c2ecf20Sopenharmony_ci psize = usb_endpoint_maxp(&ep->desc); 17258c2ecf20Sopenharmony_ci return psize; 17268c2ecf20Sopenharmony_ci default: 17278c2ecf20Sopenharmony_ci psize = usb_endpoint_maxp(&ep->desc); 17288c2ecf20Sopenharmony_ci return psize; 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci/* 17338c2ecf20Sopenharmony_ci * Initialize isochronous URBs and allocate transfer buffers. The packet size 17348c2ecf20Sopenharmony_ci * is given by the endpoint. 17358c2ecf20Sopenharmony_ci */ 17368c2ecf20Sopenharmony_cistatic int uvc_init_video_isoc(struct uvc_streaming *stream, 17378c2ecf20Sopenharmony_ci struct usb_host_endpoint *ep, gfp_t gfp_flags) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci struct urb *urb; 17408c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 17418c2ecf20Sopenharmony_ci unsigned int npackets, i; 17428c2ecf20Sopenharmony_ci u16 psize; 17438c2ecf20Sopenharmony_ci u32 size; 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); 17468c2ecf20Sopenharmony_ci size = stream->ctrl.dwMaxVideoFrameSize; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); 17498c2ecf20Sopenharmony_ci if (npackets == 0) 17508c2ecf20Sopenharmony_ci return -ENOMEM; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci size = npackets * psize; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) { 17558c2ecf20Sopenharmony_ci urb = usb_alloc_urb(npackets, gfp_flags); 17568c2ecf20Sopenharmony_ci if (urb == NULL) { 17578c2ecf20Sopenharmony_ci uvc_video_stop_transfer(stream, 1); 17588c2ecf20Sopenharmony_ci return -ENOMEM; 17598c2ecf20Sopenharmony_ci } 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci urb->dev = stream->dev->udev; 17628c2ecf20Sopenharmony_ci urb->context = uvc_urb; 17638c2ecf20Sopenharmony_ci urb->pipe = usb_rcvisocpipe(stream->dev->udev, 17648c2ecf20Sopenharmony_ci ep->desc.bEndpointAddress); 17658c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 17668c2ecf20Sopenharmony_ci urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 17678c2ecf20Sopenharmony_ci urb->transfer_dma = uvc_urb->dma; 17688c2ecf20Sopenharmony_ci#else 17698c2ecf20Sopenharmony_ci urb->transfer_flags = URB_ISO_ASAP; 17708c2ecf20Sopenharmony_ci#endif 17718c2ecf20Sopenharmony_ci urb->interval = ep->desc.bInterval; 17728c2ecf20Sopenharmony_ci urb->transfer_buffer = uvc_urb->buffer; 17738c2ecf20Sopenharmony_ci urb->complete = uvc_video_complete; 17748c2ecf20Sopenharmony_ci urb->number_of_packets = npackets; 17758c2ecf20Sopenharmony_ci urb->transfer_buffer_length = size; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci for (i = 0; i < npackets; ++i) { 17788c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].offset = i * psize; 17798c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].length = psize; 17808c2ecf20Sopenharmony_ci } 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci uvc_urb->urb = urb; 17838c2ecf20Sopenharmony_ci } 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci return 0; 17868c2ecf20Sopenharmony_ci} 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci/* 17898c2ecf20Sopenharmony_ci * Initialize bulk URBs and allocate transfer buffers. The packet size is 17908c2ecf20Sopenharmony_ci * given by the endpoint. 17918c2ecf20Sopenharmony_ci */ 17928c2ecf20Sopenharmony_cistatic int uvc_init_video_bulk(struct uvc_streaming *stream, 17938c2ecf20Sopenharmony_ci struct usb_host_endpoint *ep, gfp_t gfp_flags) 17948c2ecf20Sopenharmony_ci{ 17958c2ecf20Sopenharmony_ci struct urb *urb; 17968c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 17978c2ecf20Sopenharmony_ci unsigned int npackets, pipe; 17988c2ecf20Sopenharmony_ci u16 psize; 17998c2ecf20Sopenharmony_ci u32 size; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci psize = usb_endpoint_maxp(&ep->desc); 18028c2ecf20Sopenharmony_ci size = stream->ctrl.dwMaxPayloadTransferSize; 18038c2ecf20Sopenharmony_ci stream->bulk.max_payload_size = size; 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); 18068c2ecf20Sopenharmony_ci if (npackets == 0) 18078c2ecf20Sopenharmony_ci return -ENOMEM; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci size = npackets * psize; 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci if (usb_endpoint_dir_in(&ep->desc)) 18128c2ecf20Sopenharmony_ci pipe = usb_rcvbulkpipe(stream->dev->udev, 18138c2ecf20Sopenharmony_ci ep->desc.bEndpointAddress); 18148c2ecf20Sopenharmony_ci else 18158c2ecf20Sopenharmony_ci pipe = usb_sndbulkpipe(stream->dev->udev, 18168c2ecf20Sopenharmony_ci ep->desc.bEndpointAddress); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 18198c2ecf20Sopenharmony_ci size = 0; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) { 18228c2ecf20Sopenharmony_ci urb = usb_alloc_urb(0, gfp_flags); 18238c2ecf20Sopenharmony_ci if (urb == NULL) { 18248c2ecf20Sopenharmony_ci uvc_video_stop_transfer(stream, 1); 18258c2ecf20Sopenharmony_ci return -ENOMEM; 18268c2ecf20Sopenharmony_ci } 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci usb_fill_bulk_urb(urb, stream->dev->udev, pipe, uvc_urb->buffer, 18298c2ecf20Sopenharmony_ci size, uvc_video_complete, uvc_urb); 18308c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 18318c2ecf20Sopenharmony_ci urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 18328c2ecf20Sopenharmony_ci urb->transfer_dma = uvc_urb->dma; 18338c2ecf20Sopenharmony_ci#endif 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci uvc_urb->urb = urb; 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci return 0; 18398c2ecf20Sopenharmony_ci} 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci/* 18428c2ecf20Sopenharmony_ci * Initialize isochronous/bulk URBs and allocate transfer buffers. 18438c2ecf20Sopenharmony_ci */ 18448c2ecf20Sopenharmony_cistatic int uvc_video_start_transfer(struct uvc_streaming *stream, 18458c2ecf20Sopenharmony_ci gfp_t gfp_flags) 18468c2ecf20Sopenharmony_ci{ 18478c2ecf20Sopenharmony_ci struct usb_interface *intf = stream->intf; 18488c2ecf20Sopenharmony_ci struct usb_host_endpoint *ep; 18498c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 18508c2ecf20Sopenharmony_ci unsigned int i; 18518c2ecf20Sopenharmony_ci int ret; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci stream->sequence = -1; 18548c2ecf20Sopenharmony_ci stream->last_fid = -1; 18558c2ecf20Sopenharmony_ci stream->bulk.header_size = 0; 18568c2ecf20Sopenharmony_ci stream->bulk.skip_payload = 0; 18578c2ecf20Sopenharmony_ci stream->bulk.payload_size = 0; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci uvc_video_stats_start(stream); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (intf->num_altsetting > 1) { 18628c2ecf20Sopenharmony_ci struct usb_host_endpoint *best_ep = NULL; 18638c2ecf20Sopenharmony_ci unsigned int best_psize = UINT_MAX; 18648c2ecf20Sopenharmony_ci unsigned int bandwidth; 18658c2ecf20Sopenharmony_ci unsigned int altsetting; 18668c2ecf20Sopenharmony_ci int intfnum = stream->intfnum; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci /* Isochronous endpoint, select the alternate setting. */ 18698c2ecf20Sopenharmony_ci bandwidth = stream->ctrl.dwMaxPayloadTransferSize; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci if (bandwidth == 0) { 18728c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "Device requested null " 18738c2ecf20Sopenharmony_ci "bandwidth, defaulting to lowest.\n"); 18748c2ecf20Sopenharmony_ci bandwidth = 1; 18758c2ecf20Sopenharmony_ci } else { 18768c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "Device requested %u " 18778c2ecf20Sopenharmony_ci "B/frame bandwidth.\n", bandwidth); 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci for (i = 0; i < intf->num_altsetting; ++i) { 18818c2ecf20Sopenharmony_ci struct usb_host_interface *alts; 18828c2ecf20Sopenharmony_ci unsigned int psize; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci alts = &intf->altsetting[i]; 18858c2ecf20Sopenharmony_ci ep = uvc_find_endpoint(alts, 18868c2ecf20Sopenharmony_ci stream->header.bEndpointAddress); 18878c2ecf20Sopenharmony_ci if (ep == NULL) 18888c2ecf20Sopenharmony_ci continue; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci /* Check if the bandwidth is high enough. */ 18918c2ecf20Sopenharmony_ci psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); 18928c2ecf20Sopenharmony_ci if (psize >= bandwidth && psize <= best_psize) { 18938c2ecf20Sopenharmony_ci altsetting = alts->desc.bAlternateSetting; 18948c2ecf20Sopenharmony_ci best_psize = psize; 18958c2ecf20Sopenharmony_ci best_ep = ep; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci if (best_ep == NULL) { 19008c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " 19018c2ecf20Sopenharmony_ci "for requested bandwidth.\n"); 19028c2ecf20Sopenharmony_ci return -EIO; 19038c2ecf20Sopenharmony_ci } 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u " 19068c2ecf20Sopenharmony_ci "(%u B/frame bandwidth).\n", altsetting, best_psize); 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci /* 19098c2ecf20Sopenharmony_ci * Some devices, namely the Logitech C910 and B910, are unable 19108c2ecf20Sopenharmony_ci * to recover from a USB autosuspend, unless the alternate 19118c2ecf20Sopenharmony_ci * setting of the streaming interface is toggled. 19128c2ecf20Sopenharmony_ci */ 19138c2ecf20Sopenharmony_ci if (stream->dev->quirks & UVC_QUIRK_WAKE_AUTOSUSPEND) { 19148c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, intfnum, 19158c2ecf20Sopenharmony_ci altsetting); 19168c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, intfnum, 0); 19178c2ecf20Sopenharmony_ci } 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); 19208c2ecf20Sopenharmony_ci if (ret < 0) 19218c2ecf20Sopenharmony_ci return ret; 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); 19248c2ecf20Sopenharmony_ci } else { 19258c2ecf20Sopenharmony_ci /* Bulk endpoint, proceed to URB initialization. */ 19268c2ecf20Sopenharmony_ci ep = uvc_find_endpoint(&intf->altsetting[0], 19278c2ecf20Sopenharmony_ci stream->header.bEndpointAddress); 19288c2ecf20Sopenharmony_ci if (ep == NULL) 19298c2ecf20Sopenharmony_ci return -EIO; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci /* Reject broken descriptors. */ 19328c2ecf20Sopenharmony_ci if (usb_endpoint_maxp(&ep->desc) == 0) 19338c2ecf20Sopenharmony_ci return -EIO; 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci ret = uvc_init_video_bulk(stream, ep, gfp_flags); 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci if (ret < 0) 19398c2ecf20Sopenharmony_ci return ret; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci /* Submit the URBs. */ 19428c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) { 19438c2ecf20Sopenharmony_ci ret = usb_submit_urb(uvc_urb->urb, gfp_flags); 19448c2ecf20Sopenharmony_ci if (ret < 0) { 19458c2ecf20Sopenharmony_ci uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n", 19468c2ecf20Sopenharmony_ci uvc_urb_index(uvc_urb), ret); 19478c2ecf20Sopenharmony_ci uvc_video_stop_transfer(stream, 1); 19488c2ecf20Sopenharmony_ci return ret; 19498c2ecf20Sopenharmony_ci } 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci /* The Logitech C920 temporarily forgets that it should not be adjusting 19538c2ecf20Sopenharmony_ci * Exposure Absolute during init so restore controls to stored values. 19548c2ecf20Sopenharmony_ci */ 19558c2ecf20Sopenharmony_ci if (stream->dev->quirks & UVC_QUIRK_RESTORE_CTRLS_ON_INIT) 19568c2ecf20Sopenharmony_ci uvc_ctrl_restore_values(stream->dev); 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci return 0; 19598c2ecf20Sopenharmony_ci} 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci/* -------------------------------------------------------------------------- 19628c2ecf20Sopenharmony_ci * Suspend/resume 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci/* 19668c2ecf20Sopenharmony_ci * Stop streaming without disabling the video queue. 19678c2ecf20Sopenharmony_ci * 19688c2ecf20Sopenharmony_ci * To let userspace applications resume without trouble, we must not touch the 19698c2ecf20Sopenharmony_ci * video buffers in any way. We mark the device as frozen to make sure the URB 19708c2ecf20Sopenharmony_ci * completion handler won't try to cancel the queue when we kill the URBs. 19718c2ecf20Sopenharmony_ci */ 19728c2ecf20Sopenharmony_ciint uvc_video_suspend(struct uvc_streaming *stream) 19738c2ecf20Sopenharmony_ci{ 19748c2ecf20Sopenharmony_ci if (!uvc_queue_streaming(&stream->queue)) 19758c2ecf20Sopenharmony_ci return 0; 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci stream->frozen = 1; 19788c2ecf20Sopenharmony_ci uvc_video_stop_transfer(stream, 0); 19798c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, stream->intfnum, 0); 19808c2ecf20Sopenharmony_ci return 0; 19818c2ecf20Sopenharmony_ci} 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci/* 19848c2ecf20Sopenharmony_ci * Reconfigure the video interface and restart streaming if it was enabled 19858c2ecf20Sopenharmony_ci * before suspend. 19868c2ecf20Sopenharmony_ci * 19878c2ecf20Sopenharmony_ci * If an error occurs, disable the video queue. This will wake all pending 19888c2ecf20Sopenharmony_ci * buffers, making sure userspace applications are notified of the problem 19898c2ecf20Sopenharmony_ci * instead of waiting forever. 19908c2ecf20Sopenharmony_ci */ 19918c2ecf20Sopenharmony_ciint uvc_video_resume(struct uvc_streaming *stream, int reset) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci int ret; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci /* If the bus has been reset on resume, set the alternate setting to 0. 19968c2ecf20Sopenharmony_ci * This should be the default value, but some devices crash or otherwise 19978c2ecf20Sopenharmony_ci * misbehave if they don't receive a SET_INTERFACE request before any 19988c2ecf20Sopenharmony_ci * other video control request. 19998c2ecf20Sopenharmony_ci */ 20008c2ecf20Sopenharmony_ci if (reset) 20018c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, stream->intfnum, 0); 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci stream->frozen = 0; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci uvc_video_clock_reset(stream); 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci if (!uvc_queue_streaming(&stream->queue)) 20088c2ecf20Sopenharmony_ci return 0; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci ret = uvc_commit_video(stream, &stream->ctrl); 20118c2ecf20Sopenharmony_ci if (ret < 0) 20128c2ecf20Sopenharmony_ci return ret; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci return uvc_video_start_transfer(stream, GFP_NOIO); 20158c2ecf20Sopenharmony_ci} 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ 20188c2ecf20Sopenharmony_ci * Video device 20198c2ecf20Sopenharmony_ci */ 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci/* 20228c2ecf20Sopenharmony_ci * Initialize the UVC video device by switching to alternate setting 0 and 20238c2ecf20Sopenharmony_ci * retrieve the default format. 20248c2ecf20Sopenharmony_ci * 20258c2ecf20Sopenharmony_ci * Some cameras (namely the Fuji Finepix) set the format and frame 20268c2ecf20Sopenharmony_ci * indexes to zero. The UVC standard doesn't clearly make this a spec 20278c2ecf20Sopenharmony_ci * violation, so try to silently fix the values if possible. 20288c2ecf20Sopenharmony_ci * 20298c2ecf20Sopenharmony_ci * This function is called before registering the device with V4L. 20308c2ecf20Sopenharmony_ci */ 20318c2ecf20Sopenharmony_ciint uvc_video_init(struct uvc_streaming *stream) 20328c2ecf20Sopenharmony_ci{ 20338c2ecf20Sopenharmony_ci struct uvc_streaming_control *probe = &stream->ctrl; 20348c2ecf20Sopenharmony_ci struct uvc_format *format = NULL; 20358c2ecf20Sopenharmony_ci struct uvc_frame *frame = NULL; 20368c2ecf20Sopenharmony_ci struct uvc_urb *uvc_urb; 20378c2ecf20Sopenharmony_ci unsigned int i; 20388c2ecf20Sopenharmony_ci int ret; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci if (stream->nformats == 0) { 20418c2ecf20Sopenharmony_ci uvc_printk(KERN_INFO, "No supported video formats found.\n"); 20428c2ecf20Sopenharmony_ci return -EINVAL; 20438c2ecf20Sopenharmony_ci } 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci atomic_set(&stream->active, 0); 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci /* Alternate setting 0 should be the default, yet the XBox Live Vision 20488c2ecf20Sopenharmony_ci * Cam (and possibly other devices) crash or otherwise misbehave if 20498c2ecf20Sopenharmony_ci * they don't receive a SET_INTERFACE request before any other video 20508c2ecf20Sopenharmony_ci * control request. 20518c2ecf20Sopenharmony_ci */ 20528c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, stream->intfnum, 0); 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci /* Set the streaming probe control with default streaming parameters 20558c2ecf20Sopenharmony_ci * retrieved from the device. Webcams that don't support GET_DEF 20568c2ecf20Sopenharmony_ci * requests on the probe control will just keep their current streaming 20578c2ecf20Sopenharmony_ci * parameters. 20588c2ecf20Sopenharmony_ci */ 20598c2ecf20Sopenharmony_ci if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) 20608c2ecf20Sopenharmony_ci uvc_set_video_ctrl(stream, probe, 1); 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci /* Initialize the streaming parameters with the probe control current 20638c2ecf20Sopenharmony_ci * value. This makes sure SET_CUR requests on the streaming commit 20648c2ecf20Sopenharmony_ci * control will always use values retrieved from a successful GET_CUR 20658c2ecf20Sopenharmony_ci * request on the probe control, as required by the UVC specification. 20668c2ecf20Sopenharmony_ci */ 20678c2ecf20Sopenharmony_ci ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); 20688c2ecf20Sopenharmony_ci if (ret < 0) 20698c2ecf20Sopenharmony_ci return ret; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci /* Check if the default format descriptor exists. Use the first 20728c2ecf20Sopenharmony_ci * available format otherwise. 20738c2ecf20Sopenharmony_ci */ 20748c2ecf20Sopenharmony_ci for (i = stream->nformats; i > 0; --i) { 20758c2ecf20Sopenharmony_ci format = &stream->format[i-1]; 20768c2ecf20Sopenharmony_ci if (format->index == probe->bFormatIndex) 20778c2ecf20Sopenharmony_ci break; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci if (format->nframes == 0) { 20818c2ecf20Sopenharmony_ci uvc_printk(KERN_INFO, "No frame descriptor found for the " 20828c2ecf20Sopenharmony_ci "default format.\n"); 20838c2ecf20Sopenharmony_ci return -EINVAL; 20848c2ecf20Sopenharmony_ci } 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci /* Zero bFrameIndex might be correct. Stream-based formats (including 20878c2ecf20Sopenharmony_ci * MPEG-2 TS and DV) do not support frames but have a dummy frame 20888c2ecf20Sopenharmony_ci * descriptor with bFrameIndex set to zero. If the default frame 20898c2ecf20Sopenharmony_ci * descriptor is not found, use the first available frame. 20908c2ecf20Sopenharmony_ci */ 20918c2ecf20Sopenharmony_ci for (i = format->nframes; i > 0; --i) { 20928c2ecf20Sopenharmony_ci frame = &format->frame[i-1]; 20938c2ecf20Sopenharmony_ci if (frame->bFrameIndex == probe->bFrameIndex) 20948c2ecf20Sopenharmony_ci break; 20958c2ecf20Sopenharmony_ci } 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci probe->bFormatIndex = format->index; 20988c2ecf20Sopenharmony_ci probe->bFrameIndex = frame->bFrameIndex; 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_ci stream->def_format = format; 21018c2ecf20Sopenharmony_ci stream->cur_format = format; 21028c2ecf20Sopenharmony_ci stream->cur_frame = frame; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci /* Select the video decoding function */ 21058c2ecf20Sopenharmony_ci if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 21068c2ecf20Sopenharmony_ci if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) 21078c2ecf20Sopenharmony_ci stream->decode = uvc_video_decode_isight; 21088c2ecf20Sopenharmony_ci else if (stream->intf->num_altsetting > 1) 21098c2ecf20Sopenharmony_ci stream->decode = uvc_video_decode_isoc; 21108c2ecf20Sopenharmony_ci else 21118c2ecf20Sopenharmony_ci stream->decode = uvc_video_decode_bulk; 21128c2ecf20Sopenharmony_ci } else { 21138c2ecf20Sopenharmony_ci if (stream->intf->num_altsetting == 1) 21148c2ecf20Sopenharmony_ci stream->decode = uvc_video_encode_bulk; 21158c2ecf20Sopenharmony_ci else { 21168c2ecf20Sopenharmony_ci uvc_printk(KERN_INFO, "Isochronous endpoints are not " 21178c2ecf20Sopenharmony_ci "supported for video output devices.\n"); 21188c2ecf20Sopenharmony_ci return -EINVAL; 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci /* Prepare asynchronous work items. */ 21238c2ecf20Sopenharmony_ci for_each_uvc_urb(uvc_urb, stream) 21248c2ecf20Sopenharmony_ci INIT_WORK(&uvc_urb->work, uvc_video_copy_data_work); 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci return 0; 21278c2ecf20Sopenharmony_ci} 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ciint uvc_video_start_streaming(struct uvc_streaming *stream) 21308c2ecf20Sopenharmony_ci{ 21318c2ecf20Sopenharmony_ci int ret; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci ret = uvc_video_clock_init(stream); 21348c2ecf20Sopenharmony_ci if (ret < 0) 21358c2ecf20Sopenharmony_ci return ret; 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci /* Commit the streaming parameters. */ 21388c2ecf20Sopenharmony_ci ret = uvc_commit_video(stream, &stream->ctrl); 21398c2ecf20Sopenharmony_ci if (ret < 0) 21408c2ecf20Sopenharmony_ci goto error_commit; 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci ret = uvc_video_start_transfer(stream, GFP_KERNEL); 21438c2ecf20Sopenharmony_ci if (ret < 0) 21448c2ecf20Sopenharmony_ci goto error_video; 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci return 0; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_cierror_video: 21498c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, stream->intfnum, 0); 21508c2ecf20Sopenharmony_cierror_commit: 21518c2ecf20Sopenharmony_ci uvc_video_clock_cleanup(stream); 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci return ret; 21548c2ecf20Sopenharmony_ci} 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_civoid uvc_video_stop_streaming(struct uvc_streaming *stream) 21578c2ecf20Sopenharmony_ci{ 21588c2ecf20Sopenharmony_ci uvc_video_stop_transfer(stream, 1); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci if (stream->intf->num_altsetting > 1) { 21618c2ecf20Sopenharmony_ci usb_set_interface(stream->dev->udev, stream->intfnum, 0); 21628c2ecf20Sopenharmony_ci } else { 21638c2ecf20Sopenharmony_ci /* UVC doesn't specify how to inform a bulk-based device 21648c2ecf20Sopenharmony_ci * when the video stream is stopped. Windows sends a 21658c2ecf20Sopenharmony_ci * CLEAR_FEATURE(HALT) request to the video streaming 21668c2ecf20Sopenharmony_ci * bulk endpoint, mimic the same behaviour. 21678c2ecf20Sopenharmony_ci */ 21688c2ecf20Sopenharmony_ci unsigned int epnum = stream->header.bEndpointAddress 21698c2ecf20Sopenharmony_ci & USB_ENDPOINT_NUMBER_MASK; 21708c2ecf20Sopenharmony_ci unsigned int dir = stream->header.bEndpointAddress 21718c2ecf20Sopenharmony_ci & USB_ENDPOINT_DIR_MASK; 21728c2ecf20Sopenharmony_ci unsigned int pipe; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir; 21758c2ecf20Sopenharmony_ci usb_clear_halt(stream->dev->udev, pipe); 21768c2ecf20Sopenharmony_ci } 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci uvc_video_clock_cleanup(stream); 21798c2ecf20Sopenharmony_ci} 2180