From 74247ccc72927abb3f3acaf3a5767d976b375dc2 Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Tue, 19 Aug 2025 08:52:37 +0200 Subject: [PATCH] Driver from Andrea Raselli as of 12.01.2024 --- bus/langpib.c | 849 ++++++++++++++++ bus/langpib.h | 54 + bus/tcpip.c | 1407 ++++++++++++++++++++++++++ bus/tcpip.h | 46 + device/ets_logout.c | 217 ++++ device/ets_logout.h | 18 + device/keller_dv2ps.c | 1166 ++++++++++++++++++++++ device/keller_dv2ps.h | 11 + midas/midas.h | 2198 +++++++++++++++++++++++++++++++++++++++++ midas/msystem.h | 653 ++++++++++++ 10 files changed, 6619 insertions(+) create mode 100644 bus/langpib.c create mode 100644 bus/langpib.h create mode 100644 bus/tcpip.c create mode 100644 bus/tcpip.h create mode 100644 device/ets_logout.c create mode 100644 device/ets_logout.h create mode 100644 device/keller_dv2ps.c create mode 100644 device/keller_dv2ps.h create mode 100644 midas/midas.h create mode 100644 midas/msystem.h diff --git a/bus/langpib.c b/bus/langpib.c new file mode 100644 index 0000000..f9187ee --- /dev/null +++ b/bus/langpib.c @@ -0,0 +1,849 @@ +/********************************************************************\ + + Name: langpib.c + Created by: RA35 + + Contents: LAN/GPIB communication routines + +\********************************************************************/ + +#define OMIT_MIDAS_RPC_CALL +#include "midas.h" +#include "msystem.h" +#include "gpib_musr.h" +#include "vxi11.h" +#include "langpib.h" + + +/* #define MIDEBUG */ +#define DELTA_TIME_ERROR 3600 //!< reset error counter after DELTA_TIME_ERROR seconds + +static int debug_last = 0, debug_first = TRUE; + +typedef struct { + char server[256]; + int address; + int locktmo; + int debug; +} LANGPIB_SETTINGS; + +#define LANGPIB_SETTINGS_STR "\ +Server = STRING : [256] myhost.my.domain\n\ +Address = INT : 1\n\ +LockTMO = INT : 30000\n\ +Debug = INT : 0\n\ +" + +typedef struct { + LANGPIB_SETTINGS settings; + gpibinfoPtr gpib; /* device handle */ + DWORD lasterrtime; //!< timer for error handling + INT errorcount; //!< error counter +} LANGPIB_INFO; + +#define IO_TIMEOUT 10000 + +/*----------------------------------------------------------------------------*/ +INT langpib_lock(LANGPIB_INFO * , int ); +INT langpib_unlock(LANGPIB_INFO * ); +/*----------------------------------------------------------------------------*/ + +void langpib_debug(LANGPIB_INFO * info, char *dbg_str) +{ + FILE *f; + int delta; + + if (debug_last == 0) + delta = 0; + else + delta = ss_millitime() - debug_last; + debug_last = ss_millitime(); + + f = fopen("langpib.log", "a"); + + if (debug_first) + fprintf(f, "\n==== new session =============\n\n"); + debug_first = FALSE; + if (dbg_str != NULL) { + fprintf(f, "{%d} %s\n", delta, dbg_str); + + if ((info != NULL) && (info->settings.debug > 1)) + printf("{%d} %s\n", delta, dbg_str); + } + fclose(f); +} + +/*------------------------------------------------------------------*/ +int langpib_reset_errorcount(LANGPIB_INFO *info) +{ + if ( info != NULL) { + DWORD nowtime, difftime; + + nowtime = ss_time(); + if (nowtime > info->lasterrtime) { + difftime = nowtime - info->lasterrtime; + if (difftime > DELTA_TIME_ERROR) { + info->errorcount = 0; + info->lasterrtime = nowtime; + } + } + } + return CM_SUCCESS; +} +/*------------------------------------------------------------------*/ + +gpibinfoPtr langpib_open(char *server, int address, int rpctmo) +{ + gpibinfoPtr lgpib; + char addr[20]; + + lgpib = NULL; + if ((server != NULL) && (strlen(server) > 0)) { + sprintf(addr, "%d", address); + /* + * hpib = LAN/GPIB symbolic name + * -1 = no secondary address + * 0 = no device locking + * 120000 = set large IO timeout (2min) to get a large RPC timeout + * NOTE: make sure (lock timeout + IO timeout) < RPC timeout + * when executing RPC call to LAN/GPIB device! + */ + + if (rpctmo < 120000) + rpctmo = 120000; + + lgpib = gpib_init(server, "hpib", addr, "-1", 0, rpctmo); + if (lgpib == NULL) { + cm_msg(MERROR, "langpib_open", "ERROR opening connection to LAN/GPIB"); + cm_msg_flush_buffer(); + } else { + gpib_iotimeout(lgpib, IO_TIMEOUT, NULL); /* set IO timeout now */ + } + } + return lgpib; +} + +/*----------------------------------------------------------------------------*/ + +int langpib_exit(LANGPIB_INFO * info) +{ + if ((info != NULL) && (info->gpib != NULL)) { + + if (info->gpib->locked > 0) + gpib_reset_lock(info->gpib); + + if (!gpib_close(&info->gpib)) { + cm_msg(MERROR, "langpib_exit", "ERROR closing connection to LAN/GPIB"); + cm_msg_flush_buffer(); + } + info->gpib = NULL; + } + + if (info != NULL) + free(info); /* RA35 05-NOV-2004 */ + + return CM_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +int langpib_write(LANGPIB_INFO * info, char *data, int size) +{ + int i; + + if (info != NULL) { + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "write: "); + for (i = 0; (int) i < MIN(size, (sizeof(dbg_str) - 8) / 3 - 1); i++) + sprintf(dbg_str + strlen(dbg_str), "%X ", data[i]); + + langpib_debug(info, dbg_str); + } + + i = -1; + + if (info->gpib != NULL) { + char *string; + + string = (char *) malloc(size + 1); + if (string != NULL) { + long retval; + + strncpy(string, data, size); /* copy string */ + *(string + size) = '\0'; /* add string terminator */ + + retval = gpib_send(info->gpib, info->settings.locktmo, string); + + /* is there an error? */ + if (retval < 0) { + char errorstr[40]; + + if (info->errorcount < 5) { + cm_msg(MERROR, "langpib_write", "gpib_send to server returned \"%s\"", + gpib_error(-retval, errorstr)); + cm_msg_flush_buffer(); + } + info->errorcount++; + + if (retval == -VXI_IOTIMEOUT) i = 0; /* RA36 27-JAN-2006 */ + } else + i = strlen(string);/*number of characters sent = occurence of first '\0'*/ + + free(string); + + } else { + cm_msg(MERROR, "langpib_write", "Not able to allocate string"); + cm_msg_flush_buffer(); + } + } + } else + i = -1; + + return i; +} + +/*----------------------------------------------------------------------------*/ + +int langpib_read(LANGPIB_INFO * info, char *data, int size, int millisec) +{ + + int n; + + n = -1; + + if ((data != NULL) && (size > 0)) + memset(data, 0, size); + + if ((info != NULL) && (data != NULL) && (size > 0)) { + u_long ms, mso; + u_int sz; + long retval; + + langpib_reset_errorcount(info); + + if (millisec <= 0) { + mso = info->gpib->iotimeoutms; /* save previous value */ + info->gpib->iotimeoutms = 0; /* set value directly as 0 is special and + <0 not allowed */ + } else { + ms = (u_long) millisec; + gpib_iotimeout(info->gpib, ms, &mso); /* set IO timeout */ + } + + sz = (u_int) size; + /* + * NOTE: buffer is read out until EOI mark, buffer size reached or timeout occurs. + * if buffer size is reached additional readout will be discarded (flag = TRUE)! + * NOTE: timeout is not waited for, if a message is available and EndOfInformation + * mark is returned. + */ + retval = gpib_enter(info->gpib, info->settings.locktmo, data, &sz, TRUE); + + gpib_iotimeout(info->gpib, mso, NULL); /* reset IO timeout */ + + if (retval > 0) { + if (size > sz) /* if size==sz data WITHOUT string terminator! */ + *(data + sz) = '\0'; + + n = (int) sz; /* return number of characters */ + } else if (retval == 0) + n = -1; + else if (retval < 0) { + if (retval == -VXI_IOTIMEOUT) + n = 0; /* return 0= IO TIMEOUT */ + else + n = -1; /* return error */ + } + + if (info->settings.debug) { + int i; + char dbg_str[256]; + + sprintf(dbg_str, "read: "); + + if (n == 0) + sprintf(dbg_str + strlen(dbg_str), ""); + else +#ifdef BITOUT + for (i = 0; i < MIN(n, (sizeof(dbg_str) - 7) / 3 - 1); i++) + sprintf(dbg_str + strlen(dbg_str), "%X ", data[i]); +#else + sprintf(dbg_str + strlen(dbg_str), "%*s", MIN(n, ((INT)sizeof(dbg_str) - 8)), + data); +#endif + langpib_debug(info, dbg_str); + } + } else + n = -1; + + return n; +} + +/*----------------------------------------------------------------------------*/ +int langpib_writeread(LANGPIB_INFO * info, char *str, int size, char *str1, INT size1, + INT timeout) +{ + int n; + + n = -1; + + if (langpib_lock(info, 0) == CM_SUCCESS) { + if (langpib_write(info, str, size) >= 0) { + n = langpib_read(info, str1, size1, timeout); + } else { + if (info->errorcount < 5) { + cm_msg(MERROR, "langpib_writeread","Not able to write to GPIB device %d on %s", + info->settings.address, info->settings.server); + cm_msg_flush_buffer(); + } + info->errorcount++; + } + langpib_unlock(info); + } else { + if (info->errorcount < 3) { + cm_msg(MERROR, "langpib_writeread", "Not able to lock GPIB device %d on %s", + info->settings.address, info->settings.server); + cm_msg_flush_buffer(); + } + info->errorcount++; + } + return n; +} + +/*----------------------------------------------------------------------------*/ + +int langpib_puts(LANGPIB_INFO * info, char *str) +{ + int i; + + if (info != NULL) { + + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "puts: %*s", (INT) MIN(strlen(str), sizeof(dbg_str) - 8), str); + langpib_debug(info, dbg_str); + } + + i = -1; + + if (info->gpib != NULL) { + long retval; + + retval = gpib_send(info->gpib, info->settings.locktmo, str); + + /* is there an error? */ + if (retval < 0) { + char errorstr[40]; + + if (info->errorcount < 5) { + cm_msg(MERROR, "langpib_puts", "gpib_send %d to server %s returned \"%s\"", + info->settings.address,info->settings.server, + gpib_error(-retval, errorstr)); + cm_msg_flush_buffer(); + } + info->errorcount++; + + if (retval == -VXI_IOTIMEOUT) i = 0; /* RA36 27-JAN-2006 */ + + } else + i = strlen(str); + } + } else + i = -1; + + return i; +} + +/*----------------------------------------------------------------------------*/ + +int langpib_gets(LANGPIB_INFO * info, char *data, int size, char *pattern, int millisec) +{ + fd_set readfds; + struct timeval timeout; + int i, status, n; + + n = 0; + + if ((data != NULL) && (size > 0)) + memset(data, 0, size); + + if ((info != NULL) && (data != NULL) && (size > 0)) { + u_long ms, mso; + u_int sz; + long retval; + + langpib_reset_errorcount(info); + + if (millisec <= 0) { + mso = info->gpib->iotimeoutms; /* save previous value */ + info->gpib->iotimeoutms = 0; /* set value directly as 0 is special and <0 not allowed */ + } else { + ms = (u_long) millisec; + gpib_iotimeout(info->gpib, ms, &mso); /* set IO timeout */ + } + + sz = (u_int) size; + /* + * NOTE: buffer is read out until EOI mark, buffer size reached or timeout occurs. + * if buffer size is reached additional readout will be discarded (flag = TRUE)! + * NOTE: timeout is not waited for, if a message is available and EndOfInformation + * mark is returned. + */ + retval = gpib_enter(info->gpib, info->settings.locktmo, data, &sz, TRUE); + + gpib_iotimeout(info->gpib, mso, NULL); /* reset IO timeout */ + + if (retval > 0) { + /* discard rest of buffer after pattern is read */ + if (pattern && pattern[0]) { + char *str; + if ((str = strstr(data, pattern)) != NULL) { + str += strlen(pattern); + *str = '\0'; + sz = (str - data) / sizeof(char *); + } + } + + if (size > sz) /* if size==sz data WITHOUT string terminator! */ + *(data + sz) = '\0'; + + n = (int) sz; /* return number of characters */ + } else if (retval == 0) + n = -1; + else if (retval < 0) { + if (retval == -VXI_IOTIMEOUT) + n = 0; /* return 0= IO TIMEOUT */ + else + n = -1; /* return error */ + } + + } + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "gets [%*s]: ", (INT) MIN(strlen(pattern), sizeof(dbg_str) - 10), + pattern); + + if (data[0] == 0) { + if (strlen(dbg_str) < sizeof(dbg_str) - 10) + sprintf(dbg_str + strlen(dbg_str), ""); + } else { + if (strlen(dbg_str) < (sizeof(dbg_str) - 1)) + sprintf(dbg_str + strlen(dbg_str), "%*s", + (INT)MIN(sizeof(dbg_str) - 1 - strlen(dbg_str), strlen(data)), data); + } + langpib_debug(info, dbg_str); + } + + return n; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_lock(LANGPIB_INFO * info, int tmo) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + if (tmo == 0) + tmo = info->settings.locktmo; + if (gpib_lock(info->gpib, -tmo)) /* RA35 15-SEP-2004 WAIT for lock */ + ret = CM_SUCCESS; + else { + if (info->errorcount < 3) { + cm_msg(MERROR, "langpib_lock", "Not able to lock device %d on %s", + info->settings.address, info->settings.server); + cm_msg_flush_buffer(); + } + info->errorcount++; + + ret = SS_IO_ERROR; + } + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_lock_tmo(LANGPIB_INFO * info) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + ret = info->settings.locktmo; + } else + ret = 30000; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_unlock(LANGPIB_INFO * info) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + if (gpib_unlock(info->gpib)) + ret = CM_SUCCESS; + else + ret = SS_IO_ERROR; + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_resetlock(LANGPIB_INFO * info) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + if (gpib_reset_lock(info->gpib)) + ret = CM_SUCCESS; + else + ret = SS_IO_ERROR; + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_flush(LANGPIB_INFO * info, INT timeout) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + INT ltmo; + if (info->gpib->locked > 0) + ltmo = 0; + else + ltmo = info->settings.locktmo; + + if (gpib_flush(info->gpib, ltmo, timeout)) { + + gpib_wait(info->gpib, 100); /* wait 100 ms after IO timeout + * to be sure device is ready */ + ret = CM_SUCCESS; + } else + ret = SS_IO_ERROR; + + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_ren(LANGPIB_INFO * info, INT flag) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + INT ltmo; + if (info->gpib->locked > 0) + ltmo = 0; + else + ltmo = info->settings.locktmo; + + if (gpib_ren(info->gpib, ltmo, flag)) { + + gpib_wait(info->gpib, 100); /* wait 100 ms after IO timeout + * to be sure device is ready */ + ret = CM_SUCCESS; + } else + ret = SS_IO_ERROR; + + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_gotolocal(LANGPIB_INFO * info) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + INT ltmo; + if (info->gpib->locked > 0) + ltmo = 0; + else + ltmo = info->settings.locktmo; + // 20-MAR-06 changed from -ltmo to +ltmo to avoid problems with already locked device + if (gpib_device_local(info->gpib, ltmo)) { + ret = CM_SUCCESS; + } else + ret = SS_IO_ERROR; + + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_reconnect(LANGPIB_INFO * info, INT waitms) +{ + INT ret; + + if (info != NULL) { + INT locked; + + locked = 0; + if (info->gpib != NULL) { + /* remember number of locks, then reset lock */ + if ((locked = info->gpib->locked) > 0) + gpib_reset_lock(info->gpib); + + if (!gpib_close(&info->gpib)) { + cm_msg(MERROR, "langpib_reconnect", "ERROR closing connection to LAN/GPIB"); + cm_msg_flush_buffer(); + } + info->gpib = NULL; + } + + if (waitms > 0) + ss_sleep(waitms); /* wait some time before reconnect */ + + /* open LAN/GPIB connection */ + info->gpib = langpib_open(info->settings.server, info->settings.address, + info->settings.locktmo + IO_TIMEOUT); + + if (info->gpib != NULL) { + INT i; + + /* get as many locks as there were */ + for (i = 0; i < locked; i++) { + if (!gpib_lock(info->gpib, info->settings.locktmo)) + break; + } + + cm_msg(MLOG, "langpib_reconnect", "Reconnected to LAN/GPIB device"); + cm_msg_flush_buffer(); + + info->errorcount = 0; + info->lasterrtime = ss_time(); + + ret = CM_SUCCESS; + } else { + cm_msg(MERROR, "langpib_reconnect", "Failed to reconnect to LAN/GPIB!"); + cm_msg_flush_buffer(); + ret = SS_IO_ERROR; + } + + } else + ret = SS_INVALID_HANDLE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +INT langpib_stb(LANGPIB_INFO * info, INT *pstb) +{ + INT ret; + + if ((info != NULL) && (info->gpib != NULL)) { + INT ltmo; + unsigned char stb; + + if (info->gpib->locked > 0) + ltmo = 0; + else + ltmo = info->settings.locktmo; + + stb = 0; + if (gpib_status(info->gpib, ltmo, &stb)) { + + if (pstb) *pstb = stb; // return status byte + + ret = CM_SUCCESS; + } else + ret = SS_IO_ERROR; + + } else + ret = SS_INVALID_HANDLE; + + return ret; +} +/*----------------------------------------------------------------------------*/ +int langpib_init(HNDLE hkey, void **pinfo) +{ + HNDLE hDB, hkeybd; + INT size, status; + LANGPIB_INFO *info; + + /* allocate info structure */ + info = calloc(1, sizeof(LANGPIB_INFO)); + *pinfo = info; + + info->lasterrtime = ss_time(); + + cm_get_experiment_database(&hDB, NULL); + + /* create LANGPIB settings record */ + status = db_create_record(hDB, hkey, "BD", LANGPIB_SETTINGS_STR); + if (status != DB_SUCCESS) + return FE_ERR_ODB; + + db_find_key(hDB, hkey, "BD", &hkeybd); + size = sizeof(info->settings); + db_get_record(hDB, hkeybd, &info->settings, &size, 0); + + /* open langpib connection */ +#ifdef MIDEBUG + cm_msg(MLOG, "", + "langpib_init : opening connection to %s, GPIB address = %d, RPC timeout = %d", + info->settings.server, info->settings.address, + info->settings.locktmo + IO_TIMEOUT); + cm_msg_flush_buffer(); +#endif + info->gpib = langpib_open(info->settings.server, info->settings.address, + info->settings.locktmo + IO_TIMEOUT); + if (info->gpib == NULL) + return FE_ERR_HW; + + return CM_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +INT langpib(INT cmd, ...) +{ + va_list argptr; + HNDLE hkey; + INT status, size, size1, timeout, waitms, flag, *pstb; + void *info; + char *str, *str1, *pattern; + + va_start(argptr, cmd); + status = FE_SUCCESS; + +#ifdef MIDEBUG + cm_msg(MLOG, "", "langpib(CMD=%d)", cmd); +#endif + + switch (cmd) { + case CMD_INIT: + hkey = va_arg(argptr, HNDLE); + info = va_arg(argptr, void *); + status = langpib_init(hkey, info); + break; + + case CMD_EXIT: + info = va_arg(argptr, void *); + status = langpib_exit(info); + break; + + case CMD_NAME: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + strcpy(str, "langpib"); + break; + + case CMD_WRITE: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, int); + status = langpib_write(info, str, size); + break; + + case CMD_WRITEREAD: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, int); + str1 = va_arg(argptr, char *); + size1 = va_arg(argptr, INT); + timeout = va_arg(argptr, INT); + status = langpib_writeread(info, str, size, str1, size1, timeout); + break; + + case CMD_READ: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, INT); + timeout = va_arg(argptr, INT); + status = langpib_read(info, str, size, timeout); + break; + + case CMD_PUTS: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + status = langpib_puts(info, str); + break; + + case CMD_GETS: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, INT); + pattern = va_arg(argptr, char *); + timeout = va_arg(argptr, INT); + status = langpib_gets(info, str, size, pattern, timeout); + break; + + case CMD_LOCK: + info = va_arg(argptr, void *); + timeout = va_arg(argptr, INT); + status = langpib_lock(info, timeout); + break; + + case CMD_LOCK_TMO: + info = va_arg(argptr, void *); + status = langpib_lock_tmo(info); + break; + + case CMD_UNLOCK: + info = va_arg(argptr, void *); + status = langpib_unlock(info); + break; + + case CMD_RESETLOCK: + info = va_arg(argptr, void *); + status = langpib_resetlock(info); + break; + + case CMD_FLUSH: + info = va_arg(argptr, void *); + timeout = va_arg(argptr, INT); + status = langpib_flush(info, timeout); + break; + + case CMD_REN: + info = va_arg(argptr, void *); + flag = va_arg(argptr, INT); + status = langpib_ren(info, flag); + break; + + case CMD_GOTOLOCAL: + info = va_arg(argptr, void *); + status = langpib_gotolocal(info); + break; + + case CMD_RECONNECT: + info = va_arg(argptr, void *); + waitms = va_arg(argptr, INT); + status = langpib_reconnect(info, waitms); + break; + + case CMD_STB: + info = va_arg(argptr, void *); + pstb = va_arg(argptr, INT *); + status = langpib_stb(info, pstb); + break; + + case CMD_DEBUG: + info = va_arg(argptr, void *); + status = va_arg(argptr, INT); + ((LANGPIB_INFO *) info)->settings.debug = status; + break; + } + + va_end(argptr); + + return status; +} diff --git a/bus/langpib.h b/bus/langpib.h new file mode 100644 index 0000000..89f3790 --- /dev/null +++ b/bus/langpib.h @@ -0,0 +1,54 @@ +/********************************************************************\ + + Name: langpib.h + Created by: RA35 + + Contents: Header file for "normal" lan/gpib bus driver + + Revision 1.1 2017/01/24 15:39:53 raselli + Original Midas 1.9.5 version + + Revision 1.8 2016/09/09 13:11:51 raselli + Bulk musr 09-SEP-2016 + + Revision 1.1 2001/02/26 13:58:06 midas + Added files + +\********************************************************************/ + +#define CMD_WRITEREAD 200 +#define CMD_LOCK 201 +#define CMD_UNLOCK 202 +#define CMD_RESETLOCK 203 +#define CMD_FLUSH 204 +#define CMD_LOCK_TMO 205 +#define CMD_RECONNECT 206 +#define CMD_GOTOLOCAL 207 +#define CMD_REN 208 +#define CMD_STB 209 + +#ifdef BD_READS +#undef BD_READS // there is a bug in midas.h +#endif + +// redefine macro +#define BD_READS(s,z,t) info->bd(CMD_READ, info->bd_info, s, z, t) + +#define BD_WRITEREAD(s,z,s1,z1,t) info->bd(CMD_WRITEREAD, info->bd_info, s, z, s1, z1, t) + +#define BD_LOCK(t) info->bd(CMD_LOCK, info->bd_info, t) +#define BD_UNLOCK() info->bd(CMD_UNLOCK, info->bd_info) +#define BD_RESETLOCK(s) info->bd(CMD_RESETLOCK, info->bd_info) +#define BD_LOCK_TMO() info->bd(CMD_LOCK_TMO, info->bd_info) + +#define BD_FLUSH(t) info->bd(CMD_FLUSH, info->bd_info, t) + +#define BD_RECONNECT(t) info->bd(CMD_RECONNECT, info->bd_info, t) + +#define BD_GOTOLOCAL() info->bd(CMD_GOTOLOCAL, info->bd_info) + +#define BD_REN(f) info->bd(CMD_REN, info->bd_info, f) + +#define BD_STB(s) info->bd(CMD_STB, info->bd_info, s) + +INT langpib(INT cmd, ...); diff --git a/bus/tcpip.c b/bus/tcpip.c new file mode 100644 index 0000000..44bc293 --- /dev/null +++ b/bus/tcpip.c @@ -0,0 +1,1407 @@ +/* 1 2 3 4 5 6 7 8 89 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567*/ +/********************************************************************\ + + Name: tcpip.c + Created by: Stefan Ritt + + Contents: TCP/IP socket communication routines + + Revision 1.2 2017/02/13 14:48:57 raselli + Adding additional functionality when TCPIP_RECONNECT is called before tcpip.h + + Revision 1.1 2017/01/24 15:42:47 raselli + Midas 1.9.5 version adapted to Midas 2.1 (tcpip_open is now tcpip_connect) + + + Modification history + -------------------- + 21-APR-2015 RA36 Added TCP_NODELAY and TCP_QUICKACK as option flags + 04-MAY-2015 RA36 Some cm_msg's are now only called when verbose + 13-NOV-2015 RA36 Code modified to avoid crashes when info->fd == -1 + 24-JAN-2017 RA36 Adapted to Midas 2.1 + +\********************************************************************/ + +#include "midas.h" +#include "msystem.h" + +/*#define MIDEBUG // */ +/*#define MIDEBUG1 // */ + +#define DELTA_TIME_ERROR 3600 /*!< reset error counter after DELTA_TIME_ERROR seconds */ + +static int debug_last = 0; +static int debug_first = TRUE; + +#ifndef _TCPIP_PRIVATE_H_ + +typedef struct { + char host[256]; + int port; + int debug; +} TCPIP_SETTINGS; + +typedef struct { + TCPIP_SETTINGS settings; + int fd; /* device handle for socket device */ +} TCPIP_INFO; + +int tcpip_connect(char *host, int port); + +int tcpip_open(TCPIP_INFO * info); +int tcpip_close(TCPIP_INFO * info); + +int tcpip_fd_get(TCPIP_INFO * info); + +#endif /* #ifndef _TCPIP_PRIVATE_H_ */ + +/*----------------------------------------------------------------------------*/ + +#define TCPIP_SETTINGS_STR "\ +Host = STRING : [256] myhost.my.domain\n\ +Port = INT : 23\n\ +Debug = INT : 0\n\ +" + +/*----------------------------------------------------------------------------*/ + +#ifdef OS_WINNT +static char gstr[MAX_STRING_LENGTH]; +char *tcpip_error_message(int, char *); +#endif + +static INT errorcount; +static DWORD lasterrtime; + +extern INT verbose; + +/*----------------------------------------------------------------------------*/ +void tcpip_debug(TCPIP_INFO * info, char *dbg_str) +{ + FILE *f; + int delta; + char fn[50]; + + if (debug_last == 0) + delta = 0; + else + delta = ss_millitime() - debug_last; + + debug_last = ss_millitime(); + + snprintf(fn,49,"tcpip_%s_%d.log",info->settings.host,info->settings.port); + if ((f = fopen(fn, "a"))) { + + if (debug_first) { + cm_msg(MERROR,"tcpip","tcpip bus driver: Communication is logged to %s",fn); + cm_msg_flush_buffer(); + fprintf(f, "\n==== new session =============\n\n"); + debug_first = FALSE; + } + fprintf(f, "{%d} %s\n", delta, dbg_str); + + if (info->settings.debug > 1) + printf("{%d} %s\n", delta, dbg_str); + + fclose(f); + } +} + +/*------------------------------------------------------------------*/ + +static int connect_error; + +int tcpip_connect(char *host, int port) +{ + struct sockaddr_in bind_addr; + struct hostent *phe; + int status, fd; + +#ifdef OS_WINNT + { + WSADATA WSAData; + + /* Start windows sockets */ + if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0) { + if (!connect_error++) { + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : WSAStartup() != 0", host, port); + cm_msg_flush_buffer(); + } + return RPC_NET_ERROR; + } + } +#endif + + /* create a new socket for connecting to remote server */ + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + if (!connect_error++) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : socket() %s", host, port, + tcpip_error_message(WSAGetLastError(), gstr)); +#else + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : socket() %d %s", host, port, + errno, strerror(errno)); +#endif + cm_msg_flush_buffer(); + } + return fd; + } + + /* let OS choose any port number */ + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_addr.s_addr = 0; + bind_addr.sin_port = 0; + + status = bind(fd, (void *) &bind_addr, sizeof(bind_addr)); + if (status < 0) { + if (!connect_error++) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : bind() %s", host, port, + tcpip_error_message(WSAGetLastError(), gstr)); +#else + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : bind() %d %s", host, port, + errno, strerror(errno)); +#endif + cm_msg_flush_buffer(); + } + return -1; + } + + /* connect to remote node */ + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_addr.s_addr = 0; + bind_addr.sin_port = htons((short) port); + +#ifdef OS_VXWORKS + { + INT host_addr; + + host_addr = hostGetByName(host); + memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4); + } +#else + phe = gethostbyname(host); + if (phe == NULL) { + if (!connect_error++) { + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : unknown host name %s", host,port,host); + cm_msg_flush_buffer(); + } + closesocket(fd); +#ifdef OS_WINNT + WSACleanup(); +#endif + return -1; + } + memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length); +#endif + +#ifdef OS_UNIX + do { + status = connect(fd, (void *) &bind_addr, sizeof(bind_addr)); + + /* don't return if an alarm signal was cought */ + } while (status == -1 && errno == EINTR); +#else + status = connect(fd, (void *) &bind_addr, sizeof(bind_addr)); +#endif + + if (status != 0) { + if (!connect_error++) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : connect() %s", host, port, + tcpip_error_message(WSAGetLastError(), gstr)); +#else + cm_msg(MLOG, "", "tcpip_connect(%s,%d) : connect() %d %s", host, port, + errno, strerror(errno)); +#endif + cm_msg_flush_buffer(); + } + closesocket(fd); /* RA36 14-JUN-2011 */ +#ifdef OS_WINNT + WSACleanup(); /* RA36 14-JUN-2011 */ +#endif + return -1; + } else { + int result, flag; + socklen_t size; + + connect_error = 0; + flag = 0; size = sizeof(flag); + result = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, &size); + /*cm_msg(MLOG,"","getsockopt() result = %d, flag = %d, flag size is %d", + * result,flag,size); */ + if ((result==0) && (size > 0)) { + if (flag != 1) { + /* cm_msg(MLOG,"","TCP_NODELAY is %d",flag); */ + flag = 1; size = sizeof(flag); + result = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, size); + if (result == -1) { + cm_msg(MLOG,"","TCP_NODELAY: setsockopt() result = %d, errno = %d", + result, errno); + cm_msg_flush_buffer(); + } + flag = 0; size = sizeof(flag); + result = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, &size); + } + if (verbose && (result == 0)) { + cm_msg(MLOG,"","tcpip_connect: TCP_NODELAY is %d",flag); + cm_msg_flush_buffer(); + } + } + + flag = 0; size = sizeof(flag); + result = getsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &flag, &size); + if ((result==0) && (size > 0)) { + if (flag != 1) { + /* cm_msg(MLOG,"","TCP_QUICKACK is %d",flag); */ + flag = 1; size = sizeof(flag); + result = setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &flag, size); + if (result == -1) { + cm_msg(MLOG,"","TCP_QUICKACK: setsockopt() result = %d, errno = %d", + result, errno); + cm_msg_flush_buffer(); + } + flag = 0; size = sizeof(flag); + result = getsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &flag, &size); + } + if (verbose && (result == 0)) { + cm_msg(MLOG,"","tcpip_connect: TCP_QUICKACK is %d",flag); + cm_msg_flush_buffer(); + } + } + } + + return fd; +} + +/*----------------------------------------------------------------------------*/ + +int tcpip_exit(TCPIP_INFO * info) +{ + if (info && (info->fd != -1)) { + shutdown(info->fd, 2); /* RA35 13-SEP-2004 */ + closesocket(info->fd); + } +#ifdef OS_WINNT + WSACleanup(); +#endif + + if (info != NULL) + free(info); /* RA95 05-NOV-2004 */ + + return SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +int tcpip_open(TCPIP_INFO * info) +{ + if (!info) { + return FE_ERR_HW; + } else { + if (info->fd >= 0) { + cm_msg(MLOG, "", "tcpip_open() : connected (descr=%d) before calling " + "tcpip_connect(%s,%d)?", info->fd, + info->settings.host, info->settings.port); + cm_msg_flush_buffer(); + } + info->fd = tcpip_connect(info->settings.host, info->settings.port); + if (info->fd < 0) + return FE_ERR_HW; + if (verbose) { + cm_msg(MLOG, "", "tcpip_open() : tcpip_connect(%s,%d) returned descriptor %d", + info->settings.host, info->settings.port, info->fd); + cm_msg_flush_buffer(); + } + } + return SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +int tcpip_close(TCPIP_INFO * info) +{ + if (info && (info->fd != -1)) { + shutdown(info->fd, 2); + closesocket(info->fd); + info->fd = -1; + } + + return SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +/* return fd or when closed -1 */ +int tcpip_fd_get(TCPIP_INFO * info) +{ + int fd; + + if (info) + fd = info->fd; + else + fd = -1; + + return fd; +} + +/*----------------------------------------------------------------------------*/ +int tcpip_handle_error(TCPIP_INFO * info, int error_number) { + + if (info) { + /* socket connection ok until this error occured? */ + if (info->fd != -1) { +#ifdef OS_WINNT + /* + * WSAECONNRESET 10054 Connection reset by peer. + */ + if (error_number == 10054) info->fd = -1; /* invalidate socket connection + * without shutdown and closesocket */ +#else + /* + * /usr/src/kernels/2.6.18-53.1.4.el5-i686/include/asm-generic/errno.h + + * ENETDOWN 100 Network is down + * ENETUNREACH 101 Network is unreachable + * ENETRESET 102 Network dropped connection because of reset + * ECONNABORTED 103 Software caused connection abort + * ECONNRESET 104 Connection reset by peer + * ENOBUFS 105 No buffer space available + * EISCONN 106 Transport endpoint is already connected + * ENOTCONN 107 Transport endpoint is not connected + * ESHUTDOWN 108 Cannot send after transport endpoint shutdown + * ETOOMANYREFS 109 Too many references: cannot splice + * ETIMEDOUT 110 Connection timed out + * ECONNREFUSED 111 Connection refused + * EHOSTDOWN 112 Host is down + * EHOSTUNREACH 113 No route to host + */ + if ((error_number >= 100) && (error_number <= 113)) + info->fd = -1; /* invalidate socket connection + * without shutdown and closesocket */ +#endif + /* invalidated socket connection? */ + if (info->fd == -1) { + /* try to reopen port */ + info->fd = tcpip_connect(info->settings.host, info->settings.port); + if (info->fd != -1) { + cm_msg(MLOG,"","tcpip: Reopened broken connection (%s,%d)", + info->settings.host, info->settings.port); + cm_msg_flush_buffer(); + } + } + } + return info->fd; + } else { + return -1; + } +} +/*----------------------------------------------------------------------------*/ +/* send size number of char type data (data may include string terminators) */ +int tcpip_write(TCPIP_INFO * info, char *data, int size) +{ + int i,sent; +#ifdef MIDEBUG1 + cm_msg(MLOG,"","tcpip_write(%s,%d): %s",info->settings.host,info->settings.port,data); +#endif + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "write(HEX): "); + for (i = 0; (int) i < MIN(size,255/2); i++) + sprintf(dbg_str + strlen(dbg_str), "%2.2X ", (unsigned char)data[i]); + + tcpip_debug(info, dbg_str); + } + + if (info->fd != -1) { + sent = 0; + + do { + +#ifdef OS_UNIX + do { +#endif + i = send(info->fd, data+sent, size-sent, 0); + +#ifdef OS_UNIX + } while (i == -1 && errno == EINTR); +#endif + if (i != -1) sent += i; + + } while ((i != -1) && (sent < size)); + + if (i < 0) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_write(%s,%d) : send() %s", info->settings.host, + info->settings.port, tcpip_error_message(WSAGetLastError(), gstr)); + tcpip_handle_error( info, WSAGetLastError()); +#else + cm_msg(MLOG, "", "tcpip_write(%s,%d) : send() %d %s", info->settings.host, + info->settings.port, errno, strerror(errno)); + tcpip_handle_error( info, errno); +#endif + cm_msg_flush_buffer(); + } + } else + i = -1; + + return i; +} + +/*----------------------------------------------------------------------------*/ +/* receive a maximum of size char data, timeout after millisec (>0) no new char received + * size < 0 is used to flag not to write msg about buffer too small + * NOTE: if millisec is low, timeout may be due to network communication and not because + * no characters are transmitted from the instrument anymore! + * Therefore use the tcpip_gets() function below with a large wait interval before + * timeout and stops waiting and reading when the terminating pattern is received + * + * returned: + * > 0 number of characters read and returned + * == 0 timeout without reading anything + * < 0 -1 when not connected (fd == -1) from the beginning + * + */ +int tcpip_read(TCPIP_INFO * info, char *data, int size, int millisec) +{ + fd_set readfds; + struct timeval timeout; + int i, status, n, writemsg; + DWORD start, elapsed; + + if (size < 0) { + writemsg = 0; + size = -size; + } else + writemsg = 1; + + n = 0; + memset(data, 0, size); + + do { + if ((millisec > 0) && (info->fd != -1)){ /* RA36 12-NOV-2015 */ + FD_ZERO(&readfds); + FD_SET(info->fd, &readfds); + + start = ss_millitime(); + elapsed = 0; + +#ifdef OS_UNIX + do { +#endif + if (elapsed > millisec) elapsed = millisec; + timeout.tv_sec = (millisec-elapsed) / 1000; + timeout.tv_usec = ((millisec-elapsed) % 1000) * 1000; + + status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *)&timeout); + + /* if an alarm signal was cought, restart select with reduced timeout */ + elapsed = ss_millitime(); + if (elapsed > start) elapsed -= start; else elapsed = 0; + +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (status == -1 && errno == EINTR); +#endif + if (status == -1) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_read(%s,%d): select() %s, timeout = %d, elapsed " + "time = %d", info->settings.host, info->settings.port, + tcpip_error_message(WSAGetLastError(), gstr),millisec,elapsed); +#else + cm_msg(MLOG, "", "tcpip_read(%s,%d) : select() %d %s, timeout = %d, elapsed " + "time = %d", info->settings.host, info->settings.port, + errno, strerror(errno), millisec,elapsed); +#endif + cm_msg_flush_buffer(); + break; + } + + if ((info->fd == -1) || !FD_ISSET(info->fd, &readfds)) { /* RA36 13-NOV-2015 */ +#ifdef MIDEBUG +/* cm_msg(MLOG, "", "tcpip_read(%s,%d) : TIMEOUT : timeout = %d msec, elapsed " + * "time = %d msec", info->settings.host, + * info->settings.port, millisec, elapsed); + */ +#endif + break; + } + } + + if (info->fd != -1) { +#ifdef OS_UNIX + do { +#endif + i = recv(info->fd, data + n, 1, 0); +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (i == -1 && errno == EINTR); +#endif + if ((info->fd != -1) && (i < 0)) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_read(%s,%d) : recv() %s", info->settings.host, + info->settings.port, tcpip_error_message(WSAGetLastError(), gstr)); + tcpip_handle_error( info, WSAGetLastError()); +#else + cm_msg(MLOG, "", "tcpip_read(%s,%d) : recv() %d %s", info->settings.host, + info->settings.port, errno, strerror(errno)); + tcpip_handle_error( info, errno); +#endif + cm_msg_flush_buffer(); + } + } else + i = -1; + + if (i <= 0) + break; + + n++; + + if (n >= size) { + if (writemsg) { + cm_msg(MLOG, "", "tcpip_read(%s,%d) : Received data might be larger than " + "buffer size (%d)", info->settings.host, info->settings.port, size); + cm_msg_flush_buffer(); + } + break; + } + + } while (1); /* while (buffer[n-1] && buffer[n-1] != 10); */ + + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "read: "); + + if (n == 0) + sprintf(dbg_str + strlen(dbg_str), ""); + else + for (i = 0; i < n; i++) + if (strlen(dbg_str) < 246) sprintf(dbg_str + strlen(dbg_str),"%X ",data[i]); + + if (n > 0) { + sprintf(dbg_str + strlen(dbg_str),"\n = "); + for (i = 0; i < n; i++) + if (strlen(dbg_str) < 246) { + if (isprint(data[i])) + sprintf(dbg_str + strlen(dbg_str),"%c",data[i]); + else + sprintf(dbg_str + strlen(dbg_str),"<.>"); + } + } + tcpip_debug(info, dbg_str); + } + + return n; +} + +/*----------------------------------------------------------------------------*/ +/* send string (without string terminator) */ +int tcpip_puts(TCPIP_INFO * info, char *str) +{ + int i,len,sent; + + if (info->settings.debug) { + char dbg_str[256]; + + sprintf(dbg_str, "puts: %s", str); + tcpip_debug(info, dbg_str); + } + + if (info->fd != -1) { + len = strlen(str); + sent = 0; + + do { + +#ifdef OS_UNIX + do { +#endif + i = send(info->fd, str+sent, len-sent, 0); + +#ifdef OS_UNIX + } while (i == -1 && errno == EINTR); +#endif + if (i != -1) sent += i; + + } while ((i != -1) && (sent < len)); + + if (i < 0) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_puts(%s,%d) : send() %s", info->settings.host, + info->settings.port, tcpip_error_message(WSAGetLastError(), gstr)); + tcpip_handle_error( info, WSAGetLastError()); +#else + cm_msg(MLOG, "", "tcpip_puts(%s,%d) : send() %d %s", info->settings.host, + info->settings.port, errno, strerror(errno)); + tcpip_handle_error( info, errno); +#endif + cm_msg_flush_buffer(); + } + + } else + i = -1; + + return i; +} + +/*----------------------------------------------------------------------------*/ + +/* receive a maximum of size char data, stop reading when the terminating pattern is + * received or timeout after millisec (<>0) no new char received + * NOTE: if millisec is low, timeout may be due to network communication and not because + * no characters are transmitted from the instrument anymore! + * Therefore use tcpip_gets with a large wait interval waited before timeout. + * Stop reading when the terminating pattern is received and a short wait + * interval waited timed-out + * + * TCPIP_INFO *info bus driver specific information + * char *str buffer to return received string + * str should be larger than size*sizeof(char) when termination + * pattern is not always detected + * int size |size| max. size of buffer to return or max. number of chars + * expected + * NOTE: if (size < 0) do not write a message about timeout + * + * char *pattern terminating pattern + * is usually a string containing a terminating pattern or a single + * character terminated by a string terminator '\0'. pattern will + * be searched in the received string. + * if "" is specified as terminating pattern or '\0' as terminating + * character the string terminator will be taken as terminating + * character. It will be checked if the last received character is + * '\0', only. + * if pattern is found, data will be received until a 10 msec + * timeout occurs. + * Data received after pattern was found will be flushed. + * if (millisec <0) data will not be flushed. + * + * int millisec timeout when not receiving data during more than |millisec| + * NOTE: if (millisec < 0) the receive buffer will not be flushed + * after the pattern was found + * returned: + * > 0 number of characters read (before pattern was found or timeout occured) being returned + * == 0 timeout without reading anything + * < 0 -1 when not connected (fd == -1) from the beginning + * + */ +int tcpip_gets(TCPIP_INFO * info, char *str, int size, char *pattern, int millisec) +{ + fd_set readfds; + struct timeval timeout; + int i, status, n, flush, millisec1,dontflush,nomessage; + DWORD start, elapsed; + + /* error handling */ + if (ss_time() < lasterrtime) lasterrtime = 0; /* clock was reset? */ + + /* reset error count */ + if (ss_time()-lasterrtime > DELTA_TIME_ERROR) { + errorcount = 0; + lasterrtime = ss_time(); + } + + dontflush = FALSE; + nomessage = FALSE; + + /* special flag millisec < 0 -> dont flush buffer and do not write message about + * timeout to be able to read until buffer is empty */ + if (millisec < 0) { + dontflush = TRUE; + millisec *= -1; +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : Not flushing buffer info", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + } + + /* special flag size < 0 -> do not write message about timeout */ + if (size < 0) { + nomessage = TRUE; + size *= -1; +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : No timeout message", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + } + +#ifdef MIDEBUG + if (pattern) { + if (pattern[0]) { + if (strlen(pattern) > 1) + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : pattern is string %s", + info->settings.host,info->settings.port, pattern); + else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : pattern is ASCII %d", + info->settings.host,info->settings.port, *pattern); + } else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : pattern is string terminator", + info->settings.host,info->settings.port); + } else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : pattern is NULL pointer!", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + + n = 0; + memset(str, 0, size); + flush = FALSE; + + do { + if ((millisec > 0) && (info->fd != -1)) { /* RA36 12-NOV-2015 */ + FD_ZERO(&readfds); + FD_SET(info->fd, &readfds); + + start = ss_millitime(); + elapsed = 0; + +#ifdef OS_UNIX + do { +#endif + if (elapsed > millisec) elapsed = millisec; + timeout.tv_sec = (millisec-elapsed) / 1000; + timeout.tv_usec = ((millisec-elapsed) % 1000) * 1000; + + status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *)&timeout); + + /* if an alarm signal was cought, restart select with reduced timeout */ + elapsed = ss_millitime(); + if (elapsed > start) elapsed -= start; else elapsed = 0; + +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (status == -1 && errno == EINTR); +#endif + if (status == -1) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : select() %s, timeout = %d, elapsed " + "time = %d", info->settings.host, info->settings.port, + tcpip_error_message(WSAGetLastError(), gstr),millisec,elapsed); +#else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : select() %d %s, timeout = %d, elapsed " + "time = %d", info->settings.host, info->settings.port, + errno, strerror(errno), millisec,elapsed); +#endif + cm_msg_flush_buffer(); + break; + } + + if ((info->fd == -1) || !FD_ISSET(info->fd, &readfds)) { /* RA36 13-NOV-2015 */ + /* do flush and do tell about timeout or message */ + if (!dontflush && !nomessage) { + char dbg_str[256]; + + errorcount++; + if (errorcount < 50) { + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : TIMEOUT : timeout = %d msec, " + "elapsed time = %d msec", info->settings.host, + info->settings.port, millisec, (int)elapsed); + cm_msg_flush_buffer(); + } + snprintf(dbg_str, sizeof(dbg_str), "tcpip_gets(%s,%d) : TIMEOUT : timeout = %d msec, " + "elapsed time = %d msec", info->settings.host, + info->settings.port, millisec, (int)elapsed); + tcpip_debug(info, dbg_str); + } + break; + } + } + + if (info->fd != -1) { +#ifdef OS_UNIX + do { +#endif + i = recv(info->fd, str + n, 1, 0); +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (i == -1 && errno == EINTR); +#endif + if (i < 0) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : recv() %s", info->settings.host, + info->settings.port, tcpip_error_message(WSAGetLastError(), gstr)); + tcpip_handle_error( info, WSAGetLastError()); +#else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : recv() %d %s", info->settings.host, + info->settings.port, errno, strerror(errno)); + tcpip_handle_error( info, errno); +#endif + cm_msg_flush_buffer(); + } + } else + i = -1; + + if (i <= 0) + break; + + n += i; + + if (pattern) { + if (pattern[0]) { /* pattern is string */ + if (strlen(pattern) > 1) { + /* pattern is found in received string */ + if (strstr(str, pattern) != NULL) { +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : found pattern", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + if (!dontflush) flush = TRUE; + break; + } + } else { + /* *pattern is found in received string */ + if (strchr(str, *pattern) != NULL) { +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : found *pattern", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + if (!dontflush) flush = TRUE; + break; + } + + /* 2nd chance last character in received string is string terminator! + * but 0x00 contained in recv string */ + if ((n > 0) && (*(str + n - 1) == pattern[0])) { + /* printf("found %d\n",pattern[0]); */ +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : found string terminator", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + if (!dontflush) flush = TRUE; + break; + } + } + } else { /* pattern is \0 RA36 20-SEP-2005 */ + /* last character in received string is string terminator! */ + if ((n > 0) && (*(str + n - 1) == pattern[0])) { + /* printf("found %d\n",pattern[0]); */ +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : found string terminator", + info->settings.host,info->settings.port); + cm_msg_flush_buffer(); +#endif + if (!dontflush) flush = TRUE; + break; + } + } + } + + if (n >= size) { + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : Received data might be larger than " + "buffer size (%d)", info->settings.host, + info->settings.port, size); + cm_msg_flush_buffer(); + flush = TRUE; + break; + } + + } while (1); /* while (buffer[n-1] && buffer[n-1] != 10); */ + + /* flush buffer after receiving the terminating pattern */ + millisec1 = 10; + while(flush && (info->fd != -1)) { /* RA36 13-NOV-2015 */ + char dummy; + + FD_ZERO(&readfds); + FD_SET(info->fd, &readfds); + + start = ss_millitime(); + elapsed = 0; + +#ifdef OS_UNIX + do { +#endif + timeout.tv_sec = (millisec1-elapsed) / 1000; + timeout.tv_usec = ((millisec1-elapsed) % 1000) * 1000; + + status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout); + + /* if an alarm signal was cought, restart select with reduced timeout */ + elapsed = ss_millitime(); + if (elapsed > start) elapsed -= start; else elapsed = 0; + +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (status == -1 && errno == EINTR); +#endif + + if (status == -1) { +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : flush select() %s, timeout = %d, elapsed " + "time = %d", info->settings.host, info->settings.port, + tcpip_error_message(WSAGetLastError(), gstr),millisec,elapsed); +#else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : flush select() %d %s, timeout = %d, " + "elapsed time = %d", info->settings.host, + info->settings.port, errno, strerror(errno), millisec,elapsed); +#endif + cm_msg_flush_buffer(); + flush = FALSE; + break; + } + + if ((info->fd == -1) || !FD_ISSET(info->fd, &readfds)) { /* RA36 13-NOV-2015 */ +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : flush TIMEOUT : timeout = %d msec, " + "elapsed time = %d msec", info->settings.host, + info->settings.port, millisec1, elapsed); + cm_msg_flush_buffer(); +#endif + flush = FALSE; + break; + } + +#ifdef OS_UNIX + do { +#endif + if (info->fd == -1) break; /* RA36 13-NOV-2015 */ +#ifdef MIDEBUG + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : flushing", info->settings.host, + info->settings.port); + cm_msg_flush_buffer(); +#endif + i = recv(info->fd, &dummy, 1, 0); + errorcount++; + if (!nomessage && (errorcount < 50)) { + if (i > 0) { + if ((dummy > 31) && (dummy <126)) + cm_msg(MLOG,"","tcpip_gets(%s,%d) : flushed %d = >%c<",info->settings.host, + info->settings.port, dummy, dummy); + else + cm_msg(MLOG,"","tcpip_gets(%s,%d) : flushed %d", info->settings.host, + info->settings.port, dummy); + cm_msg_flush_buffer(); + } else if (i == 0) { + + cm_msg(MLOG,"","tcpip_gets(%s,%d) : recv() status = 0", + info->settings.host, info->settings.port); + cm_msg_flush_buffer(); + /* according to Visual Studio 6.0 Help + * 0 is returned when connection gracefully closed + * according to Linux man + * 0 is returned when peer performed orderly shutdown + + * we fake a Connection reset by peer error after 100 attempts + */ +#ifdef OS_WINNT + tcpip_handle_error( info, 10054); +#else + tcpip_handle_error( info, 104); +#endif + break; + +#ifdef OS_UNIX + } else if (errno != EINTR) { +#else + } else { +#endif + +#ifdef OS_WINNT + cm_msg(MLOG, "", "tcpip_gets(%s,%d): recv() %s", info->settings.host, + info->settings.port, + tcpip_error_message(WSAGetLastError(), gstr)); + tcpip_handle_error( info, WSAGetLastError()); +#else + cm_msg(MLOG, "", "tcpip_gets(%s,%d) : recv() %d %s", info->settings.host, + info->settings.port, errno, strerror(errno)); + tcpip_handle_error( info, errno); +#endif + cm_msg_flush_buffer(); + } + } +#ifdef OS_UNIX + /* dont return if an alarm signal was cought */ + } while (i == -1 && errno == EINTR); +#endif + } /* while(flush) */ + + if (info->settings.debug) { + char dbg_str[712]; + + /* sprintf(dbg_str, "gets [%s]: ", pattern); */ + if (pattern) { + if (pattern[0]) { + if (strlen(pattern) > 2) + sprintf(dbg_str, "gets [%s]: ", pattern); + else if (strlen(pattern) > 1) + sprintf(dbg_str, "gets [0x%2.2x,0x%2.2x]: ", *pattern, *(pattern+1)); + else + sprintf(dbg_str, "gets [0x%2.2x]: ", *pattern); + } else + sprintf(dbg_str, "gets [0x00]: "); + } else + sprintf(dbg_str, "gets [NULL]: "); + + if (str[0] == 0) + sprintf(dbg_str + strlen(dbg_str), ""); + else { + sprintf(dbg_str + strlen(dbg_str), "(HEX)"); + for (i = 0; i < n; i++) + if (strlen(dbg_str) < 690) { + sprintf(dbg_str + strlen(dbg_str), "%2.2X ", (unsigned char) str[i]); + } else { + sprintf(dbg_str + strlen(dbg_str), ""); + break; + } + } + if (n > 0) { + sprintf(dbg_str + strlen(dbg_str),"\n = "); + for (i = 0; i < n; i++) + if (strlen(dbg_str) < 246) { + if (isprint(str[i])) + sprintf(dbg_str + strlen(dbg_str),"%c",str[i]); + else + sprintf(dbg_str + strlen(dbg_str),"<.>"); + } + } + tcpip_debug(info, dbg_str); + } + + return n; +} + +/*----------------------------------------------------------------------------*/ + +int tcpip_init(HNDLE hkey, void **pinfo) +{ + HNDLE hDB, hkeybd; + INT size, status; + TCPIP_INFO *info; + + /* allocate info structure */ + info = calloc(1, sizeof(TCPIP_INFO)); + *pinfo = info; + + cm_get_experiment_database(&hDB, NULL); + + /* create TCPIP settings record */ + status = db_create_record(hDB, hkey, "BD", TCPIP_SETTINGS_STR); + if (status != DB_SUCCESS) + return FE_ERR_ODB; + + db_find_key(hDB, hkey, "BD", &hkeybd); + size = sizeof(info->settings); + db_get_record(hDB, hkeybd, &info->settings, &size, 0); + + /* open port */ + info->fd = tcpip_connect(info->settings.host, info->settings.port); + if (info->fd < 0) + return FE_ERR_HW; + + errorcount = 0; + lasterrtime = ss_time(); + + return SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +#ifdef OS_WINNT +char *tcpip_error_message(int err, char *str) +{ + + if (str != NULL) { + switch (err) { + + case 10004: + strcpy(str, "WSAEINTR 10004 Interrupted system call."); + break; + + case 10009: + strcpy(str, "WSAEBADF 10009 Bad file number."); + break; + + case 10013: + strcpy(str, "WSEACCES 10013 Permission denied."); + break; + + case 10014: + strcpy(str, "WSAEFAULT 10014 Bad address."); + break; + + case 10022: + strcpy(str, "WSAEINVAL 10022 Invalid argument."); + break; + + case 10024: + strcpy(str, "WSAEMFILE 10024 Too many open files."); + break; + + case 10035: + strcpy(str, "WSAEWOULDBLOCK 10035 Operation would block."); + break; + + case 10036: + strcpy(str, + "WSAEINPROGRESS 10036 Operation now in progress. This error " + "is returned if any Windows Sockets API " + "function is called while a blocking function is in progress."); + break; + + case 10037: + strcpy(str, "WSAEALREADY 10037 Operation already in progress."); + break; + + case 10038: + strcpy(str, "WSAENOTSOCK 10038 Socket operation on nonsocket."); + break; + + case 10039: + strcpy(str, "WSAEDESTADDRREQ 10039 Destination address required."); + break; + + case 10040: + strcpy(str, "WSAEMSGSIZE 10040 Message too long."); + break; + + case 10041: + strcpy(str, "WSAEPROTOTYPE 10041 Protocol wrong type for socket."); + break; + + case 10042: + strcpy(str, "WSAENOPROTOOPT 10042 Protocol not available."); + break; + + case 10043: + strcpy(str, "WSAEPROTONOSUPPORT 10043 Protocol not supported."); + break; + + case 10044: + strcpy(str, "WSAESOCKTNOSUPPORT 10044 Socket type not supported."); + break; + + case 10045: + strcpy(str, "WSAEOPNOTSUPP 10045 Operation not supported on socket."); + break; + + case 10046: + strcpy(str, "WSAEPFNOSUPPORT 10046 Protocol family not supported."); + break; + + case 10047: + strcpy(str, "WSAEAFNOSUPPORT 10047 Address family not supported by " + "protocol family."); + break; + + case 10048: + strcpy(str, "WSAEADDRINUSE 10048 Address already in use."); + break; + + case 10049: + strcpy(str, "WSAEADDRNOTAVAIL 10049 Cannot assign requested address."); + break; + + case 10050: + strcpy(str, + "WSAENETDOWN 10050 Network is down. This error may be " + "reported at any time if the Windows " + "Sockets implementation detects an underlying failure."); + break; + + case 10051: + strcpy(str, "WSAENETUNREACH 10051 Network is unreachable."); + break; + + case 10052: + strcpy(str, "WSAENETRESET 10052 Network dropped connection on " + "reset."); + break; + + case 10053: + strcpy(str, "WSAECONNABORTED 10053 Software caused connection abort."); + break; + + case 10054: + strcpy(str, "WSAECONNRESET 10054 Connection reset by peer."); + break; + + case 10055: + strcpy(str, "WSAENOBUFS 10055 No buffer space available."); + break; + + case 10056: + strcpy(str, "WSAEISCONN 10056 Socket is already connected."); + break; + + case 10057: + strcpy(str, "WSAENOTCONN 10057 Socket is not connected."); + break; + + case 10058: + strcpy(str,"WSAESHUTDOWN 10058 Cannot send after socket shutdown."); + break; + + case 10059: + strcpy(str, + "WSAETOOMANYREFS 10059 Too many references: cannot splice."); + break; + + case 10060: + strcpy(str, "WSAETIMEDOUT 10060 Connection timed out."); + break; + + case 10061: + strcpy(str, "WSAECONNREFUSED 10061 Connection refused."); + break; + + case 10062: + strcpy(str,"WSAELOOP 10062 Too many levels of symbolic links."); + break; + + case 10063: + strcpy(str, "WSAENAMETOOLONG 10063 File name too long."); + break; + + case 10064: + strcpy(str, "WSAEHOSTDOWN 10064 Host is down."); + break; + + case 10065: + strcpy(str, "WSAEHOSTUNREACH 10065 No route to host."); + break; + + case 10091: + strcpy(str, "WSASYSNOTREADY 10091 Returned by WSAStartup(), " + "indicating that the network subsystem is unusable."); + break; + + case 10092: + strcpy(str, "WSAVERNOTSUPPORTED 10092 Returned by WSAStartup(), " + "indicating that the Windows Sockets DLL cannot support this application."); + break; + + case 10093: + strcpy(str, "WSANOTINITIALISED 10093 Winsock not initialized. This " + "message is returned by any function except WSAStartup(), " + "indicating that a successful WSAStartup() has not yet been performed."); + break; + + case 10101: + strcpy(str, "WSAEDISCON 10101 Disconnect."); + break; + + case 11001: + strcpy(str, + "WSAHOST_NOT_FOUND 11001 Host not found. This message indicates " + "that the key (name, address, and so on) " "was not found."); + break; + + case 11002: + strcpy(str, + "WSATRY_AGAIN 11002 Nonauthoritative host not found. This " + "error may suggest that the name service " "itself is not functioning."); + break; + + case 11003: + strcpy(str, + "WSANO_RECOVERY 11003 Nonrecoverable error. This error may " + "suggest that the name service itself is not functioning."); + break; + + case 11004: + strcpy(str, + "WSANO_DATA 11004 Valid name, no data record of requested " + "type. This error indicates that the key " + "(name, address, and so on) was not found."); + break; + + default: + sprintf(str, "Unknown TCP/IP network error %d", err); + } + } + + return str; +} +#endif +/*----------------------------------------------------------------------------*/ + +INT tcpip(INT cmd, ...) +{ + va_list argptr; + HNDLE hkey; + INT status, size, timeout; + void *info; + char *str, *pattern; + + va_start(argptr, cmd); + status = FE_SUCCESS; + + switch (cmd) { + case CMD_INIT: + hkey = va_arg(argptr, HNDLE); + info = va_arg(argptr, void *); + status = tcpip_init(hkey, info); + break; + + case CMD_EXIT: + info = va_arg(argptr, void *); + status = tcpip_exit(info); + break; + + case CMD_NAME: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + strcpy(str, "tcpip"); + break; + + case CMD_OPEN: + info = va_arg(argptr, void *); + status = tcpip_open(info); + break; + + case CMD_CLOSE: + info = va_arg(argptr, void *); + status = tcpip_close(info); + break; + + case CMD_WRITE: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, int); + status = tcpip_write(info, str, size); + break; + + case CMD_READ: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, INT); + timeout = va_arg(argptr, INT); + status = tcpip_read(info, str, size, timeout); + break; + + case CMD_PUTS: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + status = tcpip_puts(info, str); + break; + + case CMD_GETS: + info = va_arg(argptr, void *); + str = va_arg(argptr, char *); + size = va_arg(argptr, INT); + pattern = va_arg(argptr, char *); + timeout = va_arg(argptr, INT); + status = tcpip_gets(info, str, size, pattern, timeout); + break; + + case CMD_DEBUG: + info = va_arg(argptr, void *); + status = va_arg(argptr, INT); + ((TCPIP_INFO *) info)->settings.debug = status; + break; + } + + va_end(argptr); + + return status; +} diff --git a/bus/tcpip.h b/bus/tcpip.h new file mode 100644 index 0000000..856c014 --- /dev/null +++ b/bus/tcpip.h @@ -0,0 +1,46 @@ +/********************************************************************\ + + Name: tcpip.h + Created by: Stefan Ritt + + Contents: Header file for TCPIP bus driver + + $Id: tcpip.h,v 1.1.1.1 2019/02/21 10:07:20 raselli Exp $ + +\********************************************************************/ + +#ifndef _TCPIP_H_ +#define _TCPIP_H_ + +INT tcpip(INT cmd, ...); + +#endif /* #ifndef _TCPIP_H_ */ + +#ifdef TCPIP_RECONNECT + +#ifndef _TCPIP_PRIVATE_H_ +#define _TCPIP_PRIVATE_H_ + +typedef struct { + char host[256]; + int port; + int debug; +} TCPIP_SETTINGS; + +typedef struct { + TCPIP_SETTINGS settings; + int fd; /* device handle for socket device */ +} TCPIP_INFO; + +int tcpip_connect(char *host, int port); + +int tcpip_open(TCPIP_INFO * info); +int tcpip_close(TCPIP_INFO * info); + +int tcpip_fd_get(TCPIP_INFO * info); + +#endif /* #ifndef _TCPIP_PRIVATE_H_ */ + +#endif /* #ifdef TCPIP_RECONNECT */ + + diff --git a/device/ets_logout.c b/device/ets_logout.c new file mode 100644 index 0000000..517009d --- /dev/null +++ b/device/ets_logout.c @@ -0,0 +1,217 @@ +/********************************************************************\ + + Name: ets_logout.c + Created by: Andreas Suter 2005/04/19 + + Contents: Routine to logout a specific port of the + ets terminal server. + + $Id: ets_logout.c,v 1.1.1.1 2019/02/21 10:07:21 raselli Exp $ + +\********************************************************************/ + +#include "ets_logout.h" + +#include "midas.h" + +#ifdef OS_UNIX +#include +#include +#include +#include +//#include +#include +#include +#include +#endif + +#define WATCHDOG + +//! structure holding the rs232 terminal server network information +typedef struct { + char host[256]; //!< rs232 terminal server host name + int port; //!< port to be logged out + int debug; //!< debug flag +} ETS_SETTINGS; // NOTE: MUST be identical with TCPIP_SETTINGS + +//! structure holding all necessary informations. +typedef struct { + ETS_SETTINGS settings; //!< rs232 terminal server network information + int fd; //!< device handle for socket device +} ETS_INFO; // NOTE: MUST be identical with TCPIP_INFO + +//------------------------------------------------------------------------ +int ets_flush(int sockfd, int verbose) { + int status; + char buffer[512]; + + status = read(sockfd, buffer, sizeof(buffer)); + if (status > 0) { + buffer[status] = '\0'; + if (strstr(buffer,"%Error:")) + cm_msg(MLOG,"","ets_logout: %s",buffer); + else if (verbose) + cm_msg(MLOG,"","ets_logout: reading is %s",buffer); + } else if (status == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d reading buffer",errno); + + return 1; +} +//------------------------------------------------------------------------ +/*! + *

