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