1059 lines
37 KiB
C
1059 lines
37 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
/* Interface between old database access and new
|
|
*
|
|
* Author: Marty Kraimer
|
|
* Andrew Johnson <anj@aps.anl.gov>
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
#include "alarm.h"
|
|
#include "dbDefs.h"
|
|
#include "ellLib.h"
|
|
#include "epicsConvert.h"
|
|
#include "epicsTime.h"
|
|
#include "errlog.h"
|
|
#include "errMdef.h"
|
|
|
|
#define db_accessHFORdb_accessC
|
|
#include "db_access.h"
|
|
#undef db_accessHFORdb_accessC
|
|
|
|
#include "dbAccessDefs.h"
|
|
#include "db_access_routines.h"
|
|
#include "dbBase.h"
|
|
#include "dbChannel.h"
|
|
#include "dbCommon.h"
|
|
#include "dbEvent.h"
|
|
#include "dbLock.h"
|
|
#include "dbNotify.h"
|
|
#include "dbStaticLib.h"
|
|
#include "recSup.h"
|
|
|
|
|
|
#define oldDBF_STRING 0
|
|
#define oldDBF_INT 1
|
|
#define oldDBF_SHORT 1
|
|
#define oldDBF_FLOAT 2
|
|
#define oldDBF_ENUM 3
|
|
#define oldDBF_CHAR 4
|
|
#define oldDBF_LONG 5
|
|
#define oldDBF_DOUBLE 6
|
|
|
|
/* data request buffer types */
|
|
#define oldDBR_STRING oldDBF_STRING
|
|
#define oldDBR_INT oldDBF_INT
|
|
#define oldDBR_SHORT oldDBF_INT
|
|
#define oldDBR_FLOAT oldDBF_FLOAT
|
|
#define oldDBR_ENUM oldDBF_ENUM
|
|
#define oldDBR_CHAR oldDBF_CHAR
|
|
#define oldDBR_LONG oldDBF_LONG
|
|
#define oldDBR_DOUBLE oldDBF_DOUBLE
|
|
#define oldDBR_STS_STRING 7
|
|
#define oldDBR_STS_INT 8
|
|
#define oldDBR_STS_SHORT 8
|
|
#define oldDBR_STS_FLOAT 9
|
|
#define oldDBR_STS_ENUM 10
|
|
#define oldDBR_STS_CHAR 11
|
|
#define oldDBR_STS_LONG 12
|
|
#define oldDBR_STS_DOUBLE 13
|
|
#define oldDBR_TIME_STRING 14
|
|
#define oldDBR_TIME_INT 15
|
|
#define oldDBR_TIME_SHORT 15
|
|
#define oldDBR_TIME_FLOAT 16
|
|
#define oldDBR_TIME_ENUM 17
|
|
#define oldDBR_TIME_CHAR 18
|
|
#define oldDBR_TIME_LONG 19
|
|
#define oldDBR_TIME_DOUBLE 20
|
|
#define oldDBR_GR_STRING 21
|
|
#define oldDBR_GR_INT 22
|
|
#define oldDBR_GR_SHORT 22
|
|
#define oldDBR_GR_FLOAT 23
|
|
#define oldDBR_GR_ENUM 24
|
|
#define oldDBR_GR_CHAR 25
|
|
#define oldDBR_GR_LONG 26
|
|
#define oldDBR_GR_DOUBLE 27
|
|
#define oldDBR_CTRL_STRING 28
|
|
#define oldDBR_CTRL_INT 29
|
|
#define oldDBR_CTRL_SHORT 29
|
|
#define oldDBR_CTRL_FLOAT 30
|
|
#define oldDBR_CTRL_ENUM 31
|
|
#define oldDBR_CTRL_CHAR 32
|
|
#define oldDBR_CTRL_LONG 33
|
|
#define oldDBR_CTRL_DOUBLE 34
|
|
#define oldDBR_PUT_ACKT oldDBR_CTRL_DOUBLE + 1
|
|
#define oldDBR_PUT_ACKS oldDBR_PUT_ACKT + 1
|
|
#define oldDBR_STSACK_STRING oldDBR_PUT_ACKS + 1
|
|
#define oldDBR_CLASS_NAME oldDBR_STSACK_STRING + 1
|
|
|
|
typedef char DBSTRING[MAX_STRING_SIZE];
|
|
|
|
struct dbChannel * dbChannel_create(const char *pname)
|
|
{
|
|
dbChannel *chan = dbChannelCreate(pname);
|
|
|
|
if (!chan)
|
|
return NULL;
|
|
|
|
if (INVALID_DB_REQ(dbChannelExportType(chan)) ||
|
|
dbChannelOpen(chan)) {
|
|
dbChannelDelete(chan);
|
|
return NULL;
|
|
}
|
|
|
|
return chan;
|
|
}
|
|
|
|
int dbChannel_get(struct dbChannel *chan,
|
|
int buffer_type, void *pbuffer, long no_elements, void *pfl)
|
|
{
|
|
long nRequest = no_elements;
|
|
int result = dbChannel_get_count(
|
|
chan, buffer_type, pbuffer, &nRequest, pfl);
|
|
if (nRequest < no_elements) {
|
|
/* The database request returned fewer elements than requested, so
|
|
* fill the remainder of the buffer with zeros.
|
|
*/
|
|
int val_size = dbr_value_size[buffer_type];
|
|
int offset = dbr_size[buffer_type] + (nRequest - 1) * val_size;
|
|
int nbytes = (no_elements - nRequest) * val_size;
|
|
|
|
memset((char *)pbuffer + offset, 0, nbytes);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* Performs the work of the public db_get_field API, but also returns the number
|
|
* of elements actually copied to the buffer. The caller is responsible for
|
|
* zeroing the remaining part of the buffer. */
|
|
int dbChannel_get_count(
|
|
struct dbChannel *chan, int buffer_type,
|
|
void *pbuffer, long *nRequest, void *pfl)
|
|
{
|
|
long status;
|
|
long options;
|
|
long i;
|
|
long zero = 0;
|
|
unsigned char local_fl = 0;
|
|
|
|
/* The order of the DBR* elements in the "newSt" structures below is
|
|
* very important and must correspond to the order of processing
|
|
* in the dbAccess.c dbGet() and getOptions() routines.
|
|
*/
|
|
|
|
dbScanLock(dbChannelRecord(chan));
|
|
|
|
/* If filters are involved in a read, create field log and run filters */
|
|
if (!pfl && (ellCount(&chan->pre_chain) || ellCount(&chan->post_chain))) {
|
|
pfl = db_create_read_log(chan);
|
|
if (pfl) {
|
|
local_fl = 1;
|
|
pfl = dbChannelRunPreChain(chan, pfl);
|
|
pfl = dbChannelRunPostChain(chan, pfl);
|
|
}
|
|
}
|
|
|
|
switch(buffer_type) {
|
|
case(oldDBR_STRING):
|
|
status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
/* case(oldDBR_INT): */
|
|
case(oldDBR_SHORT):
|
|
status = dbChannelGet(chan, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
case(oldDBR_FLOAT):
|
|
status = dbChannelGet(chan, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
case(oldDBR_ENUM):
|
|
status = dbChannelGet(chan, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
case(oldDBR_CHAR):
|
|
status = dbChannelGet(chan, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
case(oldDBR_LONG):
|
|
status = dbChannelGet(chan, DBR_LONG, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
case(oldDBR_DOUBLE):
|
|
status = dbChannelGet(chan, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
|
|
break;
|
|
|
|
case(oldDBR_STS_STRING):
|
|
case(oldDBR_GR_STRING):
|
|
case(oldDBR_CTRL_STRING):
|
|
{
|
|
struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_STRING, pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
/* case(oldDBR_STS_INT): */
|
|
case(oldDBR_STS_SHORT):
|
|
{
|
|
struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_STS_FLOAT):
|
|
{
|
|
struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_STS_ENUM):
|
|
{
|
|
struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_STS_CHAR):
|
|
{
|
|
struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_STS_LONG):
|
|
{
|
|
struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
status = dbChannelGet(chan, DBR_LONG, &pold->value, &zero,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_STS_DOUBLE):
|
|
{
|
|
struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
|
|
case(oldDBR_TIME_STRING):
|
|
{
|
|
struct dbr_time_string *pold = (struct dbr_time_string *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_STRING, pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
/* case(oldDBR_TIME_INT): */
|
|
case(oldDBR_TIME_SHORT):
|
|
{
|
|
struct dbr_time_short *pold = (struct dbr_time_short *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_TIME_FLOAT):
|
|
{
|
|
struct dbr_time_float *pold = (struct dbr_time_float *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_TIME_ENUM):
|
|
{
|
|
struct dbr_time_enum *pold = (struct dbr_time_enum *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_TIME_CHAR):
|
|
{
|
|
struct dbr_time_char *pold = (struct dbr_time_char *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_CHAR, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_CHAR, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_TIME_LONG):
|
|
{
|
|
struct dbr_time_long *pold = (struct dbr_time_long *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_TIME_DOUBLE):
|
|
{
|
|
struct dbr_time_double *pold = (struct dbr_time_double *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRtime
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_TIME;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->stamp = newSt.time; /* structure copy */
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
|
|
/* case(oldDBR_GR_STRING): NOT IMPLEMENTED - use DBR_STS_STRING */
|
|
/* case(oldDBR_GR_INT): */
|
|
case(oldDBR_GR_SHORT):
|
|
{
|
|
struct dbr_gr_int *pold = (struct dbr_gr_int *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_GR_FLOAT):
|
|
{
|
|
struct dbr_gr_float *pold = (struct dbr_gr_float *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRprecision
|
|
DBRgrDouble
|
|
DBRalDouble
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
|
DBR_AL_DOUBLE;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->precision = (dbr_short_t) newSt.precision.dp;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);
|
|
pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);
|
|
pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);
|
|
pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);
|
|
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
|
|
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
/* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */
|
|
case(oldDBR_GR_CHAR):
|
|
{
|
|
struct dbr_gr_char *pold = (struct dbr_gr_char *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_GR_LONG):
|
|
{
|
|
struct dbr_gr_long *pold = (struct dbr_gr_long *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_GR_DOUBLE):
|
|
{
|
|
struct dbr_gr_double *pold = (struct dbr_gr_double *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRprecision
|
|
DBRgrDouble
|
|
DBRalDouble
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
|
DBR_AL_DOUBLE;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->precision = (dbr_short_t) newSt.precision.dp;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
|
|
/* case(oldDBR_CTRL_INT): */
|
|
case(oldDBR_CTRL_SHORT):
|
|
{
|
|
struct dbr_ctrl_int *pold = (struct dbr_ctrl_int *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRctrlLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
|
DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
|
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_CTRL_FLOAT):
|
|
{
|
|
struct dbr_ctrl_float *pold = (struct dbr_ctrl_float *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRprecision
|
|
DBRgrDouble
|
|
DBRctrlDouble
|
|
DBRalDouble
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
|
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->precision = (dbr_short_t) newSt.precision.dp;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);
|
|
pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);
|
|
pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);
|
|
pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);
|
|
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
|
|
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
|
|
pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit);
|
|
pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit);
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_GR_ENUM):
|
|
case(oldDBR_CTRL_ENUM):
|
|
{
|
|
struct dbr_ctrl_enum *pold = (struct dbr_ctrl_enum *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRenumStrs
|
|
} newSt;
|
|
short no_str;
|
|
|
|
memset(pold, '\0', sizeof(struct dbr_ctrl_enum));
|
|
/* first get status and severity */
|
|
options = DBR_STATUS | DBR_ENUM_STRS;
|
|
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
no_str = newSt.no_str;
|
|
if (no_str>16) no_str=16;
|
|
pold->no_str = no_str;
|
|
for (i = 0; i < no_str; i++)
|
|
strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i]));
|
|
/*now get values*/
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_CTRL_CHAR):
|
|
{
|
|
struct dbr_ctrl_char *pold = (struct dbr_ctrl_char *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRctrlLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
|
DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
|
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_CTRL_LONG):
|
|
{
|
|
struct dbr_ctrl_long *pold = (struct dbr_ctrl_long *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRgrLong
|
|
DBRctrlLong
|
|
DBRalLong
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
|
DBR_AL_LONG;
|
|
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
|
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
case(oldDBR_CTRL_DOUBLE):
|
|
{
|
|
struct dbr_ctrl_double *pold = (struct dbr_ctrl_double *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
DBRunits
|
|
DBRprecision
|
|
DBRgrDouble
|
|
DBRctrlDouble
|
|
DBRalDouble
|
|
} newSt;
|
|
|
|
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
|
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->precision = (dbr_short_t) newSt.precision.dp;
|
|
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
|
pold->units[MAX_UNITS_SIZE-1] = '\0';
|
|
pold->upper_disp_limit = newSt.upper_disp_limit;
|
|
pold->lower_disp_limit = newSt.lower_disp_limit;
|
|
pold->upper_alarm_limit = newSt.upper_alarm_limit;
|
|
pold->upper_warning_limit = newSt.upper_warning_limit;
|
|
pold->lower_warning_limit = newSt.lower_warning_limit;
|
|
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
|
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
|
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
|
|
nRequest, pfl);
|
|
}
|
|
break;
|
|
|
|
case(oldDBR_STSACK_STRING):
|
|
{
|
|
struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer;
|
|
struct {
|
|
DBRstatus
|
|
} newSt;
|
|
|
|
options = DBR_STATUS;
|
|
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
|
|
pold->status = newSt.status;
|
|
pold->severity = newSt.severity;
|
|
pold->ackt = newSt.ackt;
|
|
pold->acks = newSt.acks;
|
|
options = 0;
|
|
status = dbChannelGet(chan, DBR_STRING, pold->value,
|
|
&options, nRequest, pfl);
|
|
}
|
|
break;
|
|
|
|
case(oldDBR_CLASS_NAME):
|
|
{
|
|
DBENTRY dbEntry;
|
|
char *name = 0;
|
|
char *pto = (char *)pbuffer;
|
|
|
|
if (!pdbbase) {
|
|
status = S_db_notFound;
|
|
break;
|
|
}
|
|
dbInitEntry(pdbbase, &dbEntry);
|
|
status = dbFindRecord(&dbEntry, dbChannelRecord(chan)->name);
|
|
if (!status) name = dbGetRecordTypeName(&dbEntry);
|
|
dbFinishEntry(&dbEntry);
|
|
if (status) break;
|
|
if (!name) {
|
|
status = S_dbLib_recordTypeNotFound;
|
|
break;
|
|
}
|
|
pto[MAX_STRING_SIZE-1] = 0;
|
|
strncpy(pto, name, MAX_STRING_SIZE-1);
|
|
}
|
|
break;
|
|
default:
|
|
status = -1;
|
|
break;
|
|
}
|
|
|
|
dbScanUnlock(dbChannelRecord(chan));
|
|
|
|
if (local_fl) db_delete_field_log(pfl);
|
|
|
|
if (status) return -1;
|
|
return 0;
|
|
}
|
|
|
|
int dbChannel_put(struct dbChannel *chan, int src_type,
|
|
const void *psrc, long no_elements)
|
|
{
|
|
long status;
|
|
|
|
switch (src_type) {
|
|
case(oldDBR_STRING):
|
|
status = dbChannelPutField(chan, DBR_STRING, psrc, no_elements);
|
|
break;
|
|
/* case(oldDBR_INT): */
|
|
case(oldDBR_SHORT):
|
|
status = dbChannelPutField(chan, DBR_SHORT, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_FLOAT):
|
|
status = dbChannelPutField(chan, DBR_FLOAT, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_ENUM):
|
|
status = dbChannelPutField(chan, DBR_ENUM, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_CHAR):
|
|
status = dbChannelPutField(chan, DBR_UCHAR, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_LONG):
|
|
status = dbChannelPutField(chan, DBR_LONG, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_DOUBLE):
|
|
status = dbChannelPutField(chan, DBR_DOUBLE, psrc, no_elements);
|
|
break;
|
|
|
|
case(oldDBR_STS_STRING):
|
|
status = dbChannelPutField(chan, DBR_STRING,
|
|
((const struct dbr_sts_string *)psrc)->value, no_elements);
|
|
break;
|
|
/* case(oldDBR_STS_INT): */
|
|
case(oldDBR_STS_SHORT):
|
|
status = dbChannelPutField(chan, DBR_SHORT,
|
|
&((const struct dbr_sts_short *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_STS_FLOAT):
|
|
status = dbChannelPutField(chan, DBR_FLOAT,
|
|
&((const struct dbr_sts_float *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_STS_ENUM):
|
|
status = dbChannelPutField(chan, DBR_ENUM,
|
|
&((const struct dbr_sts_enum *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_STS_CHAR):
|
|
status = dbChannelPutField(chan, DBR_UCHAR,
|
|
&((const struct dbr_sts_char *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_STS_LONG):
|
|
status = dbChannelPutField(chan, DBR_LONG,
|
|
&((const struct dbr_sts_long *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_STS_DOUBLE):
|
|
status = dbChannelPutField(chan, DBR_DOUBLE,
|
|
&((const struct dbr_sts_double *)psrc)->value, no_elements);
|
|
break;
|
|
|
|
case(oldDBR_TIME_STRING):
|
|
status = dbChannelPutField(chan, DBR_TIME,
|
|
((const struct dbr_time_string *)psrc)->value, no_elements);
|
|
break;
|
|
/* case(oldDBR_TIME_INT): */
|
|
case(oldDBR_TIME_SHORT):
|
|
status = dbChannelPutField(chan, DBR_SHORT,
|
|
&((const struct dbr_time_short *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_TIME_FLOAT):
|
|
status = dbChannelPutField(chan, DBR_FLOAT,
|
|
&((const struct dbr_time_float *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_TIME_ENUM):
|
|
status = dbChannelPutField(chan, DBR_ENUM,
|
|
&((const struct dbr_time_enum *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_TIME_CHAR):
|
|
status = dbChannelPutField(chan, DBR_UCHAR,
|
|
&((const struct dbr_time_char *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_TIME_LONG):
|
|
status = dbChannelPutField(chan, DBR_LONG,
|
|
&((const struct dbr_time_long *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_TIME_DOUBLE):
|
|
status = dbChannelPutField(chan, DBR_DOUBLE,
|
|
&((const struct dbr_time_double *)psrc)->value, no_elements);
|
|
break;
|
|
|
|
case(oldDBR_GR_STRING):
|
|
/* no struct dbr_gr_string - use dbr_sts_string instead */
|
|
status = dbChannelPutField(chan, DBR_STRING,
|
|
((const struct dbr_sts_string *)psrc)->value, no_elements);
|
|
break;
|
|
/* case(oldDBR_GR_INT): */
|
|
case(oldDBR_GR_SHORT):
|
|
status = dbChannelPutField(chan, DBR_SHORT,
|
|
&((const struct dbr_gr_short *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_GR_FLOAT):
|
|
status = dbChannelPutField(chan, DBR_FLOAT,
|
|
&((const struct dbr_gr_float *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_GR_ENUM):
|
|
status = dbChannelPutField(chan, DBR_ENUM,
|
|
&((const struct dbr_gr_enum *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_GR_CHAR):
|
|
status = dbChannelPutField(chan, DBR_UCHAR,
|
|
&((const struct dbr_gr_char *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_GR_LONG):
|
|
status = dbChannelPutField(chan, DBR_LONG,
|
|
&((const struct dbr_gr_long *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_GR_DOUBLE):
|
|
status = dbChannelPutField(chan, DBR_DOUBLE,
|
|
&((const struct dbr_gr_double *)psrc)->value, no_elements);
|
|
break;
|
|
|
|
case(oldDBR_CTRL_STRING):
|
|
/* no struct dbr_ctrl_string - use dbr_sts_string instead */
|
|
status = dbChannelPutField(chan, DBR_STRING,
|
|
((const struct dbr_sts_string *)psrc)->value, no_elements);
|
|
break;
|
|
/* case(oldDBR_CTRL_INT): */
|
|
case(oldDBR_CTRL_SHORT):
|
|
status = dbChannelPutField(chan, DBR_SHORT,
|
|
&((const struct dbr_ctrl_short *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_CTRL_FLOAT):
|
|
status = dbChannelPutField(chan, DBR_FLOAT,
|
|
&((const struct dbr_ctrl_float *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_CTRL_ENUM):
|
|
status = dbChannelPutField(chan, DBR_ENUM,
|
|
&((const struct dbr_ctrl_enum *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_CTRL_CHAR):
|
|
status = dbChannelPutField(chan, DBR_UCHAR,
|
|
&((const struct dbr_ctrl_char *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_CTRL_LONG):
|
|
status = dbChannelPutField(chan, DBR_LONG,
|
|
&((const struct dbr_ctrl_long *)psrc)->value, no_elements);
|
|
break;
|
|
case(oldDBR_CTRL_DOUBLE):
|
|
status = dbChannelPutField(chan, DBR_DOUBLE,
|
|
&((const struct dbr_ctrl_double *)psrc)->value, no_elements);
|
|
break;
|
|
|
|
case(oldDBR_PUT_ACKT):
|
|
status = dbChannelPutField(chan, DBR_PUT_ACKT, psrc, no_elements);
|
|
break;
|
|
case(oldDBR_PUT_ACKS):
|
|
status = dbChannelPutField(chan, DBR_PUT_ACKS, psrc, no_elements);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
if (status) return -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int mapOldType (short oldtype)
|
|
{
|
|
int dbrType = -1;
|
|
|
|
switch (oldtype) {
|
|
case oldDBR_STRING:
|
|
dbrType = DBR_STRING;
|
|
break;
|
|
/* case oldDBR_INT: */
|
|
case oldDBR_SHORT:
|
|
dbrType = DBR_SHORT;
|
|
break;
|
|
case oldDBR_FLOAT:
|
|
dbrType = DBR_FLOAT;
|
|
break;
|
|
case oldDBR_ENUM:
|
|
dbrType = DBR_ENUM;
|
|
break;
|
|
case oldDBR_CHAR:
|
|
dbrType = DBR_UCHAR;
|
|
break;
|
|
case oldDBR_LONG:
|
|
dbrType = DBR_LONG;
|
|
break;
|
|
case oldDBR_DOUBLE:
|
|
dbrType = DBR_DOUBLE;
|
|
break;
|
|
case oldDBR_PUT_ACKT:
|
|
dbrType = DBR_PUT_ACKT;
|
|
break;
|
|
case oldDBR_PUT_ACKS:
|
|
dbrType = DBR_PUT_ACKS;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
return dbrType;
|
|
}
|
|
|
|
int db_put_process(processNotify *ppn, notifyPutType type,
|
|
int src_type, const void *psrc, int no_elements)
|
|
{
|
|
int status = 0;
|
|
int dbrType = mapOldType(src_type);
|
|
switch(type) {
|
|
case putDisabledType:
|
|
ppn->status = notifyError;
|
|
return 0;
|
|
case putFieldType:
|
|
status = dbChannelPutField(ppn->chan, dbrType, psrc, no_elements);
|
|
break;
|
|
case putType:
|
|
status = dbChannelPut(ppn->chan, dbrType, psrc, no_elements);
|
|
break;
|
|
}
|
|
if (status)
|
|
ppn->status = notifyError;
|
|
return 1;
|
|
}
|
|
|
|
void db_process(struct dbCommon *prec)
|
|
{
|
|
if (prec->pact) {
|
|
if (dbAccessDebugPUTF && prec->tpro)
|
|
printf("%s: dbPutField to Active '%s', setting RPRO=1\n",
|
|
epicsThreadGetNameSelf(), prec->name);
|
|
prec->rpro = TRUE;
|
|
} else {
|
|
/* indicate that dbPutField called dbProcess */
|
|
prec->putf = TRUE;
|
|
(void)dbProcess(prec);
|
|
}
|
|
}
|