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