Skip to content

Commit

Permalink
Merge 7527f78 into d317b27
Browse files Browse the repository at this point in the history
  • Loading branch information
mdavidsaver committed Nov 3, 2020
2 parents d317b27 + 7527f78 commit c199689
Show file tree
Hide file tree
Showing 16 changed files with 528 additions and 2 deletions.
21 changes: 20 additions & 1 deletion modules/database/src/ioc/db/dbAccess.c
Expand Up @@ -626,6 +626,8 @@ long dbEntryToAddr(const DBENTRY *pdbentry, DBADDR *paddr)
paddr->field_size = pflddes->size;
paddr->special = pflddes->special;
paddr->dbr_field_type = mapDBFToDBR[dbfType];
paddr->ro = 0;
paddr->vfields = NULL;

if (paddr->special == SPC_DBADDR) {
const rset *prset = dbGetRset(paddr);
Expand Down Expand Up @@ -912,6 +914,15 @@ long dbGet(DBADDR *paddr, short dbrType,

if (options && *options)
getOptions(paddr, &pbuf, options, pflin);

if (dbrType==DBR_VFIELD) {
VField* vfield = (VField*)pbuffer;
if(!paddr->vfields || !(prset=dbGetRset(paddr))->get_vfield)
return S_db_badDbrtype;

return prset->get_vfield(paddr, vfield);
}

if (nRequest && *nRequest == 0)
return 0;

Expand Down Expand Up @@ -1314,7 +1325,15 @@ long dbPut(DBADDR *paddr, short dbrType,
dbFldDes *pfldDes;
int isValueField;

if (special == SPC_ATTRIBUTE)
if (dbrType == DBR_VFIELD) {
const VField* vfield = (const VField*)pbuffer;
if(!paddr->vfields || !prset->put_vfield)
return S_db_badDbrtype;

return prset->put_vfield(paddr, vfield);
}

if (special == SPC_ATTRIBUTE || paddr->ro)
return S_db_noMod;

if (dbrType == DBR_PUT_ACKT && field_type <= DBF_DEVICE) {
Expand Down
5 changes: 5 additions & 0 deletions modules/database/src/ioc/db/dbAddr.h
Expand Up @@ -11,14 +11,19 @@
#ifndef dbAddrh
#define dbAddrh

#include <ellLib.h>

struct dbCommon;
struct dbFldDes;
struct VFieldType;

typedef struct dbAddr {
struct dbCommon *precord; /* address of record */
void *pfield; /* address of field */
struct dbFldDes *pfldDes; /* address of struct fldDes */
const ELLLIST* vfields; /* list of VFieldTypeNode, vtypes to try with rset::get/put_vfield */
long no_elements; /* number of elements (arrays) */
unsigned ro:1; /* dbPut permitted? */
short field_type; /* type of database field */
short field_size; /* size of the field being accessed */
short special; /* special processing */
Expand Down
3 changes: 3 additions & 0 deletions modules/database/src/ioc/db/dbChannel.h
Expand Up @@ -199,6 +199,9 @@ DBCORE_API extern unsigned short dbDBRnewToDBRold[];
/* evaluates to short */
#define dbChannelSpecial(pChan) ((pChan)->addr.special)

/* evaluates to const ELLLIST* containing VFieldTypeNode::node */
#define dbChannelVFields(pChan) ((pChan)->addr.vfields)

/* Channel filters do not get to interpose here since there are many
* places where the field pointer is compared with the address of a
* specific record field, so they can't modify the pointer value.
Expand Down
3 changes: 3 additions & 0 deletions modules/database/src/ioc/db/dbDbLink.c
Expand Up @@ -177,11 +177,14 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
} else {
unsigned short dbfType = paddr->field_type;

if (dbrType==DBR_VFIELD && paddr->vfields) {}
else
if (dbrType < 0 || dbrType > DBR_ENUM || dbfType > DBF_DEVICE)
return S_db_badDbrtype;

if (paddr->no_elements == 1 && (!pnRequest || *pnRequest == 1)
&& paddr->special != SPC_DBADDR
&& dbrType!=DBR_VFIELD
&& paddr->special != SPC_ATTRIBUTE) {
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
Expand Down
3 changes: 3 additions & 0 deletions modules/database/src/ioc/db/dbUnitTest.c
Expand Up @@ -108,6 +108,7 @@ union anybuf {
epicsAny val;
char valStr[MAX_STRING_SIZE];
char bytes[sizeof(epicsAny)];
void *ptr;
};

long testdbVPutField(const char* pv, short dbrType, va_list ap)
Expand Down Expand Up @@ -145,6 +146,8 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap)
OP(DBR_DOUBLE, double, float64);
OP(DBR_ENUM, int, enum16);
#undef OP
case DBR_VFIELD:
return dbPutField(&addr, dbrType, va_arg(ap, void*), 1);
default:
testFail("invalid DBR: dbPutField(\"%s\", %d, ...)",
addr.precord->name, dbrType);
Expand Down
15 changes: 15 additions & 0 deletions modules/database/src/ioc/dbStatic/dbFldTypes.h
Expand Up @@ -15,11 +15,25 @@
#define INCdbFldTypesh 1

#include "shareLib.h"
#include "ellLib.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct VFieldType {
const char* name;
} VFieldType;

typedef struct VFieldTypeNode {
ELLNODE node;
const VFieldType* vtype;
} VFieldTypeNode;

typedef struct VField {
const VFieldType* vtype;
} VField;

/* field types */
typedef enum {
DBF_STRING,
Expand Down Expand Up @@ -87,6 +101,7 @@ mapdbfType pamapdbfType[DBF_NTYPES] = {
#define DBR_ENUM DBF_ENUM
#define DBR_PUT_ACKT DBR_ENUM+1
#define DBR_PUT_ACKS DBR_PUT_ACKT+1
#define DBR_VFIELD (DBR_PUT_ACKS+1)
#define DBR_NOACCESS DBF_NOACCESS
#define VALID_DB_REQ(x) ((x >= 0) && (x <= DBR_ENUM))
#define INVALID_DB_REQ(x) ((x < 0) || (x > DBR_ENUM))
Expand Down
7 changes: 6 additions & 1 deletion modules/database/src/ioc/dbStatic/recSup.h
Expand Up @@ -32,6 +32,7 @@ struct dbr_enumStrs;
struct dbr_grDouble;
struct dbr_ctrlDouble;
struct dbr_alDouble;
struct VField;

/* record support entry table */
struct typed_rset {
Expand All @@ -53,6 +54,8 @@ struct typed_rset {
long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p);
long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p);
long (*get_alarm_double)(struct dbAddr *paddr, struct dbr_alDouble *p);
long (*get_vfield)(struct dbAddr *paddr, struct VField *p);
long (*put_vfield)(struct dbAddr *paddr, const struct VField *p);
};

#ifdef USE_TYPED_RSET
Expand Down Expand Up @@ -84,13 +87,15 @@ struct rset { /* record support entry table */
long (*get_graphic_double)();
long (*get_control_double)();
long (*get_alarm_double)();
long (*get_vfield)(struct dbAddr *paddr, struct VField *p);
long (*put_vfield)(struct dbAddr *paddr, const struct VField *p);
} EPICS_DEPRECATED;

typedef struct rset rset EPICS_DEPRECATED;

#endif

#define RSETNUMBER 17
#define RSETNUMBER 19

#define S_rec_noRSET (M_recSup| 1) /*Missing record support entry table*/
#define S_rec_noSizeOffset (M_recSup| 2) /*Missing SizeOffset Routine*/
Expand Down
2 changes: 2 additions & 0 deletions modules/database/src/std/dev/Makefile
Expand Up @@ -48,6 +48,8 @@ dbRecStd_SRCS += devSiSoft.c
dbRecStd_SRCS += devSoSoft.c
dbRecStd_SRCS += devWfSoft.c

dbRecStd_SRCS += devSSiSoft.c

dbRecStd_SRCS += devAiSoftCallback.c
dbRecStd_SRCS += devBiSoftCallback.c
dbRecStd_SRCS += devI64inSoftCallback.c
Expand Down
91 changes: 91 additions & 0 deletions modules/database/src/std/dev/devSSiSoft.cpp
@@ -0,0 +1,91 @@
/*************************************************************************\
* Copyright (c) 2020 Michael Davidsaver
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/

#ifndef USE_TYPED_DSET
# define USE_TYPED_DSET
#endif

#include <dbAccess.h>
#include <recGbl.h>

// include by stdstringinRecord.h
#include "epicsTypes.h"
#include "link.h"
#include "epicsMutex.h"
#include "ellLib.h"
#include "devSup.h"
#include "epicsTime.h"

#define epicsExportSharedSymbols

#include "stdstringinRecord.h"
#include <epicsExport.h>

namespace {

long init_record(struct dbCommon *pcommon)
{
stdstringinRecord *prec = (stdstringinRecord *)pcommon;
VString ival;
ival.vtype = &vfStdString;

if (recGblInitConstantLink(&prec->inp, DBR_VFIELD, &ival)) {
prec->udf = FALSE;
prec->val = ival.value;
}

return 0;
}

long readLocked(struct link *pinp, void *dummy)
{
stdstringinRecord *prec = (stdstringinRecord *) pinp->precord;

VString ival;
ival.vtype = &vfStdString;

long status;
if(!(status = dbGetLink(pinp, DBR_VFIELD, &ival, 0, 0))) {
prec->val = ival.value;

} else if (status==S_db_badDbrtype) {
char str[MAX_STRING_SIZE];
if(!(status = dbGetLink(pinp, DBR_STRING, str, 0, 0))) {
str[MAX_STRING_SIZE-1] = '\0';
prec->val = str;
}
}
if (status) return status;

if (dbLinkIsConstant(&prec->tsel) &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(pinp, &prec->time);

return status;
}

long read_ssi(stdstringinRecord* prec)
{
long status = dbLinkDoLocked(&prec->inp, readLocked, NULL);

if (status == S_db_noLSET)
status = readLocked(&prec->inp, NULL);

if (!status && !dbLinkIsConstant(&prec->inp))
prec->udf = FALSE;

return status;
}

stdstringindset devSSiSoft = {
{5, NULL, NULL, &init_record, NULL},
&read_ssi
};

}
extern "C" {
epicsExportAddress(dset, devSSiSoft);
}
2 changes: 2 additions & 0 deletions modules/database/src/std/dev/devSoft.dbd
Expand Up @@ -25,6 +25,8 @@ device(stringout,CONSTANT,devSoSoft,"Soft Channel")
device(subArray,CONSTANT,devSASoft,"Soft Channel")
device(waveform,CONSTANT,devWfSoft,"Soft Channel")

device(stdstringin,CONSTANT,devSSiSoft,"Soft Channel")

device(ai,CONSTANT,devAiSoftRaw,"Raw Soft Channel")
device(ao,CONSTANT,devAoSoftRaw,"Raw Soft Channel")
device(bi,CONSTANT,devBiSoftRaw,"Raw Soft Channel")
Expand Down
2 changes: 2 additions & 0 deletions modules/database/src/std/rec/Makefile
Expand Up @@ -46,6 +46,8 @@ stdRecords += subRecord
stdRecords += subArrayRecord
stdRecords += waveformRecord

stdRecords += stdstringinRecord

DBDINC += $(stdRecords)

# Generate stdRecords.dbd, not really by concatenation, see RULES
Expand Down

0 comments on commit c199689

Please sign in to comment.