- 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:
cvs
2003-06-20 10:18:47 +00:00
commit 064ec37e9a
271 changed files with 115513 additions and 0 deletions

4
hardsup/README Normal file
View File

@ -0,0 +1,4 @@
This directory contains support files for the SINQ drivers.
All of the code; David Maden.

96
hardsup/StrMatch.c Executable file
View File

@ -0,0 +1,96 @@
#define ident "1A01"
#ifdef VAXC
#module StrMatch ident
#endif
#ifdef __DECC
#pragma module StrMatch ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]StrMatch.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1999
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]StrMatch -
tasmad_disk:[mad.lib.sinq]StrMatch +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrMatch debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrMatch
**
** Updates:
** 1A01 12-Nov-1999 DM. Initial version.
**============================================================================
** The following entry points are included in this module:
**
**-------------------------------------------------------------------------
** #include <sinq_prototypes.h>
**
** char *StrMatch (&str_a, &str_b, min_len)
** -------
** Input Args:
** char *str_a - Pointer to first string to be compared.
** char *str_b - Pointer to second string to be compared.
** int min_len - The minimum allowed match length.
** Output Args:
** none
** Modified Args:
** none
** Return value:
** True (non-zero) if the 2 strings match.
** Global variables modified:
** none
** Routines called:
** None
** Description:
** The routine compares 2 strings, str_a and str_b, ignoring case.
** The length of str_a must be less than or equal to the length of str_b.
** The length of str_a must be at least min_len.
**-------------------------------------------------------------------------
** Global Definitions
*/
#include <ctype.h>
#define NIL '\0'
/*
**====================================================================
*/
/*
**====================================================================
** StrMatch - compare two strings.
*/
int StrMatch (
/* ========
*/ char *str_a,
char *str_b,
int min_len) {
int i = 0;
while ((tolower(str_a[i]) == tolower(str_b[i])) && (str_a[i] != '\0')) i++;
return ((str_a[i] == '\0') && (i >= min_len));
}
/*-------------------------------------------------- End of StrMatch.C =======*/

51
hardsup/asynsrv_def.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef _asynsrv_def_
#define _asynsrv_def_
/*------------------------------------------------ AsynSrv_DEF.H Ident V01N
*/
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
#ifndef _asynsrv_errcodes_
#define _asynsrv_errcodes_
#include <asynsrv_errcodes.h>
#endif
#define AsynSrv_MAX_LINK 8
/*
** Structures needed by AsynSrv_Utility.
*/
struct AsynSrv__info {
int skt; /* The socket number of the connection */
char host[20]; /* The name of RS-232-C server */
int port; /* The TCP/IP port number of server */
int chan; /* The RS-232-C channel number on server */
int msg_id;
int protocol_code; /* Flag to identify the server's protocol level */
char protocol_id[4]; /* ASCII version of server's protocol level */
int cmnd_hdr_len; /* Header length for command strings */
char cmnd_fmt[8]; /* "sprintf" format for cmnd header conversion */
int rply_hdr_len; /* Header length for response strings */
char rply_fmt[8]; /* "sscanf" format for rply header conversion */
char chan_char[4]; /* ASCII encoded version of chan */
char tmo[4]; /* ASCII encoded time-out (deci-secs) */
char eot[4]; /* Expected terminators */
int max_replies; /* Binary version of #replies in response */
int n_replies; /* # of last response returned to caller */
void (*idleHandler) (int, int); /* MZ. handler called when waiting ..
** .. on a response */
};
struct AsynSrv_HostPortSkt {
char host[30];
int port;
int skt;
int protocol_code;
char protocol_id[4];
int cmnd_hdr_len;
int rply_hdr_len;
int usage_cnt;
int status;
};
/*------------------------------------------------ End of AsynSrv_DEF.H --*/
#endif /* _asynsrv_def_ */

View File

@ -0,0 +1,34 @@
/*
** TAS_SRC:[LIB]ASYNSRV_ERRCODES.H
**
** Include file generated from ASYNSRV_ERRCODES.OBJ
**
** 29-AUG-2000 09:49:15.56
*/
#define ASYNSRV__NO_ROOM 0x86480CC
#define ASYNSRV__FORCED_CLOSED 0x86480C4
#define ASYNSRV__BAD_SOCKET 0x86480BC
#define ASYNSRV__BAD_SEND_UNKN 0x86480B4
#define ASYNSRV__BAD_SEND_PIPE 0x86480AC
#define ASYNSRV__BAD_SEND_NET 0x86480A4
#define ASYNSRV__BAD_SEND_LEN 0x864809C
#define ASYNSRV__BAD_SEND 0x8648094
#define ASYNSRV__BAD_REPLY 0x864808C
#define ASYNSRV__BAD_RECV1_PIPE 0x8648084
#define ASYNSRV__BAD_RECV1_NET 0x864807C
#define ASYNSRV__BAD_RECV1 0x8648074
#define ASYNSRV__BAD_RECV_UNKN 0x864806C
#define ASYNSRV__BAD_RECV_PIPE 0x8648064
#define ASYNSRV__BAD_RECV_NET 0x864805C
#define ASYNSRV__BAD_RECV_LEN 0x8648054
#define ASYNSRV__BAD_RECV 0x864804C
#define ASYNSRV__BAD_PROT_LVL 0x8648044
#define ASYNSRV__BAD_PAR 0x864803C
#define ASYNSRV__BAD_NOT_BCD 0x8648034
#define ASYNSRV__BAD_HOST 0x864802C
#define ASYNSRV__BAD_FLUSH 0x8648024
#define ASYNSRV__BAD_CONNECT 0x864801C
#define ASYNSRV__BAD_CMND_LEN 0x8648014
#define ASYNSRV__BAD_BIND 0x864800C
#define ASYNSRV__FACILITY 0x864

1465
hardsup/asynsrv_mark.c Normal file

File diff suppressed because it is too large Load Diff

2121
hardsup/asynsrv_utility.c Normal file

File diff suppressed because it is too large Load Diff

472
hardsup/c_interfaces.c Normal file
View File

