[plain text]
#include "AppleiSubEngine.h"
#include "AppleUSBAudioCommon.h"
#include "AppleUSBAudioLevelControl.h"
#include "AppleUSBAudioMuteControl.h"
#include "AppleUSBAudioDictionary.h"
#include <IOKit/audio/IOAudioStream.h>
#include <IOKit/audio/IOAudioEngine.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#define kiSubFeatureUnitID 2
#define kiSubMuteControlChannelNum 0
#define kiSubVolumeControlMasterChannelNum 1
#define NUM_POWER_STATES 2
#define LOGISUBDELAY FALSE
#define super IOService
const UInt32 AppleiSubEngine::kDefaultOutputSampleRate;
const UInt32 AppleiSubEngine::kDefaultNumChannels;
const UInt32 AppleiSubEngine::kDefaultBytesPerSample;
const iSubAltInterfaceType AppleiSubEngine::kDefaultiSubAltInterface;
OSDefineMetaClassAndStructors (AppleiSubEngine, super)
#pragma mark -IOKit Routines-
void AppleiSubEngine::closeiSub (IOService * forClient) {
IOReturn result;
debugIOLog ("+ AppleiSubEngine[%p]::closeiSub (%p)", this, forClient);
if (forClient == mAudioEngine)
{
if ( ( (NULL != mMuteControl)
|| (NULL != miSubVolumeControl))
&& (NULL != mAudioEngine))
{
debugIOLog ("? AppleiSubEngine[%p]::closeiSub () - Removing iSub audio controls", this);
if (NULL != miSubVolumeControl)
{
result = mAudioEngine->removeDefaultAudioControl (miSubVolumeControl);
miSubVolumeControl->release ();
miSubVolumeControl = NULL;
#if DEBUGLOGGING
if (kIOReturnSuccess != result) debugIOLog ("! AppleiSubEngine[%p]::closeiSub () - Error 0x%x removing left iSub control", this, result);
#endif
}
if (NULL != mMuteControl)
{
result = mAudioEngine->removeDefaultAudioControl (mMuteControl);
mMuteControl->release ();
mMuteControl = NULL;
#if DEBUGLOGGING
if (kIOReturnSuccess != result) debugIOLog ("! AppleiSubEngine[%p]::closeiSub () - Error 0x%x removing mute iSub control", this, result);
#endif
}
release (); mAudioEngine = NULL;
#if DEBUGLOGGING
}
else
{
if (NULL == mMuteControl) {debugIOLog ("? AppleiSubEngine[%p]::closeiSub () - NULL == mMuteControl", this);}
if (NULL == miSubVolumeControl) {debugIOLog ("? AppleiSubEngine[%p]::closeiSub () - NULL == miSubVolumeControl", this);}
if (NULL == mAudioEngine) {debugIOLog ("? AppleiSubEngine[%p]::closeiSub () - NULL == mAudioEngine", this);}
#endif
}
}
else
{
debugIOLog ("! AppleiSubEngine[%p]::closeiSub () - The wrong client tried to close the iSub.", this);
}
debugIOLog ("- AppleiSubEngine[%p]::closeiSub (%p)", this, forClient);
}
void AppleiSubEngine::free (void) {
UInt32 frameIndex;
debugIOLog ("+ AppleiSubEngine[%p]::free ()", this);
if (NULL != mPipe)
{
mPipe->release ();
mPipe = NULL;
}
#if !defined(__ppc__) && !defined(__i386__)
if (NULL != mSampleBufferMemoryMap)
{
mSampleBufferMemoryMap->release ();
mSampleBufferMemoryMap = NULL;
}
#endif
if (NULL != mSampleBufferDescriptor)
{
mSampleBufferDescriptor->release ();
mSampleBufferDescriptor = NULL;
}
if (NULL != mSampleBuffer)
{
IOFreeAligned (mSampleBuffer, mBufferSize); mSampleBuffer = NULL;
}
for (frameIndex = 0; frameIndex < NUM_ISUB_FRAME_LISTS; frameIndex++)
{
if (NULL != mSoundBuffer[frameIndex])
{
mSoundBuffer[frameIndex]->release ();
mSoundBuffer[frameIndex] = NULL;
}
}
super::free ();
debugIOLog ("- AppleiSubEngine[%p]::free ()", this);
return;
}
bool AppleiSubEngine::openiSub (IOService * forClient, iSubRequestCloseRoutine theiSubRequestCloseRoutine) {
bool resultCode;
resultCode = FALSE;
FailIf (NULL != mAudioEngine, Exit);
mAudioEngine = OSDynamicCast (IOAudioEngine, forClient);
FailIf (NULL == mAudioEngine, Exit);
FailIf (NULL == theiSubRequestCloseRoutine, Exit);
miSubRequestCloseRoutine = theiSubRequestCloseRoutine;
mAudioEngine->pauseAudioEngine ();
mAudioEngine->beginConfigurationChange ();
retain ();
miSubVolumeControl = AppleUSBAudioLevelControl::create (kiSubFeatureUnitID,
mControlInterface->GetInterfaceNumber (),
VOLUME_CONTROL,
kiSubVolumeControlMasterChannelNum,
FALSE,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioLevelControlSubTypeLFEVolume,
kIOAudioControlUsageOutput);
FailIf (NULL == miSubVolumeControl, Exit);
mAudioEngine->addDefaultAudioControl (miSubVolumeControl);
mMuteControl = AppleUSBAudioMuteControl::create (kiSubFeatureUnitID,
mControlInterface->GetInterfaceNumber (),
0,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioControlUsageOutput,
kIOAudioToggleControlSubTypeLFEMute);
FailIf (NULL == mMuteControl, Exit);
mAudioEngine->addDefaultAudioControl (mMuteControl);
mAudioEngine->completeConfigurationChange ();
mAudioEngine->resumeAudioEngine ();
mNeedToSync = false;
resultCode = TRUE;
Exit:
debugIOLog ("- AppleiSubEngine[%p]::handleOpen (%p, %p) = %d", this, forClient, theiSubRequestCloseRoutine, resultCode);
return resultCode;
}
bool AppleiSubEngine::init (OSDictionary * properties) {
Boolean resultCode;
debugIOLog ("+ AppleiSubEngine[%p]::init (%p)", this, properties);
resultCode = FALSE;
mTerminatingDriver = FALSE;
FailIf (FALSE == super::init (properties), Exit);
resultCode = TRUE;
mFormat.altInterface = kDefaultiSubAltInterface;
mFormat.numChannels = kDefaultNumChannels;
mFormat.bytesPerSample = kDefaultBytesPerSample;
mFormat.outputSampleRate = kDefaultOutputSampleRate;
Exit:
debugIOLog ("- AppleiSubEngine[%p]::init (%p) = %d", this, properties, resultCode);
return resultCode;
}
bool AppleiSubEngine::start (IOService * provider) {
Boolean resultBool;
IOUSBFindInterfaceRequest findRequest;
IOUSBFindEndpointRequest audioIsochEndpoint;
IOReturn resultIOReturn;
UInt32 i;
UInt32 frameListNum;
UInt16 numQueued;
static IOPMPowerState iSubPowerStates[2] = {
{kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{kIOPMPowerStateVersion1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
};
debugIOLog ("+ AppleiSubEngine[%p]::start (%p)", this, provider);
resultBool = FALSE;
FailIf (FALSE == super::start (provider), Exit);
mStreamInterface = OSDynamicCast (IOUSBInterface, provider);
FailIf (NULL == mStreamInterface, Exit);
mThisInterfaceNumber = mStreamInterface->GetInterfaceNumber ();
debugIOLog ("? AppleiSubEngine[%p]::start () - AppleiSubEngine->mThisInterfaceNumber = %d", this, mThisInterfaceNumber);
mAltInterfaceID = mFormat.altInterface;
PMinit ();
mStreamInterface->joinPMtree (this);
if (pm_vars != NULL)
{
registerPowerDriver (this, iSubPowerStates, NUM_POWER_STATES);
changePowerStateTo (1);
}
mFrameListSize = CalculateNumSamplesPerBuffer (mFormat.outputSampleRate, NUM_ISUB_FRAMES_PER_LIST) * mFormat.numChannels * mFormat.bytesPerSample;
debugIOLog ("? AppleiSubEngine[%p]::start () - format = %ldHz, %ld channels, %ld bits", this, mFormat.outputSampleRate, mFormat.numChannels, mFormat.bytesPerSample * 8);
#if AML_DEBUGLOG
debugIOLog ("? AppleiSubEngine[%p]::start () - handleOpen: mFrameListSize = %d", mFrameListSize, this);
#endif
debugIOLog ("? AppleiSubEngine[%p]::start () - mFrameListSize = %d", this, mFrameListSize);
mBufferSize = CalculateNumSamplesPerBuffer (mFormat.outputSampleRate, NUM_ISUB_FRAMES_PER_LIST, NUM_ISUB_FRAME_LISTS) * mFormat.numChannels * mFormat.bytesPerSample;
debugIOLog ("? AppleiSubEngine[%p]::start () - mBufferSize = %d", this, mBufferSize);
mSampleBuffer = IOMallocAligned (mBufferSize, PAGE_SIZE);
FailIf (NULL == mSampleBuffer, Exit);
for (i = 0; i < mBufferSize / sizeof(UInt16); i++)
{
((UInt16*)mSampleBuffer)[i] = 0;
}
mSampleBufferDescriptor = IOMemoryDescriptor::withAddress (mSampleBuffer, mBufferSize, kIODirectionNone);
FailIf (NULL == mSampleBufferDescriptor, Exit);
#if !defined(__ppc__) && !defined(__i386__)
mSampleBufferMemoryMap = mSampleBufferDescriptor->map ();
FailIf (NULL == mSampleBufferMemoryMap, Exit);
#endif
FailIf (kIOReturnSuccess != PrepareFrameLists (mFrameListSize), Exit);
mShouldCloseStream = FALSE;
FailIf (FALSE == mStreamInterface->open (this), Exit);
mStreamOpened = TRUE;
resultIOReturn = mStreamInterface->SetAlternateInterface (this, kRootAlternateSetting);
FailIf (kIOReturnSuccess != resultIOReturn, Exit);
resultIOReturn = mStreamInterface->SetAlternateInterface (this, mFormat.altInterface);
FailIf (kIOReturnSuccess != resultIOReturn, Exit);
audioIsochEndpoint.type = kUSBIsoc;
audioIsochEndpoint.direction = kUSBOut;
mPipe = mStreamInterface->FindNextPipe (NULL, &audioIsochEndpoint);
FailIf (NULL == mPipe, Exit);
mPipe->retain ();
mLoopCount = 0;
mNumUSBFrameListsNotOutstanding = 0;
numQueued = 0;
mCurrentFrameList = 0;
mCurrentByteOffset = 0;
mFirstFrame = mStreamInterface->GetDevice()->GetBus()->GetFrameNumber () + kMinimumiSubFrameOffset;
for (frameListNum = mCurrentFrameList; numQueued < NUM_ISUB_FRAME_LISTS_TO_QUEUE; frameListNum++)
{
resultIOReturn = WriteFrameList (frameListNum);
FailIf (kIOReturnSuccess != resultIOReturn, Exit);
numQueued++;
}
debugIOLog ("? AppleiSubEngine[%p]::start () - writeFrameList resultIOReturn = 0x%lx", this, resultIOReturn);
findRequest.bInterfaceClass = 1;
findRequest.bInterfaceSubClass = 1;
findRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
findRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;
mControlInterface = mStreamInterface->GetDevice()->FindNextInterface (NULL, &findRequest);
FailIf (NULL == mControlInterface, Exit);
registerService ();
resultBool = TRUE;
Exit:
debugIOLog ("- AppleiSubEngine[%p]::start (%p) = %d", this, provider, resultBool);
return resultBool;
}
void AppleiSubEngine::stop (IOService *provider) {
debugIOLog("+ AppleiSubEngine::stop");
PMstop();
super::stop(provider);
debugIOLog("- AppleiSubEngine::stop");
}
bool AppleiSubEngine::willTerminate (IOService * provider, IOOptionBits options) {
bool resultCode;
debugIOLog ("+ AppleiSubEngine[%p]::willTerminate (%p, 0x%x) rc =", this, provider, options, getRetainCount ());
mTerminatingDriver = TRUE;
if (NULL != mAudioEngine)
{
(miSubRequestCloseRoutine)(mAudioEngine);
}
if (FALSE == miSubUSBRunning)
{
if ( (mStreamInterface != NULL)
&& (mStreamInterface == provider))
{
debugIOLog ("? AppleiSubEngine[%p]::willTerminate () - Closing iSub down", this);
if (NULL != mPipe)
{
mPipe->release ();
mPipe = NULL;
}
mStreamInterface->close (this);
mStreamOpened = FALSE;
}
}
else
{
mShouldCloseStream = TRUE;
}
resultCode = super::willTerminate (provider, options);
debugIOLog ("- AppleiSubEngine[%p]::willTerminate (%p, 0x%x) = %d, rc=%d", this, provider, options, resultCode, getRetainCount ());
return resultCode;
}
IOReturn AppleiSubEngine::setPowerState (unsigned long powerStateOrdinal, IOService *device) {
IOReturn result;
debugIOLog("+ AppleiSubEngine[%p]::setPowerState (%lu, %p)", this, powerStateOrdinal, device);
if (device == this)
{
switch (powerStateOrdinal)
{
case 0: debugIOLog ("? AppleiSubEngine[%p]::setPowerState () - iSub is going to sleep. Setting mIsSleeping = TRUE ...", this);
mIsSleeping = TRUE;
StopiSub ();
result = IOPMNoErr;
break;
case 1: if (mIsSleeping)
{
debugIOLog ("? AppleiSubEngine[%p]::setPowerState () - iSub is waking...");
}
mIsSleeping = FALSE;
result = IOPMNoErr;
break;
default:
result = IOPMAckImplied; }
}
else
{
result = IOPMAckImplied;
}
debugIOLog("- AppleiSubEngine[%p]::setPowerState (%lu, %p) = 0x%x", this, powerStateOrdinal, device, result);
return result;
}
#pragma mark -iSub Routines-
UInt32 AppleiSubEngine::CalculateNumSamplesPerBuffer (UInt32 sampleRate, UInt32 theNumFramesPerList, UInt32 theNumFrameLists) {
UInt32 numSamplesPerFrameList;
UInt32 totalFrames;
UInt32 numAlternateFrames;
UInt32 numAverageFrames;
UInt16 averageSamplesPerFrame;
UInt16 additionalSampleFrameFreq;
CalculateSamplesPerFrame (sampleRate, &averageSamplesPerFrame, &additionalSampleFrameFreq);
if (0 == additionalSampleFrameFreq)
{
numSamplesPerFrameList = averageSamplesPerFrame * theNumFramesPerList * theNumFrameLists;
}
else
{
totalFrames = theNumFramesPerList * theNumFrameLists;
numAlternateFrames = totalFrames / additionalSampleFrameFreq;
numAverageFrames = totalFrames - numAlternateFrames;
numSamplesPerFrameList = (numAverageFrames * averageSamplesPerFrame) + (numAlternateFrames * (averageSamplesPerFrame + 1));
}
return numSamplesPerFrameList;
}
void AppleiSubEngine::CalculateSamplesPerFrame (UInt32 sampleRate, UInt16 * averageSamplesPerFrame, UInt16 * additionalSampleFrameFreq) {
UInt32 divisor;
*averageSamplesPerFrame = sampleRate / 1000;
divisor = (sampleRate % 1000);
if (divisor)
*additionalSampleFrameFreq = 1000 / divisor;
else
*additionalSampleFrameFreq = 0;
}
IOReturn AppleiSubEngine::deviceRequest (IOUSBDevRequest * request, AppleiSubEngine * self, IOUSBCompletion * completion) {
IOReturn result;
debugIOLog ("+ AppleiSubEngine[%p]::deviceRequest (%p, %p)", self, request, completion);
result = kIOReturnSuccess;
if ( (self->mStreamInterface)
&& (request)
&& (FALSE == self->mTerminatingDriver))
{
result = self->mStreamInterface->DeviceRequest (request, completion);
}
debugIOLog ("- AppleiSubEngine[%p]::deviceRequest (%p, %p) = 0x%x", self, request, completion, result);
return result;
}
UInt32 AppleiSubEngine::GetCurrentByteCount (void) {
return mCurrentByteOffset;
}
UInt32 AppleiSubEngine::GetCurrentLoopCount (void) {
return mLoopCount;
}
#if defined(__ppc__) || defined(__i386__)
IOMemoryDescriptor * AppleiSubEngine::GetSampleBuffer (void) {
return mSampleBufferDescriptor;
}
#else
IOMemoryMap * AppleiSubEngine::GetSampleBuffer (void) {
return mSampleBufferMemoryMap;
}
#endif
IOReturn AppleiSubEngine::PrepareFrameLists (UInt32 frameListSize) {
IOReturn result;
UInt32 frameIndex;
result = kIOReturnError;
for (frameIndex = 0; frameIndex < NUM_ISUB_FRAME_LISTS; frameIndex++)
{
mUSBCompletion[frameIndex].target = (void *)this;
mUSBCompletion[frameIndex].parameter = (void *)((UInt8 *)mSampleBuffer + (frameIndex * frameListSize)); mUSBCompletion[frameIndex].action = WriteHandler;
mSoundBuffer[frameIndex] = IOMemoryDescriptor::withAddress ((UInt8 *)mUSBCompletion[frameIndex].parameter, frameListSize, kIODirectionNone);
FailIf (NULL == mSoundBuffer[frameIndex], Exit);
}
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleiSubEngine::StartiSub (void) {
UInt32 frameListNum;
UInt16 numQueued = 0; IOReturn resultCode;
debugIOLog ("+ AppleiSubEngine[%p]::StartiSub ()", this);
if (mIsSleeping)
{
for (UInt8 i = 0; i < 5 && mIsSleeping; i++)
{
IOSleep (100);
}
}
FailWithAction (TRUE == mIsSleeping, resultCode = kIOReturnOffline, Exit);
resultCode = kIOReturnError;
miSubRunning = TRUE;
#if ABORT_PIPE_ON_START
FailIf (NULL == mPipe, Exit);
mPipe->Abort (); miSubUSBRunning = FALSE;
#else
mLoopCount = 0xFFFFFFFF; mCurrentFrameList = NUM_ISUB_FRAME_LISTS - 1;
#endif
resultCode = kIOReturnSuccess;
if (FALSE == miSubUSBRunning)
{
mLoopCount = 0;
mNumUSBFrameListsNotOutstanding = 0;
numQueued = 0;
mCurrentFrameList = 0;
mCurrentByteOffset = 0;
FailIf (NULL == mStreamInterface, Exit);
mFirstFrame = mStreamInterface->GetDevice()->GetBus()->GetFrameNumber () + kMinimumiSubFrameOffset;
for (frameListNum = mCurrentFrameList; numQueued < NUM_ISUB_FRAME_LISTS_TO_QUEUE; frameListNum++)
{
resultCode = WriteFrameList (frameListNum);
FailIf (kIOReturnSuccess != resultCode, Exit);
numQueued++;
}
}
Exit:
debugIOLog ("- AppleiSubEngine[%p]::StartiSub (), result = 0x%x", this, resultCode);
return resultCode;
}
IOReturn AppleiSubEngine::StopiSub (void) {
debugIOLog ("+ AppleiSubEngine[%p]::StopiSub ()", this);
miSubRunning = FALSE;
debugIOLog ("- AppleiSubEngine[%p]::StopiSub ()", this);
return kIOReturnSuccess;
}
IOReturn AppleiSubEngine::WriteFrameList (UInt32 frameListNum) {
UInt32 frameIndex;
UInt32 firstFrame;
UInt16 averageFrameSamples;
UInt16 averageFrameSize;
UInt16 alternateFrameSize;
UInt16 additionalSampleFrameFreq;
IOReturn result;
result = kIOReturnError;
firstFrame = (frameListNum % NUM_ISUB_FRAME_LISTS_TO_QUEUE) * NUM_ISUB_FRAMES_PER_LIST;
CalculateSamplesPerFrame (mFormat.outputSampleRate, &averageFrameSamples, &additionalSampleFrameFreq);
averageFrameSize = averageFrameSamples * mFormat.numChannels * mFormat.bytesPerSample;
alternateFrameSize = (averageFrameSamples + 1) * mFormat.numChannels * mFormat.bytesPerSample;
if (additionalSampleFrameFreq)
{
for (frameIndex = 0; frameIndex < NUM_ISUB_FRAMES_PER_LIST; frameIndex++)
{
mFrames[firstFrame + frameIndex].frStatus = -1;
if ((frameIndex % additionalSampleFrameFreq) == (UInt16)(additionalSampleFrameFreq - 1))
{
mFrames[firstFrame + frameIndex].frReqCount = alternateFrameSize;
}
else
{
mFrames[firstFrame + frameIndex].frReqCount = averageFrameSize;
}
mFrames[firstFrame + frameIndex].frActCount = 0;
}
}
else
{
for (frameIndex = 0; frameIndex < NUM_ISUB_FRAMES_PER_LIST; frameIndex++)
{
mFrames[firstFrame + frameIndex].frStatus = -1;
mFrames[firstFrame + frameIndex].frReqCount = averageFrameSize;
mFrames[firstFrame + frameIndex].frActCount = 0;
}
}
FailIf (NULL == mPipe, Exit);
result = mPipe->Write (mSoundBuffer[frameListNum], mFirstFrame, NUM_ISUB_FRAMES_PER_LIST, &mFrames[firstFrame], &mUSBCompletion[frameListNum]);
if (result != kIOReturnSuccess)
{
if (mStreamInterface)
{
debugIOLog ("! AppleiSubEngine[%p]::WriteFrameList (%d) - error writing to pipe at frame %lu - current = %lu: 0x%x", this, frameListNum, (UInt32)mFirstFrame, (UInt32)mStreamInterface->GetDevice()->GetBus()->GetFrameNumber(), result);
}
miSubUSBRunning = FALSE;
}
else
{
mFirstFrame += NUM_ISUB_FRAMES_PER_LIST;
miSubUSBRunning = TRUE;
}
Exit:
return result;
}
void AppleiSubEngine::WriteHandler (void * object, void * buffer, IOReturn result, IOUSBIsocFrame * pFrames) {
AppleiSubEngine * self;
UInt64 currentUSBFrame;
UInt32 frameListToWrite;
UInt32 i;
self = (AppleiSubEngine *)object;
FailIf (TRUE == self->mIsSleeping, Exit);
if (result != kIOReturnSuccess)
{
if (result != kIOReturnAborted)
{
debugIOLog ("! AppleiSubEngine::WriteHandler () - error 0x%x", result);
}
FailIf (NULL == self->mStreamInterface, Exit);
currentUSBFrame = self->mStreamInterface->GetDevice()->GetBus()->GetFrameNumber ();
switch (result)
{
#if ABORT_PIPE_ON_START
case kIOReturnAborted:
#if AML_DEBUGLOG
debugIOLog ("? AppleiSubEngine::WriteHandler() - Aborted.");
#endif
goto Exit; break;
case kIOReturnOverrun:
#else
case kIOReturnOverrun:
case kIOReturnAborted:
#endif
default:
if (self->mFirstFrame <= currentUSBFrame)
{
self->mFirstFrame = currentUSBFrame + kMinimumiSubFrameOffset;
debugIOLog ("! AppleiSubEngine::WriteHandler () - Skipping ahead to frame %ld", self->mFirstFrame);
}
break;
}
}
for (i = 0; i < self->mFrameListSize / sizeof(UInt16); i++)
{
((UInt16*)buffer)[i] = 0;
}
if ((NUM_ISUB_FRAME_LISTS - 1) == self->mCurrentFrameList)
{
if (TRUE == self->miSubRunning)
{
self->mLoopCount++;
self->mCurrentByteOffset = 0;
}
self->mCurrentFrameList = 0;
}
else
{
self->mCurrentFrameList++;
if (TRUE == self->miSubRunning)
{
self->mCurrentByteOffset = self->mCurrentFrameList * self->mFrameListSize;
}
}
if (FALSE == self->mShouldCloseStream)
{
frameListToWrite = self->mCurrentFrameList + NUM_ISUB_FRAME_LISTS_TO_QUEUE - 1;
if (frameListToWrite >= NUM_ISUB_FRAME_LISTS)
{
frameListToWrite -= NUM_ISUB_FRAME_LISTS;
}
self->WriteFrameList (frameListToWrite);
}
AbsoluteTime t_now;
AbsoluteTime t_old;
UInt64 nanos_del;
t_old = self->mLastTime;
clock_get_uptime (&t_now);
self->mLastTime = t_now;
SUB_ABSOLUTETIME (&t_now, &t_old); absolutetime_to_nanoseconds (t_now, &nanos_del);
#if LOGISUBDELAY
nanos_del = nanos_del / (1000);
if (nanos_del > 11000)
{
debugIOLog ("? AppleiSubEngine::WriteHandler () - delta = %ld microseconds", (UInt32)(nanos_del));
}
else if (nanos_del < 9000)
{
debugIOLog ("? AppleiSubEngine::WriteHandler () - delta = %ld microseconds", (UInt32)(nanos_del));
}
#endif
if (nanos_del > ((NUM_ISUB_FRAME_LISTS_TO_QUEUE * NUM_ISUB_FRAMES_PER_LIST + 1) * 1000 * 1000))
{
self->mNeedToSync = true;
}
Exit:
if (TRUE == self->mShouldCloseStream)
{
debugIOLog ("? AppleiSubEngine[%p]::WriteHandler () - stopping: %d", self, self->mNumUSBFrameListsNotOutstanding);
self->mNumUSBFrameListsNotOutstanding++;
if (self->mNumUSBFrameListsNotOutstanding == NUM_ISUB_FRAME_LISTS_TO_QUEUE)
{
debugIOLog ("? AppleiSubEngine[%p]::WriteHandler () - iSub last write completed, closing mStreamInterface", self);
if (NULL != self->mPipe)
{
self->mPipe->release ();
self->mPipe = NULL;
}
self->mStreamInterface->close (self);
self->mStreamOpened = FALSE;
self->miSubUSBRunning = FALSE;
}
}
return;
}
Generated by GNU enscript 1.6.4.