1 /* 2 * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com. 3 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 4 * Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "UVCCamDevice.h" 10 #include "UVCDeframer.h" 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <ParameterWeb.h> 15 #include <media/Buffer.h> 16 17 18 usb_webcam_support_descriptor kSupportedDevices[] = { 19 // ofcourse we support a generic UVC device... 20 {{ CC_VIDEO, SC_VIDEOCONTROL, 0, 0, 0 }, "Generic UVC", "Video Class", "??" }, 21 // ...whilst the following IDs were 'stolen' from a recent Linux driver: 22 {{ 0, 0, 0, 0x045e, 0x00f8, }, "Microsoft", "Lifecam NX-6000", "??" }, 23 {{ 0, 0, 0, 0x045e, 0x0723, }, "Microsoft", "Lifecam VX-7000", "??" }, 24 {{ 0, 0, 0, 0x046d, 0x08c1, }, "Logitech", "QuickCam Fusion", "??" }, 25 {{ 0, 0, 0, 0x046d, 0x08c2, }, "Logitech", "QuickCam Orbit MP", "??" }, 26 {{ 0, 0, 0, 0x046d, 0x08c3, }, "Logitech", "QuickCam Pro for Notebook", "??" }, 27 {{ 0, 0, 0, 0x046d, 0x08c5, }, "Logitech", "QuickCam Pro 5000", "??" }, 28 {{ 0, 0, 0, 0x046d, 0x08c6, }, "Logitech", "QuickCam OEM Dell Notebook", "??" }, 29 {{ 0, 0, 0, 0x046d, 0x08c7, }, "Logitech", "QuickCam OEM Cisco VT Camera II", "??" }, 30 {{ 0, 0, 0, 0x046d, 0x0821, }, "Logitech", "HD Pro Webcam C910", "??" }, 31 {{ 0, 0, 0, 0x05ac, 0x8501, }, "Apple", "Built-In iSight", "??" }, 32 {{ 0, 0, 0, 0x05e3, 0x0505, }, "Genesys Logic", "USB 2.0 PC Camera", "??" }, 33 {{ 0, 0, 0, 0x0e8d, 0x0004, }, "N/A", "MT6227", "??" }, 34 {{ 0, 0, 0, 0x174f, 0x5212, }, "Syntek", "(HP Spartan)", "??" }, 35 {{ 0, 0, 0, 0x174f, 0x5931, }, "Syntek", "(Samsung Q310)", "??" }, 36 {{ 0, 0, 0, 0x174f, 0x8a31, }, "Syntek", "Asus F9SG", "??" }, 37 {{ 0, 0, 0, 0x174f, 0x8a33, }, "Syntek", "Asus U3S", "??" }, 38 {{ 0, 0, 0, 0x17ef, 0x480b, }, "N/A", "Lenovo Thinkpad SL500", "??" }, 39 {{ 0, 0, 0, 0x18cd, 0xcafe, }, "Ecamm", "Pico iMage", "??" }, 40 {{ 0, 0, 0, 0x19ab, 0x1000, }, "Bodelin", "ProScopeHR", "??" }, 41 {{ 0, 0, 0, 0x1c4f, 0x3000, }, "SiGma Micro", "USB Web Camera", "??" }, 42 {{ 0, 0, 0, 0, 0}, NULL, NULL, NULL } 43 }; 44 45 /* Table 2-1 Compression Formats of USB Video Payload Uncompressed */ 46 usbvc_guid kYUY2Guid = {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 47 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 48 usbvc_guid kNV12Guid = {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 49 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 50 51 static void 52 print_guid(const usbvc_guid guid) 53 { 54 if (!memcmp(guid, kYUY2Guid, sizeof(usbvc_guid))) 55 printf("YUY2"); 56 else if (!memcmp(guid, kNV12Guid, sizeof(usbvc_guid))) 57 printf("NV12"); 58 else { 59 printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" 60 "%02x:%02x:%02x:%02x", guid[0], guid[1], guid[2], guid[3], guid[4], 61 guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], 62 guid[12], guid[13], guid[14], guid[15]); 63 } 64 } 65 66 67 UVCCamDevice::UVCCamDevice(CamDeviceAddon& _addon, BUSBDevice* _device) 68 : CamDevice(_addon, _device), 69 fHeaderDescriptor(NULL), 70 fInterruptIn(NULL), 71 fUncompressedFormatIndex(1), 72 fUncompressedFrameIndex(1) 73 { 74 fDeframer = new UVCDeframer(this); 75 SetDataInput(fDeframer); 76 77 const BUSBConfiguration* config; 78 const BUSBInterface* interface; 79 usb_descriptor* generic; 80 uint8 buffer[1024]; 81 82 generic = (usb_descriptor*)buffer; 83 84 for (uint32 i = 0; i < _device->CountConfigurations(); i++) { 85 config = _device->ConfigurationAt(i); 86 if (config == NULL) 87 continue; 88 _device->SetConfiguration(config); 89 for (uint32 j = 0; j < config->CountInterfaces(); j++) { 90 interface = config->InterfaceAt(j); 91 if (interface == NULL) 92 continue; 93 94 if (interface->Class() == CC_VIDEO && interface->Subclass() 95 == SC_VIDEOCONTROL) { 96 printf("UVCCamDevice: (%lu,%lu): Found Video Control " 97 "interface.\n", i, j); 98 99 // look for class specific interface descriptors and parse them 100 for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 101 sizeof(buffer)) == B_OK; k++) { 102 if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 103 | USB_DESCRIPTOR_INTERFACE)) 104 continue; 105 fControlIndex = interface->Index(); 106 _ParseVideoControl((const usbvc_class_descriptor*)generic, 107 generic->generic.length); 108 } 109 for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 110 const BUSBEndpoint* e = interface->EndpointAt(i); 111 if (e && e->IsInterrupt() && e->IsInput()) { 112 fInterruptIn = e; 113 break; 114 } 115 } 116 fInitStatus = B_OK; 117 } else if (interface->Class() == CC_VIDEO && interface->Subclass() 118 == SC_VIDEOSTREAMING) { 119 printf("UVCCamDevice: (%lu,%lu): Found Video Streaming " 120 "interface.\n", i, j); 121 122 // look for class specific interface descriptors and parse them 123 for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 124 sizeof(buffer)) == B_OK; k++) { 125 if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 126 | USB_DESCRIPTOR_INTERFACE)) 127 continue; 128 fStreamingIndex = interface->Index(); 129 _ParseVideoStreaming((const usbvc_class_descriptor*)generic, 130 generic->generic.length); 131 } 132 133 for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 134 const BUSBEndpoint* e = interface->EndpointAt(i); 135 if (e && e->IsIsochronous() && e->IsInput()) { 136 fIsoIn = e; 137 break; 138 } 139 } 140 } 141 } 142 } 143 } 144 145 146 UVCCamDevice::~UVCCamDevice() 147 { 148 free(fHeaderDescriptor); 149 } 150 151 152 void 153 UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor, 154 size_t len) 155 { 156 switch (_descriptor->descriptorSubtype) { 157 case VS_INPUT_HEADER: 158 { 159 const usbvc_input_header_descriptor* descriptor 160 = (const usbvc_input_header_descriptor*)_descriptor; 161 printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor->numFormats, 162 descriptor->endpointAddress); 163 if (descriptor->info & 1) 164 printf("\tDynamic Format Change supported\n"); 165 printf("\toutput terminal id=%d\n", descriptor->terminalLink); 166 printf("\tstill capture method=%d\n", descriptor->stillCaptureMethod); 167 if (descriptor->triggerSupport) { 168 printf("\ttrigger button fixed to still capture=%s\n", 169 descriptor->triggerUsage ? "no" : "yes"); 170 } 171 const uint8* controls = descriptor->controls; 172 for (uint8 i = 0; i < descriptor->numFormats; i++, 173 controls += descriptor->controlSize) { 174 printf("\tfmt%d: %s %s %s %s - %s %s\n", i, 175 (*controls & 1) ? "wKeyFrameRate" : "", 176 (*controls & 2) ? "wPFrameRate" : "", 177 (*controls & 4) ? "wCompQuality" : "", 178 (*controls & 8) ? "wCompWindowSize" : "", 179 (*controls & 16) ? "<Generate Key Frame>" : "", 180 (*controls & 32) ? "<Update Frame Segment>" : ""); 181 } 182 break; 183 } 184 case VS_FORMAT_UNCOMPRESSED: 185 { 186 const usbvc_format_descriptor* descriptor 187 = (const usbvc_format_descriptor*)_descriptor; 188 fUncompressedFormatIndex = descriptor->formatIndex; 189 printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=", 190 descriptor->formatIndex, descriptor->numFrameDescriptors); 191 print_guid(descriptor->uncompressed.format); 192 printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 193 descriptor->uncompressed.bytesPerPixel, 194 descriptor->uncompressed.defaultFrameIndex, 195 descriptor->uncompressed.aspectRatioX, 196 descriptor->uncompressed.aspectRatioY); 197 printf("\tbmInterlaceFlags:\n"); 198 if (descriptor->uncompressed.interlaceFlags & 1) 199 printf("\tInterlaced stream or variable\n"); 200 printf("\t%d fields per frame\n", 201 (descriptor->uncompressed.interlaceFlags & 2) ? 1 : 2); 202 if (descriptor->uncompressed.interlaceFlags & 4) 203 printf("\tField 1 first\n"); 204 printf("\tField Pattern: "); 205 switch ((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) { 206 case 0: printf("Field 1 only\n"); break; 207 case 1: printf("Field 2 only\n"); break; 208 case 2: printf("Regular pattern of fields 1 and 2\n"); break; 209 case 3: printf("Random pattern of fields 1 and 2\n"); break; 210 } 211 if (descriptor->uncompressed.copyProtect) 212 printf("\tRestrict duplication\n"); 213 break; 214 } 215 case VS_FRAME_MJPEG: 216 case VS_FRAME_UNCOMPRESSED: 217 { 218 const usbvc_frame_descriptor* descriptor 219 = (const usbvc_frame_descriptor*)_descriptor; 220 if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED) { 221 printf("VS_FRAME_UNCOMPRESSED:"); 222 fUncompressedFrames.AddItem( 223 new usbvc_frame_descriptor(*descriptor)); 224 } else { 225 printf("VS_FRAME_MJPEG:"); 226 fMJPEGFrames.AddItem(new usbvc_frame_descriptor(*descriptor)); 227 } 228 printf("\tbFrameIdx=%d,stillsupported=%s," 229 "fixedframerate=%s\n", descriptor->frameIndex, 230 (descriptor->capabilities & 1) ? "yes" : "no", 231 (descriptor->capabilities & 2) ? "yes" : "no"); 232 printf("\twidth=%u,height=%u,min/max bitrate=%lu/%lu, maxbuf=%lu\n", 233 descriptor->width, descriptor->height, 234 descriptor->minBitRate, descriptor->maxBitRate, 235 descriptor->maxVideoFrameBufferSize); 236 printf("\tdefault frame interval: %lu, #intervals(0=cont): %d\n", 237 descriptor->defaultFrameInterval, descriptor->frameIntervalType); 238 if (descriptor->frameIntervalType == 0) { 239 printf("min/max frame interval=%lu/%lu, step=%lu\n", 240 descriptor->continuous.minFrameInterval, 241 descriptor->continuous.maxFrameInterval, 242 descriptor->continuous.frameIntervalStep); 243 } else for (uint8 i = 0; i < descriptor->frameIntervalType; i++) { 244 printf("\tdiscrete frame interval: %lu\n", 245 descriptor->discreteFrameIntervals[i]); 246 } 247 break; 248 } 249 case VS_COLORFORMAT: 250 { 251 const usbvc_color_matching_descriptor* descriptor 252 = (const usbvc_color_matching_descriptor*)_descriptor; 253 printf("VS_COLORFORMAT:\n\tbColorPrimaries: "); 254 switch (descriptor->colorPrimaries) { 255 case 0: printf("Unspecified\n"); break; 256 case 1: printf("BT.709,sRGB\n"); break; 257 case 2: printf("BT.470-2(M)\n"); break; 258 case 3: printf("BT.470-2(B,G)\n"); break; 259 case 4: printf("SMPTE 170M\n"); break; 260 case 5: printf("SMPTE 240M\n"); break; 261 default: printf("Invalid (%d)\n", descriptor->colorPrimaries); 262 } 263 printf("\tbTransferCharacteristics: "); 264 switch (descriptor->transferCharacteristics) { 265 case 0: printf("Unspecified\n"); break; 266 case 1: printf("BT.709\n"); break; 267 case 2: printf("BT.470-2(M)\n"); break; 268 case 3: printf("BT.470-2(B,G)\n"); break; 269 case 4: printf("SMPTE 170M\n"); break; 270 case 5: printf("SMPTE 240M\n"); break; 271 case 6: printf("Linear (V=Lc)\n"); break; 272 case 7: printf("sRGB\n"); break; 273 default: printf("Invalid (%d)\n", 274 descriptor->transferCharacteristics); 275 } 276 printf("\tbMatrixCoefficients: "); 277 switch (descriptor->matrixCoefficients) { 278 case 0: printf("Unspecified\n"); break; 279 case 1: printf("BT.709\n"); break; 280 case 2: printf("FCC\n"); break; 281 case 3: printf("BT.470-2(B,G)\n"); break; 282 case 4: printf("SMPTE 170M (BT.601)\n"); break; 283 case 5: printf("SMPTE 240M\n"); break; 284 default: printf("Invalid (%d)\n", descriptor->matrixCoefficients); 285 } 286 break; 287 } 288 case VS_OUTPUT_HEADER: 289 { 290 const usbvc_output_header_descriptor* descriptor 291 = (const usbvc_output_header_descriptor*)_descriptor; 292 printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n", 293 descriptor->numFormats, descriptor->endpointAddress); 294 printf("\toutput terminal id=%d\n", descriptor->terminalLink); 295 const uint8* controls = descriptor->controls; 296 for (uint8 i = 0; i < descriptor->numFormats; i++, 297 controls += descriptor->controlSize) { 298 printf("\tfmt%d: %s %s %s %s\n", i, 299 (*controls & 1) ? "wKeyFrameRate" : "", 300 (*controls & 2) ? "wPFrameRate" : "", 301 (*controls & 4) ? "wCompQuality" : "", 302 (*controls & 8) ? "wCompWindowSize" : ""); 303 } 304 break; 305 } 306 case VS_STILL_IMAGE_FRAME: 307 { 308 const usbvc_still_image_frame_descriptor* descriptor 309 = (const usbvc_still_image_frame_descriptor*)_descriptor; 310 printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d," 311 "ept=0x%x\n", descriptor->numImageSizePatterns, 312 descriptor->NumCompressionPatterns(), 313 descriptor->endpointAddress); 314 for (uint8 i = 0; i < descriptor->numImageSizePatterns; i++) { 315 printf("imageSize%d: %dx%d\n", i, 316 descriptor->imageSizePatterns[i].width, 317 descriptor->imageSizePatterns[i].height); 318 } 319 for (uint8 i = 0; i < descriptor->NumCompressionPatterns(); i++) { 320 printf("compression%d: %d\n", i, 321 descriptor->CompressionPatterns()[i]); 322 } 323 break; 324 } 325 case VS_FORMAT_MJPEG: 326 { 327 const usbvc_format_descriptor* descriptor 328 = (const usbvc_format_descriptor*)_descriptor; 329 fMJPEGFormatIndex = descriptor->formatIndex; 330 printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n", 331 descriptor->formatIndex, descriptor->numFrameDescriptors); 332 printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 333 descriptor->mjpeg.flags, 334 descriptor->mjpeg.defaultFrameIndex, 335 descriptor->mjpeg.aspectRatioX, 336 descriptor->mjpeg.aspectRatioY); 337 printf("\tbmInterlaceFlags:\n"); 338 if (descriptor->mjpeg.interlaceFlags & 1) 339 printf("\tInterlaced stream or variable\n"); 340 printf("\t%d fields per frame\n", 341 (descriptor->mjpeg.interlaceFlags & 2) ? 1 : 2); 342 if (descriptor->mjpeg.interlaceFlags & 4) 343 printf("\tField 1 first\n"); 344 printf("\tField Pattern: "); 345 switch ((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) { 346 case 0: printf("Field 1 only\n"); break; 347 case 1: printf("Field 2 only\n"); break; 348 case 2: printf("Regular pattern of fields 1 and 2\n"); break; 349 case 3: printf("Random pattern of fields 1 and 2\n"); break; 350 } 351 if (descriptor->mjpeg.copyProtect) 352 printf("\tRestrict duplication\n"); 353 break; 354 } 355 case VS_FORMAT_MPEG2TS: 356 printf("VS_FORMAT_MPEG2TS:\t\n"); 357 break; 358 case VS_FORMAT_DV: 359 printf("VS_FORMAT_DV:\t\n"); 360 break; 361 case VS_FORMAT_FRAME_BASED: 362 printf("VS_FORMAT_FRAME_BASED:\t\n"); 363 break; 364 case VS_FRAME_FRAME_BASED: 365 printf("VS_FRAME_FRAME_BASED:\t\n"); 366 break; 367 case VS_FORMAT_STREAM_BASED: 368 printf("VS_FORMAT_STREAM_BASED:\t\n"); 369 break; 370 default: 371 printf("INVALID STREAM UNIT TYPE=%d!\n", 372 _descriptor->descriptorSubtype); 373 } 374 } 375 376 377 void 378 UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor, 379 size_t len) 380 { 381 switch (_descriptor->descriptorSubtype) { 382 case VC_HEADER: 383 { 384 if (fHeaderDescriptor != NULL) { 385 printf("ERROR: multiple VC_HEADER! Skipping...\n"); 386 break; 387 } 388 fHeaderDescriptor = (usbvc_interface_header_descriptor*)malloc(len); 389 memcpy(fHeaderDescriptor, _descriptor, len); 390 printf("VC_HEADER:\tUVC v%x.%02x, clk %.5f MHz\n", 391 fHeaderDescriptor->version >> 8, 392 fHeaderDescriptor->version & 0xff, 393 fHeaderDescriptor->clockFrequency / 1000000.0); 394 for (uint8 i = 0; i < fHeaderDescriptor->numInterfacesNumbers; i++) { 395 printf("\tStreaming Interface %d\n", 396 fHeaderDescriptor->interfaceNumbers[i]); 397 } 398 break; 399 } 400 case VC_INPUT_TERMINAL: 401 { 402 const usbvc_input_terminal_descriptor* descriptor 403 = (const usbvc_input_terminal_descriptor*)_descriptor; 404 printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 405 "%d\n", descriptor->terminalID, descriptor->terminalType, 406 descriptor->associatedTerminal); 407 printf("\tDesc: %s\n", 408 fDevice->DecodeStringDescriptor(descriptor->terminal)); 409 if (descriptor->terminalType == 0x201) { 410 const usbvc_camera_terminal_descriptor* desc 411 = (const usbvc_camera_terminal_descriptor*)descriptor; 412 printf("\tObjectiveFocalLength Min/Max %d/%d\n", 413 desc->objectiveFocalLengthMin, 414 desc->objectiveFocalLengthMax); 415 printf("\tOcularFocalLength %d\n", desc->ocularFocalLength); 416 printf("\tControlSize %d\n", desc->controlSize); 417 } 418 break; 419 } 420 case VC_OUTPUT_TERMINAL: 421 { 422 const usbvc_output_terminal_descriptor* descriptor 423 = (const usbvc_output_terminal_descriptor*)_descriptor; 424 printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 425 "%d, src id=%d\n", descriptor->terminalID, 426 descriptor->terminalType, descriptor->associatedTerminal, 427 descriptor->sourceID); 428 printf("\tDesc: %s\n", 429 fDevice->DecodeStringDescriptor(descriptor->terminal)); 430 break; 431 } 432 case VC_SELECTOR_UNIT: 433 { 434 const usbvc_selector_unit_descriptor* descriptor 435 = (const usbvc_selector_unit_descriptor*)_descriptor; 436 printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n", 437 descriptor->unitID, descriptor->numInputPins); 438 printf("\t"); 439 for (uint8 i = 0; i < descriptor->numInputPins; i++) 440 printf("%d ", descriptor->sourceID[i]); 441 printf("\n"); 442 printf("\tDesc: %s\n", 443 fDevice->DecodeStringDescriptor(descriptor->Selector())); 444 break; 445 } 446 case VC_PROCESSING_UNIT: 447 { 448 const usbvc_processing_unit_descriptor* descriptor 449 = (const usbvc_processing_unit_descriptor*)_descriptor; 450 fControlRequestIndex = fControlIndex + (descriptor->unitID << 8); 451 printf("VC_PROCESSING_UNIT:\t unit id=%d,src id=%d, digmul=%d\n", 452 descriptor->unitID, descriptor->sourceID, 453 descriptor->maxMultiplier); 454 printf("\tbControlSize=%d\n", descriptor->controlSize); 455 if (descriptor->controlSize >= 1) { 456 if (descriptor->controls[0] & 1) 457 printf("\tBrightness\n"); 458 if (descriptor->controls[0] & 2) 459 printf("\tContrast\n"); 460 if (descriptor->controls[0] & 4) 461 printf("\tHue\n"); 462 if (descriptor->controls[0] & 8) 463 printf("\tSaturation\n"); 464 if (descriptor->controls[0] & 16) 465 printf("\tSharpness\n"); 466 if (descriptor->controls[0] & 32) 467 printf("\tGamma\n"); 468 if (descriptor->controls[0] & 64) 469 printf("\tWhite Balance Temperature\n"); 470 if (descriptor->controls[0] & 128) 471 printf("\tWhite Balance Component\n"); 472 } 473 if (descriptor->controlSize >= 2) { 474 if (descriptor->controls[1] & 1) 475 printf("\tBacklight Compensation\n"); 476 if (descriptor->controls[1] & 2) 477 printf("\tGain\n"); 478 if (descriptor->controls[1] & 4) 479 printf("\tPower Line Frequency\n"); 480 if (descriptor->controls[1] & 8) 481 printf("\t[AUTO] Hue\n"); 482 if (descriptor->controls[1] & 16) 483 printf("\t[AUTO] White Balance Temperature\n"); 484 if (descriptor->controls[1] & 32) 485 printf("\t[AUTO] White Balance Component\n"); 486 if (descriptor->controls[1] & 64) 487 printf("\tDigital Multiplier\n"); 488 if (descriptor->controls[1] & 128) 489 printf("\tDigital Multiplier Limit\n"); 490 } 491 if (descriptor->controlSize >= 3) { 492 if (descriptor->controls[2] & 1) 493 printf("\tAnalog Video Standard\n"); 494 if (descriptor->controls[2] & 2) 495 printf("\tAnalog Video Lock Status\n"); 496 } 497 printf("\tDesc: %s\n", 498 fDevice->DecodeStringDescriptor(descriptor->Processing())); 499 if (descriptor->VideoStandards() & 2) 500 printf("\tNTSC 525/60\n"); 501 if (descriptor->VideoStandards() & 4) 502 printf("\tPAL 625/50\n"); 503 if (descriptor->VideoStandards() & 8) 504 printf("\tSECAM 625/50\n"); 505 if (descriptor->VideoStandards() & 16) 506 printf("\tNTSC 625/50\n"); 507 if (descriptor->VideoStandards() & 32) 508 printf("\tPAL 525/60\n"); 509 break; 510 } 511 case VC_EXTENSION_UNIT: 512 { 513 const usbvc_extension_unit_descriptor* descriptor 514 = (const usbvc_extension_unit_descriptor*)_descriptor; 515 printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor->unitID); 516 print_guid(descriptor->guidExtensionCode); 517 printf("\n\t#ctrls=%d, #pins=%d\n", descriptor->numControls, 518 descriptor->numInputPins); 519 printf("\t"); 520 for (uint8 i = 0; i < descriptor->numInputPins; i++) 521 printf("%d ", descriptor->sourceID[i]); 522 printf("\n"); 523 printf("\tDesc: %s\n", 524 fDevice->DecodeStringDescriptor(descriptor->Extension())); 525 break; 526 } 527 default: 528 printf("Unknown control %d\n", _descriptor->descriptorSubtype); 529 } 530 } 531 532 533 bool 534 UVCCamDevice::SupportsIsochronous() 535 { 536 return true; 537 } 538 539 540 status_t 541 UVCCamDevice::StartTransfer() 542 { 543 if (_ProbeCommitFormat() != B_OK || _SelectBestAlternate() != B_OK) 544 return B_ERROR; 545 return CamDevice::StartTransfer(); 546 } 547 548 549 status_t 550 UVCCamDevice::StopTransfer() 551 { 552 _SelectIdleAlternate(); 553 return CamDevice::StopTransfer(); 554 } 555 556 557 status_t 558 UVCCamDevice::SuggestVideoFrame(uint32& width, uint32& height) 559 { 560 printf("UVCCamDevice::SuggestVideoFrame(%ld, %ld)\n", width, height); 561 // As in AcceptVideoFrame(), the suggestion should probably just be the 562 // first advertised uncompressed format, but current applications prefer 563 // 320x240, so this is tried first here as a suggestion. 564 width = 320; 565 height = 240; 566 if (!AcceptVideoFrame(width, height)) { 567 const usbvc_frame_descriptor* descriptor 568 = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem(); 569 width = (*descriptor).width; 570 height = (*descriptor).height; 571 } 572 return B_OK; 573 } 574 575 576 status_t 577 UVCCamDevice::AcceptVideoFrame(uint32& width, uint32& height) 578 { 579 printf("UVCCamDevice::AcceptVideoFrame(%ld, %ld)\n", width, height); 580 if (width <= 0 || height <= 0) { 581 // Uncomment below when applications support dimensions other than 320x240 582 // This code selects the first listed available uncompressed frame format 583 /* 584 const usbvc_frame_descriptor* descriptor 585 = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem(); 586 width = (*descriptor).width; 587 height = (*descriptor).height; 588 SetVideoFrame(BRect(0, 0, width - 1, height - 1)); 589 return B_OK; 590 */ 591 592 width = 320; 593 height = 240; 594 } 595 596 for (int i = 0; i<fUncompressedFrames.CountItems(); i++) { 597 const usbvc_frame_descriptor* descriptor 598 = (const usbvc_frame_descriptor*)fUncompressedFrames.ItemAt(i); 599 if ((*descriptor).width == width && (*descriptor).height == height) { 600 fUncompressedFrameIndex = i; 601 SetVideoFrame(BRect(0, 0, width - 1, height - 1)); 602 return B_OK; 603 } 604 } 605 606 fprintf(stderr, "UVCCamDevice::AcceptVideoFrame() Invalid frame dimensions" 607 "\n"); 608 return B_ERROR; 609 } 610 611 612 status_t 613 UVCCamDevice::_ProbeCommitFormat() 614 { 615 printf("UVCCamDevice::_ProbeCommitFormat()\n"); 616 printf("UVCCamDevice::fStreamingIndex = %ld\n", fStreamingIndex); 617 618 /* 619 char error; 620 printf("BEFORE ERROR CODE CHECK.\n"); 621 fDevice->ControlTransfer( 622 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_CUR, 623 VS_STREAM_ERROR_CODE_CONTROL << 8, fStreamingIndex, 1, &error); 624 printf("Error code = Ox%x\n", error); 625 */ 626 627 usbvc_probecommit request; 628 memset(&request, 0, sizeof(request)); 629 request.hint = 1; 630 request.SetFrameInterval(333333); 631 request.formatIndex = fUncompressedFormatIndex; 632 request.frameIndex = fUncompressedFrameIndex; 633 size_t length = fHeaderDescriptor->version > 0x100 ? 34 : 26; 634 size_t actualLength = fDevice->ControlTransfer( 635 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 636 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request); 637 if (actualLength != length) { 638 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SET_CUR ProbeControl1" 639 " failed %ld\n", actualLength); 640 return B_ERROR; 641 } 642 643 /* 644 usbvc_probecommit response; 645 actualLength = fDevice->ControlTransfer( 646 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_MAX, 647 VS_PROBE_CONTROL << 8, fStreamingIndex, sizeof(response), &response); 648 if (actualLength != sizeof(response)) { 649 fprintf(stderr, "UVCCamDevice::_ProbeFormat() GetMax ProbeControl" 650 " failed\n"); 651 return B_ERROR; 652 } 653 654 printf("usbvc_probecommit response.compQuality %d\n", response.compQuality); 655 request.compQuality = response.compQuality; 656 */ 657 658 659 usbvc_probecommit response; 660 memset(&response, 0, sizeof(response)); 661 actualLength = fDevice->ControlTransfer( 662 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_CUR, 663 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &response); 664 665 /* 666 actualLength = fDevice->ControlTransfer( 667 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 668 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request); 669 if (actualLength != length) { 670 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SetCur ProbeControl2" 671 " failed\n"); 672 return B_ERROR; 673 } 674 */ 675 676 actualLength = fDevice->ControlTransfer( 677 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR, 678 VS_COMMIT_CONTROL << 8, fStreamingIndex, length, &request); 679 if (actualLength != length) { 680 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SetCur CommitControl" 681 " failed\n"); 682 return B_ERROR; 683 } 684 685 686 fMaxVideoFrameSize = response.maxVideoFrameSize; 687 fMaxPayloadTransferSize = response.maxPayloadTransferSize; 688 printf("usbvc_probecommit setup done maxVideoFrameSize:%ld" 689 " maxPayloadTransferSize:%ld\n", fMaxVideoFrameSize, 690 fMaxPayloadTransferSize); 691 692 printf("UVCCamDevice::_ProbeCommitFormat()\n --> SUCCESSFUL\n"); 693 return B_OK; 694 } 695 696 697 status_t 698 UVCCamDevice::_SelectBestAlternate() 699 { 700 printf("UVCCamDevice::_SelectBestAlternate()\n"); 701 const BUSBConfiguration* config = fDevice->ActiveConfiguration(); 702 const BUSBInterface* streaming = config->InterfaceAt(fStreamingIndex); 703 if (streaming == NULL) 704 return B_BAD_INDEX; 705 706 uint32 bestBandwidth = 0; 707 uint32 alternateIndex = 0; 708 uint32 endpointIndex = 0; 709 710 for (uint32 i = 0; i < streaming->CountAlternates(); i++) { 711 const BUSBInterface* alternate = streaming->AlternateAt(i); 712 for (uint32 j = 0; j < alternate->CountEndpoints(); j++) { 713 const BUSBEndpoint* endpoint = alternate->EndpointAt(j); 714 if (!endpoint->IsIsochronous() || !endpoint->IsInput()) 715 continue; 716 if (fMaxPayloadTransferSize > endpoint->MaxPacketSize()) 717 continue; 718 if (bestBandwidth != 0 719 && bestBandwidth < endpoint->MaxPacketSize()) 720 continue; 721 bestBandwidth = endpoint->MaxPacketSize(); 722 endpointIndex = j; 723 alternateIndex = i; 724 } 725 } 726 727 if (bestBandwidth == 0) { 728 fprintf(stderr, "UVCCamDevice::_SelectBestAlternate()" 729 " couldn't find a valid alternate\n"); 730 return B_ERROR; 731 } 732 733 printf("UVCCamDevice::_SelectBestAlternate() %ld\n", bestBandwidth); 734 if (((BUSBInterface*)streaming)->SetAlternate(alternateIndex) != B_OK) { 735 fprintf(stderr, "UVCCamDevice::_SelectBestAlternate()" 736 " selecting alternate failed\n"); 737 return B_ERROR; 738 } 739 740 fIsoIn = streaming->EndpointAt(endpointIndex); 741 742 return B_OK; 743 } 744 745 746 status_t 747 UVCCamDevice::_SelectIdleAlternate() 748 { 749 printf("UVCCamDevice::_SelectIdleAlternate()\n"); 750 const BUSBConfiguration* config = fDevice->ActiveConfiguration(); 751 const BUSBInterface* streaming = config->InterfaceAt(fStreamingIndex); 752 if (streaming == NULL) 753 return B_BAD_INDEX; 754 if (((BUSBInterface*)streaming)->SetAlternate(0) != B_OK) { 755 fprintf(stderr, "UVCCamDevice::_SelectIdleAlternate()" 756 " selecting alternate failed\n"); 757 return B_ERROR; 758 } 759 760 fIsoIn = NULL; 761 762 return B_OK; 763 } 764 765 766 void 767 UVCCamDevice::_AddProcessingParameter(BParameterGroup* group, 768 int32 index, const usbvc_processing_unit_descriptor* descriptor) 769 { 770 BParameterGroup* subgroup; 771 BContinuousParameter* p; 772 uint16 wValue = 0; // Control Selector 773 float minValue = 0.0; 774 float maxValue = 100.0; 775 if (descriptor->controlSize >= 1) { 776 if (descriptor->controls[0] & 1) { 777 // debug_printf("\tBRIGHTNESS\n"); 778 fBrightness = _AddParameter(group, &subgroup, index, 779 PU_BRIGHTNESS_CONTROL, "Brightness"); 780 } 781 if (descriptor->controls[0] & 2) { 782 // debug_printf("\tCONSTRAST\n"); 783 fContrast = _AddParameter(group, &subgroup, index + 1, 784 PU_CONTRAST_CONTROL, "Contrast"); 785 } 786 if (descriptor->controls[0] & 4) { 787 // debug_printf("\tHUE\n"); 788 fHue = _AddParameter(group, &subgroup, index + 2, 789 PU_HUE_CONTROL, "Hue"); 790 if (descriptor->controlSize >= 2) { 791 if (descriptor->controls[1] & 8) { 792 fHueAuto = _AddAutoParameter(subgroup, index + 3, 793 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL); 794 } 795 } 796 } 797 if (descriptor->controls[0] & 8) { 798 // debug_printf("\tSATURATION\n"); 799 fSaturation = _AddParameter(group, &subgroup, index + 4, 800 PU_SATURATION_CONTROL, "Saturation"); 801 } 802 if (descriptor->controls[0] & 16) { 803 // debug_printf("\tSHARPNESS\n"); 804 fSharpness = _AddParameter(group, &subgroup, index + 5, 805 PU_SHARPNESS_CONTROL, "Sharpness"); 806 } 807 if (descriptor->controls[0] & 32) { 808 // debug_printf("\tGamma\n"); 809 fGamma = _AddParameter(group, &subgroup, index + 6, 810 PU_GAMMA_CONTROL, "Gamma"); 811 } 812 if (descriptor->controls[0] & 64) { 813 // debug_printf("\tWHITE BALANCE TEMPERATURE\n"); 814 fWBTemp = _AddParameter(group, &subgroup, index + 7, 815 PU_WHITE_BALANCE_TEMPERATURE_CONTROL, "WB Temperature"); 816 if (descriptor->controlSize >= 2) { 817 if (descriptor->controls[1] & 16) { 818 fWBTempAuto = _AddAutoParameter(subgroup, index + 8, 819 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL); 820 } 821 } 822 } 823 if (descriptor->controls[0] & 128) { 824 // debug_printf("\tWhite Balance Component\n"); 825 fWBComponent = _AddParameter(group, &subgroup, index + 9, 826 PU_WHITE_BALANCE_COMPONENT_CONTROL, "WB Component"); 827 if (descriptor->controlSize >= 2) { 828 if (descriptor->controls[1] & 32) { 829 fWBTempAuto = _AddAutoParameter(subgroup, index + 10, 830 PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL); 831 } 832 } 833 } 834 } 835 if (descriptor->controlSize >= 2) { 836 if (descriptor->controls[1] & 1) { 837 // debug_printf("\tBACKLIGHT COMPENSATION\n"); 838 int16 data; 839 wValue = PU_BACKLIGHT_COMPENSATION_CONTROL << 8; 840 fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 841 GET_MAX, wValue, fControlRequestIndex, sizeof(data), &data); 842 maxValue = (float)data; 843 fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 844 GET_MIN, wValue, fControlRequestIndex, sizeof(data), &data); 845 minValue = (float)data; 846 fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 847 GET_CUR, wValue, fControlRequestIndex, sizeof(data), &data); 848 fBacklightCompensation = (float)data; 849 subgroup = group->MakeGroup("Backlight Compensation"); 850 if (maxValue - minValue == 1) { // Binary Switch 851 fBinaryBacklightCompensation = true; 852 subgroup->MakeDiscreteParameter(index + 11, 853 B_MEDIA_RAW_VIDEO, "Backlight Compensation", 854 B_ENABLE); 855 } else { // Range of values 856 fBinaryBacklightCompensation = false; 857 p = subgroup->MakeContinuousParameter(index + 11, 858 B_MEDIA_RAW_VIDEO, "Backlight Compensation", 859 B_GAIN, "", minValue, maxValue, 1.0 / (maxValue - minValue)); 860 } 861 } 862 if (descriptor->controls[1] & 2) { 863 // debug_printf("\tGAIN\n"); 864 fGain = _AddParameter(group, &subgroup, index + 12, PU_GAIN_CONTROL, 865 "Gain"); 866 } 867 if (descriptor->controls[1] & 4) { 868 // debug_printf("\tPOWER LINE FREQUENCY\n"); 869 wValue = PU_POWER_LINE_FREQUENCY_CONTROL << 8; 870 int8 data; 871 if (fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 872 GET_CUR, wValue, fControlRequestIndex, sizeof(data), &data) == sizeof(data)) { 873 fPowerlineFrequency = data; 874 } 875 subgroup = group->MakeGroup("Power Line Frequency"); 876 p = subgroup->MakeContinuousParameter(index + 13, 877 B_MEDIA_RAW_VIDEO, "Frequency", B_GAIN, "", 0, 60.0, 1.0 / 60.0); 878 } 879 // TODO Determine whether controls apply to these 880 /* 881 if (descriptor->controls[1] & 64) 882 debug_printf("\tDigital Multiplier\n"); 883 if (descriptor->controls[1] & 128) 884 debug_printf("\tDigital Multiplier Limit\n"); 885 */ 886 } 887 // TODO Determine whether controls apply to these 888 /* 889 if (descriptor->controlSize >= 3) { 890 if (descriptor->controls[2] & 1) 891 debug_printf("\tAnalog Video Standard\n"); 892 if (descriptor->controls[2] & 2) 893 debug_printf("\tAnalog Video Lock Status\n"); 894 } 895 */ 896 897 } 898 899 900 901 float 902 UVCCamDevice::_AddParameter(BParameterGroup* group, 903 BParameterGroup** subgroup, int32 index, uint16 wValue, const char* name) 904 { 905 float minValue = 0.0; 906 float maxValue = 100.0; 907 float currValue = 0.0; 908 int16 data; 909 910 wValue <<= 8; 911 912 if (fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 913 GET_MAX, wValue, fControlRequestIndex, sizeof(data), &data) 914 == sizeof(data)) { 915 maxValue = (float)data; 916 } 917 if (fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 918 GET_MIN, wValue, fControlRequestIndex, sizeof(data), &data) 919 == sizeof(data)) { 920 minValue = (float)data; 921 } 922 if (fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 923 GET_CUR, wValue, fControlRequestIndex, sizeof(data), &data) 924 == sizeof(data)) { 925 currValue = (float)data; 926 } 927 928 *subgroup = group->MakeGroup(name); 929 BContinuousParameter* p = (*subgroup)->MakeContinuousParameter(index, 930 B_MEDIA_RAW_VIDEO, name, B_GAIN, "", minValue, maxValue, 931 1.0 / (maxValue - minValue)); 932 return currValue; 933 } 934 935 936 uint8 937 UVCCamDevice::_AddAutoParameter(BParameterGroup* subgroup, int32 index, 938 uint16 wValue) 939 { 940 uint8 data; 941 wValue <<= 8; 942 943 fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 944 GET_CUR, wValue, fControlRequestIndex, 1, &data); 945 subgroup->MakeDiscreteParameter(index, B_MEDIA_RAW_VIDEO, "Auto", 946 B_ENABLE); 947 948 return data; 949 } 950 951 952 void 953 UVCCamDevice::AddParameters(BParameterGroup* group, int32& index) 954 { 955 printf("UVCCamDevice::AddParameters()\n"); 956 fFirstParameterID = index; 957 // debug_printf("fIndex = %d\n",fIndex); 958 CamDevice::AddParameters(group, index); 959 960 const BUSBConfiguration* config; 961 const BUSBInterface* interface; 962 uint8 buffer[1024]; 963 964 usb_descriptor* generic = (usb_descriptor*)buffer; 965 966 for (uint32 i = 0; i < fDevice->CountConfigurations(); i++) { 967 config = fDevice->ConfigurationAt(i); 968 if (config == NULL) 969 continue; 970 fDevice->SetConfiguration(config); 971 for (uint32 j = 0; j < config->CountInterfaces(); j++) { 972 interface = config->InterfaceAt(j); 973 if (interface == NULL) 974 continue; 975 if (interface->Class() != CC_VIDEO || interface->Subclass() 976 != SC_VIDEOCONTROL) 977 continue; 978 for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 979 sizeof(buffer)) == B_OK; k++) { 980 if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 981 | USB_DESCRIPTOR_INTERFACE)) 982 continue; 983 984 if (((const usbvc_class_descriptor*)generic)->descriptorSubtype 985 == VC_PROCESSING_UNIT) { 986 _AddProcessingParameter(group, index, 987 (const usbvc_processing_unit_descriptor*)generic); 988 } 989 } 990 } 991 } 992 } 993 994 995 status_t 996 UVCCamDevice::GetParameterValue(int32 id, bigtime_t* last_change, void* value, 997 size_t* size) 998 { 999 printf("UVCCAmDevice::GetParameterValue(%ld)\n", id - fFirstParameterID); 1000 float* currValue; 1001 int* currValueInt; 1002 int16 data; 1003 uint16 wValue = 0; 1004 switch (id - fFirstParameterID) { 1005 case 0: 1006 // debug_printf("\tBrightness:\n"); 1007 // debug_printf("\tValue = %f\n",fBrightness); 1008 *size = sizeof(float); 1009 currValue = (float*)value; 1010 *currValue = fBrightness; 1011 *last_change = fLastParameterChanges; 1012 return B_OK; 1013 case 1: 1014 // debug_printf("\tContrast:\n"); 1015 // debug_printf("\tValue = %f\n",fContrast); 1016 *size = sizeof(float); 1017 currValue = (float*)value; 1018 *currValue = fContrast; 1019 *last_change = fLastParameterChanges; 1020 return B_OK; 1021 case 2: 1022 // debug_printf("\tHue:\n"); 1023 // debug_printf("\tValue = %f\n",fHue); 1024 *size = sizeof(float); 1025 currValue = (float*)value; 1026 *currValue = fHue; 1027 *last_change = fLastParameterChanges; 1028 return B_OK; 1029 case 4: 1030 // debug_printf("\tSaturation:\n"); 1031 // debug_printf("\tValue = %f\n",fSaturation); 1032 *size = sizeof(float); 1033 currValue = (float*)value; 1034 *currValue = fSaturation; 1035 *last_change = fLastParameterChanges; 1036 return B_OK; 1037 case 5: 1038 // debug_printf("\tSharpness:\n"); 1039 // debug_printf("\tValue = %f\n",fSharpness); 1040 *size = sizeof(float); 1041 currValue = (float*)value; 1042 *currValue = fSharpness; 1043 *last_change = fLastParameterChanges; 1044 return B_OK; 1045 case 7: 1046 // debug_printf("\tWB Temperature:\n"); 1047 *size = sizeof(float); 1048 currValue = (float*)value; 1049 wValue = PU_WHITE_BALANCE_TEMPERATURE_CONTROL << 8; 1050 if (fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, 1051 GET_CUR, wValue, fControlRequestIndex, sizeof(data), &data) 1052 == sizeof(data)) { 1053 fWBTemp = (float)data; 1054 } 1055 // debug_printf("\tValue = %f\n",fWBTemp); 1056 *currValue = fWBTemp; 1057 *last_change = fLastParameterChanges; 1058 return B_OK; 1059 case 8: 1060 // debug_printf("\tWB Temperature Auto:\n"); 1061 // debug_printf("\tValue = %d\n",fWBTempAuto); 1062 *size = sizeof(int); 1063 currValueInt = ((int*)value); 1064 *currValueInt = fWBTempAuto; 1065 *last_change = fLastParameterChanges; 1066 return B_OK; 1067 case 11: 1068 if (!fBinaryBacklightCompensation) { 1069 // debug_printf("\tBacklight Compensation:\n"); 1070 // debug_printf("\tValue = %f\n",fBacklightCompensation); 1071 *size = sizeof(float); 1072 currValue = (float*)value; 1073 *currValue = fBacklightCompensation; 1074 *last_change = fLastParameterChanges; 1075 } else { 1076 // debug_printf("\tBacklight Compensation:\n"); 1077 // debug_printf("\tValue = %d\n",fBacklightCompensationBinary); 1078 currValueInt = (int*)value; 1079 *currValueInt = fBacklightCompensationBinary; 1080 *last_change = fLastParameterChanges; 1081 } 1082 return B_OK; 1083 case 12: 1084 // debug_printf("\tGain:\n"); 1085 // debug_printf("\tValue = %f\n",fGain); 1086 *size = sizeof(float); 1087 currValue = (float*)value; 1088 *currValue = fGain; 1089 *last_change = fLastParameterChanges; 1090 return B_OK; 1091 case 13: 1092 // debug_printf("\tPowerline Frequency:\n"); 1093 // debug_printf("\tValue = %d\n",fPowerlineFrequency); 1094 *size = sizeof(float); 1095 currValue = (float*)value; 1096 switch (fPowerlineFrequency) { 1097 case 0: 1098 *currValue = 0.0; 1099 break; 1100 case 1: 1101 *currValue = 50.0; 1102 break; 1103 case 2: 1104 *currValue = 60.0; 1105 break; 1106 } 1107 *last_change = fLastParameterChanges; 1108 return B_OK; 1109 1110 } 1111 return B_BAD_VALUE; 1112 } 1113 1114 1115 status_t 1116 UVCCamDevice::SetParameterValue(int32 id, bigtime_t when, const void* value, 1117 size_t size) 1118 { 1119 printf("UVCCamDevice::SetParameterValue(%ld)\n", id - fFirstParameterID); 1120 switch (id - fFirstParameterID) { 1121 case 0: 1122 // debug_printf("\tBrightness:\n"); 1123 if (!value || (size != sizeof(float))) 1124 return B_BAD_VALUE; 1125 fBrightness = *((float*)value); 1126 fLastParameterChanges = when; 1127 return _SetParameterValue(PU_BRIGHTNESS_CONTROL, (int16)fBrightness); 1128 case 1: 1129 // debug_printf("\tContrast:\n"); 1130 if (!value || (size != sizeof(float))) 1131 return B_BAD_VALUE; 1132 fContrast = *((float*)value); 1133 fLastParameterChanges = when; 1134 return _SetParameterValue(PU_CONTRAST_CONTROL, (int16)fContrast); 1135 case 2: 1136 // debug_printf("\tHue:\n"); 1137 if (!value || (size != sizeof(float))) 1138 return B_BAD_VALUE; 1139 fHue = *((float*)value); 1140 fLastParameterChanges = when; 1141 return _SetParameterValue(PU_HUE_CONTROL, (int16)fHue); 1142 case 4: 1143 // debug_printf("\tSaturation:\n"); 1144 if (!value || (size != sizeof(float))) 1145 return B_BAD_VALUE; 1146 fSaturation = *((float*)value); 1147 fLastParameterChanges = when; 1148 return _SetParameterValue(PU_SATURATION_CONTROL, (int16)fSaturation); 1149 case 5: 1150 // debug_printf("\tSharpness:\n"); 1151 if (!value || (size != sizeof(float))) 1152 return B_BAD_VALUE; 1153 fSharpness = *((float*)value); 1154 fLastParameterChanges = when; 1155 return _SetParameterValue(PU_SHARPNESS_CONTROL, (int16)fSharpness); 1156 case 7: 1157 if (fWBTempAuto) 1158 return B_OK; 1159 // debug_printf("\tWB Temperature:\n"); 1160 if (!value || (size != sizeof(float))) 1161 return B_BAD_VALUE; 1162 fWBTemp = *((float*)value); 1163 fLastParameterChanges = when; 1164 return _SetParameterValue(PU_WHITE_BALANCE_TEMPERATURE_CONTROL, 1165 (int16)fWBTemp); 1166 case 8: 1167 // debug_printf("\tWB Temperature Auto:\n"); 1168 if (!value || (size != sizeof(int))) 1169 return B_BAD_VALUE; 1170 fWBTempAuto = *((int*)value); 1171 fLastParameterChanges = when; 1172 return _SetParameterValue( 1173 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, (int8)fWBTempAuto); 1174 case 11: 1175 if (!fBinaryBacklightCompensation) { 1176 // debug_printf("\tBacklight Compensation:\n"); 1177 if (!value || (size != sizeof(float))) 1178 return B_BAD_VALUE; 1179 fBacklightCompensation = *((float*)value); 1180 } else { 1181 // debug_printf("\tBacklight Compensation:\n"); 1182 if (!value || (size != sizeof(int))) 1183 return B_BAD_VALUE; 1184 fBacklightCompensationBinary = *((int*)value); 1185 } 1186 fLastParameterChanges = when; 1187 return _SetParameterValue(PU_BACKLIGHT_COMPENSATION_CONTROL, 1188 (int16)fBacklightCompensationBinary); 1189 case 12: 1190 // debug_printf("\tGain:\n"); 1191 if (!value || (size != sizeof(float))) 1192 return B_BAD_VALUE; 1193 fGain = *((float*)value); 1194 fLastParameterChanges = when; 1195 return _SetParameterValue(PU_GAIN_CONTROL, (int16)fGain); 1196 case 13: 1197 // debug_printf("\tPowerline Frequency:\n"); 1198 // debug_printf("\tValue = %f\n",*((float*)value)); 1199 if (!value || (size != sizeof(float))) 1200 return B_BAD_VALUE; 1201 float inValue = *((float*)value); 1202 fPowerlineFrequency = 0; 1203 if (inValue > 45.0 && inValue < 55.0) { 1204 fPowerlineFrequency = 1; 1205 } 1206 if (inValue >= 55.0) { 1207 fPowerlineFrequency = 2; 1208 } 1209 fLastParameterChanges = when; 1210 return _SetParameterValue(PU_POWER_LINE_FREQUENCY_CONTROL, 1211 (int8)fPowerlineFrequency); 1212 1213 } 1214 return B_BAD_VALUE; 1215 } 1216 1217 1218 status_t 1219 UVCCamDevice::_SetParameterValue(uint16 wValue, int16 setValue) 1220 { 1221 return (fDevice->ControlTransfer(USB_REQTYPE_CLASS 1222 | USB_REQTYPE_INTERFACE_OUT, SET_CUR, wValue << 8, fControlRequestIndex, 1223 sizeof(setValue), &setValue)) == sizeof(setValue); 1224 } 1225 1226 1227 status_t 1228 UVCCamDevice::_SetParameterValue(uint16 wValue, int8 setValue) 1229 { 1230 return (fDevice->ControlTransfer(USB_REQTYPE_CLASS 1231 | USB_REQTYPE_INTERFACE_OUT, SET_CUR, wValue << 8, fControlRequestIndex, 1232 sizeof(setValue), &setValue)) == sizeof(setValue); 1233 } 1234 1235 1236 status_t 1237 UVCCamDevice::FillFrameBuffer(BBuffer* buffer, bigtime_t* stamp) 1238 { 1239 memset(buffer->Data(), 0, buffer->SizeAvailable()); 1240 status_t err = fDeframer->WaitFrame(2000000); 1241 if (err < B_OK) { 1242 fprintf(stderr, "WaitFrame: %lx\n", err); 1243 return err; 1244 } 1245 1246 CamFrame* f; 1247 err = fDeframer->GetFrame(&f, stamp); 1248 if (err < B_OK) { 1249 fprintf(stderr, "GetFrame: %lx\n", err); 1250 return err; 1251 } 1252 1253 long int w = (long)(VideoFrame().right - VideoFrame().left + 1); 1254 long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1); 1255 1256 if (buffer->SizeAvailable() >= (size_t)w * h * 4) { 1257 // TODO: The Video Producer only outputs B_RGB32. This is OK for most 1258 // applications. This could be leveraged if applications can 1259 // consume B_YUV422. 1260 _DecodeColor((unsigned char*)buffer->Data(), 1261 (unsigned char*)f->Buffer(), w, h); 1262 } 1263 delete f; 1264 return B_OK; 1265 } 1266 1267 1268 void 1269 UVCCamDevice::_DecodeColor(unsigned char* dst, unsigned char* src, 1270 int32 width, int32 height) 1271 { 1272 long int i; 1273 unsigned char* rawpt, * scanpt; 1274 long int size; 1275 1276 rawpt = src; 1277 scanpt = dst; 1278 size = width*height; 1279 1280 for ( i = 0; i < size; i++ ) { 1281 if ( (i/width) % 2 == 0 ) { 1282 if ( (i % 2) == 0 ) { 1283 /* B */ 1284 if ( (i > width) && ((i % width) > 0) ) { 1285 *scanpt++ = (*(rawpt-width-1)+*(rawpt-width+1) 1286 + *(rawpt+width-1)+*(rawpt+width+1))/4; /* R */ 1287 *scanpt++ = (*(rawpt-1)+*(rawpt+1) 1288 + *(rawpt+width)+*(rawpt-width))/4; /* G */ 1289 *scanpt++ = *rawpt; /* B */ 1290 } else { 1291 /* first line or left column */ 1292 *scanpt++ = *(rawpt+width+1); /* R */ 1293 *scanpt++ = (*(rawpt+1)+*(rawpt+width))/2; /* G */ 1294 *scanpt++ = *rawpt; /* B */ 1295 } 1296 } else { 1297 /* (B)G */ 1298 if ( (i > width) && ((i % width) < (width-1)) ) { 1299 *scanpt++ = (*(rawpt+width)+*(rawpt-width))/2; /* R */ 1300 *scanpt++ = *rawpt; /* G */ 1301 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */ 1302 } else { 1303 /* first line or right column */ 1304 *scanpt++ = *(rawpt+width); /* R */ 1305 *scanpt++ = *rawpt; /* G */ 1306 *scanpt++ = *(rawpt-1); /* B */ 1307 } 1308 } 1309 } else { 1310 if ( (i % 2) == 0 ) { 1311 /* G(R) */ 1312 if ( (i < (width*(height-1))) && ((i % width) > 0) ) { 1313 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */ 1314 *scanpt++ = *rawpt; /* G */ 1315 *scanpt++ = (*(rawpt+width)+*(rawpt-width))/2; /* B */ 1316 } else { 1317 /* bottom line or left column */ 1318 *scanpt++ = *(rawpt+1); /* R */ 1319 *scanpt++ = *rawpt; /* G */ 1320 *scanpt++ = *(rawpt-width); /* B */ 1321 } 1322 } else { 1323 /* R */ 1324 if ( i < (width*(height-1)) && ((i % width) < (width-1)) ) { 1325 *scanpt++ = *rawpt; /* R */ 1326 *scanpt++ = (*(rawpt-1)+*(rawpt+1) 1327 + *(rawpt-width)+*(rawpt+width))/4; /* G */ 1328 *scanpt++ = (*(rawpt-width-1)+*(rawpt-width+1) 1329 + *(rawpt+width-1)+*(rawpt+width+1))/4; /* B */ 1330 } else { 1331 /* bottom line or right column */ 1332 *scanpt++ = *rawpt; /* R */ 1333 *scanpt++ = (*(rawpt-1)+*(rawpt-width))/2; /* G */ 1334 *scanpt++ = *(rawpt-width-1); /* B */ 1335 } 1336 } 1337 } 1338 rawpt++; 1339 } 1340 } 1341 1342 1343 1344 1345 UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam) 1346 : CamDeviceAddon(webcam) 1347 { 1348 printf("UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam)\n"); 1349 SetSupportedDevices(kSupportedDevices); 1350 } 1351 1352 1353 UVCCamDeviceAddon::~UVCCamDeviceAddon() 1354 { 1355 } 1356 1357 1358 const char * 1359 UVCCamDeviceAddon::BrandName() 1360 { 1361 printf("UVCCamDeviceAddon::BrandName()\n"); 1362 return "USB Video Class"; 1363 } 1364 1365 1366 UVCCamDevice * 1367 UVCCamDeviceAddon::Instantiate(CamRoster& roster, BUSBDevice* from) 1368 { 1369 printf("UVCCamDeviceAddon::Instantiate()\n"); 1370 return new UVCCamDevice(*this, from); 1371 } 1372 1373 1374 extern "C" status_t 1375 B_WEBCAM_MKINTFUNC(uvccam) 1376 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 1377 { 1378 *addon = new UVCCamDeviceAddon(webcam); 1379 return B_OK; 1380 } 1381