Simplified dbPutFieldLink, made DSXT work with all link types.
This commit is contained in:
@@ -1018,8 +1018,8 @@ long epicsShareAPI dbGet(DBADDR *paddr,short dbrType,
|
||||
return(status);
|
||||
}
|
||||
|
||||
devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *pdbRecordType, int dtyp) {
|
||||
return (devSup *)ellNth(&pdbRecordType->devList, dtyp+1);
|
||||
devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp) {
|
||||
return (devSup *)ellNth(&prdes->devList, dtyp+1);
|
||||
}
|
||||
|
||||
devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
|
||||
@@ -1031,68 +1031,80 @@ devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static long dbPutFieldLink(
|
||||
DBADDR *paddr,short dbrType,const void *pbuffer,long nRequest)
|
||||
static long dbPutFieldLink(DBADDR *paddr,
|
||||
short dbrType, const void *pbuffer, long nRequest)
|
||||
{
|
||||
long status = 0;
|
||||
long special=paddr->special;
|
||||
dbCommon *precord = (dbCommon *)(paddr->precord);
|
||||
DBLINK *plink = (DBLINK *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
DBENTRY dbEntry;
|
||||
dbCommon *precord = paddr->precord;
|
||||
dbFldDes *pfldDes = paddr->pfldDes;
|
||||
long special = paddr->special;
|
||||
DBLINK *plink = (DBLINK *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
DBENTRY dbEntry;
|
||||
DBADDR dbaddr;
|
||||
devSup *pdevSup = NULL;
|
||||
struct dsxt *old_dsxt = NULL;
|
||||
struct dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
int inpOut;
|
||||
short scan;
|
||||
long status;
|
||||
int isDevLink;
|
||||
short scan;
|
||||
|
||||
if ((dbrType!=DBR_STRING) && (dbrType!=DBR_CHAR) && (dbrType!=DBR_UCHAR))
|
||||
switch (dbrType) {
|
||||
case DBR_CHAR:
|
||||
case DBR_UCHAR:
|
||||
if (pstring[nRequest] != '\0')
|
||||
return S_db_badDbrtype;
|
||||
break;
|
||||
|
||||
case DBR_STRING:
|
||||
break;
|
||||
|
||||
default:
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
|
||||
if (((dbrType==DBR_CHAR) || (dbrType==DBR_UCHAR)) &&
|
||||
(pstring[nRequest] != '\0'))
|
||||
return S_db_badField;
|
||||
dbInitEntry(pdbbase, &dbEntry);
|
||||
status = dbFindRecord(&dbEntry, precord->name);
|
||||
if (!status) status = dbFindField(&dbEntry, pfldDes->name);
|
||||
if (status) goto finish;
|
||||
|
||||
dbInitEntry(pdbbase,&dbEntry);
|
||||
status=dbFindRecord(&dbEntry,precord->name);
|
||||
if (!status) status=dbFindField(&dbEntry,pfldDes->name);
|
||||
if (status) return status;
|
||||
|
||||
inpOut = !(strcmp(pfldDes->name,"INP") && strcmp(pfldDes->name,"OUT"));
|
||||
isDevLink = ellCount(&precord->rdes->devList) > 0 &&
|
||||
(strcmp(pfldDes->name, "INP") == 0 ||
|
||||
strcmp(pfldDes->name, "OUT") == 0);
|
||||
|
||||
dbLockSetGblLock();
|
||||
dbLockSetRecordLock(precord);
|
||||
|
||||
if (inpOut) {
|
||||
pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
|
||||
if (pdevSup == NULL) {
|
||||
/* This record type has no registered device support, but does have
|
||||
* an INP or OUT field which we're currently writing to. We handle
|
||||
* this INP/OUT field just like any other link field.
|
||||
*/
|
||||
inpOut = 0;
|
||||
} else {
|
||||
scan = precord->scan;
|
||||
|
||||
if (isDevLink) {
|
||||
devSup *pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
|
||||
if (pdevSup) {
|
||||
new_dset = pdevSup->pdset;
|
||||
new_dsxt = pdevSup->pdsxt;
|
||||
if (new_dset == NULL ||
|
||||
new_dsxt == NULL ||
|
||||
new_dsxt->add_record == NULL ||
|
||||
(precord->dset &&
|
||||
((pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset)) == NULL ||
|
||||
pdevSup->pdsxt == NULL ||
|
||||
pdevSup->pdsxt->del_record == NULL))) {
|
||||
status = S_db_noSupport;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scan = precord->scan;
|
||||
if (inpOut && (scan==menuScanI_O_Intr)) {
|
||||
scanDelete(precord);
|
||||
precord->scan = menuScanPassive;
|
||||
if (precord->dset) {
|
||||
pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset);
|
||||
if (pdevSup)
|
||||
old_dsxt = pdevSup->pdsxt;
|
||||
}
|
||||
|
||||
if (new_dsxt == NULL ||
|
||||
new_dsxt->add_record == NULL ||
|
||||
old_dsxt == NULL ||
|
||||
old_dsxt->del_record == NULL) {
|
||||
status = S_db_noSupport;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (scan == menuScanI_O_Intr) {
|
||||
scanDelete(precord);
|
||||
precord->scan = menuScanPassive;
|
||||
}
|
||||
|
||||
status = old_dsxt->del_record(precord);
|
||||
if (status)
|
||||
goto restoreScan;
|
||||
}
|
||||
|
||||
switch (plink->type) { /* Old link type */
|
||||
@@ -1122,38 +1134,46 @@ static long dbPutFieldLink(
|
||||
break; /* should never get here */
|
||||
|
||||
default: /* Hardware address */
|
||||
if (!inpOut)
|
||||
if (!isDevLink) {
|
||||
status = S_db_badHWaddr;
|
||||
else
|
||||
if (precord->dset)
|
||||
status = pdevSup->pdsxt->del_record(precord);
|
||||
if (status) goto restoreScan;
|
||||
goto restoreScan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (special) status = dbPutSpecial(paddr,0);
|
||||
if (!status) status = dbPutString(&dbEntry,pstring);
|
||||
if (special) status = dbPutSpecial(paddr, 0);
|
||||
|
||||
if (inpOut) {
|
||||
precord->dset = new_dset;
|
||||
precord->dpvt = NULL;
|
||||
precord->pact = FALSE;
|
||||
}
|
||||
if (!status) status = dbPutString(&dbEntry, pstring);
|
||||
|
||||
if (!status && special) status = dbPutSpecial(paddr, 1);
|
||||
|
||||
if (!status && special) status = dbPutSpecial(paddr,1);
|
||||
if (status) {
|
||||
if (inpOut) {
|
||||
if (isDevLink) {
|
||||
precord->dset = NULL;
|
||||
precord->pact = TRUE;
|
||||
}
|
||||
goto postScanEvent;
|
||||
}
|
||||
|
||||
if (isDevLink) {
|
||||
precord->dpvt = NULL;
|
||||
precord->dset = new_dset;
|
||||
precord->pact = FALSE;
|
||||
|
||||
status = new_dsxt->add_record(precord);
|
||||
if (status) {
|
||||
precord->dset = NULL;
|
||||
precord->pact = TRUE;
|
||||
goto postScanEvent;
|
||||
}
|
||||
}
|
||||
|
||||
switch (plink->type) { /* New link type */
|
||||
case PV_LINK:
|
||||
if (plink == &precord->tsel)
|
||||
recGblTSELwasModified(plink);
|
||||
plink->value.pv_link.precord = precord;
|
||||
|
||||
if (!(plink->value.pv_link.pvlMask & (pvlOptCA|pvlOptCP|pvlOptCPP)) &&
|
||||
(dbNameToAddr(plink->value.pv_link.pvname, &dbaddr) == 0)) {
|
||||
/* It's a DB link */
|
||||
@@ -1190,21 +1210,17 @@ static long dbPutFieldLink(
|
||||
break; /* should never get here */
|
||||
|
||||
default: /* Hardware address */
|
||||
if (!inpOut)
|
||||
if (!isDevLink) {
|
||||
status = S_db_badHWaddr;
|
||||
else
|
||||
status = new_dsxt->add_record(precord);
|
||||
if (status) {
|
||||
precord->dset = NULL;
|
||||
precord->pact = TRUE;
|
||||
goto postScanEvent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
db_post_events(precord,plink,DBE_VALUE|DBE_LOG);
|
||||
db_post_events(precord, plink, DBE_VALUE | DBE_LOG);
|
||||
|
||||
restoreScan:
|
||||
if (inpOut && (scan==menuScanI_O_Intr)) { /* undo scanDelete() */
|
||||
if (isDevLink &&
|
||||
scan == menuScanI_O_Intr) { /* undo scanDelete() */
|
||||
precord->scan = scan;
|
||||
scanAdd(precord);
|
||||
}
|
||||
@@ -1213,6 +1229,7 @@ postScanEvent:
|
||||
db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG);
|
||||
unlock:
|
||||
dbLockSetGblUnlock();
|
||||
finish:
|
||||
dbFinishEntry(&dbEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user