/*************************************************************************\
* 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.
* SPDX-License-Identifier: EPICS
* EPICS BASE is 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
 *
 */

#ifndef INC_cadef_H
#define INC_cadef_H

/*
 * done in two ifdef steps so that we will remain compatible with
 * traditional C
 */
#ifndef CA_DONT_INCLUDE_STDARGH
#   include <stdarg.h>
#endif

#include "epicsThread.h"

#include "libCaAPI.h"
#include "caerr.h"
#include "db_access.h"
#include "caeventmask.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct oldChannelNotify *chid;
typedef chid                    chanId; /* for when the structures field name is "chid" */
typedef long                    chtype;
typedef struct oldSubscription  *evid;
typedef double                  ca_real;

/* arguments passed to user connection handlers */
struct  connection_handler_args {
    chanId  chid;  /* channel id */
    long    op;    /* one of CA_OP_CONN_UP or CA_OP_CONN_DOWN */
};

typedef void caCh (struct connection_handler_args args);

typedef struct ca_access_rights {
    unsigned    read_access:1;
    unsigned    write_access:1;
} caar;

/* arguments passed to user access rights handlers */
struct  access_rights_handler_args {
    chanId  chid;   /* channel id */
    caar    ar;     /* new access rights state */
};

typedef void caArh (struct access_rights_handler_args args);

/*  The conversion routine to call for each type    */
#define VALID_TYPE(TYPE)  (((unsigned short)TYPE)<=LAST_BUFFER_TYPE)

/*
 * Arguments passed to event handlers and get/put call back handlers.
 *
 * The status field below is the CA ECA_XXX status of the requested
 * operation which is saved from when the operation was attempted in the
 * server and copied back to the clients call back routine.
 * If the status is not ECA_NORMAL then the dbr pointer will be NULL
 * and the requested operation can not be assumed to be successful.
 */
typedef struct event_handler_args {
    void            *usr;   /* user argument supplied with request */
    chanId          chid;   /* channel id */
    long            type;   /* the type of the item returned */
    long            count;  /* the element count of the item returned */
    const void      *dbr;   /* a pointer to the item returned */
    int             status; /* ECA_XXX status of the requested op from the server */
} evargs;
typedef void caEventCallBackFunc (struct event_handler_args);

LIBCA_API void epicsStdCall ca_test_event
(
    struct event_handler_args
);

/* arguments passed to user exception handlers */
struct exception_handler_args {
    void            *usr;   /* user argument supplied when installed */
    chanId          chid;   /* channel id (may be nill) */
    long            type;   /* type requested */
    long            count;  /* count requested */
    void            *addr;  /* user's address to write results of CA_OP_GET */
    long            stat;   /* channel access ECA_XXXX status code */
    long            op;     /* CA_OP_GET, CA_OP_PUT, ..., CA_OP_OTHER */
    const char      *ctx;   /* a character string containing context info */
    const char      *pFile; /* source file name (may be NULL) */
    unsigned        lineNo; /* source file line number (may be zero) */
};

typedef unsigned CA_SYNC_GID;

/*
 *  External OP codes for CA operations
 */
#define CA_OP_GET             0
#define CA_OP_PUT             1
#define CA_OP_CREATE_CHANNEL  2
#define CA_OP_ADD_EVENT       3
#define CA_OP_CLEAR_EVENT     4
#define CA_OP_OTHER           5

/*
 * used with connection_handler_args
 */
#define CA_OP_CONN_UP       6
#define CA_OP_CONN_DOWN     7

/* deprecated */
#define CA_OP_SEARCH        2

/*
 * provides efficient test and display of channel access errors
 */
#define     SEVCHK(CA_ERROR_CODE, MESSAGE_STRING) \
{ \
    int ca_unique_status_name  = (CA_ERROR_CODE); \
    if(!(ca_unique_status_name & CA_M_SUCCESS)) \
        ca_signal_with_file_and_lineno( \
            ca_unique_status_name, \
            (MESSAGE_STRING), \
            __FILE__, \
            __LINE__); \
}


