- Rearranged directory structure for forking out ANSTO
- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto
This commit is contained in:
914
hardsup/serialsinq.c
Normal file
914
hardsup/serialsinq.c
Normal file
@ -0,0 +1,914 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
S E R I A L S I N Q
|
||||
Implementation file of the functions for talking with a RS--232 port
|
||||
on a SINQ terminal server. This code has been adapted from code
|
||||
provided by David Maden for the EL734 motor controller. A new version
|
||||
became necessary as the Dornier velocity selector supports a
|
||||
completely different protocoll than the EL734. The basics, however, are
|
||||
the same.
|
||||
|
||||
Mark Koennecke, Juli 1997
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef FORTIFY
|
||||
#include "../fortify.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __VMS
|
||||
#include <unixio.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
#include "sinq_prototypes.h"
|
||||
#include "el734_def.h"
|
||||
#include "rs232c_def.h"
|
||||
#include "el734fix.h"
|
||||
#include "serialsinq.h"
|
||||
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
struct SerialInfo {
|
||||
int skt;
|
||||
int iForce;
|
||||
int port;
|
||||
int chan;
|
||||
char host[20];
|
||||
int tmo;
|
||||
int msg_id;
|
||||
int n_replies, max_replies;
|
||||
char pTerms[4];
|
||||
char pSendTerm[10];
|
||||
struct RS__MsgStruct to_host;
|
||||
struct RS__RespStruct from_host;
|
||||
SerialSleep pFunc;
|
||||
void *pData;
|
||||
struct AsynSrv__info sAsync;
|
||||
};
|
||||
/*------------------- The default sleep function -----------------------*/
|
||||
static int SerialNccrrrh(void *pData, int iTime)
|
||||
{
|
||||
usleep(50);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int SerialOpen(void **pData, char *pHost, int iPort, int iChannel)
|
||||
{
|
||||
int status;
|
||||
struct SerialInfo *my_info;
|
||||
void *my_hndl;
|
||||
struct hostent *rmt_hostent;
|
||||
struct in_addr *rmt_inet_addr_pntr;
|
||||
int rmt_sockname_len;
|
||||
struct sockaddr_in lcl_sockname;
|
||||
struct sockaddr_in rmt_sockname;
|
||||
char msr_cmnd[20];
|
||||
struct RS__RplyStruct *rply_ptr;
|
||||
|
||||
*pData = NULL;
|
||||
|
||||
/*
|
||||
** allocate memory first
|
||||
*/
|
||||
*pData = malloc (sizeof (struct SerialInfo));
|
||||
if (*pData == NULL) {
|
||||
return EL734__BAD_MALLOC; /* malloc failed!! */
|
||||
}
|
||||
my_info = *pData;
|
||||
memset(my_info,0,sizeof(struct SerialInfo));
|
||||
|
||||
/*
|
||||
**-------------------------- Set up the connection
|
||||
*/
|
||||
my_info->sAsync.port = iPort;
|
||||
strcpy(my_info->sAsync.host,pHost);
|
||||
my_info->sAsync.chan = iChannel;
|
||||
status = AsynSrv_Open (&(my_info->sAsync));
|
||||
if (status != 1) {
|
||||
return OPENFAILURE;
|
||||
}
|
||||
|
||||
/* intialize data structures */
|
||||
StrJoin (my_info->host, sizeof (my_info->host), pHost, "");
|
||||
my_info->skt = my_info->sAsync.skt;
|
||||
my_info->port = iPort;
|
||||
my_info->chan = iChannel;
|
||||
my_info->tmo = 100;
|
||||
my_info->msg_id = 0;
|
||||
my_info->pFunc = SerialNccrrrh;
|
||||
my_info->pData = NULL;
|
||||
strcpy(my_info->pTerms,"1\r\n\0");
|
||||
my_info->iForce = 0;
|
||||
memset(my_info->pSendTerm,0,9);
|
||||
strcpy(my_info->pSendTerm,"\r\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel)
|
||||
{
|
||||
int status;
|
||||
struct SerialInfo *my_info;
|
||||
void *my_hndl;
|
||||
struct hostent *rmt_hostent;
|
||||
struct in_addr *rmt_inet_addr_pntr;
|
||||
int rmt_sockname_len;
|
||||
struct sockaddr_in lcl_sockname;
|
||||
struct sockaddr_in rmt_sockname;
|
||||
char msr_cmnd[20];
|
||||
struct RS__RplyStruct *rply_ptr;
|
||||
|
||||
*pData = NULL;
|
||||
|
||||
/* create pData */
|
||||
*pData = malloc (sizeof (struct SerialInfo));
|
||||
if (*pData == NULL) {
|
||||
return EL734__BAD_MALLOC; /* malloc failed!! */
|
||||
}
|
||||
my_info = *pData;
|
||||
memset(my_info,0,sizeof(struct SerialInfo));
|
||||
|
||||
|
||||
/*
|
||||
**-------------------------- Set up the connection
|
||||
*/
|
||||
my_info->sAsync.port = iPort;
|
||||
strcpy(my_info->sAsync.host,pHost);
|
||||
my_info->sAsync.chan = iChannel;
|
||||
status = AsynSrv_OpenNew (&(my_info->sAsync));
|
||||
if (status != 1) {
|
||||
return OPENFAILURE;
|
||||
}
|
||||
|
||||
/* intialize data structures */
|
||||
StrJoin (my_info->host, sizeof (my_info->host), pHost, "");
|
||||
my_info->skt = my_info->sAsync.skt;
|
||||
my_info->port = iPort;
|
||||
my_info->chan = iChannel;
|
||||
my_info->tmo = 100;
|
||||
my_info->msg_id = 0;
|
||||
my_info->pFunc = SerialNccrrrh;
|
||||
my_info->pData = NULL;
|
||||
strcpy(my_info->pTerms,"1\r\n\0");
|
||||
my_info->iForce = 1;
|
||||
memset(my_info->pSendTerm,0,9);
|
||||
strcpy(my_info->pSendTerm,"\r\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialConfig(void **pData, int iTmo)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
assert(my_info);
|
||||
|
||||
if(iTmo < 100)
|
||||
{
|
||||
my_info->tmo = 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_info->tmo = iTmo/100; /* convert to deci seconds */
|
||||
if(my_info->tmo > 9999)my_info->tmo = 9999;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int GetSerialTmo(void **pData)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
int iTmo;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
assert(my_info);
|
||||
|
||||
iTmo = my_info->tmo*100-99; /* convert back to milli seconds */
|
||||
|
||||
return iTmo;
|
||||
}
|
||||
int SerialGetTmo(void **pData)
|
||||
{
|
||||
return GetSerialTmo(pData);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialGetSocket(void **pData)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
int iTmo;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
assert(my_info);
|
||||
|
||||
return my_info->skt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialClose(void **pData)
|
||||
{
|
||||
|
||||
struct SerialInfo *info_ptr;
|
||||
char buff[4];
|
||||
|
||||
info_ptr = (struct SerialInfo *) *pData;
|
||||
if (info_ptr == NULL) return True;
|
||||
|
||||
if (info_ptr->skt != 0) {
|
||||
AsynSrv_Close (&(info_ptr->sAsync),0);
|
||||
info_ptr->skt = 0;
|
||||
}
|
||||
free (*pData);
|
||||
*pData = NULL;
|
||||
return True;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialForceClose(void **pData)
|
||||
{
|
||||
|
||||
struct SerialInfo *info_ptr;
|
||||
char buff[4];
|
||||
|
||||
info_ptr = (struct SerialInfo *) *pData;
|
||||
if (info_ptr == NULL) return True;
|
||||
|
||||
if (info_ptr->skt != 0) {
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
}
|
||||
free (*pData);
|
||||
*pData = NULL;
|
||||
return True;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialATerm(void **pData, char *pTerm)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
if(my_info == NULL)
|
||||
{
|
||||
printf("Serious Programming problem: data = NULL\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* only three characters in this field */
|
||||
if(strlen(pTerm) > 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memset(my_info->pTerms,0,4);
|
||||
strcpy(my_info->pTerms,pTerm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SerialAGetTerm(void **pData, char *pTerm, int iTermLen)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
assert(my_info);
|
||||
|
||||
strncpy(pTerm,my_info->pTerms,iTermLen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int SerialSendTerm(void **pData, char *pTerm)
|
||||
{
|
||||
struct SerialInfo *my_info = NULL;
|
||||
|
||||
my_info = (struct SerialInfo *)*pData;
|
||||
assert(my_info);
|
||||
|
||||
/* only 0 characters in this field */
|
||||
if(strlen(pTerm) > 9)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
strcpy(my_info->pSendTerm,pTerm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
int SerialSend(void **pData, char *pCommand)
|
||||
{
|
||||
struct SerialInfo *info_ptr;
|
||||
int status, c_len, size, max_size, ncmnds;
|
||||
int bytes_to_come, bytes_left;
|
||||
int iResult;
|
||||
char *nxt_byte_ptr;
|
||||
char err_text[80];
|
||||
char text[20];
|
||||
char *txt_ptr;
|
||||
char *cmnd_lst_ptr;
|
||||
char *pComCom = NULL;
|
||||
|
||||
/*
|
||||
** Do nothing if no connection - the connection gets
|
||||
** closed if an error is detected.
|
||||
*/
|
||||
info_ptr = (struct SerialInfo *) *pData;
|
||||
if (info_ptr == NULL) return NOCONNECTION;
|
||||
if (info_ptr->skt == 0) {
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return NOCONNECTION;
|
||||
}
|
||||
|
||||
info_ptr->msg_id++; /* Set up an incrementing message id */
|
||||
if (info_ptr->msg_id > 9999) info_ptr->msg_id = 1;
|
||||
sprintf (info_ptr->to_host.msg_id, "%04.4d", info_ptr->msg_id);
|
||||
|
||||
memcpy (info_ptr->to_host.c_pcol_lvl, RS__PROTOCOL_ID_V01B,
|
||||
sizeof (info_ptr->to_host.c_pcol_lvl));
|
||||
sprintf (info_ptr->to_host.serial_port, "%04.4d", info_ptr->chan);
|
||||
sprintf (info_ptr->to_host.tmo, "%04d", info_ptr->tmo);
|
||||
|
||||
strncpy(info_ptr->sAsync.eot,info_ptr->pTerms,4);
|
||||
memcpy (info_ptr->to_host.terms, info_ptr->pTerms,
|
||||
sizeof (info_ptr->to_host.terms));
|
||||
memcpy (info_ptr->to_host.n_cmnds, "0000",
|
||||
sizeof (info_ptr->to_host.n_cmnds));
|
||||
|
||||
|
||||
txt_ptr = pCommand; /* Get pntr to cmnd string */
|
||||
ncmnds = 0;
|
||||
cmnd_lst_ptr = &info_ptr->to_host.cmnds[0];
|
||||
bytes_left = sizeof (info_ptr->to_host) -
|
||||
OffsetOf (struct RS__MsgStruct, cmnds[0]);
|
||||
|
||||
size = strlen (txt_ptr) + strlen(info_ptr->pSendTerm);
|
||||
if (size > bytes_left) {
|
||||
return EL734__BAD_SENDLEN; /* Too much to send */
|
||||
}else {
|
||||
strcpy (cmnd_lst_ptr+4, txt_ptr);
|
||||
/* make sure that the string is properly terminated */
|
||||
if((strstr(txt_ptr,info_ptr->pSendTerm) == 0) &&
|
||||
(strlen(txt_ptr) > 0) )
|
||||
{
|
||||
strcpy(cmnd_lst_ptr+4+strlen(txt_ptr),info_ptr->pSendTerm);
|
||||
c_len = strlen(txt_ptr) + strlen(info_ptr->pSendTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
c_len = strlen (txt_ptr);
|
||||
}
|
||||
sprintf (text, "%04.4d", c_len);
|
||||
memcpy (cmnd_lst_ptr, text, 4);
|
||||
cmnd_lst_ptr = cmnd_lst_ptr + c_len + 4;
|
||||
ncmnds++;
|
||||
bytes_left = bytes_left - size;
|
||||
}
|
||||
|
||||
sprintf (text, "%04.4d", ncmnds);
|
||||
memcpy (info_ptr->to_host.n_cmnds,
|
||||
text, sizeof (info_ptr->to_host.n_cmnds));
|
||||
|
||||
size = cmnd_lst_ptr - info_ptr->to_host.msg_id;
|
||||
size = (size + 3) & (~3); /* Round up to multiple of 4 */
|
||||
sprintf (text, "%04.4d", size);
|
||||
memcpy (info_ptr->to_host.msg_size, text, 4);
|
||||
|
||||
status = send (info_ptr->skt, (char *) &info_ptr->to_host, size+4, 0);
|
||||
if (status != (size+4)) {
|
||||
if (status == 0) {
|
||||
iResult = EL734__BAD_SEND; /* Server exited (probably) */
|
||||
}else if (status == -1) {
|
||||
iResult = EL734__BAD_SEND_PIPE; /* Server exited (probably) */
|
||||
}
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int SerialReceive(void **pData, char *pBuffer, int iBufLen)
|
||||
{
|
||||
struct SerialInfo *info_ptr;
|
||||
int status, c_len, size, max_size, ncmnds;
|
||||
int bytes_to_come, bytes_left;
|
||||
int iResult;
|
||||
char *nxt_byte_ptr;
|
||||
char err_text[80];
|
||||
char text[20];
|
||||
char *txt_ptr;
|
||||
char *cmnd_lst_ptr;
|
||||
struct RS__RplyStruct_V01B *ptr = NULL;
|
||||
long lMask = 0L;
|
||||
struct timeval tmo = {0,1};
|
||||
|
||||
|
||||
/*
|
||||
** Do nothing if no connection - the connection gets
|
||||
** closed if an error is detected.
|
||||
*/
|
||||
info_ptr = (struct SerialInfo *) *pData;
|
||||
if (info_ptr == NULL) return NOCONNECTION;
|
||||
if (info_ptr->skt == 0) {
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return NOCONNECTION;
|
||||
}
|
||||
|
||||
/* try with select if there is data */
|
||||
/* lMask = (1 << info_ptr->skt);
|
||||
tmo.tv_usec = 10;
|
||||
status = select((info_ptr->skt +1), (fd_set *)&lMask, NULL,NULL,&tmo);
|
||||
if(status <= 0)
|
||||
{
|
||||
return SELECTFAIL;
|
||||
}
|
||||
*/
|
||||
|
||||
/* try read the message length to come */
|
||||
size = sizeof (info_ptr->from_host.msg_size);
|
||||
status = recv (info_ptr->skt, info_ptr->from_host.msg_size, size, 0);
|
||||
if (status != size) {
|
||||
if(status > 0)
|
||||
{
|
||||
iResult = EL734__BAD_RECV; /* Server exited (probably) */
|
||||
}
|
||||
else if (status == -1) {
|
||||
iResult = EL734__BAD_RECV_NET; /* It's some other net problem */
|
||||
}
|
||||
else
|
||||
{
|
||||
iResult = EL734__BAD_RECV_NET;
|
||||
}
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}
|
||||
if (sscanf (info_ptr->from_host.msg_size, "%4d", &bytes_to_come) != 1) {
|
||||
return EL734__BAD_NOT_BCD; /* Header not an ASCII BCD integer */
|
||||
}
|
||||
|
||||
max_size = sizeof (info_ptr->from_host) -
|
||||
sizeof (info_ptr->from_host.msg_size);
|
||||
if (bytes_to_come > max_size) {
|
||||
iResult = EL734__BAD_RECVLEN;
|
||||
nxt_byte_ptr = &info_ptr->from_host.msg_size[size];
|
||||
while (bytes_to_come > 0) { /* Flush out the incoming message */
|
||||
bytes_left = bytes_to_come;
|
||||
if (bytes_left > max_size) bytes_left = max_size;
|
||||
status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0);
|
||||
if (status <= 0) {
|
||||
iResult = EL734__BAD_FLUSH; /* TCP/IP problem whilst flushing */
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}
|
||||
bytes_to_come = bytes_to_come - status;
|
||||
}
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}else {
|
||||
nxt_byte_ptr = &info_ptr->from_host.msg_size[size];
|
||||
bytes_left = bytes_to_come;
|
||||
while (bytes_left > 0) { /* Read the rest of the response */
|
||||
status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0);
|
||||
if (status <= 0) {
|
||||
if (status == 0) {
|
||||
iResult = EL734__BAD_RECV1; /* Server exited (probably) */
|
||||
}else {
|
||||
iResult = EL734__BAD_RECV1_NET; /* It's some other net fault */
|
||||
}
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
return iResult;
|
||||
}
|
||||
bytes_left = bytes_left - status;
|
||||
nxt_byte_ptr = nxt_byte_ptr + status;
|
||||
}
|
||||
}
|
||||
/* well, we got data, make it available */
|
||||
if (sscanf (info_ptr->from_host.n_rply, "%4d",
|
||||
&info_ptr->max_replies) != 1)info_ptr->max_replies = 0;
|
||||
if (info_ptr->max_replies > 0)
|
||||
ptr = (struct RS__RplyStruct_V01B *) info_ptr->from_host.u.rplys;
|
||||
info_ptr->n_replies = 1;
|
||||
if(ptr)
|
||||
{
|
||||
strncpy(pBuffer, ptr->rply,iBufLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NOREPLY;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int SerialReceiveWithTerm(void **pData, char *pBuffer,
|
||||
int iBufLen, char *cTerm )
|
||||
{
|
||||
struct SerialInfo *info_ptr;
|
||||
int status, c_len, size, max_size, ncmnds;
|
||||
int bytes_to_come, bytes_left;
|
||||
int iResult;
|
||||
char *nxt_byte_ptr;
|
||||
char err_text[80];
|
||||
char text[20];
|
||||
char *txt_ptr;
|
||||
char *cmnd_lst_ptr;
|
||||
struct RS__RplyStruct_V01B *ptr = NULL;
|
||||
long lMask = 0L;
|
||||
struct timeval tmo = {0,1};
|
||||
|
||||
|
||||
/*
|
||||
** Do nothing if no connection - the connection gets
|
||||
** closed if an error is detected.
|
||||
*/
|
||||
info_ptr = (struct SerialInfo *) *pData;
|
||||
if (info_ptr == NULL) return NOCONNECTION;
|
||||
if (info_ptr->skt == 0) {
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return NOCONNECTION;
|
||||
}
|
||||
|
||||
/* try with select if there is data */
|
||||
/* lMask = (1 << info_ptr->skt);
|
||||
tmo.tv_usec = 10;
|
||||
status = select((info_ptr->skt +1), (fd_set *)&lMask, NULL,NULL,&tmo);
|
||||
if(status <= 0)
|
||||
{
|
||||
return SELECTFAIL;
|
||||
}
|
||||
*/
|
||||
|
||||
/* try read the message length to come */
|
||||
size = sizeof (info_ptr->from_host.msg_size);
|
||||
status = recv (info_ptr->skt, info_ptr->from_host.msg_size, size, 0);
|
||||
if (status != size) {
|
||||
if(status > 0)
|
||||
{
|
||||
iResult = EL734__BAD_RECV; /* Server exited (probably) */
|
||||
}
|
||||
else if (status == -1) {
|
||||
iResult = EL734__BAD_RECV_NET; /* It's some other net problem */
|
||||
}
|
||||
else
|
||||
{
|
||||
iResult = EL734__BAD_RECV_NET;
|
||||
}
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}
|
||||
if (sscanf (info_ptr->from_host.msg_size, "%4d", &bytes_to_come) != 1) {
|
||||
return EL734__BAD_NOT_BCD; /* Header not an ASCII BCD integer */
|
||||
}
|
||||
|
||||
max_size = sizeof (info_ptr->from_host) -
|
||||
sizeof (info_ptr->from_host.msg_size);
|
||||
if (bytes_to_come > max_size) {
|
||||
iResult = EL734__BAD_RECVLEN;
|
||||
nxt_byte_ptr = &info_ptr->from_host.msg_size[size];
|
||||
while (bytes_to_come > 0) { /* Flush out the incoming message */
|
||||
bytes_left = bytes_to_come;
|
||||
if (bytes_left > max_size) bytes_left = max_size;
|
||||
status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0);
|
||||
if (status <= 0) {
|
||||
iResult = EL734__BAD_FLUSH; /* TCP/IP problem whilst flushing */
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}
|
||||
bytes_to_come = bytes_to_come - status;
|
||||
}
|
||||
memset (info_ptr->from_host.msg_size,
|
||||
'0', sizeof (info_ptr->from_host.msg_size));
|
||||
return iResult;
|
||||
}else {
|
||||
nxt_byte_ptr = &info_ptr->from_host.msg_size[size];
|
||||
bytes_left = bytes_to_come;
|
||||
while (bytes_left > 0) { /* Read the rest of the response */
|
||||
status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0);
|
||||
if (status <= 0) {
|
||||
if (status == 0) {
|
||||
iResult = EL734__BAD_RECV1; /* Server exited (probably) */
|
||||
}else {
|
||||
iResult = EL734__BAD_RECV1_NET; /* It's some other net fault */
|
||||
}
|
||||
AsynSrv_Close (&(info_ptr->sAsync),1);
|
||||
info_ptr->skt = 0;
|
||||
return iResult;
|
||||
}
|
||||
bytes_left = bytes_left - status;
|
||||
nxt_byte_ptr = nxt_byte_ptr + status;
|
||||
}
|
||||
}
|
||||
/* well, we got data, make it available */
|
||||
if (sscanf (info_ptr->from_host.n_rply, "%4d",
|
||||
&info_ptr->max_replies) != 1)info_ptr->max_replies = 0;
|
||||
if (info_ptr->max_replies > 0)
|
||||
ptr = (struct RS__RplyStruct_V01B *) info_ptr->from_host.u.rplys;
|
||||
info_ptr->n_replies = 1;
|
||||
if(ptr)
|
||||
{
|
||||
strncpy(pBuffer, ptr->rply,iBufLen);
|
||||
*cTerm = ptr->term;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NOREPLY;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SerialError(int iErr, char *pBuffer, int iBufLen)
|
||||
{
|
||||
switch(iErr)
|
||||
{
|
||||
case -320:
|
||||
strncpy(pBuffer,"Select failed to find data",iBufLen);
|
||||
break;
|
||||
case -300:
|
||||
case NOCONNECTION:
|
||||
strncpy(pBuffer,"Not connected",iBufLen);
|
||||
break;
|
||||
case -301:
|
||||
strncpy(pBuffer,"No reply found", iBufLen);
|
||||
break;
|
||||
case -100:
|
||||
strncpy(pBuffer,"No reply found", iBufLen);
|
||||
break;
|
||||
case EL734__BAD_ADR:
|
||||
strncpy(pBuffer,"SERIAL__BAD_ADR",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_BIND:
|
||||
strncpy(pBuffer,"SERIAL__BAD_BIND",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_CMD:
|
||||
strncpy(pBuffer,"SERIAL__BAD_CMD",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_CONNECT:
|
||||
strncpy(pBuffer,"SERIAL__BAD_CONNECT",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_FLUSH:
|
||||
strncpy(pBuffer,"SERIAL__BAD_FLUSH",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_HOST:
|
||||
strncpy(pBuffer,"SERIAL__BAD_HOST",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_ID:
|
||||
strncpy(pBuffer,"SERIAL__BAD_ID",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_ILLG:
|
||||
strncpy(pBuffer,"SERIAL__BAD_ILLG",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_LOC:
|
||||
strncpy(pBuffer,"SERIAL__BAD_LOC",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_MALLOC:
|
||||
strncpy(pBuffer,"SERIAL__BAD_MALLOC",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_NOT_BCD:
|
||||
strncpy(pBuffer,"SERIAL__BAD_NOT_BCD",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_OFL:
|
||||
strncpy(pBuffer,"SERIAL__BAD_OFL",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_PAR:
|
||||
strncpy(pBuffer,"SERIAL__BAD_PAR",iBufLen);
|
||||
break;
|
||||
|
||||
case EL734__BAD_RECV:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV_NET:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV_NET",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV_PIPE:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV_PIPE",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV_UNKN:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV_UNKN",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECVLEN:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECVLEN",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV1:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV1",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV1_NET:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV1_NET",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RECV1_PIPE:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RECV1_PIPE",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_RNG:
|
||||
strncpy(pBuffer,"SERIAL__BAD_RNG",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SEND:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SEND",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SEND_PIPE:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SEND_PIPE",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SEND_NET:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SEND_NET",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SEND_UNKN:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SEND_UNKN",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SENDLEN:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SENDLEN",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_SOCKET:
|
||||
strncpy(pBuffer,"SERIAL__BAD_SOCKET",iBufLen);
|
||||
break;
|
||||
case EL734__BAD_TMO:
|
||||
strncpy(pBuffer,"SERIAL__BAD_TMO",iBufLen);
|
||||
break;
|
||||
case EL734__FORCED_CLOSED:
|
||||
strncpy(pBuffer,"SERIAL__FORCED_CLOSED",iBufLen);
|
||||
break;
|
||||
case OPENFAILURE:
|
||||
strncpy(pBuffer,
|
||||
"FAILED to open connection to serial port server", iBufLen);
|
||||
break;
|
||||
default:
|
||||
strcpy(pBuffer,"Unknown SERIAL error");
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SerialWriteRead(void **pData, char *pCommand,
|
||||
char *pBuffer, int iBufLen)
|
||||
{
|
||||
|
||||
struct SerialInfo *pInfo = NULL;
|
||||
int iRet;
|
||||
time_t tTarget, tCurrent;
|
||||
|
||||
pInfo = (struct SerialInfo *)*pData;
|
||||
|
||||
/* write */
|
||||
iRet = SerialSend(pData,pCommand);
|
||||
if(iRet != 1)
|
||||
{
|
||||
SerialError(iRet, pBuffer,iBufLen);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* check for answers for maximum time out */
|
||||
tTarget = tCurrent = time(&tCurrent);
|
||||
tTarget += pInfo->tmo*100 - 90;
|
||||
|
||||
while(tCurrent < tTarget)
|
||||
{
|
||||
pInfo->pFunc(pInfo->pData, 100);
|
||||
iRet = SerialReceive(pData, pBuffer,iBufLen);
|
||||
if( iRet != 1)
|
||||
{
|
||||
if(iRet != SELECTFAIL)
|
||||
{
|
||||
/* error ! */
|
||||
SerialError(iRet, pBuffer,iBufLen);
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1; /* there is data read, we are done */
|
||||
}
|
||||
tCurrent = time(&tCurrent);
|
||||
}
|
||||
return TIMEOUT;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SerialNoReply(void **pData, char *pCommand)
|
||||
{
|
||||
|
||||
struct SerialInfo *pInfo = NULL;
|
||||
int iRet, iOld, i;
|
||||
char pBuffer[30];
|
||||
|
||||
pInfo = (struct SerialInfo *)*pData;
|
||||
|
||||
iOld = pInfo->tmo;
|
||||
pInfo->tmo = 0;
|
||||
|
||||
/* write */
|
||||
iRet = SerialSend(pData,pCommand);
|
||||
if(iRet != 1)
|
||||
{
|
||||
pInfo->tmo = iOld;
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* try some time to find a TMO */
|
||||
for(i = 0 ; i < 10; i++)
|
||||
{
|
||||
usleep(50);
|
||||
SerialReceive(pData, pBuffer,29);
|
||||
if(strcmp(pBuffer,"?TMO") == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i > 7)
|
||||
{
|
||||
printf("TMO received after %d cycles \n",i);
|
||||
}
|
||||
pInfo->tmo = iOld;
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void SetSerialSleep(void **pData, SerialSleep pFun, void *pUserData)
|
||||
{
|
||||
struct SerialInfo *pInfo = NULL;
|
||||
int iRet;
|
||||
|
||||
pInfo = (struct SerialInfo *)*pData;
|
||||
pInfo->pFunc = pFun;
|
||||
pInfo->pData = pUserData;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user