This is Unofficial EPICS BASE Doxygen Site
devMbbiDirectSoftCallback.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /* devMbbiDirectSoftCallback.c */
10 /*
11  * Authors: Marty Kraimer & Andrew Johnson
12  */
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 
17 #include "alarm.h"
18 #include "callback.h"
19 #include "cantProceed.h"
20 #include "dbCommon.h"
21 #include "dbDefs.h"
22 #include "dbAccess.h"
23 #include "dbChannel.h"
24 #include "dbNotify.h"
25 #include "epicsAssert.h"
26 #include "recGbl.h"
27 #include "recSup.h"
28 #include "devSup.h"
29 #include "link.h"
30 #include "mbbiDirectRecord.h"
31 #include "epicsExport.h"
32 
33 
34 #define GET_OPTIONS (DBR_STATUS | DBR_TIME)
35 
36 typedef struct devPvt {
37  processNotify pn;
38  epicsCallback callback;
39  long options;
40  int status;
41  struct {
42  DBRstatus
43  DBRtime
45  } buffer;
46 } devPvt;
47 
48 
49 static void getCallback(processNotify *ppn, notifyGetType type)
50 {
51  mbbiDirectRecord *prec = (mbbiDirectRecord *)ppn->usrPvt;
52  devPvt *pdevPvt = (devPvt *)prec->dpvt;
53  long no_elements = 1;
54 
55  if (ppn->status == notifyCanceled) {
56  printf("devMbbiDirectSoftCallback::getCallback notifyCanceled\n");
57  return;
58  }
59 
60  assert(type == getFieldType);
61  pdevPvt->status = dbChannelGetField(ppn->chan, DBR_ULONG,
62  &pdevPvt->buffer, &pdevPvt->options, &no_elements, 0);
63 }
64 
65 static void doneCallback(processNotify *ppn)
66 {
67  mbbiDirectRecord *prec = (mbbiDirectRecord *)ppn->usrPvt;
68  devPvt *pdevPvt = (devPvt *)prec->dpvt;
69 
70  callbackRequestProcessCallback(&pdevPvt->callback, prec->prio, prec);
71 }
72 
73 static long add_record(dbCommon *pcommon)
74 {
75  mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
76  DBLINK *plink = &prec->inp;
77  dbChannel *chan;
78  devPvt *pdevPvt;
79  processNotify *ppn;
80 
81  if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
82  return 0;
83 
84  if (plink->type != PV_LINK) {
85  long status = S_db_badField;
86 
87  recGblRecordError(status, (void *)prec,
88  "devMbbiDirectSoftCallback (add_record) Illegal INP field");
89  return status;
90  }
91 
92  chan = dbChannelCreate(plink->value.pv_link.pvname);
93  if (!chan) {
94  long status = S_db_notFound;
95 
96  recGblRecordError(status,(void *)prec,
97  "devMbbiDirectSoftCallback (add_record) linked record not found");
98  return status;
99  }
100 
101  pdevPvt = calloc(1, sizeof(*pdevPvt));
102  if (!pdevPvt) {
103  long status = S_db_noMemory;
104 
105  recGblRecordError(status, (void *)prec,
106  "devMbbiDirectSoftCallback (add_record) out of memory, calloc() failed");
107  return status;
108  }
109  ppn = &pdevPvt->pn;
110 
111  plink->type = PN_LINK;
112  plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */
113 
114  ppn->usrPvt = prec;
115  ppn->chan = chan;
116  ppn->getCallback = getCallback;
117  ppn->doneCallback = doneCallback;
118  ppn->requestType = processGetRequest;
119 
120  pdevPvt->options = GET_OPTIONS;
121 
122  prec->dpvt = pdevPvt;
123  return 0;
124 }
125 
126 static long del_record(dbCommon *pcommon) {
127  mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
128  DBLINK *plink = &prec->inp;
129  devPvt *pdevPvt = (devPvt *)prec->dpvt;
130 
131  if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
132  return 0;
133 
134  assert(plink->type == PN_LINK);
135 
136  dbNotifyCancel(&pdevPvt->pn);
137  dbChannelDelete(pdevPvt->pn.chan);
138  free(pdevPvt);
139 
140  plink->type = PV_LINK;
141  return 0;
142 }
143 
144 static struct dsxt dsxtSoftCallback = {
146 };
147 
148 static long init(int pass)
149 {
150  if (pass == 0) devExtend(&dsxtSoftCallback);
151  return 0;
152 }
153 
154 static long init_record(dbCommon *pcommon)
155 {
156  mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
157 
158  if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val))
159  prec->udf = FALSE;
160 
161  return 0;
162 }
163 
164 static long read_mbbiDirect(mbbiDirectRecord *prec)
165 {
166  devPvt *pdevPvt = (devPvt *)prec->dpvt;
167 
168  if (!prec->dpvt)
169  return 2;
170 
171  if (!prec->pact) {
172  dbProcessNotify(&pdevPvt->pn);
173  prec->pact = TRUE;
174  return 0;
175  }
176 
177  if (pdevPvt->status) {
178  recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
179  return 2;
180  }
181 
182  prec->val = pdevPvt->buffer.value;
183  prec->udf = FALSE;
184 
185  switch (prec->inp.value.pv_link.pvlMask & pvlOptMsMode) {
186  case pvlOptNMS:
187  break;
188  case pvlOptMSI:
189  if (pdevPvt->buffer.severity < INVALID_ALARM)
190  break;
191  /* else fall through */
192  case pvlOptMS:
193  recGblSetSevr(prec, LINK_ALARM, pdevPvt->buffer.severity);
194  break;
195  case pvlOptMSS:
196  recGblSetSevr(prec, pdevPvt->buffer.status,
197  pdevPvt->buffer.severity);
198  break;
199  }
200 
201  if (dbLinkIsConstant(&prec->tsel) &&
202  prec->tse == epicsTimeEventDeviceTime)
203  prec->time = pdevPvt->buffer.time;
204 
205  return 2;
206 }
207 
208 /* Create the dset for devMbbiDirectSoftCallback */
209 mbbidirectdset devMbbiDirectSoftCallback = {
210  {5, NULL, init, init_record, NULL},
211  read_mbbiDirect
212 };
Definition: devSup.h:117
epicsCallback callback
DBRstatus DBRtime epicsUInt32 value
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define FALSE
Definition: dbDefs.h:32
#define READ_ALARM
Definition: alarm.h:92
An EPICS-specific replacement for ANSI C&#39;s assert.
void devExtend(dsxt *pdsxt)
Definition: dbStaticRun.c:60
#define init_record
#define printf
Definition: epicsStdio.h:41
pvd::StructureConstPtr type
#define NULL
Definition: catime.c:38
unsigned int epicsUInt32
Definition: epicsTypes.h:43
Miscellaneous macro definitions.
struct devPvt::@2 buffer
Device support routines.
Definition: devSup.h:140
#define GET_OPTIONS
struct devPvt devPvt
#define epicsTimeEventDeviceTime
Definition: epicsTime.h:362
long(* add_record)(struct dbCommon *precord)
Definition: devSup.h:122
mbbidirectdset devMbbiDirectSoftCallback
#define LINK_ALARM
Definition: alarm.h:105
processNotify pn
DBRstatus DBRtime epicsFloat64 value
epicsExportAddress(dset, devMbbiDirectSoftCallback)
long(* del_record)(struct dbCommon *precord)
Definition: devSup.h:127
#define TRUE
Definition: dbDefs.h:27
if(yy_init)
Definition: scan.c:972
Routines for code that can&#39;t continue or return after an error.
int prec
Definition: reader.c:29
struct pv_link pv_link
Definition: link.h:178
#define INVALID_ALARM
Definition: alarm.h:53
#define DBR_ULONG
Definition: dbFldTypes.h:82
Exporting IOC objects.