707 lines
19 KiB
C++
707 lines
19 KiB
C++
/*************************************************************************\
|
|
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* EPICS BASE Versions 3.13.7
|
|
* and higher are distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
/*
|
|
*
|
|
*
|
|
* L O S A L A M O S
|
|
* Los Alamos National Laboratory
|
|
* Los Alamos, New Mexico 87545
|
|
*
|
|
* Copyright, 1986, The Regents of the University of California.
|
|
*
|
|
*
|
|
* Author Jeffrey O. Hill
|
|
* johill@lanl.gov
|
|
* 505 665 1831
|
|
*/
|
|
|
|
#include <string>
|
|
#include <stdexcept>
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning(disable:4355)
|
|
#endif
|
|
|
|
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
|
|
|
#include "errlog.h"
|
|
|
|
#define epicsExportSharedSymbols
|
|
#include "iocinf.h"
|
|
#include "oldAccess.h"
|
|
#include "cac.h"
|
|
#include "autoPtrFreeList.h"
|
|
|
|
extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
|
|
{
|
|
}
|
|
|
|
oldChannelNotify::oldChannelNotify (
|
|
epicsGuard < epicsMutex > & guard, ca_client_context & cacIn,
|
|
const char *pName, caCh * pConnCallBackIn,
|
|
void * pPrivateIn, capri priority ) :
|
|
cacCtx ( cacIn ),
|
|
io ( cacIn.createChannel ( guard, pName, *this, priority ) ),
|
|
pConnCallBack ( pConnCallBackIn ),
|
|
pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler ),
|
|
ioSeqNo ( 0 ), currentlyConnected ( false ), prevConnected ( false )
|
|
{
|
|
guard.assertIdenticalMutex ( cacIn.mutexRef () );
|
|
this->ioSeqNo = cacIn.sequenceNumberOfOutstandingIO ( guard );
|
|
if ( pConnCallBackIn == 0 ) {
|
|
cacIn.incrementOutstandingIO ( guard, this->ioSeqNo );
|
|
}
|
|
}
|
|
|
|
oldChannelNotify::~oldChannelNotify ()
|
|
{
|
|
}
|
|
|
|
void oldChannelNotify::destructor (
|
|
epicsGuard < epicsMutex > & guard )
|
|
{
|
|
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
|
|
this->io.destroy ( guard );
|
|
// no need to worry about a connect preempting here because
|
|
// the io (the nciu) has been destroyed above
|
|
if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
|
|
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
|
|
}
|
|
this->~oldChannelNotify ();
|
|
}
|
|
|
|
void oldChannelNotify::connectNotify (
|
|
epicsGuard < epicsMutex > & guard )
|
|
{
|
|
this->currentlyConnected = true;
|
|
this->prevConnected = true;
|
|
if ( this->pConnCallBack ) {
|
|
struct connection_handler_args args;
|
|
args.chid = this;
|
|
args.op = CA_OP_CONN_UP;
|
|
caCh * pFunc = this->pConnCallBack;
|
|
{
|
|
epicsGuardRelease < epicsMutex > unguard ( guard );
|
|
( *pFunc ) ( args );
|
|
}
|
|
}
|
|
else {
|
|
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
|
|
}
|
|
}
|
|
|
|
void oldChannelNotify::disconnectNotify (
|
|
epicsGuard < epicsMutex > & guard )
|
|
{
|
|
this->currentlyConnected = false;
|
|
if ( this->pConnCallBack ) {
|
|
struct connection_handler_args args;
|
|
args.chid = this;
|
|
args.op = CA_OP_CONN_DOWN;
|
|
caCh * pFunc = this->pConnCallBack;
|
|
{
|
|
epicsGuardRelease < epicsMutex > unguard ( guard );
|
|
( *pFunc ) ( args );
|
|
}
|
|
}
|
|
else {
|
|
this->cacCtx.incrementOutstandingIO (
|
|
guard, this->ioSeqNo );
|
|
}
|
|
}
|
|
|
|
void oldChannelNotify::serviceShutdownNotify (
|
|
epicsGuard < epicsMutex > & guard )
|
|
{
|
|
this->disconnectNotify ( guard );
|
|
}
|
|
|
|
void oldChannelNotify::accessRightsNotify (
|
|
epicsGuard < epicsMutex > & guard, const caAccessRights & ar )
|
|
{
|
|
struct access_rights_handler_args args;
|
|
args.chid = this;
|
|
args.ar.read_access = ar.readPermit();
|
|
args.ar.write_access = ar.writePermit();
|
|
caArh * pFunc = this->pAccessRightsFunc;
|
|
{
|
|
epicsGuardRelease < epicsMutex > unguard ( guard );
|
|
( *pFunc ) ( args );
|
|
}
|
|
}
|
|
|
|
void oldChannelNotify::exception (
|
|
epicsGuard < epicsMutex > & guard, int status, const char * pContext )
|
|
{
|
|
this->cacCtx.exception ( guard, status, pContext, __FILE__, __LINE__ );
|
|
}
|
|
|
|
void oldChannelNotify::readException (
|
|
epicsGuard < epicsMutex > & guard, int status, const char *pContext,
|
|
unsigned type, arrayElementCount count, void * /* pValue */ )
|
|
{
|
|
this->cacCtx.exception ( guard, status, pContext,
|
|
__FILE__, __LINE__, *this, type, count, CA_OP_GET );
|
|
}
|
|
|
|
void oldChannelNotify::writeException (
|
|
epicsGuard < epicsMutex > & guard, int status, const char *pContext,
|
|
unsigned type, arrayElementCount count )
|
|
{
|
|
this->cacCtx.exception ( guard, status, pContext,
|
|
__FILE__, __LINE__, *this, type, count, CA_OP_PUT );
|
|
}
|
|
|
|
void * oldChannelNotify::operator new ( size_t ) // X aCC 361
|
|
{
|
|
// The HPUX compiler seems to require this even though no code
|
|
// calls it directly
|
|
throw std::logic_error ( "why is the compiler calling private operator new" );
|
|
}
|
|
|
|
void oldChannelNotify::operator delete ( void * )
|
|
{
|
|
// Visual C++ .net appears to require operator delete if
|
|
// placement operator delete is defined? I smell a ms rat
|
|
// because if I declare placement new and delete, but
|
|
// comment out the placement delete definition there are
|
|
// no undefined symbols.
|
|
errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
|
|
__FILE__, __LINE__ );
|
|
}
|
|
|
|
/*
|
|
* ca_get_host_name ()
|
|
*/
|
|
unsigned epicsShareAPI ca_get_host_name (
|
|
chid pChan, char * pBuf, unsigned bufLength )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef() );
|
|
return pChan->io.getHostName ( guard, pBuf, bufLength );
|
|
}
|
|
|
|
/*
|
|
* ca_host_name ()
|
|
*
|
|
* !!!! not thread safe !!!!
|
|
*
|
|
*/
|
|
const char * epicsShareAPI ca_host_name (
|
|
chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.pHostName ( guard );
|
|
}
|
|
|
|
/*
|
|
* ca_set_puser ()
|
|
*/
|
|
void epicsShareAPI ca_set_puser (
|
|
chid pChan, void * puser )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
pChan->pPrivate = puser;
|
|
}
|
|
|
|
/*
|
|
* ca_get_puser ()
|
|
*/
|
|
void * epicsShareAPI ca_puser (
|
|
chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->pPrivate;
|
|
}
|
|
|
|
/*
|
|
* Specify an event subroutine to be run for connection events
|
|
*/
|
|
int epicsShareAPI ca_change_connection_event ( chid pChan, caCh * pfunc )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
if ( ! pChan->currentlyConnected ) {
|
|
if ( pfunc ) {
|
|
if ( ! pChan->pConnCallBack ) {
|
|
pChan->cacCtx.decrementOutstandingIO ( guard, pChan->ioSeqNo );
|
|
}
|
|
}
|
|
else {
|
|
if ( pChan->pConnCallBack ) {
|
|
pChan->cacCtx.incrementOutstandingIO ( guard, pChan->ioSeqNo );
|
|
}
|
|
}
|
|
}
|
|
pChan->pConnCallBack = pfunc;
|
|
return ECA_NORMAL;
|
|
}
|
|
|
|
/*
|
|
* ca_replace_access_rights_event
|
|
*/
|
|
int epicsShareAPI ca_replace_access_rights_event (
|
|
chid pChan, caArh *pfunc )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
|
|
// The order of the following is significant to guarantee that the
|
|
// access rights handler is always gets called even if the channel connects
|
|
// while this is running. There is some very small chance that the
|
|
// handler could be called twice here with the same access rights state, but
|
|
// that will not upset the application.
|
|
pChan->pAccessRightsFunc = pfunc ? pfunc : cacNoopAccesRightsHandler;
|
|
caAccessRights tmp = pChan->io.accessRights ( guard );
|
|
|
|
if ( pChan->currentlyConnected ) {
|
|
struct access_rights_handler_args args;
|
|
args.chid = pChan;
|
|
args.ar.read_access = tmp.readPermit ();
|
|
args.ar.write_access = tmp.writePermit ();
|
|
epicsGuardRelease < epicsMutex > unguard ( guard );
|
|
( *pChan->pAccessRightsFunc ) ( args );
|
|
}
|
|
return ECA_NORMAL;
|
|
}
|
|
|
|
/*
|
|
* ca_array_get ()
|
|
*/
|
|
int epicsShareAPI ca_array_get ( chtype type,
|
|
arrayElementCount count, chid pChan, void *pValue )
|
|
{
|
|
int caStatus;
|
|
try {
|
|
if ( type < 0 ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
unsigned tmpType = static_cast < unsigned > ( type );
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
pChan->eliminateExcessiveSendBacklog ( guard );
|
|
autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
|
|
( pChan->getClientCtx().getCopyFreeList,
|
|
new ( pChan->getClientCtx().getCopyFreeList )
|
|
getCopy ( guard, pChan->getClientCtx(), *pChan,
|
|
tmpType, count, pValue ) );
|
|
pChan->io.read ( guard, type, count, *pNotify, 0 );
|
|
pNotify.release ();
|
|
caStatus = ECA_NORMAL;
|
|
}
|
|
catch ( cacChannel::badString & )
|
|
{
|
|
caStatus = ECA_BADSTR;
|
|
}
|
|
catch ( cacChannel::badType & )
|
|
{
|
|
caStatus = ECA_BADTYPE;
|
|
}
|
|
catch ( cacChannel::outOfBounds & )
|
|
{
|
|
caStatus = ECA_BADCOUNT;
|
|
}
|
|
catch ( cacChannel::noReadAccess & )
|
|
{
|
|
caStatus = ECA_NORDACCESS;
|
|
}
|
|
catch ( cacChannel::notConnected & )
|
|
{
|
|
caStatus = ECA_DISCONN;
|
|
}
|
|
catch ( cacChannel::unsupportedByService & )
|
|
{
|
|
caStatus = ECA_UNAVAILINSERV;
|
|
}
|
|
catch ( cacChannel::requestTimedOut & )
|
|
{
|
|
caStatus = ECA_TIMEOUT;
|
|
}
|
|
catch ( std::bad_alloc & )
|
|
{
|
|
caStatus = ECA_ALLOCMEM;
|
|
}
|
|
catch ( cacChannel::msgBodyCacheTooSmall & ) {
|
|
caStatus = ECA_TOLARGE;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
caStatus = ECA_GETFAIL;
|
|
}
|
|
return caStatus;
|
|
}
|
|
|
|
/*
|
|
* ca_array_get_callback ()
|
|
*/
|
|
int epicsShareAPI ca_array_get_callback ( chtype type,
|
|
arrayElementCount count, chid pChan,
|
|
caEventCallBackFunc *pfunc, void *arg )
|
|
{
|
|
int caStatus;
|
|
try {
|
|
if ( type < 0 ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
unsigned tmpType = static_cast < unsigned > ( type );
|
|
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
pChan->eliminateExcessiveSendBacklog ( guard );
|
|
autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
|
|
( pChan->getClientCtx().getCallbackFreeList,
|
|
new ( pChan->getClientCtx().getCallbackFreeList )
|
|
getCallback ( *pChan, pfunc, arg ) );
|
|
pChan->io.read ( guard, tmpType, count, *pNotify, 0 );
|
|
pNotify.release ();
|
|
caStatus = ECA_NORMAL;
|
|
}
|
|
catch ( cacChannel::badString & )
|
|
{
|
|
caStatus = ECA_BADSTR;
|
|
}
|
|
catch ( cacChannel::badType & )
|
|
{
|
|
caStatus = ECA_BADTYPE;
|
|
}
|
|
catch ( cacChannel::outOfBounds & )
|
|
{
|
|
caStatus = ECA_BADCOUNT;
|
|
}
|
|
catch ( cacChannel::noReadAccess & )
|
|
{
|
|
caStatus = ECA_NORDACCESS;
|
|
}
|
|
catch ( cacChannel::notConnected & )
|
|
{
|
|
caStatus = ECA_DISCONN;
|
|
}
|
|
catch ( cacChannel::unsupportedByService & )
|
|
{
|
|
caStatus = ECA_UNAVAILINSERV;
|
|
}
|
|
catch ( cacChannel::requestTimedOut & )
|
|
{
|
|
caStatus = ECA_TIMEOUT;
|
|
}
|
|
catch ( std::bad_alloc & )
|
|
{
|
|
caStatus = ECA_ALLOCMEM;
|
|
}
|
|
catch ( cacChannel::msgBodyCacheTooSmall ) {
|
|
caStatus = ECA_TOLARGE;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
caStatus = ECA_GETFAIL;
|
|
}
|
|
return caStatus;
|
|
}
|
|
|
|
void oldChannelNotify::read (
|
|
epicsGuard < epicsMutex > & guard,
|
|
unsigned type, arrayElementCount count,
|
|
cacReadNotify & notify, cacChannel::ioid * pId )
|
|
{
|
|
this->io.read ( guard, type, count, notify, pId );
|
|
}
|
|
|
|
/*
|
|
* ca_array_put_callback ()
|
|
*/
|
|
int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
|
|
chid pChan, const void *pValue, caEventCallBackFunc *pfunc, void *usrarg )
|
|
{
|
|
int caStatus;
|
|
try {
|
|
if ( type < 0 ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
pChan->eliminateExcessiveSendBacklog ( guard );
|
|
unsigned tmpType = static_cast < unsigned > ( type );
|
|
autoPtrFreeList < putCallback, 0x400, epicsMutexNOOP > pNotify
|
|
( pChan->getClientCtx().putCallbackFreeList,
|
|
new ( pChan->getClientCtx().putCallbackFreeList )
|
|
putCallback ( *pChan, pfunc, usrarg ) );
|
|
pChan->io.write ( guard, tmpType, count, pValue, *pNotify, 0 );
|
|
pNotify.release ();
|
|
caStatus = ECA_NORMAL;
|
|
}
|
|
catch ( cacChannel::badString & )
|
|
{
|
|
caStatus = ECA_BADSTR;
|
|
}
|
|
catch ( cacChannel::badType & )
|
|
{
|
|
caStatus = ECA_BADTYPE;
|
|
}
|
|
catch ( cacChannel::outOfBounds & )
|
|
{
|
|
caStatus = ECA_BADCOUNT;
|
|
}
|
|
catch ( cacChannel::noWriteAccess & )
|
|
{
|
|
caStatus = ECA_NOWTACCESS;
|
|
}
|
|
catch ( cacChannel::notConnected & )
|
|
{
|
|
caStatus = ECA_DISCONN;
|
|
}
|
|
catch ( cacChannel::unsupportedByService & )
|
|
{
|
|
caStatus = ECA_UNAVAILINSERV;
|
|
}
|
|
catch ( cacChannel::requestTimedOut & )
|
|
{
|
|
caStatus = ECA_TIMEOUT;
|
|
}
|
|
catch ( std::bad_alloc & )
|
|
{
|
|
caStatus = ECA_ALLOCMEM;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
caStatus = ECA_PUTFAIL;
|
|
}
|
|
return caStatus;
|
|
}
|
|
|
|
/*
|
|
* ca_array_put ()
|
|
*/
|
|
int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
|
|
chid pChan, const void * pValue )
|
|
{
|
|
if ( type < 0 ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
unsigned tmpType = static_cast < unsigned > ( type );
|
|
|
|
int caStatus;
|
|
try {
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
pChan->eliminateExcessiveSendBacklog ( guard );
|
|
pChan->io.write ( guard, tmpType, count, pValue );
|
|
caStatus = ECA_NORMAL;
|
|
}
|
|
catch ( cacChannel::badString & )
|
|
{
|
|
caStatus = ECA_BADSTR;
|
|
}
|
|
catch ( cacChannel::badType & )
|
|
{
|
|
caStatus = ECA_BADTYPE;
|
|
}
|
|
catch ( cacChannel::outOfBounds & )
|
|
{
|
|
caStatus = ECA_BADCOUNT;
|
|
}
|
|
catch ( cacChannel::noWriteAccess & )
|
|
{
|
|
caStatus = ECA_NOWTACCESS;
|
|
}
|
|
catch ( cacChannel::notConnected & )
|
|
{
|
|
caStatus = ECA_DISCONN;
|
|
}
|
|
catch ( cacChannel::unsupportedByService & )
|
|
{
|
|
caStatus = ECA_UNAVAILINSERV;
|
|
}
|
|
catch ( cacChannel::requestTimedOut & )
|
|
{
|
|
caStatus = ECA_TIMEOUT;
|
|
}
|
|
catch ( std::bad_alloc & )
|
|
{
|
|
caStatus = ECA_ALLOCMEM;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
caStatus = ECA_PUTFAIL;
|
|
}
|
|
return caStatus;
|
|
}
|
|
|
|
int epicsShareAPI ca_create_subscription (
|
|
chtype type, arrayElementCount count, chid pChan,
|
|
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
|
|
evid * monixptr )
|
|
{
|
|
if ( type < 0 ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
unsigned tmpType = static_cast < unsigned > ( type );
|
|
|
|
if ( INVALID_DB_REQ (type) ) {
|
|
return ECA_BADTYPE;
|
|
}
|
|
|
|
if ( pCallBack == NULL ) {
|
|
return ECA_BADFUNCPTR;
|
|
}
|
|
|
|
static const long maskMask = 0xffff;
|
|
if ( ( mask & maskMask ) == 0) {
|
|
return ECA_BADMASK;
|
|
}
|
|
|
|
if ( mask & ~maskMask ) {
|
|
return ECA_BADMASK;
|
|
}
|
|
|
|
try {
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
try {
|
|
// if this stalls out on a live circuit then an exception
|
|
// can be forthcoming which we must ignore (this is a
|
|
// special case preserving legacy ca_create_subscription
|
|
// behavior)
|
|
pChan->eliminateExcessiveSendBacklog ( guard );
|
|
}
|
|
catch ( cacChannel::notConnected & ) {
|
|
// intentionally ignored (its ok to subscribe when not connected)
|
|
}
|
|
new ( pChan->getClientCtx().subscriptionFreeList )
|
|
oldSubscription (
|
|
guard, *pChan, pChan->io, tmpType, count, mask,
|
|
pCallBack, pCallBackArg, monixptr );
|
|
// dont touch object created after above new because
|
|
// the first callback might have canceled, and therefore
|
|
// destroyed, it
|
|
return ECA_NORMAL;
|
|
}
|
|
catch ( cacChannel::badType & )
|
|
{
|
|
return ECA_BADTYPE;
|
|
}
|
|
catch ( cacChannel::outOfBounds & )
|
|
{
|
|
return ECA_BADCOUNT;
|
|
}
|
|
catch ( cacChannel::badEventSelection & )
|
|
{
|
|
return ECA_BADMASK;
|
|
}
|
|
catch ( cacChannel::noReadAccess & )
|
|
{
|
|
return ECA_NORDACCESS;
|
|
}
|
|
catch ( cacChannel::unsupportedByService & )
|
|
{
|
|
return ECA_UNAVAILINSERV;
|
|
}
|
|
catch ( std::bad_alloc & )
|
|
{
|
|
return ECA_ALLOCMEM;
|
|
}
|
|
catch ( cacChannel::msgBodyCacheTooSmall & ) {
|
|
return ECA_TOLARGE;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
return ECA_INTERNAL;
|
|
}
|
|
}
|
|
|
|
void oldChannelNotify::write (
|
|
epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount count,
|
|
const void * pValue, cacWriteNotify & notify, cacChannel::ioid * pId )
|
|
{
|
|
this->io.write ( guard, type, count, pValue, notify, pId );
|
|
}
|
|
|
|
/*
|
|
* ca_field_type()
|
|
*/
|
|
short epicsShareAPI ca_field_type ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.nativeType ( guard );
|
|
}
|
|
|
|
/*
|
|
* ca_element_count ()
|
|
*/
|
|
arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.nativeElementCount ( guard );
|
|
}
|
|
|
|
/*
|
|
* ca_state ()
|
|
*/
|
|
enum channel_state epicsShareAPI ca_state ( chid pChan ) // X aCC 361
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
if ( pChan->io.connected ( guard ) ) {
|
|
return cs_conn;
|
|
}
|
|
else if ( pChan->prevConnected ){
|
|
return cs_prev_conn;
|
|
}
|
|
else {
|
|
return cs_never_conn;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ca_read_access ()
|
|
*/
|
|
unsigned epicsShareAPI ca_read_access ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.accessRights(guard).readPermit();
|
|
}
|
|
|
|
/*
|
|
* ca_write_access ()
|
|
*/
|
|
unsigned epicsShareAPI ca_write_access ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.accessRights(guard).writePermit();
|
|
}
|
|
|
|
/*
|
|
* ca_name ()
|
|
*/
|
|
const char * epicsShareAPI ca_name ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.pName ( guard );
|
|
}
|
|
|
|
unsigned epicsShareAPI ca_search_attempts ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.searchAttempts ( guard );
|
|
}
|
|
|
|
double epicsShareAPI ca_beacon_period ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.beaconPeriod ( guard );
|
|
}
|
|
|
|
double epicsShareAPI ca_receive_watchdog_delay ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.receiveWatchdogDelay ( guard );
|
|
}
|
|
|
|
/*
|
|
* ca_v42_ok(chid chan)
|
|
*/
|
|
int epicsShareAPI ca_v42_ok ( chid pChan )
|
|
{
|
|
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
|
return pChan->io.ca_v42_ok ( guard );
|
|
}
|
|
|
|
|