#define TYPENOTCONN (-1) /* the channel's native type when disconnected   */
LIBCA_API short epicsStdCall ca_field_type (chid chan);
LIBCA_API unsigned long epicsStdCall ca_element_count (chid chan);
LIBCA_API const char * epicsStdCall ca_name (chid chan);
LIBCA_API void epicsStdCall ca_set_puser (chid chan, void *puser);
LIBCA_API void * epicsStdCall ca_puser (chid chan);
LIBCA_API unsigned epicsStdCall ca_read_access (chid chan);
LIBCA_API unsigned epicsStdCall ca_write_access (chid chan);

/*
 *  cs_ - `channel state'
 *
 *  cs_never_conn       valid chid, IOC not found
 *  cs_prev_conn        valid chid, IOC was found, but unavailable
 *  cs_conn             valid chid, IOC was found, still available
 *  cs_closed           channel deleted by user
 */
enum channel_state {cs_never_conn, cs_prev_conn, cs_conn, cs_closed};
LIBCA_API enum channel_state epicsStdCall ca_state (chid chan);

/************************************************************************/
/*  Perform Library Initialization                                      */
/*                                                                      */
/*  Must be called once before calling any of the other routines        */
/************************************************************************/
LIBCA_API int epicsStdCall ca_task_initialize (void);
enum ca_preemptive_callback_select
{ ca_disable_preemptive_callback, ca_enable_preemptive_callback };
LIBCA_API int epicsStdCall 
        ca_context_create (enum ca_preemptive_callback_select select);
LIBCA_API void epicsStdCall ca_detach_context (); 

/************************************************************************/
/*  Remove CA facility from your task                                   */
/*                                                                      */
/*  Normally called automatically at task exit                          */
/************************************************************************/
LIBCA_API int epicsStdCall ca_task_exit (void);
LIBCA_API void epicsStdCall ca_context_destroy (void);

typedef unsigned capri;
#define CA_PRIORITY_MAX 99
#define CA_PRIORITY_MIN 0
#define CA_PRIORITY_DEFAULT CA_PRIORITY_MIN

#define CA_PRIORITY_DB_LINKS 80
#define CA_PRIORITY_ARCHIVE 20
#define CA_PRIORITY_OPI 0

/*
 * ca_create_channel ()
 *
 * pChanName            R   channel name string
 * pConnStateCallback   R   address of connection state change
 *                          callback function
 * pUserPrivate         R   placed in the channel's user private field
 *                          o can be fetched later by ca_puser(CHID)
 *                          o passed as void * arg to *pConnectCallback above
 * priority             R   priority level in the server 0 - 100
 * pChanID              RW  channel id written here
 */
LIBCA_API int epicsStdCall ca_create_channel
(
     const char     *pChanName,
     caCh           *pConnStateCallback,
     void           *pUserPrivate,
     capri          priority,
     chid           *pChanID
);

/*
 * ca_change_connection_event()
 *
 * chan     R   channel identifier
 * pfunc    R   address of connection call-back function
 */
LIBCA_API int epicsStdCall ca_change_connection_event
(
     chid       chan,
     caCh *     pfunc
);

/*
 * ca_replace_access_rights_event ()
 *
 * chan     R   channel identifier
 * pfunc    R   address of access rights call-back function
 */
LIBCA_API int epicsStdCall ca_replace_access_rights_event (
     chid   chan,
     caArh  *pfunc
);

/*
 * ca_add_exception_event ()
 *
 * replace the default exception handler
 *
 * pfunc    R   address of exception call-back function
 * pArg     R   copy of this pointer passed to exception
 *          call-back function
 */
typedef void caExceptionHandler (struct exception_handler_args);
LIBCA_API int epicsStdCall ca_add_exception_event
(
     caExceptionHandler *pfunc,
     void               *pArg
);

/*
 * ca_clear_channel()
 * - deallocate resources reserved for a channel
 *
 * chanId   R   channel ID
 */
