Пример #1
0
bool OutboundSSLProtocol::DoHandshake() {
    if (_sslHandshakeCompleted)
        return true;
    int32_t errorCode = SSL_ERROR_NONE;
    errorCode = SSL_connect(_pSSL);
    if (errorCode < 0) {
        int32_t error = SSL_get_error(_pSSL, errorCode);
        if (error != SSL_ERROR_WANT_READ &&
                error != SSL_ERROR_WANT_WRITE) {
            FATAL("Unable to connect SSL: %d; %s", error, STR(GetSSLErrors()));
            return false;
        }
    }

    _sslHandshakeCompleted = SSL_is_init_finished(_pSSL);

    if (!PerformIO()) {
        FATAL("Unable to perform I/O");
        return false;
    }

    if (_sslHandshakeCompleted)
        return EnqueueForOutbound();

    return true;
}
Пример #2
0
bool BaseSSLProtocol::SignalInputData(IOBuffer &buffer) {

	//1. get the SSL input buffer
	BIO *pInBio = SSL_get_rbio(_pSSL);

	//2. dump all the data from the network inside the ssl input
	BIO_write(pInBio, GETIBPOINTER(buffer),
			GETAVAILABLEBYTESCOUNT(buffer));
	buffer.IgnoreAll();

	//3. Do we have to do some handshake?
	if (!_sslHandshakeCompleted) {
		if (!DoHandshake()) {
			FATAL("Unable to do the SSL handshake");
			return false;
		}
		if (!_sslHandshakeCompleted) {
			return true;
		}
	}

	//4. Read the actual data an put it in the descrypted input buffer
	int32_t read = 0;
	while ((read = SSL_read(_pSSL, _pReadBuffer, MAX_SSL_READ_BUFFER)) > 0) {
		_inputBuffer.ReadFromBuffer(_pReadBuffer, (uint32_t) read);
	}
	if (read < 0) {
		int32_t error = SSL_get_error(_pSSL, read);
		if (error != SSL_ERROR_WANT_READ &&
				error != SSL_ERROR_WANT_WRITE) {
			FATAL("Unable to read data: %d", error);
			return false;
		}
	}

	//6. If we have pending data inside the decrypted buffer, bubble it up on the protocol stack
	if (GETAVAILABLEBYTESCOUNT(_inputBuffer) > 0) {
		if (_pNearProtocol != NULL) {
			if (!_pNearProtocol->SignalInputData(_inputBuffer)) {
				FATAL("Unable to signal near protocol for new data");
				return false;
			}
		}
	}

	//7. After the data was sent on the upper layers, we might have outstanding
	//data that needs to be sent.
	return PerformIO();
}
Пример #3
0
bool BaseSSLProtocol::EnqueueForOutbound() {
	//1. Is the SSL handshake completed?
	if (!_sslHandshakeCompleted) {
		return DoHandshake();
	}

	//2. Do we have some outstanding data?
	IOBuffer *pBuffer = _pNearProtocol->GetOutputBuffer();
	if (pBuffer == NULL)
		return true;

	//3. Encrypt the outstanding data
	if (SSL_write(_pSSL, GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer))
			!= (int32_t) GETAVAILABLEBYTESCOUNT(*pBuffer)) {
		FATAL("Unable to write %u bytes", GETAVAILABLEBYTESCOUNT(*pBuffer));
		return false;
	}
	pBuffer->IgnoreAll();

	//4. Do the actual I/O
	return PerformIO();
}
Пример #4
0
void
DevBeginIO( struct AHIRequest* ioreq,
            struct AHIBase*    AHIBase )
{
  if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  {
    KPrintF("BeginIO(0x%08lx)\n", ioreq);
  }

  ioreq->ahir_Std.io_Message.mn_Node.ln_Type = NT_MESSAGE;

