Convert INST_IO links to regular PV_LINK types, for VDCT support.

Added new PN_LINK type in link.h, make dbStaticLib display it.
Made all device support extended so links can be changed at runtime.
Modified startup so add_record() always called before regular link processing.
Incomplete, stilll need to add MS/MSS/MSI support, currently disabled.
This commit is contained in:
Andrew Johnson
2010-01-07 23:48:49 -06:00
parent c6da34286e
commit f7d02cc2a8
12 changed files with 812 additions and 477 deletions

View File

@@ -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:

View File

@@ -45,7 +45,7 @@ typedef enum {
typedef enum {
getFieldType,
getType
getType /* FIXME: Never used? */
}notifyGetType;
typedef enum {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);

View File

@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);

View File

@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);

View File

@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);

View File

@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);

View File

@@ -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 <stdlib.h>
@@ -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);

View File

@@ -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")