/* HWML Motion Controller Interface (C) Aryeh Eiderman */ #include "HWML.h" /* OS Dependent - Windows */ #if defined(WIN32) || defined(WINCE) #include #ifndef WINCE #pragma comment(lib, "user32.lib") #endif typedef struct { void *hCom; CRITICAL_SECTION Mutex; CRITICAL_SECTION BatchMutex; CRITICAL_SECTION ReportMutex; int PeekChar; char ReportBuffer[18]; signed short QueuePos; long X; long Y; long Z; long W; int ReportRequested; int ReportReceived; int VOverride; } HWML_Handle; int HWML_IsConnectionOK(void *HWMLHandle) { if (HWMLHandle) { DWORD Errors; COMSTAT Stat; if (ClearCommError(((HWML_Handle *)HWMLHandle)->hCom, &Errors, &Stat)) { return Errors ? 0 : 1; } } return 0; } static int HWML_CanSend(void *HWMLHandle) { if (HWMLHandle) { DWORD Errors; COMSTAT Stat; if (ClearCommError(((HWML_Handle *)HWMLHandle)->hCom, &Errors, &Stat)) { return Stat.cbOutQue ? 0 : 1; } } return 0; } static int HWML_CanReceive(void *HWMLHandle) { if (HWMLHandle) { DWORD Errors; COMSTAT Stat; Errors = 0; Stat.cbInQue = 0; if (ClearCommError(((HWML_Handle *)HWMLHandle)->hCom, &Errors, &Stat)) { return Stat.cbInQue; } } return 0; } static void *HWML_OpenPort(int PortNo, unsigned long BaudRate) { void *hCom = INVALID_HANDLE_VALUE; HWML_Handle *ret = 0; #ifdef WINCE if (BaudRate) { char pcCommPort[24]="COM"; #else if (PortNo && BaudRate) { char pcCommPort[24]="\\\\.\\COM"; #endif #ifdef UNICODE char *p = pcCommPort; wchar_t wtemp[24]; wchar_t *pw = wtemp; #endif #ifdef WINCE _itoa(PortNo, pcCommPort + 3, 10); strcat(pcCommPort, ":"); #else _itoa(PortNo, pcCommPort + 7, 10); #endif #ifdef UNICODE while (*p) { *pw = (wchar_t)(*p); ++p; ++pw; } *pw = (wchar_t)*p; hCom = CreateFile(wtemp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 ); #else hCom = CreateFile(pcCommPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 ); #endif if (hCom != INVALID_HANDLE_VALUE) { int ok = 0; DCB dcb; dcb.DCBlength = sizeof(dcb); SetupComm(hCom, 256, 256); if (GetCommState(hCom, &dcb)) { dcb.BaudRate = BaudRate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_DISABLE; if (SetCommState(hCom, &dcb)) { COMMTIMEOUTS cto; cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutMultiplier = 0; cto.ReadTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 0; if (SetCommTimeouts(hCom, &cto)) { EscapeCommFunction(hCom, CLRRTS); EscapeCommFunction(hCom, SETDTR); Sleep(100); EscapeCommFunction(hCom, CLRDTR); Sleep(1000); PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); ok = 1; } } } if (!ok) { CloseHandle(hCom); hCom = INVALID_HANDLE_VALUE; } } } if (hCom != INVALID_HANDLE_VALUE) { ret = (HWML_Handle *)malloc(sizeof(HWML_Handle)); if (ret) { ret->hCom = hCom; InitializeCriticalSection(&(ret->Mutex)); InitializeCriticalSection(&(ret->BatchMutex)); InitializeCriticalSection(&(ret->ReportMutex)); ret->PeekChar = -1; ret->ReportRequested = 0; ret->ReportReceived = 0; ret->VOverride = 10; } else { CloseHandle(hCom); hCom = INVALID_HANDLE_VALUE; } } return (hCom == INVALID_HANDLE_VALUE) ? 0 : ret; } static void HWML_ClosePort(void **pHWMLHandle) { if (pHWMLHandle ? (*pHWMLHandle) : 0) { if (((HWML_Handle *)(*pHWMLHandle))->hCom != INVALID_HANDLE_VALUE) { CloseHandle(((HWML_Handle *)(*pHWMLHandle))->hCom); } LeaveCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->Mutex)); DeleteCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->Mutex)); LeaveCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->BatchMutex)); DeleteCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->BatchMutex)); LeaveCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->ReportMutex)); DeleteCriticalSection( &(((HWML_Handle *)(*pHWMLHandle))->ReportMutex)); free(*pHWMLHandle); *pHWMLHandle = 0; } } static int HWML_ProcessMessages() { int ret = 0; MSG AnyMsg; while (PeekMessage(&AnyMsg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&AnyMsg); DispatchMessage(&AnyMsg); ret = 1; } return ret; } void HWML_Sleep(unsigned long Milliseconds) { long ms; ms = Milliseconds; if (!HWML_ProcessMessages()) { if (ms) { Sleep(1); --ms; } } if (ms) { Sleep(ms); } } static void HWML_Lock(void *HWMLHandle) { if (HWMLHandle) { EnterCriticalSection( &(((HWML_Handle *)HWMLHandle)->Mutex)); } } static void HWML_Unlock(void *HWMLHandle) { if (HWMLHandle) { LeaveCriticalSection( &(((HWML_Handle *)HWMLHandle)->Mutex)); } } static void HWML_BatchLock(void *HWMLHandle) { if (HWMLHandle) { EnterCriticalSection( &(((HWML_Handle *)HWMLHandle)->BatchMutex)); } } static void HWML_BatchUnlock(void *HWMLHandle) { if (HWMLHandle) { LeaveCriticalSection( &(((HWML_Handle *)HWMLHandle)->BatchMutex)); } } static void HWML_ReportLock(void *HWMLHandle) { if (HWMLHandle) { EnterCriticalSection( &(((HWML_Handle *)HWMLHandle)->ReportMutex)); } } static void HWML_ReportUnlock(void *HWMLHandle) { if (HWMLHandle) { LeaveCriticalSection( &(((HWML_Handle *)HWMLHandle)->ReportMutex)); } } static int HWML_Read(void *HWMLHandle, void *pBuffer, unsigned long NumberOfBytesToRead, unsigned long *pNumberOfBytesRead) { int ret = 0; if (HWMLHandle && NumberOfBytesToRead) { if (((HWML_Handle *)HWMLHandle)->PeekChar == -1) { ret = ReadFile(((HWML_Handle *)(HWMLHandle))->hCom, pBuffer, NumberOfBytesToRead, pNumberOfBytesRead, 0); } else { ret = 1; *((unsigned char *)pBuffer) = (unsigned char) ((HWML_Handle *)HWMLHandle)->PeekChar; ((HWML_Handle *)HWMLHandle)->PeekChar = -1; (*pNumberOfBytesRead) = 1; if (NumberOfBytesToRead > 1) { if (ReadFile(((HWML_Handle *)(HWMLHandle))->hCom, ((unsigned char *)pBuffer) + 1, NumberOfBytesToRead - 1, pNumberOfBytesRead, 0)) { (*pNumberOfBytesRead)++; } } } } if ((!ret) && pNumberOfBytesRead) *pNumberOfBytesRead = 0; return ret; } static int HWML_Write(void *HWMLHandle, const void *pBuffer, unsigned long NumberOfBytesToWrite, unsigned long *pNumberOfBytesWritten) { int ret = 0; if (HWMLHandle) { ret = WriteFile(((HWML_Handle *)(HWMLHandle))->hCom, pBuffer, NumberOfBytesToWrite, pNumberOfBytesWritten, 0); } if ((!ret) && pNumberOfBytesWritten) *pNumberOfBytesWritten = 0; return ret; } static int HWML_Peek(void *HWMLHandle) { int ret = -1; if (HWMLHandle) { ret = ((HWML_Handle *)HWMLHandle)->PeekChar; if (ret == -1) { if (HWML_CanReceive(HWMLHandle)) { unsigned char ch; unsigned long len = 0; if (ReadFile(((HWML_Handle *)(HWMLHandle))->hCom, &ch, 1, &len, 0)) { if (len == 1) { ((HWML_Handle *)HWMLHandle)->PeekChar = ch; ret = ch; } } } } } return ret; } #endif /* OS Independent */ void *HWML_Open(const char *Connection) { HWML_Handle *hCom; int PortNo; unsigned long BaudRate; char *t; int ok; char buf[4]; unsigned long len; int pass; hCom = 0; ok = 0; if (Connection ? (*Connection) : 0) { PortNo = 0; BaudRate = 0; t = (char *)Connection; while ((*t) && (((*t) < '0') || (('9' < (*t))))) ++t; while (('0' <= (*t)) && ((*t) <= '9')) { PortNo = (PortNo * 10) + ((*t) - '0'); ++t; } while ((*t) && (((*t) < '0') || (('9' < (*t))))) ++t; while (('0' <= (*t)) && ((*t) <= '9')) { BaudRate = (BaudRate * 10) + ((*t) - '0'); ++t; } if (!BaudRate) { BaudRate = 921600; } hCom = (HWML_Handle *)HWML_OpenPort(PortNo, BaudRate); if (hCom) { ok = 0; buf[0] = 'A'; buf[1] = '\r'; buf[2] = '\0'; if (HWML_Write(hCom, buf, 2, &len)) { pass = 1000; len = 0; while (pass && (!len) && (!ok)) { if (HWML_CanReceive(hCom)) { if (HWML_Read(hCom, buf, 1, &len)) { if ((len == 1) && (buf[0] == '\r')) { ok = 1; } else { pass = 0; } } else { pass = 0; } } else { HWML_Sleep(1); --pass; } } } if (!ok) { HWML_ClosePort((void **)(&hCom)); } } } return hCom; } void HWML_Close(void **pHWMLHandle) { if (pHWMLHandle ? (*pHWMLHandle) : 0) { HWML_ClosePort(pHWMLHandle); } } static int HWML_FillReportBuffer(void *HWMLHandle) { int ret; char ch; int i; unsigned long len; ret = 0; HWML_Lock(HWMLHandle); if (((HWML_Handle *)(HWMLHandle))->ReportRequested ? (HWML_Peek(HWMLHandle) == 18) : 0) { HWML_Read(HWMLHandle, &ch, 1, &len); if (HWML_IsConnectionOK(HWMLHandle)) { ret = 1; i = 18; while (i && ret) { while ((!HWML_CanReceive(HWMLHandle)) && HWML_IsConnectionOK(HWMLHandle)) { HWML_Sleep(0); } if (HWML_Read(HWMLHandle, ((HWML_Handle *)(HWMLHandle))->ReportBuffer + (18 - i), 1, &len)) { if (len != 1) { ret = 0; } } else { ret = 0; } --i; } if (ret) { memcpy(&(((HWML_Handle *)(HWMLHandle))->QueuePos), ((HWML_Handle *)(HWMLHandle))->ReportBuffer , 2); memcpy(&(((HWML_Handle *)(HWMLHandle))->X), ((HWML_Handle *)(HWMLHandle))->ReportBuffer + 2, 4); memcpy(&(((HWML_Handle *)(HWMLHandle))->Y), ((HWML_Handle *)(HWMLHandle))->ReportBuffer + 6, 4); memcpy(&(((HWML_Handle *)(HWMLHandle))->Z), ((HWML_Handle *)(HWMLHandle))->ReportBuffer + 10, 4); memcpy(&(((HWML_Handle *)(HWMLHandle))->W), ((HWML_Handle *)(HWMLHandle))->ReportBuffer + 14, 4); } } ((HWML_Handle *)(HWMLHandle))->ReportRequested = 0; ((HWML_Handle *)(HWMLHandle))->ReportReceived = ret; } else { ret = ((HWML_Handle *)(HWMLHandle))->ReportReceived; } HWML_Unlock(HWMLHandle); return ret; } int HWML_Poll(void *HWMLHandle) { int PeekedChar; HWML_Lock(HWMLHandle); PeekedChar = HWML_Peek(HWMLHandle); HWML_Unlock(HWMLHandle); if (PeekedChar == -1) { return 0; } else { if (PeekedChar == 18) { return 2; } else { return 1; } } } int HWML_WaitForAnswer(void *HWMLHandle, int OrReport) { int PeekedChar; int AttemptsWithoutSleep; AttemptsWithoutSleep = 1000; while (1) { if (HWML_FillReportBuffer(HWMLHandle)) { if (OrReport) { return 2; } } HWML_Lock(HWMLHandle); PeekedChar = HWML_Peek(HWMLHandle); HWML_Unlock(HWMLHandle); if ((PeekedChar != -1) && (PeekedChar != 18)) { return 1; } if (HWML_IsConnectionOK(HWMLHandle)) { if (AttemptsWithoutSleep) { HWML_Sleep(0); --AttemptsWithoutSleep; } else { HWML_Sleep(1); } } else { return 0; } } return 1; } int HWML_SendBinary(void *HWMLHandle, const char Command, const long QValue1, const long QValue2, const long QValue3, const long QValue4) { int ret; char buf; unsigned long len; ret = 0; if (HWMLHandle) { buf = '\0'; HWML_Lock(HWMLHandle); if (HWML_Write(HWMLHandle, &buf, 1, &len)) { if (len == 1) HWML_Write(HWMLHandle, &Command, 1, &len); if (len == 1) HWML_Write(HWMLHandle, &QValue1, 4, &len); if (len == 4) HWML_Write(HWMLHandle, &QValue2, 4, &len); if (len == 4) HWML_Write(HWMLHandle, &QValue3, 4, &len); if (len == 4) HWML_Write(HWMLHandle, &QValue4, 4, &len); if (len == 4) ret = 1; } HWML_Unlock(HWMLHandle); } return ret; } int HWML_ReceiveBinary(void *HWMLHandle, long *pAValue1, long *pAValue2, long *pAValue3, long *pAValue4) { int ret, cln, PeekedChar; char buf[4]; unsigned long len; ret = 0; cln = 1; if (HWMLHandle) { HWML_Lock(HWMLHandle); PeekedChar = HWML_Peek(HWMLHandle); if ((PeekedChar == 0) || (PeekedChar == 16)) { HWML_Read(HWMLHandle, buf, 1, &len); if (len == 1) { if (*buf) { HWML_Read(HWMLHandle, pAValue1 ? (void *)pAValue1 : buf, 4, &len); if (len == 4) HWML_Read(HWMLHandle, pAValue2 ? (void *)pAValue2 : buf, 4, &len); if (len == 4) HWML_Read(HWMLHandle, pAValue3 ? (void *)pAValue3 : buf, 4, &len); if (len == 4) HWML_Read(HWMLHandle, pAValue4 ? (void *)pAValue4 : buf, 4, &len); if (len == 4) { ret = 1; cln = 0; } } else { ret = 1; } } } HWML_Unlock(HWMLHandle); } if (cln) { if (pAValue1) *pAValue1 = HWML_NO_VALUE; if (pAValue2) *pAValue2 = HWML_NO_VALUE; if (pAValue3) *pAValue3 = HWML_NO_VALUE; if (pAValue4) *pAValue4 = HWML_NO_VALUE; } return ret; } int HWML_SendLiteral(void *HWMLHandle, const char *Query) { int ret; char buf; char *t; unsigned long slen; unsigned long len; if (HWMLHandle) { if (Query) { t = (char *)Query; slen = 0; if (t) { while (*t) { ++slen; ++t; } } } else { slen = 0; } len = 0; HWML_Lock(HWMLHandle); if (slen) { HWML_Write(HWMLHandle, Query, slen, &len); } if (len == slen) { buf = '\r'; HWML_Write(HWMLHandle, &buf, 1, &len); if (len == 1) ret = 1; } HWML_Unlock(HWMLHandle); } return ret; } int HWML_ReceiveLiteral(void *HWMLHandle, char *Answer) { int ret, PeekedChar; char buf; unsigned long len; char *a; ret = 0; if (HWMLHandle) { HWML_Lock(HWMLHandle); PeekedChar = HWML_Peek(HWMLHandle); if ((PeekedChar == '\r') || (PeekedChar > ' ')) { a = Answer; buf = '\0'; while ((buf != '\r') && (!ret)) { if (HWML_Read(HWMLHandle, &buf, 1, &len)) { if (len == 1) { if (buf == '\r') { if (a) { *a = '\0'; } ret = 1; } else { if (a) { *a = buf; ++a; } } } else { buf = '\r'; } } else { buf = '\r'; } } } HWML_Unlock(HWMLHandle); } if (Answer && (!ret)) { *Answer = '\0'; } return ret; } static int HWML_InterruptQueueExecution(void *HWMLHandle, char buf) { unsigned long len; int NeedSleep; len = 0; NeedSleep = 0; if (HWML_IsConnectionOK(HWMLHandle)) { HWML_Lock(HWMLHandle); if (buf == 18) { if (((HWML_Handle *)HWMLHandle)->ReportRequested) { len = 1; } else { ((HWML_Handle *)HWMLHandle)->ReportReceived = 0; HWML_Write(HWMLHandle, &buf, 1, &len); if (len == 1) { ((HWML_Handle *)HWMLHandle)->ReportRequested = 1; NeedSleep = 1; } } } else { HWML_Write(HWMLHandle, &buf, 1, &len); } HWML_Unlock(HWMLHandle); if (NeedSleep) { HWML_Sleep(1); } } return len == 1 ? 1 : 0; } int HWML_AbortQueueExecution(void *HWMLHandle) { return HWML_InterruptQueueExecution(HWMLHandle, 1); } int HWML_PauseQueueExecution(void *HWMLHandle) { return HWML_InterruptQueueExecution(HWMLHandle, 2); } int HWML_ResumeQueueExecution(void *HWMLHandle) { return HWML_InterruptQueueExecution(HWMLHandle, 3); } int HWML_AbortQueueExecutionGraceful(void *HWMLHandle) { return HWML_InterruptQueueExecution(HWMLHandle, 4); } int HWML_OverrideVelocity(void *HWMLHandle, int Percent) { int ret; int ovr; int now; int incr; char c; ret = 0; if (HWMLHandle) { now = ((HWML_Handle *)HWMLHandle)->VOverride; if (Percent >= 0) { if (Percent == 0) { HWML_InterruptQueueExecution(HWMLHandle, 6); now = 10; ((HWML_Handle *)HWMLHandle)->VOverride = now; } else { ovr = (Percent + 5) / 10; if (ovr <= 0) { ovr = 1; } else { if (ovr > 20) { ovr = 20; } } if (ovr != now) { if (ovr < now) { incr = -1; c = 5; } else { incr = 1; c = 7; } ret = 1; while (ret && (now != ovr)) { ret &= HWML_InterruptQueueExecution( HWMLHandle, c); if (ret) { now += incr; } } ((HWML_Handle *)HWMLHandle)->VOverride = now; } } } } else { now = 10; } return now * 10; } int HWML_RequestQueueExecutionReport(void *HWMLHandle) { return HWML_InterruptQueueExecution(HWMLHandle, 18); } int HWML_ReceiveQueueExecutionReport(void *HWMLHandle, signed short *pQueuePos, long *pX, long *pY, long *pZ, long *pW) { int ret; ret = 0; if (pQueuePos) *pQueuePos = -1; if (pX) *pX = HWML_NO_VALUE; if (pY) *pY = HWML_NO_VALUE; if (pZ) *pZ = HWML_NO_VALUE; if (pW) *pW = HWML_NO_VALUE; if (HWML_FillReportBuffer(HWMLHandle)) { HWML_Lock(HWMLHandle); if (((HWML_Handle *)HWMLHandle)->ReportReceived) { if (pQueuePos) *pQueuePos = ((HWML_Handle *)HWMLHandle)->QueuePos; if (pX) *pX = ((HWML_Handle *)HWMLHandle)->X; if (pY) *pY = ((HWML_Handle *)HWMLHandle)->Y; if (pZ) *pZ = ((HWML_Handle *)HWMLHandle)->Z; if (pW) *pW = ((HWML_Handle *)HWMLHandle)->W; ret = 1; } HWML_Unlock(HWMLHandle); } return ret; } int HWML_ReportQueueExecution(void *HWMLHandle, signed short *pQueuePos, long *pX, long *pY, long *pZ, long *pW) { int ret; ret = 0; HWML_ReportLock(HWMLHandle); if (HWML_RequestQueueExecutionReport(HWMLHandle)) { ret = 2; while (ret == 2) { if (HWML_ReceiveQueueExecutionReport(HWMLHandle, pQueuePos, pX, pY, pZ, pW)) { ret = 1; } else { if (HWML_IsConnectionOK(HWMLHandle)) { HWML_Sleep(1); } else { ret = 0; } } } } HWML_ReportUnlock(HWMLHandle); return ret; } int HWML_TalkBinary(void *HWMLHandle, const char Command, const long QValue1, const long QValue2, const long QValue3, const long QValue4, long *pAValue1, long *pAValue2, long *pAValue3, long *pAValue4) { int ret, cln; ret = 0; cln = 1; HWML_BatchLock(HWMLHandle); if (HWML_SendBinary(HWMLHandle, (char) ((pAValue1 || pAValue2 || pAValue3 || pAValue4) ? Command : HWML_DONT_ANSWER(Command)), QValue1, QValue2, QValue3, QValue4)) { if (HWML_WaitForAnswer(HWMLHandle, 0)) { ret = (HWML_ReceiveBinary(HWMLHandle, pAValue1, pAValue2, pAValue3, pAValue4)); cln = 0; } } HWML_BatchUnlock(HWMLHandle); if (cln) { if (pAValue1) *pAValue1 = HWML_NO_VALUE; if (pAValue2) *pAValue2 = HWML_NO_VALUE; if (pAValue3) *pAValue3 = HWML_NO_VALUE; if (pAValue4) *pAValue4 = HWML_NO_VALUE; } return ret; } int HWML_TalkLiteral(void *HWMLHandle, const char *Query, char *Answer) { int ret; ret = 0; HWML_BatchLock(HWMLHandle); if (HWML_SendLiteral(HWMLHandle, Query)) { if (HWML_WaitForAnswer(HWMLHandle, 0)) { ret = (HWML_ReceiveLiteral(HWMLHandle, Answer)); } } HWML_BatchUnlock(HWMLHandle); if (Answer && (!ret)) { *Answer = '\0'; } return ret; } /* LPT Emulation */ int HWML_PerformLPT(void *HWMLHandle, unsigned char *pDATAToSet, unsigned char *pSTATUSToSet, unsigned char *pCONTROLToSet, unsigned char *pDATAToGet, unsigned char *pSTATUSToGet, unsigned char *pCONTROLToGet) { unsigned char LPTCommand, Err; unsigned long len; len = 0; if (HWMLHandle && (pDATAToSet || pSTATUSToSet || pCONTROLToSet || pDATAToGet || pSTATUSToGet || pCONTROLToGet)) { LPTCommand = 0x88; if (pDATAToSet) LPTCommand |= 0x10; if (pSTATUSToSet) LPTCommand |= 0x20; if (pCONTROLToSet) LPTCommand |= 0x40; if (pDATAToGet) LPTCommand |= 0x01; if (pSTATUSToGet) LPTCommand |= 0x02; if (pCONTROLToGet) LPTCommand |= 0x04; HWML_BatchLock(HWMLHandle); HWML_Lock(HWMLHandle); HWML_Write(HWMLHandle, &LPTCommand, 1, &len); if (len && pDATAToSet) { HWML_Write(HWMLHandle, pDATAToSet, 1, &len); } if (len && pSTATUSToSet) { HWML_Write(HWMLHandle, pSTATUSToSet, 1, &len); } if (len && pCONTROLToSet) { HWML_Write(HWMLHandle, pCONTROLToSet, 1, &len); } HWML_Unlock(HWMLHandle); if (len) { if (HWML_WaitForAnswer(HWMLHandle, 0)) { HWML_Lock(HWMLHandle); HWML_Read(HWMLHandle, &LPTCommand, 1, &len); if ((LPTCommand & 0x8F) == 0x80) { if (len && (LPTCommand & 0x10)) { HWML_Read(HWMLHandle, pDATAToGet ? pDATAToGet : &Err, 1, &len); } if (len && (LPTCommand & 0x20)) { HWML_Read(HWMLHandle, pSTATUSToGet ? pSTATUSToGet : &Err, 1, &len); } if (len && (LPTCommand & 0x40)) { HWML_Read(HWMLHandle, pCONTROLToGet ? pCONTROLToGet : &Err, 1, &len); } } else { len = 0; } HWML_Unlock(HWMLHandle); } else { len = 0; } } HWML_BatchUnlock(HWMLHandle); } if (len) { return 1; } else { if (pDATAToGet) *pDATAToGet = 0; if (pSTATUSToGet) *pSTATUSToGet = 0; if (pCONTROLToGet) *pCONTROLToGet = 0; return 0; } }