1 /* 2 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 3 * Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "UVCCamDevice.h" 9 10 #include <stdio.h> 11 12 #include "CamStreamingDeframer.h" 13 14 15 usb_webcam_support_descriptor kSupportedDevices[] = { 16 // ofcourse we support a generic UVC device... 17 {{ CC_VIDEO, SC_VIDEOCONTROL, 0, 0, 0 }, "USB", "Video Class", "??" }, 18 // ...whilst the following IDs were 'stolen' from a recent Linux driver: 19 {{ 0, 0, 0, 0x045e, 0x00f8, }, "Microsoft", "Lifecam NX-6000", "??" }, 20 {{ 0, 0, 0, 0x045e, 0x0723, }, "Microsoft", "Lifecam VX-7000", "??" }, 21 {{ 0, 0, 0, 0x046d, 0x08c1, }, "Logitech", "QuickCam Fusion", "??" }, 22 {{ 0, 0, 0, 0x046d, 0x08c2, }, "Logitech", "QuickCam Orbit MP", "??" }, 23 {{ 0, 0, 0, 0x046d, 0x08c3, }, "Logitech", "QuickCam Pro for Notebook", "??" }, 24 {{ 0, 0, 0, 0x046d, 0x08c5, }, "Logitech", "QuickCam Pro 5000", "??" }, 25 {{ 0, 0, 0, 0x046d, 0x08c6, }, "Logitech", "QuickCam OEM Dell Notebook", "??" }, 26 {{ 0, 0, 0, 0x046d, 0x08c7, }, "Logitech", "QuickCam OEM Cisco VT Camera II", "??" }, 27 {{ 0, 0, 0, 0x05ac, 0x8501, }, "Apple", "Built-In iSight", "??" }, 28 {{ 0, 0, 0, 0x05e3, 0x0505, }, "Genesys Logic", "USB 2.0 PC Camera", "??" }, 29 {{ 0, 0, 0, 0x0e8d, 0x0004, }, "N/A", "MT6227", "??" }, 30 {{ 0, 0, 0, 0x174f, 0x5212, }, "Syntek", "(HP Spartan)", "??" }, 31 {{ 0, 0, 0, 0x174f, 0x5931, }, "Syntek", "(Samsung Q310)", "??" }, 32 {{ 0, 0, 0, 0x174f, 0x8a31, }, "Syntek", "Asus F9SG", "??" }, 33 {{ 0, 0, 0, 0x174f, 0x8a33, }, "Syntek", "Asus U3S", "??" }, 34 {{ 0, 0, 0, 0x17ef, 0x480b, }, "N/A", "Lenovo Thinkpad SL500", "??" }, 35 {{ 0, 0, 0, 0x18cd, 0xcafe, }, "Ecamm", "Pico iMage", "??" }, 36 {{ 0, 0, 0, 0x19ab, 0x1000, }, "Bodelin", "ProScopeHR", "??" }, 37 {{ 0, 0, 0, 0x1c4f, 0x3000, }, "SiGma Micro", "USB Web Camera", "??" }, 38 {{ 0, 0, 0, 0, 0}, NULL, NULL, NULL } 39 }; 40 41 /* Table 2-1 Compression Formats of USB Video Payload Uncompressed */ 42 usbvc_guid kYUY2Guid = {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 43 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 44 usbvc_guid kNV12Guid = {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 45 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 46 47 static void 48 print_guid(const usbvc_guid guid) 49 { 50 if (!memcmp(guid, kYUY2Guid, sizeof(usbvc_guid))) 51 printf("YUY2"); 52 else if (!memcmp(guid, kNV12Guid, sizeof(usbvc_guid))) 53 printf("NV12"); 54 else { 55 printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" 56 "%02x:%02x:%02x:%02x", guid[0], guid[1], guid[2], guid[3], guid[4], 57 guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], 58 guid[12], guid[13], guid[14], guid[15]); 59 } 60 } 61 62 63 // TODO dumb sof_marks and eof_marks 64 static const uint8 sof_mark_1[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00 }; 65 static const uint8 sof_mark_2[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01 }; 66 static const uint8 *sof_marks[] = { sof_mark_1, sof_mark_2 }; 67 68 static const uint8 eof_mark_1[] = { 0x00, 0x00, 0x00, 0x00 }; 69 static const uint8 eof_mark_2[] = { 0x40, 0x00, 0x00, 0x00 }; 70 static const uint8 eof_mark_3[] = { 0x80, 0x00, 0x00, 0x00 }; 71 static const uint8 eof_mark_4[] = { 0xc0, 0x00, 0x00, 0x00 }; 72 static const uint8 *eof_marks[] = { eof_mark_1, eof_mark_2, eof_mark_3, eof_mark_4 }; 73 74 75 76 UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) 77 : CamDevice(_addon, _device), 78 fHeaderDescriptor(NULL), 79 fInterruptIn(NULL) 80 { 81 fDeframer = new CamStreamingDeframer(this); 82 fDeframer->RegisterSOFTags(sof_marks, 2, sizeof(sof_mark_1), 12); 83 fDeframer->RegisterEOFTags(eof_marks, 4, sizeof(eof_mark_1), sizeof(eof_mark_1)); 84 SetDataInput(fDeframer); 85 86 const BUSBConfiguration* config; 87 const BUSBInterface* interface; 88 usb_descriptor* generic; 89 uint8 buffer[1024]; 90 91 generic = (usb_descriptor *)buffer; 92 93 for (uint32 i = 0; i < _device->CountConfigurations(); i++) { 94 config = _device->ConfigurationAt(i); 95 _device->SetConfiguration(config); 96 for (uint32 j = 0; j < config->CountInterfaces(); j++) { 97 interface = config->InterfaceAt(j); 98 99 if (interface->Class() == CC_VIDEO && interface->Subclass() 100 == SC_VIDEOCONTROL) { 101 printf("UVCCamDevice: (%lu,%lu): Found Video Control " 102 "interface.\n", i, j); 103 104 // look for class specific interface descriptors and parse them 105 for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 106 sizeof(buffer)) == B_OK; k++) { 107 if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 108 | USB_DESCRIPTOR_INTERFACE)) 109 continue; 110 fControlIndex = interface->Index(); 111 _ParseVideoControl((const usbvc_class_descriptor*)generic, 112 generic->generic.length); 113 } 114 115 for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 116 const BUSBEndpoint *e = interface->EndpointAt(i); 117 if (e && e->IsInterrupt() && e->IsInput()) { 118 fInterruptIn = e; 119 break; 120 } 121 } 122 fInitStatus = B_OK; 123 } else if (interface->Class() == CC_VIDEO && interface->Subclass() 124 == SC_VIDEOSTREAMING) { 125 printf("UVCCamDevice: (%lu,%lu): Found Video Streaming " 126 "interface.\n", i, j); 127 128 // look for class specific interface descriptors and parse them 129 for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 130 sizeof(buffer)) == B_OK; k++) { 131 if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 132 | USB_DESCRIPTOR_INTERFACE)) 133 continue; 134 fStreamingIndex = interface->Index(); 135 _ParseVideoStreaming((const usbvc_class_descriptor*)generic, 136 generic->generic.length); 137 } 138 139 for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 140 const BUSBEndpoint *e = interface->EndpointAt(i); 141 if (e && e->IsIsochronous() && e->IsInput()) { 142 fIsoIn = e; 143 break; 144 } 145 } 146 } 147 } 148 } 149 } 150 151 152 UVCCamDevice::~UVCCamDevice() 153 { 154 } 155 156 157 void 158 UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor, 159 size_t len) 160 { 161 switch(_descriptor->descriptorSubtype) { 162 case VS_INPUT_HEADER: 163 { 164 const usbvc_input_header_descriptor* descriptor = 165 (const usbvc_input_header_descriptor*)_descriptor; 166 printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor->numFormats, 167 descriptor->endpointAddress); 168 if (descriptor->info & 1) 169 printf("\tDynamic Format Change supported\n"); 170 printf("\toutput terminal id=%d\n", descriptor->terminalLink); 171 printf("\tstill capture method=%d\n", descriptor->stillCaptureMethod); 172 if (descriptor->triggerSupport) { 173 printf("\ttrigger button fixed to still capture=%s\n", 174 descriptor->triggerUsage ? "no" : "yes"); 175 } 176 const uint8 *controls = descriptor->controls; 177 for (uint8 i = 0; i < descriptor->numFormats; i++, 178 controls += descriptor->controlSize) { 179 printf("\tfmt%d: %s %s %s %s - %s %s\n", i, 180 (*controls & 1) ? "wKeyFrameRate" : "", 181 (*controls & 2) ? "wPFrameRate" : "", 182 (*controls & 4) ? "wCompQuality" : "", 183 (*controls & 8) ? "wCompWindowSize" : "", 184 (*controls & 16) ? "<Generate Key Frame>" : "", 185 (*controls & 32) ? "<Update Frame Segment>" : ""); 186 } 187 break; 188 } 189 case VS_FORMAT_UNCOMPRESSED: 190 { 191 const usbvc_format_descriptor* descriptor = 192 (const usbvc_format_descriptor*)_descriptor; 193 printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=", 194 descriptor->formatIndex, descriptor->numFrameDescriptors); 195 print_guid(descriptor->uncompressed.format); 196 printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 197 descriptor->uncompressed.bytesPerPixel, 198 descriptor->uncompressed.defaultFrameIndex, 199 descriptor->uncompressed.aspectRatioX, 200 descriptor->uncompressed.aspectRatioY); 201 printf("\tbmInterlaceFlags:\n"); 202 if (descriptor->uncompressed.interlaceFlags & 1) 203 printf("\tInterlaced stream or variable\n"); 204 printf("\t%d fields per frame\n", 205 (descriptor->uncompressed.interlaceFlags & 2) ? 1 : 2); 206 if (descriptor->uncompressed.interlaceFlags & 4) 207 printf("\tField 1 first\n"); 208 printf("\tField Pattern: "); 209 switch((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) { 210 case 0: printf("Field 1 only\n"); break; 211 case 1: printf("Field 2 only\n"); break; 212 case 2: printf("Regular pattern of fields 1 and 2\n"); break; 213 case 3: printf("Random pattern of fields 1 and 2\n"); break; 214 } 215 if (descriptor->uncompressed.copyProtect) 216 printf("\tRestrict duplication\n"); 217 break; 218 } 219 case VS_FRAME_MJPEG: 220 printf("VS_FRAME_MJPEG:"); // fall through 221 case VS_FRAME_UNCOMPRESSED: 222 { 223 if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED) 224 printf("VS_FRAME_UNCOMPRESSED:"); 225 const usbvc_frame_descriptor* descriptor = 226 (const usbvc_frame_descriptor*)_descriptor; 227 printf("\tbFrameIdx=%d,stillsupported=%s," 228 "fixedframerate=%s\n", descriptor->frameIndex, 229 (descriptor->capabilities & 1) ? "yes" : "no", 230 (descriptor->capabilities & 2) ? "yes" : "no"); 231 printf("\twidth=%u,height=%u,min/max bitrate=%lu/%lu, maxbuf=%lu\n", 232 descriptor->width, descriptor->height, 233 descriptor->minBitRate, descriptor->maxBitRate, 234 descriptor->maxVideoFrameBufferSize); 235 printf("\tdefault frame interval: %lu, #intervals(0=cont): %d\n", 236 descriptor->defaultFrameInterval, descriptor->frameIntervalType); 237 if (descriptor->frameIntervalType == 0) { 238 printf("min/max frame interval=%lu/%lu, step=%lu\n", 239 descriptor->continuous.minFrameInterval, 240 descriptor->continuous.maxFrameInterval, 241 descriptor->continuous.frameIntervalStep); 242 } else for (uint8 i = 0; i < descriptor->frameIntervalType; i++) { 243 printf("discrete frame interval: %lu\n", 244 descriptor->discreteFrameIntervals[i]); 245 } 246 break; 247 } 248 case VS_COLORFORMAT: 249 { 250 const usbvc_color_matching_descriptor* descriptor = 251 (const usbvc_color_matching_descriptor*)_descriptor; 252 printf("VS_COLORFORMAT:\n\tbColorPrimaries: "); 253 switch(descriptor->colorPrimaries) { 254 case 0: printf("Unspecified\n"); break; 255 case 1: printf("BT.709,sRGB\n"); break; 256 case 2: printf("BT.470-2(M)\n"); break; 257 case 3: printf("BT.470-2(B,G)\n"); break; 258 case 4: printf("SMPTE 170M\n"); break; 259 case 5: printf("SMPTE 240M\n"); break; 260 default: printf("Invalid (%d)\n", descriptor->colorPrimaries); 261 } 262 printf("\tbTransferCharacteristics: "); 263 switch(descriptor->transferCharacteristics) { 264 case 0: printf("Unspecified\n"); break; 265 case 1: printf("BT.709\n"); break; 266 case 2: printf("BT.470-2(M)\n"); break; 267 case 3: printf("BT.470-2(B,G)\n"); break; 268 case 4: printf("SMPTE 170M\n"); break; 269 case 5: printf("SMPTE 240M\n"); break; 270 case 6: printf("Linear (V=Lc)\n"); break; 271 case 7: printf("sRGB\n"); break; 272 default: printf("Invalid (%d)\n", 273 descriptor->transferCharacteristics); 274 } 275 printf("\tbMatrixCoefficients: "); 276 switch(descriptor->matrixCoefficients) { 277 case 0: printf("Unspecified\n"); break; 278 case 1: printf("BT.709\n"); break; 279 case 2: printf("FCC\n"); break; 280 case 3: printf("BT.470-2(B,G)\n"); break; 281 case 4: printf("SMPTE 170M (BT.601)\n"); break; 282 case 5: printf("SMPTE 240M\n"); break; 283 default: printf("Invalid (%d)\n", descriptor->matrixCoefficients); 284 } 285 break; 286 } 287 case VS_OUTPUT_HEADER: 288 { 289 const usbvc_output_header_descriptor* descriptor = 290 (const usbvc_output_header_descriptor*)_descriptor; 291 printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n", 292 descriptor->numFormats, descriptor->endpointAddress); 293 printf("\toutput terminal id=%d\n", descriptor->terminalLink); 294 const uint8 *controls = descriptor->controls; 295 for (uint8 i = 0; i < descriptor->numFormats; i++, 296 controls += descriptor->controlSize) { 297 printf("\tfmt%d: %s %s %s %s\n", i, 298 (*controls & 1) ? "wKeyFrameRate" : "", 299 (*controls & 2) ? "wPFrameRate" : "", 300 (*controls & 4) ? "wCompQuality" : "", 301 (*controls & 8) ? "wCompWindowSize" : ""); 302 } 303 break; 304 } 305 case VS_STILL_IMAGE_FRAME: 306 { 307 const usbvc_still_image_frame_descriptor* descriptor = 308 (const usbvc_still_image_frame_descriptor*)_descriptor; 309 printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d," 310 "ept=0x%x\n", descriptor->numImageSizePatterns, 311 descriptor->NumCompressionPatterns(), 312 descriptor->endpointAddress); 313 for (uint8 i = 0; i < descriptor->numImageSizePatterns; i++) { 314 printf("imageSize%d: %dx%d\n", i, 315 descriptor->imageSizePatterns[i].width, 316 descriptor->imageSizePatterns[i].height); 317 } 318 for (uint8 i = 0; i < descriptor->NumCompressionPatterns(); i++) { 319 printf("compression%d: %d\n", i, 320 descriptor->CompressionPatterns()[i]); 321 } 322 break; 323 } 324 case VS_FORMAT_MJPEG: 325 { 326 const usbvc_format_descriptor* descriptor = 327 (const usbvc_format_descriptor*)_descriptor; 328 printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n", 329 descriptor->formatIndex, descriptor->numFrameDescriptors); 330 printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 331 descriptor->mjpeg.flags, 332 descriptor->mjpeg.defaultFrameIndex, 333 descriptor->mjpeg.aspectRatioX, 334 descriptor->mjpeg.aspectRatioY); 335 printf("\tbmInterlaceFlags:\n"); 336 if (descriptor->mjpeg.interlaceFlags & 1) 337 printf("\tInterlaced stream or variable\n"); 338 printf("\t%d fields per frame\n", 339 (descriptor->mjpeg.interlaceFlags & 2) ? 1 : 2); 340 if (descriptor->mjpeg.interlaceFlags & 4) 341 printf("\tField 1 first\n"); 342 printf("\tField Pattern: "); 343 switch((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) { 344 case 0: printf("Field 1 only\n"); break; 345 case 1: printf("Field 2 only\n"); break; 346 case 2: printf("Regular pattern of fields 1 and 2\n"); break; 347 case 3: printf("Random pattern of fields 1 and 2\n"); break; 348 } 349 if (descriptor->mjpeg.copyProtect) 350 printf("\tRestrict duplication\n"); 351 break; 352 } 353 case VS_FORMAT_MPEG2TS: 354 printf("VS_FORMAT_MPEG2TS:\t\n"); 355 break; 356 case VS_FORMAT_DV: 357 printf("VS_FORMAT_DV:\t\n"); 358 break; 359 case VS_FORMAT_FRAME_BASED: 360 printf("VS_FORMAT_FRAME_BASED:\t\n"); 361 break; 362 case VS_FRAME_FRAME_BASED: 363 printf("VS_FRAME_FRAME_BASED:\t\n"); 364 break; 365 case VS_FORMAT_STREAM_BASED: 366 printf("VS_FORMAT_STREAM_BASED:\t\n"); 367 break; 368 default: 369 printf("INVALID STREAM UNIT TYPE=%d!\n", 370 _descriptor->descriptorSubtype); 371 } 372 } 373 374 375 void 376 UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor, 377 size_t len) 378 { 379 switch(_descriptor->descriptorSubtype) { 380 case VC_HEADER: 381 { 382 fHeaderDescriptor = (usbvc_interface_header_descriptor*)_descriptor; 383 printf("VC_HEADER:\tUVC v%x.%02x, clk %.5f MHz\n", 384 fHeaderDescriptor->version >> 8, 385 fHeaderDescriptor->version & 0xff, 386 fHeaderDescriptor->clockFrequency / 1000000.0); 387 for (uint8 i = 0; i < fHeaderDescriptor->numInterfacesNumbers; i++) { 388 printf("\tStreaming Interface %d\n", 389 fHeaderDescriptor->interfaceNumbers[i]); 390 } 391 break; 392 } 393 case VC_INPUT_TERMINAL: 394 { 395 const usbvc_input_terminal_descriptor* descriptor = 396 (const usbvc_input_terminal_descriptor*)_descriptor; 397 printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 398 "%d\n", descriptor->terminalID, descriptor->terminalType, 399 descriptor->associatedTerminal); 400 printf("\tDesc: %s\n", 401 fDevice->DecodeStringDescriptor(descriptor->terminal)); 402 if (descriptor->terminalType == 0x201) { 403 const usbvc_camera_terminal_descriptor* desc = 404 (const usbvc_camera_terminal_descriptor*)descriptor; 405 printf("\tObjectiveFocalLength Min/Max %d/%d\n", 406 desc->objectiveFocalLengthMin, 407 desc->objectiveFocalLengthMax); 408 printf("\tOcularFocalLength %d\n", desc->ocularFocalLength); 409 printf("\tControlSize %d\n", desc->controlSize); 410 } 411 break; 412 } 413 case VC_OUTPUT_TERMINAL: 414 { 415 const usbvc_output_terminal_descriptor* descriptor = 416 (const usbvc_output_terminal_descriptor*)_descriptor; 417 printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 418 "%d, src id=%d\n", descriptor->terminalID, 419 descriptor->terminalType, descriptor->associatedTerminal, 420 descriptor->sourceID); 421 printf("\tDesc: %s\n", 422 fDevice->DecodeStringDescriptor(descriptor->terminal)); 423 break; 424 } 425 case VC_SELECTOR_UNIT: 426 { 427 const usbvc_selector_unit_descriptor* descriptor = 428 (const usbvc_selector_unit_descriptor*)_descriptor; 429 printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n", 430 descriptor->unitID, descriptor->numInputPins); 431 printf("\t"); 432 for (uint8 i = 0; i < descriptor->numInputPins; i++) 433 printf("%d ", descriptor->sourceID[i]); 434 printf("\n"); 435 printf("\tDesc: %s\n", 436 fDevice->DecodeStringDescriptor(descriptor->Selector())); 437 break; 438 } 439 case VC_PROCESSING_UNIT: 440 { 441 const usbvc_processing_unit_descriptor* descriptor = 442 (const usbvc_processing_unit_descriptor*)_descriptor; 443 printf("VC_PROCESSING_UNIT:\tid=%d,src id=%d, digmul=%d\n", 444 descriptor->unitID, descriptor->sourceID, 445 descriptor->maxMultiplier); 446 printf("\tbControlSize=%d\n", descriptor->controlSize); 447 if (descriptor->controlSize >= 1) { 448 if (descriptor->controls[0] & 1) 449 printf("\tBrightness\n"); 450 if (descriptor->controls[0] & 2) 451 printf("\tContrast\n"); 452 if (descriptor->controls[0] & 4) 453 printf("\tHue\n"); 454 if (descriptor->controls[0] & 8) 455 printf("\tSaturation\n"); 456 if (descriptor->controls[0] & 16) 457 printf("\tSharpness\n"); 458 if (descriptor->controls[0] & 32) 459 printf("\tGamma\n"); 460 if (descriptor->controls[0] & 64) 461 printf("\tWhite Balance Temperature\n"); 462 if (descriptor->controls[0] & 128) 463 printf("\tWhite Balance Component\n"); 464 } 465 if (descriptor->controlSize >= 2) { 466 if (descriptor->controls[1] & 1) 467 printf("\tBacklight Compensation\n"); 468 if (descriptor->controls[1] & 2) 469 printf("\tGain\n"); 470 if (descriptor->controls[1] & 4) 471 printf("\tPower Line Frequency\n"); 472 if (descriptor->controls[1] & 8) 473 printf("\t[AUTO] Hue\n"); 474 if (descriptor->controls[1] & 16) 475 printf("\t[AUTO] White Balance Temperature\n"); 476 if (descriptor->controls[1] & 32) 477 printf("\t[AUTO] White Balance Component\n"); 478 if (descriptor->controls[1] & 64) 479 printf("\tDigital Multiplier\n"); 480 if (descriptor->controls[1] & 128) 481 printf("\tDigital Multiplier Limit\n"); 482 } 483 if (descriptor->controlSize >= 3) { 484 if (descriptor->controls[2] & 1) 485 printf("\tAnalog Video Standard\n"); 486 if (descriptor->controls[2] & 2) 487 printf("\tAnalog Video Lock Status\n"); 488 } 489 printf("\tDesc: %s\n", 490 fDevice->DecodeStringDescriptor(descriptor->Processing())); 491 if (descriptor->VideoStandards() & 2) 492 printf("\tNTSC 525/60\n"); 493 if (descriptor->VideoStandards() & 4) 494 printf("\tPAL 625/50\n"); 495 if (descriptor->VideoStandards() & 8) 496 printf("\tSECAM 625/50\n"); 497 if (descriptor->VideoStandards() & 16) 498 printf("\tNTSC 625/50\n"); 499 if (descriptor->VideoStandards() & 32) 500 printf("\tPAL 525/60\n"); 501 break; 502 } 503 case VC_EXTENSION_UNIT: 504 { 505 const usbvc_extension_unit_descriptor* descriptor = 506 (const usbvc_extension_unit_descriptor*)_descriptor; 507 printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor->unitID); 508 print_guid(descriptor->guidExtensionCode); 509 printf("\n\t#ctrls=%d, #pins=%d\n", descriptor->numControls, 510 descriptor->numInputPins); 511 printf("\t"); 512 for (uint8 i = 0; i < descriptor->numInputPins; i++) 513 printf("%d ", descriptor->sourceID[i]); 514 printf("\n"); 515 printf("\tDesc: %s\n", 516 fDevice->DecodeStringDescriptor(descriptor->Extension())); 517 break; 518 } 519 default: 520 printf("Unknown control %d\n", _descriptor->descriptorSubtype); 521 } 522 } 523 524 525 bool 526 UVCCamDevice::SupportsIsochronous() 527 { 528 return true; 529 } 530 531 532 status_t 533 UVCCamDevice::StartTransfer() 534 { 535 if (_ProbeCommitFormat() != B_OK || _SelectBestAlternate() != B_OK) 536 return B_ERROR; 537 return CamDevice::StartTransfer(); 538 } 539 540 541 status_t 542 UVCCamDevice::StopTransfer() 543 { 544 _SelectIdleAlternate(); 545 return CamDevice::StopTransfer(); 546 } 547 548 549 status_t 550 UVCCamDevice::SuggestVideoFrame(uint32 &width, uint32 &height) 551 { 552 width = 320; 553 height = 240; 554 return B_OK; 555 } 556 557 558 status_t 559 UVCCamDevice::AcceptVideoFrame(uint32 &width, uint32 &height) 560 { 561 width = 320; 562 height = 240; 563 564 SetVideoFrame(BRect(0, 0, width - 1, height - 1)); 565 return B_OK; 566 } 567 568 569 status_t 570 UVCCamDevice::_ProbeCommitFormat() 571 { 572 usbvc_probecommit request; 573 memset(&request, 0, sizeof(request)); 574 request.hint = 1 << 8; 575 request.SetFrameInterval(333333); 576 request.formatIndex = 1; 577 request.frameIndex = 3; 578 size_t length = fHeaderDescriptor->version > 0x100 ? 34 : 26; 579 size_t actualLength = fDevice->ControlTransfer( 580 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 581 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request); 582 if (actualLength != length) { 583 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SET_CUR ProbeControl1" 584 " failed %ld\n", actualLength); 585 return B_ERROR; 586 } 587 588 usbvc_probecommit response; 589 actualLength = fDevice->ControlTransfer( 590 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_MAX, 591 VS_PROBE_CONTROL << 8, fStreamingIndex, sizeof(response), &response); 592 if (actualLength != sizeof(response)) { 593 fprintf(stderr, "UVCCamDevice::_ProbeFormat() GetMax ProbeControl" 594 " failed\n"); 595 return B_ERROR; 596 } 597 598 printf("usbvc_probecommit response.compQuality %d\n", response.compQuality); 599 request.compQuality = response.compQuality; 600 601 actualLength = fDevice->ControlTransfer( 602 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 603 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request); 604 if (actualLength != length) { 605 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SetCur ProbeControl2" 606 " failed\n"); 607 return B_ERROR; 608 } 609 610 actualLength = fDevice->ControlTransfer( 611 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 612 VS_COMMIT_CONTROL << 8, fStreamingIndex, length, &request); 613 if (actualLength != length) { 614 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SetCur CommitControl" 615 " failed\n"); 616 return B_ERROR; 617 } 618 619 fMaxVideoFrameSize = response.maxVideoFrameSize; 620 fMaxPayloadTransferSize = response.maxPayloadTransferSize; 621 printf("usbvc_probecommit setup done maxVideoFrameSize:%ld" 622 " maxPayloadTransferSize:%ld\n", fMaxVideoFrameSize, 623 fMaxPayloadTransferSize); 624 625 return B_OK; 626 } 627 628 629 status_t 630 UVCCamDevice::_SelectBestAlternate() 631 { 632 const BUSBConfiguration *config = fDevice->ActiveConfiguration(); 633 const BUSBInterface *streaming = config->InterfaceAt(fStreamingIndex); 634 635 uint32 bestBandwidth = 0; 636 uint32 alternateIndex = 0; 637 uint32 endpointIndex = 0; 638 639 for (uint32 i = 0; i < streaming->CountAlternates(); i++) { 640 const BUSBInterface *alternate = streaming->AlternateAt(i); 641 for (uint32 j = 0; j < alternate->CountEndpoints(); j++) { 642 const BUSBEndpoint *endpoint = alternate->EndpointAt(j); 643 if (!endpoint->IsIsochronous() || !endpoint->IsInput()) 644 continue; 645 if (fMaxPayloadTransferSize > endpoint->MaxPacketSize()) 646 continue; 647 if (bestBandwidth != 0 648 && bestBandwidth < endpoint->MaxPacketSize()) 649 continue; 650 bestBandwidth = endpoint->MaxPacketSize(); 651 endpointIndex = j; 652 alternateIndex = i; 653 } 654 } 655 656 if (bestBandwidth == 0) { 657 fprintf(stderr, "UVCCamDevice::_SelectBestAlternate()" 658 " couldn't find a valid alternate\n"); 659 return B_ERROR; 660 } 661 662 printf("UVCCamDevice::_SelectBestAlternate() %ld\n", bestBandwidth); 663 if (((BUSBInterface *)streaming)->SetAlternate(alternateIndex) != B_OK) { 664 fprintf(stderr, "UVCCamDevice::_SelectBestAlternate()" 665 " selecting alternate failed\n"); 666 return B_ERROR; 667 } 668 669 fIsoIn = streaming->EndpointAt(endpointIndex); 670 671 return B_OK; 672 } 673 674 675 status_t 676 UVCCamDevice::_SelectIdleAlternate() 677 { 678 const BUSBConfiguration *config = fDevice->ActiveConfiguration(); 679 const BUSBInterface *streaming = config->InterfaceAt(fStreamingIndex); 680 if (((BUSBInterface *)streaming)->SetAlternate(0) != B_OK) { 681 fprintf(stderr, "UVCCamDevice::_SelectIdleAlternate()" 682 " selecting alternate failed\n"); 683 return B_ERROR; 684 } 685 686 fIsoIn = NULL; 687 688 return B_OK; 689 } 690 691 692 UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam) 693 : CamDeviceAddon(webcam) 694 { 695 SetSupportedDevices(kSupportedDevices); 696 } 697 698 699 UVCCamDeviceAddon::~UVCCamDeviceAddon() 700 { 701 } 702 703 704 const char * 705 UVCCamDeviceAddon::BrandName() 706 { 707 return "USB Video Class"; 708 } 709 710 711 UVCCamDevice * 712 UVCCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 713 { 714 return new UVCCamDevice(*this, from); 715 } 716 717 718 extern "C" status_t 719 B_WEBCAM_MKINTFUNC(uvccam) 720 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 721 { 722 *addon = new UVCCamDeviceAddon(webcam); 723 return B_OK; 724 } 725