uvc_driver.c revision 17706f5653a90ff277b5b36c2eb60ff872df5e7a
1c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      uvc_driver.c  --  USB Video Class driver
3c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
411fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart *      Copyright (C) 2005-2010
511fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
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
1466ede038aa7b51ffbfaf9e600536f027a6d34e56Andrew Morton#include <linux/atomic.h>
15c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/kernel.h>
16c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/list.h>
17c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/module.h>
185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
19c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb.h>
20c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/videodev2.h>
21c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/vmalloc.h>
22c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/wait.h>
23fd3e5824824d1beaf376cd523c7418c5570851d4Mauro Carvalho Chehab#include <linux/version.h>
249bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich#include <asm/unaligned.h>
25c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
26c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <media/v4l2-common.h>
27c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
28c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include "uvcvideo.h"
29c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
3011fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart#define DRIVER_AUTHOR		"Laurent Pinchart " \
3111fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart				"<laurent.pinchart@ideasonboard.com>"
32c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#define DRIVER_DESC		"USB Video Class driver"
33c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
34310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartunsigned int uvc_clock_param = CLOCK_MONOTONIC;
350fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83Laurent Pinchartunsigned int uvc_no_drop_param;
3673de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchartstatic unsigned int uvc_quirks_param = -1;
37c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartunsigned int uvc_trace_param;
38b232a012adfea9f535702e8296ea6b76e691f436Laurent Pinchartunsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
39c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
40c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
412c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * Video formats
42c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
43c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
44c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc uvc_fmts[] = {
45c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
46c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (YUYV)",
47c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YUY2,
48c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUYV,
49c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
50c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
5168f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.name		= "YUV 4:2:2 (YUYV)",
5268f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.guid		= UVC_GUID_FORMAT_YUY2_ISIGHT,
5368f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz		.fcc		= V4L2_PIX_FMT_YUYV,
5468f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	},
5568f194e027ecfbbc8d5515bc40787e542eed59e9Daniel Ritz	{
56c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (NV12)",
57c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_NV12,
58c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_NV12,
59c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
60c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
61c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "MJPEG",
62c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_MJPEG,
63c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_MJPEG,
64c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
65c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
66c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YVU 4:2:0 (YV12)",
67c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_YV12,
68c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YVU420,
69c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
70c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
71c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:0 (I420)",
72c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_I420,
73c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_YUV420,
74c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
75c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
767225a1dcc38f28fcc6178258b2072d12742f68d9Hans de Goede		.name		= "YUV 4:2:0 (M420)",
777225a1dcc38f28fcc6178258b2072d12742f68d9Hans de Goede		.guid		= UVC_GUID_FORMAT_M420,
787225a1dcc38f28fcc6178258b2072d12742f68d9Hans de Goede		.fcc		= V4L2_PIX_FMT_M420,
797225a1dcc38f28fcc6178258b2072d12742f68d9Hans de Goede	},
807225a1dcc38f28fcc6178258b2072d12742f68d9Hans de Goede	{
81c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "YUV 4:2:2 (UYVY)",
82c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_UYVY,
83c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_UYVY,
84c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
85c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
86ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.name		= "Greyscale 8-bit (Y800)",
87c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y800,
88c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_GREY,
89c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
90c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{
91ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.name		= "Greyscale 8-bit (Y8  )",
92ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.guid		= UVC_GUID_FORMAT_Y8,
93ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.fcc		= V4L2_PIX_FMT_GREY,
94ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	},
95ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	{
96ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.name		= "Greyscale 10-bit (Y10 )",
97ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.guid		= UVC_GUID_FORMAT_Y10,
98ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.fcc		= V4L2_PIX_FMT_Y10,
99ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	},
100ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	{
101ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.name		= "Greyscale 12-bit (Y12 )",
102ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.guid		= UVC_GUID_FORMAT_Y12,
103ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.fcc		= V4L2_PIX_FMT_Y12,
104ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	},
105ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel	{
106ca47e7192c314193c13942dec45f4070f57ab5a6Stefan Muenzel		.name		= "Greyscale 16-bit (Y16 )",
10761421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.guid		= UVC_GUID_FORMAT_Y16,
10861421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart		.fcc		= V4L2_PIX_FMT_Y16,
10961421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart	},
11061421206833a4085d9bdf35b2b84cd9a67dfdfacLaurent Pinchart	{
111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "RGB Bayer",
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_BY8,
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_SBGGR8,
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
115507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart	{
116507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.name		= "RGB565",
117507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.guid		= UVC_GUID_FORMAT_RGBP,
118507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.fcc		= V4L2_PIX_FMT_RGB565,
119507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart	},
12025ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky	{
12125ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.name		= "H.264",
12225ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.guid		= UVC_GUID_FORMAT_H264,
12325ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.fcc		= V4L2_PIX_FMT_H264,
12425ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky	},
125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Utility functions
129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		__u8 epaddr)
133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep;
135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = &alts->endpoint[i];
139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep->desc.bEndpointAddress == epaddr)
140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ep;
141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int len = ARRAY_SIZE(uvc_fmts);
149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < len; ++i) {
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return &uvc_fmts[i];
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic __u32 uvc_colorspace(const __u8 primaries)
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	static const __u8 colorprimaries[] = {
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		0,
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SRGB,
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_M,
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_BG,
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE170M,
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE240M,
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	};
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (primaries < ARRAY_SIZE(colorprimaries))
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return colorprimaries[primaries];
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Simplify a fraction using a simple continued fraction decomposition. The
177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * idea here is to convert fractions such as 333333/10000000 to 1/30 using
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arbitrary parameters to remove non-significative terms from the simple
180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * respectively seems to give nice results.
182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unsigned int n_terms, unsigned int threshold)
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t *an;
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t x, y, r;
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (an == NULL)
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Convert the fraction to a simple continued fraction. See
195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * http://mathforum.org/dr.math/faq/faq.fractions.html
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * Stop if the current term is bigger than or equal to the given
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * threshold.
198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = *numerator;
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = *denominator;
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (n = 0; n < n_terms && y != 0; ++n) {
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		an[n] = x / y;
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (an[n] >= threshold) {
205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (n < 2)
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				n++;
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = x - an[n] * y;
211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = y;
212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = r;
213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Expand the simple continued fraction back to an integer fraction. */
216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = 0;
217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = 1;
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = n; i > 0; --i) {
220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = y;
221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = an[i-1] * y + x;
222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = r;
223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*numerator = y;
226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*denominator = x;
227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(an);
228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to compute numerator / denominator * 10000000 using 32 bit fixed point
232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arithmetic only.
233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartuint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t multiplier;
237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Saturate the result if the operation would overflow. */
239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (denominator == 0 ||
240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    numerator/denominator >= ((uint32_t)-1)/10000000)
241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return (uint32_t)-1;
242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Divide both the denominator and the multiplier by two until
244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * numerator * multiplier doesn't overflow. If anyone knows a better
245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * algorithm please let me know.
246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	multiplier = 10000000;
248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (numerator > ((uint32_t)-1)/multiplier) {
249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		multiplier /= 2;
250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		denominator /= 2;
251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return denominator ? numerator * multiplier / denominator : 0;
254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Terminal and unit management
258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2604ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchartstruct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity;
263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(entity, &dev->entities, list) {
265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->id == id)
266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return entity;
267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id, struct uvc_entity *entity)
274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (entity == NULL)
278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(&dev->entities, struct uvc_entity, list);
279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
280c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry_continue(entity, &dev->entities, list) {
2818ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i)
2828ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (entity->baSourceID[i] == id)
283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
2908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
2918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
2928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
2948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->header.bTerminalLink == id)
2958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return stream;
2968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
2978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
2988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return NULL;
2998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
3008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
3028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Descriptors parsing
303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
305c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_format(struct uvc_device *dev,
306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming, struct uvc_format *format,
307c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 **intervals, unsigned char *buffer, int buflen)
308c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
309c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf = streaming->intf;
310c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = intf->cur_altsetting;
311c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format_desc *fmtdesc;
312c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
313c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *start = buffer;
314c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int interval;
315c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
316c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u8 ftype;
317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
318c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->type = buffer[2];
319c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->index = buffer[3];
320c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
322b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_UNCOMPRESSED:
323b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_FRAME_BASED:
324b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
325233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		if (buflen < n) {
326b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
327c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Find the format descriptor from its GUID. */
334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		fmtdesc = uvc_format_by_guid(&buffer[5]);
335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (fmtdesc != NULL) {
337d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, fmtdesc->name,
338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				sizeof format->name);
339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = fmtdesc->fcc;
340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
34136bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
34236bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
34336bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			snprintf(format->name, sizeof(format->name), "%pUl\n",
34436bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = 0;
346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = buffer[21];
349b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
350b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_UNCOMPRESSED;
351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
352b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_FRAME_BASED;
353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (buffer[27])
354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				format->flags = UVC_FMT_FLAG_COMPRESSED;
355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
358b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MJPEG:
359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 11) {
360b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
362c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
367d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(format->name, "MJPEG", sizeof format->name);
368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_MJPEG;
369c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED;
370c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
371b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		ftype = UVC_VS_FRAME_MJPEG;
372c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
374b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_DV:
375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
376b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[8] & 0x7f) {
384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 0:
385d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SD-DV", sizeof format->name);
386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 1:
388d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SDL-DV", sizeof format->name);
389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 2:
391d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "HD-DV", sizeof format->name);
392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
394b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d: unknown DV format %u\n",
396c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber, buffer[8]);
398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
401d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sizeof format->name);
403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_DV;
405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = 0;
408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Create a dummy frame descriptor. */
410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame = &format->frame[0];
411c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&format->frame[0], 0, sizeof format->frame[0]);
412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIntervalType = 1;
413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval = 1;
414c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		*(*intervals)++ = 1;
416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->nframes = 1;
417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
419b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MPEG2TS:
420b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_STREAM_BASED:
421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Not supported yet. */
422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
423b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       "interface %d unsupported format %u\n",
425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       dev->udev->devnum, alts->desc.bInterfaceNumber,
426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       buffer[2]);
427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * based formats have frame descriptors.
437c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
438c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
439c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	       buffer[2] == ftype) {
440078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		frame = &format->frame[format->nframes];
441b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED)
442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 25 ? buffer[25] : 0;
443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 21 ? buffer[21] : 0;
445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = n ? n : 3;
447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 26 + 4*n) {
449b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FRAME error\n", dev->udev->devnum,
451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIndex = buffer[3];
456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bmCapabilities = buffer[4];
4579bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wWidth = get_unaligned_le16(&buffer[5]);
4589bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wHeight = get_unaligned_le16(&buffer[7]);
4599bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
4609bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
461b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED) {
462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize =
4639bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4659bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[21]);
466c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[25];
467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = 0;
469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4709bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
471c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[21];
472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
474c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
476c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * completely. Observed behaviours range from setting the
4772c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * value to 1.1x the actual frame size to hardwiring the
478c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 16 low bits to 0. This results in a higher than necessary
479c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * memory usage as well as a wrong image size information. For
480c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * uncompressed formats this can be fixed by computing the
481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * value from the frame size.
482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = format->bpp
485c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				* frame->wWidth * frame->wHeight / 8;
486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Some bogus devices report dwMinFrameInterval equal to
488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * dwMaxFrameInterval and have dwFrameIntervalStep set to
489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * zero. Setting all null intervals to 1 fixes the problem and
4902c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * some other divisions by zero that could happen.
491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
4939bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			interval = get_unaligned_le32(&buffer[26+4*i]);
494c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			*(*intervals)++ = interval ? interval : 1;
495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure that the default frame interval stays between
498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * the boundaries.
499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n -= frame->bFrameIntervalType ? 1 : 2;
501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval =
502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			min(frame->dwFrameInterval[n],
503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    max(frame->dwFrameInterval[0],
504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				frame->dwDefaultFrameInterval));
505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
50686d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart		if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
50786d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart			frame->bFrameIntervalType = 1;
50886d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart			frame->dwFrameInterval[0] =
50986d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart				frame->dwDefaultFrameInterval;
51086d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart		}
51186d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart
512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->wWidth, frame->wHeight,
514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			10000000/frame->dwDefaultFrameInterval,
515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			(100000000/frame->dwDefaultFrameInterval)%10);
516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
517078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		format->nframes++;
518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
522c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
523c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
528c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
529c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_COLORFORMAT) {
530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 6) {
531b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d COLORFORMAT error\n",
533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
537c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->colorspace = uvc_colorspace(buffer[3]);
539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return buffer - start;
545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_streaming(struct uvc_device *dev,
548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf)
549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming = NULL;
551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format *format;
552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = &intf->altsetting[0];
554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *_buffer, *buffer = alts->extra;
555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int _buflen, buflen = alts->extralen;
556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int nformats = 0, nframes = 0, nintervals = 0;
557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int size, i, n, p;
558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 *interval;
559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 psize;
560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret = -EINVAL;
561c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass
563b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		!= UVC_SC_VIDEOSTREAMING) {
564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"video streaming interface\n", dev->udev->devnum,
566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"claimed\n", dev->udev->devnum,
573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (streaming == NULL) {
579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver, intf);
580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&streaming->mutex);
58435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	streaming->dev = dev;
585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intf = usb_get_intf(intf);
586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* The Pico iMage webcam has its class-specific interface descriptors
589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * after the endpoint descriptors.
590c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
591c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen == 0) {
592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
593c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			struct usb_host_endpoint *ep = &alts->endpoint[i];
594c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
595c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen == 0)
596c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
597c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
598c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen > 2 &&
599c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    ep->extra[1] == USB_DT_CS_INTERFACE) {
600c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "trying extra data "
601c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"from endpoint %u.\n", i);
602c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer = alts->endpoint[i].extra;
603c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buflen = alts->endpoint[i].extralen;
604c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
605c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
607c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
608c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
609c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Skip the standard interface descriptors. */
610c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
611c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
612c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
613c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
614c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
615c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen <= 2) {
616c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
617c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"interface descriptors found.\n");
618c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
619c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
620c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
621c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the header descriptor. */
622ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	switch (buffer[2]) {
623b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_OUTPUT_HEADER:
624ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
625ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 9;
626ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
627ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
628b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_INPUT_HEADER:
629ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
630ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 13;
631ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
632ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
633ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	default:
634c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
635ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"%d HEADER descriptor not found.\n", dev->udev->devnum,
636ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			alts->desc.bInterfaceNumber);
637c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
638ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
639c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
640ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	p = buflen >= 4 ? buffer[3] : 0;
641ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	n = buflen >= size ? buffer[size-1] : 0;
642ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
643ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buflen < size + p*n) {
644ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
645ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"interface %d HEADER descriptor is invalid.\n",
646ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
647ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		goto error;
648ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
649c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
650ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bNumFormats = p;
651ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bEndpointAddress = buffer[6];
652b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (buffer[2] == UVC_VS_INPUT_HEADER) {
653c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bmInfo = buffer[7];
654c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTerminalLink = buffer[8];
655c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bStillCaptureMethod = buffer[9];
656c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerSupport = buffer[10];
657c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerUsage = buffer[11];
658c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
659ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->header.bTerminalLink = buffer[7];
660ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
661ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bControlSize = n;
662ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
6630b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall	streaming->header.bmaControls = kmemdup(&buffer[size], p * n,
6640b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall						GFP_KERNEL);
665ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (streaming->header.bmaControls == NULL) {
666ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		ret = -ENOMEM;
667c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
668c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
670c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
671c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
672c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buffer = buffer;
674c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buflen = buflen;
675c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
676c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Count the format and frame descriptors. */
677042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (_buffer[2]) {
679b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
680b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
681b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
682c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
683c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
684c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
685b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
686c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			/* DV format has no frame descriptor. We will create a
687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 * dummy frame descriptor with a dummy frame interval.
688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 */
689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nintervals++;
692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
694b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MPEG2TS:
695b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_STREAM_BASED:
696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
697c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d FORMAT %u is not supported.\n",
698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->udev->devnum,
699c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, _buffer[2]);
700c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
701c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
702b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_UNCOMPRESSED:
703b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_MJPEG:
704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
705c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 25)
706c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[25] ? _buffer[25] : 3;
707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
709b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_FRAME_BASED:
710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 21)
712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[21] ? _buffer[21] : 3;
713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
714c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
715c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
716c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buflen -= _buffer[0];
717c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buffer += _buffer[0];
718c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
719c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
720c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (nformats == 0) {
721c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
722c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"%d has no supported formats defined.\n",
723c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
724c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	size = nformats * sizeof *format + nframes * sizeof *frame
728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	     + nintervals * sizeof *interval;
729c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format = kzalloc(size, GFP_KERNEL);
730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (format == NULL) {
731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ret = -ENOMEM;
732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	frame = (struct uvc_frame *)&format[nformats];
736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = (__u32 *)&frame[nframes];
737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->format = format;
739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->nformats = nformats;
740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the format descriptors. */
742042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[2]) {
744b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
745b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
746b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
747b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->frame = frame;
749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret = uvc_parse_format(dev, streaming, format,
750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				&interval, buffer, buflen);
751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ret < 0)
752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				goto error;
753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame += format->nframes;
755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format++;
756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buflen -= ret;
758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buffer += ret;
759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
762c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
764c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
765c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
766c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
767c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
769c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen)
770c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
771c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			"%d has %u bytes of trailing descriptor garbage.\n",
772c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
773c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart
774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the alternate settings to find the maximum bandwidth. */
775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < intf->num_altsetting; ++i) {
776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep;
777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		alts = &intf->altsetting[i];
778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = uvc_find_endpoint(alts,
779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				streaming->header.bEndpointAddress);
780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep == NULL)
781c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
783c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = le16_to_cpu(ep->desc.wMaxPacketSize);
784c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
785c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (psize > streaming->maxpsize)
786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->maxpsize = psize;
787c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
788c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
78935f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_add_tail(&streaming->list, &dev->streams);
790c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
791c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
792c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
793c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_driver_release_interface(&uvc_driver.driver, intf);
794c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(intf);
795c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->format);
796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->header.bmaControls);
797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming);
798c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
799c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8018ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchartstatic struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
8028ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unsigned int num_pads, unsigned int extra_size)
8038ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart{
8048ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	struct uvc_entity *entity;
8058ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int num_inputs;
8068ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int size;
8074ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	unsigned int i;
8088ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8094ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	extra_size = ALIGN(extra_size, sizeof(*entity->pads));
8108ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
8114ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
8124ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	     + num_inputs;
8138ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity = kzalloc(size, GFP_KERNEL);
8148ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	if (entity == NULL)
8158ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		return NULL;
8168ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8178ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->id = id;
8188ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->type = type;
8198ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8204ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->num_links = 0;
8214ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->num_pads = num_pads;
8224ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->pads = ((void *)(entity + 1)) + extra_size;
8234ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
8244ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	for (i = 0; i < num_inputs; ++i)
8254ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
8264ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	if (!UVC_ENTITY_IS_OTERM(entity))
8274ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
8284ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
8298ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->bNrInPins = num_inputs;
8304ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->baSourceID = (__u8 *)(&entity->pads[num_pads]);
8318ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8328ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	return entity;
8338ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart}
8348ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Parse vendor-specific extensions. */
836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_vendor_control(struct uvc_device *dev,
837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit;
842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int n, p;
843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int handled = 0;
844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0x046d:		/* Logitech */
847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[1] != 0x41 || buffer[2] != 0x01)
848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Logitech implements several vendor specific functions
851c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * through vendor specific extension units (LXU).
852c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * The LXU descriptors are similar to XU descriptors
854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * (see "USB Device Video Class for Video Devices", section
855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 3.7.2.6 "Extension Unit Descriptor") with the following
856c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * differences:
857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 0		bLength		1	 Number
860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Size of this descriptor, in bytes: 24+p+n*2
861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n	bmControlsType	N	Bitmap
863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	Individual bits in the set are defined:
864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	0: Absolute
865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	1: Relative
866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	This bitset is mapped exactly the same as bmControls.
868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n*2	bReserved	1	Boolean
870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 24+p+n*2	iExtension	1	Index
872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Index of a string descriptor that describes this
873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	extension unit.
874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 25 + p ? buffer[22+p] : 0;
878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 25 + p + 2*n) {
880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8868ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
8878ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					p + 1, 2*n);
888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
890c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
8938ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
8958ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
8968ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
8978ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					       + n;
898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[24+p+2*n] != 0)
901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[24+p+2*n], unit->name,
902c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
903c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
904c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
906c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
907c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		handled = 1;
908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
909c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return handled;
912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
913c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_standard_control(struct uvc_device *dev,
915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
917c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit, *term;
919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf;
920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n, p, len;
922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 type;
923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
925b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_HEADER:
926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 12 ? buffer[11] : 0;
927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 12 || buflen < 12 + n) {
929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d HEADER error\n", udev->devnum,
931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber);
932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9359bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->uvc_version = get_unaligned_le16(&buffer[3]);
9369bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->clock_frequency = get_unaligned_le32(&buffer[7]);
937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Parse all USB Video Streaming interfaces. */
939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf = usb_ifnum_to_if(udev, buffer[12+i]);
941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (intf == NULL) {
942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "device %d "
943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"interface %d doesn't exists\n",
944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					udev->devnum, i);
945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_parse_streaming(dev, intf);
949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
952b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_INPUT_TERMINAL:
953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 8) {
954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
955c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
956c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
9639bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL %d has invalid "
967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber,
969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer[3], type);
970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = 0;
974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = 0;
975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		len = 8;
976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
977b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (type == UVC_ITT_CAMERA) {
978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 15 ? buffer[14] : 0;
979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 15;
980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
981b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 9 ? buffer[8] : 0;
983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			p = buflen >= 10 + n ? buffer[9+n] : 0;
984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 10;
985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < len + n + p) {
988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9948ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
9958ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, n + p);
996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
999b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
1000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bControlSize = n;
1001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bmControls = (__u8 *)term + sizeof *term;
1002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMin =
10039bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[8]);
1004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMax =
10059bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[10]);
1006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wOcularFocalLength =
10079bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[12]);
1008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->camera.bmControls, &buffer[15], n);
1009b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (UVC_ENTITY_TYPE(term) ==
1010b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			   UVC_ITT_MEDIA_TRANSPORT_INPUT) {
1011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bControlSize = n;
1012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmControls = (__u8 *)term + sizeof *term;
1013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bTransportModeSize = p;
1014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmTransportModes = (__u8 *)term
1015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart						     + sizeof *term + n;
1016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmControls, &buffer[9], n);
1017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
1018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1019c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[7] != 0)
1021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[7], term->name,
1022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1023b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
1024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Camera %u", buffer[3]);
1025b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
1026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Media %u", buffer[3]);
1027c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Input %u", buffer[3]);
1029c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1030c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1031c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1032c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1033b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_OUTPUT_TERMINAL:
1034c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
1035c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL error\n",
1037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1039c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1040c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
1042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
1043c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
10449bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
1045c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
1046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL %d has invalid "
1048c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
1049c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, buffer[3], type);
1050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
1051c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1052c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10538ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
10548ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, 0);
1055c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
1056c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10588ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(term->baSourceID, &buffer[7], 1);
1059c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8] != 0)
1061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8], term->name,
1062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1064c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Output %u", buffer[3]);
1065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1066c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1067c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1068c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1069b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1070c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 5 ? buffer[4] : 0;
1071c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1072c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 5 || buflen < 6 + p) {
1073c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1074c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d SELECTOR_UNIT error\n",
1075c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1076c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1078c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10798ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
1080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10838ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[5], p);
1084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[5+p] != 0)
1086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[5+p], unit->name,
1087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1088c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Selector %u", buffer[3]);
1090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1094b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 8 ? buffer[7] : 0;
1096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = dev->uvc_version >= 0x0110 ? 10 : 9;
1097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < p + n) {
1099c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d PROCESSING_UNIT error\n",
1101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11058ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
1106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11098ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[4], 1);
1110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.wMaxMultiplier =
11119bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			get_unaligned_le16(&buffer[5]);
1112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bControlSize = buffer[7];
1113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
1114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->processing.bmControls, &buffer[8], n);
1115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->uvc_version >= 0x0110)
1116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			unit->processing.bmVideoStandards = buffer[9+n];
1117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8+n] != 0)
1119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8+n], unit->name,
1120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Processing %u", buffer[3]);
1123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1127b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
1129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 24 + p ? buffer[22+p] : 0;
1130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 24 + p + n) {
1132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
1134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11388ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
1139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
1143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
11448ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
1145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
11468ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
1147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], n);
1148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[23+p+n] != 0)
1150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[23+p+n], unit->name,
1151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
1154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
1160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptor (%u)\n", buffer[2]);
1161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_control(struct uvc_device *dev)
1168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
1170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *buffer = alts->extra;
1171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int buflen = alts->extralen;
1172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the default alternate setting only, as the UVC specification
1175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * defines a single alternate setting, the default alternate setting
1176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * zero.
1177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
1180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_parse_vendor_control(dev, buffer, buflen) ||
1181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    buffer[1] != USB_DT_CS_INTERFACE)
1182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			goto next_descriptor;
1183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
1185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ret;
1186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartnext_descriptor:
1188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
1189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
1190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1192538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	/* Check if the optional status endpoint is present. Built-in iSight
1193538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * webcams have an interrupt endpoint but spit proprietary data that
1194538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * don't conform to the UVC status endpoint messages. Don't try to
1195538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * handle the interrupt endpoint for those cameras.
1196538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 */
1197538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	if (alts->desc.bNumEndpoints == 1 &&
1198538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	    !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
1199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep = &alts->endpoint[0];
1200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_endpoint_descriptor *desc = &ep->desc;
1201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (usb_endpoint_is_int_in(desc) &&
1203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
1204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    desc->bInterval != 0) {
1205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
1206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(addr %02x).\n", desc->bEndpointAddress);
1207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->int_ep = ep;
1208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
12158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * UVC device scan
1216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Scan the UVC descriptors to locate a chain starting at an Output Terminal
1220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * and containing the following units:
1221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - one or more Output Terminals (USB Streaming or Display)
1223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one Processing Unit
12248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - zero, one or more single-input Selector Units
1225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one multiple-input Selector Units, provided all inputs are
1226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *   connected to input terminals
1227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Extension Units
12282c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one or more Input Terminals (Camera, External or USB Streaming)
1229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The terminal and units must match on of the following structures:
12318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
12338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
12348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
12358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(0)
12378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
12388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(n)
12398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The Processing Unit and Extension Units can be in any order. Additional
12418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Extension Units connected to the main chain as single-unit branches are
12428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * also supported. Single-input Selector Units are ignored.
1243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
12448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_entity(struct uvc_video_chain *chain,
1245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1248b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- XU %d", entity->id);
1251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12528ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins != 1) {
1253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
1254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"than 1 input pin.\n", entity->id);
1255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1260b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- PU %d", entity->id);
1263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->processing != NULL) {
1265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
1266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Processing Units in chain.\n");
1267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->processing = entity;
1271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1273b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- SU %d", entity->id);
1276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
12788ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1)
1279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1280c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->selector != NULL) {
1282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
1283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Units in chain.\n");
1284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
1288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1290b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
1291b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_CAMERA:
1292b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
1293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12984093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
12994093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_DISPLAY:
13004093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13014093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
13024093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart			printk(" OT %d", entity->id);
13034093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart
13044093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart		break;
13054093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart
1306b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_TT_STREAMING:
13074057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (UVC_ENTITY_IS_ITERM(entity)) {
13084057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
13094057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" <- IT %d\n", entity->id);
13104057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		} else {
13114057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
13124057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" OT %d", entity->id);
1313ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1314ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1315ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
1316ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1318c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1319c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
1320c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1322c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13236241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_add_tail(&entity->chain, &chain->entities);
1324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_forward(struct uvc_video_chain *chain,
1328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, struct uvc_entity *prev)
1329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *forward;
1331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found;
1332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Forward scan */
1334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	forward = NULL;
1335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	found = 0;
1336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (1) {
13388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		forward = uvc_entity_by_reference(chain->dev, entity->id,
1339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			forward);
1340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward == NULL)
1341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
13428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (forward == prev)
1343c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		switch (UVC_ENTITY_TYPE(forward)) {
13468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_VC_EXTENSION_UNIT:
13478ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (forward->bNrInPins != 1) {
13488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
13498e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  "has more than 1 input pin.\n",
13508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  entity->id);
13518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13546241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" XU %d", forward->id);
13608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
13638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_VENDOR_SPECIFIC:
13658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_DISPLAY:
13668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_TT_STREAMING:
13688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (UVC_ENTITY_IS_ITERM(forward)) {
13698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
13708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					"terminal %u.\n", forward->id);
13718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13746241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" OT %d", forward->id);
13808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
1383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (found)
1386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(")");
1387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_backward(struct uvc_video_chain *chain,
13924057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity **_entity)
1393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
13944057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity *entity = *_entity;
1395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
13964057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	int id = -EINVAL, i;
1397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1399b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1400b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
14018ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = entity->baSourceID[0];
1402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1404b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
14068ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1) {
14078ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[0];
1408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1411c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT");
1413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
14158ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i) {
14168ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[i];
14178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			term = uvc_entity_by_id(chain->dev, id);
1418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
1419c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
1420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input %d isn't connected to an "
1421c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input terminal\n", entity->id, i);
1422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return -1;
1423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
1426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" %d", term->id);
1427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14286241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&term->chain, &chain->entities);
14298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_scan_chain_forward(chain, term, entity);
1430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("\n");
1434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = 0;
1436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
14374057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14384057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
14394057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_CAMERA:
14404057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
14414057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
14424057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_DISPLAY:
14434057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
14444057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_TT_STREAMING:
14458ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
14464057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		break;
1447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14494057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (id <= 0) {
14504057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		*_entity = NULL;
14514057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return id;
14524057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14534057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14544057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = uvc_entity_by_id(chain->dev, id);
14554057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (entity == NULL) {
14564057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14574057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			"unknown entity %d.\n", id);
14584057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return -EINVAL;
14594057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14604057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14614057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	*_entity = entity;
14624057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	return 0;
1463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain(struct uvc_video_chain *chain,
14664057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			  struct uvc_entity *term)
1467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, *prev;
1469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14704057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
1471ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
14724057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = term;
14734057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	prev = NULL;
14748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14754057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	while (entity != NULL) {
14764057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		/* Entity must not be part of an existing chain */
14778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (entity->chain.next || entity->chain.prev) {
14788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14794057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				"entity %d already in chain.\n", entity->id);
14808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Process entity */
14848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_entity(chain, entity) < 0)
14858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Forward scan */
14888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_forward(chain, entity, prev) < 0)
14898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1490c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Backward scan */
14924057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		prev = entity;
14934057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (uvc_scan_chain_backward(chain, &entity) < 0)
14944057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			return -EINVAL;
1495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
14988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
14998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15006241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchartstatic unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
15016241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		char *buffer)
15028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
15038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
15048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	unsigned int nterms = 0;
15058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
15068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(term, terms, chain) {
15086241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (!UVC_ENTITY_IS_TERM(term) ||
15096241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		    UVC_TERM_DIRECTION(term) != dir)
15106241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			continue;
15116241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart
15126241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (nterms)
15138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			p += sprintf(p, ",");
15146241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (++nterms >= 4) {
15156241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			p += sprintf(p, "...");
15166241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			break;
15178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
15186241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		p += sprintf(p, "%u", term->id);
1519ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
1520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return p - buffer;
15228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
15238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic const char *uvc_print_chain(struct uvc_video_chain *chain)
15258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
15268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	static char buffer[43];
15278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
15288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15296241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
15308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	p += sprintf(p, " -> ");
15316241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
15328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return buffer;
1534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
153735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart * Scan the device for video chains and register video devices.
1538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
15398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Chains are scanned starting at their output terminals and walked backwards.
1540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
154135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchartstatic int uvc_scan_device(struct uvc_device *dev)
1542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
15438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
1544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(term, &dev->entities, list) {
15478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (!UVC_ENTITY_IS_OTERM(term))
1548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		/* If the terminal is already included in a chain, skip it.
15518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * This can happen for chains that have multiple output
15528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * terminals, where all output terminals beside the first one
15538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * will be inserted in the chain in forward scans.
15548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 */
15558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (term->chain.next || term->chain.prev)
1556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
15598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain == NULL)
15608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -ENOMEM;
15618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15626241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		INIT_LIST_HEAD(&chain->entities);
15638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		mutex_init(&chain->ctrl_mutex);
15648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->dev = dev;
15650550513c7a559b4933c5e1d47fbd15d15f6078d5Laurent Pinchart		v4l2_prio_init(&chain->prio);
15668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15678be8ec6ea58bd77338f6ffa2f6d2acfc88b835f4Laurent Pinchart		term->flags |= UVC_ENTITY_FLAG_DEFAULT;
15688be8ec6ea58bd77338f6ffa2f6d2acfc88b835f4Laurent Pinchart
15698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain(chain, term) < 0) {
15708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			kfree(chain);
15718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
1572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
15738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
15758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			  uvc_print_chain(chain));
15768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		list_add_tail(&chain->list, &dev->chains);
1578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (list_empty(&dev->chains)) {
1581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "No valid video chain found.\n");
1582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1583c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
15898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Video device registration and unregistration
15908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
15918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
1593716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Delete the UVC device.
1594716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1595716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Called by the kernel when the last reference to the uvc_device structure
1596716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * is released.
1597716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1598716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * As this function is called after or during disconnect(), all URBs have
1599716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * already been canceled by the USB core. There is no need to kill the
1600716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * interrupt URB manually.
1601716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart */
1602716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_delete(struct uvc_device *dev)
1603716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1604716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct list_head *p, *n;
1605716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1606716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_intf(dev->intf);
1607716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_dev(dev->udev);
1608716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1609716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_status_cleanup(dev);
1610716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_ctrl_cleanup_device(dev);
1611716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16125a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (dev->vdev.dev)
16135a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		v4l2_device_unregister(&dev->vdev);
16145a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
16155a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (media_devnode_is_registered(&dev->mdev.devnode))
16165a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		media_device_unregister(&dev->mdev);
16175a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#endif
16185a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
1619716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->chains) {
1620716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_video_chain *chain;
1621716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		chain = list_entry(p, struct uvc_video_chain, list);
1622716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(chain);
1623716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1624716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1625716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->entities) {
1626716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_entity *entity;
1627716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		entity = list_entry(p, struct uvc_entity, list);
16284ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
16294ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		uvc_mc_cleanup_entity(entity);
16304ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#endif
16318a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		if (entity->vdev) {
16328a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart			video_device_release(entity->vdev);
16338a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart			entity->vdev = NULL;
16348a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		}
1635716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(entity);
1636716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1637716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1638716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->streams) {
1639716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_streaming *streaming;
1640716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		streaming = list_entry(p, struct uvc_streaming, list);
1641716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_driver_release_interface(&uvc_driver.driver,
1642716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart			streaming->intf);
1643716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_put_intf(streaming->intf);
1644716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->format);
1645716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->header.bmaControls);
1646716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming);
1647716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1648716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1649716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	kfree(dev);
1650716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1651716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1652716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_release(struct video_device *vdev)
1653716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1654716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_streaming *stream = video_get_drvdata(vdev);
1655716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_device *dev = stream->dev;
1656716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1657716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the registered streams count and delete the device when it
1658716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * reaches zero.
1659716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1660716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1661716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
1662716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1663716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1664716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart/*
16658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Unregister the video devices.
16668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic void uvc_unregister_video(struct uvc_device *dev)
16688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1671716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Unregistering all video devices might result in uvc_delete() being
1672716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * called from inside the loop if there's no open file handle. To avoid
1673716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * that, increment the stream count before iterating over the streams
1674716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * and decrement it when done.
1675716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1676716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
1677716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
16798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->vdev == NULL)
16808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
16818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1682716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		video_unregister_device(stream->vdev);
16838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
1684edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
1685edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		uvc_debugfs_cleanup_stream(stream);
16868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
1687716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1688716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the stream count and call uvc_delete explicitly if there
1689716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * are no stream left.
1690716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1691716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1692716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
16938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
16948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_video(struct uvc_device *dev,
16968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		struct uvc_streaming *stream)
16978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct video_device *vdev;
16998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Initialize the streaming interface with default streaming
17028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * parameters.
17038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = uvc_video_init(stream);
17058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
17068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to initialize the device "
17078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			"(%d).\n", ret);
17088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
17098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1711edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_init_stream(stream);
1712edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
17138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register the device with V4L. */
17148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev = video_device_alloc();
17158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (vdev == NULL) {
17168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
17178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
17188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return -ENOMEM;
17198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* We already hold a reference to dev->udev. The video device will be
17228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * unregistered before the reference is released, so we don't need to
17238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * get another one.
17248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17255a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	vdev->v4l2_dev = &dev->vdev;
17268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->fops = &uvc_fops;
1727716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	vdev->release = uvc_release;
17280550513c7a559b4933c5e1d47fbd15d15f6078d5Laurent Pinchart	vdev->prio = &stream->chain->prio;
17290550513c7a559b4933c5e1d47fbd15d15f6078d5Laurent Pinchart	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
1730954f340fc7f2fa2ae8812670da49e828d2686d8eHans Verkuil	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1731954f340fc7f2fa2ae8812670da49e828d2686d8eHans Verkuil		vdev->vfl_dir = VFL_DIR_TX;
17328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	strlcpy(vdev->name, dev->name, sizeof vdev->name);
17338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Set the driver data before calling video_register_device, otherwise
17358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * uvc_v4l2_open might race us.
17368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	stream->vdev = vdev;
17388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	video_set_drvdata(vdev, stream);
17398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
17418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
17428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
17438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
17448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
17458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		video_device_release(vdev);
17468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
17478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1749f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1750f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart		stream->chain->caps |= V4L2_CAP_VIDEO_CAPTURE;
1751f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart	else
1752f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart		stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT;
1753f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart
1754716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
17558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
17598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Register all video devices in all chains.
17608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
17618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_terms(struct uvc_device *dev,
17626241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	struct uvc_video_chain *chain)
17638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
17658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
17668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17686241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_for_each_entry(term, &chain->entities, chain) {
17698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
17708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream = uvc_stream_by_id(dev, term->id);
17738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream == NULL) {
17748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_printk(KERN_INFO, "No streaming interface found "
17758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				   "for terminal %u.", term->id);
17768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
17788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->chain = chain;
17808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		ret = uvc_register_video(dev, stream);
17818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17838a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart
17848a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		term->vdev = stream->vdev;
17858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_chains(struct uvc_device *dev)
17918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
17938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(chain, &dev->chains, list) {
17966241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		ret = uvc_register_terms(dev, chain);
17978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
17988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
17994ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
18004ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
18014ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		ret = uvc_mc_register_entities(chain);
18024ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		if (ret < 0) {
18034ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart			uvc_printk(KERN_INFO, "Failed to register entites "
18044ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart				"(%d).\n", ret);
18054ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		}
18064ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#endif
18078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
18088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
18108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
18118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
18138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * USB probe, disconnect, suspend and resume
18148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
18158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_probe(struct usb_interface *intf,
1817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		     const struct usb_device_id *id)
1818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = interface_to_usbdev(intf);
1820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev;
1821c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1822c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1823c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (id->idVendor && id->idProduct)
1824c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
1825c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(%04x:%04x)\n", udev->devpath, id->idVendor,
1826c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				id->idProduct);
1827c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1828c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
1829c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devpath);
1830c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18312c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Allocate memory for the device and initialize it. */
1832c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
1833c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
1834c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->entities);
18368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	INIT_LIST_HEAD(&dev->chains);
183735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	INIT_LIST_HEAD(&dev->streams);
1838716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_set(&dev->nstreams, 0);
18398fb91b33c6bfa3ac5e4ad76920b7bcd7bdbbb6d0Martin Rubli	atomic_set(&dev->nmappings, 0);
184017706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	mutex_init(&dev->lock);
1841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->udev = usb_get_dev(udev);
1843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intf = usb_get_intf(intf);
1844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
184573de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	dev->quirks = (uvc_quirks_param == -1)
184673de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		    ? id->driver_info : uvc_quirks_param;
1847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (udev->product != NULL)
1849d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(dev->name, udev->product, sizeof dev->name);
1850c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1851c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		snprintf(dev->name, sizeof dev->name,
1852c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"UVC Camera (%04x:%04x)",
1853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idVendor),
1854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idProduct));
1855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18562c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Parse the Video Class control descriptor. */
1857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_parse_control(dev) < 0) {
1858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
1859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptors.\n");
1860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1863fba4578ee925110587ef9b8b6ddfabf2ce288071Laurent Pinchart	uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
1864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->uvc_version >> 8, dev->uvc_version & 0xff,
1865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		udev->product ? udev->product : "<unnamed>",
1866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idVendor),
1867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idProduct));
1868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
186973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	if (dev->quirks != id->driver_info) {
187073de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
187173de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart			"parameter for testing purpose.\n", dev->quirks);
1872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Please report required quirks to the "
1873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"linux-uvc-devel mailing list.\n");
1874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18765a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	/* Register the media and V4L2 devices. */
18775a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
18785a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->mdev.dev = &intf->dev;
18795a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
18805a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (udev->serial)
18815a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		strlcpy(dev->mdev.serial, udev->serial,
18825a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart			sizeof(dev->mdev.serial));
18835a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	strcpy(dev->mdev.bus_info, udev->devpath);
18845a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
1885fd3e5824824d1beaf376cd523c7418c5570851d4Mauro Carvalho Chehab	dev->mdev.driver_version = LINUX_VERSION_CODE;
18865a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (media_device_register(&dev->mdev) < 0)
18875a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		goto error;
18885a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
18895a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->vdev.mdev = &dev->mdev;
18905a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#endif
18915a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
18925a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		goto error;
18935a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
18942c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize controls. */
1895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_ctrl_init_device(dev) < 0)
1896c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1897c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Scan the device for video chains. */
189935f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	if (uvc_scan_device(dev) < 0)
1900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19025a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	/* Register video device nodes. */
19038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (uvc_register_chains(dev) < 0)
19048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		goto error;
19058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
19062c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Save our data pointer in the interface data. */
1907c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, dev);
1908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19092c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize the interrupt URB. */
1910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_status_init(dev)) < 0) {
1911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Unable to initialize the status "
1912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"endpoint (%d), status interrupt will not be "
1913c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"supported.\n", ret);
1914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
19173dae8b41dc5651f8eb22cf310e8b116480ba25b7Matthew Garrett	usb_enable_autosuspend(udev);
1918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
1921716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return -ENODEV;
1923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_disconnect(struct usb_interface *intf)
1926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the USB interface data to NULL. This can be done outside the
1930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock, as there's no other reader.
1931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, NULL);
1933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1934b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1935b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOSTREAMING)
1936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
1937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->state |= UVC_DEV_DISCONNECTED;
1939a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart
1940716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_suspend(struct usb_interface *intf, pm_message_t message)
1944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
194635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
1949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Controls are cached on the fly so they don't need to be saved. */
1952b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
195317706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
195417706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_lock(&dev->lock);
195517706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (dev->users)
195617706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart			uvc_status_stop(dev);
195717706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_unlock(&dev->lock);
195817706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		return 0;
195917706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	}
1960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
196135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
196235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
196335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_suspend(stream);
1964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
196635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
196735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
196835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19719b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int __uvc_resume(struct usb_interface *intf, int reset)
1972c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
197435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
1977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1979b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1980b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
198117706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		int ret = 0;
19827564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil
198317706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (reset) {
198417706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart			ret = uvc_ctrl_resume_device(dev);
19857564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			if (ret < 0)
19867564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil				return ret;
19877564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		}
1988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
198917706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_lock(&dev->lock);
199017706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (dev->users)
199117706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart			ret = uvc_status_start(dev, GFP_NOIO);
199217706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_unlock(&dev->lock);
199317706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart
199417706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		return ret;
1995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
199735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
199835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
1999d59a7b1dbce8b972ec2dc9fcaaae0bfa23687423Ming Lei			return uvc_video_resume(stream, reset);
2000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
2001c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
200235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
200335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
200435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
2005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
20079b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_resume(struct usb_interface *intf)
20089b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
20099b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 0);
20109b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
20119b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
20129b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_reset_resume(struct usb_interface *intf)
20139b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
20149b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 1);
20159b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
20169b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
2017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
2018310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart * Module parameters
2019310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart */
2020310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2021310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
2022310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
2023310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (uvc_clock_param == CLOCK_MONOTONIC)
2024310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_MONOTONIC");
2025310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
2026310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_REALTIME");
2027310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
2028310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2029310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_set(const char *val, struct kernel_param *kp)
2030310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
2031310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
2032310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		val += strlen("clock_");
2033310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2034310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strcasecmp(val, "monotonic") == 0)
2035310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_MONOTONIC;
2036310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else if (strcasecmp(val, "realtime") == 0)
2037310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_REALTIME;
2038310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
2039310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return -EINVAL;
2040310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2041310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	return 0;
2042310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
2043310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2044310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
2045310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		  &uvc_clock_param, S_IRUGO|S_IWUSR);
2046310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(clock, "Video buffers timestamp clock");
2047310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
2048310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
2049310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
2050310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(quirks, "Forced device quirks");
2051310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
2052310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(trace, "Trace level bitmask");
2053310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
2054310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(timeout, "Streaming control requests timeout");
2055310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2056310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart/* ------------------------------------------------------------------------
2057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Driver initialization and cleanup
2058c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
2059c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Logitech cameras listed below have their interface class set to
2062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * VENDOR_SPEC because they don't announce themselves as UVC devices, even
2063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * though they are compliant.
2064c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
2065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct usb_device_id uvc_ids[] = {
20664eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	/* LogiLink Wireless Webcam */
20674eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
20684eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
20694eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .idVendor		= 0x0416,
20704eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .idProduct		= 0xa91a,
20714eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20724eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceSubClass	= 1,
20734eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceProtocol	= 0,
20744eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2075bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	/* Genius eFace 2025 */
2076bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2077bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2078bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idVendor		= 0x0458,
2079bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idProduct		= 0x706e,
2080bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2081bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceSubClass	= 1,
2082bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceProtocol	= 0,
2083bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam NX-6000 */
2085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
2088c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x00f8,
2089c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam VX-7000 */
2094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
2097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0723,
2098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2099c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Fusion */
2103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c1,
2107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Orbit MP */
2111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c2,
2115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro for Notebook */
2119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c3,
2123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro 5000 */
2127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c5,
2131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Dell Notebook */
2135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c6,
2139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Cisco VT Camera II */
2143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c7,
2147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
215086d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	/* Chicony CNF7129 (Asus EEE 100HE) */
215186d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
215286d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
215386d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .idVendor		= 0x04f2,
215486d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .idProduct		= 0xb071,
215586d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
215686d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceSubClass	= 1,
215786d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceProtocol	= 0,
215886d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .driver_info		= UVC_QUIRK_RESTRICT_FRAME_RATE },
2159f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
2160f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2161f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2162f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idVendor		= 0x058f,
2163f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idProduct		= 0x3820,
2164f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2165f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2166f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2167f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
21683efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	/* Dell XPS m1530 */
21693efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21703efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21713efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .idVendor		= 0x05a9,
21723efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .idProduct		= 0x2640,
21733efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21743efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceSubClass	= 1,
21753efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceProtocol	= 0,
21763efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_DEF },
2177c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	/* Dell Alienware X51 */
2178c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2179c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury				| USB_DEVICE_ID_MATCH_INT_INFO,
2180c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .idVendor		= 0x05a9,
2181c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .idProduct		= 0x2643,
2182c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceClass	= USB_CLASS_VIDEO,
2183c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceSubClass	= 1,
2184c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceProtocol	= 0,
2185c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .driver_info	= UVC_QUIRK_PROBE_DEF },
2186afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	/* Dell Studio Hybrid 140g (OmniVision webcam) */
2187afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2188afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa				| USB_DEVICE_ID_MATCH_INT_INFO,
2189afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .idVendor		= 0x05a9,
2190afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .idProduct		= 0x264a,
2191afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceClass	= USB_CLASS_VIDEO,
2192afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceSubClass	= 1,
2193afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceProtocol	= 0,
2194afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Apple Built-In iSight */
21962c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x05ac,
2199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8501,
22002c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22012c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
22022c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
2203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
2204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| UVC_QUIRK_BUILTIN_ISIGHT },
2205949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	/* Foxlink ("HP Webcam" on HP Mini 5103) */
2206949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2207949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov				| USB_DEVICE_ID_MATCH_INT_INFO,
2208949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .idVendor		= 0x05c8,
2209949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .idProduct		= 0x0403,
2210949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceClass	= USB_CLASS_VIDEO,
2211949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceSubClass	= 1,
2212949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceProtocol	= 0,
2213949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Genesys Logic USB 2.0 PC Camera */
22152c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22172c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idVendor		= 0x05e3,
22182c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idProduct		= 0x0505,
22192c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22202c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
22212c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
22222c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2223e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	/* Hercules Classic Silver */
2224e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2225e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2226e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .idVendor		= 0x06f8,
2227e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .idProduct		= 0x300c,
2228e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2229e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceSubClass	= 1,
2230e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceProtocol	= 0,
2231e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2232d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Vega */
2233d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2234d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2235d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2236d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x332d,
2237d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2238d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2239d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2240d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2241d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro - Minoru3D */
2242d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2243d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2244d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2245d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3410,
2246d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2247d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2248d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2249d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2250d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Venus - Minoru3D */
2251d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
225250144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
225350144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idVendor		= 0x0ac8,
2254d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3420,
225550144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
225650144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceSubClass	= 1,
225750144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceProtocol	= 0,
225850144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2259d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	/* Ophir Optronics - SPCAM 620U */
2260d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2261d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2262d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .idVendor		= 0x0bd3,
2263d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .idProduct		= 0x0555,
2264d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2265d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceSubClass	= 1,
2266d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceProtocol	= 0,
2267d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* MT6227 */
2269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x0e8d,
2272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0004,
2273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2276bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2277bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart				| UVC_QUIRK_PROBE_DEF },
22789275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	/* IMC Networks (Medion Akoya) */
22799275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
22809275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22819275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idVendor		= 0x13d3,
22829275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idProduct		= 0x5103,
22839275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22849275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceSubClass	= 1,
22859275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceProtocol	= 0,
22869275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2287d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	/* JMicron USB2.0 XGA WebCam */
2288d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2289d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2290d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .idVendor		= 0x152d,
2291d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .idProduct		= 0x0310,
2292d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2293d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceSubClass	= 1,
2294d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceProtocol	= 0,
2295d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (HP Spartan) */
2297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x5212,
2301c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2302c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
230425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2305562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	/* Syntek (Samsung Q310) */
2306562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2307562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2308562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idVendor		= 0x174f,
2309562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idProduct		= 0x5931,
2310562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2311562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2312562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2313562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2314f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	/* Syntek (Packard Bell EasyNote MX52 */
2315f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2316f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2317f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idVendor		= 0x174f,
2318f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idProduct		= 0x8a12,
2319f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2320f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceSubClass	= 1,
2321f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceProtocol	= 0,
2322f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2323f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Syntek (Asus F9SG) */
232425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
232525e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
232625e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idVendor		= 0x174f,
232725e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idProduct		= 0x8a31,
232825e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
232925e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceSubClass	= 1,
233025e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceProtocol	= 0,
2331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (Asus U3S) */
2333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8a33,
2337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
23410ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	/* Syntek (JAOtech Smart Terminal) */
23420ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23430ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23440ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idVendor		= 0x174f,
23450ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idProduct		= 0x8a34,
23460ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
23470ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceSubClass	= 1,
23480ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceProtocol	= 0,
23490ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
235070092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	/* Miricle 307K */
235170092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
235270092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
235370092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idVendor		= 0x17dc,
235470092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idProduct		= 0x0202,
235570092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
235670092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceSubClass	= 1,
235770092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceProtocol	= 0,
235870092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2359849a3aba2d9830dc2a78a66078023e7e5ac26e15Filipe Rosset	/* Lenovo Thinkpad SL400/SL500 */
23602f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23612f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23622f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idVendor		= 0x17ef,
23632f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idProduct		= 0x480b,
23642f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
23652f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceSubClass	= 1,
23662f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceProtocol	= 0,
23672f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
23682d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	/* Aveo Technology USB 2.0 Camera */
23692d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23702d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23712d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idVendor		= 0x1871,
23722d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idProduct		= 0x0306,
23732d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
23742d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceSubClass	= 1,
23752d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceProtocol	= 0,
23765bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
23775bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart				| UVC_QUIRK_PROBE_EXTRAFIELDS },
2378c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Ecamm Pico iMage */
2379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2380c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x18cd,
2382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0xcafe,
2383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
23872bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	/* Manta MM-353 Plako */
23882bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23892bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23902bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idVendor		= 0x18ec,
23912bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idProduct		= 0x3188,
23922bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
23932bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceSubClass	= 1,
23942bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceProtocol	= 0,
23952bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2396ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	/* FSC WebCam V30S */
2397ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2398ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2399ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idVendor		= 0x18ec,
2400ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idProduct		= 0x3288,
2401ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2402ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceSubClass	= 1,
2403ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceProtocol	= 0,
2404ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
24051e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	/* Arkmicro unbranded */
24061e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24071e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24081e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idVendor		= 0x18ec,
24091e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idProduct		= 0x3290,
24101e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24111e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceSubClass	= 1,
24121e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceProtocol	= 0,
24131e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2414fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	/* The Imaging Source USB CCD cameras */
2415fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2416fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari				| USB_DEVICE_ID_MATCH_INT_INFO,
2417fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .idVendor		= 0x199e,
2418fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .idProduct		= 0x8102,
2419fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2420fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceSubClass	= 1,
2421fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceProtocol	= 0 },
2422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Bodelin ProScopeHR */
2423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_DEV_HI
2425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x19ab,
2427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x1000,
2428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bcdDevice_hi		= 0x0126,
2429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STATUS_INTERVAL },
24333bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	/* MSI StarCam 370i */
24343bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24353bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24363bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idVendor		= 0x1b3b,
24373bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idProduct		= 0x2951,
24383bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24393bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceSubClass	= 1,
24403bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceProtocol	= 0,
24413bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* SiGma Micro USB Web Camera */
2443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x1c4f,
2446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x3000,
2447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2451d732c44c1a4b54e3c59ad92069bc2fd848aca5f3Laurent Pinchart				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
2452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Generic USB Video Class */
2453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
2454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{}
2455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2457c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DEVICE_TABLE(usb, uvc_ids);
2458c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2459c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct uvc_driver uvc_driver = {
2460c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	.driver = {
2461c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "uvcvideo",
2462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.probe		= uvc_probe,
2463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.disconnect	= uvc_disconnect,
2464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.suspend	= uvc_suspend,
2465c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.resume		= uvc_resume,
24669b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart		.reset_resume	= uvc_reset_resume,
2467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.id_table	= uvc_ids,
2468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.supports_autosuspend = 1,
2469c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
2470c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2471c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int __init uvc_init(void)
2473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2474edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	int ret;
2475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2476edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_init();
2477edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
2478edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	ret = usb_register(&uvc_driver.driver);
2479edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	if (ret < 0) {
2480edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		uvc_debugfs_cleanup();
2481edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		return ret;
2482edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	}
2483edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
2484edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
2485edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	return 0;
2486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void __exit uvc_cleanup(void)
2489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2490c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_deregister(&uvc_driver.driver);
2491edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_cleanup();
2492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2494c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_init(uvc_init);
2495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_exit(uvc_cleanup);
2496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_AUTHOR(DRIVER_AUTHOR);
2498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DESCRIPTION(DRIVER_DESC);
2499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_LICENSE("GPL");
2500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_VERSION(DRIVER_VERSION);
2501f87086e302300fdff1bd32049deb7a7f3e3de7daHans Verkuil
2502