/*-----------------------------------------------------------------------------
 * Copyright (c) 1994,1995 Southeastern Universities Research Association,
 *               Continuous Electron Beam Accelerator Facility
 *
 * This software was developed under a United States Government license
 * described in the NOTICE file included as part of this distribution.
 *
 *-----------------------------------------------------------------------------
 *
 * Description:
 *      C public interface for CDEV
 *
 * Authors:  Danjin Wu & Jie Chen
 *
 * Revision History:
 *   cdev.h,v
 * Revision 1.3  1997/08/27  18:24:18  chen
 * include cdevVersion.h
 *
 * Revision 1.2  1996/03/22  17:56:51  chen
 * add cdevFdChangedCallback
 *
 * Revision 1.1  1995/12/14  19:09:16  chen
 * cdev C interface for C programs
 *
 *
 */
#ifndef  _CDEV_CBINDING_H
#define  _CDEV_CBINDING_H

#include <stdio.h>
#include <stdlib.h>
#include <cdevVersion.h>
#include <cdevErrCode.h>
#include <cdevSpec.h>

typedef long cdev_data_t; 
typedef long cdev_request_t;
typedef long cdev_system_t;
typedef long cdev_group_t;

/*************************************************************************
 *     User error reporting function                                     *
 *************************************************************************/
typedef void (*cdevErrHandler) (int severity,
				char* text,
				cdev_request_t req);

/*************************************************************************
 *     User fd changed callback function                                 *
 *************************************************************************/
typedef void (*cdevFdChangedCallback) (int fd,
				       int opened,
				       void* arg);

/**************************************************************************
 *     User callback function                                             *
 *************************************************************************/
typedef void (*cdevCbkFunc)    (int status,
				void* userarg,
				cdev_request_t req,
				cdev_data_t data);

typedef struct _cbk_t_ 
{
  cdevCbkFunc     func;
  void*           arg;
  /* the following element is not for public use */
  void*           cxxpart; 
}cdev_cbk, *cdev_cbk_t;

/**************************************************************************
 *       HPUX C  call C++ convention                                      *
 *            User must call this before any other routines to            *
 *            Initialize all static objects                               *
 **************************************************************************/
#ifdef __hpux
#define CDEV_INIT() (_main () )
#endif

/**************************************************************************
 *       CDEV supported data types inside cdev_data_t                     *
 **************************************************************************/
#define  CDEV_BYTE_    0       /* unsigned character                      */
#define  CDEV_INT_16   1       /* 16 bits integer                         */
#define  CDEV_UINT_16  2       /* unsigned 16 bits integer                */
#define  CDEV_INT_32   3       /* 32 bits integer                         */
#define  CDEV_UINT_32  4       /* unsigned 32 bits integer                */
#define  CDEV_FLT      5       /* float                                   */
#define  CDEV_DBL      6       /* double                                  */
#define  CDEV_STR      7       /* character string                        */
#define  CDEV_TS       8       /* structured time stamp with sec and nsec */
#define  CDEV_INVALID_TYPE 9   /* not belongs to any type above           */

#define CDEV_IMMEDIATE 0       /* cdev group exection immediately         */
#define CDEV_DEFERRED  1       /* cdev group exection deferred            */

