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/module.h> 16#include <linux/usb/video.h> 17 18#include "u_uvc.h" 19 20USB_GADGET_COMPOSITE_OPTIONS(); 21 22/*-------------------------------------------------------------------------*/ 23 24/* module parameters specific to the Video streaming endpoint */ 25static unsigned int streaming_interval = 1; 26module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); 27MODULE_PARM_DESC(streaming_interval, "1 - 16"); 28 29static unsigned int streaming_maxpacket = 1024; 30module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); 31MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); 32 33static unsigned int streaming_maxburst; 34module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); 35MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); 36 37static unsigned int trace; 38module_param(trace, uint, S_IRUGO|S_IWUSR); 39MODULE_PARM_DESC(trace, "Trace level bitmask"); 40/* -------------------------------------------------------------------------- 41 * Device descriptor 42 */ 43 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 */ 47 48static char webcam_vendor_label[] = "Linux Foundation"; 49static char webcam_product_label[] = "Webcam gadget"; 50static char webcam_config_label[] = "Video"; 51 52/* string IDs are assigned dynamically */ 53 54#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX 55 56static 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, 61 { } 62}; 63 64static struct usb_gadget_strings webcam_stringtab = { 65 .language = 0x0409, /* en-us */ 66 .strings = webcam_strings, 67}; 68 69static struct usb_gadget_strings *webcam_device_strings[] = { 70 &webcam_stringtab, 71 NULL, 72}; 73 74static struct usb_function_instance *fi_uvc; 75static struct usb_function *f_uvc; 76 77static struct usb_device_descriptor webcam_device_descriptor = { 78 .bLength = USB_DT_DEVICE_SIZE, 79 .bDescriptorType = USB_DT_DEVICE, 80 .bcdUSB = cpu_to_le16(0x0200), 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 */ 92}; 93 94DECLARE_UVC_HEADER_DESCRIPTOR(1); 95 96static 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 */ 105}; 106 107static 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, 111 .bTerminalID = 1, 112 .wTerminalType = cpu_to_le16(0x0201), 113 .bAssocTerminal = 0, 114 .iTerminal = 0, 115 .wObjectiveFocalLengthMin = cpu_to_le16(0), 116 .wObjectiveFocalLengthMax = cpu_to_le16(0), 117 .wOcularFocalLength = cpu_to_le16(0), 118 .bControlSize = 3, 119 .bmControls[0] = 2, 120 .bmControls[1] = 0, 121 .bmControls[2] = 0, 122}; 123 124static 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, 128 .bUnitID = 2, 129 .bSourceID = 1, 130 .wMaxMultiplier = cpu_to_le16(16*1024), 131 .bControlSize = 2, 132 .bmControls[0] = 1, 133 .bmControls[1] = 0, 134 .iProcessing = 0, 135}; 136 137static 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, 141 .bTerminalID = 3, 142 .wTerminalType = cpu_to_le16(0x0101), 143 .bAssocTerminal = 0, 144 .bSourceID = 2, 145 .iTerminal = 0, 146}; 147 148DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); 149 150static 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, 154 .bNumFormats = 2, 155 .wTotalLength = 0, /* dynamic */ 156 .bEndpointAddress = 0, /* dynamic */ 157 .bmInfo = 0, 158 .bTerminalLink = 3, 159 .bStillCaptureMethod = 0, 160 .bTriggerSupport = 0, 161 .bTriggerUsage = 0, 162 .bControlSize = 1, 163 .bmaControls[0][0] = 0, 164 .bmaControls[1][0] = 4, 165}; 166 167static 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, 171 .bFormatIndex = 1, 172 .bNumFrameDescriptors = 2, 173 .guidFormat = 174 { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 175 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, 176 .bBitsPerPixel = 16, 177 .bDefaultFrameIndex = 1, 178 .bAspectRatioX = 0, 179 .bAspectRatioY = 0, 180 .bmInterfaceFlags = 0, 181 .bCopyProtect = 0, 182}; 183 184DECLARE_UVC_FRAME_UNCOMPRESSED(1); 185DECLARE_UVC_FRAME_UNCOMPRESSED(3); 186 187static 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, 191 .bFrameIndex = 1, 192 .bmCapabilities = 0, 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), 203}; 204 205static 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, 209 .bFrameIndex = 2, 210 .bmCapabilities = 0, 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), 219}; 220 221static 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, 225 .bFormatIndex = 2, 226 .bNumFrameDescriptors = 2, 227 .bmFlags = 0, 228 .bDefaultFrameIndex = 1, 229 .bAspectRatioX = 0, 230 .bAspectRatioY = 0, 231 .bmInterfaceFlags = 0, 232 .bCopyProtect = 0, 233}; 234 235DECLARE_UVC_FRAME_MJPEG(1); 236DECLARE_UVC_FRAME_MJPEG(3); 237 238static 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, 242 .bFrameIndex = 1, 243 .bmCapabilities = 0, 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), 254}; 255 256static 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, 260 .bFrameIndex = 2, 261 .bmCapabilities = 0, 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), 270}; 271 272static 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, 279}; 280 281static 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, 286 NULL, 287}; 288 289static 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, 294 NULL, 295}; 296 297static 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, 306 NULL, 307}; 308 309static 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, 318 NULL, 319}; 320 321static 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, 330 NULL, 331}; 332 333/* -------------------------------------------------------------------------- 334 * USB configuration 335 */ 336 337static int 338webcam_config_bind(struct usb_configuration *c) 339{ 340 int status = 0; 341 342 f_uvc = usb_get_function(fi_uvc); 343 if (IS_ERR(f_uvc)) 344 return PTR_ERR(f_uvc); 345 346 status = usb_add_function(c, f_uvc); 347 if (status < 0) 348 usb_put_function(f_uvc); 349 350 return status; 351} 352 353static 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, 359}; 360 361static int 362webcam_unbind(struct usb_composite_dev *cdev) 363{ 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); 368 return 0; 369} 370 371static int 372webcam_bind(struct usb_composite_dev *cdev) 373{ 374 struct f_uvc_opts *uvc_opts; 375 int ret; 376 377 fi_uvc = usb_get_function_instance("uvc"); 378 if (IS_ERR(fi_uvc)) 379 return PTR_ERR(fi_uvc); 380 381 uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst); 382 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); 387 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; 393 394 /* Allocate string descriptor numbers ... note that string contents 395 * can be overridden by the composite_dev glue. 396 */ 397 ret = usb_string_ids_tab(cdev, webcam_strings); 398 if (ret < 0) 399 goto error; 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; 406 407 /* Register our configuration. */ 408 if ((ret = usb_add_config(cdev, &webcam_config_driver, 409 webcam_config_bind)) < 0) 410 goto error; 411 412 usb_composite_overwrite_options(cdev, &coverwrite); 413 INFO(cdev, "Webcam Video Gadget\n"); 414 return 0; 415 416error: 417 usb_put_function_instance(fi_uvc); 418 return ret; 419} 420 421/* -------------------------------------------------------------------------- 422 * Driver 423 */ 424 425static struct usb_composite_driver webcam_driver = { 426 .name = "g_webcam", 427 .dev = &webcam_device_descriptor, 428 .strings = webcam_device_strings, 429 .max_speed = USB_SPEED_SUPER, 430 .bind = webcam_bind, 431 .unbind = webcam_unbind, 432}; 433 434module_usb_composite_driver(webcam_driver); 435 436MODULE_AUTHOR("Laurent Pinchart"); 437MODULE_DESCRIPTION("Webcam Video Gadget"); 438MODULE_LICENSE("GPL"); 439MODULE_VERSION("0.1.0"); 440 441