From: <ro...@us...> - 2008-07-17 13:57:44
|
Revision: 1918 http://nscldaq.svn.sourceforge.net/nscldaq/?rev=1918&view=rev Author: ron-fox Date: 2008-07-17 13:56:13 +0000 (Thu, 17 Jul 2008) Log Message: ----------- Get a bunch of device independent stuff working for the USB readout skeletons. Modified Paths: -------------- trunk/nextgen/base/thread/Synchronizable.h trunk/nextgen/base/thread/dshwrappthreads.h trunk/nextgen/base/thread/dshwrapthreads.h trunk/nextgen/configure.in trunk/nextgen/usb/Makefile.am trunk/nextgen/usb/threadcom/Makefile.am Added Paths: ----------- trunk/nextgen/CRunState.cpp trunk/nextgen/usb/output/COutputThread.cpp trunk/nextgen/usb/output/COutputThread.h trunk/nextgen/usb/output/DataBuffer.cpp trunk/nextgen/usb/output/DataBuffer.h trunk/nextgen/usb/output/Makefile.am trunk/nextgen/usb/tclserver/CControlModule.cpp trunk/nextgen/usb/tclserver/CControlModule.h trunk/nextgen/usb/tclserver/CGetCommand.cpp trunk/nextgen/usb/tclserver/CGetCommand.h trunk/nextgen/usb/tclserver/CModuleCommand.cpp trunk/nextgen/usb/tclserver/CModuleCommand.h trunk/nextgen/usb/tclserver/CSetCommand.cpp trunk/nextgen/usb/tclserver/CSetCommand.h trunk/nextgen/usb/tclserver/CUpdateCommand.cpp trunk/nextgen/usb/tclserver/CUpdateCommand.h trunk/nextgen/usb/tclserver/Makefile.am trunk/nextgen/usb/tclserver/Server.cpp trunk/nextgen/usb/tclserver/TclServer.cpp trunk/nextgen/usb/tclserver/TclServer.h trunk/nextgen/usb/tclserver/server.h trunk/nextgen/usb/tclserver/serverinstance.cpp trunk/nextgen/usb/tclserver/serverinstance.h trunk/nextgen/usb/threadcom/CControlQueues.cpp trunk/nextgen/usb/threadcom/CControlQueues.h trunk/nextgen/usb/threadcom/CRunState.cpp trunk/nextgen/usb/threadcom/CRunState.h Added: trunk/nextgen/CRunState.cpp =================================================================== --- trunk/nextgen/CRunState.cpp (rev 0) +++ trunk/nextgen/CRunState.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,158 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +#include "CRunState.h" + +using namespace std; + +// Class level member data: + +CRunState* CRunState::m_pTheInstance(0); + +/*! + Construction For now the default initial state is: + - Title == "Change this title" + - Run NUmber 0 + - State idle. + + \note as befits a singleton pattern, this constructor is private! +*/ +CRunState::CRunState() : + m_title("Change this title"), + m_runNumber(0), + m_state(CRunState::Idle) +{ + m_pTheInstance = this; +} +/*! + Destructor does nothing and, in general should not get called. +*/ +CRunState::~CRunState() +{ +} + +/*! + Get singleton instance: + */ +CRunState* +CRunState::getInstance() +{ + if(!m_pTheInstance) { + m_pTheInstance = new CRunState; + } + return m_pTheInstance; +} + +/*! + Select the currenst state: + \return RunState + \retval current run state value. +*/ +CRunState::RunState +CRunState::getState() +{ + Enter(); + RunState state = m_state; + Leave(); + return state; +} +/*! + Set a new value for the run statel + \param newState : CRunState::RunState + New runstate can be one of CRunState::Idle or CRunState::Active +*/ +void +CRunState::setState(CRunState::RunState state) +{ + Enter(); + m_state = state; + Leave(); +} +/*! + Get the current title. + \return std::string + \retval String containing the run title. +*/ +string +CRunState::getTitle() +{ + Enter(); + string title = m_title; + Leave(); + return title; +} +/*! + Set a new value for the title: + \param newTitle :: std::string + New title string. +*/ +void +CRunState::setTitle(string newTitle) +{ + Enter(); + m_title = newTitle; + Leave(); +} + +/*! + Get the current run number. + \return uint16_t + \retval The current run number. +*/ +uint16_t +CRunState::getRunNumber() +{ + Enter(); + uint16_t run = m_runNumber; + Leave(); + return run; +} +/*! + Set a new run number value: + \param newRunNumber : uint16_t + New value for the run number. +*/ +void +CRunState::setRunNumber(uint16_t newRunNumber) +{ + Enter(); + m_runNumber = newRunNumber; + Leave(); + +} +/*! + Get the number of seconds between scaler readouts: +*/ +uint32_t +CRunState::getScalerPeriod() +{ + uint32_t value; + Enter(); + value = m_scalerPeriod; + Leave(); + return value; +} +/*! + Set the number of seconds between scaler readouts. +*/ +void +CRunState::setScalerPeriod(uint32_t period) +{ + Enter(); + m_scalerPeriod = period; + Leave(); +} Modified: trunk/nextgen/base/thread/Synchronizable.h =================================================================== --- trunk/nextgen/base/thread/Synchronizable.h 2008-07-17 13:46:58 UTC (rev 1917) +++ trunk/nextgen/base/thread/Synchronizable.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -18,9 +18,7 @@ #include <iostream> #include <sstream> -#ifndef DSHWRAPTHREADS_H #include <dshwrapthreads.h> -#endif // forward class references. Modified: trunk/nextgen/base/thread/dshwrappthreads.h =================================================================== --- trunk/nextgen/base/thread/dshwrappthreads.h 2008-07-17 13:46:58 UTC (rev 1917) +++ trunk/nextgen/base/thread/dshwrappthreads.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -12,10 +12,10 @@ -#ifdef USE_PTHREADS + #include <stdlib.h> #include <stdio.h> #include <signal.h> @@ -73,6 +73,6 @@ // How do we display this thing? char *dshwrappthread_tostr(char*,int,dshwrapthread_t); -#endif + #endif Modified: trunk/nextgen/base/thread/dshwrapthreads.h =================================================================== --- trunk/nextgen/base/thread/dshwrapthreads.h 2008-07-17 13:46:58 UTC (rev 1917) +++ trunk/nextgen/base/thread/dshwrapthreads.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -19,7 +19,6 @@ #include <unistd.h> #include <errno.h> -#ifdef USE_PTHREADS #include <dshwrappthreads.h> #define dshwrapthread_create dshwrappthread_create #define dshwrapthread_exit dshwrappthread_exit @@ -39,6 +38,6 @@ #define dshwrapthread_cond_timedwait dshwrappthread_cond_timedwait #define dshwrapthread_tostr dshwrappthread_tostr #define dshwrapthread_mutex_lastmod dshwrappthread_mutex_lastmod -#endif /* USE_PTHREADS */ + #endif Modified: trunk/nextgen/configure.in =================================================================== --- trunk/nextgen/configure.in 2008-07-17 13:46:58 UTC (rev 1917) +++ trunk/nextgen/configure.in 2008-07-17 13:56:13 UTC (rev 1918) @@ -382,6 +382,9 @@ daq/format/Makefile usb/Makefile usb/threadcom/Makefile + usb/tclcommon/Makefile + usb/tclserver/Makefile + usb/output/Makefile docbuild/Makefile docconfig/Makefile]) Modified: trunk/nextgen/usb/Makefile.am =================================================================== --- trunk/nextgen/usb/Makefile.am 2008-07-17 13:46:58 UTC (rev 1917) +++ trunk/nextgen/usb/Makefile.am 2008-07-17 13:56:13 UTC (rev 1918) @@ -2,4 +2,4 @@ # Builds the VM/CC usb software. It's important to build the common # code first: # -SUBDIRS = threadcom \ No newline at end of file +SUBDIRS = threadcom tclcommon tclserver output \ No newline at end of file Added: trunk/nextgen/usb/output/COutputThread.cpp =================================================================== --- trunk/nextgen/usb/output/COutputThread.cpp (rev 0) +++ trunk/nextgen/usb/output/COutputThread.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,307 @@ + + +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +#include "COutputThread.h" +#include "CRunState.h" +#include "DataBuffer.h" +#include <string> +#include <Exception.h> + + +#include <assert.h> +#include <buftypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <iostream> +#include <CRingBuffer.h> +#include <CRingItem.h> +#include <CRingPhysicsEventCountItem.h> +#include <CRingScalerItem.h> +#include <CRingStateChangeItem.h> +#include <DataFormat.h> + + +#include <unistd.h> +#include <pwd.h> +#include <sys/types.h> + + + +using namespace std; + +static DataBuffer* lastBuffer(0); +static const unsigned ReadoutStack(0); +static const unsigned ScalerStack(1); + + +//////////////////////////////////////////////////////////////////////// +///////////////////// Construction and destruction ///////////////////// +//////////////////////////////////////////////////////////////////////// + +/*! + Create an outupt thread. Should only create 1 however if the + following were parameters could create multiple: + - Event buffer queue. + - Free buffer queue. + - Run state. + - Open the ring. + + In future applications this could be done to manage multiple VM-USB + controlled VME crates in 'singles mode'... or with a subsequent chunk of + software on the end of spectrodaq assembling data. + +*/ +COutputThread::COutputThread() : + m_pRing(0) +{ + openRing(); // Open ring named after the user in localhost. + // the ring is created if necessary. +} +/*! + Disconnect from the ring. +*/ +COutputThread::~COutputThread() +{ + delete m_pRing; +} + +//////////////////////////////////////////////////////////////////////// +////////////////////// Thread entry point... /////////////////////////// +//////////////////////////////////////////////////////////////////////// + +/* + Thread entry point. This is just an infinite buffer processing loop. +*/ +void +COutputThread::run() +{ + // Main loop is pretty simple. + try { + while(1) { + + DataBuffer& buffer(getBuffer()); + processBuffer(buffer); + freeBuffer(buffer); + + } + + } + catch (string msg) { + cerr << "COutput thread caught a string exception: " << msg << endl; + throw; + } + catch (char* msg) { + cerr << "COutput thread caught a char* exception: " << msg << endl; + throw; + } + catch (CException& err) { + cerr << "COutputThread thread caught a daq exception: " + << err.ReasonText() << " while " << err.WasDoing() << endl; + throw; + } + catch (...) { + cerr << "COutput thread caught some other exception type.\n"; + throw; + } + +} + + +/* + Get a buffer from the event queue. A reference to the buffer will + be returned. + + Note that this will block if needed to wait for a buffer. + note as well that between runs, we'll wind up blocking in here. + +*/ +DataBuffer& +COutputThread::getBuffer() +{ + DataBuffer* pBuffer = gFilledBuffers.get(); // Will block if needed. + return *pBuffer; + +} +/* + Free a buffer that has been completely processed. + This will return the buffer to the gFreeBuffers queue. + Parameters: + DataBuffer& buffer - Reference to the buffer to return. + +*/ +void +COutputThread::freeBuffer(DataBuffer& buffer) +{ + gFreeBuffers.queue(&buffer); +} +/* + Process a buffer from the reader. At this time we are just going + to figure out what type of buffer we have and dispatch accordingly. + Buffers are as follows: + Begin run is indicated by the type in the DataBuffer, all others look like + data buffers. + End run is indicated by the last bit set in the vmusb header. + scaler is indicated by the scaler bit in the vm usb header. + All others are event data. + Parameters: + DataBuffer& buffer - The buffer from the readout thread. +*/ +void +COutputThread::processBuffer(DataBuffer& buffer) +{ + if (buffer.s_bufferType == 1) { + startRun(buffer.s_timeStamp); + } + else if (buffer.s_bufferType == 2) { + endRun(buffer.s_timeStamp); + } + else { + processUSBData(buffer); // will callback. + } +} + + +/* + Create a begin run item on behalf of the concrete subclass/thread. + \param when - Time the run began. + \note Much of the information about the run is implicit input from the + runstat object. +*/ +void +COutputThread::startRun(time_t when) +{ + // Update our concept of run state, and buffer size: + + CRunState* pState = CRunState::getInstance(); + m_runNumber = pState->getRunNumber(); + m_title = pState->getTitle(); + m_startTimestamp = when; + m_lastStampedBuffer = 0; + m_eventCount = 0; + + CRingStateChangeItem item(BEGIN_RUN, + m_runNumber, + 0, + when, + m_title); + item.commitToRing(*m_pRing); + + +} +/* + Called to emit an end run item for the + caller. + \param when - timestamp of the end run. +*/ +void +COutputThread::endRun(time_t when) +{ + + CRingStateChangeItem item(END_RUN, + m_runNumber, + when - m_startTimestamp, + when, + m_title); + item.commitToRing(*m_pRing); + +} + +/* + Create a scaler item for the caller. + \param when - Absolute time the scaler buffer is being emitted. + \param number- Number of scalers in the item. + \param pScalers - Pointer to the scalers. + +*/ +void +COutputThread::scaler(time_t when, int number, uint32_t* pScalers) +{ + + uint32_t startTime = m_lastStampedBuffer; + uint32_t endTime = when; + m_lastStampedBuffer= when; + + CRingScalerItem item(number); + item.setStartTime(startTime); + item.setEndTime(endTime); + item.setTimestamp(when); + for (int i = 0; i < number; i++) { + item.setScaler(i, *pScalers++); + } + item.commitToRing(*m_pRing); + +} +/*! + Create an event item. + \param size - number of uint16_t's in the event. + \param pData- Pointer to the data words. + +*/ + +void +COutputThread::event(uint32_t size, void* pData) +{ + uint32_t bytes = size*sizeof(uint16_t); + CRingItem item(PHYSICS_EVENT, bytes); + + uint8_t* pDest = reinterpret_cast<uint8_t*>(item.getBodyCursor()); + memcpy(pDest, pData, bytes); + + pDest += bytes; + item.setBodyCursor(pDest); + + item.commitToRing(*m_pRing); + + m_eventCount++; +} +/*! + Produce an event count item on behalf of the client. + We've been maintaining a count of the events in a run for the caller. + \param when -tim3 when this should be emitted. + +*/ +void +COutputThread::eventCount(time_t when) +{ + CRingPhysicsEventCountItem item(m_eventCount, + when - m_startTimestamp, + when); + item.commitToRing(*m_pRing); + +} + +////////////////////////////////////////////////////////////////////////////////// +// +// Utilities. +// + +/* +** Open the ring. The ring name is just the user name. +*/ +void +COutputThread::openRing() +{ + uid_t uid = getuid(); + passwd* pPass = getpwuid(uid); + string name(pPass->pw_name); + + m_pRing = new CRingBuffer(name, CRingBuffer::producer); +} Added: trunk/nextgen/usb/output/COutputThread.h =================================================================== --- trunk/nextgen/usb/output/COutputThread.h (rev 0) +++ trunk/nextgen/usb/output/COutputThread.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,149 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __COUTPUTTHREAD_H +#define __COUTPUTTHREAD_H + +#ifndef __THREAD_H +#include <Thread.h> +#endif + +#ifndef __CRT_STDINT_H +#include <stdint.h> +#ifndef __CRT_STDINT_H +#define __CRT_STDINT_H +#endif +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + +// Forward definitions: + +struct DataBuffer; +class CRingBuffer; +/*! + This class bridges the gap between the buffer format of the + USB devices and ring buffers. + + The data + we are using will come from a buffer queue. Elements + of the buffer queue will have the following format: + +\verbatim + +--------------------------------+ + | Buffer size | + +--------------------------------+ + | Buffer Type | + +--------------------------------+ + | Time stamp | + +--------------------------------+ + | Buffer contents as gotten | + | from the device, see the | + | manual | + +- - - - - - -- - - - - - - - - -+ + +\endverbatim + + -# Buffer size is gotten from the read from the device + and indicates the number of bytes of data + in the body and its header word (does not include either itself nor + the buffer type. + -# The buffer type is one of the following: + - 1 Run starting... in this case there will be no VM-USB body. + - 2 USB data note that run end is determined by seeing the + last buffer indicator in the buffer. + -# We will generate only the following sorts of NSCL data buffers: + - 11 Begin run. + - 12 End Run + - 1 Physics data + - 2 Scaler Data. + -# Time stamp is result of time(2) when the buffer was received from + the VMUSB. + + \note This class is a separate thread of execution. + \note This is an abstract base class that captures the common elements + of the output thread for the CC and VM usb devices. + \note A global variable: gFilledBuffers is a CBufferQueue that contains + the data shown above and is used to receive raw data buffers from + the readout thread. + \note There is no need to start/stop thread each run. Once a run is over, + this thread will simply block on the buffer queue until the next run + emits the begin run buffer. +*/ + +class COutputThread : public Thread +{ + // Thread local data: +private: + // These are fetched from the CRun state at start of run. + + uint32_t m_runNumber; // Run number; + std::string m_title; // Run title + + // other data: +private: + time_t m_startTimestamp; //!< Run start time. + time_t m_lastStampedBuffer; //!< Seconds into run of last stamped buffer + uint64_t m_eventCount; //!< Number of events this run. + CRingBuffer* m_pRing; // Where the data goes.. + + // Constuctors and other canonicals. + +public: + COutputThread(); + virtual ~COutputThread(); +private: + COutputThread(const COutputThread& rhs); + COutputThread& operator=(const COutputThread& rhs); + int operator==(const COutputThread& rhs) const; + int operator!=(const COutputThread& rhs) const; +public: + + // Thread operations are all non-public in fact.. don't want to call them + // from outside this class.. only from within the thread.. This includes the + // thread entry point. + +protected: + + virtual void run(); + + DataBuffer& getBuffer(); + void freeBuffer(DataBuffer& buffer); + + void processBuffer(DataBuffer& buffer); + virtual void processUSBData(DataBuffer& buffer); + + void startRun(time_t when); + void endRun(time_t when); + void scaler(time_t when, + int number, + uint32_t* pScalers); + void event(uint32_t size, + void* pData); + void eventCount(time_t when); + + +private: + void openRing(); + +}; + +#endif Added: trunk/nextgen/usb/output/DataBuffer.cpp =================================================================== --- trunk/nextgen/usb/output/DataBuffer.cpp (rev 0) +++ trunk/nextgen/usb/output/DataBuffer.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,61 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + + + +// This file contains the two buffer queues for event data and +// unbound functions that create and destroy event data buffers. +// + +#include <config.h> + +#include "DataBuffer.h" +#include <stdlib.h> +#include <unistd.h> + + +// Buffer queues that communicate between the readout and routing threads: + +CBufferQueue<DataBuffer*> gFilledBuffers; +CBufferQueue<DataBuffer*> gFreeBuffers; + +/*! + Create a new data buffer. + \param bodySize - Number of 16 bit words in the body. + + \return DataBuffer* + \retval A pointer to the newly created data buffer. It is up to the caller + to decide what to do with it (e.g. we don't insert it into the + gFreeBuffers queue +*/ + +DataBuffer* +createDataBuffer(uint32_t bodySize) +{ + size_t bytes = sizeof(struct DataBuffer) + (bodySize-1)*sizeof(uint16_t); + DataBuffer* p = static_cast<DataBuffer*>(malloc(bytes)); + p->s_storageSize = bodySize; + return p; +} +/*! + Free storage that was allocated by a data buffer. It would be a very bad + thing if this data buffer were in one of the buffer queues when destroyed! +*/ +void +destroyDataBuffer(DataBuffer* pBuffer) +{ + free(pBuffer); +} Added: trunk/nextgen/usb/output/DataBuffer.h =================================================================== --- trunk/nextgen/usb/output/DataBuffer.h (rev 0) +++ trunk/nextgen/usb/output/DataBuffer.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,73 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ +#ifndef __CRT_STDINT_H +#include <stdint.h> +#ifndef __CRT_STDINT_H +#define __CRT_STDINT_H +#endif +#endif + +#ifndef __CRT_UNISTD_H +#include <unistd.h> +#ifndef __CRT_UNISTD_H +#define __CRT_UNISTD_H +#endif +#endif + +#ifndef __CRT_TIME_H +#include <time.h> +#ifndef __CRT_TIME_H +#define __CRT_TIME_H +#endif +#endif + +#ifndef __CBUFFERQUEUE_h +#include <CBufferQueue.h> +#endif + +/*! + \file DataBuffer + Defines the structure of data buffers that will be + passed around from readout thread to output thread. + These are managed in two buffer queues.: + gFilledBuffers is the queue of buffers with data and + gFreeBuffers is a queue of empty buffers available for + use by the readout thread. +*/ +struct DataBuffer { + uint32_t s_bufferSize; //!< Bytes used in the buffer. + uint32_t s_storageSize; //!< bytes in s_rawData[]. + uint32_t s_bufferType; //!< Type of buffer. + time_t s_timeStamp; //!< When the buffer was received. + uint16_t s_rawData[1]; //!< Really larger than that + +}; + + +extern CBufferQueue<DataBuffer*> gFilledBuffers; +extern CBufferQueue<DataBuffer*> gFreeBuffers; + +// A couple of useful unbound functions: + +extern DataBuffer* createDataBuffer(uint32_t bodySize); //!< Create a new data buffer. +extern void destroyDataBuffer(DataBuffer* pBuffer); //!< Free data buffer. + + +// Buffer types; + +static const int TYPE_START(1); +static const int TYPE_STOP(2); +static const int TYPE_EVENTS(3); Added: trunk/nextgen/usb/output/Makefile.am =================================================================== --- trunk/nextgen/usb/output/Makefile.am (rev 0) +++ trunk/nextgen/usb/output/Makefile.am 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,21 @@ +lib_LTLIBRARIES = libOutputStage.la + +libOutputStage_la_SOURCES = DataBuffer.cpp \ + COutputThread.cpp + +noinst_HEADERS = DataBuffer.h \ + COutputThread.h + + +INCLUDES = -I@top_srcdir@/daq/format \ + -I@top_srcdir@/base/dataflow \ + -I@top_srcdir@/base/exception \ + -I@top_srcdir@/base/headers \ + -I@top_srcdir@/base/thread \ + -I@top_srcdir@/usb/threadcom + +libOutputStage_la_LIBADD = @top_srcdir@/daq/format/libdataformat.la \ + @top_srcdir@/base/dataflow/libDataFlow.la \ + @top_srcdir@/base/exception/libException.la \ + @top_srcdir@/base/thread/libdaqthreads.la \ + @top_srcdir@/usb/threadcom/libThreadComm.la \ No newline at end of file Added: trunk/nextgen/usb/tclserver/CControlModule.cpp =================================================================== --- trunk/nextgen/usb/tclserver/CControlModule.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/CControlModule.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,82 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +#include "CControlModule.h" +#include <CRunState.h> +#include <CControlQueues.h> + +using namespace std; + +//////////////////////////////////////////////////////////////////////////////////// +// +// Constructors and canonicals. +// + +/*! + Constructing a module is essentially a no-op. + An external entity will need to invoke Attach to attach a + CItemConfiguration to this object. That will in turn + invoke the onAttach function. We can't do that in the + constructor (much as I'd like to), since in constructors, + virtual functions are all confined to the textual class, rather than the + run-time class, and therefore, the wrong onAttach will get called. + +*/ +CControlModule::CControlModule() +{} + +CControlModule::~CControlModule() +{} + +CControlModule::CControlModule(const CControlModule& rhs) : + CConfigurableObject(rhs) +{} + + +CControlModule& +CControlModule::operator=(const CControlModule& rhs) +{ + return dynamic_cast<CControlModule&>(CConfigurableObject::operator=(rhs)); +} + + +int +CControlModule::operator==(const CControlModule& rhs) const +{ + return CConfigurableObject::operator==(rhs); +} + +int +CControlModule::operator!=(const CControlModule& rhs) const +{ + return !(*this == rhs); +} +///////////////////////////////////////////////////////////////////////////////// +// +// Virtual functions: + +/*! + Initialize is called to obtain access to the hardware and + do any one-time device setup. + It is optional. The default implementation here is a no-op. +*/ +void +CControlModule::Initialize() +{} + + + Added: trunk/nextgen/usb/tclserver/CControlModule.h =================================================================== --- trunk/nextgen/usb/tclserver/CControlModule.h (rev 0) +++ trunk/nextgen/usb/tclserver/CControlModule.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,98 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __CCONTROLMODULE_H +#define __CCONTROLMODULE_H + +#ifndef __CCONFIGURABLEOBJECT_H +#include <CConfigurableObject.h> +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + + + +/*! + This is the base class for programmable electronics that are not read out in events. + Since the USB controllers can only be talked to by a single process, and since they + must be taken out of data taking mode before single shot operations can be performed, + The readout frameworks support a Tcl Server taht can be sent commands to control + specific electronic hardware. + + Each specific framework (e.g. VM-USB or CC-USB) will define a set of supported + control modules. The Tcl server takes care of: + - Initializing the set of objects that get instantiated, and their configuration + (e.g. base addresses or slot numbers) via a configuration script that is analagous + to the daqconfig.tcl (controlconfig.tcl). script. + - If necessary, halting and restarting data taking in order to slip a control function + in in the middle of an active run. + - Dispatching requests received by clients to the appropriate objects. + + This is possible because requests to the server are of one of the following forms: + + - Set objectname parametername value + - Get objectname parametername + - Update objectname + + where the Set command modifes a settable named parameter in the object named + objectname to value, Get returns the value of the named parameter from the named object, + and Update loads the device with any state held internally by the object (e.g. + recovery after power up). + + + CControlModule is an abstract base class. Concrete implementation will have to implement; + - Set - Process the set command on the object. + - Get - Process the get command on the object. + - Update - Process the update command on the object + - onAttach to manage the configuration parameters accepted by the module. + - clone() Create a copy of this object. + - Optionally Initialize. + +*/ +class CControlModule : public CConfigurableObject +{ + +public: + + // Canonicals + + CControlModule(); + virtual ~CControlModule(); + CControlModule(const CControlModule& rhs); + CControlModule& operator=(const CControlModule& rhs); + +private: + int operator==(const CControlModule& rhs) const; + int operator!=(const CControlModule& rhs) const; +public: + // Functions: + + virtual void Initialize(); + virtual void onAttach() = 0; // Attach/init configuration + virtual std::string Update() = 0; // Update hardware + virtual std::string Set(const char* what, + const char* value) = 0; // Set a device parameter. + virtual std::string Get(const char* what) = 0; // Return a device parameter. + virtual CControlModule* clone() = 0; // Virtual copy constructor. +}; + + +#endif Added: trunk/nextgen/usb/tclserver/CGetCommand.cpp =================================================================== --- trunk/nextgen/usb/tclserver/CGetCommand.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/CGetCommand.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,76 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + + +#include <config.h> +#include "CGetCommand.h" + +#include "TclServer.h" +#include <TCLObject.h> +#include <TCLInterpreter.h> +#include "CControlModule.h" +#include <tcl.h> + +using namespace std; + +/*! + Construct the command. +*/ +CGetCommand::CGetCommand(CTCLInterpreter& interp, + TclServer& server) : + CTCLObjectProcessor(interp, "Get"), + m_Server(server) +{} +CGetCommand::~CGetCommand() +{} + +/* + Execute the get command. See the class comments for syntax. +*/ +int +CGetCommand::operator()(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + // Need 3 words on the command line: + + if (objv.size() != 3) { + m_Server.setResult( + "ERROR Get: Incorrect number of command parameters : need Get name point"); + return TCL_ERROR; + } + + // Get the pieces of the command: + + + string name = objv[1]; + string point = objv[2]; + + // Locate the object: + + CControlModule* pModule = m_Server.findModule(name); + if (!pModule) { + string msg("ERROR Get: unable to find module "); + msg += name; + m_Server.setResult( msg); + return TCL_ERROR; + } + + string result = pModule->Get(point.c_str()); + m_Server.setResult( result); + return TCL_OK; + +} + Added: trunk/nextgen/usb/tclserver/CGetCommand.h =================================================================== --- trunk/nextgen/usb/tclserver/CGetCommand.h (rev 0) +++ trunk/nextgen/usb/tclserver/CGetCommand.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,82 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __CGETCOMMAND_H +#define __CGETCOMMAND_H + +#ifndef __TCLOBJECTPROCESSOR_H +#include <TCLObjectProcessor.h> +#endif + +#ifndef __STL_VECTOR +#include <vector> +#ifndef __STL_VECTOR +#define __STL_VECTOR +#endif +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + +class TclServer; +class CTCLObject; +class CTCLInterpreter; +class CVMUSB; + +/*! + CGetCommand implements the Get command this command + retrieves the value of a control point. + The single form is: + + Get name what + + Where: + - name is the name of a control object + - what is the name of a control point within the object. +*/ + +class CGetCommand : public CTCLObjectProcessor +{ + TclServer& m_Server; // Tcl server that is running us. + +public: + CGetCommand(CTCLInterpreter& interp, + TclServer& server); + + virtual ~CGetCommand(); +private: + CGetCommand(const CGetCommand& rhs); + CGetCommand& operator=(const CGetCommand& rhs); + int operator==(const CGetCommand& rhs) const; + int operator!=(const CGetCommand& rhs) const; +public: + + // Command entry point: + +protected: + int operator()(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + + +}; + + + +#endif Added: trunk/nextgen/usb/tclserver/CModuleCommand.cpp =================================================================== --- trunk/nextgen/usb/tclserver/CModuleCommand.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/CModuleCommand.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,255 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +using namespace std; + +#include "CModuleCommand.h" +#include <TCLInterpreter.h> +#include <TCLObject.h> +#include <CControlModule.h> +#include <TclServer.h> +#include <CItemConfiguration.h> + + +/*! + Construct the command. + - The base class is created with the command string "Module". + creation is done with registration. + - the member data consists of a reference to the list of currently + defined modules (this is held by the interpreter thread main object + as member data so that it will never go out of scope). + \param interp : CTCLInterpreter& + The interpreter on which this command will be registered. + \param modules : vector<CControlModule*>& + Reference to the list of modules that have been defined already. +*/ +CModuleCommand::CModuleCommand(CTCLInterpreter& interp, + TclServer& server) : + CTCLObjectProcessor(interp, "Module"), + m_Server(server) +{} +//! Destroy the module.. no op provided only as a chain to the base class destructor. +CModuleCommand::~CModuleCommand() +{} + + +/*! + The command executor. The command must have at least 2 object elements: + - the command name ("Module"), + - The subcommand .. which must be either "create", "configure" or cget. + + \param interp : CTCLInterpreter& + Reference to the interpreter that is running this command. + \param vector<TCLObject>& objv + Reference to an array of objectified Tcl_Obj objects that contain the + command line prarameters. + \return int + \retval - TCL_OK - If eveything worked. + \retval - TCL_ERROR - on failures. +*/ +int +CModuleCommand::operator()(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + // validate the parameter count. + + if (objv.size() < 2) { + m_Server.setResult("module: Insufficient parameters need module create | config | cget"); + return TCL_ERROR; + } + + // dispatch to the correct function depending on the command keyword. + + + if (string(objv[1]) == string("create")) { + return create(interp, objv); + } + else if (string(objv[1]) == string("config")) { + return configure(interp, objv); + } + else if (string(objv[1]) == string("cget")) { + return cget(interp, objv); + } + else { + m_Server.setResult("module: Invalid subcommand need module create | config |cget"); + return TCL_ERROR; + } +} +/* + create a new module at present we hardcode the module type to + be jtecgdg. The full form of the command is: + module create jtecgdg name + + This module must later be configured via e.g. + module config name ... + + If module types proliferate a more scalable mechanism like an extensible + object factory might be a better way to do this. +*/ +int +CModuleCommand::create(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + if (objv.size() != 4) { + m_Server.setResult("module create: Wrong number of params need: module create type name"); + return TCL_ERROR; + } + string type = objv[2]; + string name = objv[3]; + + CControlModule* pModule = m_Server.createModule(type); + if (!pModule) { + string result = "No such module type: "; + result += type; + interp.setResult(result); + return TCL_ERROR; + } + + // Create the configuration for the module and attach it: + + CItemConfiguration* pConfiguration = new CItemConfiguration(name); + pModule->Attach(pConfiguration); + m_Server.addModule(pModule); + + + m_Server.setResult(name); + + + return TCL_OK; +} +/*! + Configures a module. The form of the command is: + module config name key1 value1... + + Configuration items are therefore keyword value pairs. + Each pair passed to the configure member of the matching + configuration object. +*/ +int +CModuleCommand::configure(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + // Must be at least 3 command elements and an odd number. + + size_t nelements = objv.size(); + if ((nelements < 3) || ((nelements % 2) == 0)) { + m_Server.setResult("module config : invalid number of command elements."); + return TCL_ERROR; + } + string name = objv[2]; + + CControlModule* pModule = m_Server.findModule(name); + if (!pModule) { + string msg("module config: "); + msg += name; + msg += " not found."; + m_Server.setResult(msg); + return TCL_ERROR; + } + for (int i = 3; i < nelements; i+=2) { + string key = objv[i]; + string value = objv[i+1]; + try { + pModule->configure(key, value); + } + catch (string failmsg) { + string msg("module config: Failed to configure "); + msg += name; + msg += " with: "; + msg += key; + msg += " "; + msg += value; + msg += " because: "; + msg += failmsg; + m_Server.setResult( msg); + return TCL_ERROR; + } + } + + + // Success if we got this far. + + return TCL_OK; // No result string. + +} + +/* + Return a configuration item. There are two forms: + module cget name ?key? + + If key is provided, only that item is returned, as just a simple value. + If key is not provided, the entire configuration is dumped + as a Tcl list of 2 element {key value} sublists. +*/ +int +CModuleCommand::cget(CTCLInterpreter& interp, vector<CTCLObject>& objv) +{ + if ((objv.size() < 3) || (objv.size() > 4)) { + m_Server.setResult("module cget : invalid number of parameters; need module cget name ?key?"); + return TCL_ERROR; + } + + string name = objv[2]; + CControlModule* pModule = m_Server.findModule(name); + if(!pModule) { + string msg("module cget "); + msg += name; + msg += " module not found"; + m_Server.setResult( msg); + return TCL_ERROR; + } + + // The two cases: + + if (objv.size() == 3) { // module cget name - dump the lot. + CItemConfiguration::ConfigurationArray config = pModule->cget(); + Tcl_Obj* result = Tcl_NewListObj(0, NULL); + for (int i =0; i < config.size(); i++) { + string key = config[i].first; + string value = config[i].second; + + Tcl_Obj* keyObj = Tcl_NewStringObj(key.c_str(), -1); + Tcl_Obj* valObj = Tcl_NewStringObj(value.c_str(), -1); + Tcl_Obj* objVector[2] = {keyObj, valObj}; + Tcl_Obj* element = Tcl_NewListObj(2, objVector); + Tcl_ListObjAppendElement(interp, result, element); + + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + else { // module cget name key dump the single key. + string key = objv[3]; + string value; + try { + value = pModule->cget(key); + } + catch (string failmsg) { + string msg("module cget: Failed for key: "); + msg += key; + msg += " because: "; + msg += failmsg; + m_Server.setResult( msg); + return TCL_ERROR; + } + m_Server.setResult(value); + return TCL_OK; + + } +} + + Added: trunk/nextgen/usb/tclserver/CModuleCommand.h =================================================================== --- trunk/nextgen/usb/tclserver/CModuleCommand.h (rev 0) +++ trunk/nextgen/usb/tclserver/CModuleCommand.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,86 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __CMODULECOMMAND_H +#define __CMODULECOMMAND_H + +#ifndef TCLOBJECTPROCESSOR_H +#include <TCLObjectProcessor.h> +#endif + +#ifndef __STL_VECTOR +#include <vector> +#ifndef __STL_VECTOR +#define __STL_VECTOR +#endif +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + + +class CTCLInterpreter; +class CTCLObject; +class TclServer; +/*! + Implements the module command. This class is subclassed from + CTclObjectProcessor The module command is the command that + each setup script uses to define the set of contrrol modules + that exist. At present, only a single type of control module + is supported: CJTECGDG Jtec/Wiener Gate and Delay generator. +*/ +class CModuleCommand : public CTCLObjectProcessor +{ + // local member data: +private: + TclServer& m_Server; + + // Canonical functions: + +public: + CModuleCommand(CTCLInterpreter& interp, + TclServer& server); + virtual ~CModuleCommand(); + +private: + CModuleCommand(const CModuleCommand& rhs); + CModuleCommand& operator=(const CModuleCommand& rhs); + int operator==(const CModuleCommand& rhs) const; + int operator!=(const CModuleCommand& rhs) const; +public: + + // Virtual function overrides and implementations. +protected: + virtual int operator()(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); +private: + int create(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + int configure(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + int cget(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + + + +}; + + +#endif Added: trunk/nextgen/usb/tclserver/CSetCommand.cpp =================================================================== --- trunk/nextgen/usb/tclserver/CSetCommand.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/CSetCommand.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,77 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +#include "CSetCommand.h" +#include "TclServer.h" +#include <TCLObject.h> +#include <TCLInterpreter.h> +#include "CControlModule.h" +#include <tcl.h> + +using namespace std; + +/*! + Construct the command. +*/ +CSetCommand::CSetCommand(CTCLInterpreter& interp, + TclServer& server) : + + CTCLObjectProcessor(interp, "Set"), + m_Server(server) +{} +CSetCommand::~CSetCommand() +{} + + + +/* + Execute the set command. Set the class comments for syntax. +*/ +int +CSetCommand::operator()(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + // Must be 4 words in the command: + + if (objv.size() != 4) { + m_Server.setResult("ERROR Set: Incorrect number of command words. Need: Set name point value"); + return TCL_ERROR; + } + // Pull out the values.. All values are strings: + + string name = objv[1]; + string point= objv[2]; + string value= objv[3]; + + // Need to find the module: + + CControlModule* pModule = m_Server.findModule(name); + if (!pModule) { + string msg("ERROR Set: Control module: "); + msg += name; + msg += " cannot be found"; + m_Server.setResult( msg); + + return TCL_ERROR; + } + // Now try the command returning any string error that is thrown: + + string result = pModule->Set(point.c_str(), value.c_str()); + m_Server.setResult( result); + return TCL_OK; + +} Added: trunk/nextgen/usb/tclserver/CSetCommand.h =================================================================== --- trunk/nextgen/usb/tclserver/CSetCommand.h (rev 0) +++ trunk/nextgen/usb/tclserver/CSetCommand.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,87 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __CSETCOMMAND_H +#define __CSETCOMMAND_H + +#ifndef __TCLOBJECTPROCESSOR_H +#include <TCLObjectProcessor.h> +#endif + +#ifndef __STL_VECTOR +#include <vector> +#ifndef __STL_VECTOR +#define __STL_VECTOR +#endif +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + + +class TclServer; +class CTCLObject; +class CTCLInterpreter; +class CVMUSB; + +/*! + CSetCommand implements the Set command. + This command sets the value of a control point. + The command has a single form: + + "Set name what value" + + where: + - name is the name of a control object. + - what is the name of a control point within that object. + - value is the new value for that control point. + + Consider for example an 8 channel gate and delay generator named + gdg1 A command like: + + Set gdg1 delay0 10 + + Might set the delay for channel 0 to 10 in that module. +*/ +class CSetCommand : public CTCLObjectProcessor +{ +private: + TclServer& m_Server; // Tcl server that is running us. +public: + CSetCommand(CTCLInterpreter& interp, + TclServer& server); + virtual ~CSetCommand(); +private: + CSetCommand(const CSetCommand& rhs); + CSetCommand& operator=(const CSetCommand& rhs); + int operator==(const CSetCommand& rhs) const; + int operator!=(const CSetCommand& rhs) const; +public: + + // Command entry point: + +protected: + int operator()(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + + +}; + +#endif Added: trunk/nextgen/usb/tclserver/CUpdateCommand.cpp =================================================================== --- trunk/nextgen/usb/tclserver/CUpdateCommand.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/CUpdateCommand.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,72 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ +#include <config.h> +#include "CUpdateCommand.h" + +#include "TclServer.h" +#include <TCLObject.h> +#include <TCLInterpreter.h> +#include "CControlModule.h" + +#include <tcl.h> + +using namespace std; + +/*! + Construct the command. +*/ +CUpdateCommand::CUpdateCommand(CTCLInterpreter& interp, + TclServer& server ) : + CTCLObjectProcessor(interp, "Update"), + m_Server(server) +{} +CUpdateCommand::~CUpdateCommand() +{} + +/* + Execute the Update command. See the class comments for syntax. +*/ +int +CUpdateCommand::operator()(CTCLInterpreter& interp, + vector<CTCLObject>& objv) +{ + // Need 2 words on the command line: + + if (objv.size() != 2) { + m_Server.setResult( + "ERROR Update: Incorrect number of command parameters : need Update name"); + return TCL_ERROR; + } + + // Get the pieces of the command: + + + string name = objv[1]; + + // Locate the object: + + CControlModule* pModule = m_Server.findModule(name); + if (!pModule) { + string msg("ERROR Update: unable to find module "); + msg += name; + m_Server.setResult( msg); + return TCL_ERROR; + } + + string result = pModule->Update(); + m_Server.setResult( result); + return TCL_OK; +} Added: trunk/nextgen/usb/tclserver/CUpdateCommand.h =================================================================== --- trunk/nextgen/usb/tclserver/CUpdateCommand.h (rev 0) +++ trunk/nextgen/usb/tclserver/CUpdateCommand.h 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,81 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#ifndef __CUPDATECOMMAND_H +#define __CUPDATECOMMAND_H + +#ifndef __TCLOBJECTPROCESSOR_H +#include <TCLObjectProcessor.h> +#endif + +#ifndef __STL_VECTOR +#include <vector> +#ifndef __STL_VECTOR +#define __STL_VECTOR +#endif +#endif + +#ifndef __STL_STRING +#include <string> +#ifndef __STL_STRING +#define __STL_STRING +#endif +#endif + + +class TclServer; +class CTCLObject; +class CTCLInterpreter; +class CVMUSB; + +/*! + CUpdateCommand implements the Update command this command + informs a control object to update its values. + The single form is: + + Update name + + Where: + - name is the name of a control object +*/ + +class CUpdateCommand : public CTCLObjectProcessor +{ + TclServer& m_Server; // Tcl server that is running us. + +public: + CUpdateCommand(CTCLInterpreter& interp, + TclServer& server); + virtual ~CUpdateCommand(); +private: + CUpdateCommand(const CUpdateCommand& rhs); + CUpdateCommand& operator=(const CUpdateCommand& rhs); + int operator==(const CUpdateCommand& rhs) const; + int operator!=(const CUpdateCommand& rhs) const; +public: + + // Command entry point: + +protected: + int operator()(CTCLInterpreter& interp, + std::vector<CTCLObject>& objv); + + +}; + + + +#endif Added: trunk/nextgen/usb/tclserver/Makefile.am =================================================================== --- trunk/nextgen/usb/tclserver/Makefile.am (rev 0) +++ trunk/nextgen/usb/tclserver/Makefile.am 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,35 @@ +lib_LTLIBRARIES = libControlServer.la +libControlServer_la_SOURCES = CModuleCommand.cpp \ + TclServer.cpp \ + CControlModule.cpp \ + CSetCommand.cpp \ + serverinstance.cpp \ + CUpdateCommand.cpp \ + CGetCommand.cpp \ + Server.cpp + +include_HEADERS = CSetCommand.h \ + server.h \ + CGetCommand.h \ + CUpdateCommand.h \ + serverinstance.h \ + CControlModule.h \ + CModuleCommand.h \ + TclServer.h + +INCLUDES = -I@top_srcdir@/base/headers \ + -I@top_srcdir@/usb/tclcommon \ + -I@top_srcdir@/usb/threadcom \ + -I@top_srcdir@/base/tclplus \ + -I@top_srcdir@/base/exception \ + -I@top_srcdir@/base/thread \ + @TCL_FLAGS@ + + + +libControlServer_la_LIBADD = @top_srcdir@/usb/tclcommon/libusbtclcommon.la \ + @top_srcdir@/usb/threadcom/libThreadComm.la \ + @top_srcdir@/base/tclplus/libtclPlus.la \ + @top_srcdir@/base/exception/libException.la \ + @top_srcdir@/base/thread/libdaqthreads.la \ + @TCL_LDFLAGS@ \ No newline at end of file Added: trunk/nextgen/usb/tclserver/Server.cpp =================================================================== --- trunk/nextgen/usb/tclserver/Server.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/Server.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,86 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +static const char* Copyright= "(C) Copyright Michigan State University 2002, All rights reserved";/* +** Implementation of Tcl Server connection. +** +*/ +#include <config.h> +#include <tcl.h> +#include <malloc.h> +#include <string.h> +#include <stdio.h> +#include "server.h" +#include "serverinstance.h" +#include <string> +#include <iostream> + +using namespace std; + + + + +static void +Server_Accept(ClientData cd, Tcl_Channel client, char* pHostname, + int nHostport) +{ + + cerr << "Client connection accepted from " << pHostname << endl; + Tcl_Interp* pInterp = (Tcl_Interp*)cd; + + + if (strcmp(pHostname, "127.0.0.1")) { + printf(">>Rejected unauthorized connection from %s on port %d\n", + pHostname, nHostport); + Tcl_Close(pInterp, client); + return; + } + + // Honor the connection + + ServerContext context; + pServerContext pContext = &context; + + + printf("Accepting connection from %s on port %d\n", pHostname, nHostport); + pContext->pInterp = pInterp; + Tcl_DStringInit(&(pContext->RemoteHost)); + Tcl_DStringAppend(&(pContext->RemoteHost), pHostname, -1); + pContext->RemotePort = nHostport; + pContext->DialogChannel = client; + Tcl_DStringInit(&(pContext->command)); + + new CServerInstance(context); + + Tcl_DStringFree(&(context.RemoteHost)); + Tcl_DStringFree(&(context.command)); + +} + +void Server_Init(Tcl_Interp* pInterp, int SERVERPORT) +{ + + // Open the server for business. + + Tcl_OpenTcpServer(pInterp, SERVERPORT, NULL, + Server_Accept, (ClientData)pInterp); + +} + + + + + Property changes on: trunk/nextgen/usb/tclserver/Server.cpp ___________________________________________________________________ Added: svn:executable + * Added: trunk/nextgen/usb/tclserver/TclServer.cpp =================================================================== --- trunk/nextgen/usb/tclserver/TclServer.cpp (rev 0) +++ trunk/nextgen/usb/tclserver/TclServer.cpp 2008-07-17 13:56:13 UTC (rev 1918) @@ -0,0 +1,312 @@ +/* + This software is Copyright by the Board of Trustees of Michigan + State University (c) Copyright 2005. + + You may use this software under the terms of the GNU public license + (GPL). The terms of this license are described at: + + http://www.gnu.org/licenses/gpl.txt + + Author: + Ron Fox + NSCL + Michigan State University + East Lansing, MI 48824-1321 +*/ + +#include <config.h> +using namespace std; + +#include "TclServer.h" +#include "server.h" +#include "serverinstance.h" +#include "CModuleCommand.h" +#include "CSetCommand.h" +#include "CGetCommand.h" +#include "CUpdateCommand.h" + + +#include <tcl.h> +#include <TCLInterpreter.h> +#include "CControlModule.h" +#include <Exception.h> +#include <string> +#include <iostream> + +/*! Constructor is not very interesting 'cause all the action is in + start and operator() +*/ +TclServer::TclServer() : + m_port(-1), + m_configFilename(string("")), + m_pInterpreter(0) +{} +/*! + These threads are built to live 'forever' so the destructor is also +uninteresting. +*/ +TclServer::~TclServer() +{} + +/*! + Start sets up the variables the entry point needs to initialize + and schedules the thread. The thread id is returned to the caller. + Note that while the entry point includes parameters, it's just so much + easier to stuff them into the member data rather than trying to force fit + them to argc,argv formalism in the caller and receiver. + \param port : int + Number of the Tcp/IP port on which we will listen for connections. + \param configFile : const char* + Name of the configuration file that is used to instantiate our controllers. + This is intended to be a Tcl script and is therefore processed by the + interpreter after it has been initialized with all the added commands, + but prior to entering the event loop. + \param vme : CVMUSB& vme + Vme controller that is used to interact with the hardware. + +*/ + +unsigned long +TclServer::start(int port, const char* configFile) +{ + // Set up the member data needed to run the thread... + + m_port = port; + m_configFilename = configFile; + + // Schedule the thread for execution: + + Thread::start(); + m_tid = getId(); + return m_tid; +} + +/*! + Locate a module by name. + \param name : std::string + Name of the module to find. + \return CControlModule* + \retval NULL - not found + \retval Other - Pointer to the found module. +*/ +CControlModule* +TclServer::findModule(string name) +{ + for (int i=0; i < m_Modules.size(); i++) { + CControlModule* pModule = m_Modules[i]; + if (pModule->getName() == name) { + return pModule; + } + } + return static_cast<CControlModule*>(NULL); +} +/*! + Add a new module to the list of modules + \param pNewModule : CControLModule* + Pointer to the new module to add. +*/ +void +TclServer::addModule(CControlModule* pNewModule) +{ + m_Modules.push_back(pNewModule); +} + +/*! + Set the interpreter result to a string value. +*/ +void +TclServer::setResult(string msg) +{ + Tcl_Obj* result = Tcl_NewStringObj(msg.c_str(), -1); + Tcl_SetObjResult(m_pInterpreter->getInterpreter(), result); + + +} +/*! + Add a prototype from which a module can be created. + + This is used by the module command to create the actual modules. + + \param typeName - Type of module. + \param prototype- Pointer to a prototype module, which must have + a lifespan that is the length of the program. + +\note prototypes should not have a... [truncated message content] |