/*-------------------------------------------------------------------------- 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 ---------------------------------------------------------------------------*/ #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); strncpy(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; }