Files
sics/serialwait.c
2015-07-29 17:47:46 +10:00

219 lines
5.2 KiB
C

/*--------------------------------------------------------------------------
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 <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#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 = TaskRegisterN(pServ->pTasker,"serialwait",
SWTask, SWSignal, NULL, &control, TASK_PRIO_LOW);
/* 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;
}