/*-------------------------------------------------------------------------- S E R I A L W A I T wait for an command to execute in a serial device by polling with null messages in SICS. copyright: see copyright.h Mark Koennecke, June 1998 This code is defunct and not used at the time being. It is left in the source tree for documentation purposes. Mark Koennecke, June 2003 ---------------------------------------------------------------------------*/ #include #include #include #include #include "fortify.h" #include "serialwait.h" #include "dynstring.h" /* #define SDEBUG 1 */ /*--------------- The wait data structure --------------------------------*/ typedef struct { int iEnd; /* end signal flag */ int iError; /* error returns */ int iFirst; /* first call, receive only */ time_t tEnd; /* not more then a minute! */ pDynString data; /* reply data read */ void **pData; /* the serial IO data structure */ } SW, *pSW; /*---------------- The signal function --------------------------------*/ static void SWSignal(void *pUser, int iSignal, void *pSigData) { pSW self = NULL; int *iInt; self = (pSW) pUser; iInt = (int *) pSigData; if (iSignal == SICSINT) { if (*iInt > eContinue) { self->iEnd = 2; } } } /*---------------------- The task function ------------------------------*/ static int SWTask(void *pData) { pSW self = NULL; char pReply[1024]; int iRet, iCount; char *pPtr; self = (pSW) pData; assert(self); /* check for interrupt end */ if (self->iEnd > 0) { return 0; } /* check for timeout */ if (time(NULL) >= self->tEnd) { self->iError = TIMEOUT; self->iEnd = 3; return 0; } /* wait for a second */ SicsWait(1); /* send a null command and read reply */ if (!self->iFirst) { iRet = SerialSend(self->pData, ""); } else { self->iFirst = 0; } pReply[0] = '\0'; iRet = SerialReceive(self->pData, pReply, 1023); #ifdef SDEBUG printf("Primary answer: %s\n", pReply); #endif if ((iRet == TIMEOUT) || (iRet == SELECTFAIL)) { #ifdef SDEBUG printf("Return 1 on timeout\n"); #endif return 1; } else if (iRet < 0) { self->iError = iRet; self->iEnd = 3; #ifdef SDEBUG printf("Error %d return Receive 0\n", iRet); #endif return 0; } /* is there data ? */ iCount = strlen(pReply); if (iCount <= 0) { #ifdef SDEBUG printf("No data in Reply, return 1\n"); #endif return 1; } /* do we have a tmo message ? */ if (strncmp("?TMO", pReply, 4) == 0) { /* is there additional data appended ? */ if (iCount > 4) { /* store what we have */ pPtr = pReply + 4; DynStringConcat(self->data, pPtr); /* set tmo high, read rest of reply */ SerialConfig(self->pData, 90000); pReply[0] = '\0'; iRet = SerialWriteRead(self->pData, "", pReply, 1023); #ifdef SDEBUG printf(" sec rep: %s\n", pReply); #endif if (iRet != 1) { self->iError = iRet; self->iEnd = 3; #ifdef SDEBUG printf("return 0, on secondary read error\n"); #endif return 0; } DynStringConcat(self->data, pReply); self->iEnd = 1; #ifdef SDEBUG printf("Complete read on second try, return 0\n"); #endif return 0; } else { /* schnuuuueeeeeffffff! no data, poll again */ #ifdef SDEBUG printf("Do agaian, got a TMO \n"); #endif return 1; } } else { /* we obtained all the data right away */ DynStringConcat(self->data, pReply); self->iEnd = 1; #ifdef SDEBUG printf("Return 0, received all data in one go \n"); #endif return 0; } /* should not get here */ #ifdef SDEBUG printf("Should not get here return 1\n"); #endif return 1; } /*-------------------------- The actual working function ------------------*/ int SerialSicsExecute(void **pData, char *pCommand, char *pReply, int iBufLen) { int iOldTmo, iRet, iResult; long lTask; SW control; char *pPtr; /* set timeout to 0 */ iOldTmo = SerialGetTmo(pData); SerialConfig(pData, 200); /* send the command to execute */ iRet = SerialSend(pData, pCommand); if (iRet != 1) { SerialConfig(pData, iOldTmo); return iRet; } /* initialize task data structure */ control.iEnd = 0; control.iError = 0; control.iFirst = 1; control.pData = pData; /* do a timeout after a minute without a reply */ control.tEnd = time(NULL) + 60; control.data = CreateDynString(1024, 1024); /* start task */ lTask = TaskRegister(pServ->pTasker, SWTask, SWSignal, NULL, &control, 1); /* wait for it to end */ TaskWait(pServ->pTasker, lTask); /* analyse what we have got, success first */ if (control.iEnd == 1) { iResult = 1; pPtr = GetCharArray(control.data); strlcpy(pReply, pPtr, iBufLen); } else if (control.iEnd == 2) { /* interrupted */ iResult = INTERRUPTED; } else { iResult = control.iError; } control.iEnd = 10; /* clear up and go */ DeleteDynString(control.data); SerialConfig(pData, iOldTmo); return iResult; }