at v3.9 412 lines 13 kB view raw
1/* 2 * webcam.c -- USB webcam gadget driver 3 * 4 * Copyright (C) 2009-2010 5 * Laurent Pinchart (laurent.pinchart@ideasonboard.com) 6 * 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. 11 */ 12 13#include <linux/kernel.h> 14#include <linux/device.h> 15#include <linux/usb/video.h> 16 17#include "f_uvc.h" 18 19/* 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. 25 */ 26#include "uvc_queue.c" 27#include "uvc_video.c" 28#include "uvc_v4l2.c" 29#include "f_uvc.c" 30 31USB_GADGET_COMPOSITE_OPTIONS(); 32/* -------------------------------------------------------------------------- 33 * Device descriptor 34 */ 35 36#define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */ 37#define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */ 38#define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */ 39 40static char webcam_vendor_label[] = "Linux Foundation"; 41static char webcam_product_label[] = "Webcam gadget"; 42static char webcam_config_label[] = "Video"; 43 44/* string IDs are assigned dynamically */ 45 46#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX 47 48static struct usb_string webcam_strings[] = { 49 [USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label, 50 [USB_GADGET_PRODUCT_IDX].s = webcam_product_label, 51 [USB_GADGET_SERIAL_IDX].s = "", 52 [STRING_DESCRIPTION_IDX].s = webcam_config_label, 53 { } 54}; 55 56static struct usb_gadget_strings webcam_stringtab = { 57 .language = 0x0409, /* en-us */ 58 .strings = webcam_strings, 59}; 60 61static struct usb_gadget_strings *webcam_device_strings[] = { 62 &webcam_stringtab, 63 NULL, 64}; 65 66static struct usb_device_descriptor webcam_device_descriptor = { 67 .bLength = USB_DT_DEVICE_SIZE, 68 .bDescriptorType = USB_DT_DEVICE, 69 .bcdUSB = cpu_to_le16(0x0200), 70 .bDeviceClass = USB_CLASS_MISC, 71 .bDeviceSubClass = 0x02, 72 .bDeviceProtocol = 0x01, 73 .bMaxPacketSize0 = 0, /* dynamic */ 74 .idVendor = cpu_to_le16(WEBCAM_VENDOR_ID), 75 .idProduct = cpu_to_le16(WEBCAM_PRODUCT_ID), 76 .bcdDevice = cpu_to_le16(WEBCAM_DEVICE_BCD), 77 .iManufacturer = 0, /* dynamic */ 78 .iProduct = 0, /* dynamic */ 79 .iSerialNumber = 0, /* dynamic */ 80 .bNumConfigurations = 0, /* dynamic */ 81}; 82 83DECLARE_UVC_HEADER_DESCRIPTOR(1); 84 85static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { 86 .bLength = UVC_DT_HEADER_SIZE(1), 87 .bDescriptorType = USB_DT_CS_INTERFACE, 88 .bDescriptorSubType = UVC_VC_HEADER, 89 .bcdUVC = cpu_to_le16(0x0100), 90 .wTotalLength = 0, /* dynamic */ 91 .dwClockFrequency = cpu_to_le32(48000000), 92 .bInCollection = 0, /* dynamic */ 93 .baInterfaceNr[0] = 0, /* dynamic */ 94}; 95 96static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = { 97 .bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3), 98 .bDescriptorType = USB_DT_CS_INTERFACE, 99 .bDescriptorSubType = UVC_VC_INPUT_TERMINAL, 100 .bTerminalID = 1, 101 .wTerminalType = cpu_to_le16(0x0201), 102 .bAssocTerminal = 0, 103 .iTerminal = 0, 104 .wObjectiveFocalLengthMin = cpu_to_le16(0), 105 .wObjectiveFocalLengthMax = cpu_to_le16(0), 106 .wOcularFocalLength = cpu_to_le16(0), 107 .bControlSize = 3, 108 .bmControls[0] = 2, 109 .bmControls[1] = 0, 110 .bmControls[2] = 0, 111}; 112 113static const struct uvc_processing_unit_descriptor uvc_processing = { 114 .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2), 115 .bDescriptorType = USB_DT_CS_INTERFACE, 116 .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, 117 .bUnitID = 2, 118 .bSourceID = 1, 119 .wMaxMultiplier = cpu_to_le16(16*1024), 120 .bControlSize = 2, 121 .bmControls[0] = 1, 122 .bmControls[1] = 0, 123 .iProcessing = 0, 124}; 125 126static const struct uvc_output_terminal_descriptor uvc_output_terminal = { 127 .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, 128 .bDescriptorType = USB_DT_CS_INTERFACE, 129 .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, 130 .bTerminalID = 3, 131 .wTerminalType = cpu_to_le16(0x0101), 132 .bAssocTerminal = 0, 133 .bSourceID = 2, 134 .iTerminal = 0, 135}; 136 137DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); 138 139static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = { 140 .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2), 141 .bDescriptorType = USB_DT_CS_INTERFACE, 142 .bDescriptorSubType = UVC_VS_INPUT_HEADER, 143 .bNumFormats = 2, 144 .wTotalLength = 0, /* dynamic */ 145 .bEndpointAddress = 0, /* dynamic */ 146 .bmInfo = 0, 147 .bTerminalLink = 3, 148 .bStillCaptureMethod = 0, 149 .bTriggerSupport = 0, 150 .bTriggerUsage = 0, 151 .bControlSize = 1, 152 .bmaControls[0][0] = 0, 153 .bmaControls[1][0] = 4, 154}; 155 156static const struct uvc_format_uncompressed uvc_format_yuv = { 157 .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE, 158 .bDescriptorType = USB_DT_CS_INTERFACE, 159 .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, 160 .bFormatIndex = 1, 161 .bNumFrameDescriptors = 2, 162 .guidFormat = 163 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 164 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, 165 .bBitsPerPixel = 16, 166 .bDefaultFrameIndex = 1, 167 .bAspectRatioX = 0, 168 .bAspectRatioY = 0, 169 .bmInterfaceFlags = 0, 170 .bCopyProtect = 0, 171}; 172 173DECLARE_UVC_FRAME_UNCOMPRESSED(1); 174DECLARE_UVC_FRAME_UNCOMPRESSED(3); 175 176static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = { 177 .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3), 178 .bDescriptorType = USB_DT_CS_INTERFACE, 179 .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, 180 .bFrameIndex = 1, 181 .bmCapabilities = 0, 182 .wWidth = cpu_to_le16(640), 183 .wHeight = cpu_to_le16(360), 184 .dwMinBitRate = cpu_to_le32(18432000), 185 .dwMaxBitRate = cpu_to_le32(55296000), 186 .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), 187 .dwDefaultFrameInterval = cpu_to_le32(666666), 188 .bFrameIntervalType = 3, 189 .dwFrameInterval[0] = cpu_to_le32(666666), 190 .dwFrameInterval[1] = cpu_to_le32(1000000), 191 .dwFrameInterval[2] = cpu_to_le32(5000000), 192}; 193 194static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = { 195 .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), 196 .bDescriptorType = USB_DT_CS_INTERFACE, 197 .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, 198 .bFrameIndex = 2, 199 .bmCapabilities = 0, 200 .wWidth = cpu_to_le16(1280), 201 .wHeight = cpu_to_le16(720), 202 .dwMinBitRate = cpu_to_le32(29491200), 203 .dwMaxBitRate = cpu_to_le32(29491200), 204 .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), 205 .dwDefaultFrameInterval = cpu_to_le32(5000000), 206 .bFrameIntervalType = 1, 207 .dwFrameInterval[0] = cpu_to_le32(5000000), 208}; 209 210static const struct uvc_format_mjpeg uvc_format_mjpg = { 211 .bLength = UVC_DT_FORMAT_MJPEG_SIZE, 212 .bDescriptorType = USB_DT_CS_INTERFACE, 213 .bDescriptorSubType = UVC_VS_FORMAT_MJPEG, 214 .bFormatIndex = 2, 215 .bNumFrameDescriptors = 2, 216 .bmFlags = 0, 217 .bDefaultFrameIndex = 1, 218 .bAspectRatioX = 0, 219 .bAspectRatioY = 0, 220 .bmInterfaceFlags = 0, 221 .bCopyProtect = 0, 222}; 223 224DECLARE_UVC_FRAME_MJPEG(1); 225DECLARE_UVC_FRAME_MJPEG(3); 226 227static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { 228 .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), 229 .bDescriptorType = USB_DT_CS_INTERFACE, 230 .bDescriptorSubType = UVC_VS_FRAME_MJPEG, 231 .bFrameIndex = 1, 232 .bmCapabilities = 0, 233 .wWidth = cpu_to_le16(640), 234 .wHeight = cpu_to_le16(360), 235 .dwMinBitRate = cpu_to_le32(18432000), 236 .dwMaxBitRate = cpu_to_le32(55296000), 237 .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), 238 .dwDefaultFrameInterval = cpu_to_le32(666666), 239 .bFrameIntervalType = 3, 240 .dwFrameInterval[0] = cpu_to_le32(666666), 241 .dwFrameInterval[1] = cpu_to_le32(1000000), 242 .dwFrameInterval[2] = cpu_to_le32(5000000), 243}; 244 245static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { 246 .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), 247 .bDescriptorType = USB_DT_CS_INTERFACE, 248 .bDescriptorSubType = UVC_VS_FRAME_MJPEG, 249 .bFrameIndex = 2, 250 .bmCapabilities = 0, 251 .wWidth = cpu_to_le16(1280), 252 .wHeight = cpu_to_le16(720), 253 .dwMinBitRate = cpu_to_le32(29491200), 254 .dwMaxBitRate = cpu_to_le32(29491200), 255 .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), 256 .dwDefaultFrameInterval = cpu_to_le32(5000000), 257 .bFrameIntervalType = 1, 258 .dwFrameInterval[0] = cpu_to_le32(5000000), 259}; 260 261static const struct uvc_color_matching_descriptor uvc_color_matching = { 262 .bLength = UVC_DT_COLOR_MATCHING_SIZE, 263 .bDescriptorType = USB_DT_CS_INTERFACE, 264 .bDescriptorSubType = UVC_VS_COLORFORMAT, 265 .bColorPrimaries = 1, 266 .bTransferCharacteristics = 1, 267 .bMatrixCoefficients = 4, 268}; 269 270static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = { 271 (const struct uvc_descriptor_header *) &uvc_control_header, 272 (const struct uvc_descriptor_header *) &uvc_camera_terminal, 273 (const struct uvc_descriptor_header *) &uvc_processing, 274 (const struct uvc_descriptor_header *) &uvc_output_terminal, 275 NULL, 276}; 277 278static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { 279 (const struct uvc_descriptor_header *) &uvc_control_header, 280 (const struct uvc_descriptor_header *) &uvc_camera_terminal, 281 (const struct uvc_descriptor_header *) &uvc_processing, 282 (const struct uvc_descriptor_header *) &uvc_output_terminal, 283 NULL, 284}; 285 286static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = { 287 (const struct uvc_descriptor_header *) &uvc_input_header, 288 (const struct uvc_descriptor_header *) &uvc_format_yuv, 289 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 290 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 291 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 292 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 293 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 294 (const struct uvc_descriptor_header *) &uvc_color_matching, 295 NULL, 296}; 297 298static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { 299 (const struct uvc_descriptor_header *) &uvc_input_header, 300 (const struct uvc_descriptor_header *) &uvc_format_yuv, 301 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 302 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 303 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 304 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 305 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 306 (const struct uvc_descriptor_header *) &uvc_color_matching, 307 NULL, 308}; 309 310static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { 311 (const struct uvc_descriptor_header *) &uvc_input_header, 312 (const struct uvc_descriptor_header *) &uvc_format_yuv, 313 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 314 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 315 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 316 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 317 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 318 (const struct uvc_descriptor_header *) &uvc_color_matching, 319 NULL, 320}; 321 322/* -------------------------------------------------------------------------- 323 * USB configuration 324 */ 325 326static int __init 327webcam_config_bind(struct usb_configuration *c) 328{ 329 return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls, 330 uvc_fs_streaming_cls, uvc_hs_streaming_cls, 331 uvc_ss_streaming_cls); 332} 333 334static struct usb_configuration webcam_config_driver = { 335 .label = webcam_config_label, 336 .bConfigurationValue = 1, 337 .iConfiguration = 0, /* dynamic */ 338 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 339 .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, 340}; 341 342static int /* __init_or_exit */ 343webcam_unbind(struct usb_composite_dev *cdev) 344{ 345 return 0; 346} 347 348static int __init 349webcam_bind(struct usb_composite_dev *cdev) 350{ 351 int ret; 352 353 /* Allocate string descriptor numbers ... note that string contents 354 * can be overridden by the composite_dev glue. 355 */ 356 ret = usb_string_ids_tab(cdev, webcam_strings); 357 if (ret < 0) 358 goto error; 359 webcam_device_descriptor.iManufacturer = 360 webcam_strings[USB_GADGET_MANUFACTURER_IDX].id; 361 webcam_device_descriptor.iProduct = 362 webcam_strings[USB_GADGET_PRODUCT_IDX].id; 363 webcam_config_driver.iConfiguration = 364 webcam_strings[STRING_DESCRIPTION_IDX].id; 365 366 /* Register our configuration. */ 367 if ((ret = usb_add_config(cdev, &webcam_config_driver, 368 webcam_config_bind)) < 0) 369 goto error; 370 371 usb_composite_overwrite_options(cdev, &coverwrite); 372 INFO(cdev, "Webcam Video Gadget\n"); 373 return 0; 374 375error: 376 webcam_unbind(cdev); 377 return ret; 378} 379 380/* -------------------------------------------------------------------------- 381 * Driver 382 */ 383 384static __refdata struct usb_composite_driver webcam_driver = { 385 .name = "g_webcam", 386 .dev = &webcam_device_descriptor, 387 .strings = webcam_device_strings, 388 .max_speed = USB_SPEED_SUPER, 389 .bind = webcam_bind, 390 .unbind = webcam_unbind, 391}; 392 393static int __init 394webcam_init(void) 395{ 396 return usb_composite_probe(&webcam_driver); 397} 398 399static void __exit 400webcam_cleanup(void) 401{ 402 usb_composite_unregister(&webcam_driver); 403} 404 405module_init(webcam_init); 406module_exit(webcam_cleanup); 407 408MODULE_AUTHOR("Laurent Pinchart"); 409MODULE_DESCRIPTION("Webcam Video Gadget"); 410MODULE_LICENSE("GPL"); 411MODULE_VERSION("0.1.0"); 412