- Fixed a bug fix with Fixed motor in TAS code

- Made AMOR write HDF-5 data in chunks
- Added  driver for a PSI-DSP magnet controller as used at SLS
- Added code for directly accessing RS232 controllers connected to a
  terminal server, thereby bypassing the SerPortServer
- A rounding problem in the PSD histogram memory was resolved.
This commit is contained in:
cvs
2001-10-25 13:57:59 +00:00
parent 22688ac0fc
commit 3c916c9a7d
32 changed files with 2247 additions and 758 deletions

619
rs232controller.c Normal file
View File

@ -0,0 +1,619 @@
/*---------------------------------------------------------------------
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 "fortify.h"
#include "sics.h"
#include "splitter.h"
#include "rs232controller.h"
/*
own error codes
*/
#define NOTCONNECTED -2700
#define BADMEMORY -2701
#define TIMEOUT -2702
#define FAILEDCONNECT -2703
/*--------------------------------------------------------------------*/
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;
}
/*--------------------------------------------------------------------*/
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(pPtr != NULL)
free(pPtr);
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;
}
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)
{
*dataLen = lRead;
return 1;
}
else
{
return (int)lRead;
}
}
/*
not reached
*/
return 0;
}
/*-----------------------------------------------------------------------*/
int availableRS232(prs232 self)
{
assert(self);
/*
catch an unconnected socket
*/
if(!self->pSock)
{
return NOTCONNECTED;
}
return NETAvailable(self->pSock,self->timeout);
}
/*------------------------------------------------------------------------*/
int transactRS232(prs232 self, void *send, int sendLen,
void *reply, int replyLen)
{
int iRet;
assert(self);
/*
catch an unconnected socket
*/
if(!self->pSock)
{
return NOTCONNECTED;
}
/*
write data
*/
iRet = writeRS232(self,send,sendLen);
if(iRet < 0)
{
return iRet;
}
/*
read
*/
memset(reply,0,replyLen);
iRet = NETReadTillTerm(self->pSock,self->timeout,self->replyTerminator,
reply, replyLen);
if(iRet == 0)
{
return TIMEOUT;
}
else
{
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:
strncpy(errorBuffer,
"Out of memory for appending terminators",
errorBufferLen);
break;
case NOTCONNECTED:
strncpy(errorBuffer,
"Not connected!",
errorBufferLen);
break;
case TIMEOUT:
strncpy(errorBuffer,
"Timeout reading data",
errorBufferLen);
break;
case FAILEDCONNECT:
strncpy(errorBuffer,
"Failed to connect to terminal server",
errorBufferLen);
break;
default:
strncpy(errorBuffer,strerror(errno),
errorBufferLen);
break;
}
}
/*--------------------------------------------------------------------*/
int initRS232(prs232 self)
{
int iRet;
assert(self);
if(self->pSock != NULL)
{
NETClosePort(self->pSock);
self->pSock = NULL;
}
self->pSock = NETConnect(self->pHost, self->iPort);
if(!self->pSock)
return FAILEDCONNECT;
else
return 1;
}
/*-------------------------------------------------------------------*/
static 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)
{
NETClosePort(self->pSock);
}
if(self->pHost)
{
free(self->pHost);
}
}
/*-------------------------------------------------------------------*/
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);
sprintf(pBuffer,"0x%x",(int)terminator[0]);
strcpy(result,pBuffer);
for(i = 1; i < len; i++)
{
sprintf(pBuffer,"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 *pPtr = NULL;
int iRet, iRead = 8191;
self = (prs232)pData;
assert(self);
assert(pCon);
/*
check for arguments
*/
if(argc < 2)
{
sprintf(pError,"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);
sprintf(pError,"%s.sendTerminator = \"%s\"",argv[0],
pBuffer);
SCWrite(pCon,pError,eValue);
return 1;
}
}
else if(strcmp(argv[1],"timeout") == 0)
{
if(checkSet(pCon,argc,usMugger))
{
setRS232Timeout(self,atoi(argv[2]));
SCSendOK(pCon);
return 1;
}
else
{
sprintf(pError,"%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))
{
pPtr = decodeTerminator(argv[2]);
setRS232ReplyTerminator(self,pPtr);
if(pPtr)
free(pPtr);
SCSendOK(pCon);
return 1;
}
else
{
encodeTerminator(pBuffer,self->replyTerminator);
sprintf(pError,"%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],"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],"init") == 0)
{
iRet = initRS232(self);
if(iRet != 1)
{
sprintf(pError,"ERROR: reinitializing connection to %s at %d failed",
self->pHost, self->iPort);
SCWrite(pCon,pError,eError);
return 0;
}
else
{
SCSendOK(pCon);
return 1;
}
}
else
{
sprintf(pError,"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;
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 = (prs232)malloc(sizeof(rs232));
if(!pNew)
{
SCWrite(pCon,"ERROR: out of memory in RS232Factory",eError);
return 0;
}
memset(pNew, 0, sizeof(rs232));
pNew->pHost = strdup(argv[2]);
pNew->iPort = atoi(argv[3]);
pNew->sendTerminator = strdup("\r");
pNew->replyTerminator = strdup("\n");
pNew->timeout = 1000;
pNew->pDes = CreateDescriptor("RS232 Controller");
if(!pNew->pDes || !pNew->pHost ||
!pNew->replyTerminator || !pNew->sendTerminator)
{
SCWrite(pCon,"ERROR: out of memory in RS232Factory",eError);
return 0;
}
pNew->pSock = NETConnect(pNew->pHost, pNew->iPort);
if(!pNew->pSock)
{
sprintf(pError,"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, KillRS232, pNew);
if(!iRet)
{
sprintf(pError,"ERROR: duplicate command %s not created", argv[1]);
SCWrite(pCon,pError,eError);
KillRS232(pNew);
return 0;
}
return 1;
}