// $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
|
// $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
|
//
|
//
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
//
|
//
|
// This program is free software; you may redistribute and/or modify it under
|
// This program is free software; you may redistribute and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
// Software Foundation, either version 2, or at your option any later version.
|
// Software Foundation, either version 2, or at your option any later version.
|
//
|
//
|
// This program is distributed in the hope that it will be useful, but
|
// This program is distributed in the hope that it will be useful, but
|
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for complete details.
|
// for complete details.
|
//
|
//
|
// Revision History:
|
// Revision History:
|
// Date Rev Version Comment
|
// Date Rev Version Comment
|
// 2013-05-20 521 1.0.1 Setup proper Tcl channel options
|
// 2013-05-20 521 1.0.1 Setup proper Tcl channel options
|
// 2013-03-01 493 1.0 Initial version
|
// 2013-03-01 493 1.0 Initial version
|
// 2013-01-12 475 0.5 First draft
|
// 2013-01-12 475 0.5 First draft
|
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
|
|
/*!
|
/*!
|
\file
|
\file
|
\version $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
|
\version $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
|
\brief Implemenation of class RtclAttnShuttle.
|
\brief Implemenation of class RtclAttnShuttle.
|
*/
|
*/
|
|
|
#include <errno.h>
|
#include <errno.h>
|
|
|
#include "boost/bind.hpp"
|
#include "boost/bind.hpp"
|
|
|
#include "librtools/Rexception.hpp"
|
#include "librtools/Rexception.hpp"
|
|
|
#include "RtclAttnShuttle.hpp"
|
#include "RtclAttnShuttle.hpp"
|
|
|
using namespace std;
|
using namespace std;
|
|
|
/*!
|
/*!
|
\class Retro::RtclAttnShuttle
|
\class Retro::RtclAttnShuttle
|
\brief FIXME_docs
|
\brief FIXME_docs
|
*/
|
*/
|
|
|
// all method definitions in namespace Retro
|
// all method definitions in namespace Retro
|
namespace Retro {
|
namespace Retro {
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! constructor
|
//! constructor
|
|
|
RtclAttnShuttle::RtclAttnShuttle(uint16_t mask, Tcl_Obj* pobj)
|
RtclAttnShuttle::RtclAttnShuttle(uint16_t mask, Tcl_Obj* pobj)
|
: fpServ(0),
|
: fpServ(0),
|
fpInterp(0),
|
fpInterp(0),
|
fFdPipeRead(-1),
|
fFdPipeRead(-1),
|
fFdPipeWrite(-1),
|
fFdPipeWrite(-1),
|
fShuttleChn(0),
|
fShuttleChn(0),
|
fMask(mask),
|
fMask(mask),
|
fpScript(pobj)
|
fpScript(pobj)
|
{
|
{
|
int pipefd[2];
|
int pipefd[2];
|
int irc = ::pipe(pipefd);
|
int irc = ::pipe(pipefd);
|
if (irc < 0)
|
if (irc < 0)
|
throw Rexception("RtclAttnShuttle::<ctor>", "pipe() failed: ", errno);
|
throw Rexception("RtclAttnShuttle::<ctor>", "pipe() failed: ", errno);
|
fFdPipeRead = pipefd[0];
|
fFdPipeRead = pipefd[0];
|
fFdPipeWrite = pipefd[1];
|
fFdPipeWrite = pipefd[1];
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Destructor
|
//! Destructor
|
|
|
RtclAttnShuttle::~RtclAttnShuttle()
|
RtclAttnShuttle::~RtclAttnShuttle()
|
{
|
{
|
Remove();
|
Remove();
|
::close(fFdPipeWrite);
|
::close(fFdPipeWrite);
|
::close(fFdPipeRead);
|
::close(fFdPipeRead);
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void RtclAttnShuttle::Add(RlinkServer* pserv, Tcl_Interp* interp)
|
void RtclAttnShuttle::Add(RlinkServer* pserv, Tcl_Interp* interp)
|
{
|
{
|
// connect to RlinkServer
|
// connect to RlinkServer
|
pserv->AddAttnHandler(boost::bind(&RtclAttnShuttle::AttnHandler, this, _1),
|
pserv->AddAttnHandler(boost::bind(&RtclAttnShuttle::AttnHandler, this, _1),
|
fMask, (void*)this);
|
fMask, (void*)this);
|
fpServ = pserv;
|
fpServ = pserv;
|
|
|
// connect to Tcl
|
// connect to Tcl
|
fShuttleChn = Tcl_MakeFileChannel((ClientData)fFdPipeRead, TCL_READABLE);
|
fShuttleChn = Tcl_MakeFileChannel((ClientData)fFdPipeRead, TCL_READABLE);
|
|
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-buffersize", "64");
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-buffersize", "64");
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-encoding", "binary");
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-encoding", "binary");
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-translation", "binary");
|
Tcl_SetChannelOption(NULL, fShuttleChn, "-translation", "binary");
|
|
|
Tcl_CreateChannelHandler(fShuttleChn, TCL_READABLE,
|
Tcl_CreateChannelHandler(fShuttleChn, TCL_READABLE,
|
(Tcl_FileProc*) ThunkTclChannelHandler,
|
(Tcl_FileProc*) ThunkTclChannelHandler,
|
(ClientData) this);
|
(ClientData) this);
|
|
|
fpInterp = interp;
|
fpInterp = interp;
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void RtclAttnShuttle::Remove()
|
void RtclAttnShuttle::Remove()
|
{
|
{
|
// disconnect from RlinkServer
|
// disconnect from RlinkServer
|
if (fpServ) {
|
if (fpServ) {
|
fpServ->RemoveAttnHandler(fMask, (void*)this);
|
fpServ->RemoveAttnHandler(fMask, (void*)this);
|
fpServ = 0;
|
fpServ = 0;
|
}
|
}
|
// disconnect from Tcl
|
// disconnect from Tcl
|
if (fpInterp) {
|
if (fpInterp) {
|
Tcl_DeleteChannelHandler(fShuttleChn,
|
Tcl_DeleteChannelHandler(fShuttleChn,
|
(Tcl_FileProc*) ThunkTclChannelHandler,
|
(Tcl_FileProc*) ThunkTclChannelHandler,
|
(ClientData) this);
|
(ClientData) this);
|
Tcl_Close(fpInterp, fShuttleChn);
|
Tcl_Close(fpInterp, fShuttleChn);
|
fpInterp = 0;
|
fpInterp = 0;
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
int RtclAttnShuttle::AttnHandler(const RlinkServer::AttnArgs& args)
|
int RtclAttnShuttle::AttnHandler(const RlinkServer::AttnArgs& args)
|
{
|
{
|
uint16_t apat = args.fAttnPatt & args.fAttnMask;
|
uint16_t apat = args.fAttnPatt & args.fAttnMask;
|
int irc = ::write(fFdPipeWrite, (void*) &apat, sizeof(apat));
|
int irc = ::write(fFdPipeWrite, (void*) &apat, sizeof(apat));
|
if (irc < 0)
|
if (irc < 0)
|
throw Rexception("RtclAttnShuttle::AttnHandler()",
|
throw Rexception("RtclAttnShuttle::AttnHandler()",
|
"write() failed: ", errno);
|
"write() failed: ", errno);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void RtclAttnShuttle::TclChannelHandler(int mask)
|
void RtclAttnShuttle::TclChannelHandler(int mask)
|
{
|
{
|
uint16_t apat;
|
uint16_t apat;
|
Tcl_ReadRaw(fShuttleChn, (char*) &apat, sizeof(apat));
|
Tcl_ReadRaw(fShuttleChn, (char*) &apat, sizeof(apat));
|
// FIXME_code: handle return code
|
// FIXME_code: handle return code
|
|
|
Tcl_SetVar2Ex(fpInterp, "Rlink_attnbits", NULL, Tcl_NewIntObj((int)apat), 0);
|
Tcl_SetVar2Ex(fpInterp, "Rlink_attnbits", NULL, Tcl_NewIntObj((int)apat), 0);
|
// FIXME_code: handle return code
|
// FIXME_code: handle return code
|
|
|
Tcl_EvalObjEx(fpInterp, fpScript, TCL_EVAL_GLOBAL);
|
Tcl_EvalObjEx(fpInterp, fpScript, TCL_EVAL_GLOBAL);
|
// FIXME_code: handle return code
|
// FIXME_code: handle return code
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void RtclAttnShuttle::ThunkTclChannelHandler(ClientData cdata, int mask)
|
void RtclAttnShuttle::ThunkTclChannelHandler(ClientData cdata, int mask)
|
{
|
{
|
((RtclAttnShuttle*) cdata)->TclChannelHandler(mask);
|
((RtclAttnShuttle*) cdata)->TclChannelHandler(mask);
|
return;
|
return;
|
}
|
}
|
|
|
} // end namespace Retro
|
} // end namespace Retro
|
|
|