1242723Sjhibbits/* 2242723Sjhibbits * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com. 3242723Sjhibbits * Copyright 2011, J��r��me Duval, korli@users.berlios.de. 4242723Sjhibbits * Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>. 5242723Sjhibbits * Distributed under the terms of the MIT License. 6242723Sjhibbits */ 7242723Sjhibbits 8242723Sjhibbits 9242723Sjhibbits#include "UVCCamDevice.h" 10242723Sjhibbits#include "UVCDeframer.h" 11242723Sjhibbits 12242723Sjhibbits#include <stdio.h> 13242723Sjhibbits#include <stdlib.h> 14242723Sjhibbits#include <ParameterWeb.h> 15242723Sjhibbits#include <media/Buffer.h> 16242723Sjhibbits 17242723Sjhibbits 18242723Sjhibbitsusb_webcam_support_descriptor kSupportedDevices[] = { 19242723Sjhibbits // ofcourse we support a generic UVC device... 20242723Sjhibbits {{ CC_VIDEO, SC_VIDEOCONTROL, 0, 0, 0 }, "Generic UVC", "Video Class", "??" }, 21260670Sjhibbits // ...whilst the following IDs were 'stolen' from a recent Linux driver: 22242723Sjhibbits {{ 0, 0, 0, 0x045e, 0x00f8, }, "Microsoft", "Lifecam NX-6000", "??" }, 23242723Sjhibbits {{ 0, 0, 0, 0x045e, 0x0723, }, "Microsoft", "Lifecam VX-7000", "??" }, 24242723Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c1, }, "Logitech", "QuickCam Fusion", "??" }, 25242723Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c2, }, "Logitech", "QuickCam Orbit MP", "??" }, 26242723Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c3, }, "Logitech", "QuickCam Pro for Notebook", "??" }, 27260670Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c5, }, "Logitech", "QuickCam Pro 5000", "??" }, 28260670Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c6, }, "Logitech", "QuickCam OEM Dell Notebook", "??" }, 29260670Sjhibbits {{ 0, 0, 0, 0x046d, 0x08c7, }, "Logitech", "QuickCam OEM Cisco VT Camera II", "??" }, 30260670Sjhibbits {{ 0, 0, 0, 0x046d, 0x0821, }, "Logitech", "HD Pro Webcam C910", "??" }, 31260670Sjhibbits {{ 0, 0, 0, 0x05ac, 0x8501, }, "Apple", "Built-In iSight", "??" }, 32260670Sjhibbits {{ 0, 0, 0, 0x05e3, 0x0505, }, "Genesys Logic", "USB 2.0 PC Camera", "??" }, 33260670Sjhibbits {{ 0, 0, 0, 0x0e8d, 0x0004, }, "N/A", "MT6227", "??" }, 34260670Sjhibbits {{ 0, 0, 0, 0x174f, 0x5212, }, "Syntek", "(HP Spartan)", "??" }, 35260670Sjhibbits {{ 0, 0, 0, 0x174f, 0x5931, }, "Syntek", "(Samsung Q310)", "??" }, 36299003Smarkj {{ 0, 0, 0, 0x174f, 0x8a31, }, "Syntek", "Asus F9SG", "??" }, 37260670Sjhibbits {{ 0, 0, 0, 0x174f, 0x8a33, }, "Syntek", "Asus U3S", "??" }, 38242723Sjhibbits {{ 0, 0, 0, 0x17ef, 0x480b, }, "N/A", "Lenovo Thinkpad SL500", "??" }, 39260670Sjhibbits {{ 0, 0, 0, 0x18cd, 0xcafe, }, "Ecamm", "Pico iMage", "??" }, 40260670Sjhibbits {{ 0, 0, 0, 0x19ab, 0x1000, }, "Bodelin", "ProScopeHR", "??" }, 41260670Sjhibbits {{ 0, 0, 0, 0x1c4f, 0x3000, }, "SiGma Micro", "USB Web Camera", "??" }, 42260670Sjhibbits {{ 0, 0, 0, 0, 0}, NULL, NULL, NULL } 43260670Sjhibbits}; 44260670Sjhibbits 45260670Sjhibbits/* Table 2-1 Compression Formats of USB Video Payload Uncompressed */ 46260670Sjhibbitsusbvc_guid kYUY2Guid = {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 47260670Sjhibbits 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 48260670Sjhibbitsusbvc_guid kNV12Guid = {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 49260670Sjhibbits 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; 50260670Sjhibbits 51260670Sjhibbitsstatic void 52260670Sjhibbitsprint_guid(const usbvc_guid guid) 53260670Sjhibbits{ 54260670Sjhibbits if (!memcmp(guid, kYUY2Guid, sizeof(usbvc_guid))) 55260670Sjhibbits printf("YUY2"); 56260670Sjhibbits else if (!memcmp(guid, kNV12Guid, sizeof(usbvc_guid))) 57260670Sjhibbits printf("NV12"); 58260670Sjhibbits else { 59260670Sjhibbits printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" 60260670Sjhibbits "%02x:%02x:%02x:%02x", guid[0], guid[1], guid[2], guid[3], guid[4], 61260670Sjhibbits guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], 62260670Sjhibbits guid[12], guid[13], guid[14], guid[15]); 63260670Sjhibbits } 64269756Smarkj} 65260670Sjhibbits 66260670Sjhibbits 67260670SjhibbitsUVCCamDevice::UVCCamDevice(CamDeviceAddon& _addon, BUSBDevice* _device) 68260670Sjhibbits : CamDevice(_addon, _device), 69260670Sjhibbits fHeaderDescriptor(NULL), 70260670Sjhibbits fInterruptIn(NULL), 71260670Sjhibbits fUncompressedFormatIndex(1), 72260670Sjhibbits fUncompressedFrameIndex(1) 73260670Sjhibbits{ 74260670Sjhibbits fDeframer = new UVCDeframer(this); 75260670Sjhibbits SetDataInput(fDeframer); 76260670Sjhibbits 77260670Sjhibbits const BUSBConfiguration* config; 78260670Sjhibbits const BUSBInterface* interface; 79260670Sjhibbits usb_descriptor* generic; 80260670Sjhibbits uint8 buffer[1024]; 81260670Sjhibbits 82260670Sjhibbits generic = (usb_descriptor*)buffer; 83260670Sjhibbits 84260670Sjhibbits for (uint32 i = 0; i < _device->CountConfigurations(); i++) { 85260670Sjhibbits config = _device->ConfigurationAt(i); 86260670Sjhibbits _device->SetConfiguration(config); 87260670Sjhibbits for (uint32 j = 0; j < config->CountInterfaces(); j++) { 88260670Sjhibbits interface = config->InterfaceAt(j); 89260670Sjhibbits 90260670Sjhibbits if (interface->Class() == CC_VIDEO && interface->Subclass() 91260670Sjhibbits == SC_VIDEOCONTROL) { 92260670Sjhibbits printf("UVCCamDevice: (%lu,%lu): Found Video Control " 93260670Sjhibbits "interface.\n", i, j); 94260670Sjhibbits 95260670Sjhibbits // look for class specific interface descriptors and parse them 96260670Sjhibbits for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 97260670Sjhibbits sizeof(buffer)) == B_OK; k++) { 98260670Sjhibbits if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 99260670Sjhibbits | USB_DESCRIPTOR_INTERFACE)) 100260670Sjhibbits continue; 101260670Sjhibbits fControlIndex = interface->Index(); 102260670Sjhibbits _ParseVideoControl((const usbvc_class_descriptor*)generic, 103260670Sjhibbits generic->generic.length); 104260670Sjhibbits } 105260670Sjhibbits for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 106260670Sjhibbits const BUSBEndpoint* e = interface->EndpointAt(i); 107260670Sjhibbits if (e && e->IsInterrupt() && e->IsInput()) { 108260670Sjhibbits fInterruptIn = e; 109260670Sjhibbits break; 110260670Sjhibbits } 111260670Sjhibbits } 112260670Sjhibbits fInitStatus = B_OK; 113260670Sjhibbits } else if (interface->Class() == CC_VIDEO && interface->Subclass() 114260670Sjhibbits == SC_VIDEOSTREAMING) { 115260670Sjhibbits printf("UVCCamDevice: (%lu,%lu): Found Video Streaming " 116260670Sjhibbits "interface.\n", i, j); 117260670Sjhibbits 118260670Sjhibbits // look for class specific interface descriptors and parse them 119260670Sjhibbits for (uint32 k = 0; interface->OtherDescriptorAt(k, generic, 120260670Sjhibbits sizeof(buffer)) == B_OK; k++) { 121260670Sjhibbits if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS 122260670Sjhibbits | USB_DESCRIPTOR_INTERFACE)) 123260670Sjhibbits continue; 124260670Sjhibbits fStreamingIndex = interface->Index(); 125260670Sjhibbits _ParseVideoStreaming((const usbvc_class_descriptor*)generic, 126260670Sjhibbits generic->generic.length); 127260670Sjhibbits } 128260670Sjhibbits 129260670Sjhibbits for (uint32 k = 0; k < interface->CountEndpoints(); k++) { 130260670Sjhibbits const BUSBEndpoint* e = interface->EndpointAt(i); 131260670Sjhibbits if (e && e->IsIsochronous() && e->IsInput()) { 132260670Sjhibbits fIsoIn = e; 133260670Sjhibbits break; 134260670Sjhibbits } 135260670Sjhibbits } 136260670Sjhibbits } 137260670Sjhibbits } 138260670Sjhibbits } 139260670Sjhibbits} 140260670Sjhibbits 141260670Sjhibbits 142260670SjhibbitsUVCCamDevice::~UVCCamDevice() 143260670Sjhibbits{ 144260670Sjhibbits free(fHeaderDescriptor); 145260670Sjhibbits} 146260670Sjhibbits 147260670Sjhibbits 148260670Sjhibbitsvoid 149260670SjhibbitsUVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor, 150260670Sjhibbits size_t len) 151260670Sjhibbits{ 152260670Sjhibbits switch (_descriptor->descriptorSubtype) { 153260670Sjhibbits case VS_INPUT_HEADER: 154260670Sjhibbits { 155260670Sjhibbits const usbvc_input_header_descriptor* descriptor 156260670Sjhibbits = (const usbvc_input_header_descriptor*)_descriptor; 157260670Sjhibbits printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor->numFormats, 158260670Sjhibbits descriptor->endpointAddress); 159260670Sjhibbits if (descriptor->info & 1) 160260670Sjhibbits printf("\tDynamic Format Change supported\n"); 161260670Sjhibbits printf("\toutput terminal id=%d\n", descriptor->terminalLink); 162260670Sjhibbits printf("\tstill capture method=%d\n", descriptor->stillCaptureMethod); 163260670Sjhibbits if (descriptor->triggerSupport) { 164260670Sjhibbits printf("\ttrigger button fixed to still capture=%s\n", 165260670Sjhibbits descriptor->triggerUsage ? "no" : "yes"); 166260670Sjhibbits } 167260670Sjhibbits const uint8* controls = descriptor->controls; 168260670Sjhibbits for (uint8 i = 0; i < descriptor->numFormats; i++, 169260670Sjhibbits controls += descriptor->controlSize) { 170260670Sjhibbits printf("\tfmt%d: %s %s %s %s - %s %s\n", i, 171260670Sjhibbits (*controls & 1) ? "wKeyFrameRate" : "", 172260670Sjhibbits (*controls & 2) ? "wPFrameRate" : "", 173260670Sjhibbits (*controls & 4) ? "wCompQuality" : "", 174260670Sjhibbits (*controls & 8) ? "wCompWindowSize" : "", 175260670Sjhibbits (*controls & 16) ? "<Generate Key Frame>" : "", 176260670Sjhibbits (*controls & 32) ? "<Update Frame Segment>" : ""); 177260670Sjhibbits } 178260670Sjhibbits break; 179260670Sjhibbits } 180260670Sjhibbits case VS_FORMAT_UNCOMPRESSED: 181260670Sjhibbits { 182260670Sjhibbits const usbvc_format_descriptor* descriptor 183260670Sjhibbits = (const usbvc_format_descriptor*)_descriptor; 184260670Sjhibbits fUncompressedFormatIndex = descriptor->formatIndex; 185260670Sjhibbits printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=", 186260670Sjhibbits descriptor->formatIndex, descriptor->numFrameDescriptors); 187260670Sjhibbits print_guid(descriptor->uncompressed.format); 188260670Sjhibbits printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 189260670Sjhibbits descriptor->uncompressed.bytesPerPixel, 190260670Sjhibbits descriptor->uncompressed.defaultFrameIndex, 191260670Sjhibbits descriptor->uncompressed.aspectRatioX, 192260670Sjhibbits descriptor->uncompressed.aspectRatioY); 193260670Sjhibbits printf("\tbmInterlaceFlags:\n"); 194260670Sjhibbits if (descriptor->uncompressed.interlaceFlags & 1) 195260670Sjhibbits printf("\tInterlaced stream or variable\n"); 196260670Sjhibbits printf("\t%d fields per frame\n", 197260670Sjhibbits (descriptor->uncompressed.interlaceFlags & 2) ? 1 : 2); 198260670Sjhibbits if (descriptor->uncompressed.interlaceFlags & 4) 199260670Sjhibbits printf("\tField 1 first\n"); 200260670Sjhibbits printf("\tField Pattern: "); 201260670Sjhibbits switch ((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) { 202260670Sjhibbits case 0: printf("Field 1 only\n"); break; 203260670Sjhibbits case 1: printf("Field 2 only\n"); break; 204260670Sjhibbits case 2: printf("Regular pattern of fields 1 and 2\n"); break; 205260670Sjhibbits case 3: printf("Random pattern of fields 1 and 2\n"); break; 206260670Sjhibbits } 207260670Sjhibbits if (descriptor->uncompressed.copyProtect) 208260670Sjhibbits printf("\tRestrict duplication\n"); 209260670Sjhibbits break; 210260670Sjhibbits } 211260670Sjhibbits case VS_FRAME_MJPEG: 212260670Sjhibbits case VS_FRAME_UNCOMPRESSED: 213260670Sjhibbits { 214260670Sjhibbits const usbvc_frame_descriptor* descriptor 215260670Sjhibbits = (const usbvc_frame_descriptor*)_descriptor; 216260670Sjhibbits if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED) { 217260670Sjhibbits printf("VS_FRAME_UNCOMPRESSED:"); 218260670Sjhibbits fUncompressedFrames.AddItem( 219260670Sjhibbits new usbvc_frame_descriptor(*descriptor)); 220260670Sjhibbits } else { 221260670Sjhibbits printf("VS_FRAME_MJPEG:"); 222260670Sjhibbits fMJPEGFrames.AddItem(new usbvc_frame_descriptor(*descriptor)); 223260670Sjhibbits } 224260670Sjhibbits printf("\tbFrameIdx=%d,stillsupported=%s," 225260670Sjhibbits "fixedframerate=%s\n", descriptor->frameIndex, 226260670Sjhibbits (descriptor->capabilities & 1) ? "yes" : "no", 227260670Sjhibbits (descriptor->capabilities & 2) ? "yes" : "no"); 228260670Sjhibbits printf("\twidth=%u,height=%u,min/max bitrate=%lu/%lu, maxbuf=%lu\n", 229260670Sjhibbits descriptor->width, descriptor->height, 230260670Sjhibbits descriptor->minBitRate, descriptor->maxBitRate, 231260670Sjhibbits descriptor->maxVideoFrameBufferSize); 232260670Sjhibbits printf("\tdefault frame interval: %lu, #intervals(0=cont): %d\n", 233260670Sjhibbits descriptor->defaultFrameInterval, descriptor->frameIntervalType); 234260670Sjhibbits if (descriptor->frameIntervalType == 0) { 235260670Sjhibbits printf("min/max frame interval=%lu/%lu, step=%lu\n", 236260670Sjhibbits descriptor->continuous.minFrameInterval, 237260670Sjhibbits descriptor->continuous.maxFrameInterval, 238260670Sjhibbits descriptor->continuous.frameIntervalStep); 239260670Sjhibbits } else for (uint8 i = 0; i < descriptor->frameIntervalType; i++) { 240260670Sjhibbits printf("\tdiscrete frame interval: %lu\n", 241260670Sjhibbits descriptor->discreteFrameIntervals[i]); 242260670Sjhibbits } 243260670Sjhibbits break; 244260670Sjhibbits } 245260670Sjhibbits case VS_COLORFORMAT: 246260670Sjhibbits { 247260670Sjhibbits const usbvc_color_matching_descriptor* descriptor 248260670Sjhibbits = (const usbvc_color_matching_descriptor*)_descriptor; 249260670Sjhibbits printf("VS_COLORFORMAT:\n\tbColorPrimaries: "); 250260670Sjhibbits switch (descriptor->colorPrimaries) { 251260670Sjhibbits case 0: printf("Unspecified\n"); break; 252260670Sjhibbits case 1: printf("BT.709,sRGB\n"); break; 253260670Sjhibbits case 2: printf("BT.470-2(M)\n"); break; 254260670Sjhibbits case 3: printf("BT.470-2(B,G)\n"); break; 255260670Sjhibbits case 4: printf("SMPTE 170M\n"); break; 256260670Sjhibbits case 5: printf("SMPTE 240M\n"); break; 257260670Sjhibbits default: printf("Invalid (%d)\n", descriptor->colorPrimaries); 258260670Sjhibbits } 259260670Sjhibbits printf("\tbTransferCharacteristics: "); 260260670Sjhibbits switch (descriptor->transferCharacteristics) { 261260670Sjhibbits case 0: printf("Unspecified\n"); break; 262260670Sjhibbits case 1: printf("BT.709\n"); break; 263260670Sjhibbits case 2: printf("BT.470-2(M)\n"); break; 264260670Sjhibbits case 3: printf("BT.470-2(B,G)\n"); break; 265260670Sjhibbits case 4: printf("SMPTE 170M\n"); break; 266260670Sjhibbits case 5: printf("SMPTE 240M\n"); break; 267260670Sjhibbits case 6: printf("Linear (V=Lc)\n"); break; 268260670Sjhibbits case 7: printf("sRGB\n"); break; 269260670Sjhibbits default: printf("Invalid (%d)\n", 270260670Sjhibbits descriptor->transferCharacteristics); 271260670Sjhibbits } 272260670Sjhibbits printf("\tbMatrixCoefficients: "); 273260670Sjhibbits switch (descriptor->matrixCoefficients) { 274260670Sjhibbits case 0: printf("Unspecified\n"); break; 275260670Sjhibbits case 1: printf("BT.709\n"); break; 276260670Sjhibbits case 2: printf("FCC\n"); break; 277260670Sjhibbits case 3: printf("BT.470-2(B,G)\n"); break; 278260670Sjhibbits case 4: printf("SMPTE 170M (BT.601)\n"); break; 279260670Sjhibbits case 5: printf("SMPTE 240M\n"); break; 280260670Sjhibbits default: printf("Invalid (%d)\n", descriptor->matrixCoefficients); 281260670Sjhibbits } 282260670Sjhibbits break; 283260670Sjhibbits } 284260670Sjhibbits case VS_OUTPUT_HEADER: 285260670Sjhibbits { 286260670Sjhibbits const usbvc_output_header_descriptor* descriptor 287260670Sjhibbits = (const usbvc_output_header_descriptor*)_descriptor; 288260670Sjhibbits printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n", 289260670Sjhibbits descriptor->numFormats, descriptor->endpointAddress); 290260670Sjhibbits printf("\toutput terminal id=%d\n", descriptor->terminalLink); 291260670Sjhibbits const uint8* controls = descriptor->controls; 292260670Sjhibbits for (uint8 i = 0; i < descriptor->numFormats; i++, 293260670Sjhibbits controls += descriptor->controlSize) { 294260670Sjhibbits printf("\tfmt%d: %s %s %s %s\n", i, 295260670Sjhibbits (*controls & 1) ? "wKeyFrameRate" : "", 296260670Sjhibbits (*controls & 2) ? "wPFrameRate" : "", 297260670Sjhibbits (*controls & 4) ? "wCompQuality" : "", 298260670Sjhibbits (*controls & 8) ? "wCompWindowSize" : ""); 299260670Sjhibbits } 300260670Sjhibbits break; 301260670Sjhibbits } 302260670Sjhibbits case VS_STILL_IMAGE_FRAME: 303260670Sjhibbits { 304260670Sjhibbits const usbvc_still_image_frame_descriptor* descriptor 305260670Sjhibbits = (const usbvc_still_image_frame_descriptor*)_descriptor; 306299003Smarkj printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d," 307260670Sjhibbits "ept=0x%x\n", descriptor->numImageSizePatterns, 308260670Sjhibbits descriptor->NumCompressionPatterns(), 309260670Sjhibbits descriptor->endpointAddress); 310260670Sjhibbits for (uint8 i = 0; i < descriptor->numImageSizePatterns; i++) { 311299003Smarkj printf("imageSize%d: %dx%d\n", i, 312260670Sjhibbits descriptor->imageSizePatterns[i].width, 313260670Sjhibbits descriptor->imageSizePatterns[i].height); 314260670Sjhibbits } 315260670Sjhibbits for (uint8 i = 0; i < descriptor->NumCompressionPatterns(); i++) { 316260670Sjhibbits printf("compression%d: %d\n", i, 317260670Sjhibbits descriptor->CompressionPatterns()[i]); 318260670Sjhibbits } 319260670Sjhibbits break; 320260670Sjhibbits } 321260670Sjhibbits case VS_FORMAT_MJPEG: 322260670Sjhibbits { 323260670Sjhibbits const usbvc_format_descriptor* descriptor 324260670Sjhibbits = (const usbvc_format_descriptor*)_descriptor; 325260670Sjhibbits fMJPEGFormatIndex = descriptor->formatIndex; 326299003Smarkj printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n", 327260670Sjhibbits descriptor->formatIndex, descriptor->numFrameDescriptors); 328260670Sjhibbits printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", 329260670Sjhibbits descriptor->mjpeg.flags, 330260670Sjhibbits descriptor->mjpeg.defaultFrameIndex, 331260670Sjhibbits descriptor->mjpeg.aspectRatioX, 332260670Sjhibbits descriptor->mjpeg.aspectRatioY); 333260670Sjhibbits printf("\tbmInterlaceFlags:\n"); 334260670Sjhibbits if (descriptor->mjpeg.interlaceFlags & 1) 335260670Sjhibbits printf("\tInterlaced stream or variable\n"); 336260670Sjhibbits printf("\t%d fields per frame\n", 337260670Sjhibbits (descriptor->mjpeg.interlaceFlags & 2) ? 1 : 2); 338260670Sjhibbits if (descriptor->mjpeg.interlaceFlags & 4) 339260670Sjhibbits printf("\tField 1 first\n"); 340260670Sjhibbits printf("\tField Pattern: "); 341260670Sjhibbits switch ((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) { 342260670Sjhibbits case 0: printf("Field 1 only\n"); break; 343260670Sjhibbits case 1: printf("Field 2 only\n"); break; 344299003Smarkj case 2: printf("Regular pattern of fields 1 and 2\n"); break; 345260670Sjhibbits case 3: printf("Random pattern of fields 1 and 2\n"); break; 346260670Sjhibbits } 347260670Sjhibbits if (descriptor->mjpeg.copyProtect) 348260670Sjhibbits printf("\tRestrict duplication\n"); 349260670Sjhibbits break; 350260670Sjhibbits } 351260670Sjhibbits case VS_FORMAT_MPEG2TS: 352260670Sjhibbits printf("VS_FORMAT_MPEG2TS:\t\n"); 353260670Sjhibbits break; 354260670Sjhibbits case VS_FORMAT_DV: 355260670Sjhibbits printf("VS_FORMAT_DV:\t\n"); 356260670Sjhibbits break; 357260670Sjhibbits case VS_FORMAT_FRAME_BASED: 358260670Sjhibbits printf("VS_FORMAT_FRAME_BASED:\t\n"); 359260670Sjhibbits break; 360260670Sjhibbits case VS_FRAME_FRAME_BASED: 361260670Sjhibbits printf("VS_FRAME_FRAME_BASED:\t\n"); 362260670Sjhibbits break; 363260670Sjhibbits case VS_FORMAT_STREAM_BASED: 364260670Sjhibbits printf("VS_FORMAT_STREAM_BASED:\t\n"); 365260670Sjhibbits break; 366260670Sjhibbits default: 367260670Sjhibbits printf("INVALID STREAM UNIT TYPE=%d!\n", 368260670Sjhibbits _descriptor->descriptorSubtype); 369260670Sjhibbits } 370260670Sjhibbits} 371260670Sjhibbits 372260670Sjhibbits 373299003Smarkjvoid 374260670SjhibbitsUVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor, 375260670Sjhibbits size_t len) 376260670Sjhibbits{ 377260670Sjhibbits switch (_descriptor->descriptorSubtype) { 378260670Sjhibbits case VC_HEADER: 379260670Sjhibbits { 380260670Sjhibbits if (fHeaderDescriptor != NULL) { 381260670Sjhibbits printf("ERROR: multiple VC_HEADER! Skipping...\n"); 382260670Sjhibbits break; 383260670Sjhibbits } 384260670Sjhibbits fHeaderDescriptor = (usbvc_interface_header_descriptor*)malloc(len); 385260670Sjhibbits memcpy(fHeaderDescriptor, _descriptor, len); 386260670Sjhibbits printf("VC_HEADER:\tUVC v%x.%02x, clk %.5f MHz\n", 387260670Sjhibbits fHeaderDescriptor->version >> 8, 388260670Sjhibbits fHeaderDescriptor->version & 0xff, 389260670Sjhibbits fHeaderDescriptor->clockFrequency / 1000000.0); 390260670Sjhibbits for (uint8 i = 0; i < fHeaderDescriptor->numInterfacesNumbers; i++) { 391260670Sjhibbits printf("\tStreaming Interface %d\n", 392260670Sjhibbits fHeaderDescriptor->interfaceNumbers[i]); 393260670Sjhibbits } 394260670Sjhibbits break; 395260670Sjhibbits } 396260670Sjhibbits case VC_INPUT_TERMINAL: 397260670Sjhibbits { 398260670Sjhibbits const usbvc_input_terminal_descriptor* descriptor 399260670Sjhibbits = (const usbvc_input_terminal_descriptor*)_descriptor; 400260670Sjhibbits printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 401260670Sjhibbits "%d\n", descriptor->terminalID, descriptor->terminalType, 402260670Sjhibbits descriptor->associatedTerminal); 403260670Sjhibbits printf("\tDesc: %s\n", 404299003Smarkj fDevice->DecodeStringDescriptor(descriptor->terminal)); 405260670Sjhibbits if (descriptor->terminalType == 0x201) { 406260670Sjhibbits const usbvc_camera_terminal_descriptor* desc 407260670Sjhibbits = (const usbvc_camera_terminal_descriptor*)descriptor; 408260670Sjhibbits printf("\tObjectiveFocalLength Min/Max %d/%d\n", 409260670Sjhibbits desc->objectiveFocalLengthMin, 410260670Sjhibbits desc->objectiveFocalLengthMax); 411260670Sjhibbits printf("\tOcularFocalLength %d\n", desc->ocularFocalLength); 412260670Sjhibbits printf("\tControlSize %d\n", desc->controlSize); 413260670Sjhibbits } 414260670Sjhibbits break; 415260670Sjhibbits } 416260670Sjhibbits case VC_OUTPUT_TERMINAL: 417260670Sjhibbits { 418260670Sjhibbits const usbvc_output_terminal_descriptor* descriptor 419260670Sjhibbits = (const usbvc_output_terminal_descriptor*)_descriptor; 420260670Sjhibbits printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=" 421260670Sjhibbits "%d, src id=%d\n", descriptor->terminalID, 422260670Sjhibbits descriptor->terminalType, descriptor->associatedTerminal, 423299003Smarkj descriptor->sourceID); 424260670Sjhibbits printf("\tDesc: %s\n", 425260670Sjhibbits fDevice->DecodeStringDescriptor(descriptor->terminal)); 426260670Sjhibbits break; 427260670Sjhibbits } 428260670Sjhibbits case VC_SELECTOR_UNIT: 429260670Sjhibbits { 430260670Sjhibbits const usbvc_selector_unit_descriptor* descriptor 431260670Sjhibbits = (const usbvc_selector_unit_descriptor*)_descriptor; 432260670Sjhibbits printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n", 433260670Sjhibbits descriptor->unitID, descriptor->numInputPins); 434260670Sjhibbits printf("\t"); 435260670Sjhibbits for (uint8 i = 0; i < descriptor->numInputPins; i++) 436260670Sjhibbits printf("%d ", descriptor->sourceID[i]); 437260670Sjhibbits printf("\n"); 438260670Sjhibbits printf("\tDesc: %s\n", 439260670Sjhibbits fDevice->DecodeStringDescriptor(descriptor->Selector())); 440260670Sjhibbits break; 441260670Sjhibbits } 442260670Sjhibbits case VC_PROCESSING_UNIT: 443260670Sjhibbits { 444260670Sjhibbits const usbvc_processing_unit_descriptor* descriptor 445260670Sjhibbits = (const usbvc_processing_unit_descriptor*)_descriptor; 446260670Sjhibbits fControlRequestIndex = fControlIndex + (descriptor->unitID << 8); 447260670Sjhibbits printf("VC_PROCESSING_UNIT:\t unit id=%d,src id=%d, digmul=%d\n", 448260670Sjhibbits descriptor->unitID, descriptor->sourceID, 449260670Sjhibbits descriptor->maxMultiplier); 450260670Sjhibbits printf("\tbControlSize=%d\n", descriptor->controlSize); 451260670Sjhibbits if (descriptor->controlSize >= 1) { 452260670Sjhibbits if (descriptor->controls[0] & 1) 453260670Sjhibbits printf("\tBrightness\n"); 454260670Sjhibbits if (descriptor->controls[0] & 2) 455260670Sjhibbits printf("\tContrast\n"); 456260670Sjhibbits if (descriptor->controls[0] & 4) 457260670Sjhibbits printf("\tHue\n"); 458260670Sjhibbits if (descriptor->controls[0] & 8) 459260670Sjhibbits printf("\tSaturation\n"); 460260670Sjhibbits if (descriptor->controls[0] & 16) 461260670Sjhibbits printf("\tSharpness\n"); 462260670Sjhibbits if (descriptor->controls[0] & 32) 463260670Sjhibbits printf("\tGamma\n"); 464260670Sjhibbits if (descriptor->controls[0] & 64) 465260670Sjhibbits printf("\tWhite Balance Temperature\n"); 466260670Sjhibbits if (descriptor->controls[0] & 128) 467260670Sjhibbits printf("\tWhite Balance Component\n"); 468260670Sjhibbits } 469260670Sjhibbits if (descriptor->controlSize >= 2) { 470260670Sjhibbits if (descriptor->controls[1] & 1) 471260670Sjhibbits printf("\tBacklight Compensation\n"); 472260670Sjhibbits if (descriptor->controls[1] & 2) 473260670Sjhibbits printf("\tGain\n"); 474260670Sjhibbits if (descriptor->controls[1] & 4) 475260670Sjhibbits printf("\tPower Line Frequency\n"); 476260670Sjhibbits if (descriptor->controls[1] & 8) 477299003Smarkj printf("\t[AUTO] Hue\n"); 478260670Sjhibbits if (descriptor->controls[1] & 16) 479260670Sjhibbits printf("\t[AUTO] White Balance Temperature\n"); 480260670Sjhibbits if (descriptor->controls[1] & 32) 481260670Sjhibbits printf("\t[AUTO] White Balance Component\n"); 482260670Sjhibbits if (descriptor->controls[1] & 64) 483260670Sjhibbits printf("\tDigital Multiplier\n"); 484260670Sjhibbits if (descriptor->controls[1] & 128) 485260670Sjhibbits printf("\tDigital Multiplier Limit\n"); 486260670Sjhibbits } 487260670Sjhibbits if (descriptor->controlSize >= 3) { 488260670Sjhibbits if (descriptor->controls[2] & 1) 489260670Sjhibbits printf("\tAnalog Video Standard\n"); 490260670Sjhibbits if (descriptor->controls[2] & 2) 491260670Sjhibbits printf("\tAnalog Video Lock Status\n"); 492260670Sjhibbits } 493260670Sjhibbits printf("\tDesc: %s\n", 494260670Sjhibbits fDevice->DecodeStringDescriptor(descriptor->Processing())); 495260670Sjhibbits if (descriptor->VideoStandards() & 2) 496260670Sjhibbits printf("\tNTSC 525/60\n"); 497260670Sjhibbits if (descriptor->VideoStandards() & 4) 498260670Sjhibbits printf("\tPAL 625/50\n"); 499260670Sjhibbits if (descriptor->VideoStandards() & 8) 500260670Sjhibbits printf("\tSECAM 625/50\n"); 501260670Sjhibbits if (descriptor->VideoStandards() & 16) 502260670Sjhibbits printf("\tNTSC 625/50\n"); 503260670Sjhibbits if (descriptor->VideoStandards() & 32) 504260670Sjhibbits printf("\tPAL 525/60\n"); 505260670Sjhibbits break; 506260670Sjhibbits } 507260670Sjhibbits case VC_EXTENSION_UNIT: 508260670Sjhibbits { 509260670Sjhibbits const usbvc_extension_unit_descriptor* descriptor 510260670Sjhibbits = (const usbvc_extension_unit_descriptor*)_descriptor; 511260670Sjhibbits printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor->unitID); 512260670Sjhibbits print_guid(descriptor->guidExtensionCode); 513260670Sjhibbits printf("\n\t#ctrls=%d, #pins=%d\n", descriptor->numControls, 514260670Sjhibbits descriptor->numInputPins); 515260670Sjhibbits printf("\t"); 516260670Sjhibbits for (uint8 i = 0; i < descriptor->numInputPins; i++) 517260670Sjhibbits printf("%d ", descriptor->sourceID[i]); 518260670Sjhibbits printf("\n"); 519260670Sjhibbits printf("\tDesc: %s\n", 520260670Sjhibbits fDevice->DecodeStringDescriptor(descriptor->Extension())); 521260670Sjhibbits break; 522260670Sjhibbits } 523260670Sjhibbits default: 524260670Sjhibbits printf("Unknown control %d\n", _descriptor->descriptorSubtype); 525260670Sjhibbits } 526260670Sjhibbits} 527260670Sjhibbits 528260670Sjhibbits 529260670Sjhibbitsbool 530260670SjhibbitsUVCCamDevice::SupportsIsochronous() 531260670Sjhibbits{ 532260670Sjhibbits return true; 533260670Sjhibbits} 534260670Sjhibbits 535260670Sjhibbits 536260670Sjhibbitsstatus_t 537260670SjhibbitsUVCCamDevice::StartTransfer() 538260670Sjhibbits{ 539260670Sjhibbits if (_ProbeCommitFormat() != B_OK || _SelectBestAlternate() != B_OK) 540260670Sjhibbits return B_ERROR; 541260670Sjhibbits return CamDevice::StartTransfer(); 542260670Sjhibbits} 543260670Sjhibbits 544260670Sjhibbits 545260670Sjhibbitsstatus_t 546260670SjhibbitsUVCCamDevice::StopTransfer() 547260670Sjhibbits{ 548260670Sjhibbits _SelectIdleAlternate(); 549260670Sjhibbits return CamDevice::StopTransfer(); 550260670Sjhibbits} 551260670Sjhibbits 552260670Sjhibbits 553260670Sjhibbitsstatus_t 554260670SjhibbitsUVCCamDevice::SuggestVideoFrame(uint32& width, uint32& height) 555260670Sjhibbits{ 556260670Sjhibbits printf("UVCCamDevice::SuggestVideoFrame(%ld, %ld)\n", width, height); 557260670Sjhibbits // As in AcceptVideoFrame(), the suggestion should probably just be the 558260670Sjhibbits // first advertised uncompressed format, but current applications prefer 559260670Sjhibbits // 320x240, so this is tried first here as a suggestion. 560260670Sjhibbits width = 320; 561260670Sjhibbits height = 240; 562260670Sjhibbits if (!AcceptVideoFrame(width, height)) { 563260670Sjhibbits const usbvc_frame_descriptor* descriptor 564260670Sjhibbits = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem(); 565260670Sjhibbits width = (*descriptor).width; 566260670Sjhibbits height = (*descriptor).height; 567260670Sjhibbits } 568260670Sjhibbits return B_OK; 569260670Sjhibbits} 570260670Sjhibbits 571260670Sjhibbits 572260670Sjhibbitsstatus_t 573260670SjhibbitsUVCCamDevice::AcceptVideoFrame(uint32& width, uint32& height) 574260670Sjhibbits{ 575260670Sjhibbits printf("UVCCamDevice::AcceptVideoFrame(%ld, %ld)\n", width, height); 576260670Sjhibbits if (width <= 0 || height <= 0) { 577260670Sjhibbits // Uncomment below when applications support dimensions other than 320x240 578260670Sjhibbits // This code selects the first listed available uncompressed frame format 579260670Sjhibbits /* 580260670Sjhibbits const usbvc_frame_descriptor* descriptor 581260670Sjhibbits = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem(); 582260670Sjhibbits 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 608status_t 609UVCCamDevice::_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 693status_t 694UVCCamDevice::_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 740status_t 741UVCCamDevice::_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 758void 759UVCCamDevice::_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 893float 894UVCCamDevice::_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 928uint8 929UVCCamDevice::_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 944void 945UVCCamDevice::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 983status_t 984UVCCamDevice::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 1103status_t 1104UVCCamDevice::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 1206status_t 1207UVCCamDevice::_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 1215status_t 1216UVCCamDevice::_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 1224status_t 1225UVCCamDevice::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 1256void 1257UVCCamDevice::_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 1333UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam) 1334 : CamDeviceAddon(webcam) 1335{ 1336 printf("UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam)\n"); 1337 SetSupportedDevices(kSupportedDevices); 1338} 1339 1340 1341UVCCamDeviceAddon::~UVCCamDeviceAddon() 1342{ 1343} 1344 1345 1346const char * 1347UVCCamDeviceAddon::BrandName() 1348{ 1349 printf("UVCCamDeviceAddon::BrandName()\n"); 1350 return "USB Video Class"; 1351} 1352 1353 1354UVCCamDevice * 1355UVCCamDeviceAddon::Instantiate(CamRoster& roster, BUSBDevice* from) 1356{ 1357 printf("UVCCamDeviceAddon::Instantiate()\n"); 1358 return new UVCCamDevice(*this, from); 1359} 1360 1361 1362extern "C" status_t 1363B_WEBCAM_MKINTFUNC(uvccam) 1364(WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 1365{ 1366 *addon = new UVCCamDeviceAddon(webcam); 1367 return B_OK; 1368} 1369