2 * webcam.c -- USB webcam gadget driver
4 * Copyright (C) 2009-2010
5 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
13 #include <linux/kernel.h>
14 #include <linux/device.h>
15 #include <linux/module.h>
16 #include <linux/usb/video.h>
20 USB_GADGET_COMPOSITE_OPTIONS();
22 /*-------------------------------------------------------------------------*/
24 /* module parameters specific to the Video streaming endpoint */
25 static unsigned int streaming_interval
= 1;
26 module_param(streaming_interval
, uint
, S_IRUGO
|S_IWUSR
);
27 MODULE_PARM_DESC(streaming_interval
, "1 - 16");
29 static unsigned int streaming_maxpacket
= 1024;
30 module_param(streaming_maxpacket
, uint
, S_IRUGO
|S_IWUSR
);
31 MODULE_PARM_DESC(streaming_maxpacket
, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
33 static unsigned int streaming_maxburst
;
34 module_param(streaming_maxburst
, uint
, S_IRUGO
|S_IWUSR
);
35 MODULE_PARM_DESC(streaming_maxburst
, "0 - 15 (ss only)");
37 static unsigned int trace
;
38 module_param(trace
, uint
, S_IRUGO
|S_IWUSR
);
39 MODULE_PARM_DESC(trace
, "Trace level bitmask");
40 /* --------------------------------------------------------------------------
44 #define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */
45 #define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */
46 #define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */
48 static char webcam_vendor_label
[] = "Linux Foundation";
49 static char webcam_product_label
[] = "Webcam gadget";
50 static char webcam_config_label
[] = "Video";
52 /* string IDs are assigned dynamically */
54 #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
56 static struct usb_string webcam_strings
[] = {
57 [USB_GADGET_MANUFACTURER_IDX
].s
= webcam_vendor_label
,
58 [USB_GADGET_PRODUCT_IDX
].s
= webcam_product_label
,
59 [USB_GADGET_SERIAL_IDX
].s
= "",
60 [STRING_DESCRIPTION_IDX
].s
= webcam_config_label
,
64 static struct usb_gadget_strings webcam_stringtab
= {
65 .language
= 0x0409, /* en-us */
66 .strings
= webcam_strings
,
69 static struct usb_gadget_strings
*webcam_device_strings
[] = {
74 static struct usb_function_instance
*fi_uvc
;
75 static struct usb_function
*f_uvc
;
77 static struct usb_device_descriptor webcam_device_descriptor
= {
78 .bLength
= USB_DT_DEVICE_SIZE
,
79 .bDescriptorType
= USB_DT_DEVICE
,
80 /* .bcdUSB = DYNAMIC */
81 .bDeviceClass
= USB_CLASS_MISC
,
82 .bDeviceSubClass
= 0x02,
83 .bDeviceProtocol
= 0x01,
84 .bMaxPacketSize0
= 0, /* dynamic */
85 .idVendor
= cpu_to_le16(WEBCAM_VENDOR_ID
),
86 .idProduct
= cpu_to_le16(WEBCAM_PRODUCT_ID
),
87 .bcdDevice
= cpu_to_le16(WEBCAM_DEVICE_BCD
),
88 .iManufacturer
= 0, /* dynamic */
89 .iProduct
= 0, /* dynamic */
90 .iSerialNumber
= 0, /* dynamic */
91 .bNumConfigurations
= 0, /* dynamic */
94 DECLARE_UVC_HEADER_DESCRIPTOR(1);
96 static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header
= {
97 .bLength
= UVC_DT_HEADER_SIZE(1),
98 .bDescriptorType
= USB_DT_CS_INTERFACE
,
99 .bDescriptorSubType
= UVC_VC_HEADER
,
100 .bcdUVC
= cpu_to_le16(0x0100),
101 .wTotalLength
= 0, /* dynamic */
102 .dwClockFrequency
= cpu_to_le32(48000000),
103 .bInCollection
= 0, /* dynamic */
104 .baInterfaceNr
[0] = 0, /* dynamic */
107 static const struct uvc_camera_terminal_descriptor uvc_camera_terminal
= {
108 .bLength
= UVC_DT_CAMERA_TERMINAL_SIZE(3),
109 .bDescriptorType
= USB_DT_CS_INTERFACE
,
110 .bDescriptorSubType
= UVC_VC_INPUT_TERMINAL
,
112 .wTerminalType
= cpu_to_le16(0x0201),
115 .wObjectiveFocalLengthMin
= cpu_to_le16(0),
116 .wObjectiveFocalLengthMax
= cpu_to_le16(0),
117 .wOcularFocalLength
= cpu_to_le16(0),
124 static const struct uvc_processing_unit_descriptor uvc_processing
= {
125 .bLength
= UVC_DT_PROCESSING_UNIT_SIZE(2),
126 .bDescriptorType
= USB_DT_CS_INTERFACE
,
127 .bDescriptorSubType
= UVC_VC_PROCESSING_UNIT
,
130 .wMaxMultiplier
= cpu_to_le16(16*1024),
137 static const struct uvc_output_terminal_descriptor uvc_output_terminal
= {
138 .bLength
= UVC_DT_OUTPUT_TERMINAL_SIZE
,
139 .bDescriptorType
= USB_DT_CS_INTERFACE
,
140 .bDescriptorSubType
= UVC_VC_OUTPUT_TERMINAL
,
142 .wTerminalType
= cpu_to_le16(0x0101),
148 DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
150 static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header
= {
151 .bLength
= UVC_DT_INPUT_HEADER_SIZE(1, 2),
152 .bDescriptorType
= USB_DT_CS_INTERFACE
,
153 .bDescriptorSubType
= UVC_VS_INPUT_HEADER
,
155 .wTotalLength
= 0, /* dynamic */
156 .bEndpointAddress
= 0, /* dynamic */
159 .bStillCaptureMethod
= 0,
160 .bTriggerSupport
= 0,
163 .bmaControls
[0][0] = 0,
164 .bmaControls
[1][0] = 4,
167 static const struct uvc_format_uncompressed uvc_format_yuv
= {
168 .bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
,
169 .bDescriptorType
= USB_DT_CS_INTERFACE
,
170 .bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
,
172 .bNumFrameDescriptors
= 2,
174 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
175 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
177 .bDefaultFrameIndex
= 1,
180 .bmInterfaceFlags
= 0,
184 DECLARE_UVC_FRAME_UNCOMPRESSED(1);
185 DECLARE_UVC_FRAME_UNCOMPRESSED(3);
187 static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p
= {
188 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
189 .bDescriptorType
= USB_DT_CS_INTERFACE
,
190 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
193 .wWidth
= cpu_to_le16(640),
194 .wHeight
= cpu_to_le16(360),
195 .dwMinBitRate
= cpu_to_le32(18432000),
196 .dwMaxBitRate
= cpu_to_le32(55296000),
197 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
198 .dwDefaultFrameInterval
= cpu_to_le32(666666),
199 .bFrameIntervalType
= 3,
200 .dwFrameInterval
[0] = cpu_to_le32(666666),
201 .dwFrameInterval
[1] = cpu_to_le32(1000000),
202 .dwFrameInterval
[2] = cpu_to_le32(5000000),
205 static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p
= {
206 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
207 .bDescriptorType
= USB_DT_CS_INTERFACE
,
208 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
211 .wWidth
= cpu_to_le16(1280),
212 .wHeight
= cpu_to_le16(720),
213 .dwMinBitRate
= cpu_to_le32(29491200),
214 .dwMaxBitRate
= cpu_to_le32(29491200),
215 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
216 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
217 .bFrameIntervalType
= 1,
218 .dwFrameInterval
[0] = cpu_to_le32(5000000),
221 static const struct uvc_format_mjpeg uvc_format_mjpg
= {
222 .bLength
= UVC_DT_FORMAT_MJPEG_SIZE
,
223 .bDescriptorType
= USB_DT_CS_INTERFACE
,
224 .bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
,
226 .bNumFrameDescriptors
= 2,
228 .bDefaultFrameIndex
= 1,
231 .bmInterfaceFlags
= 0,
235 DECLARE_UVC_FRAME_MJPEG(1);
236 DECLARE_UVC_FRAME_MJPEG(3);
238 static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p
= {
239 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(3),
240 .bDescriptorType
= USB_DT_CS_INTERFACE
,
241 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
244 .wWidth
= cpu_to_le16(640),
245 .wHeight
= cpu_to_le16(360),
246 .dwMinBitRate
= cpu_to_le32(18432000),
247 .dwMaxBitRate
= cpu_to_le32(55296000),
248 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
249 .dwDefaultFrameInterval
= cpu_to_le32(666666),
250 .bFrameIntervalType
= 3,
251 .dwFrameInterval
[0] = cpu_to_le32(666666),
252 .dwFrameInterval
[1] = cpu_to_le32(1000000),
253 .dwFrameInterval
[2] = cpu_to_le32(5000000),
256 static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p
= {
257 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(1),
258 .bDescriptorType
= USB_DT_CS_INTERFACE
,
259 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
262 .wWidth
= cpu_to_le16(1280),
263 .wHeight
= cpu_to_le16(720),
264 .dwMinBitRate
= cpu_to_le32(29491200),
265 .dwMaxBitRate
= cpu_to_le32(29491200),
266 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
267 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
268 .bFrameIntervalType
= 1,
269 .dwFrameInterval
[0] = cpu_to_le32(5000000),
272 static const struct uvc_color_matching_descriptor uvc_color_matching
= {
273 .bLength
= UVC_DT_COLOR_MATCHING_SIZE
,
274 .bDescriptorType
= USB_DT_CS_INTERFACE
,
275 .bDescriptorSubType
= UVC_VS_COLORFORMAT
,
276 .bColorPrimaries
= 1,
277 .bTransferCharacteristics
= 1,
278 .bMatrixCoefficients
= 4,
281 static const struct uvc_descriptor_header
* const uvc_fs_control_cls
[] = {
282 (const struct uvc_descriptor_header
*) &uvc_control_header
,
283 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
284 (const struct uvc_descriptor_header
*) &uvc_processing
,
285 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
289 static const struct uvc_descriptor_header
* const uvc_ss_control_cls
[] = {
290 (const struct uvc_descriptor_header
*) &uvc_control_header
,
291 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
292 (const struct uvc_descriptor_header
*) &uvc_processing
,
293 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
297 static const struct uvc_descriptor_header
* const uvc_fs_streaming_cls
[] = {
298 (const struct uvc_descriptor_header
*) &uvc_input_header
,
299 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
300 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
301 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
302 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
303 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
304 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
305 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
309 static const struct uvc_descriptor_header
* const uvc_hs_streaming_cls
[] = {
310 (const struct uvc_descriptor_header
*) &uvc_input_header
,
311 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
312 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
313 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
314 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
315 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
316 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
317 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
321 static const struct uvc_descriptor_header
* const uvc_ss_streaming_cls
[] = {
322 (const struct uvc_descriptor_header
*) &uvc_input_header
,
323 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
324 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
325 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
326 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
327 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
328 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
329 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
333 /* --------------------------------------------------------------------------
338 webcam_config_bind(struct usb_configuration
*c
)
342 f_uvc
= usb_get_function(fi_uvc
);
344 return PTR_ERR(f_uvc
);
346 status
= usb_add_function(c
, f_uvc
);
348 usb_put_function(f_uvc
);
353 static struct usb_configuration webcam_config_driver
= {
354 .label
= webcam_config_label
,
355 .bConfigurationValue
= 1,
356 .iConfiguration
= 0, /* dynamic */
357 .bmAttributes
= USB_CONFIG_ATT_SELFPOWER
,
358 .MaxPower
= CONFIG_USB_GADGET_VBUS_DRAW
,
362 webcam_unbind(struct usb_composite_dev
*cdev
)
364 if (!IS_ERR_OR_NULL(f_uvc
))
365 usb_put_function(f_uvc
);
366 if (!IS_ERR_OR_NULL(fi_uvc
))
367 usb_put_function_instance(fi_uvc
);
372 webcam_bind(struct usb_composite_dev
*cdev
)
374 struct f_uvc_opts
*uvc_opts
;
377 fi_uvc
= usb_get_function_instance("uvc");
379 return PTR_ERR(fi_uvc
);
381 uvc_opts
= container_of(fi_uvc
, struct f_uvc_opts
, func_inst
);
383 uvc_opts
->streaming_interval
= streaming_interval
;
384 uvc_opts
->streaming_maxpacket
= streaming_maxpacket
;
385 uvc_opts
->streaming_maxburst
= streaming_maxburst
;
386 uvc_set_trace_param(trace
);
388 uvc_opts
->fs_control
= uvc_fs_control_cls
;
389 uvc_opts
->ss_control
= uvc_ss_control_cls
;
390 uvc_opts
->fs_streaming
= uvc_fs_streaming_cls
;
391 uvc_opts
->hs_streaming
= uvc_hs_streaming_cls
;
392 uvc_opts
->ss_streaming
= uvc_ss_streaming_cls
;
394 /* Allocate string descriptor numbers ... note that string contents
395 * can be overridden by the composite_dev glue.
397 ret
= usb_string_ids_tab(cdev
, webcam_strings
);
400 webcam_device_descriptor
.iManufacturer
=
401 webcam_strings
[USB_GADGET_MANUFACTURER_IDX
].id
;
402 webcam_device_descriptor
.iProduct
=
403 webcam_strings
[USB_GADGET_PRODUCT_IDX
].id
;
404 webcam_config_driver
.iConfiguration
=
405 webcam_strings
[STRING_DESCRIPTION_IDX
].id
;
407 /* Register our configuration. */
408 if ((ret
= usb_add_config(cdev
, &webcam_config_driver
,
409 webcam_config_bind
)) < 0)
412 usb_composite_overwrite_options(cdev
, &coverwrite
);
413 INFO(cdev
, "Webcam Video Gadget\n");
417 usb_put_function_instance(fi_uvc
);
421 /* --------------------------------------------------------------------------
425 static struct usb_composite_driver webcam_driver
= {
427 .dev
= &webcam_device_descriptor
,
428 .strings
= webcam_device_strings
,
429 .max_speed
= USB_SPEED_SUPER
,
431 .unbind
= webcam_unbind
,
434 module_usb_composite_driver(webcam_driver
);
436 MODULE_AUTHOR("Laurent Pinchart");
437 MODULE_DESCRIPTION("Webcam Video Gadget");
438 MODULE_LICENSE("GPL");
439 MODULE_VERSION("0.1.0");