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/usb/video.h>
20 * Kbuild is not very cooperative with respect to linking separately
21 * compiled library objects into one module. So for now we won't use
22 * separate compilation ... ensuring init/exit sections work to shrink
23 * the runtime footprint, and giving us at least some parts of what
24 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
26 #include "composite.c"
27 #include "usbstring.c"
29 #include "epautoconf.c"
31 #include "uvc_queue.c"
32 #include "uvc_video.c"
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_MANUFACTURER_IDX 0
51 #define STRING_PRODUCT_IDX 1
52 #define STRING_DESCRIPTION_IDX 2
54 static struct usb_string webcam_strings
[] = {
55 [STRING_MANUFACTURER_IDX
].s
= webcam_vendor_label
,
56 [STRING_PRODUCT_IDX
].s
= webcam_product_label
,
57 [STRING_DESCRIPTION_IDX
].s
= webcam_config_label
,
61 static struct usb_gadget_strings webcam_stringtab
= {
62 .language
= 0x0409, /* en-us */
63 .strings
= webcam_strings
,
66 static struct usb_gadget_strings
*webcam_device_strings
[] = {
71 static struct usb_device_descriptor webcam_device_descriptor
= {
72 .bLength
= USB_DT_DEVICE_SIZE
,
73 .bDescriptorType
= USB_DT_DEVICE
,
74 .bcdUSB
= cpu_to_le16(0x0200),
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 DECLARE_UVC_HEADER_DESCRIPTOR(1);
90 static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header
= {
91 .bLength
= UVC_DT_HEADER_SIZE(1),
92 .bDescriptorType
= USB_DT_CS_INTERFACE
,
93 .bDescriptorSubType
= UVC_VC_HEADER
,
94 .bcdUVC
= cpu_to_le16(0x0100),
95 .wTotalLength
= 0, /* dynamic */
96 .dwClockFrequency
= cpu_to_le32(48000000),
97 .bInCollection
= 0, /* dynamic */
98 .baInterfaceNr
[0] = 0, /* dynamic */
101 static const struct uvc_camera_terminal_descriptor uvc_camera_terminal
= {
102 .bLength
= UVC_DT_CAMERA_TERMINAL_SIZE(3),
103 .bDescriptorType
= USB_DT_CS_INTERFACE
,
104 .bDescriptorSubType
= UVC_VC_INPUT_TERMINAL
,
106 .wTerminalType
= cpu_to_le16(0x0201),
109 .wObjectiveFocalLengthMin
= cpu_to_le16(0),
110 .wObjectiveFocalLengthMax
= cpu_to_le16(0),
111 .wOcularFocalLength
= cpu_to_le16(0),
118 static const struct uvc_processing_unit_descriptor uvc_processing
= {
119 .bLength
= UVC_DT_PROCESSING_UNIT_SIZE(2),
120 .bDescriptorType
= USB_DT_CS_INTERFACE
,
121 .bDescriptorSubType
= UVC_VC_PROCESSING_UNIT
,
124 .wMaxMultiplier
= cpu_to_le16(16*1024),
131 static const struct uvc_output_terminal_descriptor uvc_output_terminal
= {
132 .bLength
= UVC_DT_OUTPUT_TERMINAL_SIZE
,
133 .bDescriptorType
= USB_DT_CS_INTERFACE
,
134 .bDescriptorSubType
= UVC_VC_OUTPUT_TERMINAL
,
136 .wTerminalType
= cpu_to_le16(0x0101),
142 DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
144 static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header
= {
145 .bLength
= UVC_DT_INPUT_HEADER_SIZE(1, 2),
146 .bDescriptorType
= USB_DT_CS_INTERFACE
,
147 .bDescriptorSubType
= UVC_VS_INPUT_HEADER
,
149 .wTotalLength
= 0, /* dynamic */
150 .bEndpointAddress
= 0, /* dynamic */
153 .bStillCaptureMethod
= 0,
154 .bTriggerSupport
= 0,
157 .bmaControls
[0][0] = 0,
158 .bmaControls
[1][0] = 4,
161 static const struct uvc_format_uncompressed uvc_format_yuv
= {
162 .bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
,
163 .bDescriptorType
= USB_DT_CS_INTERFACE
,
164 .bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
,
166 .bNumFrameDescriptors
= 2,
168 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
169 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
171 .bDefaultFrameIndex
= 1,
174 .bmInterfaceFlags
= 0,
178 DECLARE_UVC_FRAME_UNCOMPRESSED(1);
179 DECLARE_UVC_FRAME_UNCOMPRESSED(3);
181 static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p
= {
182 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
183 .bDescriptorType
= USB_DT_CS_INTERFACE
,
184 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
187 .wWidth
= cpu_to_le16(640),
188 .wHeight
= cpu_to_le16(360),
189 .dwMinBitRate
= cpu_to_le32(18432000),
190 .dwMaxBitRate
= cpu_to_le32(55296000),
191 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
192 .dwDefaultFrameInterval
= cpu_to_le32(666666),
193 .bFrameIntervalType
= 3,
194 .dwFrameInterval
[0] = cpu_to_le32(666666),
195 .dwFrameInterval
[1] = cpu_to_le32(1000000),
196 .dwFrameInterval
[2] = cpu_to_le32(5000000),
199 static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p
= {
200 .bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
201 .bDescriptorType
= USB_DT_CS_INTERFACE
,
202 .bDescriptorSubType
= UVC_VS_FRAME_UNCOMPRESSED
,
205 .wWidth
= cpu_to_le16(1280),
206 .wHeight
= cpu_to_le16(720),
207 .dwMinBitRate
= cpu_to_le32(29491200),
208 .dwMaxBitRate
= cpu_to_le32(29491200),
209 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
210 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
211 .bFrameIntervalType
= 1,
212 .dwFrameInterval
[0] = cpu_to_le32(5000000),
215 static const struct uvc_format_mjpeg uvc_format_mjpg
= {
216 .bLength
= UVC_DT_FORMAT_MJPEG_SIZE
,
217 .bDescriptorType
= USB_DT_CS_INTERFACE
,
218 .bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
,
220 .bNumFrameDescriptors
= 2,
222 .bDefaultFrameIndex
= 1,
225 .bmInterfaceFlags
= 0,
229 DECLARE_UVC_FRAME_MJPEG(1);
230 DECLARE_UVC_FRAME_MJPEG(3);
232 static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p
= {
233 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(3),
234 .bDescriptorType
= USB_DT_CS_INTERFACE
,
235 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
238 .wWidth
= cpu_to_le16(640),
239 .wHeight
= cpu_to_le16(360),
240 .dwMinBitRate
= cpu_to_le32(18432000),
241 .dwMaxBitRate
= cpu_to_le32(55296000),
242 .dwMaxVideoFrameBufferSize
= cpu_to_le32(460800),
243 .dwDefaultFrameInterval
= cpu_to_le32(666666),
244 .bFrameIntervalType
= 3,
245 .dwFrameInterval
[0] = cpu_to_le32(666666),
246 .dwFrameInterval
[1] = cpu_to_le32(1000000),
247 .dwFrameInterval
[2] = cpu_to_le32(5000000),
250 static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p
= {
251 .bLength
= UVC_DT_FRAME_MJPEG_SIZE(1),
252 .bDescriptorType
= USB_DT_CS_INTERFACE
,
253 .bDescriptorSubType
= UVC_VS_FRAME_MJPEG
,
256 .wWidth
= cpu_to_le16(1280),
257 .wHeight
= cpu_to_le16(720),
258 .dwMinBitRate
= cpu_to_le32(29491200),
259 .dwMaxBitRate
= cpu_to_le32(29491200),
260 .dwMaxVideoFrameBufferSize
= cpu_to_le32(1843200),
261 .dwDefaultFrameInterval
= cpu_to_le32(5000000),
262 .bFrameIntervalType
= 1,
263 .dwFrameInterval
[0] = cpu_to_le32(5000000),
266 static const struct uvc_color_matching_descriptor uvc_color_matching
= {
267 .bLength
= UVC_DT_COLOR_MATCHING_SIZE
,
268 .bDescriptorType
= USB_DT_CS_INTERFACE
,
269 .bDescriptorSubType
= UVC_VS_COLORFORMAT
,
270 .bColorPrimaries
= 1,
271 .bTransferCharacteristics
= 1,
272 .bMatrixCoefficients
= 4,
275 static const struct uvc_descriptor_header
* const uvc_control_cls
[] = {
276 (const struct uvc_descriptor_header
*) &uvc_control_header
,
277 (const struct uvc_descriptor_header
*) &uvc_camera_terminal
,
278 (const struct uvc_descriptor_header
*) &uvc_processing
,
279 (const struct uvc_descriptor_header
*) &uvc_output_terminal
,
283 static const struct uvc_descriptor_header
* const uvc_fs_streaming_cls
[] = {
284 (const struct uvc_descriptor_header
*) &uvc_input_header
,
285 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
286 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
287 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
288 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
289 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
290 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
291 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
295 static const struct uvc_descriptor_header
* const uvc_hs_streaming_cls
[] = {
296 (const struct uvc_descriptor_header
*) &uvc_input_header
,
297 (const struct uvc_descriptor_header
*) &uvc_format_yuv
,
298 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_360p
,
299 (const struct uvc_descriptor_header
*) &uvc_frame_yuv_720p
,
300 (const struct uvc_descriptor_header
*) &uvc_format_mjpg
,
301 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_360p
,
302 (const struct uvc_descriptor_header
*) &uvc_frame_mjpg_720p
,
303 (const struct uvc_descriptor_header
*) &uvc_color_matching
,
307 /* --------------------------------------------------------------------------
312 webcam_config_bind(struct usb_configuration
*c
)
314 return uvc_bind_config(c
, uvc_control_cls
, uvc_fs_streaming_cls
,
315 uvc_hs_streaming_cls
);
318 static struct usb_configuration webcam_config_driver
= {
319 .label
= webcam_config_label
,
320 .bConfigurationValue
= 1,
321 .iConfiguration
= 0, /* dynamic */
322 .bmAttributes
= USB_CONFIG_ATT_SELFPOWER
,
323 .bMaxPower
= CONFIG_USB_GADGET_VBUS_DRAW
/ 2,
326 static int /* __init_or_exit */
327 webcam_unbind(struct usb_composite_dev
*cdev
)
333 webcam_bind(struct usb_composite_dev
*cdev
)
337 /* Allocate string descriptor numbers ... note that string contents
338 * can be overridden by the composite_dev glue.
340 if ((ret
= usb_string_id(cdev
)) < 0)
342 webcam_strings
[STRING_MANUFACTURER_IDX
].id
= ret
;
343 webcam_device_descriptor
.iManufacturer
= ret
;
345 if ((ret
= usb_string_id(cdev
)) < 0)
347 webcam_strings
[STRING_PRODUCT_IDX
].id
= ret
;
348 webcam_device_descriptor
.iProduct
= ret
;
350 if ((ret
= usb_string_id(cdev
)) < 0)
352 webcam_strings
[STRING_DESCRIPTION_IDX
].id
= ret
;
353 webcam_config_driver
.iConfiguration
= ret
;
355 /* Register our configuration. */
356 if ((ret
= usb_add_config(cdev
, &webcam_config_driver
,
357 webcam_config_bind
)) < 0)
360 INFO(cdev
, "Webcam Video Gadget\n");
368 /* --------------------------------------------------------------------------
372 static struct usb_composite_driver webcam_driver
= {
374 .dev
= &webcam_device_descriptor
,
375 .strings
= webcam_device_strings
,
376 .max_speed
= USB_SPEED_HIGH
,
377 .unbind
= webcam_unbind
,
383 return usb_composite_probe(&webcam_driver
, webcam_bind
);
389 usb_composite_unregister(&webcam_driver
);
392 module_init(webcam_init
);
393 module_exit(webcam_cleanup
);
395 MODULE_AUTHOR("Laurent Pinchart");
396 MODULE_DESCRIPTION("Webcam Video Gadget");
397 MODULE_LICENSE("GPL");
398 MODULE_VERSION("0.1.0");