mrfioc2  2.3.0
devMrmBufRx.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 <math.h>
15 #include <stdexcept>
16 #include <string>
17 #include <cfloat>
18 
19 #include <dbAccess.h>
20 #include <devSup.h>
21 #include <recSup.h>
22 #include <recGbl.h>
23 #include <devLib.h> // For S_dev_*
24 #include <alarm.h>
25 #include <mbboRecord.h>
26 #include <waveformRecord.h>
27 #include <menuFtype.h>
28 #include <callback.h>
29 
30 // for htons() et al.
31 #ifdef _WIN32
32  #include <Winsock2.h>
33 #else
34  // for htons() et al.
35  #include <netinet/in.h> // on rtems
36  #include <arpa/inet.h> // on linux
37 #endif
38 
39 #define DATABUF_H_INC_LEVEL2
40 #include <epicsExport.h>
41 #include "mrf/databuf.h"
42 #include "linkoptions.h"
43 #include "devObj.h"
44 
45 
53 static
54 void datarx(void *, epicsStatus , epicsUInt32 , const epicsUInt8* );
55 
56 struct s_priv
57 {
58  char obj[40];
59  epicsUInt32 proto;
60  epicsUInt32 proto16;
61  epicsUInt32 proto32;
62  char prop[20];
63 
65 
66  epicsUInt32 blen;
67  const epicsUInt8* buf;
68 };
69 
70 static const
71 linkOptionDef eventdef[] =
72 {
73  linkString (s_priv, obj , "OBJ" , 1, 0),
74  linkInt32 (s_priv, proto, "Proto", 0, 0),
75  linkInt32 (s_priv, proto16, "Proto16", 0, 0),
76  linkInt32 (s_priv, proto32, "Proto32", 0, 0),
77  linkString (s_priv, prop , "P", 1, 0),
79 };
80 
81 static long add_record_waveform(dbCommon *praw)
82 {
83  waveformRecord *prec=(waveformRecord*)praw;
84  long ret=0;
85  s_priv *paddr=NULL;
86 try {
87  assert(prec->inp.type==INST_IO);
88 
89  mrf::auto_ptr<s_priv> paddr(new s_priv);
90  paddr->buf=NULL;
91  paddr->blen=0;
92  paddr->proto = 0xff00;
93  paddr->proto16 = 0;
94  paddr->proto32 = 0;
95 
96  if (linkOptionsStore(eventdef, paddr.get(), prec->inp.value.instio.string, 0))
97  throw std::runtime_error("Couldn't parse link string");
98 
99  mrf::Object *O=mrf::Object::getObject(paddr->obj);
100  if(!O) {
101  errlogPrintf("%s: failed to find object '%s'\n", prec->name, paddr->obj);
102  return S_db_errArg;
103  }
104  paddr->priv=dynamic_cast<dataBufRx*>(O);
105  if(!paddr->priv)
106  throw std::runtime_error("Failed to lookup device");
107 
108  paddr->priv->dataRxAddReceive(datarx, praw);
109 
110  // prec->dpvt is set again to indicate
111  // This also serves to indicate successful
112  // initialization to other dset functions
113  prec->dpvt = (void*)paddr.release();
114 
115  return 0;
116 
117 } catch(std::runtime_error& e) {
118  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
119  ret=S_dev_noDevice;
120 } catch(std::exception& e) {
121  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
122  ret=S_db_noMemory;
123 }
124  delete paddr;
125  return ret;
126 }
127 
128 static long del_record_waveform(dbCommon *praw)
129 {
130  long ret=0;
131  if (!praw->dpvt) return 0;
132  try {
133  mrf::auto_ptr<s_priv> paddr(static_cast<s_priv*>(praw->dpvt));
134  praw->dpvt = 0;
135 
136  paddr->priv->dataRxDeleteReceive(datarx, praw);
137 
138  } catch(std::runtime_error& e) {
139  recGblRecordError(S_dev_noDevice, (void*)praw, e.what());
140  ret=S_dev_noDevice;
141  } catch(std::exception& e) {
142  recGblRecordError(S_db_noMemory, (void*)praw, e.what());
143  ret=S_db_noMemory;
144  }
145  return ret;
146 }
147 
148 static
149 void datarx(void *arg, epicsStatus ok,
150  epicsUInt32 len, const epicsUInt8* buf)
151 {
152  waveformRecord* prec=(waveformRecord*)arg;
153  s_priv *paddr=static_cast<s_priv*>(prec->dpvt);
154 
155  //check protocol id
156  if (paddr->proto != 0xff00 && paddr->proto != buf[0]) return;
157  if (paddr->proto16 && paddr->proto16 != ntohs(((epicsUInt16*)buf)[0])) return;
158  if (paddr->proto32 && paddr->proto32 != ntohl(((epicsUInt32*)buf)[0])) return;
159 
160  dbScanLock((dbCommon*)prec);
161 
162  if (ok || !prec->dpvt) {
163  // An error occured
164  paddr->buf=NULL;
165  paddr->blen=0;
166  } else {
167  paddr->buf=buf;
168  paddr->blen=len;
169  }
170 
171  rset *prset=(rset*)prec->rset;
172  (*(long (*)(waveformRecord*))prset->process)(prec);
173 
174  paddr->buf=NULL;
175  paddr->blen=0;
176 
177  dbScanUnlock((dbCommon*)prec);
178 }
179 
180 static long write_waveform(waveformRecord* prec)
181 {
182  if (!prec->dpvt) {(void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM); return -1; }
183 try {
184  s_priv *paddr=static_cast<s_priv*>(prec->dpvt);
185 
186  if (!paddr->buf) {
187  // Error condition set INVALID_ALARM
188  (void)recGblSetSevr(prec, READ_ALARM, MAJOR_ALARM);
189 
190  } else {
191 
192  long esize = dbValueSize(prec->ftvl);
193  epicsUInt32 capacity=prec->nelm*esize;
194 
195  if (paddr->blen > capacity) {
196  paddr->blen=capacity;
197  (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
198  }
199 
200  if(esize==1 || esize>8) // char or string
201  memcpy(prec->bptr, paddr->buf, paddr->blen);
202  else {
203  epicsUInt8 *buf=(epicsUInt8*)prec->bptr;
204  for(size_t i=0; i<paddr->blen; i+=esize) {
205  switch(esize) {
206  case 2:
207  *(epicsUInt16*)(buf+i) = htons( *(epicsUInt16*)(paddr->buf+i) );
208  break;
209  case 4:
210  *(epicsUInt32*)(buf+i) = htonl( *(epicsUInt32*)(paddr->buf+i) );
211  break;
212  case 8:
213  #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
214  *(epicsUInt32*)(buf+i) = *(epicsUInt32*)(paddr->buf+i);
215  *(epicsUInt32*)(buf+i+4) = *(epicsUInt32*)(paddr->buf+i+4);
216  #else
217  *(epicsUInt32*)(buf+i+4) = htonl( *(epicsUInt32*)(paddr->buf+i) );
218  *(epicsUInt32*)(buf+i) = htonl( *(epicsUInt32*)(paddr->buf+i+4) );
219  #endif
220  break;
221  }
222  }
223  }
224 
225  prec->nord = paddr->blen/dbValueSize(prec->ftvl);
226  }
227 
228  return 0;
229 } catch(std::exception& e) {
230  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
231  return S_db_noMemory;
232 }
233 }
234 
235 /*************** boiler plate *******************/
236 
237 extern "C" {
238 
239 dsxt dxtwaveforminBufTx={add_record_waveform,del_record_waveform};
240 
241 
242 static common_dset devwaveformindataBufRx = {
243  6, NULL,
244  dset_cast(&init_dset<&dxtwaveforminBufTx>),
245  (DEVSUPFUN) &init_record_empty,
246  NULL,
247  dset_cast(&write_waveform),
248  NULL };
249 epicsExportAddress(dset,devwaveformindataBufRx);
250 
251 }
252 
epicsUInt32 proto32
Definition: devMrmBufRx.cpp:61
epicsExportAddress(dset, devwaveformindataBufRx)
dsxt dxtwaveforminBufTx
dataBufRx * priv
Definition: devMrmBufRx.cpp:64
#define linkOptionEnd
Definition: linkoptions.h:111
Base object inspection.
Definition: object.h:378
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
epicsUInt32 proto16
Definition: devMrmBufRx.cpp:60
epicsUInt32 blen
Definition: devMrmBufRx.cpp:66
epicsUInt32 proto
Definition: devMrfBufTx.cpp:37
Hardware link parsing and storage.
const epicsUInt8 * buf
Definition: devMrmBufRx.cpp:67
#define linkString(Struct, Member, Name, Req, Over)
Definition: linkoptions.h:105
char prop[20]
Definition: devMrfBufTx.cpp:38
char obj[40]
Definition: devMrfBufTx.cpp:36