1 // SPDX-License-Identifier: GPL-2.0+
3 * webcam.c -- USB webcam gadget driver
5 * Copyright (C) 2009-2010
6 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
9 #include <linux/kernel.h>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/usb/video.h>
16 USB_GADGET_COMPOSITE_OPTIONS();
18 /*-------------------------------------------------------------------------*/
20 /* module parameters specific to the Video streaming endpoint */
21 static unsigned int streaming_interval
= 1;
22 module_param(streaming_interval
, uint
, S_IRUGO
|S_IWUSR
);
23 MODULE_PARM_DESC(streaming_interval
, "1 - 16");
25 static unsigned int streaming_maxpacket
= 1024;
26 module_param(streaming_maxpacket
, uint
, S_IRUGO
|S_IWUSR
);
27 MODULE_PARM_DESC(streaming_maxpacket
, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
29 static unsigned int streaming_maxburst
;
30 module_param(streaming_maxburst
, uint
, S_IRUGO
|S_IWUSR
);
31 MODULE_PARM_DESC(streaming_maxburst
, "0 - 15 (ss only)");
33 /* --------------------------------------------------------------------------
37 #define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */
38 #define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */
39 #define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */
41 static char webcam_vendor_label
[] = "Linux Foundation";
42 static char webcam_product_label
[] = "Webcam gadget";
43 static char webcam_config_label
[] = "Video";
45 /* string IDs are assigned dynamically */
47 #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
49 static struct usb_string webcam_strings
[] = {
50 [USB_GADGET_MANUFACTURER_IDX
].s
= webcam_vendor_label
,
51 [USB_GADGET_PRODUCT_IDX
].s
= webcam_product_label
,
52 [USB_GADGET_SERIAL_IDX
].s
= "",
53 [STRING_DESCRIPTION_IDX
].s
= webcam_config_label
,
57 static struct usb_gadget_strings webcam_stringtab
= {
58 .language
= 0x0409, /* en-us */
59 .strings
= webcam_strings
,
62 static struct usb_gadget_strings
*webcam_device_strings
[] = {
67 static struct usb_function_instance
*fi_uvc
;
68 static struct usb_function
*f_uvc
;
70 static struct usb_device_descriptor webcam_device_descriptor
= {
71 .bLength
= USB_DT_DEVICE_SIZE
,
72 .bDescriptorType
= USB_DT_DEVICE
,
73 /* .bcdUSB = DYNAMIC */
74 .bDeviceClass
= USB_CLASS_MISC
,
75 .bDeviceSubClass
= 0x02,
76 .bDeviceProtocol
= 0x01,
77 .bMaxPacketSize0
= 0, /* dynamic */
78 .idVendor
= cpu_to_le16(WEBCAM_VENDOR_ID
),
79 .idProduct
= cpu_to_le16(WEBCAM_PRODUCT_ID
),
80 .bcdDevice
= cpu_to_le16(WEBCAM_DEVICE_BCD
),
81 .iManufacturer
= 0, /* dynamic */
82 .iProduct
= 0, /* dynamic */
83 .iSerialNumber
= 0, /* dynamic */
84 .bNumConfigurations
= 0, /* dynamic */
87 DECLARE_UVC_HEADER_DESCRIPTOR(1);
89 static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header
= {
90 .bLength
= UVC_DT_HEADER_SIZE(1),
91 .bDescriptorType
= USB_DT_CS_INTERFACE
,
92 .bDescriptorSubType
= UVC_VC_HEADER
,
93 .bcdUVC
= cpu_to_le16(0x0100),
94 .wTotalLength
= 0, /* dynamic */
95 .dwClockFrequency
= cpu_to_le32(48000000),
96 .bInCollection
= 0, /* dynamic */
97 .baInterfaceNr
[0] = 0, /* dynamic */
100 static const struct uvc_camera_terminal_descriptor uvc_camera_terminal
= {
101 .bLength
= UVC_DT_CAMERA_TERMINAL_SIZE(3),
102 .bDescriptorType
= USB_DT_CS_INTERFACE
,
103 .bDescriptorSubType
= UVC_VC_INPUT_TERMINAL
,
105 .wTerminalType
= cpu_to_le16(0x0201),
108 .wObjectiveFocalLengthMin
= cpu_to_le16(0),
109 .wObjectiveFocalLengthMax
= cpu_to_le16(0),
110 .wOcularFocalLength
= cpu_to_le16(0),
117 static const struct uvc_processing_unit_descriptor uvc_processing
= {
118 .bLength
= UVC_DT_PROCESSING_UNIT_SIZE(2),
119 .bDescriptorType
= USB_DT_CS_INTERFACE
,
120 .bDescriptorSubType
= UVC_VC_PROCESSING_UNIT
,
123 .wMaxMultiplier
= cpu_to_le16(16*1024),
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 uvc_format_uncompressed uvc_format_yuv
= {
161 .bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
,
162 .bDescriptorType
= USB_DT_CS_INTERFACE
,
163 .bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
,
165 .bNumFrameDescriptors
= 2,
167 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
168 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
170 .bDefaultFrameIndex
= 1,
173 .bmInterfaceFlags
= 0,
177 DECLARE_UVC_FRAME_UNCOMPRESSED(1);
178 DECLARE_UVC_FRAME_UNCOMPRESSED(3);
180 static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p
= {
181 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
182 .bDescriptorType
= USB_DT_CS_INTERFACE
,
183 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
186 .wWidth
= cpu_to_le16(640),
187 .wHeight
= cpu_to_le16(360),
188 .dwMinBitRate
= cpu_to_le32(18432000),
189 .dwMaxBitRate
= cpu_to_le32(55296000),
190 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
191 .dwDefaultFrameInterval
= cpu_to_le32(666666),
192 .bFrameIntervalType
= 3,
193 .dwFrameInterval
[0] = cpu_to_le32(666666),
194 .dwFrameInterval
[1] = cpu_to_le32(1000000),
195 .dwFrameInterval
[2] = cpu_to_le32(5000000),
198 static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p
= {
199 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
200 .bDescriptorType
= USB_DT_CS_INTERFACE
,
201 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
204 .wWidth
= cpu_to_le16(1280),
205 .wHeight
= cpu_to_le16(720),
206 .dwMinBitRate
= cpu_to_le32(29491200),
207 .dwMaxBitRate
= cpu_to_le32(29491200),
208 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
209 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
210 .bFrameIntervalType
= 1,
211 .dwFrameInterval
[0] = cpu_to_le32(5000000),
214 static const struct uvc_format_mjpeg uvc_format_mjpg
= {
215 .bLength
= UVC_DT_FORMAT_MJPEG_SIZE
,
216 .bDescriptorType
= USB_DT_CS_INTERFACE
,
217 .bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
,
219 .bNumFrameDescriptors
= 2,
221 .bDefaultFrameIndex
= 1,
224 .bmInterfaceFlags
= 0,
228 DECLARE_UVC_FRAME_MJPEG(1);
229 DECLARE_UVC_FRAME_MJPEG(3);
231 static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p
= {
232 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(3),
233 .bDescriptorType
= USB_DT_CS_INTERFACE
,
234 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
237 .wWidth
= cpu_to_le16(640),
238 .wHeight
= cpu_to_le16(360),
239 .dwMinBitRate
= cpu_to_le32(18432000),
240 .dwMaxBitRate
= cpu_to_le32(55296000),
241 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
242 .dwDefaultFrameInterval
= cpu_to_le32(666666),
243 .bFrameIntervalType
= 3,
244 .dwFrameInterval
[0] = cpu_to_le32(666666),
245 .dwFrameInterval
[1] = cpu_to_le32(1000000),
246 .dwFrameInterval
[2] = cpu_to_le32(5000000),
249 static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p
= {
250 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(1),
251 .bDescriptorType
= USB_DT_CS_INTERFACE
,
252 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
255 .wWidth
= cpu_to_le16(1280),
256 .wHeight
= cpu_to_le16(720),
257 .dwMinBitRate
= cpu_to_le32(29491200),
258 .dwMaxBitRate
= cpu_to_le32(29491200),
259 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
260 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
261 .bFrameIntervalType
= 1,
262 .dwFrameInterval
[0] = cpu_to_le32(5000000),
265 static const struct uvc_color_matching_descriptor uvc_color_matching
= {
266 .bLength
= UVC_DT_COLOR_MATCHING_SIZE
,
267 .bDescriptorType
= USB_DT_CS_INTERFACE
,
268 .bDescriptorSubType
= UVC_VS_COLORFORMAT
,
269 .bColorPrimaries
= 1,
270 .bTransferCharacteristics
= 1,
271 .bMatrixCoefficients
= 4,
274 static const struct uvc_descriptor_header
* const uvc_fs_control_cls
[] = {
275 (const struct uvc_descriptor_header
*) &uvc_control_header
,
276 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
277 (const struct uvc_descriptor_header
*) &uvc_processing
,
278 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
282 static const struct uvc_descriptor_header
* const uvc_ss_control_cls
[] = {
283 (const struct uvc_descriptor_header
*) &uvc_control_header
,
284 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
285 (const struct uvc_descriptor_header
*) &uvc_processing
,
286 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
290 static const struct uvc_descriptor_header
* const uvc_fs_streaming_cls
[] = {
291 (const struct uvc_descriptor_header
*) &uvc_input_header
,
292 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
293 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
294 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
295 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
296 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
297 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
298 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
302 static const struct uvc_descriptor_header
* const uvc_hs_streaming_cls
[] = {
303 (const struct uvc_descriptor_header
*) &uvc_input_header
,
304 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
305 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
306 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
307 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
308 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
309 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
310 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
314 static const struct uvc_descriptor_header
* const uvc_ss_streaming_cls
[] = {
315 (const struct uvc_descriptor_header
*) &uvc_input_header
,
316 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
317 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
318 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
319 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
320 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
321 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
322 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
326 /* --------------------------------------------------------------------------
331 webcam_config_bind(struct usb_configuration
*c
)
335 f_uvc
= usb_get_function(fi_uvc
);
337 return PTR_ERR(f_uvc
);
339 status
= usb_add_function(c
, f_uvc
);
341 usb_put_function(f_uvc
);
346 static struct usb_configuration webcam_config_driver
= {
347 .label
= webcam_config_label
,
348 .bConfigurationValue
= 1,
349 .iConfiguration
= 0, /* dynamic */
350 .bmAttributes
= USB_CONFIG_ATT_SELFPOWER
,
351 .MaxPower
= CONFIG_USB_GADGET_VBUS_DRAW
,
355 webcam_unbind(struct usb_composite_dev
*cdev
)
357 if (!IS_ERR_OR_NULL(f_uvc
))
358 usb_put_function(f_uvc
);
359 if (!IS_ERR_OR_NULL(fi_uvc
))
360 usb_put_function_instance(fi_uvc
);
365 webcam_bind(struct usb_composite_dev
*cdev
)
367 struct f_uvc_opts
*uvc_opts
;
370 fi_uvc
= usb_get_function_instance("uvc");
372 return PTR_ERR(fi_uvc
);
374 uvc_opts
= container_of(fi_uvc
, struct f_uvc_opts
, func_inst
);
376 uvc_opts
->streaming_interval
= streaming_interval
;
377 uvc_opts
->streaming_maxpacket
= streaming_maxpacket
;
378 uvc_opts
->streaming_maxburst
= streaming_maxburst
;
380 uvc_opts
->fs_control
= uvc_fs_control_cls
;
381 uvc_opts
->ss_control
= uvc_ss_control_cls
;
382 uvc_opts
->fs_streaming
= uvc_fs_streaming_cls
;
383 uvc_opts
->hs_streaming
= uvc_hs_streaming_cls
;
384 uvc_opts
->ss_streaming
= uvc_ss_streaming_cls
;
386 /* Allocate string descriptor numbers ... note that string contents
387 * can be overridden by the composite_dev glue.
389 ret
= usb_string_ids_tab(cdev
, webcam_strings
);
392 webcam_device_descriptor
.iManufacturer
=
393 webcam_strings
[USB_GADGET_MANUFACTURER_IDX
].id
;
394 webcam_device_descriptor
.iProduct
=
395 webcam_strings
[USB_GADGET_PRODUCT_IDX
].id
;
396 webcam_config_driver
.iConfiguration
=
397 webcam_strings
[STRING_DESCRIPTION_IDX
].id
;
399 /* Register our configuration. */
400 if ((ret
= usb_add_config(cdev
, &webcam_config_driver
,
401 webcam_config_bind
)) < 0)
404 usb_composite_overwrite_options(cdev
, &coverwrite
);
405 INFO(cdev
, "Webcam Video Gadget\n");
409 usb_put_function_instance(fi_uvc
);
413 /* --------------------------------------------------------------------------
417 static struct usb_composite_driver webcam_driver
= {
419 .dev
= &webcam_device_descriptor
,
420 .strings
= webcam_device_strings
,
421 .max_speed
= USB_SPEED_SUPER
,
423 .unbind
= webcam_unbind
,
426 module_usb_composite_driver(webcam_driver
);
428 MODULE_AUTHOR("Laurent Pinchart");
429 MODULE_DESCRIPTION("Webcam Video Gadget");
430 MODULE_LICENSE("GPL");