From e4f2e7501f3c170f0b2e56a69632c715e087eb87 Mon Sep 17 00:00:00 2001
From: Taras Zaporozhets <zaporozhets.taras@gmail.com>
Date: 周二, 13 8月 2019 02:15:30 +0800
Subject: [PATCH] Add basic VXI11 support

---
 examples/test-vxi11/main.c      |  632 +++++++++++++++++++++++++++++++++
 examples/test-vxi11/Makefile    |   21 +
 examples/test-vxi11/vxi11_xdr.c |  462 ++++++++++++++++++++++++
 3 files changed, 1,115 insertions(+), 0 deletions(-)

diff --git a/examples/test-vxi11/Makefile b/examples/test-vxi11/Makefile
new file mode 100644
index 0000000..41e0277
--- /dev/null
+++ b/examples/test-vxi11/Makefile
@@ -0,0 +1,21 @@
+
+PROG = test
+
+SRCS = main.c vxi11_xdr.c ../common/scpi-def.c
+CFLAGS += -Wextra -Wmissing-prototypes -Wimplicit -I ../../libscpi/inc/ -I /usr/include/tirpc
+LDFLAGS += -lm -ltirpc ../../libscpi/dist/libscpi.a -Wl,--as-needed
+
+.PHONY: clean all
+
+all: $(PROG)
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
+
+$(PROG): $(OBJS)
+	$(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS)
+
+clean:
+	$(RM) $(PROG) $(OBJS)
diff --git a/examples/test-vxi11/main.c b/examples/test-vxi11/main.c
new file mode 100644
index 0000000..e9083b3
--- /dev/null
+++ b/examples/test-vxi11/main.c
@@ -0,0 +1,632 @@
+#include "vxi11.h"
+#include <memory.h>
+#include <netinet/in.h>
+#include <rpc/pmap_clnt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include "../common/scpi-def.h"
+#include "scpi/scpi.h"
+
+#ifndef SIG_PF
+#define SIG_PF void (*)(int)
+#endif
+
+#define RX_BUF_SIZE 512
+
+/* a global output buffer to collect output data */
+#define SCPI_OUPUT_BUFFER_SIZE (256)
+char SCPI_outputBuffer[SCPI_OUPUT_BUFFER_SIZE];
+unsigned int SCPI_outputBuffer_wr_idx = 0;
+unsigned int SCPI_outputBuffer_rd_idx = 0;
+
+char available_bytes = 0;
+
+enum {
+    VXI11_CORE_ERROR_NO_ERROR = 0,
+    VXI11_CORE_ERROR_SYNTAX_ERROR = 1,
+    VXI11_CORE_ERROR_DEVICE_NOT_ACCESSIBLE = 3,
+    VXI11_CORE_ERROR_INVALID_ID = 4,
+    VXI11_CORE_ERROR_PARAMETER_ERROR = 5,
+    VXI11_CORE_ERROR_CHANNEL_NOT_ESTABLISHED = 6,
+    VXI11_CORE_ERROR_OPERATION_NOT_SUPPORTED = 8,
+    VXI11_CORE_ERROR_OUT_OF_RESOURCES = 9,
+    VXI11_CORE_ERROR_DEVICE_LOCKED = 11,
+    VXI11_CORE_ERROR_NO_LOCK_HELD = 12,
+    VXI11_CORE_ERROR_IO_TIMEOUT = 15,
+    VXI11_CORE_ERROR_IO_ERROR = 17,
+    VXI11_CORE_ERROR_INVALID_ADDRESS = 21,
+    VXI11_CORE_ERROR_ABORT = 23,
+    VXI11_CORE_ERROR_CHANNEL_ALREADY_ESTABLISHED = 29
+};
+
+enum {
+    VXI11_REASON_REQCNT = 1,
+    VXI11_REASON_CHR = 2,
+    VXI11_REASON_END = 4
+};
+
+size_t SCPI_Write(scpi_t* context, const char* data, size_t len)
+{
+    if (STB_MAV & SCPI_RegGet(context, SCPI_REG_STB)) {
+        SCPI_RegClearBits(context, SCPI_REG_STB, STB_MAV);
+        SCPI_ErrorPush(context, SCPI_ERROR_QUERY_INTERRUPTED);
+        // Restart output buffer index
+        SCPI_outputBuffer_wr_idx = 0;
+        SCPI_outputBuffer_rd_idx = 0;
+    }
+
+    if ((SCPI_outputBuffer_wr_idx + len) > (SCPI_OUPUT_BUFFER_SIZE - 1)) {
+        len = (SCPI_OUPUT_BUFFER_SIZE - 1) - SCPI_outputBuffer_wr_idx; /* limit length to left over space */
+        /* apparently there is no mechanism to cope with buffers that are too small */
+    }
+    memcpy(&SCPI_outputBuffer[SCPI_outputBuffer_wr_idx], data, len);
+    SCPI_outputBuffer_wr_idx += len;
+
+    SCPI_outputBuffer[SCPI_outputBuffer_wr_idx] = '\0';
+    return 0;
+}
+
+scpi_result_t SCPI_Flush(scpi_t* context)
+{
+    SCPI_RegSetBits(context, SCPI_REG_STB, STB_MAV);
+    SCPI_outputBuffer_rd_idx = 0;
+    return SCPI_RES_OK;
+}
+
+int SCPI_Error(scpi_t* context, int_fast16_t err)
+{
+    (void)context;
+    /* BEEP */
+    fprintf(stderr, "**ERROR: %d, \"%s\"\r\n", (int16_t)err, SCPI_ErrorTranslate(err));
+    return 0;
+}
+
+scpi_result_t SCPI_Control(scpi_t* context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val)
+{
+    (void)context;
+
+    if (SCPI_CTRL_SRQ == ctrl) {
+        fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val);
+    } else {
+        fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val);
+    }
+    return SCPI_RES_OK;
+}
+
+scpi_result_t SCPI_Reset(scpi_t* context)
+{
+    (void)context;
+
+    fprintf(stderr, "**Reset\r\n");
+    return SCPI_RES_OK;
+}
+
+scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t* context)
+{
+    (void)context;
+
+    return SCPI_RES_ERR;
+}
+
+bool_t
+device_abort_1_svc(Device_Link* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    bool_t retval;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+int device_async_1_freeresult(SVCXPRT* transp, xdrproc_t xdr_result, caddr_t result)
+{
+    xdr_free(xdr_result, result);
+    return 1;
+}
+
+bool_t
+create_link_1_svc(Create_LinkParms* argp, Create_LinkResp* result, struct svc_req* rqstp)
+{
+    result->lid = 0;
+    result->maxRecvSize = RX_BUF_SIZE;
+    result->abortPort = rqstp->rq_xprt->xp_port;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_write_1_svc(Device_WriteParms* argp, Device_WriteResp* result, struct svc_req* rqstp)
+{
+    SCPI_Input(&scpi_context, argp->data.data_val, argp->data.data_len);
+    result->size = argp->data.data_len;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_read_1_svc(Device_ReadParms* argp, Device_ReadResp* result, struct svc_req* rqstp)
+{
+    if (STB_MAV & SCPI_RegGet(&scpi_context, SCPI_REG_STB)) {
+
+        char* data = NULL;
+
+        uint32_t in_buffer = (SCPI_outputBuffer_wr_idx - SCPI_outputBuffer_rd_idx);
+        uint32_t to_copy = (argp->requestSize > in_buffer) ? in_buffer : argp->requestSize;
+
+        data = (unsigned char*)malloc(to_copy);
+        if (NULL == data) {
+            result->error = VXI11_CORE_ERROR_IO_ERROR;
+            return 1;
+        }
+
+        memcpy(data, &SCPI_outputBuffer[SCPI_outputBuffer_rd_idx], to_copy);
+        SCPI_outputBuffer_rd_idx += to_copy;
+
+        result->data.data_val = (char*)data;
+        result->data.data_len = (u_int)to_copy;
+
+        result->reason = (to_copy == argp->requestSize) ? VXI11_REASON_REQCNT : 0;
+
+        fprintf(stderr, "in_buffer: %d\n", in_buffer);
+        fprintf(stderr, "to_copy: %d\n", to_copy);
+        fprintf(stderr, "SCPI_outputBuffer_wr_idx: %d\n", SCPI_outputBuffer_wr_idx);
+        fprintf(stderr, "SCPI_outputBuffer_rd_idx: %d\n", SCPI_outputBuffer_rd_idx);
+
+        if (SCPI_outputBuffer_rd_idx == SCPI_outputBuffer_wr_idx) {
+            SCPI_RegClearBits(&scpi_context, SCPI_REG_STB, STB_MAV);
+            SCPI_outputBuffer_wr_idx = 0;
+            SCPI_outputBuffer_rd_idx = 0;
+            result->reason |= VXI11_REASON_END;
+        }
+
+        result->error = VXI11_CORE_ERROR_NO_ERROR;
+    } else {
+        result->error = VXI11_CORE_ERROR_IO_TIMEOUT;
+    }
+
+    return 1;
+}
+
+bool_t
+device_readstb_1_svc(Device_GenericParms* argp, Device_ReadStbResp* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->stb = (u_char)SCPI_RegGet(&scpi_context, SCPI_REG_STB);
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_trigger_1_svc(Device_GenericParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_clear_1_svc(Device_GenericParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_remote_1_svc(Device_GenericParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_local_1_svc(Device_GenericParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_lock_1_svc(Device_LockParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_unlock_1_svc(Device_Link* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_enable_srq_1_svc(Device_EnableSrqParms* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+device_docmd_1_svc(Device_DocmdParms* argp, Device_DocmdResp* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+destroy_link_1_svc(Device_Link* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+create_intr_chan_1_svc(Device_RemoteFunc* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+bool_t
+destroy_intr_chan_1_svc(void* argp, Device_Error* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)rqstp;
+    result->error = VXI11_CORE_ERROR_NO_ERROR;
+    return 1;
+}
+
+int device_core_1_freeresult(SVCXPRT* transp, xdrproc_t xdr_result, caddr_t result)
+{
+    (void)transp;
+    xdr_free(xdr_result, result);
+    return 1;
+}
+
+bool_t
+device_intr_srq_1_svc(Device_SrqParms* argp, void* result, struct svc_req* rqstp)
+{
+    (void)argp;
+    (void)result;
+    (void)rqstp;
+    return 1;
+}
+
+int device_intr_1_freeresult(SVCXPRT* transp, xdrproc_t xdr_result, caddr_t result)
+{
+    (void)transp;
+    xdr_free(xdr_result, result);
+    return 1;
+}
+
+static void
+device_async_1(struct svc_req* rqstp, register SVCXPRT* transp)
+{
+    union {
+        Device_Link device_abort_1_arg;
+    } argument;
+    union {
+        Device_Error device_abort_1_res;
+    } result;
+    bool_t retval;
+    xdrproc_t _xdr_argument, _xdr_result;
+    bool_t (*local)(char*, void*, struct svc_req*);
+
+    switch (rqstp->rq_proc) {
+    case NULLPROC:
+        (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char*)NULL);
+        return;
+
+    case device_abort:
+        _xdr_argument = (xdrproc_t)xdr_Device_Link;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_abort_1_svc;
+        break;
+
+    default:
+        svcerr_noproc(transp);
+        return;
+    }
+    memset((char*)&argument, 0, sizeof(argument));
+    if (!svc_getargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        svcerr_decode(transp);
+        return;
+    }
+    retval = (bool_t)(*local)((char*)&argument, (void*)&result, rqstp);
+    if (retval > 0 && !svc_sendreply(transp, (xdrproc_t)_xdr_result, (char*)&result)) {
+        svcerr_systemerr(transp);
+    }
+    if (!svc_freeargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        fprintf(stderr, "%s", "unable to free arguments");
+        exit(1);
+    }
+    if (!device_async_1_freeresult(transp, _xdr_result, (caddr_t)&result))
+        fprintf(stderr, "%s", "unable to free results");
+
+    return;
+}
+
+static void
+device_core_1(struct svc_req* rqstp, register SVCXPRT* transp)
+{
+    union {
+        Create_LinkParms create_link_1_arg;
+        Device_WriteParms device_write_1_arg;
+        Device_ReadParms device_read_1_arg;
+        Device_GenericParms device_readstb_1_arg;
+        Device_GenericParms device_trigger_1_arg;
+        Device_GenericParms device_clear_1_arg;
+        Device_GenericParms device_remote_1_arg;
+        Device_GenericParms device_local_1_arg;
+        Device_LockParms device_lock_1_arg;
+        Device_Link device_unlock_1_arg;
+        Device_EnableSrqParms device_enable_srq_1_arg;
+        Device_DocmdParms device_docmd_1_arg;
+        Device_Link destroy_link_1_arg;
+        Device_RemoteFunc create_intr_chan_1_arg;
+    } argument;
+    union {
+        Create_LinkResp create_link_1_res;
+        Device_WriteResp device_write_1_res;
+        Device_ReadResp device_read_1_res;
+        Device_ReadStbResp device_readstb_1_res;
+        Device_Error device_trigger_1_res;
+        Device_Error device_clear_1_res;
+        Device_Error device_remote_1_res;
+        Device_Error device_local_1_res;
+        Device_Error device_lock_1_res;
+        Device_Error device_unlock_1_res;
+        Device_Error device_enable_srq_1_res;
+        Device_DocmdResp device_docmd_1_res;
+        Device_Error destroy_link_1_res;
+        Device_Error create_intr_chan_1_res;
+        Device_Error destroy_intr_chan_1_res;
+    } result;
+    bool_t retval;
+    xdrproc_t _xdr_argument, _xdr_result;
+    bool_t (*local)(char*, void*, struct svc_req*);
+
+    switch (rqstp->rq_proc) {
+    case NULLPROC:
+        (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char*)NULL);
+        return;
+
+    case create_link:
+        _xdr_argument = (xdrproc_t)xdr_Create_LinkParms;
+        _xdr_result = (xdrproc_t)xdr_Create_LinkResp;
+        local = (bool_t(*)(char*, void*, struct svc_req*))create_link_1_svc;
+        break;
+
+    case device_write:
+        _xdr_argument = (xdrproc_t)xdr_Device_WriteParms;
+        _xdr_result = (xdrproc_t)xdr_Device_WriteResp;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_write_1_svc;
+        break;
+
+    case device_read:
+        _xdr_argument = (xdrproc_t)xdr_Device_ReadParms;
+        _xdr_result = (xdrproc_t)xdr_Device_ReadResp;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_read_1_svc;
+        break;
+
+    case device_readstb:
+        _xdr_argument = (xdrproc_t)xdr_Device_GenericParms;
+        _xdr_result = (xdrproc_t)xdr_Device_ReadStbResp;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_readstb_1_svc;
+        break;
+
+    case device_trigger:
+        _xdr_argument = (xdrproc_t)xdr_Device_GenericParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_trigger_1_svc;
+        break;
+
+    case device_clear:
+        _xdr_argument = (xdrproc_t)xdr_Device_GenericParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_clear_1_svc;
+        break;
+
+    case device_remote:
+        _xdr_argument = (xdrproc_t)xdr_Device_GenericParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_remote_1_svc;
+        break;
+
+    case device_local:
+        _xdr_argument = (xdrproc_t)xdr_Device_GenericParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_local_1_svc;
+        break;
+
+    case device_lock:
+        _xdr_argument = (xdrproc_t)xdr_Device_LockParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_lock_1_svc;
+        break;
+
+    case device_unlock:
+        _xdr_argument = (xdrproc_t)xdr_Device_Link;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_unlock_1_svc;
+        break;
+
+    case device_enable_srq:
+        _xdr_argument = (xdrproc_t)xdr_Device_EnableSrqParms;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_enable_srq_1_svc;
+        break;
+
+    case device_docmd:
+        _xdr_argument = (xdrproc_t)xdr_Device_DocmdParms;
+        _xdr_result = (xdrproc_t)xdr_Device_DocmdResp;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_docmd_1_svc;
+        break;
+
+    case destroy_link:
+        _xdr_argument = (xdrproc_t)xdr_Device_Link;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))destroy_link_1_svc;
+        break;
+
+    case create_intr_chan:
+        _xdr_argument = (xdrproc_t)xdr_Device_RemoteFunc;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))create_intr_chan_1_svc;
+        break;
+
+    case destroy_intr_chan:
+        _xdr_argument = (xdrproc_t)xdr_void;
+        _xdr_result = (xdrproc_t)xdr_Device_Error;
+        local = (bool_t(*)(char*, void*, struct svc_req*))destroy_intr_chan_1_svc;
+        break;
+
+    default:
+        svcerr_noproc(transp);
+        return;
+    }
+    memset((char*)&argument, 0, sizeof(argument));
+    if (!svc_getargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        svcerr_decode(transp);
+        return;
+    }
+    retval = (bool_t)(*local)((char*)&argument, (void*)&result, rqstp);
+    if (retval > 0 && !svc_sendreply(transp, (xdrproc_t)_xdr_result, (char*)&result)) {
+        svcerr_systemerr(transp);
+    }
+    if (!svc_freeargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        fprintf(stderr, "%s", "unable to free arguments");
+        exit(1);
+    }
+    if (!device_core_1_freeresult(transp, _xdr_result, (caddr_t)&result))
+        fprintf(stderr, "%s", "unable to free results");
+
+    return;
+}
+
+static void
+device_intr_1(struct svc_req* rqstp, register SVCXPRT* transp)
+{
+    union {
+        Device_SrqParms device_intr_srq_1_arg;
+    } argument;
+    union {
+    } result;
+    bool_t retval;
+    xdrproc_t _xdr_argument, _xdr_result;
+    bool_t (*local)(char*, void*, struct svc_req*);
+
+    switch (rqstp->rq_proc) {
+    case NULLPROC:
+        (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char*)NULL);
+        return;
+
+    case device_intr_srq:
+        _xdr_argument = (xdrproc_t)xdr_Device_SrqParms;
+        _xdr_result = (xdrproc_t)xdr_void;
+        local = (bool_t(*)(char*, void*, struct svc_req*))device_intr_srq_1_svc;
+        break;
+
+    default:
+        svcerr_noproc(transp);
+        return;
+    }
+    memset((char*)&argument, 0, sizeof(argument));
+    if (!svc_getargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        svcerr_decode(transp);
+        return;
+    }
+    retval = (bool_t)(*local)((char*)&argument, (void*)&result, rqstp);
+    if (retval > 0 && !svc_sendreply(transp, (xdrproc_t)_xdr_result, (char*)&result)) {
+        svcerr_systemerr(transp);
+    }
+    if (!svc_freeargs(transp, (xdrproc_t)_xdr_argument, (caddr_t)&argument)) {
+        fprintf(stderr, "%s", "unable to free arguments");
+        exit(1);
+    }
+    if (!device_intr_1_freeresult(transp, _xdr_result, (caddr_t)&result))
+        fprintf(stderr, "%s", "unable to free results");
+
+    return;
+}
+
+int main(int argc, char** argv)
+{
+    register SVCXPRT* transp;
+
+    /* user_context will be pointer to socket */
+    scpi_context.user_context = NULL;
+
+    SCPI_Init(&scpi_context,
+        scpi_commands,
+        &scpi_interface,
+        scpi_units_def,
+        SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4,
+        scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH,
+        scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE);
+
+    pmap_unset(DEVICE_ASYNC, DEVICE_ASYNC_VERSION);
+    pmap_unset(DEVICE_CORE, DEVICE_CORE_VERSION);
+    pmap_unset(DEVICE_INTR, DEVICE_INTR_VERSION);
+
+    transp = svcudp_create(RPC_ANYSOCK);
+    if (transp == NULL) {
+        fprintf(stderr, "%s", "cannot create udp service.");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_ASYNC, DEVICE_ASYNC_VERSION, device_async_1, IPPROTO_UDP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_ASYNC, DEVICE_ASYNC_VERSION, udp).");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_CORE, DEVICE_CORE_VERSION, device_core_1, IPPROTO_UDP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_CORE, DEVICE_CORE_VERSION, udp).");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_INTR, DEVICE_INTR_VERSION, device_intr_1, IPPROTO_UDP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_INTR, DEVICE_INTR_VERSION, udp).");
+        exit(1);
+    }
+
+    transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+    if (transp == NULL) {
+        fprintf(stderr, "%s", "cannot create tcp service.");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_ASYNC, DEVICE_ASYNC_VERSION, device_async_1, IPPROTO_TCP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_ASYNC, DEVICE_ASYNC_VERSION, tcp).");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_CORE, DEVICE_CORE_VERSION, device_core_1, IPPROTO_TCP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_CORE, DEVICE_CORE_VERSION, tcp).");
+        exit(1);
+    }
+    if (!svc_register(transp, DEVICE_INTR, DEVICE_INTR_VERSION, device_intr_1, IPPROTO_TCP)) {
+        fprintf(stderr, "%s", "unable to register (DEVICE_INTR, DEVICE_INTR_VERSION, tcp).");
+        exit(1);
+    }
+
+    svc_run();
+    fprintf(stderr, "%s", "svc_run returned");
+    return 0;
+}
diff --git a/examples/test-vxi11/vxi11_xdr.c b/examples/test-vxi11/vxi11_xdr.c
new file mode 100644
index 0000000..29d9371
--- /dev/null
+++ b/examples/test-vxi11/vxi11_xdr.c
@@ -0,0 +1,462 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "vxi11.h"
+
+bool_t
+xdr_Device_Link (XDR *xdrs, Device_Link *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_long (xdrs, objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_AddrFamily (XDR *xdrs, Device_AddrFamily *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_Flags (XDR *xdrs, Device_Flags *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_long (xdrs, objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_ErrorCode (XDR *xdrs, Device_ErrorCode *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_long (xdrs, objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_Error (XDR *xdrs, Device_Error *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Create_LinkParms (XDR *xdrs, Create_LinkParms *objp)
+{
+	register int32_t *buf;
+
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_long (xdrs, &objp->clientId))
+				 return FALSE;
+			 if (!xdr_bool (xdrs, &objp->lockDevice))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+
+		} else {
+		IXDR_PUT_LONG(buf, objp->clientId);
+		IXDR_PUT_BOOL(buf, objp->lockDevice);
+		IXDR_PUT_U_LONG(buf, objp->lock_timeout);
+		}
+		 if (!xdr_string (xdrs, &objp->device, ~0))
+			 return FALSE;
+		return TRUE;
+	} else if (xdrs->x_op == XDR_DECODE) {
+		buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_long (xdrs, &objp->clientId))
+				 return FALSE;
+			 if (!xdr_bool (xdrs, &objp->lockDevice))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+
+		} else {
+		objp->clientId = IXDR_GET_LONG(buf);
+		objp->lockDevice = IXDR_GET_BOOL(buf);
+		objp->lock_timeout = IXDR_GET_U_LONG(buf);
+		}
+		 if (!xdr_string (xdrs, &objp->device, ~0))
+			 return FALSE;
+	 return TRUE;
+	}
+
+	 if (!xdr_long (xdrs, &objp->clientId))
+		 return FALSE;
+	 if (!xdr_bool (xdrs, &objp->lockDevice))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	 if (!xdr_string (xdrs, &objp->device, ~0))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Create_LinkResp (XDR *xdrs, Create_LinkResp *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_u_short (xdrs, &objp->abortPort))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->maxRecvSize))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_WriteParms (XDR *xdrs, Device_WriteParms *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->io_timeout))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	 if (!xdr_Device_Flags (xdrs, &objp->flags))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_WriteResp (XDR *xdrs, Device_WriteResp *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->size))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_ReadParms (XDR *xdrs, Device_ReadParms *objp)
+{
+	register int32_t *buf;
+
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		 if (!xdr_Device_Link (xdrs, &objp->lid))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->requestSize))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->io_timeout))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+
+		} else {
+		IXDR_PUT_U_LONG(buf, objp->requestSize);
+		IXDR_PUT_U_LONG(buf, objp->io_timeout);
+		IXDR_PUT_U_LONG(buf, objp->lock_timeout);
+		}
+		 if (!xdr_Device_Flags (xdrs, &objp->flags))
+			 return FALSE;
+		 if (!xdr_char (xdrs, &objp->termChar))
+			 return FALSE;
+		return TRUE;
+	} else if (xdrs->x_op == XDR_DECODE) {
+		 if (!xdr_Device_Link (xdrs, &objp->lid))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->requestSize))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->io_timeout))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+
+		} else {
+		objp->requestSize = IXDR_GET_U_LONG(buf);
+		objp->io_timeout = IXDR_GET_U_LONG(buf);
+		objp->lock_timeout = IXDR_GET_U_LONG(buf);
+		}
+		 if (!xdr_Device_Flags (xdrs, &objp->flags))
+			 return FALSE;
+		 if (!xdr_char (xdrs, &objp->termChar))
+			 return FALSE;
+	 return TRUE;
+	}
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->requestSize))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->io_timeout))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	 if (!xdr_Device_Flags (xdrs, &objp->flags))
+		 return FALSE;
+	 if (!xdr_char (xdrs, &objp->termChar))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_ReadResp (XDR *xdrs, Device_ReadResp *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	 if (!xdr_long (xdrs, &objp->reason))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_ReadStbResp (XDR *xdrs, Device_ReadStbResp *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	 if (!xdr_u_char (xdrs, &objp->stb))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_GenericParms (XDR *xdrs, Device_GenericParms *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_Device_Flags (xdrs, &objp->flags))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->io_timeout))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_RemoteFunc (XDR *xdrs, Device_RemoteFunc *objp)
+{
+	register int32_t *buf;
+
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->hostAddr))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->hostPort))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->progNum))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->progVers))
+				 return FALSE;
+
+		} else {
+		IXDR_PUT_U_LONG(buf, objp->hostAddr);
+		IXDR_PUT_U_LONG(buf, objp->hostPort);
+		IXDR_PUT_U_LONG(buf, objp->progNum);
+		IXDR_PUT_U_LONG(buf, objp->progVers);
+		}
+		 if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily))
+			 return FALSE;
+		return TRUE;
+	} else if (xdrs->x_op == XDR_DECODE) {
+		buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->hostAddr))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->hostPort))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->progNum))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->progVers))
+				 return FALSE;
+
+		} else {
+		objp->hostAddr = IXDR_GET_U_LONG(buf);
+		objp->hostPort = IXDR_GET_U_LONG(buf);
+		objp->progNum = IXDR_GET_U_LONG(buf);
+		objp->progVers = IXDR_GET_U_LONG(buf);
+		}
+		 if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily))
+			 return FALSE;
+	 return TRUE;
+	}
+
+	 if (!xdr_u_long (xdrs, &objp->hostAddr))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->hostPort))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->progNum))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->progVers))
+		 return FALSE;
+	 if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_EnableSrqParms (XDR *xdrs, Device_EnableSrqParms *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_bool (xdrs, &objp->enable))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, (char **)&objp->handle.handle_val, (u_int *) &objp->handle.handle_len, 40))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_LockParms (XDR *xdrs, Device_LockParms *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_Device_Flags (xdrs, &objp->flags))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_DocmdParms (XDR *xdrs, Device_DocmdParms *objp)
+{
+	register int32_t *buf;
+
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		 if (!xdr_Device_Link (xdrs, &objp->lid))
+			 return FALSE;
+		 if (!xdr_Device_Flags (xdrs, &objp->flags))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->io_timeout))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+			 if (!xdr_long (xdrs, &objp->cmd))
+				 return FALSE;
+			 if (!xdr_bool (xdrs, &objp->network_order))
+				 return FALSE;
+			 if (!xdr_long (xdrs, &objp->datasize))
+				 return FALSE;
+
+		} else {
+		IXDR_PUT_U_LONG(buf, objp->io_timeout);
+		IXDR_PUT_U_LONG(buf, objp->lock_timeout);
+		IXDR_PUT_LONG(buf, objp->cmd);
+		IXDR_PUT_BOOL(buf, objp->network_order);
+		IXDR_PUT_LONG(buf, objp->datasize);
+		}
+		 if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0))
+			 return FALSE;
+		return TRUE;
+	} else if (xdrs->x_op == XDR_DECODE) {
+		 if (!xdr_Device_Link (xdrs, &objp->lid))
+			 return FALSE;
+		 if (!xdr_Device_Flags (xdrs, &objp->flags))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_u_long (xdrs, &objp->io_timeout))
+				 return FALSE;
+			 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+				 return FALSE;
+			 if (!xdr_long (xdrs, &objp->cmd))
+				 return FALSE;
+			 if (!xdr_bool (xdrs, &objp->network_order))
+				 return FALSE;
+			 if (!xdr_long (xdrs, &objp->datasize))
+				 return FALSE;
+
+		} else {
+		objp->io_timeout = IXDR_GET_U_LONG(buf);
+		objp->lock_timeout = IXDR_GET_U_LONG(buf);
+		objp->cmd = IXDR_GET_LONG(buf);
+		objp->network_order = IXDR_GET_BOOL(buf);
+		objp->datasize = IXDR_GET_LONG(buf);
+		}
+		 if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0))
+			 return FALSE;
+	 return TRUE;
+	}
+
+	 if (!xdr_Device_Link (xdrs, &objp->lid))
+		 return FALSE;
+	 if (!xdr_Device_Flags (xdrs, &objp->flags))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->io_timeout))
+		 return FALSE;
+	 if (!xdr_u_long (xdrs, &objp->lock_timeout))
+		 return FALSE;
+	 if (!xdr_long (xdrs, &objp->cmd))
+		 return FALSE;
+	 if (!xdr_bool (xdrs, &objp->network_order))
+		 return FALSE;
+	 if (!xdr_long (xdrs, &objp->datasize))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_DocmdResp (XDR *xdrs, Device_DocmdResp *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, (char **)&objp->data_out.data_out_val, (u_int *) &objp->data_out.data_out_len, ~0))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_Device_SrqParms (XDR *xdrs, Device_SrqParms *objp)
+{
+	register int32_t *buf;
+
+	 if (!xdr_bytes (xdrs, (char **)&objp->handle.handle_val, (u_int *) &objp->handle.handle_len, ~0))
+		 return FALSE;
+	return TRUE;
+}

--
Gitblit v1.9.1