#include "vxi11.h" #include "globals.h" #include #include #include #include #include #define DEBUG #ifdef DEBUG #include #endif #define SIZEOFARRAY(a) (sizeof(a) / sizeof(a[0])) #define ERR_SYNTAXERROR 1 #define ERR_DEVICENOTACCESSIBLE 3 #define ERR_INVALIDLINKINDENTIFIER 4 #define ERR_PARAMETERERROR 5 #define ERR_CHANNELNOTESTABLISHED 6 #define ERR_OPERATIONNOTSUPPORTED 8 #define ERR_OUTOFRESOURCES 9 #define ERR_DEVICELOCKEDBYANOTHERLINK 11 #define ERR_NOLOCKHELDBYTHISLINK 12 #define ERR_IOTIMEOUT 15 #define ERR_IOERROR 17 #define ERR_INVALIDADDRESS 21 #define ERR_ABORT 23 #define ERR_CHANNELALREADYESTABLISHED 29 static CLIENT* intclient = NULL; typedef struct { } ActiveLink; static ActiveLink* links[MAX_SESSIONS] = { NULL }; static bool isValidLink(int linkid) { return links[linkid] != NULL; } static bool isLocked() { return globals.VxiLocks.locked_network_server != NO_SERVER_LOCKED; } static bool haveLock(int lid) { return globals.VxiLocks.locked_network_server == lid; } static bool waitForLock(long timeout) { return false; } static void lock(int lid) { globals.VxiLocks.locked_network_server = lid; } static void unlock() { globals.VxiLocks.locked_network_server = NO_SERVER_LOCKED; } Device_Error * device_abort_1_svc(Device_Link *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_abort_1_svc()\n"); #endif if (!isValidLink(*argp)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.error = 0; } return &result; } Create_LinkResp * create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { static Create_LinkResp result; #ifdef DEBUG printf("create_link_1_svc()\n"); #endif if (globals.Remote.vxi_connections == MAX_SESSIONS) { result.error = ERR_OUTOFRESOURCES; } else { if (argp->lockDevice && isLocked()) { result.error = ERR_DEVICELOCKEDBYANOTHERLINK; } else { ActiveLink* link = malloc(sizeof(ActiveLink)); if (link == NULL) { result.error = ERR_OUTOFRESOURCES; } else { int linkid; for (linkid = 0; linkid < SIZEOFARRAY(links); linkid++) { if (links[linkid] == NULL) { links[linkid] = link; break; } } struct sockaddr_in sin; socklen_t len = sizeof(sin); getsockname(rqstp->rq_xprt->xp_sock, (struct sockaddr *) &sin, &len); result.error = 0; result.abortPort = ntohs(sin.sin_port); result.lid = linkid; globals.Remote.vxi_connections++; } } } return &result; } Device_WriteResp * device_write_1_svc(Device_WriteParms *argp, struct svc_req *rqstp) { static Device_WriteResp result; #ifdef DEBUG printf("device_write_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (isLocked(argp->lid) && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else { printf("%s\n", argp->data.data_val); //result.size = argp->data.data_len; result.size = 1; result.error = 0; } } return &result; } Device_ReadResp * device_read_1_svc(Device_ReadParms *argp, struct svc_req *rqstp) { static Device_ReadResp result; #ifdef DEBUG printf("device_read_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (isLocked(argp->lid) && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else { result.data.data_val = "HELLO!"; result.data.data_len = 7; result.error = 0; result.reason = 0x4; } } return &result; } Device_ReadStbResp * device_readstb_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { static Device_ReadStbResp result; #ifdef DEBUG printf("device_readstb_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.error = 0; result.stb = 0; } return &result; } Device_Error * device_trigger_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_trigger_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.error = 0; } return &result; } Device_Error * device_clear_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_clear_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.error = 0; } return &result; } Device_Error * device_remote_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_remote_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (isLocked() && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else result.error = 0; } return &result; } Device_Error * device_local_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_local_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (isLocked() && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else result.error = 0; } return &result; } Device_Error * device_lock_1_svc(Device_LockParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_lock_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (isLocked(argp->lid)) { result.error = ERR_DEVICELOCKEDBYANOTHERLINK; if (haveLock(argp->lid)) { // maybe do something here to warn about a device trying to lock multiple times? } } else { lock(argp->lid); result.error = 0; } } return &result; } Device_Error * device_unlock_1_svc(Device_Link *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_unlock_1_svc()\n"); #endif if (!isValidLink(*argp)) result.error = ERR_INVALIDLINKINDENTIFIER; else { if (!isLocked(*argp) || !haveLock(*argp)) result.error = ERR_NOLOCKHELDBYTHISLINK; else { result.error = 0; unlock(); } } return &result; } Device_Error * device_enable_srq_1_svc(Device_EnableSrqParms *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("device_enable_srq_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.error = 0; } return &result; } Device_DocmdResp * device_docmd_1_svc(Device_DocmdParms *argp, struct svc_req *rqstp) { static Device_DocmdResp result; #ifdef DEBUG printf("device_docmd_1_svc()\n"); #endif if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { result.data_out.data_out_len = 0; result.data_out.data_out_val = NULL; result.error = ERR_OPERATIONNOTSUPPORTED; } return &result; } Device_Error * destroy_link_1_svc(Device_Link *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("destroy_link_1_svc()\n"); #endif int lid = *argp; if (!isValidLink(lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { #ifdef DEBUG printf("link %d destroyed\n", lid); #endif free(links[lid]); links[lid] = NULL; } globals.Remote.vxi_connections--; return &result; } Device_Error * create_intr_chan_1_svc(Device_RemoteFunc *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("create_intr_chan_1_svc()\n"); char clientaddressstring[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &argp->hostAddr, clientaddressstring, sizeof(clientaddressstring)); printf("Client %s is asking for an interrupt connection on port %u\n", clientaddressstring, argp->hostPort); #endif if (argp->progFamily != DEVICE_TCP || argp->progNum != DEVICE_INTR || argp->progVers != DEVICE_INTR_VERSION) result.error = ERR_OPERATIONNOTSUPPORTED; else if (intclient != NULL) { result.error = ERR_CHANNELALREADYESTABLISHED; } else { struct sockaddr_in clientaddr; clientaddr.sin_family = AF_INET; clientaddr.sin_port = htons(argp->hostPort); clientaddr.sin_addr.s_addr = argp->hostAddr; int sock = RPC_ANYSOCK; CLIENT* clnt = clnttcp_create(&clientaddr, DEVICE_INTR, DEVICE_INTR_VERSION, &sock, 0, 0); if (clnt == NULL) { #ifdef DEBUG printf("Couldn't create interrupt channel client\n"); #endif result.error = ERR_CHANNELNOTESTABLISHED; } else { intclient = clnt; result.error = 0; } } return &result; } Device_Error * destroy_intr_chan_1_svc(void *argp, struct svc_req *rqstp) { static Device_Error result; #ifdef DEBUG printf("destroy_intr_chan_1_svc()\n"); #endif if (intclient == NULL) { result.error = ERR_CHANNELNOTESTABLISHED; } else { intclient = NULL; result.error = 0; } return &result; }