LIBCA_API int epicsStdCall ca_clear_channel
(
     chid   chanId
);

/************************************************************************/
/*  Write a value to a channel                  */
/************************************************************************/
/*
 * ca_bput()
 *
 * WARNING: this copies the new value from a string (dbr_string_t)
 *      (and not as an integer)
 *
 * chan         R       channel identifier
 * pValue       R       new channel value string copied from this location
 */
#define ca_bput(chan, pValue) \
ca_array_put(DBR_STRING, 1u, chan, (const dbr_string_t *) (pValue))

/*
 * ca_rput()
 *
 * WARNING: this copies the new value from a dbr_float_t
 *
 * chan         R       channel identifier
 * pValue       R       new channel value copied from this location
 */
#define ca_rput(chan,pValue) \
ca_array_put(DBR_FLOAT, 1u, chan, (const dbr_float_t *) pValue)

/*
 * ca_put()
 *
 * type         R   data type from db_access.h
 * chan         R   channel identifier
 * pValue       R   new channel value copied from this location
 */
#define ca_put(type, chan, pValue) ca_array_put (type, 1u, chan, pValue)

/*
 * ca_array_put()
 *
 * type         R   data type from db_access.h
 * count        R   array element count
 * chan         R   channel identifier
 * pValue       R       new channel value copied from this location
 */
LIBCA_API int epicsStdCall ca_array_put
(
     chtype         type,
     unsigned long  count,
     chid           chanId,
     const void *   pValue
);

/*
 * ca_array_put_callback()
 *
 * This routine functions identically to the original ca put request
 * with the addition of a callback to the user supplied function
 * after recod processing completes in the IOC. The arguments
 * to the user supplied callback function are declared in
 * the structure event_handler_args and include the pointer
 * sized user argument supplied when ca_array_put_callback() is called.
 *
 * type         R   data type from db_access.h
 * count        R   array element count
 * chan         R   channel identifier
 * pValue       R       new channel value copied from this location
 * pFunc        R   pointer to call-back function
 * pArg         R   copy of this pointer passed to pFunc
 */
LIBCA_API int epicsStdCall ca_array_put_callback
(
     chtype                 type,
     unsigned long          count,
     chid                   chanId,
     const void *           pValue,
     caEventCallBackFunc *  pFunc,
     void *                 pArg
);

#define ca_put_callback(type, chan, pValue, pFunc, pArg) \
    ca_array_put_callback(type, 1u, chan, pValue, pFunc, pArg)

/************************************************************************/
/*  Read a value from a channel                                         */
/************************************************************************/

/*
 * ca_bget()
 *
 * WARNING: this copies the new value into a string (dbr_string_t)
 *      (and not into an integer)
 *
 * chan     R   channel identifier
 * pValue   W   channel value copied to this location
 */
#define ca_bget(chan, pValue) \
ca_array_get(DBR_STRING, 1u, chan, (dbr_string_t *)(pValue))

/*
 * ca_rget()
 *
 * WARNING: this copies the new value into a 32 bit float (dbr_float_t)
 *
 * chan     R   channel identifier
 * pValue   W   channel value copied to this location
 */
#define ca_rget(chan, pValue) \
ca_array_get(DBR_FLOAT, 1u, chan, (dbr_float_t *)(pValue))

/*
 * ca_rget()
 *
 * type     R   data type from db_access.h
 * chan     R   channel identifier
 * pValue   W   channel value copied to this location
 */
#define ca_get(type, chan, pValue) ca_array_get(type, 1u, chan, pValue)

/*
 * ca_array_get()
 *
 * type     R   data type from db_access.h
 * count    R   array element count
 * chan     R   channel identifier
 * pValue   W   channel value copied to this location
 */
LIBCA_API int epicsStdCall ca_array_get
(
     chtype         type,
     unsigned long  count,
     chid           chanId,
     void *         pValue
);