@ -0,0 +1,472 @@
#define ident "1A05"
#ifdef VAXC
#module C_INTERFACES ident
#endif
#ifdef __DECC
#pragma module C_INTERFACES ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Computing Section |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]C_INTERFACES.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1993
**
** C_INTERFACES.C provides some routines which make it easier for C programs
** to call some of the Fortran routines in SINQ.OLB.
**
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/job sinq_c_tlb mad_lib:sinq_c_tlb.tlb
$ define/job sinq_olb mad_lib:sinq.olb
$ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces debug
$
$ define/job sinq_olb mad_lib:sinq.olb
$ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces
**
** Updates:
** 1A01 16-Nov-1993 DM. Initial version.
** 1A02 24-Nov-1994 DM. Make compatible with DEC C (as opposed to VAX C)
** 1A03 28-Nov-1994 DM. Add the TT_PORT_... entry points.
**====================================================================
** The following entry pointd are included:
** C_log_arr_get : interface routine from C to LOG_ARR_GET.
** C_log_flt_get : interface routine from C to LOG_FLT_GET.
** C_log_int_get : interface routine from C to LOG_INT_GET.
** C_log_str_get : interface routine from C to LOG_STR_GET.
**
** C_str_edit : interface routine to STR_EDIT.
**
** C_tt_port_connect : interface routine to TT_PORT_CONNECT.
** C_tt_port_disconnect: interface routine to TT_PORT_DISCONNECT.
** C_tt_port_io : interface routine to TT_PORT_IO.
** C_tt_port_config : interface routine to TT_PORT_CONFIG.
**====================================================================
** Global Definitions
*/
#ifdef VAXC
#include stdio
#include descrip
#include string
#include sinq_prototypes
#else
#include <stdio.h>
#include <sys/descrip.h>
#include <sys/string.h>
#include <sinq_prototypes.h>
#endif
/*--------------------------------------------------------------------------
** Global Variables
*/
extern int C_gbl_status = 0;
extern struct dsc$descriptor_s C_name_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
/*--------------------------------------------------------------------------
** Old-style prototypes of routines which we are
** bridging to.
*/
int log_arr_get ();
int log_int_get ();
int log_flt_get ();
int log_str_get ();
int str_edit ();
int tt_port_connect ();
int tt_port_disconnect ();
int tt_port_io ();
int tt_port_config ();
/* --------------------------------------------------------------------------*/
int C_log_arr_get (char *name, int arr_size, int *value, int indx) {
/* =============
**
** This routine is useful for calling LOG_ARR_GET from a C program.
**
** Inputs:
** name - a pointer to the zero-terminated logical name.
** arr_size - the number of elements in the array value.
** indx - the index of the logical name.
** Outputs:
** value - an array of size arr_size set to the values converted
** to binary.
** Return status:
** the return status of the function is zero (false) if LOG_ARR_GET
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of LOG_ARR_GET.
** C_name_desc - set up as a string descriptor for name. It can
** be used to generate an error message if return status == 0.
*/
C_name_desc.dsc$w_length = strlen (name);
C_name_desc.dsc$a_pointer = name;
C_gbl_status = log_arr_get (&C_name_desc, &arr_size, value, &indx);
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_log_int_get (char *name, long int *value, int indx) {
/* =============
**
** This routine is useful for calling LOG_INT_GET from a C program.
**
** Inputs:
** name - a pointer to the zero-terminated logical name.
** indx - the index of the logical name.
** Outputs:
** value - the value of the logical converted to binary.
** Return status:
** the return status of the function is zero (false) if LOG_INT_GET
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of LOG_INT_GET.
** C_name_desc - set up as a string descriptor for name. It can
** be used to generate an error message if return status == 0.
*/
C_name_desc.dsc$w_length = strlen (name);
C_name_desc.dsc$a_pointer = name;
C_gbl_status = log_int_get (&C_name_desc, value, &indx);
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_log_flt_get (char *name, float *value, int indx) {
/* =============
**
** This routine is useful for calling LOG_FLT_GET from a C program.
**
** Inputs:
** name - a pointer to the zero-terminated logical name.
** indx - the index of the logical name.
** Outputs:
** value - the value of the logical converted to binary.
** Return status:
** the return status of the function is zero (false) if LOG_FLT_GET
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of LOG_FLT_GET.
** C_name_desc - set up as a string descriptor for name. It can
** be used to generate an error message if return status == 0.
*/
C_name_desc.dsc$w_length = strlen (name);
C_name_desc.dsc$a_pointer = name;
C_gbl_status = log_flt_get (&C_name_desc, value, &indx);
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_log_str_get (char *name, char *value, int val_size, int indx) {
/* =============
**
** This routine is useful for calling LOG_STR_GET from a C program.
**
** Inputs:
** name - a pointer to the zero-terminated logical name.
** val_size - the size of the value string.
** indx - the index of the logical name.
** Outputs:
** value - zero-terminated string giving the value of the logical.
** Trailing space characters will have been stripped.
** Return status:
** the return status of the function is zero (false) if LOG_STR_GET
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of LOG_STR_GET.
** C_name_desc - set up as a string descriptor for name. It can
** be used to generate an error message if return status == 0.
*/
struct dsc$descriptor_s my_val_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
C_name_desc.dsc$w_length = strlen (name);
C_name_desc.dsc$a_pointer = name;
my_val_desc.dsc$w_length = val_size - 1;
my_val_desc.dsc$a_pointer = value;
C_gbl_status = log_str_get (&C_name_desc, &my_val_desc, &indx);
value[val_size - 1] = 0; /* Zero-terminate the string */
if (C_gbl_status & 1) { /* If success, strip trailing spaces */
while ((strlen (value) > 0) && (value[strlen (value) - 1] == ' ')) {
value[strlen (value) - 1] = 0;
}
}
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_str_edit (char *out, char *in, char *ctrl, int *length) {
/* ==========
**
** This routine is useful for calling STR_EDIT from a C program.
**
** Inputs:
** in - the string to be edited.
** ctrl - the string specifying what editing is to be done.
** Outputs:
** out - the edited string. The maximum size of this string must
** be specified as input parameter *length. The string
** will be zero terminated on return.
** Modified:
** *length - an integer specifying, on input, the length of "out" in
** bytes. This must include room for the zero termination.
** On return, length will be set to the number of characters
** copied to "out" (not counting the zero termination byte).
** Return status:
** the return status of the function is zero (false) if STR_EDIT
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of STR_EDIT.
*/
struct dsc$descriptor_s out_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
struct dsc$descriptor_s in_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
struct dsc$descriptor_s ctrl_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
out_desc.dsc$w_length = *length - 1;
out_desc.dsc$a_pointer = out;
in_desc.dsc$w_length = strlen (in);
in_desc.dsc$a_pointer = in;
ctrl_desc.dsc$w_length = strlen (ctrl);
ctrl_desc.dsc$a_pointer = ctrl;
C_gbl_status = str_edit (&out_desc, &in_desc, &ctrl_desc, length);
if (*length >= 0) { /* zero-terminate the output string */
out[*length] = '\0';
}else {
out[0] = '\0';
}
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_tt_port_connect (int *hndl, int *chan, char *lognam, char *pwd) {
/* =================
**
** This routine is useful for calling TT_PORT_CONNECT from a C program.
**
** Inputs:
** lognam - a zero-terminated string specifying a logical name which
** defines the RS-232-C port to be connected. See description
** of TT_PORT_CONNECT for full details.
** pwd - a zero-terminated string specifying an optional password.
** This is the password associated with a terminal server
** service. See description of TT_PORT_CONNECT for full
** details. Specify NULL if no password.
** Outputs:
** hndl - an integer handle identifying the connection. It will be
** the address of a dynamically allocated data structure.
** chan - an integer (actually only 16 bit) giving the I/O channel
** associated with the connection. This can be used in QIO
** system calls to the terminal driver.
** Return status:
** the return status of the function is zero (false) if TT_PORT_CONNECT
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONNECT.
*/
struct dsc$descriptor_s lognam_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
struct dsc$descriptor_s pwd_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
lognam_desc.dsc$w_length = strlen (lognam);
lognam_desc.dsc$a_pointer = lognam;
if (pwd != NULL) {
pwd_desc.dsc$w_length = strlen (pwd);
pwd_desc.dsc$a_pointer = pwd;
C_gbl_status = tt_port_connect (
hndl, chan, &lognam_desc, &pwd_desc);
}else {
C_gbl_status = tt_port_connect (hndl, chan, &lognam_desc, NULL);
}
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_tt_port_disconnect (int *hndl) {
/* ====================
**
** This routine is useful for calling TT_PORT_DISCONNECT from a C program.
**
** Inputs:
** hndl - the integer handle identifying the connection as returned
** by C_tt_port_connect. It is the address of a dynamically
** allocated data structure which will also be released
** after the connection has been closed.
** Return status:
** the return status of the function is zero (false) if TT_PORT_DISCONNECT
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_DISCONNECT.
*/
C_gbl_status = tt_port_disconnect (hndl);
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_tt_port_io (
/* ============
*/ int *hndl,
char *rqst,
char *term,
char *answ,
int *answ_len, /* Attention -- Read/Write argument!! */
int flush,
int tmo) {
/*
** This routine is useful for calling TT_PORT_IO from a C program.
** Refer to the DELTAT.OLB description of TT_PORT_IO to clarify any
** uncertainties in the following description. Note that all arguments
** must be present (there is no portable method in C of getting the
** number of arguments in the call!).
** Inputs:
** hndl - the integer handle identifying the connection as returned
** by C_tt_port_connect.
** rqst - an optional zero-terminated string specifying a character
** string to be sent to the port. Specify NULL to not send
** any characters to the port.
** term - an optional zero-terminated string specifying a list of
** terminating characters for input read from the port.
** Specify NULL to terminate input on an exact character cnt.
** flush - an integer specifying if the type-ahead buffer should be
** flushed before the operation. If non-zero, the buffer
** is flushed.
** tmo - an integer (recommended value = 2) specifying a read
** time-out in seconds. Zero or negative indicates infinity.
** Outputs:
** answ - an optional string buffer to receive characters read from
** the port. If answ is not NULL, answ_len must also be
** not NULL. On return, answ will be zero terminated. The
** terminating character, if any (there is no terminating
** char if the buffer overflows) and if there is room in
** the buffer, will follow the zero character. No padding is
** done. If answ is NULL, no characters are read from the
** port.
** Modify:
** answ_len - an integer specifying, on input, the length of answ in
** bytes. This must include room for the zero termination.
** On return, answ_len will be set to the number of
** characters read (not counting the zero termination byte or
** any terminating character).
** Return status:
** the return status of the function is zero (false) if TT_PORT_IO
** returns an error (even) condition code.
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_IO.
*/
struct dsc$descriptor_s rqst_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
struct dsc$descriptor_s term_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
struct dsc$descriptor_s answ_desc = {0,
DSC$K_DTYPE_T,
DSC$K_CLASS_S,
0};
char *my_rqst = NULL;
char *my_term = NULL;
char *my_answ = NULL;
int my_answ_len = 0;
int my_flush = 1;
int my_tmo = 2;
my_tmo = tmo;
if (my_tmo < 0) my_tmo = 0;
my_flush = flush;
if (my_flush != 0) my_flush = 1;
if (answ != NULL) {
if (answ_len == 0) {
printf ("C_tt_port_io -- argument error.\n");
printf (" %s\n",
"answ_len must be present if answ is present.");
C_gbl_status = FALSE;
return FALSE;
}
answ_desc.dsc$w_length = *answ_len - 1;
answ_desc.dsc$a_pointer = answ;
}
if (term != NULL) {
term_desc.dsc$w_length = strlen (term);
term_desc.dsc$a_pointer = term;
}
if (rqst != NULL) {
rqst_desc.dsc$w_length = strlen (rqst);
rqst_desc.dsc$a_pointer = rqst;
}
C_gbl_status = tt_port_io (hndl, &rqst_desc, &term_desc,
&answ_desc, &my_answ_len, &my_flush, &my_tmo);
if (answ_desc.dsc$w_length > 0) { /* Process any input string */
if (answ_desc.dsc$w_length > my_answ_len) { /* Room for terminator? */
answ[my_answ_len+1] = answ[my_answ_len]; /* Yes, so move it. */
}
answ[my_answ_len] = '\0'; /* Put in null terminator */
*answ_len = my_answ_len; /* Return value to caller */
}
return (C_gbl_status & 1);
}
/*--------------------------------------------------------------------------*/
int C_tt_port_config (
/* ================
*/ int *hndl,
int mask) {
/*
** This routine is useful for calling TT_PORT_CONFIG from a C program.
** Refer to the DELTAT.OLB description of TT_PORT_CONFIG to clarify any
** uncertainties in the following description.
** Inputs:
** hndl - the integer handle identifying the connection as returned
** by C_tt_port_connect.
** mask - an integer specifying the configuration options. Set bits
** TT_PORT__NO_RETRY = 0x0001 to suppress retries on error
** TT_PORT__NO_SIG = 0x0002 to suppress signals on error
** Outputs:
** None
** Modify:
** None
** Return status:
** always non-zero (true).
** Global variables:
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONFIG.
*/
C_gbl_status = tt_port_config (hndl, &mask);
return (C_gbl_status & 1);
}
/*=========================================== End of C_INTERFACES.C ========*/

481
hardsup/dillutil.c Normal file
View File

@ -0,0 +1,481 @@
/*--------------------------------------------------------------------------
D I L U T I L
A few utility functions for dealing with a Dillution emperature controller
CC0-510/AVSI
within the SINQ setup: host -- TCP/IP -- MAC --- RS-232.
Mark Koennecke, October 1997
Copyright: see copyrigh.h
---------------------------------------------------------------------------- */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "serialsinq.h"
#include "dillutil.h"
#ifdef FORTIFY
#include "../fortify.h"
#endif
/*
#define debug 1
*/
/*-------------------------------------------------------------------------*/
int DILLU_Open(pDILLU *pData, char *pHost, int iPort, int iChannel,
int iMode, char *pTransFile)
{
int iRet;
char pCommand[80];
char pReply[132];
pDILLU self = NULL;
pSTable pTable = NULL;
FILE *fd = NULL;
/* check translation file first */
fd = fopen(pTransFile,"r");
if(!fd)
{
return DILLU__FILENOTFOUND;
}
fgets(pReply, 131,fd);
if(strstr(pReply,"DILLUTION") == NULL)
{
fclose(fd);
return DILLU__NODILLFILE;
}
pTable = CreateTable(fd);
fclose(fd);
if(!pTable)
{
return DILLU__ERRORTABLE;
}
/* allocate a new data structure */
self = (pDILLU)malloc(sizeof(DILLU));
if(self == NULL)
{
return DILLU__BADMALLOC;
}
*pData = self;
self->pTranstable = pTable;
iRet = SerialOpen(&self->pData, pHost, iPort, iChannel);
if(iRet != 1)
{
return iRet;
}
/* set an lengthy timeout for the configuration in order to
prevent problems.
*/
iRet = SerialConfig(&self->pData, 100);
if(iRet != 1)
{
return iRet;
}
self->iReadOnly = iMode;
if(!self->iReadOnly)
{
/* switch to remote operation */
/* iRet = SerialWriteRead(&self->pData,"C1\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
*/
}
return 1;
}
/* --------------------------------------------------------------------------*/
void DILLU_Close(pDILLU *pData)
{
char pReply[132];
int iRet;
pDILLU self;
self = *pData;
if(!self)
return;
/* switch to local operation */
iRet = SerialWriteRead(&self->pData,"C0\r\n",pReply,131);
/* ignore errors on this one, the thing may be down */
/* close connection */
SerialClose(&self->pData);
/* free memory */
free(self);
*pData = NULL;
}
/* --------------------------------------------------------------------------*/
int DILLU_Config(pDILLU *pData, int iTmo)
{
int iRet;
char pReply[132];
char pCommand[10];
pDILLU self;
self = *pData;
/* first timeout */
if(iTmo > 0)
{
iRet = SerialConfig(&self->pData, iTmo);
if(iRet < 0)
{
return iRet;
}
}
return 1;
}
/* --------------------------------------------------------------------------*/
int DILLU_Send(pDILLU *pData, char *pCommand, char *pReply, int iLen)
{
pDILLU self;
self = *pData;
/* make sure, that there is a \r at the end of the command */
if(strchr(pCommand,(int)'\r') == NULL)
{
strcat(pCommand,"\r\n");
}
return SerialWriteRead(&self->pData,pCommand,pReply,iLen);
}
/* --------------------------------------------------------------------------*/
int DILLU_Read(pDILLU *pData, float *fVal)
{
char pCommand[10], pReply[132];
int iRet;
float fRead = -9999.;
float fOhm;
pDILLU self;
self = *pData;
/* send D command */
sprintf(pCommand,"D\r\n");
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* read ohms */
iRet = sscanf(pReply,"%f",&fOhm);
if(iRet != 1)
{
return DILLU__BADREAD;
}
if(fOhm > 9999890.)
{
return DILLU__SILLYANSWER;
}
/* convert to K */
iRet = InterpolateVal2(self->pTranstable,fOhm,&fRead);
*fVal = fRead;
return 1;
}
/*-------------------------------------------------------------------------*/
int DILLU_Set(pDILLU *pData, float fVal)
{
char pCommand[50], pReply[132];
int iRet, i,iRange, iExec;
const float fPrecision = 0.0001;
float fSet, fRead, fOhms, tmax, fTemp;
pDILLU self;
self = *pData;
if(self->iReadOnly)
{
return DILLU__READONLY;
}
/* send D command to read current value*/
sprintf(pCommand,"D\r\n");
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* read ohms */
iRet = sscanf(pReply,"%f",&fRead);
if(iRet != 1)
{
return DILLU__BADREAD;
}
if(fRead > 9999890.)
{
return DILLU__SILLYANSWER;
}
/* convert new set value to ohms */
iRet = InterpolateVal1(self->pTranstable,fVal,&fOhms);
if(!iRet)
{
return DILLU__OUTOFRANGE;
}
/* set to remote operation */
#ifdef debug
printf("C1\n");
#endif
iRet = SerialWriteRead(&self->pData,"C1\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
/* set heater power */
strcpy(pCommand,"G3\r");
if(fOhms > 1125)
{
strcpy(pCommand,"G2\r");
}
if(fOhms > 4000)
strcpy(pCommand,"G1\r");
#ifdef debug
printf("A9\n");
#endif
iRet = SerialWriteRead(&self->pData,"A9\r",pReply,131);
if(iRet != 1)
{
return iRet;
}
#ifdef debug
printf("%s\n",pCommand);
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* Integrator time constant */
strcpy(pCommand,"G2\r");
if(fOhms > 200)
strcpy(pCommand,"G1\r");
if(fOhms > 2000)
strcpy(pCommand,"G0\r");
strcpy(pCommand,"G7\r");
if(fOhms > 400.)
{
strcpy(pCommand,"G6\r");
}
#ifdef debug
printf("A4\n");
#endif
iRet = SerialWriteRead(&self->pData,"A4\r",pReply,131);
if(iRet != 1)
{
return iRet;
}
#ifdef debug
printf("%s\n",pCommand);
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* derivator time constant */
if(fOhms > 1000.)
{
strcpy(pCommand,"G1\r");
}
else
{
strcpy(pCommand,"G2\r");
}
#ifdef debug
printf("A5\n");
#endif
iRet = SerialWriteRead(&self->pData,"A5\r",pReply,131);
if(iRet != 1)
{
return iRet;
}
#ifdef debug
printf("%s\n",pCommand);
iRet = 1;
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* proportional gain */
if(fOhms > 500.)
{
strcpy(pCommand,"G3\r");
}
if(fOhms > 1000)
{
strcpy(pCommand,"G2\r");
}
if(fOhms > 2000)
{
strcpy(pCommand,"G1\r");
}
#ifdef debug
printf("A6\n");
#endif
iRet = SerialWriteRead(&self->pData,"A6\r",pReply,131);
if(iRet != 1)
{
return iRet;
}
#ifdef debug
printf("%s\n",pCommand);
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* range calculation a la Elsenhans */
iRange = 1;
fTemp = fOhms*10000.;
if( (fRead > 1.9) || (fOhms > 1.9) )
{
iRange = 2;
fTemp = fOhms*1000.;
}
if( (fRead > 19) || (fOhms > 19) )
{
iRange = 3;
fTemp = fOhms*100.;
}
if( (fRead > 190) || (fOhms > 190) )
{
iRange = 4;
fTemp = fOhms*10.;
}
if( (fRead > 750) || (fOhms > 750) )
{
iRange = 5;
fTemp = fOhms;
}
if( (fRead > 19000) || (fOhms > 19000) )
{
iRange = 6;
fTemp = fOhms/10.;
}
if( (fRead > 190000) || (fOhms > 190000) )
{
iRange = 7;
fTemp = fOhms/100.;
}
sprintf(pCommand,"R%1.1d\r",iRange);
#ifdef debug
printf("%s\n",pCommand);
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* finally set temperature */
#ifdef debug
printf("Set Val befor hex: %d\n",(int)fTemp);
#endif
sprintf(pCommand,"G%4.4X\r",(int)fTemp);
#ifdef debug
printf("A3\n");
#endif
iRet = SerialWriteRead(&self->pData,"A3\r",pReply,131);
if(iRet != 1)
{
return iRet;
}
#ifdef debug
printf("%s\n",pCommand);
#endif
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
/* unset remote operation, so that users may mess everything up
from the panel
*/
#ifdef debug
printf("C1\n");
#endif
iRet = SerialWriteRead(&self->pData,"C0\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
return 1;
}
/*-------------------------------------------------------------------------*/
void DILLU_Error2Text(pDILLU *pData,int iCode, char *pError, int iLen)
{
char pBueffel[512];
pDILLU self;
self = *pData;
switch(iCode)
{
case DILLU__FILENOTFOUND:
strncpy(pError,"Translation Table file not found",iLen);
return;
break;
case DILLU__NODILLFILE:
strncpy(pError,"Translation Table file is not DILLU",iLen);
return;
break;
case DILLU__ERRORTABLE:
strncpy(pError,"Translation Table could not be created",iLen);
return;
break;
case DILLU__BADREAD:
strncpy(pError,"Message corrupted",iLen);
return;
break;
case DILLU__SILLYANSWER:
strncpy(pError,"Message corrupted",iLen);
return;
break;
case DILLU__BADMALLOC:
strncpy(pError,"Out of memory in Open_DILLU",iLen);
return;
break;
case DILLU__READONLY:
strncpy(pError,"DILLU is read-only",iLen);
return;
break;
case DILLU__OUTOFRANGE:
strncpy(pError,"Requested value is out of range",iLen);
return;
break;
default:
SerialError(iCode,pError,iLen);
break;
}
}

108
hardsup/dillutil.h Normal file
View File

@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------
D I L U U T I L
A few utility functions for talking to Dillution temperature controller
CCO-510/ AVSI via the SINQ setup: TCP/IP--MAC--RS-232--DILLU.
This controller is weird in that way, that is accepts temperatures as
resistance values in Ohms. Therefore a translation table is required
in order to convert from Kelvin to Ohms.
Mark Koennecke, October 1997
----------------------------------------------------------------------------*/
#ifndef SINQDILLU
#define SINQDILLU
#include <stdio.h>
#include "table.h"
/*----------------------- ERRORCODES--------------------------------------
Most functions return a negative error code on failure. Error codes
defined are those defined for serialsinq plus a few additional ones:
*/
#define DILLU__FILENOTFOUND -710
#define DILLU__NODILLFILE -711
#define DILLU__ERRORTABLE -712
#define DILLU__BADREAD -713
#define DILLU__SILLYANSWER -714
#define DILLU__READONLY -715
#define DILLU__OUTOFRANGE -716
#define DILLU__BADMALLOC -717
#define DILLU__NODILLUFOUND -711
/*------------------------------------------------------------------------*/
typedef struct __DILLU {
void *pData;
pSTable pTranstable;
int iReadOnly;
} DILLU;
typedef struct __DILLU *pDILLU;
/*-----------------------------------------------------------------------*/
int DILLU_Open(pDILLU *pData,char *pHost, int iPort, int iChannel,
int iMode, char *pTransFile);
/***** creates an DILLU datastructure and opens a connection to the ITCL4
controller. Input Parameters are:
the hostname
the port number
the RS-232 channel number on the Mac.
iMode: 1 for ReadOnly, 0 for normal mode
pTransFile: name and path of the temperature ohms
trnslation file.
Return values are 1 for success, a negative error code on
failure.
*/
void DILLU_Close(pDILLU *pData);
/****** close a connection to an DILLU controller and frees its
data structure. The only parameter is a pointer to the data
structure for this controller. This pointer will be invalid after
this call.
*/
int DILLU_Config(pDILLU *pData, int iTmo);
/***** configure some aspects of a DILLU temperature controller.
The parameter are:
- a pointer to the data structure for the controller as
returned by Open_DILLU
- a value for the connection timeout
The function returns 1 on success, a negative error code on
failure.
*/
int DILLU_Send(pDILLU *pData, char *pCommand, char *pReply, int iLen);
/******* send a the command in pCommand to the DILLU controller.
A possible reply is returned in the buffer pReply.
Maximum iLen characters are copied to pReply.
The first parameter is a pointer to a DILLU data structure
as returned by Open_DILLU.
Return values are 1 for success, a negative error code on
failure.
*/
int DILLU_Read(pDILLU *pData, float *fVal);
/******
Reads the current temperature at the controller
Return values are 1 for success, a negative error code on
failure.
*/
int DILLU_Set(pDILLU *pData, float fVal);
/****** sets a new preset temperature in the DILL temperature
controller. Parameters are:
- a pointer to a DILLU data structure as returned by Open_DILLU.
- the new preset value.
Return values are 1 for success, a negative error code on
failure.
*/
void DILLU_Error2Text(pDILLU *pData, int iCode, char *pError, int iLen);
#endif

73
hardsup/el734_def.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _el734_def_
#define _el734_def_
/*------------------------------------------------ EL734_DEF.H Ident V01R
*/
#include <asynsrv_def.h>
#include <rs232c_def.h>
#include <sinq_defs.h>
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
#ifndef _EL734_errcodes_
#define _EL734_errcodes_
#include <el734_errcodes.h>
#endif
#define MAX_MOT 12
enum EL734_Requests {FULL__STATUS,
SHORT__STATUS};
/*
** Structure to which the EL734_Open handle points.
*/
struct EL734info {
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
int motor;
int ored_msr, fp_cntr, fr_cntr;
struct RS__MsgStruct to_host;
struct RS__RespStruct from_host;
};
/*
** Structure holding everything that is known about a VME Motor Controller.
** It is also the structure of replies from the Server.
*/
struct Motor_State {
int motor; /* Motor number */
int exists; /* True if Motor exists */
int msr; /* MSR - Motor Status Register */
int ored_msr; /* Cumulated MSR */
int fp_cntr; /* Counter for *FP reports */
int fr_cntr; /* Counter for *FR reports */
int ss; /* SS - Status Flags Register */
char pos_real[16]; /* U - Position as read (degrees) */
char name[16]; /* MN */
int dec_pt; /* A - # of decimal places */
int enc_factor[2]; /* FD - Encoder scaling factors (numer/denom) */
int mot_factor[2]; /* FM - Motor scaling factors (numer/denom) */
char inertia_tol[16];/* D - Inertia tol'nce (sec) (Schleppfehler) */
int ramp; /* E - Start/stop ramp (kHz/sec) */
int loop_mode; /* F - Open loop/Closed loop (0/1) */
int slow_hz; /* G - Start/stop frequency (Mot-S/sec) */
char lims[2][16]; /* H - Lower/Upper limits */
int fast_hz; /* J - Top speed (Mot-S/sec) */
int ref_mode; /* K - Reference mode */
int backlash; /* L - Backlash par (Mot-S) (Spielausgleich) */
int pos_tol; /* M - Position tolerance (Enc-Steps) */
char ref_param[16]; /* Q - Parameter for "Goto Reference" */
int is_sided; /* T - One-sided operation flag (0 = no) */
char null_pt[16]; /* V - Null point */
int ac_par; /* W - Air-cushion dependency */
int enc_circ; /* Z - circumference of encoder (Enc-Steps) */
int stat_pos; /* SP - # of positionings */
int stat_pos_flt; /* ST - # of positioning faults (recovered) */
int stat_pos_fail; /* SR - # of positioning fails (abandoned) */
int stat_cush_fail; /* SA - # of air-cushion fails */
char set_real[16]; /* P - Position as set (degrees) */
int ac_state; /* AC - Air-cushion state (0 = down) */
int out; /* SO - State of Output Signal */
int in; /* RI - State of Input Signal */
};
/*------------------------------------------------ End of EL734_DEF.H --*/
#endif /* _el734_def_ */

28
hardsup/el734_errcodes.h Normal file
View File

@ -0,0 +1,28 @@
/*
** TAS_SRC:[LIB]EL734_ERRCODES.H
**
** Include file generated from EL734_ERRCODES.OBJ
**
** 29-AUG-2000 09:49:19.60
*/
#define EL734__VFY_ERR 0x865809C
#define EL734__NO_SOCKET 0x8658094
#define EL734__NOT_OPEN 0x865808C
#define EL734__FORCED_CLOSED 0x8658084
#define EL734__EMERG_STOP 0x865807C
#define EL734__BAD_TMO 0x8658074
#define EL734__BAD_STP 0x865806C
#define EL734__BAD_SOCKET 0x8658064
#define EL734__BAD_RNG 0x865805C
#define EL734__BAD_PAR 0x8658054
#define EL734__BAD_OVFL 0x865804C
#define EL734__BAD_OFL 0x8658044
#define EL734__BAD_MALLOC 0x865803C
#define EL734__BAD_LOC 0x8658034
#define EL734__BAD_ILLG 0x865802C
#define EL734__BAD_DEV 0x8658024
#define EL734__BAD_CMD 0x865801C
#define EL734__BAD_ASYNSRV 0x8658014
#define EL734__BAD_ADR 0x865800C
#define EL734__FACILITY 0x865

2638
hardsup/el734_utility.c Normal file

File diff suppressed because it is too large Load Diff

29
hardsup/el734fix.h Normal file
View File

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------
Fix file for David renaming lots of el734 error codes.
Mark Koennecke, October 1998
----------------------------------------------------------------------------*/
#ifndef EL734FIX
#define EL734FIX
#include "asynsrv_errcodes.h"
#define EL734__BAD_HOST ASYNSRV__BAD_HOST
#define EL734__BAD_BIND ASYNSRV__BAD_BIND
#define EL734__BAD_SENDLEN ASYNSRV__BAD_SEND_LEN
#define EL734__BAD_SEND ASYNSRV__BAD_SEND
#define EL734__BAD_SEND_PIPE ASYNSRV__BAD_SEND_PIPE
#define EL734__BAD_SEND_UNKN ASYNSRV__BAD_SEND_UNKN
#define EL734__BAD_RECV ASYNSRV__BAD_RECV
#define EL734__BAD_RECV_PIPE ASYNSRV__BAD_RECV_PIPE
#define EL734__BAD_RECV_NET ASYNSRV__BAD_RECV_NET
#define EL734__BAD_SEND_NET ASYNSRV__BAD_SEND_NET
#define EL734__BAD_RECV_UNKN ASYNSRV__BAD_RECV_UNKN
#define EL734__BAD_NOT_BCD ASYNSRV__BAD_NOT_BCD
#define EL734__BAD_RECVLEN ASYNSRV__BAD_RECV_LEN
#define EL734__BAD_FLUSH ASYNSRV__BAD_FLUSH
#define EL734__BAD_RECV1 ASYNSRV__BAD_RECV1
#define EL734__BAD_RECV1_PIPE ASYNSRV__BAD_RECV1_PIPE
#define EL734__BAD_RECV1_NET ASYNSRV__BAD_RECV1_NET
#define EL734__BAD_CONNECT ASYNSRV__BAD_CONNECT
#define EL734__BAD_ID EL734__BAD_DEV
#endif /* el734fix */

644
hardsup/el734tcl.c Normal file
View File

@ -0,0 +1,644 @@
/*--------------------------------------------------------------------------
Some code to make EL734 motors as used at SINQ available in TCL.
Just a wrapper around David Maden's motor control routines.
You are free to use and modify this software for noncommercial
usage.
No warranties or liabilities of any kind taken by me or my employer
Mark Koennecke June 1996
----------------------------------------------------------------------------*/
#include "sinq_prototypes.h"
/* #include <timers.h>*/
#include <tcl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rs232c_def.h"
#include "el734_def.h"
#define INACTIVE 999.8
#define MOTACURRACY 0.02
#define False 0
#define True 1
typedef struct
{
float fUpper; /* upper limit */
float fLower; /* Lower Limit */
int iFix; /* fixed, unfixed flag */
float fSoftZero; /* SW-zero point */
float fSoftUpper; /* software upper boundary*/
float fSoftLower; /* " lower " */
int iLowFlag, iUpFlag, iZeroFlag; /*activity flags */
void *pData; /* EL734 open struct */
} EL734st;
EXTERN int EL734Action(ClientData pDat, Tcl_Interp *i, int a, char *argv[]);
static void EL734Error2Text(char *pBuffer, int errcode);
/*---------------------------------------------------------------------------
Tcl has a high niceness level. It deletes a command properly when
exiting, reinitializing etc. I use this facility to kill off the
motor initialised in EL734.
---------------------------------------------------------------------------*/
EXTERN void EL734Murder(ClientData pData)
{
EL734st *pTa = (EL734st *)pData;
EL734_Close(&(pTa->pData));
free(pData);
}
/*----------------------------------------------------------------------------
EL734 is the main entry point for this stuff. It connects to a motor
and, on success, creates a new command with the name of the motor.
Syntax:
EL734 name host port channel index
---------------------------------------------------------------------------*/
int EL734(ClientData clientData, Tcl_Interp *interp,
int argc, char *argv[])
{
int iRet;
EL734st *pEL734 = NULL;
int iPort, iChannel, iMotor;
char *pErr = NULL;
char pBueffel[80];
/* check arguments */
if(argc < 6)
{
Tcl_AppendResult(interp,
" Insufficient arguments: EL734 name host port channel index"
, (char *) NULL);
return TCL_ERROR;
}
/* convert arguments */
iRet = Tcl_GetInt(interp,argv[3],&iPort);
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need integer value for port",
(char *)NULL);
return iRet;
}
iRet = Tcl_GetInt(interp,argv[4],&iChannel);
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need integer value for channel",
(char *)NULL);
return iRet;
}
iRet = Tcl_GetInt(interp,argv[5],&iMotor);
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need integer value for motor",
(char *)NULL);
return iRet;
}
/* make a new pointer, initialise EL734st */
pEL734 = (EL734st *)malloc(sizeof(EL734st));
if(pEL734 ==NULL)
{
Tcl_AppendResult(interp,"No memory in EL734",NULL);
return TCL_ERROR;
}
pEL734->iFix = False;
pEL734->fSoftZero = INACTIVE+1;
pEL734->fSoftUpper = INACTIVE+1.;
pEL734->fSoftLower = -INACTIVE-1.;
pEL734->iZeroFlag = False;
pEL734->iLowFlag = False;
pEL734->iUpFlag = False;
/* open the motor, finally */
iRet = EL734_Open(&(pEL734->pData), argv[2],iPort,iChannel,iMotor,"STPMC EL734");
if(iRet) /* success */
{
/* figure out motor limits */
EL734_GetLimits(&(pEL734->pData),&(pEL734->fLower),
&(pEL734->fUpper));
/* handle TCL, create new command: the motor */
Tcl_CreateCommand(interp,strdup(argv[1]),EL734Action,
(ClientData)pEL734,EL734Murder);
Tcl_AppendResult(interp,strdup(argv[1]),(char *)NULL);
return TCL_OK;
}
else
{
EL734_ErrInfo(&pErr,&iPort,&iChannel, &iMotor);
EL734Error2Text(pBueffel,iPort);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
free(pEL734);
return TCL_ERROR;
}
}
/*---------------------------------------------------------------------------
CheckPos checks a position and converts it to a real position.
Returns TCL_ERROR on mistake, TCL_OK else
---------------------------------------------------------------------------*/
static int CheckPos(Tcl_Interp *interp, EL734st *pData,
float fRequested, float *fDrive)
{
float fPos;
char pBueffel[132];
/* fixed ? */
if(pData->iFix)
{
Tcl_AppendResult(interp,"Motor fixed",NULL);
return TCL_ERROR;
}
/* check against SW-boundaries */
if(pData->iUpFlag)
{
if(fRequested > pData->fSoftUpper)
{
sprintf(pBueffel,
"Requested position: %f violates SW-boundary %f",
fRequested, pData->fSoftUpper);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
}
if(pData->iLowFlag)
{
if(fRequested < pData->fSoftLower)
{
sprintf(pBueffel,
"Requested position: %f violates SW-boundary %f",
fRequested, pData->fSoftLower);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
}
/* correct for zero point */
if(pData->iZeroFlag)
{
fPos = fRequested - pData->fSoftZero;
}
else
{
fPos = fRequested;
}
/* check HW-boundaries */
if( (fPos < pData->fLower) || (fPos > pData->fUpper) )
{
sprintf(pBueffel," %f outside limits %f %f",
fPos,pData->fLower, pData->fUpper);
Tcl_AppendResult(interp,"Requested position: ",
pBueffel,(char *)NULL);
return TCL_ERROR;
}
*fDrive = fPos;
return TCL_OK;
}
/* -------------------------------------------------------------------------
fucking standard library missing functionality!!!!!!!!!!!!!!!!
---------------------------------------------------------------------------*/
static float absf(float x)
{
if(x < .0)
return -x;
else
return x;
}
/*--------------------------------------------------------------------------
EL734 Action is the routine where commands send to the motor will
end up.
Syntax:
motor lim shows motor limits
motor dr val drives the motor to val
motor run val set the motor in motion, without waiting
for completion
motor pos shows motor position
motor fix fixes a motor at a position
motor unfix unfixes a fixed motor
motor zero val set a software zero point
motor upper val sets a software upper limit
motor lower val sets a software lower limit
----------------------------------------------------------------------------*/
EXTERN int EL734Action(ClientData clientData, Tcl_Interp *interp,
int argc, char *argv[])
{
EL734st *pData = (EL734st *)clientData;
char pBueffel[80];
char *pErr = NULL;
int iRet, iMSR, iOMSR, iFPC, iFRC, iSS;
float fPos, fNpos;
double dPos;
int i;
struct RS__RplyStruct *pReply = NULL;
/* check parameters */
if(argc < 2)
{
Tcl_AppendResult(interp,
"Usage: motor and either dr, pos, hlim slim run zero up lo",(char *)NULL);
return TCL_ERROR;
}
if(pData == NULL)
{
Tcl_AppendResult(interp,
"Motor data lost!!!!!!!!",(char *)NULL);
return TCL_ERROR;
}
/* check for HW-lim */
if(strcmp(argv[1],"hlim") == 0)
{
sprintf(pBueffel," %f %f",pData->fLower,pData->fUpper);
Tcl_AppendResult(interp,pBueffel,(char *)NULL);
return TCL_OK;
}
/* check for SW-lim */
if(strcmp(argv[1],"slim") == 0)
{
sprintf(pBueffel," %f %f",pData->fSoftLower,pData->fSoftUpper);
Tcl_AppendResult(interp,pBueffel,(char *)NULL);
return TCL_OK;
}
/* fix & unfix */
if(strcmp(argv[1],"fix") == 0)
{
pData->iFix = True;
return TCL_OK;
}
if(strcmp(argv[1],"unfix") == 0)
{
pData->iFix = False;
return TCL_OK;
}
/* reset */
if(strcmp(argv[1],"reset")== 0)
{
pData->iFix = False;
pData->iLowFlag = False;
pData->iUpFlag = False;
pData->iZeroFlag = False;
return TCL_OK;
}
/* check for pos */
if(strcmp(argv[1],"pos") == 0)
{
iRet = EL734_GetStatus(&(pData->pData),
&iMSR,
&iOMSR,
&iFPC,
&iFRC,
&iSS,
&fPos);
if(!iRet)
{
EL734_ErrInfo(&pErr,&iMSR,&iOMSR, &iSS);
EL734Error2Text(pBueffel,iMSR);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
else
{
if(pData->iZeroFlag)
{
fPos += pData->fSoftZero;
}
sprintf(pBueffel," %f",fPos);
Tcl_AppendResult(interp,pBueffel,NULL);
return TCL_OK;
}
}
/* zero point */
if(strcmp(argv[1],"zero") == 0)
{
/* check for zero already been defined */
if(pData->iZeroFlag)
{
Tcl_AppendResult(interp,
"Request to set new zero point rejected.",
" Use reset before new definition. ",
" I'll get confused otherwise ",
NULL);
return TCL_ERROR;
}
/* get the new position */
if(argc < 3)
{
Tcl_AppendResult(interp,
"Usage: motor zero val",NULL);
return TCL_ERROR;
}
iRet = Tcl_GetDouble(interp,argv[2],&dPos);
fNpos = dPos;
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need float value for new zeropint",
(char *)NULL);
return iRet;
}
pData->fSoftZero = -fNpos;
pData->iZeroFlag = True;
return TCL_OK;
}
/* upper SW-limit */
if(strcmp(argv[1],"up") == 0)
{
/* get the new position */
if(argc < 3)
{
Tcl_AppendResult(interp,
"Usage: motor up val",NULL);
return TCL_ERROR;
}
iRet = Tcl_GetDouble(interp,argv[2],&dPos);
fNpos = dPos;
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need float value for new upper limit",
(char *)NULL);
return iRet;
}
pData->fSoftUpper = fNpos;
pData->iUpFlag = True;
return TCL_OK;
}
/* lower SW-limit */
if(strcmp(argv[1],"lo") == 0)
{
/* get the new position */
if(argc < 3)
{
Tcl_AppendResult(interp,
"Usage: motor lo val",NULL);
return TCL_ERROR;
}
iRet = Tcl_GetDouble(interp,argv[2],&dPos);
fNpos = dPos;
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need float value for new lower limit",
(char *)NULL);
return iRet;
}
pData->fSoftLower = fNpos;
pData->iLowFlag = True;
return TCL_OK;
}
/* this is most important: dr for Drive */
if(strcmp(argv[1],"dr") == 0)
{
/* get the new position */
if(argc < 3)
{
Tcl_AppendResult(interp,
"Usage: motor dr val",NULL);
return TCL_ERROR;
}
iRet = Tcl_GetDouble(interp,argv[2],&dPos);
fNpos = dPos;
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need value to drive to",
(char *)NULL);
return iRet;
}
/* check if compatible with limits */
if(CheckPos(interp,pData,fNpos,&fPos) == TCL_ERROR)
return TCL_ERROR;
/* finally move */
iRet = EL734_MoveWait(&(pData->pData), fPos, &iOMSR,
&iFPC, &iFRC,&fNpos);
/* 99.99999999999% of all code is error checking */
if(!iRet)
{
EL734_ErrInfo(&pErr,&iMSR,&iOMSR, &iSS);
EL734Error2Text(pBueffel,iMSR);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
/* check if driving has been done */
if(absf(fPos-fNpos) > MOTACURRACY)
{
Tcl_AppendResult(interp,
" Motor error: inacurate driving!",
" Probably something serious is wrong ",
" Check the fucking hardware ",
NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/* this is most important: run for Driving without waiting */
if(strcmp(argv[1],"run") == 0)
{
/* get the new position */
if(argc < 3)
{
Tcl_AppendResult(interp,
"Usage: motor run val",NULL);
return TCL_ERROR;
}
iRet = Tcl_GetDouble(interp,argv[2],&dPos);
fNpos = dPos;
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need value to run for",
(char *)NULL);
return iRet;
}
/* check if compatible with limits */
if(CheckPos(interp,pData,fNpos,&fPos) == TCL_ERROR)
return TCL_ERROR;
/* finally move */
iRet = EL734_MoveNoWait (&(pData->pData), fPos);
/* 99.99999999999% of all code is error checking */
if(!iRet)
{
EL734_ErrInfo(&pErr,&iMSR,&iOMSR, &iSS);
EL734Error2Text(pBueffel,iMSR);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/* the dangerous, undocumented expert command: com:
sends something directly to the motor. All args following
com will be concatenated in one string, closed with \r
and send to the motor . A GetReply will be invoked in order
to yield a return value. Usage by normal motor users strictly
discouraged.
*/
if(strcmp(argv[1],"com") == 0)
{
strcpy(pBueffel,argv[2]);
for(i = 3; i < argc; i++)
{
strcat(pBueffel," ");
strcat(pBueffel,argv[i]);
}
sprintf(pBueffel,"%s\r",pBueffel);
iRet = EL734_SendCmnds(&(pData->pData),pBueffel,NULL);
if(!iRet)
{
EL734_ErrInfo(&pErr,&iMSR,&iOMSR, &iSS);
EL734Error2Text(pBueffel,iMSR);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
/* fetch reply */
pReply = (struct RS__RplyStruct *)EL734_GetReply(
&(pData->pData),NULL);
while(pReply != NULL)
{
Tcl_AppendElement(interp,pReply->rply);
pReply = (struct RS__RplyStruct *)EL734_GetReply(
&(pData->pData),pReply);
}
return TCL_OK;
}
/* if we end here an unknown command has been sent */
Tcl_AppendResult(interp,
"Usage: motor and either dr, run,zero, pos, hlim"
"slim up low reset fix unfix",(char *)NULL);
return TCL_ERROR;
}
/*---------------------------------------------------------------------------
EL734Error2Text converts between an EL734 error code to text
-----------------------------------------------------------------------------*/
void EL734Error2Text(char *pBuffer, int iErr)
{
switch(iErr)
{
case -28:
strcpy(pBuffer,"EL734__BAD_ADR");
break;
case -8:
strcpy(pBuffer,"EL734__BAD_BIND");
break;
case -30:
strcpy(pBuffer,"EL734__BAD_BSY");
break;
case -3:
strcpy(pBuffer,"EL734__BAD_CMD");
break;
case -9:
strcpy(pBuffer,"EL734__BAD_CONNECT");
break;
case -23:
strcpy(pBuffer,"EL734__BAD_FLUSH");
break;
case -6:
strcpy(pBuffer,"EL734__BAD_HOST");
break;
case -10:
strcpy(pBuffer,"EL734__BAD_ID");
break;
case -5:
strcpy(pBuffer,"EL734__BAD_ILLG");
break;
case -2:
strcpy(pBuffer,"EL734__BAD_LOC");
break;
case -11:
strcpy(pBuffer,"EL734__BAD_MALLOC");
break;
case -21:
strcpy(pBuffer,"EL734__BAD_NOT_BCD");
break;
case -4:
strcpy(pBuffer,"EL734__BAD_OFL");
break;
case -29:
strcpy(pBuffer,"EL734__BAD_PAR");
break;
case -17:
strcpy(pBuffer,"EL734__BAD_RECV");
break;
case -19:
strcpy(pBuffer,"EL734__BAD_RECV_NET");
break;
case -18:
strcpy(pBuffer,"EL734__BAD_RECV_PIPE");
break;
case -20:
strcpy(pBuffer,"EL734__BAD_RECV_UNKN");
break;
case -22:
strcpy(pBuffer,"EL734__BAD_RECVLEN");
break;
case -24:
strcpy(pBuffer,"EL734__BAD_RECV1");
break;
case -26:
strcpy(pBuffer,"EL734__BAD_RECV1_NET");
break;
case -25:
strcpy(pBuffer,"EL734__BAD_RECV1_PIPE");
break;
case -27:
strcpy(pBuffer,"EL734__BAD_RNG");
break;
case -13:
strcpy(pBuffer,"EL734__BAD_SEND");
break;
case -14:
strcpy(pBuffer,"EL734__BAD_SEND_PIPE");
break;
case -15:
strcpy(pBuffer,"EL734__BAD_SEND_NET");
break;
case -16:
strcpy(pBuffer,"EL734__BAD_SEND_UNKN");
break;
case -12:
strcpy(pBuffer,"EL734__BAD_SENDLEN");
break;
case -7:
strcpy(pBuffer,"EL734__BAD_SOCKET");
break;
case -1:
strcpy(pBuffer,"EL734__BAD_TMO");
break;
default:
strcpy(pBuffer,"Unknown EL734 error");
break;
}
}

67
hardsup/el737_def.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef _el737_def_
#define _el737_def_
/*----------------------------------------- [...LIB.SINQ]EL737_DEF.H Ident V02J
** Definitions for the EL737 Neutron Counter
**
** On UNIX systems, this file is located in /public/lib/include
** On VMS systems, this file is a module in mad_lib:sinq_c.tlb
*/
#include <asynsrv_def.h>
#include <rs232c_def.h>
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
#ifndef _EL737_errcodes_
#define _EL737_errcodes_
#include <el737_errcodes.h>
#endif
enum EL737_States {
UNKNOWN = -2,
OFFLINE = -1,
MS = 0x0,
PTS = 0x1,
PCS = 0x2,
LRTS = 0x5,
LRCS = 0x6,
PTSP = 0x9,
PCSP = 0xA,
LRTSP = 0xD,
LRCSP = 0xE};
enum EL737_Consts {
VMECNT__PRESET_COUNT,
VMECNT__PRESET_TIME,
VMECNT__FULL,
VMECNT__SHORT,
VMECNT__INCR};
/*
** Structure to which the EL737_Open handle points.
*/
struct EL737info {
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
int c5, c6, c7, c8;
struct RS__MsgStruct to_host;
struct RS__RespStruct from_host;
};
/*
** Structure holding everything that is known about a VME Neutron Counter.
*/
struct Counter_State {
int state; /* RS */
char timer[16]; /* RT \ RA */
int cntrs[8]; /* RC 1 ... RC 8 / */
char rates[8][16]; /* RR 1 ... RR 8 */
char thresh_integ_time[8][16]; /* DI 1 ... DI 8 */
char rate_integ_time[16]; /* DT */
int analog_indx; /* DA */
int thresh_indx; /* DR */
char threshes[8][16]; /* DL 1 ... DL 8 */
int mon_preset; /* MP */
char timer_preset[16]; /* TP */
};
/*----------------------------------------------------- End of EL737_DEF.H --*/
#endif /* _el737_def_ */

27
hardsup/el737_errcodes.h Normal file
View File

@ -0,0 +1,27 @@
/*
** TAS_SRC:[LIB]EL737_ERRCODES.H
**
** Include file generated from EL737_ERRCODES.OBJ
**
** 29-AUG-2000 09:49:21.56
*/
#define EL737__NO_VALUE 0x8668094
#define EL737__NO_SOCKET 0x866808C
#define EL737__NOT_OPEN 0x8668084
#define EL737__FORCED_CLOSED 0x866807C
#define EL737__CNTR_OVFL 0x8668074
#define EL737__BAD_TMO 0x866806C
#define EL737__BAD_SOCKET 0x8668064
#define EL737__BAD_PAR 0x866805C
#define EL737__BAD_OVFL 0x8668054
#define EL737__BAD_OFL 0x866804C
#define EL737__BAD_MALLOC 0x8668044
#define EL737__BAD_LOC 0x866803C
#define EL737__BAD_ILLG 0x8668034
#define EL737__BAD_DEV 0x866802C
#define EL737__BAD_CNTR 0x8668024
#define EL737__BAD_CMD 0x866801C
#define EL737__BAD_BSY 0x8668014
#define EL737__BAD_ASYNSRV 0x866800C
#define EL737__FACILITY 0x866

1742
hardsup/el737_utility.c Normal file

File diff suppressed because it is too large Load Diff

33
hardsup/el737fix.h Normal file
View File

@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------
Fix file for David renaming lots of el734 error codes.
Mark Koennecke, October 1998
----------------------------------------------------------------------------*/
#ifndef EL737FIX
#define EL737FIX
#include "asynsrv_errcodes.h"
#define EL737__BAD_HOST ASYNSRV__BAD_HOST
#define EL737__BAD_BIND ASYNSRV__BAD_BIND
#define EL737__BAD_SENDLEN ASYNSRV__BAD_SEND_LEN
#define EL737__BAD_SEND ASYNSRV__BAD_SEND
#define EL737__BAD_SEND_PIPE ASYNSRV__BAD_SEND_PIPE
#define EL737__BAD_SEND_UNKN ASYNSRV__BAD_SEND_UNKN
#define EL737__BAD_RECV ASYNSRV__BAD_RECV
#define EL737__BAD_RECV_PIPE ASYNSRV__BAD_RECV_PIPE
#define EL737__BAD_RECV_NET ASYNSRV__BAD_RECV_NET
#define EL737__BAD_SEND_NET ASYNSRV__BAD_SEND_NET
#define EL737__BAD_RECV_UNKN ASYNSRV__BAD_RECV_UNKN
#define EL737__BAD_NOT_BCD ASYNSRV__BAD_NOT_BCD
#define EL737__BAD_RECVLEN ASYNSRV__BAD_RECV_LEN
#define EL737__BAD_FLUSH ASYNSRV__BAD_FLUSH
#define EL737__BAD_RECV1 ASYNSRV__BAD_RECV1
#define EL737__BAD_RECV1_PIPE ASYNSRV__BAD_RECV1_PIPE
#define EL737__BAD_RECV1_NET ASYNSRV__BAD_RECV1_NET
#define EL737__BAD_CONNECT ASYNSRV__BAD_CONNECT
#define EL737__BAD_ID -99995
#define EL737__BAD_SNTX -99991
#define EL737__BAD_REPLY -99992
#define EL737__BAD_ADR -99993
#define EL737__BAD_RNG -99994
#endif /* el734fix */

400
hardsup/el737tcl.c Normal file
View File

@ -0,0 +1,400 @@
/*--------------------------------------------------------------------------
Some code to make EL737 COUNTERS as used at SINQ available in TCL.
Just a wrapper around David Maden's COUNTER routines.
You are free to use and modify this software for noncommercial
usage.
No warranties or liabilities of any kind taken by me or my employer
Mark Koennecke July 1996
----------------------------------------------------------------------------*/
#include "sinq_prototypes.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
#include <timers.h>
*/
#include <tcl.h>
#include "el737_def.h"
#define True 1
#define False 0
typedef struct
{
void *pData; /* EL737 open struct */
} EL737st;
EXTERN int EL737Action(ClientData pDat, Tcl_Interp *i, int a, char *argv[]);
static void EL737Error2Text(char *pBuffer, int errcode);
/*---------------------------------------------------------------------------
Tcl has a high niceness level. It deletes a command properly when
exiting, reinitializing etc. I use this facility to kill off the
counter initialised in CterEL737.
---------------------------------------------------------------------------*/
EXTERN void EL737Murder(ClientData pData)
{
EL737st *pTa = (EL737st *)pData;
EL737_Close(&(pTa->pData));
free(pData);
}
/*----------------------------------------------------------------------------
CterEL737 is the main entry point for this stuff. It connects to a counter
and, on success, creates a new command with the name of the counter.
Syntax:
EL737 name host port channel
---------------------------------------------------------------------------*/
int CterEL737(ClientData clientData, Tcl_Interp *interp,
int argc, char *argv[])
{
int iRet;
EL737st *pEL737 = NULL;
int iPort, iChannel, iMotor;
char *pErr = NULL;
char pBueffel[80];
/* check arguments */
if(argc < 5)
{
Tcl_AppendResult(interp,
" Insufficient arguments: CterEL737 name host port channel"
, (char *) NULL);
return TCL_ERROR;
}
/* convert arguments */
iRet = Tcl_GetInt(interp,argv[3],&iPort);
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need integer value for port",
(char *)NULL);
return iRet;
}
iRet = Tcl_GetInt(interp,argv[4],&iChannel);
if(iRet == TCL_ERROR)
{
Tcl_AppendResult(interp,"Need integer value for channel",
(char *)NULL);
return iRet;
}
/* make a new pointer, initialise EL737st */
pEL737 = (EL737st *)malloc(sizeof(EL737st));
if(pEL737 ==NULL)
{
Tcl_AppendResult(interp,"No memory in EL734",NULL);
return TCL_ERROR;
}
/* open the rotten Counter, finally */
iRet = EL737_Open(&(pEL737->pData), argv[2],iPort,iChannel);
if(iRet) /* success */
{
/* handle TCL, create new command: the Counter */
Tcl_CreateCommand(interp,strdup(argv[1]),EL737Action,
(ClientData)pEL737,EL737Murder);
Tcl_AppendResult(interp,strdup(argv[1]),(char *)NULL);
return TCL_OK;
}
else
{
EL737_ErrInfo(&pErr,&iPort,&iChannel, &iMotor);
EL737Error2Text(pBueffel,iPort);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
free(pEL737);
return TCL_ERROR;
}
}
/*--------------------------------------------------------------------------
EL737 Action is the routine where commands send to the conter will
end up.
Syntax: timer starts counter with a preset value
counter wait val for counts or time and does
monitor not return before finished
timer starts counter with a preset value
counter start val for counts or time and
monitor returns immediatly
counter isDone returns True, false depending if
started run has ended or not
counter value gets counter values as a little list
consisting of:
{ counts monitor time }
counter Stop forces counter to stop
----------------------------------------------------------------------------*/
EXTERN int EL737Action(ClientData clientData, Tcl_Interp *interp,
int argc, char *argv[])
{
EL737st *pData = (EL737st *)clientData;
char pBueffel[132];
char pNumBuf[20];
char *pErr = NULL;
int iC1, iC2, iC3, iC4, iRS, iRet;
float fTime;
int iFlag = 0;
int iMode;
double dVal;
/* obviously we need at least a keyword! */
if(argc < 2)
{
Tcl_AppendResult(interp,"No keyword given",NULL);
return TCL_ERROR;
}
/* get values out */
if(strcmp(argv[1],"value") == 0)
{
iRet = EL737_GetStatus(&(pData->pData),&iC1, &iC2, &iC3,
&iC4,&fTime,&iRS);
if(!iRet)
{
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
EL737Error2Text(pBueffel,iC1);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
sprintf(pNumBuf,"%d",iC2);
Tcl_AppendElement(interp,pNumBuf);
sprintf(pNumBuf,"%d",iC1);
Tcl_AppendElement(interp,pNumBuf);
sprintf(pNumBuf,"%f",fTime);
Tcl_AppendElement(interp,pNumBuf);
return TCL_OK;
}
/* isDone ? */
if(strcmp(argv[1],"isDone") == 0)
{
iRet = EL737_GetStatus(&(pData->pData),&iC1, &iC2, &iC3,
&iC4,&fTime,&iRS);
if(!iRet)
{
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
EL737Error2Text(pBueffel,iC1);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
if(iRS == 0) /* done is true */
{
sprintf(pNumBuf,"%d",True);
}
else
{
sprintf(pNumBuf,"%d",False);
}
Tcl_AppendResult(interp,pNumBuf,(char *) NULL);
return TCL_OK;
}
/* actual counting neutrons in two different modes */
if(strcmp(argv[1],"wait") == 0)
{
iFlag = 2;
}
if(strcmp(argv[1],"start") == 0)
{
iFlag = 1;
}
if(iFlag > 0) /* we need to count */
{
if(argc < 4) /* not enough arguments */
{
Tcl_AppendResult(interp,"Usage: ",argv[0],argv[1],
" timer or monitor val",NULL);
return TCL_ERROR;
}
/* timer or monitor preset ? */
if(strcmp(argv[2],"timer") == 0)
{
iMode = 1;
}
else if (strcmp(argv[2],"monitor") == 0)
{
iMode = 2;
}
else
{
Tcl_AppendResult(interp,"Usage: ",argv[0],argv[1],
" timer or monitor val",NULL);
return TCL_ERROR;
}
/* get the preset value */
iRet = Tcl_GetDouble(interp,argv[3],&dVal);
if(iRet == TCL_ERROR)
{
return TCL_ERROR;
}
/* actual start collecting neutrons */
if(iMode == 1)
{
iRet = EL737_StartTime(&(pData->pData),(float)dVal,
&iRS);
}
else
{
iRet = EL737_StartCnt(&(pData->pData),(int)dVal,
&iRS);
}
if(!iRet)
{
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
EL737Error2Text(pBueffel,iC1);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
} /* end of count startup code */
/* if apropriate: wait */
if(iFlag == 2)
{
iRet = EL737_WaitIdle(&(pData->pData),&iC1, &iC2, &iC3,
&iC4,&fTime);
if(!iRet)
{
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
EL737Error2Text(pBueffel,iC1);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
else if(iFlag == 1)
{
return TCL_OK;
}
/* the stop command */
if(strcmp(argv[1],"stop") == 0)
{
iRet = EL737_Stop(&(pData->pData),&iC1, &iC2, &iC3,
&iC4,&fTime,&iRS);
if(!iRet)
{
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
EL737Error2Text(pBueffel,iC1);
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
Tcl_AppendResult(interp," obscure command: ",argv[1],
" not understood by EL737 counter", NULL);
return TCL_ERROR;
}
/*---------------------------------------------------------------------------
EL737Error2Text converts between an EL734 error code to text
-----------------------------------------------------------------------------*/
void EL737Error2Text(char *pBuffer, int iErr)
{
switch(iErr)
{
case -28:
strcpy(pBuffer,"EL737__BAD_ADR");
break;
case -8:
strcpy(pBuffer,"EL737__BAD_OVFL");
break;
case -30:
strcpy(pBuffer,"EL737__BAD_BSY");
break;
case -3:
strcpy(pBuffer,"EL737__BAD_SNTX");
break;
case -9:
strcpy(pBuffer,"EL737__BAD_CONNECT");
break;
case -23:
strcpy(pBuffer,"EL737__BAD_FLUSH");
break;
case -6:
strcpy(pBuffer,"EL734__BAD_DEV");
break;
case -10:
strcpy(pBuffer,"EL737__BAD_ID");
break;
case -5:
strcpy(pBuffer,"EL737__BAD_ILLG");
break;
case -2:
strcpy(pBuffer,"EL737__BAD_LOC");
break;
case -11:
strcpy(pBuffer,"EL737__BAD_MALLOC");
break;
case -21:
strcpy(pBuffer,"EL737__BAD_NOT_BCD");
break;
case -4:
strcpy(pBuffer,"EL737__BAD_OFL");
break;
case -29:
strcpy(pBuffer,"EL737__BAD_PAR");
break;
case -17:
strcpy(pBuffer,"EL737__BAD_RECV");
break;
case -19:
strcpy(pBuffer,"EL737__BAD_RECV_NET");
break;
case -18:
strcpy(pBuffer,"EL737__BAD_RECV_PIPE");
break;
case -20:
strcpy(pBuffer,"EL737__BAD_RECV_UNKN");
break;
case -22:
strcpy(pBuffer,"EL737__BAD_RECVLEN");
break;
case -24:
strcpy(pBuffer,"EL737__BAD_RECV1");
break;
case -26:
strcpy(pBuffer,"EL737__BAD_RECV1_NET");
break;
case -25:
strcpy(pBuffer,"EL737__BAD_RECV1_PIPE");
break;
case -27:
strcpy(pBuffer,"EL737__BAD_RNG");
break;
case -13:
strcpy(pBuffer,"EL737__BAD_SEND");
break;
case -14:
strcpy(pBuffer,"EL737__BAD_SEND_PIPE");
break;
case -15:
strcpy(pBuffer,"EL737__BAD_SEND_NET");
break;
case -16:
strcpy(pBuffer,"EL737__BAD_SEND_UNKN");
break;
case -12:
strcpy(pBuffer,"EL737__BAD_SENDLEN");
break;
case -7:
strcpy(pBuffer,"EL737__BAD_SOCKET");
break;
case -1:
strcpy(pBuffer,"EL737__BAD_TMO");
break;
default:
strcpy(pBuffer,"Unknown EL737 error");
break;
}
}

31
hardsup/el755_def.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _el755_def_
#define _el755_def_
/*------------------------------------------------ EL755_DEF.H Ident V01C
** Definitions for the EL755 Magnet Power Supply Controller
**
** On UNIX systems, this file is located in /public/lib/include
** On VMS systems, this file is a module in mad_lib:sinq_c.tlb
*/
#include <asynsrv_def.h>
#include <rs232c_def.h>
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
#ifndef _EL755_errcodes_
#define _EL755_errcodes_
#include <el755_errcodes.h>
#endif
/*
** Structure to which the EL755_Open handle points.
*/
struct EL755info {
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
int index;
struct RS__MsgStruct to_host;
struct RS__RespStruct from_host;
};
/*------------------------------------------------ End of EL755_DEF.H --*/
#endif /* _el755_def_ */

27
hardsup/el755_errcodes.h Normal file
View File

@ -0,0 +1,27 @@
/*
** TAS_SRC:[LIB]EL755_ERRCODES.H
**
** Include file generated from EL755_ERRCODES.OBJ
**
** 29-AUG-2000 09:49:23.51
*/
#define EL755__TURNED_OFF 0x8678094
#define EL755__TOO_MANY 0x867808C
#define EL755__TOO_LARGE 0x8678084
#define EL755__OVFLOW 0x867807C
#define EL755__OUT_OF_RANGE 0x8678074
#define EL755__OFFLINE 0x867806C
#define EL755__NO_SOCKET 0x8678064
#define EL755__NOT_OPEN 0x867805C
#define EL755__FORCED_CLOSED 0x8678054
#define EL755__BAD_TMO 0x867804C
#define EL755__BAD_SOCKET 0x8678044
#define EL755__BAD_PAR 0x867803C
#define EL755__BAD_OFL 0x8678034
#define EL755__BAD_MALLOC 0x867802C
#define EL755__BAD_ILLG 0x8678024
#define EL755__BAD_DEV 0x867801C
#define EL755__BAD_CMD 0x8678014
#define EL755__BAD_ASYNSRV 0x867800C
#define EL755__FACILITY 0x867

26
hardsup/el755_errorlog.c Normal file
View File

@ -0,0 +1,26 @@
#define ident "1A01"
#ifdef VAXC
#module EL755_ErrorLog ident
#endif
#ifdef __DECC
#pragma module EL755_ErrorLog ident
#endif
#include <stdio.h>
/*
**--------------------------------------------------------------------------
** EL755_ErrorLog: This routine is called by EL755 routines in
** the case of certain errors. It simply prints
** to stderr. The user should supply his own
** routine if he wishes to log these errors in
** some other way.
*/
void EL755_ErrorLog (
/* ==============
*/ char *routine_name,
char *text) {
fprintf (stderr, "%s: %s\n", routine_name, text);
}
/*-------------------------------------------- End of EL755_ErrorLog.C =======*/

1445
hardsup/el755_utility.c Normal file

File diff suppressed because it is too large Load Diff

105
hardsup/err.c Normal file
View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------
EL734Error2Text converts between an EL734 error code to text
-----------------------------------------------------------------------------*/
void EL734Error2Text(char *pBuffer, int iErr)
{
switch(iErr)
{
case -28:
strcpy(pBuffer,"EL734__BAD_ADR");
break;
case -8:
strcpy(pBuffer,"EL734__BAD_BIND");
break;
case -30:
strcpy(pBuffer,"EL734__BAD_BSY");
break;
case -3:
strcpy(pBuffer,"EL734__BAD_CMD");
break;
case -9:
strcpy(pBuffer,"EL734__BAD_CONNECT");
break;
case -23:
strcpy(pBuffer,"EL734__BAD_FLUSH");
break;
case -6:
strcpy(pBuffer,"EL734__BAD_HOST");
break;
case -10:
strcpy(pBuffer,"EL734__BAD_ID");
break;
case -5:
strcpy(pBuffer,"EL734__BAD_ILLG");
break;
case -2:
strcpy(pBuffer,"EL734__BAD_LOC");
break;
case -11:
strcpy(pBuffer,"EL734__BAD_MALLOC");
break;
case -21:
strcpy(pBuffer,"EL734__BAD_NOT_BCD");
break;
case -4:
strcpy(pBuffer,"EL734__BAD_OFL");
break;
case -29:
strcpy(pBuffer,"EL734__BAD_PAR");
break;
case -17:
strcpy(pBuffer,"EL734__BAD_RECV");
break;
case -19:
strcpy(pBuffer,"EL734__BAD_RECV_NET");
break;
case -18:
strcpy(pBuffer,"EL734__BAD_RECV_PIPE");
break;
case -20:
strcpy(pBuffer,"EL734__BAD_RECV_UNKN");
break;
case -22:
strcpy(pBuffer,"EL734__BAD_RECVLEN");
break;
case -24:
strcpy(pBuffer,"EL734__BAD_RECV1");
break;
case -26:
strcpy(pBuffer,"EL734__BAD_RECV1_NET");
break;
case -25:
strcpy(pBuffer,"EL734__BAD_RECV1_PIPE");
break;
case -27:
strcpy(pBuffer,"EL734__BAD_RNG");
break;
case -13:
strcpy(pBuffer,"EL734__BAD_SEND");
break;
case -14:
strcpy(pBuffer,"EL734__BAD_SEND_PIPE");
break;
case -15:
strcpy(pBuffer,"EL734__BAD_SEND_NET");
break;
case -16:
strcpy(pBuffer,"EL734__BAD_SEND_UNKN");
break;
case -12:
strcpy(pBuffer,"EL734__BAD_SENDLEN");
break;
case -7:
strcpy(pBuffer,"EL734__BAD_SOCKET");
break;
case -1:
strcpy(pBuffer,"EL734__BAD_TMO");
break;
default:
strcpy(pBuffer,"Unknown EL734 error");
break;
}
}

109
hardsup/failinet.c Normal file
View File

@ -0,0 +1,109 @@
#define ident "1B01"
#ifdef VAXC
#module FailInet ident
#endif
#ifdef __DECC
#pragma module FailInet ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Computing Section |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]FAILINET.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]FailInet -
tasmad_disk:[mad.lib.sinq]FailInet +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb FailInet debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb FailInet
**
** Updates:
** 1A01 2-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
**============================================================================
** The following entry points are included:
**
#include <sinq_prototypes.h>
void FailInet (char *text)
** --------
** Input Args:
** text - A text string to be printed.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** none
** Global variables modified:
** none
** Routines called:
** GetErrno
** perror
** exit
** Description:
** The routine is useful if a fatal TCP/IP error occurs.
** The value of errno is printed and then "perror" is called.
** Then "exit" is called.
**============================================================================
** Global Definitions
*/
#ifdef VAXC
#include stdlib
#include stdio
#include errno
#include sinq_prototypes
#else
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sinq_prototypes.h>
#endif
/*--------------------------------------------------------------------------
** Global Variables
*/
/*
** FailInet: Some network failure has occurred.
*/
void FailInet (char *text) {
/* ========
** Output the given text and exit the process.
*/
int my_errno, my_vaxc_errno;
GetErrno (&my_errno, &my_vaxc_errno);
printf ("### Internet Error ###\n");
#ifdef __VMS
printf (" ### errno = %d.\n", my_errno);
printf (" ### vaxc$errno = %d.\n", my_vaxc_errno);
#else
printf (" ### errno = %d.\n", my_errno);
#endif
perror (text);
exit (EXIT_FAILURE);
}
/*------------------------------------------------- End of FAILINET.C =======*/

96
hardsup/geterrno.c Normal file
View File

@ -0,0 +1,96 @@
#define ident "1B01"
#ifdef VAXC
#module GetErrno ident
#endif
#ifdef __DECC
#pragma module GetErrno ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Computing Section |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]GETERRNO.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]GetErrno -
tasmad_disk:[mad.lib.sinq]GetErrno +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb GetErrno debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb GetErrno
**
** Updates:
** 1A01 2-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
**============================================================================
** The following entry points are included:
**
#include <sinq_prototypes.h>
void GetErrno (int *his_errno, int *his_vaxc_errno)
** --------
** Input Args:
** none
** Output Args:
** his_errno - value of "errno".
** his_vaxc_errno - on VMS systems only, value of "vaxc$errno". Otherwise
** set to 1.
** Modified Args:
** none
** Return status:
** none
** Global variables modified:
** none
** Description:
** GetErrno returns a copy of the universal error variable "errno" (and,
** on VMS systems, vaxc$errno) to a local variable supplied by the user.
** This can occasionally be useful when debugging since the debugger on
** VMS can't easily examine them.
**============================================================================
** Global Definitions
*/
#ifdef VAXC
#include errno
#else
#include <errno.h>
#endif
/*--------------------------------------------------------------------------
** Global Variables
*/
/*--------------------------------------------------------------------------
** GetErrno: Make copies of errno and vaxc$errno for debug.
*/
void GetErrno (int *his_errno, int *his_vaxc_errno) {
/* ========
*/
*his_errno = errno; /* Make copy of errno */
#ifdef __VMS
*his_vaxc_errno = vaxc$errno; /* Make copy of vaxc$errno */
#else
*his_vaxc_errno = 1;
#endif
return;
}
/*------------------------------------------------- End of GETERRNO.C =======*/

421
hardsup/itc4util.c Normal file
View File

@ -0,0 +1,421 @@
/*--------------------------------------------------------------------------
I T C 4 U T I L
A few utility functions for dealing with a ITC4 temperature controller
within the SINQ setup: host -- TCP/IP -- MAC --- RS-232.
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 <stdio.h>
#include <assert.h>
#include "serialsinq.h"
#include "itc4util.h"
/* -------------------------------------------------------------------------*/
int ITC4_Open(pITC4 *pData, char *pHost, int iPort, int iChannel, int iMode)
{
int iRet;
char pCommand[80];
char pReply[132];
pITC4 self = NULL;
self = (pITC4)malloc(sizeof(ITC4));
if(self == NULL)
{
return ITC4__BADMALLOC;
}
*pData = self;
self->iControl = 1;
self->iRead = 1;
self->iReadOnly = iMode;
self->fDiv = 10.;
self->fMult = 10.;
iRet = SerialOpen(&self->pData, pHost, iPort, iChannel);
if(iRet != 1)
{
return iRet;
}
/* set an lengthy timeout for the configuration in order to
prevent problems.
*/
iRet = SerialConfig(&self->pData, 100);
if(iRet != 1)
{
return iRet;
}
/* an identification test has been here, but I had to removed as not all
ITC4 controllers at SINQ answer the V command. Some versions of the
controller do not recognize it. Sighhhhhhh. I had to put it in again
in order to check for ITC-503, but I handle the thing by default as
an ITC4 if I do not get a proper response.
*/
self->i503 = 0;
iRet = SerialWriteRead(&self->pData,"V\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(strstr(pReply,"ITC503") != NULL)
{
self->i503 = 1;
}
if(!self->iReadOnly)
{
/* switch to remote and locked operation */
iRet = SerialWriteRead(&self->pData,"C3\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* set the control sensor, for this we need to switch A0 first,
the do it and switch back
*/
iRet = SerialWriteRead(&self->pData,"A0\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
sprintf(pCommand,"H%1.1d\r\n",self->iControl);
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* controls to automatic */
iRet = SerialWriteRead(&self->pData,"A3\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* reset timeout */
iRet = SerialConfig(&self->pData, 10);
if(iRet != 1)
{
return iRet;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
void ITC4_Close(pITC4 *pData)
{
char pReply[132];
int iRet;
pITC4 self;
self = *pData;
/* switch to local operation */
iRet = SerialWriteRead(&self->pData,"C0\r\n",pReply,131);
/* ignore errors on this one, the thing may be down */
/* close connection */
SerialClose(&self->pData);
/* free memory */
free(self);
*pData = NULL;
}
/*--------------------------------------------------------------------------*/
int ITC4_Config(pITC4 *pData, int iTmo, int iRead, int iControl,
float fDiv,float fMult)
{
int iRet;
char pReply[132];
char pCommand[10];
pITC4 self;
self = *pData;
/* first timeout */
if(iTmo > 0)
{
iRet = SerialConfig(&self->pData, iTmo);
if(iRet != 1)
{
return iRet;
}
}
/* Read Sensor */
if( (iRead > 0) && (iRead < 5) && (self->iRead != iRead) )
{
self->iRead = iRead;
}
/* Control Sensor */
if( (iControl > 0) && (iControl < 5) )
{
/* set the control sensor, for this we need to switch A0 first,
the do it and switch back
*/
iRet = SerialWriteRead(&self->pData,"A0\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* set sensor */
sprintf(pCommand,"H%1.1d\r\n",iControl);
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* controls to automatic */
iRet = SerialWriteRead(&self->pData,"A3\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
}
self->fDiv = fDiv;
self->fMult = fMult;
return 1;
}
/* --------------------------------------------------------------------------*/
int ITC4_Send(pITC4 *pData, char *pCommand, char *pReply, int iLen)
{
pITC4 self;
self = *pData;
/* make sure, that there is a \r at the end of the command */
if(strchr(pCommand,(int)'\r') == NULL)
{
strcat(pCommand,"\r");
}
return SerialWriteRead(&self->pData,pCommand,pReply,iLen);
}
/*--------------------------------------------------------------------------*/
int ITC4_Read(pITC4 *pData, float *fVal)
{
char pCommand[10], pReply[132];
int iRet;
float fRead = -9999999.;
pITC4 self;
self = *pData;
/* format and send R command */
sprintf(pCommand,"R%1.1d\r\n",self->iRead);
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* analyse reply */
if(pReply[0] != 'R')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
iRet = sscanf(&pReply[1],"%f",&fRead);
if(iRet != 1)
{
return ITC4__BADREAD;
}
if(self->i503)
{
*fVal = fRead;
}
else
{
*fVal = fRead/self->fDiv;
}
return 1;
}
/* -------------------------------------------------------------------------*/
int ITC4_Set(pITC4 *pData, float fVal)
{
char pCommand[10], pReply[132];
int iRet, i, iRead;
const float fPrecision = 0.0001;
float fSet, fDelta, fRead, fDum;
pITC4 self;
int iSet;
self = *pData;
if(self->iReadOnly)
{
return ITC4__READONLY;
}
/* format command */
if(self->i503)
{
sprintf(pCommand,"T%-7.3f\r\n",fVal);
}
else
{
fSet = fVal;
iSet = (int)(fSet*self->fMult);
sprintf(pCommand,"T%05.5d\r\n",iSet);
}
/* try three times: send, read, test, if OK return, else
resend. This must be done because the ITC4 tends to loose
characters
*/
for(i = 0; i < 3; i++)
{
/* send command */
iRet = SerialWriteRead(&self->pData,pCommand,pReply,131);
if(iRet != 1)
{
return iRet;
}
if(pReply[0] == '?')
{
strcpy(self->pAns,pReply);
return ITC4__BADCOM;
}
/* read the set value again */
iRead = self->iRead;
self->iRead = 0; /* make a R0 */
fDum = self->fDiv;
self->fDiv = self->fMult;
iRet = ITC4_Read(pData,&fRead);
self->iRead = iRead;
self->fDiv = fDum;
if(iRet != 1)
{
return iRet;
}
/* check the value read back */
if(self->i503)
{
fDelta = fRead - fVal;
}
else
{
fDelta = fRead - fSet;
}
if(fDelta < 0)
fDelta = -fDelta;
if(fDelta < fPrecision)
{
/* Success, go home */
return 1;
}
}
return ITC4__BADSET;
}
/* -------------------------------------------------------------------------*/
void ITC4_ErrorTxt(pITC4 *pData,int iCode, char *pError, int iLen)
{
char pBueffel[512];
pITC4 self;
self = *pData;
switch(iCode)
{
case ITC4__BADCOM:
sprintf(pBueffel,"ITC4: Invalid command or offline, got %s",
self->pAns);
strncpy(pError,pBueffel,iLen);
break;
case ITC4__BADPAR:
strncpy(pError,"ITC4: Invalid parameter specified",iLen);
break;
case ITC4__BADMALLOC:
strncpy(pError,"ITC4: Error allocating memory in ITC4",iLen);
break;
case ITC4__BADREAD:
strncpy(pError,"ITC4: Badly formatted answer",iLen);
break;
case ITC4__BADSET:
strncpy(pError,"ITC4: Failed three times to write new set value to ITC4",iLen);
break;
default:
SerialError(iCode, pError,iLen);
break;
}
}

124
hardsup/itc4util.h Normal file
View File

@ -0,0 +1,124 @@
/*---------------------------------------------------------------------------
I T C L 4 U T I L
A few utility functions for talking to a Oxford Instruments ITCL-4
temperature controller via the SINQ setup: TCP/IP--MAC--RS-232--
ITC-4.
Mark Koennecke, Juli 1997
----------------------------------------------------------------------------*/
#ifndef SINQITCL4
#define SINQITCL4
/*----------------------- ERRORCODES--------------------------------------
Most functions return a negative error code on failure. Error codes
defined are those defined for serialsinq plus a few additional ones:
*/
#define ITC4__BADCOM -501
/* command not recognized */
#define ITC4__BADPAR -502
/* bad parameter to command */
#define ITC4__BADMALLOC -503
/* error allocating memory */
#define ITC4__BADREAD -504
/* error analysing command string on Read */
#define ITC4__NOITC -510
/* Controller is no ITC-4 */
#define ITC4__BADSET -530
/* failed three times to set temperature */
#define ITC4__READONLY -531
/*------------------------------------------------------------------------*/
typedef struct __ITC4 {
int iRead;
int iControl;
void *pData;
char pAns[80];
float fDiv;
float fMult;
int iReadOnly;
int i503; /* flag for model 503, understanding float*/
} ITC4;
typedef struct __ITC4 *pITC4;
/*-----------------------------------------------------------------------*/
int ITC4_Open(pITC4 *pData,char *pHost, int iPort, int iChannel, int iMode);
/***** creates an ITC4 datastructure and opens a connection to the ITCL4
controller. Input Parameters are:
the hostname
the port number
the RS-232 channel number on the Mac.
iMode: 1 for ReadOnly, 0 for normal mode
Return values are 1 for success, a negative error code on
failure.
*/
void ITC4_Close(pITC4 *pData);
/****** close a connection to an ITC4controller and frees its
data structure. The only parameter is a pointer to the data
structure for this controller. This pointer will be invalid after
this call.
*/
int ITC4_Config(pITC4 *pData, int iTmo, int iRead,
int iControl, float fDiv, float fMult);
/***** configure some aspects of a ITC4temperature controller.
The parameter are:
- a pointer to the data structure for the controller as
returned by OpenITCL4
- a value for the connection timeout
- the temperature sensor to use for reading the
temperature.
- the temperature sensor used by the ITC4controller
for regulating the temperature.
- the divisor needed to calculate the real temperature
from the sensor.
The function returns 1 on success, a negative error code on
failure.
*/
int ITC4_Send(pITC4 *pData, char *pCommand, char *pReply, int iLen);
/******* send a the command in pCommand to the ITC4controller.
A possible reply is returned in the buffer pReply.
Maximum iLen characters are copied to pReply.
The first parameter is a pointer to a ITC4data structure
as returned by OpenITCL4.
Return values are 1 for success, a negative error code on
failure.
*/
int ITC4_Read(pITC4 *pData, float *fVal);
/******* reads the current actual temperature of the sensor
configured by ConfigITC4for reading. The value is returned
in fVal. The first parameter is a pointer to a ITCL4
data structure as returned by OpenITCL4.
Return values are 1 for success, a negative error code on
failure.
*/
int ITC4_Set(pITC4 *pData, float fVal);
/****** sets a new preset temperature in the ITC4temperature
controller. Parameters are:
- a pointer to a ITC4data structure as returned by OpenITCL4.
- the new preset value.
Return values are 1 for success, a negative error code on
failure.
*/
void ITC4_ErrorTxt(pITC4 *pData, int iCode, char *pError, int iLen);
/******* translates one of the negative error ITC4error codes
into text. Maximum iLen bytes will be copied to the
buffer pError;
*/
#endif

28
hardsup/make_gen Normal file
View File

@ -0,0 +1,28 @@
#---------------------------------------------------------------------------
# Makefile for the SINQ hardware support library
# included by a machine specific makefile
#
# Mark Koennecke, November 1996
# Markus Zolliker, March 2003
#--------------------------------------------------------------------------
.SUFFIXES:
.SUFFIXES: .c .o
OBJ= el734_utility.o asynsrv_utility.o stredit.o \
strjoin.o failinet.o geterrno.o el737_utility.o sinqhm.o serialsinq.o \
itc4util.o dillutil.o table.o el755_utility.o el755_errorlog.o \
makeprint.o StrMatch.o
libhlib.a: $(OBJ)
rm -f libhlib.a
ar cr libhlib.a $(OBJ)
ranlib libhlib.a
clean:
rm -f *.o *.a

15
hardsup/makefile_alpha Normal file
View File

@ -0,0 +1,15 @@
#---------------------------------------------------------------------------
# Makefile for the SINQ hardware support library
# machine-dependent part for Tru64 Unix
#
# Mark Koennecke, November 1996
# Markus Zolliker, March 2003
#--------------------------------------------------------------------------
# the following line only for fortified version
#DFORTIFY=-DFORTIFY
#==========================================================================
CC = cc
CFLAGS = -std1 -g $(DFORTIFY) -I$(SRC).. -I$(SRC).
include make_gen

15
hardsup/makefile_linux Normal file
View File

@ -0,0 +1,15 @@
#---------------------------------------------------------------------------
# Makefile for the SINQ hardware support library
# machine-dependent part for Redhat Linux with AFS at PSI
#
# Mark Koennecke, November 1996
# Markus Zolliker, March 2003
#--------------------------------------------------------------------------
# the following line only for fortified version
DFORTIFY=-DFORTIFY
#==========================================================================
CC = gcc
CFLAGS = -g -DLINUX $(DFORTIFY) -I$(SRC). -I$(SRC).. -I../src
include $(SRC)make_gen

276
hardsup/makeprint.c Normal file
View File

@ -0,0 +1,276 @@
#define ident "1B02"
#ifdef VAXC
#module MakePrint ident
#endif
#ifdef __DECC
#pragma module MakePrint ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]MAKEPRINT.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]MakePrint -
tasmad_disk:[mad.lib.sinq]MakePrint +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb MakePrint debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb MakePrint
**
** Updates:
** 1A01 30-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
** #include <sinq_prototypes.h>
**
** MakeCharPrintable - routine used by MakePrintable and MakeMemPrintable.
** MakeMemPrintable - version of MakePrintable which will handle
** buffers containing a NUL character.
** MakePrint - ensure all characters in a buffer are printable.
** MakePrintable - extended version of MakePrint.
**---------------------------------------------------------------------
** char *MakePrint (*text)
** ---------
** Input Args:
** none
** Output Args:
** none
** Modified Args:
** char *text
** Return status:
** A pointer to "text".
** Routines called:
** none
** Description:
** The routine ensures that all characters in "text" are 7-bit
** and then replaces any non-printing character with a ".". A trailing
** "\n" or "\r" is removed.
**---------------------------------------------------------------------------
** int *MakeCharPrintable (*out, out_size, in)
** -----------------
** Input Args:
** char in -- the character to be converted.
** int out_size -- the size of the out buffer.
** Output Args:
** char *out -- buffer to hold the converted text.
** Modified Args:
** none
** Return status:
** The number of characters put into the output buffer.
** Routines called:
** none
** Description:
** The routine puts a printable version of the character "in" into the
** "out" buffer. The printable version is generated as follows:
**
** a) If the parity bit of a char is set, a "^" is inserted into the
** output buffer, the parity bit of the char is cleared and processed
** further.
** b) If the char is "^", "\^" is inserted into the output buffer.
** c) If the char is "\", "\\" is inserted into the output buffer.
** d) If the char is a standard C-language control char, it gets replaced
** by a recognised backslash escape sequence. The following are
** recognised:
** NUL 0x00 --> \0
** BEL 0x07 --> \a
** BS 0x08 --> \b
** HT 0x09 --> \t
** LF 0x0a --> \n
** VT 0x0b --> \v
** FF 0x0c --> \f
** CR 0x0d --> \r
** e) If the character is printable (i.e. between " "/0x20 and "~"/0x7e
** inclusive), it is inserted into the output buffer as is.
** f) Anything else gets inserted as "\xxx", where xxx is the octal
** representation of the character.
**---------------------------------------------------------------------------
** char *MakePrintable (*out, out_size, *in)
** -------------
** Input Args:
** char *in -- the text to be converted.
** int out_size -- the size of the out buffer.
** Output Args:
** char *out -- buffer to hold the converted text.
** Modified Args:
** none
** Return status:
** A pointer to "out".
** Routines called:
** none
** Description:
** The routine converts characters in the "in" string to a printable
** representation using MakeCharPrintable and copies them to "out" until
** a null is detected.
**---------------------------------------------------------------------------
** char *MakeMemPrintable (*out, out_size, *in, in_len)
** ----------------
** Input Args:
** int out_size -- the size of the out buffer.
** char *in -- the text to be converted.
** int in_len -- the number of characters to be converted.
** Output Args:
** char *out -- buffer to hold the converted text.
** Modified Args:
** none
** Return status:
** A pointer to "out".
** Routines called:
** none
** Description:
** The routine is the same as MakePrintable, except that it converts
** a given number of characters rather than a null terminated string.
**============================================================================*/
/*
**---------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef FORTIFY
#include <fortify.h>
#endif
#include <sinq_prototypes.h>
#define NIL ('\0')
/*--------------------------------------------------------------------------
** Global Variables
*/
/*
**--------------------------------------------------------------------------
** MakeCharPrintable: makes a single character printable.
*/
int MakeCharPrintable (char *out, int out_size, char in) {
/* =================
**
** Return value is number of chars put into *out.
*/
char buff[8], *pntr;
pntr = buff;
if ((in & 0x80) != 0) { /* Parity bit set? */
*pntr++ = '^'; /* Yes. Put a '^' in the buffer .. */
in = in & 0x7f; /* .. and remove the parity bit. */
}
switch (in) {
case '^': *pntr++ = '\\'; *pntr++ = '^'; break;
case '\\': *pntr++ = '\\'; *pntr++ = '\\'; break;
case '\000': *pntr++ = '\\'; *pntr++ = '0'; break;
case '\007': *pntr++ = '\\'; *pntr++ = 'a'; break;
case '\010': *pntr++ = '\\'; *pntr++ = 'b'; break;
case '\011': *pntr++ = '\\'; *pntr++ = 't'; break;
case '\012': *pntr++ = '\\'; *pntr++ = 'n'; break;
case '\013': *pntr++ = '\\'; *pntr++ = 'v'; break;
case '\014': *pntr++ = '\\'; *pntr++ = 'f'; break;
case '\015': *pntr++ = '\\'; *pntr++ = 'r'; break;
default:
if ((in < ' ') || (in > '~')) {
pntr += sprintf (pntr, "\\%03.3o", in);
}else {
*pntr++ = in;
}
}
out_size = (out_size > (pntr - buff)) ? (pntr - buff) : out_size;
memcpy (out, buff, out_size);
return out_size;
}
/*
**--------------------------------------------------------------------------
** MakeMemPrintable: alternative version of MakePrintable.
*/
char *MakeMemPrintable (
/* ================
*/ char *out,
int out_size,
char *in,
int in_len) {
int i;
char *pntr;
if (out_size <= 0) return out;
while ((out_size > 1) && (in_len > 0)) {
i = MakeCharPrintable (out, (out_size - 1), *in);
out += i; out_size -= i;
in++; in_len--;
}
*out = NIL;
return out;
}
/*
**--------------------------------------------------------------------------
** MakePrint: Make all characters in a buffer printable.
*/
char *MakePrint (char *chr) {
/* =========
*/
int len, i;
for (i = 0; chr[i] != NIL; i++) chr[i] &= 0x7F;
len = strlen (chr);
if (len <= 0) return chr;
if (chr[len-1] == '\r') chr[len-1] = NIL;
if (chr[len-1] == '\n') chr[len-1] = NIL;
for (i = 0; chr[i] != NIL; i++) {
if (chr[i] < ' ') chr[i] = '.';
if (chr[i] == 0x7F) chr[i] = '.';
}
return chr;
}
/*
**--------------------------------------------------------------------------
** MakePrintable: improved version of MakePrint.
*/
char *MakePrintable (
/* =============
*/ char *out,
int out_size,
char *in) {
int i;
char *pntr;
if (out_size <= 0) return out;
while ((out_size > 1) && (*in != NIL)) {
i = MakeCharPrintable (out, (out_size - 1), *in);
in++; out += i; out_size -= i;
}
*out = NIL;
return out;
}
/*-------------------------------------------- End of MakePrint.C =======*/

186
hardsup/rs232c_def.h Normal file
View File

@ -0,0 +1,186 @@
#ifndef _rs232c_def_
#define _rs232c_def_
/*------------------------------------------------ RS232C_DEF.H Ident V02G
** Definitions for the RS-232-C Server Protocol
**
** On UNIX systems, this file is located in /public/lib/include
** On VMS systems, this file is a module in mad_lib:sinq_c.tlb
*/
#define RS__PROTOCOL_ID "V01A"
#define RS__PROTOCOL_ID_V01B "V01B"
#define RS__PROTOCOL_CODE 1 /* Code corresponding to RS__PROTOCOL_ID */
#define RS__PROTOCOL_CODE_V01B 2 /* Code corresponding to RS__PROTOCOL_ID_0 */
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
/*----------------------------------------------------------------------------
** Structure of Message from Client to Server - everything is sent in ASCII
** for LabView's benefit.
** Name #bytes Description
** ==== ====== ===========
** msg_size 4 Number of bytes following (rounded up to multiple
** of 4).
** msg_id 4 Message ident (an incrementing counter for debugging).
** c_pcol_lvl 4 Client-Protocol-Level (should be "V01A").
** serial_port 4 Serial port to which commands should be sent. This
** is a small integer).
** tmo 4 Time-out in units of 0.1 secs (<0 = "wait for ever").
** terms 1 + 3 Terminators. The first char gives the number of
** terminators (up to 3) and the following 3 chars
** are valid response terminators, e.g. "1\r\0\0".
** n_cmnds 4 Number of commands following.
** cmnds 356 The command buffer. This is a concatenated list of
** commands with the structure described below.
**
** Special Cases of msg_size
** -------------------------
** "-001" ==> the client is just about to close his connection.
** "-002" ==> this is a request to the server for him to turn on tracing.
** The reply should be simply an echo of the 4 bytes "-002".
** "-003" ==> this is a request to the server for him to turn off tracing.
** The reply should be simply an echo of the 4 bytes "-003".
** "-004" ==> this is a request to the server for him to flush his buffers.
** The reply should be simply an echo of the 4 bytes "-004".
**
** Structure of a command item in the cmnds buffer.
**
** a) RS__PROTOCOL_ID = "V01A"
**
** Name #bytes Description
** ==== ====== ===========
** cmnd_len 2 The number of bytes following encoded as 2 ASCII
** decimal chars.
** cmnd <cmnd_len> The command to be sent on Serial Port <serial_port>.
** The string should contain any required terminator
** bytes but should not be zero-terminated (unless
** the zero-byte should be transmitted at the end
** of the command). cmnd_len should count the
** terminator byte.
**
** An example of a command item might be: "06RMT 1\r"
**
** b) RS__PROTOCOL_ID = "V01B"
**
** Name #bytes Description
** ==== ====== ===========
** cmnd_len 4 The number of bytes following encoded as 4 ASCII
** decimal chars.
** cmnd <cmnd_len> The command to be sent on Serial Port <serial_port>.
** The string should contain any required terminator
** bytes but should not be zero-terminated (unless
** the zero-byte should be transmitted at the end
** of the command). <cmnd_len> should count the
** terminator byte.
**
** An example of a command item might be: "0006RMT 1\r"
**--------------------------------------------------------------------------*/
struct RS__MsgStruct {
char msg_size[4]; /* 4 ASCII decimal chars!! */
char msg_id[4];
char c_pcol_lvl[4]; /* Client protocol level */
char serial_port[4];
char tmo[4]; /* Units are 0.1 secs */
char terms[4];
char n_cmnds[4];
char cmnds[356];
};
/*
** The "cmnds" buffer in RS__MsgStruct is a concatenated
** list of the following structures.
*/
struct RS__CmndStruct {
char cmnd_len[2];
char cmnd[1];
};
struct RS__CmndStruct_V01B {
char cmnd_len[4];
char cmnd[1];
};
/*----------------------------------------------------------------------------
** Structure of Reply from Server to Client - everything is sent in ASCII
** for LabView's benefit.
**
** Name #bytes Description
** ==== ====== ===========
** msg_size 4 Number of bytes following (rounded up to multiple
** of 4).
** msg_id 4 Message ident (this is a copy of the msg_id field
** in the message from Client to Server).
** s_pcol_lvl 4 Server-Protocol-Level (should be "V01A" or "V01B").
** n_rply 4 Number of replies following. If < 0, an error has
** been detected and sub_status may give additional
** information.
** rplys 496 The reply buffer. This is a concatenated list of
** replies with the structure described below.
** sub_status 12 A sub-status code. This field overlays the first 12
** bytes of rplys and may provide additional
** information in the case that n_rply < 0.
**
** Structure of a reply item in the rplys buffer.
**
** a) RS__PROTOCOL_ID = "V01A"
**
** Name #bytes Description
** ==== ====== ===========
** rply_len 2 The number of bytes following encoded as 2 ASCII
** decimal chars.
** term 1 The terminating character which was detected at the
** end of the reply. This will be one of the
** characters specified in <terms>.
** rply <rply_len-1> The zero-terminated reply. This is effectively the
** reply as received with the terminating character
** replaced by '\0'.
**
** An example of a reply item might be: "08\r12.345\0"
**
** b) RS__PROTOCOL_ID = "V01B"
**
** Name #bytes Description
** ==== ====== ===========
** rply_len 4 The number of bytes following encoded as 4 ASCII
** decimal chars.
** term 1 The terminating character which was detected at the
** end of the reply. This will be one of the
** characters specified in <terms>.
** rply <rply_len-1> The zero-terminated reply. This is effectively the
** reply as received with the terminating character
** replaced by '\0'.
**
** An example of a reply item might be: "0009\r12.3456\0"
**--------------------------------------------------------------------------*/
struct RS__RespStruct {
char msg_size[4];
char msg_id[4];
char s_pcol_lvl[4]; /* Server protocol level */
char n_rply[4]; /* Error if < 0 */
union {
char rplys[496];
char sub_status[12];
} u;
};
/*
** The "rplys" buffer in RS__RespStruct is a
** concatenated list of the following structures.
*/
struct RS__RplyStruct {
char rply_len[2]; /* 2 ASCII decimal chars!!
** The length includes the
** terminator, term, and the
** zero terminator of rply.
*/
char term; /* The terminating character */
char rply[1]; /* Zero terminated string */
};
struct RS__RplyStruct_V01B {
char rply_len[4]; /* 4 ASCII decimal chars!!
** The length includes the
** terminator, term, and the
** zero terminator of rply.
*/
char term; /* The terminating character */
char rply[1]; /* Zero terminated string */
};
/*------------------------------------------------ End of RS232C_DEF.H --*/
#endif /* _rs232c_def_ */

914
hardsup/serialsinq.c Normal file
View 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;
}

56
hardsup/serialsinq.h Normal file
View File

@ -0,0 +1,56 @@
#line 156 "velodorn.w"
/*----------------------------------------------------------------------------
S E R I A L S I N Q
Utility functions for maintaining a connection to a RS--232 port on a
Macintosh computer running the SINQ terminal server application.
Mark Koennecke, Juli 1997
copyright: see implementation file
------------------------------------------------------------------------------*/
#ifndef SERIALSINQ
#define SERIALSINQ
#define NOREPLY -100
#define NOCONNECTION -121
#define SELECTFAIL -120
#define TIMEOUT -730
#define INTERRUPTED -132
#define OPENFAILURE -133
#line 30 "velodorn.w"
int SerialOpen(void **pData, char *pHost, int iPort, int iChannel);
int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel);
int SerialConfig(void **pData, int iTmo);
int SerialGetTmo(void **pData);
int SerialATerm(void **pData, char *pTerm);
int SerialAGetTerm(void **pData, char *pTerm, int iTermLen);
int SerialSendTerm(void **pData, char *pTerm);
int SerialGetSocket(void **pData);
int SerialClose(void **pData);
int SerialForceClose(void **pData);
int SerialSend(void **pData, char *pCommand);
int SerialReceive(void **pData, char *pBuffer, int iBufLen);
int SerialReceiveWithTerm(void **pData, char *pBuffer,
int iBufLen,char *cTerm);
int SerialError(int iError, char *pError, int iErrLen);
int SerialWriteRead(void **pData, char *pCommand,
char *pBuffer, int iBufLen);
int SerialNoReply(void **pData, char *pCommand);
#line 175 "velodorn.w"
/*-------------------------- The sleeperette -----------------------------*/
#line 116 "velodorn.w"
typedef int (*SerialSleep)(void *pData, int iTime);
void SetSerialSleep(void **pData, SerialSleep pFunc, void *pUserData);
#line 177 "velodorn.w"
#endif

108
hardsup/sinq_defs.h Normal file
View File

@ -0,0 +1,108 @@
/*
** TAS_SRC:[LIB]SINQ_DEFS.H
**
** Include file generated from SINQ_DEFS.OBJ
**
** 29-AUG-2000 09:49:31.72
*/
#define SS__NORMAL 0x1
#define SS__WASSET 0x9
#define SS__ILLEFC 0xEC
#define SS__UNASEFC 0x234
#define SEM_BIT 0x0
#define SEM_PID 0x4
#define SEM_WFLG 0x8
#define SEM_IDNT 0xC
#define SEM_CNT0 0x1C
#define SEM_CNT1 0x20
#define SEM_CNT2 0x24
#define SEM_CNT3 0x28
#define SEM_SUB_PID 0x2C
#define SEM_SIZE 0x40
#define SEM__CAMAC_CSR 0x0
#define SEM__CAMAC_IVG 0x40
#define SEM__CAMAC_GPIB 0x80
#define SEM__CAMAC_3344 0xC0
#define MAP__CAMAC_FIELD_0 0x0
#define MAP__CAMAC_FIELD_1 0x1
#define MAP__CAMAC_FIELD_2 0x2
#define MAP__CAMAC_FIELD_CSR 0x3
#define MAP__CAMAC_SEMAPHORE 0x4
#define MAP__DELTAT_CB 0x5
#define MAP__DELTAT_SCALERS 0x6
#define CAMIF__JCC 0x1
#define CAMIF__GEC0 0x3
#define CAMIF__CES 0x4
#define CAMIF__BIRA 0x5
#define CAMIF__GEC1 0x6
#define CAMIF__GEC2 0x7
#define CAMIF__GEC3 0x8
#define CAMIF__CCP 0x9
#define CAMIF__OS9 0xA
#define CAMIF__KCBD 0xB
#define CAMIF__VAN 0xC
#define CAMIF__KVCC 0xD
#define CAMIF__M_XQ 0x3
#define CAMIF__X_Q 0x0
#define CAMIF__X_NOQ 0x1
#define CAMIF__NOX_Q 0x2
#define CAMIF__NOX_NOQ 0x3
#define CAMIF__NO_CAMIF 0x4
#define CAMIF__TMOUT 0x8
#define CAMIF__ILLPAR 0xC
#define CAMIF__RPTFAIL 0x14
#define CAMIF__SEMTMO 0x18
#define MSR__BUSY 0x1
#define MSR__OK 0x2
#define MSR__REF_OK 0x4
#define MSR__STOPPED 0x8
#define MSR__LO_LIM 0x10
#define MSR__HI_LIM 0x20
#define MSR__HALT 0x40
#define MSR__RUN_FAULT 0x80
#define MSR__RUN_FAIL 0x100
#define MSR__POS_FAULT 0x200
#define MSR__POS_FAIL 0x400
#define MSR__REF_FAIL 0x800
#define MSR__AC_FAIL 0x1000
#define MSR__LIM_ERR 0x2000
#define SS__HALT 0x1
#define SS__CCW 0x2
#define SS__STP 0x4
#define SS__LS1 0x8
#define SS__LS2 0x10
#define SS__LSX 0x20
#define EL737_STATE_UNKNOWN 0xFFFFFFFE
#define EL737_STATE_OFFLINE 0xFFFFFFFF
#define EL737_STATE_MS 0x0
#define EL737_STATE_PTS 0x1
#define EL737_STATE_PCS 0x2
#define EL737_STATE_LRTS 0x5
#define EL737_STATE_LRCS 0x6
#define EL737_STATE_PTSP 0x9
#define EL737_STATE_PCSP 0xA
#define EL737_STATE_LRTSP 0xD
#define EL737_STATE_LRCSP 0xE
#define SINQHM_CNCT 0x1
#define SINQHM_CONFIG 0x2
#define SINQHM_DECONFIG 0x3
#define SINQHM_EXIT 0x4
#define SINQHM_STATUS 0x5
#define SINQHM_DBG 0x6
#define SINQHM_CLOSE 0x101
#define SINQHM_INH 0x102
#define SINQHM_IOREG 0x103
#define SINQHM_READ 0x104
#define SINQHM_SET_TDC 0x105
#define SINQHM_SHOW 0x106
#define SINQHM_WRITE 0x107
#define SINQHM_ZERO 0x108
#define INH_SET 0x1
#define INH_CLR 0x2
#define INH_TST 0x3
#define IO_SET 0x1
#define IO_CLR 0x2
#define IO_PULSE 0x3
#define TT_PORT__NO_RETRY 0x1
#define TT_PORT__NO_SIG 0x2

674
hardsup/sinq_prototypes.h Normal file
View File

@ -0,0 +1,674 @@
#ifndef _sinq_prototypes_loaded_
#define _sinq_prototypes_loaded_
/*---------------------------------------------- SINQ_PROTOTYPES.H Ident V02T
**
** Prototype header file for entry points in SINQ.OLB
**
** Updates:
** V01A 21-Mar-1996 DM Initial version.
*/
#ifdef VAXC
#include asynsrv_def
#include rs232c_def
#include el734_def
#include el737_def
#else
#include <asynsrv_def.h>
#include <rs232c_def.h>
#include <el734_def.h>
#include <el737_def.h>
#endif
/* ---------------------------------------------------------------------*/
int AsynSrv_ChanClose (
struct AsynSrv__info *asyn_info);
int AsynSrv_Close (
struct AsynSrv__info *asyn_info,
int force_flag);
int AsynSrv_Config (
struct AsynSrv__info *asyn_info,
...);
int AsynSrv_ConfigDflt (
char *par_id,
...);
void AsynSrv_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int AsynSrv_Flush (
struct AsynSrv__info *asyn_info);
int AsynSrv_GetLenTerm (
struct AsynSrv__info *asyn_info,
struct RS__RespStruct *rcve_buff,
char *rply,
int *len,
char *term);
char *AsynSrv_GetReply (
struct AsynSrv__info *asyn_info,
struct RS__RespStruct *rcve_buff,
char *last_rply);
int AsynSrv_Open (
struct AsynSrv__info *asyn_info);
int AsynSrv_OpenNew (
struct AsynSrv__info *asyn_info);
int AsynSrv_SendCmnds (
struct AsynSrv__info *asyn_info,
struct RS__MsgStruct *send_buff,
struct RS__RespStruct *rcve_buff,
...);
int AsynSrv_SendCmndsBig (
struct AsynSrv__info *asyn_info,
struct RS__MsgStruct *send_buff,
int send_buff_size,
struct RS__RespStruct *rcve_buff,
int rcve_buff_size,
...);
int AsynSrv_Trace (
struct AsynSrv__info *asyn_info,
int state);
int AsynSrv_Trace_Write (
struct AsynSrv__info *asyn_info);
/* ---------------------------------------------------------------------*/
int C_log_arr_get (
char *name,
int arr_size,
int *value,
int indx);
int C_log_flt_get (
char *name,
float *value,
int indx);
int C_log_int_get (
char *name,
long int *value,
int indx);
int C_log_str_get (
char *name,
char *value,
int val_size,
int indx);
/* ---------------------------------------------------------------------*/
int C_str_edit (
char *out,
char *in,
char *ctrl,
int *length);
/* ---------------------------------------------------------------------*/
int C_tt_port_config (
int *hndl,
int mask);
int C_tt_port_connect (
int *hndl,
int *chan,
char *lognam,
char *pwd);
int C_tt_port_disconnect (
int *hndl);
int C_tt_port_io (
int *hndl,
char *rqst,
char *term,
char *answ,
int *answ_len,
int flush,
int tmo);
/* ---------------------------------------------------------------------*/
int EL734_Close (
void **handle,
int force_flag);
int EL734_Config (
void **handle,
...);
char *EL734_EncodeMSR (
char *text,
int text_len,
int msr,
int ored_msr,
int fp_cntr,
int fr_cntr);
char *EL734_EncodeSS (
char *text,
int text_len,
int ss);
void EL734_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int EL734_GetAirCush (
void **handle,
int *present,
int *state);
int EL734_GetEncGearing (
void **handle,
int *nominator,
int *denominator);
int EL734_GetId (
void **handle,
char *id_txt,
int id_len);
int EL734_GetLimits (
void **handle,
float *lo,
float *hi);
int EL734_GetMotorGearing (
void **handle,
int *nominator,
int *denominator);
int EL734_GetNullPoint (
void **handle,
int *null_pt);
int EL734_GetPosition (
void **handle,
float *ist_posit);
int EL734_GetPrecision (
void **handle,
int *n_dec);
int EL734_GetRefMode (
void **handle,
int *mode);
int EL734_GetRefParam (
void **handle,
float *param);
int EL734_GetSpeeds (
void **handle,
int *lo,
int *hi,
int *ramp);
int EL734_GetStatus (
void **handle,
int *msr,
int *ored_msr,
int *fp_cntr,
int *fr_cntr,
int *ss,
float *ist_posit);
int EL734_GetZeroPoint (
void **handle,
float *zero_pt);
int EL734_MoveNoWait (
void **handle,
float soll_posit);
int EL734_MoveWait (
void **handle,
float soll_posit,
int *ored_msr,
int *fp_cntr,
int *fr_cntr,
float *ist_posit);
int EL734_Open (
void **handle,
char *host,
int port,
int chan,
int motor,
char *id);
int EL734_PutOffline (
void **handle);
int EL734_PutOnline (
void **handle,
int echo);
int EL734_SendCmnd (
void **handle,
char *cmnd,
char *rply,
int rply_size);
int EL734_SetAirCush (
void **handle,
int state);
int EL734_SetErrcode (
struct EL734info *info_ptr,
char *response,
char *cmnd);
int EL734_SetHighSpeed (
void **handle,
int hi);
int EL734_SetLowSpeed (
void **handle,
int lo);
int EL734_SetRamp (
void **handle,
int ramp);
int EL734_Stop (
void **handle);
int EL734_WaitIdle (
void **handle,
int *ored_msr,
int *fp_cntr,
int *fr_cntr,
float *ist_posit);
void EL734_ZeroStatus (
void **handle);
/* ---------------------------------------------------------------------*/
int EL737_Close (
void **handle,
int force_flag);
int EL737_Config (
void **handle,
...);
int EL737_Continue (
void **handle,
int *status);
int EL737_EnableThresh (
void **handle,
int indx);
void EL737_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int EL737_GetMonIntegTime (
void **handle,
int indx,
float *mon_integ_time);
int EL737_GetRateIntegTime (
void **handle,
float *rate_integ_time);
void *EL737_GetReply (
void **handle,
void *last_rply);
int EL737_GetStatus (
void **handle,
int *c1,
int *c2,
int *c3,
int *c4,
float *timer,
int *rs);
int EL737_GetStatusExtra (
void **handle,
int *c5,
int *c6,
int *c7,
int *c8);
int EL737_GetThresh (
void **handle,
int *indx,
float *val);
int EL737_Open (
void **handle,
char *host,
int port,
int chan);
int EL737_Pause (
void **handle,
int *status);
int EL737_SendCmnd (
void **handle,
char *cmnd,
char *rply,
int rply_size);
int EL737_SetErrcode (
struct EL737info *info_ptr,
char *response,
char *cmnd);
int EL737_SetThresh (
void **handle,
int indx,
float val);
int EL737_StartCnt (
void **handle,
int preset_count,
int *status);
int EL737_StartTime (
void **handle,
float preset_time,
int *status);
int EL737_Stop (
void **handle,
int *c1,
int *c2,
int *c3,
int *c4,
float *timer,
int *status);
int EL737_StopFast (
void **handle);
int EL737_WaitIdle (
void **handle,
int *c1,
int *c2,
int *c3,
int *c4,
float *timer);
/* ---------------------------------------------------------------------*/
int EL755_Close (
void **handle,
int force_flag);
int EL755_Config (
void **handle,
...);
void EL755_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int EL755_ErrorLog (
char *routine_name,
char *text);
int EL755_GetConstant (
void **handle,
float *value);
int EL755_GetCurrents (
void **handle,
float *soll,
float *ist);
int EL755_GetId (
void **handle,
char *id_txt,
int id_len);
int EL755_GetLimit (
void **handle,
float *value);
int EL755_GetRamp (
void **handle,
float *value);
int EL755_GetTimeConstant (
void **handle,
float *value);
int EL755_GetVoltageRange (
void **handle,
float *value);
int EL755_Open (
void **handle,
char *host,
int port,
int chan,
int indx);
int EL755_PutOffline (
void **handle);
int EL755_PutOnline (
void **handle,
int echo);
int EL755_SendTillSameStr (
void **handle,
char *cmnd,
char *rply,
int rply_len);
int EL755_SendTillSameVal (
void **handle,
char *cmnd,
float *val);
int EL755_SendTillTwoVals (
void **handle,
char *cmnd,
float *val0,
float *val1);
int EL755_SetConstant (
void **handle,
float value);
int EL755_SetCurrent (
void **handle,
float soll);
int EL755_SetLimit (
void **handle,
float value);
int EL755_SetRamp (
void **handle,
float value);
int EL755_SetTimeConstant (
void **handle,
float value);
int EL755_SetVoltageRange (
void **handle,
float value);
/* ---------------------------------------------------------------------*/
int Fluke_Close (
void **handle,
int force_flag);
int Fluke_Config (
void **handle,
...);
void Fluke_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int Fluke_ErrorLog (
char *routine_name,
char *text);
int Fluke_Open (
void **handle,
char *host,
int port,
int chan);
int Fluke_Read (
void **handle,
float *ist);
int Fluke_SendTillSame (
void **handle,
char *cmnd,
char *rply,
int rply_len);
int Fluke_SendTillSameVal (
void **handle,
char *cmnd,
float *val);
/* ---------------------------------------------------------------------*/
int ITC_Close (
void **handle,
int force_flag);
int ITC_Config (
void **handle,
...);
int ITC_Dump_RAM (
void **handle,
int buff_size,
char *buff,
int *dump_len,
int *n_diffs);
void ITC_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int ITC_GetConfig (
void **handle,
...);
int ITC_Load_RAM (
void **handle,
int load_len,
char *buff);
int ITC_Load_Table (
void **handle,
char *buff);
int ITC_Open (
void **handle,
char *host,
int port,
int chan);
int ITC_Read_ITC_Sensor (
void **handle,
int sensor,
float factor,
float *value);
int ITC_Read_LTC11_Sensor (
void **handle,
int sensor,
float *value);
int ITC_Read_LTC11_SetPt (
void **handle,
float *value);
int ITC_ReadAuxTemp (
void **handle,
float *value);
int ITC_ReadControlTemp (
void **handle,
float *value);
int ITC_ReadHeaterOp (
void **handle,
float *op_level,
float *op_percent);
int ITC_ReadId (
void **handle,
char *id_txt,
int id_txt_len,
int *id_len);
int ITC_ReadPID (
void **handle,
float *p,
float *i,
float *d);
int ITC_ReadSampleTemp (
void **handle,
float *s_temp);
int ITC_ReadSetPoint (
void **handle,
float *sp_temp);
int ITC_ReadStatus (
void **handle,
char *status_txt,
int status_txt_len,
int *status_len,
int *auto_state,
int *remote_state);
int ITC_SendTillAckOk (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd);
int ITC_SendTillSame (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd,
char *rply,
int rply_len);
int ITC_SendTillSameLen (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd,
char *rply,
int rply_len);
int ITC_SendTillSameLenAckOK (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd,
char *rply,
int rply_len);
int ITC_SetControlTemp (
void **handle,
float s_temp);
int ITC_SetHeatLevel (
void **handle,
float heat_percent);
int ITC_ErrorLog (
char *routine_name,
char *text);
/* ---------------------------------------------------------------------*/
int SPS_Close (
void **handle,
int force_flag);
int SPS_Config (
void **handle,
...);
void SPS_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
int SPS_ErrorLog (
char *routine_name,
char *text);
int SPS_GetStatus (
void **handle,
unsigned char *status_vals,
int n_status_vals,
int *adc_vals,
int n_adc_vals);
int SPS_Open (
void **handle,
char *host,
int port,
int chan);
int SPS_SendTillSame (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd,
char *rply,
int rply_len);
int SPS_SendTillSameLen (
void **handle,
struct RS__MsgStruct *to_host,
struct RS__RespStruct *from_host,
char *cmnd,
char *rply,
int rply_len);
/* ---------------------------------------------------------------------*/
int VelSel_Close (
void **handle,
int force_flag);
void VelSel_Config (
void **handle,
int msec_tmo,
char *eot_str);
void VelSel_ErrInfo (
char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno);
void *VelSel_GetReply (
void **handle,
void *last_rply);
int VelSel_GetStatus (
void **handle,
char *status_str,
int status_str_len);
int VelSel_Open (
void **handle,
char *host,
int port,
int chan);
int VelSel_SendCmnd (
void **handle,
char *cmnd,
char *rply,
int rply_size);
/* ---------------------------------------------------------------------*/
void FailInet (
char *text);
void GetErrno (
int *his_errno,
int *his_vaxc_errno);
int MakeCharPrintable (
char *out,
int out_size,
char in);
char *MakePrint (
char *text);
char *MakePrintable (
char *out,
int out_size,
char *in);
void *Map_to_ACS ();
char *StrEdit (
char *out,
char *in,
char *ctrl,
int *ln);
char *StrJoin (
char *result,
int result_size,
char *str_a,
char *str_b);
int StrMatch (
char *str_a,
char *str_b,
int min_len);
int Get_TASMAD_Info (
char *file_name,
int *nItems,
...);
int Get_TASMAD_Info_Filename (
char *file_name,
char *buf,
int *bufSize);
int Update_TASMAD_Info (
char *file_name,
int *nItems,
...);
/*--------------------------------------------- End of SINQ_PROTOTYPES.H --*/
#endif /* _sinq_prototypes_loaded_ */

1770
hardsup/sinqhm.c Normal file

File diff suppressed because it is too large Load Diff

107
hardsup/sinqhm.h Normal file
View File

@ -0,0 +1,107 @@
#line 363 "sinqhm.w"
/*---------------------------------------------------------------------------
S I N Q H M
Some utility functions for interfacing to the SINQ histogram memory
server.
David Maden, Mark Koennecke, April 1997
copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SINQHMUTILITY
#define SINQHMUTILITY
#include "sinqhm_def.h"
typedef struct __SINQHM *pSINQHM;
/*------------------------------ Error codes -----------------------------*/
#line 341 "sinqhm.w"
#define HMCOMPUTER_NOT_FOUND -2
#define SOCKET_ERROR -3
#define BIND_ERROR -4
#define CONNECT_ERROR -5
#define RECEIVE_ERROR -6
#define INSUFFICIENT_DATA -7
#define BYTE_ORDER_CHAOS -8
#define HIST_BAD_CREATE -9
#define HIST_BAD_STATE -10
#define HIST_BAD_VALUE -11
#define HIST_BAD_RECV -12
#define HIST_BAD_ALLOC -13
#define HIST_BAD_CODE -14
#define SEND_ERROR -15
#define CLOSE_ERROR -16
#define INVALID_HARSH -17
#define SOFTWARE_ERROR -18
#define DAQ_INHIBIT -19
#define DAQ_NOTSTOPPED -20
#line 379 "sinqhm.w"
/*------------------------------ Prototypes ------------------------------*/
#line 118 "sinqhm.w"
pSINQHM CreateSINQHM(char *pHMComputer, int iMasterPort);
pSINQHM CopySINQHM(pSINQHM self);
void DeleteSINQHM(pSINQHM self);
void SINQHMSetPar(pSINQHM self, int iRank, int iLength, int iBinWidth);
void SINQHMSetPSD(pSINQHM self, int xSize, int xOff, int xFac,
int ySize, int yOff, int yFac);
#line 142 "sinqhm.w"
int SINQHMError2Text(int iErr, char *pBuffer, int iBufLen);
#line 155 "sinqhm.w"
int SINQHMConfigure(pSINQHM self, int iMode, int iRank, int iLength,
int iBinWidth, int iLowBin, int iCompress);
int SINQHMConfigurePSD(pSINQHM self, int iMode,
int xSize, int xOff, int xFac,
int ySize, int yOff, int yFac,
int iBinWidth,
float *iEdges, int iEdgeLength);
int SINQHMDeconfigure(pSINQHM self, int iHarsh);
int SINQHMGetStatus(pSINQHM self,int *iMode, int *iDaq,
int *iRank, int *iBinWidth,
int *iLength, int *iClients);
int SINQHMDebug(pSINQHM self, int iLevel);
int SINQHMKill(pSINQHM self);
#line 261 "sinqhm.w"
int SINQHMOpenDAQ(pSINQHM self);
int SINQHMCloseDAQ(pSINQHM self);
int SINQHMStartDAQ(pSINQHM self);
int SINQHMStopDAQ(pSINQHM self);
int SINQHMInhibitDAQ(pSINQHM self);
int SINQHMContinueDAQ(pSINQHM self);
int SINQHMWrite(pSINQHM self, int iNum, int iStart, int iEnd,
void *pData);
long SINQHMSize(pSINQHM self, int iNum, int iStart, int iEnd);
int SINQHMRead(pSINQHM self, int iNum, int iStart, int iEnd,
void *pData, int iDataLen);
int SINQHMProject(pSINQHM self, int code, int xStart, int nx,
int yStart, int ny, void *pData, int iDataLen);
int SINQHMZero(pSINQHM self, int iNum, int iStart, int iEnd);
#line 382 "sinqhm.w"
#line 232 "sinqhm.w"
int SINQHMDefineBank(pSINQHM self, int iBankNumber, int iStart, int iEnd,
float *iEdges, int iEdgeLength);
#line 383 "sinqhm.w"
#endif

483
hardsup/sinqhm_def.h Normal file
View File

@ -0,0 +1,483 @@
/*=================================================== [...SinqHM]SinqHM_def.h
**
** Definition Include file for SinqHM_SRV and its clients.
**
**------------------------------------------------------------------------------
*/
#define SINQHM_DEF_ID "V03C"
#ifdef __alpha
#ifndef __vms
#pragma pack 1
#endif
#endif
/*------------------------------------------------------------------------------
*/
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
/*------------------------------------------------------------------------------
** Define some defaults.
*/
#define PORT_BASE 2400 /* The Internet Port for Server Requests */
#define MAX_CLIENTS 8 /* The maximum number of active clients */
#define MAX_TOF_CNTR 1024 /* The maximum number of individual counters ..
** which can be handled in TOF mode */
#define MAX_PSD_CNTR 1048576 /* maximum number of PSD elements */
#define MAX_TOF_NBINS 32768 /* The maximum number of bins in a TOF histog */
#define MAX_TOF_EDGE 16 /* The maximum number of TOF edge arrays */
#define VMIO_BASE_ADDR 0x1900 /* VME address of a (possible) VMIO10 module */
#define IDENT_MSGE_LEN 256 /* Length of Ident info for SQHM_IDENT */
#define uchar unsigned char
#define usint unsigned short int
#define uint unsigned int
/*------------------------------------------------------------------------------
** Define some status values (similar to VAXeln).
*/
#define KER__SUCCESS 1
#define KER__BAD_CREATE -2
#define KER__BAD_STATE -4
#define KER__BAD_VALUE -6
#define KER__EXIT_SIGNAL -10
#define KER__BAD_RECV -14
#define KER__BAD_ALLOC -16
#ifndef True
#define True 1
#endif
#ifndef False
#define False 0
#endif
#ifndef NIL
#define NIL '\0'
#endif
/*------------------------------------------------------------------------------
** Define command verbs to SinqHM.
*/
#define SQHM_CNCT 0x01
#define SQHM_CLOSE 0x02
#define SQHM_CONFIG 0x03
#define SQHM_DAQ 0x04
#define SQHM_DBG 0x05
#define SQHM_DECONFIG 0x06
#define SQHM_EXIT 0x07
#define SQHM_IDENT 0x0e
#define SQHM_PROJECT 0x0d
#define SQHM_READ 0x08
#define SQHM_SELECT 0x09
#define SQHM_STATUS 0x0a
#define SQHM_WRITE 0x0b
#define SQHM_ZERO 0x0c
/*
** Define the various operation modes
*/
#define SQHM__TRANS 0x1000 /* Transparent mode */
#define SQHM__HM_DIG 0x2000 /* Hist mode (with digitised read-out) */
#define SQHM__TOF 0x3000 /* Time-of-Flight mode */
#define SQHM__HM_PSD 0x4000 /* Hist mode (with Pos-sens-detect read-out) */
#define SQHM__HRPT 0x5000 /* Hist mode for HRPT */
/*
** Define the various sub-mode bits of the operation modes
*/
#define SQHM__SUB_MODE_MSK 0xff /* Mask for extracting "sub-mode" bits */
#define SQHM__DEBUG 0x01 /* Debug flag - FILLER will suspend itself ..
** .. after starting to allow debugging */
#define SQHM__UD 0x02 /* Use Up/Down bit information */
#define SQHM__BO_MSK 0x18 /* Mask for extracting "bin-overflow" bits */
#define SQHM__BO_IGN 0x00 /* Ignore bin-overflows (bin-contents wrap) */
#define SQHM__BO_SMAX 0x08 /* On bin-overflow, stop at maximum */
#define SQHM__BO_CNT 0x10 /* Keep counts of overflow bins */
#define SQHM__STROBO 0x20 /* Use strobo-bit information */
#define SQHM__REFLECT 0x40 /* Reflect histograms */
#define SQHM__NO_STAT 0x80 /* Suppress status info from "Filler" */
/*
** ----------------------------------------------------------
** SQHM_DAQ sub-function codes
*/
#define DAQ__EXIT 0xffffffff
#define DAQ__CLR 0x01
#define DAQ__GO 0x02
#define DAQ__INH 0x03
#define DAQ__STOP 0x04
#define DAQ__TST 0x05
/*
** ----------------------------------------------------------
** SQHM_PROJECT sub-codes
*/
#define PROJECT__ON_Y 0x0001 /* Project onto y-axis */
#define PROJECT__1_DIM 0x0002 /* Make projection of a 1-dim histogram */
#define PROJECT__COLL 0x0003 /* collapse PSD on one time channel */
#define PROJECT__SAMPLE 0x0004 /* sum a rectangular part of the PSD
detector in time
*/
/*
** ----------------------------------------------------------
** Definition of bits in <flag> of TOF edge-array
*/
#define FLAG__VAR_BIN 0x01 /* Bin span of histogram is variable */
/*
** ----------------------------------------------------------
** Definition of bits in <flags> of SQHM_STATUS response
*/
#define STATUS_FLAGS__PF 0x8000 /* PF - Power Fail */
#define STATUS_FLAGS__SWC 0x4000 /* SWC - Status Word Changed */
#define STATUS_FLAGS__NRL 0x2000 /* NRL - Neutron Rate Low */
#define STATUS_FLAGS__DAQ 0x1000 /* DAQ on -- set if Hdr Mask Bits are
** correct so that data acq is active */
#define STATUS_FLAGS__SYNC3 0x0800 /* Ext Synch Bit #3 */
#define STATUS_FLAGS__SYNC2 0x0400 /* Ext Synch Bit #2 */
#define STATUS_FLAGS__SYNC1 0x0200 /* Ext Synch Bit #1 */
#define STATUS_FLAGS__SYNC0 0x0100 /* Ext Synch Bit #0 */
#define STATUS_FLAGS__UD 0x0080 /* UD - Up/Down */
#define STATUS_FLAGS__GU 0x0040 /* GU - Gummi (i.e. Strobo) */
/*
** ----------------------------------------------------------
*/
#define N_HISTS_MAX 64 /* Maximum number of histograms supported */
#define N_BINS_MAX 0x00ffff /* Maximum histogram bin number permitted */
#define N_TOTAL_BYTES 0x400000 /* Maximum total bytes of histogram */
/*
**------------------------------------------------------------------------------
** Definitions of Filler states in HRPT mode
*/
#define HRPT__SRCH_FRAME 1
#define HRPT__READ_FRAME 2
/*
**------------------------------------------------------------------------------
** Definitions for the LWL Datagrams
*/
#define LWL_HDR_TYPE_MASK (0x1f000000) /* Mask for extracting main dgrm ..
** .. hdr command-type bits */
#define LWL_HDR_PF_MASK (0x80000000) /* Mask for extr Power Fail bit */
#define LWL_HDR_SWC_MASK (0x40000000) /* Mask for extr Status Word Chng bit */
#define LWL_HDR_NRL_MASK (0x20000000) /* Mask for extr Neutron Rate Low bit */
#define LWL_HDR_SYNC3_MASK (0x00800000) /* Mask for one of ext synch bits */
#define LWL_HDR_SYNC2_MASK (0x00400000) /* Mask for one of ext synch bits */
#define LWL_HDR_SYNC1_MASK (0x00200000) /* Mask for one of ext synch bits */
#define LWL_HDR_SYNC0_MASK (0x00100000) /* Mask for one of ext synch bits */
#define LWL_HDR_UD_MASK LWL_HDR_SYNC1_MASK /* Mask for Up/Down bit */
#define LWL_HDR_GU_MASK LWL_HDR_SYNC0_MASK /* Mask for GU bit */
#define LWL_HDR_BA_MASK (0x00f00000) /* Mask for TSI Binning Addr */
#define LWL_HDR_TS_MASK (0x000fffff) /* Mask for TSI Time Stamp */
#define LWL_FIFO_EMPTY (0x1e000000) /* FIFO Empty */
#define LWL_TSI_TR (0x1f000000) /* Time-Status-Info Transp-Mode */
#define LWL_TSI_HM_NC (0x1f000000) /* Time-Status-Info Hist-Mode+No-Coinc */
#define LWL_TSI_HM_C (0x0e000000) /* Time-Status-Info Hist-Mode+Coinc */
#define LWL_TSI_TOF (0x1f000000) /* Time-Status-Info TOF-Mode */
#define LWL_TSI_SM_NC (0x1f000000) /* Time-Status-Info Strobo-Mode+No-Coin */
#define LWL_TSI_SM_C (0x0e000000) /* Time-Status-Info Strobo-Mode+Coinc */
#define LWL_TSI_DT_MSK (0x000fffff) /* Mask for Dead-Time in TSI */
#define LWL_TSI_DTS_MSK (0x000fffff) /* Mask for Delay-Time-to-Start in TSI */
#define LWL_TR_C1 (0x00000001) /* Transp. Mode Chan 1 */
#define LWL_TR_C2 (0x00000002) /* Transp. Mode Chan 2 */
#define LWL_TR_C3 (0x00000003) /* Transp. Mode Chan 3 */
#define LWL_TR_C4 (0x00000004) /* Transp. Mode Chan 4 */
#define LWL_TR_C5 (0x00000005) /* Transp. Mode Chan 5 */
#define LWL_TR_C6 (0x00000006) /* Transp. Mode Chan 6 */
#define LWL_TR_C7 (0x00000007) /* Transp. Mode Chan 7 */
#define LWL_TR_C8 (0x00000008) /* Transp. Mode Chan 8 */
#define LWL_TR_C9 (0x00000009) /* Transp. Mode Chan 9 */
#define LWL_HM_NC (0x10000000) /* Hist-Mode/No-Coinc 0 chan dgrm hdr */
#define LWL_HM_NC_C1 (0x11000000) /* Hist-Mode/No-Coinc 1 chan dgrm hdr */
#define LWL_HM_NC_C2 (0x12000000) /* Hist-Mode/No-Coinc 2 chan dgrm hdr */
#define LWL_HM_NC_C3 (0x13000000) /* Hist-Mode/No-Coinc 3 chan dgrm hdr */
#define LWL_HM_NC_C4 (0x14000000) /* Hist-Mode/No-Coinc 4 chan dgrm hdr */
#define LWL_HM_NC_C5 (0x15000000) /* Hist-Mode/No-Coinc 5 chan dgrm hdr */
#define LWL_HM_NC_C6 (0x16000000) /* Hist-Mode/No-Coinc 6 chan dgrm hdr */
#define LWL_HM_NC_C7 (0x17000000) /* Hist-Mode/No-Coinc 7 chan dgrm hdr */
#define LWL_HM_NC_C8 (0x18000000) /* Hist-Mode/No-Coinc 8 chan dgrm hdr */
#define LWL_HM_NC_C9 (0x19000000) /* Hist-Mode/No-Coinc 9 chan dgrm hdr */
#define LWL_HM_CO (0x10000000) /* Hist-Mode+Coinc 0 chan dgrm hdr */
#define LWL_HM_CO_C2 (0x12000000) /* Hist-Mode+Coinc 2 chan dgrm hdr */
#define LWL_HM_CO_C3 (0x13000000) /* Hist-Mode+Coinc 3 chan dgrm hdr */
#define LWL_HM_CO_C4 (0x14000000) /* Hist-Mode+Coinc 4 chan dgrm hdr */
#define LWL_HM_CO_C5 (0x15000000) /* Hist-Mode+Coinc 5 chan dgrm hdr */
#define LWL_HM_CO_C6 (0x16000000) /* Hist-Mode+Coinc 6 chan dgrm hdr */
#define LWL_HM_CO_C7 (0x17000000) /* Hist-Mode+Coinc 7 chan dgrm hdr */
#define LWL_HM_CO_C8 (0x18000000) /* Hist-Mode+Coinc 8 chan dgrm hdr */
#define LWL_HM_CO_C9 (0x19000000) /* Hist-Mode+Coinc 9 chan dgrm hdr */
#define LWL_TOF_C1 (0x01000000) /* TOF-Mode 1 chan dgrm hdr */
#define LWL_TOF_C2 (0x02000000) /* TOF-Mode 2 chan dgrm hdr */
#define LWL_TOF_C3 (0x03000000) /* TOF-Mode 3 chan dgrm hdr */
#define LWL_TOF_C4 (0x04000000) /* TOF-Mode 4 chan dgrm hdr */
#define LWL_TOF_C5 (0x05000000) /* TOF-Mode 5 chan dgrm hdr */
#define LWL_TOF_C6 (0x06000000) /* TOF-Mode 6 chan dgrm hdr */
#define LWL_TOF_C7 (0x07000000) /* TOF-Mode 7 chan dgrm hdr */
#define LWL_TOF_C8 (0x08000000) /* TOF-Mode 8 chan dgrm hdr */
#define LWL_TOF_C9 (0x09000000) /* TOF-Mode 9 chan dgrm hdr */
#define LWL_PSD_TSI 0x0E000000 /* PSD-Mode TSI datagram */
#define LWL_PSD_DATA 0x12000000 /* PSD-mode data datagram */
#define LWL_PSD_PWF 0x20000000 /* PSD-mode Power Fail bit */
#define LWL_PSD_TIME 0x000fffff /* PSD-mode time stamp extraction
mask */
#define LWL_PSD_FLASH_MASK 0x00ff /* mask for flash count */
#define LWL_PSD_XORF 0x2000 /* mask for TDC-XORF bit */
#define LWL_PSD_CONF 0x0100 /* mask for TDC-CONF flag */
#define LWL_SM_NC (0x10000000) /* Strobo-Mode/No-Coinc 0 chan dgrm hdr */
#define LWL_SM_NC_C1 (0x11000000) /* Strobo-Mode/No-Coinc 1 chan dgrm hdr */
#define LWL_SM_NC_C2 (0x12000000) /* Strobo-Mode/No-Coinc 2 chan dgrm hdr */
#define LWL_SM_NC_C3 (0x13000000) /* Strobo-Mode/No-Coinc 3 chan dgrm hdr */
#define LWL_SM_NC_C4 (0x14000000) /* Strobo-Mode/No-Coinc 4 chan dgrm hdr */
#define LWL_SM_NC_C5 (0x15000000) /* Strobo-Mode/No-Coinc 5 chan dgrm hdr */
#define LWL_SM_NC_C6 (0x16000000) /* Strobo-Mode/No-Coinc 6 chan dgrm hdr */
#define LWL_SM_NC_C7 (0x17000000) /* Strobo-Mode/No-Coinc 7 chan dgrm hdr */
#define LWL_SM_NC_C8 (0x18000000) /* Strobo-Mode/No-Coinc 8 chan dgrm hdr */
#define LWL_SM_NC_C9 (0x19000000) /* Strobo-Mode/No-Coinc 9 chan dgrm hdr */
#define LWL_SM_CO (0x10000000) /* Strobo-Mode + Coinc 0 chan dgrm hdr */
#define LWL_SM_CO_C1 (0x11000000) /* Strobo-Mode + Coinc 1 chan dgrm hdr */
#define LWL_SM_CO_C2 (0x12000000) /* Strobo-Mode + Coinc 2 chan dgrm hdr */
#define LWL_SM_CO_C3 (0x13000000) /* Strobo-Mode + Coinc 3 chan dgrm hdr */
#define LWL_SM_CO_C4 (0x14000000) /* Strobo-Mode + Coinc 4 chan dgrm hdr */
#define LWL_SM_CO_C5 (0x15000000) /* Strobo-Mode + Coinc 5 chan dgrm hdr */
#define LWL_SM_CO_C6 (0x16000000) /* Strobo-Mode + Coinc 6 chan dgrm hdr */
#define LWL_SM_CO_C7 (0x17000000) /* Strobo-Mode + Coinc 7 chan dgrm hdr */
#define LWL_SM_CO_C8 (0x18000000) /* Strobo-Mode + Coinc 8 chan dgrm hdr */
#define LWL_SM_CO_C9 (0x19000000) /* Strobo-Mode + Coinc 9 chan dgrm hdr */
#define LWL_TSI_MODE_MASK (0x000e) /* Mask for mode in Time Status Info */
#define LWL_TSI_MODE_TR (0x0000) /* TSI Transparent-Mode */
#define LWL_TSI_MODE_HM (0x0002) /* TSI Hist-Mode */
#define LWL_TSI_MODE_TOF (0x0004) /* TSI TOF-Mode */
#define LWL_TSI_MODE_SM1 (0x0006) /* TSI Strobo-Mode 1 - time-stamp coded */
#define LWL_TSI_MODE_TR_UD (0x0008) /* TSI Transparent-Mode Up-Down */
#define LWL_TSI_MODE_HM_UD (0x000a) /* TSI Hist-Mode Up-Down */
#define LWL_TSI_MODE_TOF_UD (0x000c) /* TSI TOF-Mode Up-Down */
#define LWL_TSI_MODE_SM2 (0x000e) /* TSI Strobo-Mode 2 - h/w coded */
/*
**------------------------------------------------------------------------------
** Define structure of a TOF histogram data item.
*/
struct tof_histog {
int cntr_nmbr; /* Counter number */
uint lo_edge; /* Low edge of first bin (20-bit value) */
uint hi_edge; /* Top edge of last bin (20-bit value) */
usint flag; /* Bit mask giving info on histog -- may be
** used to help optimise the code */
usint bytes_per_bin; /* Number of bytes in each histogram bin */
uint n_bins; /* Number of bins in histogram */
uint cnt_early_up; /* Count of early events (pol'n up) */
uint cnt_late_up; /* Count of late events (pol'n up) */
uint cnt_early_down; /* Count of early events (pol'n down) */
uint cnt_late_down; /* Count of late events (pol'n down) */
uint *bin_edge; /* Pointer to array of bin edges */
union { /* Pointer to histogram array */
uchar *b_bin_data; /* .. pointer if it's 8-bit bins */
usint *w_bin_data; /* .. pointer if it's 16-bit bins */
uint *l_bin_data; /* .. pointer if it's 32-bit bins */
} u;
};
/* Define a TOF 'edge-info' structure. This structure is created
** as a result of a TOF 'edge-array' in a SQHM__TOF config cmnd.
*/
struct tof_edge_info {
uint n_bins; /* Number of bins in histogram */
uint flag; /* Flag bits defining type of histo */
uint bin_span; /* Time spanned by a histogram bin (20-bit
** value) if bin width is constant. Otherwise
** it is zero. */
uint hi_edge; /* Top edge of last bin (20-bit value) */
uint edges[2]; /* Array of edge data (20-bit values). There
** are actually (n_bins+1) items in the array
** and give the bottom edges of the bin */
};
/* Define structure of a TOF 'edge-array' in SQHM__TOF config cmnd
*/
struct tof_edge_arr {
uint n_bins; /* Number of bins in histogram */
uint flag; /* Flag (0/1) for fixed/variable bin size */
uint *edges; /* Array of bottom edges (20-bit values) */
};
/* Define structure of a TOF 'bank' in SQHM__TOF config command
*/
struct tof_bank {
usint first; /* Number of first counter in bank */
usint n_cntrs; /* Number of counters in bank */
usint edge_indx; /* Index of edge array */
usint bytes_per_bin; /* Number of bytes per bin */
};
/*
**------------------------------------------------------------------------------
** Define command structure.
*/
struct req_buff_struct { /* For messages to SinqHM */
uint bigend;
uint cmnd;
union {
char filler[56];
struct {uint max_pkt,
strt_mode;} cnct;
struct {uint mode;
union {
struct {
uint n_buffs;
uint n_bytes;
} trans;
struct {
uint n_hists;
uint lo_bin;
uint num_bins;
uint bytes_per_bin;
uint compress;
} hm_dig;
struct {
uint n_extra_bytes;
usint n_edges;
usint n_banks;
uint preset_delay;
struct tof_edge_arr edge_0;
struct tof_bank bank_0;
} tof;
struct {
uint n_extra_bytes;
usint n_edges;
usint n_banks;
uint preset_delay;
usint xFactor;
usint yFactor;
usint xOffset;
usint yOffset;
usint xSize;
usint ySize;
struct tof_edge_arr edge_0;
struct tof_bank bank_0;
} psd;
} u;
} cnfg;
struct {uint mask;} dbg;
struct {uint sub_code;} decnfg;
struct {uint sub_cmnd;} daq;
struct {uint sub_code,
x_lo,
nx,
y_lo,
ny,
xdim,
nhist;} project;
struct {uint hist_no,
first_bin,
n_bins;} read;
struct {uint hist_no;} select;
struct {uint hist_no,
first_bin,
n_bins,
bytes_per_bin;} write;
struct {uint hist_no,
first_bin,
n_bins;} zero;
} u;
};
/*
**------------------------------------------------------------------------------
** Define status response structure.
*/
struct rply_buff_struct { /* For messages from SinqHM */
uint bigend;
uint status;
uint sub_status;
union {
char message[52];
struct {uint port;
uint pkt_size;
uint hm_mode;
uint n_hists;
uint num_bins;
uint bytes_per_bin;
uint curr_hist;
uint max_block;
uint total_bytes;
uint lo_cntr;
uint lo_bin;
uint compress;
uint up_time;} cnct;
struct {usint daq_now;
usint daq_was;
usint filler_mask;
usint server_mask;} daq;
struct {uint n_extra_bytes;
uint up_time;
usint offset_vxWorks_ident;
usint offset_vxWorks_date;
usint offset_instr;
usint offset_def_ident;
usint offset_sinqhm_main_ident;
usint offset_sinqhm_main_date;
usint offset_sinqhm_server_ident;
usint offset_sinqhm_server_date;
usint offset_sinqhm_filler_ident;
usint offset_sinqhm_filler_date;
usint offset_sinqhm_routines_ident;
usint offset_sinqhm_routines_date;} ident;
struct {uint n_bins;
uint bytes_per_bin;
uint cnts_lo;
uint cnts_hi;} project;
struct {uint first_bin;
uint n_bins;
uint bytes_per_bin;
uint cnts_lo;
uint cnts_hi;} read;
struct {uint cfg_state;
usint n_hists, curr_hist;
uint num_bins;
uint max_n_hists;
uint max_num_bins;
uchar max_srvrs, act_srvrs, bytes_per_bin, compress;
usint daq_now, filler_mask;
uint max_block;
usint tsi_status, flags;
union {
uint dead_time;
uint dts;
uint both;
} dt_or_dts;
uint num_bad_events;
uint up_time;} status;
} u;
};
/*
**------------------------------------------------------------------------------
** Define structure of message to SinqHM-filler.
*/
struct msg_to_filler_struct { /* For messages to SinqHM-filler */
union {
char message[32]; /* Ensure buffer is 32 bytes total */
struct {
uint cmnd;
uint index;
usint new_mask;} uu;
} u;
};
/*======================================================= End of SinqHM_def.h */

415
hardsup/stredit.c Normal file
View File

@ -0,0 +1,415 @@
#define ident "1B03"
#ifdef VAXC
#module StrEdit ident
#endif
#ifdef __DECC
#pragma module StrEdit ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]StrEdit.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Jan 1996
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]StrEdit -
tasmad_disk:[mad.lib.sinq]StrEdit +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit
**
** Updates:
** 1A01 19-Jan-1996 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
**============================================================================
** The following entry points are included in this module:
**
**-------------------------------------------------------------------------
** #include <sinq_prototypes.h>
**
** char *StrEdit (char *out, char *in, char *ctrl, int *ln)
** -------
** Input Args:
** in - the string to be edited.
** ctrl - the string specifying what is to be done. See Description
** below.
** Output Args:
** out - the edited string. The maximum size of this string must
** be specified as input parameter *ln. The string
** will be zero terminated on return.
** Modified Args:
** *ln - an integer specifying, on input, the length of "out" in
** bytes. This must include room for the zero termination.
** On return, ln will be set to the number of characters
** copied to "out" (not counting the zero termination byte).
** Return value:
** If an error is detected, the return value is a NULL pointer. Otherwise
** it is a pointer to the resulting string (i.e. "out").
** Global variables:
** none
** Routines called:
** none
** Description:
** StrEdit (out, in, ctrl, ln) - This routine is intended to mimic the
** OpenVMS DCL lexical function F$EDIT.
**
** It first processes the string "in" to convert any C-style
** escape sequences introduced by a '\' character. Recognised
** escape sequences are:
** \a --> \007 BEL
** \b --> \010 BS (backspace)
** \f --> \014 FF (formfeed)
** \n --> \012 LF (linefeed)
** \r --> \015 CR (carriage return)
** \t --> \011 HT (horizontal tab)
** \v --> \013 VT (vertical tab)
** \\ --> \
** \' --> '
** \" --> "
** \? --> ?
** \xhh --> hh are an arbitrary number of hex digits.
** \nnn --> nnn are up to 3 octal digits.
** Any unrecognised escape sequence will be left unchanged.
**
** The resulting string is then edited according to the
** keywords specified in the control string "ctrl". The result
** will be written to string "out". The "out" argument may be
** the same as "in".
**
** On entry, "ln" specifies the size of "out" in bytes, including
** space for a null terminating byte. On return, it is set to the
** length of the result (not counting the zero-terminator).
**
** The following control strings are recognised:
**
** COLLAPSE - Removes all spaces and tabs from the string.
** COMPRESS - Replaces multiple spaces and tabs with a
** single space.
** LOWERCASE - Makes the string lower case.
** TRIM - Removes leading and trailing spaces and tabs
** from the string.
** UNCOMMENT - Removes comments from the string.
** UPCASE - Makes the string upper case.
**
** All keywords must be specified in full. They may be separated
** by white-space or commas and be in upper or lower case.
**
** If the input string contains non-escaped double quotes ("),
** then the editing functions are not applied to substrings within
** these quotes ("), there must be an even number of such quotes
** and the quotes are not copied to the resulting string. On the
** other hand, escaped double quotes (\") are treated as normal
** characters.
**
** Return Status:
** StrEdit returns a pointer to "out". If any errors are detected (e.g. an
** odd number of quotes), string editing is abandoned and a null pointer
** is returned.
**
** Example:
** strcpy (in, " asdfg \"hello there\" folks ");
** len = sizeof (in);
** printf ("\"%s\"\n", StrEdit (in, in, "trim upcase compress", &len));
** will generate
** "ASDFG hello there FOLKS"
**-------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sinq_prototypes.h>
#define NIL '\0'
#define True 1
#define False 0
#define QUOTE ((char) (('\"' ^ 0xff) & 0xff))
/*
**====================================================================
*/
/*
**====================================================================
*/
/*--------------------------------------------------------------------------
** Global Variables
*/
/*
**---------------------------------------------------------------------------
** StrEdit - edit a string.
** Note: strncat is used exclusively rather than
** strncpy to be sure result is always
** null terminated.
*/
char *StrEdit (
/* =======
*/ char *out,
char *in,
char *ctrl,
int *ln) {
int i, j, k, l, m, len, inxt, out_size;
char my_ctrl[80];
char *tok_nxt, *my_in, *my_out, *my_tmp, *nxt;
int do_collapse, do_compress, do_lowercase, do_trim;
int do_uncomment, do_upcase;
out_size = *ln;
if (out_size < 1) {*ln = 0; return NULL;} /* Can't do anything!! */
if (strlen (in) <= 0) {
*out = NIL; *ln = 0; return out; /* Nothing to do!! */
}
/*
** Scan ctrl looking to see what has to be done. Do this by first
** taking a copy of it (in case it is declared "const" in the calling
** routine, convert to lowercase and split into tokens at any space,
** tab or comma.
*/
len = strlen (ctrl);
if (len >= sizeof (my_ctrl)) {
*out = NIL; *ln = 0; return NULL;
}
for (i = 0; i <= len; i++) my_ctrl[i] = tolower (ctrl[i]);
do_collapse = do_compress = do_lowercase = do_trim = do_uncomment =
do_upcase = False;
tok_nxt = strtok (my_ctrl, ", \t\f\v\n");
while (tok_nxt != NULL) {
if (strcmp (tok_nxt, "collapse") == 0) {
do_collapse = True;
}else if (strcmp (tok_nxt, "compress") == 0) {
do_compress = True;
}else if (strcmp (tok_nxt, "lowercase") == 0) {
do_lowercase = True;
}else if (strcmp (tok_nxt, "trim") == 0) {
do_trim = True;
}else if (strcmp (tok_nxt, "uncomment") == 0) {
do_uncomment = True;
}else if (strcmp (tok_nxt, "upcase") == 0) {
do_upcase = True;
}else {
*out = NIL; *ln = 0; return NULL; /* Illegal ctrl verb */
}
tok_nxt = strtok (NULL, ", \t\f\v\n");
}
len = strlen (in) + 1;
my_in = malloc (len); /* Get some working space */
if (my_in == NULL) {
*out = NIL; *ln = 0; return NULL;
}
/*
** Copy "in" to the "my_in" working space, processing any '\' escape
** sequences as we go. Note that, since "my_in" is big enough to hold
** "in" and the escape sequence processing can only shorten the length
** of "in", there's no need to check for an overflow of "my_in". Any
** non-escaped double quotes are converted to something special so
** that they can be recognised at the editing stage.
*/
nxt = my_in;
while (*in != '\0') {
if (*in == '\\') { /* Look for escape sequence */
in++;
switch (*in) {
case 'a': case 'A': *nxt++ = '\007'; in++; break;
case 'b': case 'B': *nxt++ = '\010'; in++; break;
case 'f': case 'F': *nxt++ = '\014'; in++; break;
case 'n': case 'N': *nxt++ = '\012'; in++; break;
case 'r': case 'R': *nxt++ = '\015'; in++; break;
case 't': case 'T': *nxt++ = '\011'; in++; break;
case 'v': case 'V': *nxt++ = '\013'; in++; break;
case '\\': *nxt++ = '\\'; in++; break;
case '\'': *nxt++ = '\''; in++; break;
case '\"': *nxt++ = '\"'; in++; break;
case '\?': *nxt++ = '\?'; in++; break;
case 'x': case 'X':
in++;
i = strspn (in, "0123456789abcdefABCDEF");
if (i > 0) {
*nxt++ = strtol (in, &in, 16); break;
}else {
*nxt++ = '\\'; break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
i = strspn (in, "01234567");
if (i > 3) {
sscanf (in, "%3o", &j);
*nxt++ = j;
in += 3;
break;
}else if (i > 0) {
sscanf (in, "%o", &j);
*nxt++ = j;
in += i;
break;
}else {
*nxt++ = '\\';
break;
}
default:
*nxt++ = '\\'; /* Invalid esc sequ - just copy it */
}
}else if (*in == '\"') { /* Look for non-escaped double quotes */
*nxt++ = QUOTE; *in++; /* Make it something unlikely */
}else {
*nxt++ = *in++;
}
}
*nxt = '\0';
my_out = malloc (len); /* Get some working space */
if (my_out == NULL) {
free (my_in); *out = NIL; *ln = 0; return NULL;
}
*my_out = NIL;
my_tmp = malloc (len); /* Get some working space */
if (my_tmp == NULL) {
free (my_out); free (my_in);
*out = NIL; *ln = 0; return NULL;
}
*my_tmp = NIL;
*out = NIL;
/*
** Ensure "in" has an even number of non-escaped quotes. Return if not.
*/
i = 0;
for (j = 0; my_in[j] != NIL; j++) if (my_in[j] == QUOTE) i++;
if ((i & 1) == 1) {
free (my_tmp);
free (my_out);
free (my_in);
*ln = strlen (out);
return NULL;
}
/*
** Scan through "in", substring by substring, to
** handle quotation marks correctly.
*/
inxt = 0;
while (my_in[inxt] != NIL) {
if (my_in[inxt] == QUOTE) { /* Is there a quoted string next? */
nxt = strchr (&my_in[inxt+1], QUOTE); /* Yes, find matching quote. */
j = nxt - &my_in[inxt+1];
memcpy (my_tmp, &my_in[inxt+1], j); /* Make copy of it */
my_tmp[j] = NIL;
inxt = inxt + j + 2;
}else {
nxt = strchr (&my_in[inxt], QUOTE); /* Not a quoted string; ..
** .. find next non-escaped ..
** .. quote.
*/
if (nxt != NULL) {
j = nxt - my_in - inxt;
}else {
j = strlen (&my_in[inxt]);
}
memcpy (my_tmp, &my_in[inxt], j); /* Make copy for us to work on */
my_tmp[j] = NIL;
inxt = inxt + j;
/*
** For collapse and compress, start by turning all white space
** chars to spaces.
*/
if (do_collapse || do_compress) {
for (k = 0; my_tmp[k] != NIL; k++) {
if (my_tmp[k] == '\t') my_tmp[k] = ' ';
if (my_tmp[k] == '\f') my_tmp[k] = ' ';
if (my_tmp[k] == '\v') my_tmp[k] = ' ';
if (my_tmp[k] == '\n') my_tmp[k] = ' ';
}
if (do_collapse) {
l = 0;
for (k = 0; my_tmp[k] != NIL; k++) {
if (my_tmp[k] != ' ') {
my_tmp[l] = my_tmp[k];
l++;
}
}
my_tmp[l] = NIL;
}else if (do_compress) {
for (k = 0; my_tmp[k] != NIL; k++) {
if (my_tmp[k] == ' ') {
l = strspn (&my_tmp[k], " ");
if (l > 1) {
for (m = 0; my_tmp[k+l+m] != NIL; m++) {
my_tmp[k+m+1] = my_tmp[k+l+m];
}
my_tmp[k+m+1] = NIL;
}
}
}
}
}
if (do_lowercase) {
for (k = 0; my_tmp[k] != NIL; k++) my_tmp[k] = _tolower (my_tmp[k]);
}
if (do_upcase) {
for (k = 0; my_tmp[k] != NIL; k++) my_tmp[k] = _toupper (my_tmp[k]);
}
if (do_uncomment) {
nxt = strchr (my_tmp, '!');
if (nxt != NULL) {
*nxt = NIL; /* Truncate the string at the "!" */
my_in[inxt] = NIL; /* Stop processing loop too */
}
}
}
StrJoin (out, out_size, my_out, my_tmp);
strcpy (my_out, out);
}
if (do_trim) {
i = strspn (my_out, " ");
if (i == strlen (my_out)) { /* If all spaces, result is a null string */
*out = NIL;
}else {
for (j = strlen (my_out); my_out[j-1] == ' '; j--);
my_out[j] = NIL;
}
strcpy (out, &my_out[i]);
}
free (my_tmp);
free (my_out);
free (my_in);
*ln = strlen (out);
/*
** Undo any encoded escape characters.
*/
for (i = 0; out[i] != NIL; i++) {
if (out[i] == ~'\"') out[i] = '\"';
}
return out;
}
/*-------------------------------------------------- End of StrEdit.C -------*/

142
hardsup/strjoin.c Normal file
View File

@ -0,0 +1,142 @@
#define ident "1B03"
#ifdef VAXC
#module StrJoin ident
#endif
#ifdef __DECC
#pragma module StrJoin ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]STRJOIN.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]StrEdit -
tasmad_disk:[mad.lib.sinq]StrEdit +
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit
**
** Updates:
** 1A01 2-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
** 1B03 28-May-1997 DM. Allow result string to be either of source
** strings.
**============================================================================
** The following entry points are included in this module:
**
**-------------------------------------------------------------------------
** #include <sinq_prototypes.h>
**
** char *StrJoin (&result, result_size, &str_a, &str_b)
** -------
** Input Args:
** int result_size - max size of "result". The resultant string will
** have a max length of (result_size - 1) to allow
** for the zero terminator
** char *str_a - Pointer to first string to be joined.
** char *str_b - Pointer to second string to be joined.
** Output Args:
** char *result - Pointer to resulting string.
** Modified Args:
** none
** Return value:
** Pointer to resulting string.
** Global variables modified:
** none
** Routines called:
** None
** Description:
** The routine joins 2 strings, checking for total string length and
** ensuring the result will be zero terminated. The "result" arg may be
** the same as "str_a" or "str_b".
**-------------------------------------------------------------------------
** Global Definitions
*/
#include <string.h>
#define NIL '\0'
/*
**====================================================================
*/
/*
**====================================================================
** StrJoin - join 2 strings.
** Note: strncat is used exclusively rather than
** strncpy to be sure result is always
** null terminated.
*/
char *StrJoin (
/* =======
*/ char *result,
int result_size,
char *str_a,
char *str_b) {
int i, size, size_a, size_b;
size = result_size - 1;
if (size < 0) return result;
if (result == str_a) { /* Are the result and str_a the same? */
size_a = strlen (str_a); /* Yes */
if (size_a > size) { /* Check sizes anyway. */
result[size] = NIL; /* Truncate str_a. No room for str_b! */
}else {
size = size - strlen (result); /* And append str_b */
if (size > 0) {
strncat (result, str_b, size);
}
}
}else if (result == str_b) { /* Are the result and str_b the same? */
size_a = strlen (str_a); /* Yes, this is a bit complicated! */
size_b = strlen (str_b);
if (size_a >= size) { /* If str_a completely fills result, .. */
result[0] = NIL; /* .. then just copy in str_a */
strncat (result, str_a, size);
}else {
/*
** Otherwise, str_b must first be moved to
** make room for str_a and then str_a must
** be put at the front of the result.
*/
if ((size_a + size_b) > size) size_b = size - size_a;
result[size_a+size_b] = NIL;
for (i = (size_b-1); i >= 0; i--) {
result[size_a+i] = str_b[i];
}
memcpy (result, str_a, size_a);
}
}else { /* Result is neither str_a nor str_b so .. */
result[0] = NIL; /* .. str_a needs to be copied */
strncat (result, str_a, size);
size = size - strlen (result); /* And str_a appended */
if (size > 0) strncat (result, str_b, size);
}
return result;
}
/*-------------------------------------------------- End of STRJOIN.C =======*/

176
hardsup/table.c Normal file
View File

@ -0,0 +1,176 @@
/*-------------------------------------------------------------------------
Implementation file for translation table.
Mark Koennecke, October 1997
copyright: see copyright.h
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "table.h"
/*-------------------------------------------------------------------------*/
typedef struct __SicsTable {
float *fVal1;
float *fVal2;
int iLength;
} STable;
/*-------------------------------------------------------------------------*/
pSTable CreateTable(FILE *fd)
{
pSTable pNew = NULL;
long lStart, lEnd, lData, i;
char *pBuffer = NULL, *pEnd = NULL, *pEndLine, *pPtr;
int iLength, iRet;
float fVal1, fVal2;
assert(fd);
/* find length of file, create a buffer and read it in */
lStart = ftell(fd);
fseek(fd,0L,SEEK_END);
lEnd = ftell(fd);
lData = lEnd - lStart;
pBuffer = (char *)malloc(lData*sizeof(char));
if(!pBuffer)
{
return NULL;
}
fseek(fd,lStart,SEEK_SET);
fread(pBuffer,sizeof(char),lData,fd);
/* find number of lines */
for(i = 0, iLength = 0; i < lData; i++)
{
if(pBuffer[i] == '\n')
{
iLength++;
}
}
/* allocate the table structure */
pNew = (pSTable)malloc(sizeof(STable));
if(!pNew)
{
free(pBuffer);
return NULL;
}
pNew->iLength = iLength;
pNew->fVal1 = (float *)malloc(sizeof(float)*iLength);
pNew->fVal2 = (float *)malloc(sizeof(float)*iLength);
if( (!pNew->fVal1) || (!pNew->fVal2))
{
free(pBuffer);
free(pNew);
return NULL;
}
memset(pNew->fVal1,0,iLength*sizeof(float));
memset(pNew->fVal2,0,iLength*sizeof(float));
/* dodge through the file reading pairs until end */
pPtr = pBuffer;
pEnd = pBuffer + lData;
pEndLine = pBuffer;
i = 0;
while(pEndLine < pEnd)
{
if(*pEndLine == '\n')
{
*pEndLine = '\0';
iRet = sscanf(pPtr,"%f %f",&fVal1, &fVal2);
if(iRet == 2)
{
pNew->fVal1[i] = fVal1;
pNew->fVal2[i] = fVal2;
i++;
}
pEndLine++;
pPtr = pEndLine;
}
else
{
pEndLine++;
}
}
free(pBuffer);
return pNew;
}
/*--------------------------------------------------------------------------*/
void DeleteTable(pSTable self)
{
if(self->fVal1)
{
free(self->fVal1);
}
if(self->fVal2)
{
free(self->fVal2);
}
free(self);
}
/*--------------------------------------------------------------------------*/
int InterpolateVal1(pSTable self, float fKey, float *fResult)
{
float fFrac;
int i1,i;
assert(self);
assert(self->fVal1);
assert(self->fVal2);
/* search the entry point */
for(i = 0; i < self->iLength; i++)
{
if(self->fVal1[i] >= fKey)
{
i1 = i;
break;
}
}
if(i1 >= self->iLength)
{
return 0;
}
/* interpolate */
fFrac = (fKey - self->fVal1[i1 -1])
/ (self->fVal1[i1] - self->fVal1[i1 - 1]);
*fResult = self->fVal2[i1-1]
+ fFrac*(self->fVal2[i1] - self->fVal2[i1 -1]);
return 1;
}
/*---------------------------------------------------------------------------*/
int InterpolateVal2(pSTable self, float fKey, float *fResult)
{
float fFrac;
int i1,i;
assert(self);
assert(self->fVal1);
assert(self->fVal2);
/* search the entry point */
for(i = 0; i < self->iLength; i++)
{
if(self->fVal2[i] <= fKey)
{
i1 = i;
break;
}
}
if(i1 >= self->iLength)
{
return 0;
}
/* interpolate */
fFrac = (fKey - self->fVal2[i1 -1])
/ (self->fVal2[i1] - self->fVal2[i1 - 1]);
*fResult = self->fVal1[i1-1]
+ fFrac*(self->fVal1[i1] - self->fVal1[i1 -1]);
return 1;
}

35
hardsup/table.h Normal file
View File

@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------
A general purpose translation table and interpolation module.
Interpolation tables are read from a file, which is meant to
contain pairs of val1 val2 per line.
Mark Koennecke, October 1997
copyright: see copyright.h
-----------------------------------------------------------------------------*/
#ifndef SICSTABLE
#define SICSTABLE
typedef struct __SicsTable *pSTable;
/*------------------------- live & death ----------------------------------*/
pSTable CreateTable(FILE *fd);
/*
creates a new table from a given file. The file is meant to have
been positioned to the first entry for the table in the file.
This leaves the caller free to examine a header, if any.
*/
void DeleteTable(pSTable self);
/*------------------------- Interpolation --------------------------------*/
int InterpolateVal1(pSTable pTable, float fKey, float *fResult);
/*
Returns a result from the second column for a key from the
first column.
*/
int InterpolateVal2(pSTable pTable, float fKey, float *fResult);
/*
Returns a result from the first column for a key from the
second column.
*/
#endif

58
hardsup/velsel_def.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef _velsel_def_
#define _velsel_def_
/*------------------------------------------------ VelSel_DEF.H Ident V01B
*/
#include <asynsrv_def.h>
#include <rs232c_def.h>
#ifndef OffsetOf
#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier))
#endif
enum VelSel_Errors {VELSEL__BAD_TMO = -1,
VELSEL__BAD_CMD = -3,
VELSEL__BAD_OFL = -4,
VELSEL__BAD_ILLG = -5,
VELSEL__BAD_HOST = -6,
VELSEL__BAD_SOCKET = -7,
VELSEL__BAD_BIND = -8,
VELSEL__BAD_CONNECT = -9,
VELSEL__BAD_DEV = -10,
VELSEL__BAD_MALLOC = -11,
VELSEL__BAD_SENDLEN = -12,
VELSEL__BAD_SEND = -13,
VELSEL__BAD_SEND_PIPE = -14,
VELSEL__BAD_SEND_NET = -15,
VELSEL__BAD_SEND_UNKN = -16,
VELSEL__BAD_RECV = -17,
VELSEL__BAD_RECV_PIPE = -18,
VELSEL__BAD_RECV_NET = -19,
VELSEL__BAD_RECV_UNKN = -20,
VELSEL__BAD_NOT_BCD = -21,
VELSEL__BAD_RECVLEN = -22,
VELSEL__BAD_FLUSH = -23,
VELSEL__BAD_RECV1 = -24,
VELSEL__BAD_RECV1_PIPE = -25,
VELSEL__BAD_RECV1_NET = -26,
VELSEL__BAD_PAR = -29,
VELSEL__BAD_BSY = -30,
VELSEL__BAD_OPEN = -31,
VELSEL__FORCED_CLOSED = -32,
VELSEL__BAD_STP = -33,
VELSEL__NOT_OPEN = -35,
VELSEL__BAD_ASYNSRV = -36,
VELSEL__BAD_REPLY = -34};
/*
** Structure to which the VelSel_Open handle points.
*/
struct VelSel_info {
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
int tmo;
char eot[4];
int msg_id;
int n_replies, max_replies;
struct RS__MsgStruct to_host;
struct RS__RespStruct from_host;
};
/*------------------------------------------------ End of VelSel_DEF.H --*/
#endif /* _velsel_def_ */

928
hardsup/velsel_utility.c Normal file
View File

@ -0,0 +1,928 @@
#define ident "1A01"
#ifdef VAXC
#module VelSel_Utility ident
#endif
#ifdef __DECC
#pragma module VelSel_Utility ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]VelSel_Utility.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : June 1997
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]VelSel_Utility -
tasmad_disk:[mad.psi.lib.sinq]VelSel_Utility + -
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb VelSel_Utility debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb VelSel_Utility
**
** Updates:
** 1A01 13-Jun-1997 DM. Initial version.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
** #include <sinq_prototypes.h>
**
** VelSel_Close - Close a connection to a Velocity Selector.
** VelSel_Config - Configure a connection to a Velocity Selector.
** VelSel_ErrInfo - Return detailed status from last operation.
** VelSel_GetReply - Get next reply from a reply buffer.
** VelSel_GetStatus - Get "???" response.
** VelSel_Open - Open a connection to a Velocity Selector.
** VelSel_SendCmnds - Send commands to RS232C server.
**---------------------------------------------------------------------
** int VelSel_Close (&handle, int force_flag)
** ------------
** Input Args:
** int force_flag - if non-zero, all connections using the same socket
** will also be closed (this gets AsynSrv_Close to
** actually close the socket and is needed for error
** recovery operations).
** Output Args:
** none
** Modified Args:
** void **handle - The pointer to the structure returned by VelSel_Open.
** On return, the pointer is set to NULL.
** Return status:
** True always (error returns from close and free are not checked).
** Routines called:
** AsynSrv_Close
** Description:
** The routine calls AsynSrv_Close to close the connection to the RS232C
** server. If 'force_flag' is non-zero, all other connections to the
** RS232C server which use the same socket will also be closed.
**
** The 'force_flag' can be useful in error recovery situations. The AsynSrv
** utility operates by only opening a socket for each separate combination
** of host/port. Hence, if several connections are open to the server,
** then calling VelSel_Close doesn't actually close the socket until all
** connections have been closed. In the situation
** where an error has been detected, it is often desirable to
** close and re-open the socket as part of the recovery procedure. Calling
** VelSel_Close with 'force_flag' non-zero will force the socket to be
** closed and will mark all connections using this socket so that they
** will be informed of the event when they next call any AsynSrv
** dependent routine.
**
** Note: The force-close action is effected by the AsynSrv package. A
** force-close will thus also close any connections to other
** RS-232-C devices (e.g. EL737 neutron cntr) on the same server.
**-------------------------------------------------------------------------
** void VelSel_Config (&handle, msec_tmo, eot_str)
** -------------
** Input Args:
** void **handle - The pointer to the structure returned by VelSel_Open.
** int msec_tmo - The time-out for responses. Dflt = 10000.
** char *eot_str - A string of up to 3 characters specifying terminating
** characters for input.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** none
** Routines called:
** none
** Description:
** The routine sets values in the VelSel_info data structure.
**-------------------------------------------------------------------------
** void VelSel_ErrInfo (&entry_txt_ptr, &errcode, &my_errno, &vaxc_errno)
** --------------
** Input Args:
** None
** Output Args:
** char **entry_txt_ptr - Pointer to a text string giving the call stack
** at the time that the error was detected.
** int *errcode - An internal error code indicating the detected error.
** int *my_errno - Saved value of errno.
** int *vaxc_errno - Saved value of vaxc$errno (OpenVMS only).
** Modified Args:
** none
** Return status:
** none
** Routines called:
** none
** Description:
** Returns detailed status of the last operation. Once an error has been
** detected, the error status is frozen until this routine has been called.
**-------------------------------------------------------------------------
** void *VelSel_GetReply (&handle, last_rply)
** ---------------
** Input Args:
** void **handle - The pntr to the structure returned by VelSel_Open.
** void *last_rply - Address of last reply processed or NULL.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** Address of next reply structure in the buffer or NULL if no more.
** Routines called:
** none
** Description:
** VelSel_GetReply is a utility routine mainly intended for internal use
** by the VelSel_Utility package. It unpacks the replies in the response
** packet from the RS232C server.
**
** Having received a response from the server to a sequence of commands,
** VelSel_GetReply is called with last_rply = NULL. The return value is
** a pointer to the first reply sub-structure in the response. On calling
** VelSel_GetReply again with last_rply set to this address, one receives
** the address of the second reply sub-structure and so on, until NULL
** is returned when all responses have been exhausted. The structure of
** a reply sub-structure is RS__RplyStruct.
**-------------------------------------------------------------------------
** int VelSel_GetStatus (&handle, &status_str, status_str_len)
** ----------------
** Input Args:
** void **handle - The pointer to the structure returned by VelSel_Open.
** int status_str_len - The length of status_str.
** Output Args:
** char *status_str - Pointer to a buffer to save the status.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and VelSel_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** VelSel_GetStatus are (other values may be set by the called routines):
** VELSEL__BAD_TMO, _LOC, _CMD, _OFL, _ADR --> see VelSel_Open.
** VELSEL__BAD_ILLG = -5 --> one of the responses could probably not be
** decoded. This could happen if there is noise
** on the RS232C connection to the Velocity
** Selector.
** If an error is detected, ist_posit is set to 0.0 and all other
** arguments to -1.
** Routines called:
** VelSel_SendCmnds
** Description:
** The routine issues a "???" command to the Velocity Selector and
** analyses the result.
**-------------------------------------------------------------------------
** int VelSel_Open (&handle, host, port, chan, id)
** -----------
** Input Args:
** char *host - Name of host offering the TCP/IP service.
** int port - Number of TCP/IP port of TCP/IP server.
** int chan - RS-232-C Channel number on the TCP/IP server.
** char *id - The expected ID of the device, normally "????".
** If id is NULL, the device ID is not checked.
** Output Args:
** void *handle - A pointer to a structure of type VelSel_info needed
** for subsequent calls to VelSel_... routines. Buffer
** space for the structure is allocated dynamically.
** It gets released via a call to VelSel_Close.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False. If False, VelSel_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** VelSel_Open are (other values may be set by the called routines):
** VELSEL__BAD_TMO = -1 --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** VELSEL__BAD_LOC = -2 --> Off-line ("?LOC"). This should not
** happen on calls to VelSel_Open since it
** sends an "RMT 1" cmnd.
** VELSEL__BAD_CMD = -3 --> Command error ("?CMD"). This could be
** caused by noise in the RS-232-C
** transmission.
** VELSEL__BAD_OFL = -4 --> Connection broken ("?OFL").
** This can get generated by RS232C_SRV
** if, for example, the connection is via
** a terminal server and the terminal
** server loses power.
** VELSEL__BAD_ILLG = -5 --> Some other unrecognised response. This
** should never occur, of course!
** VELSEL__BAD_HOST = -6 --> Call to "gethostbyname" failed to get
** network addr of host.
** VELSEL__BAD_SOCKET = -7 --> Call to "socket" failed.
** VELSEL__BAD_BIND = -8 --> Call to "bind" failed.
** VELSEL__BAD_CONNECT = -9 --> Call to "connect" failed.
** VELSEL__BAD_DEV = -10 --> Bad cmnd response - is device a VelSel?
** VELSEL__BAD_MALLOC = -11 --> Call to "malloc" failed
** Routines called:
** AsynSrv_open, the memory alloc routine "malloc" and VelSel_SendCmnds.
** Description:
** The routine calls AsynSrv_open to open a TCP/IP connection to a server
** offering the "RS-232-C" service for a Velocity Selector. "RMT 1"
** and "ECHO 0" commands are sent to ensure the device is on-line.
**-------------------------------------------------------------------------
** int VelSel_SendCmnds (&handle, ...)
** ----------------
** Input Args:
** void **handle - The pntr to the structure returned by VelSel_Open.
** char * ... - A list of commands, terminated by NULL, for
** sending to the Velocity Selector. The commands must
** have any necessary \r characters included.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** VelSel_ErrInfo) is set to indicate the nature of the problem.
** VelSel_errcode may be set as follows:
** VELSEL__BAD_SENDLEN = -12 --> Too much to send; either too many
** commands or too long. The buffer
** is 232 bytes long and each command
** has a 2-byte header.
** Errors -13 to -16 are related to network errors whilst sending the
** message buffer to the server:
** VELSEL__BAD_SEND = -13 --> Network problem - server has
** probably abended.
** VELSEL__BAD_SEND_PIPE = -14 --> Network pipe broken - probably same
** cause as VELSEL__BAD_SEND.
** VELSEL__BAD_SEND_NET = -15 --> Some other network problem. "errno"
** may be helpful.
** VELSEL__BAD_SEND_UNKN = -16 --> Some other network problem happened
** resulting in the message not
** getting sent completely. "errno" is
** probably not helpful in this case.
** Errors VELSEL__BAD_RECV, VELSEL__BAD_RECV_PIPE, VELSEL__BAD_RECV_NET
** and VELSEL__BAD_RECV_UNKN (-17 to -20) are related to network
** errors whilst receiving the 4-byte response header. They are
** analogous to VELSEL__BAD_SEND to VELSEL__BAD_SEND_UNKN.
** VELSEL__BAD_NOT_BCD = -21 --> The 4-byte response header is not an
** ASCII coded decimal integer.
** VELSEL__BAD_RECVLEN = -22 --> The body of the response would be too
** big to fit in the input buffer. The
** buffer is 244 bytes long and each
** response has a 3-byte header and a
** trailing zero-byte. The response
** is flushed.
** VELSEL__BAD_FLUSH = -23 --> Some network error was detected
** during flushing. This is an "or"
** of errors VELSEL__BAD_RECV to
** VELSEL__BAD_RECV_UNKN.
** VELSEL__FORCED_CLOSED = -32 --> The connection to the Velocity
** Selector has been forcefully
** closed. See below.
** VELSEL__BAD_REPLY = -34 --> The n_rply field of the response was
** either non-numeric or <0, indicating
** that the Terminal Server detected an
** error. The reply is added to the
** routine call stack for debug purposes.
**
** Errors VELSEL__BAD_RECV1, VELSEL__BAD_RECV1_PIPE and
** VELSEL__BAD_RECV1_NET (-24 to -26) are related to network
** errors whilst receiving the body of the response. They are
** equivalent to errors VELSEL__BAD_RECV, to VELSEL__BAD_RECV_NET.
**
** VELSEL__FORCED_CLOSED occurs if AsynSrv_Close has been called (e.g.
** via a call to VelSel_Close) for another device on the same
** server and the 'force_flag' was set (see VelSel_Close). The
** caller should call VelSel_Close and then VelSel_Open to
** re-establish a connection to the Velocity Selector.
** Routines called:
** Socket library routines send and recv.
** Description:
** The list of commands is assembled into a message buffer with appropriate
** header information and sent off to the server. The response is then
** awaited and read in when it arrives.
**
** For any of the following errors:
** VELSEL__BAD_SEND (Note: VELSEL__BAD_SENDLEN and
** VELSEL__BAD_SEND_PIPE VELSEL__BAD_RECVLEN do not cause a close
** VELSEL__BAD_SEND_NET
** VELSEL__BAD_SEND_UNKN
** VELSEL__BAD_RECV
** VELSEL__BAD_RECV_PIPE
** VELSEL__BAD_RECV_NET
** VELSEL__BAD_RECV_UNKN
** VELSEL__BAD_NOT_BCD
** VELSEL__BAD_FLUSH
** VELSEL__BAD_RECV1
** VELSEL__BAD_RECV1_PIPE
** VELSEL__BAD_RECV1_NET
** the network link to the server is force-closed via a call to VelSel_Close.
** Once the error has been corrected, the link can be re-opened via a
** call to VelSel_Open. As a result of the force-close, other active handles
** will need to be released via a call to VelSel_Close before VelSel_Open is
** called.
**
** Note: neither of the errors VELSEL__BAD_SENDLEN, VELSEL__BAD_RECVLEN
** nor VELSEL__BAD_REPLY cause the link to be closed.
**============================================================================*/
/*
**---------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#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 <rs232c_def.h>
#include <asynsrv_def.h>
#include <VelSel_def.h>
#include <sinq_prototypes.h>
#define True 1
#define False 0
/*--------------------------------------------------------------------------
** Global Variables
*/
static int VelSel_call_depth = 0;
static char VelSel_routine[5][64];
static int VelSel_errcode = 0;
static int VelSel_errno, VelSel_vaxc_errno;
/*
**---------------------------------------------------------------------------
** VelSel_Close: Close a connection to a Velocity Selector.
*/
int VelSel_Close (
/* ===========
*/ void **handle,
int force_flag) {
struct VelSel_info *info_ptr;
char buff[4];
info_ptr = (struct VelSel_info *) *handle;
if (info_ptr == NULL) return True;
if (info_ptr->asyn_info.skt != 0) {
if (info_ptr->asyn_info.skt > 0) {
AsynSrv_Close (*handle, force_flag);
}
}
free (*handle);
*handle = NULL;
return True;
}
/*
**---------------------------------------------------------------------------
** VelSel_Config: Configure a connection to a Velocity Selector.
*/
void VelSel_Config (
/* ============
*/ void **handle,
int msec_tmo,
char *eot_str) {
int i;
struct VelSel_info *info_ptr;
info_ptr = (struct VelSel_info *) *handle;
if (info_ptr == NULL) return;
/*-------------------------
** Set up the time-out
*/
if (msec_tmo < 0) {
info_ptr->tmo = -1;
}else {
info_ptr->tmo = (msec_tmo + 99)/100; /* Convert to deci-secs */
if (info_ptr->tmo > 9999) info_ptr->tmo = 9999;
}
/*---------------------------------
** Set up the end-of-text string
*/
if (eot_str != NULL) {
for (i = 0; i < sizeof (info_ptr->eot); i++) info_ptr->eot[i] = '\0';
for (i = 0; i < sizeof (info_ptr->eot); i++) {
if (eot_str[i] == '\0') break;
info_ptr->eot[i+1] = eot_str[i];
}
info_ptr->eot[0] = '0' + i;
}
return;
}
/*
** -------------------------------------------------------------------------
** VelSel_ErrInfo: Return detailed status from last operation.
*/
void VelSel_ErrInfo (
/* =============
*/ char **entry_txt,
int *errcode,
int *my_errno,
int *vaxc_errno) {
int i;
char buff[80];
int asyn_errcode, asyn_errno, asyn_vaxerrno;
char* asyn_errtxt;
if (VelSel_call_depth <= 0) {
strcpy (VelSel_routine[0], "VelSel_no_error_detected");
*errcode = 0;
*my_errno = 0;
*vaxc_errno = 0;
}else {
if (VelSel_call_depth > 1) { /* Concatenate the names */
for (i = 1; i < VelSel_call_depth; i++) {
strcat (VelSel_routine[0], "/");
StrJoin (VelSel_routine[0], sizeof (VelSel_routine),
VelSel_routine[0], VelSel_routine[i]);
}
}
*errcode = VelSel_errcode;
*my_errno = VelSel_errno;
*vaxc_errno = VelSel_vaxc_errno;
switch (VelSel_errcode) {
case VELSEL__BAD_TMO: strcpy (buff, "/VELSEL__BAD_TMO"); break;
case VELSEL__BAD_CMD: strcpy (buff, "/VELSEL__BAD_CMD"); break;
case VELSEL__BAD_OFL: strcpy (buff, "/VELSEL__BAD_OFL"); break;
case VELSEL__BAD_ILLG: strcpy (buff, "/VELSEL__BAD_ILLG"); break;
case VELSEL__BAD_HOST: strcpy (buff, "/VELSEL__BAD_HOST"); break;
case VELSEL__BAD_SOCKET: strcpy (buff, "/VELSEL__BAD_SOCKET"); break;
case VELSEL__BAD_BIND: strcpy (buff, "/VELSEL__BAD_BIND"); break;
case VELSEL__BAD_CONNECT: strcpy (buff, "/VELSEL__BAD_CONNECT"); break;
case VELSEL__BAD_DEV: strcpy (buff, "/VELSEL__BAD_DEV"); break;
case VELSEL__BAD_MALLOC: strcpy (buff, "/VELSEL__BAD_MALLOC"); break;
case VELSEL__BAD_SENDLEN: strcpy (buff, "/VELSEL__BAD_SENDLEN"); break;
case VELSEL__BAD_SEND: strcpy (buff, "/VELSEL__BAD_SEND"); break;
case VELSEL__BAD_SEND_PIPE: strcpy (buff, "/VELSEL__BAD_SEND_PIPE"); break;
case VELSEL__BAD_SEND_NET: strcpy (buff, "/VELSEL__BAD_SEND_NET"); break;
case VELSEL__BAD_SEND_UNKN: strcpy (buff, "/VELSEL__BAD_SEND_UNKN"); break;
case VELSEL__BAD_RECV: strcpy (buff, "/VELSEL__BAD_RECV"); break;
case VELSEL__BAD_RECV_PIPE: strcpy (buff, "/VELSEL__BAD_RECV_PIPE"); break;
case VELSEL__BAD_RECV_NET: strcpy (buff, "/VELSEL__BAD_RECV_NET"); break;
case VELSEL__BAD_RECV_UNKN: strcpy (buff, "/VELSEL__BAD_RECV_UNKN"); break;
case VELSEL__BAD_NOT_BCD: strcpy (buff, "/VELSEL__BAD_NOT_BCD"); break;
case VELSEL__BAD_RECVLEN: strcpy (buff, "/VELSEL__BAD_RECVLEN"); break;
case VELSEL__BAD_FLUSH: strcpy (buff, "/VELSEL__BAD_FLUSH"); break;
case VELSEL__BAD_RECV1: strcpy (buff, "/VELSEL__BAD_RECV1"); break;
case VELSEL__BAD_RECV1_PIPE: strcpy (buff, "/VELSEL__BAD_RECV1_PIPE"); break;
case VELSEL__BAD_RECV1_NET: strcpy (buff, "/VELSEL__BAD_RECV1_NET"); break;
case VELSEL__BAD_PAR: strcpy (buff, "/VELSEL__BAD_PAR"); break;
case VELSEL__BAD_BSY: strcpy (buff, "/VELSEL__BAD_BSY"); break;
case VELSEL__BAD_OPEN: strcpy (buff, "/VELSEL__BAD_OPEN"); break;
case VELSEL__FORCED_CLOSED: strcpy (buff, "/VELSEL__FORCED_CLOSED"); break;
case VELSEL__BAD_STP: strcpy (buff, "/VELSEL__BAD_STP"); break;
case VELSEL__BAD_REPLY: strcpy (buff, "/VELSEL__BAD_REPLY"); break;
default: sprintf (buff, "/VELSEL__unknown_err_code: %d", VelSel_errcode);
}
StrJoin (VelSel_routine[0], sizeof(VelSel_routine), VelSel_routine[0], buff);
}
AsynSrv_ErrInfo (&asyn_errtxt, &asyn_errcode, &asyn_errno, &asyn_vaxerrno);
if (asyn_errcode != 0) {
strcat (VelSel_routine[0], "/");
StrJoin (VelSel_routine[0], sizeof(VelSel_routine),
VelSel_routine[0], asyn_errtxt);
}
*entry_txt = VelSel_routine[0];
VelSel_call_depth = 0;
VelSel_errcode = 0;
}
/*
**---------------------------------------------------------------------------
** VelSel_GetReply - Get next reply from a reply buffer.
*/
void *VelSel_GetReply (
/* ==============
*/ void **handle, /* Pointer to structure containing
** message to pull apart */
void *last_rply) { /* Starting point */
int rply_len;
struct RS__RplyStruct *ptr;
struct VelSel_info *my_info_ptr;
struct RS__RplyStruct *my_last_rply;
ptr = NULL;
my_info_ptr = (struct VelSel_info *) *handle;
my_last_rply = (struct RS__RplyStruct *) last_rply;
if (my_last_rply == NULL) { /* Start with first reply? */
/* Yes */
if (sscanf (my_info_ptr->from_host.n_rply, "%4d",
&my_info_ptr->max_replies) != 1) my_info_ptr->max_replies = 0;
if (my_info_ptr->max_replies > 0)
ptr = (struct RS__RplyStruct *) my_info_ptr->from_host.u.rplys;
my_info_ptr->n_replies = 1;
}else {
my_info_ptr->n_replies++;
if (my_info_ptr->n_replies <= my_info_ptr->max_replies) {
if (sscanf (my_last_rply->rply_len, "%2d", &rply_len) == 1) {
ptr =
(struct RS__RplyStruct *) ((char *) my_last_rply + rply_len + 2);
}
}
}
return (void *) ptr;
}
/*
**---------------------------------------------------------------------------
** VelSel_GetStatus: Get "???" response from Vel Selector
*/
int VelSel_GetStatus (
/* ===============
*/ void **handle,
char *status_str,
int status_str_len) {
int status;
struct VelSel_info *info_ptr;
struct RS__RplyStruct *rply_ptr;
struct RS__RplyStruct *rply_ptr0;
/*----------------------------------------------
*/
status_str[0] = '\0';
/*----------------------------------------------
** Pre-set the routine name (in case of error)
*/
if (VelSel_errcode == 0 && VelSel_call_depth < 5) {
strcpy (VelSel_routine[VelSel_call_depth], "VelSel_GetStatus");
VelSel_call_depth++;
}
/*----------------------------------------------
** Do nothing if no connection - the connection gets
** closed if an error is detected.
*/
info_ptr = (struct VelSel_info *) *handle;
if (info_ptr == NULL) {
return False;
}
if (info_ptr->asyn_info.skt <= 0) {
memset (info_ptr->from_host.msg_size,
'0', sizeof (info_ptr->from_host.msg_size));
if ((VelSel_errcode == 0) && (info_ptr->asyn_info.skt < 0)) {
VelSel_errcode = VELSEL__FORCED_CLOSED;
}
return False;
}
/*----------------------------------------------
** Send "???" command to Velocity Selector
*/
status = VelSel_SendCmnds (handle, "???", NULL);
if (!status) {
/* Error in VelSel_SendCmnds */
return False;
}else {
rply_ptr0 = VelSel_GetReply (handle, NULL);
if (rply_ptr0 == NULL) rply_ptr0 = (struct RS__RplyStruct *) "06\rNULL";
StrJoin (status_str, status_str_len, rply_ptr0->rply, "");
}
VelSel_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** VelSel_Open: Open a connection to a Velocity Selector.
*/
int VelSel_Open (
/* ==========
*/ void **handle,
char *host,
int port,
int chan) {
int status;
struct VelSel_info *my_handle;
struct RS__RplyStruct *rply_ptr;
struct RS__RplyStruct *rply_ptr0;
struct RS__RplyStruct *rply_ptr1;
struct RS__RplyStruct *rply_ptr2;
struct RS__RplyStruct *rply_ptr3;
/*--------------------------------------------------------
** Initialise the error info stack and pre-set the
** routine name (in case of error).
*/
VelSel_errcode = VelSel_errno = VelSel_vaxc_errno = 0;
strcpy (VelSel_routine[0], "VelSel_Open");
VelSel_call_depth = 1;
/*--------------------------------------------------------
** Assume trouble
*/
*handle = NULL;
/*--------------------------------------------------------
** Reserve space for the data we need to store.
*/
my_handle = (struct VelSel_info *) malloc (sizeof (*my_handle));
if (my_handle == NULL) {
VelSel_errcode = VELSEL__BAD_MALLOC; /* malloc failed!! */
return False;
}
/*--------------------------------------------------------
** Set up the connection
*/
StrJoin (my_handle->asyn_info.host, sizeof (my_handle->asyn_info.host),
host, "");
my_handle->asyn_info.port = port;
my_handle->asyn_info.chan = chan;
status = AsynSrv_Open (&my_handle->asyn_info);
if (!status) {
VelSel_errcode = VELSEL__BAD_SOCKET;
GetErrno (&VelSel_errno, &VelSel_vaxc_errno); /* Save errno info */
fprintf (stderr, "\nVelSel_Open/AsynSrv_Open: "
"Failed to make connection.\n");
free (my_handle);
return False;
}
my_handle->tmo = 25; /* Set a short time-out initially since
** there should be no reason for the REM
** command to take very long
*/
strcpy (my_handle->eot, "1\n\0\0");
my_handle->msg_id = 0;
/*
** Now ensure the VelSel is on-line. The first "REM" command can
** fail due to pending characters in the VelSel input buffer causing
** the "REM" to be corrupted. The response of the VelSel to this
** command is ignored for this reason (but the VelSel_SendCmnds
** status must be OK otherwise it indicates a network problem).
*/
status = VelSel_SendCmnds ((void *) &my_handle, "REM", NULL);
if (status) {
status = VelSel_SendCmnds ((void *) &my_handle, "REM", NULL);
}
if (!status) {
/* Some error occurred in VelSel_SendCmnds - Errcode will
** have been set up there.
*/
AsynSrv_Close (&my_handle->asyn_info, False);
free (my_handle);
return False;
}
/*
** Check the responses carefully.
*/
rply_ptr0 = VelSel_GetReply ((void *) &my_handle, NULL);
if (rply_ptr0 == NULL) rply_ptr0 = (struct RS__RplyStruct *) "06\rNULL";
if (rply_ptr0->rply[0] == '?') {
VelSel_errcode = VELSEL__BAD_DEV; /* Error response - not a VelSel? */
AsynSrv_Close (&my_handle->asyn_info, False);
free (my_handle);
return False;
}
/*
** The connection is complete. Pass the data structure
** back to the caller as a handle.
*/
my_handle->tmo = 100; /* Default time-out is 10 secs */
*handle = my_handle;
VelSel_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** VelSel_SendCmnds - Send commands to RS232C server.
*/
int VelSel_SendCmnds (
/* ================
*/ void **handle,
...) { /* Now we have list of commands -
** char *txt = pntr to cmnd strng
** Terminate list with *txt = NULL.
*/
struct VelSel_info *info_ptr;
int i, status, c_len, size, max_size, ncmnds;
int bytes_to_come, bytes_left;
char *nxt_byte_ptr;
char err_text[80];
char text[20];
va_list ap; /* Pointer to variable args */
char *txt_ptr;
char *cmnd_lst_ptr;
/*----------------------------------------------
** Pre-set the routine name (in case of error)
*/
if (VelSel_errcode == 0 && VelSel_call_depth < 5) {
strcpy (VelSel_routine[VelSel_call_depth], "VelSel_SendCmnds");
VelSel_call_depth++;
}
/*----------------------------------------------
** Do nothing if no connection - the connection gets
** closed if an error is detected. The connection may
** also be marked to have been forcefully closed.
*/
info_ptr = (struct VelSel_info *) *handle;
if (info_ptr == NULL) {
return False;
}
if (info_ptr->asyn_info.skt <= 0) {
memset (info_ptr->from_host.msg_size,
'0', sizeof (info_ptr->from_host.msg_size));
if ((VelSel_errcode == 0) && (info_ptr->asyn_info.skt < 0)) {
VelSel_errcode = VELSEL__FORCED_CLOSED;
}
return False;
}
/*----------------------------------------------
** Build message for Vel Selector from the list of commands.
*/
info_ptr->n_replies = info_ptr->max_replies = 0;
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,
sizeof (info_ptr->to_host.c_pcol_lvl));
sprintf (info_ptr->to_host.serial_port, "%04.4d", info_ptr->asyn_info.chan);
sprintf (info_ptr->to_host.tmo, "%04.4d", info_ptr->tmo);
memcpy (info_ptr->to_host.terms, info_ptr->eot,
sizeof (info_ptr->to_host.terms));
memcpy (info_ptr->to_host.n_cmnds, "0000",
sizeof (info_ptr->to_host.n_cmnds));
va_start (ap, handle); /* Set up var arg machinery */
txt_ptr = va_arg (ap, char *); /* Get pntr to next 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]);
while (txt_ptr != NULL) {
size = 2 + strlen (txt_ptr);
if (size > bytes_left) {
VelSel_errcode = VELSEL__BAD_SENDLEN; /* Too much to send */
fprintf (stderr, "\nVelSel_SendCmnds/send: too much to send"
" - request ignored.\n");
memset (info_ptr->from_host.msg_size,
'0', sizeof (info_ptr->from_host.msg_size));
return False;
}else {
strcpy (cmnd_lst_ptr+2, txt_ptr);
c_len = strlen (txt_ptr);
sprintf (text, "%02.2d", c_len);
memcpy (cmnd_lst_ptr, text, 2);
cmnd_lst_ptr = cmnd_lst_ptr + c_len + 2;
ncmnds++;
bytes_left = bytes_left - size;
txt_ptr = va_arg (ap, char *);
}
}
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->asyn_info.skt,
(char *) &info_ptr->to_host, size+4, 0);
if (status != (size+4)) {
GetErrno (&VelSel_errno, &VelSel_vaxc_errno);
if (status == 0) {
VelSel_errcode = VELSEL__BAD_SEND; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/send: probable network problem");
}else if (status == -1) {
if (VelSel_errno == EPIPE) {
VelSel_errcode = VELSEL__BAD_SEND_PIPE; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/send: broken network pipe");
}else {
VelSel_errcode = VELSEL__BAD_SEND_NET; /* It's some other net problem */
perror ("VelSel_SendCmnds/send");
}
}else {
VelSel_errcode = VELSEL__BAD_SEND_UNKN; /* TCP/IP problems */
fprintf (stderr, "\nVelSel_SendCmnds/send: probable TCP/IP problem");
}
VelSel_Close (handle, True); /* Force close TCP/IP connection */
fprintf (stderr, " - link to server force-closed.\n");
return False;
}
size = sizeof (info_ptr->from_host.msg_size);
status = recv (info_ptr->asyn_info.skt,
info_ptr->from_host.msg_size, size, 0);
if (status != size) {
GetErrno (&VelSel_errno, &VelSel_vaxc_errno);
if (status == 0) {
VelSel_errcode = VELSEL__BAD_RECV; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/recv: probable network problem");
}else if (status == -1) {
if (VelSel_errno == EPIPE) {
VelSel_errcode = VELSEL__BAD_RECV_PIPE; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/recv: broken network pipe");
}else {
VelSel_errcode = VELSEL__BAD_RECV_NET; /* It's some other net problem */
perror ("VelSel_SendCmnds/recv");
}
}else {
VelSel_errcode = VELSEL__BAD_RECV_UNKN; /* TCP/IP problems */
fprintf (stderr, "\nVelSel_SendCmnds/recv: probable TCP/IP problem");
}
VelSel_Close (handle, True); /* Force close TCP/IP connection */
fprintf (stderr, " - link to server force-closed.\n");
return False;
}
if (sscanf (info_ptr->from_host.msg_size, "%4d", &bytes_to_come) != 1) {
VelSel_errcode = VELSEL__BAD_NOT_BCD; /* Header not an ASCII BCD integer */
VelSel_Close (handle, True); /* Force close TCP/IP connection */
fprintf (stderr, "\nVelSel_SendCmnds/recv: non-BCD byte count"
" - link to server force-closed.\n");
return False;
}
max_size = sizeof (info_ptr->from_host) -
sizeof (info_ptr->from_host.msg_size);
if (bytes_to_come > max_size) {
VelSel_errcode = VELSEL__BAD_RECVLEN;
fprintf (stderr, "\nVelSel_SendCmnds/recv: pending message length too big"
" - flushing ...\n");
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->asyn_info.skt, nxt_byte_ptr, bytes_left, 0);
if (status <= 0) {
VelSel_errcode = VELSEL__BAD_FLUSH; /* TCP/IP problem whilst flushing */
GetErrno (&VelSel_errno, &VelSel_vaxc_errno);
VelSel_Close (handle, True); /* Force close TCP/IP connection */
fprintf (stderr, "\nVelSel_SendCmnds/recv: network problem during"
" flush.\nLink to server force-closed.\n");
return False;
}
bytes_to_come = bytes_to_come - status;
}
fprintf (stderr, "\n flushed OK.\n");
memset (info_ptr->from_host.msg_size,
'0', sizeof (info_ptr->from_host.msg_size));
return False;
}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->asyn_info.skt, nxt_byte_ptr, bytes_left, 0);
if (status <= 0) {
GetErrno (&VelSel_errno, &VelSel_vaxc_errno);
if (status == 0) {
VelSel_errcode = VELSEL__BAD_RECV1; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/recv/1: probable network "
"problem");
}else {
if (VelSel_errno == EPIPE) {
VelSel_errcode = VELSEL__BAD_RECV1_PIPE; /* Server exited (probably) */
fprintf (stderr, "\nVelSel_SendCmnds/recv/1: broken network pipe");
}else {
VelSel_errcode = VELSEL__BAD_RECV1_NET; /* It's some other net fault */
perror ("VelSel_SendCmnds/recv/1");
}
}
VelSel_Close (handle, True); /* Force close TCP/IP connection */
fprintf (stderr, " - link to server force-closed.\n");
return False;
}
bytes_left = bytes_left - status;
nxt_byte_ptr = nxt_byte_ptr + status;
}
if ((sscanf (info_ptr->from_host.n_rply, "%4d",
&info_ptr->max_replies) != 1) ||
(info_ptr->max_replies < 0)) {
VelSel_errcode = VELSEL__BAD_REPLY; /* Reply is bad */
if (VelSel_call_depth < 5) { /* Add reply to routine stack */
bytes_to_come = bytes_to_come + 4;
if (bytes_to_come >= sizeof (VelSel_routine[0]))
bytes_to_come = sizeof (VelSel_routine[0]) - 1;
for (i=0; i<bytes_to_come; i++) {
if (info_ptr->from_host.msg_size[i] == '\0')
info_ptr->from_host.msg_size[i] = '.';
}
info_ptr->from_host.msg_size[bytes_to_come] = '\0';
strcpy (VelSel_routine[VelSel_call_depth],
info_ptr->from_host.msg_size);
VelSel_call_depth++;
}
return False;
}
}
VelSel_call_depth--;
return True;
}
/*-------------------------------------------- End of VelSel_Utility.C =======*/