PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.10/support/asyn/4-14/asyn/miscellaneous/asynPortDriver.cpp

http://atf2flightsim.googlecode.com/
C++ | 1544 lines | 1008 code | 163 blank | 373 comment | 205 complexity | 3159591f8aec13e341d01859f360ce38 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * asynPortDriver.cpp
  3. *
  4. * Base class that implements methods for asynStandardInterfaces with a parameter library.
  5. *
  6. * Author: Mark Rivers
  7. *
  8. * Created April 27, 2008
  9. */
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <errno.h>
  14. #include <epicsString.h>
  15. #include <epicsMutex.h>
  16. #include <epicsThread.h>
  17. #include <cantProceed.h>
  18. /* NOTE: This is needed for interruptAccept */
  19. #include <dbAccess.h>
  20. #include <asynStandardInterfaces.h>
  21. #include "asynPortDriver.h"
  22. static const char *driverName = "asynPortDriver";
  23. /* I thought this would be a temporary fix until EPICS supported PINI after interruptAccept, which would then be used
  24. * for input records that need callbacks after output records that also have PINI and that could affect them. But this
  25. * does not work with asyn device support because of the ring buffer. Records with SCAN=I/O Intr must not processed
  26. * for any other reason, including PINI, or the ring buffer can get out of sync. */
  27. static void callbackTaskC(void *drvPvt)
  28. {
  29. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  30. pPvt->callbackTask();
  31. }
  32. void asynPortDriver::callbackTask()
  33. {
  34. int addr;
  35. while(!interruptAccept) epicsThreadSleep(0.1);
  36. epicsMutexLock(this->mutexId);
  37. for (addr=0; addr<this->maxAddr; addr++) {
  38. callParamCallbacks(addr, addr);
  39. }
  40. epicsMutexUnlock(this->mutexId);
  41. }
  42. /** Constructor for paramList class.
  43. * \param[in] nVals Number of parameters in the list.
  44. * \param[in] pasynInterfaces Pointer to asynStandardInterfaces structure, used for callbacks */
  45. paramList::paramList(int nVals, asynStandardInterfaces *pasynInterfaces)
  46. : nextParam(0), nVals(nVals), nFlags(0), pasynInterfaces(pasynInterfaces)
  47. {
  48. vals = (paramVal *) calloc(nVals, sizeof(paramVal));
  49. flags = (int *) calloc(nVals, sizeof(int));
  50. }
  51. /** Destructor for paramList class; frees resources allocated in constructor */
  52. paramList::~paramList()
  53. {
  54. free(vals);
  55. free(flags);
  56. }
  57. asynStatus paramList::setFlag(int index)
  58. {
  59. int i;
  60. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  61. /* See if we have already set the flag for this parameter */
  62. for (i=0; i<this->nFlags; i++) if (this->flags[i] == index) break;
  63. /* If not found add a flag */
  64. if (i == this->nFlags) this->flags[this->nFlags++] = index;
  65. return asynSuccess;
  66. }
  67. /** Adds a new parameter to the parameter library.
  68. * \param[in] name The name of this parameter
  69. * \param[in] type The type of this parameter
  70. * \param[out] index The parameter number
  71. * \return Returns asynParamAlreadyExists if the parameter already exists, or asynBadParamIndex if
  72. * adding this parameter would exceed the size of the parameter list. */
  73. asynStatus paramList::createParam(const char *name, asynParamType type, int *index)
  74. {
  75. if (this->findParam(name, index) == asynSuccess) return asynParamAlreadyExists;
  76. *index = this->nextParam++;
  77. if (*index < 0 || *index >= this->nVals) return asynParamBadIndex;
  78. this->vals[*index].name = epicsStrDup(name);
  79. this->vals[*index].type = type;
  80. this->vals[*index].valueDefined = 0;
  81. return asynSuccess;
  82. }
  83. /** Finds a parameter in the parameter library.
  84. * \param[in] name The name of this parameter
  85. * \param[out] index The parameter number
  86. * \return Returns asynParamNotFound if name is not found in the parameter list. */
  87. asynStatus paramList::findParam(const char *name, int *index)
  88. {
  89. for (*index=0; *index<this->nVals; (*index)++) {
  90. if (name && this->vals[*index].name && (epicsStrCaseCmp(name, this->vals[*index].name) == 0)) return asynSuccess;
  91. }
  92. return asynParamNotFound;
  93. }
  94. /** Sets the value for an integer in the parameter library.
  95. * \param[in] index The parameter number
  96. * \param[in] value Value to set.
  97. * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parametertype is not asynParamInt32. */
  98. asynStatus paramList::setInteger(int index, int value)
  99. {
  100. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  101. if (this->vals[index].type != asynParamInt32) return asynParamWrongType;
  102. if ((!this->vals[index].valueDefined) || (this->vals[index].data.ival != value))
  103. {
  104. this->vals[index].valueDefined = 1;
  105. setFlag(index);
  106. this->vals[index].data.ival = value;
  107. }
  108. return asynSuccess;
  109. }
  110. /** Sets the value for an integer in the parameter library.
  111. * \param[in] index The parameter number
  112. * \param[in] value Value to set.
  113. * \param[in] mask Mask to use when setting the value.
  114. * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamUInt32Digital. */
  115. asynStatus paramList::setUInt32(int index, epicsUInt32 value, epicsUInt32 mask)
  116. {
  117. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  118. if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
  119. if ((!this->vals[index].valueDefined) || (this->vals[index].data.uival != value))
  120. {
  121. this->vals[index].valueDefined = 1;
  122. setFlag(index);
  123. /* Set any bits that are set in the value and the mask */
  124. this->vals[index].data.uival |= (value & mask);
  125. /* Clear bits that are clear in the value and set in the mask */
  126. this->vals[index].data.uival &= (value | ~mask);
  127. }
  128. return asynSuccess;
  129. }
  130. /** Sets the value for a double in the parameter library.
  131. * \param[in] index The parameter number
  132. * \param[in] value Value to set.
  133. * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamFloat64. */
  134. asynStatus paramList::setDouble(int index, double value)
  135. {
  136. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  137. if (this->vals[index].type != asynParamFloat64) return asynParamWrongType;
  138. if ((!this->vals[index].valueDefined) || (this->vals[index].data.dval != value))
  139. {
  140. this->vals[index].valueDefined = 1;
  141. setFlag(index);
  142. this->vals[index].data.dval = value;
  143. }
  144. return asynSuccess;
  145. }
  146. /** Sets the value for a string in the parameter library.
  147. * \param[in] index The parameter number
  148. * \param[out] value Address of value to set.
  149. * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamOctet. */
  150. asynStatus paramList::setString(int index, const char *value)
  151. {
  152. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  153. if (this->vals[index].type != asynParamOctet) return asynParamWrongType;
  154. if ((!this->vals[index].valueDefined) || (strcmp(this->vals[index].data.sval, value)))
  155. {
  156. this->vals[index].valueDefined = 1;
  157. setFlag(index);
  158. free(this->vals[index].data.sval);
  159. this->vals[index].data.sval = epicsStrDup(value);
  160. }
  161. return asynSuccess;
  162. }
  163. /** Returns the value for an integer from the parameter library.
  164. * \param[in] index The parameter number
  165. * \param[out] value Address of value to get.
  166. * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamInt32,
  167. * or asynParamUndefined if the value has not been defined. */
  168. asynStatus paramList::getInteger(int index, int *value)
  169. {
  170. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  171. if (this->vals[index].type != asynParamInt32) return asynParamWrongType;
  172. if (!this->vals[index].valueDefined) return asynParamUndefined;
  173. *value = this->vals[index].data.ival;
  174. return asynSuccess;
  175. }
  176. /** Returns the value for an integer from the parameter library.
  177. * \param[in] index The parameter number
  178. * \param[out] value Address of value to get.
  179. * \param[in] mask The mask to use when getting the value.
  180. * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamUInt32Digital,
  181. * or asynParamUndefined if the value has not been defined. */
  182. asynStatus paramList::getUInt32(int index, epicsUInt32 *value, epicsUInt32 mask)
  183. {
  184. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  185. if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
  186. if (!this->vals[index].valueDefined) return asynParamUndefined;
  187. *value = this->vals[index].data.uival & mask;
  188. return asynSuccess;
  189. }
  190. /** Returns the value for a double from the parameter library.
  191. * \param[in] index The parameter number
  192. * \param[out] value Address of value to get.
  193. * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamFloat64,
  194. * or asynParamUndefined if the value has not been defined. */
  195. asynStatus paramList::getDouble(int index, double *value)
  196. {
  197. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  198. if (this->vals[index].type != asynParamFloat64) return asynParamWrongType;
  199. if (!this->vals[index].valueDefined) return asynParamUndefined;
  200. *value = this->vals[index].data.dval;
  201. return asynSuccess;
  202. }
  203. /** Sets the value of the UInt32Interrupt in the parameter library.
  204. * \param[in] index The parameter number
  205. * \param[in] mask The interrupt mask.
  206. * \param[in] reason The interrupt reason.
  207. * \return Returns asynParamBadIndex if the index is not valid,
  208. * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
  209. asynStatus paramList::setUInt32Interrupt(int index, epicsUInt32 mask, interruptReason reason)
  210. {
  211. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  212. if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
  213. this->vals[index].uInt32InterruptMask = mask;
  214. this->vals[index].uInt32InterruptReason = reason;
  215. return asynSuccess;
  216. }
  217. /** Clears the UInt32Interrupt in the parameter library.
  218. * \param[in] index The parameter number
  219. * \param[in] mask The interrupt mask.
  220. * \return Returns asynParamBadIndex if the index is not valid,
  221. * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
  222. asynStatus paramList::clearUInt32Interrupt(int index, epicsUInt32 mask)
  223. {
  224. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  225. if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
  226. this->vals[index].uInt32InterruptMask = mask;
  227. return asynSuccess;
  228. }
  229. /** Returns the UInt32Interrupt from the parameter library.
  230. * \param[in] index The parameter number
  231. * \param[out] mask The address of the interrupt mask to return.
  232. * \param[in] reason The interrupt reason.
  233. * \return Returns asynParamBadIndex if the index is not valid,
  234. * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
  235. asynStatus paramList::getUInt32Interrupt(int index, epicsUInt32 *mask, interruptReason reason)
  236. {
  237. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  238. if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
  239. *mask = this->vals[index].uInt32InterruptMask;
  240. return asynSuccess;
  241. }
  242. /** Returns the value for a string from the parameter library.
  243. * \param[in] index The parameter number
  244. * \param[in] maxChars Maximum number of characters to return.
  245. * \param[out] value Address of value to get.
  246. * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamOctet,
  247. * or asynParamUndefined if the value has not been defined. */
  248. asynStatus paramList::getString(int index, int maxChars, char *value)
  249. {
  250. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  251. if (this->vals[index].type != asynParamOctet) return asynParamWrongType;
  252. if (!this->vals[index].valueDefined) return asynParamUndefined;
  253. if (maxChars > 0) {
  254. strncpy(value, this->vals[index].data.sval, maxChars-1);
  255. value[maxChars-1] = '\0';
  256. }
  257. return asynSuccess;
  258. }
  259. /** Returns the name of a parameter from the parameter library.
  260. * \param[in] index The parameter number
  261. * \param[out] value Address of pointer that will contain name string pointer.
  262. * \return Returns asynParamBadIndex if the index is not valid */
  263. asynStatus paramList::getName(int index, const char **value)
  264. {
  265. if (index < 0 || index >= this->nVals) return asynParamBadIndex;
  266. *value = (const char *)this->vals[index].name;
  267. return asynSuccess;
  268. }
  269. /** Calls the registered asyn callback functions for all clients for an integer parameter */
  270. asynStatus paramList::int32Callback(int command, int addr, epicsInt32 value)
  271. {
  272. ELLLIST *pclientList;
  273. interruptNode *pnode;
  274. asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
  275. int address;
  276. /* Pass int32 interrupts */
  277. if (!pInterfaces->int32InterruptPvt) return(asynParamNotFound);
  278. pasynManager->interruptStart(pInterfaces->int32InterruptPvt, &pclientList);
  279. pnode = (interruptNode *)ellFirst(pclientList);
  280. while (pnode) {
  281. asynInt32Interrupt *pInterrupt = (asynInt32Interrupt *) pnode->drvPvt;
  282. pasynManager->getAddr(pInterrupt->pasynUser, &address);
  283. /* If this is not a multi-device then address is -1, change to 0 */
  284. if (address == -1) address = 0;
  285. if ((command == pInterrupt->pasynUser->reason) &&
  286. (address == addr)) {
  287. pInterrupt->callback(pInterrupt->userPvt,
  288. pInterrupt->pasynUser,
  289. value);
  290. }
  291. pnode = (interruptNode *)ellNext(&pnode->node);
  292. }
  293. pasynManager->interruptEnd(pInterfaces->int32InterruptPvt);
  294. return(asynSuccess);
  295. }
  296. /** Calls the registered asyn callback functions for all clients for an UInt32 parameter */
  297. asynStatus paramList::uint32Callback(int command, int addr, epicsUInt32 value, epicsUInt32 interruptMask)
  298. {
  299. ELLLIST *pclientList;
  300. interruptNode *pnode;
  301. asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
  302. int address;
  303. /* Pass UInt32Digital interrupts */
  304. if (!pInterfaces->uInt32DigitalInterruptPvt) return(asynParamNotFound);
  305. pasynManager->interruptStart(pInterfaces->uInt32DigitalInterruptPvt, &pclientList);
  306. pnode = (interruptNode *)ellFirst(pclientList);
  307. while (pnode) {
  308. asynUInt32DigitalInterrupt *pInterrupt = (asynUInt32DigitalInterrupt *) pnode->drvPvt;
  309. pasynManager->getAddr(pInterrupt->pasynUser, &address);
  310. /* If this is not a multi-device then address is -1, change to 0 */
  311. if (address == -1) address = 0;
  312. if ((command == pInterrupt->pasynUser->reason) &&
  313. (address == addr) &&
  314. (pInterrupt->mask & interruptMask)) {
  315. pInterrupt->callback(pInterrupt->userPvt,
  316. pInterrupt->pasynUser,
  317. pInterrupt->mask & value);
  318. }
  319. pnode = (interruptNode *)ellNext(&pnode->node);
  320. }
  321. pasynManager->interruptEnd(pInterfaces->uInt32DigitalInterruptPvt);
  322. return(asynSuccess);
  323. }
  324. /** Calls the registered asyn callback functions for all clients for a double parameter */
  325. asynStatus paramList::float64Callback(int command, int addr, epicsFloat64 value)
  326. {
  327. ELLLIST *pclientList;
  328. interruptNode *pnode;
  329. asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
  330. int address;
  331. /* Pass float64 interrupts */
  332. if (!pInterfaces->float64InterruptPvt) return(asynParamNotFound);
  333. pasynManager->interruptStart(pInterfaces->float64InterruptPvt, &pclientList);
  334. pnode = (interruptNode *)ellFirst(pclientList);
  335. while (pnode) {
  336. asynFloat64Interrupt *pInterrupt = (asynFloat64Interrupt *) pnode->drvPvt;
  337. pasynManager->getAddr(pInterrupt->pasynUser, &address);
  338. /* If this is not a multi-device then address is -1, change to 0 */
  339. if (address == -1) address = 0;
  340. if ((command == pInterrupt->pasynUser->reason) &&
  341. (address == addr)) {
  342. pInterrupt->callback(pInterrupt->userPvt,
  343. pInterrupt->pasynUser,
  344. value);
  345. }
  346. pnode = (interruptNode *)ellNext(&pnode->node);
  347. }
  348. pasynManager->interruptEnd(pInterfaces->float64InterruptPvt);
  349. return(asynSuccess);
  350. }
  351. /** Calls the registered asyn callback functions for all clients for a string parameter */
  352. asynStatus paramList::octetCallback(int command, int addr, char *value)
  353. {
  354. ELLLIST *pclientList;
  355. interruptNode *pnode;
  356. asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
  357. int address;
  358. /* Pass octet interrupts */
  359. if (!pInterfaces->octetInterruptPvt) return(asynParamNotFound);
  360. pasynManager->interruptStart(pInterfaces->octetInterruptPvt, &pclientList);
  361. pnode = (interruptNode *)ellFirst(pclientList);
  362. while (pnode) {
  363. asynOctetInterrupt *pInterrupt = (asynOctetInterrupt *) pnode->drvPvt;
  364. pasynManager->getAddr(pInterrupt->pasynUser, &address);
  365. /* If this is not a multi-device then address is -1, change to 0 */
  366. if (address == -1) address = 0;
  367. if ((command == pInterrupt->pasynUser->reason) &&
  368. (address == addr)) {
  369. pInterrupt->callback(pInterrupt->userPvt,
  370. pInterrupt->pasynUser,
  371. value, strlen(value), ASYN_EOM_END);
  372. }
  373. pnode = (interruptNode *)ellNext(&pnode->node);
  374. }
  375. pasynManager->interruptEnd(pInterfaces->octetInterruptPvt);
  376. return(asynSuccess);
  377. }
  378. /** Calls the registered asyn callback functions for all clients for any parameters that have changed
  379. * since the last time this function was called.
  380. * \param[in] addr A client will be called if addr matches the asyn address registered for that client.
  381. *
  382. * Don't do anything if interruptAccept=0.
  383. * There is a thread that will do all callbacks once when interruptAccept goes to 1.
  384. */
  385. asynStatus paramList::callCallbacks(int addr)
  386. {
  387. int i, index;
  388. asynStatus status = asynSuccess;
  389. if (!interruptAccept) return(asynSuccess);
  390. for (i = 0; i < this->nFlags; i++)
  391. {
  392. index = this->flags[i];
  393. if (!this->vals[index].valueDefined) return(status);
  394. switch(this->vals[index].type) {
  395. case asynParamInt32:
  396. status = int32Callback(index, addr, this->vals[index].data.ival);
  397. break;
  398. case asynParamUInt32Digital:
  399. status = uint32Callback(index, addr, this->vals[index].data.uival, this->vals[index].uInt32InterruptMask);
  400. break;
  401. case asynParamFloat64:
  402. status = float64Callback(index, addr, this->vals[index].data.dval);
  403. break;
  404. case asynParamOctet:
  405. status = octetCallback(index, addr, this->vals[index].data.sval);
  406. break;
  407. default:
  408. break;
  409. }
  410. }
  411. this->nFlags=0;
  412. return(status);
  413. }
  414. asynStatus paramList::callCallbacks()
  415. {
  416. return(callCallbacks(0));
  417. }
  418. /** Reports on status of the paramList
  419. * \param[in] fp The file pointer on which report information will be written
  420. * \param[in] details The level of report detail desired. Prints the number of parameters in the list,
  421. * and if details >1 also prints the index, data type, name, and value of each parameter.
  422. */
  423. void paramList::report(FILE *fp, int details)
  424. {
  425. int i;
  426. printf( "Number of parameters is: %d\n", this->nVals );
  427. if (details <= 1) return;
  428. for (i=0; i<this->nVals; i++)
  429. {
  430. switch (this->vals[i].type)
  431. {
  432. case asynParamInt32:
  433. if (this->vals[i].valueDefined)
  434. fprintf(fp, "Parameter %d type=asynInt32, name=%s, value=%d\n", i, this->vals[i].name, this->vals[i].data.ival );
  435. else
  436. fprintf(fp, "Parameter %d type=asynInt32, name=%s, value is undefined\n", i, this->vals[i].name);
  437. break;
  438. case asynParamUInt32Digital:
  439. if (this->vals[i].valueDefined)
  440. fprintf(fp, "Parameter %d type=asynUInt32Digital, name=%s, value=%u, mask=%u\n", i, this->vals[i].name,
  441. this->vals[i].data.uival, this->vals[i].uInt32Mask );
  442. else
  443. fprintf(fp, "Parameter %d type=asynUInt32Digital, name=%s, value is undefined\n", i, this->vals[i].name);
  444. break;
  445. case asynParamFloat64:
  446. if (this->vals[i].valueDefined)
  447. fprintf(fp, "Parameter %d type=asynFloat64, name=%s, value=%f\n", i, this->vals[i].name, this->vals[i].data.dval );
  448. else
  449. fprintf(fp, "Parameter %d type=asynFloat64, name=%s, value is undefined\n", i, this->vals[i].name);
  450. break;
  451. case asynParamOctet:
  452. if (this->vals[i].valueDefined)
  453. fprintf(fp, "Parameter %d type=string, name=%s, value=%s\n", i, this->vals[i].name, this->vals[i].data.sval );
  454. else
  455. fprintf(fp, "Parameter %d type=string, name=%s, value is undefined\n", i, this->vals[i].name);
  456. break;
  457. case asynParamInt8Array:
  458. if (this->vals[i].valueDefined)
  459. fprintf(fp, "Parameter %d type=asynInt8Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi8 );
  460. else
  461. fprintf(fp, "Parameter %d type=asynInt8Array, name=%s, value is undefined\n", i, this->vals[i].name);
  462. break;
  463. case asynParamInt16Array:
  464. if (this->vals[i].valueDefined)
  465. fprintf(fp, "Parameter %d type=asynInt16Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi16 );
  466. else
  467. fprintf(fp, "Parameter %d type=asynInt16Array, name=%s, value is undefined\n", i, this->vals[i].name);
  468. break;
  469. case asynParamInt32Array:
  470. if (this->vals[i].valueDefined)
  471. fprintf(fp, "Parameter %d type=asynInt32Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi32 );
  472. else
  473. fprintf(fp, "Parameter %d type=asynInt32Array, name=%s, value is undefined\n", i, this->vals[i].name);
  474. break;
  475. case asynParamFloat32Array:
  476. if (this->vals[i].valueDefined)
  477. fprintf(fp, "Parameter %d type=asynFloat32Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pf32 );
  478. else
  479. fprintf(fp, "Parameter %d type=asynFloat32Array, name=%s, value is undefined\n", i, this->vals[i].name);
  480. break;
  481. case asynParamFloat64Array:
  482. if (this->vals[i].valueDefined)
  483. fprintf(fp, "Parameter %d type=asynFloat64Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pf64 );
  484. else
  485. fprintf(fp, "Parameter %d type=asynFloat64Array, name=%s, value is undefined\n", i, this->vals[i].name);
  486. break;
  487. default:
  488. fprintf(fp, "Parameter %d is undefined, name=%s\n", i, this->vals[i].name);
  489. break;
  490. }
  491. }
  492. }
  493. /** Locks the driver to prevent multiple threads from accessing memory at the same time.
  494. * This function is called whenever asyn clients call the functions on the asyn interfaces.
  495. * Drivers with their own background threads must call lock() to protect conflicts with
  496. * asyn clients. They can call unlock() to permit asyn clients to run during times that the driver
  497. * thread is idle or is performing compute bound work that does not access memory also accessible by clients. */
  498. asynStatus asynPortDriver::lock()
  499. {
  500. int status;
  501. status = epicsMutexLock(this->mutexId);
  502. if (status) return(asynError);
  503. else return(asynSuccess);
  504. }
  505. /** Unocks the driver; called when an asyn client or driver is done accessing common memory. */
  506. asynStatus asynPortDriver::unlock()
  507. {
  508. epicsMutexUnlock(this->mutexId);
  509. return(asynSuccess);
  510. }
  511. /** Creates a parameter in the parameter library.
  512. * Calls paramList::createParam (list, name, index) for all parameters lists.
  513. * \param[in] name Parameter name
  514. * \param[in] type Parameter type
  515. * \param[out] index Parameter number */
  516. asynStatus asynPortDriver::createParam(const char *name, asynParamType type, int *index)
  517. {
  518. int list;
  519. asynStatus status;
  520. /* All parameters lists support the same parameters, so add the parameter name to all lists */
  521. for (list=0; list<this->maxAddr; list++) {
  522. status = createParam(list, name, type, index);
  523. if (status) return asynError;
  524. }
  525. return asynSuccess;
  526. }
  527. /** Creates a parameter in the parameter library.
  528. * Calls paramList::addParam (name, index) for the parameter list indexed by list.
  529. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  530. * \param[in] name Parameter name
  531. * \param[in] type Parameter type
  532. * \param[out] index Parameter number */
  533. asynStatus asynPortDriver::createParam(int list, const char *name, asynParamType type, int *index)
  534. {
  535. asynStatus status;
  536. int itemp;
  537. static const char *functionName = "createParam";
  538. status = this->params[list]->findParam(name, &itemp);
  539. if (status == asynParamAlreadyExists) {
  540. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  541. "%s:%s: port=%s error adding parameter %s to list %d, parameter already exists.\n",
  542. driverName, functionName, portName, name, list);
  543. return(asynError);
  544. }
  545. status = this->params[list]->createParam(name, type, index);
  546. if (status == asynParamBadIndex) {
  547. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  548. "%s:%s: port=%s error adding parameter %s to list %d, too many parameters\n",
  549. driverName, functionName, portName, name, list);
  550. return(asynError);
  551. }
  552. return asynSuccess;
  553. }
  554. /** Finds a parameter in the parameter library.
  555. * Calls findParam(0, name, index), i.e. for parameter list 0.
  556. * \param[in] name Parameter name
  557. * \param[out] index Parameter number */
  558. asynStatus asynPortDriver::findParam(const char *name, int *index)
  559. {
  560. return this->findParam(0, name, index);
  561. }
  562. /** Finds a parameter in the parameter library.
  563. * Calls paramList::findParam (name, index) for the parameter list indexed by list.
  564. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  565. * \param[in] name Parameter name
  566. * \param[out] index Parameter number */
  567. asynStatus asynPortDriver::findParam(int list, const char *name, int *index)
  568. {
  569. return this->params[list]->findParam(name, index);
  570. }
  571. /** Returns the name of a parameter in the parameter library.
  572. * Calls getParamName(0, index, name) i.e. for parameter list 0.
  573. * \param[in] index Parameter number
  574. * \param[out] name Parameter name */
  575. asynStatus asynPortDriver::getParamName(int index, const char **name)
  576. {
  577. return this->getParamName(0, index, name);
  578. }
  579. /** Returns the name of a parameter in the parameter library.
  580. * Calls paramList::getName (index, name) for the parameter list indexed by list.
  581. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  582. * \param[in] index Parameter number
  583. * \param[out] name Parameter name */
  584. asynStatus asynPortDriver::getParamName(int list, int index, const char **name)
  585. {
  586. return this->params[list]->getName(index, name);
  587. }
  588. /** Reports errors when setting parameters.
  589. * \param[in] status The error status.
  590. * \param[in] index The parameter number
  591. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  592. * \param[in] functionName The name of the function that generated the error */
  593. void asynPortDriver::reportSetParamErrors(asynStatus status, int index, int list, const char *functionName)
  594. {
  595. if (status == asynParamBadIndex) {
  596. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  597. "%s:%s: port=%s error setting parameter %d in list %d, bad index\n",
  598. driverName, functionName, portName, index, list);
  599. }
  600. if (status == asynParamWrongType) {
  601. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  602. "%s:%s: port=%s error setting parameter %d in list %d, wrong type\n",
  603. driverName, functionName, portName, index, list);
  604. }
  605. }
  606. /** Sets the value for an integer in the parameter library.
  607. * Calls setIntegerParam(0, index, value) i.e. for parameter list 0.
  608. * \param[in] index The parameter number
  609. * \param[in] value Value to set. */
  610. asynStatus asynPortDriver::setIntegerParam(int index, int value)
  611. {
  612. return this->setIntegerParam(0, index, value);
  613. }
  614. /** Sets the value for an integer in the parameter library.
  615. * Calls paramList::setInteger (index, value) for the parameter list indexed by list.
  616. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  617. * \param[in] index The parameter number
  618. * \param[in] value Value to set. */
  619. asynStatus asynPortDriver::setIntegerParam(int list, int index, int value)
  620. {
  621. asynStatus status;
  622. static const char *functionName = "setIntegerParam";
  623. status = this->params[list]->setInteger(index, value);
  624. if (status) reportSetParamErrors(status, index, list, functionName);
  625. return(status);
  626. }
  627. /** Sets the value for a UInt32Digital in the parameter library.
  628. * Calls setUIntDigitalParam(0, index, value) i.e. for parameter list 0.
  629. * \param[in] index The parameter number
  630. * \param[in] value Value to set.
  631. * \param[in] mask The mask to use when setting the value. */
  632. asynStatus asynPortDriver::setUIntDigitalParam(int index, epicsUInt32 value, epicsUInt32 mask)
  633. {
  634. return this->setUIntDigitalParam(0, index, value, mask);
  635. }
  636. /** Sets the value for a UInt32Digital in the parameter library.
  637. * Calls paramList::setInteger (index, value) for the parameter list indexed by list.
  638. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  639. * \param[in] index The parameter number
  640. * \param[in] value Value to set.
  641. * \param[in] mask The mask to use when setting the value. */
  642. asynStatus asynPortDriver::setUIntDigitalParam(int list, int index, epicsUInt32 value, epicsUInt32 mask)
  643. {
  644. asynStatus status;
  645. static const char *functionName = "setUIntDigitalParam";
  646. status = this->params[list]->setUInt32(index, value, mask);
  647. if (status) reportSetParamErrors(status, index, list, functionName);
  648. return(status);
  649. }
  650. /** Sets the value for a double in the parameter library.
  651. * Calls setDoubleParam(0, index, value) i.e. for parameter list 0.
  652. * \param[in] index The parameter number
  653. * \param[in] value Value to set. */
  654. asynStatus asynPortDriver::setDoubleParam(int index, double value)
  655. {
  656. return this->setDoubleParam(0, index, value);
  657. }
  658. /** Sets the value for a double in the parameter library.
  659. * Calls paramList::setDouble (index, value) for the parameter list indexed by list.
  660. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  661. * \param[in] index The parameter number
  662. * \param[in] value Value to set. */
  663. asynStatus asynPortDriver::setDoubleParam(int list, int index, double value)
  664. {
  665. asynStatus status;
  666. static const char *functionName = "setDoubleParam";
  667. status = this->params[list]->setDouble(index, value);
  668. if (status) reportSetParamErrors(status, index, list, functionName);
  669. return(status);
  670. }
  671. /** Sets the value for a string in the parameter library.
  672. * Calls setStringParam(0, index, value) i.e. for parameter list 0.
  673. * \param[in] index The parameter number
  674. * \param[in] value Address of value to set. */
  675. asynStatus asynPortDriver::setStringParam(int index, const char *value)
  676. {
  677. return this->setStringParam(0, index, value);
  678. }
  679. /** Sets the value for a string in the parameter library.
  680. * Calls paramList::setString (index, value) for the parameter list indexed by list.
  681. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  682. * \param[in] index The parameter number
  683. * \param[in] value Address of value to set. */
  684. asynStatus asynPortDriver::setStringParam(int list, int index, const char *value)
  685. {
  686. asynStatus status;
  687. static const char *functionName = "setStringParam";
  688. status = this->params[list]->setString(index, value);
  689. if (status) reportSetParamErrors(status, index, list, functionName);
  690. return(status);
  691. }
  692. /** Reports errors when getting parameters.
  693. * asynParamBadIndex and asynParamWrongType are printed with ASYN_TRACE_ERROR because they should never happen.
  694. * asynParamUndefined is printed with ASYN_TRACE_FLOW because it is an expected error if the value is read before it
  695. * is defined, which device support can do.
  696. * \param[in] status The error status.
  697. * \param[in] index The parameter number
  698. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  699. * \param[in] functionName The name of the function that generated the error */
  700. void asynPortDriver::reportGetParamErrors(asynStatus status, int index, int list, const char *functionName)
  701. {
  702. if (status == asynParamBadIndex) {
  703. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  704. "%s:%s: port=%s error getting parameter %d in list %d, bad index\n",
  705. driverName, functionName, portName, index, list);
  706. }
  707. if (status == asynParamWrongType) {
  708. asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
  709. "%s:%s: port=%s error getting parameter %d in list %d, wrong type\n",
  710. driverName, functionName, portName, index, list);
  711. }
  712. if (status == asynParamUndefined) {
  713. asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
  714. "%s:%s: port=%s error getting parameter %d in list %d, value undefined\n",
  715. driverName, functionName, portName, index, list);
  716. }
  717. }
  718. /** Returns the value for an integer from the parameter library.
  719. * Calls getIntegerParam(0, index, value) i.e. for parameter list 0.
  720. * \param[in] index The parameter number
  721. * \param[out] value Address of value to get. */
  722. asynStatus asynPortDriver::getIntegerParam(int index, int *value)
  723. {
  724. return this->getIntegerParam(0, index, value);
  725. }
  726. /** Returns the value for an integer from the parameter library.
  727. * Calls paramList::getInteger (index, value) for the parameter list indexed by list.
  728. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  729. * \param[in] index The parameter number
  730. * \param[out] value Address of value to get. */
  731. asynStatus asynPortDriver::getIntegerParam(int list, int index, int *value)
  732. {
  733. asynStatus status;
  734. static const char *functionName = "getIntegerParam";
  735. status = this->params[list]->getInteger(index, value);
  736. if (status) reportGetParamErrors(status, index, list, functionName);
  737. return(status);
  738. }
  739. /** Returns the value for an UInt32Digital parameter from the parameter library.
  740. * Calls getUIntDigitalParam(0, index, value, mask) i.e. for parameter list 0.
  741. * \param[in] index The parameter number
  742. * \param[out] value Address of value to get.
  743. * \param[in] mask The mask to apply when getting the value */
  744. asynStatus asynPortDriver::getUIntDigitalParam(int index, epicsUInt32 *value, epicsUInt32 mask)
  745. {
  746. return this->getUIntDigitalParam(0, index, value, mask);
  747. }
  748. /** Returns the value for an UInt32Digital parameter from the parameter library.
  749. * Calls paramList::getUInt32 (index, value, mask) for the parameter list indexed by list.
  750. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  751. * \param[in] index The parameter number
  752. * \param[out] value Address of value to get.
  753. * \param[in] mask The mask to apply when getting the value. */
  754. asynStatus asynPortDriver::getUIntDigitalParam(int list, int index, epicsUInt32 *value, epicsUInt32 mask)
  755. {
  756. asynStatus status;
  757. static const char *functionName = "getUIntDigitalParam";
  758. status = this->params[list]->getUInt32(index, value, mask);
  759. if (status) reportGetParamErrors(status, index, list, functionName);
  760. return(status);
  761. }
  762. /** Returns the value for a double from the parameter library.
  763. * Calls getDoubleParam(0, index, value) i.e. for parameter list 0.
  764. * \param[in] index The parameter number
  765. * \param[out] value Address of value to get. */
  766. asynStatus asynPortDriver::getDoubleParam(int index, double *value)
  767. {
  768. return this->getDoubleParam(0, index, value);
  769. }
  770. /** Returns the value for a double from the parameter library.
  771. * Calls paramList::getDouble (index, value) for the parameter list indexed by list.
  772. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  773. * \param[in] index The parameter number
  774. * \param[out] value Address of value to get. */
  775. asynStatus asynPortDriver::getDoubleParam(int list, int index, double *value)
  776. {
  777. asynStatus status;
  778. static const char *functionName = "getDoubleParam";
  779. status = this->params[list]->getDouble(index, value);
  780. if (status) reportGetParamErrors(status, index, list, functionName);
  781. return(status);
  782. }
  783. /** Returns the value for a string from the parameter library.
  784. * Calls getStringParam(0, index, maxChars, value) i.e. for parameter list 0.
  785. * \param[in] index The parameter number
  786. * \param[in] maxChars Maximum number of characters to return.
  787. * \param[out] value Address of value to get. */
  788. asynStatus asynPortDriver::getStringParam(int index, int maxChars, char *value)
  789. {
  790. return this->getStringParam(0, index, maxChars, value);
  791. }
  792. /** Returns the value for a string from the parameter library.
  793. * Calls paramList::getString (index, maxChars, value) for the parameter list indexed by list.
  794. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  795. * \param[in] index The parameter number
  796. * \param[in] maxChars Maximum number of characters to return.
  797. * \param[out] value Address of value to get. */
  798. asynStatus asynPortDriver::getStringParam(int list, int index, int maxChars, char *value)
  799. {
  800. asynStatus status;
  801. static const char *functionName = "getStringParam";
  802. status = this->params[list]->getString(index, maxChars, value);
  803. if (status) reportGetParamErrors(status, index, list, functionName);
  804. return(status);
  805. }
  806. /** Calls callParamCallbacks(0, 0) i.e. with both list and asyn address. */
  807. asynStatus asynPortDriver::callParamCallbacks()
  808. {
  809. return this->callParamCallbacks(0, 0);
  810. }
  811. /** Calls callParamCallbacks(addr, addr) i.e. with list=addr, which is normal. */
  812. asynStatus asynPortDriver::callParamCallbacks(int addr)
  813. {
  814. return this->callParamCallbacks(addr, addr);
  815. }
  816. /** Calls paramList::callCallbacks(addr) for a specific parameter list.
  817. * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
  818. * \param[in] addr The asyn address to be used in the callback. Typically the same value as list. */
  819. asynStatus asynPortDriver::callParamCallbacks(int list, int addr)
  820. {
  821. return this->params[list]->callCallbacks(addr);
  822. }
  823. /** Calls paramList::report(fp, details) for each parameter list that the driver supports.
  824. * \param[in] fp The file pointer on which report information will be written
  825. * \param[in] details The level of report detail desired. */
  826. void asynPortDriver::reportParams(FILE *fp, int details)
  827. {
  828. int i;
  829. for (i=0; i<this->maxAddr; i++) {
  830. fprintf(fp, "Parameter list %d\n", i);
  831. this->params[i]->report(fp, details);
  832. }
  833. }
  834. template <typename epicsType>
  835. asynStatus readArray(asynUser *pasynUser, epicsType *value, size_t nElements, size_t *nIn)
  836. {
  837. epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
  838. "%s:readArray not implemented", driverName);
  839. return(asynError);
  840. }
  841. template <typename epicsType>
  842. asynStatus writeArray(asynUser *pasynUser, epicsType *value, size_t nElements)
  843. {
  844. epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
  845. "%s:writeArray not implemented", driverName);
  846. return(asynError);
  847. }
  848. template <typename epicsType, typename interruptType>
  849. asynStatus doCallbacksArray(epicsType *value, size_t nElements,
  850. int reason, int address, void *interruptPvt)
  851. {
  852. ELLLIST *pclientList;
  853. interruptNode *pnode;
  854. int addr;
  855. pasynManager->interruptStart(interruptPvt, &pclientList);
  856. pnode = (interruptNode *)ellFirst(pclientList);
  857. while (pnode) {
  858. interruptType *pInterrupt = (interruptType *)pnode->drvPvt;
  859. pasynManager->getAddr(pInterrupt->pasynUser, &addr);
  860. /* If this is not a multi-device then address is -1, change to 0 */
  861. if (addr == -1) addr = 0;
  862. if ((pInterrupt->pasynUser->reason == reason) &&
  863. (address == addr)) {
  864. pInterrupt->callback(pInterrupt->userPvt,
  865. pInterrupt->pasynUser,
  866. value, nElements);
  867. }
  868. pnode = (interruptNode *)ellNext(&pnode->node);
  869. }
  870. pasynManager->interruptEnd(interruptPvt);
  871. return(asynSuccess);
  872. }
  873. template <typename interruptType>
  874. void reportInterrupt(FILE *fp, void *interruptPvt, const char *interruptTypeString)
  875. {
  876. ELLLIST *pclientList;
  877. interruptNode *pnode;
  878. if (interruptPvt) {
  879. pasynManager->interruptStart(interruptPvt, &pclientList);
  880. pnode = (interruptNode *)ellFirst(pclientList);
  881. while (pnode) {
  882. interruptType *pInterrupt = (interruptType *)pnode->drvPvt;
  883. fprintf(fp, " %s callback client address=%p, addr=%d, reason=%d, userPvt=%p\n",
  884. interruptTypeString, pInterrupt->callback, pInterrupt->addr,
  885. pInterrupt->pasynUser->reason, pInterrupt->userPvt);
  886. pnode = (interruptNode *)ellNext(&pnode->node);
  887. }
  888. pasynManager->interruptEnd(interruptPvt);
  889. }
  890. }
  891. /** Returns the asyn address associated with a pasynUser structure.
  892. * Derived classes rarely need to reimplement this function.
  893. * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  894. * \param[out] address Returned address.
  895. * \return Returns asynError if the address is > maxAddr value passed to asynPortDriver::asynPortDriver. */
  896. asynStatus asynPortDriver::getAddress(asynUser *pasynUser, int *address)
  897. {
  898. static const char *functionName = "getAddress";
  899. pasynManager->getAddr(pasynUser, address);
  900. /* If this is not a multi-device then address is -1, change to 0 */
  901. if (*address == -1) *address = 0;
  902. if (*address > this->maxAddr-1) {
  903. asynPrint(pasynUser, ASYN_TRACE_ERROR,
  904. "%s:%s: %s invalid address=%d, max=%d\n",
  905. driverName, functionName, portName, *address, this->maxAddr-1);
  906. return(asynError);
  907. }
  908. return(asynSuccess);
  909. }
  910. /* asynInt32 interface methods */
  911. extern "C" {static asynStatus readInt32(void *drvPvt, asynUser *pasynUser,
  912. epicsInt32 *value)
  913. {
  914. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  915. asynStatus status;
  916. pPvt->lock();
  917. status = pPvt->readInt32(pasynUser, value);
  918. pPvt->unlock();
  919. return(status);
  920. }}
  921. /** Called when asyn clients call pasynInt32->read().
  922. * The base class implementation simply returns the value from the parameter library.
  923. * Derived classes rarely need to reimplement this function.
  924. * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  925. * \param[out] value Address of the value to read. */
  926. asynStatus asynPortDriver::readInt32(asynUser *pasynUser, epicsInt32 *value)
  927. {
  928. int function = pasynUser->reason;
  929. int addr=0;
  930. asynStatus status = asynSuccess;
  931. const char *functionName = "readInt32";
  932. status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
  933. /* We just read the current value of the parameter from the parameter library.
  934. * Those values are updated whenever anything could cause them to change */
  935. status = (asynStatus) getIntegerParam(addr, function, value);
  936. if (status)
  937. epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
  938. "%s:%s: status=%d, function=%d, value=%d",
  939. driverName, functionName, status, function, *value);
  940. else
  941. asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
  942. "%s:%s: function=%d, value=%d\n",
  943. driverName, functionName, function, *value);
  944. return(status);
  945. }
  946. extern "C" {static asynStatus writeInt32(void *drvPvt, asynUser *pasynUser,
  947. epicsInt32 value)
  948. {
  949. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  950. asynStatus status;
  951. pPvt->lock();
  952. status = pPvt->writeInt32(pasynUser, value);
  953. pPvt->unlock();
  954. return(status);
  955. }}
  956. /** Called when asyn clients call pasynInt32->write().
  957. * The base class implementation simply sets the value in the parameter library and
  958. * calls any registered callbacks for this pasynUser->reason and address.
  959. * Derived classes will reimplement this function if they need to perform an action when an
  960. * asynInt32 value is written.
  961. * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  962. * \param[in] value Value to write. */
  963. asynStatus asynPortDriver::writeInt32(asynUser *pasynUser, epicsInt32 value)
  964. {
  965. int function = pasynUser->reason;
  966. int addr=0;
  967. asynStatus status = asynSuccess;
  968. const char* functionName = "writeInt32";
  969. status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
  970. /* Set the parameter in the parameter library. */
  971. status = (asynStatus) setIntegerParam(addr, function, value);
  972. /* Do callbacks so higher layers see any changes */
  973. status = (asynStatus) callParamCallbacks(addr, addr);
  974. if (status)
  975. epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
  976. "%s:%s: status=%d, function=%d, value=%d",
  977. driverName, functionName, status, function, value);
  978. else
  979. asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
  980. "%s:%s: function=%d, value=%d\n",
  981. driverName, functionName, function, value);
  982. return status;
  983. }
  984. extern "C" {static asynStatus getBounds(void *drvPvt, asynUser *pasynUser,
  985. epicsInt32 *low, epicsInt32 *high)
  986. {
  987. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  988. asynStatus status;
  989. pPvt->lock();
  990. status = pPvt->getBounds(pasynUser, low, high);
  991. pPvt->unlock();
  992. return(status);
  993. }}
  994. /** Called when asyn clients call pasynInt32->getBounds(), returning the bounds on the asynInt32 interface
  995. * for drivers that use raw units.
  996. * Device support uses these values for unit conversion.
  997. * The base class implementation simply returns low=0, high=65535.
  998. * Derived classes can reimplement this function if they support raw units with different limits.
  999. * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  1000. * \param[out] low Address of the low limit.
  1001. * \param[out] high Address of the high limit. */
  1002. asynStatus asynPortDriver::getBounds(asynUser *pasynUser,
  1003. epicsInt32 *low, epicsInt32 *high)
  1004. {
  1005. /* This is only needed for the asynInt32 interface when the device uses raw units.
  1006. Our interface is using engineering units. */
  1007. *low = 0;
  1008. *high = 65535;
  1009. asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
  1010. "%s::getBounds,low=%d, high=%d\n",
  1011. driverName, *low, *high);
  1012. return(asynSuccess);
  1013. }
  1014. /* asynUInt32Digital interface methods */
  1015. extern "C" {static asynStatus readUInt32Digital(void *drvPvt, asynUser *pasynUser,
  1016. epicsUInt32 *value, epicsUInt32 mask)
  1017. {
  1018. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  1019. asynStatus status;
  1020. pPvt->lock();
  1021. status = pPvt->readUInt32Digital(pasynUser, value, mask);
  1022. pPvt->unlock();
  1023. return(status);
  1024. }}
  1025. /** Called when asyn clients call pasynUInt32Digital->read().
  1026. * The base class implementation simply returns the value from the parameter library.
  1027. * Derived classes rarely need to reimplement this function.
  1028. * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  1029. * \param[out] value Address of the value to read.
  1030. * \param[in] mask Mask value to use when reading the value. */
  1031. asynStatus asynPortDriver::readUInt32Digital(asynUser *pasynUser, epicsUInt32 *value, epicsUInt32 mask)
  1032. {
  1033. int function = pasynUser->reason;
  1034. int addr=0;
  1035. asynStatus status = asynSuccess;
  1036. const char *functionName = "readUInt32Digital";
  1037. status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
  1038. /* We just read the current value of the parameter from the parameter library.
  1039. * Those values are updated whenever anything could cause them to change */
  1040. status = (asynStatus) getUIntDigitalParam(addr, function, value, mask);
  1041. if (status)
  1042. epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
  1043. "%s:%s: status=%d, function=%d, value=%u mask=%u",
  1044. driverName, functionName, status, function, *value, mask);
  1045. else
  1046. asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
  1047. "%s:%s: function=%d, value=%u, mask=%u\n",
  1048. driverName, functionName, function, *value, mask);
  1049. return(status);
  1050. }
  1051. extern "C" {static asynStatus writeUInt32Digital(void *drvPvt, asynUser *pasynUser,
  1052. epicsUInt32 value, epicsUInt32 mask)
  1053. {
  1054. asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
  1055. asynStatus status;

Large files files are truncated, but you can click here to view the full file