uvc_driver.c revision f129b03ba272c86c42ad476684caa0d6109cb383
1c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      uvc_driver.c  --  USB Video Class driver
3c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
42c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart *      Copyright (C) 2005-2009
5c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *          Laurent Pinchart (laurent.pinchart@skynet.be)
6c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
7c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      This program is free software; you can redistribute it and/or modify
8c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      it under the terms of the GNU General Public License as published by
9c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      the Free Software Foundation; either version 2 of the License, or
10c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      (at your option) any later version.
11c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
13c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
15ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * This driver aims to support video input and ouput devices compliant with the
16ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart * 'USB Video Class' specification.
17c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
18c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The driver doesn't support the deprecated v4l1 interface. It implements the
19c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * mmap capture method only, and doesn't do any image format conversion in
20c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * software. If your user-space application doesn't support YUYV or MJPEG, fix
21c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * it :-). Please note that the MJPEG data have been stripped from their
22c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Huffman tables (DHT marker), you will need to add it back if your JPEG
23c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * codec can't handle MJPEG data.
24c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
25c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
26c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/kernel.h>
27c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/list.h>
28c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/module.h>
295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
30c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb.h>
31c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/videodev2.h>
32c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/vmalloc.h>
33c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/wait.h>
34c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <asm/atomic.h>
359bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich#include <asm/unaligned.h>
36c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
37c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <media/v4l2-common.h>
38c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
39c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include "uvcvideo.h"
40c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
41c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_AUTHOR		"Laurent Pinchart <laurent.pinchart@skynet.be>"
42c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_DESC		"USB Video Class driver"
43c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#ifndef DRIVER_VERSION
44c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_VERSION		"v0.1.0"
45c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#endif
46c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
47310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartunsigned int uvc_clock_param = CLOCK_MONOTONIC;
480fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent Pinchartunsigned int uvc_no_drop_param;
4973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchartstatic unsigned int uvc_quirks_param = -1;
50c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartunsigned int uvc_trace_param;
51b232a012adfea9f535702e8296ea6b76e691f436Laurent Pinchartunsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
52c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
53c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
542c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * Video formats
55c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
56c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
57c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc uvc_fmts[] = {
58c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
59c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (YUYV)",
60c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YUY2,
61c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUYV,
62c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
63c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
6468f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.name		= "YUV 4:2:2 (YUYV)",
6568f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.guid		= UVC_GUID_FORMAT_YUY2_ISIGHT,
6668f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.fcc		= V4L2_PIX_FMT_YUYV,
6768f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	},
6868f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	{
69c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (NV12)",
70c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_NV12,
71c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_NV12,
72c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
73c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
74c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "MJPEG",
75c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_MJPEG,
76c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_MJPEG,
77c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
78c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
79c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YVU 4:2:0 (YV12)",
80c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YV12,
81c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YVU420,
82c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
83c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
84c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (I420)",
85c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_I420,
86c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUV420,
87c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
88c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
89c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (UYVY)",
90c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_UYVY,
91c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_UYVY,
92c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
93c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
94c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "Greyscale",
95c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y800,
96c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_GREY,
97c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
98c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
99c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "RGB Bayer",
100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_BY8,
101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_SBGGR8,
102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Utility functions
107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		__u8 epaddr)
111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep;
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = &alts->endpoint[i];
117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep->desc.bEndpointAddress == epaddr)
118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ep;
119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int len = ARRAY_SIZE(uvc_fmts);
127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < len; ++i) {
130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return &uvc_fmts[i];
132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic __u32 uvc_colorspace(const __u8 primaries)
138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	static const __u8 colorprimaries[] = {
140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		0,
141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SRGB,
142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_M,
143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_BG,
144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE170M,
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE240M,
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	};
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (primaries < ARRAY_SIZE(colorprimaries))
149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return colorprimaries[primaries];
150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Simplify a fraction using a simple continued fraction decomposition. The
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * idea here is to convert fractions such as 333333/10000000 to 1/30 using
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arbitrary parameters to remove non-significative terms from the simple
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * respectively seems to give nice results.
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unsigned int n_terms, unsigned int threshold)
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t *an;
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t x, y, r;
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (an == NULL)
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Convert the fraction to a simple continued fraction. See
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * http://mathforum.org/dr.math/faq/faq.fractions.html
174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * Stop if the current term is bigger than or equal to the given
175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * threshold.
176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = *numerator;
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = *denominator;
179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (n = 0; n < n_terms && y != 0; ++n) {
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		an[n] = x / y;
182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (an[n] >= threshold) {
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (n < 2)
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				n++;
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = x - an[n] * y;
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = y;
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = r;
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Expand the simple continued fraction back to an integer fraction. */
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = 0;
195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = 1;
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = n; i > 0; --i) {
198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = y;
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = an[i-1] * y + x;
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = r;
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*numerator = y;
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*denominator = x;
205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(an);
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to compute numerator / denominator * 10000000 using 32 bit fixed point
210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arithmetic only.
211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartuint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t multiplier;
215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Saturate the result if the operation would overflow. */
217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (denominator == 0 ||
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    numerator/denominator >= ((uint32_t)-1)/10000000)
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return (uint32_t)-1;
220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Divide both the denominator and the multiplier by two until
222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * numerator * multiplier doesn't overflow. If anyone knows a better
223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * algorithm please let me know.
224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	multiplier = 10000000;
226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (numerator > ((uint32_t)-1)/multiplier) {
227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		multiplier /= 2;
228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		denominator /= 2;
229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return denominator ? numerator * multiplier / denominator : 0;
232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Terminal and unit management
236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity;
241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(entity, &dev->entities, list) {
243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->id == id)
244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return entity;
245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id, struct uvc_entity *entity)
252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (entity == NULL)
256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(&dev->entities, struct uvc_entity, list);
257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry_continue(entity, &dev->entities, list) {
2598ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i)
2608ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (entity->baSourceID[i] == id)
261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
2688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
2698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
2708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
2728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->header.bTerminalLink == id)
2738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return stream;
2748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
2758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return NULL;
2778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
2788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
2808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Descriptors parsing
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]) {
300b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_UNCOMPRESSED:
301b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_FRAME_BASED:
302b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
303233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		if (buflen < n) {
304b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent 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 {
31936bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
32036bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
32136bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			snprintf(format->name, sizeof(format->name), "%pUl\n",
32236bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = 0;
324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = buffer[21];
327b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
328b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_UNCOMPRESSED;
329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
330b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_FRAME_BASED;
331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (buffer[27])
332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				format->flags = UVC_FMT_FLAG_COMPRESSED;
333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
336b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MJPEG:
337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 11) {
338b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
345d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(format->name, "MJPEG", sizeof format->name);
346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_MJPEG;
347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED;
348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
349b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		ftype = UVC_VS_FRAME_MJPEG;
350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
352b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_DV:
353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
354b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[8] & 0x7f) {
362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 0:
363d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SD-DV", sizeof format->name);
364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 1:
366d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SDL-DV", sizeof format->name);
367c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 2:
369d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "HD-DV", sizeof format->name);
370c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
371c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
372b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d: unknown DV format %u\n",
374c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber, buffer[8]);
376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
379d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sizeof format->name);
381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_DV;
383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = 0;
386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Create a dummy frame descriptor. */
388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame = &format->frame[0];
389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&format->frame[0], 0, sizeof format->frame[0]);
390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIntervalType = 1;
391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval = 1;
392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		*(*intervals)++ = 1;
394c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->nframes = 1;
395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
396c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
397b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MPEG2TS:
398b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_STREAM_BASED:
399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Not supported yet. */
400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
401b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       "interface %d unsupported format %u\n",
403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       dev->udev->devnum, alts->desc.bInterfaceNumber,
404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       buffer[2]);
405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
411c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
414c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * based formats have frame descriptors.
415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
416c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
417c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	       buffer[2] == ftype) {
418078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		frame = &format->frame[format->nframes];
419b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_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) {
427b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent 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]);
439b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_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
494c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
495c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
500c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
501c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_COLORFORMAT) {
502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 6) {
503b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d COLORFORMAT error\n",
505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
508c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->colorspace = uvc_colorspace(buffer[3]);
511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return buffer - start;
517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_streaming(struct uvc_device *dev,
520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf)
521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming = NULL;
523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format *format;
524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = &intf->altsetting[0];
526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *_buffer, *buffer = alts->extra;
527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int _buflen, buflen = alts->extralen;
528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int nformats = 0, nframes = 0, nintervals = 0;
529c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int size, i, n, p;
530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 *interval;
531c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 psize;
532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret = -EINVAL;
533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass
535b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		!= UVC_SC_VIDEOSTREAMING) {
536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"video streaming interface\n", dev->udev->devnum,
538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"claimed\n", dev->udev->devnum,
545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (streaming == NULL) {
551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver, intf);
552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&streaming->mutex);
55635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	streaming->dev = dev;
557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intf = usb_get_intf(intf);
558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* The Pico iMage webcam has its class-specific interface descriptors
561c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * after the endpoint descriptors.
562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
563c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen == 0) {
564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			struct usb_host_endpoint *ep = &alts->endpoint[i];
566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen == 0)
568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen > 2 &&
571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    ep->extra[1] == USB_DT_CS_INTERFACE) {
572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "trying extra data "
573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"from endpoint %u.\n", i);
574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer = alts->endpoint[i].extra;
575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buflen = alts->endpoint[i].extralen;
576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Skip the standard interface descriptors. */
582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen <= 2) {
588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"interface descriptors found.\n");
590c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
591c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
593c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the header descriptor. */
594ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	switch (buffer[2]) {
595b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_OUTPUT_HEADER:
596ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
597ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 9;
598ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
599ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
600b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_INPUT_HEADER:
601ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
602ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 13;
603ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
604ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
605ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	default:
606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
607ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"%d HEADER descriptor not found.\n", dev->udev->devnum,
608ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			alts->desc.bInterfaceNumber);
609c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
610ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
611c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
612ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	p = buflen >= 4 ? buffer[3] : 0;
613ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	n = buflen >= size ? buffer[size-1] : 0;
614ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
615ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buflen < size + p*n) {
616ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
617ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"interface %d HEADER descriptor is invalid.\n",
618ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
619ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		goto error;
620ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
621c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
622ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bNumFormats = p;
623ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bEndpointAddress = buffer[6];
624b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (buffer[2] == UVC_VS_INPUT_HEADER) {
625c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bmInfo = buffer[7];
626c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTerminalLink = buffer[8];
627c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bStillCaptureMethod = buffer[9];
628c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerSupport = buffer[10];
629c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerUsage = buffer[11];
630c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
631ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->header.bTerminalLink = buffer[7];
632ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
633ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bControlSize = n;
634ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
635ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
636ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (streaming->header.bmaControls == NULL) {
637ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		ret = -ENOMEM;
638c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
639c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
640c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
641ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	memcpy(streaming->header.bmaControls, &buffer[size], p*n);
642ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
643c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
644c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
645c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
646c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buffer = buffer;
647c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buflen = buflen;
648c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
649c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Count the format and frame descriptors. */
650042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
651c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (_buffer[2]) {
652b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
653b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
654b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
655c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
656c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
657c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
658b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
659c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			/* DV format has no frame descriptor. We will create a
660c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 * dummy frame descriptor with a dummy frame interval.
661c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 */
662c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
663c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
664c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nintervals++;
665c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
666c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
667b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MPEG2TS:
668b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_STREAM_BASED:
669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
670c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d FORMAT %u is not supported.\n",
671c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->udev->devnum,
672c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, _buffer[2]);
673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
674c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
675b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_UNCOMPRESSED:
676b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_MJPEG:
677c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 25)
679c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[25] ? _buffer[25] : 3;
680c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
681c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
682b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_FRAME_BASED:
683c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
684c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 21)
685c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[21] ? _buffer[21] : 3;
686c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buflen -= _buffer[0];
690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buffer += _buffer[0];
691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (nformats == 0) {
694c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
695c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"%d has no supported formats defined.\n",
696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
697c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
699c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
700c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	size = nformats * sizeof *format + nframes * sizeof *frame
701c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	     + nintervals * sizeof *interval;
702c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format = kzalloc(size, GFP_KERNEL);
703c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (format == NULL) {
704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ret = -ENOMEM;
705c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
706c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	frame = (struct uvc_frame *)&format[nformats];
709c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = (__u32 *)&frame[nframes];
710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->format = format;
712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->nformats = nformats;
713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
714c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the format descriptors. */
715042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
716c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[2]) {
717b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
718b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
719b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
720b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
721c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->frame = frame;
722c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret = uvc_parse_format(dev, streaming, format,
723c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				&interval, buffer, buflen);
724c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ret < 0)
725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				goto error;
726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame += format->nframes;
728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format++;
729c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buflen -= ret;
731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buffer += ret;
732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
742c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen)
743c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
744c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			"%d has %u bytes of trailing descriptor garbage.\n",
745c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
746c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart
747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the alternate settings to find the maximum bandwidth. */
748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < intf->num_altsetting; ++i) {
749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep;
750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		alts = &intf->altsetting[i];
751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = uvc_find_endpoint(alts,
752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				streaming->header.bEndpointAddress);
753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep == NULL)
754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = le16_to_cpu(ep->desc.wMaxPacketSize);
757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (psize > streaming->maxpsize)
759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->maxpsize = psize;
760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
76235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_add_tail(&streaming->list, &dev->streams);
763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_driver_release_interface(&uvc_driver.driver, intf);
767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(intf);
768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->format);
769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->header.bmaControls);
770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming);
771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
7748ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchartstatic struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
7758ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unsigned int num_pads, unsigned int extra_size)
7768ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart{
7778ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	struct uvc_entity *entity;
7788ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int num_inputs;
7798ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int size;
7808ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7818ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
7828ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	size = sizeof(*entity) + extra_size + num_inputs;
7838ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity = kzalloc(size, GFP_KERNEL);
7848ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	if (entity == NULL)
7858ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		return NULL;
7868ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7878ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->id = id;
7888ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->type = type;
7898ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7908ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->bNrInPins = num_inputs;
7918ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size;
7928ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
7938ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	return entity;
7948ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart}
7958ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Parse vendor-specific extensions. */
797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_vendor_control(struct uvc_device *dev,
798c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
799c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
802c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit;
803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int n, p;
804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int handled = 0;
805c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0x046d:		/* Logitech */
808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[1] != 0x41 || buffer[2] != 0x01)
809c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Logitech implements several vendor specific functions
812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * through vendor specific extension units (LXU).
813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * The LXU descriptors are similar to XU descriptors
815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * (see "USB Device Video Class for Video Devices", section
816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 3.7.2.6 "Extension Unit Descriptor") with the following
817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * differences:
818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 0		bLength		1	 Number
821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Size of this descriptor, in bytes: 24+p+n*2
822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n	bmControlsType	N	Bitmap
824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	Individual bits in the set are defined:
825c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	0: Absolute
826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	1: Relative
827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	This bitset is mapped exactly the same as bmControls.
829c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n*2	bReserved	1	Boolean
831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 24+p+n*2	iExtension	1	Index
833c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Index of a string descriptor that describes this
834c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	extension unit.
835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 25 + p ? buffer[22+p] : 0;
839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 25 + p + 2*n) {
841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8478ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
8488ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					p + 1, 2*n);
849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
851c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
852c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
8548ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
8568ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
8578ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
8588ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					       + n;
859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[24+p+2*n] != 0)
862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[24+p+2*n], unit->name,
863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		handled = 1;
869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return handled;
873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_standard_control(struct uvc_device *dev,
876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit, *term;
880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf;
881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n, p, len;
883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 type;
884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
886b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_HEADER:
887c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 12 ? buffer[11] : 0;
888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 12 || buflen < 12 + n) {
890c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d HEADER error\n", udev->devnum,
892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber);
893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8969bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->uvc_version = get_unaligned_le16(&buffer[3]);
8979bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->clock_frequency = get_unaligned_le32(&buffer[7]);
898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Parse all USB Video Streaming interfaces. */
900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf = usb_ifnum_to_if(udev, buffer[12+i]);
902c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (intf == NULL) {
903c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "device %d "
904c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"interface %d doesn't exists\n",
905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					udev->devnum, i);
906c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
907c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
909c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_parse_streaming(dev, intf);
910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
913b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_INPUT_TERMINAL:
914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 8) {
915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
917c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
9249bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL %d has invalid "
928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber,
930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer[3], type);
931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = 0;
935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = 0;
936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		len = 8;
937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
938b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (type == UVC_ITT_CAMERA) {
939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 15 ? buffer[14] : 0;
940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 15;
941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
942b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 9 ? buffer[8] : 0;
944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			p = buflen >= 10 + n ? buffer[9+n] : 0;
945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 10;
946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < len + n + p) {
949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9558ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
9568ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, n + p);
957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
960b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bControlSize = n;
962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bmControls = (__u8 *)term + sizeof *term;
963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMin =
9649bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[8]);
965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMax =
9669bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[10]);
967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wOcularFocalLength =
9689bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[12]);
969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->camera.bmControls, &buffer[15], n);
970b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (UVC_ENTITY_TYPE(term) ==
971b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			   UVC_ITT_MEDIA_TRANSPORT_INPUT) {
972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bControlSize = n;
973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmControls = (__u8 *)term + sizeof *term;
974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bTransportModeSize = p;
975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmTransportModes = (__u8 *)term
976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart						     + sizeof *term + n;
977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmControls, &buffer[9], n);
978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[7] != 0)
982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[7], term->name,
983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
984b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Camera %u", buffer[3]);
986b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Media %u", buffer[3]);
988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Input %u", buffer[3]);
990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
994b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_OUTPUT_TERMINAL:
995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL error\n",
998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
1003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
1004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
10059bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
1006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
1007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL %d has invalid "
1009c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
1010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, buffer[3], type);
1011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
1012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10148ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
10158ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, 0);
1016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
1017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10198ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(term->baSourceID, &buffer[7], 1);
1020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8] != 0)
1022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8], term->name,
1023c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1025c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Output %u", buffer[3]);
1026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1027c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1029c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1030b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1031c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 5 ? buffer[4] : 0;
1032c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1033c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 5 || buflen < 6 + p) {
1034c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1035c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d SELECTOR_UNIT error\n",
1036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1039c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10408ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
1041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1043c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10448ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[5], p);
1045c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[5+p] != 0)
1047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[5+p], unit->name,
1048c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1049c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Selector %u", buffer[3]);
1051c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1052c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1053c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1054c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1055b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1056c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 8 ? buffer[7] : 0;
1057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = dev->uvc_version >= 0x0110 ? 10 : 9;
1058c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1059c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < p + n) {
1060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d PROCESSING_UNIT error\n",
1062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1064c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10668ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
1067c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1068c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1069c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10708ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[4], 1);
1071c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.wMaxMultiplier =
10729bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			get_unaligned_le16(&buffer[5]);
1073c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bControlSize = buffer[7];
1074c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
1075c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->processing.bmControls, &buffer[8], n);
1076c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->uvc_version >= 0x0110)
1077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			unit->processing.bmVideoStandards = buffer[9+n];
1078c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1079c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8+n] != 0)
1080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8+n], unit->name,
1081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Processing %u", buffer[3]);
1084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1088b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
1090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 24 + p ? buffer[22+p] : 0;
1091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 24 + p + n) {
1093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
1095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10998ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
1100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
1104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
11058ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
1106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
11078ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
1108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], n);
1109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[23+p+n] != 0)
1111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[23+p+n], unit->name,
1112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
1115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
1121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptor (%u)\n", buffer[2]);
1122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_control(struct uvc_device *dev)
1129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
1131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *buffer = alts->extra;
1132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int buflen = alts->extralen;
1133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the default alternate setting only, as the UVC specification
1136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * defines a single alternate setting, the default alternate setting
1137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * zero.
1138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
1141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_parse_vendor_control(dev, buffer, buflen) ||
1142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    buffer[1] != USB_DT_CS_INTERFACE)
1143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			goto next_descriptor;
1144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
1146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ret;
1147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartnext_descriptor:
1149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
1150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
1151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1153538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	/* Check if the optional status endpoint is present. Built-in iSight
1154538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * webcams have an interrupt endpoint but spit proprietary data that
1155538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * don't conform to the UVC status endpoint messages. Don't try to
1156538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * handle the interrupt endpoint for those cameras.
1157538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 */
1158538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	if (alts->desc.bNumEndpoints == 1 &&
1159538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	    !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
1160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep = &alts->endpoint[0];
1161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_endpoint_descriptor *desc = &ep->desc;
1162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (usb_endpoint_is_int_in(desc) &&
1164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
1165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    desc->bInterval != 0) {
1166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
1167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(addr %02x).\n", desc->bEndpointAddress);
1168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->int_ep = ep;
1169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
11768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * UVC device scan
1177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Scan the UVC descriptors to locate a chain starting at an Output Terminal
1181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * and containing the following units:
1182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
11838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - one or more Output Terminals (USB Streaming or Display)
1184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one Processing Unit
11858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - zero, one or more single-input Selector Units
1186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one multiple-input Selector Units, provided all inputs are
1187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *   connected to input terminals
1188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Extension Units
11892c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one or more Input Terminals (Camera, External or USB Streaming)
1190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
11918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The terminal and units must match on of the following structures:
11928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
11938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
11948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
11958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
11968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
11978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(0)
11988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
11998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(n)
12008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The Processing Unit and Extension Units can be in any order. Additional
12028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Extension Units connected to the main chain as single-unit branches are
12038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * also supported. Single-input Selector Units are ignored.
1204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
12058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_entity(struct uvc_video_chain *chain,
1206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1209b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- XU %d", entity->id);
1212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12138ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins != 1) {
1214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
1215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"than 1 input pin.\n", entity->id);
1216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1221b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- PU %d", entity->id);
1224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->processing != NULL) {
1226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
1227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Processing Units in chain.\n");
1228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->processing = entity;
1232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1234b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- SU %d", entity->id);
1237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
12398ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1)
1240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->selector != NULL) {
1243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
1244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Units in chain.\n");
1245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
1249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1251b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
1252b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_CAMERA:
1253b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
1254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1259b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_TT_STREAMING:
12604057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (UVC_ENTITY_IS_ITERM(entity)) {
12614057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
12624057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" <- IT %d\n", entity->id);
12634057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		} else {
12644057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
12654057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" OT %d", entity->id);
1266ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1267ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1268ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
1269ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
1273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12766241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_add_tail(&entity->chain, &chain->entities);
1277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_forward(struct uvc_video_chain *chain,
1281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, struct uvc_entity *prev)
1282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *forward;
1284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found;
1285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Forward scan */
1287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	forward = NULL;
1288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	found = 0;
1289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (1) {
12918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		forward = uvc_entity_by_reference(chain->dev, entity->id,
1292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			forward);
1293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward == NULL)
1294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
12958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (forward == prev)
1296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		switch (UVC_ENTITY_TYPE(forward)) {
12998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_VC_EXTENSION_UNIT:
13008ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (forward->bNrInPins != 1) {
13018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
13028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  "has more than 1 input pin.\n",
13038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  entity->id);
13048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13076241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" XU %d", forward->id);
13138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
13168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_VENDOR_SPECIFIC:
13188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_DISPLAY:
13198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_TT_STREAMING:
13218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (UVC_ENTITY_IS_ITERM(forward)) {
13228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
13238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					"terminal %u.\n", forward->id);
13248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13276241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" OT %d", forward->id);
13338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
1336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (found)
1339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(")");
1340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_backward(struct uvc_video_chain *chain,
13454057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity **_entity)
1346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
13474057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity *entity = *_entity;
1348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
13494057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	int id = -EINVAL, i;
1350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1352b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1353b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
13548ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = entity->baSourceID[0];
1355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1357b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
13598ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1) {
13608ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[0];
1361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT");
1366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
13688ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i) {
13698ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[i];
13708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			term = uvc_entity_by_id(chain->dev, id);
1371c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
1372c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
1373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input %d isn't connected to an "
1374c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input terminal\n", entity->id, i);
1375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return -1;
1376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
1379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" %d", term->id);
1380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13816241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&term->chain, &chain->entities);
13828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_scan_chain_forward(chain, term, entity);
1383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("\n");
1387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = 0;
1389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
13904057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
13914057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
13924057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_CAMERA:
13934057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
13944057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
13954057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_DISPLAY:
13964057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13974057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_TT_STREAMING:
13988ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
13994057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		break;
1400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1401c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14024057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (id <= 0) {
14034057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		*_entity = NULL;
14044057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return id;
14054057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14064057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14074057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = uvc_entity_by_id(chain->dev, id);
14084057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (entity == NULL) {
14094057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14104057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			"unknown entity %d.\n", id);
14114057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return -EINVAL;
14124057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14134057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14144057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	*_entity = entity;
14154057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	return 0;
1416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain(struct uvc_video_chain *chain,
14194057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			  struct uvc_entity *term)
1420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, *prev;
1422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14234057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
1424ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
14254057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = term;
14264057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	prev = NULL;
14278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14284057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	while (entity != NULL) {
14294057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		/* Entity must not be part of an existing chain */
14308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (entity->chain.next || entity->chain.prev) {
14318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14324057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				"entity %d already in chain.\n", entity->id);
14338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Process entity */
14378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_entity(chain, entity) < 0)
14388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Forward scan */
14418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_forward(chain, entity, prev) < 0)
14428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Backward scan */
14454057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		prev = entity;
14464057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (uvc_scan_chain_backward(chain, &entity) < 0)
14474057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			return -EINVAL;
1448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
14518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
14528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14536241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchartstatic unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
14546241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		char *buffer)
14558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
14568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
14578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	unsigned int nterms = 0;
14588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
14598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(term, terms, chain) {
14616241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (!UVC_ENTITY_IS_TERM(term) ||
14626241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		    UVC_TERM_DIRECTION(term) != dir)
14636241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			continue;
14646241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart
14656241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (nterms)
14668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			p += sprintf(p, ",");
14676241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (++nterms >= 4) {
14686241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			p += sprintf(p, "...");
14696241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			break;
14708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
14716241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		p += sprintf(p, "%u", term->id);
1472ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
1473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return p - buffer;
14758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
14768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic const char *uvc_print_chain(struct uvc_video_chain *chain)
14788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
14798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	static char buffer[43];
14808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
14818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14826241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
14838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	p += sprintf(p, " -> ");
14846241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
14858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return buffer;
1487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
149035f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart * Scan the device for video chains and register video devices.
1491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
14928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Chains are scanned starting at their output terminals and walked backwards.
1493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
149435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchartstatic int uvc_scan_device(struct uvc_device *dev)
1495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
14968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
1497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(term, &dev->entities, list) {
15008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (!UVC_ENTITY_IS_OTERM(term))
1501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		/* If the terminal is already included in a chain, skip it.
15048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * This can happen for chains that have multiple output
15058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * terminals, where all output terminals beside the first one
15068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * will be inserted in the chain in forward scans.
15078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 */
15088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (term->chain.next || term->chain.prev)
1509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
15128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain == NULL)
15138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -ENOMEM;
15148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15156241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		INIT_LIST_HEAD(&chain->entities);
15168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		mutex_init(&chain->ctrl_mutex);
15178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->dev = dev;
15188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain(chain, term) < 0) {
15208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			kfree(chain);
15218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
1522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
15238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
15258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			  uvc_print_chain(chain));
15268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		list_add_tail(&chain->list, &dev->chains);
1528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1529c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (list_empty(&dev->chains)) {
1531c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "No valid video chain found.\n");
1532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
15398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Video device registration and unregistration
15408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
15418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
1543716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Delete the UVC device.
1544716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1545716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Called by the kernel when the last reference to the uvc_device structure
1546716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * is released.
1547716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1548716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * As this function is called after or during disconnect(), all URBs have
1549716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * already been canceled by the USB core. There is no need to kill the
1550716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * interrupt URB manually.
1551716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart */
1552716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_delete(struct uvc_device *dev)
1553716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1554716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct list_head *p, *n;
1555716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1556716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_intf(dev->intf);
1557716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_dev(dev->udev);
1558716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1559716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_status_cleanup(dev);
1560716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_ctrl_cleanup_device(dev);
1561716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1562716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->chains) {
1563716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_video_chain *chain;
1564716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		chain = list_entry(p, struct uvc_video_chain, list);
1565716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(chain);
1566716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1567716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1568716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->entities) {
1569716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_entity *entity;
1570716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		entity = list_entry(p, struct uvc_entity, list);
1571716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(entity);
1572716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1573716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1574716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->streams) {
1575716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_streaming *streaming;
1576716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		streaming = list_entry(p, struct uvc_streaming, list);
1577716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_driver_release_interface(&uvc_driver.driver,
1578716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart			streaming->intf);
1579716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_put_intf(streaming->intf);
1580716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->format);
1581716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->header.bmaControls);
1582716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming);
1583716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1584716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1585716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	kfree(dev);
1586716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1587716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1588716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_release(struct video_device *vdev)
1589716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1590716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_streaming *stream = video_get_drvdata(vdev);
1591716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_device *dev = stream->dev;
1592716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1593716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	video_device_release(vdev);
1594716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1595716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the registered streams count and delete the device when it
1596716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * reaches zero.
1597716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1598716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1599716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
1600716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1601716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1602716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart/*
16038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Unregister the video devices.
16048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic void uvc_unregister_video(struct uvc_device *dev)
16068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1609716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Unregistering all video devices might result in uvc_delete() being
1610716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * called from inside the loop if there's no open file handle. To avoid
1611716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * that, increment the stream count before iterating over the streams
1612716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * and decrement it when done.
1613716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1614716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
1615716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
16178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->vdev == NULL)
16188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
16198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1620716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		video_unregister_device(stream->vdev);
16218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
16228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
1623716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1624716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the stream count and call uvc_delete explicitly if there
1625716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * are no stream left.
1626716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1627716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1628716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
16298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
16308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_video(struct uvc_device *dev,
16328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		struct uvc_streaming *stream)
16338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct video_device *vdev;
16358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
16368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Initialize the streaming interface with default streaming
16388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * parameters.
16398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = uvc_video_init(stream);
16418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
16428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to initialize the device "
16438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			"(%d).\n", ret);
16448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
16458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register the device with V4L. */
16488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev = video_device_alloc();
16498e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (vdev == NULL) {
16508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
16518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
16528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return -ENOMEM;
16538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* We already hold a reference to dev->udev. The video device will be
16568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * unregistered before the reference is released, so we don't need to
16578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * get another one.
16588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->parent = &dev->intf->dev;
16608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->fops = &uvc_fops;
1661716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	vdev->release = uvc_release;
16628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	strlcpy(vdev->name, dev->name, sizeof vdev->name);
16638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Set the driver data before calling video_register_device, otherwise
16658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * uvc_v4l2_open might race us.
16668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
16678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	stream->vdev = vdev;
16688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	video_set_drvdata(vdev, stream);
16698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
16718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
16728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
16738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
16748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
16758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		video_device_release(vdev);
16768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
16778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
16788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1679716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
16808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
16818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
16828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
16848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Register all video devices in all chains.
16858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_terms(struct uvc_device *dev,
16876241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	struct uvc_video_chain *chain)
16888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
16918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
16928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16936241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_for_each_entry(term, &chain->entities, chain) {
16948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
16958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
16968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream = uvc_stream_by_id(dev, term->id);
16988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream == NULL) {
16998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_printk(KERN_INFO, "No streaming interface found "
17008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				   "for terminal %u.", term->id);
17018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
17038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->chain = chain;
17058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		ret = uvc_register_video(dev, stream);
17068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_chains(struct uvc_device *dev)
17148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
17168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(chain, &dev->chains, list) {
17196241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		ret = uvc_register_terms(dev, chain);
17208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
17288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * USB probe, disconnect, suspend and resume
17298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
17308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_probe(struct usb_interface *intf,
1732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		     const struct usb_device_id *id)
1733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = interface_to_usbdev(intf);
1735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev;
1736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (id->idVendor && id->idProduct)
1739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
1740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(%04x:%04x)\n", udev->devpath, id->idVendor,
1741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				id->idProduct);
1742c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
1744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devpath);
1745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17462c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Allocate memory for the device and initialize it. */
1747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
1748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
1749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->entities);
17518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	INIT_LIST_HEAD(&dev->chains);
175235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	INIT_LIST_HEAD(&dev->streams);
1753716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_set(&dev->nstreams, 0);
175404a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart	atomic_set(&dev->users, 0);
1755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->udev = usb_get_dev(udev);
1757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intf = usb_get_intf(intf);
1758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
175973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	dev->quirks = (uvc_quirks_param == -1)
176073de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		    ? id->driver_info : uvc_quirks_param;
1761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (udev->product != NULL)
1763d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(dev->name, udev->product, sizeof dev->name);
1764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		snprintf(dev->name, sizeof dev->name,
1766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"UVC Camera (%04x:%04x)",
1767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idVendor),
1768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idProduct));
1769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17702c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Parse the Video Class control descriptor. */
1771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_parse_control(dev) < 0) {
1772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
1773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptors.\n");
1774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1777fba4578ee925110587ef9b8b6ddfabf2ce288071Laurent Pinchart	uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
1778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->uvc_version >> 8, dev->uvc_version & 0xff,
1779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		udev->product ? udev->product : "<unnamed>",
1780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idVendor),
1781c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idProduct));
1782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
178373de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	if (dev->quirks != id->driver_info) {
178473de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
178573de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart			"parameter for testing purpose.\n", dev->quirks);
1786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Please report required quirks to the "
1787c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"linux-uvc-devel mailing list.\n");
1788c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1789c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17902c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize controls. */
1791c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_ctrl_init_device(dev) < 0)
1792c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1793c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Scan the device for video chains. */
179535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	if (uvc_scan_device(dev) < 0)
1796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
17988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register video devices. */
17998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (uvc_register_chains(dev) < 0)
18008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		goto error;
18018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18022c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Save our data pointer in the interface data. */
1803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, dev);
1804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18052c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize the interrupt URB. */
1806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_status_init(dev)) < 0) {
1807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Unable to initialize the status "
1808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"endpoint (%d), status interrupt will not be "
1809c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"supported.\n", ret);
1810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
1813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
1816716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return -ENODEV;
1818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_disconnect(struct usb_interface *intf)
1821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the USB interface data to NULL. This can be done outside the
1825c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock, as there's no other reader.
1826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, NULL);
1828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1829b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1830b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOSTREAMING)
1831c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
1832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1833c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->state |= UVC_DEV_DISCONNECTED;
1834a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart
1835716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_suspend(struct usb_interface *intf, pm_message_t message)
1839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
184135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
1844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Controls are cached on the fly so they don't need to be saved. */
1847b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1848b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL)
1849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_suspend(dev);
1850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
185135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
185235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
185335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_suspend(stream);
1854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
185635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
185735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
185835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18619b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int __uvc_resume(struct usb_interface *intf, int reset)
1862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
186435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
1867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1869b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1870b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
18717564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		if (reset) {
18727564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			int ret = uvc_ctrl_resume_device(dev);
18737564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil
18747564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			if (ret < 0)
18757564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil				return ret;
18767564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		}
1877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return uvc_status_resume(dev);
1879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
188135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
188235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
188335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_resume(stream);
1884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
188635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
188735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
188835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1890c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18919b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_resume(struct usb_interface *intf)
18929b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
18939b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 0);
18949b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
18959b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
18969b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_reset_resume(struct usb_interface *intf)
18979b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
18989b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 1);
18999b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
19009b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
1901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
1902310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart * Module parameters
1903310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart */
1904310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1905310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
1906310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
1907310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (uvc_clock_param == CLOCK_MONOTONIC)
1908310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_MONOTONIC");
1909310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
1910310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_REALTIME");
1911310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
1912310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1913310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_set(const char *val, struct kernel_param *kp)
1914310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
1915310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
1916310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		val += strlen("clock_");
1917310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1918310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strcasecmp(val, "monotonic") == 0)
1919310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_MONOTONIC;
1920310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else if (strcasecmp(val, "realtime") == 0)
1921310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_REALTIME;
1922310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
1923310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return -EINVAL;
1924310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1925310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	return 0;
1926310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
1927310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1928310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
1929310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		  &uvc_clock_param, S_IRUGO|S_IWUSR);
1930310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(clock, "Video buffers timestamp clock");
1931310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
1932310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
1933310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
1934310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(quirks, "Forced device quirks");
1935310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
1936310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(trace, "Trace level bitmask");
1937310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
1938310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(timeout, "Streaming control requests timeout");
1939310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
1940310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart/* ------------------------------------------------------------------------
1941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Driver initialization and cleanup
1942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Logitech cameras listed below have their interface class set to
1946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * VENDOR_SPEC because they don't announce themselves as UVC devices, even
1947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * though they are compliant.
1948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct usb_device_id uvc_ids[] = {
1950bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	/* Genius eFace 2025 */
1951bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1952bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1953bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idVendor		= 0x0458,
1954bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idProduct		= 0x706e,
1955bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1956bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceSubClass	= 1,
1957bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceProtocol	= 0,
1958bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam NX-6000 */
1960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x00f8,
1964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam VX-7000 */
1969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
1972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0723,
1973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
1974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
1976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
1977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Fusion */
1978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c1,
1982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Orbit MP */
1986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c2,
1990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
1992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
1993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro for Notebook */
1994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
1995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
1996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
1997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c3,
1998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
1999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro 5000 */
2002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c5,
2006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2009c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Dell Notebook */
2010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c6,
2014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Cisco VT Camera II */
2018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2019c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c7,
2022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2023c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2025f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
2026f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2027f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2028f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idVendor		= 0x058f,
2029f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idProduct		= 0x3820,
2030f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2031f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2032f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2033f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2034c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Apple Built-In iSight */
20352c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x05ac,
2038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8501,
20392c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20402c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
20412c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
2042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
2043c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| UVC_QUIRK_BUILTIN_ISIGHT },
2044c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Genesys Logic USB 2.0 PC Camera */
20452c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
20472c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idVendor		= 0x05e3,
20482c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idProduct		= 0x0505,
20492c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20502c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
20512c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
20522c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2053d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Vega */
2054d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2055d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2056d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2057d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x332d,
2058d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2059d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2060d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2061d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2062d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro - Minoru3D */
2063d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2064d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2065d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2066d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3410,
2067d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2068d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2069d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2070d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2071d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Venus - Minoru3D */
2072d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
207350144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
207450144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idVendor		= 0x0ac8,
2075d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3420,
207650144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
207750144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceSubClass	= 1,
207850144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceProtocol	= 0,
207950144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* MT6227 */
2081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x0e8d,
2084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0004,
2085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2088bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2089bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart				| UVC_QUIRK_PROBE_DEF },
2090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (HP Spartan) */
2091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x5212,
2095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
209825e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2099562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	/* Syntek (Samsung Q310) */
2100562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2101562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2102562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idVendor		= 0x174f,
2103562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idProduct		= 0x5931,
2104562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2105562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2106562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2107562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2108f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	/* Syntek (Packard Bell EasyNote MX52 */
2109f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2110f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2111f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idVendor		= 0x174f,
2112f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idProduct		= 0x8a12,
2113f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2114f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceSubClass	= 1,
2115f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceProtocol	= 0,
2116f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2117f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Syntek (Asus F9SG) */
211825e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
211925e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
212025e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idVendor		= 0x174f,
212125e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idProduct		= 0x8a31,
212225e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
212325e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceSubClass	= 1,
212425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceProtocol	= 0,
2125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (Asus U3S) */
2127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8a33,
2131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
21350ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	/* Syntek (JAOtech Smart Terminal) */
21360ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21370ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21380ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idVendor		= 0x174f,
21390ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idProduct		= 0x8a34,
21400ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21410ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceSubClass	= 1,
21420ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceProtocol	= 0,
21430ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2144849a3aba2d9830dc2a78a66078023e7e5ac26e15Filipe Rosset	/* Lenovo Thinkpad SL400/SL500 */
21452f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21462f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21472f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idVendor		= 0x17ef,
21482f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idProduct		= 0x480b,
21492f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21502f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceSubClass	= 1,
21512f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceProtocol	= 0,
21522f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
21532d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	/* Aveo Technology USB 2.0 Camera */
21542d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21552d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21562d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idVendor		= 0x1871,
21572d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idProduct		= 0x0306,
21582d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21592d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceSubClass	= 1,
21602d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceProtocol	= 0,
21615bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
21625bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart				| UVC_QUIRK_PROBE_EXTRAFIELDS },
2163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Ecamm Pico iMage */
2164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x18cd,
2167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0xcafe,
2168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
2172ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	/* FSC WebCam V30S */
2173ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2174ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2175ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idVendor		= 0x18ec,
2176ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idProduct		= 0x3288,
2177ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2178ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceSubClass	= 1,
2179ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceProtocol	= 0,
2180ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
21811e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	/* Arkmicro unbranded */
21821e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21831e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21841e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idVendor		= 0x18ec,
21851e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idProduct		= 0x3290,
21861e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21871e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceSubClass	= 1,
21881e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceProtocol	= 0,
21891e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Bodelin ProScopeHR */
2191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_DEV_HI
2193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x19ab,
2195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x1000,
2196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bcdDevice_hi		= 0x0126,
2197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STATUS_INTERVAL },
22013bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	/* MSI StarCam 370i */
22023bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
22033bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22043bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idVendor		= 0x1b3b,
22053bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idProduct		= 0x2951,
22063bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22073bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceSubClass	= 1,
22083bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceProtocol	= 0,
22093bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* SiGma Micro USB Web Camera */
2211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x1c4f,
2214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x3000,
2215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2219d732c44c1a4b54e3c59ad92069bc2fd848aca5f3Laurent Pinchart				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
2220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Generic USB Video Class */
2221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
2222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{}
2223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DEVICE_TABLE(usb, uvc_ids);
2226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct uvc_driver uvc_driver = {
2228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	.driver = {
2229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "uvcvideo",
2230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.probe		= uvc_probe,
2231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.disconnect	= uvc_disconnect,
2232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.suspend	= uvc_suspend,
2233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.resume		= uvc_resume,
22349b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart		.reset_resume	= uvc_reset_resume,
2235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.id_table	= uvc_ids,
2236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.supports_autosuspend = 1,
2237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
2238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int __init uvc_init(void)
2241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int result;
2243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.devices);
2245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&uvc_driver.controls);
2246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&uvc_driver.ctrl_mutex);
2247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_ctrl_init();
2249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	result = usb_register(&uvc_driver.driver);
2251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (result == 0)
2252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
2253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return result;
2254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void __exit uvc_cleanup(void)
2257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_deregister(&uvc_driver.driver);
2259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_init(uvc_init);
2262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_exit(uvc_cleanup);
2263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_AUTHOR(DRIVER_AUTHOR);
2265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DESCRIPTION(DRIVER_DESC);
2266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_LICENSE("GPL");
2267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_VERSION(DRIVER_VERSION);
2268f87086e302300fdff1bd32049deb7a7f3e3de7daHans Verkuil
2269