This routine connects to the rs232 terminal server and logouts the + * port specified in the ETS_INFO structure. It is needed since the + * rs232 terminal server sometimes is blocking a port (reason: unkown). + * + *

return: + * - 1 (true), if OK + * - 0 (false), if a problem occured + * + * \param info structure containing data in form of the ETS_INFO structure. + * \param wait waiting timer in (us) between commands. + * \param detailed_msg flag indicating if detailed messages shall be sent to MIDAS + * (cm_msg) + */ +int ets_logout(void *info, int wait, int detailed_msg) +{ + int sockfd; + int status; + struct sockaddr_in adr; + struct hostent *ets; + char cmd[64]; + ETS_INFO *bd_info; + BOOL wflag; + DWORD wtimeout,wtimeoutn; + + wait = wait/1000+1; // from usec to msec + + if (!info) { + cm_msg(MERROR, "ets_logout", "NULL pointer to bus driver info"); + return 0; + } + bd_info = (ETS_INFO *)info; + + /* code from info->bd(CMD_EXIT,info->bd_info); */ + /* close connection */ + if (bd_info->fd != -1) { + if (detailed_msg) cm_msg(MINFO,"","ets_logout: trying to shut down and " + "close the open TCP/IP connection first"); + shutdown(bd_info->fd, 2); + close(bd_info->fd); + bd_info->fd = -1; + } + +#ifdef MIDEBUGETS + if (detailed_msg) + cm_msg(MINFO, "ets_logout", "ets_logout: trying to log out port %d of ets %s", + bd_info->settings.port, bd_info->settings.host); +#endif + +#ifdef WATCHDOG + // turn off watchdog as fe might wait forever + cm_get_watchdog_params(&wflag, &wtimeout); + wtimeoutn = 0; + cm_set_watchdog_params(wflag,wtimeoutn); +#endif + + // get host info + ets = gethostbyname(bd_info->settings.host); + if (ets == NULL) { +#ifdef WATCHDOG + // restore watchdog params + cm_set_watchdog_params(wflag, wtimeout); +#endif + return 0; + } + + // set up socket + adr.sin_family = AF_INET; + adr.sin_port = htons(23); // telnet port + + memcpy(&adr.sin_addr, ets->h_addr_list[0], sizeof(adr.sin_addr)); + + sockfd = socket(PF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { +#ifdef WATCHDOG + // restore watchdog params + cm_set_watchdog_params(wflag, wtimeout); +#endif + return 0; + } + + status = connect(sockfd, (struct sockaddr *) &adr, sizeof(adr)); + if (status < 0) { + close(sockfd); +#ifdef WATCHDOG + // restore watchdog params + cm_set_watchdog_params(wflag, wtimeout); +#endif + return 0; + } + + ets_flush(sockfd, FALSE); + + // send logout commands + strcpy(cmd, "\r\n"); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"Return\"",errno); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + strcpy(cmd, "s\r\n"); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"dummy name\"",errno); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + strcpy(cmd, "su\r\n"); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"su\"",errno); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + strcpy(cmd, "system\r\n"); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"password\"",errno); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + sprintf(cmd, "logout port %d\r\n", bd_info->settings.port%1000); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"logout port %d\"",errno, + bd_info->settings.port%1000); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + strcpy(cmd, "logout\r\n"); + if ((status = write(sockfd, cmd, strlen(cmd))) == -1) + cm_msg(MLOG,"","ets_logout: ERROR %d sending \"logout\"",errno); + else if (status != strlen(cmd)) + cm_msg(MLOG,"","ets_logout: ERROR number of bytes sent != string length"); + ets_flush(sockfd, FALSE); + + ss_sleep(wait); + shutdown(sockfd, 2); + close(sockfd); + + if (detailed_msg) + cm_msg(MINFO, "ets_logout", "ets_logout: logged out port %d of ets %s", + bd_info->settings.port%1000, bd_info->settings.host); + +#ifdef WATCHDOG + // restore watchdog params + cm_set_watchdog_params(wflag, wtimeout); +#endif + + return 1; +} diff --git a/device/ets_logout.h b/device/ets_logout.h new file mode 100644 index 0000000..45b3a95 --- /dev/null +++ b/device/ets_logout.h @@ -0,0 +1,18 @@ +/********************************************************************\ + + Name: ets_logout.h + Created by: Andreas Suter 2005/04/19 + + Contents: declaration of a routine to logout out a specific port + of the ets terminal server. + + $Id: ets_logout.h,v 1.1.1.1 2019/02/21 10:07:20 raselli Exp $ + +\********************************************************************/ + +#ifndef _ETS_LOGOUT_ +#define _ETS_LOGOUT_ + +int ets_logout(void *info, int wait, int detailed_msg); + +#endif // _ETS_LOGOUT_ diff --git a/device/keller_dv2ps.c b/device/keller_dv2ps.c new file mode 100644 index 0000000..da5ae76 --- /dev/null +++ b/device/keller_dv2ps.c @@ -0,0 +1,1166 @@ +/********************************************************************\ + + Name: keller_dv2ps.c + Created by: RA36 + + Contents: Keller dV-2 PS Digital Manometer with Switch Outputs + +\********************************************************************/ + +#include +#include +#include +#include +#include "midas.h" +#include "msystem.h" +#include "bus/langpib.h" /* modified BD_READS */ + +// NOTE: Currently only works with MOXA N-Port terminal server + +#define DV2PS_ECHOED /* query is echoed by device before result is sent from device */ + +/* #define HANDLE_F66 */ /* handle f66 0 query masking 0 by 254 */ + +//#define HAVE_EDS +#ifndef HAVE_EDS +#define HAVE_ETS +#endif + +#ifdef HAVE_ETS +#include "ets_logout.h" +#endif +#ifdef HAVE_EDS +#include "eds_logout.h" +#endif + +#ifndef TCPIP_SUPPORT +#define TCPIP_SUPPORT +#endif + +#ifdef TCPIP_SUPPORT +#ifndef TCPIP_RECONNECT +#define TCPIP_RECONNECT +#endif + +/*---- when TCPIP_RECONNECT is #defined before tcpip.h is included the tcpip bus driver + * * structure is defined to be able to reset tcp/ip communication --------*/ +#include "bus/tcpip.h" + +#endif /* #ifdef TCPIP_SUPPORT */ + +//#define MIDEBUG /* */ +//#define MIDEBUG1 /* */ + +/* + * Serial interface specifications + * + * Baud Rate 9600 + * Bits per Character 1 Start, 8 Data, 1 Stop + * Parity No + * Terminator NONE + * + * Lantronix ETS8P settings + * + * = serial port connection on ETS8P (1-8) + * + * DEFINE PORT PARITY NONE + * DEFINE PORT STOP 1 + * DEFINE PORT SPEED 9600 + * DEFINE PORT CHARACTER 8 + * DEFINE PORT FLOW NONE + * + * + * Use command telnet 300 to connect to device + * + */ + + +/*---- globals -----------------------------------------------------*/ + +#define NUMCHANS 4 + +#define IO_TIMEOUT 300 +#define MAX_ERROR 15 /* max. number of error messages */ +#define DELTA_TIME_ERROR 3600 /* reset error count after this time [sec] */ + +/* Store any parameters the device driver needs in following + structure. */ + +typedef struct { + char name[NAME_LENGTH]; + char ets_in_use; /* Y = logout ets/epr connection */ + char status; /* Init, Normal, CommandErr, BusErr, DeviceErr */ +} KELLER_DV2PS_SETTINGS; + +#define KELLER_DV2PS_SETTINGS_STR "\ +Name = STRING : [32] NONE\n\ +TS_in_Use = CHAR : Y \n\ +Status = CHAR : E\n\ +" + +/* following structure contains private variables to the device + driver. It is necessary to store it here in case the device + driver is used for more than one device in one frontend. If it + would be stored in a global variable, one device could over- + write the other device's variables. */ + +typedef struct { + KELLER_DV2PS_SETTINGS keller_dv2ps_settings; + float *array; + INT num_channels; + INT(*bd) (INT cmd, ...); /* bus driver entry function */ + void *bd_info; /* private info of bus driver */ + HNDLE hkey; /* ODB key for bus driver info */ + INT startup_error; + INT errorcount; + DWORD lasterrtime; + DWORD lastlog; + INT ngets; + BOOL inpowerup; + unsigned char address; +} KELLER_DV2PS_INFO; + +/*---- device driver routines --------------------------------------*/ + +INT keller_dv2ps_append_crc16(char *); +INT keller_dv2ps_verify_crc16(char *, int ); +INT keller_dv2ps_calc_crc16 (char *, int , char *, char *); + +INT keller_dv2ps_powerup_init(KELLER_DV2PS_INFO *); +INT keller_dv2ps_sendr(KELLER_DV2PS_INFO *, char *, char *, int, INT, int); +INT keller_dv2ps_get(KELLER_DV2PS_INFO * , INT , float *); +INT keller_dv2ps_exit(KELLER_DV2PS_INFO * ); + +/*----------------------------------------------------------------------------*/ + // calculate and return 16-bit CRC from supplied buffer + // NOTE: buf may contain 0x00 as returned data +INT keller_dv2ps_calc_crc16(char *buf, int len, char *crc16_h, char *crc16_l) { + INT retval; + + retval = FALSE; + if (buf && crc16_h && crc16_l) { + unsigned int crc; + int i; + + crc = 0xFFFF; + + for (i=0;i>= 1; + crc ^= 0xA001; + } else + crc >>= 1; + } + } + + *crc16_h = (crc >> 8) & 0xFF; + *crc16_l = crc & 0xFF; + + retval = TRUE; + } else { + if (!buf) + cm_msg(MERROR, "keller_dv2ps_calc_crc16", + "NULL pointer supplied as message"); + if (!crc16_h) + cm_msg(MERROR, "keller_dv2ps_calc_crc16", + "NULL pointer to return 16-bit crc high byte"); + if (!crc16_l) + cm_msg(MERROR, "keller_dv2ps_calc_crc16", + "NULL pointer to return 16-bit crc low byte"); + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ + // append crc16 bytes to message buffer buf + // NOTE: buf must be large enough to hold additional two bytes added + // NOTE: buf may not contain 0x00 in data fields +INT keller_dv2ps_append_crc16(char *buf) { + INT retval,len; + + retval = FALSE; + if (buf && ((len=strlen(buf)) >= 2)) { + char crc16_h, crc16_l; + + crc16_h = crc16_l = '\0'; + // calculate 16-bit CRC +#ifdef HANDLE_F66 + // unmask special case + if ((buf[1] == 66) && (buf[2] == (char) 254)) buf[2] = 0; +#endif + if ((retval = keller_dv2ps_calc_crc16(buf,len,&crc16_h,&crc16_l))) { + // append crc16 bytes + *(buf+len) = crc16_h; + *(buf+len+1) = crc16_l; + *(buf+len+2) = '\0'; + retval = TRUE; + } +#ifdef HANDLE_F66 + if ((buf[1] == 66) && (buf[2] == 0)) buf[2] = (char)254; // (re)mask +#endif + } else if (buf){ + cm_msg(MERROR,"keller_dv2ps_append_crc16", + "NULL pointer supplied as message"); + } else { + cm_msg(MERROR,"keller_dv2ps_append_crc16","Supplied message is too short " + "to contain a valid command/query"); + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ + // calculate 16-bit CRC from buf (omitting last 2 bytes) + // and check if 16-bit CRC and last two bytes are identical + // NOTE: buf may contain 0x00 in data fields +INT keller_dv2ps_verify_crc16(char *buf, int len) { + INT retval; + + retval = 0; + if (buf && (len >= 2)) { + char s_crc16_h, s_crc16_l; + char crc16_h, crc16_l; + + s_crc16_h = *(buf+len-2); // remember 16-bit crc at end of buffer + s_crc16_l = *(buf+len-1); + + *(buf+len-2) = '\0'; // temporary remove 16-bit crc from buffer + + crc16_h = crc16_l = '\0'; + + // calculate crc16 + if ((retval = keller_dv2ps_calc_crc16(buf,len-2,&crc16_h,&crc16_l))){ + if ((crc16_h != s_crc16_h)||(crc16_l != s_crc16_l)) { // verify +#ifdef MIDEBUG + if (crc16_h != s_crc16_h) { + cm_msg(MLOG,"","Received and calculated 16-bit CRC high byte do not " + "match! %d <> %d", (unsigned char)s_crc16_h, + (unsigned char)crc16_h); + } + if (crc16_l != s_crc16_l) { + cm_msg(MLOG,"","Received and calculated 16-bit CRC low byte do not " + "match! %d <> %d", (unsigned char)s_crc16_l, + (unsigned char)crc16_l); + } +#endif + } else { + *(buf+len-2) = s_crc16_h; // restore crc bytes + *(buf+len-1) = s_crc16_l; + *(buf+len) = '\0'; + retval = 1; + } + } + } else if (!buf){ + cm_msg(MERROR,"keller_dv2ps_verify_crc16", + "NULL pointer supplied as message"); + } else { + cm_msg(MERROR,"keller_dv2ps_verify_crc16","Supplied message is too short " + "to contain a valid command/query"); + } + + //retval = 1; // TESTTEST + return retval; +} + +/*----------------------------------------------------------------------------*/ +INT keller_dv2ps_settings_update(KELLER_DV2PS_INFO * info) +{ + HNDLE hDB, hkeydd; + int size; + INT status1; + +#ifdef MIDEBUG + cm_msg(MLOG, "", "keller_dv2ps_settings_update DD settings update necessary"); +#endif + + cm_get_experiment_database(&hDB, NULL); + + if ((status1 = db_find_key(hDB, info->hkey, "DD", &hkeydd)) == DB_SUCCESS) { + size = sizeof(info->keller_dv2ps_settings); + db_set_record(hDB, hkeydd, &info->keller_dv2ps_settings, size, 0); +#ifdef MIDEBUG + cm_msg(MLOG, "", "keller_dv2ps_settings_update() Updating DD settings"); +#endif + } else { + cm_msg(MLOG, "", "keller_dv2ps_settings_update() ERROR key for DD not " + "found db_find_key() status = %d", status1); + } + + return FE_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + + // NOTE: send may not contain 0x00 in data fields + // NOTE: recv may contain 0x00 in data fields +INT keller_dv2ps_sendr(KELLER_DV2PS_INFO * info, char *send, + char *recv, int size, INT tmo, int ntries) +{ + int status, errcnto, itries,i; + char tstat; + BOOL wflag; + DWORD wtimeout, wtimeoutn; + char senda[256]; + int fd; + + status = -1; + fd = 0; + + // RA36 10-JUL-2023 init receive buffer + if (recv != NULL) *recv = '\0'; + + if ((info == NULL) || (info->bd_info == NULL)) { +#ifdef MIDEBUG1 + cm_msg(MLOG, "", "keller_dv2ps_sendr(NULL pointer to BusDriver info) Returning -1"); +#endif + return status; + } else { + char name[NAME_LENGTH]; + + name[0] = '\0'; + info->bd(CMD_NAME, info->bd_info, name); /* get name of bus driver */ + + if (strcmp(name, "tcpip") == 0) { /* TCP/IP bus driver? */ +#ifdef TCPIP_RECONNECT + /* get file descriptor to check if (re)open failed */ + fd = tcpip_fd_get((TCPIP_INFO *) info->bd_info); +#endif + } + } + + senda[0] = '\0'; + if (send) { + char temp[64]; + + for (i=0; i < strlen(send); i++) { + temp[0] = '\0'; + sprintf(temp,"%d", ((unsigned char)send[i])); + if (i != strlen(send)-1) strcat(temp," "); + strncat(senda,temp,255); + } + senda[255] = '\0'; + } +#ifdef MIDEBUG + cm_msg(MLOG,"","keller_dv2ps_sendr(%s,tmo=%d)", send?senda:"\"NULL\"", tmo); +#endif + errcnto = info->errorcount; + + tstat = info->keller_dv2ps_settings.status; + + cm_get_watchdog_params(&wflag, &wtimeout); + wtimeoutn = 0; + cm_set_watchdog_params(wflag,wtimeoutn); + +send_again: + + if ((send != NULL) && (fd != -1)) { + int slen; +#ifdef MIDEBUG + //cm_msg(MLOG, "", "++BD_WRITES() send = %s", senda); + cm_msg(MLOG, "", "++BD_WRITES()"); +#endif + slen = strlen(send); +#ifdef HANDLE_F66 + // unmask special case + if ((send[1] == 66) && (send[2] == (char) 254)) send[2] = 0; +#endif + status = BD_WRITES(send,slen); +#ifdef HANDLE_F66 + // mask special case + if ((send[1] == 66) && (send[2] == 0)) send[2] = (char)254; +#endif + + ss_sleep(100); // RA36 27-JAN-2006 +#ifdef MIDEBUG + cm_msg(MLOG, "", "--BD_WRITES() status = %d", status); +#endif + } else { + if (fd == -1) { + status = -1; /* connection not open -> skip reading reply */ + /* case will be handled as communication error */ + } else + status = 1; + } + + if (status != -1) { + info->keller_dv2ps_settings.status = 'N'; + if (recv != NULL) { + itries = 0; + try_again: + *recv = '\0'; + status = BD_READS(recv, size, tmo); + // status = BD_GETS(recv, size, "\x0d", tmo); // MAY NOT BE USED! + // status = BD_GETS(recv, size, "", tmo); // MAY NOT BE USED! +#ifdef MIDEBUG + cm_msg(MLOG, "", "BD_READS() status = %d", status); + if (status > 0) { + for (i=0; i < status ; i++) + cm_msg(MLOG,"","recv[%d] = %d = 0x%2.2x ",i, + (unsigned char)recv[i], (unsigned char)recv[i]); + } +#endif + itries++; + if ((status <= 0) && (itries < ntries)) { +#ifdef MIDEBUG + cm_msg(MLOG, "", + "keller_dv2ps_sendr_status : Timeout - trying again!"); +#endif + goto try_again; + + } else if (status >= 4) { // something returned? then check for errors + int offset; + +#ifdef DV2PS_ECHOED + offset = strlen(send); // sent command (including crc16) is echoed +#else + offset = 0; // sent command is not echoed +#endif + if (send[0] != recv[0+offset]) { // device address different? +#ifndef MIDEBUG + itries++; + if (itries < ntries) + goto send_again; +#endif + cm_msg(MLOG,"","Sent device address %d <> returned %d", + (unsigned char)send[0],(unsigned char)recv[0+offset]); + } + if (send[1] != recv[1+offset]) { // function code changed or error bit set? + + if (send[1]+128 != recv[1+offset]) { // function code changed +#ifndef MIDEBUG + itries++; + if (itries < ntries) + goto send_again; +#endif + cm_msg(MLOG,"","Sent function code %d <> returned %d", + (unsigned char)send[1],(unsigned char)recv[1+offset]); + + } else { // error bit set + char msg[64]; + + switch (send[2]) { // interpret exception code + case 1: strcpy(msg,"non-implemented function"); + break; + case 2: strcpy(msg,"incorrect parameters"); + break; + case 3: strcpy(msg,"erroneous data"); + break; + case 32: strcpy(msg,"device not initialised yet"); + break; + default: strcpy(msg,"UNKNOWN"); + } + + cm_msg(MLOG,"","Exception error %d (%s) returned", + (unsigned char)send[2],msg); + + if (send[2] == 32) { // device not initialized yet due to power cycle + if (!info->inpowerup) { // avoid init when already in init + // do device initialisation -> when successful send query again + if (keller_dv2ps_powerup_init(info) == FE_SUCCESS) goto send_again; + } + } else { + /* Exception error */ + info->keller_dv2ps_settings.status = 'E'; + } + } + } + } + + if (status == 0) + cm_msg(MLOG, "", "keller_dv2ps_sendr_status : Timeout reading reply of %s!", + send ? senda : "NULL"); + } else { +#ifdef MIDEBUG + cm_msg(MLOG, "", "recv == NULL"); +#endif + } + } + + /* communication error? */ + if (status == -1) { + info->errorcount++; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_sendr_status", "Communication error!"); + /* Bus error */ + info->keller_dv2ps_settings.status = 'B'; + } + + if (tstat != info->keller_dv2ps_settings.status) + keller_dv2ps_settings_update(info); + + /* many errors? try to reconnect to Keller dV-2 PS */ + if ((errcnto < info->errorcount) && (info->errorcount > MAX_ERROR + 60)) { + char name[NAME_LENGTH]; + + name[0] = '\0'; + info->bd(CMD_NAME, info->bd_info, name); /* get name of bus driver */ + + if (strcmp(name, "tcpip") == 0) { /* TCP/IP bus driver? */ +#ifdef TCPIP_RECONNECT + if (info->bd_info != NULL) { + if (tcpip_fd_get((TCPIP_INFO *) info->bd_info) != -1) { + tcpip_close((TCPIP_INFO *) info->bd_info); + } + +#ifdef HAVE_ETS + if (toupper(info->keller_dv2ps_settings.ets_in_use) == 'Y') + ets_logout(info->bd_info, 0, TRUE); // log out ets +#endif +#ifdef HAVE_EDS + if (toupper(info->keller_dv2ps_settings.ets_in_use) == 'Y') + eds_logout(info->bd_info, 0, TRUE); // log out epr +#endif + ss_sleep(3000); /* wait 3 seconds */ + + /* (re)open TCP/IP connection */ + tcpip_open((TCPIP_INFO *) info->bd_info); + + if (tcpip_fd_get((TCPIP_INFO *) info->bd_info) != -1) { + cm_msg(MLOG,"","Reconnected to Keller Digital Manometer dV-2 PS"); + /* reset error count - but avoid generation of messages */ + info->errorcount = MAX_ERROR + 1; + } else + cm_msg(MERROR, "keller_dv2ps_sendr", + "Failed to reconnect Keller dV-2 PS Digital Manometer!"); + } +#else + cm_msg(MERROR, "keller_dv2ps_sendr", "TCPIP_RECONNECT not defined" + " - Not able to reconnect to TCP/IP device!"); +#endif /* TCPIP_RECONNECT */ + + } else { + cm_msg(MERROR, "keller_dv2ps_sendr", "Unknown bus driver %s" + " - Not able to reconnect!", name); + } + + } + + cm_set_watchdog_params(wflag,wtimeout); + return status; +} + +/*----------------------------------------------------------------------------*/ + +/* the init function creates a ODB record which contains the + settings and initialized it variables as well as the bus driver */ + +INT keller_dv2ps_init(HNDLE hkey, void **pinfo, INT channels, INT(*bd) (INT cmd, ...)) +{ + int status, size, len, i; + HNDLE hDB, hkeydd; + KELLER_DV2PS_INFO *info; + + /* allocate info structure */ + info = calloc(1, sizeof(KELLER_DV2PS_INFO)); + *pinfo = info; + + cm_get_experiment_database(&hDB, NULL); + + /* create settings record */ + status = db_create_record(hDB, hkey, "DD", KELLER_DV2PS_SETTINGS_STR); + if (status != DB_SUCCESS) + return FE_ERR_ODB; + + db_find_key(hDB, hkey, "DD", &hkeydd); + size = sizeof(info->keller_dv2ps_settings); + db_get_record(hDB, hkeydd, &info->keller_dv2ps_settings, &size, 0); + + /* initialize driver */ + info->num_channels = channels; + info->array = calloc(channels, sizeof(float)); + info->bd = bd; + info->hkey = hkey; + info->lasterrtime = ss_time(); + info->errorcount = 0; + info->startup_error = 0; + info->lastlog = 0; + info->ngets = 0; + info->inpowerup = FALSE; + info->address = 250; // using non-bus mode default address 250 + + cm_msg_flush_buffer(); + + if (!bd) + return FE_ERR_ODB; + + /* initialize bus driver */ + status = info->bd(CMD_INIT, info->hkey, &info->bd_info); + + if (status != SUCCESS) { + cm_msg(MLOG, "", "keller_dv2ps_init : ERROR initialising bus driver"); + keller_dv2ps_exit(info); + *pinfo = NULL; + return status; + } + + if (toupper(info->keller_dv2ps_settings.ets_in_use) == 'Y') +#ifdef HAVE_ETS + cm_msg(MLOG,"","DD/TS_in_Use is set. " + "Will logout Lantonix ETS in case of RS232 communication errors"); +#elif defined( HAVE_EDS) + cm_msg(MLOG,"","DD/TS_in_Use is set. " + "Will logout Lantronix EPR in case of RS232 communication errors"); +#else + cm_msg(MLOG,"","DD/ETS_in_Use is set. " + "However Lantronix logout functionality is not included"); +#endif + cm_msg_flush_buffer(); + + /* initialization of device */ + if (keller_dv2ps_powerup_init(info) == FE_SUCCESS) { + info->keller_dv2ps_settings.status = 'I'; + keller_dv2ps_settings_update(info); + } + + return FE_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +INT keller_dv2ps_exit(KELLER_DV2PS_INFO * info) +{ + /* call EXIT function of bus driver, usually closes device */ + if (info->bd) + info->bd(CMD_EXIT, info->bd_info); + + /* free local variables */ + if (info->array) + free(info->array); + + free(info); + + return FE_SUCCESS; +} +/*----------------------------------------------------------------------------*/ +INT keller_dv2ps_powerup_init(KELLER_DV2PS_INFO *info) { + INT retval; + + retval = FE_SUCCESS; + + if (info && !info->inpowerup) { + char send[32],recv[64],msg[64]; + int isend,i,rlen,slen; + INT n; + + info->inpowerup = TRUE; // block repeated calling of powerup init + + // F48: Init + send[0] = (char) info->address; + send[1] = 48; + send[2] = '\0'; + + keller_dv2ps_append_crc16(send); + +#ifdef DV2PS_ECHOED + slen = strlen(send); +#else + slen = 0; +#endif + + isend = 0; +send_f48: + if ((rlen=keller_dv2ps_sendr(info,send,recv,sizeof(recv),IO_TIMEOUT,6)) + >= 10+slen) { + if (keller_dv2ps_verify_crc16(recv+slen,rlen-slen)) { + cm_msg(MLOG,"","Device ID code is %d", + (unsigned char) recv[2+slen]); + cm_msg(MLOG,"","Subdivision of class is %d", + (unsigned char) recv[3+slen]); + cm_msg(MLOG,"","Firmware version is %d, %d", + (unsigned char) recv[4+slen], + + (unsigned char) recv[5+slen]); + cm_msg(MLOG,"","Length of internal receive buffer is %d", + (unsigned char) recv[6+slen]); + if (recv[7+slen] == 0) + cm_msg(MLOG,"","Device addressed for first time after power on"); + else + cm_msg(MLOG,"","Device was already initialised"); + + } else { + isend++; + if (isend < 5) goto send_f48; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "CRC16 error reading reply of F48 Query"); + } + +#ifdef HANDLE_F66 + // F66: Query device address + send[0] = (char) info->address; + send[1] = 66; + send[2] = (char) 254; // should actually be 0 for query + send[3] = '\0'; + + keller_dv2ps_append_crc16(send); +#ifdef DV2PS_ECHOED + slen = strlen(send); +#else + slen = 0; +#endif + + isend = 0; +send_f66: + if ((rlen=keller_dv2ps_sendr(info,send,recv,sizeof(recv),IO_TIMEOUT,6)) + >= 5+slen) { + if (keller_dv2ps_verify_crc16(recv+slen,rlen-slen)) { + cm_msg(MLOG,"","Device Address is %d",*(unsigned char *) &recv[2+slen]); + } else { + isend++; + if (isend < 5) goto send_f66; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "CRC16 error reading reply of F66 Query"); + } + } else { + isend++; + if (isend < 5) goto send_f66; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "Communication to query F66 failed!"); + } +#endif + + // F69: Query Serial Number + send[0] = (char) info->address; + send[1] = 69; + send[2] = '\0'; + + keller_dv2ps_append_crc16(send); +#ifdef DV2PS_ECHOED + slen = strlen(send); +#else + slen = 0; +#endif + + isend = 0; +send_f69: + if ((rlen=keller_dv2ps_sendr(info,send,recv,sizeof(recv),IO_TIMEOUT,6)) + >= 8+slen) { + if (keller_dv2ps_verify_crc16(recv+slen,rlen-slen)) { + cm_msg(MLOG,"","S/N is %d", + 256*256*256*(*(unsigned char *) &recv[2+slen]) + + 256*256*(*(unsigned char *) &recv[3+slen]) + + 256*(*(unsigned char *) &recv[4+slen]) + + (*(unsigned char *) &recv[5+slen])); + } else { + isend++; + if (isend < 5) goto send_f69; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "CRC16 error reading reply of F69 Query"); + } + } else { + isend++; + if (isend < 5) goto send_f69; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "Communication to query F69 failed!"); + } + + // F30: Read Calibration/Configuration values + send[0] = (char) info->address; + send[1] = 30; + for (i=0; i < 7; i++) { + switch (i) { + case 0: + send[2] = 52; + strcpy(msg,"Offset of Pressure Sensor P1 (Key or F95)"); + break; + case 1: + send[2] = 64; + strcpy(msg,"Offset of Pressure Sensor P1 (calibration)"); + break; + case 2: + send[2] = 65; + strcpy(msg,"Gain Factor of Pressure Sensor P1 (calibration)"); + break; + case 3: + send[2] = 72; + strcpy(msg,"Switch_1_on"); + break; + case 4: + send[2] = 73; + strcpy(msg,"Switch_1_off"); + break; + case 5: + send[2] = 78; + strcpy(msg,"Switch_2_on"); + break; + case 6: + send[2] = 79; + strcpy(msg,"Switch_2_off"); + break; + } + send[3] = '\0'; + + keller_dv2ps_append_crc16(send); + +#ifdef DV2PS_ECHOED + slen = strlen(send); +#else + slen = 0; +#endif + + isend = 0; +send_f30: + if ((rlen=keller_dv2ps_sendr(info,send,recv,sizeof(recv),IO_TIMEOUT,6)) + >= 8+slen) { + if (keller_dv2ps_verify_crc16(recv+slen,rlen-slen)) { + DWORD_SWAP(&recv[2+slen]); + cm_msg(MLOG,"","%s is %f bar", msg, *((float *)&recv[2+slen])); + + } else { + isend++; + if (isend < 5) goto send_f30; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "CRC16 error reading reply of F30 Query"); + } + } else { + isend++; + if (isend < 5) goto send_f30; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "Communication to query F30 failed!"); + } + } // for + { + float tval; + if (keller_dv2ps_get(info,0,&tval) == FE_SUCCESS) + cm_msg(MLOG,"","Currently measured pressure is %.1f mbar",tval); + if (keller_dv2ps_get(info,1,&tval) == FE_SUCCESS) + cm_msg(MLOG,"","Currently measured device temperature is %.3f degC", + tval); + } + } else { + isend++; + if (isend < 15) goto send_f48; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", + "Communication to query F48 failed! " + "Not possible to Init device!"); + } + + info->inpowerup = FALSE; // release blocking + + } else if (info) { + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_powerup_init", "Reentrant function call!"); + } else { + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR,"keller_dv2ps_powerup_init","NULL pointer to device info!"); + } + + return retval; +} +/*----------------------------------------------------------------------------*/ + +INT keller_dv2ps_get(KELLER_DV2PS_INFO * info, INT channel, float *pvalue) +{ + char status; + char sendbuf[128]; + char recvbuf[128]; + int isend; + int size,rlen,slen; + int j,i,crc,crc0,crc1; + + if ((info->ngets)++ > 50) { + ss_sleep(1000); + } + + if ((ss_time() - info->lasterrtime) > DELTA_TIME_ERROR) { + info->errorcount = 0; + info->lasterrtime = ss_time(); + } + + if (info->startup_error == 1) { /* there was an error during CMD_INIT */ + *pvalue = (float) -2.0; /* return error */ + ss_sleep(100); /* keep CPU load low */ + return FE_SUCCESS; + } + + status = info->keller_dv2ps_settings.status; + if (pvalue != NULL) + *pvalue = -1.0f; + + if ((channel < 0) || (channel >= NUMCHANS)) { + return FE_SUCCESS; + } + + size = sizeof(recvbuf); + + j = 0; + + sendbuf[j++] = (char) info->address; // Address + if (channel == 0) { + sendbuf[j++] = 73; // F73 + sendbuf[j++] = 1; // channel 1 + } else if (channel == 1) { + sendbuf[j++] = 73; // F73 + sendbuf[j++] = 4; // channel 4 + } else if ((channel == 2)||(channel == 3)) { + sendbuf[j++] = 100; // F100 + sendbuf[j++] = 18; // channel 18 + } + sendbuf[j++] = '\0'; // set string terminator [] + + keller_dv2ps_append_crc16(sendbuf); + +#ifdef DV2PS_ECHOED + slen = strlen(sendbuf); +#else + slen = 0; +#endif + + isend = 0; +send_again: + if ((rlen=keller_dv2ps_sendr(info,sendbuf,recvbuf,size,IO_TIMEOUT,6)) + >= 5+slen) { + + // compare CRC of received data with calculated + if (keller_dv2ps_verify_crc16(recvbuf+slen,rlen-slen)) { + // + // interpret received buffer according to Midas channel + if (channel == 0) { // pressure mbar + if ((recvbuf[6+slen] & 0x02) != 0x02) { // reading OK when STAT bit .1 not set + float tval; + DWORD_SWAP(&recvbuf[2+slen]); + tval = 1000.f*(*((float *) &recvbuf[2+slen])); + if ((tval >= -1.f) && (tval <= 100000.f)) { // sometimes reading is invalid + if (pvalue) *pvalue = tval; // check range -1 mbar - 100 bar + if (*(info->array+channel) == -1.f) + cm_msg(MLOG,"","Pressure reading is now OK"); + } else { + if (pvalue) *pvalue = *(info->array+channel); // NOT OK -> return previous + } + } else if (*(info->array+channel) != -1.f) { + cm_msg(MLOG,"","Pressure reading is not OK"); + } + if (pvalue) *(info->array+channel) = *pvalue; + + } else if (channel == 1) { // temperature degC + if ((recvbuf[6+slen] & 0x10) != 0x10) { // reading OK when STAT bit .4 not set + float tval; + DWORD_SWAP(&recvbuf[2+slen]); + tval = *((float *) &recvbuf[2+slen]); + if ((tval >= -1.f) && (tval <= 100.f)) { // sometimes reading is invalid + if (pvalue) *pvalue = tval; // check range -1 - 100 degC + } else { + if (pvalue) *pvalue = *(info->array+channel); // NOT OK -> return previous + } + } else if (*(info->array+channel) != -1.f) { + cm_msg(MLOG,"","Temperature reading is not OK"); + } + if (pvalue) *(info->array+channel) = *pvalue; + + } else if (channel == 2) { + // NIY interpret Switch_config1 revcbuf[2] + if (recvbuf[6+slen] & 0x01) { + if (*(info->array+channel) != 1.f) { + cm_msg(MLOG,"","Switch 1 Status changed to ON"); + *(info->array+channel) = 1.f; + } + if (pvalue) *pvalue = 1.f; + } else { + if (*(info->array+channel) != 0.f) { + cm_msg(MLOG,"","Switch 1 Status changed to OFF"); + *(info->array+channel) = 0.f; + } + if (pvalue) *pvalue = 0.f; + } + } else if (channel == 3) { + // NIY interpret Switch_config2 recvbuf[3] + if (recvbuf[6+slen] & 0x02) { + if (*(info->array+channel) != 1.f) { + cm_msg(MLOG,"","Switch 2 Status changed to ON"); + *(info->array+channel) = 1.f; + } + if (pvalue) *pvalue = 1.f; + } else { + if (*(info->array+channel) != 0.f) { + cm_msg(MLOG,"","Switch 2 Status changed to OFF"); + *(info->array+channel) = 0.f; + } + if (pvalue) *pvalue = 0.f; + } + } + + } else { + isend++; + if (isend < 5) goto send_again; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_get", + "CRC16 error sending Query %d %d %d", + (unsigned char)sendbuf[0],(unsigned char) sendbuf[1], + (unsigned char)sendbuf[2]); + } + + } else { + isend++; + if (isend < 5) goto send_again; + if (info->errorcount < MAX_ERROR) + cm_msg(MERROR, "keller_dv2ps_get", + "Communication error sending Query %d %d %d", + (unsigned char)sendbuf[0],(unsigned char) sendbuf[1], + (unsigned char)sendbuf[2]); + } + + if (status != info->keller_dv2ps_settings.status) + keller_dv2ps_settings_update(info); + +#ifdef MIDEBUG + if (pvalue) + cm_msg(MLOG,"","--keller_dv2ps_get(channel=%d,value=%f)",channel,*pvalue); +#endif + return FE_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +INT keller_dv2ps_get_all(KELLER_DV2PS_INFO * info, INT channels, float *pvalue) +{ + if (channels > 0) { + int i; + + for (i = 0; i < MIN(channels, info->num_channels); i++) + keller_dv2ps_get(info, i, pvalue + i); + } + return FE_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +INT keller_dv2ps_get_default_threshold(KELLER_DV2PS_INFO * info, INT channel, + float *pvalue) +{ + + if (pvalue != NULL) { + if (channel < 2) + *pvalue = 0.0005; + else + *pvalue = 0.5; + } + return FE_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +INT keller_dv2ps_get_name(KELLER_DV2PS_INFO * info, INT channel, char *name) +{ + if (name != NULL) { + if ((channel >= 0) && (channel < NUMCHANS)) { + char lname[11]; + + // truncate name to 10 characters that + // "_Temperature Measured" is not longer than 31 characters + strncpy(lname,info->keller_dv2ps_settings.name,10); + lname[10] = '\0'; + + if (channel == 0) + sprintf(name, "%s_Pressure", lname); + else if (channel == 1) + sprintf(name, "%s_Temperature", lname); + else if (channel == 2) + sprintf(name, "%s_Switch1", lname); + else if (channel == 3) + sprintf(name, "%s_Switch2", lname); + else + sprintf(name, "%s_Channel %d", lname,channel+1); + } else + sprintf(name, "Out of range %d", channel + 1); + } + return FE_SUCCESS; +} + +/*---- device driver entry point -----------------------------------*/ + +INT keller_dv2ps(INT cmd, ...) +{ + va_list argptr; + HNDLE hKey; + INT channel, status; + DWORD flags; + float value, *pvalue; + void *info, *bd; + char *name; + + va_start(argptr, cmd); + status = FE_SUCCESS; + + switch (cmd) { + case CMD_INIT: + hKey = va_arg(argptr, HNDLE); + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + flags = va_arg(argptr, DWORD); + bd = va_arg(argptr, void *); + status = keller_dv2ps_init(hKey, info, channel, bd); + break; + + case CMD_EXIT: + info = va_arg(argptr, void *); + status = keller_dv2ps_exit(info); + break; + + case CMD_GET: + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + pvalue = va_arg(argptr, float *); + status = keller_dv2ps_get(info, channel, pvalue); + break; + +#ifdef OBSOLETE_2_1 + case CMD_GET_ALL: + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + pvalue = va_arg(argptr, float *); + status = keller_dv2ps_get_all(info, channel, pvalue); + break; +#endif + + case CMD_GET_THRESHOLD: + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + pvalue = va_arg(argptr, float *); + status = keller_dv2ps_get_default_threshold(info, channel, pvalue); + break; + + case CMD_GET_LABEL: + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + name = va_arg(argptr, char *); + status = keller_dv2ps_get_name(info, channel, name); + break; + + case CMD_GET_DEMAND: + /* not necessary to implement */ + info = va_arg(argptr, void *); + channel = va_arg(argptr, INT); + pvalue = va_arg(argptr, float *); + if (pvalue) *pvalue = 0.f; + break; + + case CMD_SET_LABEL: + case CMD_SET: +#ifdef OBSOLETE_2_1 + case CMD_SET_ALL: +#endif + /* not necessary to implement */ ; + break; + + default: + break; + } + + va_end(argptr); + + return status; +} + +/*------------------------------------------------------------------*/ diff --git a/device/keller_dv2ps.h b/device/keller_dv2ps.h new file mode 100644 index 0000000..78343de --- /dev/null +++ b/device/keller_dv2ps.h @@ -0,0 +1,11 @@ +/********************************************************************\ + + Name: keller_dv2ps.h + Created by: RA35 + + Contents: Device driver function declarations for + Keller dV-2 PS Digital Manometer with Switch Outputs + +\********************************************************************/ + +INT keller_dv2ps(INT cmd, ...); diff --git a/midas/midas.h b/midas/midas.h new file mode 100644 index 0000000..539b1a1 --- /dev/null +++ b/midas/midas.h @@ -0,0 +1,2198 @@ +/********************************************************************\ + + Name: MIDAS.H + Created by: Stefan Ritt + + Contents: Type definitions and function declarations needed + for MIDAS applications + + + $Id: midas.h,v 1.3 2023/03/31 07:39:44 raselli Exp $ + +\********************************************************************/ + +#ifndef _MIDAS_H_ +#define _MIDAS_H_ + +/*------------------------------------------------------------------*/ + +#ifdef __cplusplus /* RA36 fortify may not be used for c++ compilation */ +//#define FORTIFY /* define or undefine NOTE: does not work */ +#else +//#define FORTIFY /* define or undefine */ +#endif + + +/**dox***************************************************************/ +/** @file midas.h +The main include file +*/ + +/** @defgroup midasincludecode The midas.h & midas.c + */ +/** @defgroup mdefineh Midas Define + */ +/** @defgroup mmacroh Midas Macros + */ +/** @defgroup mdeferrorh Midas Error definition + */ +/** @defgroup msectionh Midas Structure Declaration + */ + +/**dox***************************************************************/ +/** @addtogroup midasincludecode + * + * @{ */ + +/* has to be changed whenever binary ODB format changes */ +#define DATABASE_VERSION 3 + +/* MIDAS version number which will be incremented for every release */ +#define MIDAS_VERSION "2.1n" + +/**dox***************************************************************/ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/*------------------------------------------------------------------*/ + +/* find out on which operating system we are running */ + +#if defined( VAX ) || defined( __VMS ) +#define OS_VMS +#endif + +#if defined( _MSC_VER ) +#define OS_WINNT +#endif + +#if defined( __MSDOS__ ) +#define OS_MSDOS +#endif + +#if defined ( vxw ) +#define OS_VXWORKS +#undef OS_UNIX +#endif + +#if !defined(OS_LINUX) +#if defined ( __linux__ ) +#define OS_LINUX +#endif +#endif + +#if !defined(OS_DARWIN) +#if defined ( __APPLE__ ) +#define OS_LINUX +#define OS_DARWIN +#endif +#endif + +#if defined(OS_LINUX) || defined(OS_OSF1) || defined(OS_ULTRIX) || defined(OS_FREEBSD) || defined(OS_SOLARIS) || defined(OS_IRIX) || defined(OS_DARWIN) +#ifndef OS_UNIX +#define OS_UNIX +#endif +#endif + +#if !defined(OS_IRIX) && !defined(OS_VMS) && !defined(OS_MSDOS) && !defined(OS_UNIX) && !defined(OS_VXWORKS) && !defined(OS_WINNT) +#error MIDAS cannot be used on this operating system +#endif + +/*------------------------------------------------------------------*/ + +#ifdef FORTIFY +#include "fortify.h" +#endif +#include + +/* Define basic data types */ + +#ifndef MIDAS_TYPE_DEFINED +#define MIDAS_TYPE_DEFINED + +typedef unsigned char BYTE; +typedef unsigned short int WORD; +#ifndef OS_WINNT // Windows defines already DWORD +typedef unsigned int DWORD; +#endif + +#ifndef OS_WINNT +#ifndef OS_VXWORKS +typedef DWORD BOOL; +#endif +#endif + +#endif /* MIDAS_TYPE_DEFINED */ + +/* + Definitions depending on integer types: + + Note that the alpha chip uses 32 bit integers by default. + Therefore always use 'INT' instead 'int'. +*/ +#if defined(OS_MSDOS) +typedef long int INT; +#elif defined( OS_WINNT ) + +/* INT predefined in windows.h */ +#ifndef _INC_WINDOWS +#include +#endif + +#undef DB_TRUNCATED + +#else +typedef int INT; +#endif + +typedef INT HNDLE; + +/* Include vxWorks for BOOL definition */ +#ifdef OS_VXWORKS +#ifndef __INCvxWorksh +#include +#endif +#endif + +/* + Conversion from pointer to interger and back. + + On 64-bit systems, pointers are long ints + On 32-bit systems, pointers are int + + Never use direct casting, since the code might then + not be portable between 32-bit and 64-bit systems + +*/ +#if defined(__alpha) || defined(_LP64) +#define POINTER_T long int +#else +#define POINTER_T int +#endif + +/* define old PTYPE for compatibility with old code */ +#define PTYPE POINTER_T + +/* need system-dependant thread type */ +#if defined(OS_WINNT) +typedef HANDLE midas_thread_t; +#elif defined(OS_UNIX) +#include +typedef pthread_t midas_thread_t; +#else +typedef INT midas_thread_t; +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* directory separator */ +#if defined(OS_MSDOS) || defined(OS_WINNT) +#define DIR_SEPARATOR '\\' +#define DIR_SEPARATOR_STR "\\" +#elif defined(OS_VMS) +#define DIR_SEPARATOR ']' +#define DIR_SEPARATOR_STR "]" +#else +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#endif + +/* inline functions */ +#if defined( _MSC_VER ) +#define INLINE __inline +#elif defined(__GNUC__) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else +#define INLINE +#endif + +/* large file (>2GB) support */ +#ifndef _LARGEFILE64_SOURCE +#define O_LARGEFILE 0 +#endif + +/* disable "deprecated" warning */ +#if defined( _MSC_VER ) +#pragma warning( disable: 4996) +#endif + +#if defined __GNUC__ +#define MATTRPRINTF(a, b) __attribute__ ((format (printf, a, b))) +#else +#define MATTRPRINTF(a, b) +#endif + +/* mutex definitions */ +#if defined(OS_WINNT) +typedef HANDLE MUTEX_T; +#elif defined(OS_LINUX) +typedef pthread_mutex_t MUTEX_T; +#else +typedef INT MUTEX_T; +#endif + +/* OSX brings its own strlcpy/stlcat */ +#ifdef OS_DARWIN +#ifndef HAVE_STRLCPY +#define HAVE_STRLCPY 1 +#endif +#endif + +#ifdef __cplusplus +#include +#include +typedef std::vector STRING_LIST; +#endif + +/**dox***************************************************************/ +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +/*------------------------------------------------------------------*/ + +/* Definition of implementation specific constants */ + +#define DEFAULT_MAX_EVENT_SIZE (4*1024*1024) /**< default maximum event size 4MiB, actual maximum event size is set by ODB /Experiment/MAX_EVENT_SIZE */ +#define DEFAULT_BUFFER_SIZE (32*1024*1024) /**< default event buffer size 32MiB, actual event buffer size is set by ODB /Experiment/Buffer sizes/SYSTEM */ + +#ifdef OS_WINNT +#define TAPE_BUFFER_SIZE 0x100000 /**< buffer size for taping data */ +#else +#define TAPE_BUFFER_SIZE 0x8000 /**< buffer size for taping data */ +#endif +#define NET_TCP_SIZE 0xFFFF /**< maximum TCP transfer size */ +#define OPT_TCP_SIZE 8192 /**< optimal TCP buffer size */ +#define NET_UDP_SIZE 8192 /**< maximum UDP transfer */ + +#define EVENT_BUFFER_NAME "SYSTEM" /**< buffer name for commands */ +#define DEFAULT_ODB_SIZE 0x100000 /**< online database 1M */ + +#define NAME_LENGTH 32 /**< length of names, mult.of 8! */ +#define HOST_NAME_LENGTH 256 /**< length of TCP/IP names */ +#define MAX_CLIENTS 64 /**< client processes per buf/db */ +#define MAX_EVENT_REQUESTS 10 /**< event requests per client */ +#define MAX_OPEN_RECORDS 256 /**< number of open DB records */ +#define MAX_ODB_PATH 256 /**< length of path in ODB */ +#define MAX_EXPERIMENT 32 /**< number of different exp. */ +#define BANKLIST_MAX 4096 /**< max # of banks in event */ +#define STRING_BANKLIST_MAX BANKLIST_MAX * 4 /**< for bk_list() */ + + +#define MIDAS_TCP_PORT 1177 /* port under which server is listening */ + /* MODIFIED RA36 10-DEC-2018 was initially 1175 */ + +/** +Timeouts [ms] */ +#define DEFAULT_RPC_TIMEOUT 60000 /* RA36 10-DEC-2018 was 10000 */ +#define WATCHDOG_INTERVAL 1000 + +#define DEFAULT_WATCHDOG_TIMEOUT 60000 /**< Watchdog RA36 10-DEC-2018 was 10000 */ + +#define USE_HIDDEN_EQ /**< Use hidden equipment in status page */ + +/*------------------------------------------------------------------*/ + +/* Enumeration definitions */ + +/**dox***************************************************************/ +/** @addtogroup mdefineh + * + * @{ */ + +/** +System states */ +#define STATE_STOPPED 1 /**< MIDAS run stopped */ +#define STATE_PAUSED 2 /**< MIDAS run paused */ +#define STATE_RUNNING 3 /**< MIDAS run running */ + +/** +Data format */ +#define FORMAT_MIDAS 1 /**< MIDAS banks */ +#define FORMAT_YBOS 2 /**< YBOS banks */ +#define FORMAT_ASCII 3 /**< ASCII format */ +#define FORMAT_FIXED 4 /**< Fixed length binary records */ +#define FORMAT_DUMP 5 /**< Dump (detailed ASCII) format */ +#define FORMAT_HBOOK 6 /**< CERN hbook (rz) format */ +#define FORMAT_ROOT 7 /**< CERN ROOT format */ + +/** +Event Sampling type */ +#define GET_ALL (1<<0) /**< get all events (consume) */ +#define GET_NONBLOCKING (1<<1)/**< get as much as possible without blocking producer */ +#define GET_RECENT (1<<2) /**< get recent event (not older than 1 s)*/ + +/** +Data types Definition min max */ +#define TID_BYTE 1 /**< unsigned byte 0 255 */ +#define TID_SBYTE 2 /**< signed byte -128 127 */ +#define TID_CHAR 3 /**< single character 0 255 */ +#define TID_WORD 4 /**< two bytes 0 65535 */ +#define TID_SHORT 5 /**< signed word -32768 32767 */ +#define TID_DWORD 6 /**< four bytes 0 2^32-1 */ +#define TID_INT 7 /**< signed dword -2^31 2^31-1 */ +#define TID_BOOL 8 /**< four bytes bool 0 1 */ +#define TID_FLOAT 9 /**< 4 Byte float format */ +#define TID_DOUBLE 10 /**< 8 Byte float format */ +#define TID_BITFIELD 11 /**< 32 Bits Bitfield 0 111... (32) */ +#define TID_STRING 12 /**< zero terminated string */ +#define TID_ARRAY 13 /**< array with unknown contents */ +#define TID_STRUCT 14 /**< structure with fixed length */ +#define TID_KEY 15 /**< key in online database */ +#define TID_LINK 16 /**< link in online database */ +#define TID_LAST 17 /**< end of TID list indicator */ + +/** +Transition flags */ +#define TR_SYNC 1 +#define TR_ASYNC 2 +#define TR_DETACH 4 +#define TR_MTHREAD 8 + +/** +Synchronous / Asynchronous flags */ +#define BM_WAIT 0 +#define BM_NO_WAIT 1 + +/** +Access modes */ +#define MODE_READ (1<<0) +#define MODE_WRITE (1<<1) +#define MODE_DELETE (1<<2) +#define MODE_EXCLUSIVE (1<<3) +#define MODE_ALLOC (1<<6) +#define MODE_WATCH (1<<7) + +/** +RPC options */ +#define RPC_OTIMEOUT 1 +#define RPC_OTRANSPORT 2 +#define RPC_OCONVERT_FLAG 3 +#define RPC_OHW_TYPE 4 +#define RPC_OSERVER_TYPE 5 +#define RPC_OSERVER_NAME 6 +#define RPC_CONVERT_FLAGS 7 +#define RPC_ODB_HANDLE 8 +#define RPC_CLIENT_HANDLE 9 +#define RPC_SEND_SOCK 10 +#define RPC_WATCHDOG_TIMEOUT 11 +#define RPC_NODELAY 12 + +#define RPC_TCP 0 +#define RPC_FTCP 1 + +/** +Watchdog flags */ +#define WF_WATCH_ME (1<<0) /* see cm_set_watchdog_flags */ +#define WF_CALL_WD (1<<1) + +/** +Transitions values */ +#define TR_START (1<<0) /**< Start transition */ +#define TR_STOP (1<<1) /**< Stop transition */ +#define TR_PAUSE (1<<2) /**< Pause transition */ +#define TR_RESUME (1<<3) /**< Resume transition */ +#define TR_STARTABORT (1<<4) /**< Start aborted transition */ +#define TR_DEFERRED (1<<12) + +/** +Equipment types */ +#define EQ_PERIODIC (1<<0) /**< Periodic Event */ +#define EQ_POLLED (1<<1) /**< Polling Event */ +#define EQ_INTERRUPT (1<<2) /**< Interrupt Event */ +#define EQ_MULTITHREAD (1<<3) /**< Multithread Event readout */ +#define EQ_SLOW (1<<4) /**< Slow Control Event */ +#define EQ_MANUAL_TRIG (1<<5) /**< Manual triggered Event */ +#define EQ_FRAGMENTED (1<<6) /**< Fragmented Event */ +#define EQ_EB (1<<7) /**< Event run through the event builder */ +#define EQ_USER (1<<8) /**< Polling handled in user part */ + +/** +Read - On flags */ +#define RO_RUNNING (1<<0) /**< While running */ +#define RO_STOPPED (1<<1) /**< Before stopping the run */ +#define RO_PAUSED (1<<2) /**< ??? */ +#define RO_BOR (1<<3) /**< At the Begin of run */ +#define RO_EOR (1<<4) /**< At the End of run */ +#define RO_PAUSE (1<<5) /**< Before pausing the run */ +#define RO_RESUME (1<<6) /**< Before resuming the run */ + +#define RO_TRANSITIONS (RO_BOR|RO_EOR|RO_PAUSE|RO_RESUME) /**< At all transitions */ +#define RO_ALWAYS (0xFF) /**< Always (independent of the run status) */ + +#define RO_ODB (1<<8) /**< Submit data to ODB only */ + +/**dox***************************************************************/ + /** @} *//* end of mdefineh */ + +/** +special characters */ +#define CH_BS 8 +#define CH_TAB 9 +#define CH_CR 13 + +#define CH_EXT 0x100 + +#define CH_HOME (CH_EXT+0) +#define CH_INSERT (CH_EXT+1) +#define CH_DELETE (CH_EXT+2) +#define CH_END (CH_EXT+3) +#define CH_PUP (CH_EXT+4) +#define CH_PDOWN (CH_EXT+5) +#define CH_UP (CH_EXT+6) +#define CH_DOWN (CH_EXT+7) +#define CH_RIGHT (CH_EXT+8) +#define CH_LEFT (CH_EXT+9) + +/* event sources in equipment */ +/** +Code the LAM crate and LAM station into a bitwise register. +@param c Crate number +@param s Slot number +*/ +#define LAM_SOURCE(c, s) (c<<24 | ((s) & 0xFFFFFF)) + +/** +Code the Station number bitwise for the LAM source. +@param s Slot number +*/ +#define LAM_STATION(s) (1<<(s-1)) + +/** +Convert the coded LAM crate to Crate number. +@param c coded crate +*/ +#define LAM_SOURCE_CRATE(c) (c>>24) + +/** +Convert the coded LAM station to Station number. +@param s Slot number +*/ +#define LAM_SOURCE_STATION(s) ((s) & 0xFFFFFF) + +/** +CNAF commands */ +#define CNAF 0x1 /* normal read/write */ +#define CNAF_nQ 0x2 /* Repeat read until noQ */ + +#define CNAF_INHIBIT_SET 0x100 +#define CNAF_INHIBIT_CLEAR 0x101 +#define CNAF_CRATE_CLEAR 0x102 +#define CNAF_CRATE_ZINIT 0x103 +#define CNAF_TEST 0x110 + +/**dox***************************************************************/ +/** @addtogroup mmacroh + * + * @{ + */ + +/** +MAX */ +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +/** +MIN */ +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +/*------------------------------------------------------------------*/ + +/** +Align macro for data alignment on 8-byte boundary */ +#define ALIGN8(x) (((x)+7) & ~7) + +/** +Align macro for variable data alignment */ +#define VALIGN(adr,align) (((POINTER_T) (adr)+align-1) & ~(align-1)) + +/**dox***************************************************************/ + /** @} *//* end of mmacroh */ + +/**dox***************************************************************/ +/** @addtogroup mdefineh + * + * @{ */ +/* +* Bit flags */ +#define EVENTID_ALL -1 /* any event id */ +#define TRIGGER_ALL -1 /* any type of trigger */ + +/** +System message types */ +#define MT_ERROR (1<<0) /**< - */ +#define MT_INFO (1<<1) /**< - */ +#define MT_DEBUG (1<<2) /**< - */ +#define MT_USER (1<<3) /**< - */ +#define MT_LOG (1<<4) /**< - */ +#define MT_TALK (1<<5) /**< - */ +#define MT_CALL (1<<6) /**< - */ +#define MT_ALL 0xFF /**< - */ + +#define MT_ERROR_STR "ERROR" +#define MT_INFO_STR "INFO" +#define MT_DEBUG_STR "DEBUG" +#define MT_USER_STR "USER" +#define MT_LOG_STR "LOG" +#define MT_TALK_STR "TALK" +#define MT_CALL_STR "CALL" + +#define MERROR MT_ERROR, __FILE__, __LINE__ /**< - */ +#define MINFO MT_INFO, __FILE__, __LINE__ /**< - */ +#define MDEBUG MT_DEBUG, __FILE__, __LINE__ /**< - */ +#define MUSER MT_USER, __FILE__, __LINE__ /**< produced by interactive user */ +#define MLOG MT_LOG, __FILE__, __LINE__ /**< info message which is only logged */ +#define MTALK MT_TALK, __FILE__, __LINE__ /**< info message for speech system */ +#define MCALL MT_CALL, __FILE__, __LINE__ /**< info message for telephone call */ + +/**dox***************************************************************/ + /** @} *//* end of mdefineh */ + + +/**dox***************************************************************/ +/** @addtogroup mdeferrorh + * + * @{ + */ + +/**dox***************************************************************/ +/** + @defgroup err21 Status and error codes + @{ */ +#define SUCCESS 1 /**< Success */ +#define CM_SUCCESS 1 /**< Same */ +#define CM_SET_ERROR 102 /**< set */ +#define CM_NO_CLIENT 103 /**< nobody */ +#define CM_DB_ERROR 104 /**< db access error */ +#define CM_UNDEF_EXP 105 /**< - */ +#define CM_VERSION_MISMATCH 106 /**< - */ +#define CM_SHUTDOWN 107 /**< - */ +#define CM_WRONG_PASSWORD 108 /**< - */ +#define CM_UNDEF_ENVIRON 109 /**< - */ +#define CM_DEFERRED_TRANSITION 110 /**< - */ +#define CM_TRANSITION_IN_PROGRESS 111 /**< - */ +#define CM_TIMEOUT 112 /**< - */ +#define CM_INVALID_TRANSITION 113 /**< - */ +#define CM_TOO_MANY_REQUESTS 114 /**< - */ +#define CM_TRUNCATED 115 /**< - */ +#define CM_INVALID_DIR 116 /**< - */ /* START MOD RA36 10-DEC-2018 */ +#define CM_NO_SUBPROCESS 117 /**< - */ /* END MOD RA36 10-DEC-2018 */ +#define CM_INVALID_VERSION 118 /**< - */ /* MOD RA36 25-APR-2019 */ +/**dox***************************************************************/ + /** @} *//* end of err21 */ + +/**dox***************************************************************/ +/** + @defgroup err22 Buffer Manager error codes + @{ */ +#define BM_SUCCESS 1 /**< - */ +#define BM_CREATED 202 /**< - */ +#define BM_NO_MEMORY 203 /**< - */ +#define BM_INVALID_NAME 204 /**< - */ +#define BM_INVALID_HANDLE 205 /**< - */ +#define BM_NO_SLOT 206 /**< - */ +#define BM_NO_SEMAPHORE 207 /**< - */ +#define BM_NOT_FOUND 208 /**< - */ +#define BM_ASYNC_RETURN 209 /**< - */ +#define BM_TRUNCATED 210 /**< - */ +#define BM_MULTIPLE_HOSTS 211 /**< - */ +#define BM_MEMSIZE_MISMATCH 212 /**< - */ +#define BM_CONFLICT 213 /**< - */ +#define BM_EXIT 214 /**< - */ +#define BM_INVALID_PARAM 215 /**< - */ +#define BM_MORE_EVENTS 216 /**< - */ +#define BM_INVALID_MIXING 217 /**< - */ +#define BM_NO_SHM 218 /**< - */ +/**dox***************************************************************/ + /** @} *//* end of group 22 */ + +/**dox***************************************************************/ +/** @defgroup err23 Online Database error codes +@{ */ +#define DB_SUCCESS 1 /**< - */ +#define DB_CREATED 302 /**< - */ +#define DB_NO_MEMORY 303 /**< - */ +#define DB_INVALID_NAME 304 /**< - */ +#define DB_INVALID_HANDLE 305 /**< - */ +#define DB_NO_SLOT 306 /**< - */ +#define DB_NO_SEMAPHORE 307 /**< - */ +#define DB_MEMSIZE_MISMATCH 308 /**< - */ +#define DB_INVALID_PARAM 309 /**< - */ +#define DB_FULL 310 /**< - */ +#define DB_KEY_EXIST 311 /**< - */ +#define DB_NO_KEY 312 /**< - */ +#define DB_KEY_CREATED 313 /**< - */ +#define DB_TRUNCATED 314 /**< - */ +#define DB_TYPE_MISMATCH 315 /**< - */ +#define DB_NO_MORE_SUBKEYS 316 /**< - */ +#define DB_FILE_ERROR 317 /**< - */ +#define DB_NO_ACCESS 318 /**< - */ +#define DB_STRUCT_SIZE_MISMATCH 319 /**< - */ +#define DB_OPEN_RECORD 320 /**< - */ +#define DB_OUT_OF_RANGE 321 /**< - */ +#define DB_INVALID_LINK 322 /**< - */ +#define DB_CORRUPTED 323 /**< - */ +#define DB_STRUCT_MISMATCH 324 /**< - */ +#define DB_TIMEOUT 325 /**< - */ +#define DB_VERSION_MISMATCH 326 /**< - */ +/**dox***************************************************************/ + /** @} *//* end of group 23 */ + +/**dox***************************************************************/ +/** @defgroup err24 System Services error code +@{ */ +#define SS_SUCCESS 1 /**< - */ +#define SS_CREATED 402 /**< - */ +#define SS_NO_MEMORY 403 /**< - */ +#define SS_INVALID_NAME 404 /**< - */ +#define SS_INVALID_HANDLE 405 /**< - */ +#define SS_INVALID_ADDRESS 406 /**< - */ +#define SS_FILE_ERROR 407 /**< - */ +#define SS_NO_SEMAPHORE 408 /**< - */ +#define SS_NO_PROCESS 409 /**< - */ +#define SS_NO_THREAD 410 /**< - */ +#define SS_SOCKET_ERROR 411 /**< - */ +#define SS_TIMEOUT 412 /**< - */ +#define SS_SERVER_RECV 413 /**< - */ +#define SS_CLIENT_RECV 414 /**< - */ +#define SS_ABORT 415 /**< - */ +#define SS_EXIT 416 /**< - */ +#define SS_NO_TAPE 417 /**< - */ +#define SS_DEV_BUSY 418 /**< - */ +#define SS_IO_ERROR 419 /**< - */ +#define SS_TAPE_ERROR 420 /**< - */ +#define SS_NO_DRIVER 421 /**< - */ +#define SS_END_OF_TAPE 422 /**< - */ +#define SS_END_OF_FILE 423 /**< - */ +#define SS_FILE_EXISTS 424 /**< - */ +#define SS_NO_SPACE 425 /**< - */ +#define SS_INVALID_FORMAT 426 /**< - */ +#define SS_NO_ROOT 427 /**< - */ +#define SS_SIZE_MISMATCH 428 /**< - */ +#define SS_NO_MUTEX 429 /**< - */ +/* START MOD RA36 10-DEC-2018 */ +#define SS_DIR_NOT_FOUND 440 /**< - */ +#define SS_DIR_EMPTY 441 /**< - */ +#define SS_NOT_IMPLEMENTED 442 /**< - */ +#define SS_INVALID_SIZE 443 /**< - */ +#define SS_INVALID_PARAM 444 /**< - */ +/* START MOD RA36 10-DEC-2018 */ + +/**dox***************************************************************/ + /** @} *//* end of group 24 */ + +/**dox***************************************************************/ +/** @defgroup err25 Remote Procedure Calls error codes +@{ */ +#define RPC_SUCCESS 1 /**< - */ +#define RPC_ABORT SS_ABORT /**< - */ +#define RPC_NO_CONNECTION 502 /**< - */ +#define RPC_NET_ERROR 503 /**< - */ +#define RPC_TIMEOUT 504 /**< - */ +#define RPC_EXCEED_BUFFER 505 /**< - */ +#define RPC_NOT_REGISTERED 506 /**< - */ +#define RPC_CONNCLOSED 507 /**< - */ +#define RPC_INVALID_ID 508 /**< - */ +#define RPC_SHUTDOWN 509 /**< - */ +#define RPC_NO_MEMORY 510 /**< - */ +#define RPC_DOUBLE_DEFINED 511 /**< - */ +#define RPC_MUTEX_TIMEOUT 512 /**< - */ +/**dox***************************************************************/ + /** @} *//* end of group 25 */ + +/**dox***************************************************************/ +/** @defgroup err26 Other errors +@{ */ +#define FE_SUCCESS 1 /**< - */ +#define FE_ERR_ODB 602 /**< - */ +#define FE_ERR_HW 603 /**< - */ +#define FE_ERR_DISABLED 604 /**< - */ +#define FE_ERR_DRIVER 605 /**< - */ +#define FE_PARTIALLY_DISABLED 606 /**< - */ + +/** +History error code */ +#define HS_SUCCESS 1 /**< - */ +#define HS_FILE_ERROR 702 /**< - */ +#define HS_NO_MEMORY 703 /**< - */ +#define HS_TRUNCATED 704 /**< - */ +#define HS_WRONG_INDEX 705 /**< - */ +#define HS_UNDEFINED_EVENT 706 /**< - */ +#define HS_UNDEFINED_VAR 707 /**< - */ +#define HS_FILE_NOT_FOUND 708 /**< - */ + +/** +FTP error code */ +#define FTP_SUCCESS 1 /**< - */ +#define FTP_NET_ERROR 802 /**< - */ +#define FTP_FILE_ERROR 803 /**< - */ +#define FTP_RESPONSE_ERROR 804 /**< - */ +#define FTP_INVALID_ARG 805 /**< - */ + +/** +ELog error code */ +#define EL_SUCCESS 1 /**< - */ +#define EL_FILE_ERROR 902 /**< - */ +#define EL_NO_MESSAGE 903 /**< - */ +#define EL_TRUNCATED 904 /**< - */ +#define EL_FIRST_MSG 905 /**< - */ +#define EL_LAST_MSG 906 /**< - */ + +/** +Alarm error code */ +#define AL_SUCCESS 1 /**< - */ +#define AL_INVALID_NAME 1002 /**< - */ +#define AL_ERROR_ODB 1003 /**< - */ +#define AL_RESET 1004 /**< - */ +#define AL_TRIGGERED 1005 /**< - */ + +/* START MOD RA36 10-DEC-2018 */ +/** + * * BE commands */ +#define BE_SUCCESS 1 /**< - */ +#define BE_FILE_ERROR 1102 /**< - */ +#define BE_NO_MEMORY 1103 /**< - */ +#define BE_INVALID_ADDRESS 1104 /**< - */ +#define BE_INVALID_NAME 1105 /**< - */ +#define BE_INVALID_PARAM 1106 /**< - */ +#define BE_INVALID_HANDLE 1107 /**< - */ +#define BE_INVALID_BUFFER 1108 /**< - */ +#define BE_INVALID_BUFSIZ 1109 /**< - */ +#define CM_FILE_EXISTS 1110 /**< - */ +#define CM_FILE_NOT_FOUND 1111 /**< - */ +/* END MOD RA36 10-DEC-2018 */ + +/** +Slow control device driver commands */ +#define CMD_INIT 1 /* misc. commands must be below 20 !! */ +#define CMD_EXIT 2 +#define CMD_START 3 +#define CMD_STOP 4 +#define CMD_IDLE 5 +#define CMD_GET_THRESHOLD 6 +#define CMD_GET_THRESHOLD_CURRENT 7 +#define CMD_GET_THRESHOLD_ZERO 8 +#define CMD_SET_LABEL 9 +#define CMD_GET_LABEL 10 +#define CMD_OPEN 11 +#define CMD_CLOSE 12 +#define CMD_MISC_LAST 12 /* update this if you add new commands */ + +#define CMD_SET_FIRST CMD_MISC_LAST+1 /* set commands */ +#define CMD_SET CMD_SET_FIRST // = 13 +#define CMD_SET_VOLTAGE_LIMIT CMD_SET_FIRST+1 +#define CMD_SET_CURRENT_LIMIT CMD_SET_FIRST+2 +#define CMD_SET_RAMPUP CMD_SET_FIRST+3 +#define CMD_SET_RAMPDOWN CMD_SET_FIRST+4 +#define CMD_SET_TRIP_TIME CMD_SET_FIRST+5 +#define CMD_SET_CHSTATE CMD_SET_FIRST+6 +#define CMD_SET_LAST CMD_SET_FIRST+6 /* update this if you add new commands */ + +#define CMD_GET_FIRST CMD_SET_LAST+1 /* multithreaded get commands */ +#define CMD_GET CMD_GET_FIRST // = 20 +#define CMD_GET_CURRENT CMD_GET_FIRST+1 +#define CMD_GET_TRIP CMD_GET_FIRST+2 +#define CMD_GET_STATUS CMD_GET_FIRST+3 +#define CMD_GET_TEMPERATURE CMD_GET_FIRST+4 +#define CMD_GET_LAST CMD_GET_FIRST+4 /* update this if you add new commands ! */ + +#define CMD_GET_DIRECT CMD_GET_LAST+1 /* direct get commands */ +#define CMD_GET_DEMAND CMD_GET_DIRECT // = 25 +#define CMD_GET_VOLTAGE_LIMIT CMD_GET_DIRECT+1 +#define CMD_GET_CURRENT_LIMIT CMD_GET_DIRECT+2 +#define CMD_GET_RAMPUP CMD_GET_DIRECT+3 +#define CMD_GET_RAMPDOWN CMD_GET_DIRECT+4 +#define CMD_GET_TRIP_TIME CMD_GET_DIRECT+5 +#define CMD_GET_CHSTATE CMD_GET_DIRECT+6 +#define CMD_GET_CRATEMAP CMD_GET_DIRECT+7 +#define CMD_GET_DIRECT_LAST CMD_GET_DIRECT+7 /* update this if you add new commands ! */ + +#define CMD_ENABLE_COMMAND (1<<14) /* these two commands can be used to enable/disable */ +#define CMD_DISABLE_COMMAND (1<<15) /* one of the other commands */ + +/** +Slow control bus driver commands */ +#define CMD_WRITE 100 +#define CMD_READ 101 +#define CMD_PUTS 102 +#define CMD_GETS 103 +#define CMD_DEBUG 104 +#define CMD_NAME 105 + +/** +Commands for interrupt events */ +#define CMD_INTERRUPT_ENABLE 100 +#define CMD_INTERRUPT_DISABLE 101 +#define CMD_INTERRUPT_ATTACH 102 +#define CMD_INTERRUPT_DETACH 103 + +/** +macros for bus driver access */ +#define BD_GETS(s,z,p,t) info->bd(CMD_GETS, info->bd_info, s, z, p, t) +#define BD_READS(s,z,t) info->bd(CMD_READ, info->bd_info, s, z, t) +#define BD_PUTS(s) info->bd(CMD_PUTS, info->bd_info, s) +#define BD_WRITES(s,z) info->bd(CMD_WRITE, info->bd_info, s, z) /* MOD RA36 10-DEC-2018 added z */ + +/**dox***************************************************************/ + /** @} *//* end of 26 */ + +/**dox***************************************************************/ + /** @} *//* end of mdeferrorh */ + + +#define ANA_CONTINUE 1 +#define ANA_SKIP 0 + +/* START MOD RA36 10-DEC-2018 */ +/* size of find file list */ +#define BE_FF_LIST_SIZE 512 + +/* Back end commands */ +#define BE_FIRST_CMD_STR "FIRST" +#define BE_LAST_CMD_STR "LAST" +#define BE_NEXT_CMD_STR "NEXT" +#define BE_LINE_CMD_STR "LINE=" /* LINE=%d */ +#define BE_ENTRY_CMD_STR "ENTRY=" /* ENTRY=%d */ + +/* Back end returned */ +#define BE_FIRST_RET_STR "FIRST=" +#define BE_LAST_RET_STR "LAST=" +#define BE_NEXT_RET_STR "NEXT=" +#define BE_LINE_RET_STR "LINE" /* LINE%d= */ +#define BE_EOF_RET_STR "EOF=" +#define BE_ERROR_RET_STR "ERROR=" +#define BE_UNKNOWN_RET_STR "UNKNOWN=" +#define BE_ENTRY_RET_STR "ENTRY" /* ENTRY%d= */ +#define BE_END_RET_STR "END=" + +/* ss_file_find flags */ +#define SS_FF_NONE 0 +#define SS_FF_DIR 1 +#define SS_FF_FILE 2 +#define SS_FF_EXTENSION 4 +#define SS_FF_VERSION 8 + +#define SS_FF_ALL ~SS_FF_NONE +/* END MOD RA36 10-DEC-2018 */ + +/*---- Buffer manager structures -----------------------------------*/ + +/**dox***************************************************************/ +/** @addtogroup msectionh + * + * @{ */ + +/**dox***************************************************************/ +/** @defgroup mbufferh Buffer Section + * @{ */ +/** +Event header */ +typedef struct { + short int event_id; /**< event ID starting from one */ + short int trigger_mask; /**< hardware trigger mask */ + DWORD serial_number; /**< serial number starting from one */ + DWORD time_stamp; /**< time of production of event */ + DWORD data_size; /**< size of event in bytes w/o header */ +} EVENT_HEADER; + +/** +TRIGGER_MASK +Extract or set the trigger mask field pointed by the argument. +@param e pointer to the midas event (pevent) +*/ +#define TRIGGER_MASK(e) ((((EVENT_HEADER *) e)-1)->trigger_mask) + +/** +EVENT_ID +Extract or set the event ID field pointed by the argument.. +@param e pointer to the midas event (pevent) +*/ +#define EVENT_ID(e) ((((EVENT_HEADER *) e)-1)->event_id) + +/** +SERIAL_NUMBER +Extract or set/reset the serial number field pointed by the argument. +@param e pointer to the midas event (pevent) +*/ +#define SERIAL_NUMBER(e) ((((EVENT_HEADER *) e)-1)->serial_number) + +/** +TIME_STAMP +Extract or set/reset the time stamp field pointed by the argument. +@param e pointer to the midas event (pevent) +*/ +#define TIME_STAMP(e) ((((EVENT_HEADER *) e)-1)->time_stamp) + +/** +DATA_SIZE +Extract or set/reset the data size field pointed by the argument. +@param e pointer to the midas event (pevent) +*/ +#define DATA_SIZE(e) ((((EVENT_HEADER *) e)-1)->data_size) + +#define EVENT_SOURCE(e,o) (* (INT*) (e+o)) + +/** +system event IDs */ +#define EVENTID_BOR ((short int) 0x8000) /**< Begin-of-run */ +#define EVENTID_EOR ((short int) 0x8001) /**< End-of-run */ +#define EVENTID_MESSAGE ((short int) 0x8002) /**< Message events */ + +/** +fragmented events */ +#define EVENTID_FRAG1 ((unsigned short) 0xC000) /* first fragment */ +#define EVENTID_FRAG ((unsigned short) 0xD000) /* added to real event-id */ + +/** +magic number used in trigger_mask for BOR event */ +#define MIDAS_MAGIC 0x494d /**< 'MI' */ + + +/** +Buffer structure */ +typedef struct { + INT id; /**< request id */ + BOOL valid; /**< indicating a valid entry */ + short int event_id; /**< event ID */ + short int trigger_mask; /**< trigger mask */ + INT sampling_type; /**< GET_ALL, GET_NONBLOCKING, GET_RECENT */ +} EVENT_REQUEST; + +typedef struct { + char name[NAME_LENGTH]; /**< name of client */ + INT pid; /**< process ID */ + INT unused0; /**< was thread ID */ + INT unused; /**< was thread handle */ + INT port; /**< UDP port for wake up */ + INT read_pointer; /**< read pointer to buffer */ + INT max_request_index; /**< index of last request */ + INT num_received_events; /**< no of received events */ + INT num_sent_events; /**< no of sent events */ + INT num_waiting_events; /**< no of waiting events */ + float data_rate; /**< data rate in kB/sec */ + BOOL read_wait; /**< wait for read - flag */ + INT write_wait; /**< wait for write # bytes */ + BOOL wake_up; /**< client got a wake-up msg */ + BOOL all_flag; /**< at least one GET_ALL request */ + DWORD last_activity; /**< time of last activity */ + DWORD watchdog_timeout; /**< timeout in ms */ + + EVENT_REQUEST event_request[MAX_EVENT_REQUESTS]; + +} BUFFER_CLIENT; + +typedef struct { + char name[NAME_LENGTH]; /**< name of buffer */ + INT num_clients; /**< no of active clients */ + INT max_client_index; /**< index of last client */ + INT size; /**< size of data area in bytes */ + INT read_pointer; /**< read pointer */ + INT write_pointer; /**< write pointer */ + INT num_in_events; /**< no of received events */ + INT num_out_events; /**< no of distributed events */ + + BUFFER_CLIENT client[MAX_CLIENTS]; /**< entries for clients */ + +} BUFFER_HEADER; + +/* Per-process buffer access structure (descriptor) */ + +typedef struct { + BOOL attached; /**< TRUE if buffer is attached */ + INT client_index; /**< index to CLIENT str. in buf. */ + BUFFER_HEADER *buffer_header; /**< pointer to buffer header */ + void *buffer_data; /**< pointer to buffer data */ + char *read_cache; /**< cache for burst read */ + INT read_cache_size; /**< cache size in bytes */ + INT read_cache_rp; /**< cache read pointer */ + INT read_cache_wp; /**< cache write pointer */ + char *write_cache; /**< cache for burst read */ + INT write_cache_size; /**< cache size in bytes */ + INT write_cache_rp; /**< cache read pointer */ + INT write_cache_wp; /**< cache write pointer */ + HNDLE semaphore; /**< semaphore handle */ + INT shm_handle; /**< handle to shared memory */ + INT index; /**< connection index / tid */ + BOOL callback; /**< callback defined for this buffer */ + +} BUFFER; + +typedef struct { + DWORD type; /**< TID_xxx type */ + INT num_values; /**< number of values */ + char name[NAME_LENGTH]; /**< name of variable */ + INT data; /**< Address of variable (offset) */ + INT total_size; /**< Total size of data block */ + INT item_size; /**< Size of single data item */ + WORD access_mode; /**< Access mode */ + WORD notify_count; /**< Notify counter */ + INT next_key; /**< Address of next key */ + INT parent_keylist; /**< keylist to which this key belongs */ + INT last_written; /**< Time of last write action */ +} KEY; + +typedef struct { + INT parent; /**< Address of parent key */ + INT num_keys; /**< number of keys */ + INT first_key; /**< Address of first key */ +} KEYLIST; + +/**dox***************************************************************/ + /** @} *//* end of mbufferh */ + +/*---- Equipment ---------------------------------------------------*/ + +/**dox***************************************************************/ +/** @defgroup mequipment Equipment related + * @{ */ + +#define DF_INPUT (1<<0) /**< channel is input */ +#define DF_OUTPUT (1<<1) /**< channel is output */ +#define DF_PRIO_DEVICE (1<<2) /**< get demand values from device instead of ODB */ +#define DF_READ_ONLY (1<<3) /**< never write demand values to device */ +#define DF_MULTITHREAD (1<<4) //*< access device with a dedicated thread */ +#define DF_HW_RAMP (1<<5) //*< high voltage device can do hardware ramping */ +#define DF_LABELS_FROM_DEVICE (1<<6) //*< pull HV channel names from device */ +#define DF_REPORT_TEMP (1<<7) //*< report temperature from HV cards */ +#define DF_REPORT_STATUS (1<<8) //*< report status word from HV channels */ +#define DF_REPORT_CHSTATE (1<<9) //*< report channel state word from HV channels */ +#define DF_REPORT_CRATEMAP (1<<10) //*< reports an integer encoding size and occupancy of HV crate */ +#define DF_ALW_DEVICE (1<<11) /**< update ODB demand values reading it from device */ /* RA36 */ +#define DF_NOUPDALL (1<<12) /**< do not update all demand values if no change was found */ /* RA36 */ + + +typedef struct { + char name[NAME_LENGTH]; /**< Driver name */ + INT(*bd) (INT cmd, ...); /**< Device driver entry point */ + void *bd_info; /**< Private info for bus driver */ +} BUS_DRIVER; + +typedef struct { + float variable[CMD_GET_LAST+1]; /**< Array for various values */ + char label[NAME_LENGTH]; /**< Array for channel labels */ +} DD_MT_CHANNEL; + +typedef struct { + INT n_channels; /**< Number of channels */ + midas_thread_t thread_id; /**< Thread ID */ + INT status; /**< Status passed from device thread */ + DD_MT_CHANNEL *channel; /**< One data set for each channel */ + +} DD_MT_BUFFER; + +typedef struct { + WORD event_id; /**< Event ID associated with equipm. */ + WORD trigger_mask; /**< Trigger mask */ + char buffer[NAME_LENGTH]; /**< Event buffer to send events into */ + INT eq_type; /**< One of EQ_xxx */ + INT source; /**< Event source (LAM/IRQ) */ + char format[8]; /**< Data format to produce */ + BOOL enabled; /**< Enable flag */ + INT read_on; /**< Combination of Read-On flags RO_xxx */ + INT period; /**< Readout interval/Polling time in ms */ + double event_limit; /**< Stop run when limit is reached */ + DWORD num_subevents; /**< Number of events in super event */ + INT history; /**< Log history */ + char frontend_host[NAME_LENGTH]; /**< Host on which FE is running */ + char frontend_name[NAME_LENGTH]; /**< Frontend name */ + char frontend_file_name[256]; /**< Source file used for user FE */ + char status[256]; /**< Current status of equipment */ + char status_color[NAME_LENGTH]; /**< Color or class to be used by mhttpd for status */ + BOOL hidden; /**< Hidden flag */ +} EQUIPMENT_INFO; + +#define EQUIPMENT_COMMON_STR "\ +Event ID = WORD : 0\n\ +Trigger mask = WORD : 0\n\ +Buffer = STRING : [32] SYSTEM\n\ +Type = INT : 0\n\ +Source = INT : 0\n\ +Format = STRING : [8] FIXED\n\ +Enabled = BOOL : 0\n\ +Read on = INT : 0\n\ +Period = INT : 0\n\ +Event limit = DOUBLE : 0\n\ +Num subevents = DWORD : 0\n\ +Log history = INT : 0\n\ +Frontend host = STRING : [32] \n\ +Frontend name = STRING : [32] \n\ +Frontend file name = STRING : [256] \n\ +Status = STRING : [256] \n\ +Status color = STRING : [32] \n\ +Hidden = BOOL : 0\n\ +" + +typedef struct { + char name[NAME_LENGTH]; /**< Driver name */ + INT(*dd) (INT cmd, ...); /**< Device driver entry point */ + INT channels; /**< Number of channels */ + INT(*bd) (INT cmd, ...); /**< Bus driver entry point */ + DWORD flags; /**< Combination of DF_xx */ + BOOL enabled; /**< Enable flag */ + void *dd_info; /**< Private info for device driver */ + DD_MT_BUFFER *mt_buffer; /**< pointer to multithread buffer */ + INT stop_thread; /**< flag used to stop the thread */ + MUTEX_T *mutex; /**< mutex for buffer */ + INT semaphore; /**< semaphore for device access */ + EQUIPMENT_INFO *pequipment; /**< pointer to equipment */ +} DEVICE_DRIVER; + +INT device_driver(DEVICE_DRIVER *device_driver, INT cmd, ...); + +typedef struct { + double events_sent; + double events_per_sec; + double kbytes_per_sec; +} EQUIPMENT_STATS; + +#define EQUIPMENT_STATISTICS_STR "\ +Events sent = DOUBLE : 0\n\ +Events per sec. = DOUBLE : 0\n\ +kBytes per sec. = DOUBLE : 0\n\ +" + +typedef struct eqpmnt *PEQUIPMENT; + +typedef struct eqpmnt { + char name[NAME_LENGTH]; /**< Equipment name */ + EQUIPMENT_INFO info; /**< From above */ + INT(*readout) (char *, INT); /**< Pointer to user readout routine */ + INT(*cd) (INT cmd, PEQUIPMENT); /**< Class driver routine */ + DEVICE_DRIVER *driver; /**< Device driver list */ + void *event_descrip; /**< Init string for fixed events or bank list */ + void *cd_info; /**< private data for class driver */ + INT status; /**< One of FE_xxx */ + DWORD last_called; /**< Last time event was read */ + DWORD last_idle; /**< Last time idle func was called */ + DWORD poll_count; /**< Needed to poll 'period' */ + INT format; /**< FORMAT_xxx */ + HNDLE buffer_handle; /**< MIDAS buffer handle */ + HNDLE hkey_variables; /**< Key to variables subtree in ODB */ + DWORD serial_number; /**< event serial number */ + DWORD subevent_number; /**< subevent number */ + DWORD odb_out; /**< # updates FE -> ODB */ + DWORD odb_in; /**< # updated ODB -> FE */ + DWORD bytes_sent; /**< number of bytes sent */ + DWORD events_sent; /**< number of events sent */ + EQUIPMENT_STATS stats; +} EQUIPMENT; +/**dox***************************************************************/ + /** @} *//* end of mequipmenth */ + +/*---- Banks -------------------------------------------------------*/ + +/**dox***************************************************************/ +/** @defgroup mbank Bank related + * @{ */ + +#define BANK_FORMAT_VERSION 1 /**< - */ +#define BANK_FORMAT_32BIT (1<<4) /**< - */ + +typedef struct { + DWORD data_size; /**< Size in bytes */ + DWORD flags; /**< internal flag */ +} BANK_HEADER; + +typedef struct { + char name[4]; /**< - */ + WORD type; /**< - */ + WORD data_size; /**< - */ +} BANK; + +typedef struct { + char name[4]; /**< - */ + DWORD type; /**< - */ + DWORD data_size; /**< - */ +} BANK32; + +typedef struct { + char name[NAME_LENGTH]; /**< - */ + DWORD type; /**< - */ + DWORD n_data; /**< - */ +} TAG; + +typedef struct { + char name[9]; /**< - */ + WORD type; /**< - */ + DWORD size; /**< - */ + char **init_str; /**< - */ + BOOL output_flag; /**< - */ + void *addr; /**< - */ + DWORD n_data; /**< - */ + HNDLE def_key; /**< - */ +} BANK_LIST; +/**dox***************************************************************/ + /** @} *//* end of mbank */ + +/*---- Analyzer request --------------------------------------------*/ +/**dox***************************************************************/ +/** @defgroup manalyzer Analyzer related + * @{ */ + +typedef struct { + char name[NAME_LENGTH]; /**< Module name */ + char author[NAME_LENGTH]; /**< Author */ + INT(*analyzer) (EVENT_HEADER *, void *); + /**< Pointer to user analyzer routine */ + INT(*bor) (INT run_number); /**< Pointer to begin-of-run routine */ + INT(*eor) (INT run_number); /**< Pointer to end-of-run routine */ + INT(*init) (void); /**< Pointer to init routine */ + INT(*exit) (void); /**< Pointer to exit routine */ + void *parameters; /**< Pointer to parameter structure */ + INT param_size; /**< Size of parameter structure */ + const char **init_str; /**< Parameter init string */ + BOOL enabled; /**< Enabled flag */ + void *histo_folder; +} ANA_MODULE; + +typedef struct { + INT event_id; /**< Event ID associated with equipm. */ + INT trigger_mask; /**< Trigger mask */ + INT sampling_type; /**< GET_ALL/GET_NONBLOCKING/GET_RECENT*/ + char buffer[NAME_LENGTH]; /**< Event buffer to send events into */ + BOOL enabled; /**< Enable flag */ + char client_name[NAME_LENGTH]; /**< Analyzer name */ + char host[NAME_LENGTH]; /**< Host on which analyzer is running */ +} AR_INFO; + +typedef struct { + double events_received; + double events_per_sec; + double events_written; +} AR_STATS; + +typedef struct { + char event_name[NAME_LENGTH]; /**< Event name */ + AR_INFO ar_info; /**< From above */ + INT(*analyzer) (EVENT_HEADER *, void *);/**< Pointer to user analyzer routine */ + ANA_MODULE **ana_module; /**< List of analyzer modules */ + BANK_LIST *bank_list; /**< List of banks for event */ + INT rwnt_buffer_size; /**< Size in events of RW N-tuple buf */ + BOOL use_tests; /**< Use tests for this event */ + char **init_string; + INT status; /**< One of FE_xxx */ + HNDLE buffer_handle; /**< MIDAS buffer handle */ + HNDLE request_id; /**< Event request handle */ + HNDLE hkey_variables; /**< Key to variables subtree in ODB */ + HNDLE hkey_common; /**< Key to common subtree */ + void *addr; /**< Buffer for CWNT filling */ + struct { + DWORD run; + DWORD serial; + DWORD time; + } number; /**< Buffer for event number for CWNT */ + DWORD events_received; /**< number of events sent */ + DWORD events_written; /**< number of events written */ + AR_STATS ar_stats; + +} ANALYZE_REQUEST; + +/* output file information, maps to //Output */ +typedef struct { + char filename[256]; + BOOL rwnt; + BOOL histo_dump; + char histo_dump_filename[256]; + BOOL clear_histos; + char last_histo_filename[256]; + BOOL events_to_odb; + char global_memory_name[8]; +} ANA_OUTPUT_INFO; + +#define ANA_OUTPUT_INFO_STR "\ +Filename = STRING : [256] run%05d.asc\n\ +RWNT = BOOL : 0\n\ +Histo Dump = BOOL : 0\n\ +Histo Dump Filename = STRING : [256] his%05d.rz\n\ +Clear histos = BOOL : 1\n\ +Last Histo Filename = STRING : [256] last.rz\n\ +Events to ODB = BOOL : 1\n\ +Global Memory Name = STRING : [8] ONLN\n\ +" + +/*---- Tests -------------------------------------------------------*/ + +typedef struct { + char name[80]; + BOOL registered; + DWORD count; + DWORD previous_count; + BOOL value; +} ANA_TEST; + +#define SET_TEST(t, v) { if (!t.registered) test_register(&t); t.value = (v); } +#define TEST(t) (t.value) + +#ifdef DEFINE_TESTS +#define DEF_TEST(t) ANA_TEST t = { #t, 0, 0, FALSE }; +#else +#define DEF_TEST(t) extern ANA_TEST t; +#endif +/**dox***************************************************************/ + /** @} *//* end of manalyzer */ + +/*---- History structures ------------------------------------------*/ + +/**dox***************************************************************/ +/** @defgroup mhistoryh History related + * @{ */ + +#define RT_DATA (*((DWORD *) "HSDA")) +#define RT_DEF (*((DWORD *) "HSDF")) + +typedef struct { + DWORD record_type; /* RT_DATA or RT_DEF */ + DWORD event_id; + DWORD time; + DWORD def_offset; /* place of definition */ + DWORD data_size; /* data following this header in bytes */ +} HIST_RECORD; + +typedef struct { + DWORD event_id; + char event_name[NAME_LENGTH]; + DWORD def_offset; +} DEF_RECORD; + +typedef struct { + DWORD event_id; + DWORD time; + DWORD offset; +} INDEX_RECORD; + +typedef struct { + DWORD event_id; + char event_name[NAME_LENGTH]; + DWORD n_tag; + TAG *tag; + DWORD hist_fh; + DWORD index_fh; + DWORD def_fh; + DWORD base_time; + DWORD def_offset; +} HISTORY; +/**dox***************************************************************/ + /** @} *//* end of mhistoryh */ + +/*---- ODB runinfo -------------------------------------------------*/ + +/**dox***************************************************************/ +/** @defgroup modbh ODB runinfo related + * @{ */ +/** Contains the main parameters regarding the run status. + The containt reflects the current system ONLY if Midas clients + are connected. Otherwise the status is erroneous. +*/ +typedef struct { + INT state; /**< Current run condition */ + INT online_mode; /**< Mode of operation online/offline */ + INT run_number; /**< Current processing run number */ + INT transition_reserved; /**< Transition is reserved external to cm_transition */ /* RA36 */ + INT transition_in_progress; /**< Intermediate state during transition */ + INT start_abort; /**< Set if run start was aborted */ + INT requested_transition; /**< Deferred transition request */ + char start_time[32]; /**< ASCII of the last start time */ + DWORD start_time_binary; /**< Bin of the last start time */ + char stop_time[32]; /**< ASCII of the last stop time */ + DWORD stop_time_binary; /**< ASCII of the last stop time */ +} RUNINFO; + +#define RUNINFO_STR(_name) const char *_name[] = {\ +"[.]",\ +"State = INT : 1",\ +"Online Mode = INT : 1",\ +"Run number = INT : 0",\ +"Transition reserved = INT : 0",\ +"Transition in progress = INT : 0",\ +"Start abort = INT : 0",\ +"Requested transition = INT : 0",\ +"Start time = STRING : [32] Tue Sep 09 15:04:42 1997",\ +"Start time binary = DWORD : 0",\ +"Stop time = STRING : [32] Tue Sep 09 15:04:42 1997",\ +"Stop time binary = DWORD : 0",\ +"",\ +NULL } +/**dox***************************************************************/ + /** @} *//* end of modbh */ + +/*---- Alarm system ------------------------------------------------*/ +/**dox***************************************************************/ +/** @defgroup malarmh Alarm related + * Alarm structure. + * @{ */ + +/********************************************************************/ +/** +Program information structure */ +typedef struct { + BOOL required; + INT watchdog_timeout; + DWORD check_interval; + char start_command[256]; + BOOL auto_start; + BOOL auto_stop; + BOOL auto_restart; + char alarm_class[32]; + DWORD first_failed; +} PROGRAM_INFO; + +#define AT_INTERNAL 1 /**< - */ +#define AT_PROGRAM 2 /**< - */ +#define AT_EVALUATED 3 /**< - */ +#define AT_PERIODIC 4 /**< - */ +#define AT_LAST 4 /**< - */ + +#define PROGRAM_INFO_STR(_name) const char *_name[] = {\ +"[.]",\ +"Required = BOOL : n",\ +"Watchdog timeout = INT : 10000",\ +"Check interval = DWORD : 180000",\ +"Start command = STRING : [256] ",\ +"Auto start = BOOL : n",\ +"Auto stop = BOOL : n",\ +"Auto restart = BOOL : n",\ +"Alarm class = STRING : [32] ",\ +"First failed = DWORD : 0",\ +"",\ +NULL } + +/** +Alarm class structure */ +typedef struct { + BOOL write_system_message; + BOOL write_elog_message; + INT system_message_interval; + DWORD system_message_last; + char execute_command[256]; + INT execute_interval; + DWORD execute_last; + BOOL stop_run; + char display_bgcolor[32]; + char display_fgcolor[32]; +} ALARM_CLASS; + +#define ALARM_CLASS_STR(_name) const char *_name[] = {\ +"[.]",\ +"Write system message = BOOL : y",\ +"Write Elog message = BOOL : n",\ +"System message interval = INT : 60",\ +"System message last = DWORD : 0",\ +"Execute command = STRING : [256] ",\ +"Execute interval = INT : 0",\ +"Execute last = DWORD : 0",\ +"Stop run = BOOL : n",\ +"Display BGColor = STRING : [32] red",\ +"Display FGColor = STRING : [32] black",\ +"",\ +NULL } + +/** +Alarm structure */ +typedef struct { + BOOL active; + INT triggered; + INT type; + /* RA36 ADD 10-DEC-2018 states 0=all, 1=stopped | 2=paused | 4=running!! + * or any ored combination */ + INT states; + INT check_interval; + DWORD checked_last; + char time_triggered_first[32]; + char time_triggered_last[32]; + char condition[256]; + char alarm_class[32]; + char alarm_message[80]; +} ALARM; + +#define ALARM_ODB_STR(_name) const char *_name[] = {\ +"[.]",\ +"Active = BOOL : n",\ +"Triggered = INT : 0",\ +"Type = INT : 3",\ +"States = INT : 7",\ +"Check interval = INT : 60",\ +"Checked last = DWORD : 0",\ +"Time triggered first = STRING : [32] ",\ +"Time triggered last = STRING : [32] ",\ +"Condition = STRING : [256] /Runinfo/Run number > 100",\ +"Alarm Class = STRING : [32] Alarm",\ +"Alarm Message = STRING : [80] Run number became too large",\ +"",\ +NULL } + +#define ALARM_PERIODIC_STR(_name) const char *_name[] = {\ +"[.]",\ +"Active = BOOL : n",\ +"Triggered = INT : 0",\ +"Type = INT : 4",\ +"States = INT : 7",\ +"Check interval = INT : 28800",\ +"Checked last = DWORD : 0",\ +"Time triggered first = STRING : [32] ",\ +"Time triggered last = STRING : [32] ",\ +"Condition = STRING : [256] ",\ +"Alarm Class = STRING : [32] Warning",\ +"Alarm Message = STRING : [80] Please do your shift checks",\ +"",\ +NULL } + +/**dox***************************************************************/ + /** @} *//* end of malarmh */ + +/**dox***************************************************************/ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/*---- malloc/free routines for debugging --------------------------*/ + +#ifdef _MEM_DBG +#define M_MALLOC(x) dbg_malloc((x), __FILE__, __LINE__) +#define M_CALLOC(x,y) dbg_calloc((x), (y), __FILE__, __LINE__) +#define M_FREE(x) dbg_free ((x), __FILE__, __LINE__) +#else +#define M_MALLOC(x) malloc(x) +#define M_CALLOC(x,y) calloc(x,y) +#define M_FREE(x) free(x) +#endif + +void *dbg_malloc(unsigned int size, char *file, int line); +void *dbg_calloc(unsigned int size, unsigned int count, char *file, int line); +void dbg_free(void *adr, char *file, int line); + +/*---- CERN libray -------------------------------------------------*/ + +#ifdef extname +#define PAWC_NAME pawc_ +#else +#define PAWC_NAME PAWC +#endif + +#define PAWC_DEFINE(size) \ +INT PAWC_NAME[size/4]; \ +INT pawc_size = size + +/* bug in ROOT include files */ +#undef GetCurrentTime + +/*---- RPC ---------------------------------------------------------*/ + +/** +flags */ +#define RPC_IN (1 << 0) +#define RPC_OUT (1 << 1) +#define RPC_POINTER (1 << 2) +#define RPC_FIXARRAY (1 << 3) +#define RPC_VARARRAY (1 << 4) +#define RPC_OUTGOING (1 << 5) + +/** +Server types */ +#define ST_NONE 0 +#define ST_SINGLE 1 +#define ST_MTHREAD 2 +#define ST_MPROCESS 3 +#define ST_SUBPROCESS 4 +#define ST_REMOTE 5 + +/** +function list */ +typedef struct { + WORD tid; + WORD flags; + INT n; +} RPC_PARAM; + +typedef struct { + INT id; + const char *name; + RPC_PARAM param[20]; + INT(*dispatch) (INT, void **); +} RPC_LIST; + +/** +IDs allow for users */ +#define RPC_MIN_ID 1 +#define RPC_MAX_ID 9999 + +/** +Data conversion flags */ +#define CF_ENDIAN (1<<0) +#define CF_IEEE2VAX (1<<1) +#define CF_VAX2IEEE (1<<2) +#define CF_ASCII (1<<3) + +#define CBYTE(_i) (* ((BYTE *) prpc_param[_i])) +#define CPBYTE(_i) ( ((BYTE *) prpc_param[_i])) + +#define CSHORT(_i) (* ((short *) prpc_param[_i])) +#define CPSHORT(_i) ( ((short *) prpc_param[_i])) + +#define CINT(_i) (* ((INT *) prpc_param[_i])) +#define CPINT(_i) ( ((INT *) prpc_param[_i])) + +#define CWORD(_i) (* ((WORD *) prpc_param[_i])) +#define CPWORD(_i) ( ((WORD *) prpc_param[_i])) + +#define CLONG(_i) (* ((long *) prpc_param[_i])) +#define CPLONG(_i) ( ((long *) prpc_param[_i])) + +#define CDWORD(_i) (* ((DWORD *) prpc_param[_i])) +#define CPDWORD(_i) ( ((DWORD *) prpc_param[_i])) + +#define CHNDLE(_i) (* ((HNDLE *) prpc_param[_i])) +#define CPHNDLE(_i) ( ((HNDLE *) prpc_param[_i])) + +#define CBOOL(_i) (* ((BOOL *) prpc_param[_i])) +#define CPBOOL(_i) ( ((BOOL *) prpc_param[_i])) + +#define CFLOAT(_i) (* ((float *) prpc_param[_i])) +#define CPFLOAT(_i) ( ((float *) prpc_param[_i])) + +#define CDOUBLE(_i) (* ((double *) prpc_param[_i])) +#define CPDOUBLE(_i) ( ((double *) prpc_param[_i])) + +#define CSTRING(_i) ( ((char *) prpc_param[_i])) +#define CARRAY(_i) ( ((void *) prpc_param[_i])) + +#define CBYTE(_i) (* ((BYTE *) prpc_param[_i])) +#define CPBYTE(_i) ( ((BYTE *) prpc_param[_i])) + +#define CSHORT(_i) (* ((short *) prpc_param[_i])) +#define CPSHORT(_i) ( ((short *) prpc_param[_i])) + +#define CINT(_i) (* ((INT *) prpc_param[_i])) +#define CPINT(_i) ( ((INT *) prpc_param[_i])) + +#define CWORD(_i) (* ((WORD *) prpc_param[_i])) +#define CPWORD(_i) ( ((WORD *) prpc_param[_i])) + +#define CLONG(_i) (* ((long *) prpc_param[_i])) +#define CPLONG(_i) ( ((long *) prpc_param[_i])) + +#define CDWORD(_i) (* ((DWORD *) prpc_param[_i])) +#define CPDWORD(_i) ( ((DWORD *) prpc_param[_i])) + +#define CHNDLE(_i) (* ((HNDLE *) prpc_param[_i])) +#define CPHNDLE(_i) ( ((HNDLE *) prpc_param[_i])) + +#define CBOOL(_i) (* ((BOOL *) prpc_param[_i])) +#define CPBOOL(_i) ( ((BOOL *) prpc_param[_i])) + +#define CFLOAT(_i) (* ((float *) prpc_param[_i])) +#define CPFLOAT(_i) ( ((float *) prpc_param[_i])) + +#define CDOUBLE(_i) (* ((double *) prpc_param[_i])) +#define CPDOUBLE(_i) ( ((double *) prpc_param[_i])) + +#define CSTRING(_i) ( ((char *) prpc_param[_i])) +#define CARRAY(_i) ( ((void *) prpc_param[_i])) + + + +#define cBYTE (* ((BYTE *) prpc_param[--n_param])) +#define cPBYTE ( ((BYTE *) prpc_param[--n_param])) + +#define cSHORT (* ((short *) prpc_param[--n_param])) +#define cPSHORT ( ((short *) prpc_param[--n_param])) + +#define cINT (* ((INT *) prpc_param[--n_param])) +#define cPINT ( ((INT *) prpc_param[--n_param])) + +#define cWORD (* ((WORD *) prpc_param[--n_param])) +#define cPWORD ( ((WORD *) prpc_param[--n_param])) + +#define cLONG (* ((long *) prpc_param[--n_param])) +#define cPLONG ( ((long *) prpc_param[--n_param])) + +#define cDWORD (* ((DWORD *) prpc_param[--n_param])) +#define cPDWORD ( ((DWORD *) prpc_param[--n_param])) + +#define cHNDLE (* ((HNDLE *) prpc_param[--n_param])) +#define cPHNDLE ( ((HNDLE *) prpc_param[--n_param])) + +#define cBOOL (* ((BOOL *) prpc_param[--n_param])) +#define cPBOOL ( ((BOOL *) prpc_param[--n_param])) + +#define cFLOAT (* ((float *) prpc_param[--n_param])) +#define cPFLOAT ( ((float *) prpc_param[--n_param])) + +#define cDOUBLE (* ((double *) prpc_param[--n_param])) +#define cPDOUBLE ( ((double *) prpc_param[--n_param])) + +#define cSTRING ( ((char *) prpc_param[--n_param])) +#define cARRAY ( ((void *) prpc_param[--n_param])) + +/*---- Function declarations ---------------------------------------*/ + +/* make functions callable from a C++ program */ +#ifdef __cplusplus +extern "C" { +#endif + +/* make functions under WinNT dll exportable */ +#if defined(OS_WINNT) && defined(MIDAS_DLL) +#define EXPRT __declspec(dllexport) +#else +#define EXPRT +#endif + + /*---- common routines ----*/ + INT EXPRT cm_get_error(INT code, char *string); + const char* EXPRT cm_get_version(void); + const char* EXPRT cm_get_revision(void); + INT EXPRT cm_get_experiment_name(char *name, int name_size); + INT EXPRT cm_get_environment(char *host_name, int host_name_size, + char *exp_name, int exp_name_size); + INT EXPRT cm_list_experiments(const char *host_name, + char exp_name[MAX_EXPERIMENT][NAME_LENGTH]); + INT EXPRT cm_get_exptab_filename(char* filename, int filename_size); + INT EXPRT cm_get_exptab(const char* exp_name, char* expdir, int expdir_size, char* expuser, int expuser_size); + INT EXPRT cm_select_experiment(const char *host_name, char *exp_name); + INT EXPRT cm_connect_experiment(const char *host_name, const char *exp_name, + const char *client_name, void (*func) (char *)); + INT EXPRT cm_connect_experiment1(const char *host_name, const char *exp_name, + const char *client_name, + void (*func) (char *), INT odb_size, + DWORD watchdog_timeout); + INT EXPRT cm_disconnect_experiment(void); + INT EXPRT cm_register_transition(INT transition, INT(*func) (INT, char *), + int sequence_number); + INT EXPRT cm_deregister_transition(INT transition); + INT EXPRT cm_set_transition_sequence(INT transition, INT sequence_number); + INT EXPRT cm_set_run_state(INT state); + INT EXPRT cm_query_transition(int *transition, int *run_number, int *trans_time); + INT EXPRT cm_register_deferred_transition(INT transition, BOOL(*func) (INT, BOOL)); + INT EXPRT cm_check_deferred_transition(void); + INT EXPRT cm_transition(INT transition, INT run_number, char *error, + INT strsize, INT async_flag, INT debug_flag); + INT EXPRT cm_transition_status_json(char** json_status); + INT EXPRT cm_register_server(void); + INT EXPRT cm_register_function(INT id, INT(*func) (INT, void **)); + INT EXPRT cm_connect_client(const char *client_name, HNDLE * hConn); + INT EXPRT cm_disconnect_client(HNDLE hConn, BOOL bShutdown); + INT EXPRT cm_set_experiment_database(HNDLE hDB, HNDLE hKeyClient); + INT EXPRT cm_get_experiment_database(HNDLE * hDB, HNDLE * hKeyClient); + INT EXPRT cm_set_experiment_semaphore(INT semaphore_alarm, INT semaphore_elog, INT semaphore_history, INT semaphore_msg); + INT EXPRT cm_get_experiment_semaphore(INT * semaphore_alarm, INT * semaphore_elog, INT * semaphore_history, INT * semaphore_msg); + INT EXPRT cm_set_client_info(HNDLE hDB, HNDLE * hKeyClient, + char *host_name, char *client_name, + INT computer_id, char *password, DWORD watchdog_timeout); + INT EXPRT cm_get_client_info(char *client_name); + INT EXPRT cm_check_client(HNDLE hDB, HNDLE hKeyClient); + INT EXPRT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout); + INT EXPRT cm_get_watchdog_params(BOOL * call_watchdog, DWORD * timeout); + INT EXPRT cm_get_watchdog_info(HNDLE hDB, char *client_name, + DWORD * timeout, DWORD * last); + INT EXPRT cm_enable_watchdog(BOOL flag); + void EXPRT cm_watchdog(int); + INT EXPRT cm_shutdown(const char *name, BOOL bUnique); + INT EXPRT cm_exist(const char *name, BOOL bUnique); + INT EXPRT cm_cleanup(const char *client_name, BOOL ignore_timeout); + INT EXPRT cm_yield(INT millisec); + INT EXPRT cm_execute(const char *command, char *result, INT buf_size); + INT EXPRT cm_synchronize(DWORD * sec); + INT EXPRT cm_asctime(char *str, INT buf_size); + INT EXPRT cm_time(DWORD * t); + BOOL EXPRT cm_is_ctrlc_pressed(void); + void EXPRT cm_ack_ctrlc_pressed(void); + + INT EXPRT cm_set_msg_print(INT system_mask, INT user_mask, int (*func) (const char *)); + INT EXPRT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format, ...) MATTRPRINTF(5,6); + INT EXPRT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format, ...) MATTRPRINTF(6,7); + INT EXPRT cm_msg_flush_buffer(void); + INT EXPRT cm_msg_register(void (*func) + (HNDLE, HNDLE, EVENT_HEADER *, void *)); + INT EXPRT cm_msg_retrieve(INT n_message, char *message, INT buf_size); + INT EXPRT cm_msg_retrieve2(const char *facility, time_t t, int min_messages, char** messages, int* num_messages); +#ifdef __cplusplus + INT EXPRT cm_msg_facilities(STRING_LIST *list); +#endif + INT EXPRT cm_msg_get_logfile(const char *facility, time_t t, char *filename, int fsize, char *linkname, int lsize); + + BOOL EXPRT equal_ustring(const char *str1, const char *str2); + + /*---- buffer manager ----*/ + INT EXPRT bm_open_buffer(const char *buffer_name, INT buffer_size, INT * buffer_handle); + INT EXPRT bm_close_buffer(INT buffer_handle); + INT EXPRT bm_close_all_buffers(void); + INT EXPRT bm_init_buffer_counters(INT buffer_handle); + INT EXPRT bm_get_buffer_info(INT buffer_handle, BUFFER_HEADER * buffer_header); + INT EXPRT bm_get_buffer_level(INT buffer_handle, INT * n_bytes); + INT EXPRT bm_set_cache_size(INT buffer_handle, INT read_size, INT write_size); + INT EXPRT bm_compose_event(EVENT_HEADER * event_header, + short int event_id, short int trigger_mask, + DWORD size, DWORD serial); + INT EXPRT bm_request_event(INT buffer_handle, short int event_id, + short int trigger_mask, INT sampling_type, + INT * request_id, void (*func) (HNDLE, HNDLE, + EVENT_HEADER *, void *)); + INT EXPRT bm_add_event_request(INT buffer_handle, short int event_id, + short int trigger_mask, + INT sampling_type, void (*func) (HNDLE, + HNDLE, + EVENT_HEADER + *, + void *), + INT request_id); + INT EXPRT bm_delete_request(INT request_id); + INT EXPRT bm_send_event(INT buffer_handle, const void *event, INT buf_size, INT async_flag); + INT EXPRT bm_receive_event(INT buffer_handle, void *destination, + INT * buf_size, INT async_flag); + INT EXPRT bm_skip_event(INT buffer_handle); + INT EXPRT bm_flush_cache(INT buffer_handle, INT async_flag); + INT EXPRT bm_poll_event(INT flag); + INT EXPRT bm_empty_buffers(void); + + /*---- online database functions -----*/ + INT EXPRT db_open_database(const char *database_name, INT database_size, HNDLE * hdb, const char *client_name); + INT EXPRT db_close_database(HNDLE database_handle); + INT EXPRT db_close_all_databases(void); + INT EXPRT db_protect_database(HNDLE database_handle); + + INT EXPRT db_create_key(HNDLE hdb, HNDLE key_handle, const char *key_name, DWORD type); + INT EXPRT db_create_link(HNDLE hdb, HNDLE key_handle, const char *link_name, const char *destination); + INT EXPRT db_set_value(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, const void *data, INT size, INT num_values, DWORD type); + INT EXPRT db_set_value_index(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT index, DWORD type, BOOL truncate); + INT EXPRT db_get_value(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, void *data, INT * size, DWORD type, BOOL create); +#ifdef __cplusplus + INT EXPRT db_resize_string(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_size); + INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string* s, BOOL create); + INT EXPRT db_set_value_string(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const std::string* s); +#endif + INT EXPRT db_find_key(HNDLE hdb, HNDLE hkey, const char *name, HNDLE * hsubkey); + INT EXPRT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE * subhKey); + INT EXPRT db_find_key1(HNDLE hdb, HNDLE hkey, const char *name, HNDLE * hsubkey); + INT EXPRT db_find_link1(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE * subhKey); + INT EXPRT db_scan_tree(HNDLE hDB, HNDLE hKey, int level, INT(*callback) (HNDLE, HNDLE, KEY *, INT, void *), void *info); + INT EXPRT db_scan_tree_link(HNDLE hDB, HNDLE hKey, int level, void (*callback) (HNDLE, HNDLE, KEY *, INT, void *), void *info); + INT EXPRT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size); + INT EXPRT db_delete_key(HNDLE database_handle, HNDLE key_handle, BOOL follow_links); + INT EXPRT db_enum_key(HNDLE hdb, HNDLE key_handle, INT index, HNDLE * subkey_handle); + INT EXPRT db_enum_link(HNDLE hdb, HNDLE key_handle, INT index, HNDLE * subkey_handle); + INT EXPRT db_get_next_link(HNDLE hdb, HNDLE key_handle, HNDLE * subkey_handle); + INT EXPRT db_get_key(HNDLE hdb, HNDLE key_handle, KEY * key); + INT EXPRT db_get_link(HNDLE hdb, HNDLE key_handle, KEY * key); + INT EXPRT db_get_key_info(HNDLE hDB, HNDLE hKey, char *name, INT name_size, INT * type, INT * num_values, INT * item_size); + INT EXPRT db_get_key_time(HNDLE hdb, HNDLE key_handle, DWORD * delta); + INT EXPRT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name); + INT EXPRT db_reorder_key(HNDLE hDB, HNDLE hKey, INT index); + INT EXPRT db_get_data(HNDLE hdb, HNDLE key_handle, void *data, INT * buf_size, DWORD type); + INT EXPRT db_get_link_data(HNDLE hdb, HNDLE key_handle, void *data, INT * buf_size, DWORD type); + INT EXPRT db_get_data1(HNDLE hDB, HNDLE hKey, void *data, INT * buf_size, DWORD type, INT * num_values); + INT EXPRT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT * buf_size, INT index, DWORD type); + INT EXPRT db_set_data(HNDLE hdb, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type); + INT EXPRT db_set_data1(HNDLE hdb, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type); + INT EXPRT db_notify_clients_array(HNDLE hdb, HNDLE hKey[], INT n); + INT EXPRT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type); + INT EXPRT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT size, INT index, DWORD type); + INT EXPRT db_set_link_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT size, INT index, DWORD type); + INT EXPRT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT size, INT index, DWORD type, BOOL bNotify); + INT EXPRT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values); + INT EXPRT db_merge_data(HNDLE hDB, HNDLE hKeyRoot, const char *name, void *data, INT data_size, INT num_values, INT type); + INT EXPRT db_set_mode(HNDLE hdb, HNDLE key_handle, WORD mode, BOOL recurse); + INT EXPRT db_create_record(HNDLE hdb, HNDLE hkey, const char *name, const char *init_str); + INT EXPRT db_check_record(HNDLE hDB, HNDLE hKey, const char *key_name, const char *rec_str, BOOL correct); + INT EXPRT db_open_record(HNDLE hdb, HNDLE hkey, void *ptr, INT rec_size, WORD access, void (*dispatcher) (INT, INT, void *), void *info); + INT EXPRT db_open_record1(HNDLE hdb, HNDLE hkey, void *ptr, INT rec_size, WORD access, void (*dispatcher) (INT, INT, void *), void *info, const char *rec_str); + INT EXPRT db_close_record(HNDLE hdb, HNDLE hkey); + INT EXPRT db_get_record(HNDLE hdb, HNDLE hKey, void *data, INT * buf_size, INT align); + INT EXPRT db_get_record1(HNDLE hdb, HNDLE hKey, void *data, INT * buf_size, INT align, const char *rec_str); + INT EXPRT db_get_record2(HNDLE hdb, HNDLE hKey, void *data, INT * buf_size, INT align, const char *rec_str, BOOL correct); + INT EXPRT db_get_record_size(HNDLE hdb, HNDLE hKey, INT align, INT * buf_size); + INT EXPRT db_set_record(HNDLE hdb, HNDLE hKey, void *data, INT buf_size, INT align); + INT EXPRT db_set_record2(HNDLE hdb, HNDLE hKey, void *data, INT buf_size, INT align, const char *rec_str); + INT EXPRT db_send_changed_records(void); + INT EXPRT db_get_open_records(HNDLE hDB, HNDLE hKey, char *str, INT buf_size, BOOL fix); + + INT EXPRT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode); + INT EXPRT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock); + + INT EXPRT db_watch(HNDLE hDB, HNDLE hKey, void (*dispatcher) (INT, INT, INT, void *info), void *info); + INT EXPRT db_unwatch(HNDLE hDB, HNDLE hKey); + INT EXPRT db_unwatch_all(void); + + INT EXPRT db_load(HNDLE hdb, HNDLE key_handle, const char *filename, BOOL bRemote); + INT EXPRT db_save(HNDLE hdb, HNDLE key_handle, const char *filename, BOOL bRemote); + INT EXPRT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT * buffer_size, const char *path); + INT EXPRT db_paste(HNDLE hDB, HNDLE hKeyRoot, const char *buffer); + INT EXPRT db_paste_xml(HNDLE hDB, HNDLE hKeyRoot, const char *buffer); + INT EXPRT db_save_struct(HNDLE hDB, HNDLE hKey, const char *file_name, const char *struct_name, BOOL append); + INT EXPRT db_save_string(HNDLE hDB, HNDLE hKey, const char *file_name, const char *string_name, BOOL append); + INT EXPRT db_save_xml(HNDLE hDB, HNDLE hKey, const char *file_name); + INT EXPRT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, INT * buffer_size); + + INT EXPRT db_save_json(HNDLE hDB, HNDLE hKey, const char *file_name); + INT EXPRT db_load_json(HNDLE hdb, HNDLE key_handle, const char *filename); + + /* db_copy_json() is obsolete, use db_copy_json_save, _values and _ls instead */ + INT EXPRT db_copy_json_obsolete(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int save_keys, int follow_links, int recurse); + + /* json encoder using the "ODB save" encoding, for use with "ODB load" and db_paste_json() */ + INT EXPRT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int* buffer_size, int* buffer_end); + /* json encoder using the "ls" format, for getting the contents of a single ODB subdirectory */ + INT EXPRT db_copy_json_ls(HNDLE hDB, HNDLE hKey, char **buffer, int* buffer_size, int* buffer_end); + /* json encoder using the "get_values" format, for resolving links and normalized ODB path names (converted to lower-case) */ + INT EXPRT db_copy_json_values(HNDLE hDB, HNDLE hKey, char **buffer, int* buffer_size, int* buffer_end, int omit_names, int omit_last_written, time_t omit_old_timestamp, int preserve_case); + /* json encoder for an ODB array */ + INT EXPRT db_copy_json_array(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end); + /* json encoder for a single element of an ODB array */ + INT EXPRT db_copy_json_index(HNDLE hDB, HNDLE hKey, int index, char **buffer, int *buffer_size, int *buffer_end); + + INT EXPRT db_paste_json(HNDLE hDB, HNDLE hKey, const char *buffer); + INT EXPRT db_paste_json_node(HNDLE hDB, HNDLE hKey, int index, const /* MJsonNode */ void *json_node); + + INT EXPRT db_sprintf(char *string, const void *data, INT data_size, INT index, DWORD type); + INT EXPRT db_sprintff(char *string, const char *format, const void *data, INT data_size, INT index, DWORD type); + INT EXPRT db_sprintfh(char *string, const void *data, INT data_size, INT index, DWORD type); + INT EXPRT db_sscanf(const char *string, void *data, INT * data_size, INT index, DWORD type); + char EXPRT *strcomb(const char **list); + INT db_get_watchdog_info(HNDLE hDB, const char *client_name, DWORD * timeout, DWORD * last); + + /*---- Bank routines ----*/ + void EXPRT bk_init(void *pbh); + void EXPRT bk_init32(void *event); + BOOL EXPRT bk_is32(const void *event); + INT EXPRT bk_size(const void *pbh); + void EXPRT bk_create(void *pbh, const char *name, WORD type, void **pdata); + INT EXPRT bk_delete(void *event, const char *name); + INT EXPRT bk_close(void *pbh, void *pdata); + INT EXPRT bk_list(const void *pbh, char *bklist); + INT EXPRT bk_locate(const void *pbh, const char *name, void *pdata); + INT EXPRT bk_iterate(const void *pbh, BANK ** pbk, void *pdata); + INT EXPRT bk_iterate32(const void *pbh, BANK32 ** pbk, void *pdata); + INT EXPRT bk_copy(char * pevent, char * psrce, const char * bkname); + INT EXPRT bk_swap(void *event, BOOL force); + INT EXPRT bk_find(const BANK_HEADER * pbkh, const char *name, DWORD * bklen, DWORD * bktype, void **pdata); + + /*---- RPC routines ----*/ + INT EXPRT rpc_clear_allowed_hosts(void); + INT EXPRT rpc_add_allowed_host(const char* hostname); + + INT EXPRT rpc_register_functions(const RPC_LIST * new_list, INT(*func) (INT, void **)); + INT EXPRT rpc_register_function(INT id, INT(*func) (INT, void **)); + INT EXPRT rpc_get_option(HNDLE hConn, INT item); + INT EXPRT rpc_set_option(HNDLE hConn, INT item, INT value); + INT EXPRT rpc_set_name(const char *name); + INT EXPRT rpc_get_name(char *name); + INT EXPRT rpc_is_remote(void); + INT EXPRT rpc_set_debug(void (*func) (const char *), INT mode); + void EXPRT rpc_debug_printf(const char *format, ...); + + INT EXPRT rpc_register_server(INT server_type, const char *name, INT * port, + INT(*func) (INT, void **)); + INT EXPRT rpc_register_client(const char *name, RPC_LIST * list); + INT EXPRT rpc_server_thread(void *pointer); + INT EXPRT rpc_server_shutdown(void); + INT EXPRT rpc_client_call(HNDLE hConn, const INT routine_id, ...); +#ifndef OMIT_MIDAS_RPC_CALL +#define rpc_call m_rpc_call /* RA36 10-DEC-2018 conflict with oncRPC rpc_call function */ + INT EXPRT rpc_call(const INT routine_id, ...); +#endif + INT EXPRT rpc_tid_size(INT id); + const char EXPRT *rpc_tid_name(INT id); + INT EXPRT rpc_server_connect(const char *host_name, const char *exp_name); + INT EXPRT rpc_client_connect(const char *host_name, INT midas_port, + const char *client_name, HNDLE * hConnection); + INT EXPRT rpc_client_disconnect(HNDLE hConn, BOOL bShutdown); + + INT EXPRT rpc_send_event(INT buffer_handle, void *source, INT buf_size, + INT async_flag, INT mode); + INT EXPRT rpc_flush_event(void); + + void EXPRT rpc_get_convert_flags(INT * convert_flags); + void EXPRT rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags); + void EXPRT rpc_convert_data(void *data, INT tid, INT flags, INT size, + INT convert_flags); + + /*---- system services ----*/ + DWORD EXPRT ss_millitime(void); + DWORD EXPRT ss_time(void); + DWORD EXPRT ss_settime(DWORD seconds); + char EXPRT *ss_asctime(void); + INT EXPRT ss_sleep(INT millisec); + BOOL EXPRT ss_kbhit(void); + + double EXPRT ss_nan(void); + int EXPRT ss_isnan(double x); + int EXPRT ss_isfin(double x); + + void EXPRT ss_clear_screen(void); + void EXPRT ss_printf(INT x, INT y, const char *format, ...); + void ss_set_screen_size(int x, int y); + + char EXPRT *ss_getpass(const char *prompt); + INT EXPRT ss_getchar(BOOL reset); + char EXPRT *ss_crypt(const char *key, const char *salt); + char EXPRT *ss_gets(char *string, int size); + + void EXPRT *ss_ctrlc_handler(void (*func) (int)); + + INT ss_operating_system(char *, char *, char *); /* RA36 10-DEC-2018 */ + BOOL ss_filter_command(const char *); /* RA36 10-DEC-2018 */ + + /*---- direct io routines ----*/ + INT EXPRT ss_directio_give_port(INT start, INT end); + INT EXPRT ss_directio_lock_port(INT start, INT end); + + /*---- tape routines ----*/ + INT EXPRT ss_tape_open(char *path, INT oflag, INT * channel); + INT EXPRT ss_tape_close(INT channel); + INT EXPRT ss_tape_status(char *path); + INT EXPRT ss_tape_read(INT channel, void *pdata, INT * count); + INT EXPRT ss_tape_write(INT channel, void *pdata, INT count); + INT EXPRT ss_tape_write_eof(INT channel); + INT EXPRT ss_tape_fskip(INT channel, INT count); + INT EXPRT ss_tape_rskip(INT channel, INT count); + INT EXPRT ss_tape_rewind(INT channel); + INT EXPRT ss_tape_spool(INT channel); + INT EXPRT ss_tape_mount(INT channel); + INT EXPRT ss_tape_unmount(INT channel); + INT EXPRT ss_tape_get_blockn(INT channel); + + /*---- disk routines ----*/ + double EXPRT ss_disk_free(const char *path); + double EXPRT ss_file_size(const char *path); + INT EXPRT ss_file_exist(const char *path); + INT EXPRT ss_file_remove(const char *path); + INT EXPRT ss_file_find(const char *path, const char *pattern, char **plist); + INT EXPRT ss_dir_find(const char *path, const char *pattern, char **plist); + double EXPRT ss_disk_size(const char *path); + + INT EXPRT ss_find_files(char *, char *, INT, char **, INT *); /* RA36 10-DEC-2018 */ + + /*---- history routines ----*/ + INT EXPRT hs_set_path(const char *path); + INT EXPRT hs_define_event(DWORD event_id, const char *name, const TAG * tag, DWORD size); + INT EXPRT hs_write_event(DWORD event_id, const void *data, DWORD size); + INT EXPRT hs_count_events(DWORD ltime, DWORD * count); + INT EXPRT hs_enum_events(DWORD ltime, char *event_name, DWORD * name_size, INT event_id[], DWORD * id_size); + INT EXPRT hs_count_vars(DWORD ltime, DWORD event_id, DWORD * count); + INT EXPRT hs_enum_vars(DWORD ltime, DWORD event_id, char *var_name, DWORD * size, DWORD * var_n, DWORD * n_size); + INT EXPRT hs_get_var(DWORD ltime, DWORD event_id, const char *var_name, DWORD * type, INT * n_data); + INT EXPRT hs_get_event_id(DWORD ltime, const char *name, DWORD * id); + INT EXPRT hs_get_tags(DWORD ltime, DWORD event_id, char event_name[NAME_LENGTH], int *n_tags, TAG **tags); + INT EXPRT hs_read(DWORD event_id, DWORD start_time, DWORD end_time, + DWORD interval, const char *tag_name, DWORD var_index, + DWORD * time_buffer, DWORD * tbsize, + void *data_buffer, DWORD * dbsize, DWORD * type, DWORD * n); + INT EXPRT hs_dump(DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, BOOL binary_time); + INT EXPRT hs_fdump(const char *file_name, DWORD id, BOOL binary_time); + + /* ---- RA36 10-DEC-2018 History functions for bulk muSR */ + INT EXPRT hs_dump_bmusr(DWORD event_id, DWORD start_time, DWORD end_time, + DWORD interval, BOOL binary_time, BOOL mlog, BOOL verbose); + INT EXPRT hs_dump_run_bmusr(INT run_number, DWORD event_id, int year, DWORD interval, + BOOL binary_time, BOOL tlog, BOOL verbose); + + /*---- ELog functions ----*/ + INT EXPRT el_retrieve(char *tag, char *date, int *run, char *author, + char *type, char *system, char *subject, + char *text, int *textsize, char *orig_tag, + char *reply_tag, char *attachment1, + char *attachment2, char *attachment3, char *encoding); + INT EXPRT el_submit(int run, const char *author, const char *type, const char *system, + const char *subject, const char *text, const char *reply_to, + const char *encoding, const char *afilename1, char *buffer1, + INT buffer_size1, const char *afilename2, char *buffer2, + INT buffer_size2, const char *afilename3, char *buffer3, + INT buffer_size3, char *tag, INT tag_size); + INT EXPRT el_search_message(char *tag, int *fh, BOOL walk, char* filename, int filename_size); + INT EXPRT el_search_run(int run, char *return_tag); + INT EXPRT el_delete_message(const char *tag); + + /*---- alarm functions ----*/ + INT EXPRT al_check(void); + INT EXPRT al_trigger_alarm(const char *alarm_name, const char *alarm_message, + const char *default_class, const char *cond_str, INT type); + INT EXPRT al_trigger_class(const char *alarm_class, const char *alarm_message, BOOL first); + INT EXPRT al_reset_alarm(const char *alarm_name); + BOOL EXPRT al_evaluate_condition(const char *condition, char *value); + INT al_get_alarms(char *result, int result_size); + + /*---- frontend functions ----*/ + INT get_frontend_index(void); + void mfe_get_args(int *argc, char ***argv); + void register_cnaf_callback(int debug); + void mfe_error(const char *error); + void mfe_set_error(void (*dispatcher) (const char *)); + int set_equipment_status(const char *name, const char *eq_status, const char *status_color); + INT create_event_rb(int i); + INT get_event_rbh(int i); + INT create_event_rb(int i); + void stop_readout_threads(void); + int is_readout_thread_enabled(void); + int is_readout_thread_active(void); + void signal_readout_thread_active(int index, int flag); + + /*---- analyzer functions ----*/ + void EXPRT test_register(ANA_TEST * t); + void EXPRT add_data_dir(char *result, char *file); + void EXPRT lock_histo(INT id); + + void EXPRT open_subfolder(const char *name); + void EXPRT close_subfolder(void); + + /* we need a duplicate of mxml/strlcpy.h or nobody can use strlcpy() from libmidas.a */ +#ifndef HAVE_STRLCPY +#ifndef _STRLCPY_H_ +#define _STRLCPY_H_ + size_t EXPRT strlcpy(char *dst, const char *src, size_t size); + size_t EXPRT strlcat(char *dst, const char *src, size_t size); +#endif +#endif + + /* START MOD RA36 10-DEC-2018 */ + /*---- read file on backend ----*/ + INT EXPRT be_file_open(char *, char *, DWORD, DWORD *); + INT EXPRT be_file_open_write(char *, char *, DWORD, DWORD *); + INT EXPRT be_file_close(DWORD); + INT EXPRT be_files_close(void); + INT EXPRT be_file_read(DWORD, char *, char *, INT *); + INT EXPRT be_file_write(DWORD, char *, char *); + INT EXPRT be_file_timeout(DWORD); + INT EXPRT be_files_timeout(void); + INT EXPRT be_files_check(void); + + /*---- create and read find file list on backend ----*/ + INT EXPRT be_find_files(char *, char *, INT, DWORD, INT *, DWORD *); + INT EXPRT be_find_close(DWORD); + INT EXPRT be_finds_close(void); + INT EXPRT be_find_read(DWORD, char *, char *, INT *); + INT EXPRT be_find_timeout(DWORD); + INT EXPRT be_finds_timeout(void); + INT EXPRT be_finds_check(void); + INT EXPRT cm_file_exists(char *); + INT EXPRT cm_directory_list(char *, char *); + + /*---- get operating system information of backend ----*/ + INT EXPRT be_operating_system(char *, INT *, char *, INT *, char *, INT *); + INT EXPRT be_operating_system1(char *, char *, char *); + + /*---- test data types ----*/ + void EXPRT show_data_types(void); + + /*---- check if client is still in list ----*/ + INT EXPRT cm_client_in_list(void); + INT EXPRT cm_client_in_list_reset(void); + /* END MOD RA36 10-DEC-2018 */ + +#ifdef __cplusplus +} + +#endif +#endif /* _MIDAS_H */ +/**dox***************************************************************/ +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +/**dox***************************************************************/ + /** @} *//* end of msectionh */ + +/**dox***************************************************************/ + /** @} *//* end of midasincludecode */ diff --git a/midas/msystem.h b/midas/msystem.h new file mode 100644 index 0000000..56043f0 --- /dev/null +++ b/midas/msystem.h @@ -0,0 +1,653 @@ +/********************************************************************\ + + Name: MSYSTEM.H + Created by: Stefan Ritt + + Contents: Function declarations and constants for internal + routines + + $Id: msystem.h,v 1.1.1.1 2019/02/21 10:07:22 raselli Exp $ + +\********************************************************************/ + +/**dox***************************************************************/ +/** @file msystem.h +The Midas System include file +*/ + +/** @defgroup msystemincludecode The msystem.h & system.c + */ +/** @defgroup msdefineh System Define + */ +/** @defgroup msmacroh System Macros + */ +/** @defgroup mssectionh System Structure Declaration + */ + +/**dox***************************************************************/ +/** @addtogroup msystemincludecode + * + * @{ */ + +/**dox***************************************************************/ +#ifndef _MSYSTEM_H_ +#define _MSYSTEM_H_ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#include "midasinc.h" + +/**dox***************************************************************/ +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +/**dox***************************************************************/ +/** @addtogroup msdefineh + * + * @{ */ + +/** +data representations +*/ +#define DRI_16 (1<<0) /**< - */ +#define DRI_32 (1<<1) /**< - */ +#define DRI_64 (1<<2) /**< - */ +#define DRI_LITTLE_ENDIAN (1<<3) /**< - */ +#define DRI_BIG_ENDIAN (1<<4) /**< - */ +#define DRF_IEEE (1<<5) /**< - */ +#define DRF_G_FLOAT (1<<6) /**< - */ +#define DR_ASCII (1<<7) /**< - */ + +/**dox***************************************************************/ + /** @} *//* end of msdefineh */ + +/**dox***************************************************************/ +/** @addtogroup msmacroh + * + * @{ */ + +/* Byte and Word swapping big endian <-> little endian */ +/** +SWAP WORD macro */ +#ifndef WORD_SWAP +#define WORD_SWAP(x) { BYTE _tmp; \ + _tmp= *((BYTE *)(x)); \ + *((BYTE *)(x)) = *(((BYTE *)(x))+1); \ + *(((BYTE *)(x))+1) = _tmp; } +#endif + +/** +SWAP DWORD macro */ +#ifndef DWORD_SWAP +#define DWORD_SWAP(x) { BYTE _tmp; \ + _tmp= *((BYTE *)(x)); \ + *((BYTE *)(x)) = *(((BYTE *)(x))+3); \ + *(((BYTE *)(x))+3) = _tmp; \ + _tmp= *(((BYTE *)(x))+1); \ + *(((BYTE *)(x))+1) = *(((BYTE *)(x))+2); \ + *(((BYTE *)(x))+2) = _tmp; } +#endif + +/** +SWAP QWORD macro */ +#ifndef QWORD_SWAP +#define QWORD_SWAP(x) { BYTE _tmp; \ + _tmp= *((BYTE *)(x)); \ + *((BYTE *)(x)) = *(((BYTE *)(x))+7); \ + *(((BYTE *)(x))+7) = _tmp; \ + _tmp= *(((BYTE *)(x))+1); \ + *(((BYTE *)(x))+1) = *(((BYTE *)(x))+6); \ + *(((BYTE *)(x))+6) = _tmp; \ + _tmp= *(((BYTE *)(x))+2); \ + *(((BYTE *)(x))+2) = *(((BYTE *)(x))+5); \ + *(((BYTE *)(x))+5) = _tmp; \ + _tmp= *(((BYTE *)(x))+3); \ + *(((BYTE *)(x))+3) = *(((BYTE *)(x))+4); \ + *(((BYTE *)(x))+4) = _tmp; } +#endif + +/**dox***************************************************************/ + /** @} *//* end of msmacroh */ + +/**dox***************************************************************/ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/** +Definition of implementation specific constants */ +#define MESSAGE_BUFFER_SIZE 100000 /**< buffer used for messages */ +#define MESSAGE_BUFFER_NAME "SYSMSG" /**< buffer name for messages */ +#define MAX_RPC_CONNECTION 64 /**< server/client connections */ +#define MAX_STRING_LENGTH 256 /**< max string length for odb */ +#define NET_BUFFER_SIZE (8*1024*1024) /**< size of network receive buffers */ + +/*------------------------------------------------------------------*/ +/* flag for conditional compilation of debug messages */ +#undef DEBUG_MSG + +/* flag for local routines (not for pure network clients) */ +#if !defined ( OS_MSDOS ) && !defined ( OS_VXWORKS ) +#define LOCAL_ROUTINES +#endif + +/* YBOS support not in MSDOS */ +#if !defined ( OS_MSDOS ) +#define YBOS_SUPPORT +#endif + +/*------------------------------------------------------------------*/ + +/* Mapping of function names for socket operations */ + +#ifdef OS_MSDOS + +#define closesocket(s) close(s) +#define ioctlsocket(s,c,d) ioctl(s,c,d) +#define malloc(i) farmalloc(i) + +#undef NET_TCP_SIZE +#define NET_TCP_SIZE 0x7FFF + +#endif /* OS_MSDOS */ + +#ifdef OS_VMS + +#define closesocket(s) close(s) +#define ioctlsocket(s,c,d) + +#ifndef FD_SET +typedef struct { + INT fds_bits; +} fd_set; + +#define FD_SET(n, p) ((p)->fds_bits |= (1 << (n))) +#define FD_CLR(n, p) ((p)->fds_bits &= ~(1 << (n))) +#define FD_ISSET(n, p) ((p)->fds_bits & (1 << (n))) +#define FD_ZERO(p) ((p)->fds_bits = 0) +#endif /* FD_SET */ + +#endif /* OS_VMS */ + +/* Missing #defines in VMS */ + +#ifdef OS_VMS + +#define P_WAIT 0 +#define P_NOWAIT 1 +#define P_DETACH 4 + +#endif + +/* and for UNIX */ + +#ifdef OS_UNIX + +#define closesocket(s) close(s) +#define ioctlsocket(s,c,d) ioctl(s,c,d) +#ifndef stricmp +#define stricmp(s1, s2) strcasecmp(s1, s2) +#endif + +#define P_WAIT 0 +#define P_NOWAIT 1 +#define P_DETACH 4 + +#endif + +#ifndef FD_SETSIZE +#define FD_SETSIZE 32 +#endif + +/* and VXWORKS */ + +#ifdef OS_VXWORKS + +#define P_NOWAIT 1 +#define closesocket(s) close(s) +#define ioctlsocket(s,c,d) ioctl(s,c,d) + +#endif + +/* missing O_BINARY for non-PC */ +#ifndef O_BINARY +#define O_BINARY 0 +#define O_TEXT 0 +#endif + +/* min/max/abs macros */ +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ABS +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#endif + +/* missing tell() for some operating systems */ +#define TELL(fh) lseek(fh, 0, SEEK_CUR) + +/* define file truncation */ +#ifdef OS_WINNT +#define TRUNCATE(fh) chsize(fh, TELL(fh)) +#else +#define TRUNCATE(fh) ftruncate(fh, TELL(fh)) +#endif + +/* reduced shared memory size */ +#ifdef OS_SOLARIS +#define MAX_SHM_SIZE 0x20000 /* 128k */ +#endif + +/* missing isnan() & co under Windows */ +#ifdef OS_WINNT +#include +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define ftruncate(x,y) _chsize(x,y) +#endif + +/*------------------------------------------------------------------*/ + +/* Network structures */ + +typedef struct { + DWORD routine_id; /* routine ID like ID_BM_xxx */ + DWORD param_size; /* size in Bytes of parameter */ +} NET_COMMAND_HEADER; + +typedef struct { + NET_COMMAND_HEADER header; + char param[32]; /* parameter array */ +} NET_COMMAND; + + +typedef struct { + DWORD serial_number; + DWORD sequence_number; +} UDP_HEADER; + +#define UDP_FIRST 0x80000000l +#define TCP_FAST 0x80000000l + +#define MSG_BM 1 +#define MSG_ODB 2 +#define MSG_CLIENT 3 +#define MSG_SERVER 4 +#define MSG_LISTEN 5 +#define MSG_WATCHDOG 6 + +/* RPC structures */ + +struct callback_addr { + char host_name[HOST_NAME_LENGTH]; + unsigned short host_port1; + unsigned short host_port2; + unsigned short host_port3; + int debug; + char experiment[NAME_LENGTH]; + char directory[MAX_STRING_LENGTH]; + char user[NAME_LENGTH]; + INT index; +}; + +typedef struct { + char host_name[HOST_NAME_LENGTH]; /* server name */ + INT port; /* ip port */ + char exp_name[NAME_LENGTH]; /* experiment to connect */ + int send_sock; /* tcp send socket */ + int connected; /* socket is connected */ + INT remote_hw_type; /* remote hardware type */ + char client_name[NAME_LENGTH]; /* name of remote client */ + INT transport; /* RPC_TCP/RPC_FTCP */ + INT rpc_timeout; /* in milliseconds */ + +} RPC_CLIENT_CONNECTION; + +typedef struct { + char host_name[HOST_NAME_LENGTH]; /* server name */ + INT port; /* ip port */ + char exp_name[NAME_LENGTH]; /* experiment to connect */ + int send_sock; /* tcp send socket */ + int recv_sock; /* tcp receive socket */ + int event_sock; /* event socket */ + INT remote_hw_type; /* remote hardware type */ + INT transport; /* RPC_TCP/RPC_FTCP */ + INT rpc_timeout; /* in milliseconds */ + +} RPC_SERVER_CONNECTION; + +typedef struct { + INT tid; /* thread id */ + char prog_name[NAME_LENGTH]; /* client program name */ + char host_name[HOST_NAME_LENGTH]; /* client name */ + int send_sock; /* tcp send socket */ + int recv_sock; /* tcp receive socket */ + int event_sock; /* tcp event socket */ + INT remote_hw_type; /* hardware type */ + INT transport; /* RPC_TCP/RPC_FTCP */ + INT watchdog_timeout; /* in milliseconds */ + DWORD last_activity; /* time of last recv */ + INT convert_flags; /* convertion flags */ + char *net_buffer; /* TCP cache buffer */ + char *ev_net_buffer; + INT net_buffer_size; /* size of TCP cache */ + INT write_ptr, read_ptr, misalign; /* pointers for cache */ + INT ev_write_ptr, ev_read_ptr, ev_misalign; + HNDLE odb_handle; /* handle to online datab. */ + HNDLE client_handle; /* client key handle . */ + +} RPC_SERVER_ACCEPTION; + +/**dox***************************************************************/ +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +/**dox***************************************************************/ +/** @addtogroup mssectionh + * + * @{ */ + +typedef struct { + INT size; /**< size in bytes */ + INT next_free; /**< Address of next free block */ +} FREE_DESCRIP; + +typedef struct { + INT handle; /**< Handle of record base key */ + WORD access_mode; /**< R/W flags */ + WORD flags; /**< Data format, ... */ + +} OPEN_RECORD; + +typedef struct { + char name[NAME_LENGTH]; /* name of client */ + INT pid; /* process ID */ + INT unused0; /* was thread ID */ + INT unused; /* was thread handle */ + INT port; /* UDP port for wake up */ + INT num_open_records; /* number of open records */ + DWORD last_activity; /* time of last activity */ + DWORD watchdog_timeout; /* timeout in ms */ + INT max_index; /* index of last opren record */ + + OPEN_RECORD open_record[MAX_OPEN_RECORDS]; + +} DATABASE_CLIENT; + +typedef struct { + char name[NAME_LENGTH]; /* name of database */ + INT version; /* database version */ + INT num_clients; /* no of active clients */ + INT max_client_index; /* index of last client */ + INT key_size; /* size of key area in bytes */ + INT data_size; /* size of data area in bytes */ + INT root_key; /* root key offset */ + INT first_free_key; /* first free key memory */ + INT first_free_data; /* first free data memory */ + + DATABASE_CLIENT client[MAX_CLIENTS]; /* entries for clients */ + +} DATABASE_HEADER; + +/* Per-process buffer access structure (descriptor) */ + +typedef struct { + char name[NAME_LENGTH]; /* Name of database */ + BOOL attached; /* TRUE if database is attached */ + INT client_index; /* index to CLIENT str. in buf. */ + DATABASE_HEADER *database_header; /* pointer to database header */ + void *database_data; /* pointer to database data */ + HNDLE semaphore; /* semaphore handle */ + INT lock_cnt; /* flag to avoid multiple locks */ + HNDLE shm_handle; /* handle (id) to shared memory */ + INT index; /* connection index / tid */ + BOOL protect; /* read/write protection */ + BOOL protect_read; /* read is permitted */ + BOOL protect_write; /* write is permitted */ + MUTEX_T *mutex; /* mutex for multi-thread access */ + INT timeout; /* timeout for mutex and semaphore */ + +} DATABASE; + +/* Open record descriptor */ + +typedef struct { + HNDLE handle; /* Handle of record base key */ + HNDLE hDB; /* Handle of record's database */ + WORD access_mode; /* R/W flags */ + void *data; /* Pointer to local data */ + void *copy; /* Pointer of copy to data */ + INT buf_size; /* Record size in bytes */ + void (*dispatcher) (INT, INT, void *); /* Pointer to dispatcher func. */ + void *info; /* addtl. info for dispatcher */ + +} RECORD_LIST; + +/* Watch record descriptor */ + +typedef struct { + HNDLE handle; /* Handle of watched base key */ + HNDLE hDB; /* Handle of watched database */ + void (*dispatcher) (INT, INT, INT, void* info); /* Pointer to dispatcher func. */ + void* info; /* addtl. info for dispatcher */ +} WATCH_LIST; + +/* Event request descriptor */ + +typedef struct { + INT buffer_handle; /* Buffer handle */ + short int event_id; /* same as in EVENT_HEADER */ + short int trigger_mask; + void (*dispatcher) (HNDLE, HNDLE, EVENT_HEADER *, void *); /* Dispatcher func. */ + +} REQUEST_LIST; + +/**dox***************************************************************/ + /** @} *//* end of mssectionh */ + +/**dox***************************************************************/ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/*---- Logging channel information ---------------------------------*/ + +#define LOG_TYPE_DISK 1 +#define LOG_TYPE_TAPE 2 +#define LOG_TYPE_FTP 3 + +/*---- VxWorks specific taskSpawn arguments ----------------------*/ + +typedef struct { + char name[32]; + int priority; + int options; + int stackSize; + int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10; +} VX_TASK_SPAWN; + +/*---- Channels for ss_suspend_set_dispatch() ----------------------*/ + +#define CH_IPC 1 +#define CH_CLIENT 2 +#define CH_SERVER 3 +#define CH_LISTEN 4 + +/*---- Function declarations ---------------------------------------*/ + +/* make functions callable from a C++ program */ +#ifdef __cplusplus +extern "C" { +#endif + + /*---- common function ----*/ + INT EXPRT cm_set_path(const char *path); + INT EXPRT cm_get_path(char *path, int path_size); +#ifdef __cplusplus + INT EXPRT cm_get_path_string(std::string* path); +#endif + INT EXPRT cm_set_experiment_name(const char *name); + INT cm_dispatch_ipc(const char *message, int s); + INT EXPRT cm_msg_log(INT message_type, const char *facility, const char *message); + void EXPRT name2c(char *str); + INT cm_delete_client_info(HNDLE hDB, INT pid); + + /*---- buffer manager ----*/ + INT bm_lock_buffer(INT buffer_handle); + INT bm_unlock_buffer(INT buffer_handle); + INT bm_notify_client(char *buffer_name, int s); + INT EXPRT bm_mark_read_waiting(BOOL flag); + INT bm_push_event(char *buffer_name); + INT bm_check_buffers(void); + INT EXPRT bm_remove_event_request(INT buffer_handle, INT request_id); + void EXPRT bm_defragment_event(HNDLE buffer_handle, HNDLE request_id, + EVENT_HEADER * pevent, void *pdata, + void (*dispatcher) (HNDLE, HNDLE, + EVENT_HEADER *, void *)); + + /*---- online database ----*/ + INT EXPRT db_lock_database(HNDLE database_handle); + INT EXPRT db_unlock_database(HNDLE database_handle); + INT EXPRT db_get_lock_cnt(HNDLE database_handle); + INT EXPRT db_set_lock_timeout(HNDLE database_handle, int timeout_millisec); + INT db_update_record(INT hDB, INT hKeyRoot, INT hKey, int index, int s); + INT db_close_all_records(void); + INT EXPRT db_flush_database(HNDLE hDB); + INT EXPRT db_notify_clients(HNDLE hDB, HNDLE hKey, int index, BOOL bWalk); + INT EXPRT db_set_client_name(HNDLE hDB, const char *client_name); + INT db_delete_key1(HNDLE hDB, HNDLE hKey, INT level, BOOL follow_links); + INT EXPRT db_show_mem(HNDLE hDB, char *result, INT buf_size, BOOL verbose); + INT EXPRT db_get_free_mem(HNDLE hDB, INT *key_size, INT *data_size); + INT db_allow_write_locked(DATABASE* p, const char* caller_name); + void db_update_last_activity(DWORD actual_time); + void db_cleanup(const char *who, DWORD actual_time, BOOL wrong_interval); + void db_cleanup2(const char* client_name, int ignore_timeout, DWORD actual_time, const char *who); + void db_set_watchdog_params(DWORD timeout); + INT db_check_client(HNDLE hDB, HNDLE hKeyClient); + + /*---- rpc functions -----*/ + RPC_LIST EXPRT *rpc_get_internal_list(INT flag); + INT rpc_server_receive(INT idx, int sock, BOOL check); + INT rpc_server_callback(struct callback_addr *callback); + INT EXPRT rpc_server_accept(int sock); + INT rpc_client_accept(int sock); + INT rpc_get_server_acception(void); + INT rpc_set_server_acception(INT idx); + INT EXPRT rpc_set_server_option(INT item, POINTER_T value); + POINTER_T EXPRT rpc_get_server_option(INT item); + INT recv_tcp_check(int sock); + INT recv_event_check(int sock); + INT rpc_deregister_functions(void); + INT rpc_check_channels(void); + void EXPRT rpc_client_check(void); + INT rpc_server_disconnect(void); + int EXPRT rpc_get_send_sock(void); + int EXPRT rpc_get_event_sock(void); + INT EXPRT rpc_set_opt_tcp_size(INT tcp_size); + INT EXPRT rpc_get_opt_tcp_size(void); + + /*---- system services ----*/ + INT ss_shm_open(const char *name, INT size, void **adr, HNDLE *handle, BOOL get_size); + INT ss_shm_close(const char *name, void *adr, HNDLE handle, INT destroy_flag); + INT ss_shm_flush(const char *name, const void *adr, INT size, HNDLE handle); + INT EXPRT ss_shm_delete(const char *name); + INT ss_shm_protect(HNDLE handle, void *adr); + INT ss_shm_unprotect(HNDLE handle, void **adr, BOOL read, BOOL write, const char* caller_name); + INT ss_spawnv(INT mode, const char *cmdname, const char* const argv[]); + INT ss_shell(int sock); + INT EXPRT ss_daemon_init(BOOL keep_stdout); + INT EXPRT ss_system(const char *command); + INT EXPRT ss_exec(const char *cmd, INT * child_pid); + BOOL EXPRT ss_existpid(INT pid); + INT EXPRT ss_getpid(void); + INT EXPRT ss_gettid(void); + INT ss_set_async_flag(INT flag); + INT EXPRT ss_semaphore_create(const char *semaphore_name, HNDLE * semaphore_handle); + INT EXPRT ss_semaphore_wait_for(HNDLE semaphore_handle, INT timeout); + INT EXPRT ss_semaphore_release(HNDLE semaphore_handle); + INT EXPRT ss_semaphore_delete(HNDLE semaphore_handle, INT destroy_flag); + INT EXPRT ss_mutex_create(MUTEX_T **mutex, BOOL recursive); + INT EXPRT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout); + INT EXPRT ss_mutex_release(MUTEX_T *mutex); + INT EXPRT ss_mutex_delete(MUTEX_T *mutex); + INT ss_alarm(INT millitime, void (*func) (int)); + INT ss_suspend_get_port(INT * port); + INT ss_suspend_set_dispatch(INT channel, void *connection, INT(*dispatch) (void)); + INT ss_resume(INT port, const char *message); + INT ss_suspend_exit(void); + INT ss_exception_handler(void (*func) (void)); + void EXPRT ss_force_single_thread(void); + INT EXPRT ss_suspend(INT millisec, INT msg); + midas_thread_t EXPRT ss_thread_create(INT(*func) (void *), void *param); + INT EXPRT ss_thread_kill(midas_thread_t thread_id); + INT EXPRT ss_get_struct_align(void); + INT EXPRT ss_get_struct_padding(void); + INT EXPRT ss_timezone(void); + INT EXPRT ss_stack_get(char ***string); + void EXPRT ss_stack_print(void); + void EXPRT ss_stack_history_entry(char *tag); + void EXPRT ss_stack_history_dump(char *filename); + INT ss_gethostname(char* buffer, int buffer_size); + + /*---- socket routines ----*/ + INT EXPRT send_tcp(int sock, char *buffer, DWORD buffer_size, INT flags); + INT EXPRT recv_tcp(int sock, char *buffer, DWORD buffer_size, INT flags); + INT EXPRT recv_tcp2(int sock, char *buffer, int buffer_size, int timeout_ms); + INT send_udp(int sock, char *buffer, DWORD buffer_size, INT flags); + INT recv_udp(int sock, char *buffer, DWORD buffer_size, INT flags); + INT EXPRT recv_string(int sock, char *buffer, DWORD buffer_size, INT flags); + INT EXPRT ss_socket_wait(int sock, int millisec); + INT EXPRT ss_recv_net_command(int sock, DWORD* routine_id, DWORD* param_size, char **param_ptr, int timeout_ms); + + /*---- event buffer routines ----*/ + INT EXPRT eb_create_buffer(INT size); + INT EXPRT eb_free_buffer(void); + BOOL EXPRT eb_buffer_full(void); + BOOL EXPRT eb_buffer_empty(void); + EVENT_HEADER EXPRT *eb_get_pointer(void); + INT EXPRT eb_increment_pointer(INT buffer_handle, INT event_size); + INT EXPRT eb_send_events(BOOL send_all); + + /*---- dual memory event buffer routines ----*/ + INT EXPRT dm_buffer_create(INT size, INT usize); + INT EXPRT dm_buffer_release(void); + BOOL EXPRT dm_area_full(void); + EVENT_HEADER EXPRT *dm_pointer_get(void); + INT EXPRT dm_pointer_increment(INT buffer_handle, INT event_size); + INT EXPRT dm_area_send(void); + INT EXPRT dm_area_flush(void); + INT EXPRT dm_task(void *pointer); + DWORD EXPRT dm_buffer_time_get(void); + INT EXPRT dm_async_area_send(void *pointer); + + /*---- ring buffer routines ----*/ + int EXPRT rb_set_nonblocking(void); + int EXPRT rb_create(int size, int max_event_size, int *ring_buffer_handle); + int EXPRT rb_delete(int ring_buffer_handle); + int EXPRT rb_get_wp(int handle, void **p, int millisec); + int EXPRT rb_increment_wp(int handle, int size); + int EXPRT rb_get_rp(int handle, void **p, int millisec); + int EXPRT rb_increment_rp(int handle, int size); + int EXPRT rb_get_buffer_level(int handle, int * n_bytes); + +/*---- Include RPC identifiers -------------------------------------*/ + +#include "mrpc.h" + +#ifdef __cplusplus +} +#endif +/**dox***************************************************************/ +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +#endif /* _MSYSTEM_H_ */ + +/**dox***************************************************************//** @} *//* end of msystemincludecode */ +/* emacs + * Local Variables: + * tab-width: 8 + * c-basic-offset: 3 + * indent-tabs-mode: nil + * End: + */