/************************************************************************/
/*  Read a value from a channel and run a callback when the value       */
/*  returns                                                             */
/*                                                                      */
/*                                                                      */
/************************************************************************/
/*
 * ca_bget_callback()
 *
 * WARNING: this returns the new value as a string (dbr_string_t)
 *      (and not as an integer)
 *
 * chan     R   channel identifier
 * pFunc    R   pointer to call-back function
 * pArg     R   copy of this pointer passed to pFunc
 */
#define ca_bget_callback(chan, pFunc, pArg)\
ca_array_get_callback (DBR_STRING, 1u, chan, pFunc, pArg)

/*
 * ca_rget_callback()
 *
 * WARNING: this returns the new value as a float (dbr_float_t)
 *
 * chan     R   channel identifier
 * pFunc    R   pointer to call-back function
 * pArg     R   copy of this pointer passed to pFunc
 */
#define ca_rget_callback(chan, pFunc, pArg)\
ca_array_get_callback (DBR_FLOAT, 1u, chan, pFunc, pArg)

/*
 * ca_get_callback()
 *
 * type     R   data type from db_access.h
 * chan     R   channel identifier
 * pFunc    R   pointer to call-back function
 * pArg     R   copy of this pointer passed to pFunc
 */
#define ca_get_callback(type, chan, pFunc, pArg)\
ca_array_get_callback (type, 1u, chan, pFunc, pArg)

/*
 * ca_array_get_callback()
 *
 * type     R   data type from db_access.h
 * count    R   array element count
 * chan     R   channel identifier
 * pFunc    R   pointer to call-back function
 * pArg     R   copy of this pointer passed to pFunc
 */
LIBCA_API int epicsStdCall ca_array_get_callback
(
     chtype                 type,
     unsigned long          count,
     chid                   chanId,
     caEventCallBackFunc *  pFunc,
     void *                 pArg
);

/************************************************************************/
/*  Specify a function to be executed whenever significant changes      */
/*  occur to a channel.                                                 */
/*  NOTES:                                                              */
/*  1)  Evid may be omitted by passing a NULL pointer                    */
/*                                                                      */
/*  2)  An array count of zero specifies the native db count            */
/*                                                                      */
/************************************************************************/

/*
 * ca_create_subscription ()
 *
 * type     R   data type from db_access.h
 * count    R   array element count
 * chan     R   channel identifier
 * mask     R   event mask - one of {DBE_VALUE, DBE_ALARM, DBE_LOG}
 * pFunc    R   pointer to call-back function
 * pArg     R   copy of this pointer passed to pFunc
 * pEventID W   event id written at specified address
 */
LIBCA_API int epicsStdCall ca_create_subscription
(
     chtype                 type,
     unsigned long          count,
     chid                   chanId,
     long                   mask,
     caEventCallBackFunc *  pFunc,
     void *                 pArg,
     evid *                 pEventID
);

/************************************************************************/
/*  Remove a function from a list of those specified to run             */
/*  whenever significant changes occur to a channel                     */
/*                                                                      */
/************************************************************************/
/*
 * ca_clear_subscription()
 *
 * eventID  R   event id
 */
LIBCA_API int epicsStdCall ca_clear_subscription
(
     evid eventID
);

LIBCA_API chid epicsStdCall ca_evid_to_chid ( evid id );


/************************************************************************/
/*                                                                      */
/*   Requested data is not necessarily stable prior to                  */
/*   return from called subroutine.  Call ca_pend_io()                  */
/*   to guarantee that requested data is stable.  Call the routine      */
/*   ca_flush_io() to force all outstanding requests to be              */
/*   sent out over the network.  Significant increases in               */
/*   performance have been measured when batching several remote        */
/*   requests together into one message.  Additional                    */
/*   improvements can be obtained by performing local processing        */
/*   in parallel with outstanding remote processing.                    */
/*                                                                      */
/*   FLOW OF TYPICAL APPLICATION                                        */
/*                                                                      */
/*   search()       ! Obtain Channel ids                                */
/*   .              ! "                                                 */
/*   .              ! "                                                 */
/*   pend_io        ! wait for channels to connect                      */
/*                                                                      */
/*   get()          ! several requests for remote info                  */
/*   get()          ! "                                                 */
/*   add_event()    ! "                                                 */
/*   get()          ! "                                                 */
/*   .                                                                  */
/*   .                                                                  */
/*   .                                                                  */
/*   flush_io()     ! send get requests                                 */
/*                  ! optional parallel processing                      */
/*   .              ! "                                                 */
/*   .              ! "                                                 */
/*   pend_io()      ! wait for replies from get requests                */
/*   .              ! access to requested data                          */
/*   .              ! "                                                 */
/*   pend_event()   ! wait for requested events                         */
/*                                                                      */
/************************************************************************/

