uvc_driver.c revision 078f8947926732a526fb280c0f3a8920bf173b9c
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>
29c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb.h>
30c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/videodev2.h>
31c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/vmalloc.h>
32c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/wait.h>
33c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <asm/atomic.h>
349bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich#include <asm/unaligned.h>
35c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
36c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <media/v4l2-common.h>
37c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
38c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include "uvcvideo.h"
39c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
40c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_AUTHOR		"Laurent Pinchart <laurent.pinchart@skynet.be>"
41c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_DESC		"USB Video Class driver"
42c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#ifndef DRIVER_VERSION
43c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_VERSION		"v0.1.0"
44c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#endif
45c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
460fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent Pinchartunsigned int uvc_no_drop_param;
47c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic unsigned int uvc_quirks_param;
48c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartunsigned int uvc_trace_param;
49c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
50c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
512c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * Video formats
52c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
53c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
54c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc uvc_fmts[] = {
55c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
56c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (YUYV)",
57c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YUY2,
58c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUYV,
59c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
60c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
61c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (NV12)",
62c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_NV12,
63c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_NV12,
64c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
65c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
66c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "MJPEG",
67c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_MJPEG,
68c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_MJPEG,
69c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
70c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
71c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YVU 4:2:0 (YV12)",
72c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YV12,
73c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YVU420,
74c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
75c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
76c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (I420)",
77c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_I420,
78c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUV420,
79c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
80c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
81c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (UYVY)",
82c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_UYVY,
83c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_UYVY,
84c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
85c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
86c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "Greyscale",
87c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y800,
88c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_GREY,
89c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
90c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
91c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "RGB Bayer",
92c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_BY8,
93c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_SBGGR8,
94c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
95c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
96c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
97c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
98c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Utility functions
99c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		__u8 epaddr)
103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep;
105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = &alts->endpoint[i];
109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep->desc.bEndpointAddress == epaddr)
110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ep;
111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int len = ARRAY_SIZE(uvc_fmts);
119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < len; ++i) {
122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return &uvc_fmts[i];
124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic __u32 uvc_colorspace(const __u8 primaries)
130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	static const __u8 colorprimaries[] = {
132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		0,
133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SRGB,
134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_M,
135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_BG,
136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE170M,
137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE240M,
138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	};
139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (primaries < ARRAY_SIZE(colorprimaries))
141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return colorprimaries[primaries];
142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Simplify a fraction using a simple continued fraction decomposition. The
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * idea here is to convert fractions such as 333333/10000000 to 1/30 using
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arbitrary parameters to remove non-significative terms from the simple
150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * respectively seems to give nice results.
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unsigned int n_terms, unsigned int threshold)
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t *an;
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t x, y, r;
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (an == NULL)
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Convert the fraction to a simple continued fraction. See
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * http://mathforum.org/dr.math/faq/faq.fractions.html
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * Stop if the current term is bigger than or equal to the given
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * threshold.
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = *numerator;
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = *denominator;
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (n = 0; n < n_terms && y != 0; ++n) {
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		an[n] = x / y;
174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (an[n] >= threshold) {
175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (n < 2)
176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				n++;
177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = x - an[n] * y;
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = y;
182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = r;
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Expand the simple continued fraction back to an integer fraction. */
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = 0;
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = 1;
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = n; i > 0; --i) {
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = y;
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = an[i-1] * y + x;
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = r;
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*numerator = y;
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*denominator = x;
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(an);
198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to compute numerator / denominator * 10000000 using 32 bit fixed point
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arithmetic only.
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartuint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t multiplier;
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Saturate the result if the operation would overflow. */
209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (denominator == 0 ||
210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    numerator/denominator >= ((uint32_t)-1)/10000000)
211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return (uint32_t)-1;
212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Divide both the denominator and the multiplier by two until
214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * numerator * multiplier doesn't overflow. If anyone knows a better
215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * algorithm please let me know.
216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	multiplier = 10000000;
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (numerator > ((uint32_t)-1)/multiplier) {
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		multiplier /= 2;
220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		denominator /= 2;
221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return denominator ? numerator * multiplier / denominator : 0;
224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Terminal and unit management
228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity;
233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(entity, &dev->entities, list) {
235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->id == id)
236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return entity;
237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id, struct uvc_entity *entity)
244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (entity == NULL)
248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(&dev->entities, struct uvc_entity, list);
249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry_continue(entity, &dev->entities, list) {
251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (UVC_ENTITY_TYPE(entity)) {
252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case TT_STREAMING:
253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (entity->output.bSourceID == id)
254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VC_PROCESSING_UNIT:
258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (entity->processing.bSourceID == id)
259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VC_SELECTOR_UNIT:
263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			for (i = 0; i < entity->selector.bNrInPins; ++i)
264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				if (entity->selector.baSourceID[i] == id)
265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					return entity;
266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VC_EXTENSION_UNIT:
269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			for (i = 0; i < entity->extension.bNrInPins; ++i)
270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				if (entity->extension.baSourceID[i] == id)
271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					return entity;
272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
280c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Descriptors handling
281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_format(struct uvc_device *dev,
284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming, struct uvc_format *format,
285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 **intervals, unsigned char *buffer, int buflen)
286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf = streaming->intf;
288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = intf->cur_altsetting;
289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format_desc *fmtdesc;
290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *start = buffer;
292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int interval;
293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u8 ftype;
295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->type = buffer[2];
297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->index = buffer[3];
298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_UNCOMPRESSED:
301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_FRAME_BASED:
302233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28;
303233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		if (buflen < n) {
304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
305c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
307c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
308c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
309c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
310c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
311c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Find the format descriptor from its GUID. */
312c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		fmtdesc = uvc_format_by_guid(&buffer[5]);
313c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
314c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (fmtdesc != NULL) {
315d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, fmtdesc->name,
316c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				sizeof format->name);
317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = fmtdesc->fcc;
318c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
319c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_printk(KERN_INFO, "Unknown video format "
320c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				UVC_GUID_FORMAT "\n",
321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				UVC_GUID_ARGS(&buffer[5]));
322c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			snprintf(format->name, sizeof format->name,
323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5]));
324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = 0;
325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
327c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = buffer[21];
328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[2] == VS_FORMAT_UNCOMPRESSED) {
329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ftype = VS_FRAME_UNCOMPRESSED;
330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ftype = VS_FRAME_FRAME_BASED;
332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (buffer[27])
333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				format->flags = UVC_FMT_FLAG_COMPRESSED;
334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_MJPEG:
338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 11) {
339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
346d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(format->name, "MJPEG", sizeof format->name);
347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_MJPEG;
348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED;
349c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = VS_FRAME_MJPEG;
351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_DV:
354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[8] & 0x7f) {
363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 0:
364d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SD-DV", sizeof format->name);
365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 1:
367d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SDL-DV", sizeof format->name);
368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
369c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 2:
370d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "HD-DV", sizeof format->name);
371c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
372c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
374c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d: unknown DV format %u\n",
375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber, buffer[8]);
377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
380d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sizeof format->name);
382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_DV;
384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = 0;
387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Create a dummy frame descriptor. */
389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame = &format->frame[0];
390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&format->frame[0], 0, sizeof format->frame[0]);
391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIntervalType = 1;
392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval = 1;
393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
394c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		*(*intervals)++ = 1;
395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->nframes = 1;
396c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_MPEG2TS:
399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VS_FORMAT_STREAM_BASED:
400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Not supported yet. */
401c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       "interface %d unsupported format %u\n",
404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       dev->udev->devnum, alts->desc.bInterfaceNumber,
405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       buffer[2]);
406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
411c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
414c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * based formats have frame descriptors.
416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[2] == ftype) {
418078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		frame = &format->frame[format->nframes];
419c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ftype != VS_FRAME_FRAME_BASED)
420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 25 ? buffer[25] : 0;
421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 21 ? buffer[21] : 0;
423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = n ? n : 3;
425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 26 + 4*n) {
427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FRAME error\n", dev->udev->devnum,
429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIndex = buffer[3];
434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bmCapabilities = buffer[4];
4359bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wWidth = get_unaligned_le16(&buffer[5]);
4369bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wHeight = get_unaligned_le16(&buffer[7]);
4379bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
4389bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ftype != VS_FRAME_FRAME_BASED) {
440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize =
4419bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4439bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[21]);
444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[25];
445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = 0;
447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4489bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[21];
450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * completely. Observed behaviours range from setting the
4552c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * value to 1.1x the actual frame size to hardwiring the
456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 16 low bits to 0. This results in a higher than necessary
457c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * memory usage as well as a wrong image size information. For
458c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * uncompressed formats this can be fixed by computing the
459c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * value from the frame size.
460c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
461c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = format->bpp
463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				* frame->wWidth * frame->wHeight / 8;
464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
465c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Some bogus devices report dwMinFrameInterval equal to
466c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * dwMaxFrameInterval and have dwFrameIntervalStep set to
467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * zero. Setting all null intervals to 1 fixes the problem and
4682c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * some other divisions by zero that could happen.
469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
470c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
4719bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			interval = get_unaligned_le32(&buffer[26+4*i]);
472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			*(*intervals)++ = interval ? interval : 1;
473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
474c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure that the default frame interval stays between
476c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * the boundaries.
477c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
478c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n -= frame->bFrameIntervalType ? 1 : 2;
479c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval =
480c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			min(frame->dwFrameInterval[n],
481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    max(frame->dwFrameInterval[0],
482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				frame->dwDefaultFrameInterval));
483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
485c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->wWidth, frame->wHeight,
486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			10000000/frame->dwDefaultFrameInterval,
487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			(100000000/frame->dwDefaultFrameInterval)%10);
488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
489078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		format->nframes++;
490c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
494c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) {
495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen > 2 && buffer[2] == VS_COLORFORMAT) {
500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 6) {
501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d COLORFORMAT error\n",
503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
508c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->colorspace = uvc_colorspace(buffer[3]);
509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return buffer - start;
515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_streaming(struct uvc_device *dev,
518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf)
519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming = NULL;
521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format *format;
522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = &intf->altsetting[0];
524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *_buffer, *buffer = alts->extra;
525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int _buflen, buflen = alts->extralen;
526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int nformats = 0, nframes = 0, nintervals = 0;
527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int size, i, n, p;
528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 *interval;
529c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 psize;
530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret = -EINVAL;
531c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass
533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		!= SC_VIDEOSTREAMING) {
534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"video streaming interface\n", dev->udev->devnum,
536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"claimed\n", dev->udev->devnum,
543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (streaming == NULL) {
549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver, intf);
550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&streaming->mutex);
554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intf = usb_get_intf(intf);
555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* The Pico iMage webcam has its class-specific interface descriptors
558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * after the endpoint descriptors.
559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen == 0) {
561c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			struct usb_host_endpoint *ep = &alts->endpoint[i];
563c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen == 0)
565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen > 2 &&
568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    ep->extra[1] == USB_DT_CS_INTERFACE) {
569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "trying extra data "
570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"from endpoint %u.\n", i);
571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer = alts->endpoint[i].extra;
572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buflen = alts->endpoint[i].extralen;
573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Skip the standard interface descriptors. */
579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen <= 2) {
585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"interface descriptors found.\n");
587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
590c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the header descriptor. */
591ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	switch (buffer[2]) {
592ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	case VS_OUTPUT_HEADER:
593ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
594ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 9;
595ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
596ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
597ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	case VS_INPUT_HEADER:
598ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
599ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 13;
600ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
601ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
602ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	default:
603c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
604ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"%d HEADER descriptor not found.\n", dev->udev->devnum,
605ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			alts->desc.bInterfaceNumber);
606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
607ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
608c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
609ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	p = buflen >= 4 ? buffer[3] : 0;
610ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	n = buflen >= size ? buffer[size-1] : 0;
611ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
612ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buflen < size + p*n) {
613ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
614ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"interface %d HEADER descriptor is invalid.\n",
615ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
616ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		goto error;
617ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
618c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
619ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bNumFormats = p;
620ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bEndpointAddress = buffer[6];
621ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buffer[2] == VS_INPUT_HEADER) {
622c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bmInfo = buffer[7];
623c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTerminalLink = buffer[8];
624c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bStillCaptureMethod = buffer[9];
625c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerSupport = buffer[10];
626c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerUsage = buffer[11];
627c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
628ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->header.bTerminalLink = buffer[7];
629ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
630ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bControlSize = n;
631ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
632ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
633ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (streaming->header.bmaControls == NULL) {
634ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		ret = -ENOMEM;
635c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
636c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
637c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
638ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	memcpy(streaming->header.bmaControls, &buffer[size], p*n);
639ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
640c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
641c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
642c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
643c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buffer = buffer;
644c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buflen = buflen;
645c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
646c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Count the format and frame descriptors. */
647c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (_buflen > 2) {
648c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (_buffer[2]) {
649c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_UNCOMPRESSED:
650c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_MJPEG:
651c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_FRAME_BASED:
652c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
653c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
654c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
655c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_DV:
656c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			/* DV format has no frame descriptor. We will create a
657c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 * dummy frame descriptor with a dummy frame interval.
658c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 */
659c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
660c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
661c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nintervals++;
662c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
663c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
664c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_MPEG2TS:
665c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_STREAM_BASED:
666c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
667c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d FORMAT %u is not supported.\n",
668c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->udev->devnum,
669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, _buffer[2]);
670c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
671c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
672c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FRAME_UNCOMPRESSED:
673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FRAME_MJPEG:
674c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
675c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 25)
676c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[25] ? _buffer[25] : 3;
677c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
679c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FRAME_FRAME_BASED:
680c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
681c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 21)
682c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[21] ? _buffer[21] : 3;
683c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
684c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
685c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
686c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buflen -= _buffer[0];
687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buffer += _buffer[0];
688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (nformats == 0) {
691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"%d has no supported formats defined.\n",
693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
694c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
695c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
697c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	size = nformats * sizeof *format + nframes * sizeof *frame
698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	     + nintervals * sizeof *interval;
699c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format = kzalloc(size, GFP_KERNEL);
700c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (format == NULL) {
701c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ret = -ENOMEM;
702c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
703c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
705c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	frame = (struct uvc_frame *)&format[nformats];
706c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = (__u32 *)&frame[nframes];
707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->format = format;
709c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->nformats = nformats;
710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the format descriptors. */
712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[2]) {
714c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_UNCOMPRESSED:
715c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_MJPEG:
716c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_DV:
717c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case VS_FORMAT_FRAME_BASED:
718c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->frame = frame;
719c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret = uvc_parse_format(dev, streaming, format,
720c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				&interval, buffer, buflen);
721c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ret < 0)
722c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				goto error;
723c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
724c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame += format->nframes;
725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format++;
726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buflen -= ret;
728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buffer += ret;
729c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the alternate settings to find the maximum bandwidth. */
740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < intf->num_altsetting; ++i) {
741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep;
742c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		alts = &intf->altsetting[i];
743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = uvc_find_endpoint(alts,
744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				streaming->header.bEndpointAddress);
745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep == NULL)
746c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = le16_to_cpu(ep->desc.wMaxPacketSize);
749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (psize > streaming->maxpsize)
751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->maxpsize = psize;
752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_add_tail(&streaming->list, &dev->streaming);
755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_driver_release_interface(&uvc_driver.driver, intf);
759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(intf);
760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->format);
761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->header.bmaControls);
762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming);
763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Parse vendor-specific extensions. */
767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_vendor_control(struct uvc_device *dev,
768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit;
773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int n, p;
774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int handled = 0;
775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0x046d:		/* Logitech */
778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[1] != 0x41 || buffer[2] != 0x01)
779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
781c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Logitech implements several vendor specific functions
782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * through vendor specific extension units (LXU).
783c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
784c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * The LXU descriptors are similar to XU descriptors
785c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * (see "USB Device Video Class for Video Devices", section
786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 3.7.2.6 "Extension Unit Descriptor") with the following
787c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * differences:
788c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
789c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
790c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 0		bLength		1	 Number
791c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Size of this descriptor, in bytes: 24+p+n*2
792c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
793c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n	bmControlsType	N	Bitmap
794c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	Individual bits in the set are defined:
795c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	0: Absolute
796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	1: Relative
797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
798c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	This bitset is mapped exactly the same as bmControls.
799c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n*2	bReserved	1	Boolean
801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
802c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 24+p+n*2	iExtension	1	Index
803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Index of a string descriptor that describes this
804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	extension unit.
805c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 25 + p ? buffer[22+p] : 0;
809c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 25 + p + 2*n) {
811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL);
818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->id = buffer[3];
822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->type = VC_EXTENSION_UNIT;
823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
8259bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]);
826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.baSourceID, &buffer[22], p);
828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
829c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p;
830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit
831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					       + p + n;
832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
833c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
834c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[24+p+2*n] != 0)
835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[24+p+2*n], unit->name,
836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		handled = 1;
842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return handled;
846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_standard_control(struct uvc_device *dev,
849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
851c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
852c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit, *term;
853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf;
854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n, p, len;
856c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 type;
857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_HEADER:
860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 12 ? buffer[11] : 0;
861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 12 || buflen < 12 + n) {
863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d HEADER error\n", udev->devnum,
865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber);
866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8699bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->uvc_version = get_unaligned_le16(&buffer[3]);
8709bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->clock_frequency = get_unaligned_le32(&buffer[7]);
871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Parse all USB Video Streaming interfaces. */
873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf = usb_ifnum_to_if(udev, buffer[12+i]);
875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (intf == NULL) {
876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "device %d "
877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"interface %d doesn't exists\n",
878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					udev->devnum, i);
879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_parse_streaming(dev, intf);
883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
886c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_INPUT_TERMINAL:
887c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 8) {
888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
890c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
896c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
8979bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL %d has invalid "
901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
902c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber,
903c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer[3], type);
904c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
906c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
907c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = 0;
908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = 0;
909c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		len = 8;
910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (type == ITT_CAMERA) {
912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 15 ? buffer[14] : 0;
913c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 15;
914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else if (type == ITT_MEDIA_TRANSPORT_INPUT) {
916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 9 ? buffer[8] : 0;
917c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			p = buflen >= 10 + n ? buffer[9+n] : 0;
918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 10;
919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < len + n + p) {
922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term = kzalloc(sizeof *term + n + p, GFP_KERNEL);
929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term->id = buffer[3];
933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term->type = type | UVC_TERM_INPUT;
934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) {
936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bControlSize = n;
937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bmControls = (__u8 *)term + sizeof *term;
938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMin =
9399bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[8]);
940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMax =
9419bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[10]);
942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wOcularFocalLength =
9439bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[12]);
944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->camera.bmControls, &buffer[15], n);
945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) {
946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bControlSize = n;
947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmControls = (__u8 *)term + sizeof *term;
948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bTransportModeSize = p;
949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmTransportModes = (__u8 *)term
950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart						     + sizeof *term + n;
951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmControls, &buffer[9], n);
952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
955c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[7] != 0)
956c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[7], term->name,
957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA)
959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Camera %u", buffer[3]);
960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT)
961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Media %u", buffer[3]);
962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Input %u", buffer[3]);
964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_OUTPUT_TERMINAL:
969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL error\n",
972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
9799bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL %d has invalid "
983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, buffer[3], type);
985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term = kzalloc(sizeof *term, GFP_KERNEL);
989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term->id = buffer[3];
993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term->type = type | UVC_TERM_OUTPUT;
994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		term->output.bSourceID = buffer[7];
995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8] != 0)
997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8], term->name,
998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Output %u", buffer[3]);
1001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_SELECTOR_UNIT:
1006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 5 ? buffer[4] : 0;
1007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 5 || buflen < 6 + p) {
1009c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d SELECTOR_UNIT error\n",
1011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit = kzalloc(sizeof *unit + p, GFP_KERNEL);
1016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1019c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->id = buffer[3];
1020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->type = buffer[2];
1021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->selector.bNrInPins = buffer[4];
1022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->selector.baSourceID = (__u8 *)unit + sizeof *unit;
1023c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->selector.baSourceID, &buffer[5], p);
1024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1025c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[5+p] != 0)
1026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[5+p], unit->name,
1027c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1029c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Selector %u", buffer[3]);
1030c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1031c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1032c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1033c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1034c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_PROCESSING_UNIT:
1035c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 8 ? buffer[7] : 0;
1036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = dev->uvc_version >= 0x0110 ? 10 : 9;
1037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < p + n) {
1039c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1040c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d PROCESSING_UNIT error\n",
1041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1043c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1044c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1045c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit = kzalloc(sizeof *unit + n, GFP_KERNEL);
1046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1048c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1049c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->id = buffer[3];
1050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->type = buffer[2];
1051c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bSourceID = buffer[4];
1052c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.wMaxMultiplier =
10539bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			get_unaligned_le16(&buffer[5]);
1054c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bControlSize = buffer[7];
1055c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
1056c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->processing.bmControls, &buffer[8], n);
1057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->uvc_version >= 0x0110)
1058c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			unit->processing.bmVideoStandards = buffer[9+n];
1059c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8+n] != 0)
1061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8+n], unit->name,
1062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1064c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Processing %u", buffer[3]);
1065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1066c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1067c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1068c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1069c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_EXTENSION_UNIT:
1070c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
1071c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 24 + p ? buffer[22+p] : 0;
1072c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1073c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 24 + p + n) {
1074c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1075c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
1076c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1078c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1079c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL);
1081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->id = buffer[3];
1085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->type = buffer[2];
1086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
1087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
10889bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]);
1089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
1090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.baSourceID, &buffer[22], p);
1091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
1092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p;
1093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], n);
1094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[23+p+n] != 0)
1096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[23+p+n], unit->name,
1097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1099c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
1100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
1106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptor (%u)\n", buffer[2]);
1107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_control(struct uvc_device *dev)
1114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
1116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *buffer = alts->extra;
1117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int buflen = alts->extralen;
1118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the default alternate setting only, as the UVC specification
1121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * defines a single alternate setting, the default alternate setting
1122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * zero.
1123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
1126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_parse_vendor_control(dev, buffer, buflen) ||
1127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    buffer[1] != USB_DT_CS_INTERFACE)
1128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			goto next_descriptor;
1129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
1131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ret;
1132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartnext_descriptor:
1134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
1135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
1136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1138538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	/* Check if the optional status endpoint is present. Built-in iSight
1139538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * webcams have an interrupt endpoint but spit proprietary data that
1140538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * don't conform to the UVC status endpoint messages. Don't try to
1141538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * handle the interrupt endpoint for those cameras.
1142538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 */
1143538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	if (alts->desc.bNumEndpoints == 1 &&
1144538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	    !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
1145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep = &alts->endpoint[0];
1146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_endpoint_descriptor *desc = &ep->desc;
1147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (usb_endpoint_is_int_in(desc) &&
1149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
1150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    desc->bInterval != 0) {
1151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
1152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(addr %02x).\n", desc->bEndpointAddress);
1153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->int_ep = ep;
1154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
1161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * USB probe and disconnect
1162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Unregister the video devices.
1166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_unregister_video(struct uvc_device *dev)
1168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (dev->video.vdev) {
1170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->video.vdev->minor == -1)
1171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			video_device_release(dev->video.vdev);
1172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			video_unregister_device(dev->video.vdev);
1174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->video.vdev = NULL;
1175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Scan the UVC descriptors to locate a chain starting at an Output Terminal
1180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * and containing the following units:
1181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
11822c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one Output Terminal (USB Streaming or Display)
1183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one Processing Unit
1184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Selector Units
1185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one multiple-input Selector Units, provided all inputs are
1186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *   connected to input terminals
1187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Extension Units
11882c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one or more Input Terminals (Camera, External or USB Streaming)
1189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * A side forward scan is made on each detected entity to check for additional
1191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * extension units.
1192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_scan_chain_entity(struct uvc_video_device *video,
1194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_EXTENSION_UNIT:
1198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- XU %d", entity->id);
1200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->extension.bNrInPins != 1) {
1202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
1203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"than 1 input pin.\n", entity->id);
1204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&entity->chain, &video->extensions);
1208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_PROCESSING_UNIT:
1211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- PU %d", entity->id);
1213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (video->processing != NULL) {
1215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
1216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Processing Units in chain.\n");
1217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		video->processing = entity;
1221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_SELECTOR_UNIT:
1224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- SU %d", entity->id);
1226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
1228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->selector.bNrInPins == 1)
1229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (video->selector != NULL) {
1232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
1233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Units in chain.\n");
1234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		video->selector = entity;
1238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case ITT_VENDOR_SPECIFIC:
1241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case ITT_CAMERA:
1242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case ITT_MEDIA_TRANSPORT_INPUT:
1243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&entity->chain, &video->iterms);
1247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1249ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	case TT_STREAMING:
1250ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1251ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1252ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1253ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		if (!UVC_ENTITY_IS_ITERM(entity)) {
1254ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
1255ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart				"terminal %u.\n", entity->id);
1256ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			return -1;
1257ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1258ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1259ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		if (video->sterm != NULL) {
1260ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming "
1261ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart				"entities in chain.\n");
1262ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			return -1;
1263ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1264ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1265ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		list_add_tail(&entity->chain, &video->iterms);
1266ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		video->sterm = entity;
1267ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
1268ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
1272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_scan_chain_forward(struct uvc_video_device *video,
1279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, struct uvc_entity *prev)
1280c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *forward;
1282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found;
1283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Forward scan */
1285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	forward = NULL;
1286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	found = 0;
1287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (1) {
1289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		forward = uvc_entity_by_reference(video->dev, entity->id,
1290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			forward);
1291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward == NULL)
1292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT ||
1295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    forward == prev)
1296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward->extension.bNrInPins != 1) {
1299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has"
1300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"more than 1 input pin.\n", entity->id);
1301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1302c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&forward->chain, &video->extensions);
1305c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE) {
1306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (!found)
1307c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" (-> XU");
1308c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1309c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" %d", forward->id);
1310c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			found = 1;
1311c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1312c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1313c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (found)
1314c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(")");
1315c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1316c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1318c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1319c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_scan_chain_backward(struct uvc_video_device *video,
1320c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1322c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id = -1, i;
1324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_EXTENSION_UNIT:
1327c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = entity->extension.baSourceID[0];
1328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_PROCESSING_UNIT:
1331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = entity->processing.bSourceID;
1332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case VC_SELECTOR_UNIT:
1335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
1336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->selector.bNrInPins == 1) {
1337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			id = entity->selector.baSourceID[0];
1338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT");
1343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		video->selector = entity;
1345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < entity->selector.bNrInPins; ++i) {
1346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			id = entity->selector.baSourceID[i];
1347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term = uvc_entity_by_id(video->dev, id);
1348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
1349c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
1350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input %d isn't connected to an "
1351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input terminal\n", entity->id, i);
1352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return -1;
1353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
1356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" %d", term->id);
1357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			list_add_tail(&term->chain, &video->iterms);
1359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_scan_chain_forward(video, term, entity);
1360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("\n");
1364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = 0;
1366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1367c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1369c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return id;
1370c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1371c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1372c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_scan_chain(struct uvc_video_device *video)
1373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1374c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, *prev;
1375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id;
1376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	entity = video->oterm;
1378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
1379ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1380ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (UVC_ENTITY_TYPE(entity) == TT_STREAMING)
1381ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		video->sterm = entity;
1382ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	id = entity->output.bSourceID;
1384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (id != 0) {
1385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		prev = entity;
1386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = uvc_entity_by_id(video->dev, id);
1387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity == NULL) {
1388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
1389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"unknown entity %d.\n", id);
1390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Process entity */
1394c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_scan_chain_entity(video, entity) < 0)
1395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1396c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Forward scan */
1398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_scan_chain_forward(video, entity, prev) < 0)
1399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1401c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Stop when a terminal is found. */
1402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (!UVC_ENTITY_IS_UNIT(entity))
1403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Backward scan */
1406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = uvc_scan_chain_backward(video, entity);
1407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (id < 0)
1408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return id;
1409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1411ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (video->sterm == NULL) {
1412ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in "
1413ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"chain.\n");
1414ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		return -1;
1415ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
1416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1419c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Register the video devices.
1422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The driver currently supports a single video device per control interface
1424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * only. The terminal and units must match the following structure:
1425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1426ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING
1427ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_*
1428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Extension Units, if present, must have a single input pin. The
1430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Processing Unit and Extension Units can be in any order. Additional
1431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Extension Units connected to the main chain as single-unit branches are
1432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * also supported.
1433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_register_video(struct uvc_device *dev)
1435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct video_device *vdev;
1437c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found = 0, ret;
1439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Check if the control interface matches the structure we expect. */
1441c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(term, &dev->entities, list) {
1442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct uvc_streaming *streaming;
1443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1444ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term))
1445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&dev->video, 0, sizeof dev->video);
1448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		mutex_init(&dev->video.ctrl_mutex);
1449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		INIT_LIST_HEAD(&dev->video.iterms);
1450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		INIT_LIST_HEAD(&dev->video.extensions);
1451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->video.oterm = term;
1452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->video.dev = dev;
1453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_scan_chain(&dev->video) < 0)
1454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_for_each_entry(streaming, &dev->streaming, list) {
1457ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			if (streaming->header.bTerminalLink ==
1458ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			    dev->video.sterm->id) {
1459c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->video.streaming = streaming;
1460c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				found = 1;
1461c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
1462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1465c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (found)
1466c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (!found) {
1470c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "No valid video chain found.\n");
1471c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1474c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_trace_param & UVC_TRACE_PROBE) {
1475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Found a valid video chain (");
1476c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_for_each_entry(term, &dev->video.iterms, chain) {
1477c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("%d", term->id);
1478c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term->chain.next != &dev->video.iterms)
1479c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(",");
1480c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(" -> %d).\n", dev->video.oterm->id);
1482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1484ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	/* Initialize the video buffers queue. */
1485ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	uvc_queue_init(&dev->video.queue, dev->video.streaming->type);
1486ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Initialize the streaming interface with default streaming
1488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * parameters.
1489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1490c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_video_init(&dev->video)) < 0) {
1491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_ERR, "Failed to initialize the device "
1492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"(%d).\n", ret);
1493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return ret;
1494c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Register the device with V4L. */
1497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	vdev = video_device_alloc();
1498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (vdev == NULL)
1499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* We already hold a reference to dev->udev. The video device will be
1502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * unregistered before the reference is released, so we don't need to
1503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * get another one.
1504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
15055e85e732f0ed56aa97a3ba26ac2b93ffe597a208Hans Verkuil	vdev->parent = &dev->intf->dev;
1506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	vdev->minor = -1;
1507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	vdev->fops = &uvc_fops;
1508c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	vdev->release = video_device_release;
1509d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart	strlcpy(vdev->name, dev->name, sizeof vdev->name);
1510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the driver data before calling video_register_device, otherwise
1512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * uvc_v4l2_open might race us.
1513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->video.vdev = vdev;
1515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	video_set_drvdata(vdev, &dev->video);
1516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) {
1518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->video.vdev = NULL;
1519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		video_device_release(vdev);
1520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Delete the UVC device.
1528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1529c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Called by the kernel when the last reference to the uvc_device structure
1530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * is released.
1531c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Unregistering the video devices is done here because every opened instance
1533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * must be closed before the device can be unregistered. An alternative would
1534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * have been to use another reference count for uvc_v4l2_open/uvc_release, and
1535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * unregister the video devices on disconnect when that reference count drops
1536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to zero.
1537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
1538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * As this function is called after or during disconnect(), all URBs have
1539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * already been canceled by the USB core. There is no need to kill the
1540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * interrupt URB manually.
1541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_delete(struct kref *kref)
1543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
1545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct list_head *p, *n;
1546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15472c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Unregister the video device. */
1548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_unregister_video(dev);
1549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(dev->intf);
1550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_dev(dev->udev);
1551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_status_cleanup(dev);
1553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_ctrl_cleanup_device(dev);
1554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_safe(p, n, &dev->entities) {
1556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct uvc_entity *entity;
1557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(p, struct uvc_entity, list);
1558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		kfree(entity);
1559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1561c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_safe(p, n, &dev->streaming) {
1562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct uvc_streaming *streaming;
1563c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming = list_entry(p, struct uvc_streaming, list);
1564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver,
1565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->intf);
1566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_put_intf(streaming->intf);
1567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		kfree(streaming->format);
1568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		kfree(streaming->header.bmaControls);
1569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		kfree(streaming);
1570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(dev);
1573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_probe(struct usb_interface *intf,
1576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		     const struct usb_device_id *id)
1577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = interface_to_usbdev(intf);
1579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev;
1580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (id->idVendor && id->idProduct)
1583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
1584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(%04x:%04x)\n", udev->devpath, id->idVendor,
1585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				id->idProduct);
1586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
1588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devpath);
1589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15902c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Allocate memory for the device and initialize it. */
1591c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
1592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
1593c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1594c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->entities);
1595c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->streaming);
1596c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kref_init(&dev->kref);
1597c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1598c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->udev = usb_get_dev(udev);
1599c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intf = usb_get_intf(intf);
1600c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
1601c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->quirks = id->driver_info | uvc_quirks_param;
1602c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1603c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (udev->product != NULL)
1604d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(dev->name, udev->product, sizeof dev->name);
1605c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		snprintf(dev->name, sizeof dev->name,
1607c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"UVC Camera (%04x:%04x)",
1608c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idVendor),
1609c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idProduct));
1610c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16112c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Parse the Video Class control descriptor. */
1612c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_parse_control(dev) < 0) {
1613c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
1614c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptors.\n");
1615c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1616c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1617c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1618fba4578ee925110587ef9b8b6ddfabf2ce288071Laurent Pinchart	uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
1619c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->uvc_version >> 8, dev->uvc_version & 0xff,
1620c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		udev->product ? udev->product : "<unnamed>",
1621c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idVendor),
1622c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idProduct));
1623c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1624c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_quirks_param != 0) {
1625c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module "
1626c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"parameter for testing purpose.\n", uvc_quirks_param);
1627c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Please report required quirks to the "
1628c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"linux-uvc-devel mailing list.\n");
1629c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1630c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16312c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize controls. */
1632c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_ctrl_init_device(dev) < 0)
1633c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1634c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16352c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Register the video devices. */
1636c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_register_video(dev) < 0)
1637c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1638c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16392c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Save our data pointer in the interface data. */
1640c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, dev);
1641c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16422c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize the interrupt URB. */
1643c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_status_init(dev)) < 0) {
1644c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Unable to initialize the status "
1645c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"endpoint (%d), status interrupt will not be "
1646c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"supported.\n", ret);
1647c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1648c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1649c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
1650c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1651c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1652c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
1653c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kref_put(&dev->kref, uvc_delete);
1654c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return -ENODEV;
1655c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1656c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1657c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_disconnect(struct usb_interface *intf)
1658c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1659c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1660c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1661c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the USB interface data to NULL. This can be done outside the
1662c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock, as there's no other reader.
1663c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1664c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, NULL);
1665c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1666c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING)
1667c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
1668c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide
1670c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock is needed to prevent uvc_disconnect from releasing its
1671c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * reference to the uvc_device instance after uvc_v4l2_open() received
1672c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * the pointer to the device (video_devdata) but before it got the
1673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * chance to increase the reference count (kref_get).
1674a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart	 *
1675a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart	 * Note that the reference can't be released with the lock held,
1676a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart	 * otherwise a AB-BA deadlock can occur with videodev_lock that
1677a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart	 * videodev acquires in videodev_open() and video_unregister_device().
1678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1679c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_lock(&uvc_driver.open_mutex);
1680c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->state |= UVC_DEV_DISCONNECTED;
1681c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_unlock(&uvc_driver.open_mutex);
1682a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart
1683a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart	kref_put(&dev->kref, uvc_delete);
1684c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1685c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1686c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_suspend(struct usb_interface *intf, pm_message_t message)
1687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
1691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Controls are cached on the fly so they don't need to be saved. */
1694c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL)
1695c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_suspend(dev);
1696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1697c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (dev->video.streaming->intf != intf) {
1698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB "
1699c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface mismatch.\n");
1700c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
1701c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1702c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1703c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return uvc_video_suspend(&dev->video);
1704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1705c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17069b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int __uvc_resume(struct usb_interface *intf, int reset)
1707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1709c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
1711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
17147564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		if (reset) {
17157564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			int ret = uvc_ctrl_resume_device(dev);
17167564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil
17177564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			if (ret < 0)
17187564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil				return ret;
17197564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		}
1720c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1721c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_resume(dev);
1722c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1723c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1724c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (dev->video.streaming->intf != intf) {
1725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB "
1726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface mismatch.\n");
1727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
1728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1729c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return uvc_video_resume(&dev->video);
1731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17339b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_resume(struct usb_interface *intf)
17349b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
17359b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 0);
17369b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
17379b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
17389b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_reset_resume(struct usb_interface *intf)
17399b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
17409b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 1);
17419b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
17429b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
1743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
1744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Driver initialization and cleanup
1745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1746c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Logitech cameras listed below have their interface class set to
1749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * VENDOR_SPEC because they don't announce themselves as UVC devices, even
1750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * though they are compliant.
1751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct usb_device_id uvc_ids[] = {
1753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam NX-6000 */
1754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x00f8,
1758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam VX-7000 */
1763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0723,
1767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Fusion */
1772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c1,
1776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Orbit MP */
1780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1781c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1783c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c2,
1784c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1785c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1787c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro for Notebook */
1788c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1789c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1790c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1791c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c3,
1792c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1793c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1794c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1795c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro 5000 */
1796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1798c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1799c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c5,
1800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1802c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Dell Notebook */
1804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1805c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c6,
1808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1809c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Cisco VT Camera II */
1812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c7,
1816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1819f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
1820f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1821f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1822f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idVendor		= 0x058f,
1823f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idProduct		= 0x3820,
1824f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1825f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceSubClass	= 1,
1826f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceProtocol	= 0,
1827f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Apple Built-In iSight */
18292c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x05ac,
1832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8501,
18332c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
18342c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
18352c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
1836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
1837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| UVC_QUIRK_BUILTIN_ISIGHT },
1838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Genesys Logic USB 2.0 PC Camera */
18392c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
18412c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idVendor		= 0x05e3,
18422c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idProduct		= 0x0505,
18432c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
18442c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
18452c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
18462c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
184750144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	/* ViMicro */
184850144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_VENDOR
184950144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
185050144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idVendor		= 0x0ac8,
185150144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idProduct		= 0x0000,
185250144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
185350144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceSubClass	= 1,
185450144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceProtocol	= 0,
185550144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
1856c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* MT6227 */
1857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x0e8d,
1860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0004,
1861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (HP Spartan) */
1866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
1869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x5212,
1870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
187325e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
1874562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	/* Syntek (Samsung Q310) */
1875562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1876562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1877562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idVendor		= 0x174f,
1878562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idProduct		= 0x5931,
1879562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1880562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1881562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1882562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
1883f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Syntek (Asus F9SG) */
188425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
188525e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
188625e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idVendor		= 0x174f,
188725e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idProduct		= 0x8a31,
188825e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
188925e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceSubClass	= 1,
189025e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceProtocol	= 0,
1891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
1892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (Asus U3S) */
1893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
1896c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8a33,
1897c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
19010ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	/* Syntek (JAOtech Smart Terminal) */
19020ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
19030ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
19040ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idVendor		= 0x174f,
19050ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idProduct		= 0x8a34,
19060ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
19070ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceSubClass	= 1,
19080ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceProtocol	= 0,
19090ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
19102f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	/* Lenovo Thinkpad SL500 */
19112f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
19122f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
19132f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idVendor		= 0x17ef,
19142f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idProduct		= 0x480b,
19152f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
19162f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceSubClass	= 1,
19172f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceProtocol	= 0,
19182f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
1919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Ecamm Pico iMage */
1920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x18cd,
1923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0xcafe,
1924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
1928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Bodelin ProScopeHR */
1929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_DEV_HI
1931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x19ab,
1933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x1000,
1934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bcdDevice_hi		= 0x0126,
1935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STATUS_INTERVAL },
1939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* SiGma Micro USB Web Camera */
1940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x1c4f,
1943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x3000,
1944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
19482bdd29cf3d4d32e4371fbd6b27ea171f2c1f0836Laurent Pinchart				| UVC_QUIRK_IGNORE_SELECTOR_UNIT
19492bdd29cf3d4d32e4371fbd6b27ea171f2c1f0836Laurent Pinchart				| UVC_QUIRK_PRUNE_CONTROLS },
1950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Generic USB Video Class */
1951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
1952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{}
1953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
1954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1955c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DEVICE_TABLE(usb, uvc_ids);
1956c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct uvc_driver uvc_driver = {
1958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	.driver = {
1959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "uvcvideo",
1960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.probe		= uvc_probe,
1961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.disconnect	= uvc_disconnect,
1962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.suspend	= uvc_suspend,
1963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.resume		= uvc_resume,
19649b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart		.reset_resume	= uvc_reset_resume,
1965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.id_table	= uvc_ids,
1966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.supports_autosuspend = 1,
1967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
1968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
1969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int __init uvc_init(void)
1971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int result;
1973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.devices);
1975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.controls);
1976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&uvc_driver.open_mutex);
1977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&uvc_driver.ctrl_mutex);
1978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_ctrl_init();
1980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	result = usb_register(&uvc_driver.driver);
1982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (result == 0)
1983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
1984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return result;
1985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void __exit uvc_cleanup(void)
1988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_deregister(&uvc_driver.driver);
1990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_init(uvc_init);
1993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_exit(uvc_cleanup);
1994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19950fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent Pinchartmodule_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
19960fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent PinchartMODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
1997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
1998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_PARM_DESC(quirks, "Forced device quirks");
1999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
2000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_PARM_DESC(trace, "Trace level bitmask");
2001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_AUTHOR(DRIVER_AUTHOR);
2003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DESCRIPTION(DRIVER_DESC);
2004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_LICENSE("GPL");
2005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_VERSION(DRIVER_VERSION);
2006f87086e302300fdff1bd32049deb7a7f3e3de7daHans Verkuil
2007