mrfioc2  2.3.0
devMrfBufTx.cpp
Go to the documentation of this file.
1 
2 #include <stdlib.h>
3 #include <math.h>
4 
5 #include <dbAccess.h>
6 #include <devSup.h>
7 #include <recGbl.h>
8 #include <devLib.h> // For S_dev_*
9 #include <alarm.h>
10 #include <mbboRecord.h>
11 #include <waveformRecord.h>
12 #include <menuFtype.h>
13 #include <epicsEndian.h>
14 
15 #ifdef _WIN32
16  #include <Winsock2.h>
17 #else
18  // for htons() et al.
19  #include <netinet/in.h> // on rtems
20  #include <arpa/inet.h> // on linux
21 #endif
22 
23 
24 #include "linkoptions.h"
25 #include "devObj.h"
26 #include "mrf/databuf.h"
27 
28 #include <stdexcept>
29 #include <string>
30 #include <cfloat>
31 
32 
33 #include <epicsExport.h>
34 struct s_priv
35 {
36  char obj[40];
37  epicsUInt32 proto;
38  char prop[20];
39 
41  epicsUInt8 *scratch;
42 };
43 
44 static const
45 linkOptionDef eventdef[] =
46 {
47  linkString (s_priv, obj , "OBJ" , 1, 0),
48  linkInt32 (s_priv, proto, "Proto", 1, 0),
49  linkString (s_priv, prop , "P", 1, 0),
51 };
52 
53 static long add_record_waveform(dbCommon *praw)
54 {
55  waveformRecord *prec=(waveformRecord*)praw;
56  long ret=0;
57 try {
58  assert(prec->inp.type==INST_IO);
59 
60  mrf::auto_ptr<s_priv> paddr(new s_priv);
61 
62  if (linkOptionsStore(eventdef, paddr.get(), prec->inp.value.instio.string, 0))
63  throw std::runtime_error("Couldn't parse link string");
64 
65  mrf::Object *O=mrf::Object::getObject(paddr->obj);
66  if(!O) {
67  errlogPrintf("%s: failed to find object '%s'\n", prec->name, paddr->obj);
68  return S_db_errArg;
69  }
70  paddr->priv=dynamic_cast<dataBufTx*>(O);
71  if(!paddr->priv)
72  throw std::runtime_error("Failed to lookup device");
73 
74  // scratch space for endian swap if needed
75  if(dbValueSize(prec->ftvl)>1 && dbValueSize(prec->ftvl)<=8)
76  paddr->scratch = new epicsUInt8[prec->nelm*dbValueSize(prec->ftvl)];
77  else
78  paddr->scratch = 0;
79 
80  // prec->dpvt is set again to indicate
81  // This also serves to indicate successful
82  // initialization to other dset functions
83  prec->dpvt = paddr.release();
84 
85  return 0;
86 
87 } catch(std::runtime_error& e) {
88  recGblRecordError(S_dev_noDevice, (void*)prec, e.what());
89  ret=S_dev_noDevice;
90 } catch(std::exception& e) {
91  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
92  ret=S_db_noMemory;
93 }
94  return ret;
95 }
96 
97 static long del_record_waveform(dbCommon *praw)
98 {
99  long ret=0;
100  if (!praw->dpvt) return 0;
101  try {
102  mrf::auto_ptr<s_priv> paddr((s_priv*)praw->dpvt);
103  praw->dpvt = 0;
104  delete[] paddr->scratch;
105 
106  } catch(std::runtime_error& e) {
107  recGblRecordError(S_dev_noDevice, (void*)praw, e.what());
108  ret=S_dev_noDevice;
109  } catch(std::exception& e) {
110  recGblRecordError(S_db_noMemory, (void*)praw, e.what());
111  ret=S_db_noMemory;
112  }
113  return ret;
114 }
115 
116 static long write_waveform(waveformRecord* prec)
117 {
118  if (!prec->dpvt) {(void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM); return -1; }
119 try {
120  s_priv *paddr=static_cast<s_priv*>(prec->dpvt);
121 
122  epicsUInt32 capacity=paddr->priv->lenMax();
123  const long esize=dbValueSize(prec->ftvl);
124  epicsUInt32 requested=prec->nord*esize;
125 
126  if (requested > capacity)
127  requested=capacity;
128 
129  epicsUInt8 *buf;
130  if(esize==1 || esize>8)
131  buf=static_cast<epicsUInt8*>(prec->bptr);
132  else {
133  buf=paddr->scratch;
134  for(size_t i=0; i<requested; i+=esize) {
135  switch(esize) {
136  case 2:
137  *(epicsUInt16*)(buf+i) = htons( *(epicsUInt16*)((char*)prec->bptr+i) );
138  break;
139  case 4:
140  *(epicsUInt32*)(buf+i) = htonl( *(epicsUInt32*)((char*)prec->bptr+i) );
141  break;
142  case 8:
143 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
144  *(epicsUInt32*)(buf+i) = *(epicsUInt32*)((char*)prec->bptr+i);
145  *(epicsUInt32*)(buf+i+4) = *(epicsUInt32*)((char*)prec->bptr+i+4);
146 #else
147  *(epicsUInt32*)(buf+i+4) = htonl( *(epicsUInt32*)((char*)prec->bptr+i) );
148  *(epicsUInt32*)(buf+i) = htonl( *(epicsUInt32*)((char*)prec->bptr+i+4) );
149 #endif
150  break;
151  }
152  }
153  }
154 
155  paddr->priv->dataSend(requested,buf);
156 
157  return 0;
158 } catch(std::exception& e) {
159  recGblRecordError(S_db_noMemory, (void*)prec, e.what());
160  return S_db_noMemory;
161 }
162 }
163 
164 /*************** boiler plate *******************/
165 
166 extern "C" {
167 
168 dsxt dxtwaveformBufTx={add_record_waveform,del_record_waveform};
169 
170 
171 static common_dset devwaveformoutdataBufTx = {
172  6, NULL,
173  dset_cast(&init_dset<&dxtwaveformBufTx>),
174  (DEVSUPFUN) init_record_empty,
175  NULL,
176  dset_cast(&write_waveform),
177  NULL };
178 epicsExportAddress(dset,devwaveformoutdataBufTx);
179 
180 }
dataBufTx * priv
Definition: devMrfBufTx.cpp:40
#define linkOptionEnd
Definition: linkoptions.h:111
Base object inspection.
Definition: object.h:378
epicsUInt8 * scratch
Definition: devMrfBufTx.cpp:41
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
epicsExportAddress(dset, devwaveformoutdataBufTx)
epicsUInt32 proto
Definition: devMrfBufTx.cpp:37
dsxt dxtwaveformBufTx
Hardware link parsing and storage.
const epicsUInt8 * buf
Definition: devMrmBufRx.cpp:67
virtual epicsUInt32 lenMax() const =0
#define linkString(Struct, Member, Name, Req, Over)
Definition: linkoptions.h:105
virtual void dataSend(epicsUInt32 len, const epicsUInt8 *buf)=0
Transmit a byte array.
char prop[20]
Definition: devMrfBufTx.cpp:38
char obj[40]
Definition: devMrfBufTx.cpp:36