#include "Brooks0254Set.hh" // unsigned long Brooks0254Set::bsSleepTime = 1000000; unsigned long Brooks0254Set::bsSleepTime = 100000; map > Brooks0254Set::bsDevMap; pthread_mutex_t Brooks0254Set::bsGlobMutex; pthread_mutexattr_t Brooks0254Set::bsGlobMtxAttr; pthread_cond_t Brooks0254Set::bsThrdStop; int Brooks0254Set::bsDummyInt = Brooks0254Set::InitGlobalMutex(); //! Start a new chassis instance from within a newly launched thread //! Then start a loop which never exits unless the ForcedExit //! flag is set void* Brooks0254Set::Thread( void* argPtr ) { Brooks0254ChassisID* chassID = (Brooks0254ChassisID*) argPtr; unsigned portID = chassID->id; string devName = chassID->dev; unsigned addr = chassID->addr; cout << "Brooks0254Set::Thread(): Chassis #" << setw(2) << portID << " starts its thread function" << endl; MtxLock globLock( bsGlobMutex ); Brooks0254Chassis* newChassis = 0; try { newChassis = new Brooks0254Chassis( portID, addr, devName ); } catch ( Brooks0254Port::FailedOpenPort& except ) { cerr << "Exception: " << except.msg << endl; //! Send signal that the chassis constructor was called. //! The IOC can continue on. pthread_cond_signal( &bsThrdStop ); return 0; } catch ( Brooks0254Port::FailedWritePort& err ) { cerr << "Exception: " << err.msg << endl; pthread_cond_signal( &bsThrdStop ); return 0; } catch ( Brooks0254Port::FailedReadPort& err ) { cerr << "Exception: " << err.msg << endl; pthread_cond_signal( &bsThrdStop ); return 0; } pair tmpPair( false, newChassis ); bsDevMap[portID] = tmpPair; //! Send signal that the chassis constructor was called. //! The IOC can continue on. pthread_cond_signal( &bsThrdStop ); globLock.Unlock(); cout << "Starting loop for chassis #" << portID << endl; //! Start the loop for the device which will not return for //! while until exit flag for the device is not raised Loop( portID ); globLock.Lock(); cout << "Removing device from the device map" << endl; bsDevMap.erase(portID); try { cout << "Will call chassis destructor" << endl; delete newChassis; } catch ( Brooks0254Port::FailedClosePort& except ) { cerr << except.msg << endl; return 0; } cout << "Exiting the thread for chassis #" << portID << endl; return 0; } //! Static method called from outside to start a new Brooks0254 device. //! It launches a new thread and exits int Brooks0254Set::StartDevice( unsigned portID, unsigned addr, const char* devName ) { MtxLock globLock( bsGlobMutex ); if( bsDevMap.find( portID ) != bsDevMap.end() ) { cerr << "Brooks0254Set::StartDevice(): Chassis #" << portID << " is already running " << endl; return(-1); } globLock.Unlock(); //! Create a description object for this chassis Brooks0254ChassisID* thMsg = new Brooks0254ChassisID( portID, devName, addr ); //! Start the thread for this chassis globLock.Lock(); pthread_t thID; int thStat = pthread_create( &thID, NULL, (void* (*)(void*))Brooks0254Set::Thread, (void*) thMsg); if ( thStat !=0 ) { cerr << "Brooks0254Set::StartDevice(): pthread_create(" << hex << showbase << thID << "[" << dec << portID << "],...) failure" << endl; return -1 ; } pthread_cond_wait( &bsThrdStop, &bsGlobMutex ); globLock.Unlock(); cout << "Brooks0254Set::StartDevice(): pthread_create(" << hex << showbase << thID << "[" << dec << portID << "],...) done." << endl; return 0; } //! Method to set forced exit flag to make the thread exit int Brooks0254Set::StopDevice( int portID ) { MtxLock globLock( bsGlobMutex ); if( bsDevMap.find( portID ) == bsDevMap.end() ) { cerr << "Brooks0254Set::StopDevice: Chassis #" << portID << " is not running " << endl; return(-1); } cout << "Setting Forced Exit Flag for chassis #" << portID << endl; bsDevMap[portID].first = true ; return 0; } // Method constantly looping until exit flag is not set void Brooks0254Set::Loop( unsigned portID ) { bool exitFlag = false; Brooks0254Chassis* chasPtr = 0; while( !exitFlag ) { usleep( Brooks0254Set::bsSleepTime ); //! Check the exit flag, and if it set, break out of the loop { MtxLock globLock( bsGlobMutex ); exitFlag = GetChassisFlag( portID ); chasPtr = GetChassisPtr( portID ); } //! Sync the chassis and all its subcomponents if( !exitFlag ) chasPtr->Sync(); } cout << "Exiting the loop for chassis #" << portID << endl; return; } //! Return pointer to chassis. If does not exist, return 0 Brooks0254Chassis* Brooks0254Set::GetChassisPtr( unsigned chassis ) { if( Brooks0254Set::bsDevMap.find( chassis ) == Brooks0254Set::bsDevMap.end() ) return 0; return bsDevMap[chassis].second; } //! Return pointer to chassis. If does not exist, return 0 bool Brooks0254Set::GetChassisFlag( unsigned chassis ) { if( Brooks0254Set::bsDevMap.find( chassis ) == Brooks0254Set::bsDevMap.end() ) return 0; return bsDevMap[chassis].first; } //! Initiliaze global mutex int Brooks0254Set::InitGlobalMutex() { pthread_mutexattr_init( &bsGlobMtxAttr ); pthread_mutexattr_setpshared( &bsGlobMtxAttr, PTHREAD_PROCESS_PRIVATE ); pthread_mutex_init( &bsGlobMutex, &bsGlobMtxAttr ); pthread_cond_init( &bsThrdStop, NULL ); return 0; } //! Interface with C to connect to EPICS device support extern "C" { #include "Brooks0254Set.h" int brooksGetCommStatus( unsigned chassis, int* val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } *val = chasPtr->GetCommStatus(); return 0; } //! Soft Reset Communication port on the driver side int brooksResetCommPort( unsigned chassis ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254Port* portPtr = chasPtr->GetPort(); if( portPtr == 0 ) return -20; portPtr->Reset(); return 0; } /*! Set batch mode */ int brooksSetBatchMode( unsigned chassis, int mode ) { Brooks0254Port::bpDebFlag = 10; Brooks0254Module::bmDebFlag = 10; MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } chasPtr->SetBatchMode( mode ); usleep( 200000 ); Brooks0254Module::bmDebFlag = 0; Brooks0254Port::bpDebFlag = 0; return 0; } int brooksGetParBool( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, int* val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; return -20; } *val = static_cast( parPtr->GetReadValue() ); return 0; } int brooksGetParInt( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, int* val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; return -20; } *val = parPtr->GetReadValue(); return 0; } int brooksGetParDouble( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, double* val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; return -20; } *val = parPtr->GetReadValue(); return 0; } int brooksGetGlobPar( unsigned chassis, unsigned parNum, int* val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( Brooks0254ParID::bpiGlobal, parNum ); Brooks0254GlobPar* parPtr = dynamic_cast*> ( chasPtr->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find global parameter " << parNum << endl; return -20; } *val = static_cast( parPtr->GetReadValue() ); return 0; } int brooksSetParBool( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, int val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; return -20; } parPtr->SetWriteValue( static_cast( val ) ); return 0; } int brooksSetParInt( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, int val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; return -20; } parPtr->SetWriteValue( val ); return 0; } int brooksSetParDouble( unsigned chassis, unsigned card, unsigned portType, unsigned parNum, double val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( static_cast(portType), parNum ); Brooks0254Par* parPtr = dynamic_cast*> ( chasPtr->GetCard( card )->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find parameter " << parNum << " for card #" << card << " on port type " << portType << endl; cout << "Will continue" << endl; } parPtr->SetWriteValue( val ); return 0; } int brooksSetGlobPar( unsigned chassis, unsigned parNum, int val ) { MtxLock globLock( Brooks0254Set::bsGlobMutex ); Brooks0254Chassis* chasPtr = Brooks0254Set::GetChassisPtr( chassis ); if( chasPtr == 0 ) { cerr << "Chassis #" << chassis << " could not be found" << endl; return -10; } Brooks0254ParID parID( Brooks0254ParID::bpiGlobal, parNum ); Brooks0254GlobPar* parPtr = dynamic_cast*> ( chasPtr->GetPar( parID ) ); if( parPtr == 0 ) { cerr << "Chassis #" << chassis << " could not find global parameter " << parNum << endl; return -20; } parPtr->SetWriteValue( static_cast( val ) ); return 0; } };