[plain text]
#include "AppleUSBAudioDevice.h"
#define super IOAudioDevice
#define LOCALIZABLE FALSE
OSDefineMetaClassAndStructors (AppleUSBAudioDevice, super)
void AppleUSBAudioDevice::free () {
debugIOLog ("+AppleUSBAudioDevice[%p]::free ()", this);
if (mInterfaceLock) {
IORecursiveLockFree (mInterfaceLock);
mInterfaceLock = NULL;
}
if (mUSBAudioConfig) {
mUSBAudioConfig->release ();
mUSBAudioConfig = NULL;
}
if (mRegisteredEngines) {
mRegisteredEngines->release ();
mRegisteredEngines = NULL;
}
super::free ();
debugIOLog ("-AppleUSBAudioDevice[%p]::free ()", this);
}
bool AppleUSBAudioDevice::ControlsStreamNumber (UInt8 streamNumber) {
UInt8 * streamNumbers;
UInt8 numStreams;
UInt8 index;
bool doesControl;
doesControl = FALSE;
if (mUSBAudioConfig) {
mUSBAudioConfig->GetControlledStreamNumbers (&streamNumbers, &numStreams);
for (index = 0; index < numStreams; index++) {
debugIOLog ("Checking stream %d against controled stream %d", streamNumber, streamNumbers[index]);
if (streamNumber == streamNumbers[index]) {
doesControl = TRUE;
break; }
}
}
return doesControl;
}
bool AppleUSBAudioDevice::start (IOService * provider) {
bool result;
debugIOLog ("+ AppleUSBAudioDevice[%p]::start (%p)", this, provider);
result = FALSE;
mControlInterface = OSDynamicCast (IOUSBInterface, provider);
FailIf (FALSE == mControlInterface->open (this), Exit);
mInitHardwareThread = thread_call_allocate ((thread_call_func_t)AppleUSBAudioDevice::initHardwareThread, (thread_call_param_t)this);
FailIf (NULL == mInitHardwareThread, Exit);
debugIOLog ("- AppleUSBAudioDevice[%p]::start (%p)", this, provider);
result = super::start (provider);
Exit:
return result;
}
bool AppleUSBAudioDevice::initHardware (IOService * provider) {
bool result;
result = FALSE;
FailIf (NULL == mInitHardwareThread, Exit);
thread_call_enter1 (mInitHardwareThread, (void *)provider);
result = TRUE;
Exit:
return result;
}
void AppleUSBAudioDevice::initHardwareThread (AppleUSBAudioDevice * aua, void * provider) {
IOCommandGate * cg;
IOReturn result;
FailIf (NULL == aua, Exit);
cg = aua->getCommandGate ();
if (cg) {
result = cg->runAction (aua->initHardwareThreadAction, provider);
}
Exit:
return;
}
IOReturn AppleUSBAudioDevice::initHardwareThreadAction (OSObject * owner, void * provider, void * arg2, void * arg3, void * arg4) {
AppleUSBAudioDevice * aua;
IOReturn result;
result = kIOReturnError;
aua = (AppleUSBAudioDevice *)owner;
FailIf (NULL == aua, Exit);
result = aua->protectedInitHardware ((IOService *)provider);
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::protectedInitHardware (IOService * provider) {
char string[kStringBufferSize];
UInt8 stringIndex;
IOReturn err;
Boolean resultCode;
UInt8 * streamNumbers;
UInt8 numStreams;
debugIOLog ("+AppleUSBAudioDevice[%p]::start (%p)", this, provider);
resultCode = FALSE;
FailIf (NULL == mControlInterface, Exit);
debugIOLog ("There are %d configurations on this device", mControlInterface->GetDevice()->GetNumConfigurations ());
debugIOLog ("Our control interface number is %d", mControlInterface->GetInterfaceNumber ());
mUSBAudioConfig = USBAudioConfigObject::create (mControlInterface->GetDevice()->GetFullConfigurationDescriptor (0), mControlInterface->GetInterfaceNumber ());
FailIf (NULL == mUSBAudioConfig, Exit);
mControlGraph = BuildConnectionGraph (mControlInterface->GetInterfaceNumber ());
FailIf (NULL == mControlGraph, Exit);
mUSBAudioConfig->GetControlledStreamNumbers (&streamNumbers, &numStreams);
debugIOLog ("Num streams controlled = %d", numStreams);
debugIOLog ("GetNumStreamInterfaces = %d", mUSBAudioConfig->GetNumStreamInterfaces ());
FailIf (0 == numStreams, Exit);
FailIf (mUSBAudioConfig->GetNumOutputTerminals (0, 0) == 1 && mUSBAudioConfig->GetIndexedOutputTerminalType (0, 0, 0) == OUTPUT_LOW_FREQUENCY_EFFECTS_SPEAKER, Exit);
err = kIOReturnError;
string[0] = 0;
stringIndex = mControlInterface->GetInterfaceStringIndex ();
if (0 != stringIndex) {
err = mControlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
} else {
stringIndex = mControlInterface->GetDevice()->GetProductStringIndex ();
if (0 != stringIndex) {
err = mControlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
}
}
if (0 == string[0] || kIOReturnSuccess != err) {
strcpy (string, "Unknown USB Audio Device");
}
setDeviceName (string);
err = kIOReturnError;
string[0] = 0;
stringIndex = mControlInterface->GetDevice()->GetManufacturerStringIndex ();
if (0 != stringIndex) {
err = mControlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
}
if (0 == string[0] || kIOReturnSuccess != err) {
strcpy (string, "Unknown Manufacturer");
}
setManufacturerName (string);
setDeviceTransportType (kIOAudioDeviceTransportTypeUSB);
#if LOCALIZABLE
setProperty (kIOAudioDeviceLocalizedBundleKey, "AppleUSBAudio.kext");
#endif
mInterfaceLock = IORecursiveLockAlloc ();
FailIf (NULL == mInterfaceLock, Exit);
resultCode = super::initHardware (provider);
Exit:
debugIOLog ("-AppleUSBAudioDevice[%p]::start (%p)", this, provider);
return TRUE;
}
IOReturn AppleUSBAudioDevice::performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microSecsUntilComplete) {
IOReturn result;
debugIOLog ("+AppleUSBAudioDevice[%p]::performPowerStateChange (%d, %d, %p)", this, oldPowerState, newPowerState, microSecsUntilComplete);
result = super::performPowerStateChange (oldPowerState, newPowerState, microSecsUntilComplete);
if (oldPowerState == kIOAudioDeviceSleep) {
debugIOLog ("Waking from sleep - flushing controls to the device.");
flushAudioControls ();
}
return result;
}
void AppleUSBAudioDevice::stop (IOService *provider) {
debugIOLog ("+AppleUSBAudioDevice[%p]::stop (%p) - audioEngines = %p - rc=%d", this, provider, audioEngines, getRetainCount());
super::stop (provider);
if (mControlInterface) {
mControlInterface->close (this);
mControlInterface = NULL;
}
debugIOLog("-AppleUSBAudioDevice[%p]::stop ()", this);
}
Boolean AppleUSBAudioDevice::ShouldUpdatePRAM (void) {
const IORegistryPlane * usbPlane;
IORegistryEntry * usbRegEntry;
OSObject * obj;
OSNumber * number;
UInt16 productID;
UInt16 vendorID;
Boolean speakersGood;
Boolean connectionGood;
Boolean result;
result = FALSE;
speakersGood = FALSE;
connectionGood = FALSE;
FailIf (NULL == mControlInterface, Exit);
vendorID = mControlInterface->GetDevice()->GetVendorID ();
debugIOLog ("+ ShouldUpdatePRAM\nspeaker's vendorID = 0x%x", vendorID);
if (kIOUSBVendorIDAppleComputer == vendorID || kIOUSBVendorIDHaronKardon == vendorID || kIOUSBVendorMicronas == vendorID) {
speakersGood = TRUE;
}
debugIOLog ("speakersGood = %d", speakersGood);
if (TRUE == speakersGood) {
usbPlane = getPlane (kIOUSBPlane);
FailIf (NULL == usbPlane, Exit);
usbRegEntry = mControlInterface->GetDevice()->getParentEntry (usbPlane);
FailIf (NULL == usbRegEntry, Exit);
obj = usbRegEntry->getProperty (kUSBVendorID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
vendorID = number->unsigned32BitValue ();
debugIOLog ("hub's vendorID = 0x%x", vendorID);
if (kIOUSBVendorIDAppleComputer == vendorID) {
obj = usbRegEntry->getProperty (kUSBDevicePropertyLocationID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
if (OSDynamicCast (IOUSBRootHubDevice, usbRegEntry)) {
connectionGood = TRUE;
debugIOLog ("Directly connected to the root hub");
} else {
obj = usbRegEntry->getProperty (kUSBProductID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
productID = number->unsigned32BitValue ();
debugIOLog ("hub's productID = 0x%x", productID);
if (kStudioDisplay15CRT == productID || kStudioDisplay17CRT == productID || kCinemaDisplay == productID || kStudioDisplay17FP == productID) {
connectionGood = TRUE;
debugIOLog ("Connected to a capable monitor");
}
}
}
}
debugIOLog ("connectionGood = %d", connectionGood);
if (TRUE == connectionGood && FALSE == FindSoundNode ()) {
result = TRUE;
}
Exit:
debugIOLog ("- ShouldUpdatePRAM result = %d", result);
return result;
}
Boolean AppleUSBAudioDevice::FindSoundNode (void) {
const IORegistryPlane * dtPlane;
IORegistryEntry * regEntry;
IORegistryIterator * iterator;
Boolean found;
Boolean done;
const char * name;
found = FALSE;
dtPlane = IORegistryEntry::getPlane (kIODeviceTreePlane);
FailIf (NULL == dtPlane, Exit);
iterator = IORegistryIterator::iterateOver (dtPlane, kIORegistryIterateRecursively);
FailIf (NULL == iterator, Exit);
done = FALSE;
regEntry = iterator->getNextObject ();
while (NULL != regEntry && FALSE == done) {
name = regEntry->getName ();
if (0 == strcmp (name, "mac-io")) {
iterator->release (); iterator = IORegistryIterator::iterateOver (regEntry, dtPlane);
done = TRUE;
}
regEntry = iterator->getNextObject ();
}
regEntry = iterator->getNextObject ();
while (NULL != regEntry && FALSE == found) {
name = regEntry->getName ();
if (0 == strcmp (name, "sound")) {
found = TRUE;
}
regEntry = iterator->getNextObject ();
}
iterator->release ();
Exit:
return found;
}
IOReturn AppleUSBAudioDevice::message (UInt32 type, IOService * provider, void * arg) {
debugIOLog ("+AppleUSBAudioDevice[%p]::message (0x%x, %p) - rc=%d", this, type, provider, getRetainCount ());
switch (type) {
case kIOMessageServiceIsTerminated:
case kIOMessageServiceIsRequestingClose:
if (mControlInterface != NULL && mControlInterface == provider) {
mControlInterface->close (this);
mControlInterface = NULL;
}
default:
;
}
debugIOLog ("-AppleUSBAudioDevice[%p]::message (0x%x, %p) - rc=%d", this, type, provider, getRetainCount ());
return kIOReturnSuccess;
}
SInt32 AppleUSBAudioDevice::getEngineInfoIndex (AppleUSBAudioEngine * inAudioEngine) {
OSDictionary * engineInfo;
AppleUSBAudioEngine * usbAudioEngine;
SInt32 theEngineIndex;
theEngineIndex = -1;
if (mRegisteredEngines) {
for (; theEngineIndex < (SInt32)mRegisteredEngines->getCount (); theEngineIndex++) {
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (theEngineIndex));
if (engineInfo) {
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, engineInfo->getObject (kEngine));
if (inAudioEngine == usbAudioEngine) {
break; }
}
}
}
return theEngineIndex;
}
IOReturn AppleUSBAudioDevice::doControlStuff (IOAudioEngine *audioEngine, UInt8 interfaceNum, UInt8 altSettingNum) {
AppleUSBAudioEngine * usbAudioEngine;
IOAudioSelectorControl * inputSelector;
OSArray * arrayOfPathsFromOutputTerminal;
OSArray * aPath;
OSArray * playThroughPaths;
OSNumber * theUnitIDNum;
OSNumber * number;
OSDictionary * engineInfo;
IOReturn result;
UInt32 numUnitsInPath, unitIndexInPath ;
UInt32 outputTerminalIndex;
UInt32 numOutputTerminalArrays;
UInt32 numPathsFromOutputTerminal;
UInt32 numOutputTerminals;
UInt32 pathsToOutputTerminalN;
UInt32 selection;
SInt32 engineIndex;
UInt8 selectorUnitID;
UInt8 featureUnitID;
UInt8 controlInterfaceNum;
UInt8 unitID;
UInt8 outputTerminalID;
Boolean done;
result = kIOReturnError;
inputSelector = NULL;
done = FALSE;
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, audioEngine);
FailIf (NULL == usbAudioEngine, Exit);
FailIf (NULL == mControlInterface, Exit);
debugIOLog ("this usbAudioEngine = %p", usbAudioEngine);
if (NULL == mRegisteredEngines) {
mRegisteredEngines = OSArray::withCapacity (1);
FailIf (NULL == mRegisteredEngines, Exit);
}
engineInfo = OSDictionary::withCapacity (1);
FailIf (NULL == engineInfo, Exit);
engineInfo->setObject (kEngine, usbAudioEngine);
number = OSNumber::withNumber (interfaceNum, 8);
engineInfo->setObject (kInterface, number);
number->release ();
number = OSNumber::withNumber (altSettingNum, 8);
engineInfo->setObject (kAltSetting, number);
number->release ();
mRegisteredEngines->setObject (engineInfo);
engineInfo->release ();
featureUnitID = 0;
selectorUnitID = 0;
outputTerminalID = 0;
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
numOutputTerminals = mUSBAudioConfig->GetNumOutputTerminals (controlInterfaceNum, 0);
if (usbAudioEngine->getDirection () == kIOAudioStreamDirectionOutput) {
for (outputTerminalIndex = 0; outputTerminalIndex < numOutputTerminals && FALSE == done; outputTerminalIndex++) {
if (mUSBAudioConfig->GetIndexedOutputTerminalType (controlInterfaceNum, 0, outputTerminalIndex) != 0x101) {
outputTerminalID = mUSBAudioConfig->GetIndexedOutputTerminalID (controlInterfaceNum, 0, outputTerminalIndex);
numOutputTerminalArrays = mControlGraph->getCount ();
for (pathsToOutputTerminalN = 0; pathsToOutputTerminalN < numOutputTerminalArrays; pathsToOutputTerminalN++) {
arrayOfPathsFromOutputTerminal = OSDynamicCast (OSArray, mControlGraph->getObject (pathsToOutputTerminalN));
FailIf (NULL == arrayOfPathsFromOutputTerminal, Exit);
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (0));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (0));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
if (unitID == outputTerminalID) {
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageOutput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageOutput);
featureUnitID = 0;
}
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageOutput, interfaceNum, altSettingNum, kMuteControl);
if (featureUnitID) {
addMuteControl (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageOutput);
featureUnitID = 0;
done = TRUE;
}
}
}
}
}
} else { for (outputTerminalIndex = 0; outputTerminalIndex < numOutputTerminals; outputTerminalIndex++) {
if (mUSBAudioConfig->GetIndexedOutputTerminalType (controlInterfaceNum, 0, outputTerminalIndex) == 0x101) {
outputTerminalID = mUSBAudioConfig->GetIndexedOutputTerminalID (controlInterfaceNum, 0, outputTerminalIndex);
break; }
}
numOutputTerminalArrays = mControlGraph->getCount ();
for (pathsToOutputTerminalN = 0; pathsToOutputTerminalN < numOutputTerminalArrays; pathsToOutputTerminalN++) {
arrayOfPathsFromOutputTerminal = OSDynamicCast (OSArray, mControlGraph->getObject (pathsToOutputTerminalN));
FailIf (NULL == arrayOfPathsFromOutputTerminal, Exit);
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (0));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (0));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
if (unitID == outputTerminalID) {
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getLastObject ());
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
playThroughPaths = getPlaythroughPaths ();
if (playThroughPaths) {
doPlaythroughSetup (usbAudioEngine, playThroughPaths, interfaceNum, altSettingNum);
playThroughPaths->release ();
}
numPathsFromOutputTerminal = arrayOfPathsFromOutputTerminal->getCount ();
if (numPathsFromOutputTerminal > 1 && mUSBAudioConfig->GetNumSelectorUnits (controlInterfaceNum, 0)) {
numUnitsInPath = aPath->getCount ();
for (unitIndexInPath = 1; unitIndexInPath < numUnitsInPath; unitIndexInPath++) {
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (unitIndexInPath));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
if (SELECTOR_UNIT == mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID)) {
if (kIOReturnSuccess == setSelectorSetting (unitID, 1)) {
selectorUnitID = unitID;
engineIndex = getEngineInfoIndex (usbAudioEngine);
if (-1 != engineIndex) {
selection = (0xFF000000 & (pathsToOutputTerminalN << 24)) | (0x00FF0000 & (0 << 16)) | (0x0000FF00 & (selectorUnitID << 8)) | 1;
inputSelector = IOAudioSelectorControl::createInputSelector (selection, kIOAudioControlChannelIDAll, 0, engineIndex);
FailIf (NULL == inputSelector, Exit);
inputSelector->setValueChangeHandler (controlChangedHandler, this);
usbAudioEngine->addDefaultAudioControl (inputSelector);
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageInput);
featureUnitID = 0;
}
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kMuteControl);
if (featureUnitID) {
addMuteControl (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageInput);
featureUnitID = 0;
}
}
}
break; }
}
if (NULL != inputSelector) {
addSelectorSourcesToSelectorControl (inputSelector, arrayOfPathsFromOutputTerminal, pathsToOutputTerminalN, unitIndexInPath);
inputSelector->release ();
} else {
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageInput);
featureUnitID = 0;
}
}
} else {
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsageInput);
featureUnitID = 0;
}
}
break; }
}
}
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::doPlaythroughSetup (AppleUSBAudioEngine * usbAudioEngine, OSArray * playThroughPaths, UInt8 interfaceNum, UInt8 altSettingNum) {
OSArray * aPath;
OSNumber * theUnitIDNum;
OSString * nameString;
IOAudioSelectorControl * playThroughSelector;
OSDictionary * engineInfo;
UInt32 numPlayThroughPaths;
UInt32 pathIndex;
SInt32 engineInfoIndex;
UInt8 channelNum;
UInt8 featureUnitID;
UInt8 inputTerminalID;
UInt8 controlInterfaceNum;
IOReturn result;
result = kIOReturnError;
FailIf (NULL == mControlInterface, Exit);
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
engineInfoIndex = getEngineInfoIndex (usbAudioEngine);
FailIf (-1 == engineInfoIndex, Exit);
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (engineInfoIndex));
FailIf (NULL == engineInfo, Exit);
engineInfo->setObject (kPassThruPathsArray, playThroughPaths);
numPlayThroughPaths = playThroughPaths->getCount ();
if (numPlayThroughPaths > 1) {
playThroughSelector = IOAudioSelectorControl::create (0, kIOAudioControlChannelIDAll, 0, engineInfoIndex, kIOAudioSelectorControlSubTypeInput, kIOAudioControlUsagePassThru);
FailIf (NULL == playThroughSelector, Exit);
playThroughSelector->setValueChangeHandler (controlChangedHandler, this);
usbAudioEngine->addDefaultAudioControl (playThroughSelector);
for (pathIndex = 0; pathIndex < numPlayThroughPaths; pathIndex++) {
aPath = OSDynamicCast (OSArray, playThroughPaths->getObject (pathIndex));
FailIf (NULL == aPath, Exit);
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getLastObject ());
FailIf (NULL == theUnitIDNum, Exit);
inputTerminalID = theUnitIDNum->unsigned8BitValue ();
nameString = OSString::withCString (TerminalTypeString (mUSBAudioConfig->GetInputTerminalType (controlInterfaceNum, 0, inputTerminalID)));
FailIf (NULL == nameString, Exit);
playThroughSelector->addAvailableSelection (pathIndex, nameString);
nameString->release ();
for (channelNum = 0; channelNum < mUSBAudioConfig->GetNumControls (controlInterfaceNum, 0, featureUnitID); channelNum++) {
setCurVolume (featureUnitID, channelNum, 0);
setCurMute (featureUnitID, channelNum, 0);
}
}
}
aPath = OSDynamicCast (OSArray, playThroughPaths->getObject (0));
FailIf (NULL == aPath, Exit);
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsagePassThru);
}
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsageInput, interfaceNum, altSettingNum, kMuteControl);
if (featureUnitID) {
addMuteControl (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsagePassThru);
}
result = kIOReturnSuccess;
} else {
aPath = OSDynamicCast (OSArray, playThroughPaths->getObject (0));
FailIf (NULL == aPath, Exit);
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsagePassThru, interfaceNum, altSettingNum, kVolumeControl);
if (featureUnitID) {
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsagePassThru);
}
featureUnitID = getBestFeatureUnitInPath (aPath, kIOAudioControlUsagePassThru, interfaceNum, altSettingNum, kMuteControl);
if (featureUnitID) {
addMuteControl (usbAudioEngine, featureUnitID, interfaceNum, altSettingNum, kIOAudioControlUsagePassThru);
}
result = kIOReturnSuccess;
}
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::addSelectorSourcesToSelectorControl (IOAudioSelectorControl * theSelectorControl, OSArray * arrayOfPathsFromOutputTerminal, UInt32 pathsToOutputTerminalN, UInt8 selectorIndex) {
OSArray * aPath;
OSNumber * theUnitIDNum;
OSString * nameString;
UInt32 selectorSourceIndex;
UInt32 pathIndex;
UInt32 selection;
UInt8 numSelectorSources;
UInt8 selectorID;
UInt8 controlInterfaceNum;
FailIf (NULL == mControlInterface, Exit);
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (0));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (selectorIndex));
FailIf (NULL == theUnitIDNum, Exit);
selectorID = theUnitIDNum->unsigned8BitValue ();
pathIndex = 0;
numSelectorSources = mUSBAudioConfig->GetNumSources (controlInterfaceNum, 0, selectorID);
for (selectorSourceIndex = 0; selectorSourceIndex < numSelectorSources; selectorSourceIndex++) {
nameString = getNameForPath (arrayOfPathsFromOutputTerminal, &pathIndex, selectorIndex + 1);
if (NULL != nameString) {
selection = (0xFF000000 & (pathsToOutputTerminalN << 24)) | (0x00FF0000 & ((pathIndex - 1) << 16)) | (0x0000FF00 & (selectorID << 8)) | (0x000000FF & (selectorSourceIndex + 1));
theSelectorControl->addAvailableSelection (selection, nameString);
nameString->release ();
}
}
Exit:
return kIOReturnSuccess;
}
OSString * AppleUSBAudioDevice::getNameForPath (OSArray * arrayOfPathsFromOutputTerminal, UInt32 * pathIndex, UInt8 startingPoint) {
OSString * theString;
OSString * tempString;
OSArray * aPath;
OSNumber * theUnitIDNum;
UInt32 numElementsInPath;
UInt32 elementIndex;
UInt8 unitID;
UInt8 subType;
UInt8 controlInterfaceNum;
Boolean done;
done = FALSE;
theString = NULL;
FailIf (NULL == mControlInterface, Exit);
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (*pathIndex));
FailIf (NULL == aPath, Exit);
numElementsInPath = aPath->getCount ();
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
for (elementIndex = startingPoint; elementIndex < numElementsInPath && FALSE == done; elementIndex++) {
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (elementIndex));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID);
switch (subType) {
case INPUT_TERMINAL:
tempString = OSString::withCString (TerminalTypeString (mUSBAudioConfig->GetInputTerminalType (controlInterfaceNum, 0, unitID)));
FailIf (NULL == tempString, Exit);
if (!tempString->isEqualTo ("USB streaming")) {
theString = OSString::withString (tempString);
}
tempString->release ();
(*pathIndex)++;
break;
case MIXER_UNIT:
theString = getNameForMixerPath (arrayOfPathsFromOutputTerminal, pathIndex, elementIndex);
done = TRUE;
break;
}
}
Exit:
return theString;
}
OSString * AppleUSBAudioDevice::getNameForMixerPath (OSArray * arrayOfPathsFromOutputTerminal, UInt32 * pathIndex, UInt8 startingPoint) {
char string[255];
OSString * theString;
OSString * tempString;
OSArray * aPath;
OSNumber * theUnitIDNum;
UInt32 numElementsInPath;
UInt32 mixerSourceIndex;
UInt32 elementIndex;
UInt8 numMixerSources;
UInt8 unitID;
UInt8 subType;
UInt8 controlInterfaceNum;
string[0] = 0;
FailIf (NULL == mControlInterface, Exit);
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (*pathIndex));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (startingPoint));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
numElementsInPath = aPath->getCount ();
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
numMixerSources = mUSBAudioConfig->GetNumSources (controlInterfaceNum, 0, unitID);
for (mixerSourceIndex = *pathIndex; mixerSourceIndex < *pathIndex + numMixerSources; ) {
for (elementIndex = startingPoint + 1; elementIndex < numElementsInPath; elementIndex++) {
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (elementIndex));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID);
switch (subType) {
case INPUT_TERMINAL:
tempString = getNameForPath (arrayOfPathsFromOutputTerminal, &mixerSourceIndex, elementIndex);
if (NULL != tempString) {
strcat (string, tempString->getCStringNoCopy ());
strcat (string, " & ");
tempString->release ();
}
break;
case MIXER_UNIT:
tempString = getNameForMixerPath (arrayOfPathsFromOutputTerminal, &mixerSourceIndex, elementIndex);
if (NULL != tempString) {
strcat (string, tempString->getCStringNoCopy ());
tempString->release ();
}
break;
}
}
}
*pathIndex = mixerSourceIndex;
if (strlen (string) > 3) {
string[strlen (string) - 3] = 0;
}
Exit:
theString = OSString::withCString (string);
return theString;
}
void AppleUSBAudioDevice::addVolumeControls (AppleUSBAudioEngine * usbAudioEngine, UInt8 featureUnitID, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 usage) {
OSArray * inputGainControlsArray;
OSArray * passThruVolControlsArray;
OSArray * outputVolControlsArray;
OSDictionary * engineInfo;
IOAudioLevelControl * theLevelControl;
IOFixed deviceMinDB;
IOFixed deviceMaxDB;
SInt32 engineInfoIndex;
SInt16 deviceCur;
SInt16 deviceMin;
SInt16 deviceMax;
SInt16 volRes;
SInt16 offset;
UInt8 channelNum;
UInt8 controlInterfaceNum;
engineInfoIndex = getEngineInfoIndex (usbAudioEngine);
FailIf (-1 == engineInfoIndex, Exit);
FailIf (NULL == mControlInterface, Exit);
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (engineInfoIndex));
FailIf (NULL == engineInfo, Exit);
inputGainControlsArray = NULL;
passThruVolControlsArray = NULL;
outputVolControlsArray = NULL;
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
for (channelNum = 0; channelNum <= mUSBAudioConfig->GetNumControls (controlInterfaceNum, 0, featureUnitID); channelNum++) {
debugIOLog ("checking channel %d for vol controls", channelNum);
if (mUSBAudioConfig->ChannelHasVolumeControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
debugIOLog ("creating vol controls for channel %d", channelNum);
deviceCur = getCurVolume (featureUnitID, channelNum);
deviceMin = getMinVolume (featureUnitID, channelNum);
debugIOLog ("deviceMin = %x", deviceMin);
deviceMax = getMaxVolume (featureUnitID, channelNum);
debugIOLog ("deviceMax = %x", deviceMax);
volRes = getVolumeResolution (featureUnitID, channelNum);
debugIOLog ("volRes = %x", volRes);
if ((SInt16)0x8000 == deviceMin) {
deviceMin = (SInt16)0x8001;
}
deviceMinDB = ConvertUSBVolumeTodB (deviceMin);
deviceMaxDB = ConvertUSBVolumeTodB (deviceMax);
offset = -deviceMin;
deviceCur = (deviceCur + offset) / volRes;
if (deviceMin < 0 && deviceMax > 0) {
deviceMax += volRes;
}
deviceMax = ((deviceMin + offset) + (deviceMax + offset)) / volRes;
deviceMin = -1;
theLevelControl = IOAudioLevelControl::createVolumeControl (deviceCur, deviceMin, deviceMax, deviceMinDB, deviceMaxDB, channelNum, 0, featureUnitID, usage);
FailIf (NULL == theLevelControl, Exit);
theLevelControl->setValueChangeHandler (controlChangedHandler, this);
usbAudioEngine->addDefaultAudioControl (theLevelControl);
switch (usage) {
case kIOAudioControlUsageInput:
if (NULL == inputGainControlsArray) {
inputGainControlsArray = OSArray::withObjects ((const OSObject **)&theLevelControl, 1);
} else {
inputGainControlsArray->setObject (theLevelControl);
}
break;
case kIOAudioControlUsagePassThru:
if (NULL == passThruVolControlsArray) {
passThruVolControlsArray = OSArray::withObjects ((const OSObject **)&theLevelControl, 1);
} else {
passThruVolControlsArray->setObject (theLevelControl);
}
break;
case kIOAudioControlUsageOutput:
if (NULL == outputVolControlsArray) {
outputVolControlsArray = OSArray::withObjects ((const OSObject **)&theLevelControl, 1);
} else {
outputVolControlsArray->setObject (theLevelControl);
}
break;
}
theLevelControl->release ();
}
}
if (NULL != inputGainControlsArray) {
engineInfo->setObject (kInputGainControls, inputGainControlsArray);
inputGainControlsArray->release ();
}
if (NULL != passThruVolControlsArray) {
engineInfo->setObject (kPassThruVolControls, passThruVolControlsArray);
passThruVolControlsArray->release ();
}
if (NULL != outputVolControlsArray) {
engineInfo->setObject (kOutputVolControls, outputVolControlsArray);
outputVolControlsArray->release ();
}
Exit:
return;
}
void AppleUSBAudioDevice::addMuteControl (AppleUSBAudioEngine * usbAudioEngine, UInt8 featureUnitID, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 usage) {
OSArray * inputMuteControlsArray;
OSDictionary * engineInfo;
IOAudioToggleControl * theMuteControl;
SInt32 engineInfoIndex;
SInt16 deviceCur;
UInt8 channelNum;
UInt8 controlInterfaceNum;
engineInfoIndex = getEngineInfoIndex (usbAudioEngine);
FailIf (-1 == engineInfoIndex, Exit);
FailIf (NULL == mControlInterface, Exit);
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (engineInfoIndex));
FailIf (NULL == engineInfo, Exit);
inputMuteControlsArray = NULL;
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
for (channelNum = 0; channelNum <= mUSBAudioConfig->GetNumControls (controlInterfaceNum, 0, featureUnitID); channelNum++) {
if (mUSBAudioConfig->ChannelHasMuteControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
deviceCur = getCurMute (featureUnitID, channelNum);
theMuteControl = IOAudioToggleControl::createMuteControl (deviceCur, channelNum, 0, featureUnitID, usage);
setCurMute (featureUnitID, channelNum, deviceCur);
FailIf (NULL == theMuteControl, Exit);
theMuteControl->setValueChangeHandler (controlChangedHandler, this);
usbAudioEngine->addDefaultAudioControl (theMuteControl);
switch (usage) {
case kIOAudioControlUsageInput:
if (NULL == inputMuteControlsArray) {
inputMuteControlsArray = OSArray::withObjects ((const OSObject **)&theMuteControl, 1);
} else {
inputMuteControlsArray->setObject (theMuteControl);
}
break;
case kIOAudioControlUsagePassThru:
break;
case kIOAudioControlUsageOutput:
break;
}
theMuteControl->release ();
}
}
if (NULL != inputMuteControlsArray) {
engineInfo->setObject (kInputMuteControls, inputMuteControlsArray);
inputMuteControlsArray->release ();
}
Exit:
return;
}
IOFixed AppleUSBAudioDevice::ConvertUSBVolumeTodB (SInt16 volume) {
IOFixed dBVolumeFixed;
if (volume == (SInt16)0x8000) {
dBVolumeFixed = ((SInt16)0x8000 * 256) << 8; } else {
dBVolumeFixed = volume * 256;
}
debugIOLog ("volume = %d, dBVolumeFixed = 0x%X", volume, dBVolumeFixed);
return dBVolumeFixed;
}
SInt16 AppleUSBAudioDevice::getFeatureUnitSetting (UInt8 controlSelector, UInt8 unitID, UInt8 channelNumber, UInt8 requestType) {
IOUSBDevRequestDesc devReq;
IOReturn result;
UInt16 theSetting;
IOBufferMemoryDescriptor * theSettingDesc = NULL;
UInt8 length;
theSetting = 0;
FailIf (NULL == mControlInterface, Exit);
switch (controlSelector) {
case MUTE_CONTROL:
length = 1;
break;
case VOLUME_CONTROL:
length = 2;
break;
default:
length = 0;
}
theSettingDesc = IOBufferMemoryDescriptor::withOptions (kIODirectionIn, length);
FailIf (NULL == theSettingDesc, Exit);
devReq.bmRequestType = USBmakebmRequestType (kUSBIn, kUSBClass, kUSBInterface);
devReq.bRequest = requestType;
devReq.wValue = (controlSelector << 8) | channelNumber;
devReq.wIndex = (0xFF00 & (unitID << 8)) | (0x00FF & mControlInterface->GetInterfaceNumber ());
devReq.wLength = length;
devReq.pData = theSettingDesc;
result = deviceRequest (&devReq);
FailIf (kIOReturnSuccess != result, Exit);
memcpy (&theSetting, theSettingDesc->getBytesNoCopy (), length);
Exit:
if (NULL != theSettingDesc) {
theSettingDesc->release ();
}
return USBToHostWord (theSetting);
}
IOReturn AppleUSBAudioDevice::setFeatureUnitSetting (UInt8 controlSelector, UInt8 unitID, UInt8 channelNumber, UInt8 requestType, UInt16 newValue, UInt16 newValueLen) {
IOUSBDevRequestDesc devReq;
IOBufferMemoryDescriptor * theSettingDesc = NULL;
IOReturn result;
result = kIOReturnError;
FailIf (NULL == mControlInterface, Exit);
theSettingDesc = OSTypeAlloc (IOBufferMemoryDescriptor);
FailIf (NULL == theSettingDesc, Exit);
theSettingDesc->initWithBytes (&newValue, newValueLen, kIODirectionIn);
devReq.bmRequestType = USBmakebmRequestType (kUSBOut, kUSBClass, kUSBInterface);
devReq.bRequest = requestType;
devReq.wValue = (controlSelector << 8) | channelNumber;
devReq.wIndex = (0xFF00 & (unitID << 8)) | (0x00FF & mControlInterface->GetInterfaceNumber ());
devReq.wLength = newValueLen;
devReq.pData = theSettingDesc;
FailIf ((TRUE == isInactive()), DeviceInactive); result = deviceRequest (&devReq);
Exit:
if (NULL != theSettingDesc) {
theSettingDesc->release ();
}
return result;
DeviceInactive:
debugIOLog("AppleUSBAudioLevelControl::SetCurVolume ERROR attempt to send a device request to and inactive device");
goto Exit;
}
SInt16 AppleUSBAudioDevice::getCurMute (UInt8 unitID, UInt8 channelNumber) {
return getFeatureUnitSetting (MUTE_CONTROL, unitID, channelNumber, GET_CUR);
}
SInt16 AppleUSBAudioDevice::getCurVolume (UInt8 unitID, UInt8 channelNumber) {
return getFeatureUnitSetting (VOLUME_CONTROL, unitID, channelNumber, GET_CUR);
}
SInt16 AppleUSBAudioDevice::getMaxVolume (UInt8 unitID, UInt8 channelNumber) {
return getFeatureUnitSetting (VOLUME_CONTROL, unitID, channelNumber, GET_MAX);
}
SInt16 AppleUSBAudioDevice::getMinVolume (UInt8 unitID, UInt8 channelNumber) {
return getFeatureUnitSetting (VOLUME_CONTROL, unitID, channelNumber, GET_MIN);
}
UInt16 AppleUSBAudioDevice::getVolumeResolution (UInt8 unitID, UInt8 channelNumber) {
return getFeatureUnitSetting (VOLUME_CONTROL, unitID, channelNumber, GET_RES);
}
IOReturn AppleUSBAudioDevice::setCurVolume (UInt8 unitID, UInt8 channelNumber, SInt16 volume) {
return setFeatureUnitSetting (VOLUME_CONTROL, unitID, channelNumber, SET_CUR, volume, 2);
}
IOReturn AppleUSBAudioDevice::setCurMute (UInt8 unitID, UInt8 channelNumber, SInt16 mute) {
return setFeatureUnitSetting (MUTE_CONTROL, unitID, channelNumber, SET_CUR, mute, 1);
}
IOReturn AppleUSBAudioDevice::controlChangedHandler (OSObject * target, IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
AppleUSBAudioDevice * self;
result = kIOReturnError;
self = OSDynamicCast (AppleUSBAudioDevice, target);
FailIf (NULL == self, Exit);
result = self->protectedControlChangedHandler (audioControl, oldValue, newValue);
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::protectedControlChangedHandler (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
result = kIOReturnError;
switch (audioControl->getType ()) {
case kIOAudioControlTypeLevel:
result = doVolumeControlChange (audioControl, oldValue, newValue);
break;
case kIOAudioControlTypeToggle:
result = doToggleControlChange (audioControl, oldValue, newValue);
break;
case kIOAudioControlTypeSelector:
result = doSelectorControlChange (audioControl, oldValue, newValue);
break;
}
return result;
}
IOReturn AppleUSBAudioDevice::doSelectorControlChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
result = kIOReturnError;
switch (audioControl->getUsage ()) {
case kIOAudioControlUsageInput:
result = doInputSelectorChange (audioControl, oldValue, newValue);
break;
case kIOAudioControlUsageOutput:
break;
case kIOAudioControlUsagePassThru:
result = doPassThruSelectorChange (audioControl, oldValue, newValue);
break;
}
return result;
}
IOReturn AppleUSBAudioDevice::doVolumeControlChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
SInt16 newVolume;
SInt16 deviceMin;
SInt16 offset;
UInt8 unitID;
UInt8 channelNum;
unitID = audioControl->getControlID ();
channelNum = audioControl->getChannelID ();
deviceMin = getMinVolume (unitID, channelNum);
offset = -deviceMin;
if (newValue < 0) {
newVolume = 0x8000;
} else {
if (newValue > 0) {
newVolume = ((newValue - 1) * getVolumeResolution (unitID, channelNum)) - offset;
} else {
newVolume = (newValue * getVolumeResolution (unitID, channelNum)) - offset;
}
}
debugIOLog ("setting volume to 0x%x", newVolume);
result = setCurVolume (unitID, channelNum, HostToUSBWord (newVolume));
return result;
}
IOReturn AppleUSBAudioDevice::doToggleControlChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
UInt8 unitID;
UInt8 channelNum;
unitID = audioControl->getControlID ();
channelNum = audioControl->getChannelID ();
result = setCurMute (unitID, channelNum, HostToUSBWord (newValue));
return result;
}
IOReturn AppleUSBAudioDevice::doPassThruSelectorChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
AppleUSBAudioEngine * usbAudioEngine;
OSArray * playThroughPaths;
OSArray * passThruVolControlsArray;
OSArray * thePath;
OSNumber * number;
OSDictionary * engineInfo;
UInt32 i;
UInt32 numPassThruControls;
UInt8 interfaceNum;
UInt8 altSetting;
UInt8 featureUnitID;
UInt8 pathIndex;
pathIndex = (newValue & 0x000000FF);
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (audioControl->getControlID ()));
FailIf (NULL == engineInfo, Exit);
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, engineInfo->getObject (kEngine));
FailIf (NULL == usbAudioEngine, Exit);
number = OSDynamicCast (OSNumber, engineInfo->getObject (kInterface));
FailIf (NULL == number, Exit);
interfaceNum = number->unsigned8BitValue ();
number = OSDynamicCast (OSNumber, engineInfo->getObject (kAltSetting));
FailIf (NULL == number, Exit);
altSetting = number->unsigned8BitValue ();
passThruVolControlsArray = OSDynamicCast (OSArray, engineInfo->getObject (kPassThruVolControls));
FailIf (NULL == passThruVolControlsArray, Exit);
numPassThruControls = passThruVolControlsArray->getCount ();
usbAudioEngine->pauseAudioEngine ();
usbAudioEngine->beginConfigurationChange ();
for (i = 0; i < numPassThruControls; i++) {
usbAudioEngine->removeDefaultAudioControl ((IOAudioLevelControl *)passThruVolControlsArray->getObject (i));
}
passThruVolControlsArray->flushCollection ();
playThroughPaths = OSDynamicCast (OSArray, engineInfo->getObject (kPassThruPathsArray));
FailIf (NULL == playThroughPaths, Exit);
thePath = OSDynamicCast (OSArray, playThroughPaths->getObject (pathIndex));
FailIf (NULL == thePath, Exit);
featureUnitID = getBestFeatureUnitInPath (thePath, kIOAudioControlUsagePassThru, interfaceNum, altSetting, kVolumeControl);
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSetting, kIOAudioControlUsagePassThru);
usbAudioEngine->completeConfigurationChange ();
usbAudioEngine->resumeAudioEngine ();
Exit:
return kIOReturnSuccess;
}
IOReturn AppleUSBAudioDevice::doInputSelectorChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
AppleUSBAudioEngine * usbAudioEngine;
OSArray * inputGainControlsArray;
OSArray * arrayOfPathsFromOutputTerminal;
OSArray * thePath;
OSNumber * number;
OSDictionary * engineInfo;
IOReturn result;
UInt32 i;
UInt32 numGainControls;
UInt8 interfaceNum;
UInt8 altSetting;
UInt8 featureUnitID;
UInt8 selectorUnitID;
UInt8 selectorPosition;
UInt8 pathsToOutputTerminal;
UInt8 pathIndex;
pathsToOutputTerminal = (newValue & 0xFF000000) >> 24;
pathIndex = (newValue & 0x00FF0000) >> 16;
selectorUnitID = (newValue & 0x0000FF00) >> 8;
selectorPosition = newValue & 0x000000FF;
result = setSelectorSetting (selectorUnitID, selectorPosition);
FailIf (kIOReturnSuccess != result, Exit);
engineInfo = OSDynamicCast (OSDictionary, mRegisteredEngines->getObject (audioControl->getControlID ()));
FailIf (NULL == engineInfo, Exit);
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, engineInfo->getObject (kEngine));
FailIf (NULL == usbAudioEngine, Exit);
number = OSDynamicCast (OSNumber, engineInfo->getObject (kInterface));
FailIf (NULL == number, Exit);
interfaceNum = number->unsigned8BitValue ();
number = OSDynamicCast (OSNumber, engineInfo->getObject (kAltSetting));
FailIf (NULL == number, Exit);
altSetting = number->unsigned8BitValue ();
inputGainControlsArray = OSDynamicCast (OSArray, engineInfo->getObject (kInputGainControls));
FailIf (NULL == inputGainControlsArray, Exit);
numGainControls = inputGainControlsArray->getCount ();
usbAudioEngine->pauseAudioEngine ();
usbAudioEngine->beginConfigurationChange ();
for (i = 0; i < numGainControls; i++) {
usbAudioEngine->removeDefaultAudioControl ((IOAudioLevelControl *)inputGainControlsArray->getObject (i));
}
inputGainControlsArray->flushCollection ();
arrayOfPathsFromOutputTerminal = OSDynamicCast (OSArray, mControlGraph->getObject (pathsToOutputTerminal));
FailIf (NULL == arrayOfPathsFromOutputTerminal, Exit);
thePath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (pathIndex));
FailIf (NULL == thePath, Exit);
featureUnitID = getBestFeatureUnitInPath (thePath, kIOAudioControlUsageInput, interfaceNum, altSetting, kVolumeControl);
addVolumeControls (usbAudioEngine, featureUnitID, interfaceNum, altSetting, kIOAudioControlUsageInput);
usbAudioEngine->completeConfigurationChange ();
usbAudioEngine->resumeAudioEngine ();
Exit:
return result;
}
OSArray * AppleUSBAudioDevice::getPlaythroughPaths () {
OSArray * arrayOfPathsFromOutputTerminal;
OSArray * playThroughPaths;
OSArray * aPath;
OSNumber * theUnitIDNum;
UInt32 numOutputTerminalArrays;
UInt32 numPathsFromOutputTerminal;
UInt32 pathsToOutputTerminalN;
UInt32 pathNumber;
UInt16 terminalType;
UInt8 controlInterfaceNum;
UInt8 unitID;
playThroughPaths = NULL;
FailIf (NULL == mControlInterface, Exit);
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
numOutputTerminalArrays = mControlGraph->getCount ();
for (pathsToOutputTerminalN = 0; pathsToOutputTerminalN < numOutputTerminalArrays; pathsToOutputTerminalN++) {
arrayOfPathsFromOutputTerminal = OSDynamicCast (OSArray, mControlGraph->getObject (pathsToOutputTerminalN));
FailIf (NULL == arrayOfPathsFromOutputTerminal, Exit);
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (0));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getObject (0));
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
if (mUSBAudioConfig->GetOutputTerminalType (controlInterfaceNum, 0, unitID) == 0x101) continue;
numPathsFromOutputTerminal = arrayOfPathsFromOutputTerminal->getCount ();
for (pathNumber = 0; pathNumber < numPathsFromOutputTerminal; pathNumber++) {
aPath = OSDynamicCast (OSArray, arrayOfPathsFromOutputTerminal->getObject (pathNumber));
FailIf (NULL == aPath, Exit);
theUnitIDNum = OSDynamicCast (OSNumber, aPath->getLastObject ());
FailIf (NULL == theUnitIDNum, Exit);
unitID = theUnitIDNum->unsigned8BitValue ();
terminalType = mUSBAudioConfig->GetInputTerminalType (controlInterfaceNum, 0, unitID);
if (terminalType != 0x101) {
if (NULL == playThroughPaths) {
playThroughPaths = OSArray::withObjects ((const OSObject **)&aPath, 1);
} else {
playThroughPaths->setObject (aPath);
}
}
}
}
Exit:
return playThroughPaths;
}
UInt8 AppleUSBAudioDevice::getBestFeatureUnitInPath (OSArray * thePath, UInt32 direction, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 controlTypeWanted) {
OSNumber * theUnitIDNum;
UInt32 numUnitsInPath;
UInt8 featureUnitID;
UInt8 unitIndex;
UInt8 controlInterfaceNum;
UInt8 unitID;
UInt8 subType;
UInt8 channelNum;
Boolean found;
featureUnitID = 0;
FailIf (NULL == mControlInterface, Exit);
controlInterfaceNum = mControlInterface->GetInterfaceNumber ();
numUnitsInPath = thePath->getCount ();
found = FALSE;
switch (direction) {
case kIOAudioControlUsageInput:
case kIOAudioControlUsagePassThru:
for (unitIndex = numUnitsInPath - 2; unitIndex > 0; unitIndex--) {
theUnitIDNum = OSDynamicCast (OSNumber, thePath->getObject (unitIndex));
if (NULL != theUnitIDNum) {
unitID = theUnitIDNum->unsigned8BitValue ();
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID);
if (FEATURE_UNIT == subType) {
for (channelNum = 0; channelNum <= mUSBAudioConfig->GetNumChannels (interfaceNum, altSettingNum); channelNum++) {
switch (controlTypeWanted) {
case kVolumeControl:
if (mUSBAudioConfig->ChannelHasVolumeControl (controlInterfaceNum, 0, unitID, channelNum)) {
featureUnitID = unitID;
found = TRUE;
}
break;
case kMuteControl:
if (mUSBAudioConfig->ChannelHasMuteControl (controlInterfaceNum, 0, unitID, channelNum)) {
featureUnitID = unitID;
found = TRUE;
}
break;
}
}
}
}
}
break;
case kIOAudioControlUsageOutput:
default:
for (unitIndex = 1; unitIndex < numUnitsInPath && !found; unitIndex++) {
theUnitIDNum = OSDynamicCast (OSNumber, thePath->getObject (unitIndex));
if (NULL != theUnitIDNum) {
unitID = theUnitIDNum->unsigned8BitValue ();
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID);
if (FEATURE_UNIT == subType) {
for (channelNum = 0; channelNum <= mUSBAudioConfig->GetNumChannels (interfaceNum, altSettingNum); channelNum++) {
switch (controlTypeWanted) {
case kVolumeControl:
if (mUSBAudioConfig->ChannelHasVolumeControl (controlInterfaceNum, 0, unitID, channelNum)) {
featureUnitID = unitID;
found = TRUE;
}
break;
case kMuteControl:
if (mUSBAudioConfig->ChannelHasMuteControl (controlInterfaceNum, 0, unitID, channelNum)) {
featureUnitID = unitID;
found = TRUE;
}
break;
}
}
}
}
}
break;
}
Exit:
return featureUnitID;
}
UInt8 AppleUSBAudioDevice::getSelectorSetting (UInt8 selectorID) {
IOUSBDevRequestDesc devReq;
IOReturn result;
UInt8 setting;
IOBufferMemoryDescriptor * settingDesc = NULL;
setting = 0;
FailIf (NULL == mControlInterface, Exit);
settingDesc = IOBufferMemoryDescriptor::withOptions (kIODirectionIn, 1);
FailIf (NULL == settingDesc, Exit);
devReq.bmRequestType = USBmakebmRequestType (kUSBIn, kUSBClass, kUSBInterface);
devReq.bRequest = GET_CUR;
devReq.wValue = 0;
devReq.wIndex = (0xFF00 & (selectorID << 8)) | (0x00FF & mControlInterface->GetInterfaceNumber ());
devReq.wLength = 1;
devReq.pData = settingDesc;
result = deviceRequest (&devReq);
FailIf (kIOReturnSuccess != result, Exit);
memcpy (&setting, settingDesc->getBytesNoCopy (), 1);
Exit:
if (NULL != settingDesc) {
settingDesc->release ();
}
return setting;
}
IOReturn AppleUSBAudioDevice::setSelectorSetting (UInt8 selectorID, UInt8 setting) {
IOUSBDevRequestDesc devReq;
IOReturn result;
IOBufferMemoryDescriptor * settingDesc = NULL;
result = kIOReturnError;
FailIf (NULL == mControlInterface, Exit);
settingDesc = OSTypeAlloc (IOBufferMemoryDescriptor);
FailIf (NULL == settingDesc, Exit);
settingDesc->initWithBytes (&setting, 1, kIODirectionIn);
devReq.bmRequestType = USBmakebmRequestType (kUSBOut, kUSBClass, kUSBInterface);
devReq.bRequest = SET_CUR;
devReq.wValue = 0;
devReq.wIndex = (0xFF00 & (selectorID << 8)) | (0x00FF & mControlInterface->GetInterfaceNumber ());
devReq.wLength = 1;
devReq.pData = settingDesc;
result = deviceRequest (&devReq);
Exit:
if (NULL != settingDesc) {
settingDesc->release ();
}
return result;
}
IOReturn AppleUSBAudioDevice::createControlsForInterface (IOAudioEngine *audioEngine, UInt8 interfaceNum, UInt8 altSettingNum) {
AppleUSBAudioEngine * usbAudioEngine;
IOReturn result;
debugIOLog ("+AppleUSBAudioDevice[%p]::createControlsForInterface %d %d", this, interfaceNum, altSettingNum);
result = kIOReturnError;
mTerminatingDriver = FALSE;
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, audioEngine);
FailIf (NULL == usbAudioEngine, Exit);
doControlStuff (audioEngine, interfaceNum, altSettingNum);
Exit:
return result;
}
OSArray * AppleUSBAudioDevice::BuildConnectionGraph (UInt8 controlInterfaceNum) {
OSArray * allOutputTerminalPaths;
OSArray * pathsFromOutputTerminalN;
OSArray * thisPath;
#if 0
UInt32 h, i, j;
#endif
UInt8 terminalIndex;
UInt8 numTerminals;
thisPath = NULL;
allOutputTerminalPaths = OSArray::withCapacity (1);
FailIf (NULL == allOutputTerminalPaths, Exit);
pathsFromOutputTerminalN = OSArray::withCapacity (1);
FailIf (NULL == pathsFromOutputTerminalN, Exit);
numTerminals = mUSBAudioConfig->GetNumOutputTerminals (controlInterfaceNum, 0);
for (terminalIndex = 0; terminalIndex < numTerminals; terminalIndex++) {
BuildPath (controlInterfaceNum, mUSBAudioConfig->GetIndexedOutputTerminalID (controlInterfaceNum, 0, terminalIndex), pathsFromOutputTerminalN, thisPath);
allOutputTerminalPaths->setObject (pathsFromOutputTerminalN);
pathsFromOutputTerminalN->release ();
pathsFromOutputTerminalN = OSArray::withCapacity (1);
FailIf (NULL == pathsFromOutputTerminalN, Exit);
}
#if 0
for (h = 0; h < allOutputTerminalPaths->getCount (); h++) {
IOLog ("h = %ld\n", h);
pathsFromOutputTerminalN = OSDynamicCast (OSArray, allOutputTerminalPaths->getObject (h));
FailIf (NULL == pathsFromOutputTerminalN, Exit);
for (i = 0; i < pathsFromOutputTerminalN->getCount (); i++) {
OSArray * theArray;
OSNumber * theUnitIDNum;
UInt8 unitID;
theArray = OSDynamicCast (OSArray, pathsFromOutputTerminalN->getObject (i));
if (NULL != theArray) {
for (j = 0; j < theArray->getCount (); j++) {
theUnitIDNum = OSDynamicCast (OSNumber, theArray->getObject (j));
if (NULL != theUnitIDNum) {
unitID = theUnitIDNum->unsigned8BitValue ();
IOLog ("%x->", unitID);
}
}
IOLog ("\n\n");
}
}
}
#endif
Exit:
return allOutputTerminalPaths;
}
#if 0
void AppleUSBAudioDevice::PruneInputPaths (OSArray * allOutputTerminalPaths) {
OSArray * allOutputTerminalPaths;
OSArray * pathsFromOutputTerminalN;
OSArray * thisPath;
UInt32 h, i;
UInt8 outputTerminalID;
UInt8 inputTerminalID;
for (h = 0; h < allOutputTerminalPaths->getCount (); h++) {
pathsFromOutputTerminalN = OSDynamicCast (OSArray, allOutputTerminalPaths->getObject (h));
FailIf (NULL == pathsFromOutputTerminalN, Exit);
for (i = 0; i < pathsFromOutputTerminalN->getCount (); i++) {
OSArray * theArray;
OSNumber * theUnitIDNum;
UInt8 unitID;
theArray = OSDynamicCast (OSArray, pathsFromOutputTerminalN->getObject (i));
if (NULL != theArray) {
theUnitIDNum = OSDynamicCast (OSNumber, theArray->getObject (0));
FailIf (NULL == theUnitIDNum, Exit);
outputTerminalID = theUnitIDNum->unsigned8BitValue ();
theUnitIDNum = OSDynamicCast (OSNumber, theArray->getLastObject ());
FailIf (NULL == theUnitIDNum, Exit);
inputTerminalID = theUnitIDNum->unsigned8BitValue ();
if (mUSBAudioConfig->GetOutputTerminalType (controlInterfaceNum, 0, outputTerminalID) == mUSBAudioConfig->GetInputTerminalType (controlInterfaceNum, 0, inputTerminalID)) {
pathsFromOutputTerminalN->removeObject (i);
i--;
}
}
}
}
Exit:
return
}
#endif
OSArray * AppleUSBAudioDevice::BuildPath (UInt8 controlInterfaceNum, UInt8 startingUnitID, OSArray * allPaths, OSArray * startingPath) {
OSArray * curPath;
OSArray * tempPath;
OSNumber * thisUnitIDNum;
UInt8 unitID;
UInt8 * sourceIDs;
UInt32 i;
UInt8 thisUnitID;
UInt8 numSources;
UInt8 sourceID;
UInt8 subType;
thisUnitID = startingUnitID;
curPath = NULL;
thisUnitIDNum = OSNumber::withNumber (thisUnitID, 8);
FailIf (NULL == thisUnitIDNum, Exit);
if (NULL != startingPath) {
curPath = OSArray::withArray (startingPath);
}
if (NULL == curPath) {
curPath = OSArray::withObjects ((const OSObject **)&thisUnitIDNum, 1);
} else {
curPath->setObject (thisUnitIDNum);
}
thisUnitIDNum->release ();
thisUnitIDNum = NULL;
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, thisUnitID);
while (INPUT_TERMINAL != subType && subType != 0) {
switch (subType) {
case MIXER_UNIT:
case SELECTOR_UNIT:
case EXTENSION_UNIT:
case PROCESSING_UNIT:
numSources = mUSBAudioConfig->GetNumSources (controlInterfaceNum, 0, thisUnitID);
sourceIDs = mUSBAudioConfig->GetSourceIDs (controlInterfaceNum, 0, thisUnitID);
tempPath = OSArray::withArray (curPath);
for (i = 0; i < numSources; i++) {
if (NULL == curPath) {
curPath = OSArray::withCapacity (1);
}
FailIf (NULL == curPath, Exit);
curPath = BuildPath (controlInterfaceNum, sourceIDs[i], allPaths, tempPath);
if (curPath && curPath->getCount ()) {
thisUnitIDNum = OSDynamicCast (OSNumber, curPath->getLastObject ());
FailIf (NULL == thisUnitIDNum, Exit);
unitID = thisUnitIDNum->unsigned8BitValue ();
if (unitID && mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, unitID) == INPUT_TERMINAL) {
allPaths->setObject (curPath);
}
}
if (curPath) {
curPath->release ();
curPath = NULL;
}
}
tempPath->release ();
subType = 0;
break;
case OUTPUT_TERMINAL:
case FEATURE_UNIT:
default:
sourceID = mUSBAudioConfig->GetSourceID (controlInterfaceNum, 0, thisUnitID);
thisUnitID = sourceID;
thisUnitIDNum = OSNumber::withNumber (thisUnitID, 8);
if (NULL != thisUnitIDNum) {
curPath->setObject (thisUnitIDNum);
thisUnitIDNum->release ();
thisUnitIDNum = NULL;
}
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, thisUnitID);
if (subType == INPUT_TERMINAL && mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, startingUnitID) == OUTPUT_TERMINAL) {
allPaths->setObject (curPath);
}
break;
}
}
Exit:
return curPath;
}
#if 0
OSArray * AppleUSBAudioDevice::FindAllInputSources (OSArray * outputTerminalPaths, UInt8 outputTerminalID, Boolean forOutput) {
OSArray * inputSources;
OSArray * thePath;
OSArray * thePath2;
OSNumber * theUnitIDNum;
UInt32 i, j;
inputSources = OSArray::withCapacity (1);
if (NULL != inputSources) {
for (i = 0; i < outputTerminalPaths->getCount (); i++) {
thePath = OSDynamicCast (OSArray, outputTerminalPaths->getObject (i));
if (NULL != thePath) {
theUnitIDNum = OSDynamicCast (OSNumber, thePath->getObject (0));
if ((NULL != theUnitIDNum) && (theUnitIDNum->unsigned8BitValue () == outputTerminalID)) {
inputSources->setObject (thePath);
}
}
}
for (i = 0; i < inputSources->getCount (); i++) {
thePath = OSDynamicCast (OSArray, inputSources->getObject (i));
if (NULL != thePath) {
theUnitIDNum = OSDynamicCast (OSNumber, thePath->getLastObject ());
for (j = i + 1; j < inputSources->getCount (); j++) {
thePath2 = OSDynamicCast (OSArray, inputSources->getObject (j));
if ((NULL != thePath2) && (NULL != theUnitIDNum) && (theUnitIDNum->unsigned8BitValue () == OSDynamicCast (OSNumber, thePath2->getLastObject ())->unsigned8BitValue ())) {
if (thePath->getCount () > thePath2->getCount ()) {
inputSources->removeObject (i);
} else {
inputSources->removeObject (j);
}
j--; }
}
}
}
}
#if 0
IOLog ("Input sources from OT %x are:\n", outputTerminalID);
for (i = 0; i < inputSources->getCount (); i++) {
OSArray * theArray;
OSNumber * theUnitIDNum;
UInt8 unitID;
theArray = OSDynamicCast (OSArray, inputSources->getObject (i));
if (NULL != theArray) {
for (j = 0; j < theArray->getCount (); j++) {
theUnitIDNum = OSDynamicCast (OSNumber, theArray->getObject (j));
if (NULL != theUnitIDNum) {
unitID = theUnitIDNum->unsigned8BitValue ();
IOLog ("%x->", unitID);
}
}
IOLog ("\n\n");
}
}
#endif
return inputSources;
}
OSArray * AppleUSBAudioDevice::FindSelectorUnitsInPath (UInt8 controlInterfaceNum, UInt8 startingUnitID) {
OSArray * selectors;
OSNumber * theSourceID;
UInt8 * sourceIDs;
UInt32 i;
UInt8 numSources;
UInt8 thisUnitID;
UInt8 sourceID;
UInt8 subType;
selectors = NULL;
thisUnitID = startingUnitID;
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, thisUnitID);
sourceID = 0;
while (INPUT_TERMINAL != subType) {
switch (subType) {
case SELECTOR_UNIT:
numSources = mUSBAudioConfig->GetNumSources (controlInterfaceNum, 0, thisUnitID);
sourceIDs = mUSBAudioConfig->GetSourceIDs (controlInterfaceNum, 0, thisUnitID);
theSourceID = OSNumber::withNumber (sourceID, 8);
if (NULL != theSourceID) {
if (NULL == selectors) {
selectors = OSArray::withObjects ((const OSObject **)&theSourceID, 1);
} else {
selectors->setObject (theSourceID);
}
theSourceID->release ();
theSourceID = NULL;
} case MIXER_UNIT:
case EXTENSION_UNIT:
case PROCESSING_UNIT:
numSources = mUSBAudioConfig->GetNumSources (controlInterfaceNum, 0, thisUnitID);
sourceIDs = mUSBAudioConfig->GetSourceIDs (controlInterfaceNum, 0, thisUnitID);
for (i = 0; i < numSources; i++) {
selectors->merge (FindSelectorUnitsInPath (controlInterfaceNum, sourceIDs[i]));
}
break;
case OUTPUT_TERMINAL:
case FEATURE_UNIT:
default:
sourceID = mUSBAudioConfig->GetSourceID (controlInterfaceNum, 0, thisUnitID);
break;
}
thisUnitID = sourceID;
subType = mUSBAudioConfig->GetSubType (controlInterfaceNum, 0, thisUnitID);
}
return selectors;
}
#endif
char * AppleUSBAudioDevice::TerminalTypeString (UInt16 terminalType) {
char * terminalTypeString;
switch (terminalType) {
case 0x101: terminalTypeString = "USB streaming"; break;
#if LOCALIZABLE
case INPUT_UNDEFINED: terminalTypeString = "StringInputUndefined"; break;
case INPUT_MICROPHONE: terminalTypeString = "StringMicrophone"; break;
case INPUT_DESKTOP_MICROPHONE: terminalTypeString = "StringDesktopMicrophone"; break;
case INPUT_PERSONAL_MICROPHONE: terminalTypeString = "StringPersonalMicrophone"; break;
case INPUT_OMNIDIRECTIONAL_MICROPHONE: terminalTypeString = "StringOmnidirectionalMicrophone"; break;
case INPUT_MICROPHONE_ARRAY: terminalTypeString = "StringMicrophoneArray"; break;
case INPUT_PROCESSING_MICROPHONE_ARRAY: terminalTypeString = "StringProcessingMicrophoneArray"; break;
case INPUT_MODEM_AUDIO: terminalTypeString = "StringModemAudio"; break;
case OUTPUT_UNDEFINED: terminalTypeString = "StringOutputUndefined"; break;
case OUTPUT_SPEAKER: terminalTypeString = "StringSpeaker"; break;
case OUTPUT_HEADPHONES: terminalTypeString = "StringHeadphones"; break;
case OUTPUT_HEAD_MOUNTED_DISPLAY_AUDIO: terminalTypeString = "StringHeadMountedDisplayAudio"; break;
case OUTPUT_DESKTOP_SPEAKER: terminalTypeString = "StringDesktopSpeaker"; break;
case OUTPUT_ROOM_SPEAKER: terminalTypeString = "StringRoomSpeaker"; break;
case OUTPUT_COMMUNICATION_SPEAKER: terminalTypeString = "StringCommunicationSpeaker"; break;
case OUTPUT_LOW_FREQUENCY_EFFECTS_SPEAKER: terminalTypeString = "StringLowFrequencyEffectsSpeaker"; break;
case BIDIRECTIONAL_UNDEFINED: terminalTypeString = "StringBidirectionalUndefined"; break;
case BIDIRECTIONAL_HANDSET: terminalTypeString = "StringBidirectionalHandset"; break;
case BIDIRECTIONAL_HEADSET: terminalTypeString = "StringBidirectionalHeadset"; break;
case BIDIRECTIONAL_SPEAKERPHONE_NO_ECHO_REDX: terminalTypeString = "StringBidirectionalSpeakerphoneNoEchoRedx"; break;
case BIDIRECTIONAL_ECHO_SUPPRESSING_SPEAKERPHONE: terminalTypeString = "StringBidirectionalEchoSuppressingSpeakerphone"; break;
case BIDIRECTIONAL_ECHO_CANCELING_SPEAKERPHONE: terminalTypeString = "StringBidirectionalEchoCancelingSpeakerphone"; break;
case TELEPHONY_UNDEFINED: terminalTypeString = "StringTelephoneUndefined"; break;
case TELEPHONY_PHONE_LINE: terminalTypeString = "StringTelephoneLine"; break;
case TELEPHONY_TELEPHONE: terminalTypeString = "StringTelephone"; break;
case TELEPHONY_DOWN_LINE_PHONE: terminalTypeString = "StringDownLinePhone"; break;
case EXTERNAL_UNDEFINED: terminalTypeString = "StringExternalUndefined"; break;
case EXTERNAL_ANALOG_CONNECTOR: terminalTypeString = "StringExternalAnalogConnector"; break;
case EXTERNAL_DIGITAL_AUDIO_INTERFACE: terminalTypeString = "StringExternalDigitalAudioInterface"; break;
case EXTERNAL_LINE_CONNECTOR: terminalTypeString = "StringExternalLineConnector"; break;
case EXTERNAL_LEGACY_AUDIO_CONNECTOR: terminalTypeString = "StringExternalLegacyAudioConnector"; break;
case EXTERNAL_SPDIF_INTERFACE: terminalTypeString = "StringExternalSPDIFInterface"; break;
case EXTERNAL_1394_DA_STREAM: terminalTypeString = "StringExternal1394DAStream"; break;
case EXTERNAL_1394_DV_STREAM_SOUNDTRACK: terminalTypeString = "StringExternal1394DVStreamSoundtrack"; break;
case EMBEDDED_UNDEFINED: terminalTypeString = "StringEmbeddedUndefined"; break;
case EMBEDDED_LEVEL_CALIBRATION_NOISE_SOURCE: terminalTypeString = "StringEmbeddedLevelCalibrationNoiseSource"; break;
case EMBEDDED_EQUALIZATION_NOISE: terminalTypeString = "StringEmbeddedEqualizationNoise"; break;
case EMBEDDED_CD_PLAYER: terminalTypeString = "StringEmbeddedCDPlayer"; break;
case EMBEDDED_DAT: terminalTypeString = "StringEmbeddedDAT"; break;
case EMBEDDED_DCC: terminalTypeString = "StringEmbeddedDCC"; break;
case EMBEDDED_MINIDISK: terminalTypeString = "StringEmbeddedMiniDisc"; break;
case EMBEDDED_ANALOG_TAPE: terminalTypeString = "StringEmbeddedAnalogTape"; break;
case EMBEDDED_PHONOGRAPH: terminalTypeString = "StringEmbeddedPhonograph"; break;
case EMBEDDED_VCR_AUDIO: terminalTypeString = "StringEmbeddedVCRAudio"; break;
case EMBEDDED_VIDEO_DISC_AUDIO: terminalTypeString = "StringEmbeddedVideoDiscAudio"; break;
case EMBEDDED_DVD_AUDIO: terminalTypeString = "StringEmbeddedDVDAudio"; break;
case EMBEDDED_TV_TUNER_AUDIO: terminalTypeString = "StringEmbeddedTVTunerAudio"; break;
case EMBEDDED_SATELLITE_RECEIVER_AUDIO: terminalTypeString = "StringEmbeddedSatelliteReceiverAudio"; break;
case EMBEDDED_CABLE_TUNER_AUDIO: terminalTypeString = "StringEmbeddedCableTunerAudio"; break;
case EMBEDDED_DSS_AUDIO: terminalTypeString = "StringEmbeddedDSSAudio"; break;
case EMBEDDED_RADIO_RECEIVER: terminalTypeString = "StringEmbeddedRadioReceiver"; break;
case EMBEDDED_RADIO_TRANSMITTER: terminalTypeString = "StringEmbeddedRadioTransmitter"; break;
case EMBEDDED_MULTITRACK_RECORDER: terminalTypeString = "StringEmbeddedMultitrackRecorder"; break;
case EMBEDDED_SYNTHESIZER: terminalTypeString = "StringEmbeddedSynthesizer"; break;
default: terminalTypeString = "StringUnknown"; break;
#else
case INPUT_UNDEFINED: terminalTypeString = "InputUndefined"; break;
case INPUT_MICROPHONE: terminalTypeString = "Microphone"; break;
case INPUT_DESKTOP_MICROPHONE: terminalTypeString = "Desktop Microphone"; break;
case INPUT_PERSONAL_MICROPHONE: terminalTypeString = "Personal Microphone"; break;
case INPUT_OMNIDIRECTIONAL_MICROPHONE: terminalTypeString = "Omnidirectional Microphone"; break;
case INPUT_MICROPHONE_ARRAY: terminalTypeString = "Microphone Array"; break;
case INPUT_PROCESSING_MICROPHONE_ARRAY: terminalTypeString = "Processing Microphone Array"; break;
case INPUT_MODEM_AUDIO: terminalTypeString = "Modem Audio"; break;
case OUTPUT_UNDEFINED: terminalTypeString = "Output Undefined"; break;
case OUTPUT_SPEAKER: terminalTypeString = "Speaker"; break;
case OUTPUT_HEADPHONES: terminalTypeString = "Headphones"; break;
case OUTPUT_HEAD_MOUNTED_DISPLAY_AUDIO: terminalTypeString = "Head Mounted Display Audio"; break;
case OUTPUT_DESKTOP_SPEAKER: terminalTypeString = "Desktop Speaker"; break;
case OUTPUT_ROOM_SPEAKER: terminalTypeString = "Room Speaker"; break;
case OUTPUT_COMMUNICATION_SPEAKER: terminalTypeString = "Communication Speaker"; break;
case OUTPUT_LOW_FREQUENCY_EFFECTS_SPEAKER: terminalTypeString = "Low Frequency Effects Speaker"; break;
case BIDIRECTIONAL_UNDEFINED: terminalTypeString = "Bidirectional Undefined"; break;
case BIDIRECTIONAL_HANDSET: terminalTypeString = "Bidirectional Handset"; break;
case BIDIRECTIONAL_HEADSET: terminalTypeString = "Bidirectional Headset"; break;
case BIDIRECTIONAL_SPEAKERPHONE_NO_ECHO_REDX: terminalTypeString = "Bidirectional Speakerphone No Echo Redx"; break;
case BIDIRECTIONAL_ECHO_SUPPRESSING_SPEAKERPHONE: terminalTypeString = "Bidirectional Echo Suppressing Speakerphone"; break;
case BIDIRECTIONAL_ECHO_CANCELING_SPEAKERPHONE: terminalTypeString = "Bidirectional Echo Canceling Speakerphone"; break;
case TELEPHONY_UNDEFINED: terminalTypeString = "Telephone Undefined"; break;
case TELEPHONY_PHONE_LINE: terminalTypeString = "Telephone Line"; break;
case TELEPHONY_TELEPHONE: terminalTypeString = "Telephone"; break;
case TELEPHONY_DOWN_LINE_PHONE: terminalTypeString = "Down Line Phone"; break;
case EXTERNAL_UNDEFINED: terminalTypeString = "External Undefined"; break;
case EXTERNAL_ANALOG_CONNECTOR: terminalTypeString = "External Analog Connector"; break;
case EXTERNAL_DIGITAL_AUDIO_INTERFACE: terminalTypeString = "External Digital Audio Interface"; break;
case EXTERNAL_LINE_CONNECTOR: terminalTypeString = "External Line Connector"; break;
case EXTERNAL_LEGACY_AUDIO_CONNECTOR: terminalTypeString = "External Legacy Audio Connector"; break;
case EXTERNAL_SPDIF_INTERFACE: terminalTypeString = "External SPDIF Interface"; break;
case EXTERNAL_1394_DA_STREAM: terminalTypeString = "External 1394 DA Stream"; break;
case EXTERNAL_1394_DV_STREAM_SOUNDTRACK: terminalTypeString = "External 1394 DV Stream Soundtrack"; break;
case EMBEDDED_UNDEFINED: terminalTypeString = "Embedded Undefined"; break;
case EMBEDDED_LEVEL_CALIBRATION_NOISE_SOURCE: terminalTypeString = "Embedded Level Calibration Noise Source"; break;
case EMBEDDED_EQUALIZATION_NOISE: terminalTypeString = "Embedded Equalization Noise"; break;
case EMBEDDED_CD_PLAYER: terminalTypeString = "Embedded CD Player"; break;
case EMBEDDED_DAT: terminalTypeString = "Embedded DAT"; break;
case EMBEDDED_DCC: terminalTypeString = "Embedded DCC"; break;
case EMBEDDED_MINIDISK: terminalTypeString = "Embedded Mini Disc"; break;
case EMBEDDED_ANALOG_TAPE: terminalTypeString = "Embedded Analog Tape"; break;
case EMBEDDED_PHONOGRAPH: terminalTypeString = "Embedded Phonograph"; break;
case EMBEDDED_VCR_AUDIO: terminalTypeString = "Embedded VCR Audio"; break;
case EMBEDDED_VIDEO_DISC_AUDIO: terminalTypeString = "Embedded Video Disc Audio"; break;
case EMBEDDED_DVD_AUDIO: terminalTypeString = "Embedded DVD Audio"; break;
case EMBEDDED_TV_TUNER_AUDIO: terminalTypeString = "Embedded TV Tuner Audio"; break;
case EMBEDDED_SATELLITE_RECEIVER_AUDIO: terminalTypeString = "Embedded Satellite Receiver Audio"; break;
case EMBEDDED_CABLE_TUNER_AUDIO: terminalTypeString = "Embedded Cable Tuner Audio"; break;
case EMBEDDED_DSS_AUDIO: terminalTypeString = "Embedded DSS Audio"; break;
case EMBEDDED_RADIO_RECEIVER: terminalTypeString = "Embedded Radio Receiver"; break;
case EMBEDDED_RADIO_TRANSMITTER: terminalTypeString = "Embedded Radio Transmitter"; break;
case EMBEDDED_MULTITRACK_RECORDER: terminalTypeString = "Embedded Multitrack Recorder"; break;
case EMBEDDED_SYNTHESIZER: terminalTypeString = "Embedded Synthesizer"; break;
default: terminalTypeString = "Unknown"; break;
#endif
}
return terminalTypeString;
}
IOReturn AppleUSBAudioDevice::deviceRequest (IOUSBDevRequestDesc * request, IOUSBCompletion * completion) {
IOReturn result;
UInt32 timeout;
Boolean done;
debugIOLog ("+AppleUSBAudioDevice[%p]::deviceRequest (%p, %p)", this, request, completion);
result = kIOReturnSuccess;
FailIf (NULL == mInterfaceLock, Exit);
IORecursiveLockLock (mInterfaceLock);
if (FALSE == mTerminatingDriver) {
done = FALSE;
timeout = 5;
while (!done && timeout && mControlInterface) {
result = mControlInterface->DeviceRequest (request, completion);
if (result != kIOReturnSuccess) {
timeout--;
IOSleep (1);
} else {
done = TRUE;
}
}
}
IORecursiveLockUnlock (mInterfaceLock);
debugIOLog ("-AppleUSBAudioDevice[%p]::deviceRequest (%p, %p) = %lx", this, request, completion, result);
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::deviceRequest (IOUSBDevRequest * request, IOUSBCompletion * completion) {
IOReturn result;
UInt32 timeout;
Boolean done;
debugIOLog ("+AppleUSBAudioDevice[%p]::deviceRequest (%p, %p)", this, request, completion);
result = kIOReturnSuccess;
FailIf (NULL == mInterfaceLock, Exit);
IORecursiveLockLock (mInterfaceLock);
if (FALSE == mTerminatingDriver) {
done = FALSE;
timeout = 5;
while (!done && timeout && mControlInterface) {
result = mControlInterface->DeviceRequest (request, completion);
if (result != kIOReturnSuccess) {
timeout--;
IOSleep (1);
} else {
done = TRUE;
}
}
}
IORecursiveLockUnlock (mInterfaceLock);
debugIOLog ("-AppleUSBAudioDevice[%p]::deviceRequest (%p, %p) = %lx", this, request, completion, result);
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::deviceRequest (IOUSBDevRequest *request, AppleUSBAudioDevice * self, IOUSBCompletion *completion) {
IOReturn result;
UInt32 timeout;
Boolean done;
debugIOLog ("+AppleUSBAudioDevice[%p]::deviceRequest (%p, %p)", self, request, completion);
result = kIOReturnSuccess;
FailIf (NULL == self->mInterfaceLock, Exit);
IORecursiveLockLock (self->mInterfaceLock);
if (FALSE == self->mTerminatingDriver) {
done = FALSE;
timeout = 5;
while (!done && timeout && self->mControlInterface) {
result = self->mControlInterface->DeviceRequest (request, completion);
if (result != kIOReturnSuccess) {
timeout--;
IOSleep (1);
} else {
done = TRUE;
}
}
}
IORecursiveLockUnlock (self->mInterfaceLock);
debugIOLog ("-AppleUSBAudioDevice[%p]::deviceRequest (%p, %p) = %lx", self, request, completion, result);
Exit:
return result;
}
bool AppleUSBAudioDevice::willTerminate (IOService * provider, IOOptionBits options) {
debugIOLog ("+AppleUSBAudioDevice[%p]::willTerminate (%p)", this, provider);
if (mControlInterface == provider) {
mTerminatingDriver = TRUE;
}
debugIOLog ("-AppleUSBAudioDevice[%p]::willTerminate", this);
return super::willTerminate (provider, options);
}
void AppleUSBAudioDevice::setConfigurationApp (const char *bundleID) {
setConfigurationApplicationBundle (bundleID);
}
#ifdef DEBUG
void AppleUSBAudioDevice::retain() const
{
super::retain();
}
void AppleUSBAudioDevice::release() const
{
super::release();
}
#endif
Generated by GNU enscript 1.6.4.