#ifdef __cplusplus
extern "C" {
#endif

/**************************************************************************
 *    C interface for cdev_data_t                                         *
 *************************************************************************/

/*    create and allocate for cdev_data_t                                */
extern CDEVAPI int  cdevDataAllocate    (cdev_data_t *id);

/*    free memory associated with cdev_data_t                            */
extern CDEVAPI void cdevDataFree        (cdev_data_t id);

/*    convert a character string tag to an integer tag                   */
extern CDEVAPI int  cdevDataTagC2I      (char *tag, int *tagid);

/*    convert an integer tag to a character string tag.                  */
/*    the return tag is a pointer to internal char string.               */
/*    do not free the tag !!!                                            */
extern CDEVAPI int  cdevDataTagI2C      (int tagid, char **tag);

/*    insert an new tag to cdev_data_t data                              */
extern CDEVAPI void cdevDataInsertTag   (int tagid, char *tag);

/*    insert a new data with data type 'type' pointed by data            */
extern CDEVAPI int  cdevDataInsert      (cdev_data_t id, int tagid, 
                                         int type, void *data);

/*    insert an array of data into cdev_data_t                           */
extern CDEVAPI int  cdevDataInsertArray (cdev_data_t id, int tagid, 
                                         int type, void *data, 
				 size_t len, size_t ndim);

/*    retrieve data with tag 'tagid' to memory pointed by 'data'         */
extern CDEVAPI int  cdevDataGet         (cdev_data_t id, int tagid, 
                                         int type, void *data);

/*    return the memory address of data with tag 'tagid'                 */
extern CDEVAPI int  cdevDataFind        (cdev_data_t id, int tagid, void **data);

/*    return data type associated with tag 'tagid'                       */
extern CDEVAPI int  cdevDataGetType     (cdev_data_t id, int tagid, int *type);

/*    return dimention information with tag 'tagid'                      */
extern CDEVAPI int  cdevDataGetDim      (cdev_data_t id, int tagid, size_t *dim);

/*    get number of elements associated with tag 'tagid'                 */
extern CDEVAPI int  cdevDataGetElems    (cdev_data_t id, int tagid, size_t *elems);

/*    get information about where to start/end inside the multiple       */
/*    dimentional array of data for this tag 'tagid'                     */
extern CDEVAPI int  cdevDataGetBounds   (cdev_data_t id, int tagid, 
                                         size_t *bounds, size_t bsize);

/*    set information about where to start/end inside the multiple       */
/*    dimentional array of data for this tag 'tagid'                     */
extern CDEVAPI int  cdevDataSetBounds   (cdev_data_t id, int tagid, 
                                         size_t *bounds, size_t bsize);

/*    remove all data inside cdev_data_t 'id'                            */
extern CDEVAPI void cdevDataRemoveAll   (cdev_data_t id);

/*    remove a single data item from a cdev_data_t with tag 'tagid'      */
extern CDEVAPI void cdevDataRemove      (cdev_data_t id, int tagid);

/*    change tag associated with a data item from 'tagid' to 'newtagid'  */
extern CDEVAPI int  cdevDataChangeTag   (cdev_data_t id, int tagid, int newtagid);

/*    print out ASCII representation of all internal data of 'id'        */
#ifdef _WIN32
extern CDEVAPI void cdevDataAsciiDump   (cdev_data_t id);
#else
extern CDEVAPI void cdevDataAsciiDump   (cdev_data_t id, FILE *fp);
#endif

/*    copy cdev_data_t from 'from' to 'to'                               */
extern CDEVAPI void cdevDataCopy        (cdev_data_t from, cdev_data_t *to);

/*************************************************************************
 *    C interface for setting up user callback routines                  *
 ************************************************************************/

/*    create cdev_cbk_t structure with 'func' and 'arg'                 */
extern CDEVAPI int  cdevCbkAllocate (cdevCbkFunc func, void* arg, cdev_cbk_t* id);

/*    destroy/free cdev_cbk_t structure pointed by id                   */
extern CDEVAPI void cdevCbkFree     (cdev_cbk_t id);

/************************************************************************
 *    C interface for cdev global system                                *
 ***********************************************************************/

/*    get a handle on the default system, do not use it now :-)        */
extern CDEVAPI int  cdevDefaultSystem   (cdev_system_t* sys);

/*    return all file descriptors inside the cdev. caller provide      */
/*    buffer for fds and intial value of numFds should be the buffer   */
/*    size. e.g. int fds[10], numFds = 10, cdevGetFds (fds, &numFds)   */
/*    If success, numFds has real number of fd                         */
extern CDEVAPI int  cdevGetFds          (int fds[], int* numFds);

/*    add a callback function which will be called when file           */
/*    descriptors monitored by the system closed/opend                 */
/*    Note: service dependent. Underlying cdevService must provide     */
/*    some mechanism to notify the system (see caService)              */
extern CDEVAPI int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg);

/*    flush out all network requests                                   */
extern CDEVAPI int  cdevFlush           (void);

