/* * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #import "DecodeVideoInterfaceDescriptor.h" @implementation DecodeVideoInterfaceDescriptor +(void)decodeBytes:(UInt8 *)descriptor forDevice:(BusProbeDevice *)thisDevice withDeviceInterface:(IOUSBDeviceRef)deviceIntf { static char buf[256]; static char buf2[256]; auto IOUSBVCInterfaceDescriptor * pVideoControlHeader = NULL; auto IOUSBVCInputTerminalDescriptor * pVideoInTermDesc = NULL; auto IOUSBVCCameraTerminalDescriptor * pCameraTermDesc = NULL; auto IOUSBVCOutputTerminalDescriptor * pVideoOutTermDesc = NULL; auto IOUSBVCSelectorUnitDescriptor * pSelectorUnitDesc = NULL; auto IOUSBVCSelectorUnit2Descriptor * pSelectorUnit2Desc = NULL; auto IOUSBVCProcessingUnitDescriptor * pProcessingUnitDesc = NULL; auto IOUSBVCProcessingUnit2Descriptor * pProcessingUnit2Desc = NULL; auto IOUSBVCExtensionUnitDescriptor * pExtensionUnitDesc = NULL; auto IOUSBVCExtensionUnit2Descriptor * pExtensionUnit2Desc = NULL; auto IOUSBVCExtensionUnit3Descriptor * pExtensionUnit3Desc = NULL; auto IOUSBVCInterruptEndpointDescriptor * pVCInterruptEndpintDesc = NULL; auto IOUSBVSInputHeaderDescriptor * pVSInputHeaderDesc = NULL; auto IOUSBVSOutputHeaderDescriptor * pVSOutputHeaderDesc = NULL; auto IOUSBVDC_MJPEGFormatDescriptor * pMJPEGFormatDesc = NULL; auto IOUSBVDC_MJPEGFrameDescriptor * pMJPEGFrameDesc = NULL; auto IOUSBVDC_MJPEGDiscreteFrameDescriptor * pMJPEGDiscreteFrameDesc = NULL; auto IOUSBVDC_ColorFormatDescriptor * pColorFormatDesc = NULL; auto IOUSBVDC_UncompressedFormatDescriptor * pUncompressedFormatDesc = NULL; auto IOUSBVDC_UncompressedFrameDescriptor * pUncompressedFrameDesc = NULL; auto IOUSBVDC_UncompressedDiscreteFrameDescriptor * pUncompressedDiscreteFrameDesc = NULL; UInt16 i, j; UInt8 *p; UInt32 *t; char *s = NULL; IOUSBVCInterfaceDescriptor * desc = (IOUSBVCInterfaceDescriptor *) descriptor; UInt64 uuidHI; UInt64 uuidLO; UInt32 data1; UInt16 data2, data3; char str[256]; if ( desc->bDescriptorType == CS_ENDPOINT ) { pVCInterruptEndpintDesc = (IOUSBVCInterruptEndpointDescriptor *)desc; switch ( pVCInterruptEndpintDesc->bDescriptorSubType ) { case EP_INTERRUPT: sprintf((char *)buf, "VDC Specific Interrupt Endpoint"); break; default: sprintf((char *)buf, "Unknown Endpoint SubType Descriptor"); } [thisDevice addProperty:buf withValue:"" atDepth:INTERFACE_LEVEL]; // Print the Length and contents of this class-specific descriptor // sprintf(str, "%u", pVCInterruptEndpintDesc->bLength); [thisDevice addProperty:"Length (and contents):" withValue:str atDepth:INTERFACE_LEVEL+1]; [DescriptorDecoder dumpRawDescriptor:(Byte*)desc forDevice:thisDevice atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "%u", Swap16(&pVCInterruptEndpintDesc->wMaxTransferSize) ); [thisDevice addProperty:"Max Transfer Size:" withValue:buf atDepth:INTERFACE_LEVEL+1]; return; } if ( desc->bDescriptorType != CS_INTERFACE ) return; if( SC_VIDEOCONTROL == [[thisDevice lastInterfaceClassInfo] subclassNum] ) { switch ( desc->bDescriptorSubType ) { case VC_DESCRIPTOR_UNDEFINED: sprintf((char *)buf, "Video Control Class Unknown Header"); break; case VC_HEADER: sprintf((char *)buf, "VDC (Control) Header"); break; case VC_INPUT_TERMINAL: sprintf((char *)buf, "VDC (Control) Input Terminal"); break; case VC_OUTPUT_TERMINAL: sprintf((char *)buf, "VDC (Control) Output Terminal"); break; case VC_SELECTOR_UNIT: sprintf((char *)buf, "VDC (Control) Selector Unit"); break; case VC_PROCESSING_UNIT: sprintf((char *)buf, "VDC (Control) Processing Unit"); break; case VC_EXTENSION_UNIT: sprintf((char *)buf, "VDC (Control) Extension Unit"); break; default: sprintf((char *)buf, "Unknown SC_VIDEOCONTROL SubType Descriptor"); } } else if( SC_VIDEOSTREAMING == [[thisDevice lastInterfaceClassInfo] subclassNum] ) { switch ( desc->bDescriptorSubType ) { case VS_UNDEFINED: sprintf((char *)buf, "VDC (Streaming) Unknown Header"); break; case VS_INPUT_HEADER: sprintf((char *)buf, "VDC (Streaming) Input Header"); break; case VS_OUTPUT_HEADER: sprintf((char *)buf, "VDC (Streaming) Output Header"); break; case VS_STILL_IMAGE_FRAME: sprintf((char *)buf, "VDC (Streaming) Still Image Frame Descriptor"); break; case VS_FORMAT_UNCOMPRESSED: sprintf((char *)buf, "VDC (Streaming) Uncompressed Format Descriptor"); break; case VS_FRAME_UNCOMPRESSED: sprintf((char *)buf, "VDC (Streaming) Uncompressed Frame Descriptor"); break; case VS_FORMAT_MJPEG: sprintf((char *)buf, "VDC (Streaming) MJPEG Format Descriptor"); break; case VS_FRAME_MJPEG: sprintf((char *)buf, "VDC (Streaming) MJPEG Frame Descriptor"); break; case VS_FORMAT_MPEG1: sprintf((char *)buf, "VDC (Streaming) MPEG1 Format Descriptor"); break; case VS_FORMAT_MPEG2PS: sprintf((char *)buf, "VDC (Streaming) MPEG2-PS Format Descriptor"); break; case VS_FORMAT_MPEG2TS: sprintf((char *)buf, "VDC (Streaming) MPEG2-TS Format Descriptor"); break; case VS_FORMAT_MPEG4SL: sprintf((char *)buf, "VDC (Streaming) MPEG4-SL Format Descriptor"); break; case VS_FORMAT_DV: sprintf((char *)buf, "VDC (Streaming) DV Format Descriptor"); break; case VS_COLORFORMAT: sprintf((char *)buf, "VDC (Streaming) Color Format Descriptor"); break; case VS_FORMAT_VENDOR: sprintf((char *)buf, "VDC (Streaming) Vendor-specific Format Descriptor"); break; case VS_FRAME_VENDOR: sprintf((char *)buf, "VDC (Streaming) Vendor-specific Frame Descriptor"); break; default: sprintf((char *)buf, "Unknown SC_VIDEOSTREAMING SubType Descriptor"); } } else sprintf((char *)buf, "Unknown VDC Interface Subclass Type"); [thisDevice addProperty:buf withValue:"" atDepth:INTERFACE_LEVEL]; // Print the Length and contents of this class-specific descriptor // sprintf(str, "%u", desc->bLength); [thisDevice addProperty:"Length (and contents):" withValue:str atDepth:INTERFACE_LEVEL+1]; [DescriptorDecoder dumpRawDescriptor:(Byte*)desc forDevice:thisDevice atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%x", desc->bDescriptorType ); [thisDevice addProperty:"bDescriptorType:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", desc->bDescriptorSubType ); [thisDevice addProperty:"bDescriptorSubType:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if( SC_VIDEOCONTROL == [[thisDevice lastInterfaceClassInfo] subclassNum] ) // Video Control Subclass { switch ( desc->bDescriptorSubType ) { case VC_HEADER: pVideoControlHeader = (IOUSBVCInterfaceDescriptor *)desc; i = Swap16(&pVideoControlHeader->bcdVDC); // If release is less than 0x0100, then we need to display the release version if ( (pVideoControlHeader->bcdVDC & 0xFF00) == 0 ) { sprintf((char *)buf, "%1x%1x.%1x%1c", (i>>12)&0x000f, (i>>8)&0x000f, (i>>4)&0x000f, MapNumberToVersion((i>>0)&0x000f)); } else { sprintf((char *)buf, "%1x%1x.%1x%1c", (i>>12)&0x000f, (i>>8)&0x000f, (i>>4)&0x000f, (i>>0)&0x000f); } [thisDevice addProperty:"Specification Version Number:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", Swap16(&pVideoControlHeader->wTotalLength) ); sprintf((char *)buf, "%lu", Swap32(&pVideoControlHeader->dwClockFrequency) ); [thisDevice addProperty:"Device Clock Frequency (Hz):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pVideoControlHeader->bInCollection ); [thisDevice addProperty:"Number of Video Streaming Interfaces:" withValue:buf atDepth:INTERFACE_LEVEL+1]; // Haven't seen this array filled with more than 1 yet. // for (i = 0, p = &pVideoControlHeader->baInterfaceNr[0]; i < pVideoControlHeader->bInCollection; i++, p++ ) { sprintf((char *)buf, "%u", *p ); [thisDevice addProperty:"Video Interface Number:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } break; case VC_INPUT_TERMINAL: pVideoInTermDesc = (IOUSBVCInputTerminalDescriptor *)desc; sprintf((char *)buf, "%u", pVideoInTermDesc->bTerminalID ); [thisDevice addProperty:"Terminal ID" withValue:buf atDepth:INTERFACE_LEVEL+1]; switch ( Swap16(&pVideoInTermDesc->wTerminalType) ) { case TT_VENDOR_SPECIFIC: s="USB vendor specific"; break; case TT_STREAMING: s="USB streaming"; break; case ITT_VENDOR_SPECIFIC: s="Vendor Specific Input Terminal"; break; case ITT_CAMERA: s="Camera Sensor"; break; case ITT_MEDIA_TRANSPORT_UNIT: s="Sequential Media"; break; default: s="Invalid Input Terminal Type"; } sprintf((char *)buf, "0x%x (%s)", pVideoInTermDesc->wTerminalType, s ); [thisDevice addProperty:"Input Terminal Type:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if( !pVideoInTermDesc->bAssocTerminal ) sprintf((char *)buf, "%u [NONE]", pVideoInTermDesc->bAssocTerminal ); else sprintf((char *)buf, "%u", pVideoInTermDesc->bAssocTerminal ); [thisDevice addProperty:"Input Terminal ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if( !pVideoInTermDesc->iTerminal ) { sprintf((char *)buf, "%u [NONE]", pVideoInTermDesc->iTerminal ); [thisDevice addProperty:"Input Terminal String Index:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } else { [thisDevice addStringProperty:"Input Terminal String:" fromStringIndex: (UInt8)pVideoInTermDesc->iTerminal fromDeviceInterface:deviceIntf atDepth:INTERFACE_LEVEL+1]; } if ( ITT_CAMERA == pVideoInTermDesc->wTerminalType ) { pCameraTermDesc = (IOUSBVCCameraTerminalDescriptor *)desc; sprintf((char *)buf, "%u", Swap16(&pCameraTermDesc->wObjectiveFocalLengthMin) ); [thisDevice addProperty:"Minimum Focal Length" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", Swap16(&pCameraTermDesc->wObjectiveFocalLengthMax) ); [thisDevice addProperty:"Maximum Focal Length" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", Swap16(&pCameraTermDesc->wOcularFocalLength) ); [thisDevice addProperty:"Ocular Focal Length" withValue:buf atDepth:INTERFACE_LEVEL+1]; if ( pCameraTermDesc->bControlSize != 0 ) { sprintf((char *)buf, "Description"); [thisDevice addProperty:"Controls Supported" withValue:buf atDepth:INTERFACE_LEVEL+1]; } strcpy((char *)buf, ""); /* // Need to swap the following bmControls field // switch ( pCameraTermDesc->bControlSize) { case 1: break; case 2: Swap16(&pCameraTermDesc->bmControls); break; //case 3: Swap24(&pCameraTermDesc->bmControls); break; case 3: break; case 4: Swap32(&pCameraTermDesc->bmControls); break; } */ for (i = 0, p = &pCameraTermDesc->bmControls[0]; i < pCameraTermDesc->bControlSize; i++, p++ ) { // For 1.0, only 19 bits are defined.... // p is pointing to the first byte of a little endian field. // // i = 0, p -> D0-D7 // i = 1, p -> D8-D15 // i = 2, p -> D16-D23 // i = 4, p -> D24-D31 // if ( i > 2 ) { sprintf((char *)buf, "Unknown"); [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 0) ) { if ( i == 0 ) sprintf((char *)buf, "Scanning Mode"); else if ( i == 1 ) sprintf((char *)buf, "Iris (Relative)"); else if ( i == 2 ) sprintf((char *)buf, "Iris (Relative)"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 1) ) { if ( i == 0 ) sprintf((char *)buf, "Auto Exposure Mode"); else if ( i == 1 ) sprintf((char *)buf, "Zoom (Absolute)"); else if ( i == 2 ) sprintf((char *)buf, "Tilt (Relative)"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 2) ) { if ( i == 0 ) sprintf((char *)buf, "Auto Exposure Priority"); else if ( i == 1 ) sprintf((char *)buf, "Zoom (Relative)"); else if ( i == 2 ) sprintf((char *)buf, "Focus, Auto"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 3) ) { if ( i == 0 ) sprintf((char *)buf, "Exposure Time (Absolute)"); else if ( i == 1 ) sprintf((char *)buf, "Pan (Absolute)"); else if ( i == 2 ) sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 4) ) { if ( i == 0 ) sprintf((char *)buf, "Exposure Time (Relative)"); else if ( i == 1 ) sprintf((char *)buf, "Pan (Relative)"); else if ( i == 2 ) sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 5) ) { if ( i == 0 ) sprintf((char *)buf, "Focus (Absolute)"); else if ( i == 1 ) sprintf((char *)buf, "Roll (Absolute)"); else if ( i == 2 ) sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 6) ) { if ( i == 0 ) sprintf((char *)buf, "Focus (Relative)"); else if ( i == 1 ) sprintf((char *)buf, "Roll (Relative)"); else if ( i == 2 ) sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 7) ) { if ( i == 0 ) sprintf((char *)buf, "Iris (Absolute)"); else if ( i == 1 ) sprintf((char *)buf, "Tilt (Absolute)"); else if ( i == 2 ) sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } } } break; case VC_OUTPUT_TERMINAL: pVideoOutTermDesc = (IOUSBVCOutputTerminalDescriptor *)desc; sprintf((char *)buf, "%u", pVideoOutTermDesc->bTerminalID ); [thisDevice addProperty:"Terminal ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; switch ( Swap16(&pVideoOutTermDesc->wTerminalType) ) { case TT_VENDOR_SPECIFIC: s="USB vendor specific"; break; case TT_STREAMING: s="USB streaming"; break; case OTT_VENDOR_SPECIFIC: s="USB vendor specific"; break; case OTT_DISPLAY: s="Generic Display"; break; case OTT_MEDIA_TRANSPORT_OUTPUT: s="Sequential Media Output Terminal"; break; default: s="Invalid Output Terminal Type"; } sprintf((char *)buf, "0x%x (%s)", pVideoOutTermDesc->wTerminalType, s ); [thisDevice addProperty:"Output Terminal Type:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if( !pVideoOutTermDesc->bAssocTerminal ) sprintf((char *)buf, "%u [NONE]", pVideoOutTermDesc->bAssocTerminal ); else sprintf((char *)buf, "%u", pVideoOutTermDesc->bAssocTerminal ); [thisDevice addProperty:"Output Terminal ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if( !pVideoOutTermDesc->iTerminal ) { sprintf((char *)buf, "%u [NONE]", pVideoOutTermDesc->iTerminal ); [thisDevice addProperty:"Output Terminal String Index:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } else { [thisDevice addStringProperty:"Output Terminal String:" fromStringIndex: (UInt8)pVideoOutTermDesc->iTerminal fromDeviceInterface:deviceIntf atDepth:INTERFACE_LEVEL+1]; } break; case VC_SELECTOR_UNIT: pSelectorUnitDesc = (IOUSBVCSelectorUnitDescriptor *)desc; sprintf((char *)buf, "%u", pSelectorUnitDesc->bUnitID ); [thisDevice addProperty:"Unit ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pSelectorUnitDesc->bNrInPins ); [thisDevice addProperty:"Number of pins:" withValue:buf atDepth:INTERFACE_LEVEL+1]; // for (i = 0, p = &pSelectorUnitDesc->baSourceID[0]; i < pSelectorUnitDesc->bNrInPins; i++, p++ ) { sprintf((char *)buf2, "Source ID Pin[%d]:", i); sprintf((char *)buf, "%u", *p ); [thisDevice addProperty:buf2 withValue:buf atDepth:INTERFACE_LEVEL+1]; } // Now, p will point to the IOUSBVCSelectorUnit2Descriptor // pSelectorUnit2Desc = (IOUSBVCSelectorUnit2Descriptor *) p; if( !pSelectorUnit2Desc->iSelector ) { sprintf((char *)buf, "%u [NONE]", pSelectorUnit2Desc->iSelector ); [thisDevice addProperty:"Selector Unit String Index:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } else { [thisDevice addStringProperty:"Selector Unit String:" fromStringIndex: (UInt8)pSelectorUnit2Desc->iSelector fromDeviceInterface:deviceIntf atDepth:INTERFACE_LEVEL+1]; } break; case VC_PROCESSING_UNIT: pProcessingUnitDesc = ( IOUSBVCProcessingUnitDescriptor *) desc; sprintf((char *)buf, "%u", pProcessingUnitDesc->bUnitID ); [thisDevice addProperty:"Unit ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pProcessingUnitDesc->bSourceID ); [thisDevice addProperty:"Source ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", Swap16(&pProcessingUnitDesc->wMaxMultiplier) ); [thisDevice addProperty:"Digital Multiplier (100X):" withValue:buf atDepth:INTERFACE_LEVEL+1]; if ( pProcessingUnitDesc->bControlSize != 0 ) { sprintf((char *)buf, "Description"); [thisDevice addProperty:"Controls Supported" withValue:buf atDepth:INTERFACE_LEVEL+1]; } strcpy((char *)buf, ""); /* // Need to swap the following bmControls field // switch ( pProcessingUnitDesc->bControlSize) { case 1: break; case 2: Swap16(&pProcessingUnitDesc->bmControls); break; case 3: Swap24(&pCameraTermDesc->bmControls); break; case 4: Swap32(&pProcessingUnitDesc->bmControls); break; } */ for (i = 0, p = &pProcessingUnitDesc->bmControls[0]; i < pProcessingUnitDesc->bControlSize; i++, p++ ) { // For 1.0, only 16 bits are defined: // // p is pointing to the first byte of a little endian field. // // i = 0, p -> D0-D7 // i = 1, p -> D8-D15 // i = 2, p -> D16-D23 // i = 4, p -> D24-D31 // if ( (*p) & (1 << 0) ) { if ( i == 0 ) sprintf((char *)buf, "Brightness"); else if ( i == 1 ) sprintf((char *)buf, "Backlight Compensation"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 1) ) { if ( i == 0 ) sprintf((char *)buf, "Contrast"); else if ( i == 1 ) sprintf((char *)buf, "Gain"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 2) ) { if ( i == 0 ) sprintf((char *)buf, "Hue"); else if ( i == 1 ) sprintf((char *)buf, "Power Line Frequency"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 3) ) { if ( i == 0 ) sprintf((char *)buf, "Saturation"); else if ( i == 1 ) sprintf((char *)buf, "Hue, Auto"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 4) ) { if ( i == 0 ) sprintf((char *)buf, "Sharpness"); else if ( i == 1 ) sprintf((char *)buf, "White Balance Temperature, Auto"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 5) ) { if ( i == 0 ) sprintf((char *)buf, "Gamma"); else if ( i == 1 ) sprintf((char *)buf, "White Balance Component, Auto"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 6) ) { if ( i == 0 ) sprintf((char *)buf, "White Balance Temperature"); else if ( i == 1 ) sprintf((char *)buf, "Digital Multiplier"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 7) ) { if ( i == 0 ) sprintf((char *)buf, "White Balance Component"); else if ( i == 1 ) sprintf((char *)buf, "Digital Multiplier Limit"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } } // At this point, p should be pointing to the iProcessing field: pProcessingUnit2Desc = (IOUSBVCProcessingUnit2Descriptor *) p; if( !pProcessingUnit2Desc->iProcessing ) { sprintf((char *)buf, "%u [NONE]", pProcessingUnit2Desc->iProcessing ); [thisDevice addProperty:"Processing Unit String Index:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } else { [thisDevice addStringProperty:"Selector Unit String:" fromStringIndex: (UInt8)pProcessingUnit2Desc->iProcessing fromDeviceInterface:deviceIntf atDepth:INTERFACE_LEVEL+1]; } break; case VC_EXTENSION_UNIT: sprintf((char *)buf, "%u", desc->bLength ); [thisDevice addProperty:"bLength:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", desc->bDescriptorType ); [thisDevice addProperty:"bDescriptorType:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", desc->bDescriptorSubType ); [thisDevice addProperty:"bDescriptorSubType:" withValue:buf atDepth:INTERFACE_LEVEL+1]; pExtensionUnitDesc = (IOUSBVCExtensionUnitDescriptor *)desc; sprintf((char *)buf, "%u", pExtensionUnitDesc->bUnitID ); [thisDevice addProperty:"Unit ID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; uuidHI = pExtensionUnitDesc->guidExtensionCodeHi; uuidLO = pExtensionUnitDesc->guidExtensionCodeLo; // Decode the GUID per section 2.9 of the FAQ // data1 = (uuidHI >> 32 ); Swap32(&data1); data2 = (uuidHI >> 16 ) & 0x0000ffff; Swap16(&data2); data3 = (uuidHI & 0x0000ffff); Swap16(&data3); sprintf((char *)buf, "%8.8lx-%4.4x-%4.4x-%4.4lx-%12.12qx", data1, data2, data3, (UInt32) ( (uuidLO & 0xffff000000000000ULL)>>48), (uuidLO & 0x0000FFFFFFFFFFFFULL) ); [thisDevice addProperty:"Vendor UUID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pExtensionUnitDesc->bNumControls ); [thisDevice addProperty:"Number of Controls:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pExtensionUnitDesc->bNrInPins ); [thisDevice addProperty:"Number of In pins:" withValue:buf atDepth:INTERFACE_LEVEL+1]; for (i = 0, p = &pExtensionUnitDesc->baSourceID[0]; i < pExtensionUnitDesc->bNrInPins; i++, p++ ) { sprintf((char *)buf2, "Source ID Pin[%d]:", i); sprintf((char *)buf, "%u", *p ); [thisDevice addProperty:buf2 withValue:buf atDepth:INTERFACE_LEVEL+1]; } // Now, p points to the rest of the Extension Unit descriptor: // pExtensionUnit2Desc = ( IOUSBVCExtensionUnit2Descriptor *) p; if ( pExtensionUnit2Desc->bControlSize != 0 ) { sprintf((char *)buf, "Description"); [thisDevice addProperty:"Controls Supported" withValue:buf atDepth:INTERFACE_LEVEL+1]; } strcpy((char *)buf, ""); for (i = 0, p = &pExtensionUnit2Desc->bmControls[0]; i < pExtensionUnit2Desc->bControlSize; i++, p++ ) { // For 1.0, all bits are vendor specific: // sprintf((char *)buf, "Vendor Specific Byte[i] = 0x%x", (*p)); [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } // At this point, p should be pointing to the iProcessing field: pExtensionUnit3Desc = ( IOUSBVCExtensionUnit3Descriptor *) p; if( !pExtensionUnit3Desc->iExtension ) { sprintf((char *)buf, "%u [NONE]", pExtensionUnit3Desc->iExtension ); [thisDevice addProperty:"Processing Unit String Index:" withValue:buf atDepth:INTERFACE_LEVEL+1]; } else { [thisDevice addStringProperty:"Selector Unit String:" fromStringIndex: (UInt8)pExtensionUnit3Desc->iExtension fromDeviceInterface:deviceIntf atDepth:INTERFACE_LEVEL+1]; } break; case VC_DESCRIPTOR_UNDEFINED: default: [thisDevice addProperty:"Undefined Descriptor:" withValue:"" atDepth:INTERFACE_LEVEL+1]; } } else if( SC_VIDEOSTREAMING == [[thisDevice lastInterfaceClassInfo] subclassNum] ) // Video Streaming Subclass { switch ( desc->bDescriptorSubType ) { case VS_INPUT_HEADER: pVSInputHeaderDesc = (IOUSBVSInputHeaderDescriptor *)desc; sprintf((char *)buf, "%u", pVSInputHeaderDesc->bNumFormats ); [thisDevice addProperty:"bNumFormats:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x (%u)", Swap16(&pVSInputHeaderDesc->wTotalLength), pVSInputHeaderDesc->wTotalLength ); [thisDevice addProperty:"wTotalLength:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pVSInputHeaderDesc->bEndpointAddress ); [thisDevice addProperty:"bEndpointAddress:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "Capabilities (0x%x)", pVSInputHeaderDesc->bmInfo ); [thisDevice addProperty:buf withValue:"bmInfo" atDepth:INTERFACE_LEVEL+1]; if (pVSInputHeaderDesc->bmInfo & 0x01) [thisDevice addProperty:"" withValue:"Dynamic Format Change supported" atDepth:INTERFACE_LEVEL+2]; if ( pVSInputHeaderDesc->bmInfo & 0xfe) [thisDevice addProperty:"" withValue:"Unknown capabilities" atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "%u", pVSInputHeaderDesc->bTerminalLink ); [thisDevice addProperty:"bTerminalLink:" withValue:buf atDepth:INTERFACE_LEVEL+1]; switch (pVSInputHeaderDesc->bStillCaptureMethod) { case 0: s = "None"; break; case 1: s = "Method 1"; break; case 2: s = "Method 2"; break; case 3: s = "Method 3"; break; default: s = "Unknown Method"; } sprintf((char *)buf, "%u (%s)", pVSInputHeaderDesc->bStillCaptureMethod, s ); [thisDevice addProperty:"bStillCaptureMethod:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%s", pVSInputHeaderDesc->bTriggerSupport ? "Supported" : "Not Supported"); [thisDevice addProperty:"bTriggerSupport" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%s", pVSInputHeaderDesc->bTriggerUsage ? "General Purpose" : "Initiate Still Image Capture"); [thisDevice addProperty:"bTriggerUsage" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pVSInputHeaderDesc->bControlSize ); [thisDevice addProperty:"bControlSize:" withValue:buf atDepth:INTERFACE_LEVEL+1]; for (j = 0; j < pVSInputHeaderDesc->bNumFormats; j++ ) { strcpy((char *)buf, ""); strcpy((char *)buf2, ""); for (i = 0, p = &pVSInputHeaderDesc->bmControls[0]; i < pVSInputHeaderDesc->bControlSize; i++, p++ ) { sprintf((char *)buf, "0x%x", *p ); strcat( buf2, buf); } sprintf((char *)buf, "bmaControls( Format %d):", j+1 ); [thisDevice addProperty:buf withValue:buf2 atDepth:INTERFACE_LEVEL+1]; strcpy((char *)buf, ""); for (i = 0, p = &pVSInputHeaderDesc->bmControls[0]; i < pVSInputHeaderDesc->bControlSize; i++, p++ ) { if ( (*p) & (1 << 0) ) { if ( i == 0 ) sprintf((char *)buf, "Key Frame Rate"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 1) ) { if ( i == 0 ) sprintf((char *)buf, "P frame Rate"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 2) ) { if ( i == 0 ) sprintf((char *)buf, "Compression quality"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 3) ) { if ( i == 0 ) sprintf((char *)buf, "Compression window size"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 4) ) { if ( i == 0 ) sprintf((char *)buf, "Generate Key Frame"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 5) ) { if ( i == 0 ) sprintf((char *)buf, "Update Frame Segment"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 6) ) { sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } if ( (*p) & (1 << 7) ) { sprintf((char *)buf, "Unknown"); if ( strcmp(buf,"") ) [thisDevice addProperty:"" withValue:buf atDepth:INTERFACE_LEVEL+2]; } } } break; case VS_OUTPUT_HEADER: pVSOutputHeaderDesc = (IOUSBVSOutputHeaderDescriptor *)desc; sprintf((char *)buf, "%u", pVSOutputHeaderDesc->bNumFormats); [thisDevice addProperty:"Number of Formats:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", Swap16(&pVSOutputHeaderDesc->wTotalLength) ); [thisDevice addProperty:"Total Length of Descriptor:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pVSOutputHeaderDesc->bEndpointAddress ); [thisDevice addProperty:"Endpoint Address:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "%u", pVSOutputHeaderDesc->bTerminalLink ); [thisDevice addProperty:"Terminal ID of Output Terminal:" withValue:buf atDepth:INTERFACE_LEVEL+1]; break; case VS_FORMAT_MJPEG: pMJPEGFormatDesc = (IOUSBVDC_MJPEGFormatDescriptor *)desc; sprintf((char *)buf, "0x%x", pMJPEGFormatDesc->bFormatIndex); [thisDevice addProperty:"bFormatIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pMJPEGFormatDesc->bNumFrameDescriptors); [thisDevice addProperty:"bNumFrameDescriptors:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "(0x%x)", pMJPEGFormatDesc->bmFlags ); [thisDevice addProperty:"bmFlags" withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pMJPEGFormatDesc->bmFlags & 0x01) [thisDevice addProperty:"" withValue:"Fixed Sample Sizes Supported" atDepth:INTERFACE_LEVEL+2]; if ( pMJPEGFormatDesc->bmFlags & 0xfe) [thisDevice addProperty:"" withValue:"Unknown characteristics" atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%x", pMJPEGFormatDesc->bDefaultFrameIndex); [thisDevice addProperty:"bDefaultFrameIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pMJPEGFormatDesc->bAspectRatioX); [thisDevice addProperty:"bAspectRatioX:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pMJPEGFormatDesc->bAspectRatioY); [thisDevice addProperty:"bAspectRatioY:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "(0x%x)", pMJPEGFormatDesc->bmInterlaceFlags ); [thisDevice addProperty:"bmInterlaceFlags" withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pMJPEGFormatDesc->bmInterlaceFlags & 0x01) [thisDevice addProperty:"Interlaced Stream or Variable" withValue:"Yes" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Interlaced Stream or Variable" withValue:"No" atDepth:INTERFACE_LEVEL+2]; if (pMJPEGFormatDesc->bmInterlaceFlags & 0x02) [thisDevice addProperty:"Fields per frame" withValue:"2" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Fields per frame" withValue:"1" atDepth:INTERFACE_LEVEL+2]; if (pMJPEGFormatDesc->bmInterlaceFlags & 0x04) [thisDevice addProperty:"Field 1 first" withValue:"Yes" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Field 1 first" withValue:"No" atDepth:INTERFACE_LEVEL+2]; if (pMJPEGFormatDesc->bmInterlaceFlags & 0x08) [thisDevice addProperty:"" withValue:"Reserved field used!" atDepth:INTERFACE_LEVEL+2]; i = (pMJPEGFormatDesc->bmInterlaceFlags & 0x30) >> 4; switch (i) { case 0: s = "Field 1 only"; break; case 1: s = "Field 2 only"; break; case 2: s = "Regular pattern of fields 1 and 2"; break; case 3: s = "Random pattern of fields 1 and 2"; break; } sprintf((char *)buf, "%s", s ); [thisDevice addProperty:"Field Pattern" withValue:buf atDepth:INTERFACE_LEVEL+2]; i = (pMJPEGFormatDesc->bmInterlaceFlags & 0xc0) >> 6; switch (i) { case 0: s = "Bob only"; break; case 1: s = "Weave only"; break; case 2: s = "Bob or weave"; break; case 3: s = "Unknown"; break; } sprintf((char *)buf, "%s", s ); [thisDevice addProperty:"Display Mode" withValue:buf atDepth:INTERFACE_LEVEL+2]; if (pMJPEGFormatDesc->bCopyProtect == 1) [thisDevice addProperty:"bCopyProtect:" withValue:"Restricted" atDepth:INTERFACE_LEVEL+1]; else [thisDevice addProperty:"bCopyProtect" withValue:"No Restriction" atDepth:INTERFACE_LEVEL+1]; break; case VS_FRAME_MJPEG: pMJPEGFrameDesc = (IOUSBVDC_MJPEGFrameDescriptor *)desc; sprintf((char *)buf, "%u", pMJPEGFrameDesc->bFrameIndex); [thisDevice addProperty:"bFrameIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "(0x%x)", pMJPEGFrameDesc->bmCapabilities ); [thisDevice addProperty:"bmCapabilities " withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pMJPEGFrameDesc->bmCapabilities & 0x01) [thisDevice addProperty:"" withValue:"Still Image supported" atDepth:INTERFACE_LEVEL+2]; if ( pMJPEGFrameDesc->bmCapabilities & 0xfe) [thisDevice addProperty:"" withValue:"Unknown capabilities" atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%x (%u)", Swap16(&pMJPEGFrameDesc->wWidth), pMJPEGFrameDesc->wWidth); [thisDevice addProperty:"wWidth:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x (%u)", Swap16(&pMJPEGFrameDesc->wHeight), pMJPEGFrameDesc->wHeight); [thisDevice addProperty:"wHeight:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pMJPEGFrameDesc->dwMinBitRate), pMJPEGFrameDesc->dwMinBitRate); [thisDevice addProperty:"dwMinBitRate (bps):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pMJPEGFrameDesc->dwMaxBitRate), pMJPEGFrameDesc->dwMaxBitRate); [thisDevice addProperty:"dwMaxBitRate (bps):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pMJPEGFrameDesc->dwMaxVideoFrameBufferSize), pMJPEGFrameDesc->dwMaxVideoFrameBufferSize); [thisDevice addProperty:"dwMaxVideoFrameBufferSize (bytes):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pMJPEGFrameDesc->dwDefaultFrameInterval), (double) ( pMJPEGFrameDesc->dwDefaultFrameInterval / 10000) ); [thisDevice addProperty:"dwDefaultFrameInterval:" withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pMJPEGFrameDesc->bFrameIntervalType == 0) { [thisDevice addProperty:"bFrameIntervalType:" withValue:"Continuous" atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pMJPEGFrameDesc->dwMinFrameInterval), (double) ( pMJPEGFrameDesc->dwMinFrameInterval / 10000) ); [thisDevice addProperty:"dwMinFrameInterval:" withValue:buf atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pMJPEGFrameDesc->dwMaxFrameInterval), (double) ( pMJPEGFrameDesc->dwMaxFrameInterval / 10000) ); [thisDevice addProperty:"dwMaxFrameInterval:" withValue:buf atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pMJPEGFrameDesc->dwFrameIntervalStep), (double) ( pMJPEGFrameDesc->dwFrameIntervalStep / 10000) ); [thisDevice addProperty:"dwFrameIntervalStep:" withValue:buf atDepth:INTERFACE_LEVEL+2]; } else { // Need to recast as a IOUSBVDC_MJPEGDiscreteFrameDescriptor // pMJPEGDiscreteFrameDesc = (IOUSBVDC_MJPEGDiscreteFrameDescriptor *) pMJPEGFrameDesc; sprintf((char *)buf, "%u", (pMJPEGDiscreteFrameDesc->bFrameIntervalType)); [thisDevice addProperty:"Discrete Frame Intervals supported" withValue:buf atDepth:INTERFACE_LEVEL+1]; for (i = 0, t = &pMJPEGDiscreteFrameDesc->dwFrameInterval[0]; i < pMJPEGDiscreteFrameDesc->bFrameIntervalType; i++, t++ ) { UInt32 interval = *t; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&interval), (double) (interval / 10000)); sprintf((char *)buf2, "dwFrameInterval[%u] (100 ns)", i+1 ); [thisDevice addProperty:buf2 withValue:buf atDepth:INTERFACE_LEVEL+2]; } } break; case VS_COLORFORMAT: pColorFormatDesc = (IOUSBVDC_ColorFormatDescriptor *)desc; switch (pColorFormatDesc->bColorPrimaries) { case 0: s = "Unspecified (Image characteristic unknown)"; break; case 1: s = "BT.709, sRGB (default)"; break; case 2: s = "BT.470-2(M)"; break; case 3: s = "BT.470-2(B,G)"; break; case 4: s = "SMPTE 170M"; break; case 5: s = "SMPTE 240M"; break; default: s = "reserved"; break; } sprintf((char *) buf, "%u ( %s )", pColorFormatDesc->bColorPrimaries, s); [thisDevice addProperty:"Color Primaries:" withValue:buf atDepth:INTERFACE_LEVEL+1]; switch (pColorFormatDesc->bTransferCharacteristics) { case 0: s = "Unspecified (Image characteristic unknown)"; break; case 1: s = "BT.709 (default)"; break; case 2: s = "BT.470-2(M)"; break; case 3: s = "BT.470-2(B,G)"; break; case 4: s = "SMPTE 170M"; break; case 5: s = "SMPTE 240M"; break; case 6: s = "Linear ( V = Lc)"; break; case 7: s = "sRGB (very similar to BT.709)"; break; default: s = "reserved"; break; } sprintf((char *) buf, "%u ( %s )", pColorFormatDesc->bTransferCharacteristics, s); [thisDevice addProperty:"Transfer Characteristics:" withValue:buf atDepth:INTERFACE_LEVEL+1]; switch (pColorFormatDesc->bMatrixCoefficients) { case 0: s = "Unspecified (Image characteristic unknown)"; break; case 1: s = "BT.709"; break; case 2: s = "FCC"; break; case 3: s = "BT.470-2(B,G)"; break; case 4: s = "SMPTE 170M (BT.601, default)"; break; case 5: s = "SMPTE 240M"; break; default: s = "reserved"; break; } sprintf((char *) buf, "%u ( %s )", pColorFormatDesc->bMatrixCoefficients, s); [thisDevice addProperty:"Matrix Coefficients:" withValue:buf atDepth:INTERFACE_LEVEL+1]; break; case VS_FORMAT_UNCOMPRESSED: pUncompressedFormatDesc = (IOUSBVDC_UncompressedFormatDescriptor *)desc; sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bFormatIndex); [thisDevice addProperty:"bFormatIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bNumFrameDescriptors); [thisDevice addProperty:"bNumFrameDescriptors:" withValue:buf atDepth:INTERFACE_LEVEL+1]; // Decode the GUID per section 2.9 of the FAQ // uuidHI = pUncompressedFormatDesc->guidFormatHi; uuidLO = pUncompressedFormatDesc->guidFormatLo; data1 = (uuidHI >> 32 ); Swap32(&data1); data2 = (uuidHI >> 16 ) & 0x0000ffff; Swap16(&data2); data3 = (uuidHI & 0x0000ffff); Swap16(&data3); sprintf((char *)buf, "%8.8lx-%4.4x-%4.4x-%4.4lx-%12.12qx", data1, data2, data3, (UInt32) ( (uuidLO & 0xffff000000000000ULL)>>48), (uuidLO & 0x0000FFFFFFFFFFFFULL) ); [thisDevice addProperty:"Format GUID:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x (%u)", pUncompressedFormatDesc->bBitsPerPixel,pUncompressedFormatDesc->bBitsPerPixel); [thisDevice addProperty:"bBitsPerPixel:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bDefaultFrameIndex); [thisDevice addProperty:"bDefaultFrameIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bAspectRatioX); [thisDevice addProperty:"bAspectRatioX:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bAspectRatioY); [thisDevice addProperty:"bAspectRatioY:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "(0x%x)", pUncompressedFormatDesc->bmInterlaceFlags ); [thisDevice addProperty:"bmInterlaceFlags" withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pUncompressedFormatDesc->bmInterlaceFlags & 0x01) [thisDevice addProperty:"Interlace Stream or variable" withValue:"YES" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Interlace Stream or variable" withValue:"NO" atDepth:INTERFACE_LEVEL+2]; if (pUncompressedFormatDesc->bmInterlaceFlags & 0x02) [thisDevice addProperty:"Fields per Frame" withValue:"1" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Fields per Frame" withValue:"2" atDepth:INTERFACE_LEVEL+2]; if (pUncompressedFormatDesc->bmInterlaceFlags & 0x04) [thisDevice addProperty:"Field 1 First" withValue:"Yes" atDepth:INTERFACE_LEVEL+2]; else [thisDevice addProperty:"Field 1 First" withValue:"No" atDepth:INTERFACE_LEVEL+2]; if (pUncompressedFormatDesc->bmInterlaceFlags & 0x08) [thisDevice addProperty:"" withValue:"Reserved field used" atDepth:INTERFACE_LEVEL+2]; switch ( pUncompressedFormatDesc->bmInterlaceFlags & 0x30 ) { case 0: [thisDevice addProperty:"Field Pattern" withValue:"Field 1 only" atDepth:INTERFACE_LEVEL+2]; break; case 1: [thisDevice addProperty:"Field Pattern" withValue:"Field 2 only" atDepth:INTERFACE_LEVEL+2]; break; case 2: [thisDevice addProperty:"Field Pattern" withValue:"Regular pattern of fields 1 and 2" atDepth:INTERFACE_LEVEL+2]; break; case 3: [thisDevice addProperty:"Field Pattern" withValue:"Random pattern of fields 1 and 2" atDepth:INTERFACE_LEVEL+2]; break; } switch ( pUncompressedFormatDesc->bmInterlaceFlags & 0xc0 ) { case 0: [thisDevice addProperty:"Display Mode" withValue:"Bob only" atDepth:INTERFACE_LEVEL+2]; break; case 1: [thisDevice addProperty:"Display Mode" withValue:"Weave only" atDepth:INTERFACE_LEVEL+2]; break; case 2: [thisDevice addProperty:"Display Mode" withValue:"Bob or Weave" atDepth:INTERFACE_LEVEL+2]; break; case 3: [thisDevice addProperty:"Display Mode" withValue:"Undefined" atDepth:INTERFACE_LEVEL+2]; break; } sprintf((char *)buf, "0x%x", pUncompressedFormatDesc->bCopyProtect); if (pUncompressedFormatDesc->bCopyProtect) [thisDevice addProperty:"Copy Protection:" withValue:"Restrict Duplication" atDepth:INTERFACE_LEVEL+1]; else [thisDevice addProperty:"Copy Protection:" withValue:"No Restrictions" atDepth:INTERFACE_LEVEL+1]; break; case VS_FRAME_UNCOMPRESSED: pUncompressedFrameDesc = (IOUSBVDC_UncompressedFrameDescriptor *)desc; sprintf((char *)buf, "0x%x", pUncompressedFrameDesc->bFrameIndex); [thisDevice addProperty:"bFrameIndex:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "(0x%x)", pUncompressedFrameDesc->bmCapabilities ); [thisDevice addProperty:"bmCapabilities " withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pUncompressedFrameDesc->bmCapabilities & 0x01) [thisDevice addProperty:"" withValue:"Still Image supported" atDepth:INTERFACE_LEVEL+2]; if ( pUncompressedFrameDesc->bmCapabilities & 0xfe) [thisDevice addProperty:"" withValue:"Unknown capabilities" atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%x (%u)", Swap16(&pUncompressedFrameDesc->wWidth), pUncompressedFrameDesc->wWidth); [thisDevice addProperty:"wWidth:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%x (%u)", Swap16(&pUncompressedFrameDesc->wHeight), pUncompressedFrameDesc->wHeight); [thisDevice addProperty:"wHeight:" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pUncompressedFrameDesc->dwMinBitRate), pUncompressedFrameDesc->dwMinBitRate); [thisDevice addProperty:"dwMinBitRate (bps):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pUncompressedFrameDesc->dwMaxBitRate), pUncompressedFrameDesc->dwMaxBitRate); [thisDevice addProperty:"dwMaxBitRate (bps):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%lu)", Swap32(&pUncompressedFrameDesc->dwMaxVideoFrameBufferSize), pUncompressedFrameDesc->dwMaxVideoFrameBufferSize); [thisDevice addProperty:"dwMaxVideoFrameBufferSize (bytes):" withValue:buf atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pUncompressedFrameDesc->dwDefaultFrameInterval), (double) (pUncompressedFrameDesc->dwDefaultFrameInterval / 10000)); [thisDevice addProperty:"dwDefaultFrameInterval (100 ns):" withValue:buf atDepth:INTERFACE_LEVEL+1]; if (pUncompressedFrameDesc->bFrameIntervalType == 0) { [thisDevice addProperty:"bFrameIntervalType:" withValue:"Continuous" atDepth:INTERFACE_LEVEL+1]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pUncompressedFrameDesc->dwMinFrameInterval), (double ) (pUncompressedFrameDesc->dwMinFrameInterval / 100000) ); [thisDevice addProperty:"dwMinFrameInterval (100 ns):" withValue:buf atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pUncompressedFrameDesc->dwMaxFrameInterval), (double ) (pUncompressedFrameDesc->dwMaxFrameInterval / 100000) ); [thisDevice addProperty:"dwMaxFrameInterval (100 ns):" withValue:buf atDepth:INTERFACE_LEVEL+2]; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&pUncompressedFrameDesc->dwFrameIntervalStep), (double ) (pUncompressedFrameDesc->dwFrameIntervalStep / 100000) ); [thisDevice addProperty:"dwFrameIntervalStep (100 ns):" withValue:buf atDepth:INTERFACE_LEVEL+2]; } else { // Need to recast as a IOUSBVDC_UncompressedDiscreteFrameDescriptor // pUncompressedDiscreteFrameDesc = (IOUSBVDC_UncompressedDiscreteFrameDescriptor *) pUncompressedFrameDesc; sprintf((char *)buf, "0x%x", (pUncompressedDiscreteFrameDesc->bFrameIntervalType)); [thisDevice addProperty:"Discrete Frame Intervals supported" withValue:buf atDepth:INTERFACE_LEVEL+1]; for (i = 0, t = &pUncompressedDiscreteFrameDesc->dwFrameInterval[0]; i < pUncompressedDiscreteFrameDesc->bFrameIntervalType; i++, t++ ) { UInt32 interval = *t; sprintf((char *)buf, "0x%lx (%8.3f ms)", Swap32(&interval), (double) (interval / 10000)); sprintf((char *)buf2, "dwFrameInterval[%u] (100 ns)", i+1 ); [thisDevice addProperty:buf2 withValue:buf atDepth:INTERFACE_LEVEL+2]; } } break; // default: } } } char MapNumberToVersion( int i ) { char rev; switch (i) { case 1: rev = 'a'; break; case 2: rev = 'b'; break; case 3: rev = 'c'; break; case 4: rev = 'd'; break; case 5: rev = 'e'; break; case 6: rev = 'f'; break; case 7: rev = 'g'; break; case 8: rev = 'h'; break; case 9: rev = 'i'; break; default: rev = 'a'; } return rev; } @end