#include #include #include #include "vxi11.h" #define DEBUG #ifdef DEBUG #include #include #endif /** * This is a thin wrapper around the rpcgen generated code to give it a simpler interface. * Only one server with a single link is supported. */ #define FLAG_TERMCHRSET (1 << 7) #define FLAG_END (1 << 3) #define FLAG_WAITLOCK 1 #define VXI11_DEFAULT_TIMEOUT 1000 static CLIENT* clnt = NULL; static CLIENT* abortclnt = NULL; static Device_Link link; static Device_Flags vxi11_generateflags(bool waitlock, bool end, bool termchrset) { Device_Flags flags = 0; if (waitlock) flags |= FLAG_WAITLOCK; if (end) flags |= FLAG_END; if (termchrset) flags |= FLAG_TERMCHRSET; return flags; } /** * create an RPC client and open a link to the server at $address. * $device is apparently used for VXI-11 -> GPIB gateways.. this is untested. */ int vxi11_open(char* address, char* device) { clnt = clnt_create(address, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp"); if (clnt == NULL) return 0; else { Create_LinkParms link_parms; link_parms.clientId = (long) clnt; link_parms.lockDevice = 0; link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT; link_parms.device = device != NULL ? device : "device0"; Create_LinkResp* linkresp = create_link_1(&link_parms, clnt); if (linkresp != NULL && linkresp->error == 0) { link = linkresp->lid; #ifdef DEBUG printf("Link created, abort channel port %d\n", ntohs(linkresp->abortPort)); #endif struct sockaddr_in serveraddr; if (clnt_control(clnt, CLGET_SERVER_ADDR, (char*) &serveraddr)) { #ifdef DEBUG char addressstring[INET_ADDRSTRLEN]; *inet_ntop(AF_INET, &serveraddr.sin_addr, addressstring, sizeof(addressstring)); printf("Remote is %s\n", addressstring); #endif serveraddr.sin_port = linkresp->abortPort; int sock = RPC_ANYSOCK; abortclnt = clnttcp_create(&serveraddr, DEVICE_ASYNC, DEVICE_ASYNC_VERSION, &sock, 0, 0); if (abortclnt == NULL) return 0; } else // failed! return 0; return 1; } else if (linkresp == NULL) return 0; else return -(linkresp->error); } } /** * read the status byte of the connected server */ int vxi11_readstatusbyte(bool waitforlock) { if (clnt == NULL) return 0; Device_GenericParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout = VXI11_DEFAULT_TIMEOUT }; Device_ReadStbResp* resp = device_readstb_1(¶ms, clnt); if (resp != NULL && resp->error == 0) return resp->stb; else if (resp == NULL) return 0; else return -1; } /** * write to the connected device */ int vxi11_write(char* data, unsigned int len, bool waitlock, bool end) { if (clnt == NULL) return 0; Device_WriteParms params = { .lid = link, .io_timeout = VXI11_DEFAULT_TIMEOUT, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .flags = vxi11_generateflags(waitlock, end, false) }; params.data.data_len = len; params.data.data_val = data; Device_WriteResp* resp = device_write_1(¶ms, clnt); if (resp != NULL && resp->error == 0) return resp->size; else if (resp == NULL) return 0; else return -1; } /** * read from the connected device */ int vxi11_read(char* buffer, unsigned int bufferlen, bool waitlock, bool termchrset, char termchr) { if (clnt == NULL) return 0; Device_ReadParms params = { .lid = link, .requestSize = 256, .io_timeout = VXI11_DEFAULT_TIMEOUT, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .flags = vxi11_generateflags(waitlock, false, termchrset), .termChar = termchrset ? termchr : 0 }; Device_ReadResp* resp = device_read_1(¶ms, clnt); if (resp != NULL && resp->error == 0) return resp->data.data_len; else if (resp == NULL) return 0; else return -1; } /** * */ int vxi11_docmd(unsigned long cmd, bool waitforlock) { if (clnt == NULL) return 0; Device_DocmdParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .io_timeout = VXI11_DEFAULT_TIMEOUT, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .cmd = cmd, .network_order = 0, .datasize = 0 }; params.data_in.data_in_len = 0; params.data_in.data_in_val = NULL; Device_DocmdResp* resp = device_docmd_1(¶ms, clnt); if (resp != NULL && resp->error == 0) return 1; else if (resp == NULL) return 0; else return -(resp->error); } /** * trigger the connected device */ int vxi11_trigger(bool waitforlock) { if (clnt == NULL) return 0; Device_GenericParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout = VXI11_DEFAULT_TIMEOUT }; Device_Error* error = device_trigger_1(¶ms, clnt); if (error->error == 0) return 1; else return -(error->error); } /** * clear the connected device */ int vxi11_clear(bool waitforlock) { if (clnt == NULL) return 0; Device_GenericParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout = VXI11_DEFAULT_TIMEOUT }; Device_Error* error = device_clear_1(¶ms, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * remote the connected device */ int vxi11_remote(bool waitforlock) { if (clnt == NULL) return 0; Device_GenericParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout = VXI11_DEFAULT_TIMEOUT }; Device_Error* error = device_remote_1(¶ms, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * local the connected device */ int vxi11_local(bool waitforlock) { if (clnt == NULL) return 0; Device_GenericParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout = VXI11_DEFAULT_TIMEOUT }; Device_Error* error = device_local_1(¶ms, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * lock the connected device */ int vxi11_lock(bool waitforlock) { if (clnt == NULL) return 0; Device_LockParms params = { .lid = link, .flags = vxi11_generateflags(waitforlock, false, false), .lock_timeout = VXI11_DEFAULT_TIMEOUT }; Device_Error* error = device_lock_1(¶ms, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * unlock the connected device */ int vxi11_unlock() { if (clnt == NULL) return 0; Device_Error* error = device_unlock_1(&link, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * create an interrupt channel from the connected device */ int vxi11_create_intr_chan() { if (clnt == NULL) return 0; Device_RemoteFunc remotefunc = { .hostAddr = 0x0, .hostPort = 0x0, .progNum = 0x0, .progVers = 0x0, .progFamily = DEVICE_TCP }; Device_Error* error = create_intr_chan_1(&remotefunc, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * destroy an interrupt channel from the connected device */ int vxi11_destroy_intr_chan() { if (clnt == NULL) return 0; Device_Error* error = destroy_intr_chan_1(NULL, clnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * send an abort to the connected device */ int vxi11_abort() { if (abortclnt == NULL) return 0; Device_Error* error = device_abort_1(&link, abortclnt); if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); } /** * close the current link and free the RPC client */ int vxi11_close() { if (clnt == NULL) return 0; Device_Error* error = destroy_link_1(&link, clnt); clnt_destroy(clnt); clnt = NULL; clnt_destroy(abortclnt); abortclnt = NULL; if (error != NULL && error->error == 0) return 1; else if (error == NULL) return 0; else return -(error->error); }