/*    wait for network requests to come back for upto 'seconds'        */
/*    long. If seconds = 0.0, wait forever                             */
extern CDEVAPI int  cdevPend            (double seconds);

/*    poll the network to see whether there are outstanding I/O       */
/*    events on all communication channels.                           */
extern CDEVAPI int  cdevPoll            (void);

/*    turn automatic error reporting mechanism on: system error       */
/*    reporting function will be in charge                            */
extern CDEVAPI int  cdevAutoErrorOn     (void);

/*    turn automatic error reporting mechanism off: user error        */
/*    reporting function will be in charge (if there is one)          */
extern CDEVAPI int  cdevAutoErrorOff    (void);

/*    set error reporting threshold. check cdev_error_code.h to see   */
/*    all available threshold values.                                 */
extern CDEVAPI void cdevSetThreshold    (int errorThreshold);

/*    set your own error reporting function. If func = 0, default     */
/*    system error reporting function will be used                    */
extern CDEVAPI void cdevSetErrorHandler (cdevErrHandler func);

/*    printf like error reporting interface                           */
extern CDEVAPI int  cdevReportError     (int severity, char* name,
                                         cdev_request_t req, char* format, ...);

/**********************************************************************
 *    cdev high level I/O operations                                  *
 *********************************************************************/

/*    synchronous send with device/msg pair + out/in data            */
extern CDEVAPI int  cdevSend            (char* device, char* msg,
                                         cdev_data_t out, cdev_data_t result);

/*    asynchronous send with device/msg pair + out/in data           */
/*    caller has to use synchronization mechanism to retrieve        */
/*    result by cdevGroupPend or cdevPend methods                    */
extern CDEVAPI int  cdevSendNoBlock     (char* device, char* msg,
                                         cdev_data_t out, cdev_data_t result);

/*    asynchronous send with device/msg pair + out data and a        */
/*    user provided callback.                                        */
/*    caller has to use synchronization mechanism to retrieve        */
/*    result by cdevGroupPend or cdevPend methods                    */
extern CDEVAPI int  cdevSendCallback    (char* device, char* msg,
                                         cdev_data_t out, cdev_cbk_t cbk);

/*    get context associcated with a device 'device'                 */
extern CDEVAPI int  cdevGetContext      (char* device, cdev_data_t* data);

/*    set context for the device 'device'                            */
extern CDEVAPI int  cdevSetContext      (char* device, cdev_data_t data);

/*    set private data for device 'device'                           */
extern CDEVAPI int  cdevSetPrivate      (char* device, void* data);

/*    get private data associated with this 'device'                 */
extern CDEVAPI int  cdevGetPrivate      (char* device, void** data);

/*********************************************************************
 *    Efficient cdev I/O handle routines                             *
 ********************************************************************/

/*    Create/Allocate cdev_request_t object                         */
extern CDEVAPI int  cdevRequestAllocate    (char* device, char* msg, 
                                            cdev_request_t* id);

/*    Destroy/Free a cdev_request_t object                          */
extern CDEVAPI void cdevRequestFree        (cdev_request_t id);

/*    synchronous send by a cdev_request_t object                   */
extern CDEVAPI int  cdevRequestSend        (cdev_request_t id,
                                            cdev_data_t    out,
                                            cdev_data_t    result);

/*    asynchronous send. user has use synchronization routines      */
/*    such as cdevGroupPend or cdevPend etc to get result           */
extern CDEVAPI int  cdevRequestSendNoBlock (cdev_request_t id,
                                            cdev_data_t    out,
                                            cdev_data_t    result);

/*    asynchronous send with callback. user has use synchronization */
/*    routines such as cdevGroupPend or cdevPend etc to get result  */
extern CDEVAPI int  cdevRequestSendCallback(cdev_request_t id,
                                            cdev_data_t    out,
                                            cdev_cbk_t     cbk);

/*    get current communication state of cdev_request_t. e.g.       */
/*    connected or disconnected                                     */
extern CDEVAPI int  cdevRequestState       (cdev_request_t id);
  
