mrfioc2  2.3.0
devEvrEvent.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * mrfioc2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /*
9  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
10  */
11 
12 #include <stdlib.h>
13 #include <string.h>
14 #include <epicsExport.h>
15 #include <dbAccess.h>
16 #include <devSup.h>
17 #include <recGbl.h>
18 #include <devLib.h> // For S_dev_*
19 #include <alarm.h>
20 #include <errlog.h>
21 
22 #include <longoutRecord.h>
23 #include <stringoutRecord.h>
24 #include <eventRecord.h>
25 #include <epicsVersion.h>
26 
27 #include "devObj.h"
28 #include "evr/evr.h"
29 
30 #include "linkoptions.h"
31 
32 #include <stdexcept>
33 #include <string>
34 
35 #if defined(EPICS_VERSION_INT) && EPICS_VERSION_INT>=VERSION_INT(3,15,1,0)
36 // Use new API allowing events to have name strings instead of just numbers
37 #define USE_EVENT_NAMES
38 #endif
39 
40 /***************** Event *****************/
41 
42 struct priv {
43  EVR* evr;
44  char obj[30];
45  int event;
46 #ifdef USE_EVENT_NAMES
47  EVENTPVT handle;
48  char prev[sizeof( ((stringoutRecord*)0)->val)];
49 #endif
50 };
51 
52 static const
53 linkOptionDef eventdef[] =
54 {
55  linkString (priv, obj , "OBJ" , 1, 0),
56  linkInt32 (priv, event, "Code", 1, 0),
58 };
59 
60 static
61 long add_record(struct dbCommon *prec, struct link* link)
62 {
63  long ret=0;
64 try {
65  assert(link->type==INST_IO);
66 
67  mrf::auto_ptr<priv> p(new priv);
68  p->event=0;
69 
70  if (linkOptionsStore(eventdef, p.get(), link->value.instio.string, 0))
71  throw std::runtime_error("Couldn't parse link string");
72 
74  if(!O) {
75  errlogPrintf("%s: failed to find object '%s'\n", prec->name, p->obj);
76  return S_db_errArg;
77  }
78  p->evr=dynamic_cast<EVR*>(O);
79  if(!p->evr)
80  throw std::runtime_error("Failed to lookup device");
81 
82  if (!p->evr->interestedInEvent(p->event, true))
83  throw std::runtime_error("Failed to register interest");
84 
85  prec->dpvt=(void*)p.release();
86 
87  return 0;
88 } catch(std::runtime_error& e) {
89  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
90  ret=S_dev_noDevice;
91 } catch(std::exception& e) {
92  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
93  ret=S_db_noMemory;
94 }
95  return ret;
96 }
97 
98 static
99 long del_record(struct dbCommon *prec)
100 {
101  priv *p=static_cast<priv*>(prec->dpvt);
102  long ret=0;
103  if (!p) return 0;
104 try {
105 
106  p->evr->interestedInEvent(p->event, false);
107  delete p;
108  prec->dpvt=0;
109 
110 } catch(std::runtime_error& e) {
111  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
112  ret=S_dev_noDevice;
113 } catch(std::exception& e) {
114  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
115  ret=S_db_noMemory;
116 }
117  return ret;
118 }
119 
120 static
121 long
122 get_ioint_info(int, dbCommon* prec,IOSCANPVT* io)
123 {
124  if(!prec->dpvt)
125  return S_db_errArg;
126  priv *p=static_cast<priv*>(prec->dpvt);
127  long ret=0;
128 try {
129 
130  if(!p) return 1;
131 
132  *io=p->evr->eventOccurred(p->event);
133 
134  return 0;
135 } catch(std::runtime_error& e) {
136  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
137  ret=S_dev_noDevice;
138 } catch(std::exception& e) {
139  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
140  ret=S_db_noMemory;
141 }
142  *io=NULL;
143  return ret;
144 }
145 
146 static long process_longout(longoutRecord *prec)
147 {
148  priv *p=static_cast<priv*>(prec->dpvt);
149  long ret=0;
150 try {
151 
152  if (prec->val>=0 && prec->val<=255)
153  post_event(prec->val);
154 
155  if(prec->tse==epicsTimeEventDeviceTime){
156  p->evr->getTimeStamp(&prec->time,p->event);
157  }
158 
159  return 0;
160 } catch(std::runtime_error& e) {
161  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
162  ret=S_dev_noDevice;
163 } catch(std::exception& e) {
164  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
165  ret=S_db_noMemory;
166 }
167  return ret;
168 }
169 
170 
171 
172 static long process_stringout(stringoutRecord *prec)
173 {
174  priv *p=static_cast<priv*>(prec->dpvt);
175  long ret=0;
176 try {
177  if(!prec->val[0]) return 0;
178 
179 #ifdef USE_EVENT_NAMES
180  if(!p->handle || strcmp(prec->val, p->prev)!=0) {
181  p->handle = eventNameToHandle(prec->val);
182  strcpy(p->prev, prec->val);
183  }
184 
185  if(p->handle) postEvent(p->handle);
186 #else
187  // for compatibility attempt to parse string to integer
188  {
189  char *end = prec->val;
190  unsigned evt = strtoul(prec->val, &end, 0);
191  if ( evt==ULONG_MAX || *end!='\0' ) {
192  (void)recGblSetSevr(prec, WRITE_ALARM, INVALID_ALARM);
193  } else {
194  post_event(evt);
195  }
196  }
197 #endif
198 
199  if(prec->tse==epicsTimeEventDeviceTime){
200  p->evr->getTimeStamp(&prec->time,p->event);
201  }
202 
203  return 0;
204 } catch(std::runtime_error& e) {
205  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
206  ret=S_dev_noDevice;
207 } catch(std::exception& e) {
208  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
209  ret=S_db_noMemory;
210 }
211  return ret;
212 }
213 
214 static long process_event(eventRecord *prec)
215 {
216  priv *p=static_cast<priv*>(prec->dpvt);
217  long ret=0;
218 try {
219  if(prec->tse==epicsTimeEventDeviceTime){
220  p->evr->getTimeStamp(&prec->time,p->event);
221  }
222 
223  return 0;
224 } catch(std::runtime_error& e) {
225  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
226  ret=S_dev_noDevice;
227 } catch(std::exception& e) {
228  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
229  ret=S_db_noMemory;
230 }
231  return ret;
232 }
233 
234 static
235 long add_longout(struct dbCommon *precord)
236 {
237  return add_record(precord, &((struct longoutRecord*)precord)->out);
238 }
239 
240 static
241 long add_stringout(struct dbCommon *precord)
242 {
243  return add_record(precord, &((struct stringoutRecord*)precord)->out);
244 }
245 
246 static
247 long add_event(struct dbCommon *precord)
248 {
249  return add_record(precord, &((struct eventRecord*)precord)->inp);
250 }
251 
252 dsxt dxtLOEventEVR={add_longout,del_record};
253 static common_dset devLOEventEVR = {
254  6, NULL,
255  dset_cast(&init_dset<&dxtLOEventEVR>),
256  (DEVSUPFUN) init_record_empty,
257  (DEVSUPFUN) &get_ioint_info,
258  dset_cast(&process_longout),
259  NULL };
260 
261 dsxt dxtSOEventEVR={add_stringout,del_record};
262 static common_dset devSOEventEVR = {
263  6, NULL,
264  dset_cast(&init_dset<&dxtSOEventEVR>),
265  (DEVSUPFUN) init_record_empty,
266  (DEVSUPFUN) &get_ioint_info,
267  dset_cast(&process_stringout),
268  NULL };
269 
270 dsxt dxtEVEventEVR={add_event,del_record};
271 static common_dset devEVEventEVR = {
272  6, NULL,
273  dset_cast(&init_dset<&dxtEVEventEVR>),
274  (DEVSUPFUN) init_record_empty,
275  (DEVSUPFUN) &get_ioint_info,
276  dset_cast(&process_event),
277  NULL };
278 
279 extern "C" {
280 
281 epicsExportAddress(dset,devLOEventEVR);
282 epicsExportAddress(dset,devSOEventEVR);
283 epicsExportAddress(dset,devEVEventEVR);
284 
285 }
dsxt dxtEVEventEVR
dsxt dxtSOEventEVR
int event
Definition: devEvrEvent.cpp:45
virtual IOSCANPVT eventOccurred(epicsUInt32 event) const =0
#define linkOptionEnd
Definition: linkoptions.h:111
Base object inspection.
Definition: object.h:378
char obj[30]
Definition: devEvrEvent.cpp:44
DEVSUPFUN get_ioint_info
static Object * getObject(const std::string &name)
Definition: object.cpp:107
int epicsShareAPI linkOptionsStore(const linkOptionDef *opts, void *user, const char *str, int options)
Parse a string a store the result.
Definition: linkoptions.c:135
#define linkInt32(Struct, Member, Name, Req, Over)
Definition: linkoptions.h:99
Base interface for EVRs.
Definition: evr.h:45
Hardware link parsing and storage.
epicsExportAddress(dset, devLOEventEVR)
#define linkString(Struct, Member, Name, Req, Over)
Definition: linkoptions.h:105
EVR * evr
Definition: devEvrEvent.cpp:43
virtual bool interestedInEvent(epicsUInt32 event, bool set)=0
virtual bool getTimeStamp(epicsTimeStamp *ts, epicsUInt32 event)=0
dsxt dxtLOEventEVR