root/drivers/usb/gadget/legacy/webcam.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. webcam_config_bind
  2. webcam_unbind
  3. webcam_bind

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

/* [<][>][^][v][top][bottom][index][help] */