uvc_driver.c revision 9275b32bced808bd57bdf3884748ed1126ba90e0
1c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      uvc_driver.c  --  USB Video Class driver
3c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
42c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart *      Copyright (C) 2005-2009
5c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *          Laurent Pinchart (laurent.pinchart@skynet.be)
6c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
7c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      This program is free software; you can redistribute it and/or modify
8c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      it under the terms of the GNU General Public License as published by
9c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      the Free Software Foundation; either version 2 of the License, or
10c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      (at your option) any later version.
11c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
13c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
15ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * This driver aims to support video input and ouput devices compliant with the
16ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * 'USB Video Class' specification.
17c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
18c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The driver doesn't support the deprecated v4l1 interface. It implements the
19c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * mmap capture method only, and doesn't do any image format conversion in
20c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * software. If your user-space application doesn't support YUYV or MJPEG, fix
21c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * it :-). Please note that the MJPEG data have been stripped from their
22c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Huffman tables (DHT marker), you will need to add it back if your JPEG
23c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * codec can't handle MJPEG data.
24c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
25c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
26c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/kernel.h>
27c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/list.h>
28c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/module.h>
295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
30c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb.h>
31c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/videodev2.h>
32c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/vmalloc.h>
33c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/wait.h>
34c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <asm/atomic.h>
359bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich#include <asm/unaligned.h>
36c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
37c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <media/v4l2-common.h>
38c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
39c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include "uvcvideo.h"
40c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
41c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_AUTHOR		"Laurent Pinchart <laurent.pinchart@skynet.be>"
42c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_DESC		"USB Video Class driver"
43c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#ifndef DRIVER_VERSION
44c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_VERSION		"v0.1.0"
45c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#endif
46c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
47310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartunsigned int uvc_clock_param = CLOCK_MONOTONIC;
480fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent Pinchartunsigned int uvc_no_drop_param;
4973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchartstatic unsigned int uvc_quirks_param = -1;
50c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartunsigned int uvc_trace_param;
51b232a012adfea9f535702e8296ea6b76e691f436Laurent Pinchartunsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
52c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
53c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
542c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * Video formats
55c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
56c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
57c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc uvc_fmts[] = {
58c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
59c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (YUYV)",
60c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YUY2,
61c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUYV,
62c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
63c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
6468f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.name		= "YUV 4:2:2 (YUYV)",
6568f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.guid		= UVC_GUID_FORMAT_YUY2_ISIGHT,
6668f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.fcc		= V4L2_PIX_FMT_YUYV,
6768f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	},
6868f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	{
69c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (NV12)",
70c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_NV12,
71c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_NV12,
72c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
73c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
74c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "MJPEG",
75c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_MJPEG,
76c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_MJPEG,
77c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
78c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
79c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YVU 4:2:0 (YV12)",
80c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YV12,
81c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YVU420,
82c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
83c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
84c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (I420)",
85c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_I420,
86c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUV420,
87c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
88c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
89c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (UYVY)",
90c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_UYVY,
91c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_UYVY,
92c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
93c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
9461421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.name		= "Greyscale (8-bit)",
95c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y800,
96c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_GREY,
97c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
98c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
9961421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.name		= "Greyscale (16-bit)",
10061421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y16,
10161421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.fcc		= V4L2_PIX_FMT_Y16,
10261421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart	},
10361421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart	{
104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "RGB Bayer",
105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_BY8,
106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_SBGGR8,
107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Utility functions
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		__u8 epaddr)
116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep;
118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = &alts->endpoint[i];
122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep->desc.bEndpointAddress == epaddr)
123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ep;
124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int len = ARRAY_SIZE(uvc_fmts);
132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < len; ++i) {
135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return &uvc_fmts[i];
137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic __u32 uvc_colorspace(const __u8 primaries)
143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	static const __u8 colorprimaries[] = {
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		0,
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SRGB,
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_M,
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_BG,
149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE170M,
150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE240M,
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	};
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (primaries < ARRAY_SIZE(colorprimaries))
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return colorprimaries[primaries];
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Simplify a fraction using a simple continued fraction decomposition. The
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * idea here is to convert fractions such as 333333/10000000 to 1/30 using
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arbitrary parameters to remove non-significative terms from the simple
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * respectively seems to give nice results.
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unsigned int n_terms, unsigned int threshold)
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t *an;
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t x, y, r;
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (an == NULL)
175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Convert the fraction to a simple continued fraction. See
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * http://mathforum.org/dr.math/faq/faq.fractions.html
179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * Stop if the current term is bigger than or equal to the given
180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * threshold.
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = *numerator;
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = *denominator;
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (n = 0; n < n_terms && y != 0; ++n) {
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		an[n] = x / y;
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (an[n] >= threshold) {
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (n < 2)
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				n++;
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = x - an[n] * y;
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = y;
195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = r;
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Expand the simple continued fraction back to an integer fraction. */
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = 0;
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = 1;
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = n; i > 0; --i) {
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = y;
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = an[i-1] * y + x;
205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = r;
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*numerator = y;
209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*denominator = x;
210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(an);
211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to compute numerator / denominator * 10000000 using 32 bit fixed point
215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arithmetic only.
216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartuint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t multiplier;
220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Saturate the result if the operation would overflow. */
222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (denominator == 0 ||
223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    numerator/denominator >= ((uint32_t)-1)/10000000)
224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return (uint32_t)-1;
225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Divide both the denominator and the multiplier by two until
227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * numerator * multiplier doesn't overflow. If anyone knows a better
228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * algorithm please let me know.
229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	multiplier = 10000000;
231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (numerator > ((uint32_t)-1)/multiplier) {
232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		multiplier /= 2;
233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		denominator /= 2;
234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return denominator ? numerator * multiplier / denominator : 0;
237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Terminal and unit management
241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity;
246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(entity, &dev->entities, list) {
248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->id == id)
249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return entity;
250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id, struct uvc_entity *entity)
257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (entity == NULL)
261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(&dev->entities, struct uvc_entity, list);
262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry_continue(entity, &dev->entities, list) {
2648ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i)
2658ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (entity->baSourceID[i] == id)
266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
2738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
2748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
2758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
2778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->header.bTerminalLink == id)
2788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return stream;
2798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
2808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return NULL;
2828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
2838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
2858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Descriptors parsing
286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_format(struct uvc_device *dev,
289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming, struct uvc_format *format,
290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 **intervals, unsigned char *buffer, int buflen)
291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf = streaming->intf;
293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = intf->cur_altsetting;
294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format_desc *fmtdesc;
295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *start = buffer;
297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int interval;
298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u8 ftype;
300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->type = buffer[2];
302c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->index = buffer[3];
303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
305b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_UNCOMPRESSED:
306b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_FRAME_BASED:
307b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
308233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		if (buflen < n) {
309b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
310c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
311c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
312c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
313c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
314c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
315c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
316c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Find the format descriptor from its GUID. */
317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		fmtdesc = uvc_format_by_guid(&buffer[5]);
318c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
319c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (fmtdesc != NULL) {
320d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, fmtdesc->name,
321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				sizeof format->name);
322c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = fmtdesc->fcc;
323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
32436bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
32536bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
32636bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			snprintf(format->name, sizeof(format->name), "%pUl\n",
32736bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = 0;
329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = buffer[21];
332b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
333b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_UNCOMPRESSED;
334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
335b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_FRAME_BASED;
336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (buffer[27])
337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				format->flags = UVC_FMT_FLAG_COMPRESSED;
338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
341b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MJPEG:
342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 11) {
343b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
349c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
350d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(format->name, "MJPEG", sizeof format->name);
351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_MJPEG;
352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED;
353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
354b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		ftype = UVC_VS_FRAME_MJPEG;
355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
357b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_DV:
358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
359b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[8] & 0x7f) {
367c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 0:
368d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SD-DV", sizeof format->name);
369c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
370c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 1:
371d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SDL-DV", sizeof format->name);
372c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 2:
374d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "HD-DV", sizeof format->name);
375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
377b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d: unknown DV format %u\n",
379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber, buffer[8]);
381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
384d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sizeof format->name);
386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_DV;
388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = 0;
391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Create a dummy frame descriptor. */
393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame = &format->frame[0];
394c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&format->frame[0], 0, sizeof format->frame[0]);
395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIntervalType = 1;
396c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval = 1;
397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		*(*intervals)++ = 1;
399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->nframes = 1;
400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
401c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
402b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MPEG2TS:
403b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_STREAM_BASED:
404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Not supported yet. */
405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
406b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       "interface %d unsupported format %u\n",
408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       dev->udev->devnum, alts->desc.bInterfaceNumber,
409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       buffer[2]);
410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
411c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
414c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
419c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * based formats have frame descriptors.
420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
421c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
422c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	       buffer[2] == ftype) {
423078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		frame = &format->frame[format->nframes];
424b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED)
425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 25 ? buffer[25] : 0;
426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 21 ? buffer[21] : 0;
428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = n ? n : 3;
430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 26 + 4*n) {
432b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FRAME error\n", dev->udev->devnum,
434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
437c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIndex = buffer[3];
439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bmCapabilities = buffer[4];
4409bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wWidth = get_unaligned_le16(&buffer[5]);
4419bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wHeight = get_unaligned_le16(&buffer[7]);
4429bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
4439bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
444b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED) {
445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize =
4469bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4489bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[21]);
449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[25];
450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = 0;
452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4539bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[21];
455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
457c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
458c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
459c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * completely. Observed behaviours range from setting the
4602c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * value to 1.1x the actual frame size to hardwiring the
461c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 16 low bits to 0. This results in a higher than necessary
462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * memory usage as well as a wrong image size information. For
463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * uncompressed formats this can be fixed by computing the
464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * value from the frame size.
465c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
466c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = format->bpp
468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				* frame->wWidth * frame->wHeight / 8;
469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
470c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Some bogus devices report dwMinFrameInterval equal to
471c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * dwMaxFrameInterval and have dwFrameIntervalStep set to
472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * zero. Setting all null intervals to 1 fixes the problem and
4732c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * some other divisions by zero that could happen.
474c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
4769bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			interval = get_unaligned_le32(&buffer[26+4*i]);
477c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			*(*intervals)++ = interval ? interval : 1;
478c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
479c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
480c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure that the default frame interval stays between
481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * the boundaries.
482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n -= frame->bFrameIntervalType ? 1 : 2;
484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval =
485c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			min(frame->dwFrameInterval[n],
486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    max(frame->dwFrameInterval[0],
487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				frame->dwDefaultFrameInterval));
488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
490c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->wWidth, frame->wHeight,
491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			10000000/frame->dwDefaultFrameInterval,
492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			(100000000/frame->dwDefaultFrameInterval)%10);
493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
494078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		format->nframes++;
495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
499c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
500c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
505c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
506c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_COLORFORMAT) {
507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 6) {
508b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d COLORFORMAT error\n",
510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->colorspace = uvc_colorspace(buffer[3]);
516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return buffer - start;
522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_streaming(struct uvc_device *dev,
525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf)
526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming = NULL;
528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format *format;
529c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = &intf->altsetting[0];
531c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *_buffer, *buffer = alts->extra;
532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int _buflen, buflen = alts->extralen;
533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int nformats = 0, nframes = 0, nintervals = 0;
534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int size, i, n, p;
535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 *interval;
536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 psize;
537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret = -EINVAL;
538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass
540b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		!= UVC_SC_VIDEOSTREAMING) {
541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"video streaming interface\n", dev->udev->devnum,
543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"claimed\n", dev->udev->devnum,
550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (streaming == NULL) {
556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver, intf);
557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&streaming->mutex);
56135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	streaming->dev = dev;
562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intf = usb_get_intf(intf);
563c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* The Pico iMage webcam has its class-specific interface descriptors
566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * after the endpoint descriptors.
567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen == 0) {
569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			struct usb_host_endpoint *ep = &alts->endpoint[i];
571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen == 0)
573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen > 2 &&
576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    ep->extra[1] == USB_DT_CS_INTERFACE) {
577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "trying extra data "
578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"from endpoint %u.\n", i);
579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer = alts->endpoint[i].extra;
580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buflen = alts->endpoint[i].extralen;
581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Skip the standard interface descriptors. */
587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
590c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
591c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen <= 2) {
593c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
594c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"interface descriptors found.\n");
595c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
596c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
597c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
598c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the header descriptor. */
599ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	switch (buffer[2]) {
600b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_OUTPUT_HEADER:
601ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
602ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 9;
603ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
604ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
605b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_INPUT_HEADER:
606ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
607ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 13;
608ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
609ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
610ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	default:
611c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
612ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"%d HEADER descriptor not found.\n", dev->udev->devnum,
613ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			alts->desc.bInterfaceNumber);
614c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
615ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
616c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
617ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	p = buflen >= 4 ? buffer[3] : 0;
618ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	n = buflen >= size ? buffer[size-1] : 0;
619ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
620ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buflen < size + p*n) {
621ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
622ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"interface %d HEADER descriptor is invalid.\n",
623ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
624ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		goto error;
625ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
626c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
627ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bNumFormats = p;
628ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bEndpointAddress = buffer[6];
629b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (buffer[2] == UVC_VS_INPUT_HEADER) {
630c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bmInfo = buffer[7];
631c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTerminalLink = buffer[8];
632c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bStillCaptureMethod = buffer[9];
633c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerSupport = buffer[10];
634c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerUsage = buffer[11];
635c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
636ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->header.bTerminalLink = buffer[7];
637ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
638ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bControlSize = n;
639ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
6400b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall	streaming->header.bmaControls = kmemdup(&buffer[size], p * n,
6410b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall						GFP_KERNEL);
642ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (streaming->header.bmaControls == NULL) {
643ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		ret = -ENOMEM;
644c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
645c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
646c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
647c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
648c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
649c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
650c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buffer = buffer;
651c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buflen = buflen;
652c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
653c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Count the format and frame descriptors. */
654042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
655c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (_buffer[2]) {
656b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
657b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
658b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
659c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
660c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
661c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
662b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
663c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			/* DV format has no frame descriptor. We will create a
664c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 * dummy frame descriptor with a dummy frame interval.
665c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 */
666c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
667c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
668c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nintervals++;
669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
670c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
671b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MPEG2TS:
672b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_STREAM_BASED:
673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
674c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d FORMAT %u is not supported.\n",
675c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->udev->devnum,
676c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, _buffer[2]);
677c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
679b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_UNCOMPRESSED:
680b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_MJPEG:
681c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
682c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 25)
683c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[25] ? _buffer[25] : 3;
684c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
685c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
686b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_FRAME_BASED:
687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 21)
689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[21] ? _buffer[21] : 3;
690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buflen -= _buffer[0];
694c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buffer += _buffer[0];
695c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
697c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (nformats == 0) {
698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
699c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"%d has no supported formats defined.\n",
700c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
701c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
702c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
703c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	size = nformats * sizeof *format + nframes * sizeof *frame
705c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	     + nintervals * sizeof *interval;
706c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format = kzalloc(size, GFP_KERNEL);
707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (format == NULL) {
708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ret = -ENOMEM;
709c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	frame = (struct uvc_frame *)&format[nformats];
713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = (__u32 *)&frame[nframes];
714c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
715c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->format = format;
716c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->nformats = nformats;
717c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
718c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the format descriptors. */
719042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
720c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[2]) {
721b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
722b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
723b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
724b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->frame = frame;
726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret = uvc_parse_format(dev, streaming, format,
727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				&interval, buffer, buflen);
728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ret < 0)
729c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				goto error;
730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame += format->nframes;
732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format++;
733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buflen -= ret;
735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buffer += ret;
736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
742c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
746c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen)
747c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
748c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			"%d has %u bytes of trailing descriptor garbage.\n",
749c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
750c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart
751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the alternate settings to find the maximum bandwidth. */
752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < intf->num_altsetting; ++i) {
753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep;
754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		alts = &intf->altsetting[i];
755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = uvc_find_endpoint(alts,
756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				streaming->header.bEndpointAddress);
757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep == NULL)
758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = le16_to_cpu(ep->desc.wMaxPacketSize);
761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (psize > streaming->maxpsize)
763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->maxpsize = psize;
764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
76635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_add_tail(&streaming->list, &dev->streams);
767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_driver_release_interface(&uvc_driver.driver, intf);
771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(intf);
772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->format);
773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->header.bmaControls);
774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming);
775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
7788ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchartstatic struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
7798ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unsigned int num_pads, unsigned int extra_size)
7808ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart{
7818ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	struct uvc_entity *entity;
7828ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int num_inputs;
7838ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int size;
7848ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7858ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
7868ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	size = sizeof(*entity) + extra_size + num_inputs;
7878ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity = kzalloc(size, GFP_KERNEL);
7888ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	if (entity == NULL)
7898ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		return NULL;
7908ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7918ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->id = id;
7928ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->type = type;
7938ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7948ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->bNrInPins = num_inputs;
7958ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size;
7968ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7978ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	return entity;
7988ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart}
7998ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Parse vendor-specific extensions. */
801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_vendor_control(struct uvc_device *dev,
802c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
805c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit;
807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int n, p;
808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int handled = 0;
809c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0x046d:		/* Logitech */
812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[1] != 0x41 || buffer[2] != 0x01)
813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Logitech implements several vendor specific functions
816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * through vendor specific extension units (LXU).
817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * The LXU descriptors are similar to XU descriptors
819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * (see "USB Device Video Class for Video Devices", section
820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 3.7.2.6 "Extension Unit Descriptor") with the following
821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * differences:
822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 0		bLength		1	 Number
825c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Size of this descriptor, in bytes: 24+p+n*2
826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n	bmControlsType	N	Bitmap
828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	Individual bits in the set are defined:
829c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	0: Absolute
830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	1: Relative
831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	This bitset is mapped exactly the same as bmControls.
833c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
834c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n*2	bReserved	1	Boolean
835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 24+p+n*2	iExtension	1	Index
837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Index of a string descriptor that describes this
838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	extension unit.
839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 25 + p ? buffer[22+p] : 0;
843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 25 + p + 2*n) {
845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8518ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
8528ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					p + 1, 2*n);
853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
856c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
8588ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
8608ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
8618ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
8628ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					       + n;
863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[24+p+2*n] != 0)
866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[24+p+2*n], unit->name,
867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		handled = 1;
873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return handled;
877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_standard_control(struct uvc_device *dev,
880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit, *term;
884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf;
885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
886c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n, p, len;
887c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 type;
888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
890b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_HEADER:
891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 12 ? buffer[11] : 0;
892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 12 || buflen < 12 + n) {
894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d HEADER error\n", udev->devnum,
896c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber);
897c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9009bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->uvc_version = get_unaligned_le16(&buffer[3]);
9019bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->clock_frequency = get_unaligned_le32(&buffer[7]);
902c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
903c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Parse all USB Video Streaming interfaces. */
904c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf = usb_ifnum_to_if(udev, buffer[12+i]);
906c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (intf == NULL) {
907c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "device %d "
908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"interface %d doesn't exists\n",
909c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					udev->devnum, i);
910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
913c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_parse_streaming(dev, intf);
914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
917b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_INPUT_TERMINAL:
918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 8) {
919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
9289bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL %d has invalid "
932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber,
934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer[3], type);
935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = 0;
939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = 0;
940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		len = 8;
941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
942b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (type == UVC_ITT_CAMERA) {
943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 15 ? buffer[14] : 0;
944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 15;
945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
946b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 9 ? buffer[8] : 0;
948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			p = buflen >= 10 + n ? buffer[9+n] : 0;
949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 10;
950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < len + n + p) {
953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
955c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
956c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9598ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
9608ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, n + p);
961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
964b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bControlSize = n;
966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bmControls = (__u8 *)term + sizeof *term;
967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMin =
9689bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[8]);
969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMax =
9709bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[10]);
971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wOcularFocalLength =
9729bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[12]);
973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->camera.bmControls, &buffer[15], n);
974b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (UVC_ENTITY_TYPE(term) ==
975b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			   UVC_ITT_MEDIA_TRANSPORT_INPUT) {
976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bControlSize = n;
977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmControls = (__u8 *)term + sizeof *term;
978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bTransportModeSize = p;
979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmTransportModes = (__u8 *)term
980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart						     + sizeof *term + n;
981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmControls, &buffer[9], n);
982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[7] != 0)
986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[7], term->name,
987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
988b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Camera %u", buffer[3]);
990b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Media %u", buffer[3]);
992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Input %u", buffer[3]);
994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
998b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_OUTPUT_TERMINAL:
999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
1000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL error\n",
1002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
1007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
1008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
10099bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
1010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
1011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL %d has invalid "
1013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
1014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, buffer[3], type);
1015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
1016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10188ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
10198ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, 0);
1020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
1021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10238ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(term->baSourceID, &buffer[7], 1);
1024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1025c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8] != 0)
1026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8], term->name,
1027c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1029c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Output %u", buffer[3]);
1030c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1031c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1032c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1033c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1034b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1035c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 5 ? buffer[4] : 0;
1036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 5 || buflen < 6 + p) {
1038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1039c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d SELECTOR_UNIT error\n",
1040c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1043c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10448ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
1045c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10488ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[5], p);
1049c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[5+p] != 0)
1051c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[5+p], unit->name,
1052c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1053c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1054c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Selector %u", buffer[3]);
1055c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1056c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1058c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1059b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 8 ? buffer[7] : 0;
1061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = dev->uvc_version >= 0x0110 ? 10 : 9;
1062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < p + n) {
1064c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d PROCESSING_UNIT error\n",
1066c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1067c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1068c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1069c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10708ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
1071c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1072c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1073c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10748ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[4], 1);
1075c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.wMaxMultiplier =
10769bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			get_unaligned_le16(&buffer[5]);
1077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bControlSize = buffer[7];
1078c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
1079c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->processing.bmControls, &buffer[8], n);
1080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->uvc_version >= 0x0110)
1081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			unit->processing.bmVideoStandards = buffer[9+n];
1082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8+n] != 0)
1084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8+n], unit->name,
1085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Processing %u", buffer[3]);
1088c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1092b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
1094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 24 + p ? buffer[22+p] : 0;
1095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 24 + p + n) {
1097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
1099c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11038ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
1104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
1108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
11098ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
1110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
11118ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
1112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], n);
1113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[23+p+n] != 0)
1115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[23+p+n], unit->name,
1116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
1119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
1125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptor (%u)\n", buffer[2]);
1126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_control(struct uvc_device *dev)
1133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
1135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *buffer = alts->extra;
1136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int buflen = alts->extralen;
1137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the default alternate setting only, as the UVC specification
1140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * defines a single alternate setting, the default alternate setting
1141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * zero.
1142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
1145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_parse_vendor_control(dev, buffer, buflen) ||
1146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    buffer[1] != USB_DT_CS_INTERFACE)
1147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			goto next_descriptor;
1148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
1150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ret;
1151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartnext_descriptor:
1153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
1154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
1155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1157538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	/* Check if the optional status endpoint is present. Built-in iSight
1158538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * webcams have an interrupt endpoint but spit proprietary data that
1159538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * don't conform to the UVC status endpoint messages. Don't try to
1160538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * handle the interrupt endpoint for those cameras.
1161538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 */
1162538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	if (alts->desc.bNumEndpoints == 1 &&
1163538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	    !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
1164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep = &alts->endpoint[0];
1165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_endpoint_descriptor *desc = &ep->desc;
1166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (usb_endpoint_is_int_in(desc) &&
1168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
1169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    desc->bInterval != 0) {
1170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
1171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(addr %02x).\n", desc->bEndpointAddress);
1172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->int_ep = ep;
1173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
11808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * UVC device scan
1181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Scan the UVC descriptors to locate a chain starting at an Output Terminal
1185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * and containing the following units:
1186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
11878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - one or more Output Terminals (USB Streaming or Display)
1188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one Processing Unit
11898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - zero, one or more single-input Selector Units
1190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one multiple-input Selector Units, provided all inputs are
1191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *   connected to input terminals
1192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Extension Units
11932c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one or more Input Terminals (Camera, External or USB Streaming)
1194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
11958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The terminal and units must match on of the following structures:
11968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
11978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
11988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
11998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
12008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(0)
12028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
12038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(n)
12048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The Processing Unit and Extension Units can be in any order. Additional
12068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Extension Units connected to the main chain as single-unit branches are
12078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * also supported. Single-input Selector Units are ignored.
1208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
12098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_entity(struct uvc_video_chain *chain,
1210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1213b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- XU %d", entity->id);
1216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12178ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins != 1) {
1218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
1219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"than 1 input pin.\n", entity->id);
1220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1225b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- PU %d", entity->id);
1228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->processing != NULL) {
1230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
1231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Processing Units in chain.\n");
1232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->processing = entity;
1236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1238b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- SU %d", entity->id);
1241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
12438ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1)
1244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->selector != NULL) {
1247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
1248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Units in chain.\n");
1249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
1253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1255b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
1256b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_CAMERA:
1257b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
1258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1263b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_TT_STREAMING:
12644057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (UVC_ENTITY_IS_ITERM(entity)) {
12654057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
12664057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" <- IT %d\n", entity->id);
12674057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		} else {
12684057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
12694057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" OT %d", entity->id);
1270ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1271ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1272ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
1273ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
1277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12806241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_add_tail(&entity->chain, &chain->entities);
1281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_forward(struct uvc_video_chain *chain,
1285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, struct uvc_entity *prev)
1286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *forward;
1288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found;
1289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Forward scan */
1291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	forward = NULL;
1292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	found = 0;
1293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (1) {
12958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		forward = uvc_entity_by_reference(chain->dev, entity->id,
1296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			forward);
1297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward == NULL)
1298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
12998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (forward == prev)
1300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		switch (UVC_ENTITY_TYPE(forward)) {
13038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_VC_EXTENSION_UNIT:
13048ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (forward->bNrInPins != 1) {
13058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
13068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  "has more than 1 input pin.\n",
13078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  entity->id);
13088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1310c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13116241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" XU %d", forward->id);
13178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
13208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_VENDOR_SPECIFIC:
13228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_DISPLAY:
13238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_TT_STREAMING:
13258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (UVC_ENTITY_IS_ITERM(forward)) {
13268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
13278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					"terminal %u.\n", forward->id);
13288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13316241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" OT %d", forward->id);
13378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
1340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (found)
1343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(")");
1344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_backward(struct uvc_video_chain *chain,
13494057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity **_entity)
1350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
13514057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity *entity = *_entity;
1352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
13534057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	int id = -EINVAL, i;
1354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1356b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1357b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
13588ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = entity->baSourceID[0];
1359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1361b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
13638ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1) {
13648ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[0];
1365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1367c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1369c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT");
1370c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
13728ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i) {
13738ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[i];
13748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			term = uvc_entity_by_id(chain->dev, id);
1375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
1376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
1377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input %d isn't connected to an "
1378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input terminal\n", entity->id, i);
1379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return -1;
1380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
1383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" %d", term->id);
1384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13856241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&term->chain, &chain->entities);
13868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_scan_chain_forward(chain, term, entity);
1387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("\n");
1391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = 0;
1393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
13944057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
13954057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
13964057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_CAMERA:
13974057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
13984057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
13994057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_DISPLAY:
14004057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
14014057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_TT_STREAMING:
14028ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
14034057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		break;
1404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14064057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (id <= 0) {
14074057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		*_entity = NULL;
14084057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return id;
14094057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14104057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14114057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = uvc_entity_by_id(chain->dev, id);
14124057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (entity == NULL) {
14134057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14144057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			"unknown entity %d.\n", id);
14154057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return -EINVAL;
14164057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14174057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14184057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	*_entity = entity;
14194057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	return 0;
1420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain(struct uvc_video_chain *chain,
14234057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			  struct uvc_entity *term)
1424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, *prev;
1426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14274057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
1428ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
14294057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = term;
14304057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	prev = NULL;
14318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14324057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	while (entity != NULL) {
14334057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		/* Entity must not be part of an existing chain */
14348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (entity->chain.next || entity->chain.prev) {
14358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14364057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				"entity %d already in chain.\n", entity->id);
14378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Process entity */
14418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_entity(chain, entity) < 0)
14428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Forward scan */
14458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_forward(chain, entity, prev) < 0)
14468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Backward scan */
14494057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		prev = entity;
14504057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (uvc_scan_chain_backward(chain, &entity) < 0)
14514057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			return -EINVAL;
1452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
14558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
14568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14576241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchartstatic unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
14586241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		char *buffer)
14598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
14608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
14618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	unsigned int nterms = 0;
14628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
14638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(term, terms, chain) {
14656241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (!UVC_ENTITY_IS_TERM(term) ||
14666241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		    UVC_TERM_DIRECTION(term) != dir)
14676241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			continue;
14686241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart
14696241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (nterms)
14708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			p += sprintf(p, ",");
14716241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (++nterms >= 4) {
14726241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			p += sprintf(p, "...");
14736241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			break;
14748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
14756241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		p += sprintf(p, "%u", term->id);
1476ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
1477c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return p - buffer;
14798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
14808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic const char *uvc_print_chain(struct uvc_video_chain *chain)
14828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
14838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	static char buffer[43];
14848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
14858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14866241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
14878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	p += sprintf(p, " -> ");
14886241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
14898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return buffer;
1491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
149435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart * Scan the device for video chains and register video devices.
1495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
14968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Chains are scanned starting at their output terminals and walked backwards.
1497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
149835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchartstatic int uvc_scan_device(struct uvc_device *dev)
1499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
15008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
1501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(term, &dev->entities, list) {
15048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (!UVC_ENTITY_IS_OTERM(term))
1505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		/* If the terminal is already included in a chain, skip it.
15088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * This can happen for chains that have multiple output
15098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * terminals, where all output terminals beside the first one
15108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * will be inserted in the chain in forward scans.
15118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 */
15128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (term->chain.next || term->chain.prev)
1513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
15168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain == NULL)
15178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -ENOMEM;
15188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15196241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		INIT_LIST_HEAD(&chain->entities);
15208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		mutex_init(&chain->ctrl_mutex);
15218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->dev = dev;
15228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain(chain, term) < 0) {
15248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			kfree(chain);
15258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
1526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
15278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
15298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			  uvc_print_chain(chain));
15308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		list_add_tail(&chain->list, &dev->chains);
1532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (list_empty(&dev->chains)) {
1535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "No valid video chain found.\n");
1536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
15438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Video device registration and unregistration
15448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
15458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
1547716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Delete the UVC device.
1548716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1549716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Called by the kernel when the last reference to the uvc_device structure
1550716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * is released.
1551716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1552716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * As this function is called after or during disconnect(), all URBs have
1553716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * already been canceled by the USB core. There is no need to kill the
1554716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * interrupt URB manually.
1555716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart */
1556716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_delete(struct uvc_device *dev)
1557716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1558716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct list_head *p, *n;
1559716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1560716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_intf(dev->intf);
1561716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_dev(dev->udev);
1562716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1563716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_status_cleanup(dev);
1564716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_ctrl_cleanup_device(dev);
1565716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1566716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->chains) {
1567716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_video_chain *chain;
1568716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		chain = list_entry(p, struct uvc_video_chain, list);
1569716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(chain);
1570716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1571716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1572716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->entities) {
1573716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_entity *entity;
1574716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		entity = list_entry(p, struct uvc_entity, list);
1575716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(entity);
1576716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1577716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1578716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->streams) {
1579716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_streaming *streaming;
1580716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		streaming = list_entry(p, struct uvc_streaming, list);
1581716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_driver_release_interface(&uvc_driver.driver,
1582716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart			streaming->intf);
1583716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_put_intf(streaming->intf);
1584716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->format);
1585716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->header.bmaControls);
1586716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming);
1587716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1588716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1589716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	kfree(dev);
1590716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1591716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1592716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_release(struct video_device *vdev)
1593716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1594716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_streaming *stream = video_get_drvdata(vdev);
1595716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_device *dev = stream->dev;
1596716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1597716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	video_device_release(vdev);
1598716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1599716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the registered streams count and delete the device when it
1600716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * reaches zero.
1601716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1602716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1603716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
1604716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1605716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1606716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart/*
16078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Unregister the video devices.
16088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic void uvc_unregister_video(struct uvc_device *dev)
16108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1613716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Unregistering all video devices might result in uvc_delete() being
1614716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * called from inside the loop if there's no open file handle. To avoid
1615716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * that, increment the stream count before iterating over the streams
1616716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * and decrement it when done.
1617716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1618716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
1619716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
16218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->vdev == NULL)
16228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
16238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1624716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		video_unregister_device(stream->vdev);
16258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
16268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
1627716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1628716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the stream count and call uvc_delete explicitly if there
1629716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * are no stream left.
1630716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1631716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1632716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
16338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
16348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_video(struct uvc_device *dev,
16368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		struct uvc_streaming *stream)
16378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct video_device *vdev;
16398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
16408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Initialize the streaming interface with default streaming
16428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * parameters.
16438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = uvc_video_init(stream);
16458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
16468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to initialize the device "
16478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			"(%d).\n", ret);
16488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
16498e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register the device with V4L. */
16528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev = video_device_alloc();
16538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (vdev == NULL) {
16548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
16558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
16568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return -ENOMEM;
16578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* We already hold a reference to dev->udev. The video device will be
16608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * unregistered before the reference is released, so we don't need to
16618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * get another one.
16628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->parent = &dev->intf->dev;
16648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->fops = &uvc_fops;
1665716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	vdev->release = uvc_release;
16668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	strlcpy(vdev->name, dev->name, sizeof vdev->name);
16678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Set the driver data before calling video_register_device, otherwise
16698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * uvc_v4l2_open might race us.
16708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	stream->vdev = vdev;
16728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	video_set_drvdata(vdev, stream);
16738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
16758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
16768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
16778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
16788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
16798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		video_device_release(vdev);
16808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
16818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1683716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
16848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
16858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
16868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
16888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Register all video devices in all chains.
16898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_terms(struct uvc_device *dev,
16916241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	struct uvc_video_chain *chain)
16928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
16958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
16968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16976241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_for_each_entry(term, &chain->entities, chain) {
16988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
16998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream = uvc_stream_by_id(dev, term->id);
17028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream == NULL) {
17038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_printk(KERN_INFO, "No streaming interface found "
17048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				   "for terminal %u.", term->id);
17058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
17078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->chain = chain;
17098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		ret = uvc_register_video(dev, stream);
17108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_chains(struct uvc_device *dev)
17188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
17208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(chain, &dev->chains, list) {
17236241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		ret = uvc_register_terms(dev, chain);
17248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
17328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * USB probe, disconnect, suspend and resume
17338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
17348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_probe(struct usb_interface *intf,
1736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		     const struct usb_device_id *id)
1737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = interface_to_usbdev(intf);
1739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev;
1740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1742c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (id->idVendor && id->idProduct)
1743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
1744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(%04x:%04x)\n", udev->devpath, id->idVendor,
1745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				id->idProduct);
1746c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
1748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devpath);
1749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17502c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Allocate memory for the device and initialize it. */
1751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
1752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
1753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->entities);
17558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	INIT_LIST_HEAD(&dev->chains);
175635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	INIT_LIST_HEAD(&dev->streams);
1757716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_set(&dev->nstreams, 0);
175804a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart	atomic_set(&dev->users, 0);
1759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->udev = usb_get_dev(udev);
1761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intf = usb_get_intf(intf);
1762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
176373de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	dev->quirks = (uvc_quirks_param == -1)
176473de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		    ? id->driver_info : uvc_quirks_param;
1765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (udev->product != NULL)
1767d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(dev->name, udev->product, sizeof dev->name);
1768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		snprintf(dev->name, sizeof dev->name,
1770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"UVC Camera (%04x:%04x)",
1771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idVendor),
1772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idProduct));
1773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17742c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Parse the Video Class control descriptor. */
1775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_parse_control(dev) < 0) {
1776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
1777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptors.\n");
1778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1781fba4578ee925110587ef9b8b6ddfabf2ce288071Laurent Pinchart	uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
1782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->uvc_version >> 8, dev->uvc_version & 0xff,
1783c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		udev->product ? udev->product : "<unnamed>",
1784c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idVendor),
1785c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idProduct));
1786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
178773de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	if (dev->quirks != id->driver_info) {
178873de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
178973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart			"parameter for testing purpose.\n", dev->quirks);
1790c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Please report required quirks to the "
1791c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"linux-uvc-devel mailing list.\n");
1792c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1793c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17942c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize controls. */
1795c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_ctrl_init_device(dev) < 0)
1796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Scan the device for video chains. */
179935f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	if (uvc_scan_device(dev) < 0)
1800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register video devices. */
18038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (uvc_register_chains(dev) < 0)
18048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		goto error;
18058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18062c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Save our data pointer in the interface data. */
1807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, dev);
1808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18092c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize the interrupt URB. */
1810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_status_init(dev)) < 0) {
1811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Unable to initialize the status "
1812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"endpoint (%d), status interrupt will not be "
1813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"supported.\n", ret);
1814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
1817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
1820716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return -ENODEV;
1822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_disconnect(struct usb_interface *intf)
1825c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the USB interface data to NULL. This can be done outside the
1829c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock, as there's no other reader.
1830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, NULL);
1832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1833b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1834b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOSTREAMING)
1835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
1836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->state |= UVC_DEV_DISCONNECTED;
1838a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart
1839716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_suspend(struct usb_interface *intf, pm_message_t message)
1843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
184535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
1848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Controls are cached on the fly so they don't need to be saved. */
1851b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1852b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL)
1853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_suspend(dev);
1854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
185535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
185635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
185735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_suspend(stream);
1858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
186035f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
186135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
186235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18659b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int __uvc_resume(struct usb_interface *intf, int reset)
1866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
186835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
1871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1873b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1874b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
18757564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		if (reset) {
18767564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			int ret = uvc_ctrl_resume_device(dev);
18777564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil
18787564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			if (ret < 0)
18797564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil				return ret;
18807564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		}
1881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_resume(dev);
1883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
188535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
188635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
188735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_resume(stream);
1888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
189035f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
189135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
189235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18959b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_resume(struct usb_interface *intf)
18969b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
18979b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 0);
18989b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
18999b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
19009b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_reset_resume(struct usb_interface *intf)
19019b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
19029b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 1);
19039b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
19049b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
1905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
1906310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart * Module parameters
1907310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart */
1908310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1909310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
1910310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
1911310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (uvc_clock_param == CLOCK_MONOTONIC)
1912310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_MONOTONIC");
1913310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
1914310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_REALTIME");
1915310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
1916310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1917310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_set(const char *val, struct kernel_param *kp)
1918310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
1919310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
1920310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		val += strlen("clock_");
1921310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1922310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strcasecmp(val, "monotonic") == 0)
1923310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_MONOTONIC;
1924310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else if (strcasecmp(val, "realtime") == 0)
1925310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_REALTIME;
1926310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
1927310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return -EINVAL;
1928310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1929310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	return 0;
1930310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
1931310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1932310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
1933310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		  &uvc_clock_param, S_IRUGO|S_IWUSR);
1934310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(clock, "Video buffers timestamp clock");
1935310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
1936310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
1937310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
1938310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(quirks, "Forced device quirks");
1939310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
1940310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(trace, "Trace level bitmask");
1941310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
1942310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(timeout, "Streaming control requests timeout");
1943310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1944310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart/* ------------------------------------------------------------------------
1945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Driver initialization and cleanup
1946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Logitech cameras listed below have their interface class set to
1950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * VENDOR_SPEC because they don't announce themselves as UVC devices, even
1951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * though they are compliant.
1952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct usb_device_id uvc_ids[] = {
1954bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	/* Genius eFace 2025 */
1955bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1956bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1957bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idVendor		= 0x0458,
1958bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idProduct		= 0x706e,
1959bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1960bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceSubClass	= 1,
1961bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceProtocol	= 0,
1962bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam NX-6000 */
1964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x00f8,
1968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam VX-7000 */
1973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0723,
1977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Fusion */
1982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c1,
1986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Orbit MP */
1990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c2,
1994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro for Notebook */
1998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c3,
2002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro 5000 */
2006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2009c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c5,
2010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Dell Notebook */
2014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c6,
2018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2019c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Cisco VT Camera II */
2022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2023c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2025c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c7,
2026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2027c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2029f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
2030f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2031f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2032f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idVendor		= 0x058f,
2033f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idProduct		= 0x3820,
2034f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2035f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2036f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2037f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Apple Built-In iSight */
20392c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2040c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x05ac,
2042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8501,
20432c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20442c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
20452c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
2046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
2047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| UVC_QUIRK_BUILTIN_ISIGHT },
2048c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Genesys Logic USB 2.0 PC Camera */
20492c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
20512c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idVendor		= 0x05e3,
20522c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idProduct		= 0x0505,
20532c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20542c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
20552c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
20562c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2057d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Vega */
2058d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2059d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2060d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2061d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x332d,
2062d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2063d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2064d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2065d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2066d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro - Minoru3D */
2067d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2068d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2069d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2070d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3410,
2071d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2072d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2073d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2074d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2075d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Venus - Minoru3D */
2076d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
207750144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
207850144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idVendor		= 0x0ac8,
2079d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3420,
208050144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
208150144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceSubClass	= 1,
208250144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceProtocol	= 0,
208350144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* MT6227 */
2085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x0e8d,
2088c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0004,
2089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2092bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2093bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart				| UVC_QUIRK_PROBE_DEF },
20949275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	/* IMC Networks (Medion Akoya) */
20959275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
20969275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
20979275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idVendor		= 0x13d3,
20989275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idProduct		= 0x5103,
20999275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21009275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceSubClass	= 1,
21019275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceProtocol	= 0,
21029275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (HP Spartan) */
2104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x5212,
2108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
211125e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2112562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	/* Syntek (Samsung Q310) */
2113562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2114562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2115562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idVendor		= 0x174f,
2116562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idProduct		= 0x5931,
2117562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2118562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2119562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2120562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2121f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	/* Syntek (Packard Bell EasyNote MX52 */
2122f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2123f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2124f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idVendor		= 0x174f,
2125f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idProduct		= 0x8a12,
2126f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2127f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceSubClass	= 1,
2128f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceProtocol	= 0,
2129f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2130f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Syntek (Asus F9SG) */
213125e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
213225e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
213325e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idVendor		= 0x174f,
213425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idProduct		= 0x8a31,
213525e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
213625e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceSubClass	= 1,
213725e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceProtocol	= 0,
2138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (Asus U3S) */
2140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8a33,
2144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
21480ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	/* Syntek (JAOtech Smart Terminal) */
21490ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21500ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21510ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idVendor		= 0x174f,
21520ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idProduct		= 0x8a34,
21530ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21540ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceSubClass	= 1,
21550ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceProtocol	= 0,
21560ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
215770092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	/* Miricle 307K */
215870092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
215970092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
216070092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idVendor		= 0x17dc,
216170092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idProduct		= 0x0202,
216270092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
216370092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceSubClass	= 1,
216470092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceProtocol	= 0,
216570092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2166849a3aba2d9830dc2a78a66078023e7e5ac26e15Filipe Rosset	/* Lenovo Thinkpad SL400/SL500 */
21672f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21682f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21692f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idVendor		= 0x17ef,
21702f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idProduct		= 0x480b,
21712f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21722f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceSubClass	= 1,
21732f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceProtocol	= 0,
21742f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
21752d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	/* Aveo Technology USB 2.0 Camera */
21762d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21772d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21782d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idVendor		= 0x1871,
21792d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idProduct		= 0x0306,
21802d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21812d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceSubClass	= 1,
21822d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceProtocol	= 0,
21835bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
21845bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart				| UVC_QUIRK_PROBE_EXTRAFIELDS },
2185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Ecamm Pico iMage */
2186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x18cd,
2189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0xcafe,
2190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
21942bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	/* Manta MM-353 Plako */
21952bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21962bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21972bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idVendor		= 0x18ec,
21982bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idProduct		= 0x3188,
21992bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22002bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceSubClass	= 1,
22012bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceProtocol	= 0,
22022bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2203ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	/* FSC WebCam V30S */
2204ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2205ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2206ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idVendor		= 0x18ec,
2207ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idProduct		= 0x3288,
2208ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2209ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceSubClass	= 1,
2210ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceProtocol	= 0,
2211ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
22121e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	/* Arkmicro unbranded */
22131e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
22141e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22151e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idVendor		= 0x18ec,
22161e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idProduct		= 0x3290,
22171e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22181e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceSubClass	= 1,
22191e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceProtocol	= 0,
22201e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Bodelin ProScopeHR */
2222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_DEV_HI
2224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x19ab,
2226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x1000,
2227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bcdDevice_hi		= 0x0126,
2228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STATUS_INTERVAL },
22323bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	/* MSI StarCam 370i */
22333bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
22343bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22353bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idVendor		= 0x1b3b,
22363bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idProduct		= 0x2951,
22373bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22383bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceSubClass	= 1,
22393bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceProtocol	= 0,
22403bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* SiGma Micro USB Web Camera */
2242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x1c4f,
2245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x3000,
2246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2250d732c44c1a4b54e3c59ad92069bc2fd848aca5f3Laurent Pinchart				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
2251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Generic USB Video Class */
2252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
2253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{}
2254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DEVICE_TABLE(usb, uvc_ids);
2257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct uvc_driver uvc_driver = {
2259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	.driver = {
2260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "uvcvideo",
2261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.probe		= uvc_probe,
2262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.disconnect	= uvc_disconnect,
2263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.suspend	= uvc_suspend,
2264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.resume		= uvc_resume,
22659b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart		.reset_resume	= uvc_reset_resume,
2266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.id_table	= uvc_ids,
2267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.supports_autosuspend = 1,
2268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
2269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int __init uvc_init(void)
2272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int result;
2274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.devices);
2276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.controls);
2277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&uvc_driver.ctrl_mutex);
2278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_ctrl_init();
2280c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	result = usb_register(&uvc_driver.driver);
2282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (result == 0)
2283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
2284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return result;
2285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void __exit uvc_cleanup(void)
2288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_deregister(&uvc_driver.driver);
2290561474c2d2a1e212ea186e0b65cc69fb330e7bd5Laurent Pinchart	uvc_ctrl_cleanup();
2291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_init(uvc_init);
2294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_exit(uvc_cleanup);
2295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_AUTHOR(DRIVER_AUTHOR);
2297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DESCRIPTION(DRIVER_DESC);
2298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_LICENSE("GPL");
2299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_VERSION(DRIVER_VERSION);
2300f87086e302300fdff1bd32049deb7a7f3e3de7daHans Verkuil
2301