/*    get access right of this cdev_request_t. e.g. readonly        */
extern CDEVAPI int  cdevRequestAccess      (cdev_request_t id);

/*    get device name associated with this cdev_request_t. caller   */
/*    has control of memory of 'device'.                            */
/*    e.g. char *device; cdevRequestDevice (id, &device);           */
/*         free (device);                                           */
extern CDEVAPI int  cdevRequestDevice      (cdev_request_t id, char** device);

/*    get message  associated with this cdev_request_t. caller      */
/*    has control of memory of 'msg'.                               */
/*    e.g. char *msg; cdevRequestMessage (id, &msg);                */
/*         free (msg);                                              */
extern CDEVAPI int  cdevRequestMessage     (cdev_request_t id, char** msg);

/*    get context associated with this request. caller has          */
/*    control of memory of return 'cxt'.                            */
/*    e.g. cdev_data_t data; cdevRequestGetContext (id, &data);     */
/*    cdevDataFree (data);                                          */
extern CDEVAPI int  cdevRequestGetContext  (cdev_request_t id, cdev_data_t* cxt);

/*    set context for this I/O request                              */
extern CDEVAPI int  cdevRequestSetContext  (cdev_request_t id, cdev_data_t cxt);

/*    get private data associated with this request. returned       */
/*    data is just a pointer                                        */
extern CDEVAPI int  cdevRequestGetPrivate  (cdev_request_t id, void** data);

/*    set private data to this request                              */
extern CDEVAPI int  cdevRequestSetPrivate  (cdev_request_t id, void* data);

/********************************************************************
 *     cdev group routines useful for synchronization of multiple   *
 *     asynchronous I/O requests                                    *
 *******************************************************************/

/*     create/allocate a new cdev group                            */
extern CDEVAPI int  cdevGroupAllocate      (cdev_group_t* id);

/*     destroy/free a cdev group                                   */
extern CDEVAPI void cdevGroupFree          (cdev_group_t id);

/*     start a cdev group, all I/O requests will be registered     */
/*     this group                                                  */
extern CDEVAPI int  cdevGroupStart         (cdev_group_t id);

/*     end a cdev group                                            */
extern CDEVAPI int  cdevGroupEnd           (cdev_group_t id);

/*     poll the network to see whether there are outstanding       */
/*     I/O events pending  for this group                          */
extern CDEVAPI int  cdevGroupPoll          (cdev_group_t id);

/*     wait for all I/O requests upto 'seconds'. If seconds = 0.0  */
/*     wait until all I/O requests of this group have come back    */
extern CDEVAPI int  cdevGroupPend          (cdev_group_t id, double seconds);

/*     flush all I/O requests                                      */
extern CDEVAPI int  cdevGroupFlush         (cdev_group_t id);

/*     check whether all I/O requests inside this group have come  */
/*     back. return 1: yes, return 0: no                           */
extern CDEVAPI int  cdevGroupAllFinished   (cdev_group_t id);

/*     check all I/O requests status inside the group. caller      */
/*     provide large enough integer buffer and initial size of     */
/*     buffer. It returns with real number of I/O requests and     */
/*     status[i] = 0 stands for a finished I/O, status[i] = 1      */
/*     stands for a unfinished I/O.                                */
/*     e.g. int status[100], nstatus = 100;                        */
/*          cdevGroupStatus (id, status, &nstatus);                */
/*          for (i = 0; i < nstatus; i++)                          */
/*             if (status[i] == 0) do something                    */
extern CDEVAPI int  cdevGroupStatus        (cdev_group_t id, 
				    int status[], int* nstatus);

/*     do not buffer I/O requests. send them out immediatly.       */
/*     This is the default mode                                    */
extern CDEVAPI int  cdevGroupExecImmediate (cdev_group_t id);

/*     defer execution of all I/O requests inside the group until  */
/*     cdevGroup flush is called                                   */
extern CDEVAPI int  cdevGroupExecDeferred  (cdev_group_t id);

/*     return the execution mode of this group                     */
extern CDEVAPI int  cdevGroupExecutionMode (cdev_group_t id, int* mode);

#ifdef __cplusplus
};
#endif

#endif