/************************************************************************/
/*  These routines wait for channel subscription events and call the    */
/*  functions specified with add_event when events occur. If the        */
/*  timeout is specified as 0 an infinite timeout is assumed.           */
/*  ca_flush_io() is called by this routine. If ca_pend_io ()           */
/*  is called when no IO is outstanding then it will return immediately */
/*  without processing.                                                 */
/************************************************************************/

/*
 * ca_pend_event()
 *
 * timeout  R   wait for this delay in seconds
 */
LIBCA_API int epicsStdCall ca_pend_event (ca_real timeout);
#define ca_poll() ca_pend_event(1e-12)

/*
 * ca_pend_io()
 *
 * timeout  R   wait for this delay in seconds but return early
 *              if all get requests (or search requests with null
 *              connection handler pointer have completed)
 */
LIBCA_API int epicsStdCall ca_pend_io (ca_real timeout);

/* calls ca_pend_io() if early is true otherwise ca_pend_event() is called */
LIBCA_API int epicsStdCall ca_pend (ca_real timeout, int early);

/*
 * ca_test_io()
 *
 * returns TRUE when get requests (or search requests with null
 * connection handler pointer) are outstanding
 */
LIBCA_API int epicsStdCall ca_test_io (void);

/************************************************************************/
/*  Send out all outstanding messages in the send queue                 */
/************************************************************************/
/*
 * ca_flush_io()
 */
LIBCA_API int epicsStdCall ca_flush_io (void);


/*
 *  ca_signal()
 *
 * errorCode    R   status returned from channel access function
 * pCtxStr  R   context string included with error print out
 */
LIBCA_API void epicsStdCall ca_signal
(
     long errorCode,
     const char *pCtxStr
);

/*
 * ca_signal_with_file_and_lineno()
 * errorCode    R   status returned from channel access function
 * pCtxStr  R   context string included with error print out
 * pFileStr R   file name string included with error print out
 * lineNo   R   line number included with error print out
 *
 */
LIBCA_API void epicsStdCall ca_signal_with_file_and_lineno
(
     long errorCode,
     const char *pCtxStr,
     const char *pFileStr,
     int lineNo
);

/*
 * ca_signal_formated()
 * errorCode    R   status returned from channel access function
 * pFileStr     R   file name string included with error print out
 * lineNo       R   line number included with error print out
 * pFormat      R   printf dtyle format string (and optional arguments)
 *
 */
LIBCA_API void epicsStdCall ca_signal_formated (long ca_status, const char *pfilenm, 
                                       int lineno, const char *pFormat, ...);

/*
 * ca_host_name_function()
 *
 * channel  R   channel identifier
 *
 * !!!! this function is _not_ thread safe !!!!
 */
LIBCA_API const char * epicsStdCall ca_host_name (chid channel);
/* thread safe version */
LIBCA_API unsigned epicsStdCall ca_get_host_name ( chid pChan, 
    char *pBuf, unsigned bufLength );

/*
 *  CA_ADD_FD_REGISTRATION
 *
 *  call their function with their argument whenever
 *  a new fd is added or removed
 *  (for use with a manager of the select system call under UNIX)
 *
 *  if (opened) then fd was created
 *  if (!opened) then fd was deleted
 *
 */
typedef void CAFDHANDLER (void *parg, int fd, int opened);

