[plain text]
#define THREAD_ISUB_OPEN FALSE
#include "AppleUSBAudioEngine.h"
#include "AppleUSBAudioPlugin.h"
#define super IOAudioEngine
OSDefineMetaClassAndStructors(AppleUSBAudioEngine, IOAudioEngine)
#pragma mark -IOKit Routines-
void AppleUSBAudioEngine::free () {
debugIOLog ("+ AppleUSBAudioEngine[%p]::free ()", this);
if (NULL != mLowFreqSamples)
{
IOFreeAligned (mLowFreqSamples, mFreqSampleBufferSize);
mLowFreqSamples = NULL;
}
if (NULL != mHighFreqSamples)
{
IOFreeAligned (mHighFreqSamples, mFreqSampleBufferSize);
mHighFreqSamples = NULL;
}
mFreqSampleBufferSize = 0;
if (NULL != miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine[%p]::free () - Removing miSubEngineNotifier ...", this);
miSubEngineNotifier->remove ();
miSubEngineNotifier = NULL;
}
if (NULL != miSubAttachToggle)
{
miSubAttachToggle->release ();
miSubAttachToggle = NULL;
}
if (NULL != mClockSelectorControl)
{
mClockSelectorControl->release ();
mClockSelectorControl = NULL;
}
if (NULL != mStreamInterfaceNumberArray)
{
mStreamInterfaceNumberArray->release ();
mStreamInterfaceNumberArray = NULL;
}
if (NULL != mIOAudioStreamArray)
{
mIOAudioStreamArray->release ();
mIOAudioStreamArray = NULL;
}
mMainOutputStream = NULL;
mMainInputStream = NULL;
super::free ();
debugIOLog ("- AppleUSBAudioEngine[%p]::free()", this);
}
bool AppleUSBAudioEngine::init ( OSArray * streamInterfaceNumberArray ) {
Boolean result = false;
debugIOLog("+ AppleUSBAudioEngine[%p]::init ()", this);
FailIf (NULL == streamInterfaceNumberArray, Exit);
FailIf (0 == streamInterfaceNumberArray->getCount (), Exit);
result = FALSE;
FailIf (FALSE == super::init (NULL), Exit);
mStreamInterfaceNumberArray = streamInterfaceNumberArray;
mStreamInterfaceNumberArray->retain ();
mIOAudioStreamArray = OSArray::withCapacity (1);
FailIf ( NULL == mIOAudioStreamArray, Exit );
setProperty ("IOAudioStreamSampleFormatByteOrder", "Little Endian");
result = TRUE;
mSrcPhase = 1.0; mSrcState = 0.0; mJustResetClipPosition = FALSE;
Exit:
debugIOLog("- AppleUSBAudioEngine[%p]::init ()", this);
return result;
}
bool AppleUSBAudioEngine::requestTerminate (IOService * provider, IOOptionBits options) {
bool result = TRUE;
debugIOLog ("+ AppleUSBAudioEngine[%p]::requestTerminate (%p, %x)", this, provider, options);
if ( mUSBAudioDevice == provider )
{
result = TRUE; }
else
{
result = FALSE; }
debugIOLog ("- AppleUSBAudioEngine[%p]::requestTerminate (%p, %x) = %d", this, provider, options, result);
return result;
}
bool AppleUSBAudioEngine::start (IOService * provider, IOAudioDevice * device) {
bool resultCode;
AUAConfigurationDictionary * configDictionary = NULL;
debugIOLog ("+ AppleUSBAudioEngine[%p]::start (%p)", this, provider);
resultCode = FALSE;
FailIf (NULL == device, Exit);
mUSBAudioDevice = OSDynamicCast (AppleUSBAudioDevice, device);
mUSBAudioDevice->retain ();
FailIf ( NULL == mUSBAudioDevice->mControlInterface, Exit );
if ( 0 == mUSBAudioDevice->mControlInterface->GetInterfaceNumber() )
{
FailIf (NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary()), Exit);
FailIf (configDictionary->isiSub(), Exit);
}
resultCode = super::start (provider, device);
Exit:
if (!resultCode)
{
if (NULL != mUSBAudioDevice)
{
mUSBAudioDevice->release ();
mUSBAudioDevice = NULL;
}
}
debugIOLog ("- AppleUSBAudioEngine[%p]::start (%p) = %d", this, provider, resultCode);
return resultCode;
}
void AppleUSBAudioEngine::stop (IOService * provider) {
debugIOLog("+ AppleUSBAudioEngine[%p]::stop (%p)", this, provider);
if (provider == miSubEngine)
{
goto Exit;
}
if (NULL != mPluginNotification)
{
mPluginNotification->remove ();
mPluginNotification = NULL;
}
if (NULL != mPluginInitThread)
{
thread_call_cancel (mPluginInitThread);
thread_call_free (mPluginInitThread);
mPluginInitThread = NULL;
}
if (NULL != miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine[%p]::stop () - Removing miSubEngineNotifier ...", this);
miSubEngineNotifier->remove ();
miSubEngineNotifier = NULL;
}
if (mPlugin)
{
mPlugin->close (this);
mPlugin = NULL;
}
if (NULL != miSubEngine)
{
iSubTeardownConnection ();
}
if (mUSBAudioDevice)
{
mUSBAudioDevice->release ();
mUSBAudioDevice = NULL;
}
Exit:
super::stop (provider);
debugIOLog ( "- AppleUSBAudioEngine[%p]::stop (%p) - rc=%ld", this, provider, getRetainCount() );
}
bool AppleUSBAudioEngine::terminate (IOOptionBits options) {
bool shouldTerminate;
bool result;
result = TRUE;
shouldTerminate = TRUE;
debugIOLog ("+ AppleUSBAudioEngine[%p]::terminate ()", this);
if (shouldTerminate)
{
result = super::terminate (options);
}
debugIOLog ("- AppleUSBAudioEngine[%p]::terminate ()", this);
return result;
}
bool AppleUSBAudioEngine::matchPropertyTable(OSDictionary * table, SInt32 *score)
{
bool returnValue = false;
if (super::matchPropertyTable (table, score))
{
if (compareProperty (table, kIDVendorString) &&
compareProperty (table, kIDProductString))
{
returnValue = true;
}
}
return returnValue;
}
void AppleUSBAudioEngine::openStreamInterfaces () {
FailIf ( NULL == mIOAudioStreamArray, Exit );
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
FailIf ( NULL == audioStream, Exit );
audioStream->openStreamInterface ();
}
Exit:
return;
}
void AppleUSBAudioEngine::closeStreamInterfaces () {
FailIf ( NULL == mIOAudioStreamArray, Exit );
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
FailIf ( NULL == audioStream, Exit );
audioStream->closeStreamInterface ();
}
Exit:
return;
}
#pragma mark -USB Audio driver-
IOReturn AppleUSBAudioEngine::clipOutputSamples (const void *mixBuf, void *sampleBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream) {
void * iSubBuffer = NULL;
UInt32 iSubBufferLen = 0;
UInt32 sampleRate;
SInt32 offsetDelta;
SInt32 safetyOffset;
IOReturn result;
iSubAudioFormatType iSubFormat; AppleUSBAudioStream * appleUSBAudioStream;
result = kIOReturnError;
appleUSBAudioStream = OSDynamicCast ( AppleUSBAudioStream, audioStream );
FailIf ( NULL == appleUSBAudioStream, Exit );
appleUSBAudioStream->queueOutputFrames ();
if (TRUE == streamFormat->fIsMixable)
{
if (NULL != miSubBufferMemory && NULL != miSubEngine && appleUSBAudioStream == mMainOutputStream )
{
iSubBufferLen = miSubBufferMemory->getLength ();
#if defined(__ppc__) || defined(__i386__)
iSubBuffer = (void*)miSubBufferMemory->getVirtualSegment (0, &iSubBufferLen);
#else
iSubBuffer = (void*)miSubBufferMemory->getVirtualAddress();
#endif
iSubBufferLen = iSubBufferLen / 2;
sampleRate = getSampleRate()->whole;
iSubFormat.altInterface = miSubEngine->GetAltInterface();
iSubFormat.numChannels = miSubEngine->GetNumChannels();
iSubFormat.bytesPerSample = miSubEngine->GetBytesPerSample();
iSubFormat.outputSampleRate = miSubEngine->GetSampleRate();
#if ABORT_PIPE_ON_START
if (mNeedToSync == FALSE && mLastClippedFrame == firstSampleFrame && 0x0 != miSubEngine->GetCurrentLoopCount ())
#else
if (mNeedToSync == FALSE && mLastClippedFrame == firstSampleFrame && 0xFFFFFFFF != miSubEngine->GetCurrentLoopCount ())
#endif
{
safetyOffset = miSubBufferOffset - ((iSubFormat.outputSampleRate) / 1000); if (safetyOffset < 0)
{
safetyOffset += iSubBufferLen;
}
if (miSubLoopCount == miSubEngine->GetCurrentLoopCount () && safetyOffset < (SInt32)(miSubEngine->GetCurrentByteCount () / 2))
{
#if DEBUGISUB
debugIOLog ("****iSub is in front of write head miSubBufferOffset = %ld, miSubEngine->GetCurrentByteCount () / 2 = %ld", miSubBufferOffset, miSubEngine->GetCurrentByteCount () / 2);
#endif
mNeedToSync = TRUE;
mStartiSub = TRUE;
}
else if (miSubLoopCount > (miSubEngine->GetCurrentLoopCount () + 1))
{
#if DEBUGISUB
debugIOLog ("****looped more than the iSub miSubLoopCount = %ld, miSubEngine->GetCurrentLoopCount () = %ld", miSubLoopCount, miSubEngine->GetCurrentLoopCount ());
#endif
mNeedToSync = TRUE;
mStartiSub = TRUE;
}
else if (miSubLoopCount < miSubEngine->GetCurrentLoopCount ())
{
#if DEBUGISUB
debugIOLog ("****iSub is ahead of us miSubLoopCount = %ld, miSubEngine->GetCurrentLoopCount () = %ld", miSubLoopCount, miSubEngine->GetCurrentLoopCount ());
#endif
mNeedToSync = TRUE;
mStartiSub = TRUE;
}
else if (miSubLoopCount == miSubEngine->GetCurrentLoopCount () && miSubBufferOffset > ((SInt32)((miSubEngine->GetCurrentByteCount() + (((iSubFormat.outputSampleRate)/1000 * NUM_ISUB_FRAME_LISTS_TO_QUEUE * NUM_ISUB_FRAMES_PER_LIST) * iSubFormat.bytesPerSample * iSubFormat.numChannels)) / 2)))
{
#if DEBUGISUB
debugIOLog ("****iSub is too far behind write head miSubBufferOffset = %ld, (miSubEngine->GetCurrentByteCount () / 2 + iSubBufferLen) = %ld", miSubBufferOffset, (miSubEngine->GetCurrentByteCount() / 2 + iSubBufferLen));
#endif
mNeedToSync = TRUE;
mStartiSub = TRUE;
}
}
if (FALSE == mNeedToSync && mLastClippedFrame != firstSampleFrame && !(mLastClippedFrame == getNumSampleFramesPerBuffer () && firstSampleFrame == 0))
{
#if DEBUGISUB
debugIOLog ("miSubBufferOffset was %ld", miSubBufferOffset);
#endif
if (firstSampleFrame < mLastClippedFrame)
{
offsetDelta = (getNumSampleFramesPerBuffer () - firstSampleFrame + mLastClippedFrame) * miSubEngine->GetNumChannels();
}
else
{
offsetDelta = (firstSampleFrame - mLastClippedFrame) * miSubEngine->GetNumChannels();
}
offsetDelta = (offsetDelta * 1000) / ((sampleRate * 1000) / iSubFormat.outputSampleRate);
miSubBufferOffset += offsetDelta;
#if DEBUGISUB
debugIOLog ("clip to point was %ld, now %ld (delta = %ld)", mLastClippedFrame, firstSampleFrame, offsetDelta);
debugIOLog ("miSubBufferOffset is now %ld", miSubBufferOffset);
#endif
if (miSubBufferOffset > (SInt32)iSubBufferLen)
{
miSubLoopCount += miSubBufferOffset / iSubBufferLen;
miSubBufferOffset = miSubBufferOffset % iSubBufferLen;
#if DEBUGISUB
debugIOLog ("miSubBufferOffset > iSubBufferLen, miSubBufferOffset is now %ld", miSubBufferOffset);
#endif
}
else if (miSubBufferOffset < 0)
{
miSubBufferOffset += iSubBufferLen;
#if DEBUGISUB
debugIOLog ("miSubBufferOffset < 0, miSubBufferOffset is now %ld", miSubBufferOffset);
#endif
}
}
if (TRUE == mJustResetClipPosition)
{
mJustResetClipPosition = FALSE;
mNeedToSync = FALSE;
mStartiSub = FALSE;
}
if ( (TRUE == mNeedToSync)
|| (miSubEngine->GetNeedToSync()))
{
mNeedToSync = FALSE;
miSubEngine->SetNeedToSync(false);
mSrcPhase = 1.0; mSrcState = 0.0;
mFilterState.xl_1 = 0.0;
mFilterState.xr_1 = 0.0;
mFilterState.xl_2 = 0.0;
mFilterState.xr_2 = 0.0;
mFilterState.yl_1 = 0.0;
mFilterState.yr_1 = 0.0;
mFilterState.yl_2 = 0.0;
mFilterState.yr_2 = 0.0;
mFilterState2.xl_1 = 0.0;
mFilterState2.xr_1 = 0.0;
mFilterState2.xl_2 = 0.0;
mFilterState2.xr_2 = 0.0;
mFilterState2.yl_1 = 0.0;
mFilterState2.yr_1 = 0.0;
mFilterState2.yl_2 = 0.0;
mFilterState2.yr_2 = 0.0;
mPhaseCompState.xl_1 = 0.0;
mPhaseCompState.xr_1 = 0.0;
mPhaseCompState.xl_2 = 0.0;
mPhaseCompState.xr_2 = 0.0;
mPhaseCompState.yl_1 = 0.0;
mPhaseCompState.yr_1 = 0.0;
mPhaseCompState.yl_2 = 0.0;
mPhaseCompState.yr_2 = 0.0;
#if ABORT_PIPE_ON_START
bzero(iSubBuffer, iSubBufferLen);
#endif
UInt32 curSampleFrame = getCurrentSampleFrame ();
if (firstSampleFrame < curSampleFrame)
{
offsetDelta = (getNumSampleFramesPerBuffer () - curSampleFrame + firstSampleFrame) * miSubEngine->GetNumChannels();
}
else
{
offsetDelta = (firstSampleFrame - curSampleFrame) * miSubEngine->GetNumChannels();
}
offsetDelta = (offsetDelta * 1000) / ((sampleRate * 1000) / iSubFormat.outputSampleRate);
miSubBufferOffset = offsetDelta;
#if DEBUGISUB
debugIOLog ("USBEngine: need sync: starting miSubBufferOffset = %ld, miSubLoopCount = %ld", miSubBufferOffset, miSubLoopCount);
#endif
}
if (miSubBufferOffset > (SInt32)iSubBufferLen)
{
mNeedToSync = TRUE;
miSubLoopCount += miSubBufferOffset / iSubBufferLen;
miSubBufferOffset = miSubBufferOffset % iSubBufferLen;
#if DEBUGISUB
debugIOLog ("miSubBufferOffset > iSubBufferLen, miSubBufferOffset is now %ld", miSubBufferOffset);
#endif
}
else if (miSubBufferOffset < 0)
{
miSubBufferOffset += iSubBufferLen;
#if DEBUGISUB
debugIOLog ("miSubBufferOffset < 0, miSubBufferOffset is now %ld", miSubBufferOffset);
#endif
}
if (appleUSBAudioStream->mPlugin)
{
appleUSBAudioStream->mPlugin->pluginProcess ((Float32*)mixBuf + (firstSampleFrame * streamFormat->fNumChannels), numSampleFrames, streamFormat->fNumChannels);
}
if (mPlugin)
{
mPlugin->pluginProcess ((Float32*)mixBuf + (firstSampleFrame * streamFormat->fNumChannels), numSampleFrames, streamFormat->fNumChannels);
}
result = clipAppleUSBAudioToOutputStreamiSub (mixBuf, sampleBuf, &mFilterState, &mFilterState2, &mPhaseCompState, mLowFreqSamples, mHighFreqSamples, firstSampleFrame, numSampleFrames, sampleRate, streamFormat, (SInt16*)iSubBuffer, &miSubLoopCount, &miSubBufferOffset, iSubBufferLen, &iSubFormat, &mSrcPhase, &mSrcState);
if (TRUE == mStartiSub)
{
miSubEngine->StartiSub ();
mStartiSub = FALSE;
miSubLoopCount = 0;
}
mLastClippedFrame = firstSampleFrame + numSampleFrames;
}
else
{
if (appleUSBAudioStream->mPlugin)
{
appleUSBAudioStream->mPlugin->pluginProcess ((Float32*)mixBuf + (firstSampleFrame * streamFormat->fNumChannels), numSampleFrames, streamFormat->fNumChannels);
}
if (mPlugin)
{
if (appleUSBAudioStream == mMainOutputStream)
{
mPlugin->pluginProcess ((Float32*)mixBuf + (firstSampleFrame * streamFormat->fNumChannels), numSampleFrames, streamFormat->fNumChannels);
}
}
result = clipAppleUSBAudioToOutputStream (mixBuf, sampleBuf, firstSampleFrame, numSampleFrames, streamFormat);
#if DEBUGLATENCY
if (!mHaveClipped)
{
mHaveClipped = true;
}
else if ((0 == firstSampleFrame) || true)
{
}
#endif
}
if (mUHCISupport)
{
UInt16 alternateFrameSize = appleUSBAudioStream->getAlternateFrameSize ();
UInt32 start = firstSampleFrame * streamFormat->fNumChannels * (streamFormat->fBitWidth / 8); if ( start < alternateFrameSize )
{
UInt32 size = alternateFrameSize - start;
memcpy( &( ( ( char * )sampleBuf )[ appleUSBAudioStream->mSampleBufferSize + start ] ), & ( ( ( char * )sampleBuf )[ start ] ), size );
#if DEBUGUHCI
debugIOLog( "? AppleUSBAudioEngine::clipOutputSamples () - firstSampleFrame = %d. Just copied %d bytes from %d to %d \n", firstSampleFrame, size, start, start + appleUSBAudioStream->mSampleBufferSize );
#endif
}
} }
else
{
UInt32 offset;
offset = firstSampleFrame * streamFormat->fNumChannels * (streamFormat->fBitWidth / 8);
memcpy ((UInt8 *)sampleBuf + offset, (UInt8 *)mixBuf, numSampleFrames * streamFormat->fNumChannels * (streamFormat->fBitWidth / 8));
mLastClippedFrame = firstSampleFrame + numSampleFrames;
result = kIOReturnSuccess;
}
Exit:
return result;
}
IOReturn AppleUSBAudioEngine::controlledFormatChange (IOAudioStream *audioStream, const IOAudioStreamFormat *newFormat, const IOAudioSampleRate *newSampleRate)
{
IOReturn result;
AUAConfigurationDictionary * configDictionary = NULL;
UInt32 numSamplesInBuffer;
bool needToChangeChannels;
bool forcedFormatChange = false;
AppleUSBAudioStream * appleUSBAudioStream;
OSDictionary * channelNamesDictionary = NULL;
debugIOLog ("+ AppleUSBAudioEngine[%p]::controlledFormatChange (%p, %p, %p)", this, audioStream, newFormat, newSampleRate);
result = kIOReturnError;
FailIf (NULL == mStreamInterfaceNumberArray, Exit);
FailIf (NULL == mUSBAudioDevice, Exit);
FailIf (NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary()), Exit);
if ( (newFormat == NULL)
&& (audioStream != NULL))
{
result = kIOReturnSuccess;
goto Exit;
}
if (NULL == audioStream)
{
forcedFormatChange = true;
audioStream = (NULL != mMainOutputStream) ? mMainOutputStream : mMainInputStream;
if (NULL == newFormat)
{
newFormat = &(audioStream->format);
}
}
FailIf (NULL == audioStream, Exit);
FailIf (NULL == newFormat, Exit);
appleUSBAudioStream = OSDynamicCast ( AppleUSBAudioStream, audioStream );
FailIf ( NULL == appleUSBAudioStream, Exit );
result = appleUSBAudioStream->controlledFormatChange ( newFormat, newSampleRate );
FailIf ( kIOReturnSuccess != result, Exit );
for (UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++)
{
AppleUSBAudioStream * stream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
FailIf ( NULL == stream, Exit );
if ( stream != appleUSBAudioStream )
{
stream->controlledFormatChange ( stream->getFormat (), newSampleRate );
}
}
if (newFormat->fNumChannels != audioStream->format.fNumChannels)
{
needToChangeChannels = TRUE;
debugIOLog ("? AppleUSBAudioEngine[%p]::controlledFormatChange () - Need to adjust channel controls (cur = %d, new = %d)", this, audioStream->format.fNumChannels, newFormat->fNumChannels);
if (kIOAudioStreamDirectionOutput == appleUSBAudioStream->getDirection ())
{
if (1 == newFormat->fNumChannels)
{
mUSBAudioDevice->setMonoState (TRUE);
}
else
{
mUSBAudioDevice->setMonoState (FALSE);
}
}
}
else
{
needToChangeChannels = FALSE;
}
if (newSampleRate)
{
debugIOLog ("? AppleUSBAudioEngine[%p]::controlledFormatChange () - Changing sampling rate to %d", this, newSampleRate->whole);
mCurSampleRate = *newSampleRate;
}
else
{
debugIOLog ("Keeping existing sampling rate of %d", mCurSampleRate.whole);
}
if ((appleUSBAudioStream == mMainOutputStream) || ((appleUSBAudioStream == mMainInputStream) && (NULL == mMainOutputStream)))
{
if (mPlugin)
{
mPlugin->pluginSetFormat (newFormat, &mCurSampleRate);
}
}
setNumSampleFramesPerBuffer (0);
mAverageSampleRate = mCurSampleRate.whole; debugIOLog ("mAverageSampleRate = %d", mAverageSampleRate);
numSamplesInBuffer = mAverageSampleRate / 4;
numSamplesInBuffer += (PAGE_SIZE*2 - 1);
numSamplesInBuffer /= PAGE_SIZE*2;
numSamplesInBuffer *= PAGE_SIZE*2;
debugIOLog("? AppleUSBAudioEngine[%p]::controlledFormatChange () - New numSamplesInBuffer = %d", this, numSamplesInBuffer );
setNumSampleFramesPerBuffer (numSamplesInBuffer);
if ( TRUE == needToChangeChannels )
{
beginConfigurationChange ();
channelNamesDictionary = OSDictionary::withCapacity ( 4 );
FailIf ( NULL == channelNamesDictionary, Exit );
setProperty ( kIOAudioEngineFullChannelNamesKey, channelNamesDictionary );
channelNamesDictionary->release ();
removeAllDefaultAudioControls ();
for (UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++)
{
AppleUSBAudioStream * stream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
if ( NULL != stream )
{
mUSBAudioDevice->createControlsForInterface (this, stream->mInterfaceNumber, stream->mAlternateSettingID);
}
}
if ( IP_VERSION_02_00 == mUSBAudioDevice->mControlInterface->GetInterfaceProtocol() )
{
doClockSelectorSetup ( appleUSBAudioStream->mInterfaceNumber, appleUSBAudioStream->mAlternateSettingID, mCurSampleRate.whole );
}
if (NULL != miSubAttachToggle)
{
addDefaultAudioControl (miSubAttachToggle);
}
completeConfigurationChange ();
}
if ( appleUSBAudioStream == mMainOutputStream )
{
if (NULL != miSubBufferMemory)
{
if (FALSE == isiSubCompatibleFormat (newFormat, mCurSampleRate))
{
debugIOLog ("! AppleUSBAudioEngine[%p]::controlledFormatChange () - Closing connection to iSub due to incompatible format", this);
iSubTeardownConnection ();
}
} else
{
if (miSubAttachToggle)
{
}
if (NULL != miSubAttachToggle && 1 == miSubAttachToggle->getIntValue ())
{
iSubAttachChangeCall (isiSubCompatibleFormat (newFormat, mCurSampleRate));
}
}
if ((IOAudioStreamDirection)kUSBOut == appleUSBAudioStream->getDirection () )
{
if (NULL != miSubBufferMemory)
{
if (NULL != mLowFreqSamples)
{
IOFreeAligned (mLowFreqSamples, mFreqSampleBufferSize); mLowFreqSamples = NULL;
}
if (NULL != mHighFreqSamples)
{
IOFreeAligned (mHighFreqSamples, mFreqSampleBufferSize); mHighFreqSamples = NULL;
}
mFreqSampleBufferSize = 0;
if ((2 == newFormat->fNumChannels) && ((8000 == mCurSampleRate.whole) || (11025 == mCurSampleRate.whole) || (22050 == mCurSampleRate.whole) ||
(44100 == mCurSampleRate.whole) || (48000 == mCurSampleRate.whole) || (96000 == mCurSampleRate.whole)))
{
mFreqSampleBufferSize = appleUSBAudioStream->mSampleBufferSize * 2;
mLowFreqSamples = (float *)IOMallocAligned (mFreqSampleBufferSize, PAGE_SIZE);
FailIf (NULL == mLowFreqSamples, Exit);
mHighFreqSamples = (float *)IOMallocAligned (mFreqSampleBufferSize, PAGE_SIZE);
FailIf (NULL == mHighFreqSamples, Exit);
}
}
}
}
debugIOLog ("? AppleUSBAudioEngine[%p]::controlledFormatChange () - Called setNumSampleFramesPerBuffer with %d", this, appleUSBAudioStream->mSampleBufferSize / (appleUSBAudioStream->mSampleSize ? appleUSBAudioStream->mSampleSize : 1));
debugIOLog ("? AppleUSBAudioEngine[%p]::controlledFormatChange () - newFormat->fNumChannels = %d, newFormat->fBitWidth %d", this, newFormat->fNumChannels, newFormat->fBitWidth);
result = kIOReturnSuccess;
Exit:
debugIOLog ("- AppleUSBAudioEngine[%p]::controlledFormatChange () = 0x%x", this, result);
return result;
}
IOReturn AppleUSBAudioEngine::convertInputSamples (const void *sampleBuf,
void *destBuf,
UInt32 firstSampleFrame,
UInt32 numSampleFrames,
const IOAudioStreamFormat *streamFormat,
IOAudioStream *audioStream) {
UInt32 lastSampleByte;
UInt32 windowStartByte;
UInt32 windowEndByte;
IOReturn coalescenceErrorCode = kIOReturnSuccess;
IOReturn result = kIOReturnSuccess;
AppleUSBAudioStream * appleUSBAudioStream;
#if DEBUGCONVERT
debugIOLog ("+ AppleUSBAudioEngine::convertInputSamples (%p, %p, %lu, %lu, %p, %p)", sampleBuf, destBuf, firstSampleFrame, numSampleFrames, streamFormat, audioStream);
#endif
appleUSBAudioStream = OSDynamicCast ( AppleUSBAudioStream, audioStream );
FailWithAction ( NULL == appleUSBAudioStream, result = kIOReturnError, Exit );
appleUSBAudioStream->queueInputFrames ();
#if 1 lastSampleByte = (firstSampleFrame + numSampleFrames) * streamFormat->fNumChannels * (streamFormat->fBitWidth / 8);
if (appleUSBAudioStream->mBufferOffset + 1 > appleUSBAudioStream->getSampleBufferSize ())
{
windowStartByte = 0;
}
else
{
windowStartByte = appleUSBAudioStream->mBufferOffset + 1;
}
windowEndByte = windowStartByte + (appleUSBAudioStream->mNumUSBFrameListsToQueue * appleUSBAudioStream->mReadUSBFrameListSize);
if (windowEndByte > appleUSBAudioStream->getSampleBufferSize ())
{
windowEndByte -= appleUSBAudioStream->getSampleBufferSize ();
}
if ((windowStartByte < lastSampleByte && windowEndByte > lastSampleByte) ||
(windowEndByte > lastSampleByte && windowStartByte > windowEndByte) ||
(windowStartByte < lastSampleByte && windowStartByte > windowEndByte && windowEndByte < lastSampleByte))
{
if (appleUSBAudioStream->mBufferOffset < lastSampleByte)
{
coalescenceErrorCode = appleUSBAudioStream->CoalesceInputSamples (lastSampleByte - appleUSBAudioStream->mBufferOffset, NULL);
#if DEBUGLOADING
debugIOLog ("! AppleUSBAudioEngine::convertInputSamples () - Coalesce from convert %d bytes", lastSampleByte - appleUSBAudioStream->mBufferOffset);
#endif
}
else
{
UInt32 numBytesToCoalesce = appleUSBAudioStream->getSampleBufferSize () - appleUSBAudioStream->mBufferOffset + lastSampleByte;
coalescenceErrorCode = appleUSBAudioStream->CoalesceInputSamples (numBytesToCoalesce, NULL);
#if DEBUGLOADING
debugIOLog ("! AppleUSBAudioEngine::convertInputSamples () - Coalesce from convert %d bytes (wrapping)", numBytesToCoalesce);
#endif
}
}
#endif
result = convertFromAppleUSBAudioInputStream_NoWrap (sampleBuf, destBuf, firstSampleFrame, numSampleFrames, streamFormat);
if (appleUSBAudioStream->mPlugin)
{
appleUSBAudioStream->mPlugin->pluginProcessInput ((float *)destBuf, numSampleFrames, streamFormat->fNumChannels);
}
if (mPlugin)
{
if (appleUSBAudioStream == mMainInputStream)
{
mPlugin->pluginProcessInput ((float *)destBuf, numSampleFrames, streamFormat->fNumChannels);
}
}
#if 0
if (0 == firstSampleFrame) {
debugIOLog("sample 0 converted on USB frame %llu", mUSBAudioDevice->getUSBFrameNumber());
}
#endif
Exit:
if ( kIOReturnSuccess != coalescenceErrorCode )
{
result = coalescenceErrorCode;
}
if ( kIOReturnSuccess != result )
{
debugIOLog ( "! AppleUSBAudioEngine::convertInputSamples () = 0x%x", result );
}
return result;
}
IOReturn AppleUSBAudioEngine::eraseOutputSamples(const void *mixBuf, void *sampleBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream)
{
super::eraseOutputSamples (mixBuf, sampleBuf, firstSampleFrame, numSampleFrames, streamFormat, audioStream);
if (mUHCISupport)
{
AppleUSBAudioStream * appleUSBAudioStream = OSDynamicCast ( AppleUSBAudioStream, audioStream );
FailIf ( NULL == appleUSBAudioStream, Exit );
if ( appleUSBAudioStream->getDirection () == kIOAudioStreamDirectionOutput )
{
UInt16 alternateFrameSize = appleUSBAudioStream->getAlternateFrameSize ();
UInt32 start = firstSampleFrame * streamFormat->fNumChannels * (streamFormat->fBitWidth / 8); if ( start < alternateFrameSize )
{
UInt32 size = alternateFrameSize - start;
bzero( &( ( ( char * )sampleBuf )[ appleUSBAudioStream->mSampleBufferSize + start ] ), size );
}
}
}
Exit:
return kIOReturnSuccess;
}
UInt32 AppleUSBAudioEngine::getCurrentSampleFrame () {
UInt32 currentSampleFrame;
currentSampleFrame = 0;
FailIf (NULL == mMainOutputStream && NULL == mMainInputStream, Exit);
if (mMainOutputStream)
{
currentSampleFrame = mMainOutputStream->getCurrentSampleFrame ();
}
else if (mMainInputStream)
{
currentSampleFrame = mMainInputStream->getCurrentSampleFrame ();
}
Exit:
return currentSampleFrame;
}
IOReturn AppleUSBAudioEngine::GetDefaultSampleRate (IOAudioSampleRate * sampleRate) {
IOReturn result = kIOReturnError;
UInt16 format;
UInt8 newAltSettingID;
UInt8 interfaceNumber;
IOAudioSampleRate newSampleRate;
AUAConfigurationDictionary * configDictionary = NULL;
UInt32 streamIndex;
OSNumber * streamInterfaceNumber;
bool foundSampleRate = false;
debugIOLog ("+ AppleUSBAudioEngine[%p]::GetDefaultSampleRate ()", this);
result = kIOReturnError;
FailIf (NULL == mStreamInterfaceNumberArray, Exit);
newSampleRate.whole = kDefaultSamplingRate;
newSampleRate.fraction = 0;
configDictionary = mUSBAudioDevice->getConfigDictionary ();
for ( streamIndex = 0; streamIndex < mStreamInterfaceNumberArray->getCount (); streamIndex++ )
{
result = kIOReturnError;
streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (streamIndex));
FailIf (NULL == streamInterfaceNumber, Exit);
interfaceNumber = streamInterfaceNumber->unsigned8BitValue();
result = configDictionary->getAltSettingWithSettings (&newAltSettingID, interfaceNumber, kChannelDepth_STEREO, kBitDepth_16bits, newSampleRate.whole);
if ( ( kIOReturnSuccess == result )
&& ( kIOReturnSuccess == configDictionary->getFormat( &format, interfaceNumber, newAltSettingID ) )
&& ( PCM == format ) )
{
foundSampleRate = true;
break;
}
}
if (!foundSampleRate)
{
for ( streamIndex = 0; streamIndex < mStreamInterfaceNumberArray->getCount (); streamIndex++ )
{
result = kIOReturnError;
streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (streamIndex));
FailIf (NULL == streamInterfaceNumber, Exit);
interfaceNumber = streamInterfaceNumber->unsigned8BitValue();
result = configDictionary->getAltSettingWithSettings (&newAltSettingID, interfaceNumber, kChannelDepth_MONO, kBitDepth_16bits, newSampleRate.whole);
if ( ( kIOReturnSuccess == result )
&& ( kIOReturnSuccess == configDictionary->getFormat( &format, interfaceNumber, newAltSettingID ) )
&& ( PCM == format ) )
{
foundSampleRate = true;
break;
}
}
}
if (!foundSampleRate)
{
for ( streamIndex = 0; streamIndex < mStreamInterfaceNumberArray->getCount (); streamIndex++ )
{
result = kIOReturnError;
streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (streamIndex));
FailIf (NULL == streamInterfaceNumber, Exit);
interfaceNumber = streamInterfaceNumber->unsigned8BitValue();
if ( ( kIOReturnSuccess == (result = configDictionary->getAltSettingWithSettings (&newAltSettingID, interfaceNumber, kChannelDepth_STEREO, kBitDepth_16bits ) ) )
&& ( kIOReturnSuccess == configDictionary->getFormat( &format, interfaceNumber, newAltSettingID )
&& ( PCM == format ) ) )
{
configDictionary->getHighestSampleRate (&(newSampleRate.whole), interfaceNumber, newAltSettingID);
foundSampleRate = true;
break;
}
}
}
if (!foundSampleRate)
{
for ( streamIndex = 0; streamIndex < mStreamInterfaceNumberArray->getCount (); streamIndex++ )
{
result = kIOReturnError;
streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (streamIndex));
FailIf (NULL == streamInterfaceNumber, Exit);
interfaceNumber = streamInterfaceNumber->unsigned8BitValue();
if ( ( kIOReturnSuccess == (result = configDictionary->getAltSettingWithSettings (&newAltSettingID, interfaceNumber, kChannelDepth_MONO, kBitDepth_16bits ) ) )
&& ( kIOReturnSuccess == configDictionary->getFormat( &format, interfaceNumber, newAltSettingID )
&& ( PCM == format ) ) )
{
configDictionary->getHighestSampleRate (&(newSampleRate.whole), interfaceNumber, newAltSettingID);
foundSampleRate = true;
break;
}
}
}
if (!foundSampleRate)
{
result = kIOReturnError;
streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (0));
FailIf (NULL == streamInterfaceNumber, Exit);
interfaceNumber = streamInterfaceNumber->unsigned8BitValue();
newAltSettingID = configDictionary->alternateSettingZeroCanStream (interfaceNumber) ? 0 : 1;
debugIOLog ("? AppleUSBAudioEngine[%p]::GetDefaultSampleRate () - Taking first available alternate setting (%d)", this, newAltSettingID);
FailIf (kIOReturnSuccess != (result = configDictionary->getHighestSampleRate (&(newSampleRate.whole), interfaceNumber, newAltSettingID)), Exit);
}
debugIOLog ("? AppleUSBAudioEngine[%p]::GetDefaultSampleRate () - Default sample rate is %d", this, newSampleRate.whole);
debugIOLog ("? AppleUSBAudioEngine[%p]::GetDefaultSampleRate () - Default alternate setting ID is %d", this, newAltSettingID);
FailIf (0 == newSampleRate.whole, Exit);
*sampleRate = newSampleRate;
result = kIOReturnSuccess;
Exit:
debugIOLog ("- AppleUSBAudioEngine[%p]::GetDefaultSampleRate (%lu) = 0x%x", this, sampleRate->whole, result);
return result;
}
OSString * AppleUSBAudioEngine::getGlobalUniqueID () {
char * uniqueIDStr;
OSString * localID;
OSString * uniqueID;
OSNumber * usbLocation;
IOReturn err;
UInt32 uniqueIDSize;
UInt32 locationID;
UInt8 stringIndex;
UInt8 interfaceNumber;
char productString[kStringBufferSize];
char manufacturerString[kStringBufferSize];
char serialNumberString[kStringBufferSize];
char locationIDString[kStringBufferSize];
char interfaceNumberString[4]; OSObject * nameObject = NULL;
OSString * nameString = NULL;
usbLocation = NULL;
uniqueIDStr = NULL;
localID = NULL;
uniqueID = NULL;
FailIf (NULL == mUSBAudioDevice, Exit);
FailIf (NULL == mUSBAudioDevice->mControlInterface, Exit);
uniqueIDSize = 5; uniqueIDSize += strlen ("AppleUSBAudioEngine");
err = kIOReturnSuccess;
manufacturerString[0] = 0;
nameObject = mUSBAudioDevice->mControlInterface->GetDevice ()->getProperty ( "USB Vendor Name" );
if ( nameObject )
{
if ( NULL != ( nameString = OSDynamicCast ( OSString, nameObject ) ) )
{
debugIOLog ( "? AppleUSBAudioEngine[%p]::getGlobalUniqueID () - Retrieved vendor name %s from registry", this, nameString->getCStringNoCopy () );
strncpy ( manufacturerString, nameString->getCStringNoCopy (), kStringBufferSize );
err = kIOReturnSuccess;
}
}
else
{
stringIndex = mUSBAudioDevice->getManufacturerStringIndex ();
if (0 != stringIndex)
{
err = mUSBAudioDevice->getStringDescriptor (stringIndex, manufacturerString, kStringBufferSize);
}
}
if (0 == manufacturerString[0] || kIOReturnSuccess != err)
{
strncpy (manufacturerString, "Unknown Manufacturer", kStringBufferSize);
}
uniqueIDSize += strlen (manufacturerString);
err = kIOReturnSuccess;
productString[0] = 0;
nameObject = mUSBAudioDevice->mControlInterface->GetDevice ()->getProperty ( "USB Product Name" );
if ( nameObject )
{
if ( NULL != ( nameString = OSDynamicCast ( OSString, nameObject ) ) )
{
debugIOLog ( "? AppleUSBAudioEngine[%p]::getGlobalUniqueID () - Retrieved product name %s from registry", this, nameString->getCStringNoCopy () );
strncpy ( productString, nameString->getCStringNoCopy (), kStringBufferSize );
err = kIOReturnSuccess;
}
}
else
{
stringIndex = mUSBAudioDevice->getProductStringIndex ();
if (0 != stringIndex)
{
err = mUSBAudioDevice->getStringDescriptor (stringIndex, productString, kStringBufferSize);
}
}
if (0 == productString[0] || kIOReturnSuccess != err)
{
strncpy (productString, "Unknown USB Audio Device", kStringBufferSize);
}
uniqueIDSize += strlen (productString);
stringIndex = 0;
err = kIOReturnSuccess;
serialNumberString[0] = 0;
nameObject = mUSBAudioDevice->mControlInterface->GetDevice ()->getProperty ( "USB Serial Number" );
if ( nameObject )
{
if ( NULL != ( nameString = OSDynamicCast ( OSString, nameObject ) ) )
{
debugIOLog ( "? AppleUSBAudioEngine[%p]::getGlobalUniqueID () - Retrieved serial number %s from registry", this, nameString->getCStringNoCopy () );
strncpy ( serialNumberString, nameString->getCStringNoCopy (), kStringBufferSize );
err = kIOReturnSuccess;
}
}
else
{
stringIndex = mUSBAudioDevice->getSerialNumberStringIndex ();
if (0 != stringIndex)
{
err = mUSBAudioDevice->getStringDescriptor (stringIndex, serialNumberString, kStringBufferSize);
}
}
if (0 == serialNumberString[0] || kIOReturnSuccess != err)
{
usbLocation = mUSBAudioDevice->getLocationID ();
if (NULL != usbLocation)
{
locationID = usbLocation->unsigned32BitValue ();
snprintf (locationIDString, kStringBufferSize, "%x", locationID);
}
else
{
strncpy (locationIDString, "Unknown location", kStringBufferSize);
}
uniqueIDSize += strlen (locationIDString);
}
else
{
debugIOLog ("? AppleUSBAudioEngine[%p]::getGlobalUniqueID () - Device has a serial number = %s", this, serialNumberString);
uniqueIDSize += strlen (serialNumberString);
}
if ( mStreamInterfaceNumberArray->getCount () == 1 )
{
OSNumber * streamInterfaceNumber = OSDynamicCast ( OSNumber, mStreamInterfaceNumberArray->getObject (0) );
if (NULL != streamInterfaceNumber)
{
interfaceNumber = streamInterfaceNumber->unsigned8BitValue ();
snprintf (interfaceNumberString, 4, "%d", interfaceNumber);
uniqueIDSize += strlen (interfaceNumberString);
}
}
uniqueIDStr = (char *)IOMalloc (uniqueIDSize);
if (NULL != uniqueIDStr)
{
uniqueIDStr[0] = 0;
if (0 == serialNumberString[0])
{
snprintf (uniqueIDStr, uniqueIDSize, "AppleUSBAudioEngine:%s:%s:%s", manufacturerString, productString, locationIDString);
}
else
{
snprintf (uniqueIDStr,uniqueIDSize, "AppleUSBAudioEngine:%s:%s:%s", manufacturerString, productString, serialNumberString);
}
if ( mStreamInterfaceNumberArray->getCount () == 1 )
{
strncat ( uniqueIDStr, ":", 1 );
strncat ( uniqueIDStr, interfaceNumberString, 4 );
}
uniqueID = OSString::withCString (uniqueIDStr);
debugIOLog ("AppleUSBAudioEngine[%p]::getGlobalUniqueID () - getGlobalUniqueID = %s", this, uniqueIDStr);
IOFree (uniqueIDStr, uniqueIDSize);
}
Exit:
return uniqueID;
}
bool AppleUSBAudioEngine::initHardware (IOService *provider) {
OSNumber * idVendor = NULL;
OSNumber * idProduct = NULL;
AUAConfigurationDictionary * configDictionary;
IOReturn resultCode;
Boolean resultBool;
OSObject * nameObject = NULL;
OSString * nameString = NULL;
OSString * coreAudioPluginPathString = NULL;
char * streamDescription = NULL;
bool syncOutputCompensation = false; bool syncInputCompensation = false; AppleUSBAudioStream * masterStream = NULL;
OSDictionary * channelNamesDictionary = NULL; OSObject * propertiesReadyObject = NULL; UInt32 numTriesForStreamPropertiesReady;
debugIOLog ("+ AppleUSBAudioEngine[%p]::initHardware (%p)", this, provider);
resultBool = FALSE;
mTerminatingDriver = FALSE;
FailIf (FALSE == super::initHardware (provider), Exit);
FailIf (NULL == mStreamInterfaceNumberArray, Exit);
FailIf (NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary ()), Exit);
GetDefaultSampleRate (&sampleRate);
mCurSampleRate = sampleRate;
mUHCISupport = mUSBAudioDevice->checkForUHCI ();
mSplitTransactions = mUSBAudioDevice->detectSplitTransactions ();
setSampleRate (&sampleRate);
mDefaultAudioSampleRate = sampleRate;
channelNamesDictionary = OSDictionary::withCapacity ( 4 );
FailIf ( NULL == channelNamesDictionary, Exit );
setProperty ( kIOAudioEngineFullChannelNamesKey, channelNamesDictionary );
channelNamesDictionary->release ();
mStartInputChannelID = 1;
mStartOutputChannelID = 1;
for ( UInt32 streamIndex = 0; streamIndex < mStreamInterfaceNumberArray->getCount (); streamIndex++ )
{
OSNumber * streamInterfaceNumber = OSDynamicCast (OSNumber, mStreamInterfaceNumberArray->getObject (streamIndex) );
FailIf (NULL == streamInterfaceNumber, Exit);
IOUSBInterface * streamInterface = mUSBAudioDevice->getUSBInterface (streamInterfaceNumber->unsigned8BitValue ());
FailIf (NULL == streamInterface, Exit);
propertiesReadyObject = NULL;
for ( numTriesForStreamPropertiesReady = 0; numTriesForStreamPropertiesReady < kMaxTriesForStreamPropertiesReady; numTriesForStreamPropertiesReady++ )
{
propertiesReadyObject = streamInterface->getProperty ( "AppleUSBAudioStreamPropertiesReady" );
if ( propertiesReadyObject )
{
debugIOLog ( "! AppleUSBAudioStream[%p]::initHardware () - AppleUSBAudioStreamPropertiesReady found for stream #%d", this, streamInterfaceNumber->unsigned8BitValue () );
break;
}
debugIOLog ( "! AppleUSBAudioStream[%p]::initHardware () - AppleUSBAudioStreamPropertiesReady NOT found for stream #%d, sleeping 10 ms...", this, streamInterfaceNumber->unsigned8BitValue () );
IOSleep ( 10 );
FailIf ( mUSBAudioDevice->isInactive (), Exit );
}
AppleUSBAudioStream * audioStream = OSTypeAlloc ( AppleUSBAudioStream );
FailIf (NULL == audioStream, Exit);
if ( mStreamInterfaceNumberArray->getCount () > 1 )
{
nameObject = streamInterface->getProperty ( "USB Interface Name" );
if ( nameObject )
{
if ( NULL != ( nameString = OSDynamicCast ( OSString, nameObject ) ) )
{
debugIOLog ( "! AppleUSBAudioStream[%p]::initHardware () - Retrieved product name %s", this, nameString->getCStringNoCopy () );
streamDescription = (char *)nameString->getCStringNoCopy();
}
}
}
FailWithAction (!audioStream->initWithAudioEngine (mUSBAudioDevice, this, streamInterface, sampleRate, streamDescription), audioStream->release(), Exit);
mIOAudioStreamArray->setObject ( audioStream );
if (kIOAudioStreamDirectionOutput == audioStream->getDirection ())
{
if (NULL == mMainOutputStream)
{
mMainOutputStream = audioStream;
}
else
{
if ( kAdaptiveSyncType == audioStream->getSyncType () )
{
mMainOutputStream = audioStream;
}
}
}
if (NULL == mMainInputStream && kIOAudioStreamDirectionInput == audioStream->getDirection ())
{
mMainInputStream = audioStream;
}
FailWithAction (!audioStream->configureAudioStream (sampleRate), audioStream->release(), Exit);
FailWithAction (kIOReturnSuccess != (resultCode = addAudioStream (audioStream)), audioStream->release(), Exit);
if ( kIOAudioStreamDirectionOutput == audioStream->getDirection () )
{
mStartOutputChannelID += audioStream->getFormat ()->fNumChannels;
}
else
{
mStartInputChannelID += audioStream->getFormat ()->fNumChannels;
}
audioStream->release ();
}
if ( ( NULL != mMainOutputStream ) && ( kAdaptiveSyncType == mMainOutputStream->getSyncType () ) )
{
masterStream = mMainOutputStream;
debugIOLog ("? AppleUSBAudioEngine[%p]::initHardware (%p) - Main output stream (%p) is adaptive and designated as master", this, provider, mMainOutputStream);
}
else
{
if ( NULL != mMainInputStream )
{
masterStream = mMainInputStream;
}
else
{
masterStream = mMainOutputStream;
}
if ( 1 < mIOAudioStreamArray->getCount () )
{
syncOutputCompensation = true;
}
}
FailIf ( NULL == masterStream, Exit );
masterStream->setMasterStreamMode ( true );
debugIOLog ("? AppleUSBAudioEngine[%p]::initHardware (%p) - Compensate for output synchronization: %d", this, provider, syncOutputCompensation);
if ( syncOutputCompensation )
{
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast ( AppleUSBAudioStream, mIOAudioStreamArray->getObject ( streamIndex ) );
if ( NULL != audioStream && kIOAudioStreamDirectionOutput == audioStream->getDirection () )
{
audioStream->compensateForSynchronization ( true );
audioStream->updateSampleOffsetAndLatency ();
}
}
}
debugIOLog ("? AppleUSBAudioEngine[%p]::initHardware (%p) - Compensate for input synchronization: %d", this, provider, syncInputCompensation);
if ( syncInputCompensation )
{
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast ( AppleUSBAudioStream, mIOAudioStreamArray->getObject ( streamIndex ) );
if ( NULL != audioStream && kIOAudioStreamDirectionInput == audioStream->getDirection () )
{
audioStream->compensateForSynchronization ( true );
audioStream->updateSampleOffsetAndLatency ();
}
}
}
miSubBufferMemory = NULL;
miSubEngine = NULL;
if (NULL != mMainOutputStream)
{
miSubAttachToggle = IOAudioToggleControl::create (FALSE,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
0,
kIOAudioToggleControlSubTypeiSubAttach,
kIOAudioControlUsageOutput);
if (NULL != miSubAttachToggle)
{
miSubAttachToggle->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)iSubAttachChangeHandler, this);
miSubAttachToggle->flushValue ();
beginConfigurationChange ();
addDefaultAudioControl (miSubAttachToggle);
completeConfigurationChange ();
}
}
if ( mIOAudioStreamArray->getCount () > 1 )
{
nameObject = mUSBAudioDevice->mControlInterface->getProperty ( "USB Interface Name" );
}
else
{
if ((NULL != mMainOutputStream) && (NULL != mMainOutputStream->mStreamInterface))
{
nameObject = mMainOutputStream->mStreamInterface->getProperty ( "USB Interface Name" );
}
else if ((NULL != mMainInputStream) && (NULL != mMainInputStream->mStreamInterface))
{
nameObject = mMainInputStream->mStreamInterface->getProperty ( "USB Interface Name" );
}
}
if ( nameObject )
{
if ( NULL != ( nameString = OSDynamicCast ( OSString, nameObject ) ) )
{
debugIOLog ( "! AppleUSBAudioEngine[%p]::initHardware () - Retrieved product name %s", this, nameString->getCStringNoCopy () );
setDescription ( nameString->getCStringNoCopy() );
}
}
if ( mIOAudioStreamArray->getCount () > 1 )
{
coreAudioPluginPathString = OSDynamicCast ( OSString, mUSBAudioDevice->mControlInterface->getProperty ( kIOAudioEngineCoreAudioPlugInKey ) );
}
if (NULL == coreAudioPluginPathString)
{
if ((NULL != mMainOutputStream) && (NULL != mMainOutputStream->mStreamInterface))
{
coreAudioPluginPathString = OSDynamicCast ( OSString, mMainOutputStream->mStreamInterface->getProperty ( kIOAudioEngineCoreAudioPlugInKey ) );
}
else if ((NULL != mMainInputStream) && (NULL != mMainInputStream->mStreamInterface))
{
coreAudioPluginPathString = OSDynamicCast ( OSString, mMainInputStream->mStreamInterface->getProperty ( kIOAudioEngineCoreAudioPlugInKey ) );
}
}
if (NULL == coreAudioPluginPathString)
{
coreAudioPluginPathString = OSDynamicCast ( OSString, mUSBAudioDevice->mControlInterface->getProperty ( kIOAudioEngineCoreAudioPlugInKey ) );
}
if (NULL != coreAudioPluginPathString)
{
debugIOLog ( "! AppleUSBAudioEngine[%p]::initHardware () - Retrieved CoreAudio plugin path %s", this, coreAudioPluginPathString->getCStringNoCopy () );
setProperty ( kIOAudioEngineCoreAudioPlugInKey, coreAudioPluginPathString );
}
resultBool = TRUE;
idVendor = OSNumber::withNumber (mUSBAudioDevice->getVendorID (), 16);
if (NULL != idVendor)
{
setProperty (kIDVendorString, idVendor);
idVendor->release ();
}
idProduct = OSNumber::withNumber (mUSBAudioDevice->getProductID (), 16);
if (NULL != idProduct)
{
setProperty (kIDProductString, idProduct);
idProduct->release ();
}
Exit:
if ( !resultBool )
{
stop ( provider );
}
debugIOLog("- AppleUSBAudioEngine[%p]::initHardware(%p), resultCode = %x, resultBool = %d", this, provider, resultCode, resultBool);
return resultBool;
}
OSString * AppleUSBAudioEngine::getChannelNameString ( UInt8 inputTerminalID, UInt8 channelNum )
{
AUAConfigurationDictionary * configDictionary = NULL;
UInt8 controlInterfaceNum;
AudioClusterDescriptor clusterDescriptor;
UInt8 numPreDefinedChannels = 0;
char stringBuffer[kStringBufferSize];
IOReturn result = kIOReturnNotFound;
OSString * theString = NULL;
FailIf ( NULL == mUSBAudioDevice, Exit );
controlInterfaceNum = mUSBAudioDevice->mControlInterface->GetInterfaceNumber();
FailIf (NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary()), Exit);
FailIf ( kIOReturnSuccess != configDictionary->getAudioClusterDescriptor ( &clusterDescriptor, controlInterfaceNum, 0, inputTerminalID ), Exit );
debugIOLog ("? AppleUSBAudioEngine[%p]::getChannelNameString (%d, %d) - Audio cluster descriptor { %d, %d, %d }", this, inputTerminalID, channelNum, clusterDescriptor.bNrChannels, clusterDescriptor.bmChannelConfig, clusterDescriptor.iChannelNames);
for ( UInt8 channelIndex = 0; channelIndex < sizeof ( UInt32 ); channelIndex++ )
{
if ( clusterDescriptor.bmChannelConfig & ( 1 << channelIndex ) )
{
numPreDefinedChannels++;
}
if ( numPreDefinedChannels == channelNum )
{
strncpy ( stringBuffer, ChannelConfigString ( channelIndex ), kStringBufferSize );
result = kIOReturnSuccess;
break;
}
}
if ( ( numPreDefinedChannels != channelNum ) && ( channelNum <= clusterDescriptor.bNrChannels ) )
{
if ( 0 != clusterDescriptor.iChannelNames )
{
result = mUSBAudioDevice->getStringDescriptor ( clusterDescriptor.iChannelNames + channelNum - 1 - numPreDefinedChannels, stringBuffer, kStringBufferSize );
debugIOLog ("? AppleUSBAudioDevice::getChannelNameString (%d, %d) - stringIndex = %d, stringBuffer = %s, result = 0%x", inputTerminalID, channelNum, clusterDescriptor.iChannelNames + channelNum - 1 - numPreDefinedChannels, stringBuffer, result);
}
}
if ( kIOReturnSuccess == result )
{
debugIOLog ("? AppleUSBAudioDevice::getChannelNameString () - terminalID = %d, channelNum = %d, stringBuffer = %s", inputTerminalID, channelNum, stringBuffer);
theString = OSString::withCString ( stringBuffer );
}
Exit:
return theString;
}
void AppleUSBAudioEngine::updateChannelNames ( UInt8 inputTerminalID, UInt8 interfaceNum, UInt8 altSettingNum ) {
OSDictionary * oldChannelNamesDictionary = NULL; OSDictionary * newChannelNamesDictionary = NULL; AUAConfigurationDictionary * configDictionary = NULL;
UInt8 controlInterfaceNum;
char keyString[32];
OSString * nameString = NULL;
AudioClusterDescriptor clusterDescriptor;
debugIOLog ("+ AppleUSBAudioEngine[%p]::updateChannelNames (%d, %d, %d)", this, inputTerminalID, interfaceNum, altSettingNum);
FailIf ( NULL == mUSBAudioDevice, Exit );
controlInterfaceNum = mUSBAudioDevice->mControlInterface->GetInterfaceNumber();
FailIf (NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary()), Exit);
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast ( AppleUSBAudioStream, mIOAudioStreamArray->getObject ( streamIndex ) );
if ( NULL != audioStream && interfaceNum == audioStream->mInterfaceNumber && altSettingNum == audioStream->mAlternateSettingID )
{
debugIOLog ("? AppleUSBAudioEngine[%p]::updateChannelNames (%d, %d, %d) - Found audio stream = %p", this, inputTerminalID, interfaceNum, altSettingNum, audioStream);
oldChannelNamesDictionary = OSDynamicCast ( OSDictionary, getProperty ( kIOAudioEngineFullChannelNamesKey ) );
FailIf ( NULL == oldChannelNamesDictionary, Exit );
newChannelNamesDictionary = OSDictionary::withDictionary ( oldChannelNamesDictionary );
FailIf ( NULL == newChannelNamesDictionary, Exit );
FailIf ( kIOReturnSuccess != configDictionary->getAudioClusterDescriptor ( &clusterDescriptor, controlInterfaceNum, 0, inputTerminalID ), Exit );
debugIOLog ("? AppleUSBAudioEngine[%p]::updateChannelNames (%d, %d, %d) - Audio cluster descriptor { %d, %d, %d }", this, inputTerminalID, interfaceNum, altSettingNum, clusterDescriptor.bNrChannels, clusterDescriptor.bmChannelConfig, clusterDescriptor.iChannelNames);
for ( UInt8 channelIndex = 0; channelIndex < clusterDescriptor.bNrChannels; channelIndex++ )
{
nameString = getChannelNameString ( inputTerminalID, channelIndex + 1 );
if ( NULL != nameString )
{
keyString[0] = 0;
if ( kIOAudioStreamDirectionOutput == audioStream->getDirection () )
{
snprintf ( keyString, 32, kIOAudioEngineFullChannelNameKeyOutputFormat, audioStream->getStartingChannelID () + channelIndex );
}
else
{
snprintf ( keyString, 32, kIOAudioEngineFullChannelNameKeyInputFormat, audioStream->getStartingChannelID () + channelIndex );
}
debugIOLog ("? AppleUSBAudioEngine[%p]::updateChannelNames (%d, %d, %d) - Setting %s to %s", this, inputTerminalID, interfaceNum, altSettingNum, keyString, nameString->getCStringNoCopy());
newChannelNamesDictionary->setObject ( keyString, nameString ); nameString->release ();
}
}
setProperty ( kIOAudioEngineFullChannelNamesKey, newChannelNamesDictionary );
newChannelNamesDictionary->release ();
break;
}
}
Exit:
debugIOLog ("- AppleUSBAudioEngine[%p]::updateChannelNames (%d, %d, %d)", this, inputTerminalID, interfaceNum, altSettingNum);
return;
}
char * AppleUSBAudioEngine::ChannelConfigString (UInt8 channel)
{
char * channelNameString;
switch (channel) {
#if LOCALIZABLE
case 0: channelNameString = (char*)"StringFrontLeft"; break;
case 1: channelNameString = (char*)"StringFrontRight"; break;
case 2: channelNameString = (char*)"StringFrontCenter"; break;
case 3: channelNameString = (char*)"StringLowFrequencyEffects"; break;
case 4: channelNameString = (char*)"StringBackLeft"; break;
case 5: channelNameString = (char*)"StringBackRight"; break;
case 6: channelNameString = (char*)"StringFrontLeftofCenter"; break;
case 7: channelNameString = (char*)"StringFrontRightofCenter"; break;
case 8: channelNameString = (char*)"StringBackCenter"; break;
case 9: channelNameString = (char*)"StringSideLeft"; break;
case 10: channelNameString = (char*)"StringSideRight"; break;
case 11: channelNameString = (char*)"StringTopCenter"; break;
case 12: channelNameString = (char*)"StringTopFrontLeft"; break;
case 13: channelNameString = (char*)"StringTopFrontCenter"; break;
case 14: channelNameString = (char*)"StringTopFrontRight"; break;
case 15: channelNameString = (char*)"StringTopBackLeft"; break;
case 16: channelNameString = (char*)"StringTopBackCenter"; break;
case 17: channelNameString = (char*)"StringTopBackRight"; break;
case 18: channelNameString = (char*)"StringTopFrontLeftofCenter"; break;
case 19: channelNameString = (char*)"StringTopFrontRightofCenter"; break;
case 20: channelNameString = (char*)"StringLeftLowFrequencyEffects"; break;
case 21: channelNameString = (char*)"StringRightLowFrequencyEffects"; break;
case 22: channelNameString = (char*)"StringTopSideLeft"; break;
case 23: channelNameString = (char*)"StringTopSideRight"; break;
case 24: channelNameString = (char*)"StringBottomCenter"; break;
case 25: channelNameString = (char*)"StringBackLeftofCenter"; break;
case 26: channelNameString = (char*)"StringBackRightofCenter"; break;
case 27:
case 28:
case 29:
case 30: channelNameString = (char*)"StringReserved"; break;
case 31: channelNameString = (char*)"StringRawData"; break;
default: channelNameString = (char*)"StringUnknown"; break;
#else
case 0: channelNameString = (char*)"Front Left"; break;
case 1: channelNameString = (char*)"Front Right"; break;
case 2: channelNameString = (char*)"Front Center"; break;
case 3: channelNameString = (char*)"Low Frequency Effects"; break;
case 4: channelNameString = (char*)"Back Left"; break;
case 5: channelNameString = (char*)"Back Right"; break;
case 6: channelNameString = (char*)"Front Left of Center"; break;
case 7: channelNameString = (char*)"Front Right of Center"; break;
case 8: channelNameString = (char*)"Back Center"; break;
case 9: channelNameString = (char*)"Side Left"; break;
case 10: channelNameString = (char*)"Side Right"; break;
case 11: channelNameString = (char*)"Top Center"; break;
case 12: channelNameString = (char*)"Top Front Left"; break;
case 13: channelNameString = (char*)"Top Front Center"; break;
case 14: channelNameString = (char*)"Top Front Right"; break;
case 15: channelNameString = (char*)"Top Back Left"; break;
case 16: channelNameString = (char*)"Top Back Center"; break;
case 17: channelNameString = (char*)"Top Back Right"; break;
case 18: channelNameString = (char*)"Top Front Left of Center"; break;
case 19: channelNameString = (char*)"Top Front Right of Center"; break;
case 20: channelNameString = (char*)"Left Low Frequency Effects"; break;
case 21: channelNameString = (char*)"Right Low Frequency Effects"; break;
case 22: channelNameString = (char*)"Top Side Left"; break;
case 23: channelNameString = (char*)"Top Side Right"; break;
case 24: channelNameString = (char*)"Bottom Center"; break;
case 25: channelNameString = (char*)"Back Left of Center"; break;
case 26: channelNameString = (char*)"Back Right of Center"; break;
case 27:
case 28:
case 29:
case 30: channelNameString = (char*)"Reserved"; break;
case 31: channelNameString = (char*)"Raw Data"; break;
default: channelNameString = (char*)"Unknown"; break;
#endif
}
return channelNameString;
}
void AppleUSBAudioEngine::registerPlugin (AppleUSBAudioPlugin * thePlugin) {
mPlugin = thePlugin;
mPluginInitThread = thread_call_allocate ((thread_call_func_t)pluginLoaded, (thread_call_param_t)this);
if (NULL != mPluginInitThread)
{
thread_call_enter (mPluginInitThread);
}
}
void AppleUSBAudioEngine::pluginLoaded (AppleUSBAudioEngine * usbAudioEngineObject) {
IOReturn result;
FailIf ( (NULL == usbAudioEngineObject->mMainOutputStream) && (NULL == usbAudioEngineObject->mMainInputStream), Exit );
if (usbAudioEngineObject->mPlugin && (usbAudioEngineObject->mMainOutputStream->mStreamInterface || usbAudioEngineObject->mMainInputStream->mStreamInterface))
{
usbAudioEngineObject->mPlugin->open (usbAudioEngineObject);
result = usbAudioEngineObject->mPlugin->pluginInit (usbAudioEngineObject, usbAudioEngineObject->mUSBAudioDevice->getVendorID (), usbAudioEngineObject->mUSBAudioDevice->getProductID ());
if (result == kIOReturnSuccess)
{
debugIOLog ("success initing the plugin");
if (usbAudioEngineObject->mMainOutputStream)
{
usbAudioEngineObject->mPlugin->pluginSetDirection ((IOAudioStreamDirection) kIOAudioStreamDirectionOutput);
usbAudioEngineObject->mPlugin->pluginSetFormat (usbAudioEngineObject->mMainOutputStream->getFormat (), &usbAudioEngineObject->sampleRate);
}
else if (usbAudioEngineObject->mMainInputStream)
{
usbAudioEngineObject->mPlugin->pluginSetDirection ((IOAudioStreamDirection) kIOAudioStreamDirectionInput);
usbAudioEngineObject->mPlugin->pluginSetFormat (usbAudioEngineObject->mMainInputStream->getFormat (), &usbAudioEngineObject->sampleRate);
}
}
else
{
debugIOLog ("Error initing the plugin");
usbAudioEngineObject->mPlugin->close (usbAudioEngineObject);
usbAudioEngineObject->mPlugin = NULL;
}
if (NULL != usbAudioEngineObject->mPluginNotification)
{
usbAudioEngineObject->mPluginNotification->remove ();
usbAudioEngineObject->mPluginNotification = NULL;
}
}
Exit:
return;
}
IOReturn AppleUSBAudioEngine::pluginDeviceRequest (IOUSBDevRequest * request, IOUSBCompletion * completion) {
IOReturn result;
result = kIOReturnBadArgument;
if (request)
{
result = mUSBAudioDevice->deviceRequest (request, mUSBAudioDevice, completion);
}
return result;
}
void AppleUSBAudioEngine::pluginSetConfigurationApp (const char * bundleID) {
if (bundleID)
{
mUSBAudioDevice->setConfigurationApp (bundleID);
}
}
IOReturn AppleUSBAudioEngine::iSubAttachChangeHandler (IOService *target, IOAudioControl *theControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
AppleUSBAudioEngine * audioEngine;
debugIOLog ("+ AppleUSBAudioEngine::iSubAttachChangeHandler (%p, %p, %ld, %ld)", target, theControl, oldValue, newValue);
result = kIOReturnSuccess;
audioEngine = OSDynamicCast (AppleUSBAudioEngine, target);
FailIf (NULL == audioEngine, Exit);
FailIf (NULL == audioEngine->mMainOutputStream, Exit);
if ( (newValue)
&& (!oldValue) && (audioEngine->isiSubCompatibleFormat (audioEngine->mMainOutputStream->getFormat (), audioEngine->sampleRate))) {
if (NULL == audioEngine->miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeHandler () - Adding miSubEngineNotifier ...");
audioEngine->miSubEngineNotifier = addNotification (gIOPublishNotification, serviceMatching ("AppleiSubEngine"), (IOServiceNotificationHandler)&iSubEnginePublished, audioEngine);
if (NULL != audioEngine->miSubBufferMemory)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeHandler () - Removing miSubEngineNotifier because notifier was already called ...");
audioEngine->miSubEngineNotifier->remove ();
audioEngine->miSubEngineNotifier = NULL;
}
}
else
{
debugIOLog ("! AppleUSBAudioEngine::iSubAttachChangeHandler () - There is already a notifier @ 0x%x!", audioEngine->miSubEngineNotifier);
}
}
else if (oldValue != newValue) {
if (NULL != audioEngine->miSubBufferMemory && NULL != audioEngine->miSubEngine)
{
audioEngine->iSubTeardownConnection ();
}
if (NULL != audioEngine->miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeHandler () - Removing miSubEngineNotifier because iSub was detached ...");
audioEngine->miSubEngineNotifier->remove ();
audioEngine->miSubEngineNotifier = NULL;
}
}
Exit:
debugIOLog("- AppleUSBAudioEngine::iSubAttachChangeHandler ()");
return result;
}
IOReturn AppleUSBAudioEngine::iSubAttachChangeCall (Boolean isiSubCompatible) {
IOReturn result;
debugIOLog ("+ AppleUSBAudioEngine[%p]::iSubAttachChangeCall (%d)", this, isiSubCompatible);
result = kIOReturnSuccess;
if (isiSubCompatible)
{
if (NULL == miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeCall () - Adding miSubEngineNotifier ...");
miSubEngineNotifier = addNotification (gIOPublishNotification, serviceMatching ("AppleiSubEngine"), (IOServiceNotificationHandler)&iSubEnginePublished, this);
if (NULL != miSubBufferMemory)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeCall () - Removing miSubEngineNotifier because notifier was already called ...");
miSubEngineNotifier->remove ();
miSubEngineNotifier = NULL;
}
}
else
{
debugIOLog ("! AppleUSBAudioEngine::iSubAttachChangeHandler () - There is already a notifier @ 0x%x!", miSubEngineNotifier);
}
}
else
{
if (NULL != miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine::iSubAttachChangeCall () - Removing miSubEngineNotifier because this is not an iSub-compatible format ...");
miSubEngineNotifier->remove ();
miSubEngineNotifier = NULL;
}
}
debugIOLog("- AppleUSBAudioEngine::iSubAttachChangeCall");
return result;
}
IOReturn AppleUSBAudioEngine::iSubCloseAction (OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) {
debugIOLog("+ AppleUSBAudioEngine::iSubCloseAction");
AppleUSBAudioEngine *audioEngine = OSDynamicCast (AppleUSBAudioEngine, owner);
FailIf (NULL == audioEngine, Exit);
if (TRUE == audioEngine->miSubIsOpen && NULL != audioEngine->mOldiSubEngine)
{
audioEngine->mOldiSubEngine->closeiSub (audioEngine);
audioEngine->detach (audioEngine->mOldiSubEngine);
audioEngine->miSubIsOpen = FALSE;
audioEngine->miSubEngine = NULL;
audioEngine->miSubBufferMemory = NULL;
#if DEBUGISUB
}
else
{
if (TRUE != audioEngine->miSubIsOpen) {debugIOLog ("TRUE != audioEngine->miSubIsOpen");}
if (NULL == audioEngine->mOldiSubEngine) {debugIOLog ("NULL == audioEngine->mOldiSubEngine");}
#endif
}
if (NULL != audioEngine->mLowFreqSamples)
{
IOFreeAligned (audioEngine->mLowFreqSamples, audioEngine->mFreqSampleBufferSize); audioEngine->mLowFreqSamples = NULL;
}
if (NULL != audioEngine->mHighFreqSamples)
{
IOFreeAligned (audioEngine->mHighFreqSamples, audioEngine->mFreqSampleBufferSize); audioEngine->mHighFreqSamples = NULL;
}
audioEngine->mFreqSampleBufferSize = 0;
Exit:
debugIOLog("- AppleUSBAudioEngine::iSubCloseAction");
return kIOReturnSuccess;
}
bool AppleUSBAudioEngine::iSubEnginePublished (AppleUSBAudioEngine * usbAudioEngineObject, void * refCon, IOService * newService) {
debugIOLog ("? AppleUSBAudioEngine::iSubEnginePublished (%p, %p, %p)", usbAudioEngineObject, refCon, newService);
FailIf (NULL == usbAudioEngineObject, Exit);
FailIf (NULL == newService, Exit);
if (FALSE == usbAudioEngineObject->miSubIsOpen)
{
usbAudioEngineObject->miSubEngine = (AppleiSubEngine *)newService;
#if THREAD_ISUB_OPEN
usbAudioEngineObject->miSubOpenThreadCall = thread_call_allocate ((thread_call_func_t)usbAudioEngineObject->iSubOpen, (thread_call_param_t)usbAudioEngineObject);
if (NULL != usbAudioEngineObject->miSubOpenThreadCall)
{
AbsoluteTime callTime;
AbsoluteTime delayAmount;
clock_get_uptime (&callTime);
nanoseconds_to_absolutetime (750ULL * 1000 * 1000, &delayAmount);
ADD_ABSOLUTETIME (&callTime, &delayAmount);
thread_call_enter_delayed (usbAudioEngineObject->miSubOpenThreadCall, callTime);
}
else
{
}
#else
iSubOpen(usbAudioEngineObject);
#endif
}
else
{
debugIOLog ("? AppleUSBAudioEngine::iSubEnginePublished () - iSub is already open");
}
Exit:
return TRUE;
}
void AppleUSBAudioEngine::iSubOpen (AppleUSBAudioEngine * usbAudioEngineObject) {
IOReturn result;
IOCommandGate * cg;
debugIOLog ("+ AppleUSBAudioEngine::iSubOpen (%p)", usbAudioEngineObject);
FailIf (NULL == usbAudioEngineObject, Exit);
cg = usbAudioEngineObject->getCommandGate ();
if (NULL != cg)
{
result = cg->runAction (iSubOpenAction);
}
Exit:
if (NULL != usbAudioEngineObject && NULL != usbAudioEngineObject->miSubOpenThreadCall)
{
thread_call_free(usbAudioEngineObject->miSubOpenThreadCall);
}
debugIOLog ("- AppleUSBAudioEngine::iSubOpen (%p)", usbAudioEngineObject);
return;
}
IOReturn AppleUSBAudioEngine::iSubOpenAction (OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) {
AppleUSBAudioEngine * usbAudioEngineObject;
UInt32 streamNumChannels;
IOReturn result;
bool resultBool;
UInt32 sampleRateWhole;
UInt32 numTries;
debugIOLog ("+ AppleUSBAudioEngine::iSubOpenAction (%p)", owner);
result = kIOReturnError;
usbAudioEngineObject = OSDynamicCast (AppleUSBAudioEngine, owner);
FailIf (NULL == usbAudioEngineObject, Exit);
FailIf (NULL == usbAudioEngineObject->miSubEngine, Exit);
FailIf (NULL == usbAudioEngineObject->mMainOutputStream, Exit);
streamNumChannels = usbAudioEngineObject->mMainOutputStream->mNumChannels;
sampleRateWhole = usbAudioEngineObject->mCurSampleRate.whole;
if ((2 != streamNumChannels) || ((8000 != usbAudioEngineObject->mCurSampleRate.whole) && (11025 != usbAudioEngineObject->mCurSampleRate.whole) &&
(22050 != usbAudioEngineObject->mCurSampleRate.whole) && (44100 != usbAudioEngineObject->mCurSampleRate.whole) &&
(48000 != usbAudioEngineObject->mCurSampleRate.whole) && (96000 != usbAudioEngineObject->mCurSampleRate.whole)))
{
goto Exit;
}
usbAudioEngineObject->mFreqSampleBufferSize = usbAudioEngineObject->mMainOutputStream->getSampleBufferSize () * 2;
usbAudioEngineObject->mLowFreqSamples = (float *)IOMallocAligned (usbAudioEngineObject->mFreqSampleBufferSize, PAGE_SIZE);
FailIf (NULL == usbAudioEngineObject->mLowFreqSamples, Cleanup);
usbAudioEngineObject->mHighFreqSamples = (float *)IOMallocAligned (usbAudioEngineObject->mFreqSampleBufferSize, PAGE_SIZE);
FailIf (NULL == usbAudioEngineObject->mHighFreqSamples, Cleanup);
usbAudioEngineObject->attach (usbAudioEngineObject->miSubEngine);
numTries = 0;
do
{
resultBool = usbAudioEngineObject->miSubEngine->openiSub (usbAudioEngineObject, &requestiSubClose);
numTries++;
if (!resultBool) IOSleep (102);
} while (FALSE == resultBool && numTries < 5);
FailWithAction (FALSE == resultBool, usbAudioEngineObject->detach (usbAudioEngineObject->miSubEngine), Cleanup);
result = kIOReturnSuccess;
Cleanup:
if (NULL != usbAudioEngineObject->miSubEngineNotifier)
{
debugIOLog ("? AppleUSBAudioEngine::iSubOpenAction () - Removing miSubEngineNotifier because we found an iSub ...");
usbAudioEngineObject->miSubEngineNotifier->remove ();
usbAudioEngineObject->miSubEngineNotifier = NULL;
}
if (kIOReturnSuccess == result)
{
debugIOLog ("? AppleUSBAudioEngine::iSubOpenAction () - Successfully opened the iSub");
usbAudioEngineObject->miSubBufferMemory = usbAudioEngineObject->miSubEngine->GetSampleBuffer ();
usbAudioEngineObject->miSubIsOpen = TRUE;
}
else
{
usbAudioEngineObject->miSubBufferMemory = NULL;
usbAudioEngineObject->miSubEngine = NULL;
usbAudioEngineObject->miSubIsOpen = FALSE;
if (NULL != usbAudioEngineObject->mLowFreqSamples)
{
IOFreeAligned (usbAudioEngineObject->mLowFreqSamples, usbAudioEngineObject->mFreqSampleBufferSize); usbAudioEngineObject->mLowFreqSamples = NULL;
}
if (NULL != usbAudioEngineObject->mHighFreqSamples)
{
IOFreeAligned (usbAudioEngineObject->mHighFreqSamples, usbAudioEngineObject->mFreqSampleBufferSize); usbAudioEngineObject->mHighFreqSamples = NULL;
}
usbAudioEngineObject->mFreqSampleBufferSize = 0;
}
Exit:
debugIOLog ("- AppleUSBAudioEngine::iSubOpenAction (%p) = 0x%lx", owner, result);
return result;
}
void AppleUSBAudioEngine::iSubTeardown (AppleUSBAudioEngine * usbAudioEngine, thread_call_t iSubTeardownThreadCall) {
IOCommandGate * cg;
Boolean streamWasRunning;
debugIOLog ("+ AppleUSBAudioEngine::iSubTeardown ()");
if (NULL != usbAudioEngine)
{
streamWasRunning = usbAudioEngine->mUSBStreamRunning;
usbAudioEngine->mUSBStreamRunning = FALSE;
usbAudioEngine->pauseAudioEngine ();
usbAudioEngine->beginConfigurationChange ();
cg = usbAudioEngine->getCommandGate ();
if (NULL != cg)
{
cg->runAction (iSubCloseAction);
}
usbAudioEngine->completeConfigurationChange ();
usbAudioEngine->resumeAudioEngine ();
usbAudioEngine->mUSBStreamRunning = streamWasRunning;
}
if (NULL != iSubTeardownThreadCall)
{
thread_call_free(iSubTeardownThreadCall);
}
debugIOLog ("- AppleUSBAudioEngine::iSubTeardown ()");
}
void AppleUSBAudioEngine::iSubTeardownConnection (void) {
debugIOLog ("+ AppleUSBAudioEngine::iSubTeardownConnection ()");
mOldiSubEngine = miSubEngine;
miSubTeardownThreadCall = thread_call_allocate ((thread_call_func_t)iSubTeardown, (thread_call_param_t)this);
if (NULL != miSubTeardownThreadCall)
{
thread_call_enter1 (miSubTeardownThreadCall, miSubTeardownThreadCall);
}
else
{
}
debugIOLog ("- AppleUSBAudioEngine::iSubTeardownConnection ()");
return;
}
bool AppleUSBAudioEngine::isiSubCompatibleFormat (const IOAudioStreamFormat *format, IOAudioSampleRate sampleRate)
{
if ( (NULL != format)
&& (2 == format->fNumChannels)
&& (16 == format->fBitDepth)
&& ( (8000 == sampleRate.whole)
|| (11025 == sampleRate.whole)
|| (22050 == sampleRate.whole)
|| (44100 == sampleRate.whole)
|| (48000 == sampleRate.whole)
|| (96000 == sampleRate.whole)))
{
debugIOLog ("? AppleUSBAudioEngine::isiSubCompatibleFormat () - TRUE");
return TRUE;
}
else
{
debugIOLog ("? AppleUSBAudioEngine::isiSubCompatibleFormat () - FALSE");
return FALSE;
}
}
IOReturn AppleUSBAudioEngine::performAudioEngineStart () {
IOReturn resultCode;
UInt32 usbFramesToDelay = 0;
UInt32 lockDelayFrames = 0;
UInt64 currentUSBFrame = 0;
UInt32 streamIndex;
AppleUSBAudioStream * audioStream;
debugIOLog ("+ AppleUSBAudioEngine[%p]::performAudioEngineStart ()", this);
resultCode = kIOReturnError;
FailIf (NULL == mUSBAudioDevice, Exit);
FailIf (NULL == mIOAudioStreamArray, Exit);
if (mUSBAudioDevice->mNewReferenceUSBFrame == 0ull)
{
debugIOLog ("! AppleUSBAudioEngine[%p]::performAudioEngineStart () - Getting an anchor for the first timestamp.", this);
FailIf (kIOReturnSuccess != mUSBAudioDevice->getAnchorFrameAndTimeStamp (NULL, NULL), Exit);
}
resultCode = kIOReturnSuccess;
if (mPlugin)
{
mPlugin->pluginStart ();
}
for ( streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
if (audioStream && audioStream->mPlugin)
{
audioStream->mPlugin->pluginStart ();
}
}
if (NULL != miSubEngine)
{
mStartiSub = TRUE;
mNeedToSync = TRUE;
}
if (!mUSBStreamRunning)
{
#if DEBUGLATENCY
mHaveClipped = false;
#endif
for ( streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
resultCode = kIOReturnError;
audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
FailIf ( NULL == audioStream, Exit );
resultCode = audioStream->prepareUSBStream ();
FailIf ( kIOReturnSuccess != resultCode, Exit );
lockDelayFrames = audioStream->getLockDelayFrames ();
if ( usbFramesToDelay < lockDelayFrames )
{
usbFramesToDelay = lockDelayFrames;
}
}
currentUSBFrame = mUSBAudioDevice->getUSBFrameNumber ();
currentUSBFrame += kStartDelayOffset;
for ( streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream;
resultCode = kIOReturnError;
audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
FailIf ( NULL == audioStream, Exit );
resultCode = audioStream->startUSBStream (currentUSBFrame, usbFramesToDelay);
FailIf ( kIOReturnSuccess != resultCode, Exit );
}
if ( kIOReturnSuccess == resultCode )
{
if ( 0 != usbFramesToDelay )
{
IOSleep ( usbFramesToDelay );
}
mUSBStreamRunning = TRUE;
}
}
Exit:
if (resultCode != kIOReturnSuccess)
{
debugIOLog ("! AppleUSBAudioEngine[%p]::performAudioEngineStart () - NOT started, error = 0x%x", this, resultCode);
performAudioEngineStop ();
if ( ( (kIOReturnNotResponding == resultCode)
|| (kIOReturnExclusiveAccess == resultCode))
&& ( ! mUSBAudioDevice->recoveryRequested ()))
{
if (mUSBAudioDevice)
{
debugIOLog ("! AppleUSBAudioEngine[%p]::performAudioEngineStart () - Device not responding! Requesting a recovery attempt.");
mUSBAudioDevice->requestDeviceRecovery ();
}
}
}
else
{
debugIOLog ("\n");
debugIOLog (" sampleRate->whole = %lu", getSampleRate()->whole);
debugIOLog ("\n");
}
debugIOLog ("- AppleUSBAudioEngine[%p]::performAudioEngineStart ()", this);
return resultCode;
}
IOReturn AppleUSBAudioEngine::performAudioEngineStop() {
UInt32 streamIndex;
AppleUSBAudioStream * audioStream;
debugIOLog("+ AppleUSBAudioEngine[%p]::performAudioEngineStop ()", this);
for ( streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
if (audioStream && audioStream->mPlugin)
{
audioStream->mPlugin->pluginStop ();
}
}
if (mPlugin)
{
mPlugin->pluginStop ();
}
if (NULL != miSubEngine)
{
miSubEngine->StopiSub ();
mNeedToSync = TRUE;
}
if (mUSBStreamRunning)
{
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream;
audioStream = OSDynamicCast (AppleUSBAudioStream, mIOAudioStreamArray->getObject (streamIndex) );
if ( NULL != audioStream )
{
audioStream->stopUSBStream ();
}
}
}
mUSBStreamRunning = FALSE;
debugIOLog("? AppleUSBAudioEngine[%p]::performAudioEngineStop() - stopped", this);
debugIOLog("- AppleUSBAudioEngine[%p]::performAudioEngineStop()", this);
return kIOReturnSuccess;
}
IOReturn AppleUSBAudioEngine::performFormatChange (IOAudioStream *audioStream, const IOAudioStreamFormat *newFormat, const IOAudioSampleRate *newSampleRate) {
IOReturn result;
UInt32 controllerResult;
bool streamIsRunning = false;
debugIOLog ("+ AppleUSBAudioEngine[%p]::performFormatChange (%p, %p, %p)", this, audioStream, newFormat, newSampleRate);
result = kIOReturnError;
FailIf (NULL == mUSBAudioDevice, Exit);
streamIsRunning = mUSBStreamRunning;
if (streamIsRunning)
{
pauseAudioEngine ();
}
controllerResult = mUSBAudioDevice->formatChangeController (this, audioStream, newFormat, newSampleRate);
switch (controllerResult)
{
case kAUAFormatChangeNormal:
result = kIOReturnSuccess;
break;
case kAUAFormatChangeForced:
debugIOLog ("? AppleUSBAudioEngine[%p]::performFormatChange () - This request was forced.");
result = kIOReturnSuccess;
break;
case kAUAFormatChangeForceFailure:
debugIOLog ("! AppleUSBAudioEngine[%p]::performFormatChange () - Force of this request was attempted but failed.");
result = kIOReturnSuccess;
break;
case kAUAFormatChangeError:
default:
debugIOLog ("! AppleUSBAudioEngine[%p]::performFormatChange () - Error encountered.");
result = kIOReturnError;
}
IOSleep ( kFormatChangeDelayInMs );
Exit:
if (streamIsRunning)
{
resumeAudioEngine ();
}
debugIOLog ("- AppleUSBAudioEngine[%p]::performFormatChange () = 0x%x", this, result);
return result;
}
void AppleUSBAudioEngine::resetClipPosition (IOAudioStream *audioStream, UInt32 clipSampleFrame) {
AppleUSBAudioStream * appleUSBAudioStream;
appleUSBAudioStream = OSDynamicCast ( AppleUSBAudioStream, audioStream );
FailIf ( NULL == appleUSBAudioStream, Exit );
if (appleUSBAudioStream->mPlugin)
{
appleUSBAudioStream->mPlugin->pluginReset ();
}
if (mPlugin)
{
mPlugin->pluginReset ();
}
if ( (NULL != miSubBufferMemory)
&& (NULL != miSubEngine)
&& (mMainOutputStream == appleUSBAudioStream))
{
mSrcPhase = 1.0; mSrcState = 0.0;
mFilterState.xl_1 = 0.0;
mFilterState.xr_1 = 0.0;
mFilterState.xl_2 = 0.0;
mFilterState.xr_2 = 0.0;
mFilterState.yl_1 = 0.0;
mFilterState.yr_1 = 0.0;
mFilterState.yl_2 = 0.0;
mFilterState.yr_2 = 0.0;
mFilterState2.xl_1 = 0.0;
mFilterState2.xr_1 = 0.0;
mFilterState2.xl_2 = 0.0;
mFilterState2.xr_2 = 0.0;
mFilterState2.yl_1 = 0.0;
mFilterState2.yr_1 = 0.0;
mFilterState2.yl_2 = 0.0;
mFilterState2.yr_2 = 0.0;
mPhaseCompState.xl_1 = 0.0;
mPhaseCompState.xr_1 = 0.0;
mPhaseCompState.xl_2 = 0.0;
mPhaseCompState.xr_2 = 0.0;
mPhaseCompState.yl_1 = 0.0;
mPhaseCompState.yr_1 = 0.0;
mPhaseCompState.yl_2 = 0.0;
mPhaseCompState.yr_2 = 0.0;
#if DEBUGISUB
debugIOLog ("+resetClipPosition, miSubBufferOffset=%ld, mLastClippedFrame=%ld, clipSampleFrame=%ld", miSubBufferOffset, mLastClippedFrame, clipSampleFrame);
#endif
UInt32 clipAdjustment;
if (mLastClippedFrame < clipSampleFrame)
{
clipAdjustment = (mLastClippedFrame + ((mMainOutputStream->getSampleBufferSize () / (2 * miSubEngine->GetNumChannels())) - clipSampleFrame)) * miSubEngine->GetNumChannels();
}
else
{
clipAdjustment = (mLastClippedFrame - clipSampleFrame) * miSubEngine->GetNumChannels();
}
clipAdjustment = (clipAdjustment * 1000) / ((1000 * getSampleRate()->whole) / miSubEngine->GetSampleRate());
miSubBufferOffset -= clipAdjustment;
if (miSubBufferOffset < 0)
{
miSubBufferOffset += (miSubBufferMemory->getLength () / 2);
miSubLoopCount--; }
mLastClippedFrame = clipSampleFrame;
mJustResetClipPosition = TRUE; #if DEBUGISUB
debugIOLog ("-resetClipPosition, miSubBufferOffset=%ld, mLastClippedFrame=%ld", miSubBufferOffset, mLastClippedFrame);
#endif
}
Exit:
return;
}
void AppleUSBAudioEngine::requestiSubClose (IOAudioEngine * audioEngine) {
}
void AppleUSBAudioEngine::takeTimeStamp (bool incrementLoopCount, AbsoluteTime *timestamp)
{
#if LOGTIMESTAMPS
UInt64 time_nanos;
absolutetime_to_nanoseconds (*timestamp, &time_nanos);
if (true)
{
debugIOLog ("? AppleUSBAudioEngine[%p]::takeTimeStamp (%d, %p) = %llu ns", this, timestamp, time_nanos);
}
#endif
super::takeTimeStamp (incrementLoopCount, timestamp);
}
bool AppleUSBAudioEngine::willTerminate (IOService * provider, IOOptionBits options) {
debugIOLog ("+ AppleUSBAudioEngine[%p]::willTerminate (%p)", this, provider);
if (miSubEngine == (AppleiSubEngine *)provider)
{
debugIOLog ("? AppleUSBAudioEngine[%p]::willTerminate () - iSub requesting termination", this);
iSubTeardownConnection ();
if ( (miSubAttachToggle->getIntValue ())
&& (NULL == miSubEngineNotifier)) {
debugIOLog ("? AppleUSBAudioEngine[%p]::willTerminate () - Adding miSubEngineNotifier because of iSub termination ...", this);
miSubEngineNotifier = addNotification (gIOPublishNotification, serviceMatching ("AppleiSubEngine"), (IOServiceNotificationHandler)&iSubEnginePublished, this);
}
}
if (mUSBAudioDevice == provider)
{
mTerminatingDriver = TRUE;
mOldiSubEngine = miSubEngine;
iSubCloseAction (this, NULL, NULL, NULL, NULL);
}
debugIOLog ("- AppleUSBAudioEngine[%p]::willTerminate ()", this);
return super::willTerminate (provider, options);
}
OSSet * AppleUSBAudioEngine::copyDefaultAudioControls ( void )
{
return OSSet::withSet ( defaultAudioControls, defaultAudioControls->getCount () );
}
#pragma mark -Clock Source Selector-
IOReturn AppleUSBAudioEngine::doClockSelectorSetup (UInt8 interfaceNum, UInt8 altSettingNum, UInt32 sampleRate) {
OSArray * clockPathGroup = NULL;
OSNumber * clockIDNumber;
UInt8 clockSelectorID = 0;
UInt8 clockID;
OSArray * clockPath;
UInt8 clockPathGroupIndex = 0;
UInt8 clockPathIndex = 0;
UInt32 clockSelection = 0;
UInt8 controlInterfaceNum;
AUAConfigurationDictionary * configDictionary = NULL;
bool hasNonProgrammableClockSource = false;
IOReturn result;
debugIOLog ("+ AppleUSBAudioEngine[%p]::doClockSelectorSetup( 0x%x, 0x%x, %d )", this, interfaceNum, altSettingNum, sampleRate);
result = kIOReturnError;
FailIf ( NULL == mUSBAudioDevice, Exit );
FailIf ( NULL == mUSBAudioDevice->mControlInterface, Exit );
FailIf ( NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary () ), Exit );
controlInterfaceNum = mUSBAudioDevice->mControlInterface->GetInterfaceNumber ();
if ( NULL == mClockSelectorControl )
{
clockPath = mUSBAudioDevice->getOptimalClockPath ( this, interfaceNum, altSettingNum, sampleRate, NULL, &clockPathGroupIndex );
FailIf ( NULL == clockPath, Exit );
FailIf ( NULL == ( clockIDNumber = OSDynamicCast ( OSNumber, clockPath->getLastObject () ) ), Exit );
clockID = clockIDNumber->unsigned8BitValue ();
result = mUSBAudioDevice->getClockSelectorIDAndPathIndex ( &clockSelectorID, &clockPathIndex, clockPath );
FailIf ( kIOReturnSuccess != result, Exit );
result = mUSBAudioDevice->getClockPathCurSampleRate ( NULL, &mClockSourceValidity, clockPath );
FailIf ( kIOReturnSuccess != result, Exit );
if ( !mClockSourceValidityInitialized )
{
mClockSourceValidityInitialized = true;
mShouldRepublishFormat = true;
}
}
else
{
clockID = (mClockSelectorControl->getIntValue () >> 24) & 0xFF;
clockSelectorID = (mClockSelectorControl->getIntValue () >> 16) & 0xFF;
clockPathGroupIndex = (mClockSelectorControl->getIntValue () >> 8) & 0xFF;
clockPathIndex = mClockSelectorControl->getIntValue () & 0xFF;
result = kIOReturnSuccess;
mClockSelectorControl->release ();
mClockSelectorControl = NULL;
}
mCurrentClockSourceID = clockID;
mCurrentClockPathGroupIndex = clockPathGroupIndex;
mCurrentClockPathIndex = clockPathIndex;
if ( ( kIOReturnSuccess == result ) &&
( 0 != clockSelectorID ) && ( 0 != clockPathIndex ) )
{
debugIOLog ("? AppleUSBAudioEngine[%p]::doClockSelectorSetup( 0x%x, 0x%x, %d ) - clockSelectorID = %d, clockPathIndex = %d", this, interfaceNum, altSettingNum, sampleRate, clockSelectorID, clockPathIndex);
FailIf ( kIOReturnSuccess != mUSBAudioDevice->setCurClockSelector ( clockSelectorID, clockPathIndex ), Exit );
clockSelection = ( ( UInt32 )( clockID ) << 24 ) | ( ( UInt32 )( clockSelectorID ) << 16 ) | ( clockPathGroupIndex << 8 ) | ( clockPathIndex );
mClockSelectorControl = IOAudioSelectorControl::create ( clockSelection,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
0,
kIOAudioSelectorControlSubTypeClockSource,
kIOAudioControlUsageInput);
FailIf ( NULL == mClockSelectorControl, Exit );
mClockSelectorControl->setValueChangeHandler ( controlChangedHandler, this );
clockPathGroup = mUSBAudioDevice->getClockPathGroup ( interfaceNum, altSettingNum );
FailIf ( NULL == clockPathGroup, Exit );
for ( UInt32 pathIndex = 0; pathIndex < clockPathGroup->getCount (); pathIndex++ )
{
UInt8 subType;
FailIf ( NULL == ( clockPath = OSDynamicCast ( OSArray, clockPathGroup->getObject ( pathIndex ) ) ), Exit );
FailIf ( NULL == ( clockIDNumber = OSDynamicCast ( OSNumber, clockPath->getLastObject () ) ), Exit );
clockID = clockIDNumber->unsigned8BitValue ();
FailIf (kIOReturnSuccess != ( result = configDictionary->getSubType ( &subType, controlInterfaceNum, 0, clockID ) ), Exit );
debugIOLog ("? AppleUSBAudioEngine[%p]::doClockSelectorSetup( 0x%x, 0x%x, %d ) - %d: clockID = %d, subType = %d", this, interfaceNum, altSettingNum, sampleRate, pathIndex, clockID, subType);
if ( USBAUDIO_0200::CLOCK_SOURCE == subType )
{
UInt8 clockType;
UInt8 assocTerminal = 0;
UInt16 terminalType = 0;
UInt8 stringIndex;
char * clockSelectionString = NULL;
clockSelection = ( ( UInt32 )( clockID ) << 24 ) | ( ( UInt32 )( clockSelectorID ) << 16 ) | ( clockPathGroupIndex << 8 ) | ( pathIndex + 1 );
if ( !mClockSelectorControl->valueExists ( clockSelection ) )
{
char tempString[kStringBufferSize] = { 0 };
if ( ( kIOReturnSuccess == configDictionary->getStringIndex ( &stringIndex, controlInterfaceNum, 0, clockID ) ) &&
( 0 != stringIndex ) &&
( kIOReturnSuccess == mUSBAudioDevice->getStringDescriptor(stringIndex, tempString, kStringBufferSize) ) )
{
clockSelectionString = tempString;
}
else
{
FailIf ( kIOReturnSuccess != ( result = configDictionary->getClockSourceClockType ( &clockType, controlInterfaceNum, 0, clockID ) ), Exit );
switch ( clockType )
{
case USBAUDIO_0200::CLOCK_TYPE_EXTERNAL:
FailIf ( kIOReturnSuccess != ( result = configDictionary->getClockSourceAssocTerminal ( &assocTerminal, controlInterfaceNum, 0, clockID ) ), Exit );
if ( 0 != assocTerminal )
{
FailIf ( kIOReturnSuccess != ( result = configDictionary->getInputTerminalType (&terminalType, controlInterfaceNum, 0, assocTerminal) ), Exit);
if ( USB_STREAMING == terminalType )
{
#if LOCALIZABLE
clockSelectionString = (char *)"StringMacSync";
#else
clockSelectionString = (char *)"Mac Sync";
#endif
}
else
{
if ( ( kIOReturnSuccess == configDictionary->getStringIndex ( &stringIndex, controlInterfaceNum, 0, assocTerminal ) ) &&
( 0 != stringIndex ) &&
( kIOReturnSuccess == mUSBAudioDevice->getStringDescriptor(stringIndex, tempString, kStringBufferSize) ) )
{
clockSelectionString = tempString;
}
else
{
clockSelectionString = mUSBAudioDevice->TerminalTypeString ( terminalType );
}
}
}
else
{
clockSelectionString = mUSBAudioDevice->ClockTypeString ( clockType );
}
break;
case USBAUDIO_0200::CLOCK_TYPE_INTERNAL_FIXED:
case USBAUDIO_0200::CLOCK_TYPE_INTERNAL_VARIABLE:
case USBAUDIO_0200::CLOCK_TYPE_INTERNAL_PROGRAMMABLE:
#if LOCALIZABLE
clockSelectionString = (char *)"StringDevice";
#else
clockSelectionString = (char *)"Device";
#endif
break;
}
}
if ( NULL != clockSelectionString )
{
mClockSelectorControl->addAvailableSelection ( clockSelection, clockSelectionString );
}
}
if ( !configDictionary->clockSourceHasFrequencyControl ( controlInterfaceNum, 0, clockID, true ) )
{
hasNonProgrammableClockSource = true;
}
}
}
addDefaultAudioControl ( mClockSelectorControl );
}
else
{
hasNonProgrammableClockSource = !configDictionary->clockSourceHasFrequencyControl ( controlInterfaceNum, 0, mCurrentClockSourceID, true );
}
determineMacSyncMode ( mCurrentClockSourceID );
#if POLLCLOCKSTATUS
mShouldPollClockStatus = hasNonProgrammableClockSource && ( !configDictionary->hasInterruptEndpoint ( controlInterfaceNum, 0 ) );
mPollClockStatusCounter = 0;
debugIOLog ("? AppleUSBAudioEngine[%p]::doClockSelectorSetup( 0x%x, 0x%x, %d ) - Should poll = %d", this, interfaceNum, altSettingNum, sampleRate, mShouldPollClockStatus);
#endif
result = kIOReturnSuccess;
Exit:
debugIOLog ("- AppleUSBAudioEngine[%p]::doClockSelectorSetup( 0x%x, 0x%x, %d ) = 0x%x", this, interfaceNum, altSettingNum, sampleRate, result);
return result;
}
IOReturn AppleUSBAudioEngine::controlChangedHandler (OSObject * target, IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
AppleUSBAudioEngine * self;
result = kIOReturnError;
self = OSDynamicCast (AppleUSBAudioEngine, target);
FailIf (NULL == self, Exit);
result = self->protectedControlChangedHandler (audioControl, oldValue, newValue);
Exit:
return result;
}
IOReturn AppleUSBAudioEngine::protectedControlChangedHandler (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
result = kIOReturnError;
switch (audioControl->getType ())
{
case kIOAudioControlTypeSelector:
if ( kIOAudioSelectorControlSubTypeClockSource == audioControl->getSubType () )
{
result = doClockSelectorChange (audioControl, oldValue, newValue);
}
break;
}
return result;
}
IOReturn AppleUSBAudioEngine::doClockSelectorChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue) {
UInt8 clockSourceID;
UInt8 clockSelectorID;
UInt8 newClockPathGroupIndex;
UInt8 newClockPathIndex;
OSArray * newClockPathGroup;
OSArray * newClockPath;
UInt8 oldClockPathGroupIndex;
UInt8 oldClockPathIndex;
OSArray * oldClockPathGroup;
OSArray * oldClockPath;
Boolean clockValidity = false;
IOAudioSampleRate newSampleRate;
IOAudioSampleRate oldSampleRate;
IOReturn result = kIOReturnError;
debugIOLog ("+ AppleUSBAudioEngine[%p]::doClockSelectorChange( %p, 0x%x, 0x%x )", this, audioControl, oldValue, newValue);
clockSourceID = ( newValue >> 24 ) & 0xFF;
clockSelectorID = ( newValue >> 16 ) & 0xFF;
newClockPathGroupIndex = ( newValue >> 8 ) & 0xFF;
newClockPathIndex = newValue & 0xFF;
oldClockPathGroupIndex = ( oldValue >> 8 ) & 0xFF;
oldClockPathIndex = oldValue & 0xFF;
if ( oldValue != newValue )
{
pauseAudioEngine ();
beginConfigurationChange ();
newClockPathGroup = mUSBAudioDevice->getClockPathGroup ( newClockPathGroupIndex );
FailIf ( NULL == newClockPathGroup, Exit );
newClockPath = OSDynamicCast ( OSArray, newClockPathGroup->getObject ( newClockPathIndex - 1 ) );
FailIf ( NULL == newClockPath, Exit )
newSampleRate.whole = 0;
newSampleRate.fraction = 0;
oldSampleRate.whole = 0;
oldSampleRate.fraction = 0;
result = mUSBAudioDevice->getClockPathCurSampleRate ( &newSampleRate.whole, &clockValidity, newClockPath );
debugIOLog ("? AppleUSBAudioEngine[%p]::doClockSelectorChange( %p, 0x%x, 0x%x ) - result = 0x%x, sample rate = %d, clockValidity = %d", this, audioControl, oldValue, newValue, result, newSampleRate.whole, clockValidity);
if ( kIOReturnSuccess == result )
{
if ( clockValidity )
{
oldClockPathGroup = mUSBAudioDevice->getClockPathGroup ( oldClockPathGroupIndex );
FailIf ( NULL == oldClockPathGroup, Exit );
oldClockPath = OSDynamicCast ( OSArray, oldClockPathGroup->getObject ( oldClockPathIndex - 1 ) );
FailIf ( NULL == oldClockPath, Exit )
result = mUSBAudioDevice->getClockPathCurSampleRate ( &oldSampleRate.whole, NULL, oldClockPath );
FailIf ( kIOReturnSuccess != result, Exit );
result = mUSBAudioDevice->setClockPathCurSampleRate ( newSampleRate.whole, oldClockPath );
FailIf ( kIOReturnSuccess != result, Exit );
mCurrentClockSourceID = clockSourceID;
mCurrentClockPathIndex = newClockPathIndex;
republishAvailableFormats ();
result = performFormatChange ( NULL, NULL, &newSampleRate );
FailMessage ( kIOReturnSuccess != result );
if ( kIOReturnSuccess == result )
{
determineMacSyncMode ( mCurrentClockSourceID );
hardwareSampleRateChanged ( &newSampleRate );
}
else
{
mCurrentClockSourceID = ( oldValue >> 24 ) & 0xFF;
mCurrentClockPathIndex = oldClockPathIndex;
republishAvailableFormats ();
FailMessage ( kIOReturnSuccess != performFormatChange ( NULL, NULL, &oldSampleRate ) );
mRestoreClockSelection = true;
mRestoreClockSelectionValue = oldValue;
result = kIOReturnSuccess;
}
}
else
{
mRestoreClockSelection = true;
mRestoreClockSelectionValue = oldValue;
result = kIOReturnSuccess;
}
}
completeConfigurationChange ();
resumeAudioEngine ();
}
else
{
clockSelectorID = ( newValue >> 16 ) & 0xFF;
newClockPathIndex = newValue & 0xFF;
result = mUSBAudioDevice->setCurClockSelector ( clockSelectorID, newClockPathIndex );
}
debugIOLog ("- AppleUSBAudioEngine[%p]::doClockSelectorChange( %p, 0x%x, 0x%x ) = 0x%x", this, audioControl, oldValue, newValue, result);
Exit:
return result;
}
IOReturn AppleUSBAudioEngine::republishAvailableFormats () {
AUAConfigurationDictionary * configDictionary = NULL;
FailIf ( NULL == ( configDictionary = mUSBAudioDevice->getConfigDictionary () ), Exit );
for ( UInt32 streamIndex = 0; streamIndex < mIOAudioStreamArray->getCount (); streamIndex++ )
{
AppleUSBAudioStream * audioStream = OSDynamicCast ( AppleUSBAudioStream, mIOAudioStreamArray->getObject ( streamIndex ) );
if ( NULL != audioStream )
{
audioStream->clearAvailableFormats ();
audioStream->addAvailableFormats ( configDictionary );
}
}
Exit:
return kIOReturnSuccess;
}
bool AppleUSBAudioEngine::determineMacSyncMode ( UInt8 clockID )
{
UInt8 clockType = 0xFF;
UInt8 assocTerminal = 0;
UInt16 terminalType = 0;
AUAConfigurationDictionary * configDictionary = NULL;
UInt8 controlInterfaceNum;
bool macSyncMode = false;
debugIOLog ( "+ AppleUSBAudioEngine[%p]::determineMacSyncMode( %d )", this, clockID );
FailIf ( NULL == mUSBAudioDevice, Exit );
FailIf ( NULL == mUSBAudioDevice->mControlInterface, Exit );
FailIf ( NULL == (configDictionary = mUSBAudioDevice->getConfigDictionary () ), Exit );
controlInterfaceNum = mUSBAudioDevice->mControlInterface->GetInterfaceNumber ();
FailIf ( kIOReturnSuccess != configDictionary->getClockSourceClockType ( &clockType, controlInterfaceNum, 0, clockID ), Exit );
FailIf ( kIOReturnSuccess != configDictionary->getClockSourceAssocTerminal ( &assocTerminal, controlInterfaceNum, 0, clockID ), Exit );
if ( ( USBAUDIO_0200::CLOCK_TYPE_EXTERNAL == clockType ) && ( 0 != assocTerminal ) )
{
FailIf ( kIOReturnSuccess != configDictionary->getInputTerminalType (&terminalType, controlInterfaceNum, 0, assocTerminal), Exit);
macSyncMode = ( USB_STREAMING == terminalType );
}
if ( ( NULL != mMainOutputStream ) && ( NULL != mMainInputStream ) )
{
if ( ( macSyncMode ) || ( kAdaptiveSyncType == mMainOutputStream->getSyncType () ) )
{
mMainInputStream->setMasterStreamMode ( false );
mMainOutputStream->setMasterStreamMode ( true );
}
else
{
mMainInputStream->setMasterStreamMode ( true );
mMainOutputStream->setMasterStreamMode ( false );
}
}
Exit:
debugIOLog ( "- AppleUSBAudioEngine[%p]::determineMacSyncMode( %d ) = %d", this, clockID, macSyncMode );
return macSyncMode;
}
void AppleUSBAudioEngine::updateClockStatus ( UInt8 clockID )
{
UInt32 clockRate;
bool clockValidity = false;
if ( ( 0 != clockID ) && ( clockID == mCurrentClockSourceID ) )
{
if ( kIOReturnSuccess == mUSBAudioDevice->getCurClockSourceSamplingFrequency ( clockID, &clockRate, &clockValidity ) )
{
if ( NULL != mClockSelectorControl )
{
if ( !clockValidity )
{
SInt32 currentValue = mClockSelectorControl->getIntValue ();
OSArray * availableSelections = OSDynamicCast ( OSArray, mClockSelectorControl->getProperty ( kIOAudioSelectorControlAvailableSelectionsKey ) );
if ( NULL != availableSelections )
{
for ( UInt32 index = 0; index < availableSelections->getCount (); index++ )
{
OSDictionary * selectionDictionary = OSDynamicCast ( OSDictionary, availableSelections->getObject ( index ) );
if ( NULL != selectionDictionary )
{
OSNumber * selectionNumber = OSDynamicCast ( OSNumber, selectionDictionary->getObject ( kIOAudioSelectorControlSelectionValueKey ) );
if ( NULL != selectionNumber )
{
SInt32 selection = (SInt32)selectionNumber->unsigned32BitValue ();
if ( selection != currentValue )
{
clockID = ( selection >> 24 ) & 0xFF;
if ( kIOReturnSuccess == mUSBAudioDevice->getCurClockSourceSamplingFrequency ( clockID, &clockRate, &clockValidity ) && ( clockValidity ) )
{
debugIOLog ( "? AppleUSBAudioDevice[%p]::updateClockStatus () - Switch over to selection = 0x%x", this, selection );
mClockSelectorControl->setValue ( selection );
break;
}
}
}
}
}
}
}
}
else
{
if ( mShouldRepublishFormat || ( clockValidity != mClockSourceValidity ) )
{
OSArray * clockPathGroup;
OSArray * clockPath;
IOAudioSampleRate sampleRate;
sampleRate.whole = 0;
sampleRate.fraction = 0;
mClockSourceValidity = clockValidity;
clockPathGroup = mUSBAudioDevice->getClockPathGroup ( mCurrentClockPathGroupIndex );
FailIf ( NULL == clockPathGroup, Exit );
clockPath = OSDynamicCast ( OSArray, clockPathGroup->getObject ( mCurrentClockPathIndex - 1 ) );
FailIf ( NULL == clockPath, Exit )
FailIf ( kIOReturnSuccess != mUSBAudioDevice->getClockPathCurSampleRate ( &sampleRate.whole, NULL, clockPath ), Exit );
republishAvailableFormats ();
FailMessage ( kIOReturnSuccess != performFormatChange ( NULL, NULL, &sampleRate ) );
mShouldRepublishFormat = false;
}
}
}
}
Exit:
return;
}
void AppleUSBAudioEngine::runPolledTask () {
FailIf ( NULL == mUSBAudioDevice, Exit );
if ( mRestoreClockSelection )
{
OSNumber * number = OSNumber::withNumber ( mRestoreClockSelectionValue, 32 );
if ( NULL != number )
{
if ( NULL != mClockSelectorControl )
{
mClockSelectorControl->hardwareValueChanged ( number );
}
number->release ();
}
mRestoreClockSelection = false;
}
#if POLLCLOCKSTATUS
else if ( mShouldPollClockStatus )
{
if ( 0 == mPollClockStatusCounter )
{
updateClockStatus ( mCurrentClockSourceID );
}
mPollClockStatusCounter++;
if ( ( 1024 / kRefreshInterval ) == mPollClockStatusCounter ) {
mPollClockStatusCounter = 0;
}
}
#endif
Exit:
return;
}
Generated by GNU enscript 1.6.4.