1 // SPDX-License-Identifier: GPL-2.0+
3 * webcam.c -- USB webcam gadget driver
5 * Copyright (C) 2009-2010
9 #include <linux/kernel.h>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/usb/video.h>
15 #include "uvc_configfs.h"
17 USB_GADGET_COMPOSITE_OPTIONS();
19 /*-------------------------------------------------------------------------*/
21 /* module parameters specific to the Video streaming endpoint */
22 static unsigned int streaming_interval = 1;
23 module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
24 MODULE_PARM_DESC(streaming_interval, "1 - 16");
26 static unsigned int streaming_maxpacket = 1024;
27 module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
28 MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
30 static unsigned int streaming_maxburst;
31 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
32 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
34 /* --------------------------------------------------------------------------
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 */
42 static char webcam_vendor_label[] = "Linux Foundation";
43 static char webcam_product_label[] = "Webcam gadget";
44 static char webcam_config_label[] = "Video";
46 /* string IDs are assigned dynamically */
48 #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
50 static 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,
58 static struct usb_gadget_strings webcam_stringtab = {
59 .language = 0x0409, /* en-us */
60 .strings = webcam_strings,
63 static struct usb_gadget_strings *webcam_device_strings[] = {
68 static struct usb_function_instance *fi_uvc;
69 static struct usb_function *f_uvc;
71 static 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 */
88 static 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 */
99 static 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,
104 .wTerminalType = cpu_to_le16(0x0201),
107 .wObjectiveFocalLengthMin = cpu_to_le16(0),
108 .wObjectiveFocalLengthMax = cpu_to_le16(0),
109 .wOcularFocalLength = cpu_to_le16(0),
116 static 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,
122 .wMaxMultiplier = cpu_to_le16(16*1024),
127 .bmVideoStandards = 0,
130 static 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,
135 .wTerminalType = cpu_to_le16(0x0101),
141 DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
143 static 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,
148 .wTotalLength = 0, /* dynamic */
149 .bEndpointAddress = 0, /* dynamic */
152 .bStillCaptureMethod = 0,
153 .bTriggerSupport = 0,
156 .bmaControls[0][0] = 0,
157 .bmaControls[1][0] = 4,
160 static const struct uvcg_color_matching uvcg_color_matching = {
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,
171 static struct uvcg_uncompressed uvcg_format_yuv = {
173 .type = UVCG_UNCOMPRESSED,
174 /* add to .frames and fill .num_frames at runtime */
175 .color_matching = (struct uvcg_color_matching *)&uvcg_color_matching,
178 .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
179 .bDescriptorType = USB_DT_CS_INTERFACE,
180 .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
182 .bNumFrameDescriptors = 2,
184 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
185 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
188 .bDefaultFrameIndex = 1,
191 .bmInterlaceFlags = 0,
196 static struct uvcg_format_ptr uvcg_format_ptr_yuv = {
197 .fmt = &uvcg_format_yuv.fmt,
200 DECLARE_UVC_FRAME_UNCOMPRESSED(1);
201 DECLARE_UVC_FRAME_UNCOMPRESSED(3);
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
213 static 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,
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),
231 static 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,
237 static const struct uvcg_frame uvcg_frame_yuv_360p = {
238 .fmt_type = UVCG_UNCOMPRESSED,
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,
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,
253 .dw_frame_interval = uvcg_frame_yuv_360p_dw_frame_interval,
256 static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_360p = {
257 .frm = (struct uvcg_frame *)&uvcg_frame_yuv_360p,
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
267 static 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,
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),
283 static u32 uvcg_frame_yuv_720p_dw_frame_interval[] = {
284 [0] = UVCG_FRM_INTERV_0_720P,
287 static const struct uvcg_frame uvcg_frame_yuv_720p = {
288 .fmt_type = UVCG_UNCOMPRESSED,
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,
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,
303 .dw_frame_interval = uvcg_frame_yuv_720p_dw_frame_interval,
306 static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_720p = {
307 .frm = (struct uvcg_frame *)&uvcg_frame_yuv_720p,
310 static struct uvcg_mjpeg uvcg_format_mjpeg = {
313 /* add to .frames and fill .num_frames at runtime */
314 .color_matching = (struct uvcg_color_matching *)&uvcg_color_matching,
317 .bLength = UVC_DT_FORMAT_MJPEG_SIZE,
318 .bDescriptorType = USB_DT_CS_INTERFACE,
319 .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
321 .bNumFrameDescriptors = 2,
323 .bDefaultFrameIndex = 1,
326 .bmInterlaceFlags = 0,
331 static struct uvcg_format_ptr uvcg_format_ptr_mjpeg = {
332 .fmt = &uvcg_format_mjpeg.fmt,
335 DECLARE_UVC_FRAME_MJPEG(1);
336 DECLARE_UVC_FRAME_MJPEG(3);
338 static 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,
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),
356 static 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,
362 static const struct uvcg_frame uvcg_frame_mjpeg_360p = {
363 .fmt_type = UVCG_MJPEG,
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,
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,
378 .dw_frame_interval = uvcg_frame_mjpeg_360p_dw_frame_interval,
381 static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_360p = {
382 .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_360p,
385 static 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,
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),
401 static u32 uvcg_frame_mjpeg_720p_dw_frame_interval[] = {
402 [0] = UVCG_FRM_INTERV_0_720P,
405 static const struct uvcg_frame uvcg_frame_mjpeg_720p = {
406 .fmt_type = UVCG_MJPEG,
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,
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,
421 .dw_frame_interval = uvcg_frame_mjpeg_720p_dw_frame_interval,
424 static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_720p = {
425 .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_720p,
428 static struct uvcg_streaming_header uvcg_streaming_header = {
431 static 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,
439 static 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,
447 static 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,
460 static 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,
473 static 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,
486 /* --------------------------------------------------------------------------
491 webcam_config_bind(struct usb_configuration *c)
495 f_uvc = usb_get_function(fi_uvc);
497 return PTR_ERR(f_uvc);
499 status = usb_add_function(c, f_uvc);
501 usb_put_function(f_uvc);
506 static 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,
515 webcam_unbind(struct usb_composite_dev *cdev)
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);
525 webcam_bind(struct usb_composite_dev *cdev)
527 struct f_uvc_opts *uvc_opts;
530 fi_uvc = usb_get_function_instance("uvc");
532 return PTR_ERR(fi_uvc);
534 uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst);
536 uvc_opts->streaming_interval = streaming_interval;
537 uvc_opts->streaming_maxpacket = streaming_maxpacket;
538 uvc_opts->streaming_maxburst = streaming_maxburst;
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;
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;
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;
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;
561 uvc_opts->header = &uvcg_streaming_header;
563 /* Allocate string descriptor numbers ... note that string contents
564 * can be overridden by the composite_dev glue.
566 ret = usb_string_ids_tab(cdev, webcam_strings);
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;
576 /* Register our configuration. */
577 if ((ret = usb_add_config(cdev, &webcam_config_driver,
578 webcam_config_bind)) < 0)
581 usb_composite_overwrite_options(cdev, &coverwrite);
582 INFO(cdev, "Webcam Video Gadget\n");
586 usb_put_function_instance(fi_uvc);
590 /* --------------------------------------------------------------------------
594 static struct usb_composite_driver webcam_driver = {
596 .dev = &webcam_device_descriptor,
597 .strings = webcam_device_strings,
598 .max_speed = USB_SPEED_SUPER,
600 .unbind = webcam_unbind,
603 module_usb_composite_driver(webcam_driver);
605 MODULE_AUTHOR("Laurent Pinchart");
606 MODULE_DESCRIPTION("Webcam Video Gadget");
607 MODULE_LICENSE("GPL");