/*
 * ca_add_fd_registration()
 *
 * pHandler R   pointer to function which is to be called
 *                  when an fd is created or deleted
 * pArg     R   argument passed to above function
 */
LIBCA_API int epicsStdCall ca_add_fd_registration
(
     CAFDHANDLER    *pHandler,
     void           *pArg
);


/*
 * CA synch groups
 *
 * This facility will allow the programmer to create
 * any number of synchronization groups. The programmer might then
 * interleave IO requests within any of the groups. Once The
 * IO operations are initiated then the programmer is free to
 * block for IO completion within any one of the groups as needed.
 */

/*
 * ca_sg_create()
 *
 * create a sync group
 *
 * pgid     W   pointer to sync group id that will be written
 */
LIBCA_API int epicsStdCall ca_sg_create (CA_SYNC_GID *  pgid);

/*
 * ca_sg_delete()
 *
 * delete a sync group
 *
 * gid      R   sync group id
 */
LIBCA_API int epicsStdCall ca_sg_delete (const CA_SYNC_GID gid);

/*
 * ca_sg_block()
 *
 * block for IO performed within a sync group to complete
 *
 * gid      R   sync group id
 * timeout  R   wait for this duration prior to timing out
 *          and returning ECA_TIMEOUT
 */
LIBCA_API int epicsStdCall ca_sg_block (const CA_SYNC_GID gid, ca_real timeout);

/*
 * ca_sg_test()
 *
 * test for sync group IO operations in progress
 *
 * gid      R   sync group id
 *
 * returns one of ECA_BADSYNCGRP, ECA_IOINPROGRESS, ECA_IODONE
 */
LIBCA_API int epicsStdCall ca_sg_test (const CA_SYNC_GID gid);

/*
 * ca_sg_reset
 *
 * gid      R   sync group id
 */
LIBCA_API int epicsStdCall ca_sg_reset(const CA_SYNC_GID gid);

/*
 * ca_sg_array_get()
 *
 * initiate a get within a sync group
 * (essentially a ca_array_get() with a sync group specified)
 *
 * gid      R   sync group id
 * type     R   data type from db_access.h
 * count    R   array element count
 * chan     R   channel identifier
 * pValue   W   channel value copied to this location
 */
LIBCA_API int epicsStdCall ca_sg_array_get
(
    const CA_SYNC_GID gid,
    chtype type,
    unsigned long count,
    chid chan,
    void *pValue
);

#define ca_sg_get(gid, type, chan, pValue) \
ca_sg_array_get (gid, type, 1u, chan, pValue)

/*
 * ca_sg_array_put()
 *
 * initiate a put within a sync group
 * (essentially a ca_array_put() with a sync group specified)
 *
 * gid      R   sync group id
 * type     R   data type from db_access.h
 * count    R   array element count
 * chan     R   channel identifier
 * pValue   R   new channel value copied from this location
 */
LIBCA_API int epicsStdCall ca_sg_array_put
(
    const CA_SYNC_GID gid,
    chtype type,
    unsigned long count,
    chid chan,
    const void *pValue
);

#define ca_sg_put(gid, type, chan, pValue) \
ca_sg_array_put (gid, type, 1u, chan, pValue)

/*
 * ca_sg_stat()
 *
 * print status of a sync group
 *
 * gid      R   sync group id
 */
LIBCA_API int epicsStdCall ca_sg_stat (CA_SYNC_GID gid);

LIBCA_API void epicsStdCall ca_dump_dbr (chtype type, unsigned count, const void * pbuffer);


/*
 * ca_v42_ok()
 *
 * Put call back is available if the CA server is on version is 4.2
 *  or higher.
 *
 * chan     R   channel identifier
 *
 * (returns true or false)
 */
LIBCA_API int epicsStdCall ca_v42_ok (chid chan);

/*
 * ca_version()
 *
 * returns the CA version string
 */
LIBCA_API const char * epicsStdCall ca_version (void);

