/* * chassisAsynPar.hh * * Created on: February 09, 2015 * Author: Hovanes Egiyan * * This file defines an augmenting class for asynDrvChassis to keep track of asyn parameters. * Some of the methods of this class expect to receive the pointer of the asynDrvChassis object * for which the parameter instance is used for. So, this class is very much tied to the * asynDrvChassis class and should not be considered as "an" independent class, these objects expect * to be members of asynDrvChassis class object. */ #ifndef __CHASSIS_ASYNPAR_HH__ #define __CHASSIS_ASYNPAR_HH__ /************/ /* Includes */ /************/ #include #include #include #include #include #include /* EPICS includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "new" #include "asynDrvChassis.hh" #include "MtxLock.hh" #include "MutexedClass.hh" #include "chassisVAsynPar.hh" // Template class for asyn parameters. For different parameters types we will // use specialized methods for particular variable types. This class inherits // from the virtual base class. template class chassisAsynPar: public chassisVAsynPar { protected: VarType capValue; // Parameter value public: // Default constructor chassisAsynPar() : capValue() { return;} // Main constructor chassisAsynPar(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); virtual ~chassisAsynPar() { return; } // Copy constructor chassisAsynPar(const chassisAsynPar& par); // Copy operator virtual chassisAsynPar& operator=( const chassisAsynPar& argPar); // Method to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor virtual void Connect2Driver(asynDrvChassis* driver); virtual asynStatus Write(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Virtual Write asyn parameter virtual asynStatus Read(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32* mask = 0); // Virtual Read asyn parameter virtual asynStatus WriteTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Write asyn parameter virtual asynStatus ReadTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32* mask = 0); // Read asyn parameter inline VarType GetValue(); inline VarType SetValue(const VarType value); }; // Template class for asyn unsigned parameters. This class inherits // from the double-template class base class and is a partial specialization for epicsUInt32. template class chassisAsynParUInt32 : public chassisAsynPar { public: chassisAsynParUInt32(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Method to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor virtual void Connect2Driver(asynDrvChassis* driver); // virtual asynStatus Write(asynDrvChassis* driver, void* valPtr = // 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Virtual Write asyn parameter // virtual asynStatus Read(asynDrvChassis* driver, // void* valPtr = 0, epicsUInt32* mask = 0); // Virtual Read asyn parameter virtual asynStatus WriteTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Write asyn parameter virtual asynStatus ReadTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32* mask = 0); // Read asyn parameter }; // Template class for asyn string(octet) parameters. This class inherits // from the double-template class base class and is a partial specialization for string parameters. template class chassisAsynParString : public chassisAsynPar { public: chassisAsynParString(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Method to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor virtual void Connect2Driver(asynDrvChassis* driver); // virtual asynStatus Write(asynDrvChassis* driver, void* valPtr = // 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Virtual Write asyn parameter // virtual asynStatus Read(asynDrvChassis* driver, // void* valPtr = 0, epicsUInt32* mask = 0); // Virtual Read asyn parameter virtual asynStatus WriteTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32 mask = chassisVAsynPar::cvapAllBitMask); // Write asyn parameter virtual asynStatus ReadTmpl(asynDrvChassis* driver, void* valPtr = 0, epicsUInt32* mask = 0); // Read asyn parameter }; //======================================================================== // Implementation for double template class chassisAsynPar //======================================================================== // Main constructor template chassisAsynPar::chassisAsynPar(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask) : chassisVAsynPar(parName, parNum, readFun, writeFun, mask), capValue() { cout << "Created chassisAsynPar " << this->GetName() << endl; return; } // Copy constructor template chassisAsynPar::chassisAsynPar( const chassisAsynPar& par) : chassisVAsynPar(par), capValue(par.GetValue()) { return; } // Method to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor template void chassisAsynPar::Connect2Driver( asynDrvChassis* driver) { throw std::runtime_error("chassisAsynPar: Must use a specialized Connect2Driver method"); } template asynStatus chassisAsynPar::Write( asynDrvChassis* driver, void* valPtr, epicsUInt32 mask) // Virtual Write asyn parameter { return this->WriteTmpl(driver, valPtr, mask); } template asynStatus chassisAsynPar::Read( asynDrvChassis* driver, void* valPtr, epicsUInt32* mask) // Virtual Read asyn parameter { return this->ReadTmpl(driver, valPtr, mask); } template asynStatus chassisAsynPar::WriteTmpl( asynDrvChassis* driver, void* valPtr, epicsUInt32 mask) // Write asyn parameter { throw std::runtime_error("chassisAsynPar: Must use a specialized Write method"); } template asynStatus chassisAsynPar::ReadTmpl( asynDrvChassis* driver, void* valPtr, epicsUInt32* mask) // Read asyn parameter { throw std::runtime_error("chassisAsynPar: Must use a specialized Read method"); } template chassisAsynPar& chassisAsynPar::operator=( const chassisAsynPar& argPar) { chassisAsynPar& par = const_cast&>(argPar); chassisVAsynPar* baseClassPtr = dynamic_cast*>(this); baseClassPtr->operator=(par); MtxLock selfObjLock(this->mcMutex); MtxLock otherObjLock(par.mcMutex); capValue = par.capValue; return *this; } template inline VarType chassisAsynPar::GetValue() { MtxLock objLock(this->mcMutex); return capValue; } template inline VarType chassisAsynPar::SetValue( const VarType value) { MtxLock objLock(this->mcMutex); return (capValue = value); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Below are the implementation of partially specialized classes ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //========================================================================================================== // Specialized for string type parameters //========================================================================================================== template chassisAsynParUInt32::chassisAsynParUInt32(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask ) : chassisAsynPar( parName, parNum, readFun, writeFun, mask ) { return;} // Specialized method for UInt32 to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor template void chassisAsynParUInt32::Connect2Driver( asynDrvChassis* driver ) { // cout << "Inside chassisAsynPar::Connect2Driver" << endl; MtxLock objLock(this->mcMutex); driver->createParam( this->cvapParName.c_str(), asynParamUInt32Digital, &this->cvapParNum ) ; return; } // Specialized for UInt32 method to write asyn parameter template asynStatus chassisAsynParUInt32::WriteTmpl( asynDrvChassis* driver, void* valPtr, epicsUInt32 mask ) { // cout << "Inside chassisAsynParUInt32>::WriteTmpl" << endl; vmeChassis* chassis = driver->getChassis(); MtxLock objLock(this->mcMutex); if( this->cvapWriteFun != 0 ) { asynStatus aStat = asynError; epicsUInt32 value = *static_cast( valPtr ); cout << "Setting UInt32 parameter " << this->cvapParName << " to " << value << endl; ( (*chassis).*(this->cvapWriteFun) ) ( value ); aStat = driver->setUIntDigitalParam( this->cvapParNum, value, mask, mask ); return aStat; } else { char parName[128]; driver->getParamName( this->cvapParNum, (const char**)&parName ); stringstream ssMessage; ssMessage << "From chassisAsynParUIn32::WriteTmpl " << endl; ssMessage << "Zero pointer to write function for parameter " << parName << " for port " << driver->getPortName(); throw std::runtime_error( ssMessage.str() ); } return asynError; } // Specialized for UInt32 to read asyn parameter template asynStatus chassisAsynParUInt32::ReadTmpl(asynDrvChassis* driver, void* valPtr, epicsUInt32* mask) { // cout << "Inside chassisAsynPar::ReadTmpl" << endl; vmeChassis* chassis = driver->getChassis(); MtxLock objLock(this->mcMutex); // If pointer is set to zero and the control got here, throw an exception if( this->cvapReadFun == 0 ) { char parName[128]; driver->getParamName( this->cvapParNum, (const char**)&parName ); stringstream ssMessage; ssMessage << "From chassisAsynPar::ReadTmpl " << endl; ssMessage << "Zero pointer to read function for parameter " << parName << " for port " << driver->getPortName(); throw std::runtime_error( ssMessage.str() ); } else { asynStatus aStat = asynError; // cout << "Calling read function for parameter " << cvapParName << endl; this->capValue = ((*chassis).*(this->cvapReadFun))(); aStat = driver->setUIntDigitalParam(this->cvapParNum, this->capValue, *mask, *mask); *(static_cast(valPtr)) = this->capValue; return aStat; } return asynError; } //========================================================================================================== // Specialized for string type parameters //========================================================================================================== template chassisAsynParString::chassisAsynParString(string parName, int parNum, typename chassisVAsynPar::cvapRdPtr readFun, typename chassisVAsynPar::cvapWtPtr writeFun, epicsUInt32 mask ) : chassisAsynPar( parName, parNum, readFun, writeFun, mask ) { return;} // Specialized method for UInt32 to create the parameter for the driver passed by the argument. // This method is expected to be called from the AsynDriver constructor template void chassisAsynParString::Connect2Driver( asynDrvChassis* driver ) { // cout << "Inside chassisAsynPar::Connect2Driver" << endl; MtxLock objLock(this->mcMutex); driver->createParam( this->cvapParName.c_str(), asynParamOctet, &this->cvapParNum ) ; return; } // Specialized for UInt32 method to write asyn parameter template asynStatus chassisAsynParString::WriteTmpl( asynDrvChassis* driver, void* valPtr, epicsUInt32 mask ) { // cout << "Inside chassisAsynPar::WriteTmpl" << endl; vmeChassis* chassis = driver->getChassis(); MtxLock objLock(this->mcMutex); if( this->cvapWriteFun != 0 ) { asynStatus aStat = asynError; string value = *static_cast( valPtr ); cout << "Setting string parameter " << this->cvapParName << " to " << value << endl; // Since the pointers for the read/write functions in the base class were defined for unsigned int // we need to cast it to string type here. typedef string (vmeChassis::*stringWrtPtrType)(string); stringWrtPtrType writePtrForString = reinterpret_cast(this->cvapWriteFun); ( (*chassis).*writePtrForString ) ( value ); aStat = driver->setStringParam( this->cvapParNum, value.c_str() ); return aStat; } else { char parName[128]; driver->getParamName( this->cvapParNum, (const char**)&parName ); stringstream ssMessage; ssMessage << "From chassisAsynPar::WriteTmpl " << endl; ssMessage << "Zero pointer to write function for parameter " << parName << " for port " << driver->getPortName(); throw std::runtime_error( ssMessage.str() ); } return asynError; } // Specialized for string to read asyn parameter template asynStatus chassisAsynParString::ReadTmpl(asynDrvChassis* driver, void* valPtr, epicsUInt32* mask) { // cout << "Inside chassisAsynPar::ReadTmpl" << endl; vmeChassis* chassis = driver->getChassis(); MtxLock objLock(this->mcMutex); if (this->cvapReadFun != 0) { asynStatus aStat = asynError; // cout << "Calling read function for parameter " << cvapParName << endl; // Since the pointers for the read/write functions in the base class were defined for unsigned int // we need to cast it to string type here. typedef string (vmeChassis::*stringReadPtrType)(); stringReadPtrType ReadPtrForString = reinterpret_cast(this->cvapReadFun); this->capValue = ((*chassis).*ReadPtrForString)(); aStat = driver->setStringParam(this->cvapParNum, this->capValue.c_str() ); // Do not write into the value field since it may be a pointer to non-string memory area. // Writing into this are is usually not used. string* tmpString = new( valPtr ) string; *tmpString = this->capValue; // cout << "Returning " << capValue << " in the buffer " << endl; return aStat; } else { char parName[128]; driver->getParamName( this->cvapParNum, (const char**)&parName ); stringstream ssMessage; ssMessage << "From chassisAsynPar::ReadTmpl " << endl; ssMessage << "Zero pointer to read function for parameter " << parName << " for port " << driver->getPortName(); throw std::runtime_error( ssMessage.str() ); } return asynError; } #endif /* __CHASSIS_ASYNPAR_HH__ */