mrfioc2  2.3.0
devObj.h
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2011 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * mrfioc2 is distributed subject to a Software License Agreement found
5 * in file LICENSE that is included with this distribution.
6 \*************************************************************************/
7 /*
8  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
9  */
10 #ifndef DEVOBJ_H
11 #define DEVOBJ_H
12 
13 #include <stdlib.h>
14 #include <dbAccess.h>
15 #include <dbScan.h>
16 #include <link.h>
17 #include <devSup.h>
18 #include <recGbl.h>
19 #include <devLib.h> // For S_dev_*
20 #include <alarm.h>
21 #include <errlog.h>
22 #include <menuConvert.h>
23 
24 #include "mrf/object.h"
25 #include "linkoptions.h"
26 #include "mrfCommon.h"
27 
28 #include <stdexcept>
29 #include <string>
30 
31 #define CATCH(RET) catch(alarm_exception& e) {\
32  (void)recGblSetSevr(prec, e.status(), e.severity());\
33  return (RET);\
34  } catch(std::exception& e) {\
35  (void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM);\
36  epicsPrintf("%s: error: %s\n", prec->name, e.what());\
37  return (RET);\
38  }
39 
40 /* Device support related casting functions */
41 
42 template<typename REC>
43 static inline
44 DEVSUPFUN
45 dset_cast(long (*fn)(REC*))
46 {
47  return (DEVSUPFUN)fn;
48 }
49 
50 DEVSUPFUN
51 static inline
52 dset_cast(long (*fn)(int,dbCommon*,IOSCANPVT*))
53 {
54  return (DEVSUPFUN)fn;
55 }
56 
57 DEVSUPFUN
58 static inline
59 dset_cast(long (*fn)(int))
60 {
61  return (DEVSUPFUN)fn;
62 }
63 
64 typedef long (*DSXTFUN)(dbCommon*);
65 
66 template<typename REC>
67 static inline
68 DSXTFUN
69 dsxt_cast(long (*fn)(REC*))
70 {
71  return (DSXTFUN)fn;
72 }
73 
74 struct common_dset{
75  long num;
76  DEVSUPFUN report;
77  DEVSUPFUN init;
78  DEVSUPFUN init_record;
79  DEVSUPFUN get_ioint_info;
80  DEVSUPFUN readwrite;
81  DEVSUPFUN special_linconv;
82 };
83 
84 struct addrBase {
85  char obj[30];
86  char prop[30];
87  char klass[30];
88  char parent[30];
89  int rbv;
91 };
92 
93 epicsShareExtern const
95 
96 template<typename T>
97 struct addr : public addrBase {
98  mrf::auto_ptr<mrf::property<T> > P;
99 };
100 
101 epicsShareExtern const
103 
104 struct epicsShareClass CurrentRecord {
105  template<typename Rec>
106  explicit CurrentRecord(Rec* prec)
107  {
108  (void)prec->dpvt;
109  set((dbCommon*)prec);
110  }
111  ~CurrentRecord();
112  static
113  dbCommon* get();
114  void set(dbCommon* prec);
115 };
116 
117 template<dsxt* D>
118 static inline
119 long init_dset(int i)
120 {
121  if (i==0) devExtend(D);
122  return 0;
123 }
124 
125 static inline
126 long init_record_empty(void *)
127 {
128  return 0;
129 }
130 
131 static inline
132 long init_record_return2(void *)
133 {
134  return 2;
135 }
136 
137 static inline
138 long del_record_empty(dbCommon*)
139 {
140  return 0;
141 }
142 
143 template<typename P>
144 static long add_record_property(
145  dbCommon *prec,
146  DBLINK* lnk)
147 {
148  using namespace mrf;
149 try {
150  if(lnk->type!=INST_IO)
151  return S_db_errArg;
152 
153  mrf::auto_ptr<addr<P> > a;
154  if(prec->dpvt) {
155  a.reset((addr<P>*)prec->dpvt);
156  prec->dpvt=0;
157  } else
158  a.reset(new addr<P>);
159 
160  a->rbv=0;
161  a->obj[0] = a->prop[0] = a->klass[0] = a->parent[0] = '\0';
162 
163  if(linkOptionsStore(objdef, (void*)(addrBase*)a.get(),
164  lnk->value.instio.string, 0)) {
165  errlogPrintf("%s: Invalid Input link", prec->name);
166  return S_db_errArg;
167  }
168 
169  Object *o;
170  try {
172  args["PARENT"] = a->parent;
173  o = Object::getCreateObject(a->obj, a->klass, args);
174 
175  } catch(std::exception& e) {
176  errlogPrintf("%s: failed to find/create object '%s' : %s\n", prec->name, a->obj, e.what());
177  return S_db_errArg;
178  }
179 
180  mrf::auto_ptr<property<P> > prop = o->getProperty<P>(a->prop);
181  if(!prop.get()) {
182  errlogPrintf("%s: '%s' lacks property '%s' of required type %s\n",
183  prec->name, o->name().c_str(), a->prop, typeid(P).name());
184  return S_db_errArg;
185  }
186 
187  a->O = o;
188  a->P = PTRMOVE(prop);
189 
190  prec->dpvt = (void*)a.release();
191 
192  return 0;
193 } catch (std::exception& e) {
194  errlogPrintf("%s: add_record failed: %s\n", prec->name, e.what());
195  return S_db_errArg;
196 }
197 }
198 
199 template<typename REC, typename T>
200 static inline
201 long add_record_inp(dbCommon *pcom)
202 {
203  REC *prec=(REC*)pcom;
204  return add_record_property<T>(pcom, &prec->inp);
205 }
206 
207 template<typename REC, typename T>
208 static inline
209 long add_record_out(dbCommon *pcom)
210 {
211  REC *prec=(REC*)pcom;
212  return add_record_property<T>(pcom, &prec->out);
213 }
214 
215 template<typename DT>
216 static inline
217 long del_record_delete(dbCommon* prec)
218 {
219  DT *prop=static_cast<DT*>(prec->dpvt);
220  if (!prop)
221  return 0;
222  prec->dpvt = 0;
223  delete prop;
224  return 0;
225 }
226 
227 static inline
228 long del_record_property(dbCommon* prec)
229 {
230  using namespace mrf;
231  addrBase *prop=static_cast<addrBase*>(prec->dpvt);
232  if (!prop)
233  return 0;
234  prec->dpvt = 0;
235  delete prop;
236  return 0;
237 }
238 
239 static inline long get_ioint_info_property(int, dbCommon* prec, IOSCANPVT* io)
240 {
241  using namespace mrf;
242 if (!prec->dpvt) {(void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM); return -1; }
243 try {
244  addrBase *prop=static_cast<addrBase*>(prec->dpvt);
245 
246  mrf::auto_ptr<property<IOSCANPVT> > up = prop->O->getProperty<IOSCANPVT>(prop->prop);
247 
248  if(up.get()) {
249  *io = up->get();
250  } else {
251  errlogPrintf("%s Warning: I/O Intr not supported by PROP=%s\n", prec->name, prop->prop);
252  }
253 
254  return 0;
255 } catch(std::exception& e) {
256  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
257  return S_db_noMemory;
258 }
259 }
260 
261 #define OBJECT_DSET(NAME, ADD, DEL, INIT, WRITE, LINR) \
262 dsxt dxt ## NAME={ADD,DEL}; \
263 static common_dset dev ## NAME = { \
264  6, NULL, \
265  dset_cast(&init_dset<&dxt ## NAME>), \
266  (DEVSUPFUN) INIT, \
267  (DEVSUPFUN) &get_ioint_info_property, \
268  dset_cast(WRITE), \
269  LINR }
270 
271 #define OBJECT_DSET_EXPORT(NAME) epicsExportAddress(dset,dev ## NAME)
272 
273 #endif // DEVOBJ_H
std::map< std::string, std::string > create_args_t
Definition: object.h:422
CurrentRecord(Rec *prec)
Definition: devObj.h:106
long num
Definition: devObj.h:75
DEVSUPFUN readwrite
Definition: devObj.h:80
Definition: evrdump.c:37
DEVSUPFUN special_linconv
Definition: devObj.h:81
Base object inspection.
Definition: object.h:378
int epicsShareAPI linkOptionsStore(const linkOptionDef *opts, void *user, const char *str, int options)
Parse a string a store the result.
Definition: linkoptions.c:135
DEVSUPFUN report
Definition: devObj.h:76
DEVSUPFUN get_ioint_info
Definition: devObj.h:79
Definition: devObj.h:97
mrf::Object * O
Definition: devObj.h:90
char prop[30]
Definition: devObj.h:86
const std::string & name() const
Definition: object.h:393
mrf::auto_ptr< property< P > > getProperty(const char *pname)
Definition: object.h:405
epicsShareExtern const linkOptionEnumType readbackEnum[]
Definition: devObj.h:94
epicsShareExtern const linkOptionDef objdef[]
Definition: devObj.h:102
Hardware link parsing and storage.
mrf::auto_ptr< mrf::property< T > > P
Definition: devObj.h:98
long(* DSXTFUN)(dbCommon *)
Definition: devObj.h:64
Definition: flash.cpp:23
DEVSUPFUN init
Definition: devObj.h:77
int rbv
Definition: devObj.h:89
DEVSUPFUN init_record
Definition: devObj.h:78