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(0x0110), 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 .bmVideoStandards = 0, 129 }; 130 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, 135 .bTerminalID = 3, 136 .wTerminalType = cpu_to_le16(0x0101), 137 .bAssocTerminal = 0, 138 .bSourceID = 2, 139 .iTerminal = 0, 140 }; 141 142 DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); 143 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, 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 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, 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 178 DECLARE_UVC_FRAME_UNCOMPRESSED(1); 179 DECLARE_UVC_FRAME_UNCOMPRESSED(3); 180 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, 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 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, 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 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, 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 229 DECLARE_UVC_FRAME_MJPEG(1); 230 DECLARE_UVC_FRAME_MJPEG(3); 231 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, 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 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, 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 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, 273 }; 274 275 static const struct uvc_descriptor_header * const uvc_fs_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 283 static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { 284 (const struct uvc_descriptor_header *) &uvc_control_header, 285 (const struct uvc_descriptor_header *) &uvc_camera_terminal, 286 (const struct uvc_descriptor_header *) &uvc_processing, 287 (const struct uvc_descriptor_header *) &uvc_output_terminal, 288 NULL, 289 }; 290 291 static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = { 292 (const struct uvc_descriptor_header *) &uvc_input_header, 293 (const struct uvc_descriptor_header *) &uvc_format_yuv, 294 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 295 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 296 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 297 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 298 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 299 (const struct uvc_descriptor_header *) &uvc_color_matching, 300 NULL, 301 }; 302 303 static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { 304 (const struct uvc_descriptor_header *) &uvc_input_header, 305 (const struct uvc_descriptor_header *) &uvc_format_yuv, 306 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 307 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 308 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 309 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 310 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 311 (const struct uvc_descriptor_header *) &uvc_color_matching, 312 NULL, 313 }; 314 315 static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { 316 (const struct uvc_descriptor_header *) &uvc_input_header, 317 (const struct uvc_descriptor_header *) &uvc_format_yuv, 318 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, 319 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, 320 (const struct uvc_descriptor_header *) &uvc_format_mjpg, 321 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, 322 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, 323 (const struct uvc_descriptor_header *) &uvc_color_matching, 324 NULL, 325 }; 326 327 /* -------------------------------------------------------------------------- 328 * USB configuration 329 */ 330 331 static int 332 webcam_config_bind(struct usb_configuration *c) 333 { 334 int status = 0; 335 336 f_uvc = usb_get_function(fi_uvc); 337 if (IS_ERR(f_uvc)) 338 return PTR_ERR(f_uvc); 339 340 status = usb_add_function(c, f_uvc); 341 if (status < 0) 342 usb_put_function(f_uvc); 343 344 return status; 345 } 346 347 static struct usb_configuration webcam_config_driver = { 348 .label = webcam_config_label, 349 .bConfigurationValue = 1, 350 .iConfiguration = 0, /* dynamic */ 351 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 352 .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, 353 }; 354 355 static int 356 webcam_unbind(struct usb_composite_dev *cdev) 357 { 358 if (!IS_ERR_OR_NULL(f_uvc)) 359 usb_put_function(f_uvc); 360 if (!IS_ERR_OR_NULL(fi_uvc)) 361 usb_put_function_instance(fi_uvc); 362 return 0; 363 } 364 365 static int 366 webcam_bind(struct usb_composite_dev *cdev) 367 { 368 struct f_uvc_opts *uvc_opts; 369 int ret; 370 371 fi_uvc = usb_get_function_instance("uvc"); 372 if (IS_ERR(fi_uvc)) 373 return PTR_ERR(fi_uvc); 374 375 uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst); 376 377 uvc_opts->streaming_interval = streaming_interval; 378 uvc_opts->streaming_maxpacket = streaming_maxpacket; 379 uvc_opts->streaming_maxburst = streaming_maxburst; 380 381 uvc_opts->fs_control = uvc_fs_control_cls; 382 uvc_opts->ss_control = uvc_ss_control_cls; 383 uvc_opts->fs_streaming = uvc_fs_streaming_cls; 384 uvc_opts->hs_streaming = uvc_hs_streaming_cls; 385 uvc_opts->ss_streaming = uvc_ss_streaming_cls; 386 387 /* Allocate string descriptor numbers ... note that string contents 388 * can be overridden by the composite_dev glue. 389 */ 390 ret = usb_string_ids_tab(cdev, webcam_strings); 391 if (ret < 0) 392 goto error; 393 webcam_device_descriptor.iManufacturer = 394 webcam_strings[USB_GADGET_MANUFACTURER_IDX].id; 395 webcam_device_descriptor.iProduct = 396 webcam_strings[USB_GADGET_PRODUCT_IDX].id; 397 webcam_config_driver.iConfiguration = 398 webcam_strings[STRING_DESCRIPTION_IDX].id; 399 400 /* Register our configuration. */ 401 if ((ret = usb_add_config(cdev, &webcam_config_driver, 402 webcam_config_bind)) < 0) 403 goto error; 404 405 usb_composite_overwrite_options(cdev, &coverwrite); 406 INFO(cdev, "Webcam Video Gadget\n"); 407 return 0; 408 409 error: 410 usb_put_function_instance(fi_uvc); 411 return ret; 412 } 413 414 /* -------------------------------------------------------------------------- 415 * Driver 416 */ 417 418 static struct usb_composite_driver webcam_driver = { 419 .name = "g_webcam", 420 .dev = &webcam_device_descriptor, 421 .strings = webcam_device_strings, 422 .max_speed = USB_SPEED_SUPER, 423 .bind = webcam_bind, 424 .unbind = webcam_unbind, 425 }; 426 427 module_usb_composite_driver(webcam_driver); 428 429 MODULE_AUTHOR("Laurent Pinchart"); 430 MODULE_DESCRIPTION("Webcam Video Gadget"); 431 MODULE_LICENSE("GPL"); 432 433