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	{
111e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.name		= "BGGR Bayer (BY8 )",
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.guid		= UVC_GUID_FORMAT_BY8,
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.fcc		= V4L2_PIX_FMT_SBGGR8,
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
115507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart	{
116e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.name		= "BGGR Bayer (BA81)",
117e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.guid		= UVC_GUID_FORMAT_BA81,
118e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.fcc		= V4L2_PIX_FMT_SBGGR8,
119e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	},
120e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	{
121e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.name		= "GBRG Bayer (GBRG)",
122e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.guid		= UVC_GUID_FORMAT_GBRG,
123e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.fcc		= V4L2_PIX_FMT_SGBRG8,
124e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	},
125e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	{
126e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.name		= "GRBG Bayer (GRBG)",
127e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.guid		= UVC_GUID_FORMAT_GRBG,
128e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.fcc		= V4L2_PIX_FMT_SGRBG8,
129e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	},
130e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	{
131e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.name		= "RGGB Bayer (RGGB)",
132e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.guid		= UVC_GUID_FORMAT_RGGB,
133e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier		.fcc		= V4L2_PIX_FMT_SRGGB8,
134e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	},
135e72ed08e66d044ed74c485da68ca809bebf99739Edgar Thier	{
136507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.name		= "RGB565",
137507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.guid		= UVC_GUID_FORMAT_RGBP,
138507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart		.fcc		= V4L2_PIX_FMT_RGB565,
139507910799160e85eac5e7729e0d2f1ba26f6a8cfLaurent Pinchart	},
14025ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky	{
14125ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.name		= "H.264",
14225ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.guid		= UVC_GUID_FORMAT_H264,
14325ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky		.fcc		= V4L2_PIX_FMT_H264,
14425ad8a8ddeeb26c77728c806a5f66608c9baa986Stephan Lachowsky	},
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Utility functions
149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		__u8 epaddr)
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep;
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = &alts->endpoint[i];
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep->desc.bEndpointAddress == epaddr)
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ep;
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int len = ARRAY_SIZE(uvc_fmts);
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < len; ++i) {
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return &uvc_fmts[i];
174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic __u32 uvc_colorspace(const __u8 primaries)
180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	static const __u8 colorprimaries[] = {
182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		0,
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SRGB,
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_M,
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_470_SYSTEM_BG,
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE170M,
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		V4L2_COLORSPACE_SMPTE240M,
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	};
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (primaries < ARRAY_SIZE(colorprimaries))
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return colorprimaries[primaries];
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Simplify a fraction using a simple continued fraction decomposition. The
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * idea here is to convert fractions such as 333333/10000000 to 1/30 using
198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arbitrary parameters to remove non-significative terms from the simple
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * respectively seems to give nice results.
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unsigned int n_terms, unsigned int threshold)
205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t *an;
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t x, y, r;
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (an == NULL)
212c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
213c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
214c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Convert the fraction to a simple continued fraction. See
215c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * http://mathforum.org/dr.math/faq/faq.fractions.html
216c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * Stop if the current term is bigger than or equal to the given
217c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * threshold.
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = *numerator;
220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = *denominator;
221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (n = 0; n < n_terms && y != 0; ++n) {
223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		an[n] = x / y;
224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (an[n] >= threshold) {
225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (n < 2)
226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				n++;
227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = x - an[n] * y;
231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = y;
232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = r;
233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
235c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Expand the simple continued fraction back to an integer fraction. */
236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	x = 0;
237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	y = 1;
238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = n; i > 0; --i) {
240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		r = y;
241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		y = an[i-1] * y + x;
242c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		x = r;
243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
244c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*numerator = y;
246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	*denominator = x;
247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(an);
248c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
251c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * to compute numerator / denominator * 10000000 using 32 bit fixed point
252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * arithmetic only.
253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartuint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
255c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
256c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uint32_t multiplier;
257c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Saturate the result if the operation would overflow. */
259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (denominator == 0 ||
260c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    numerator/denominator >= ((uint32_t)-1)/10000000)
261c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return (uint32_t)-1;
262c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Divide both the denominator and the multiplier by two until
264c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * numerator * multiplier doesn't overflow. If anyone knows a better
265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * algorithm please let me know.
266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	multiplier = 10000000;
268c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (numerator > ((uint32_t)-1)/multiplier) {
269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		multiplier /= 2;
270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		denominator /= 2;
271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
272c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return denominator ? numerator * multiplier / denominator : 0;
274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Terminal and unit management
278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2804ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchartstruct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity;
283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
284c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(entity, &dev->entities, list) {
285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (entity->id == id)
286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return entity;
287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
290c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
293c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int id, struct uvc_entity *entity)
294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i;
296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (entity == NULL)
298c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		entity = list_entry(&dev->entities, struct uvc_entity, list);
299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry_continue(entity, &dev->entities, list) {
3018ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i)
3028ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (entity->baSourceID[i] == id)
303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return entity;
304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
305c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return NULL;
307c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
308c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
3098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
3108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
3118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
3128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
3138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
3148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->header.bTerminalLink == id)
3158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return stream;
3168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
3178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
3188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return NULL;
3198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
3208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
321c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
3228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Descriptors parsing
323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_format(struct uvc_device *dev,
326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming, struct uvc_format *format,
327c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 **intervals, unsigned char *buffer, int buflen)
328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf = streaming->intf;
330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = intf->cur_altsetting;
331c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format_desc *fmtdesc;
332c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
333c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *start = buffer;
334c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int interval;
335c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n;
336c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u8 ftype;
337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->type = buffer[2];
339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format->index = buffer[3];
340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
342b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_UNCOMPRESSED:
343b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_FRAME_BASED:
344b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
345233548a2fd934a0220db8b1521c0bc88c82e5e53Laurent Pinchart		if (buflen < n) {
346b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
347c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
349c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Find the format descriptor from its GUID. */
354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		fmtdesc = uvc_format_by_guid(&buffer[5]);
355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (fmtdesc != NULL) {
357d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, fmtdesc->name,
358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				sizeof format->name);
359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = fmtdesc->fcc;
360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
36136bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
36236bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
36336bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart			snprintf(format->name, sizeof(format->name), "%pUl\n",
36436bd883ef98ac6003ab6ec7b91f66d3fb2159318Laurent Pinchart				&buffer[5]);
365c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->fcc = 0;
366c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
367c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
368c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = buffer[21];
369b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
370b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_UNCOMPRESSED;
371c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
372b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			ftype = UVC_VS_FRAME_FRAME_BASED;
373c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (buffer[27])
374c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				format->flags = UVC_FMT_FLAG_COMPRESSED;
375c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
376c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
377c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
378b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MJPEG:
379c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 11) {
380b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
381c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
382c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
383c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
384c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
385c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
387d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(format->name, "MJPEG", sizeof format->name);
388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_MJPEG;
389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED;
390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
391b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		ftype = UVC_VS_FRAME_MJPEG;
392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
394b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_DV:
395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
396b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
397c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FORMAT error\n",
398c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
399c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
400c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
401c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
402c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[8] & 0x7f) {
404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 0:
405d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SD-DV", sizeof format->name);
406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 1:
408d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "SDL-DV", sizeof format->name);
409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case 2:
411d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart			strlcpy(format->name, "HD-DV", sizeof format->name);
412c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
414b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d: unknown DV format %u\n",
416c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber, buffer[8]);
418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
419c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
420c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
421d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sizeof format->name);
423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
424c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->fcc = V4L2_PIX_FMT_DV;
425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
426c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->bpp = 0;
427c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ftype = 0;
428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Create a dummy frame descriptor. */
430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame = &format->frame[0];
431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memset(&format->frame[0], 0, sizeof format->frame[0]);
432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIntervalType = 1;
433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval = 1;
434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		*(*intervals)++ = 1;
436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->nframes = 1;
437c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
439b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_MPEG2TS:
440b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_FORMAT_STREAM_BASED:
441c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Not supported yet. */
442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
443b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       "interface %d unsupported format %u\n",
445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       dev->udev->devnum, alts->desc.bInterfaceNumber,
446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		       buffer[2]);
447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
448c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
449c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * based formats have frame descriptors.
457c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
458c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
459c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	       buffer[2] == ftype) {
460078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		frame = &format->frame[format->nframes];
461b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED)
462c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 25 ? buffer[25] : 0;
463c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
464c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen > 21 ? buffer[21] : 0;
465c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
466c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = n ? n : 3;
467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 26 + 4*n) {
469b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
470c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d FRAME error\n", dev->udev->devnum,
471c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
472c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
473c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
474c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
475c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bFrameIndex = buffer[3];
476c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->bmCapabilities = buffer[4];
4779bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wWidth = get_unaligned_le16(&buffer[5]);
4789bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->wHeight = get_unaligned_le16(&buffer[7]);
4799bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
4809bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
481b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (ftype != UVC_VS_FRAME_FRAME_BASED) {
482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize =
4839bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4859bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[21]);
486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[25];
487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		} else {
488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = 0;
489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwDefaultFrameInterval =
4909bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le32(&buffer[17]);
491c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->bFrameIntervalType = buffer[21];
492c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
493c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwFrameInterval = *intervals;
494c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
495c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
496c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * completely. Observed behaviours range from setting the
4972c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * value to 1.1x the actual frame size to hardwiring the
498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 16 low bits to 0. This results in a higher than necessary
499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * memory usage as well as a wrong image size information. For
500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * uncompressed formats this can be fixed by computing the
501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * value from the frame size.
502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->dwMaxVideoFrameBufferSize = format->bpp
505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				* frame->wWidth * frame->wHeight / 8;
506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Some bogus devices report dwMinFrameInterval equal to
508c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * dwMaxFrameInterval and have dwFrameIntervalStep set to
509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * zero. Setting all null intervals to 1 fixes the problem and
5102c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart		 * some other divisions by zero that could happen.
511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
5139bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			interval = get_unaligned_le32(&buffer[26+4*i]);
514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			*(*intervals)++ = interval ? interval : 1;
515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure that the default frame interval stays between
518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * the boundaries.
519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n -= frame->bFrameIntervalType ? 1 : 2;
521c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		frame->dwDefaultFrameInterval =
522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			min(frame->dwFrameInterval[n],
523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    max(frame->dwFrameInterval[0],
524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				frame->dwDefaultFrameInterval));
525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
52686d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart		if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
52786d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart			frame->bFrameIntervalType = 1;
52886d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart			frame->dwFrameInterval[0] =
52986d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart				frame->dwDefaultFrameInterval;
53086d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart		}
53186d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart
532c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
533c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame->wWidth, frame->wHeight,
534c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			10000000/frame->dwDefaultFrameInterval,
535c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			(100000000/frame->dwDefaultFrameInterval)%10);
536c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
537078f8947926732a526fb280c0f3a8920bf173b9cLaurent Pinchart		format->nframes++;
538c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
539c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
542c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
543c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
546c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
548c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
549c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	    buffer[2] == UVC_VS_COLORFORMAT) {
550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 6) {
551b2d9cc4226fa512aa36fd78738f5069dfce0583dLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       "interface %d COLORFORMAT error\n",
553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       dev->udev->devnum,
554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			       alts->desc.bInterfaceNumber);
555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
557c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		format->colorspace = uvc_colorspace(buffer[3]);
559c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
561c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
563c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return buffer - start;
565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
567c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_streaming(struct uvc_device *dev,
568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf)
569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
570c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_streaming *streaming = NULL;
571c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_format *format;
572c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_frame *frame;
573c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = &intf->altsetting[0];
574c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *_buffer, *buffer = alts->extra;
575c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int _buflen, buflen = alts->extralen;
576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int nformats = 0, nframes = 0, nintervals = 0;
577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int size, i, n, p;
578c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u32 *interval;
579c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 psize;
580c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret = -EINVAL;
581c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
582c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass
583b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		!= UVC_SC_VIDEOSTREAMING) {
584c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
585c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"video streaming interface\n", dev->udev->devnum,
586c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
587c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
588c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
589c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
590c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
591c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"claimed\n", dev->udev->devnum,
593c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf->altsetting[0].desc.bInterfaceNumber);
594c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
595c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
596c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
597c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
598c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (streaming == NULL) {
599c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		usb_driver_release_interface(&uvc_driver.driver, intf);
600c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -EINVAL;
601c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
602c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
603c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	mutex_init(&streaming->mutex);
60435f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	streaming->dev = dev;
605c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intf = usb_get_intf(intf);
606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
607c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
608c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* The Pico iMage webcam has its class-specific interface descriptors
609c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * after the endpoint descriptors.
610c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
611c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen == 0) {
612c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
613c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			struct usb_host_endpoint *ep = &alts->endpoint[i];
614c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
615c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen == 0)
616c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
617c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
618c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ep->extralen > 2 &&
619c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			    ep->extra[1] == USB_DT_CS_INTERFACE) {
620c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "trying extra data "
621c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"from endpoint %u.\n", i);
622c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer = alts->endpoint[i].extra;
623c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buflen = alts->endpoint[i].extralen;
624c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				break;
625c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
626c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
627c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
628c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
629c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Skip the standard interface descriptors. */
630c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
631c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
632c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
633c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
634c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
635c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (buflen <= 2) {
636c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
637c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"interface descriptors found.\n");
638c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
639c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
640c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
641c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the header descriptor. */
642ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	switch (buffer[2]) {
643b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_OUTPUT_HEADER:
644ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
645ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 9;
646ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
647ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
648b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VS_INPUT_HEADER:
649ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
650ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		size = 13;
651ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
652ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
653ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	default:
654c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
655ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"%d HEADER descriptor not found.\n", dev->udev->devnum,
656ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			alts->desc.bInterfaceNumber);
657c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
658ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
659c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
660ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	p = buflen >= 4 ? buffer[3] : 0;
661ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	n = buflen >= size ? buffer[size-1] : 0;
662ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
663ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (buflen < size + p*n) {
664ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
665ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			"interface %d HEADER descriptor is invalid.\n",
666ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
667ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		goto error;
668ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
669c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
670ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bNumFormats = p;
671ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bEndpointAddress = buffer[6];
672b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (buffer[2] == UVC_VS_INPUT_HEADER) {
673c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bmInfo = buffer[7];
674c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTerminalLink = buffer[8];
675c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bStillCaptureMethod = buffer[9];
676c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerSupport = buffer[10];
677c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		streaming->header.bTriggerUsage = buffer[11];
678c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
679ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		streaming->header.bTerminalLink = buffer[7];
680ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
681ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	streaming->header.bControlSize = n;
682ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
6830b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall	streaming->header.bmaControls = kmemdup(&buffer[size], p * n,
6840b21d55f8904ff3d52262e91867f9eb2c0b472f3Julia Lawall						GFP_KERNEL);
685ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	if (streaming->header.bmaControls == NULL) {
686ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		ret = -ENOMEM;
687c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
688c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
689c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
690c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buflen -= buffer[0];
691c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	buffer += buffer[0];
692c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
693c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buffer = buffer;
694c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	_buflen = buflen;
695c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
696c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Count the format and frame descriptors. */
697042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
698c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (_buffer[2]) {
699b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
700b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
701b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
702c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
703c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
704c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
705b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
706c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			/* DV format has no frame descriptor. We will create a
707c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 * dummy frame descriptor with a dummy frame interval.
708c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			 */
709c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nformats++;
710c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
711c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nintervals++;
712c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
713c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
714b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MPEG2TS:
715b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_STREAM_BASED:
716c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
717c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d FORMAT %u is not supported.\n",
718c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				dev->udev->devnum,
719c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, _buffer[2]);
720c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
721c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
722b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_UNCOMPRESSED:
723b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_MJPEG:
724c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
725c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 25)
726c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[25] ? _buffer[25] : 3;
727c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
728c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
729b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FRAME_FRAME_BASED:
730c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			nframes++;
731c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (_buflen > 21)
732c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				nintervals += _buffer[21] ? _buffer[21] : 3;
733c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
734c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
735c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
736c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buflen -= _buffer[0];
737c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		_buffer += _buffer[0];
738c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
739c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
740c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (nformats == 0) {
741c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
742c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"%d has no supported formats defined.\n",
743c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber);
744c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
745c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
746c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
747c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	size = nformats * sizeof *format + nframes * sizeof *frame
748c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	     + nintervals * sizeof *interval;
749c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	format = kzalloc(size, GFP_KERNEL);
750c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (format == NULL) {
751c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ret = -ENOMEM;
752c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
753c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
754c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
755c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	frame = (struct uvc_frame *)&format[nformats];
756c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = (__u32 *)&frame[nframes];
757c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
758c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->format = format;
759c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	streaming->nformats = nformats;
760c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
761c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the format descriptors. */
762042e143e8b21dca7c84e32c2e647980cb9101224Laurent Pinchart	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
763c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (buffer[2]) {
764b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_UNCOMPRESSED:
765b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_MJPEG:
766b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_DV:
767b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		case UVC_VS_FORMAT_FRAME_BASED:
768c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format->frame = frame;
769c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret = uvc_parse_format(dev, streaming, format,
770c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				&interval, buffer, buflen);
771c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (ret < 0)
772c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				goto error;
773c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
774c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			frame += format->nframes;
775c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			format++;
776c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
777c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buflen -= ret;
778c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			buffer += ret;
779c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
780c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
781c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
782c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
783c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
784c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
785c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
786c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
787c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
788c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
789c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart	if (buflen)
790c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
791c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			"%d has %u bytes of trailing descriptor garbage.\n",
792c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart			dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
793c4ed8c66d79d707d89fe732ff5b97739edf1ba62Laurent Pinchart
794c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the alternate settings to find the maximum bandwidth. */
795c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	for (i = 0; i < intf->num_altsetting; ++i) {
796c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep;
797c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		alts = &intf->altsetting[i];
798c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		ep = uvc_find_endpoint(alts,
799c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				streaming->header.bEndpointAddress);
800c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (ep == NULL)
801c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
802c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
803c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = le16_to_cpu(ep->desc.wMaxPacketSize);
804c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
805c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (psize > streaming->maxpsize)
806c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			streaming->maxpsize = psize;
807c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
808c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
80935f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_add_tail(&streaming->list, &dev->streams);
810c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
811c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
812c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
813c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_driver_release_interface(&uvc_driver.driver, intf);
814c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_put_intf(intf);
815c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->format);
816c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming->header.bmaControls);
817c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	kfree(streaming);
818c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
819c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
820c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
8218ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchartstatic struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
8228ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unsigned int num_pads, unsigned int extra_size)
8238ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart{
8248ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	struct uvc_entity *entity;
8258ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int num_inputs;
8268ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	unsigned int size;
8274ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	unsigned int i;
8288ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8294ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	extra_size = ALIGN(extra_size, sizeof(*entity->pads));
8308ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
8314ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
8324ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	     + num_inputs;
8338ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity = kzalloc(size, GFP_KERNEL);
8348ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	if (entity == NULL)
8358ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		return NULL;
8368ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8378ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->id = id;
8388ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->type = type;
8398ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8404ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->num_links = 0;
8414ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->num_pads = num_pads;
8424ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->pads = ((void *)(entity + 1)) + extra_size;
8434ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
8444ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	for (i = 0; i < num_inputs; ++i)
8454ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
8464ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	if (!UVC_ENTITY_IS_OTERM(entity))
8474ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
8484ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
8498ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	entity->bNrInPins = num_inputs;
8504ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart	entity->baSourceID = (__u8 *)(&entity->pads[num_pads]);
8518ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
8528ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart	return entity;
8538ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart}
8548ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart
855c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* Parse vendor-specific extensions. */
856c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_vendor_control(struct uvc_device *dev,
857c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
858c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
859c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit;
862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int n, p;
863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int handled = 0;
864c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
865c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0x046d:		/* Logitech */
867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[1] != 0x41 || buffer[2] != 0x01)
868c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Logitech implements several vendor specific functions
871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * through vendor specific extension units (LXU).
872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * The LXU descriptors are similar to XU descriptors
874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * (see "USB Device Video Class for Video Devices", section
875c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 3.7.2.6 "Extension Unit Descriptor") with the following
876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * differences:
877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 0		bLength		1	 Number
880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Size of this descriptor, in bytes: 24+p+n*2
881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
882c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n	bmControlsType	N	Bitmap
883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	Individual bits in the set are defined:
884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	0: Absolute
885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	1: Relative
886c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *
887c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 	This bitset is mapped exactly the same as bmControls.
888c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
889c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 23+p+n*2	bReserved	1	Boolean
890c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * 24+p+n*2	iExtension	1	Index
892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	Index of a string descriptor that describes this
893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 *	extension unit.
894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * ----------------------------------------------------------
895c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
896c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
897c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 25 + p ? buffer[22+p] : 0;
898c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
899c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 25 + p + 2*n) {
900c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
901c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
902c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
903c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
904c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
905c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9068ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
9078ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					p + 1, 2*n);
908c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
909c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
910c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
911c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
912c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
9138ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
9158ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
9168ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
9178ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					       + n;
918c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[24+p+2*n] != 0)
921c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[24+p+2*n], unit->name,
922c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
923c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
924c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
925c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		handled = 1;
928c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return handled;
932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_standard_control(struct uvc_device *dev,
935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	const unsigned char *buffer, int buflen)
936c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = dev->udev;
938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *unit, *term;
939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_interface *intf;
940c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int i, n, p, len;
942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	__u16 type;
943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (buffer[2]) {
945b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_HEADER:
946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 12 ? buffer[11] : 0;
947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
948daf41ac2c4b5b2e663079ccc58b8d6a70a3c111bOliver Neukum		if (buflen < 12 + n) {
949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d HEADER error\n", udev->devnum,
951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber);
952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
953c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
954c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
9559bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->uvc_version = get_unaligned_le16(&buffer[3]);
9569bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		dev->clock_frequency = get_unaligned_le32(&buffer[7]);
957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
958c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Parse all USB Video Streaming interfaces. */
959c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		for (i = 0; i < n; ++i) {
960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			intf = usb_ifnum_to_if(udev, buffer[12+i]);
961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (intf == NULL) {
962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "device %d "
963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"interface %d doesn't exists\n",
964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					udev->devnum, i);
965c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				continue;
966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_parse_streaming(dev, intf);
969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
971c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
972b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_INPUT_TERMINAL:
973c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 8) {
974c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
975c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
976c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
977c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
978c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
980c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
981c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
982c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
9839bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
985c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
986c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL %d has invalid "
987c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber,
989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				buffer[3], type);
990c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
993c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = 0;
994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = 0;
995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		len = 8;
996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
997b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (type == UVC_ITT_CAMERA) {
998c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 15 ? buffer[14] : 0;
999c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 15;
1000c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1001b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
1002c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			n = buflen >= 9 ? buffer[8] : 0;
1003c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			p = buflen >= 10 + n ? buffer[9+n] : 0;
1004c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			len = 10;
1005c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1006c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < len + n + p) {
1008c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1009c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d INPUT_TERMINAL error\n",
1010c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1011c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1012c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1013c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10148ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
10158ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, n + p);
1016c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
1017c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1018c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1019b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
1020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bControlSize = n;
1021c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.bmControls = (__u8 *)term + sizeof *term;
1022c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMin =
10239bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[8]);
1024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wObjectiveFocalLengthMax =
10259bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[10]);
1026c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->camera.wOcularFocalLength =
10279bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich				get_unaligned_le16(&buffer[12]);
1028c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->camera.bmControls, &buffer[15], n);
1029b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		} else if (UVC_ENTITY_TYPE(term) ==
1030b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart			   UVC_ITT_MEDIA_TRANSPORT_INPUT) {
1031c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bControlSize = n;
1032c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmControls = (__u8 *)term + sizeof *term;
1033c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bTransportModeSize = p;
1034c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			term->media.bmTransportModes = (__u8 *)term
1035c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart						     + sizeof *term + n;
1036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmControls, &buffer[9], n);
1037c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
1038c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1039c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1040c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[7] != 0)
1041c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[7], term->name,
1042c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1043b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
1044c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Camera %u", buffer[3]);
1045b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
1046c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Media %u", buffer[3]);
1047c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1048c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Input %u", buffer[3]);
1049c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1050c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1051c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1052c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1053b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_OUTPUT_TERMINAL:
1054c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 9) {
1055c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1056c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL error\n",
1057c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1058c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1059c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1060c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1061c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Make sure the terminal type MSB is not null, otherwise it
1062c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 * could be confused with a unit.
1063c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		 */
10649bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich		type = get_unaligned_le16(&buffer[4]);
1065c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((type & 0xff00) == 0) {
1066c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1067c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d OUTPUT_TERMINAL %d has invalid "
1068c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"type 0x%04x, skipping\n", udev->devnum,
1069c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				alts->desc.bInterfaceNumber, buffer[3], type);
1070c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return 0;
1071c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1072c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10738ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
10748ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart					1, 0);
1075c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (term == NULL)
1076c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10788ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(term->baSourceID, &buffer[7], 1);
1079c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8] != 0)
1081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8], term->name,
1082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof term->name);
1083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(term->name, "Output %u", buffer[3]);
1085c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1086c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&term->list, &dev->entities);
1087c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1088c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1089b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1090c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 5 ? buffer[4] : 0;
1091c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1092c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 5 || buflen < 6 + p) {
1093c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1094c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d SELECTOR_UNIT error\n",
1095c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1096c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1097c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1098c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
10998ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
1100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11038ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[5], p);
1104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[5+p] != 0)
1106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[5+p], unit->name,
1107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Selector %u", buffer[3]);
1110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1114b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 8 ? buffer[7] : 0;
1116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = dev->uvc_version >= 0x0110 ? 10 : 9;
1117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < p + n) {
1119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d PROCESSING_UNIT error\n",
1121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11258ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
1126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11298ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[4], 1);
1130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.wMaxMultiplier =
11319bc6218dc1dc7bd421f3d141241c8e0e70c4e92bMichael Hennerich			get_unaligned_le16(&buffer[5]);
1132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bControlSize = buffer[7];
1133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
1134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->processing.bmControls, &buffer[8], n);
1135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (dev->uvc_version >= 0x0110)
1136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			unit->processing.bmVideoStandards = buffer[9+n];
1137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[8+n] != 0)
1139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[8+n], unit->name,
1140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Processing %u", buffer[3]);
1143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1147b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		p = buflen >= 22 ? buffer[21] : 0;
1149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		n = buflen >= 24 + p ? buffer[22+p] : 0;
1150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buflen < 24 + p + n) {
1152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
1153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"interface %d EXTENSION_UNIT error\n",
1154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devnum, alts->desc.bInterfaceNumber);
1155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -EINVAL;
1156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
11588ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
1159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (unit == NULL)
1160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -ENOMEM;
1161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
1163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bNumControls = buffer[20];
11648ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		memcpy(unit->baSourceID, &buffer[22], p);
1165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		unit->extension.bControlSize = buffer[22+p];
11668ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
1167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		memcpy(unit->extension.bmControls, &buffer[23+p], n);
1168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (buffer[23+p+n] != 0)
1170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			usb_string(udev, buffer[23+p+n], unit->name,
1171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				   sizeof unit->name);
1172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		else
1173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			sprintf(unit->name, "Extension %u", buffer[3]);
1174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		list_add_tail(&unit->list, &dev->entities);
1176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1179c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
1180c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptor (%u)\n", buffer[2]);
1181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1182c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_parse_control(struct uvc_device *dev)
1188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_interface *alts = dev->intf->cur_altsetting;
1190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned char *buffer = alts->extra;
1191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int buflen = alts->extralen;
1192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Parse the default alternate setting only, as the UVC specification
1195c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * defines a single alternate setting, the default alternate setting
1196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * zero.
1197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1198c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (buflen > 2) {
1200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_parse_vendor_control(dev, buffer, buflen) ||
1201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    buffer[1] != USB_DT_CS_INTERFACE)
1202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			goto next_descriptor;
1203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
1205c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return ret;
1206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartnext_descriptor:
1208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buflen -= buffer[0];
1209c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		buffer += buffer[0];
1210c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1211c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1212538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	/* Check if the optional status endpoint is present. Built-in iSight
1213538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * webcams have an interrupt endpoint but spit proprietary data that
1214538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * don't conform to the UVC status endpoint messages. Don't try to
1215538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 * handle the interrupt endpoint for those cameras.
1216538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	 */
1217538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	if (alts->desc.bNumEndpoints == 1 &&
1218538e7a004bf960c96c7e9eb836b59989eb5f5b7fLaurent Pinchart	    !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
1219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_host_endpoint *ep = &alts->endpoint[0];
1220c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		struct usb_endpoint_descriptor *desc = &ep->desc;
1221c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1222c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (usb_endpoint_is_int_in(desc) &&
1223c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
1224c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		    desc->bInterval != 0) {
1225c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
1226c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(addr %02x).\n", desc->bEndpointAddress);
1227c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			dev->int_ep = ep;
1228c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1229c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1230c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1231c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1232c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1233c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1234c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
12358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * UVC device scan
1236c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
1237c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1238c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
1239c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Scan the UVC descriptors to locate a chain starting at an Output Terminal
1240c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * and containing the following units:
1241c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - one or more Output Terminals (USB Streaming or Display)
1243c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one Processing Unit
12448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * - zero, one or more single-input Selector Units
1245c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero or one multiple-input Selector Units, provided all inputs are
1246c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *   connected to input terminals
1247c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * - zero, one or mode single-input Extension Units
12482c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart * - one or more Input Terminals (Camera, External or USB Streaming)
1249c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The terminal and units must match on of the following structures:
12518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
12538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
12548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
12558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(0)
12578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
12588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *                 +---------+    +---------+ -> OTT_*(n)
12598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart *
12608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * The Processing Unit and Extension Units can be in any order. Additional
12618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Extension Units connected to the main chain as single-unit branches are
12628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * also supported. Single-input Selector Units are ignored.
1263c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
12648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_entity(struct uvc_video_chain *chain,
1265c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity)
1266c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1267c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1268b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1270c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- XU %d", entity->id);
1271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12728ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins != 1) {
1273c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
1274c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"than 1 input pin.\n", entity->id);
1275c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1276c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1277c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1278c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1279c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1280b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
1281c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1282c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- PU %d", entity->id);
1283c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->processing != NULL) {
1285c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
1286c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Processing Units in chain.\n");
1287c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1288c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1289c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
12908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->processing = entity;
1291c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1292c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1293b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1294c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1295c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- SU %d", entity->id);
1296c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1297c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
12988ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1)
1299c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1300c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain->selector != NULL) {
1302c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
1303c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"Units in chain.\n");
1304c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return -1;
1305c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1306c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
1308c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1309c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1310b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
1311b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_CAMERA:
1312b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
1313c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1314c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT %d\n", entity->id);
1315c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1316c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1317c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13184093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
13194093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_DISPLAY:
13204093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13214093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
13224093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart			printk(" OT %d", entity->id);
13234093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart
13244093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart		break;
13254093a5c4a3f59cba1a085bbf87b6ffdddc5a443dLaurent Pinchart
1326b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_TT_STREAMING:
13274057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (UVC_ENTITY_IS_ITERM(entity)) {
13284057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
13294057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" <- IT %d\n", entity->id);
13304057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		} else {
13314057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
13324057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				printk(" OT %d", entity->id);
1333ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		}
1334ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1335ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart		break;
1336ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
1337c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
1338c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1339c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
1340c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1341c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1342c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13436241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_add_tail(&entity->chain, &chain->entities);
1344c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1345c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1346c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_forward(struct uvc_video_chain *chain,
1348c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, struct uvc_entity *prev)
1349c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1350c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *forward;
1351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int found;
1352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Forward scan */
1354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	forward = NULL;
1355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	found = 0;
1356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	while (1) {
13588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		forward = uvc_entity_by_reference(chain->dev, entity->id,
1359c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			forward);
1360c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (forward == NULL)
1361c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
13628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (forward == prev)
1363c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1364c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		switch (UVC_ENTITY_TYPE(forward)) {
13668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_VC_EXTENSION_UNIT:
13678ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			if (forward->bNrInPins != 1) {
13688e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
13698e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  "has more than 1 input pin.\n",
13708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					  entity->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(" XU %d", forward->id);
13808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
13818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
13828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
13838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_VENDOR_SPECIFIC:
13858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_DISPLAY:
13868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
13878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		case UVC_TT_STREAMING:
13888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (UVC_ENTITY_IS_ITERM(forward)) {
13898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
13908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					"terminal %u.\n", forward->id);
13918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				return -EINVAL;
13928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
1393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
13946241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&forward->chain, &chain->entities);
13958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE) {
13968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				if (!found)
13978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart					printk(" (->");
13988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
13998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				printk(" OT %d", forward->id);
14008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				found = 1;
14018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			}
14028e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			break;
1403c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1404c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1405c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (found)
1406c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		printk(")");
1407c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1408c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1409c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1410c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain_backward(struct uvc_video_chain *chain,
14124057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity **_entity)
1413c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
14144057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	struct uvc_entity *entity = *_entity;
1415c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
14164057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	int id = -EINVAL, i;
1417c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1418c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (UVC_ENTITY_TYPE(entity)) {
1419b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_EXTENSION_UNIT:
1420b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_PROCESSING_UNIT:
14218ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = entity->baSourceID[0];
1422c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
1423c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1424b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	case UVC_VC_SELECTOR_UNIT:
1425c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Single-input selector units are ignored. */
14268ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		if (entity->bNrInPins == 1) {
14278ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[0];
1428c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
1429c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1430c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1431c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1432c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk(" <- IT");
1433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->selector = entity;
14358ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		for (i = 0; i < entity->bNrInPins; ++i) {
14368ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart			id = entity->baSourceID[i];
14378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			term = uvc_entity_by_id(chain->dev, id);
1438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
1439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
1440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input %d isn't connected to an "
1441c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart					"input terminal\n", entity->id, i);
1442c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				return -1;
1443c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			}
1444c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1445c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			if (uvc_trace_param & UVC_TRACE_PROBE)
1446c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				printk(" %d", term->id);
1447c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14486241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			list_add_tail(&term->chain, &chain->entities);
14498e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_scan_chain_forward(chain, term, entity);
1450c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1451c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1452c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (uvc_trace_param & UVC_TRACE_PROBE)
1453c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			printk("\n");
1454c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1455c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		id = 0;
1456c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
14574057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14584057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_VENDOR_SPECIFIC:
14594057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_CAMERA:
14604057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
14614057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_VENDOR_SPECIFIC:
14624057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_DISPLAY:
14634057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
14644057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	case UVC_TT_STREAMING:
14658ca5a639f4f3eb8958a7e270fcff7516374637a5Laurent Pinchart		id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
14664057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		break;
1467c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1468c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14694057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (id <= 0) {
14704057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		*_entity = NULL;
14714057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return id;
14724057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14734057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14744057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = uvc_entity_by_id(chain->dev, id);
14754057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	if (entity == NULL) {
14764057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14774057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			"unknown entity %d.\n", id);
14784057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		return -EINVAL;
14794057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	}
14804057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart
14814057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	*_entity = entity;
14824057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	return 0;
1483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_scan_chain(struct uvc_video_chain *chain,
14864057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			  struct uvc_entity *term)
1487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1488c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *entity, *prev;
1489c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14904057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
1491ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart
14924057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	entity = term;
14934057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	prev = NULL;
14948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
14954057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart	while (entity != NULL) {
14964057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		/* Entity must not be part of an existing chain */
14978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (entity->chain.next || entity->chain.prev) {
14988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
14994057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart				"entity %d already in chain.\n", entity->id);
15008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
1502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Process entity */
15048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_entity(chain, entity) < 0)
15058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1506c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Forward scan */
15088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain_forward(chain, entity, prev) < 0)
15098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -EINVAL;
1510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		/* Backward scan */
15124057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		prev = entity;
15134057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart		if (uvc_scan_chain_backward(chain, &entity) < 0)
15144057ac6ca9a77c4275b34b5925ab5c99557913b1Laurent Pinchart			return -EINVAL;
1515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
15188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
15198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15206241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchartstatic unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
15216241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		char *buffer)
15228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
15238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
15248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	unsigned int nterms = 0;
15258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
15268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(term, terms, chain) {
15286241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (!UVC_ENTITY_IS_TERM(term) ||
15296241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		    UVC_TERM_DIRECTION(term) != dir)
15306241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			continue;
15316241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart
15326241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (nterms)
15338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			p += sprintf(p, ",");
15346241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		if (++nterms >= 4) {
15356241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			p += sprintf(p, "...");
15366241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart			break;
15378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
15386241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		p += sprintf(p, "%u", term->id);
1539ff924203c9e4a5bc218143bc37182851185f4e5fLaurent Pinchart	}
1540c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return p - buffer;
15428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
15438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic const char *uvc_print_chain(struct uvc_video_chain *chain)
15458e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
15468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	static char buffer[43];
15478e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	char *p = buffer;
15488e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15496241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
15508e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	p += sprintf(p, " -> ");
15516241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
15528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return buffer;
1554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1556c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
155735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart * Scan the device for video chains and register video devices.
1558c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
15598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Chains are scanned starting at their output terminals and walked backwards.
1560c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
156135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchartstatic int uvc_scan_device(struct uvc_device *dev)
1562c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
15638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
1564c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_entity *term;
1565c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1566c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	list_for_each_entry(term, &dev->entities, list) {
15678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (!UVC_ENTITY_IS_OTERM(term))
1568c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1569c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15708e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		/* If the terminal is already included in a chain, skip it.
15718e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * This can happen for chains that have multiple output
15728e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * terminals, where all output terminals beside the first one
15738e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 * will be inserted in the chain in forward scans.
15748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		 */
15758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (term->chain.next || term->chain.prev)
1576c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			continue;
1577c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
15788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
15798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (chain == NULL)
15808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return -ENOMEM;
15818e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15826241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		INIT_LIST_HEAD(&chain->entities);
15838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		mutex_init(&chain->ctrl_mutex);
15848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		chain->dev = dev;
15850550513c7a559b4933c5e1d47fbd15d15f6078d5Laurent Pinchart		v4l2_prio_init(&chain->prio);
15868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15878be8ec6ea58bd77338f6ffa2f6d2acfc88b835f4Laurent Pinchart		term->flags |= UVC_ENTITY_FLAG_DEFAULT;
15888be8ec6ea58bd77338f6ffa2f6d2acfc88b835f4Laurent Pinchart
15898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (uvc_scan_chain(chain, term) < 0) {
15908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			kfree(chain);
15918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
1592c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
15938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
15958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			  uvc_print_chain(chain));
15968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
15978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		list_add_tail(&chain->list, &dev->chains);
1598c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1599c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (list_empty(&dev->chains)) {
1601c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "No valid video chain found.\n");
1602c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -1;
1603c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1604c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1605c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1606c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1607c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
16088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
16098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Video device registration and unregistration
16108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
16128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
1613716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Delete the UVC device.
1614716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1615716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * Called by the kernel when the last reference to the uvc_device structure
1616716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * is released.
1617716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart *
1618716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * As this function is called after or during disconnect(), all URBs have
1619716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * already been canceled by the USB core. There is no need to kill the
1620716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart * interrupt URB manually.
1621716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart */
1622716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_delete(struct uvc_device *dev)
1623716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1624716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct list_head *p, *n;
1625716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1626716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_intf(dev->intf);
1627716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	usb_put_dev(dev->udev);
1628716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1629716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_status_cleanup(dev);
1630716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_ctrl_cleanup_device(dev);
1631716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16325a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (dev->vdev.dev)
16335a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		v4l2_device_unregister(&dev->vdev);
16345a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
16355a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (media_devnode_is_registered(&dev->mdev.devnode))
16365a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		media_device_unregister(&dev->mdev);
16375a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#endif
16385a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
1639716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->chains) {
1640716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_video_chain *chain;
1641716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		chain = list_entry(p, struct uvc_video_chain, list);
1642716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(chain);
1643716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1644716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1645716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->entities) {
1646716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_entity *entity;
1647716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		entity = list_entry(p, struct uvc_entity, list);
16484ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
16494ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		uvc_mc_cleanup_entity(entity);
16504ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#endif
16518a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		if (entity->vdev) {
16528a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart			video_device_release(entity->vdev);
16538a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart			entity->vdev = NULL;
16548a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		}
1655716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(entity);
1656716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1657716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1658716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	list_for_each_safe(p, n, &dev->streams) {
1659716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		struct uvc_streaming *streaming;
1660716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		streaming = list_entry(p, struct uvc_streaming, list);
1661716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_driver_release_interface(&uvc_driver.driver,
1662716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart			streaming->intf);
1663716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		usb_put_intf(streaming->intf);
1664716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->format);
1665716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming->header.bmaControls);
1666716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		kfree(streaming);
1667716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	}
1668716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1669716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	kfree(dev);
1670716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1671716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1672716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchartstatic void uvc_release(struct video_device *vdev)
1673716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart{
1674716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_streaming *stream = video_get_drvdata(vdev);
1675716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	struct uvc_device *dev = stream->dev;
1676716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1677716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the registered streams count and delete the device when it
1678716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * reaches zero.
1679716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1680716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1681716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
1682716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart}
1683716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1684716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart/*
16858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Unregister the video devices.
16868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
16878e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic void uvc_unregister_video(struct uvc_device *dev)
16888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
16898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
16908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1691716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Unregistering all video devices might result in uvc_delete() being
1692716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * called from inside the loop if there's no open file handle. To avoid
1693716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * that, increment the stream count before iterating over the streams
1694716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * and decrement it when done.
1695716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1696716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
1697716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
16988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
16998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream->vdev == NULL)
17008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1702716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		video_unregister_device(stream->vdev);
17038e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
1704edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
1705edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		uvc_debugfs_cleanup_stream(stream);
17068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
1707716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart
1708716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	/* Decrement the stream count and call uvc_delete explicitly if there
1709716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 * are no stream left.
1710716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	 */
1711716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	if (atomic_dec_and_test(&dev->nstreams))
1712716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart		uvc_delete(dev);
17138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17158e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_video(struct uvc_device *dev,
17168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		struct uvc_streaming *stream)
17178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17188e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct video_device *vdev;
17198e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17208e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17218e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Initialize the streaming interface with default streaming
17228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * parameters.
17238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = uvc_video_init(stream);
17258e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
17268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to initialize the device "
17278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			"(%d).\n", ret);
17288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
17298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1731edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_init_stream(stream);
1732edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
17338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Register the device with V4L. */
17348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev = video_device_alloc();
17358e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (vdev == NULL) {
17368e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
17378e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
17388e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return -ENOMEM;
17398e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17408e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17418e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* We already hold a reference to dev->udev. The video device will be
17428e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * unregistered before the reference is released, so we don't need to
17438e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * get another one.
17448e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17455a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	vdev->v4l2_dev = &dev->vdev;
17468e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	vdev->fops = &uvc_fops;
1747716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	vdev->release = uvc_release;
17480550513c7a559b4933c5e1d47fbd15d15f6078d5Laurent Pinchart	vdev->prio = &stream->chain->prio;
1749954f340fc7f2fa2ae8812670da49e828d2686d8eHans Verkuil	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1750954f340fc7f2fa2ae8812670da49e828d2686d8eHans Verkuil		vdev->vfl_dir = VFL_DIR_TX;
17518e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	strlcpy(vdev->name, dev->name, sizeof vdev->name);
17528e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17538e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Set the driver data before calling video_register_device, otherwise
17548e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 * uvc_v4l2_open might race us.
17558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	 */
17568e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	stream->vdev = vdev;
17578e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	video_set_drvdata(vdev, stream);
17588e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17598e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
17608e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (ret < 0) {
17618e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
17628e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			   ret);
17638e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->vdev = NULL;
17648e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		video_device_release(vdev);
17658e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		return ret;
17668e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
17678e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1768f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1769f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart		stream->chain->caps |= V4L2_CAP_VIDEO_CAPTURE;
1770f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart	else
1771f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart		stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT;
1772f887e99ae2210e23c9726b6f146938a84f6acc47Laurent Pinchart
1773716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_inc(&dev->nstreams);
17748e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
17758e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
17768e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17778e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/*
17788e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * Register all video devices in all chains.
17798e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
17808e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_terms(struct uvc_device *dev,
17816241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	struct uvc_video_chain *chain)
17828e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
17838e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_streaming *stream;
17848e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_entity *term;
17858e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
17868e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17876241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart	list_for_each_entry(term, &chain->entities, chain) {
17888e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
17898e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17908e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17918e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream = uvc_stream_by_id(dev, term->id);
17928e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (stream == NULL) {
17938e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			uvc_printk(KERN_INFO, "No streaming interface found "
17948e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart				   "for terminal %u.", term->id);
17958e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			continue;
17968e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		}
17978e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
17988e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		stream->chain = chain;
17998e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		ret = uvc_register_video(dev, stream);
18008e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
18018e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
18028a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart
18038a65a9485832f90e18e2f7069b75a4181e2840c0Laurent Pinchart		term->vdev = stream->vdev;
18048e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
18058e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18068e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
18078e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
18088e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18098e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchartstatic int uvc_register_chains(struct uvc_device *dev)
18108e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart{
18118e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	struct uvc_video_chain *chain;
18128e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	int ret;
18138e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18148e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	list_for_each_entry(chain, &dev->chains, list) {
18156241d8ca1dc27356180011dff4d93a3c5b3cbd76Laurent Pinchart		ret = uvc_register_terms(dev, chain);
18168e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		if (ret < 0)
18178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart			return ret;
18184ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart
18194ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
18204ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		ret = uvc_mc_register_entities(chain);
18214ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		if (ret < 0) {
18224ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart			uvc_printk(KERN_INFO, "Failed to register entites "
18234ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart				"(%d).\n", ret);
18244ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart		}
18254ffc2d89f38a7fbb3b24adb7fb066a159c351c11Laurent Pinchart#endif
18268e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	}
18278e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18288e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	return 0;
18298e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart}
18308e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
18318e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart/* ------------------------------------------------------------------------
18328e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart * USB probe, disconnect, suspend and resume
18338e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart */
18348e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
1835c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_probe(struct usb_interface *intf,
1836c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		     const struct usb_device_id *id)
1837c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1838c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_device *udev = interface_to_usbdev(intf);
1839c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev;
1840c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
1841c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1842c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (id->idVendor && id->idProduct)
1843c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
1844c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"(%04x:%04x)\n", udev->devpath, id->idVendor,
1845c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				id->idProduct);
1846c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1847c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
1848c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				udev->devpath);
1849c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18502c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Allocate memory for the device and initialize it. */
1851c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
1852c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
1853c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1854c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	INIT_LIST_HEAD(&dev->entities);
18558e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	INIT_LIST_HEAD(&dev->chains);
185635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	INIT_LIST_HEAD(&dev->streams);
1857716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	atomic_set(&dev->nstreams, 0);
18588fb91b33c6bfa3ac5e4ad76920b7bcd7bdbbb6d0Martin Rubli	atomic_set(&dev->nmappings, 0);
185917706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	mutex_init(&dev->lock);
1860c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1861c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->udev = usb_get_dev(udev);
1862c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intf = usb_get_intf(intf);
1863c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
186473de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	dev->quirks = (uvc_quirks_param == -1)
186573de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		    ? id->driver_info : uvc_quirks_param;
1866c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1867c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (udev->product != NULL)
1868d0ebf3073f8812464c9f6014d6cee09ab37c3fb5Laurent Pinchart		strlcpy(dev->name, udev->product, sizeof dev->name);
1869c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	else
1870c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		snprintf(dev->name, sizeof dev->name,
1871c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"UVC Camera (%04x:%04x)",
1872c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idVendor),
1873c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			le16_to_cpu(udev->descriptor.idProduct));
1874c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18752c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Parse the Video Class control descriptor. */
1876c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_parse_control(dev) < 0) {
1877c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
1878c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"descriptors.\n");
1879c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1880c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1881c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1882fba4578ee925110587ef9b8b6ddfabf2ce288071Laurent Pinchart	uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
1883c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev->uvc_version >> 8, dev->uvc_version & 0xff,
1884c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		udev->product ? udev->product : "<unnamed>",
1885c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idVendor),
1886c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		le16_to_cpu(udev->descriptor.idProduct));
1887c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
188873de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart	if (dev->quirks != id->driver_info) {
188973de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart		uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
189073de3592c0da2313b25bac7789e9ea02c4b9f082Laurent Pinchart			"parameter for testing purpose.\n", dev->quirks);
1891c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Please report required quirks to the "
1892c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"linux-uvc-devel mailing list.\n");
1893c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1894c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
18955a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	/* Register the media and V4L2 devices. */
18965a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#ifdef CONFIG_MEDIA_CONTROLLER
18975a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->mdev.dev = &intf->dev;
18985a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
18995a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (udev->serial)
19005a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		strlcpy(dev->mdev.serial, udev->serial,
19015a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart			sizeof(dev->mdev.serial));
19025a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	strcpy(dev->mdev.bus_info, udev->devpath);
19035a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
1904fd3e5824824d1beaf376cd523c7418c5570851d4Mauro Carvalho Chehab	dev->mdev.driver_version = LINUX_VERSION_CODE;
19055a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (media_device_register(&dev->mdev) < 0)
19065a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		goto error;
19075a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
19085a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	dev->vdev.mdev = &dev->mdev;
19095a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart#endif
19105a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
19115a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart		goto error;
19125a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart
19132c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize controls. */
1914c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (uvc_ctrl_init_device(dev) < 0)
1915c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1916c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19178e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	/* Scan the device for video chains. */
191835f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	if (uvc_scan_device(dev) < 0)
1919c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
1920c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19215a254d751e52e0f817090c29950d16cf18490d5bLaurent Pinchart	/* Register video device nodes. */
19228e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart	if (uvc_register_chains(dev) < 0)
19238e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart		goto error;
19248e113595edf0741b45ba10ba88cb5d077787c155Laurent Pinchart
19252c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Save our data pointer in the interface data. */
1926c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, dev);
1927c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19282c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	/* Initialize the interrupt URB. */
1929c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = uvc_status_init(dev)) < 0) {
1930c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_INFO, "Unable to initialize the status "
1931c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"endpoint (%d), status interrupt will not be "
1932c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"supported.\n", ret);
1933c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1934c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1935c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
19363dae8b41dc5651f8eb22cf310e8b116480ba25b7Matthew Garrett	usb_enable_autosuspend(udev);
1937c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
1938c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1939c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
1940716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1941c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return -ENODEV;
1942c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1943c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1944c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_disconnect(struct usb_interface *intf)
1945c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1946c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
1947c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1948c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Set the USB interface data to NULL. This can be done outside the
1949c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * lock, as there's no other reader.
1950c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
1951c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_set_intfdata(intf, NULL);
1952c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1953b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1954b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOSTREAMING)
1955c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
1956c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1957c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->state |= UVC_DEV_DISCONNECTED;
1958a9e285856112e5e721b6a341d15437a164128b30Laurent Pinchart
1959716fdee110ceb816cca8c46c0890d08c5a1addb9Laurent Pinchart	uvc_unregister_video(dev);
1960c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1961c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1962c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_suspend(struct usb_interface *intf, pm_message_t message)
1963c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1964c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
196535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1966c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1967c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
1968c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1969c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1970c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Controls are cached on the fly so they don't need to be saved. */
1971b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
197217706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
197317706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_lock(&dev->lock);
197417706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (dev->users)
197517706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart			uvc_status_stop(dev);
197617706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_unlock(&dev->lock);
197717706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		return 0;
197817706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	}
1979c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
198035f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
198135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
198235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			return uvc_video_suspend(stream);
1983c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
1984c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
198535f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
198635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
198735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
1988c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
1989c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19909b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int __uvc_resume(struct usb_interface *intf, int reset)
1991c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
1992c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = usb_get_intfdata(intf);
199335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	struct uvc_streaming *stream;
1994c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1995c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
1996c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		intf->cur_altsetting->desc.bInterfaceNumber);
1997c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
1998b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
1999b482d9231a73478763e6b42fd88ea453731a67ebLaurent Pinchart	    UVC_SC_VIDEOCONTROL) {
200017706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		int ret = 0;
20017564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil
200217706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (reset) {
200317e1319fd051f6f1d8b923ca3104c3391610ab32William Manley			ret = uvc_ctrl_restore_values(dev);
20047564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil			if (ret < 0)
20057564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil				return ret;
20067564f67d5b38eb814e67edd8ba0c70fd8eb475b6Hans Verkuil		}
2007c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
200817706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_lock(&dev->lock);
200917706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		if (dev->users)
201017706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart			ret = uvc_status_start(dev, GFP_NOIO);
201117706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		mutex_unlock(&dev->lock);
201217706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart
201317706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart		return ret;
2014c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
2015c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
201635f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	list_for_each_entry(stream, &dev->streams, list) {
201735f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart		if (stream->intf == intf)
2018d59a7b1dbce8b972ec2dc9fcaaae0bfa23687423Ming Lei			return uvc_video_resume(stream, reset);
2019c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
2020c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
202135f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
202235f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart			"mismatch.\n");
202335f02a681b72ece756cf005e17f305a72329c140Laurent Pinchart	return -EINVAL;
2024c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2025c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
20269b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_resume(struct usb_interface *intf)
20279b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
20289b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 0);
20299b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
20309b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
20319b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchartstatic int uvc_reset_resume(struct usb_interface *intf)
20329b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart{
20339b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart	return __uvc_resume(intf, 1);
20349b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart}
20359b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart
2036c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* ------------------------------------------------------------------------
2037310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart * Module parameters
2038310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart */
2039310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2040310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
2041310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
2042310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (uvc_clock_param == CLOCK_MONOTONIC)
2043310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_MONOTONIC");
2044310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
2045310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return sprintf(buffer, "CLOCK_REALTIME");
2046310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
2047310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2048310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartstatic int uvc_clock_param_set(const char *val, struct kernel_param *kp)
2049310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart{
2050310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
2051310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		val += strlen("clock_");
2052310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2053310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	if (strcasecmp(val, "monotonic") == 0)
2054310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_MONOTONIC;
2055310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else if (strcasecmp(val, "realtime") == 0)
2056310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		uvc_clock_param = CLOCK_REALTIME;
2057310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	else
2058310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		return -EINVAL;
2059310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2060310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart	return 0;
2061310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart}
2062310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2063310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
2064310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart		  &uvc_clock_param, S_IRUGO|S_IWUSR);
2065310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(clock, "Video buffers timestamp clock");
2066310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
2067310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
2068310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
2069310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(quirks, "Forced device quirks");
2070310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
2071310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(trace, "Trace level bitmask");
2072310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchartmodule_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
2073310fe52461e6244b01a04b011c2e886d6b69de16Laurent PinchartMODULE_PARM_DESC(timeout, "Streaming control requests timeout");
2074310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart
2075310fe52461e6244b01a04b011c2e886d6b69de16Laurent Pinchart/* ------------------------------------------------------------------------
2076c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Driver initialization and cleanup
2077c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
2078c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2079c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2080c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * The Logitech cameras listed below have their interface class set to
2081c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * VENDOR_SPEC because they don't announce themselves as UVC devices, even
2082c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * though they are compliant.
2083c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
2084c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic struct usb_device_id uvc_ids[] = {
20854eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	/* LogiLink Wireless Webcam */
20864eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
20874eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
20884eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .idVendor		= 0x0416,
20894eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .idProduct		= 0xa91a,
20904eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
20914eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceSubClass	= 1,
20924eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .bInterfaceProtocol	= 0,
20934eb2697e0a65c6a30c2c6a4ae602dfc6fe68edb2Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2094bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	/* Genius eFace 2025 */
2095bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2096bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2097bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idVendor		= 0x0458,
2098bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .idProduct		= 0x706e,
2099bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2100bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceSubClass	= 1,
2101bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .bInterfaceProtocol	= 0,
2102bce039c099e97b07534518b5f3c0ce31b1606ff6Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam NX-6000 */
2104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
2107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x00f8,
2108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
21121558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	/* Microsoft Lifecam NX-3000 */
21131558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
21141558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
21151558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .idVendor		= 0x045e,
21161558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .idProduct		= 0x0721,
21171558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
21181558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .bInterfaceSubClass	= 1,
21191558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .bInterfaceProtocol	= 0,
21201558ec837f4aa85987193d057377c42b243ca140Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Microsoft Lifecam VX-7000 */
2122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x045e,
2125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0723,
2126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Fusion */
2131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c1,
2135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Orbit MP */
2139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c2,
2143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro for Notebook */
2147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2149c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2150c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c3,
2151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam Pro 5000 */
2155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c5,
2159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Dell Notebook */
2163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c6,
2167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
2170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Logitech Quickcam OEM Cisco VT Camera II */
2171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x046d,
2174c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x08c7,
2175c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2176c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2177c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0 },
217817e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	/* Logitech HD Pro Webcam C920 */
217917e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
218017e1319fd051f6f1d8b923ca3104c3391610ab32William Manley				| USB_DEVICE_ID_MATCH_INT_INFO,
218117e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .idVendor		= 0x046d,
218217e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .idProduct		= 0x082d,
218317e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .bInterfaceClass	= USB_CLASS_VIDEO,
218417e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .bInterfaceSubClass	= 1,
218517e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .bInterfaceProtocol	= 0,
218617e1319fd051f6f1d8b923ca3104c3391610ab32William Manley	  .driver_info		= UVC_QUIRK_RESTORE_CTRLS_ON_INIT },
218786d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	/* Chicony CNF7129 (Asus EEE 100HE) */
218886d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
218986d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
219086d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .idVendor		= 0x04f2,
219186d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .idProduct		= 0xb071,
219286d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
219386d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceSubClass	= 1,
219486d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .bInterfaceProtocol	= 0,
219586d8b6abbbc973a1dd7d3c8f9e3c3e06131703b2Laurent Pinchart	  .driver_info		= UVC_QUIRK_RESTRICT_FRAME_RATE },
2196f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
2197f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2198f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2199f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idVendor		= 0x058f,
2200f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .idProduct		= 0x3820,
2201f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2202f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2203f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2204f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
22053efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	/* Dell XPS m1530 */
22063efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
22073efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22083efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .idVendor		= 0x05a9,
22093efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .idProduct		= 0x2640,
22103efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
221189e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .bInterfaceSubClass	= 1,
221289e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .bInterfaceProtocol	= 0,
221389e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .driver_info 		= UVC_QUIRK_PROBE_DEF },
221489e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	/* Dell SP2008WFP Monitor */
221589e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
221689e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury				| USB_DEVICE_ID_MATCH_INT_INFO,
221789e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .idVendor		= 0x05a9,
221889e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .idProduct		= 0x2641,
221989e0f248dcd301e44985510dee2a3d5ab4c2fc2dJoseph Salisbury	  .bInterfaceClass	= USB_CLASS_VIDEO,
22203efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceSubClass	= 1,
22213efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .bInterfaceProtocol	= 0,
22223efe2f1b12664c075215b1e4e409346080907af6Laurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_DEF },
2223c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	/* Dell Alienware X51 */
2224c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2225c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury				| USB_DEVICE_ID_MATCH_INT_INFO,
2226c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .idVendor		= 0x05a9,
2227c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .idProduct		= 0x2643,
2228c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceClass	= USB_CLASS_VIDEO,
2229c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceSubClass	= 1,
2230c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .bInterfaceProtocol	= 0,
2231c2a273b24f2c82184cc0f04ba3a61da51c84724bJoseph Salisbury	  .driver_info	= UVC_QUIRK_PROBE_DEF },
2232afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	/* Dell Studio Hybrid 140g (OmniVision webcam) */
2233afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2234afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa				| USB_DEVICE_ID_MATCH_INT_INFO,
2235afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .idVendor		= 0x05a9,
2236afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .idProduct		= 0x264a,
2237afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceClass	= USB_CLASS_VIDEO,
2238afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceSubClass	= 1,
2239afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .bInterfaceProtocol	= 0,
2240afcf44c786765b4eee44eea39ac0fddbbb830926Kamal Mostafa	  .driver_info		= UVC_QUIRK_PROBE_DEF },
224162ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	/* Dell XPS M1330 (OmniVision OV7670 webcam) */
224262ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
224362ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser				| USB_DEVICE_ID_MATCH_INT_INFO,
224462ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .idVendor		= 0x05a9,
224562ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .idProduct		= 0x7670,
224662ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .bInterfaceClass	= USB_CLASS_VIDEO,
224762ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .bInterfaceSubClass	= 1,
224862ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .bInterfaceProtocol	= 0,
224962ea864f84fed6e04dd033d500d4c9183a83d590Paul Fertser	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2250c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Apple Built-In iSight */
22512c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2252c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2253c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x05ac,
2254c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8501,
22552c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22562c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
22572c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
2258c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
2259c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| UVC_QUIRK_BUILTIN_ISIGHT },
2260949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	/* Foxlink ("HP Webcam" on HP Mini 5103) */
2261949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2262949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov				| USB_DEVICE_ID_MATCH_INT_INFO,
2263949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .idVendor		= 0x05c8,
2264949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .idProduct		= 0x0403,
2265949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceClass	= USB_CLASS_VIDEO,
2266949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceSubClass	= 1,
2267949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .bInterfaceProtocol	= 0,
2268949d9264589b759df66d40d497d14ecc49681b3aKirill Smelkov	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2269c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Genesys Logic USB 2.0 PC Camera */
22702c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2271c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
22722c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idVendor		= 0x05e3,
22732c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .idProduct		= 0x0505,
22742c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
22752c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceSubClass	= 1,
22762c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .bInterfaceProtocol	= 0,
22772c2d264bb951c1a846b86431d3e784edfb79ab39Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2278e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	/* Hercules Classic Silver */
2279e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2280e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2281e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .idVendor		= 0x06f8,
2282e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .idProduct		= 0x300c,
2283e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2284e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceSubClass	= 1,
2285e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .bInterfaceProtocol	= 0,
2286e01a234407af60c4b9854d069a7217d75fcdfa29Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2287d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Vega */
2288d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2289d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2290d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2291d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x332d,
2292d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2293d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2294d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2295d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2296d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro - Minoru3D */
2297d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2298d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2299d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idVendor		= 0x0ac8,
2300d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3410,
2301d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2302d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceSubClass	= 1,
2303d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .bInterfaceProtocol	= 0,
2304d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2305d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	/* ViMicro Venus - Minoru3D */
2306d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
230750144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
230850144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .idVendor		= 0x0ac8,
2309d79cd8393ae85ebaf53a8fc93491eea96522d68eLaurent Pinchart	  .idProduct		= 0x3420,
231050144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
231150144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceSubClass	= 1,
231250144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .bInterfaceProtocol	= 0,
231350144aeeb702ea105697ae5249f059ea3990b838Laurent Pinchart	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
2314d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	/* Ophir Optronics - SPCAM 620U */
2315d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2316d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2317d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .idVendor		= 0x0bd3,
2318d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .idProduct		= 0x0555,
2319d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2320d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceSubClass	= 1,
2321d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .bInterfaceProtocol	= 0,
2322d584b8386e1dacfb153cd9962ae2a01142234750Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2323c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* MT6227 */
2324c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2325c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2326c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x0e8d,
2327c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x0004,
2328c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2329c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2330c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2331bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2332bab6f66c08043a93b9460f6e0bf2b1cd9cc03e53Laurent Pinchart				| UVC_QUIRK_PROBE_DEF },
23339275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	/* IMC Networks (Medion Akoya) */
23349275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23359275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23369275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idVendor		= 0x13d3,
23379275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .idProduct		= 0x5103,
23389275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
23399275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceSubClass	= 1,
23409275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .bInterfaceProtocol	= 0,
23419275b32bced808bd57bdf3884748ed1126ba90e0Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2342d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	/* JMicron USB2.0 XGA WebCam */
2343d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2344d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2345d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .idVendor		= 0x152d,
2346d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .idProduct		= 0x0310,
2347d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2348d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceSubClass	= 1,
2349d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .bInterfaceProtocol	= 0,
2350d1787b1f8d0a2ac0a77c0e04f9fcbc494eb3fee2Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2351c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (HP Spartan) */
2352c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2353c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2354c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2355c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x5212,
2356c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2357c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2358c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
235925e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2360562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	/* Syntek (Samsung Q310) */
2361562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2362562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2363562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idVendor		= 0x174f,
2364562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .idProduct		= 0x5931,
2365562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2366562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2367562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2368562f0fed97722fc58230d21e401f1259caa94b4cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2369f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	/* Syntek (Packard Bell EasyNote MX52 */
2370f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2371f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2372f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idVendor		= 0x174f,
2373f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .idProduct		= 0x8a12,
2374f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2375f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceSubClass	= 1,
2376f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .bInterfaceProtocol	= 0,
2377f129b03ba272c86c42ad476684caa0d6109cb383Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2378f61d1d8a563b1f3c5f1f55d856278aae3fd3987eLaurent Pinchart	/* Syntek (Asus F9SG) */
237925e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
238025e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
238125e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idVendor		= 0x174f,
238225e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .idProduct		= 0x8a31,
238325e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
238425e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceSubClass	= 1,
238525e69850d1bb315f251c91183b89da44d4f9be23Laurent Pinchart	  .bInterfaceProtocol	= 0,
2386c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2387c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Syntek (Asus U3S) */
2388c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2389c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2390c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x174f,
2391c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x8a33,
2392c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2393c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2394c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2395c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
23960ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	/* Syntek (JAOtech Smart Terminal) */
23970ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
23980ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
23990ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idVendor		= 0x174f,
24000ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .idProduct		= 0x8a34,
24010ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24020ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceSubClass	= 1,
24030ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .bInterfaceProtocol	= 0,
24040ce566da77767bc7dd6e4016a6544c9e814d2ed3Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
240570092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	/* Miricle 307K */
240670092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
240770092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
240870092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idVendor		= 0x17dc,
240970092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .idProduct		= 0x0202,
241070092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
241170092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceSubClass	= 1,
241270092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .bInterfaceProtocol	= 0,
241370092c26dcfcdcc463e157c103ec4c9d2d49de67Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
2414849a3aba2d9830dc2a78a66078023e7e5ac26e15Filipe Rosset	/* Lenovo Thinkpad SL400/SL500 */
24152f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24162f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24172f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idVendor		= 0x17ef,
24182f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .idProduct		= 0x480b,
24192f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24202f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceSubClass	= 1,
24212f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .bInterfaceProtocol	= 0,
24222f38483bc45e11dc138cedce72135f57819f57c4Laurent Pinchart	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
24232d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	/* Aveo Technology USB 2.0 Camera */
24242d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24252d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24262d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idVendor		= 0x1871,
24272d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .idProduct		= 0x0306,
24282d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24292d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceSubClass	= 1,
24302d2bf2a3a6c84f0b316764e521d5dcee557e9c65Laurent Pinchart	  .bInterfaceProtocol	= 0,
24315bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
24325bdf1377587bbde8ef0893cf726de116c2250208Laurent Pinchart				| UVC_QUIRK_PROBE_EXTRAFIELDS },
2433c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Ecamm Pico iMage */
2434c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2435c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2436c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x18cd,
2437c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0xcafe,
2438c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2439c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2440c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2441c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
24422bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	/* Manta MM-353 Plako */
24432bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24442bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24452bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idVendor		= 0x18ec,
24462bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .idProduct		= 0x3188,
24472bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24482bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceSubClass	= 1,
24492bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .bInterfaceProtocol	= 0,
24502bb00fe6336687f08e0a3733bce2343a821af843Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2451ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	/* FSC WebCam V30S */
2452ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2453ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2454ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idVendor		= 0x18ec,
2455ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .idProduct		= 0x3288,
2456ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2457ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceSubClass	= 1,
2458ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .bInterfaceProtocol	= 0,
2459ca4a3456858775081f172e89077aa65cf5dbc52aLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
24601e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	/* Arkmicro unbranded */
24611e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24621e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24631e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idVendor		= 0x18ec,
24641e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .idProduct		= 0x3290,
24651e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24661e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceSubClass	= 1,
24671e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .bInterfaceProtocol	= 0,
24681e4d05bc95a0fe2972c5c91ed45466587d07cd2cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_DEF },
2469fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	/* The Imaging Source USB CCD cameras */
2470fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2471fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari				| USB_DEVICE_ID_MATCH_INT_INFO,
2472fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .idVendor		= 0x199e,
2473fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .idProduct		= 0x8102,
2474fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
2475fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceSubClass	= 1,
2476fd3e9f2f9a4c46f5d67d384c78b2d364c99d3de6Arne Caspari	  .bInterfaceProtocol	= 0 },
2477c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Bodelin ProScopeHR */
2478c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2479c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_DEV_HI
2480c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2481c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x19ab,
2482c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x1000,
2483c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bcdDevice_hi		= 0x0126,
2484c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2485c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2486c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2487c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_STATUS_INTERVAL },
24883bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	/* MSI StarCam 370i */
24893bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
24903bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
24913bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idVendor		= 0x1b3b,
24923bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .idProduct		= 0x2951,
24933bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
24943bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceSubClass	= 1,
24953bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .bInterfaceProtocol	= 0,
24963bc766ad374d04349ba09bd93f51980ad29d11c3Laurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
2497c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* SiGma Micro USB Web Camera */
2498c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
2499c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				| USB_DEVICE_ID_MATCH_INT_INFO,
2500c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idVendor		= 0x1c4f,
2501c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .idProduct		= 0x3000,
2502c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceClass	= USB_CLASS_VIDEO,
2503c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceSubClass	= 1,
2504c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .bInterfaceProtocol	= 0,
2505c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
2506d732c44c1a4b54e3c59ad92069bc2fd848aca5f3Laurent Pinchart				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
2507c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Generic USB Video Class */
2508c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
2509c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	{}
2510c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2511c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2512c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DEVICE_TABLE(usb, uvc_ids);
2513c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2514c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstruct uvc_driver uvc_driver = {
2515c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	.driver = {
2516c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.name		= "uvcvideo",
2517c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.probe		= uvc_probe,
2518c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.disconnect	= uvc_disconnect,
2519c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.suspend	= uvc_suspend,
2520c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.resume		= uvc_resume,
25219b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96cLaurent Pinchart		.reset_resume	= uvc_reset_resume,
2522c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.id_table	= uvc_ids,
2523c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		.supports_autosuspend = 1,
2524c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	},
2525c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart};
2526c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2527c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int __init uvc_init(void)
2528c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2529edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	int ret;
2530c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2531edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_init();
2532edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
2533edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	ret = usb_register(&uvc_driver.driver);
2534edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	if (ret < 0) {
2535edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		uvc_debugfs_cleanup();
2536edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher		return ret;
2537edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	}
2538edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher
2539edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
2540edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	return 0;
2541c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2542c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2543c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void __exit uvc_cleanup(void)
2544c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
2545c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_deregister(&uvc_driver.driver);
2546edbaa39842793fc4ac6603b277f2ad76f2057a45Alexey Fisher	uvc_debugfs_cleanup();
2547c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
2548c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2549c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_init(uvc_init);
2550c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartmodule_exit(uvc_cleanup);
2551c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
2552c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_AUTHOR(DRIVER_AUTHOR);
2553c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_DESCRIPTION(DRIVER_DESC);
2554c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_LICENSE("GPL");
2555c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent PinchartMODULE_VERSION(DRIVER_VERSION);
2556f87086e302300fdff1bd32049deb7a7f3e3de7daHans Verkuil
2557