/* An object whose purpose is to abstract a USB audio class device descriptor. The basic idea is that a USB device is described by a chunk of memory on the device. This chunk of memory is formatted with length bytes so that you can skip over any data that you don't care about, and is aranged into a basic list, starting with the device descriptor, then one or more configuration descriptors, one or more stream descriptors, and one or more HID descriptors. It is possible for the configutation and stream descriptors to come in any order and not necessarily all config descriptors, then all stream descriptors. Because Mac OS X's implementation of USB services doesn't allow you to get the device descriptor, this object only parses configuration and interface descriptors. Code calling this object's init function must pass it configuration descriptor pointer, which is gotten from the USB services API via GetFullConfigurationDescriptor (). To use this code you do all of your interactions through the USBAudioConfigObject. You do not directly call any of the other objects. First allocate a USBAudioConfigObject and call its init function which will do the parsing of config descriptor and create the other objects as necessary. Once the config object has been init'ed you should call GetNumStreamInterfaces, GetNumAltStreamInterfaces, and GetFirstStreamInterfaceNum so that you know how many interfaces there are and can query each interface for its properties. Once you have found an interface that has the properties that you want you can proceed with the normal USB calls to select and configure that interface. The implementation of USBAudioConfigObject is to create two OSArrays, one for the control interfaces and one for the stream interfaces. As the configuration descriptor is parsed new control or stream objects are created and inserted in the appropriate array after being filled in with the information from the parsed descriptor. */ #include #include #include "USBAudioObject.h" #include "AppleUSBAudioCommon.h" /* ------------------------------------------------------ USBAudioConfigObject ------------------------------------------------------ */ OSDefineMetaClassAndStructors (USBAudioConfigObject, OSObject); /* Public methods */ USBAudioConfigObject * USBAudioConfigObject::create (const IOUSBConfigurationDescriptor * newConfigurationDescriptor, UInt8 controlInterfaceNum) { USBAudioConfigObject * configObject; configObject = new USBAudioConfigObject; FailIf (NULL == configObject, Exit); if (FALSE == configObject->init (newConfigurationDescriptor, controlInterfaceNum)) { configObject->release(); configObject = 0; } Exit: return configObject; } #if DEBUGLOG void USBAudioConfigObject::DumpConfigMemoryToIOLog (void) { #if 0 UInt8 * descriptorPtr; UInt8 descriptorIndex; UInt8 length; descriptorPtr = (UInt8*)theConfigurationDescriptorPtr; while (*descriptorPtr != 0) { length = *descriptorPtr; for (descriptorIndex = 0; descriptorIndex < length; descriptorIndex++) { debug2IOLog ("%2x ", *descriptorPtr++); } debugIOLog ("\n"); } #endif } #endif bool USBAudioConfigObject::init (const IOUSBConfigurationDescriptor * newConfigurationDescriptor, UInt8 controlInterfaceNum) { Boolean result; result = FALSE; FailIf (FALSE == OSObject::init (), Exit); FailIf (NULL == newConfigurationDescriptor, Exit); theControlInterfaceNum = controlInterfaceNum; debug2IOLog ("allocating %d bytes for config descriptor\n", USBToHostWord (newConfigurationDescriptor->wTotalLength)); theConfigurationDescriptorPtr = (IOUSBConfigurationDescriptor *)IOMalloc (USBToHostWord (newConfigurationDescriptor->wTotalLength) + 1); FailIf (NULL == theConfigurationDescriptorPtr, Exit); memcpy (theConfigurationDescriptorPtr, newConfigurationDescriptor, USBToHostWord (newConfigurationDescriptor->wTotalLength)); ((UInt8 *)theConfigurationDescriptorPtr)[USBToHostWord (newConfigurationDescriptor->wTotalLength)] = 0; #if DEBUGLOG DumpConfigMemoryToIOLog (); #endif ParseConfigurationDescriptor (); result = TRUE; Exit: if (NULL != theConfigurationDescriptorPtr) { IOFree (theConfigurationDescriptorPtr, USBToHostWord (newConfigurationDescriptor->wTotalLength) + 1); theConfigurationDescriptorPtr = NULL; } return result; } void USBAudioConfigObject::free (void) { if (NULL != theControls) { theControls->release (); theControls = NULL; } if (NULL != theStreams) { theStreams->release (); theStreams = NULL; } if (NULL != theConfigurationDescriptorPtr) { IOFree (theConfigurationDescriptorPtr, USBToHostWord (theConfigurationDescriptorPtr->wTotalLength) + 1); } OSObject::free (); } Boolean USBAudioConfigObject::ChannelHasMuteControl (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 featureUnitID, UInt8 channelNum) { USBAudioControlObject * thisControl; Boolean theControl; theControl = FALSE; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) theControl = thisControl->ChannelHasMuteControl (featureUnitID, channelNum); return theControl; } Boolean USBAudioConfigObject::ChannelHasVolumeControl (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 featureUnitID, UInt8 channelNum) { USBAudioControlObject * thisControl; Boolean theControl; theControl = FALSE; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) theControl = thisControl->ChannelHasVolumeControl (featureUnitID, channelNum); return theControl; } UInt8 USBAudioConfigObject::FindNextAltInterfaceWithNumChannels (UInt8 interfaceNum, UInt8 startingAltInterface, UInt8 numChannelsRequested) { UInt16 numAltInterfaces; UInt8 altInterface; UInt8 altInterfaceIndx; altInterface = 255; if (startingAltInterface == 0) startingAltInterface = 1; numAltInterfaces = GetNumAltStreamInterfaces (interfaceNum); for (altInterfaceIndx = startingAltInterface; altInterfaceIndx < numAltInterfaces && altInterface == 255; altInterfaceIndx++) { if (numChannelsRequested == GetNumChannels (interfaceNum, altInterfaceIndx)) { altInterface = altInterfaceIndx; } } return altInterface; } UInt8 USBAudioConfigObject::FindNextAltInterfaceWithSampleSize (UInt8 interfaceNum, UInt8 startingAltInterface, UInt8 sampleSizeRequested) { UInt16 numAltInterfaces; UInt8 altInterface; UInt8 altInterfaceIndx; altInterface = 255; if (startingAltInterface == 0) startingAltInterface = 1; numAltInterfaces = GetNumAltStreamInterfaces (interfaceNum); for (altInterfaceIndx = startingAltInterface; altInterfaceIndx < numAltInterfaces && altInterface == 255; altInterfaceIndx++) { if (sampleSizeRequested == GetSampleSize (interfaceNum, altInterfaceIndx)) { altInterface = altInterfaceIndx; } } return altInterface; } UInt8 USBAudioConfigObject::FindNextAltInterfaceWithSampleRate (UInt8 interfaceNum, UInt8 startingAltInterface, UInt32 sampleRateRequested) { UInt16 numAltInterfaces; UInt8 altInterface; UInt8 altInterfaceIndx; altInterface = 255; if (startingAltInterface == 0) startingAltInterface = 1; numAltInterfaces = GetNumAltStreamInterfaces (interfaceNum); for (altInterfaceIndx = startingAltInterface; altInterfaceIndx < numAltInterfaces && altInterface == 255; altInterfaceIndx++) { if (TRUE == VerifySampleRateIsSupported (interfaceNum, altInterfaceIndx, sampleRateRequested)) { altInterface = altInterfaceIndx; } } return altInterface; } UInt8 USBAudioConfigObject::FindAltInterfaceWithSettings (UInt8 interfaceNum, UInt8 numChannels, UInt8 sampleSize, UInt32 sampleRate) { UInt8 potentialAltInterface; UInt8 theAltInterface; Boolean found; potentialAltInterface = 1; theAltInterface = 255; found = FALSE; while (!found && potentialAltInterface != 255) { potentialAltInterface = FindNextAltInterfaceWithNumChannels (interfaceNum, potentialAltInterface, numChannels); FailIf (255 == potentialAltInterface, Exit); if (potentialAltInterface == FindNextAltInterfaceWithSampleSize (interfaceNum, potentialAltInterface, sampleSize)) { FailIf (255 == potentialAltInterface, Exit); if (0 != sampleRate) { // they want a specific sample rate on this interface if (potentialAltInterface == FindNextAltInterfaceWithSampleRate (interfaceNum, potentialAltInterface, sampleRate)) { found = TRUE; theAltInterface = potentialAltInterface; } else { potentialAltInterface++; } } else { // they don't care about the sample rate found = TRUE; theAltInterface = potentialAltInterface; } } else { potentialAltInterface++; } } Exit: return theAltInterface; } UInt32 USBAudioConfigObject::GetAC3BSID (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt32 bmBSID; bmBSID = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) bmBSID = thisStream->GetAC3BSID (); return bmBSID; } UInt8 USBAudioConfigObject::GetFeatureUnitIDConnectedToOutputTerminal (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 outputTerminalID) { USBAudioControlObject * thisControl; UInt8 featureUnitID; featureUnitID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) featureUnitID = thisControl->GetFeatureUnitIDConnectedToOutputTerminal (outputTerminalID); return featureUnitID; } UInt8 USBAudioConfigObject::GetFirstStreamInterfaceNum (void) { USBAudioStreamObject * thisStream; UInt8 interfaceNum; thisStream = NULL; interfaceNum = 0; if (NULL != theStreams) { thisStream = OSDynamicCast (USBAudioStreamObject, theStreams->getObject (0)); } if (thisStream) interfaceNum = thisStream->GetInterfaceNum (); return interfaceNum; } void USBAudioConfigObject::GetControlledStreamNumbers (UInt8 **controledStreams, UInt8 *numControledStreams) { USBAudioControlObject * thisControl; *controledStreams = 0; *numControledStreams = 0; thisControl = NULL; if (NULL != theControls) { thisControl = OSDynamicCast (USBAudioControlObject, theControls->getObject (0)); } else { debugIOLog ("couldn't get the control object\n"); } if (thisControl) { *controledStreams = thisControl->GetStreamInterfaceNumbers (); *numControledStreams = thisControl->GetNumStreamInterfaces (); } } UInt8 USBAudioConfigObject::GetControlInterfaceNum (void) { USBAudioControlObject * thisControl; UInt8 interfaceNum; thisControl = NULL; interfaceNum = 0; if (NULL != theControls) { thisControl = OSDynamicCast (USBAudioControlObject, theControls->getObject (0)); } if (thisControl) interfaceNum = thisControl->GetInterfaceNum (); return interfaceNum; } UInt16 USBAudioConfigObject::GetFormat (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt16 formatTag; formatTag = TYPE_I_UNDEFINED; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) formatTag = USBToHostWord (thisStream->GetFormatTag ()); return formatTag; } UInt32 USBAudioConfigObject::GetHighestSampleRate (UInt8 interfaceNum, UInt8 altInterfaceNum) { UInt32 * sampleRates; UInt32 highSampleRate; UInt32 i; UInt8 numSampleRates; UInt8 highest; highSampleRate = 0; numSampleRates = GetNumSampleRates (interfaceNum, altInterfaceNum); sampleRates = GetSampleRates (interfaceNum, altInterfaceNum); FailIf (NULL == sampleRates, Exit); highest = 0; for (i = 1; i < numSampleRates; i++) { if (sampleRates[i] > sampleRates[highest]) highest = i; } highSampleRate = sampleRates[highest]; Exit: return highSampleRate; } UInt8 USBAudioConfigObject::GetIsocAssociatedEndpointAddress (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 address) { USBAudioStreamObject * thisStream; UInt8 assocEndpointAddress; assocEndpointAddress = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) assocEndpointAddress = thisStream->GetIsocAssociatedEndpointAddress (address); return assocEndpointAddress; } UInt8 USBAudioConfigObject::GetIsocAssociatedEndpointRefreshInt (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 address) { USBAudioStreamObject * thisStream; UInt8 assocEndpointRefresh; assocEndpointRefresh = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) assocEndpointRefresh = thisStream->GetIsocAssociatedEndpointRefreshInt (address); return assocEndpointRefresh; } UInt8 USBAudioConfigObject::GetIsocEndpointAddress (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 direction) { USBAudioStreamObject * thisStream; UInt8 endpointAddress; endpointAddress = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) endpointAddress = thisStream->GetIsocEndpointAddress (direction); return endpointAddress; } // Use GetTerminalLink to get the unit number of the input or output terminal that the endpoint is associated with. // Once you have that terminal, you can figure out if it's an input or output terminal, and once you know that you // know which direction the endpoint is supposed to be. UInt8 USBAudioConfigObject::GetIsocEndpointDirection (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; USBAudioControlObject * thisControl; UInt8 endpointDirection; UInt8 terminalLink; UInt8 numOutputs; UInt8 numInputs; UInt8 numEndpoints; UInt8 index; UInt8 terminalID; UInt8 direction; endpointDirection = 0xFF; direction = 0xFF; index = 0; numEndpoints = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); debug4IOLog ("GetIsocEndpointDirection (%d, %d), thisStream = %p\n", interfaceNum, altInterfaceNum, thisStream); thisControl = GetControlObject (theControlInterfaceNum, 0); debug4IOLog ("GetIsocEndpointDirection (%d, %d), thisControl = %p\n", interfaceNum, altInterfaceNum, thisControl); if (NULL != thisStream && NULL != thisControl) { terminalLink = thisStream->GetTerminalLink (); // returns the unitID of the terminal the endpoint goes with debug4IOLog ("GetIsocEndpointDirection (%d, %d), terminalLink = %d\n", interfaceNum, altInterfaceNum, terminalLink); if (0 != terminalLink) { numOutputs = thisControl->GetNumOutputTerminals (); debug4IOLog ("GetIsocEndpointDirection (%d, %d), numOutputs = %d\n", interfaceNum, altInterfaceNum, numOutputs); while (0xFF == direction && index < numOutputs) { terminalID = thisControl->GetIndexedOutputTerminalID (index); debug4IOLog ("GetIsocEndpointDirection (%d, %d), terminalID = %d\n", interfaceNum, altInterfaceNum, terminalID); if (terminalID == terminalLink) { direction = kUSBIn; numEndpoints = numOutputs; debug5IOLog ("GetIsocEndpointDirection (%d, %d), found an output terminal (#%d) at index %d\n", interfaceNum, altInterfaceNum, terminalID, index); } else { index++; } } if (0xFF == direction) { numInputs = thisControl->GetNumInputTerminals (); debug3IOLog ("GetIsocEndpointDirection (%d, %d), Didn't find an output terminal, checking for an input terminal\n", interfaceNum, altInterfaceNum); debug4IOLog ("GetIsocEndpointDirection (%d, %d), numInputs = %d\n", interfaceNum, altInterfaceNum, numInputs); index = 0; while (0xFF == direction && index < numInputs) { terminalID = thisControl->GetIndexedInputTerminalID (index); debug4IOLog ("GetIsocEndpointDirection, terminalID = %d\n", interfaceNum, altInterfaceNum, terminalID); if (terminalID == terminalLink) { direction = kUSBOut; numEndpoints = numInputs; debug5IOLog ("GetIsocEndpointDirection (%d, %d), found an input terminal (#%d) at index %d\n", interfaceNum, altInterfaceNum, terminalID, index); } else { index++; } } } } if (0xFF != direction) { for (index = 0; index < numEndpoints; index++) { endpointDirection = thisStream->GetIsocEndpointDirection (index); if (endpointDirection == direction) { break; // found the right endpoint, get out of for loop } } } } debug4IOLog ("GetIsocEndpointDirection (%d, %d), endpointDirection = %d\n", interfaceNum, altInterfaceNum, endpointDirection); return endpointDirection; } UInt8 USBAudioConfigObject::GetIsocEndpointSyncType (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 address) { USBAudioStreamObject * thisStream; UInt8 endpointSyncType; endpointSyncType = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) endpointSyncType = thisStream->GetIsocEndpointSyncType (address); return endpointSyncType; } UInt8 USBAudioConfigObject::GetIndexedFeatureUnitID (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 featureUnitIndex) { USBAudioControlObject * thisControl; UInt8 featureUnitID; featureUnitID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) featureUnitID = thisControl->GetIndexedFeatureUnitID (featureUnitIndex); return featureUnitID; } UInt8 USBAudioConfigObject::GetIndexedMixerUnitID (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 mixerUnitIndex) { USBAudioControlObject * thisControl; UInt8 mixerUnitID; mixerUnitID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) mixerUnitID = thisControl->GetIndexedMixerUnitID (mixerUnitIndex); return mixerUnitID; } UInt8 USBAudioConfigObject::GetIndexedSelectorUnitID (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 selectorUnitIndex) { USBAudioControlObject * thisControl; UInt8 selectorUnitID; selectorUnitID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) selectorUnitID = thisControl->GetIndexedSelectorUnitID (selectorUnitIndex); return selectorUnitID; } UInt16 USBAudioConfigObject::GetIndexedInputTerminalType (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 index) { USBAudioControlObject * thisControl; UInt16 terminalType; terminalType = USBToHostWord (INPUT_UNDEFINED); thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalType = USBToHostWord (thisControl->GetIndexedInputTerminalType (index)); return terminalType; } UInt8 USBAudioConfigObject::GetIndexedInputTerminalID (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 index) { USBAudioControlObject * thisControl; UInt16 terminalID; terminalID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalID = thisControl->GetIndexedInputTerminalID (index); return terminalID; } UInt8 USBAudioConfigObject::GetIndexedOutputTerminalID (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 index) { USBAudioControlObject * thisControl; UInt16 terminalID; terminalID = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalID = thisControl->GetIndexedOutputTerminalID (index); return terminalID; } UInt16 USBAudioConfigObject::GetIndexedOutputTerminalType (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 index) { USBAudioControlObject * thisControl; UInt16 terminalType; terminalType = USBToHostWord (OUTPUT_UNDEFINED); thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalType = USBToHostWord (thisControl->GetIndexedOutputTerminalType (index)); return terminalType; } UInt16 USBAudioConfigObject::GetInputTerminalType (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 terminalNum) { USBAudioControlObject * thisControl; UInt16 terminalType; terminalType = USBToHostWord (INPUT_UNDEFINED); thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalType = USBToHostWord (thisControl->GetInputTerminalType (terminalNum)); return terminalType; } UInt8 USBAudioConfigObject::GetInterfaceClass (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 interfaceClass; interfaceClass = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) interfaceClass = thisStream->GetInterfaceClass (); return interfaceClass; } UInt8 USBAudioConfigObject::GetInterfaceSubClass (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 interfaceSubClass; interfaceSubClass = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) interfaceSubClass = thisStream->GetInterfaceSubClass (); return interfaceSubClass; } UInt32 USBAudioConfigObject::GetLowestSampleRate (UInt8 interfaceNum, UInt8 altInterfaceNum) { UInt32 * sampleRates; UInt32 lowSampleRate; UInt32 i; UInt8 numSampleRates; UInt8 lowest; lowSampleRate = 0xFFFFFFFF; numSampleRates = GetNumSampleRates (interfaceNum, altInterfaceNum); sampleRates = GetSampleRates (interfaceNum, altInterfaceNum); FailIf (NULL == sampleRates, Exit); lowest = 0; for (i = 1; i < numSampleRates; i++) { if (sampleRates[i] < sampleRates[lowest]) lowest = i; } lowSampleRate = sampleRates[lowest]; Exit: return lowSampleRate; } UInt16 USBAudioConfigObject::GetMaxBitRate (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt16 maxBitRate; maxBitRate = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) maxBitRate = USBToHostWord (thisStream->GetMaxBitRate ()); return maxBitRate; } UInt8 USBAudioConfigObject::GetNumAltStreamInterfaces (UInt8 interfaceNum) { USBAudioStreamObject * thisStream; UInt16 numAltInterfaces; UInt16 indx; numAltInterfaces = 0; if (NULL != theStreams) { debug2IOLog ("USBAudioConfigObject::GetNumAltInterfaces %d = theStreams->getCount ()\n", theStreams->getCount ()); for (indx = 0; indx < theStreams->getCount (); indx++) { thisStream = OSDynamicCast (USBAudioStreamObject, theStreams->getObject (indx)); if (thisStream && thisStream->GetInterfaceNum () == interfaceNum) { numAltInterfaces++; } } } return numAltInterfaces; } UInt8 USBAudioConfigObject::GetNumChannels (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 numChannels; numChannels = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) numChannels = thisStream->GetNumChannels (); return numChannels; } UInt8 USBAudioConfigObject::GetNumSampleRates (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 numSampleRates; numSampleRates = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) numSampleRates = thisStream->GetNumSampleRates (); return numSampleRates; } UInt8 USBAudioConfigObject::GetNumInputTerminals (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioControlObject * thisControl; UInt8 numInputTerminals; numInputTerminals = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) numInputTerminals = thisControl->GetNumInputTerminals (); return numInputTerminals; } UInt8 USBAudioConfigObject::GetNumOutputTerminals (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioControlObject * thisControl; UInt8 numOutputTerminals; numOutputTerminals = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) numOutputTerminals = thisControl->GetNumOutputTerminals (); return numOutputTerminals; } UInt8 USBAudioConfigObject::GetNumSelectorSources (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 unitID) { USBAudioControlObject * thisControl; UInt8 numSelectorSources; numSelectorSources = 0; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) numSelectorSources = thisControl->GetNumSelectorSources (unitID); return numSelectorSources; } UInt8 USBAudioConfigObject::GetNumStreamInterfaces (void) { USBAudioStreamObject * thisStream; UInt16 numInterfaces; UInt16 interfaceNum; UInt16 indx; numInterfaces = 0; interfaceNum = 0; if (NULL != theStreams) { debug2IOLog ("USBAudioConfigObject::GetNumInterfaces %d = theStreams->getCount ()\n", theStreams->getCount ()); for (indx = 0; indx < theStreams->getCount (); indx++) { thisStream = OSDynamicCast (USBAudioStreamObject, theStreams->getObject (indx)); if (thisStream && thisStream->GetInterfaceNum () != interfaceNum) { interfaceNum = thisStream->GetInterfaceNum (); numInterfaces++; } } } return numInterfaces; } UInt16 USBAudioConfigObject::GetSamplesPerFrame (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt16 samplesPerFrame; samplesPerFrame = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) samplesPerFrame = USBToHostWord (thisStream->GetMaxBitRate ()); return samplesPerFrame; } UInt32 * USBAudioConfigObject::GetSampleRates (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt32 * sampleRates; sampleRates = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) sampleRates = thisStream->GetSampleRates (); return sampleRates; } UInt8 USBAudioConfigObject::GetSampleSize (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 sampleSize; sampleSize = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) sampleSize = thisStream->GetSampleSize (); return sampleSize; } UInt8 * USBAudioConfigObject::GetSelectorSources (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 unitID) { USBAudioControlObject * thisControl; UInt8 * sources; sources = NULL; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) sources = thisControl->GetSelectorSources (unitID); return sources; } UInt8 USBAudioConfigObject::GetSubframeSize (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 subframeSize; subframeSize = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) subframeSize = thisStream->GetSubframeSize (); return subframeSize; } UInt8 USBAudioConfigObject::GetTerminalLink (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 terminalLink; terminalLink = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) terminalLink = thisStream->GetTerminalLink (); return terminalLink; } UInt16 USBAudioConfigObject::GetOutputTerminalType (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 terminalNum) { USBAudioControlObject * thisControl; UInt16 terminalType; terminalType = USBToHostWord (OUTPUT_UNDEFINED); thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) terminalType = USBToHostWord (thisControl->GetOutputTerminalType (terminalNum)); return terminalType; } Boolean USBAudioConfigObject::IsocEndpointDoesMaxPacketsOnly (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; Boolean maxPacketsOnly; maxPacketsOnly = FALSE; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) maxPacketsOnly = thisStream->IsocEndpointDoesMaxPacketsOnly (); return maxPacketsOnly; } UInt8 USBAudioConfigObject::IsocEndpointGetLockDelay (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 lockDelay; lockDelay = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) lockDelay = thisStream->IsocEndpointGetLockDelay (); return lockDelay; } UInt8 USBAudioConfigObject::IsocEndpointGetLockDelayUnits (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 lockDelayUnits; lockDelayUnits = 0; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) lockDelayUnits = thisStream->IsocEndpointGetLockDelayUnits (); return lockDelayUnits; } Boolean USBAudioConfigObject::IsocEndpointHasPitchControl (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; Boolean hasPitchCntrl; hasPitchCntrl = FALSE; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) hasPitchCntrl = thisStream->IsocEndpointHasPitchControl (); return hasPitchCntrl; } Boolean USBAudioConfigObject::IsocEndpointHasSampleFreqControl (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; Boolean hasSampleFreqCntrl; hasSampleFreqCntrl = FALSE; thisStream = GetStreamObject (interfaceNum, altInterfaceNum); if (thisStream) hasSampleFreqCntrl = thisStream->IsocEndpointHasSampleFreqControl (); return hasSampleFreqCntrl; } Boolean USBAudioConfigObject::MasterHasMuteControl (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt8 featureUnitID) { USBAudioControlObject * thisControl; Boolean theControl; theControl = FALSE; thisControl = GetControlObject (interfaceNum, altInterfaceNum); if (thisControl) theControl = thisControl->MasterHasMuteControl (featureUnitID); return theControl; } Boolean USBAudioConfigObject::VerifySampleRateIsSupported (UInt8 interfaceNum, UInt8 altInterfaceNum, UInt32 verifyRate) { IOReturn result; UInt32 * sampleRates; UInt8 rateIndx; UInt8 numSampleRates; result = FALSE; numSampleRates = GetNumSampleRates (interfaceNum, altInterfaceNum); sampleRates = GetSampleRates (interfaceNum, altInterfaceNum); if (numSampleRates) { // There are a discrete number of sample rates supported, so check each one to see if they support the one we want. for (rateIndx = 0; rateIndx < numSampleRates && result == FALSE; rateIndx++) { if (sampleRates[rateIndx] == verifyRate) { result = TRUE; } } } else if (sampleRates) { // There is a range of sample rates supported, so check to see if the one we want is within that range. if (sampleRates[0] <= verifyRate && sampleRates[1] >= verifyRate) { result = TRUE; } } else { debugIOLog ("!!!!There aren't any sample rates!!!!\n"); } return result; } /* Private methods */ USBAudioStreamObject * USBAudioConfigObject::GetStreamObject (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioStreamObject * thisStream; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisStream = NULL; if (NULL != theStreams) { while (!found && indx < theStreams->getCount ()) { thisStream = OSDynamicCast (USBAudioStreamObject, theStreams->getObject (indx)); if (thisStream && interfaceNum == thisStream->GetInterfaceNum () && altInterfaceNum == thisStream->GetAltInterfaceNum ()) { found = TRUE; } indx++; } } if (found != TRUE) thisStream = NULL; return thisStream; } USBAudioControlObject * USBAudioConfigObject::GetControlObject (UInt8 interfaceNum, UInt8 altInterfaceNum) { USBAudioControlObject * thisControl; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisControl = NULL; if (NULL != theControls) { while (!found && indx < theControls->getCount ()) { thisControl = OSDynamicCast (USBAudioControlObject, theControls->getObject (indx)); if (thisControl && interfaceNum == thisControl->GetInterfaceNum () && altInterfaceNum == thisControl->GetAltInterfaceNum ()) { found = TRUE; } indx++; } } if (found != TRUE) thisControl = NULL; return thisControl; } void USBAudioConfigObject::ParseConfigurationDescriptor (void) { USBInterfaceDescriptorPtr theInterfacePtr; USBAudioControlObject * theControlObject; USBAudioStreamObject * theStreamObject; UInt8 * streamInterfaceNumbers; UInt8 thisInterfaceNumber; UInt8 lastInterfaceNumber; UInt8 numStreamInterfaces; UInt8 interfaceClass; UInt8 interfaceSubClass; UInt8 numParsedInterfaces; UInt8 index; bool haveControlInterface; bool foundStreamInterface; FailIf (NULL == theConfigurationDescriptorPtr, Exit); FailIf (0 == theConfigurationDescriptorPtr->bLength, Exit); FailIf (CONFIGURATION != theConfigurationDescriptorPtr->bDescriptorType, Exit); theControlObject = NULL; theStreamObject = NULL; theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theConfigurationDescriptorPtr + theConfigurationDescriptorPtr->bLength); numParsedInterfaces = 0; numStreamInterfaces = 0; lastInterfaceNumber = 0; haveControlInterface = FALSE; foundStreamInterface = FALSE; while (theInterfacePtr && 0 != theInterfacePtr->bLength) { if (INTERFACE == ((ACInterfaceDescriptorPtr)theInterfacePtr)->bDescriptorType) { debugIOLog ("in INTERFACE in ParseConfigurationDescriptor\n"); thisInterfaceNumber = ((ACInterfaceDescriptorPtr)theInterfacePtr)->bInterfaceNumber; theInterfacePtr = ParseInterfaceDescriptor (theInterfacePtr, &interfaceClass, &interfaceSubClass); debug3IOLog ("theControlInterfaceNum = %d, thisInterfaceNumber = %d\n", theControlInterfaceNum, thisInterfaceNumber); if (AUDIOCONTROL == interfaceSubClass && theControlInterfaceNum == thisInterfaceNumber) { debugIOLog ("found a AUDIOCONTROL CS_INTERFACE \n"); if (NULL != theControls) { theControlObject = OSDynamicCast (USBAudioControlObject, theControls->getLastObject ()); } FailIf (NULL == theControlObject, Exit); theInterfacePtr = theControlObject->ParseACInterfaceDescriptor (theInterfacePtr, ((ACInterfaceDescriptorPtr)theInterfacePtr)->bInterfaceNumber); GetControlledStreamNumbers (&streamInterfaceNumbers, &numStreamInterfaces); haveControlInterface = TRUE; } else if (haveControlInterface && AUDIOSTREAMING == interfaceSubClass) { debugIOLog ("in CS_INTERFACE in ParseConfigurationDescriptor\n"); for (index = 0; index < numStreamInterfaces; index++) { debug3IOLog ("comparing thisInterfaceNum = %d with %d\n", thisInterfaceNumber, streamInterfaceNumbers[index]); if (thisInterfaceNumber == streamInterfaceNumbers[index]) { debugIOLog ("found a AUDIOSTREAMING CS_INTERFACE \n"); if (NULL != theStreams) { theStreamObject = OSDynamicCast (USBAudioStreamObject, theStreams->getLastObject ()); } FailIf (NULL == theStreamObject, Exit); theInterfacePtr = theStreamObject->ParseASInterfaceDescriptor (theInterfacePtr, ((ACInterfaceDescriptorPtr)theInterfacePtr)->bInterfaceNumber); foundStreamInterface = TRUE; break; // Get out of for loop } } if (thisInterfaceNumber != lastInterfaceNumber) { lastInterfaceNumber = thisInterfaceNumber; numParsedInterfaces++; if (numParsedInterfaces > numStreamInterfaces) { break; // Get out of while loop, we've parsed everything associated with this control interface } } } else if (MIDISTREAMING == interfaceSubClass) { debug2IOLog ("MIDI, jumping forward %d bytes\n", theInterfacePtr->bLength); for (index = 0; index < numStreamInterfaces; index++) { if (thisInterfaceNumber == streamInterfaceNumbers[index]) { break; } } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } else if (AUDIOCONTROL == interfaceSubClass) { debugIOLog ("Found a control interface that we don't care about\n"); debug2IOLog ("jumping forward %d bytes\n", ((((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->wTotalLength[1] << 8) | (((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->wTotalLength[0]))); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + ((((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->wTotalLength[1] << 8) | (((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->wTotalLength[0]))); } else { debug2IOLog ("Unknown, jumping forward %d bytes\n", theInterfacePtr->bLength); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } } else { debug2IOLog ("in default in ParseConfigurationDescriptor, jumping forward %d bytes\n", theInterfacePtr->bLength); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } } if (theControlObject && FALSE == foundStreamInterface) { theControls->removeObject (theControls->getCount () - 1); } Exit: return; } USBInterfaceDescriptorPtr USBAudioConfigObject::ParseInterfaceDescriptor (USBInterfaceDescriptorPtr theInterfacePtr, UInt8 * interfaceClass, UInt8 * interfaceSubClass) { USBAudioControlObject * theControlObject; USBAudioStreamObject * theStreamObject; debugIOLog ("in ParseInterfaceDescriptor\n"); FailIf (NULL == theInterfacePtr, Exit); FailIf (0 == theInterfacePtr->bLength, Exit); if (NULL != interfaceClass) *interfaceClass = theInterfacePtr->bInterfaceClass; if (NULL != interfaceSubClass) *interfaceSubClass = theInterfacePtr->bInterfaceSubClass; if (AUDIOCONTROL == theInterfacePtr->bInterfaceSubClass) { debugIOLog ("found a AUDIOCONTROL interface\n"); if (theControlInterfaceNum == theInterfacePtr->bDescriptorSubtype) { theControlObject = USBAudioControlObject::create (); FailIf (NULL == theControlObject, Exit); theControlObject->SetInterfaceNumber (theInterfacePtr->bDescriptorSubtype); theControlObject->SetAlternateSetting (theInterfacePtr->bAlternateSetting); theControlObject->SetNumEndpoints (theInterfacePtr->bNumEndpoints); theControlObject->SetInterfaceClass (theInterfacePtr->bInterfaceClass); theControlObject->SetInterfaceSubClass (theInterfacePtr->bInterfaceSubClass); theControlObject->SetInterfaceProtocol (theInterfacePtr->bInterfaceProtocol); if (NULL == theControls) { theControls = OSArray::withObjects ((const OSObject **)&theControlObject, 1); FailIf (NULL == theControls, Exit); } else { theControls->setObject (theControlObject); } theControlObject->release (); } } else if (AUDIOSTREAMING == theInterfacePtr->bInterfaceSubClass) { debugIOLog ("found a AUDIOSTREAMING interface\n"); theStreamObject = USBAudioStreamObject::create (); FailIf (NULL == theStreamObject, Exit); theStreamObject->SetInterfaceNumber (theInterfacePtr->bDescriptorSubtype); theStreamObject->SetAlternateSetting (theInterfacePtr->bAlternateSetting); theStreamObject->SetNumEndpoints (theInterfacePtr->bNumEndpoints); theStreamObject->SetInterfaceClass (theInterfacePtr->bInterfaceClass); theStreamObject->SetInterfaceSubClass (theInterfacePtr->bInterfaceSubClass); theStreamObject->SetInterfaceProtocol (theInterfacePtr->bInterfaceProtocol); if (NULL == theStreams) { theStreams = OSArray::withObjects ((const OSObject **)&theStreamObject, 1); FailIf (NULL == theStreams, Exit); } else { theStreams->setObject (theStreamObject); } theStreamObject->release (); } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); Exit: return theInterfacePtr; } /* ------------------------------------------------------ USBAudioControlObject ------------------------------------------------------ */ /* Public methods */ OSDefineMetaClassAndStructors (USBAudioControlObject, OSObject); USBAudioControlObject * USBAudioControlObject::create (void) { USBAudioControlObject * controlObject; controlObject = new USBAudioControlObject; FailIf (NULL == controlObject, Exit); if (FALSE == controlObject->init ()) { controlObject->release (); controlObject = 0; } Exit: return controlObject; } void USBAudioControlObject::free (void) { if (NULL != theInputTerminals) { theInputTerminals->release (); theInputTerminals = NULL; } if (NULL != theOutputTerminals) { theOutputTerminals->release (); theOutputTerminals = NULL; } if (NULL != theFeatureUnits) { theFeatureUnits->release (); theFeatureUnits = NULL; } if (NULL != theMixerUnits) { theMixerUnits->release (); theMixerUnits = NULL; } if (NULL != theSelectorUnits) { theSelectorUnits->release (); theSelectorUnits = NULL; } OSObject::free (); } // Channel #1 is left channel, #2 is right channel Boolean USBAudioControlObject::ChannelHasMuteControl (UInt8 featureUnitID, UInt8 channelNum) { USBFeatureUnitObject * thisFeatureUnit; Boolean result; result = FALSE; thisFeatureUnit = GetFeatureUnitObject (featureUnitID); if (thisFeatureUnit) result = thisFeatureUnit->ChannelHasMuteControl (channelNum); return result; } Boolean USBAudioControlObject::ChannelHasVolumeControl (UInt8 featureUnitID, UInt8 channelNum) { USBFeatureUnitObject * thisFeatureUnit; Boolean result; result = FALSE; thisFeatureUnit = GetFeatureUnitObject (featureUnitID); if (thisFeatureUnit) result = thisFeatureUnit->ChannelHasVolumeControl (channelNum); return result; } USBACDescriptorObject * USBAudioControlObject::GetACDescriptorObject (UInt8 unitID) { USBACDescriptorObject * thisACDescriptorObject; UInt8 indx; Boolean done; indx = 0; done = FALSE; thisACDescriptorObject = GetInputTerminalObject (unitID); if (!thisACDescriptorObject) thisACDescriptorObject = GetOutputTerminalObject (unitID); if (!thisACDescriptorObject) thisACDescriptorObject = GetMixerObject (unitID); return thisACDescriptorObject; } UInt8 USBAudioControlObject::GetFeatureSourceID (UInt8 featureUnitID) { USBFeatureUnitObject * theFeatureUnit; UInt8 sourceID; sourceID = 0; theFeatureUnit = GetFeatureUnitObject (featureUnitID); if (theFeatureUnit) sourceID = theFeatureUnit->GetSourceID (); return sourceID; } UInt8 USBAudioControlObject::GetIndexedFeatureUnitID (UInt8 featureUnitIndex) { USBFeatureUnitObject * theFeatureUnit; UInt8 unitID; unitID = 0; theFeatureUnit = GetIndexedFeatureUnitObject (featureUnitIndex); if (theFeatureUnit) unitID = theFeatureUnit->GetUnitID (); return unitID; } UInt8 USBAudioControlObject::GetIndexedMixerUnitID (UInt8 mixerUnitIndex) { USBMixerUnitObject * theMixerUnit; UInt8 unitID; unitID = 0; theMixerUnit = GetIndexedMixerUnitObject (mixerUnitIndex); if (theMixerUnit) unitID = theMixerUnit->GetUnitID (); return unitID; } UInt8 USBAudioControlObject::GetIndexedSelectorUnitID (UInt8 selectorUnitIndex) { USBSelectorUnitObject * theSelectorUnit; UInt8 unitID; unitID = 0; theSelectorUnit = GetIndexedSelectorUnitObject (selectorUnitIndex); if (theSelectorUnit) unitID = theSelectorUnit->GetUnitID (); return unitID; } UInt8 USBAudioControlObject::GetFeatureUnitIDConnectedToOutputTerminal (UInt8 outputTerminalID) { USBOutputTerminalObject * thisOutputTerminal; USBFeatureUnitObject * thisFeatureUnit; UInt8 outputTerminalSourceID; UInt8 featureUnitID; outputTerminalSourceID = 0; featureUnitID = 0; thisOutputTerminal = GetOutputTerminalObject (outputTerminalID); if (thisOutputTerminal) outputTerminalSourceID = thisOutputTerminal->GetSourceID (); if (0 != outputTerminalSourceID) { thisFeatureUnit = GetFeatureUnitObject (outputTerminalSourceID); if (thisFeatureUnit) featureUnitID = outputTerminalSourceID; else { // have to keep looking upstream of whatever this object is } } return featureUnitID; } UInt16 USBAudioControlObject::GetIndexedInputTerminalType (UInt8 index) { USBInputTerminalObject * thisInputTerminal; UInt16 terminalType; thisInputTerminal = NULL; terminalType = USBToHostWord (INPUT_UNDEFINED); if (NULL != theInputTerminals) { thisInputTerminal = OSDynamicCast (USBInputTerminalObject, theInputTerminals->getObject (index)); } if (thisInputTerminal) terminalType = USBToHostWord (thisInputTerminal->GetTerminalType ()); return terminalType; } UInt8 USBAudioControlObject::GetIndexedInputTerminalID (UInt8 index) { USBInputTerminalObject * thisInputTerminal; UInt8 terminalID; thisInputTerminal = NULL; terminalID = 0; if (NULL != theInputTerminals) { thisInputTerminal = OSDynamicCast (USBInputTerminalObject, theInputTerminals->getObject (index)); } if (thisInputTerminal) terminalID = thisInputTerminal->GetUnitID (); return terminalID; } UInt8 USBAudioControlObject::GetIndexedOutputTerminalID (UInt8 index) { USBOutputTerminalObject * thisOutputTerminal; UInt8 terminalID; thisOutputTerminal = NULL; terminalID = 0; if (NULL != theOutputTerminals) { thisOutputTerminal = OSDynamicCast (USBOutputTerminalObject, theOutputTerminals->getObject (index)); } if (thisOutputTerminal) terminalID = thisOutputTerminal->GetUnitID (); return terminalID; } UInt16 USBAudioControlObject::GetIndexedOutputTerminalType (UInt8 index) { USBOutputTerminalObject * thisOutputTerminal; UInt16 terminalType; thisOutputTerminal = NULL; terminalType = USBToHostWord (OUTPUT_UNDEFINED); if (NULL != theOutputTerminals) { thisOutputTerminal = OSDynamicCast (USBOutputTerminalObject, theOutputTerminals->getObject (index)); } if (thisOutputTerminal) terminalType = USBToHostWord (thisOutputTerminal->GetTerminalType ()); return terminalType; } USBFeatureUnitObject * USBAudioControlObject::GetIndexedFeatureUnitObject (UInt8 index) { USBFeatureUnitObject * indexedFeatureUnit; indexedFeatureUnit = NULL; if (NULL != theFeatureUnits) { indexedFeatureUnit = OSDynamicCast (USBFeatureUnitObject, theFeatureUnits->getObject (index)); } return indexedFeatureUnit; } USBMixerUnitObject * USBAudioControlObject::GetIndexedMixerUnitObject (UInt8 index) { USBMixerUnitObject * indexedMixerUnit; indexedMixerUnit = NULL; if (NULL != theMixerUnits) { indexedMixerUnit = OSDynamicCast (USBMixerUnitObject, theMixerUnits->getObject (index)); } return indexedMixerUnit; } USBSelectorUnitObject * USBAudioControlObject::GetIndexedSelectorUnitObject (UInt8 index) { USBSelectorUnitObject * indexedSelectorUnit; indexedSelectorUnit = NULL; if (NULL != theSelectorUnits) { indexedSelectorUnit = OSDynamicCast (USBSelectorUnitObject, theSelectorUnits->getObject (index)); } return indexedSelectorUnit; } USBFeatureUnitObject * USBAudioControlObject::GetFeatureUnitObject (UInt8 unitID) { USBFeatureUnitObject * thisFeatureUnit; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisFeatureUnit = NULL; if (NULL != theFeatureUnits) { while (!found && indx < theFeatureUnits->getCount ()) { thisFeatureUnit = OSDynamicCast (USBFeatureUnitObject, theFeatureUnits->getObject (indx)); if (thisFeatureUnit && unitID == thisFeatureUnit->GetUnitID ()) { found = TRUE; } indx++; } } if (found != TRUE) thisFeatureUnit = NULL; return thisFeatureUnit; } USBInputTerminalObject * USBAudioControlObject::GetInputTerminalObject (UInt8 unitID) { USBInputTerminalObject * thisInputTerminal; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisInputTerminal = NULL; if (NULL != theInputTerminals) { while (!found && indx < theInputTerminals->getCount ()) { thisInputTerminal = OSDynamicCast (USBInputTerminalObject, theInputTerminals->getObject (indx)); if (thisInputTerminal && unitID == thisInputTerminal->GetUnitID ()) { found = TRUE; } indx++; } } if (found != TRUE) thisInputTerminal = NULL; return thisInputTerminal; } UInt16 USBAudioControlObject::GetInputTerminalType (UInt8 unitID) { USBInputTerminalObject * thisInputTerminal; UInt16 terminalType; terminalType = USBToHostWord (INPUT_UNDEFINED); thisInputTerminal = GetInputTerminalObject (unitID); if (thisInputTerminal) terminalType = USBToHostWord (thisInputTerminal->GetTerminalType ()); return terminalType; } UInt8 USBAudioControlObject::GetNumInputTerminals (void) { UInt8 count; count = 0; if (NULL != theInputTerminals) { count = theInputTerminals->getCount (); } return count; } UInt8 USBAudioControlObject::GetNumOutputTerminals (void) { UInt8 count; count = 0; if (NULL != theOutputTerminals) { count = theOutputTerminals->getCount (); } return count; } UInt8 USBAudioControlObject::GetNumSelectorSources (UInt8 unitID) { USBSelectorUnitObject * thisSelectorUnit; UInt8 numSelectorSources; numSelectorSources = 0; thisSelectorUnit = GetSelectorUnitObject (unitID); if (thisSelectorUnit) numSelectorSources = thisSelectorUnit->GetNumInPins (); return numSelectorSources; } USBMixerUnitObject * USBAudioControlObject::GetMixerObject (UInt8 unitID) { USBMixerUnitObject * thisMixerObject; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisMixerObject = NULL; if (NULL != theMixerUnits) { while (!found && indx < theMixerUnits->getCount ()) { thisMixerObject = OSDynamicCast (USBMixerUnitObject, theMixerUnits->getObject (indx)); if (thisMixerObject && unitID == thisMixerObject->GetUnitID ()) { found = TRUE; } indx++; } } if (found != TRUE) thisMixerObject = NULL; return thisMixerObject; } USBOutputTerminalObject * USBAudioControlObject::GetOutputTerminalObject (UInt8 unitID) { USBOutputTerminalObject * thisOutputTerminal; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisOutputTerminal = NULL; if (NULL != theOutputTerminals) { while (!found && indx < theOutputTerminals->getCount ()) { thisOutputTerminal = OSDynamicCast (USBOutputTerminalObject, theOutputTerminals->getObject (indx)); if (thisOutputTerminal && unitID == thisOutputTerminal->GetUnitID ()) { found = TRUE; } indx++; } } if (found != TRUE) thisOutputTerminal = NULL; return thisOutputTerminal; } USBSelectorUnitObject * USBAudioControlObject::GetSelectorUnitObject (UInt8 unitID) { USBSelectorUnitObject * thisSelectorObject; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisSelectorObject = NULL; if (NULL != theSelectorUnits) { while (!found && indx < theSelectorUnits->getCount ()) { thisSelectorObject = OSDynamicCast (USBSelectorUnitObject, theSelectorUnits->getObject (indx)); if (thisSelectorObject && unitID == thisSelectorObject->GetUnitID ()) { found = TRUE; } indx++; } } if (found != TRUE) thisSelectorObject = NULL; return thisSelectorObject; } UInt16 USBAudioControlObject::GetOutputTerminalType (UInt8 unitID) { USBOutputTerminalObject * thisOutputTerminal; UInt16 terminalType; terminalType = USBToHostWord (OUTPUT_UNDEFINED); thisOutputTerminal = GetOutputTerminalObject (unitID); if (thisOutputTerminal) terminalType = USBToHostWord (thisOutputTerminal->GetTerminalType ()); return terminalType; } UInt8 * USBAudioControlObject::GetSelectorSources (UInt8 unitID) { USBSelectorUnitObject * thisSelectorUnit; UInt8 * selectorSources; selectorSources = NULL; thisSelectorUnit = GetSelectorUnitObject (unitID); if (thisSelectorUnit) selectorSources = thisSelectorUnit->GetSelectorSources (); return selectorSources; } Boolean USBAudioControlObject::MasterHasMuteControl (UInt8 featureUnitID) { USBFeatureUnitObject * thisFeatureUnit; Boolean result; result = FALSE; thisFeatureUnit = GetFeatureUnitObject (featureUnitID); if (thisFeatureUnit) result = thisFeatureUnit->MasterHasMuteControl (); return result; } USBInterfaceDescriptorPtr USBAudioControlObject::ParseACInterfaceDescriptor (USBInterfaceDescriptorPtr theInterfacePtr, UInt8 const currentInterface) { USBInputTerminalObject * inputTerminal; USBOutputTerminalObject * outputTerminal; USBFeatureUnitObject * featureUnit; USBMixerUnitObject * mixerUnit; USBSelectorUnitObject * selectorUnit; UInt8 index; debug3IOLog ("+USBAudioControlObject::ParseACInterfaceDescriptor (%p, %d)\n", theInterfacePtr, currentInterface); FailIf (NULL == theInterfacePtr, Exit); FailIf (0 == theInterfacePtr->bLength, Exit); FailIf (CS_INTERFACE != theInterfacePtr->bDescriptorType, Exit); while (theInterfacePtr->bLength && CS_INTERFACE == theInterfacePtr->bDescriptorType) { switch (theInterfacePtr->bDescriptorSubtype) { case HEADER: debugIOLog ("in HEADER in ParseACInterfaceDescriptor\n"); adcVersion = USBToHostWord (((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->bcdADC[0]); if (adcVersion != 0x0100) { } // !!!Need to check the adcVersion to make sure that it's 0x0100 or else we don't know how to parse this descriptor!!! numStreamInterfaces = ((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->bInCollection; debug2IOLog ("numStreamInterfaces = %d\n", numStreamInterfaces); streamInterfaceNumbers = (UInt8 *)IOMalloc (numStreamInterfaces); memcpy (streamInterfaceNumbers, ((ACInterfaceHeaderDescriptorPtr)theInterfacePtr)->baInterfaceNr, numStreamInterfaces); debugIOLog ("they are: "); for (index = 0; index < numStreamInterfaces; index++) { debug2IOLog ("%d, ", streamInterfaceNumbers[index]); } debugIOLog ("\n"); break; case INPUT_TERMINAL: debugIOLog ("in INPUT_TERMINAL in ParseACInterfaceDescriptor\n"); inputTerminal = new USBInputTerminalObject; FailIf (NULL == inputTerminal, Exit); inputTerminal->SetUnitID (((ACInputTerminalDescriptorPtr)theInterfacePtr)->bTerminalID); inputTerminal->SetTerminalType (USBToHostWord (((ACInputTerminalDescriptorPtr)theInterfacePtr)->wTerminalType)); inputTerminal->SetAssocTerminal (((ACInputTerminalDescriptorPtr)theInterfacePtr)->bAssocTerminal); inputTerminal->SetNumChannels (((ACInputTerminalDescriptorPtr)theInterfacePtr)->bNrChannels); inputTerminal->SetChannelConfig (USBToHostWord (((ACInputTerminalDescriptorPtr)theInterfacePtr)->wChannelConfig)); if (NULL == theInputTerminals) { theInputTerminals = OSArray::withObjects ((const OSObject **)&inputTerminal, 1); FailIf (NULL == theInputTerminals, Exit); } else { theInputTerminals->setObject (inputTerminal); } inputTerminal->release (); break; case OUTPUT_TERMINAL: debugIOLog ("in OUTPUT_TERMINAL in ParseACInterfaceDescriptor\n"); outputTerminal = new USBOutputTerminalObject; FailIf (NULL == outputTerminal, Exit); outputTerminal->SetUnitID (((ACOutputTerminalDescriptorPtr)theInterfacePtr)->bTerminalID); outputTerminal->SetTerminalType (USBToHostWord (((ACOutputTerminalDescriptorPtr)theInterfacePtr)->wTerminalType)); outputTerminal->SetAssocTerminal (((ACOutputTerminalDescriptorPtr)theInterfacePtr)->bAssocTerminal); outputTerminal->SetSourceID (((ACOutputTerminalDescriptorPtr)theInterfacePtr)->bSourceID); if (NULL == theOutputTerminals) { theOutputTerminals = OSArray::withObjects ((const OSObject **)&outputTerminal, 1); FailIf (NULL == theOutputTerminals, Exit); } else { theOutputTerminals->setObject (outputTerminal); } outputTerminal->release (); break; case FEATURE_UNIT: { UInt8 numControls; debugIOLog ("in FEATURE_UNIT in ParseACInterfaceDescriptor\n"); featureUnit = new USBFeatureUnitObject; FailIf (NULL == featureUnit, Exit); featureUnit->SetUnitID (((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bUnitID); featureUnit->SetSourceID (((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bSourceID); featureUnit->SetControlSize (((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bControlSize); // subtract 7 because that's how many fields are guaranteed to be in the struct numControls = (((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bLength - 7) / ((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bControlSize; debug2IOLog ("There are %d controls on this feature unit\n", numControls); featureUnit->InitControlsArray (&((ACFeatureUnitDescriptorPtr)theInterfacePtr)->bmaControls[0], numControls); if (NULL == theFeatureUnits) { theFeatureUnits = OSArray::withObjects ((const OSObject **)&featureUnit, 1); FailIf (NULL == theFeatureUnits, Exit); } else { theFeatureUnits->setObject (featureUnit); } featureUnit->release (); break; } case MIXER_UNIT: { UInt32 controlSize; UInt16 * channelConfig; UInt8 nrChannels; debugIOLog ("in MIXER_UNIT in ParseACInterfaceDescriptor\n"); mixerUnit = new USBMixerUnitObject; FailIf (NULL == mixerUnit, Exit); debug2IOLog ("descriptor length = %d\n", theInterfacePtr->bLength); mixerUnit->SetUnitID (((ACMixerUnitDescriptorPtr)theInterfacePtr)->bUnitID); debug2IOLog ("unit ID = %d\n", ((ACMixerUnitDescriptorPtr)theInterfacePtr)->bUnitID); debug2IOLog ("numInPins = %d\n", ((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins); mixerUnit->InitSourceIDs (&((ACMixerUnitDescriptorPtr)theInterfacePtr)->baSourceID[0], ((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins); nrChannels = ((ACMixerUnitDescriptorPtr)theInterfacePtr)->baSourceID[((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins]; debug2IOLog ("nrChannels = %d\n", nrChannels); mixerUnit->SetNumChannels (nrChannels); channelConfig = (UInt16 *)&((ACMixerUnitDescriptorPtr)theInterfacePtr)->baSourceID[((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins + 1]; *channelConfig = USBToHostWord (*channelConfig); debug2IOLog ("channelConfig = %d\n", *channelConfig); mixerUnit->SetChannelConfig (*channelConfig); controlSize = ((ACMixerUnitDescriptorPtr)theInterfacePtr)->bLength - 10 - ((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins; debug2IOLog ("controlSize = %d\n", controlSize); mixerUnit->InitControlsArray (&((ACMixerUnitDescriptorPtr)theInterfacePtr)->baSourceID[((ACMixerUnitDescriptorPtr)theInterfacePtr)->bNrInPins + 3], controlSize); if (NULL == theMixerUnits) { theMixerUnits = OSArray::withObjects ((const OSObject **)&mixerUnit, 1); FailIf (NULL == theMixerUnits, Exit); } else { theMixerUnits->setObject (mixerUnit); } mixerUnit->release (); break; } case SELECTOR_UNIT: debugIOLog ("in SELECTOR_UNIT in ParseACInterfaceDescriptor\n"); selectorUnit = new USBSelectorUnitObject; FailIf (NULL == selectorUnit, Exit); selectorUnit->SetUnitID (((ACSelectorUnitDescriptorPtr)theInterfacePtr)->bUnitID); selectorUnit->InitSourceIDs (&((ACSelectorUnitDescriptorPtr)theInterfacePtr)->baSourceID[0], ((ACSelectorUnitDescriptorPtr)theInterfacePtr)->bNrInPins); debug2IOLog ("numInPins on selector = %d\n", ((ACSelectorUnitDescriptorPtr)theInterfacePtr)->bNrInPins); if (NULL == theSelectorUnits) { theSelectorUnits = OSArray::withObjects ((const OSObject **)&selectorUnit, 1); FailIf (NULL == theSelectorUnits, Exit); } else { theSelectorUnits->setObject (selectorUnit); } selectorUnit->release (); break; case PROCESSING_UNIT: debugIOLog ("in PROCESSING_UNIT in ParseACInterfaceDescriptor\n"); break; case EXTENSION_UNIT: debugIOLog ("in EXTENSION_UNIT in ParseACInterfaceDescriptor\n"); break; default: debugIOLog ("in default in ParseACInterfaceDescriptor\n"); } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } Exit: debug3IOLog ("-USBAudioControlObject::ParseACInterfaceDescriptor (%p, %d)\n", theInterfacePtr, currentInterface); return theInterfacePtr; } /* ------------------------------------------------------ USBAudioStreamObject ------------------------------------------------------ */ /* Public methods */ OSDefineMetaClassAndStructors (USBAudioStreamObject, OSObject); USBAudioStreamObject * USBAudioStreamObject::create (void) { USBAudioStreamObject * streamObject; streamObject = new USBAudioStreamObject; FailIf (NULL == streamObject, Exit); if (FALSE == streamObject->init ()) { streamObject->release (); streamObject = 0; } Exit: return streamObject; } void USBAudioStreamObject::free (void) { IOFree (sampleFreqs, numSampleFreqs * sizeof (UInt32)); if (NULL != theEndpointObjects) { theEndpointObjects->release (); theEndpointObjects = NULL; } OSObject::free (); } USBEndpointObject * USBAudioStreamObject::GetIndexedEndpointObject (UInt8 index) { USBEndpointObject * thisEndpoint; if (theEndpointObjects) { thisEndpoint = OSDynamicCast (USBEndpointObject, theEndpointObjects->getObject (index)); } else { thisEndpoint = NULL; } return thisEndpoint; } UInt8 USBAudioStreamObject::GetIsocAssociatedEndpointAddress (UInt8 address) { USBEndpointObject * thisEndpoint; UInt8 assocEndpointAddress; assocEndpointAddress = 0; thisEndpoint = GetEndpointByAddress (address); if (thisEndpoint) { assocEndpointAddress = thisEndpoint->GetSynchAddress (); } return assocEndpointAddress; } UInt8 USBAudioStreamObject::GetIsocAssociatedEndpointRefreshInt (UInt8 address) { USBEndpointObject * thisEndpoint; UInt8 assocEndpointRefresh; assocEndpointRefresh = 0; thisEndpoint = GetEndpointByAddress (address); if (thisEndpoint) { assocEndpointRefresh = thisEndpoint->GetRefreshInt (); } return assocEndpointRefresh; } UInt8 USBAudioStreamObject::GetIsocEndpointAddress (UInt8 direction) { USBEndpointObject * thisEndpointObject; UInt8 address; UInt8 indx; indx = 0; address = 0; debug2IOLog ("GetIsocEndpointAddress, looking for direction %d\n", direction); if (theEndpointObjects) { while (!address && indx < theEndpointObjects->getCount ()) { thisEndpointObject = GetIndexedEndpointObject (indx); debug2IOLog ("GetIsocEndpointAddress, this endpoint's direction %d\n", thisEndpointObject->GetDirection ()); if (thisEndpointObject && direction == thisEndpointObject->GetDirection ()) { address = thisEndpointObject->GetAddress (); debug2IOLog ("GetIsocEndpointAddress, found endpoint address %d\n", address); } indx++; } } return address; } UInt8 USBAudioStreamObject::GetIsocEndpointDirection (UInt8 index) { USBEndpointObject * thisEndpointObject; UInt8 direction; direction = 0xFF; thisEndpointObject = NULL; if (theEndpointObjects) { thisEndpointObject = GetIndexedEndpointObject (index); } if (NULL != thisEndpointObject) direction = thisEndpointObject->GetDirection (); return direction; } UInt8 USBAudioStreamObject::GetIsocEndpointSyncType (UInt8 address) { USBEndpointObject * thisEndpointObject; UInt8 syncType; syncType = 0; thisEndpointObject = GetEndpointByAddress (address); if (NULL != thisEndpointObject) syncType = thisEndpointObject->GetSyncType (); return syncType; } inline UInt32 ConvertSampleFreq(UInt8 *p) // convert little-endian 24-bit (unsigned) to native 32-bit. Make it a macro. { UInt32 bigEndianSampleFreq = (p[2] << 16) | (p[1] << 8) | p[0]; return (bigEndianSampleFreq); } USBInterfaceDescriptorPtr USBAudioStreamObject::ParseASInterfaceDescriptor (USBInterfaceDescriptorPtr theInterfacePtr, UInt8 const currentInterface) { UInt32 indx; UInt16 wFormatTag; Boolean done; USBEndpointObject * theEndpoint; debug3IOLog ("+USBAudioStreamObject::ParseASInterfaceDescriptor (%x, %d)\n", theInterfacePtr, currentInterface); FailIf (NULL == theInterfacePtr, Exit); FailIf (0 == theInterfacePtr->bLength, Exit); // FailIf (CS_INTERFACE != theInterfacePtr->bDescriptorType, Exit); done = FALSE; while (theInterfacePtr->bLength && !done) { if (CS_INTERFACE == theInterfacePtr->bDescriptorType) { switch (theInterfacePtr->bDescriptorSubtype) { case AS_GENERAL: debugIOLog ("in AS_GENERAL in ParseASInterfaceDescriptor\n"); terminalLink = ((ASInterfaceDescriptorPtr)theInterfacePtr)->bTerminalLink; delay = ((ASInterfaceDescriptorPtr)theInterfacePtr)->bDelay; formatTag = USBToHostWord ((((ASInterfaceDescriptorPtr)theInterfacePtr)->wFormatTag[1] << 8) | ((ASInterfaceDescriptorPtr)theInterfacePtr)->wFormatTag[0]); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); break; case FORMAT_TYPE: debugIOLog ("in FORMAT_TYPE in ParseASInterfaceDescriptor\n"); switch (((ASFormatTypeIDescriptorPtr)theInterfacePtr)->bFormatType) { case FORMAT_TYPE_I: case FORMAT_TYPE_III: debugIOLog ("in FORMAT_TYPE_I/FORMAT_TYPE_III in FORMAT_TYPE\n"); numChannels = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->bNrChannels; subframeSize = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->bSubframeSize; bitResolution = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->bBitResolution; numSampleFreqs = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->bSamFreqType; if (0 != numSampleFreqs) { debugIOLog ("device has a discrete number of sample rates\n"); sampleFreqs = (UInt32 *)IOMalloc (numSampleFreqs * sizeof (UInt32)); for (indx = 0; indx < numSampleFreqs; indx++) { sampleFreqs[indx] = ConvertSampleFreq( &((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3] ); /*((UInt8 *)sampleFreqs)[indx * 4] = 0; ((UInt8 *)sampleFreqs)[indx * 4 + 1] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 2]; ((UInt8 *)sampleFreqs)[indx * 4 + 2] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 1]; ((UInt8 *)sampleFreqs)[indx * 4 + 3] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3]; */ } } else { debugIOLog ("device has a variable number of sample rates\n"); sampleFreqs = (UInt32 *)IOMalloc (2 * sizeof (UInt32)); for (indx = 0; indx < 2; indx++) { sampleFreqs[indx] = ConvertSampleFreq( &((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3] ); /*((UInt8 *)sampleFreqs)[indx * 4] = 0; ((UInt8 *)sampleFreqs)[indx * 4 + 1] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 2]; ((UInt8 *)sampleFreqs)[indx * 4 + 2] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 1]; ((UInt8 *)sampleFreqs)[indx * 4 + 3] = ((ASFormatTypeIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3]; */ } } break; case FORMAT_TYPE_II: debugIOLog ("in FORMAT_TYPE_II in FORMAT_TYPE\n"); maxBitRate = USBToHostWord (((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->wMaxBitRate); samplesPerFrame = USBToHostWord (((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->wSamplesPerFrame); numSampleFreqs = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->bSamFreqType; if (0 != numSampleFreqs) { debugIOLog ("device has a discrete number of sample rates\n"); sampleFreqs = (UInt32 *)IOMalloc (numSampleFreqs * sizeof (UInt32)); for (indx = 0; indx < numSampleFreqs; indx++) { sampleFreqs[indx] = ConvertSampleFreq( &((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3] ); /*((UInt8 *)sampleFreqs)[indx * 4] = 0; ((UInt8 *)sampleFreqs)[indx * 4 + 1] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 2]; ((UInt8 *)sampleFreqs)[indx * 4 + 2] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 1]; ((UInt8 *)sampleFreqs)[indx * 4 + 3] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3]; */ } } else { debugIOLog ("device has a variable number of sample rates\n"); sampleFreqs = (UInt32 *)IOMalloc (2 * sizeof (UInt32)); for (indx = 0; indx < 2; indx++) { sampleFreqs[indx] = ConvertSampleFreq( &((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3] ); /*((UInt8 *)sampleFreqs)[indx * 4] = 0; ((UInt8 *)sampleFreqs)[indx * 4 + 1] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 2]; ((UInt8 *)sampleFreqs)[indx * 4 + 2] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3 + 1]; ((UInt8 *)sampleFreqs)[indx * 4 + 3] = ((ASFormatTypeIIDescriptorPtr)theInterfacePtr)->sampleFreq[indx * 3]; */ } } break; default: debugIOLog ("!!!!unknown format type in FORMAT_TYPE!!!!\n"); } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); break; case FORMAT_SPECIFIC: debugIOLog ("in FORMAT_SPECIFIC in ParseASInterfaceDescriptor\n"); wFormatTag = USBToHostWord (((ASFormatSpecificDescriptorHeaderPtr)theInterfacePtr)->wFormatTag[1] << 8 | ((ASFormatSpecificDescriptorHeaderPtr)theInterfacePtr)->wFormatTag[0]); switch (wFormatTag) { case MPEG: debugIOLog ("in FORMAT_SPECIFIC in MPEG\n"); bmMPEGCapabilities = USBToHostWord( ((ASMPEGFormatSpecificDescriptorPtr)theInterfacePtr)->bmMPEGCapabilities[1] << 8 | ((ASMPEGFormatSpecificDescriptorPtr)theInterfacePtr)->bmMPEGCapabilities[0]); bmMPEGFeatures = ((ASMPEGFormatSpecificDescriptorPtr)theInterfacePtr)->bmMPEGFeatures; break; case AC3: debugIOLog ("in FORMAT_SPECIFIC in AC3\n"); bmAC3BSID = USBToHostLong( ((ASAC3FormatSpecificDescriptorPtr)theInterfacePtr)->bmBSID[3] << 24 | ((ASAC3FormatSpecificDescriptorPtr)theInterfacePtr)->bmBSID[2] << 16 | ((ASAC3FormatSpecificDescriptorPtr)theInterfacePtr)->bmBSID[1] << 8 | ((ASAC3FormatSpecificDescriptorPtr)theInterfacePtr)->bmBSID[0]); bmAC3Features = ((ASAC3FormatSpecificDescriptorPtr)theInterfacePtr)->bmAC3Features; break; default: debug2IOLog ("!!!!unknown format type 0x%x in FORMAT_SPECIFIC!!!!\n", wFormatTag); break; } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); break; default: debugIOLog ("in default in ParseASInterfaceDescriptor\n"); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } } else { switch (theInterfacePtr->bDescriptorType) { case INTERFACE: // need to make a new interface object for this new interface or new alternate interface debugIOLog ("in INTERFACE in ParseASInterfaceDescriptor\n"); done = TRUE; break; case ENDPOINT: debugIOLog ("in ENDPOINT in ParseASInterfaceDescriptor\n"); theEndpoint = USBEndpointObject::create (); theEndpoint->SetAddress (((USBEndpointDescriptorPtr)theInterfacePtr)->bEndpointAddress); theEndpoint->SetAttributes (((USBEndpointDescriptorPtr)theInterfacePtr)->bmAttributes); theEndpoint->SetMaxPacketSize (USBToHostWord (((USBEndpointDescriptorPtr)theInterfacePtr)->wMaxPacketSize)); theEndpoint->SetRefreshInt (((USBEndpointDescriptorPtr)theInterfacePtr)->bRefresh); theEndpoint->SetSynchAddress (((USBEndpointDescriptorPtr)theInterfacePtr)->bSynchAddress); if (NULL == theEndpointObjects) { theEndpointObjects = OSArray::withObjects ((const OSObject **)&theEndpoint, 1); FailIf (NULL == theEndpointObjects, Exit); } else { theEndpointObjects->setObject (theEndpoint); } theEndpoint->release (); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); break; case CS_ENDPOINT: debugIOLog ("in CS_ENDPOINT in ParseASInterfaceDescriptor\n"); if (EP_GENERAL == ((ASEndpointDescriptorPtr)theInterfacePtr)->bDescriptorSubtype) { debugIOLog ("in EP_GENERAL in CS_ENDPOINT\n"); theIsocEndpointObject = new USBCSASIsocADEndpointObject (((ASEndpointDescriptorPtr)theInterfacePtr)->bmAttributes & (1 << sampleFreqControlBit), ((ASEndpointDescriptorPtr)theInterfacePtr)->bmAttributes & (1 << pitchControlBit), ((ASEndpointDescriptorPtr)theInterfacePtr)->bmAttributes & (1 << maxPacketsOnlyBit), ((ASEndpointDescriptorPtr)theInterfacePtr)->bLockDelayUnits, USBToHostWord (((UInt16 *)((ASEndpointDescriptorPtr)theInterfacePtr)->wLockDelay)[0])); } theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); break; default: debugIOLog ("in default in else in ParseASInterfaceDescriptor\n"); theInterfacePtr = (USBInterfaceDescriptorPtr)((UInt8 *)theInterfacePtr + theInterfacePtr->bLength); } } } Exit: debug3IOLog ("-USBAudioStreamObject::ParseASInterfaceDescriptor (%x, %d)\n", theInterfacePtr, currentInterface); return theInterfacePtr; } /* Private methods */ USBEndpointObject * USBAudioStreamObject::GetEndpointByAddress (UInt8 address) { USBEndpointObject * thisEndpoint; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisEndpoint = NULL; if (theEndpointObjects) { while (!found && indx < theEndpointObjects->getCount ()) { thisEndpoint = GetIndexedEndpointObject (indx); if (thisEndpoint && (thisEndpoint->GetAddress () == address)) { found = TRUE; } indx++; } } if (found != TRUE) thisEndpoint = NULL; return thisEndpoint; } USBEndpointObject * USBAudioStreamObject::GetEndpointObjectByAddress (UInt8 address) { USBEndpointObject * thisEndpointObject; UInt8 indx; Boolean found; indx = 0; found = FALSE; thisEndpointObject = NULL; if (theEndpointObjects) { while (!found && indx < theEndpointObjects->getCount ()) { thisEndpointObject = OSDynamicCast (USBEndpointObject, theEndpointObjects->getObject (indx)); if (thisEndpointObject && address == thisEndpointObject->GetAddress ()) { found = TRUE; } indx++; } } if (found != TRUE) thisEndpointObject = NULL; return thisEndpointObject; } //UInt8 GetEndpointAttributes (void) {if (theEndpointObject) return theEndpointObject->GetAttributes (); else return 0;} //UInt8 GetEndpointDirection (void) {if (theEndpointObject) return theEndpointObject->GetDirection (); else return 0;} /* ------------------------------------------------------ USBEndpointObject ------------------------------------------------------ */ OSDefineMetaClassAndStructors (USBEndpointObject, OSObject); USBEndpointObject * USBEndpointObject::create (void) { USBEndpointObject * endpointObject; endpointObject = new USBEndpointObject; FailIf (NULL == endpointObject, Exit); if (FALSE == endpointObject->init ()) { endpointObject->release (); endpointObject = 0; } Exit: return endpointObject; } void USBEndpointObject::free (void) { OSObject::free (); } /* ------------------------------------------------------ USBASIsocEndpointObject ------------------------------------------------------ */ USBCSASIsocADEndpointObject::USBCSASIsocADEndpointObject (Boolean theSampleFreqControl, Boolean thePitchControl, Boolean theMaxPacketsOnly, UInt8 theLockDelayUnits, UInt16 theLockDelay) : sampleFreqControl (theSampleFreqControl), pitchControl (thePitchControl), maxPacketsOnly (theMaxPacketsOnly), lockDelayUnits (theLockDelayUnits), lockDelay (theLockDelay) { } /* ------------------------------------------------------ USBInputTerminalObject ------------------------------------------------------ */ //OSDefineMetaClassAndStructors (USBInputTerminalObject, OSObject); void USBInputTerminalObject::free (void) { USBACDescriptorObject::free (); } /* ------------------------------------------------------ USBOutputTerminalObject ------------------------------------------------------ */ //OSDefineMetaClassAndStructors (USBOutputTerminalObject, OSObject); void USBOutputTerminalObject::free (void) { USBACDescriptorObject::free (); } /* ------------------------------------------------------ USBMixerUnitObject ------------------------------------------------------ */ void USBMixerUnitObject::free (void) { USBACDescriptorObject::free (); } void USBMixerUnitObject::InitControlsArray (UInt8 * bmCntrls, UInt8 bmControlSize) { UInt8 i; controlSize = bmControlSize; bmControls = ((UInt8 *)IOMalloc (bmControlSize)); FailIf (NULL == bmControls, Exit); memcpy (bmControls, bmCntrls, bmControlSize); for (i = 0; i < bmControlSize; i++) { debug3IOLog ("bmCntrls[%d] = 0x%X\n", i, bmCntrls[i]); debug3IOLog ("bmControls[%d] = 0x%X\n", i, bmControls[i]); } Exit: return; } void USBMixerUnitObject::InitSourceIDs (UInt8 * baSrcIDs, UInt8 nrInPins) { numInPins = nrInPins; baSourceIDs = (UInt8 *)IOMalloc (nrInPins); FailIf (NULL == baSourceIDs, Exit); memcpy (baSourceIDs, baSrcIDs, nrInPins); #if DEBUGLOG { UInt8 i; for (i = 0; i < nrInPins; i++) { debug3IOLog ("baSourceIDs[%d] = %d\n", i, baSourceIDs[i]); } } #endif Exit: return; } /* ------------------------------------------------------ USBSelectorUnitObject ------------------------------------------------------ */ void USBSelectorUnitObject::free (void) { USBACDescriptorObject::free (); } void USBSelectorUnitObject::InitSourceIDs (UInt8 * baSrcIDs, UInt8 nrInPins) { numInPins = nrInPins; baSourceIDs = (UInt8 *)IOMalloc (nrInPins); FailIf (NULL == baSourceIDs, Exit); memcpy (baSourceIDs, baSrcIDs, nrInPins); Exit: return; } /* ------------------------------------------------------ USBFeatureUnitObject ------------------------------------------------------ */ //OSDefineMetaClassAndStructors (USBFeatureUnitObject, OSObject); void USBFeatureUnitObject::free (void) { IOFree (bmaControls, numControls * controlSize); USBACDescriptorObject::free (); } Boolean USBFeatureUnitObject::MasterHasMuteControl (void) { return ChannelHasMuteControl (0); // Master channel is always bmaControls[0] } // Channel #1 is left channel, #2 is right channel Boolean USBFeatureUnitObject::ChannelHasMuteControl (UInt8 channelNum) { Boolean result; result = FALSE; if (numControls >= channelNum + 1) { if (1 == controlSize) { result = ((UInt8 *)bmaControls)[channelNum] & (1 << kMuteBit); } else { result = ((UInt16 *)bmaControls)[channelNum] & (1 << kMuteBit); } } return result; } Boolean USBFeatureUnitObject::ChannelHasVolumeControl (UInt8 channelNum) { Boolean result; result = FALSE; if (numControls >= channelNum + 1) { if (1 == controlSize) { result = ((UInt8 *)bmaControls)[channelNum] & (1 << kVolumeBit); } else { result = ((UInt16 *)bmaControls)[channelNum] & (1 << kVolumeBit); } } return result; } void USBFeatureUnitObject::InitControlsArray (UInt8 * bmaControlsArrary, UInt8 numCntrls) { UInt32 bmaControlIndex; numControls = numCntrls; bmaControls = (UInt8 *)IOMalloc (numControls * controlSize); FailIf (NULL == bmaControls, Exit); memcpy (bmaControls, bmaControlsArrary, numControls * controlSize); if (2 == controlSize) { for (bmaControlIndex = 0; bmaControlIndex < numControls; bmaControlIndex++) { ((UInt16 *)bmaControls)[bmaControlIndex] = USBToHostWord (((UInt16 *)bmaControls)[bmaControlIndex]); } } Exit: return; } /* ------------------------------------------------------ USBACDescriptorObject ------------------------------------------------------ */ OSDefineMetaClassAndStructors (USBACDescriptorObject, OSObject); void USBACDescriptorObject::free (void) { OSObject::free (); }