linux/drivers/usb/gadget/webcam.c
<<
>>
Prefs
   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 "composite.c"
  27#include "usbstring.c"
  28#include "config.c"
  29#include "epautoconf.c"
  30
  31#include "uvc_queue.c"
  32#include "uvc_video.c"
  33#include "uvc_v4l2.c"
  34#include "f_uvc.c"
  35
  36/* --------------------------------------------------------------------------
  37 * Device descriptor
  38 */
  39
  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 */
  43
  44static char webcam_vendor_label[] = "Linux Foundation";
  45static char webcam_product_label[] = "Webcam gadget";
  46static char webcam_config_label[] = "Video";
  47
  48/* string IDs are assigned dynamically */
  49
  50#define STRING_MANUFACTURER_IDX         0
  51#define STRING_PRODUCT_IDX              1
  52#define STRING_DESCRIPTION_IDX          2
  53
  54static 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,
  58        {  }
  59};
  60
  61static struct usb_gadget_strings webcam_stringtab = {
  62        .language = 0x0409,     /* en-us */
  63        .strings = webcam_strings,
  64};
  65
  66static struct usb_gadget_strings *webcam_device_strings[] = {
  67        &webcam_stringtab,
  68        NULL,
  69};
  70
  71static 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 */
  86};
  87
  88DECLARE_UVC_HEADER_DESCRIPTOR(1);
  89
  90static 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 */
  99};
 100
 101static 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,
 105        .bTerminalID            = 1,
 106        .wTerminalType          = cpu_to_le16(0x0201),
 107        .bAssocTerminal         = 0,
 108        .iTerminal              = 0,
 109        .wObjectiveFocalLengthMin       = cpu_to_le16(0),
 110        .wObjectiveFocalLengthMax       = cpu_to_le16(0),
 111        .wOcularFocalLength             = cpu_to_le16(0),
 112        .bControlSize           = 3,
 113        .bmControls[0]          = 2,
 114        .bmControls[1]          = 0,
 115        .bmControls[2]          = 0,
 116};
 117
 118static 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,
 122        .bUnitID                = 2,
 123        .bSourceID              = 1,
 124        .wMaxMultiplier         = cpu_to_le16(16*1024),
 125        .bControlSize           = 2,
 126        .bmControls[0]          = 1,
 127        .bmControls[1]          = 0,
 128        .iProcessing            = 0,
 129};
 130
 131static 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,
 135        .bTerminalID            = 3,
 136        .wTerminalType          = cpu_to_le16(0x0101),
 137        .bAssocTerminal         = 0,
 138        .bSourceID              = 2,
 139        .iTerminal              = 0,
 140};
 141
 142DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
 143
 144static 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,
 148        .bNumFormats            = 2,
 149        .wTotalLength           = 0, /* dynamic */
 150        .bEndpointAddress       = 0, /* dynamic */
 151        .bmInfo                 = 0,
 152        .bTerminalLink          = 3,
 153        .bStillCaptureMethod    = 0,
 154        .bTriggerSupport        = 0,
 155        .bTriggerUsage          = 0,
 156        .bControlSize           = 1,
 157        .bmaControls[0][0]      = 0,
 158        .bmaControls[1][0]      = 4,
 159};
 160
 161static 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,
 165        .bFormatIndex           = 1,
 166        .bNumFrameDescriptors   = 2,
 167        .guidFormat             =
 168                { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
 169                 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
 170        .bBitsPerPixel          = 16,
 171        .bDefaultFrameIndex     = 1,
 172        .bAspectRatioX          = 0,
 173        .bAspectRatioY          = 0,
 174        .bmInterfaceFlags       = 0,
 175        .bCopyProtect           = 0,
 176};
 177
 178DECLARE_UVC_FRAME_UNCOMPRESSED(1);
 179DECLARE_UVC_FRAME_UNCOMPRESSED(3);
 180
 181static 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,
 185        .bFrameIndex            = 1,
 186        .bmCapabilities         = 0,
 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),
 197};
 198
 199static 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,
 203        .bFrameIndex            = 2,
 204        .bmCapabilities         = 0,
 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),
 213};
 214
 215static 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,
 219        .bFormatIndex           = 2,
 220        .bNumFrameDescriptors   = 2,
 221        .bmFlags                = 0,
 222        .bDefaultFrameIndex     = 1,
 223        .bAspectRatioX          = 0,
 224        .bAspectRatioY          = 0,
 225        .bmInterfaceFlags       = 0,
 226        .bCopyProtect           = 0,
 227};
 228
 229DECLARE_UVC_FRAME_MJPEG(1);
 230DECLARE_UVC_FRAME_MJPEG(3);
 231
 232static 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,
 236        .bFrameIndex            = 1,
 237        .bmCapabilities         = 0,
 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),
 248};
 249
 250static 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,
 254        .bFrameIndex            = 2,
 255        .bmCapabilities         = 0,
 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),
 264};
 265
 266static 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,
 273};
 274
 275static 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,
 280        NULL,
 281};
 282
 283static 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,
 292        NULL,
 293};
 294
 295static 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,
 304        NULL,
 305};
 306
 307/* --------------------------------------------------------------------------
 308 * USB configuration
 309 */
 310
 311static int __init
 312webcam_config_bind(struct usb_configuration *c)
 313{
 314        return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
 315                               uvc_hs_streaming_cls);
 316}
 317
 318static 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,
 324};
 325
 326static int /* __init_or_exit */
 327webcam_unbind(struct usb_composite_dev *cdev)
 328{
 329        return 0;
 330}
 331
 332static int __init
 333webcam_bind(struct usb_composite_dev *cdev)
 334{
 335        int ret;
 336
 337        /* Allocate string descriptor numbers ... note that string contents
 338         * can be overridden by the composite_dev glue.
 339         */
 340        if ((ret = usb_string_id(cdev)) < 0)
 341                goto error;
 342        webcam_strings[STRING_MANUFACTURER_IDX].id = ret;
 343        webcam_device_descriptor.iManufacturer = ret;
 344
 345        if ((ret = usb_string_id(cdev)) < 0)
 346                goto error;
 347        webcam_strings[STRING_PRODUCT_IDX].id = ret;
 348        webcam_device_descriptor.iProduct = ret;
 349
 350        if ((ret = usb_string_id(cdev)) < 0)
 351                goto error;
 352        webcam_strings[STRING_DESCRIPTION_IDX].id = ret;
 353        webcam_config_driver.iConfiguration = ret;
 354
 355        /* Register our configuration. */
 356        if ((ret = usb_add_config(cdev, &webcam_config_driver,
 357                                        webcam_config_bind)) < 0)
 358                goto error;
 359
 360        INFO(cdev, "Webcam Video Gadget\n");
 361        return 0;
 362
 363error:
 364        webcam_unbind(cdev);
 365        return ret;
 366}
 367
 368/* --------------------------------------------------------------------------
 369 * Driver
 370 */
 371
 372static struct usb_composite_driver webcam_driver = {
 373        .name           = "g_webcam",
 374        .dev            = &webcam_device_descriptor,
 375        .strings        = webcam_device_strings,
 376        .max_speed      = USB_SPEED_HIGH,
 377        .unbind         = webcam_unbind,
 378};
 379
 380static int __init
 381webcam_init(void)
 382{
 383        return usb_composite_probe(&webcam_driver, webcam_bind);
 384}
 385
 386static void __exit
 387webcam_cleanup(void)
 388{
 389        usb_composite_unregister(&webcam_driver);
 390}
 391
 392module_init(webcam_init);
 393module_exit(webcam_cleanup);
 394
 395MODULE_AUTHOR("Laurent Pinchart");
 396MODULE_DESCRIPTION("Webcam Video Gadget");
 397MODULE_LICENSE("GPL");
 398MODULE_VERSION("0.1.0");
 399
 400