/ATF2/control-software/epics-3.14.10/support/asyn/4-14/asyn/miscellaneous/asynPortDriver.cpp
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
- /*
- * asynPortDriver.cpp
- *
- * Base class that implements methods for asynStandardInterfaces with a parameter library.
- *
- * Author: Mark Rivers
- *
- * Created April 27, 2008
- */
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <errno.h>
- #include <epicsString.h>
- #include <epicsMutex.h>
- #include <epicsThread.h>
- #include <cantProceed.h>
- /* NOTE: This is needed for interruptAccept */
- #include <dbAccess.h>
- #include <asynStandardInterfaces.h>
- #include "asynPortDriver.h"
- static const char *driverName = "asynPortDriver";
- /* I thought this would be a temporary fix until EPICS supported PINI after interruptAccept, which would then be used
- * for input records that need callbacks after output records that also have PINI and that could affect them. But this
- * does not work with asyn device support because of the ring buffer. Records with SCAN=I/O Intr must not processed
- * for any other reason, including PINI, or the ring buffer can get out of sync. */
- static void callbackTaskC(void *drvPvt)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
-
- pPvt->callbackTask();
- }
- void asynPortDriver::callbackTask()
- {
- int addr;
-
- while(!interruptAccept) epicsThreadSleep(0.1);
- epicsMutexLock(this->mutexId);
- for (addr=0; addr<this->maxAddr; addr++) {
- callParamCallbacks(addr, addr);
- }
- epicsMutexUnlock(this->mutexId);
- }
- /** Constructor for paramList class.
- * \param[in] nVals Number of parameters in the list.
- * \param[in] pasynInterfaces Pointer to asynStandardInterfaces structure, used for callbacks */
- paramList::paramList(int nVals, asynStandardInterfaces *pasynInterfaces)
- : nextParam(0), nVals(nVals), nFlags(0), pasynInterfaces(pasynInterfaces)
- {
- vals = (paramVal *) calloc(nVals, sizeof(paramVal));
- flags = (int *) calloc(nVals, sizeof(int));
- }
- /** Destructor for paramList class; frees resources allocated in constructor */
- paramList::~paramList()
- {
- free(vals);
- free(flags);
- }
- asynStatus paramList::setFlag(int index)
- {
- int i;
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- /* See if we have already set the flag for this parameter */
- for (i=0; i<this->nFlags; i++) if (this->flags[i] == index) break;
- /* If not found add a flag */
- if (i == this->nFlags) this->flags[this->nFlags++] = index;
- return asynSuccess;
- }
- /** Adds a new parameter to the parameter library.
- * \param[in] name The name of this parameter
- * \param[in] type The type of this parameter
- * \param[out] index The parameter number
- * \return Returns asynParamAlreadyExists if the parameter already exists, or asynBadParamIndex if
- * adding this parameter would exceed the size of the parameter list. */
- asynStatus paramList::createParam(const char *name, asynParamType type, int *index)
- {
- if (this->findParam(name, index) == asynSuccess) return asynParamAlreadyExists;
- *index = this->nextParam++;
- if (*index < 0 || *index >= this->nVals) return asynParamBadIndex;
- this->vals[*index].name = epicsStrDup(name);
- this->vals[*index].type = type;
- this->vals[*index].valueDefined = 0;
- return asynSuccess;
- }
- /** Finds a parameter in the parameter library.
- * \param[in] name The name of this parameter
- * \param[out] index The parameter number
- * \return Returns asynParamNotFound if name is not found in the parameter list. */
- asynStatus paramList::findParam(const char *name, int *index)
- {
- for (*index=0; *index<this->nVals; (*index)++) {
- if (name && this->vals[*index].name && (epicsStrCaseCmp(name, this->vals[*index].name) == 0)) return asynSuccess;
- }
- return asynParamNotFound;
- }
- /** Sets the value for an integer in the parameter library.
- * \param[in] index The parameter number
- * \param[in] value Value to set.
- * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parametertype is not asynParamInt32. */
- asynStatus paramList::setInteger(int index, int value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamInt32) return asynParamWrongType;
- if ((!this->vals[index].valueDefined) || (this->vals[index].data.ival != value))
- {
- this->vals[index].valueDefined = 1;
- setFlag(index);
- this->vals[index].data.ival = value;
- }
- return asynSuccess;
- }
- /** Sets the value for an integer in the parameter library.
- * \param[in] index The parameter number
- * \param[in] value Value to set.
- * \param[in] mask Mask to use when setting the value.
- * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamUInt32Digital. */
- asynStatus paramList::setUInt32(int index, epicsUInt32 value, epicsUInt32 mask)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
- if ((!this->vals[index].valueDefined) || (this->vals[index].data.uival != value))
- {
- this->vals[index].valueDefined = 1;
- setFlag(index);
- /* Set any bits that are set in the value and the mask */
- this->vals[index].data.uival |= (value & mask);
- /* Clear bits that are clear in the value and set in the mask */
- this->vals[index].data.uival &= (value | ~mask);
- }
- return asynSuccess;
- }
- /** Sets the value for a double in the parameter library.
- * \param[in] index The parameter number
- * \param[in] value Value to set.
- * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamFloat64. */
- asynStatus paramList::setDouble(int index, double value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamFloat64) return asynParamWrongType;
- if ((!this->vals[index].valueDefined) || (this->vals[index].data.dval != value))
- {
- this->vals[index].valueDefined = 1;
- setFlag(index);
- this->vals[index].data.dval = value;
- }
- return asynSuccess;
- }
- /** Sets the value for a string in the parameter library.
- * \param[in] index The parameter number
- * \param[out] value Address of value to set.
- * \return Returns asynParamBadIndex if the index is not valid or asynParamWrongType if the parameter type is not asynParamOctet. */
- asynStatus paramList::setString(int index, const char *value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamOctet) return asynParamWrongType;
- if ((!this->vals[index].valueDefined) || (strcmp(this->vals[index].data.sval, value)))
- {
- this->vals[index].valueDefined = 1;
- setFlag(index);
- free(this->vals[index].data.sval);
- this->vals[index].data.sval = epicsStrDup(value);
- }
- return asynSuccess;
- }
- /** Returns the value for an integer from the parameter library.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get.
- * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamInt32,
- * or asynParamUndefined if the value has not been defined. */
- asynStatus paramList::getInteger(int index, int *value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamInt32) return asynParamWrongType;
- if (!this->vals[index].valueDefined) return asynParamUndefined;
- *value = this->vals[index].data.ival;
- return asynSuccess;
- }
- /** Returns the value for an integer from the parameter library.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get.
- * \param[in] mask The mask to use when getting the value.
- * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamUInt32Digital,
- * or asynParamUndefined if the value has not been defined. */
- asynStatus paramList::getUInt32(int index, epicsUInt32 *value, epicsUInt32 mask)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
- if (!this->vals[index].valueDefined) return asynParamUndefined;
- *value = this->vals[index].data.uival & mask;
- return asynSuccess;
- }
- /** Returns the value for a double from the parameter library.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get.
- * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamFloat64,
- * or asynParamUndefined if the value has not been defined. */
- asynStatus paramList::getDouble(int index, double *value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamFloat64) return asynParamWrongType;
- if (!this->vals[index].valueDefined) return asynParamUndefined;
- *value = this->vals[index].data.dval;
- return asynSuccess;
- }
- /** Sets the value of the UInt32Interrupt in the parameter library.
- * \param[in] index The parameter number
- * \param[in] mask The interrupt mask.
- * \param[in] reason The interrupt reason.
- * \return Returns asynParamBadIndex if the index is not valid,
- * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
- asynStatus paramList::setUInt32Interrupt(int index, epicsUInt32 mask, interruptReason reason)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
- this->vals[index].uInt32InterruptMask = mask;
- this->vals[index].uInt32InterruptReason = reason;
- return asynSuccess;
- }
- /** Clears the UInt32Interrupt in the parameter library.
- * \param[in] index The parameter number
- * \param[in] mask The interrupt mask.
- * \return Returns asynParamBadIndex if the index is not valid,
- * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
- asynStatus paramList::clearUInt32Interrupt(int index, epicsUInt32 mask)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
- this->vals[index].uInt32InterruptMask = mask;
- return asynSuccess;
- }
- /** Returns the UInt32Interrupt from the parameter library.
- * \param[in] index The parameter number
- * \param[out] mask The address of the interrupt mask to return.
- * \param[in] reason The interrupt reason.
- * \return Returns asynParamBadIndex if the index is not valid,
- * or asynParamWrongType if the parameter type is not asynParamUInt32Digital */
- asynStatus paramList::getUInt32Interrupt(int index, epicsUInt32 *mask, interruptReason reason)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamUInt32Digital) return asynParamWrongType;
- *mask = this->vals[index].uInt32InterruptMask;
- return asynSuccess;
- }
- /** Returns the value for a string from the parameter library.
- * \param[in] index The parameter number
- * \param[in] maxChars Maximum number of characters to return.
- * \param[out] value Address of value to get.
- * \return Returns asynParamBadIndex if the index is not valid, asynParamWrongType if the parameter type is not asynParamOctet,
- * or asynParamUndefined if the value has not been defined. */
- asynStatus paramList::getString(int index, int maxChars, char *value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- if (this->vals[index].type != asynParamOctet) return asynParamWrongType;
- if (!this->vals[index].valueDefined) return asynParamUndefined;
- if (maxChars > 0) {
- strncpy(value, this->vals[index].data.sval, maxChars-1);
- value[maxChars-1] = '\0';
- }
- return asynSuccess;
- }
- /** Returns the name of a parameter from the parameter library.
- * \param[in] index The parameter number
- * \param[out] value Address of pointer that will contain name string pointer.
- * \return Returns asynParamBadIndex if the index is not valid */
- asynStatus paramList::getName(int index, const char **value)
- {
- if (index < 0 || index >= this->nVals) return asynParamBadIndex;
- *value = (const char *)this->vals[index].name;
- return asynSuccess;
- }
- /** Calls the registered asyn callback functions for all clients for an integer parameter */
- asynStatus paramList::int32Callback(int command, int addr, epicsInt32 value)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
- asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
- int address;
- /* Pass int32 interrupts */
- if (!pInterfaces->int32InterruptPvt) return(asynParamNotFound);
- pasynManager->interruptStart(pInterfaces->int32InterruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- asynInt32Interrupt *pInterrupt = (asynInt32Interrupt *) pnode->drvPvt;
- pasynManager->getAddr(pInterrupt->pasynUser, &address);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (address == -1) address = 0;
- if ((command == pInterrupt->pasynUser->reason) &&
- (address == addr)) {
- pInterrupt->callback(pInterrupt->userPvt,
- pInterrupt->pasynUser,
- value);
- }
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(pInterfaces->int32InterruptPvt);
- return(asynSuccess);
- }
- /** Calls the registered asyn callback functions for all clients for an UInt32 parameter */
- asynStatus paramList::uint32Callback(int command, int addr, epicsUInt32 value, epicsUInt32 interruptMask)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
- asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
- int address;
- /* Pass UInt32Digital interrupts */
- if (!pInterfaces->uInt32DigitalInterruptPvt) return(asynParamNotFound);
- pasynManager->interruptStart(pInterfaces->uInt32DigitalInterruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- asynUInt32DigitalInterrupt *pInterrupt = (asynUInt32DigitalInterrupt *) pnode->drvPvt;
- pasynManager->getAddr(pInterrupt->pasynUser, &address);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (address == -1) address = 0;
- if ((command == pInterrupt->pasynUser->reason) &&
- (address == addr) &&
- (pInterrupt->mask & interruptMask)) {
- pInterrupt->callback(pInterrupt->userPvt,
- pInterrupt->pasynUser,
- pInterrupt->mask & value);
- }
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(pInterfaces->uInt32DigitalInterruptPvt);
- return(asynSuccess);
- }
- /** Calls the registered asyn callback functions for all clients for a double parameter */
- asynStatus paramList::float64Callback(int command, int addr, epicsFloat64 value)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
- asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
- int address;
- /* Pass float64 interrupts */
- if (!pInterfaces->float64InterruptPvt) return(asynParamNotFound);
- pasynManager->interruptStart(pInterfaces->float64InterruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- asynFloat64Interrupt *pInterrupt = (asynFloat64Interrupt *) pnode->drvPvt;
- pasynManager->getAddr(pInterrupt->pasynUser, &address);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (address == -1) address = 0;
- if ((command == pInterrupt->pasynUser->reason) &&
- (address == addr)) {
- pInterrupt->callback(pInterrupt->userPvt,
- pInterrupt->pasynUser,
- value);
- }
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(pInterfaces->float64InterruptPvt);
- return(asynSuccess);
- }
- /** Calls the registered asyn callback functions for all clients for a string parameter */
- asynStatus paramList::octetCallback(int command, int addr, char *value)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
- asynStandardInterfaces *pInterfaces = this->pasynInterfaces;
- int address;
- /* Pass octet interrupts */
- if (!pInterfaces->octetInterruptPvt) return(asynParamNotFound);
- pasynManager->interruptStart(pInterfaces->octetInterruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- asynOctetInterrupt *pInterrupt = (asynOctetInterrupt *) pnode->drvPvt;
- pasynManager->getAddr(pInterrupt->pasynUser, &address);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (address == -1) address = 0;
- if ((command == pInterrupt->pasynUser->reason) &&
- (address == addr)) {
- pInterrupt->callback(pInterrupt->userPvt,
- pInterrupt->pasynUser,
- value, strlen(value), ASYN_EOM_END);
- }
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(pInterfaces->octetInterruptPvt);
- return(asynSuccess);
- }
- /** Calls the registered asyn callback functions for all clients for any parameters that have changed
- * since the last time this function was called.
- * \param[in] addr A client will be called if addr matches the asyn address registered for that client.
- *
- * Don't do anything if interruptAccept=0.
- * There is a thread that will do all callbacks once when interruptAccept goes to 1.
- */
- asynStatus paramList::callCallbacks(int addr)
- {
- int i, index;
- asynStatus status = asynSuccess;
-
- if (!interruptAccept) return(asynSuccess);
-
- for (i = 0; i < this->nFlags; i++)
- {
- index = this->flags[i];
- if (!this->vals[index].valueDefined) return(status);
- switch(this->vals[index].type) {
- case asynParamInt32:
- status = int32Callback(index, addr, this->vals[index].data.ival);
- break;
- case asynParamUInt32Digital:
- status = uint32Callback(index, addr, this->vals[index].data.uival, this->vals[index].uInt32InterruptMask);
- break;
- case asynParamFloat64:
- status = float64Callback(index, addr, this->vals[index].data.dval);
- break;
- case asynParamOctet:
- status = octetCallback(index, addr, this->vals[index].data.sval);
- break;
- default:
- break;
- }
- }
- this->nFlags=0;
- return(status);
- }
- asynStatus paramList::callCallbacks()
- {
- return(callCallbacks(0));
- }
- /** Reports on status of the paramList
- * \param[in] fp The file pointer on which report information will be written
- * \param[in] details The level of report detail desired. Prints the number of parameters in the list,
- * and if details >1 also prints the index, data type, name, and value of each parameter.
- */
- void paramList::report(FILE *fp, int details)
- {
- int i;
- printf( "Number of parameters is: %d\n", this->nVals );
- if (details <= 1) return;
- for (i=0; i<this->nVals; i++)
- {
- switch (this->vals[i].type)
- {
- case asynParamInt32:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynInt32, name=%s, value=%d\n", i, this->vals[i].name, this->vals[i].data.ival );
- else
- fprintf(fp, "Parameter %d type=asynInt32, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamUInt32Digital:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynUInt32Digital, name=%s, value=%u, mask=%u\n", i, this->vals[i].name,
- this->vals[i].data.uival, this->vals[i].uInt32Mask );
- else
- fprintf(fp, "Parameter %d type=asynUInt32Digital, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamFloat64:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynFloat64, name=%s, value=%f\n", i, this->vals[i].name, this->vals[i].data.dval );
- else
- fprintf(fp, "Parameter %d type=asynFloat64, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamOctet:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=string, name=%s, value=%s\n", i, this->vals[i].name, this->vals[i].data.sval );
- else
- fprintf(fp, "Parameter %d type=string, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamInt8Array:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynInt8Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi8 );
- else
- fprintf(fp, "Parameter %d type=asynInt8Array, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamInt16Array:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynInt16Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi16 );
- else
- fprintf(fp, "Parameter %d type=asynInt16Array, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamInt32Array:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynInt32Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pi32 );
- else
- fprintf(fp, "Parameter %d type=asynInt32Array, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamFloat32Array:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynFloat32Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pf32 );
- else
- fprintf(fp, "Parameter %d type=asynFloat32Array, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- case asynParamFloat64Array:
- if (this->vals[i].valueDefined)
- fprintf(fp, "Parameter %d type=asynFloat64Array, name=%s, value=%p\n", i, this->vals[i].name, this->vals[i].data.pf64 );
- else
- fprintf(fp, "Parameter %d type=asynFloat64Array, name=%s, value is undefined\n", i, this->vals[i].name);
- break;
- default:
- fprintf(fp, "Parameter %d is undefined, name=%s\n", i, this->vals[i].name);
- break;
- }
- }
- }
- /** Locks the driver to prevent multiple threads from accessing memory at the same time.
- * This function is called whenever asyn clients call the functions on the asyn interfaces.
- * Drivers with their own background threads must call lock() to protect conflicts with
- * asyn clients. They can call unlock() to permit asyn clients to run during times that the driver
- * thread is idle or is performing compute bound work that does not access memory also accessible by clients. */
- asynStatus asynPortDriver::lock()
- {
- int status;
- status = epicsMutexLock(this->mutexId);
- if (status) return(asynError);
- else return(asynSuccess);
- }
- /** Unocks the driver; called when an asyn client or driver is done accessing common memory. */
- asynStatus asynPortDriver::unlock()
- {
- epicsMutexUnlock(this->mutexId);
- return(asynSuccess);
- }
- /** Creates a parameter in the parameter library.
- * Calls paramList::createParam (list, name, index) for all parameters lists.
- * \param[in] name Parameter name
- * \param[in] type Parameter type
- * \param[out] index Parameter number */
- asynStatus asynPortDriver::createParam(const char *name, asynParamType type, int *index)
- {
- int list;
- asynStatus status;
-
- /* All parameters lists support the same parameters, so add the parameter name to all lists */
- for (list=0; list<this->maxAddr; list++) {
- status = createParam(list, name, type, index);
- if (status) return asynError;
- }
- return asynSuccess;
- }
- /** Creates a parameter in the parameter library.
- * Calls paramList::addParam (name, index) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] name Parameter name
- * \param[in] type Parameter type
- * \param[out] index Parameter number */
- asynStatus asynPortDriver::createParam(int list, const char *name, asynParamType type, int *index)
- {
- asynStatus status;
- int itemp;
- static const char *functionName = "createParam";
-
- status = this->params[list]->findParam(name, &itemp);
- if (status == asynParamAlreadyExists) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error adding parameter %s to list %d, parameter already exists.\n",
- driverName, functionName, portName, name, list);
- return(asynError);
- }
- status = this->params[list]->createParam(name, type, index);
- if (status == asynParamBadIndex) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error adding parameter %s to list %d, too many parameters\n",
- driverName, functionName, portName, name, list);
- return(asynError);
- }
- return asynSuccess;
- }
- /** Finds a parameter in the parameter library.
- * Calls findParam(0, name, index), i.e. for parameter list 0.
- * \param[in] name Parameter name
- * \param[out] index Parameter number */
- asynStatus asynPortDriver::findParam(const char *name, int *index)
- {
- return this->findParam(0, name, index);
- }
- /** Finds a parameter in the parameter library.
- * Calls paramList::findParam (name, index) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] name Parameter name
- * \param[out] index Parameter number */
- asynStatus asynPortDriver::findParam(int list, const char *name, int *index)
- {
- return this->params[list]->findParam(name, index);
- }
- /** Returns the name of a parameter in the parameter library.
- * Calls getParamName(0, index, name) i.e. for parameter list 0.
- * \param[in] index Parameter number
- * \param[out] name Parameter name */
- asynStatus asynPortDriver::getParamName(int index, const char **name)
- {
- return this->getParamName(0, index, name);
- }
- /** Returns the name of a parameter in the parameter library.
- * Calls paramList::getName (index, name) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index Parameter number
- * \param[out] name Parameter name */
- asynStatus asynPortDriver::getParamName(int list, int index, const char **name)
- {
- return this->params[list]->getName(index, name);
- }
- /** Reports errors when setting parameters.
- * \param[in] status The error status.
- * \param[in] index The parameter number
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] functionName The name of the function that generated the error */
- void asynPortDriver::reportSetParamErrors(asynStatus status, int index, int list, const char *functionName)
- {
- if (status == asynParamBadIndex) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error setting parameter %d in list %d, bad index\n",
- driverName, functionName, portName, index, list);
- }
- if (status == asynParamWrongType) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error setting parameter %d in list %d, wrong type\n",
- driverName, functionName, portName, index, list);
- }
- }
- /** Sets the value for an integer in the parameter library.
- * Calls setIntegerParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[in] value Value to set. */
- asynStatus asynPortDriver::setIntegerParam(int index, int value)
- {
- return this->setIntegerParam(0, index, value);
- }
- /** Sets the value for an integer in the parameter library.
- * Calls paramList::setInteger (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[in] value Value to set. */
- asynStatus asynPortDriver::setIntegerParam(int list, int index, int value)
- {
- asynStatus status;
- static const char *functionName = "setIntegerParam";
-
- status = this->params[list]->setInteger(index, value);
- if (status) reportSetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Sets the value for a UInt32Digital in the parameter library.
- * Calls setUIntDigitalParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[in] value Value to set.
- * \param[in] mask The mask to use when setting the value. */
- asynStatus asynPortDriver::setUIntDigitalParam(int index, epicsUInt32 value, epicsUInt32 mask)
- {
- return this->setUIntDigitalParam(0, index, value, mask);
- }
- /** Sets the value for a UInt32Digital in the parameter library.
- * Calls paramList::setInteger (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[in] value Value to set.
- * \param[in] mask The mask to use when setting the value. */
- asynStatus asynPortDriver::setUIntDigitalParam(int list, int index, epicsUInt32 value, epicsUInt32 mask)
- {
- asynStatus status;
- static const char *functionName = "setUIntDigitalParam";
-
- status = this->params[list]->setUInt32(index, value, mask);
- if (status) reportSetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Sets the value for a double in the parameter library.
- * Calls setDoubleParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[in] value Value to set. */
- asynStatus asynPortDriver::setDoubleParam(int index, double value)
- {
- return this->setDoubleParam(0, index, value);
- }
- /** Sets the value for a double in the parameter library.
- * Calls paramList::setDouble (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[in] value Value to set. */
- asynStatus asynPortDriver::setDoubleParam(int list, int index, double value)
- {
- asynStatus status;
- static const char *functionName = "setDoubleParam";
-
- status = this->params[list]->setDouble(index, value);
- if (status) reportSetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Sets the value for a string in the parameter library.
- * Calls setStringParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[in] value Address of value to set. */
- asynStatus asynPortDriver::setStringParam(int index, const char *value)
- {
- return this->setStringParam(0, index, value);
- }
- /** Sets the value for a string in the parameter library.
- * Calls paramList::setString (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[in] value Address of value to set. */
- asynStatus asynPortDriver::setStringParam(int list, int index, const char *value)
- {
- asynStatus status;
- static const char *functionName = "setStringParam";
- status = this->params[list]->setString(index, value);
- if (status) reportSetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Reports errors when getting parameters.
- * asynParamBadIndex and asynParamWrongType are printed with ASYN_TRACE_ERROR because they should never happen.
- * asynParamUndefined is printed with ASYN_TRACE_FLOW because it is an expected error if the value is read before it
- * is defined, which device support can do.
- * \param[in] status The error status.
- * \param[in] index The parameter number
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] functionName The name of the function that generated the error */
- void asynPortDriver::reportGetParamErrors(asynStatus status, int index, int list, const char *functionName)
- {
- if (status == asynParamBadIndex) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error getting parameter %d in list %d, bad index\n",
- driverName, functionName, portName, index, list);
- }
- if (status == asynParamWrongType) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
- "%s:%s: port=%s error getting parameter %d in list %d, wrong type\n",
- driverName, functionName, portName, index, list);
- }
- if (status == asynParamUndefined) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
- "%s:%s: port=%s error getting parameter %d in list %d, value undefined\n",
- driverName, functionName, portName, index, list);
- }
- }
- /** Returns the value for an integer from the parameter library.
- * Calls getIntegerParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getIntegerParam(int index, int *value)
- {
- return this->getIntegerParam(0, index, value);
- }
- /** Returns the value for an integer from the parameter library.
- * Calls paramList::getInteger (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getIntegerParam(int list, int index, int *value)
- {
- asynStatus status;
- static const char *functionName = "getIntegerParam";
- status = this->params[list]->getInteger(index, value);
- if (status) reportGetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Returns the value for an UInt32Digital parameter from the parameter library.
- * Calls getUIntDigitalParam(0, index, value, mask) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get.
- * \param[in] mask The mask to apply when getting the value */
- asynStatus asynPortDriver::getUIntDigitalParam(int index, epicsUInt32 *value, epicsUInt32 mask)
- {
- return this->getUIntDigitalParam(0, index, value, mask);
- }
- /** Returns the value for an UInt32Digital parameter from the parameter library.
- * Calls paramList::getUInt32 (index, value, mask) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get.
- * \param[in] mask The mask to apply when getting the value. */
- asynStatus asynPortDriver::getUIntDigitalParam(int list, int index, epicsUInt32 *value, epicsUInt32 mask)
- {
- asynStatus status;
- static const char *functionName = "getUIntDigitalParam";
- status = this->params[list]->getUInt32(index, value, mask);
- if (status) reportGetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Returns the value for a double from the parameter library.
- * Calls getDoubleParam(0, index, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getDoubleParam(int index, double *value)
- {
- return this->getDoubleParam(0, index, value);
- }
- /** Returns the value for a double from the parameter library.
- * Calls paramList::getDouble (index, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getDoubleParam(int list, int index, double *value)
- {
- asynStatus status;
- static const char *functionName = "getDoubleParam";
- status = this->params[list]->getDouble(index, value);
- if (status) reportGetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Returns the value for a string from the parameter library.
- * Calls getStringParam(0, index, maxChars, value) i.e. for parameter list 0.
- * \param[in] index The parameter number
- * \param[in] maxChars Maximum number of characters to return.
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getStringParam(int index, int maxChars, char *value)
- {
- return this->getStringParam(0, index, maxChars, value);
- }
- /** Returns the value for a string from the parameter library.
- * Calls paramList::getString (index, maxChars, value) for the parameter list indexed by list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] index The parameter number
- * \param[in] maxChars Maximum number of characters to return.
- * \param[out] value Address of value to get. */
- asynStatus asynPortDriver::getStringParam(int list, int index, int maxChars, char *value)
- {
- asynStatus status;
- static const char *functionName = "getStringParam";
- status = this->params[list]->getString(index, maxChars, value);
- if (status) reportGetParamErrors(status, index, list, functionName);
- return(status);
- }
- /** Calls callParamCallbacks(0, 0) i.e. with both list and asyn address. */
- asynStatus asynPortDriver::callParamCallbacks()
- {
- return this->callParamCallbacks(0, 0);
- }
- /** Calls callParamCallbacks(addr, addr) i.e. with list=addr, which is normal. */
- asynStatus asynPortDriver::callParamCallbacks(int addr)
- {
- return this->callParamCallbacks(addr, addr);
- }
- /** Calls paramList::callCallbacks(addr) for a specific parameter list.
- * \param[in] list The parameter list number. Must be < maxAddr passed to asynPortDriver::asynPortDriver.
- * \param[in] addr The asyn address to be used in the callback. Typically the same value as list. */
- asynStatus asynPortDriver::callParamCallbacks(int list, int addr)
- {
- return this->params[list]->callCallbacks(addr);
- }
- /** Calls paramList::report(fp, details) for each parameter list that the driver supports.
- * \param[in] fp The file pointer on which report information will be written
- * \param[in] details The level of report detail desired. */
- void asynPortDriver::reportParams(FILE *fp, int details)
- {
- int i;
- for (i=0; i<this->maxAddr; i++) {
- fprintf(fp, "Parameter list %d\n", i);
- this->params[i]->report(fp, details);
- }
- }
- template <typename epicsType>
- asynStatus readArray(asynUser *pasynUser, epicsType *value, size_t nElements, size_t *nIn)
- {
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s:readArray not implemented", driverName);
- return(asynError);
- }
- template <typename epicsType>
- asynStatus writeArray(asynUser *pasynUser, epicsType *value, size_t nElements)
- {
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s:writeArray not implemented", driverName);
- return(asynError);
- }
- template <typename epicsType, typename interruptType>
- asynStatus doCallbacksArray(epicsType *value, size_t nElements,
- int reason, int address, void *interruptPvt)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
- int addr;
- pasynManager->interruptStart(interruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- interruptType *pInterrupt = (interruptType *)pnode->drvPvt;
- pasynManager->getAddr(pInterrupt->pasynUser, &addr);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (addr == -1) addr = 0;
- if ((pInterrupt->pasynUser->reason == reason) &&
- (address == addr)) {
- pInterrupt->callback(pInterrupt->userPvt,
- pInterrupt->pasynUser,
- value, nElements);
- }
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(interruptPvt);
- return(asynSuccess);
- }
- template <typename interruptType>
- void reportInterrupt(FILE *fp, void *interruptPvt, const char *interruptTypeString)
- {
- ELLLIST *pclientList;
- interruptNode *pnode;
-
- if (interruptPvt) {
- pasynManager->interruptStart(interruptPvt, &pclientList);
- pnode = (interruptNode *)ellFirst(pclientList);
- while (pnode) {
- interruptType *pInterrupt = (interruptType *)pnode->drvPvt;
- fprintf(fp, " %s callback client address=%p, addr=%d, reason=%d, userPvt=%p\n",
- interruptTypeString, pInterrupt->callback, pInterrupt->addr,
- pInterrupt->pasynUser->reason, pInterrupt->userPvt);
- pnode = (interruptNode *)ellNext(&pnode->node);
- }
- pasynManager->interruptEnd(interruptPvt);
- }
- }
- /** Returns the asyn address associated with a pasynUser structure.
- * Derived classes rarely need to reimplement this function.
- * \param[in] pasynUser pasynUser structure that encodes the reason and address.
- * \param[out] address Returned address.
- * \return Returns asynError if the address is > maxAddr value passed to asynPortDriver::asynPortDriver. */
- asynStatus asynPortDriver::getAddress(asynUser *pasynUser, int *address)
- {
- static const char *functionName = "getAddress";
-
- pasynManager->getAddr(pasynUser, address);
- /* If this is not a multi-device then address is -1, change to 0 */
- if (*address == -1) *address = 0;
- if (*address > this->maxAddr-1) {
- asynPrint(pasynUser, ASYN_TRACE_ERROR,
- "%s:%s: %s invalid address=%d, max=%d\n",
- driverName, functionName, portName, *address, this->maxAddr-1);
- return(asynError);
- }
- return(asynSuccess);
- }
- /* asynInt32 interface methods */
- extern "C" {static asynStatus readInt32(void *drvPvt, asynUser *pasynUser,
- epicsInt32 *value)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
- asynStatus status;
-
- pPvt->lock();
- status = pPvt->readInt32(pasynUser, value);
- pPvt->unlock();
- return(status);
- }}
- /** Called when asyn clients call pasynInt32->read().
- * The base class implementation simply returns the value from the parameter library.
- * Derived classes rarely need to reimplement this function.
- * \param[in] pasynUser pasynUser structure that encodes the reason and address.
- * \param[out] value Address of the value to read. */
- asynStatus asynPortDriver::readInt32(asynUser *pasynUser, epicsInt32 *value)
- {
- int function = pasynUser->reason;
- int addr=0;
- asynStatus status = asynSuccess;
- const char *functionName = "readInt32";
-
- status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
- /* We just read the current value of the parameter from the parameter library.
- * Those values are updated whenever anything could cause them to change */
- status = (asynStatus) getIntegerParam(addr, function, value);
- if (status)
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s:%s: status=%d, function=%d, value=%d",
- driverName, functionName, status, function, *value);
- else
- asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
- "%s:%s: function=%d, value=%d\n",
- driverName, functionName, function, *value);
- return(status);
- }
- extern "C" {static asynStatus writeInt32(void *drvPvt, asynUser *pasynUser,
- epicsInt32 value)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
- asynStatus status;
-
- pPvt->lock();
- status = pPvt->writeInt32(pasynUser, value);
- pPvt->unlock();
- return(status);
- }}
- /** Called when asyn clients call pasynInt32->write().
- * The base class implementation simply sets the value in the parameter library and
- * calls any registered callbacks for this pasynUser->reason and address.
- * Derived classes will reimplement this function if they need to perform an action when an
- * asynInt32 value is written.
- * \param[in] pasynUser pasynUser structure that encodes the reason and address.
- * \param[in] value Value to write. */
- asynStatus asynPortDriver::writeInt32(asynUser *pasynUser, epicsInt32 value)
- {
- int function = pasynUser->reason;
- int addr=0;
- asynStatus status = asynSuccess;
- const char* functionName = "writeInt32";
- status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
- /* Set the parameter in the parameter library. */
- status = (asynStatus) setIntegerParam(addr, function, value);
- /* Do callbacks so higher layers see any changes */
- status = (asynStatus) callParamCallbacks(addr, addr);
-
- if (status)
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s:%s: status=%d, function=%d, value=%d",
- driverName, functionName, status, function, value);
- else
- asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
- "%s:%s: function=%d, value=%d\n",
- driverName, functionName, function, value);
- return status;
- }
- extern "C" {static asynStatus getBounds(void *drvPvt, asynUser *pasynUser,
- epicsInt32 *low, epicsInt32 *high)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
- asynStatus status;
-
- pPvt->lock();
- status = pPvt->getBounds(pasynUser, low, high);
- pPvt->unlock();
- return(status);
- }}
- /** Called when asyn clients call pasynInt32->getBounds(), returning the bounds on the asynInt32 interface
- * for drivers that use raw units.
- * Device support uses these values for unit conversion.
- * The base class implementation simply returns low=0, high=65535.
- * Derived classes can reimplement this function if they support raw units with different limits.
- * \param[in] pasynUser pasynUser structure that encodes the reason and address.
- * \param[out] low Address of the low limit.
- * \param[out] high Address of the high limit. */
- asynStatus asynPortDriver::getBounds(asynUser *pasynUser,
- epicsInt32 *low, epicsInt32 *high)
- {
- /* This is only needed for the asynInt32 interface when the device uses raw units.
- Our interface is using engineering units. */
- *low = 0;
- *high = 65535;
- asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
- "%s::getBounds,low=%d, high=%d\n",
- driverName, *low, *high);
- return(asynSuccess);
- }
- /* asynUInt32Digital interface methods */
- extern "C" {static asynStatus readUInt32Digital(void *drvPvt, asynUser *pasynUser,
- epicsUInt32 *value, epicsUInt32 mask)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
- asynStatus status;
-
- pPvt->lock();
- status = pPvt->readUInt32Digital(pasynUser, value, mask);
- pPvt->unlock();
- return(status);
- }}
- /** Called when asyn clients call pasynUInt32Digital->read().
- * The base class implementation simply returns the value from the parameter library.
- * Derived classes rarely need to reimplement this function.
- * \param[in] pasynUser pasynUser structure that encodes the reason and address.
- * \param[out] value Address of the value to read.
- * \param[in] mask Mask value to use when reading the value. */
- asynStatus asynPortDriver::readUInt32Digital(asynUser *pasynUser, epicsUInt32 *value, epicsUInt32 mask)
- {
- int function = pasynUser->reason;
- int addr=0;
- asynStatus status = asynSuccess;
- const char *functionName = "readUInt32Digital";
-
- status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
- /* We just read the current value of the parameter from the parameter library.
- * Those values are updated whenever anything could cause them to change */
- status = (asynStatus) getUIntDigitalParam(addr, function, value, mask);
- if (status)
- epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
- "%s:%s: status=%d, function=%d, value=%u mask=%u",
- driverName, functionName, status, function, *value, mask);
- else
- asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
- "%s:%s: function=%d, value=%u, mask=%u\n",
- driverName, functionName, function, *value, mask);
- return(status);
- }
- extern "C" {static asynStatus writeUInt32Digital(void *drvPvt, asynUser *pasynUser,
- epicsUInt32 value, epicsUInt32 mask)
- {
- asynPortDriver *pPvt = (asynPortDriver *)drvPvt;
- asynStatus status;
-
- …
Large files files are truncated, but you can click here to view the full file