
- Fixed performance problems in many protocol drivers. SKIPPED: psi/julprot.c psi/phytron.c psi/pmacprot.c psi/polterwrite.c psi/spss7.c
874 lines
21 KiB
C
874 lines
21 KiB
C
/*---------------------------------------------------------------------
|
|
R S 2 3 2 C o n t r o l l e r
|
|
|
|
A general object which represents a controller connected to the network
|
|
via a terminal server. This bypasses David Maden's SerPortServer software.
|
|
Basic facilities are provided for writinga nd reading to and from the
|
|
device. For more information see the rs232controller.tex file.
|
|
|
|
copyright: see copyright.h
|
|
|
|
Mark Koennecke, October 2001
|
|
-----------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "splitter.h"
|
|
#include "nread.h"
|
|
#include "rs232controller.h"
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static char *MakeID(prs232 self){
|
|
static char id[132];
|
|
snprintf(id,sizeof(id),"%s:%d",self->pHost, self->iPort);
|
|
return id;
|
|
}
|
|
/*--------------------------------------------------------------------*/
|
|
void setRS232SendTerminator(prs232 self, char *term)
|
|
{
|
|
assert(self);
|
|
|
|
if (self->sendTerminator != NULL) {
|
|
free(self->sendTerminator);
|
|
}
|
|
|
|
if (term != NULL) {
|
|
self->sendTerminator = strdup(term);
|
|
} else {
|
|
self->sendTerminator = NULL;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
void setRS232ReplyTerminator(prs232 self, char *term)
|
|
{
|
|
assert(self);
|
|
if (self->replyTerminator != NULL) {
|
|
free(self->replyTerminator);
|
|
}
|
|
|
|
if (term != NULL) {
|
|
self->replyTerminator = strdup(term);
|
|
} else {
|
|
self->replyTerminator = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
void setRS232Timeout(prs232 self, int timeout)
|
|
{
|
|
assert(self);
|
|
self->timeout = timeout;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
void setRS232Debug(prs232 self, int deb)
|
|
{
|
|
assert(self);
|
|
self->debug = deb;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int writeRS232(prs232 self, void *data, int dataLen)
|
|
{
|
|
char *pPtr = NULL;
|
|
int iRet;
|
|
|
|
|
|
assert(self);
|
|
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
/*
|
|
do the terminator processing, if required.
|
|
If new data had to be allocated in order to add the terminator,
|
|
pPtr is not NULL. I any other case it is.
|
|
*/
|
|
if (self->sendTerminator != NULL) {
|
|
pPtr = (char *) data;
|
|
if (strstr(pPtr, self->sendTerminator) == NULL) {
|
|
/*
|
|
the terminator is missing. add it.
|
|
*/
|
|
pPtr = (char *) malloc((dataLen + strlen(self->sendTerminator) + 2)
|
|
* sizeof(char));
|
|
if (!pPtr) {
|
|
return BADMEMORY;
|
|
}
|
|
strcpy(pPtr, (char *) data);
|
|
strcat(pPtr, self->sendTerminator);
|
|
dataLen += strlen(self->sendTerminator);
|
|
data = pPtr;
|
|
} else {
|
|
pPtr = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
send
|
|
*/
|
|
iRet = NETWrite(self->pSock, data, dataLen);
|
|
if (self->debug > 0) {
|
|
printf("RS232 OUT : %s", (char *) data);
|
|
if (strchr((char *) data, '\n') == NULL) {
|
|
puts("");
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
if(strlen((char *)data) <= dataLen){
|
|
traceIO(MakeID(self),"out:%s",(char *)data);
|
|
} else {
|
|
traceIO(MakeID(self),"out:%s","Binary output");
|
|
}
|
|
|
|
if (pPtr != NULL)
|
|
free(pPtr);
|
|
|
|
if (iRet != 1) {
|
|
return BADSEND;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int readRS232(prs232 self, void *data, int *dataLen)
|
|
{
|
|
long lRead;
|
|
int iRet;
|
|
size_t rLength;
|
|
|
|
assert(self);
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
/*
|
|
clean our space in order to prevent corrupted stuff
|
|
*/
|
|
memset(data, 0, *dataLen);
|
|
|
|
iRet = NETAvailable(self->pSock, self->timeout);
|
|
if (iRet < 0) {
|
|
return iRet;
|
|
} else if (iRet == 0) {
|
|
*dataLen = 0;
|
|
return TIMEOUT;
|
|
} else {
|
|
rLength = *dataLen;
|
|
lRead = recv(self->pSock->sockid, data, rLength, 0);
|
|
if (lRead >= 0) {
|
|
if (self->debug > 0) {
|
|
printf("RS232 IN : %s", (char *) data);
|
|
if (strchr((char *) data, '\n') == NULL) {
|
|
puts("");
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
if(strlen((char *)data) <= *dataLen){
|
|
traceIO(MakeID(self),"in:%s",(char *)data);
|
|
} else {
|
|
traceIO(MakeID(self),"in:%s","Binary Input");
|
|
}
|
|
*dataLen = lRead;
|
|
return 1;
|
|
} else {
|
|
return (int) lRead;
|
|
}
|
|
}
|
|
|
|
/*
|
|
not reached
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int readRS232TillTerm(prs232 self, void *data, int *datalen)
|
|
{
|
|
int iRet, replylen;
|
|
assert(self);
|
|
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
memset(data, 0, *datalen);
|
|
replylen = *datalen;
|
|
iRet = NETReadTillTerm(self->pSock, self->timeout, self->replyTerminator,
|
|
(char *) data, replylen);
|
|
if (self->debug > 0 && iRet > 0) {
|
|
printf("RS232 IN/TERM : %s", (char *) data);
|
|
if (strchr((char *) data, '\n') == NULL) {
|
|
puts("");
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
if (iRet == 0) {
|
|
if (self->debug > 0) {
|
|
printf("RS232 IN/TERM : TIMEOUT:%s\n", (char *) data);
|
|
}
|
|
traceIO(MakeID(self),"in:%s","TIMEOUT");
|
|
return TIMEOUT;
|
|
} else if (iRet == -1) {
|
|
traceIO(MakeID(self),"in:%s %s","Incomplete read", (char *)data);
|
|
printf("Incomplete read: %s, errno = %d\n", (char *) data, errno);
|
|
return INCOMPLETE;
|
|
} else if (iRet < 0) {
|
|
traceIO(MakeID(self),"in:Error %d",errno);
|
|
return iRet;
|
|
}
|
|
if (*self->replyTerminator != 0) {
|
|
*datalen = strlen((char *) data);
|
|
} else {
|
|
*datalen = iRet;
|
|
}
|
|
traceIO(MakeID(self),"in:%s",(char *)data);
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int readRS232UntilWord(prs232 self, char *buffer, int buflen, char *word)
|
|
{
|
|
time_t endTime;
|
|
int status;
|
|
int bytesRead = 0;
|
|
|
|
endTime = time(NULL) + self->timeout;
|
|
memset(buffer, 0, buflen);
|
|
while (time(NULL) < endTime) {
|
|
if (availableRS232(self)) {
|
|
bytesRead = recv(self->pSock->sockid, buffer + bytesRead,
|
|
buflen - bytesRead - 1, 0);
|
|
if (bytesRead < 0) {
|
|
return BADREAD;
|
|
}
|
|
if (strstr(buffer, word) != NULL) {
|
|
return 1;
|
|
}
|
|
} else {
|
|
SicsWait(1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int availableRS232(prs232 self)
|
|
{
|
|
assert(self);
|
|
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
return NETAvailable(self->pSock, 0);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int availableNetRS232(prs232 self)
|
|
{
|
|
int status;
|
|
assert(self);
|
|
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
if (!self->registered) {
|
|
if (pServ->pReader != NULL) {
|
|
NetReadRegisterUserSocket(pServ->pReader, self->pSock->sockid);
|
|
self->registered = 1;
|
|
return 0;
|
|
}
|
|
}
|
|
status = NetReadReadable(pServ->pReader, self->pSock->sockid);
|
|
NetReadResetUser(pServ->pReader, self->pSock->sockid);
|
|
return status;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int transactRS232(prs232 self, void *send, int sendLen,
|
|
void *reply, int replyLen)
|
|
{
|
|
int iRet, len;
|
|
|
|
assert(self);
|
|
|
|
/*
|
|
catch an unconnected socket
|
|
*/
|
|
if (!self->pSock) {
|
|
return NOTCONNECTED;
|
|
}
|
|
|
|
/*
|
|
if there is still data on the socket: clear it
|
|
while(availableRS232(self)){
|
|
len = replyLen;
|
|
readRS232(self,reply,&len);
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
write data
|
|
*/
|
|
iRet = writeRS232(self, send, sendLen);
|
|
if (iRet <= 0) {
|
|
return BADSEND;
|
|
}
|
|
|
|
/*
|
|
read
|
|
*/
|
|
memset(reply, 0, replyLen);
|
|
iRet = NETReadTillTerm(self->pSock, self->timeout, self->replyTerminator,
|
|
reply, replyLen);
|
|
if (self->debug > 0) {
|
|
if (iRet > 0) {
|
|
printf("RS232 IN/TRANS: %s", (char *) reply);
|
|
if (strchr((char *) reply, '\n') == NULL) {
|
|
puts("");
|
|
}
|
|
fflush(stdout);
|
|
} else if (iRet == 0) {
|
|
printf("RS232 IN/TRANS: TIMEOUT\n");
|
|
} else {
|
|
printf("RS232 IN/TRANS/INCOMPLETE: %s, errno = %d", (char *) reply,
|
|
errno);
|
|
}
|
|
}
|
|
if (iRet == 0) {
|
|
traceIO(MakeID(self),"in:%s", "TIMEOUT");
|
|
return TIMEOUT;
|
|
} else if (iRet == -1) {
|
|
traceIO(MakeID(self),"in:%s:%d", "Incomplete read", errno);
|
|
return INCOMPLETE;
|
|
} else {
|
|
traceIO(MakeID(self),"in:%s", (char *)reply);
|
|
return iRet;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
void getRS232Error(int iCode, char *errorBuffer, int errorBufferLen)
|
|
{
|
|
/*
|
|
the error code is either one of our errors, or an errno code from
|
|
the system
|
|
*/
|
|
switch (iCode) {
|
|
case BADMEMORY:
|
|
strlcpy(errorBuffer,
|
|
"Out of memory for appending terminators", errorBufferLen);
|
|
break;
|
|
case NOTCONNECTED:
|
|
strlcpy(errorBuffer, "Not connected!", errorBufferLen);
|
|
break;
|
|
case TIMEOUT:
|
|
strlcpy(errorBuffer,
|
|
"Timeout or network error when reading data", errorBufferLen);
|
|
break;
|
|
case FAILEDCONNECT:
|
|
strlcpy(errorBuffer,
|
|
"Failed to connect to terminal server", errorBufferLen);
|
|
break;
|
|
case INCOMPLETE:
|
|
strlcpy(errorBuffer, "Did not find terminator in read buffer",
|
|
errorBufferLen);
|
|
break;
|
|
case BADSEND:
|
|
strlcpy(errorBuffer, "Network problem: failed to send",
|
|
errorBufferLen);
|
|
break;
|
|
default:
|
|
strlcpy(errorBuffer, strerror(errno), errorBufferLen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int fixRS232Error(prs232 self, int iCode)
|
|
{
|
|
int i, status, read;
|
|
char buffer[8192];
|
|
|
|
switch (iCode) {
|
|
case BADMEMORY:
|
|
case FAILEDCONNECT:
|
|
return 0;
|
|
break;
|
|
case INCOMPLETE:
|
|
case TIMEOUT:
|
|
/*
|
|
* try to clear possibly pending stuff
|
|
*/
|
|
for (i = 0; i < 3; i++) {
|
|
if (availableRS232(self)) {
|
|
read = 8192;
|
|
readRS232(self, buffer, &read);
|
|
}
|
|
}
|
|
return 1;
|
|
break;
|
|
case NOTCONNECTED:
|
|
case BADSEND:
|
|
closeRS232(self);
|
|
status = initRS232(self);
|
|
if (status > 0) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int getRS232Timeout(prs232 self)
|
|
{
|
|
return self->timeout;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int initRS232WithFlags(prs232 self, int flags)
|
|
{
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
traceIO(MakeID(self),"connect");
|
|
|
|
if (self->pSock != NULL) {
|
|
if (pServ->pReader != NULL) {
|
|
NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid);
|
|
}
|
|
NETClosePort(self->pSock);
|
|
free(self->pSock);
|
|
self->pSock = NULL;
|
|
}
|
|
self->pSock = NETConnectWithFlags(self->pHost, self->iPort, flags);
|
|
if (!self->pSock) {
|
|
return FAILEDCONNECT;
|
|
} else {
|
|
if (pServ->pReader != NULL) {
|
|
NetReadRegisterUserSocket(pServ->pReader, self->pSock->sockid);
|
|
self->registered = 1;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int initRS232(prs232 self)
|
|
{
|
|
return initRS232WithFlags(self, 0);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int initRS232Finished(prs232 self)
|
|
{
|
|
int iret;
|
|
|
|
iret = NETConnectFinished(self->pSock);
|
|
if (iret < 0) {
|
|
return FAILEDCONNECT;
|
|
} else {
|
|
return iret;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
void closeRS232(prs232 self)
|
|
{
|
|
assert(self);
|
|
|
|
if (self->pSock != NULL) {
|
|
if (pServ->pReader != NULL) {
|
|
NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid);
|
|
}
|
|
NETClosePort(self->pSock);
|
|
free(self->pSock);
|
|
self->pSock = NULL;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
prs232 createRS232(char *host, int iPort)
|
|
{
|
|
prs232 pNew = NULL;
|
|
|
|
assert(iPort > 0);
|
|
|
|
/*
|
|
create data structure
|
|
*/
|
|
pNew = (prs232) malloc(sizeof(rs232));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(rs232));
|
|
|
|
pNew->pHost = strdup(host);
|
|
pNew->iPort = iPort;
|
|
pNew->sendTerminator = strdup("\r");
|
|
pNew->replyTerminator = strdup("\n");
|
|
pNew->timeout = 1000;
|
|
pNew->debug = 0;
|
|
pNew->pDes = CreateDescriptor("RS232 Controller");
|
|
if (!pNew->pDes || !pNew->pHost ||
|
|
!pNew->replyTerminator || !pNew->sendTerminator) {
|
|
return NULL;
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
void KillRS232(void *pData)
|
|
{
|
|
prs232 self = (prs232) pData;
|
|
if (!self) {
|
|
return;
|
|
}
|
|
|
|
if (self->pDes) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if (self->sendTerminator != NULL) {
|
|
free(self->sendTerminator);
|
|
}
|
|
if (self->replyTerminator != NULL) {
|
|
free(self->replyTerminator);
|
|
}
|
|
if (self->pSock) {
|
|
if (pServ->pReader != NULL) {
|
|
NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid);
|
|
}
|
|
NETClosePort(self->pSock);
|
|
free(self->pSock);
|
|
}
|
|
if (self->pHost) {
|
|
free(self->pHost);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static void KillAndFreeRS232(void *pData)
|
|
{
|
|
KillRS232(pData);
|
|
free(pData);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static int checkSet(SConnection * pCon, int argc, int rights)
|
|
{
|
|
if (argc < 3) {
|
|
return 0;
|
|
} else {
|
|
if (SCMatchRights(pCon, rights)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*
|
|
not reached
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static void encodeTerminator(char *result, char *terminator)
|
|
{
|
|
int i, len;
|
|
char pBuffer[10];
|
|
|
|
if (terminator == NULL) {
|
|
result[0] = '\0';
|
|
}
|
|
len = strlen(terminator);
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "0x%x", (int) terminator[0]);
|
|
strcpy(result, pBuffer);
|
|
for (i = 1; i < len; i++) {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "0x%x", (int) terminator[i]);
|
|
strcat(result, pBuffer);
|
|
}
|
|
}
|
|
extern char *stptok(char *pPtr, char *pToken, int tokenLen, char *term);
|
|
/*--------------------------------------------------------------------*/
|
|
char *decodeTerminator(char *code)
|
|
{
|
|
int count = 0, icode;
|
|
char *pResult;
|
|
char *pPtr, pToken[10];
|
|
|
|
/*
|
|
max 10 terminators!
|
|
*/
|
|
pResult = (char *) malloc(10 * sizeof(char));
|
|
if (!pResult) {
|
|
return NULL;
|
|
}
|
|
memset(pResult, 0, 10);
|
|
|
|
pToken[0] = '0';
|
|
/*
|
|
I seem to get an empty token on the first call to stptok, this is why
|
|
I do 2 stptoks. Strange and wonderful.
|
|
*/
|
|
pPtr = stptok(code, pToken + 1, 9, "0");
|
|
pPtr = stptok(pPtr, pToken + 1, 9, "0");
|
|
while (pPtr != NULL) {
|
|
sscanf(pToken, "%x", &icode);
|
|
pResult[count] = (char) icode;
|
|
count++;
|
|
pPtr = stptok(pPtr, pToken + 1, 9, "0");
|
|
}
|
|
return pResult;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int RS232Action(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
prs232 self = NULL;
|
|
char pError[256];
|
|
char pBuffer[8192], pReply[8192];
|
|
char pTerm[10];
|
|
char *pPtr = NULL;
|
|
int iRet, iRead = 8191, count, i;
|
|
|
|
self = (prs232) pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/*
|
|
check for arguments
|
|
*/
|
|
if (argc < 2) {
|
|
snprintf(pError,sizeof(pError)-1, "ERROR: insufficient no of arguments to %s", argv[0]);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "sendterminator") == 0) {
|
|
if (checkSet(pCon, argc, usMugger)) {
|
|
pPtr = decodeTerminator(argv[2]);
|
|
setRS232SendTerminator(self, pPtr);
|
|
if (pPtr)
|
|
free(pPtr);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
encodeTerminator(pBuffer, self->sendTerminator);
|
|
snprintf(pError,sizeof(pError)-1, "%s.sendTerminator = \"%s\"", argv[0], pBuffer);
|
|
SCWrite(pCon, pError, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "debug") == 0) {
|
|
self->debug = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "timeout") == 0) {
|
|
if (checkSet(pCon, argc, usUser)) {
|
|
setRS232Timeout(self, atoi(argv[2]));
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pError,sizeof(pError)-1, "%s.Timeout = %d", argv[0], self->timeout);
|
|
SCWrite(pCon, pError, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "replyterminator") == 0) {
|
|
if (checkSet(pCon, argc, usMugger)) {
|
|
memset(pTerm, 0, 10);
|
|
for (i = 2; i < argc; i++) {
|
|
pPtr = decodeTerminator(argv[i]);
|
|
pTerm[i - 2] = pPtr[0];
|
|
if (pPtr)
|
|
free(pPtr);
|
|
}
|
|
setRS232ReplyTerminator(self, pTerm);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
encodeTerminator(pBuffer, self->replyTerminator);
|
|
snprintf(pError,sizeof(pError)-1, "%s.replyTerminator = \"%s\"", argv[0], pBuffer);
|
|
SCWrite(pCon, pError, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "write") == 0) {
|
|
Arg2Text(argc - 2, argv + 2, pBuffer, 8191);
|
|
iRet = writeRS232(self, pBuffer, strlen(pBuffer));
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "read") == 0) {
|
|
if (!availableRS232(self)) {
|
|
SCWrite(pCon, "Nothing to read!", eError);
|
|
return 1;
|
|
}
|
|
iRet = readRS232(self, pBuffer, &iRead);
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
SCWrite(pCon, pBuffer, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "readchar") == 0) {
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need number of chars to read", eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iRead);
|
|
if (iRet != TCL_OK) {
|
|
SCWrite(pCon, "ERROR: failed to convert argument to number", eError);
|
|
return 0;
|
|
}
|
|
if (!availableRS232(self)) {
|
|
SCWrite(pCon, "Nothing to read!", eError);
|
|
return 1;
|
|
}
|
|
iRet = readRS232(self, pBuffer, &iRead);
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
SCWrite(pCon, pBuffer, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "available") == 0) {
|
|
iRet = availableRS232(self);
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
} else if (iRet == 0) {
|
|
SCWrite(pCon, "No data pending", eValue);
|
|
return 1;
|
|
} else {
|
|
SCWrite(pCon, "Data available", eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "send") == 0) {
|
|
Arg2Text(argc - 2, argv + 2, pBuffer, 8191);
|
|
iRet = transactRS232(self, pBuffer, strlen(pBuffer), pReply, iRead);
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
SCWrite(pCon, pReply, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "binwrite") == 0) {
|
|
count = argc - 2;
|
|
for (i = 0; i < count; i++) {
|
|
pBuffer[i] = (char) atoi(argv[i + 2]);
|
|
}
|
|
if (self->pSock) {
|
|
iRet = NETWrite(self->pSock, pBuffer, count);
|
|
} else {
|
|
iRet = NOTCONNECTED;
|
|
}
|
|
if (iRet < 0) {
|
|
getRS232Error(iRet, pError, 255);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "init") == 0) {
|
|
iRet = initRS232(self);
|
|
if (iRet != 1) {
|
|
snprintf(pError,sizeof(pError)-1,
|
|
"ERROR: reinitializing connection to %s at %d failed",
|
|
self->pHost, self->iPort);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
} else {
|
|
snprintf(pError,sizeof(pError)-1, "ERROR: %s does not understand %s", argv[0], argv[1]);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
int RS232Factory(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
prs232 pNew = NULL;
|
|
int iRet, status;
|
|
char pError[256];
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: insufficient no of arguments to RS232Factory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
create data structure and open port
|
|
*/
|
|
pNew = createRS232(argv[2], atoi(argv[3]));
|
|
|
|
if (!pNew) {
|
|
SCWrite(pCon, "ERROR: out of memory in RS232Factory", eError);
|
|
return 0;
|
|
}
|
|
|
|
status = initRS232(pNew);
|
|
if (status != 1) {
|
|
snprintf(pError,sizeof(pError)-1, "ERROR: failed to connect to %s at port %d",
|
|
pNew->pHost, pNew->iPort);
|
|
SCWrite(pCon, pError, eError);
|
|
}
|
|
|
|
/*
|
|
create the command
|
|
*/
|
|
iRet = AddCommand(pSics, argv[1], RS232Action, KillAndFreeRS232, pNew);
|
|
if (!iRet) {
|
|
snprintf(pError,sizeof(pError)-1, "ERROR: duplicate command %s not created", argv[1]);
|
|
SCWrite(pCon, pError, eError);
|
|
KillAndFreeRS232(pNew);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|