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