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 static unsigned int trace
;
34 module_param(trace
, uint
, S_IRUGO
|S_IWUSR
);
35 MODULE_PARM_DESC(trace
, "Trace level bitmask");
36 /* --------------------------------------------------------------------------
40 #define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */
41 #define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */
42 #define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */
44 static char webcam_vendor_label
[] = "Linux Foundation";
45 static char webcam_product_label
[] = "Webcam gadget";
46 static char webcam_config_label
[] = "Video";
48 /* string IDs are assigned dynamically */
50 #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
52 static struct usb_string webcam_strings
[] = {
53 [USB_GADGET_MANUFACTURER_IDX
].s
= webcam_vendor_label
,
54 [USB_GADGET_PRODUCT_IDX
].s
= webcam_product_label
,
55 [USB_GADGET_SERIAL_IDX
].s
= "",
56 [STRING_DESCRIPTION_IDX
].s
= webcam_config_label
,
60 static struct usb_gadget_strings webcam_stringtab
= {
61 .language
= 0x0409, /* en-us */
62 .strings
= webcam_strings
,
65 static struct usb_gadget_strings
*webcam_device_strings
[] = {
70 static struct usb_function_instance
*fi_uvc
;
71 static struct usb_function
*f_uvc
;
73 static struct usb_device_descriptor webcam_device_descriptor
= {
74 .bLength
= USB_DT_DEVICE_SIZE
,
75 .bDescriptorType
= USB_DT_DEVICE
,
76 /* .bcdUSB = DYNAMIC */
77 .bDeviceClass
= USB_CLASS_MISC
,
78 .bDeviceSubClass
= 0x02,
79 .bDeviceProtocol
= 0x01,
80 .bMaxPacketSize0
= 0, /* dynamic */
81 .idVendor
= cpu_to_le16(WEBCAM_VENDOR_ID
),
82 .idProduct
= cpu_to_le16(WEBCAM_PRODUCT_ID
),
83 .bcdDevice
= cpu_to_le16(WEBCAM_DEVICE_BCD
),
84 .iManufacturer
= 0, /* dynamic */
85 .iProduct
= 0, /* dynamic */
86 .iSerialNumber
= 0, /* dynamic */
87 .bNumConfigurations
= 0, /* dynamic */
90 DECLARE_UVC_HEADER_DESCRIPTOR(1);
92 static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header
= {
93 .bLength
= UVC_DT_HEADER_SIZE(1),
94 .bDescriptorType
= USB_DT_CS_INTERFACE
,
95 .bDescriptorSubType
= UVC_VC_HEADER
,
96 .bcdUVC
= cpu_to_le16(0x0100),
97 .wTotalLength
= 0, /* dynamic */
98 .dwClockFrequency
= cpu_to_le32(48000000),
99 .bInCollection
= 0, /* dynamic */
100 .baInterfaceNr
[0] = 0, /* dynamic */
103 static const struct uvc_camera_terminal_descriptor uvc_camera_terminal
= {
104 .bLength
= UVC_DT_CAMERA_TERMINAL_SIZE(3),
105 .bDescriptorType
= USB_DT_CS_INTERFACE
,
106 .bDescriptorSubType
= UVC_VC_INPUT_TERMINAL
,
108 .wTerminalType
= cpu_to_le16(0x0201),
111 .wObjectiveFocalLengthMin
= cpu_to_le16(0),
112 .wObjectiveFocalLengthMax
= cpu_to_le16(0),
113 .wOcularFocalLength
= cpu_to_le16(0),
120 static const struct uvc_processing_unit_descriptor uvc_processing
= {
121 .bLength
= UVC_DT_PROCESSING_UNIT_SIZE(2),
122 .bDescriptorType
= USB_DT_CS_INTERFACE
,
123 .bDescriptorSubType
= UVC_VC_PROCESSING_UNIT
,
126 .wMaxMultiplier
= cpu_to_le16(16*1024),
133 static const struct uvc_output_terminal_descriptor uvc_output_terminal
= {
134 .bLength
= UVC_DT_OUTPUT_TERMINAL_SIZE
,
135 .bDescriptorType
= USB_DT_CS_INTERFACE
,
136 .bDescriptorSubType
= UVC_VC_OUTPUT_TERMINAL
,
138 .wTerminalType
= cpu_to_le16(0x0101),
144 DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
146 static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header
= {
147 .bLength
= UVC_DT_INPUT_HEADER_SIZE(1, 2),
148 .bDescriptorType
= USB_DT_CS_INTERFACE
,
149 .bDescriptorSubType
= UVC_VS_INPUT_HEADER
,
151 .wTotalLength
= 0, /* dynamic */
152 .bEndpointAddress
= 0, /* dynamic */
155 .bStillCaptureMethod
= 0,
156 .bTriggerSupport
= 0,
159 .bmaControls
[0][0] = 0,
160 .bmaControls
[1][0] = 4,
163 static const struct uvc_format_uncompressed uvc_format_yuv
= {
164 .bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
,
165 .bDescriptorType
= USB_DT_CS_INTERFACE
,
166 .bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
,
168 .bNumFrameDescriptors
= 2,
170 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
171 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
173 .bDefaultFrameIndex
= 1,
176 .bmInterfaceFlags
= 0,
180 DECLARE_UVC_FRAME_UNCOMPRESSED(1);
181 DECLARE_UVC_FRAME_UNCOMPRESSED(3);
183 static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p
= {
184 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
185 .bDescriptorType
= USB_DT_CS_INTERFACE
,
186 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
189 .wWidth
= cpu_to_le16(640),
190 .wHeight
= cpu_to_le16(360),
191 .dwMinBitRate
= cpu_to_le32(18432000),
192 .dwMaxBitRate
= cpu_to_le32(55296000),
193 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
194 .dwDefaultFrameInterval
= cpu_to_le32(666666),
195 .bFrameIntervalType
= 3,
196 .dwFrameInterval
[0] = cpu_to_le32(666666),
197 .dwFrameInterval
[1] = cpu_to_le32(1000000),
198 .dwFrameInterval
[2] = cpu_to_le32(5000000),
201 static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p
= {
202 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
203 .bDescriptorType
= USB_DT_CS_INTERFACE
,
204 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
207 .wWidth
= cpu_to_le16(1280),
208 .wHeight
= cpu_to_le16(720),
209 .dwMinBitRate
= cpu_to_le32(29491200),
210 .dwMaxBitRate
= cpu_to_le32(29491200),
211 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
212 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
213 .bFrameIntervalType
= 1,
214 .dwFrameInterval
[0] = cpu_to_le32(5000000),
217 static const struct uvc_format_mjpeg uvc_format_mjpg
= {
218 .bLength
= UVC_DT_FORMAT_MJPEG_SIZE
,
219 .bDescriptorType
= USB_DT_CS_INTERFACE
,
220 .bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
,
222 .bNumFrameDescriptors
= 2,
224 .bDefaultFrameIndex
= 1,
227 .bmInterfaceFlags
= 0,
231 DECLARE_UVC_FRAME_MJPEG(1);
232 DECLARE_UVC_FRAME_MJPEG(3);
234 static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p
= {
235 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(3),
236 .bDescriptorType
= USB_DT_CS_INTERFACE
,
237 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
240 .wWidth
= cpu_to_le16(640),
241 .wHeight
= cpu_to_le16(360),
242 .dwMinBitRate
= cpu_to_le32(18432000),
243 .dwMaxBitRate
= cpu_to_le32(55296000),
244 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
245 .dwDefaultFrameInterval
= cpu_to_le32(666666),
246 .bFrameIntervalType
= 3,
247 .dwFrameInterval
[0] = cpu_to_le32(666666),
248 .dwFrameInterval
[1] = cpu_to_le32(1000000),
249 .dwFrameInterval
[2] = cpu_to_le32(5000000),
252 static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p
= {
253 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(1),
254 .bDescriptorType
= USB_DT_CS_INTERFACE
,
255 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
258 .wWidth
= cpu_to_le16(1280),
259 .wHeight
= cpu_to_le16(720),
260 .dwMinBitRate
= cpu_to_le32(29491200),
261 .dwMaxBitRate
= cpu_to_le32(29491200),
262 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
263 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
264 .bFrameIntervalType
= 1,
265 .dwFrameInterval
[0] = cpu_to_le32(5000000),
268 static const struct uvc_color_matching_descriptor uvc_color_matching
= {
269 .bLength
= UVC_DT_COLOR_MATCHING_SIZE
,
270 .bDescriptorType
= USB_DT_CS_INTERFACE
,
271 .bDescriptorSubType
= UVC_VS_COLORFORMAT
,
272 .bColorPrimaries
= 1,
273 .bTransferCharacteristics
= 1,
274 .bMatrixCoefficients
= 4,
277 static const struct uvc_descriptor_header
* const uvc_fs_control_cls
[] = {
278 (const struct uvc_descriptor_header
*) &uvc_control_header
,
279 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
280 (const struct uvc_descriptor_header
*) &uvc_processing
,
281 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
285 static const struct uvc_descriptor_header
* const uvc_ss_control_cls
[] = {
286 (const struct uvc_descriptor_header
*) &uvc_control_header
,
287 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
288 (const struct uvc_descriptor_header
*) &uvc_processing
,
289 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
293 static const struct uvc_descriptor_header
* const uvc_fs_streaming_cls
[] = {
294 (const struct uvc_descriptor_header
*) &uvc_input_header
,
295 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
296 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
297 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
298 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
299 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
300 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
301 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
305 static const struct uvc_descriptor_header
* const uvc_hs_streaming_cls
[] = {
306 (const struct uvc_descriptor_header
*) &uvc_input_header
,
307 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
308 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
309 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
310 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
311 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
312 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
313 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
317 static const struct uvc_descriptor_header
* const uvc_ss_streaming_cls
[] = {
318 (const struct uvc_descriptor_header
*) &uvc_input_header
,
319 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
320 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
321 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
322 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
323 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
324 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
325 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
329 /* --------------------------------------------------------------------------
334 webcam_config_bind(struct usb_configuration
*c
)
338 f_uvc
= usb_get_function(fi_uvc
);
340 return PTR_ERR(f_uvc
);
342 status
= usb_add_function(c
, f_uvc
);
344 usb_put_function(f_uvc
);
349 static struct usb_configuration webcam_config_driver
= {
350 .label
= webcam_config_label
,
351 .bConfigurationValue
= 1,
352 .iConfiguration
= 0, /* dynamic */
353 .bmAttributes
= USB_CONFIG_ATT_SELFPOWER
,
354 .MaxPower
= CONFIG_USB_GADGET_VBUS_DRAW
,
358 webcam_unbind(struct usb_composite_dev
*cdev
)
360 if (!IS_ERR_OR_NULL(f_uvc
))
361 usb_put_function(f_uvc
);
362 if (!IS_ERR_OR_NULL(fi_uvc
))
363 usb_put_function_instance(fi_uvc
);
368 webcam_bind(struct usb_composite_dev
*cdev
)
370 struct f_uvc_opts
*uvc_opts
;
373 fi_uvc
= usb_get_function_instance("uvc");
375 return PTR_ERR(fi_uvc
);
377 uvc_opts
= container_of(fi_uvc
, struct f_uvc_opts
, func_inst
);
379 uvc_opts
->streaming_interval
= streaming_interval
;
380 uvc_opts
->streaming_maxpacket
= streaming_maxpacket
;
381 uvc_opts
->streaming_maxburst
= streaming_maxburst
;
382 uvc_set_trace_param(trace
);
384 uvc_opts
->fs_control
= uvc_fs_control_cls
;
385 uvc_opts
->ss_control
= uvc_ss_control_cls
;
386 uvc_opts
->fs_streaming
= uvc_fs_streaming_cls
;
387 uvc_opts
->hs_streaming
= uvc_hs_streaming_cls
;
388 uvc_opts
->ss_streaming
= uvc_ss_streaming_cls
;
390 /* Allocate string descriptor numbers ... note that string contents
391 * can be overridden by the composite_dev glue.
393 ret
= usb_string_ids_tab(cdev
, webcam_strings
);
396 webcam_device_descriptor
.iManufacturer
=
397 webcam_strings
[USB_GADGET_MANUFACTURER_IDX
].id
;
398 webcam_device_descriptor
.iProduct
=
399 webcam_strings
[USB_GADGET_PRODUCT_IDX
].id
;
400 webcam_config_driver
.iConfiguration
=
401 webcam_strings
[STRING_DESCRIPTION_IDX
].id
;
403 /* Register our configuration. */
404 if ((ret
= usb_add_config(cdev
, &webcam_config_driver
,
405 webcam_config_bind
)) < 0)
408 usb_composite_overwrite_options(cdev
, &coverwrite
);
409 INFO(cdev
, "Webcam Video Gadget\n");
413 usb_put_function_instance(fi_uvc
);
417 /* --------------------------------------------------------------------------
421 static struct usb_composite_driver webcam_driver
= {
423 .dev
= &webcam_device_descriptor
,
424 .strings
= webcam_device_strings
,
425 .max_speed
= USB_SPEED_SUPER
,
427 .unbind
= webcam_unbind
,
430 module_usb_composite_driver(webcam_driver
);
432 MODULE_AUTHOR("Laurent Pinchart");
433 MODULE_DESCRIPTION("Webcam Video Gadget");
434 MODULE_LICENSE("GPL");