  switch(ioreq->ahir_Std.io_Command)
  {

// Immediate commands
    case NSCMD_DEVICEQUERY:
    case CMD_STOP:
    case CMD_FLUSH:
      PerformIO(ioreq,AHIBase);
      break;

// Queued commands
    case CMD_RESET:
    case CMD_READ:
    case CMD_WRITE:
    case CMD_START:
      ioreq->ahir_Std.io_Flags &= ~IOF_QUICK;
      PutMsg(&ioreq->ahir_Std.io_Unit->unit_MsgPort,&ioreq->ahir_Std.io_Message);
      break;

// Unknown commands
    default:
      ioreq->ahir_Std.io_Error = IOERR_NOCMD;
      TermIO(ioreq,AHIBase);
      break;
  }
}
Пример #5
0
DWORD
InstallSoftwareDeviceInterface(IN LPGUID DeviceId,
                               IN LPGUID InterfaceId,
                               IN LPWSTR ReferenceString)
{
    HDEVINFO hDevInfo;
    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    GUID SWBusGuid = {STATIC_BUSID_SoftwareDeviceEnumerator};
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
    HANDLE hDevice;
    PSWENUM_INSTALL_INTERFACE InstallInterface;
    DWORD dwResult;

    hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL,  DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
    if (!hDevInfo)
    {
        // failed
        return GetLastError();
    }

    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
    if (!DeviceInterfaceDetailData)
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo,  &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
    {
        // failed
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    hDevice = CreateFileW(DeviceInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        // failed
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    InstallInterface  = (PSWENUM_INSTALL_INTERFACE)HeapAlloc(GetProcessHeap(), 0, sizeof(SWENUM_INSTALL_INTERFACE) + wcslen(ReferenceString) * sizeof(WCHAR));
    if (!InstallInterface)
    {
        // failed
        CloseHandle(hDevice);
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    // init install interface param
    InstallInterface->DeviceId = *DeviceId;
    InstallInterface->InterfaceId = *InterfaceId;
    wcscpy(InstallInterface->ReferenceString, ReferenceString);

    PerformIO(hDevice, IOCTL_SWENUM_INSTALL_INTERFACE, InstallInterface, sizeof(SWENUM_INSTALL_INTERFACE) + wcslen(ReferenceString) * sizeof(WCHAR), NULL, 0, NULL);
    dwResult = HeapFree(GetProcessHeap(), 0, InstallInterface);

    CloseHandle(hDevice);
    HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return dwResult;
}
Пример #6
0
void CheapieBlade::On()
{
	mLedPowerLevel = 255;
	PerformIO();
}
Пример #7
0
void CheapieBlade::Off()
{
	mLedPowerLevel = 0;
	PerformIO();

}
Пример #8
0
void	ZKMORHP_IOThreadSlave::WorkLoop()
{
	//	grab the IO guard
	bool wasLocked = mIOGuard.Lock();
	
	//	initialize some stuff
	mWorkLoopPhase = kInitializingPhase;
	mIOCycleCounter = 0;
	mOverloadCounter = 0;
	CAPropertyAddress theIsRunningAddress(kAudioDevicePropertyDeviceIsRunning);
	mDevice->GetIOCycleTelemetry().IOCycleInitializeBegin(mIOCycleCounter);
		
	try
	{
		//	and signal that the IO thread is running
		mIOGuard.NotifyAll();
		
		//	initialize the work loop stopping conditions
		mStopWorkLoop = false;
		
		//	Tell the device that the IO thread has initialized. Note that we unlock around this call
		//	due to the fact that IOCycleInitialize might not return for a while because it might
		//	have to wait for the hardware to start.
		if(wasLocked)
		{
			mIOGuard.Unlock();
		}
		
		//	tell the device that the IO cycle is initializing to start the timing services
		mDevice->StartIOCycleTimingServices();
		
		//	set the device state to know the engine is running
		mDevice->IOEngineStarted();
		
		//	notify clients that the engine is running
		mDevice->PropertiesChanged(1, &theIsRunningAddress);
		
		//	re-lock the guard
		wasLocked = mIOGuard.Lock();

		//	make sure the thread is still running before moving on
		if(!mStopWorkLoop)
		{
			//	set the time constraints for the IOThread
			SetTimeConstraints();
			
			//	initialize the clock
			mDevice->EstablishIOCycleAnchorTime(mAnchorTime);
			mFrameCounter = 0;
			
#if	Offset_For_Input
			if(mDevice->HasInputStreams())
			{
				//	the first sleep cycle as to be at least the input safety offset and a buffer's
				//	worth of time to be sure that the input data is all there
				mFrameCounter += mDevice->GetSafetyOffset(true);
			}
#endif
			
			//	enter the work loop
			mWorkLoopPhase = kRunningPhase;
			bool isInNeedOfResynch = false;
			mDevice->GetIOCycleTelemetry().IOCycleInitializeEnd(mIOCycleCounter, mAnchorTime);
			while(!mStopWorkLoop)
			{
				//	get the current time
				AudioTimeStamp theCurrentTime;
				mDevice->GetCurrentTime(theCurrentTime);
				
				//	calculate the next wake up time
				AudioTimeStamp theNextWakeUpTime = CAAudioTimeStamp::kZero;
				theNextWakeUpTime.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
				if(CalculateNextWakeUpTime(theCurrentTime, theNextWakeUpTime, isInNeedOfResynch, wasLocked))
				{
					//	sleep until the  next wake up time
					mDevice->GetIOCycleTelemetry().IOCycleWorkLoopEnd(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
					mIOGuard.WaitUntil(CAHostTimeBase::ConvertToNanos(theNextWakeUpTime.mHostTime));
					
					//	increment the counter
					++mIOCycleCounter;
					
					//	do IO if the thread wasn't stopped
					if(!mStopWorkLoop)
					{
						//	get the current time
						mDevice->GetCurrentTime(theCurrentTime);
						
						#if Log_SchedulingLatency
							//	check to see if we have incurred a large scheduling latency
							if(theCurrentTime.mHostTime > (theNextWakeUpTime.mHostTime + mAllowedLatency))
							{
								//	log it
								mLatencyLog->Capture(theNextWakeUpTime.mHostTime - mAllowedLatency, theCurrentTime.mHostTime, true);
								
								//	print how late we are
								DebugMessageN1("HP_IOThread::WorkLoop: woke up late by %f milliseconds", ((Float64)CAHostTimeBase::ConvertToNanos(theCurrentTime.mHostTime - theNextWakeUpTime.mHostTime)) / (1000.0 * 1000.0));
							}
						#endif
						
						if(theCurrentTime.mSampleTime >= (mAnchorTime.mSampleTime + mFrameCounter))
						{
							//	increment the frame counter
							mFrameCounter += mDevice->GetIOBufferFrameSize();
						
							//	the new cycle is starting
							mDevice->GetIOCycleTelemetry().IOCycleWorkLoopBegin(mIOCycleCounter, theCurrentTime);
							if(mDevice->UpdateIOCycleTimingServices())
							{
								//	something unexpected happenned with the time stamp, so resynch prior to doing IO
								AudioTimeStamp theNewAnchor = CAAudioTimeStamp::kZero;
								theNewAnchor.mSampleTime = 0;
								theNewAnchor.mHostTime = 0;
								theNewAnchor.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
								if(mDevice->EstablishIOCycleAnchorTime(theNewAnchor))
								{
									Resynch(&theNewAnchor, false);
								}
								else
								{
									Resynch(NULL, false);
								}
								
								//	re-get the current time too
								mDevice->GetCurrentTime(theCurrentTime);
							}
						
							//	do the IO
							isInNeedOfResynch = PerformIO(theCurrentTime);
						}
					}
				}
				else
				{
					//	calculating the next wake up time failed, so we just stop everything (which
					//	will get picked up when the commands are executed
					mDevice->ClearAllCommands();
					mDevice->Do_StopAllIOProcs();
				}
				
				//	execute any deferred commands
				mDevice->ExecuteAllCommands();
			}
		}
	
		mWorkLoopPhase = kTeardownPhase;
		mDevice->GetIOCycleTelemetry().IOCycleTeardownBegin(mIOCycleCounter);

		//	the work loop has finished, clear the time constraints
		ClearTimeConstraints();
		
		//	tell the device that the IO thread is torn down
		mDevice->StopIOCycleTimingServices();
	}
	catch(const CAException& inException)
	{
		DebugMessageN1("HP_IOThread::WorkLoop: Caught a CAException, code == %ld", (long int)inException.GetError());
	}
	catch(...)
	{
		DebugMessage("HP_IOThread::WorkLoop: Caught an unknown exception.");
	}
	
	//	set the device state to know the engine has stopped
	mDevice->IOEngineStopped();
		
	//	Notify clients that the IO thread is stopping. Note that we unlock around this call
	//	due to the fact that clients might want to call back into the HAL.
	if(wasLocked)
	{
		mIOGuard.Unlock();
	}

	//	Notify clients that the IO thread is stopping
	mDevice->PropertiesChanged(1, &theIsRunningAddress);
		
	//	re-lock the guard
	wasLocked = mIOGuard.Lock();

	mDevice->GetIOCycleTelemetry().IOCycleTeardownEnd(mIOCycleCounter);
	mWorkLoopPhase = kNotRunningPhase;
	mIOGuard.NotifyAll();
	mIOCycleCounter = 0;
	
	if(wasLocked)
	{
		mIOGuard.Unlock();
	}
}
Пример #9
0
void	ZKMORHP_IOThreadSlave::WorkLoopIteration(bool& isInNeedOfResynch)
{
	if (mStopWorkLoop) {
		WorkLoopTeardown();
		return;
	}
	
	try	{
		bool wasLocked = mIOGuard.Lock();
//		bool wasLocked;
		wasLocked = mIOGuard.Try(wasLocked);
		
		//	get the current time
		AudioTimeStamp theCurrentTime;
		mDevice->GetCurrentTime(theCurrentTime);
		
			//	increment the counter
			++mIOCycleCounter;
			
		//	do IO if the thread wasn't stopped
		if(!mStopWorkLoop)
		{
			if(theCurrentTime.mSampleTime >= (mAnchorTime.mSampleTime + mFrameCounter))
			{
				//	increment the frame counter
				mFrameCounter += mDevice->GetIOBufferFrameSize();
			
				//	the new cycle is starting
				mDevice->GetIOCycleTelemetry().IOCycleWorkLoopBegin(mIOCycleCounter, theCurrentTime);
				if(mDevice->UpdateIOCycleTimingServices())
				{
					//	something unexpected happened with the time stamp, so resynch prior to doing IO
					AudioTimeStamp theNewAnchor = CAAudioTimeStamp::kZero;
					theNewAnchor.mSampleTime = 0;
					theNewAnchor.mHostTime = 0;
					theNewAnchor.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
					if(mDevice->EstablishIOCycleAnchorTime(theNewAnchor))
					{
						Resynch(&theNewAnchor, false);
					}
					else
					{
						Resynch(NULL, false);
					}
					
					//	re-get the current time too
					mDevice->GetCurrentTime(theCurrentTime);
				}
			
				//	do the IO
				isInNeedOfResynch = PerformIO(theCurrentTime);
			}
		}
		
		//	calculate the next wake up time
		AudioTimeStamp theNextWakeUpTime = CAAudioTimeStamp::kZero;
		theNextWakeUpTime.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
//		bool wasLocked = false;
//		bool wasLocked = mIOGuard.Lock();
		if(CalculateNextWakeUpTime(theCurrentTime, theNextWakeUpTime, isInNeedOfResynch, wasLocked))
		{
			mDevice->GetIOCycleTelemetry().IOCycleWorkLoopEnd(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
		}
		
		//	execute any deferred commands
		mDevice->ExecuteAllCommands();
		if (wasLocked) mIOGuard.Unlock();
	} 
	catch(const CAException& inException)
	{
		DebugMessageN1("ZKMORHP_IOThreadSlave::WorkLoopIteration: Caught a CAException, code == %ld", (long int)inException.GetError());
	}
	catch(...)
	{
		DebugMessage("ZKMORHP_IOThreadSlave::WorkLoopIteration: Caught an unknown exception.");
	}
}
Пример #10
0
void	HP_IOThread::WorkLoop()
{
	//	grab the IO guard
	bool wasLocked = mIOGuard.Lock();
	
	//	initialize some stuff
	mWorkLoopPhase = kInitializingPhase;
	mIOCycleCounter = 0;
	mOverloadCounter = 0;
	CAPropertyAddress theIsRunningAddress(kAudioDevicePropertyDeviceIsRunning);
#if Use_HAL_Telemetry
	mDevice->GetIOCycleTelemetry().IOCycleInitializeBegin(mIOCycleCounter);
#else
	HAL_IOCYCLEINITIALIZEBEGIN(mIOCycleCounter);
#endif
	try
	{
		//	and signal that the IO thread is running
		mIOGuard.NotifyAll();
		
		//	initialize the work loop stopping conditions
		mStopWorkLoop = false;
		
		//	Tell the device that the IO thread has initialized. Note that we unlock around this call
		//	due to the fact that IOCycleInitialize might not return for a while because it might
		//	have to wait for the hardware to start.
		if(wasLocked)
		{
			mIOGuard.Unlock();
		}
		
		//	tell the device that the IO cycle is initializing to start the timing services
		mDevice->StartIOCycleTimingServices();
		
		//	set the device state to know the engine is running
		mDevice->IOEngineStarted();
		
		//	notify clients that the engine is running
		mDevice->PropertiesChanged(1, &theIsRunningAddress);
		
		//	re-lock the guard
		wasLocked = mIOGuard.Lock();

		//	make sure the thread is still running before moving on
		if(!mStopWorkLoop)
		{
			//	set the time constraints for the IOThread
			SetTimeConstraints();
			
			//	initialize the clock
			mDevice->EstablishIOCycleAnchorTime(mAnchorTime);
			mFrameCounter = 0;
			
#if	Offset_For_Input
			if(mDevice->HasInputStreams())
			{
				//	the first sleep cycle as to be at least the input safety offset and a buffer's
				//	worth of time to be sure that the input data is all there
				mFrameCounter += mDevice->GetSafetyOffset(true);
			}
#endif
			
			//	get the current time
			AudioTimeStamp theCurrentTime;
			mDevice->GetCurrentTime(theCurrentTime);
				
			//	enter the work loop
			mWorkLoopPhase = kRunningPhase;
			bool isInNeedOfResynch = false;
			bool isCheckingForOverloads = false;
			Float64 theIOBufferFrameSize = mDevice->GetIOBufferFrameSize();
#if Use_HAL_Telemetry
			mDevice->GetIOCycleTelemetry().IOCycleInitializeEnd(mIOCycleCounter, mAnchorTime);
			mDevice->GetIOCycleTelemetry().IOCycleWorkLoopBegin(mIOCycleCounter, theCurrentTime);
#else
			HAL_IOCYCLEINITIALIZEEND(mIOCycleCounter, mAnchorTime);
			HAL_IOCYCLEWORKLOOPBEGIN(mIOCycleCounter, theCurrentTime);
#endif
			while(!mStopWorkLoop)
			{
				//	get the new IO buffer frame size
				Float64 theNewIOBufferFrameSize = mDevice->GetIOBufferFrameSize();
				
				//	initialize the next wake up time
				AudioTimeStamp theNextWakeUpTime = CAAudioTimeStamp::kZero;
				theNextWakeUpTime.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
				
				//	get the current time
				mDevice->GetCurrentTime(theCurrentTime);
				
				//	we have to run a special, untimed IO cycle if the IO buffer size changed
				if((theNewIOBufferFrameSize != theIOBufferFrameSize) && (theCurrentTime.mSampleTime >= (mAnchorTime.mSampleTime + mFrameCounter)))
				{
					//	mark the end of the previous cycle
#if Use_HAL_Telemetry
					mDevice->GetIOCycleTelemetry().IOCycleWorkLoopEnd(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
#else
					HAL_IOCYCLEWORKLOOPEND(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
#endif
					//	increment the cycle counter
					++mIOCycleCounter;
					
					//	increment the frame counter
					mFrameCounter += theIOBufferFrameSize;
				
					//	the new cycle is starting
#if Use_HAL_Telemetry
					mDevice->GetIOCycleTelemetry().IOCycleWorkLoopBegin(mIOCycleCounter, theCurrentTime);
#else
					HAL_IOCYCLEWORKLOOPBEGIN(mIOCycleCounter, theCurrentTime);
#endif

					//	do the IO, note that we don't need to update the timing services for this special cycle
					isInNeedOfResynch = PerformIO(theCurrentTime, theIOBufferFrameSize);
					
					//	turn off overload checking for the next cycle to be nice to clients
					isCheckingForOverloads = false;
				}
				
				//	calculate the next wake up time
				if(CalculateNextWakeUpTime(theCurrentTime, theIOBufferFrameSize, theNextWakeUpTime, isCheckingForOverloads, isInNeedOfResynch, wasLocked))
				{
					//	sleep until the  next wake up time
#if Use_HAL_Telemetry
					mDevice->GetIOCycleTelemetry().IOCycleWorkLoopEnd(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
#else
					HAL_IOCYCLEWORKLOOPEND(mIOCycleCounter, theCurrentTime, theNextWakeUpTime);
#endif

					mIOGuard.WaitUntil(CAHostTimeBase::ConvertToNanos(theNextWakeUpTime.mHostTime));
					
					//	increment the cycle counter
					++mIOCycleCounter;
					
					//	make sure overload checking is enabled
					isCheckingForOverloads = true;
					
					//	do IO if the thread wasn't stopped
					if(!mStopWorkLoop)
					{
						//	get the current time
						mDevice->GetCurrentTime(theCurrentTime);
						
						if(theCurrentTime.mSampleTime >= (mAnchorTime.mSampleTime + mFrameCounter))
						{
							//	increment the frame counter
							mFrameCounter += theIOBufferFrameSize;
						
							//	refresh the current buffer size
							theIOBufferFrameSize = theNewIOBufferFrameSize;
							
							//	the new cycle is starting
#if Use_HAL_Telemetry
							mDevice->GetIOCycleTelemetry().IOCycleWorkLoopBegin(mIOCycleCounter, theCurrentTime);
#else
							HAL_IOCYCLEWORKLOOPBEGIN(mIOCycleCounter, theCurrentTime);
#endif

							if(mDevice->UpdateIOCycleTimingServices())
							{
								//	something unexpected happenned with the time stamp, so resynch prior to doing IO
								AudioTimeStamp theNewAnchor = CAAudioTimeStamp::kZero;
								theNewAnchor.mSampleTime = 0;
								theNewAnchor.mHostTime = 0;
								theNewAnchor.mFlags = kAudioTimeStampSampleTimeValid + kAudioTimeStampHostTimeValid + kAudioTimeStampRateScalarValid;
								if(mDevice->EstablishIOCycleAnchorTime(theNewAnchor))
								{
									Resynch(&theNewAnchor, false);
								}
								else
								{
									Resynch(NULL, false);
								}
								
								//	re-get the current time too
								mDevice->GetCurrentTime(theCurrentTime);
								
								//	mark the telemetry
#if Use_HAL_Telemetry
								mDevice->GetIOCycleTelemetry().Resynch(GetIOCycleNumber(), mAnchorTime);
#else
								HAL_RESYNCH(GetIOCycleNumber(), mAnchorTime);
#endif
							}
						
							//	do the IO
							isInNeedOfResynch = PerformIO(theCurrentTime, theIOBufferFrameSize);
						}
					}
				}
				else
				{
					//	calculating the next wake up time failed, so we just stop everything (which
					//	will get picked up when the commands are executed
					mDevice->ClearAllCommands();
					mDevice->Do_StopAllIOProcs();
				}
				
				//	execute any deferred commands
				mDevice->ExecuteAllCommands();
			}
		}
	
		mWorkLoopPhase = kTeardownPhase;
#if Use_HAL_Telemetry
		mDevice->GetIOCycleTelemetry().IOCycleTeardownBegin(mIOCycleCounter);
#else
		HAL_IOCYCLETEARDOWNBEGIN(mIOCycleCounter);
#endif

		//	the work loop has finished, clear the time constraints
		ClearTimeConstraints();
		
		//	tell the device that the IO thread is torn down
		mDevice->StopIOCycleTimingServices();
	}
	catch(const CAException& inException)
	{
		DebugMessageN1("HP_IOThread::WorkLoop: Caught a CAException, code == %ld", (long int)inException.GetError());
	}
	catch(...)
	{
		DebugMessage("HP_IOThread::WorkLoop: Caught an unknown exception.");
	}
	
	//	set the device state to know the engine has stopped
	mDevice->IOEngineStopped();
		
	//	Notify clients that the IO thread is stopping. Note that we unlock around this call
	//	due to the fact that clients might want to call back into the HAL.
	if(wasLocked)
	{
		mIOGuard.Unlock();
	}

	//	Notify clients that the IO thread is stopping
	mDevice->PropertiesChanged(1, &theIsRunningAddress);
		
	//	re-lock the guard
	wasLocked = mIOGuard.Lock();

#if Use_HAL_Telemetry
	mDevice->GetIOCycleTelemetry().IOCycleTeardownEnd(mIOCycleCounter);
#else
	HAL_IOCYCLETEARDOWNEND(mIOCycleCounter);
#endif

	mWorkLoopPhase = kNotRunningPhase;
	mIOGuard.NotifyAll();
	mIOCycleCounter = 0;
	
	if(wasLocked)
	{
		mIOGuard.Unlock();
	}
}