/*
 * ca_replace_printf_handler ()
 *
 * for apps that want to change where ca formatted
 * text output goes
 *
 * use two ifdef's for trad C compatibility
 *
 * ca_printf_func   R   pointer to new function called when
 *                          CA prints an error message
 */
#ifndef CA_DONT_INCLUDE_STDARGH
typedef int caPrintfFunc (const char *pformat, va_list args);
LIBCA_API int epicsStdCall ca_replace_printf_handler (
    caPrintfFunc    *ca_printf_func
);
#endif /*CA_DONT_INCLUDE_STDARGH*/

/*
 * (for testing purposes only)
 */
LIBCA_API unsigned epicsStdCall ca_get_ioc_connection_count (void);
LIBCA_API int epicsStdCall ca_preemtive_callback_is_enabled (void);
LIBCA_API void epicsStdCall ca_self_test (void);
LIBCA_API unsigned epicsStdCall ca_beacon_anomaly_count (void);
LIBCA_API unsigned epicsStdCall ca_search_attempts (chid chan);
LIBCA_API double epicsStdCall ca_beacon_period (chid chan);
LIBCA_API double epicsStdCall ca_receive_watchdog_delay (chid chan);

/*
 * used when an auxiliary thread needs to join a CA client context started
 * by another thread
 */
LIBCA_API struct ca_client_context * epicsStdCall ca_current_context ();
LIBCA_API int epicsStdCall ca_attach_context ( struct ca_client_context * context );


LIBCA_API int epicsStdCall ca_client_status ( unsigned level );
LIBCA_API int epicsStdCall ca_context_status ( struct ca_client_context *, unsigned level );

/*
 * deprecated
 */
#define ca_build_channel(NAME,XXXXX,CHIDPTR,YYYYY)\
ca_build_and_connect(NAME, XXXXX, 1, CHIDPTR, YYYYY, 0, 0)
#define ca_array_build(NAME,XXXXX, ZZZZZZ, CHIDPTR,YYYYY)\
ca_build_and_connect(NAME, XXXXX, ZZZZZZ, CHIDPTR, YYYYY, 0, 0)
LIBCA_API int epicsStdCall ca_build_and_connect
    ( const char *pChanName, chtype, unsigned long,
    chid * pChanID, void *, caCh * pFunc, void * pArg );
#define ca_search(pChanName, pChanID)\
ca_search_and_connect (pChanName, pChanID, 0, 0)
LIBCA_API int epicsStdCall ca_search_and_connect
    ( const char * pChanName, chid * pChanID,
    caCh *pFunc, void * pArg );
LIBCA_API int epicsStdCall ca_channel_status (epicsThreadId tid);
LIBCA_API int epicsStdCall ca_clear_event ( evid eventID );
#define ca_add_event(type,chan,pFunc,pArg,pEventID)\
ca_add_array_event(type,1u,chan,pFunc,pArg,0.0,0.0,0.0,pEventID)
#define ca_add_delta_event(TYPE,CHID,ENTRY,ARG,DELTA,EVID)\
    ca_add_array_event(TYPE,1,CHID,ENTRY,ARG,DELTA,DELTA,0.0,EVID)
#define ca_add_general_event(TYPE,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)\
ca_add_array_event(TYPE,1,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)
#define ca_add_array_event(TYPE,COUNT,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)\
ca_add_masked_array_event(TYPE,COUNT,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID, DBE_VALUE | DBE_ALARM)
LIBCA_API int epicsStdCall ca_add_masked_array_event
    ( chtype type, unsigned long count, chid chanId, caEventCallBackFunc * pFunc,
        void * pArg, ca_real p_delta, ca_real n_delta, ca_real timeout,
        evid * pEventID, long mask );

/*
 * defunct
 */
LIBCA_API int epicsStdCall ca_modify_user_name ( const char *pUserName );
LIBCA_API int epicsStdCall ca_modify_host_name ( const char *pHostName );

#ifdef __cplusplus
}
#endif

/*
 * no additions below this endif
 */
#endif /* ifndef INC_cadef_H */

