1// SPDX-License-Identifier: GPL-2.0+
2/*
3 *	webcam.c -- USB webcam gadget driver
4 *
5 *	Copyright (C) 2009-2010
6 *	    Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7 */
8
9#include <linux/kernel.h>
10#include <linux/device.h>
11#include <linux/module.h>
12#include <linux/usb/video.h>
13
14#include "u_uvc.h"
15#include "uvc_configfs.h"
16
17USB_GADGET_COMPOSITE_OPTIONS();
18
19/*-------------------------------------------------------------------------*/
20
21/* module parameters specific to the Video streaming endpoint */
22static unsigned int streaming_interval = 1;
23module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
24MODULE_PARM_DESC(streaming_interval, "1 - 16");
25
26static unsigned int streaming_maxpacket = 1024;
27module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
28MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
29
30static unsigned int streaming_maxburst;
31module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
32MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
33
34/* --------------------------------------------------------------------------
35 * Device descriptor
36 */
37
38#define WEBCAM_VENDOR_ID		0x1d6b	/* Linux Foundation */
39#define WEBCAM_PRODUCT_ID		0x0102	/* Webcam A/V gadget */
40#define WEBCAM_DEVICE_BCD		0x0010	/* 0.10 */
41
42static char webcam_vendor_label[] = "Linux Foundation";
43static char webcam_product_label[] = "Webcam gadget";
44static char webcam_config_label[] = "Video";
45
46/* string IDs are assigned dynamically */
47
48#define STRING_DESCRIPTION_IDX		USB_GADGET_FIRST_AVAIL_IDX
49
50static struct usb_string webcam_strings[] = {
51	[USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label,
52	[USB_GADGET_PRODUCT_IDX].s = webcam_product_label,
53	[USB_GADGET_SERIAL_IDX].s = "",
54	[STRING_DESCRIPTION_IDX].s = webcam_config_label,
55	{  }
56};
57
58static struct usb_gadget_strings webcam_stringtab = {
59	.language = 0x0409,	/* en-us */
60	.strings = webcam_strings,
61};
62
63static struct usb_gadget_strings *webcam_device_strings[] = {
64	&webcam_stringtab,
65	NULL,
66};
67
68static struct usb_function_instance *fi_uvc;
69static struct usb_function *f_uvc;
70
71static struct usb_device_descriptor webcam_device_descriptor = {
72	.bLength		= USB_DT_DEVICE_SIZE,
73	.bDescriptorType	= USB_DT_DEVICE,
74	/* .bcdUSB = DYNAMIC */
75	.bDeviceClass		= USB_CLASS_MISC,
76	.bDeviceSubClass	= 0x02,
77	.bDeviceProtocol	= 0x01,
78	.bMaxPacketSize0	= 0, /* dynamic */
79	.idVendor		= cpu_to_le16(WEBCAM_VENDOR_ID),
80	.idProduct		= cpu_to_le16(WEBCAM_PRODUCT_ID),
81	.bcdDevice		= cpu_to_le16(WEBCAM_DEVICE_BCD),
82	.iManufacturer		= 0, /* dynamic */
83	.iProduct		= 0, /* dynamic */
84	.iSerialNumber		= 0, /* dynamic */
85	.bNumConfigurations	= 0, /* dynamic */
86};
87
88static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
89	.bLength		= UVC_DT_HEADER_SIZE(1),
90	.bDescriptorType	= USB_DT_CS_INTERFACE,
91	.bDescriptorSubType	= UVC_VC_HEADER,
92	.bcdUVC			= cpu_to_le16(0x0110),
93	.wTotalLength		= 0, /* dynamic */
94	.dwClockFrequency	= cpu_to_le32(48000000),
95	.bInCollection		= 0, /* dynamic */
96	.baInterfaceNr[0]	= 0, /* dynamic */
97};
98
99static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
100	.bLength		= UVC_DT_CAMERA_TERMINAL_SIZE(3),
101	.bDescriptorType	= USB_DT_CS_INTERFACE,
102	.bDescriptorSubType	= UVC_VC_INPUT_TERMINAL,
103	.bTerminalID		= 1,
104	.wTerminalType		= cpu_to_le16(0x0201),
105	.bAssocTerminal		= 0,
106	.iTerminal		= 0,
107	.wObjectiveFocalLengthMin	= cpu_to_le16(0),
108	.wObjectiveFocalLengthMax	= cpu_to_le16(0),
109	.wOcularFocalLength		= cpu_to_le16(0),
110	.bControlSize		= 3,
111	.bmControls[0]		= 2,
112	.bmControls[1]		= 0,
113	.bmControls[2]		= 0,
114};
115
116static const struct uvc_processing_unit_descriptor uvc_processing = {
117	.bLength		= UVC_DT_PROCESSING_UNIT_SIZE(2),
118	.bDescriptorType	= USB_DT_CS_INTERFACE,
119	.bDescriptorSubType	= UVC_VC_PROCESSING_UNIT,
120	.bUnitID		= 2,
121	.bSourceID		= 1,
122	.wMaxMultiplier		= cpu_to_le16(16*1024),
123	.bControlSize		= 2,
124	.bmControls[0]		= 1,
125	.bmControls[1]		= 0,
126	.iProcessing		= 0,
127	.bmVideoStandards	= 0,
128};
129
130static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
131	.bLength		= UVC_DT_OUTPUT_TERMINAL_SIZE,
132	.bDescriptorType	= USB_DT_CS_INTERFACE,
133	.bDescriptorSubType	= UVC_VC_OUTPUT_TERMINAL,
134	.bTerminalID		= 3,
135	.wTerminalType		= cpu_to_le16(0x0101),
136	.bAssocTerminal		= 0,
137	.bSourceID		= 2,
138	.iTerminal		= 0,
139};
140
141DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
142
143static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
144	.bLength		= UVC_DT_INPUT_HEADER_SIZE(1, 2),
145	.bDescriptorType	= USB_DT_CS_INTERFACE,
146	.bDescriptorSubType	= UVC_VS_INPUT_HEADER,
147	.bNumFormats		= 2,
148	.wTotalLength		= 0, /* dynamic */
149	.bEndpointAddress	= 0, /* dynamic */
150	.bmInfo			= 0,
151	.bTerminalLink		= 3,
152	.bStillCaptureMethod	= 0,
153	.bTriggerSupport	= 0,
154	.bTriggerUsage		= 0,
155	.bControlSize		= 1,
156	.bmaControls[0][0]	= 0,
157	.bmaControls[1][0]	= 4,
158};
159
160static const struct uvcg_color_matching uvcg_color_matching = {
161	.desc = {
162		.bLength		= UVC_DT_COLOR_MATCHING_SIZE,
163		.bDescriptorType	= USB_DT_CS_INTERFACE,
164		.bDescriptorSubType	= UVC_VS_COLORFORMAT,
165		.bColorPrimaries	= 1,
166		.bTransferCharacteristics	= 1,
167		.bMatrixCoefficients	= 4,
168	},
169};
170
171static struct uvcg_uncompressed uvcg_format_yuv = {
172	.fmt = {
173		.type			= UVCG_UNCOMPRESSED,
174		/* add to .frames and fill .num_frames at runtime */
175		.color_matching		= (struct uvcg_color_matching *)&uvcg_color_matching,
176	},
177	.desc = {
178		.bLength		= UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
179		.bDescriptorType	= USB_DT_CS_INTERFACE,
180		.bDescriptorSubType	= UVC_VS_FORMAT_UNCOMPRESSED,
181		.bFormatIndex		= 1,
182		.bNumFrameDescriptors	= 2,
183		.guidFormat		= {
184			'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
185			 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
186		},
187		.bBitsPerPixel		= 16,
188		.bDefaultFrameIndex	= 1,
189		.bAspectRatioX		= 0,
190		.bAspectRatioY		= 0,
191		.bmInterlaceFlags	= 0,
192		.bCopyProtect		= 0,
193	},
194};
195
196static struct uvcg_format_ptr uvcg_format_ptr_yuv = {
197	.fmt = &uvcg_format_yuv.fmt,
198};
199
200DECLARE_UVC_FRAME_UNCOMPRESSED(1);
201DECLARE_UVC_FRAME_UNCOMPRESSED(3);
202
203#define UVCG_WIDTH_360P			640
204#define UVCG_HEIGHT_360P		360
205#define UVCG_MIN_BITRATE_360P		18432000
206#define UVCG_MAX_BITRATE_360P		55296000
207#define UVCG_MAX_VIDEO_FB_SZ_360P	460800
208#define UVCG_FRM_INTERV_0_360P		666666
209#define UVCG_FRM_INTERV_1_360P		1000000
210#define UVCG_FRM_INTERV_2_360P		5000000
211#define UVCG_DEFAULT_FRM_INTERV_360P	UVCG_FRM_INTERV_0_360P
212
213static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
214	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
215	.bDescriptorType	= USB_DT_CS_INTERFACE,
216	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
217	.bFrameIndex		= 1,
218	.bmCapabilities		= 0,
219	.wWidth			= cpu_to_le16(UVCG_WIDTH_360P),
220	.wHeight		= cpu_to_le16(UVCG_HEIGHT_360P),
221	.dwMinBitRate		= cpu_to_le32(UVCG_MIN_BITRATE_360P),
222	.dwMaxBitRate		= cpu_to_le32(UVCG_MAX_BITRATE_360P),
223	.dwMaxVideoFrameBufferSize	= cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
224	.dwDefaultFrameInterval	= cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
225	.bFrameIntervalType	= 3,
226	.dwFrameInterval[0]	= cpu_to_le32(UVCG_FRM_INTERV_0_360P),
227	.dwFrameInterval[1]	= cpu_to_le32(UVCG_FRM_INTERV_1_360P),
228	.dwFrameInterval[2]	= cpu_to_le32(UVCG_FRM_INTERV_2_360P),
229};
230
231static u32 uvcg_frame_yuv_360p_dw_frame_interval[] = {
232	[0] = UVCG_FRM_INTERV_0_360P,
233	[1] = UVCG_FRM_INTERV_1_360P,
234	[2] = UVCG_FRM_INTERV_2_360P,
235};
236
237static const struct uvcg_frame uvcg_frame_yuv_360p = {
238	.fmt_type		= UVCG_UNCOMPRESSED,
239	.frame = {
240		.b_length			= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
241		.b_descriptor_type		= USB_DT_CS_INTERFACE,
242		.b_descriptor_subtype		= UVC_VS_FRAME_UNCOMPRESSED,
243		.b_frame_index			= 1,
244		.bm_capabilities		= 0,
245		.w_width			= UVCG_WIDTH_360P,
246		.w_height			= UVCG_HEIGHT_360P,
247		.dw_min_bit_rate		= UVCG_MIN_BITRATE_360P,
248		.dw_max_bit_rate		= UVCG_MAX_BITRATE_360P,
249		.dw_max_video_frame_buffer_size	= UVCG_MAX_VIDEO_FB_SZ_360P,
250		.dw_default_frame_interval	= UVCG_DEFAULT_FRM_INTERV_360P,
251		.b_frame_interval_type		= 3,
252	},
253	.dw_frame_interval	= uvcg_frame_yuv_360p_dw_frame_interval,
254};
255
256static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_360p = {
257	.frm = (struct uvcg_frame *)&uvcg_frame_yuv_360p,
258};
259#define UVCG_WIDTH_720P			1280
260#define UVCG_HEIGHT_720P		720
261#define UVCG_MIN_BITRATE_720P		29491200
262#define UVCG_MAX_BITRATE_720P		29491200
263#define UVCG_MAX_VIDEO_FB_SZ_720P	1843200
264#define UVCG_FRM_INTERV_0_720P		5000000
265#define UVCG_DEFAULT_FRM_INTERV_720P	UVCG_FRM_INTERV_0_720P
266
267static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
268	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
269	.bDescriptorType	= USB_DT_CS_INTERFACE,
270	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
271	.bFrameIndex		= 2,
272	.bmCapabilities		= 0,
273	.wWidth			= cpu_to_le16(UVCG_WIDTH_720P),
274	.wHeight		= cpu_to_le16(UVCG_HEIGHT_720P),
275	.dwMinBitRate		= cpu_to_le32(UVCG_MIN_BITRATE_720P),
276	.dwMaxBitRate		= cpu_to_le32(UVCG_MAX_BITRATE_720P),
277	.dwMaxVideoFrameBufferSize	= cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
278	.dwDefaultFrameInterval	= cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
279	.bFrameIntervalType	= 1,
280	.dwFrameInterval[0]	= cpu_to_le32(UVCG_FRM_INTERV_0_720P),
281};
282
283static u32 uvcg_frame_yuv_720p_dw_frame_interval[] = {
284	[0] = UVCG_FRM_INTERV_0_720P,
285};
286
287static const struct uvcg_frame uvcg_frame_yuv_720p = {
288	.fmt_type		= UVCG_UNCOMPRESSED,
289	.frame = {
290		.b_length			= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
291		.b_descriptor_type		= USB_DT_CS_INTERFACE,
292		.b_descriptor_subtype		= UVC_VS_FRAME_UNCOMPRESSED,
293		.b_frame_index			= 2,
294		.bm_capabilities		= 0,
295		.w_width			= UVCG_WIDTH_720P,
296		.w_height			= UVCG_HEIGHT_720P,
297		.dw_min_bit_rate		= UVCG_MIN_BITRATE_720P,
298		.dw_max_bit_rate		= UVCG_MAX_BITRATE_720P,
299		.dw_max_video_frame_buffer_size	= UVCG_MAX_VIDEO_FB_SZ_720P,
300		.dw_default_frame_interval	= UVCG_DEFAULT_FRM_INTERV_720P,
301		.b_frame_interval_type		= 1,
302	},
303	.dw_frame_interval	= uvcg_frame_yuv_720p_dw_frame_interval,
304};
305
306static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_720p = {
307	.frm = (struct uvcg_frame *)&uvcg_frame_yuv_720p,
308};
309
310static struct uvcg_mjpeg uvcg_format_mjpeg = {
311	.fmt = {
312		.type			= UVCG_MJPEG,
313		/* add to .frames and fill .num_frames at runtime */
314		.color_matching		= (struct uvcg_color_matching *)&uvcg_color_matching,
315	},
316	.desc = {
317		.bLength		= UVC_DT_FORMAT_MJPEG_SIZE,
318		.bDescriptorType	= USB_DT_CS_INTERFACE,
319		.bDescriptorSubType	= UVC_VS_FORMAT_MJPEG,
320		.bFormatIndex		= 2,
321		.bNumFrameDescriptors	= 2,
322		.bmFlags		= 0,
323		.bDefaultFrameIndex	= 1,
324		.bAspectRatioX		= 0,
325		.bAspectRatioY		= 0,
326		.bmInterlaceFlags	= 0,
327		.bCopyProtect		= 0,
328	},
329};
330
331static struct uvcg_format_ptr uvcg_format_ptr_mjpeg = {
332	.fmt = &uvcg_format_mjpeg.fmt,
333};
334
335DECLARE_UVC_FRAME_MJPEG(1);
336DECLARE_UVC_FRAME_MJPEG(3);
337
338static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
339	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(3),
340	.bDescriptorType	= USB_DT_CS_INTERFACE,
341	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
342	.bFrameIndex		= 1,
343	.bmCapabilities		= 0,
344	.wWidth			= cpu_to_le16(UVCG_WIDTH_360P),
345	.wHeight		= cpu_to_le16(UVCG_HEIGHT_360P),
346	.dwMinBitRate		= cpu_to_le32(UVCG_MIN_BITRATE_360P),
347	.dwMaxBitRate		= cpu_to_le32(UVCG_MAX_BITRATE_360P),
348	.dwMaxVideoFrameBufferSize	= cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
349	.dwDefaultFrameInterval	= cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
350	.bFrameIntervalType	= 3,
351	.dwFrameInterval[0]	= cpu_to_le32(UVCG_FRM_INTERV_0_360P),
352	.dwFrameInterval[1]	= cpu_to_le32(UVCG_FRM_INTERV_1_360P),
353	.dwFrameInterval[2]	= cpu_to_le32(UVCG_FRM_INTERV_2_360P),
354};
355
356static u32 uvcg_frame_mjpeg_360p_dw_frame_interval[] = {
357	[0] = UVCG_FRM_INTERV_0_360P,
358	[1] = UVCG_FRM_INTERV_1_360P,
359	[2] = UVCG_FRM_INTERV_2_360P,
360};
361
362static const struct uvcg_frame uvcg_frame_mjpeg_360p = {
363	.fmt_type		= UVCG_MJPEG,
364	.frame = {
365		.b_length			= UVC_DT_FRAME_MJPEG_SIZE(3),
366		.b_descriptor_type		= USB_DT_CS_INTERFACE,
367		.b_descriptor_subtype		= UVC_VS_FRAME_MJPEG,
368		.b_frame_index			= 1,
369		.bm_capabilities		= 0,
370		.w_width			= UVCG_WIDTH_360P,
371		.w_height			= UVCG_HEIGHT_360P,
372		.dw_min_bit_rate		= UVCG_MIN_BITRATE_360P,
373		.dw_max_bit_rate		= UVCG_MAX_BITRATE_360P,
374		.dw_max_video_frame_buffer_size	= UVCG_MAX_VIDEO_FB_SZ_360P,
375		.dw_default_frame_interval	= UVCG_DEFAULT_FRM_INTERV_360P,
376		.b_frame_interval_type		= 3,
377	},
378	.dw_frame_interval	= uvcg_frame_mjpeg_360p_dw_frame_interval,
379};
380
381static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_360p = {
382	.frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_360p,
383};
384
385static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
386	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(1),
387	.bDescriptorType	= USB_DT_CS_INTERFACE,
388	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
389	.bFrameIndex		= 2,
390	.bmCapabilities		= 0,
391	.wWidth			= cpu_to_le16(UVCG_WIDTH_720P),
392	.wHeight		= cpu_to_le16(UVCG_HEIGHT_720P),
393	.dwMinBitRate		= cpu_to_le32(UVCG_MIN_BITRATE_720P),
394	.dwMaxBitRate		= cpu_to_le32(UVCG_MAX_BITRATE_720P),
395	.dwMaxVideoFrameBufferSize	= cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
396	.dwDefaultFrameInterval	= cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
397	.bFrameIntervalType	= 1,
398	.dwFrameInterval[0]	= cpu_to_le32(UVCG_FRM_INTERV_0_720P),
399};
400
401static u32 uvcg_frame_mjpeg_720p_dw_frame_interval[] = {
402	[0] = UVCG_FRM_INTERV_0_720P,
403};
404
405static const struct uvcg_frame uvcg_frame_mjpeg_720p = {
406	.fmt_type		= UVCG_MJPEG,
407	.frame = {
408		.b_length			= UVC_DT_FRAME_MJPEG_SIZE(1),
409		.b_descriptor_type		= USB_DT_CS_INTERFACE,
410		.b_descriptor_subtype		= UVC_VS_FRAME_MJPEG,
411		.b_frame_index			= 2,
412		.bm_capabilities		= 0,
413		.w_width			= UVCG_WIDTH_720P,
414		.w_height			= UVCG_HEIGHT_720P,
415		.dw_min_bit_rate		= UVCG_MIN_BITRATE_720P,
416		.dw_max_bit_rate		= UVCG_MAX_BITRATE_720P,
417		.dw_max_video_frame_buffer_size	= UVCG_MAX_VIDEO_FB_SZ_720P,
418		.dw_default_frame_interval	= UVCG_DEFAULT_FRM_INTERV_720P,
419		.b_frame_interval_type		= 1,
420	},
421	.dw_frame_interval	= uvcg_frame_mjpeg_720p_dw_frame_interval,
422};
423
424static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_720p = {
425	.frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_720p,
426};
427
428static struct uvcg_streaming_header uvcg_streaming_header = {
429};
430
431static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
432	(const struct uvc_descriptor_header *) &uvc_control_header,
433	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
434	(const struct uvc_descriptor_header *) &uvc_processing,
435	(const struct uvc_descriptor_header *) &uvc_output_terminal,
436	NULL,
437};
438
439static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
440	(const struct uvc_descriptor_header *) &uvc_control_header,
441	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
442	(const struct uvc_descriptor_header *) &uvc_processing,
443	(const struct uvc_descriptor_header *) &uvc_output_terminal,
444	NULL,
445};
446
447static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
448	(const struct uvc_descriptor_header *) &uvc_input_header,
449	(const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
450	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
451	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
452	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
453	(const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
454	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
455	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
456	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
457	NULL,
458};
459
460static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
461	(const struct uvc_descriptor_header *) &uvc_input_header,
462	(const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
463	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
464	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
465	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
466	(const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
467	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
468	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
469	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
470	NULL,
471};
472
473static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
474	(const struct uvc_descriptor_header *) &uvc_input_header,
475	(const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
476	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
477	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
478	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
479	(const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
480	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
481	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
482	(const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
483	NULL,
484};
485
486/* --------------------------------------------------------------------------
487 * USB configuration
488 */
489
490static int
491webcam_config_bind(struct usb_configuration *c)
492{
493	int status = 0;
494
495	f_uvc = usb_get_function(fi_uvc);
496	if (IS_ERR(f_uvc))
497		return PTR_ERR(f_uvc);
498
499	status = usb_add_function(c, f_uvc);
500	if (status < 0)
501		usb_put_function(f_uvc);
502
503	return status;
504}
505
506static struct usb_configuration webcam_config_driver = {
507	.label			= webcam_config_label,
508	.bConfigurationValue	= 1,
509	.iConfiguration		= 0, /* dynamic */
510	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
511	.MaxPower		= CONFIG_USB_GADGET_VBUS_DRAW,
512};
513
514static int
515webcam_unbind(struct usb_composite_dev *cdev)
516{
517	if (!IS_ERR_OR_NULL(f_uvc))
518		usb_put_function(f_uvc);
519	if (!IS_ERR_OR_NULL(fi_uvc))
520		usb_put_function_instance(fi_uvc);
521	return 0;
522}
523
524static int
525webcam_bind(struct usb_composite_dev *cdev)
526{
527	struct f_uvc_opts *uvc_opts;
528	int ret;
529
530	fi_uvc = usb_get_function_instance("uvc");
531	if (IS_ERR(fi_uvc))
532		return PTR_ERR(fi_uvc);
533
534	uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst);
535
536	uvc_opts->streaming_interval = streaming_interval;
537	uvc_opts->streaming_maxpacket = streaming_maxpacket;
538	uvc_opts->streaming_maxburst = streaming_maxburst;
539
540	uvc_opts->fs_control = uvc_fs_control_cls;
541	uvc_opts->ss_control = uvc_ss_control_cls;
542	uvc_opts->fs_streaming = uvc_fs_streaming_cls;
543	uvc_opts->hs_streaming = uvc_hs_streaming_cls;
544	uvc_opts->ss_streaming = uvc_ss_streaming_cls;
545
546	INIT_LIST_HEAD(&uvcg_format_yuv.fmt.frames);
547	list_add_tail(&uvcg_frame_ptr_yuv_360p.entry, &uvcg_format_yuv.fmt.frames);
548	list_add_tail(&uvcg_frame_ptr_yuv_720p.entry, &uvcg_format_yuv.fmt.frames);
549	uvcg_format_yuv.fmt.num_frames = 2;
550
551	INIT_LIST_HEAD(&uvcg_format_mjpeg.fmt.frames);
552	list_add_tail(&uvcg_frame_ptr_mjpeg_360p.entry, &uvcg_format_mjpeg.fmt.frames);
553	list_add_tail(&uvcg_frame_ptr_mjpeg_720p.entry, &uvcg_format_mjpeg.fmt.frames);
554	uvcg_format_mjpeg.fmt.num_frames = 2;
555
556	INIT_LIST_HEAD(&uvcg_streaming_header.formats);
557	list_add_tail(&uvcg_format_ptr_yuv.entry, &uvcg_streaming_header.formats);
558	list_add_tail(&uvcg_format_ptr_mjpeg.entry, &uvcg_streaming_header.formats);
559	uvcg_streaming_header.num_fmt = 2;
560
561	uvc_opts->header = &uvcg_streaming_header;
562
563	/* Allocate string descriptor numbers ... note that string contents
564	 * can be overridden by the composite_dev glue.
565	 */
566	ret = usb_string_ids_tab(cdev, webcam_strings);
567	if (ret < 0)
568		goto error;
569	webcam_device_descriptor.iManufacturer =
570		webcam_strings[USB_GADGET_MANUFACTURER_IDX].id;
571	webcam_device_descriptor.iProduct =
572		webcam_strings[USB_GADGET_PRODUCT_IDX].id;
573	webcam_config_driver.iConfiguration =
574		webcam_strings[STRING_DESCRIPTION_IDX].id;
575
576	/* Register our configuration. */
577	if ((ret = usb_add_config(cdev, &webcam_config_driver,
578					webcam_config_bind)) < 0)
579		goto error;
580
581	usb_composite_overwrite_options(cdev, &coverwrite);
582	INFO(cdev, "Webcam Video Gadget\n");
583	return 0;
584
585error:
586	usb_put_function_instance(fi_uvc);
587	return ret;
588}
589
590/* --------------------------------------------------------------------------
591 * Driver
592 */
593
594static struct usb_composite_driver webcam_driver = {
595	.name		= "g_webcam",
596	.dev		= &webcam_device_descriptor,
597	.strings	= webcam_device_strings,
598	.max_speed	= USB_SPEED_SUPER,
599	.bind		= webcam_bind,
600	.unbind		= webcam_unbind,
601};
602
603module_usb_composite_driver(webcam_driver);
604
605MODULE_AUTHOR("Laurent Pinchart");
606MODULE_DESCRIPTION("Webcam Video Gadget");
607MODULE_LICENSE("GPL");
608
609