diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index d1ea856ec..ba0865461 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -1216,10 +1216,10 @@ static long dbPutFieldLink(DBADDR *paddr, plink->value.pv_link.lastGetdbrType = 0; break; + case PV_LINK: case CONSTANT: break; /* do nothing */ - case PV_LINK: case MACRO_LINK: break; /* should never get here */ @@ -1292,7 +1292,7 @@ static long dbPutFieldLink(DBADDR *paddr, break; case CONSTANT: - break; + break; /* do nothing */ case DB_LINK: case CA_LINK: diff --git a/src/ioc/db/dbNotify.h b/src/ioc/db/dbNotify.h index 4812368b5..7d93080b9 100644 --- a/src/ioc/db/dbNotify.h +++ b/src/ioc/db/dbNotify.h @@ -45,7 +45,7 @@ typedef enum { typedef enum { getFieldType, - getType + getType /* FIXME: Never used? */ }notifyGetType; typedef enum { diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index 8841e1aeb..e5b3bdd89 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -59,6 +59,7 @@ epicsShareDef maplinkType pamaplinkType[LINK_NTYPES] = { {"GPIB_IO",GPIB_IO}, {"BITBUS_IO",BITBUS_IO}, {"MACRO_LINK",MACRO_LINK}, + {"PN_LINK",PN_LINK}, {"DB_LINK",DB_LINK}, {"CA_LINK",CA_LINK}, {"INST_IO",INST_IO}, @@ -291,7 +292,8 @@ static long setLinkType(DBENTRY *pdbentry) } type = plink->type; - if ((type == CONSTANT || type == PV_LINK || type == DB_LINK || type == CA_LINK) && + if ((type == CONSTANT || type == PV_LINK || + type == PN_LINK || type == DB_LINK || type == CA_LINK) && (link_type == CONSTANT || link_type == PV_LINK)) goto done; dbFreeLinkContents(plink); @@ -2015,6 +2017,12 @@ char * epicsShareAPI dbGetString(DBENTRY *pdbentry) strcpy(message,""); } break; + case PN_LINK: + if(plink->value.pv_link.pvname) + strcpy(message,plink->value.pv_link.pvname); + else + strcpy(message,""); + break; case PV_LINK: case CA_LINK: case DB_LINK: { @@ -3706,6 +3714,7 @@ int epicsShareAPI dbGetLinkType(DBENTRY *pdbentry) case CONSTANT: return(DCT_LINK_CONSTANT); case PV_LINK: + case PN_LINK: case DB_LINK: case CA_LINK: return(DCT_LINK_PV); diff --git a/src/ioc/dbStatic/link.h b/src/ioc/dbStatic/link.h index c9818f6f0..4b9948dbf 100644 --- a/src/ioc/dbStatic/link.h +++ b/src/ioc/dbStatic/link.h @@ -35,13 +35,15 @@ extern "C" { #define GPIB_IO 5 #define BITBUS_IO 6 #define MACRO_LINK 7 + +#define PN_LINK 9 #define DB_LINK 10 #define CA_LINK 11 #define INST_IO 12 /* instrument */ #define BBGPIB_IO 13 /* bitbus -> gpib */ #define RF_IO 14 #define VXI_IO 15 -#define LINK_NTYPES 14 +#define LINK_NTYPES 15 typedef struct maplinkType{ char *strvalue; int value; diff --git a/src/ioc/misc/iocInit.c b/src/ioc/misc/iocInit.c index b394bec50..5e271766a 100644 --- a/src/ioc/misc/iocInit.c +++ b/src/ioc/misc/iocInit.c @@ -426,7 +426,6 @@ static void doInitRecord0(dbRecordType *pdbRecordType, dbCommon *precord, static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord, void *user) { - devSup *pdevSup; int j; /* Convert all PV_LINKs to DB_LINKs or CA_LINKs */ @@ -435,6 +434,19 @@ static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord, dbFldDes *pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]]; DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset); + int isDevLink = ellCount(&precord->rdes->devList) > 0 && + (strcmp(pdbFldDes->name, "INP") == 0 || strcmp(pdbFldDes->name, "OUT") == 0); + + if (isDevLink) { + devSup *pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp); + + if (pdevSup) { + struct dsxt *pdsxt = pdevSup->pdsxt; + if (pdsxt && pdsxt->add_record) { + pdsxt->add_record(precord); + } + } + } if (plink->type == PV_LINK) { DBADDR dbaddr; @@ -469,13 +481,6 @@ static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord, } } } - pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp); - if (pdevSup) { - struct dsxt *pdsxt = pdevSup->pdsxt; - if (pdsxt && pdsxt->add_record) { - pdsxt->add_record(precord); - } - } } static void doInitRecord1(dbRecordType *pdbRecordType, dbCommon *precord, diff --git a/src/std/dev/devAiSoftCallback.c b/src/std/dev/devAiSoftCallback.c index 89c59016e..24b933d88 100644 --- a/src/std/dev/devAiSoftCallback.c +++ b/src/std/dev/devAiSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,17 +8,20 @@ \*************************************************************************/ /* devAiSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson + */ + +/* TODO: + * Support MS/MSS/MSI link flags */ #include #include -#include #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +32,35 @@ #include "aiRecord.h" #include "epicsExport.h" -/* Create the dset for devAiSoftCallback */ -static long init_record(); -static long read_ai(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_ai; - DEVSUPFUN special_linconv; -}devAiSoftCallback={ - 6, - NULL, - NULL, - init_record, - NULL, - read_ai, - NULL}; -epicsExportAddress(dset,devAiSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; double value; - int status; -}notifyInfo; + int status; + int smooth; +} notifyInfo; -static void getCallback(processNotify *ppn,notifyGetType type) +static void getCallback(processNotify *ppn, notifyGetType type) { - struct aiRecord *prec = (struct aiRecord *)ppn->usrPvt; + aiRecord *prec = (aiRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if(ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status == notifyCanceled) { + printf("devAiSoftCallback::getCallback notifyCanceled\n"); return; } - switch(type) { + + switch (type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_DOUBLE,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_DOUBLE, &pnotifyInfo->value, + &options, &no_elements, 0); break; case getType: - status = dbGet(ppn->paddr,DBR_DOUBLE,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr, DBR_DOUBLE, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +68,152 @@ static void getCallback(processNotify *ppn,notifyGetType type) static void doneCallback(processNotify *ppn) { - struct aiRecord *prec = (struct aiRecord *)ppn->usrPvt; + aiRecord *prec = (aiRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } - -static long init_record(struct aiRecord *prec) +static long add_record(dbCommon *pcommon) { + aiRecord *prec = (aiRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; + DBADDR *pdbaddr; long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if(plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devAiSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; - return(S_db_badField); + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devAiSoftCallback (add_record) Illegal INP field"); + return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devAiSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); - if(status) { - recGblRecordError(status,(void *)prec, - "devAiSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; - return(status); + "devAiSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); + if (status) { + free(pdbaddr); + recGblRecordError(status, (void *)prec, + "devAiSoftCallback (add_record) link target not found"); + return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devAiSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devAiSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devAiSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devAiSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devAiSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devAiSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } +static long del_record(dbCommon *pcommon) { + aiRecord *prec = (aiRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(aiRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBF_DOUBLE, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devAiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + static long read_ai(aiRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if(prec->pact) { - if(pnotifyInfo->status) { - recGblSetSevr(prec,READ_ALARM,INVALID_ALARM); - return(2); - } - prec->val = pnotifyInfo->value; - prec->udf = FALSE; - return(2); + if (!prec->dpvt) + return 2; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return(0); + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + pnotifyInfo->smooth = FALSE; + return 2; + } + + /* Apply smoothing algorithm */ + if (prec->smoo != 0.0 && pnotifyInfo->smooth) + prec->val = pnotifyInfo->value * (1.0 - prec->smoo) + prec->val * prec->smoo; + else + prec->val = pnotifyInfo->value; + prec->udf = FALSE; + pnotifyInfo->smooth = TRUE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 2; } + +/* Create the dset for devAiSoftCallback */ +struct { + dset common; + DEVSUPFUN read_ai; + DEVSUPFUN special_linconv; +} devAiSoftCallback = { + {6, NULL, init, init_record, NULL}, + read_ai, + NULL +}; +epicsExportAddress(dset, devAiSoftCallback); diff --git a/src/std/dev/devBiSoftCallback.c b/src/std/dev/devBiSoftCallback.c index 8a9c97c8f..a19609ee6 100644 --- a/src/std/dev/devBiSoftCallback.c +++ b/src/std/dev/devBiSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,17 +8,16 @@ \*************************************************************************/ /* devBiSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson */ #include #include -#include #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +28,34 @@ #include "biRecord.h" #include "epicsExport.h" -/* Create the dset for devBiSoftCallback */ -static long init_record(); -static long read_bi(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_bi; - DEVSUPFUN special_linconv; -}devBiSoftCallback={ - 6, - NULL, - NULL, - init_record, - NULL, - read_bi, - NULL}; -epicsExportAddress(dset,devBiSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; - unsigned short value; - int status; -}notifyInfo; + epicsEnum16 value; + int status; +} notifyInfo; static void getCallback(processNotify *ppn,notifyGetType type) { - struct biRecord *prec = (struct biRecord *)ppn->usrPvt; + biRecord *prec = (biRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if(ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status == notifyCanceled) { + printf("devBiSoftCallback::getCallback notifyCanceled\n"); return; } - switch(type) { + + switch (type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_ENUM, &pnotifyInfo->value, + &options, &no_elements, 0); break; case getType: - status = dbGet(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr, DBR_ENUM, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +63,144 @@ static void getCallback(processNotify *ppn,notifyGetType type) static void doneCallback(processNotify *ppn) { - struct biRecord *prec = (struct biRecord *)ppn->usrPvt; + biRecord *prec = (biRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } - -static long init_record(struct biRecord *prec) +static long add_record(dbCommon *pcommon) { + biRecord *prec = (biRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; + DBADDR *pdbaddr; long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if(plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devBiSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; - return(S_db_badField); + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devBiSoftCallback (add_record) Illegal INP field"); + return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devBiSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); - if(status) { - recGblRecordError(status,(void *)prec, - "devBiSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; - return(status); + "devBiSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); + if (status) { + free(pdbaddr); + recGblRecordError(status, (void *)prec, + "devBiSoftCallback (add_record) link target not found"); + return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devBiSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devBiSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devBiSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devBiSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devBiSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devBiSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } +static long del_record(dbCommon *pcommon) { + biRecord *prec = (biRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(biRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devBiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + static long read_bi(biRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if(prec->pact) { - if(pnotifyInfo->status) { - recGblSetSevr(prec,READ_ALARM,INVALID_ALARM); - return(2); - } - prec->val = pnotifyInfo->value; - prec->udf = FALSE; - return(2); + if (!prec->dpvt) + return 2; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return(0); + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + return 2; + } + + prec->val = pnotifyInfo->value; + prec->udf = FALSE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 2; } + +/* Create the dset for devBiSoftCallback */ +struct { + dset common; + DEVSUPFUN read_bi; +} devBiSoftCallback = { + {5, NULL, init, init_record, NULL}, + read_bi +}; +epicsExportAddress(dset, devBiSoftCallback); diff --git a/src/std/dev/devLiSoftCallback.c b/src/std/dev/devLiSoftCallback.c index de87dbc06..fe710d579 100644 --- a/src/std/dev/devLiSoftCallback.c +++ b/src/std/dev/devLiSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,17 +8,16 @@ \*************************************************************************/ /* devLiSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson */ #include #include -#include #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +28,34 @@ #include "longinRecord.h" #include "epicsExport.h" -/* Create the dset for devLiSoftCallback */ -static long init_record(); -static long read_li(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_li; - DEVSUPFUN special_linconv; -}devLiSoftCallback={ - 6, - NULL, - NULL, - init_record, - NULL, - read_li, - NULL}; -epicsExportAddress(dset,devLiSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; - long value; - int status; -}notifyInfo; + epicsInt32 value; + int status; +} notifyInfo; -static void getCallback(processNotify *ppn,notifyGetType type) +static void getCallback(processNotify *ppn, notifyGetType type) { - struct longinRecord *prec = (struct longinRecord *)ppn->usrPvt; + longinRecord *prec = (longinRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if(ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status == notifyCanceled) { + printf("devLiSoftCallback::getCallback notifyCanceled\n"); return; } - switch(type) { + + switch (type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_LONG,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_LONG, &pnotifyInfo->value, + &options, &no_elements, 0); break; case getType: - status = dbGet(ppn->paddr,DBR_LONG,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr, DBR_LONG, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +63,144 @@ static void getCallback(processNotify *ppn,notifyGetType type) static void doneCallback(processNotify *ppn) { - struct longinRecord *prec = (struct longinRecord *)ppn->usrPvt; + longinRecord *prec = (longinRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } - -static long init_record(struct longinRecord *prec) +static long add_record(dbCommon *pcommon) { + longinRecord *prec = (longinRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; + DBADDR *pdbaddr; long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if(plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devLiSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; - return(S_db_badField); + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devLiSoftCallback (add_record) Illegal INP field"); + return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devLiSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); - if(status) { - recGblRecordError(status,(void *)prec, + "devLiSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); + if (status) { + free(pdbaddr); + recGblRecordError(status, (void *)prec, "devLiSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; - return(status); + return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devLiSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devLiSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devLiSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devLiSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devLiSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devLiSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } +static long del_record(dbCommon *pcommon) { + longinRecord *prec = (longinRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(longinRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devLiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + static long read_li(longinRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if(prec->pact) { - if(pnotifyInfo->status) { - recGblSetSevr(prec,READ_ALARM,INVALID_ALARM); - return(pnotifyInfo->status); - } - prec->val = pnotifyInfo->value; - prec->udf = FALSE; - return(0); + if (!prec->dpvt) + return 0; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return(0); + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + return pnotifyInfo->status; + } + + prec->val = pnotifyInfo->value; + prec->udf = FALSE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 0; } + +/* Create the dset for devLiSoftCallback */ +struct { + dset common; + DEVSUPFUN read_li; +} devLiSoftCallback = { + {5, NULL, init, init_record, NULL}, + read_li +}; +epicsExportAddress(dset, devLiSoftCallback); diff --git a/src/std/dev/devMbbiDirectSoftCallback.c b/src/std/dev/devMbbiDirectSoftCallback.c index e56ef6e16..96c8b7cea 100644 --- a/src/std/dev/devMbbiDirectSoftCallback.c +++ b/src/std/dev/devMbbiDirectSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,17 +8,16 @@ \*************************************************************************/ /* devMbbiDirectSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson */ #include #include -#include #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +28,34 @@ #include "mbbiDirectRecord.h" #include "epicsExport.h" -/* Create the dset for devMbbiDirectSoftCallback */ -static long init_record(); -static long read_mbbiDirect(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_mbbiDirect; - DEVSUPFUN special_linconv; -} devMbbiDirectSoftCallback = { - 6, - NULL, - NULL, - init_record, - NULL, - read_mbbiDirect, - NULL}; -epicsExportAddress(dset, devMbbiDirectSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; - unsigned short value; - int status; + epicsUInt16 value; + int status; } notifyInfo; static void getCallback(processNotify *ppn, notifyGetType type) { - struct mbbiDirectRecord *prec = (struct mbbiDirectRecord *)ppn->usrPvt; + mbbiDirectRecord *prec = (mbbiDirectRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if (ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status == notifyCanceled) { + printf("devMbbiDirectSoftCallback::getCallback notifyCanceled\n"); return; } + switch (type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_USHORT, &pnotifyInfo->value, + &options, &no_elements, 0); break; case getType: - status = dbGet(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr, DBR_USHORT, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +63,144 @@ static void getCallback(processNotify *ppn, notifyGetType type) static void doneCallback(processNotify *ppn) { - struct mbbiDirectRecord *prec = (struct mbbiDirectRecord *)ppn->usrPvt; + mbbiDirectRecord *prec = (mbbiDirectRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } - -static long init_record(struct mbbiDirectRecord *prec) +static long add_record(dbCommon *pcommon) { + mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; - long status; + DBADDR *pdbaddr; + long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if (plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devMbbiDirectSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devMbbiDirectSoftCallback (add_record) Illegal INP field"); return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devMbbiDirectSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); + "devMbbiDirectSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); if (status) { + free(pdbaddr); recGblRecordError(status,(void *)prec, - "devMbbiDirectSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; + "devMbbiDirectSoftCallback (add_record) linked record not found"); return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devMbbiDirectSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devMbbiDirectSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devMbbiDirectSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devMbbiDirectSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devMbbiDirectSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devMbbiDirectSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } +static long del_record(dbCommon *pcommon) { + mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(mbbiDirectRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devMbbiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + static long read_mbbiDirect(mbbiDirectRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if (prec->pact) { - if (pnotifyInfo->status) { - recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); - return 2; - } - prec->val = pnotifyInfo->value; - prec->udf = FALSE; + if (!prec->dpvt) + return 2; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; + } + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); return 2; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return 0; + + prec->val = pnotifyInfo->value; + prec->udf = FALSE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 2; } + +/* Create the dset for devMbbiDirectSoftCallback */ +struct { + dset common; + DEVSUPFUN read_mbbiDirect; +} devMbbiDirectSoftCallback = { + {5, NULL, init, init_record, NULL}, + read_mbbiDirect +}; +epicsExportAddress(dset, devMbbiDirectSoftCallback); diff --git a/src/std/dev/devMbbiSoftCallback.c b/src/std/dev/devMbbiSoftCallback.c index 71afe482a..fbac4f6f7 100644 --- a/src/std/dev/devMbbiSoftCallback.c +++ b/src/std/dev/devMbbiSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,17 +8,16 @@ \*************************************************************************/ /* devMbbiSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson */ #include #include -#include #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +28,34 @@ #include "mbbiRecord.h" #include "epicsExport.h" -/* Create the dset for devMbbiSoftCallback */ -static long init_record(); -static long read_mbbi(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_mbbi; - DEVSUPFUN special_linconv; -}devMbbiSoftCallback={ - 6, - NULL, - NULL, - init_record, - NULL, - read_mbbi, - NULL}; -epicsExportAddress(dset,devMbbiSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; - unsigned short value; - int status; -}notifyInfo; + epicsEnum16 value; + int status; +} notifyInfo; -static void getCallback(processNotify *ppn,notifyGetType type) +static void getCallback(processNotify *ppn, notifyGetType type) { - struct mbbiRecord *prec = (struct mbbiRecord *)ppn->usrPvt; + mbbiRecord *prec = (mbbiRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if(ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status == notifyCanceled) { + printf("devMbbiSoftCallback::getCallback notifyCanceled\n"); return; } - switch(type) { + + switch (type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_ENUM, &pnotifyInfo->value, + &options, &no_elements,0); break; case getType: - status = dbGet(ppn->paddr,DBR_USHORT,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr,DBR_ENUM, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +63,144 @@ static void getCallback(processNotify *ppn,notifyGetType type) static void doneCallback(processNotify *ppn) { - struct mbbiRecord *prec = (struct mbbiRecord *)ppn->usrPvt; + mbbiRecord *prec = (mbbiRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } - -static long init_record(struct mbbiRecord *prec) +static long add_record(dbCommon *pcommon) { + mbbiRecord *prec = (mbbiRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; - long status; + DBADDR *pdbaddr; + long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if(plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devMbbiSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; - return(S_db_badField); + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devMbbiSoftCallback (add_record) Illegal INP field"); + return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devMbbiSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); - if(status) { - recGblRecordError(status,(void *)prec, - "devMbbiSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; - return(status); + "devMbbiSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); + if (status) { + free(pdbaddr); + recGblRecordError(status, (void *)prec, + "devMbbiSoftCallback (add_record) linked record not found"); + return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devMbbiSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devMbbiSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devMbbiSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devMbbiSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devMbbiSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devMbbiSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } +static long del_record(dbCommon *pcommon) { + mbbiRecord *prec = (mbbiRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(mbbiRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devMbbiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + static long read_mbbi(mbbiRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if(prec->pact) { - if(pnotifyInfo->status) { - recGblSetSevr(prec,READ_ALARM,INVALID_ALARM); - return(2); - } - prec->val = pnotifyInfo->value; - prec->udf = FALSE; - return(2); + if (!prec->dpvt) + return 2; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return(0); + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + return 2; + } + + prec->val = pnotifyInfo->value; + prec->udf = FALSE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 2; } + +/* Create the dset for devMbbiSoftCallback */ +struct { + dset common; + DEVSUPFUN read_mbbi; +} devMbbiSoftCallback = { + {5, NULL, init, init_record, NULL}, + read_mbbi +}; +epicsExportAddress(dset,devMbbiSoftCallback); diff --git a/src/std/dev/devSiSoftCallback.c b/src/std/dev/devSiSoftCallback.c index c5ac85d48..85f7efc3f 100644 --- a/src/std/dev/devSiSoftCallback.c +++ b/src/std/dev/devSiSoftCallback.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 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. @@ -8,8 +8,7 @@ \*************************************************************************/ /* devSiSoftCallback.c */ /* - * Author: Marty Kraimer - * Date: 23APR2008 + * Authors: Marty Kraimer & Andrew Johnson */ #include @@ -19,6 +18,7 @@ #include "alarm.h" #include "callback.h" #include "cantProceed.h" +#include "dbCommon.h" #include "dbDefs.h" #include "dbAccess.h" #include "dbNotify.h" @@ -29,54 +29,34 @@ #include "stringinRecord.h" #include "epicsExport.h" -/* Create the dset for devSiSoftCallback */ -static long init_record(); -static long read_stringin(); -struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_stringin; - DEVSUPFUN special_linconv; -}devSiSoftCallback={ - 6, - NULL, - NULL, - init_record, - NULL, - read_stringin, - NULL}; -epicsExportAddress(dset,devSiSoftCallback); - typedef struct notifyInfo { processNotify *ppn; CALLBACK *pcallback; - char value[40]; - int status; -}notifyInfo; + char value[MAX_STRING_SIZE]; + int status; +} notifyInfo; -static void getCallback(processNotify *ppn,notifyGetType type) +static void getCallback(processNotify *ppn, notifyGetType type) { - struct stringinRecord *prec = (struct stringinRecord *)ppn->usrPvt; + stringinRecord *prec = (stringinRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; int status = 0; long no_elements = 1; long options = 0; - if(ppn->status==notifyCanceled) { - printf("dbtpn:getCallback notifyCanceled\n"); + if (ppn->status==notifyCanceled) { + printf("devSiSoftCallback::getCallback notifyCanceled\n"); return; } + switch(type) { case getFieldType: - status = dbGetField(ppn->paddr,DBR_STRING,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGetField(ppn->paddr, DBR_STRING, &pnotifyInfo->value, + &options, &no_elements, 0); break; case getType: - status = dbGet(ppn->paddr,DBR_STRING,&pnotifyInfo->value, - &options,&no_elements,0); + status = dbGet(ppn->paddr, DBR_STRING, &pnotifyInfo->value, + &options, &no_elements, 0); break; } pnotifyInfo->status = status; @@ -84,72 +64,144 @@ static void getCallback(processNotify *ppn,notifyGetType type) static void doneCallback(processNotify *ppn) { - struct stringinRecord *prec = (struct stringinRecord *)ppn->usrPvt; + stringinRecord *prec = (stringinRecord *)ppn->usrPvt; notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - callbackRequestProcessCallback(pnotifyInfo->pcallback,prec->prio,prec); + callbackRequestProcessCallback(pnotifyInfo->pcallback, prec->prio, prec); } -static long init_record(struct stringinRecord *prec) +static long add_record(dbCommon *pcommon) { + stringinRecord *prec = (stringinRecord *)pcommon; DBLINK *plink = &prec->inp; - struct instio *pinstio; - char *pvname; - DBADDR *pdbaddr=NULL; + DBADDR *pdbaddr; long status; notifyInfo *pnotifyInfo; - CALLBACK *pcallback; - processNotify *ppn=NULL; + processNotify *ppn; - if(plink->type!=INST_IO) { - recGblRecordError(S_db_badField,(void *)prec, - "devSiSoftCallback (init_record) Illegal INP field"); - prec->pact=TRUE; - return(S_db_badField); + if (plink->type == CONSTANT) return 0; + + if (plink->type != PV_LINK) { + recGblRecordError(S_db_badField, (void *)prec, + "devSiSoftCallback (add_record) Illegal INP field"); + return S_db_badField; } - pinstio=(struct instio*)&(plink->value); - pvname = pinstio->string; + pdbaddr = callocMustSucceed(1, sizeof(*pdbaddr), - "devSiSoftCallback::init_record"); - status = dbNameToAddr(pvname,pdbaddr); - if(status) { - recGblRecordError(status,(void *)prec, - "devSiSoftCallback (init_record) linked record not found"); - prec->pact=TRUE; - return(status); + "devSiSoftCallback::add_record"); + status = dbNameToAddr(plink->value.pv_link.pvname, pdbaddr); + if (status) { + free(pdbaddr); + recGblRecordError(status, (void *)prec, + "devSiSoftCallback (add_record) linked record not found"); + return status; } - pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), - "devSiSoftCallback::init_record"); - pcallback = callocMustSucceed(1, sizeof(*pcallback), - "devSiSoftCallback::init_record"); + + plink->type = PN_LINK; + plink->value.pv_link.precord = pcommon; + plink->value.pv_link.pvt = pdbaddr; + plink->value.pv_link.pvlMask = 0; + ppn = callocMustSucceed(1, sizeof(*ppn), - "devSiSoftCallback::init_record"); - pnotifyInfo->ppn = ppn; - pnotifyInfo->pcallback = pcallback; + "devSiSoftCallback::add_record"); ppn->usrPvt = prec; ppn->paddr = pdbaddr; ppn->getCallback = getCallback; ppn->doneCallback = doneCallback; ppn->requestType = processGetRequest; + + pnotifyInfo = callocMustSucceed(1, sizeof(*pnotifyInfo), + "devSiSoftCallback::add_record"); + pnotifyInfo->pcallback = callocMustSucceed(1, sizeof(CALLBACK), + "devSiSoftCallback::add_record"); + pnotifyInfo->ppn = ppn; + prec->dpvt = pnotifyInfo; return 0; } -static long read_stringin(stringinRecord *prec) +static long del_record(dbCommon *pcommon) { + stringinRecord *prec = (stringinRecord *)pcommon; + DBLINK *plink = &prec->inp; + notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; + + if (plink->type == CONSTANT) return 0; + assert (plink->type == PN_LINK); + + dbNotifyCancel(pnotifyInfo->ppn); + free(pnotifyInfo->ppn); + free(pnotifyInfo->pcallback); + free(pnotifyInfo); + free(plink->value.pv_link.pvt); + + plink->type = PV_LINK; + plink->value.pv_link.pvt = NULL; + return 0; +} + +static struct dsxt dsxtSoftCallback = { + add_record, del_record +}; + +static long init(int pass) +{ + if (pass == 0) devExtend(&dsxtSoftCallback); + return 0; +} + +static long init_record(stringinRecord *prec) +{ + /* INP must be CONSTANT or PN_LINK */ + switch (prec->inp.type) { + case CONSTANT: + if (recGblInitConstantLink(&prec->inp, DBR_STRING, &prec->val)) + prec->udf = FALSE; + break; + case PN_LINK: + /* Handled by add_record */ + break; + default: + recGblRecordError(S_db_badField, (void *)prec, + "devSiSoftCallback (init_record) Illegal INP field"); + prec->pact = TRUE; + return S_db_badField; + } + return 0; +} + +static long read_si(stringinRecord *prec) { notifyInfo *pnotifyInfo = (notifyInfo *)prec->dpvt; - if(prec->pact) { - if(pnotifyInfo->status) { - recGblSetSevr(prec,READ_ALARM,INVALID_ALARM); - return(pnotifyInfo->status); - } - strcpy(prec->val,pnotifyInfo->value); - prec->udf = FALSE; - return(0); + if (!prec->dpvt) + return 0; + + if (!prec->pact) { + dbProcessNotify(pnotifyInfo->ppn); + prec->pact = TRUE; + return 0; } - dbProcessNotify(pnotifyInfo->ppn); - prec->pact = TRUE; - return(0); + + if (pnotifyInfo->status) { + recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + return pnotifyInfo->status; + } + strncpy(prec->val, pnotifyInfo->value, MAX_STRING_SIZE); + prec->udf = FALSE; + + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + prec->time = prec->inp.value.pv_link.precord->time; + return 0; } + +/* Create the dset for devSiSoftCallback */ +struct { + dset common; + DEVSUPFUN read_li; +} devSiSoftCallback = { + {5, NULL, init, init_record, NULL}, + read_si +}; +epicsExportAddress(dset,devSiSoftCallback); diff --git a/src/std/dev/devSoft.dbd b/src/std/dev/devSoft.dbd index f6a93241d..3df80c52d 100644 --- a/src/std/dev/devSoft.dbd +++ b/src/std/dev/devSoft.dbd @@ -27,19 +27,18 @@ device(mbbiDirect,CONSTANT,devMbbiDirectSoftRaw,"Raw Soft Channel") device(mbbo,CONSTANT,devMbboSoftRaw,"Raw Soft Channel") device(mbboDirect,CONSTANT,devMbboDirectSoftRaw,"Raw Soft Channel") -device(ai,INST_IO,devAiSoftCallback,"Async Soft Channel") -device(bi,INST_IO,devBiSoftCallback,"Async Soft Channel") -device(mbbi,INST_IO,devMbbiSoftCallback,"Async Soft Channel") -device(mbbiDirect,INST_IO,devMbbiDirectSoftCallback,"Async Soft Channel") -device(longin,INST_IO,devLiSoftCallback,"Async Soft Channel") -device(stringin,INST_IO,devSiSoftCallback,"Async Soft Channel") - +device(ai,CONSTANT,devAiSoftCallback,"Async Soft Channel") device(ao,CONSTANT,devAoSoftCallback,"Async Soft Channel") +device(bi,CONSTANT,devBiSoftCallback,"Async Soft Channel") device(bo,CONSTANT,devBoSoftCallback,"Async Soft Channel") device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel") +device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel") device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel") +device(mbbi,CONSTANT,devMbbiSoftCallback,"Async Soft Channel") +device(mbbiDirect,CONSTANT,devMbbiDirectSoftCallback,"Async Soft Channel") device(mbbo,CONSTANT,devMbboSoftCallback,"Async Soft Channel") device(mbboDirect,CONSTANT,devMbboDirectSoftCallback,"Async Soft Channel") +device(stringin,CONSTANT,devSiSoftCallback,"Async Soft Channel") device(stringout,CONSTANT,devSoSoftCallback,"Async Soft Channel") device(ai, INST_IO,devTimestampAI,"Soft Timestamp")