/* This software is subject to the license described in the License.txt file included with this software distribution. You may not use this file except in compliance with this license. Copyright (c) Dynastream Innovations Inc. 2014 All rights reserved. */ #include "types.h" #include "dsi_thread.h" #include "config.h" #include "dsi_convert.h" #include "antfs_host.hpp" #include "dsi_debug.hpp" #if defined(DEBUG_FILE) #include "macros.h" #endif //#include //#include //#include //#include ////////////////////////////////////////////////////////////////////////////////// // Private Definitions ////////////////////////////////////////////////////////////////////////////////// #define DEFAULT_CHANNEL_NUMBER ((UCHAR) 0) ////////////////////////////////////////////////////////////////////////////////// // Public Functions ////////////////////////////////////////////////////////////////////////////////// ANTFSHost::ANTFSHost() { bInitFailed = FALSE; bOpen = FALSE; eWrappedState = ANTFS_STATE_IDLE; ulHostSerialNumber = 0; hANTFSThread = (DSI_THREAD_ID)NULL; // Handle for the ANTFS thread bKillThread = FALSE; bANTFSThreadRunning = FALSE; pclMsgHandler = new DSIANTDevice(); pclHost = new ANTFSHostChannel(); if (DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE) { bInitFailed = TRUE; } if (DSIThread_MutexInit(&stMutexResponseQueue) != DSI_THREAD_ENONE) { bInitFailed = TRUE; } if (DSIThread_CondInit(&stCondANTFSThreadExit) != DSI_THREAD_ENONE) { bInitFailed = TRUE; } if (DSIThread_CondInit(&stCondWaitForResponse) != DSI_THREAD_ENONE) { bInitFailed = TRUE; } } /////////////////////////////////////////////////////////////////////// ANTFSHost::~ANTFSHost() { this->Close(); delete pclHost; delete pclMsgHandler; if (bInitFailed == FALSE) { DSIThread_MutexDestroy(&stMutexCriticalSection); DSIThread_MutexDestroy(&stMutexResponseQueue); DSIThread_CondDestroy(&stCondANTFSThreadExit); DSIThread_CondDestroy(&stCondWaitForResponse); } } /////////////////////////////////////////////////////////////////////// UCHAR ANTFSHost::GetVersion(UCHAR *pucVersionString_, UCHAR ucBufferSize_) { return pclHost->GetVersion(pucVersionString_, ucBufferSize_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::Init(UCHAR ucUSBDeviceNum_, USHORT usBaudRate_) { return InitHost(ucUSBDeviceNum_, usBaudRate_, FALSE); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::Init(void) { return InitHost(0, 0 , TRUE); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::SetChannelID(UCHAR ucDeviceType_, UCHAR ucTransmissionType_) { pclHost->SetChannelID(ucDeviceType_, ucTransmissionType_); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::SetMessagePeriod(USHORT usMessagePeriod_) { pclHost->SetChannelPeriod(usMessagePeriod_); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::SetNetworkkey(UCHAR ucNetworkkey[]) { pclHost->SetNetworkKey(0, ucNetworkkey); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::SetProximitySearch(UCHAR ucSearchThreshold_) { pclHost->SetProximitySearch(ucSearchThreshold_); } /////////////////////////////////////////////////////////////////////// ANTFS_STATE ANTFSHost::GetStatus(void) { ANT_USB_STATE eUSBState; ANTFS_HOST_STATE eANTFSState; DSIThread_MutexLock(&stMutexCriticalSection); eUSBState = pclMsgHandler->GetStatus(); switch(eUSBState) { case ANT_USB_STATE_OFF: case ANT_USB_STATE_IDLE: eWrappedState = ANTFS_STATE_IDLE; break; case ANT_USB_STATE_IDLE_POLLING_USB: eWrappedState = ANTFS_STATE_IDLE_POLLING_USB; break; case ANT_USB_STATE_OPEN: eWrappedState = ANTFS_STATE_OPEN; break; } if(eWrappedState < ANTFS_STATE_OPEN) { DSIThread_MutexUnlock(&stMutexCriticalSection); return eWrappedState; } eANTFSState = pclHost->GetStatus(); switch(eANTFSState) { case ANTFS_HOST_STATE_OFF: case ANTFS_HOST_STATE_IDLE: // Keep state... break; case ANTFS_HOST_STATE_REQUESTING_SESSION: // We should not get this one // Keep as Open break; case ANTFS_HOST_STATE_DISCONNECTING: eWrappedState = ANTFS_STATE_DISCONNECTING; break; case ANTFS_HOST_STATE_SEARCHING: eWrappedState = ANTFS_STATE_SEARCHING; break; case ANTFS_HOST_STATE_CONNECTED: eWrappedState = ANTFS_STATE_CONNECTED; break; case ANTFS_HOST_STATE_AUTHENTICATING: eWrappedState = ANTFS_STATE_AUTHENTICATING; break; case ANTFS_HOST_STATE_TRANSPORT: eWrappedState = ANTFS_STATE_TRANSPORT; break; case ANTFS_HOST_STATE_DOWNLOADING: eWrappedState = ANTFS_STATE_DOWNLOADING; break; case ANTFS_HOST_STATE_UPLOADING: eWrappedState = ANTFS_STATE_UPLOADING; break; case ANTFS_HOST_STATE_ERASING: eWrappedState = ANTFS_STATE_ERASING; break; case ANTFS_HOST_STATE_SENDING: eWrappedState = ANTFS_STATE_SENDING; break; case ANTFS_HOST_STATE_RECEIVING: eWrappedState = ANTFS_STATE_RECEIVING; break; } DSIThread_MutexUnlock(&stMutexCriticalSection); return eWrappedState; } /////////////////////////////////////////////////////////////////////// void ANTFSHost::Close(void) { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): Closing ANTFS..."); #endif DSIThread_MutexLock(&stMutexCriticalSection); // Stop the response thread bKillThread = TRUE; #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): SetEvent(stCondWaitForResponse)."); #endif DSIThread_MutexLock(&stMutexResponseQueue); DSIThread_CondSignal(&stCondWaitForResponse); clResponseQueue.Clear(); DSIThread_MutexUnlock(&stMutexResponseQueue); if (hANTFSThread) { if (bANTFSThreadRunning == TRUE) { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): Killing thread."); #endif if (DSIThread_CondTimedWait(&stCondANTFSThreadExit, &stMutexCriticalSection, 9000) != DSI_THREAD_ENONE) { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): Thread not dead."); DSIDebug::ThreadWrite("ANTFSHost::Close(): Forcing thread termination..."); #endif DSIThread_DestroyThread(hANTFSThread); } else { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): Thread terminated successfully."); #endif } } DSIThread_ReleaseThreadID(hANTFSThread); hANTFSThread = (DSI_THREAD_ID)NULL; } DSIThread_MutexUnlock(&stMutexCriticalSection); pclMsgHandler->RemoveMessageProcessor((DSIANTMessageProcessor*) pclHost); pclMsgHandler->Close(); bOpen = FALSE; eWrappedState = ANTFS_STATE_IDLE; #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::Close(): Closed."); #endif } /////////////////////////////////////////////////////////////////////// void ANTFSHost::Cancel(void) { pclHost->Cancel(); } ////////////////////////////////////////////////////////////////////////////////// // ANTFS Link Layer ////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// USHORT ANTFSHost::AddSearchDevice(ANTFS_DEVICE_PARAMETERS *pstDeviceSearchMask_, ANTFS_DEVICE_PARAMETERS *pstDeviceParameters_) { return pclHost->AddSearchDevice(pstDeviceSearchMask_, pstDeviceParameters_); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::RemoveSearchDevice(USHORT usHandle_) { pclHost->RemoveSearchDevice(usHandle_); } /////////////////////////////////////////////////////////////////////// void ANTFSHost::ClearSearchDeviceList(void) { pclHost->ClearSearchDeviceList(); } /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::SearchForDevice(UCHAR ucSearchRadioFrequency_, UCHAR ucConnectedRadioFrequency_, USHORT usRadioChannelID_, BOOL bUseRequestPage_) { DSIThread_MutexLock(&stMutexCriticalSection); if ((pclMsgHandler->GetStatus() < ANT_USB_STATE_OPEN)) { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::SearchForDevice(): Not in correct state."); #endif DSIThread_MutexUnlock(&stMutexCriticalSection); return ANTFS_RETURN_FAIL; } DSIThread_MutexUnlock(&stMutexCriticalSection); return pclHost->SearchForDevice(ucSearchRadioFrequency_, ucConnectedRadioFrequency_, usRadioChannelID_, bUseRequestPage_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::GetFoundDeviceParameters(ANTFS_DEVICE_PARAMETERS *pstDeviceParameters_, UCHAR *aucFriendlyName_, UCHAR *pucBufferSize_) { return pclHost->GetFoundDeviceParameters(pstDeviceParameters_, aucFriendlyName_, pucBufferSize_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::GetFoundDeviceChannelID(USHORT *pusDeviceNumber_, UCHAR *pucDeviceType_, UCHAR *pucTransmitType_) { return pclHost->GetFoundDeviceChannelID(pusDeviceNumber_, pucDeviceType_, pucTransmitType_); } ////////////////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::Authenticate(UCHAR ucAuthenticationType_, UCHAR *pucAuthenticationString_, UCHAR ucLength_, UCHAR *pucResponseBuffer_, UCHAR *pucResponseBufferSize_, ULONG ulResponseTimeout_) { return pclHost->Authenticate(ucAuthenticationType_, pucAuthenticationString_, ucLength_, pucResponseBuffer_, pucResponseBufferSize_, ulResponseTimeout_); } ////////////////////////////////////////////////////////////////////////////////// // Always On Transport Layer ////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::Disconnect(USHORT usBlackoutTime_, UCHAR ucDisconnectType_, UCHAR ucTimeDuration_, UCHAR ucAppSpecificDuration_) { return pclHost->Disconnect(usBlackoutTime_, ucDisconnectType_, ucTimeDuration_, ucAppSpecificDuration_); } /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::Download(USHORT usFileIndex_, ULONG ulDataOffset_, ULONG ulMaxDataLength_, ULONG ulMaxBlockSize_) { return pclHost->Download(usFileIndex_, ulDataOffset_, ulMaxDataLength_, ulMaxBlockSize_); } /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::Upload(USHORT usFileIndex_, ULONG ulDataOffset_, ULONG ulDataLength_, void *pvData_, BOOL bForceOffset_, ULONG ulMaxBlockSize_) { return pclHost->Upload(usFileIndex_, ulDataOffset_, ulDataLength_, pvData_, bForceOffset_, ulMaxBlockSize_); } /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::ManualTransfer(USHORT usFileIndex_, ULONG ulDataOffset_, ULONG ulDataLength_, void *pvData_) { return pclHost->ManualTransfer(usFileIndex_, ulDataOffset_, ulDataLength_, pvData_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::GetDownloadStatus(ULONG *pulByteProgress_, ULONG *pulTotalLength_) { return pclHost->GetDownloadStatus(pulByteProgress_, pulTotalLength_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::GetTransferData(ULONG *pulDataSize_ , void *pvData_) { return pclHost->GetTransferData(pulDataSize_, pvData_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::RecoverTransferData(ULONG *pulDataSize_ , void *pvData_) { return pclHost->RecoverTransferData(pulDataSize_, pvData_); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::GetUploadStatus(ULONG *pulByteProgress_, ULONG *pulTotalLength_) { return pclHost->GetUploadStatus(pulByteProgress_, pulTotalLength_); } /////////////////////////////////////////////////////////////////////// ANTFS_RETURN ANTFSHost::EraseData(USHORT usDataFileIndex_) { return pclHost->EraseData(usDataFileIndex_); } ////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::EnablePing(BOOL bEnable_) { return pclHost->EnablePing(bEnable_); } #if defined(DEBUG_FILE) /////////////////////////////////////////////////////////////////////// void ANTFSHost::SetDebug(BOOL bDebugOn_, const char *pcDirectory_) { pclMsgHandler->SetDebug(bDebugOn_, pcDirectory_); } #endif ////////////////////////////////////////////////////////////////////////////////// // Private Functions ////////////////////////////////////////////////////////////////////////////////// DSI_THREAD_RETURN ANTFSHost::ANTFSThreadStart(void *pvParameter_) { #if defined(DEBUG_FILE) DSIDebug::ThreadInit("ANTFSHostWrapper"); #endif ((ANTFSHost *)pvParameter_)->ANTFSThread(); return 0; } /////////////////////////////////////////////////////////////////////// // ANTFS Task Thread /////////////////////////////////////////////////////////////////////// void ANTFSHost::ANTFSThread(void) { ANTFS_RESPONSE eWrappedResponse; ANT_USB_RESPONSE eUSBResponse; ANTFS_HOST_RESPONSE eANTFSResponse; bANTFSThreadRunning = TRUE; #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::ANTFSThread(): Awaiting Responses.."); #endif while (bKillThread == FALSE) { eWrappedResponse = ANTFS_RESPONSE_NONE; eUSBResponse = ANT_USB_RESPONSE_NONE; eANTFSResponse = ANTFS_HOST_RESPONSE_NONE; eANTFSResponse = pclHost->WaitForResponse(100); switch(eANTFSResponse) { case ANTFS_HOST_RESPONSE_NONE: eWrappedResponse = ANTFS_RESPONSE_NONE; break; case ANTFS_HOST_RESPONSE_INIT_PASS: eWrappedResponse = ANTFS_RESPONSE_NONE; break; case ANTFS_HOST_RESPONSE_SERIAL_FAIL: #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::ANTFSThread(): Serial fail from ANTFSHostChannel .."); #endif eWrappedResponse = ANTFS_RESPONSE_SERIAL_FAIL; break; case ANTFS_HOST_RESPONSE_REQUEST_SESSION_FAIL: // Should not get this one, as Request Session is not included from this wrapper break; case ANTFS_HOST_RESPONSE_CONNECT_PASS: eWrappedResponse = ANTFS_RESPONSE_CONNECT_PASS; break; case ANTFS_HOST_RESPONSE_DISCONNECT_PASS: eWrappedResponse = ANTFS_RESPONSE_DISCONNECT_PASS; break; case ANTFS_HOST_RESPONSE_CONNECTION_LOST: eWrappedResponse = ANTFS_RESPONSE_CONNECTION_LOST; break; case ANTFS_HOST_RESPONSE_AUTHENTICATE_NA: eWrappedResponse = ANTFS_RESPONSE_AUTHENTICATE_NA; break; case ANTFS_HOST_RESPONSE_AUTHENTICATE_PASS: eWrappedResponse = ANTFS_RESPONSE_AUTHENTICATE_PASS; break; case ANTFS_HOST_RESPONSE_AUTHENTICATE_REJECT: eWrappedResponse = ANTFS_RESPONSE_AUTHENTICATE_REJECT; break; case ANTFS_HOST_RESPONSE_AUTHENTICATE_FAIL: eWrappedResponse = ANTFS_RESPONSE_AUTHENTICATE_FAIL; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_PASS: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_PASS; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_REJECT: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_REJECT; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_INVALID_INDEX: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_INVALID_INDEX; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_FILE_NOT_READABLE: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_FILE_NOT_READABLE; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_NOT_READY: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_NOT_READY; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_FAIL: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_FAIL; break; case ANTFS_HOST_RESPONSE_DOWNLOAD_CRC_REJECTED: eWrappedResponse = ANTFS_RESPONSE_DOWNLOAD_CRC_REJECTED; break; case ANTFS_HOST_RESPONSE_UPLOAD_PASS: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_PASS; break; case ANTFS_HOST_RESPONSE_UPLOAD_REJECT: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_REJECT; break; case ANTFS_HOST_RESPONSE_UPLOAD_INVALID_INDEX: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_INVALID_INDEX; break; case ANTFS_HOST_RESPONSE_UPLOAD_FILE_NOT_WRITEABLE: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_FILE_NOT_WRITEABLE; break; case ANTFS_HOST_RESPONSE_UPLOAD_INSUFFICIENT_SPACE: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_INSUFFICIENT_SPACE; break; case ANTFS_HOST_RESPONSE_UPLOAD_FAIL: eWrappedResponse = ANTFS_RESPONSE_UPLOAD_FAIL; break; case ANTFS_HOST_RESPONSE_ERASE_PASS: eWrappedResponse = ANTFS_RESPONSE_ERASE_PASS; break; case ANTFS_HOST_RESPONSE_ERASE_FAIL: eWrappedResponse = ANTFS_RESPONSE_ERASE_FAIL; break; case ANTFS_HOST_RESPONSE_MANUAL_TRANSFER_PASS: eWrappedResponse = ANTFS_RESPONSE_MANUAL_TRANSFER_PASS; break; case ANTFS_HOST_RESPONSE_MANUAL_TRANSFER_TRANSMIT_FAIL: eWrappedResponse = ANTFS_RESPONSE_MANUAL_TRANSFER_TRANSMIT_FAIL; break; case ANTFS_HOST_RESPONSE_MANUAL_TRANSFER_RESPONSE_FAIL: eWrappedResponse = ANTFS_RESPONSE_MANUAL_TRANSFER_RESPONSE_FAIL; break; case ANTFS_HOST_RESPONSE_CANCEL_DONE: eWrappedResponse = ANTFS_RESPONSE_CANCEL_DONE; break; } if(eWrappedResponse != ANTFS_RESPONSE_NONE) { AddResponse(eWrappedResponse); } if (bKillThread) break; eUSBResponse = pclMsgHandler->WaitForResponse(100); switch(eUSBResponse) { case ANT_USB_RESPONSE_OPEN_FAIL: // Using PollUSB, so should not get this event #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::ANTFSThread(): Invalid response ANT_USB_RESPONSE_OPEN_FAIL..."); #endif case ANT_USB_RESPONSE_NONE: eWrappedResponse = ANTFS_RESPONSE_NONE; break; case ANT_USB_RESPONSE_OPEN_PASS: eWrappedResponse = ANTFS_RESPONSE_OPEN_PASS; if(ulHostSerialNumber == 0) { ulHostSerialNumber = pclMsgHandler->GetSerialNumber(); pclHost->SetSerialNumber(ulHostSerialNumber); } break; case ANT_USB_RESPONSE_SERIAL_FAIL: #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::ANTFSThread(): Serial fail from DSIANTDevice .."); #endif if(eWrappedResponse != ANTFS_RESPONSE_SERIAL_FAIL) // We do this to avoid reporting a serial failure twice eWrappedResponse = ANTFS_RESPONSE_SERIAL_FAIL; else eWrappedResponse = ANTFS_RESPONSE_NONE; break; } if(eWrappedResponse != ANTFS_RESPONSE_NONE) { AddResponse(eWrappedResponse); } } // while() #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::ANTFSThread(): Exiting thread."); #endif DSIThread_MutexLock(&stMutexCriticalSection); bANTFSThreadRunning = FALSE; DSIThread_CondSignal(&stCondANTFSThreadExit); DSIThread_MutexUnlock(&stMutexCriticalSection); } /////////////////////////////////////////////////////////////////////// BOOL ANTFSHost::InitHost(UCHAR ucUSBDeviceNum_, USHORT usBaudRate_, BOOL bAutoInit_) { if (bInitFailed == TRUE) { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::InitHost(): bInitFailed == TRUE"); #endif return FALSE; } if(bOpen) this->Close(); bKillThread = FALSE; if(bAutoInit_) { if(pclMsgHandler->Init(TRUE) == FALSE) // Poll USB { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::InitHost(): Failed to init pclMsgHandler."); #endif return FALSE; } } else { if(pclMsgHandler->Init(ucUSBDeviceNum_, usBaudRate_, TRUE) == FALSE) // Poll USB { #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::InitHost(): Failed to init pclMsgHandler."); #endif return FALSE; } } pclMsgHandler->AddMessageProcessor(DEFAULT_CHANNEL_NUMBER, (DSIANTMessageProcessor*) pclHost); // Initializes channel object if (hANTFSThread == NULL) { hANTFSThread = DSIThread_CreateThread(&ANTFSHost::ANTFSThreadStart, this); if (hANTFSThread == NULL) return FALSE; } DSIThread_MutexLock(&stMutexResponseQueue); clResponseQueue.Clear(); DSIThread_MutexUnlock(&stMutexResponseQueue); bOpen = TRUE; return TRUE; } /////////////////////////////////////////////////////////////////////// void ANTFSHost::AddResponse(ANTFS_RESPONSE eResponse_) { DSIThread_MutexLock(&stMutexResponseQueue); clResponseQueue.AddResponse(eResponse_); DSIThread_CondSignal(&stCondWaitForResponse); DSIThread_MutexUnlock(&stMutexResponseQueue); } /////////////////////////////////////////////////////////////////////// //Returns a response if there is one ready, otherwise waits the specified time for one to occur ANTFS_RESPONSE ANTFSHost::WaitForResponse(ULONG ulMilliseconds_) { ANTFS_RESPONSE stResponse = ANTFS_RESPONSE_NONE; if (bKillThread == TRUE) return ANTFS_RESPONSE_NONE; //Wait for response DSIThread_MutexLock(&stMutexResponseQueue); if(clResponseQueue.isEmpty()) { UCHAR ucResult = DSIThread_CondTimedWait(&stCondWaitForResponse, &stMutexResponseQueue, ulMilliseconds_); switch(ucResult) { case DSI_THREAD_ENONE: stResponse = clResponseQueue.GetResponse(); break; case DSI_THREAD_ETIMEDOUT: stResponse = ANTFS_RESPONSE_NONE; break; case DSI_THREAD_EOTHER: #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::WaitForResponse(): CondTimedWait() Failed!"); #endif stResponse = ANTFS_RESPONSE_NONE; break; default: #if defined(DEBUG_FILE) DSIDebug::ThreadWrite("ANTFSHost::WaitForResponse(): Error Unknown"); #endif stResponse = ANTFS_RESPONSE_NONE; break; } } else { stResponse = clResponseQueue.GetResponse(); } DSIThread_MutexUnlock(&stMutexResponseQueue); return stResponse; }