long vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout) { Device_ReadParms read_parms; Device_ReadResp read_resp; long curr_pos = 0; read_parms.lid = link->lid; read_parms.requestSize = len; read_parms.io_timeout = timeout; /* in ms */ read_parms.lock_timeout = timeout; /* in ms */ read_parms.flags = 0; read_parms.termChar = 0; do { memset(&read_resp, 0, sizeof(read_resp)); read_resp.data.data_val = buffer + curr_pos; read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len if(device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) { return -VXI11_NULL_READ_RESP; /* there is nothing to read. Usually occurs after sending a query which times out on the instrument. If we don't check this first, then the following line causes a seg fault */ } if (read_resp . error != 0) { /* Read failed for reason specified in error code. * 0 no error * 4 invalid link identifier * 11 device locked by another link * 15 I/O timeout * 17 I/O error * 23 abort */ printf("vxi11_user: read error: %d\n",(int)(read_resp . error)); return -(read_resp . error); } if((curr_pos + read_resp . data.data_len) <= len) { curr_pos += read_resp . data.data_len; } if( (read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT) ) { break; } else if( (unsigned long)curr_pos == len ) { printf("xvi11_user: read error: buffer too small. Read %ld bytes without hitting terminator.\n", curr_pos ); return -100; } } while(1); return (curr_pos); /*actual number of bytes received*/ }
static int scpi_vxi_read_data(void *priv, char *buf, int maxlen) { struct scpi_vxi *vxi = priv; Device_ReadParms read_parms; Device_ReadResp *read_resp; read_parms.lid = vxi->link; read_parms.io_timeout = VXI_DEFAULT_TIMEOUT; read_parms.lock_timeout = VXI_DEFAULT_TIMEOUT; read_parms.flags = 0; read_parms.termChar = 0; read_parms.requestSize = maxlen; if (!(read_resp = device_read_1(&read_parms, vxi->client)) || read_resp->error) { sr_err("Device read failed for %s with error %d", vxi->address, read_resp ? read_resp->error : 0); return SR_ERR; } memcpy(buf, read_resp->data.data_val, read_resp->data.data_len); vxi->read_complete = read_resp->reason & (RRR_SIZE | RRR_TERM | RRR_END); return read_resp->data.data_len; /* actual number of bytes received */ }
int vxi11_close_link_client(const char *inputip, CLIENT *client, VXI11_LINK *link) { Device_Error dev_error; #ifdef __APPLE__ char ip[strlen(inputip)]; strcpy(ip, inputip); #else const char *ip = inputip; #endif memset(&dev_error, 0, sizeof(dev_error)); #ifdef __APPLE__ if (destroy_link_1(&link->lid, client) == NULL) { #else if (destroy_link_1(&link->lid, &dev_error, client) != RPC_SUCCESS) { #endif clnt_perror(client,ip); return -1; } return 0; } /* SEND FUNCTIONS * * ============== */ /* A _lot_ of the time we are sending text strings, and can safely rely on * strlen(cmd). */ int vxi11_send_client(CLIENT *client, VXI11_LINK *link, const char *cmd) { return vxi11_send_data_client(client, link, cmd, strlen(cmd)); } /* We still need the version of the function where the length is set explicitly * though, for when we are sending fixed length data blocks. */ int vxi11_send_data_client(CLIENT *client, VXI11_LINK *link, const char *cmd, unsigned long len) { Device_WriteParms write_parms; unsigned int bytes_left = len; char *send_cmd; send_cmd = (char *)malloc(len); memcpy(send_cmd, cmd, len); write_parms.lid = link->lid; write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT; write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT; /* We can only write (link->maxRecvSize) bytes at a time, so we sit in a loop, * writing a chunk at a time, until we're done. */ do { Device_WriteResp write_resp; memset(&write_resp, 0, sizeof(write_resp)); if (bytes_left <= link->maxRecvSize) { write_parms.flags = 8; write_parms.data.data_len = bytes_left; } else { write_parms.flags = 0; /* We need to check that maxRecvSize is a sane value (ie >0). Believe it * or not, on some versions of Agilent Infiniium scope firmware the scope * returned "0", which breaks Rule B.6.3 of the VXI-11 protocol. Nevertheless * we need to catch this, otherwise the program just hangs. */ if (link->maxRecvSize > 0) { write_parms.data.data_len = link->maxRecvSize; } else { write_parms.data.data_len = 4096; /* pretty much anything should be able to cope with 4kB */ } } write_parms.data.data_val = send_cmd + (len - bytes_left); #ifdef __APPLE__ Device_WriteResp *tmp; if((tmp = device_write_1(&write_parms, client)) == NULL) { #else if(device_write_1(&write_parms, &write_resp, client) != RPC_SUCCESS) { #endif free(send_cmd); return -VXI11_NULL_WRITE_RESP; /* The instrument did not acknowledge the write, just completely dropped it. There was no vxi11 comms error as such, the instrument is just being rude. Usually occurs when the instrument is busy. If we don't check this first, then the following line causes a seg fault */ } #ifdef __APPLE__ memcpy(&write_resp, tmp, sizeof(*tmp)); #endif if (write_resp.error != 0) { printf("vxi11_user: write error: %d\n", (int)write_resp.error); free(send_cmd); return -(write_resp.error); } bytes_left -= write_resp.size; } while (bytes_left > 0); free(send_cmd); return 0; } /* RECEIVE FUNCTIONS * * ================= */ // It appeared that this function wasn't correctly dealing with more data available than specified in len. // This patch attempts to fix this issue. RDP 2007/8/13 /* wrapper, for default timeout */ long vxi11_receive_client(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len) { return vxi11_receive_timeout_client(client, link, buffer, len, VXI11_READ_TIMEOUT); } #define RCV_END_BIT 0x04 // An end indicator has been read #define RCV_CHR_BIT 0x02 // A termchr is set in flags and a character which matches termChar is transferred #define RCV_REQCNT_BIT 0x01 // requestSize bytes have been transferred. This includes a request size of zero. long vxi11_receive_timeout_client(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout) { Device_ReadParms read_parms; Device_ReadResp read_resp; unsigned long curr_pos = 0; read_parms.lid = link->lid; read_parms.requestSize = len; read_parms.io_timeout = timeout; /* in ms */ read_parms.lock_timeout = timeout; /* in ms */ read_parms.flags = 0; read_parms.termChar = 0; do { memset(&read_resp, 0, sizeof(read_resp)); read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len #ifdef __APPLE__ Device_ReadResp *tmp; if((tmp = device_read_1(&read_parms, client)) == NULL) { #else read_resp.data.data_val = buffer + curr_pos; if(device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) { #endif return -VXI11_NULL_READ_RESP; /* there is nothing to read. Usually occurs after sending a query which times out on the instrument. If we don't check this first, then the following line causes a seg fault */ } #ifdef __APPLE__ memcpy(&read_resp, tmp, sizeof(*tmp)); memcpy(buffer + curr_pos, read_resp.data.data_val, read_resp.data.data_len); #endif if (read_resp.error != 0) { /* Read failed for reason specified in error code. * (From published VXI-11 protocol, section B.5.2) * 0 no error * 1 syntax error * 3 device not accessible * 4 invalid link identifier * 5 parameter error * 6 channel not established * 8 operation not supported * 9 out of resources * 11 device locked by another link * 12 no lock held by this link * 15 I/O timeout * 17 I/O error * 21 invalid address * 23 abort * 29 channel already established */ printf("vxi11_user: read error: %d\n", (int)read_resp.error); return -(read_resp.error); } if((curr_pos + read_resp.data.data_len) <= len) { curr_pos += read_resp.data.data_len; } if( (read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT) ) { break; } else if( curr_pos == len ) { printf("xvi11_user: read error: buffer too small. Read %d bytes without hitting terminator.\n", (int)curr_pos ); return -100; } } while(1); return (curr_pos); /*actual number of bytes received*/ }
ssize_t vxi11_receive_timeout(VXI11_CLINK * clink, char *buffer, size_t len, unsigned long timeout) { size_t curr_pos = 0; #ifdef WIN32 viRead(clink->session, (unsigned char *)buffer, len, &curr_pos); #else Device_ReadParms read_parms; Device_ReadResp read_resp; read_parms.lid = clink->link->lid; read_parms.requestSize = len; read_parms.io_timeout = timeout; /* in ms */ read_parms.lock_timeout = timeout; /* in ms */ read_parms.flags = 0; read_parms.termChar = 0; do { memset(&read_resp, 0, sizeof(read_resp)); read_resp.data.data_val = buffer + curr_pos; read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len if (device_read_1(&read_parms, &read_resp, clink->client) != RPC_SUCCESS) { return -VXI11_NULL_READ_RESP; /* there is nothing to read. Usually occurs after sending a query which times out on the instrument. If we don't check this first, then the following line causes a seg fault */ } if (read_resp.error != 0) { /* Read failed for reason specified in error code. * (From published VXI-11 protocol, section B.5.2) * 0 no error * 1 syntax error * 3 device not accessible * 4 invalid link identifier * 5 parameter error * 6 channel not established * 8 operation not supported * 9 out of resources * 11 device locked by another link * 12 no lock held by this link * 15 I/O timeout * 17 I/O error * 21 invalid address * 23 abort * 29 channel already established */ printf("vxi11_user: read error: %d\n", (int)read_resp.error); return -(read_resp.error); } if ((curr_pos + read_resp.data.data_len) <= len) { curr_pos += read_resp.data.data_len; } if ((read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT)) { break; } else if (curr_pos == len) { printf("xvi11_user: read error: buffer too small. Read %d bytes without hitting terminator.\n", (int)curr_pos); return -100; } } while (1); #endif return (curr_pos); /*actual number of bytes received */ }
void device_core_1(char *host) { CLIENT *clnt; Create_LinkResp *result_1; Create_LinkParms create_link_1_arg; Device_WriteResp *result_2; Device_WriteParms device_write_1_arg; Device_ReadResp *result_3; Device_ReadParms device_read_1_arg; Device_ReadStbResp *result_4; Device_GenericParms device_readstb_1_arg; Device_Error *result_5; Device_GenericParms device_trigger_1_arg; Device_Error *result_6; Device_GenericParms device_clear_1_arg; Device_Error *result_7; Device_GenericParms device_remote_1_arg; Device_Error *result_8; Device_GenericParms device_local_1_arg; Device_Error *result_9; Device_LockParms device_lock_1_arg; Device_Error *result_10; Device_Link device_unlock_1_arg; Device_Error *result_11; Device_EnableSrqParms device_enable_srq_1_arg; Device_DocmdResp *result_12; Device_DocmdParms device_docmd_1_arg; Device_Error *result_13; Device_Link destroy_link_1_arg; Device_Error *result_14; Device_RemoteFunc create_intr_chan_1_arg; Device_Error *result_15; char *destroy_intr_chan_1_arg; #ifndef DEBUG clnt = clnt_create (host, DEVICE_CORE, DEVICE_CORE_VERSION, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } #endif /* DEBUG */ result_1 = create_link_1(&create_link_1_arg, clnt); if (result_1 == (Create_LinkResp *) NULL) { clnt_perror (clnt, "call failed"); } result_2 = device_write_1(&device_write_1_arg, clnt); if (result_2 == (Device_WriteResp *) NULL) { clnt_perror (clnt, "call failed"); } result_3 = device_read_1(&device_read_1_arg, clnt); if (result_3 == (Device_ReadResp *) NULL) { clnt_perror (clnt, "call failed"); } result_4 = device_readstb_1(&device_readstb_1_arg, clnt); if (result_4 == (Device_ReadStbResp *) NULL) { clnt_perror (clnt, "call failed"); } result_5 = device_trigger_1(&device_trigger_1_arg, clnt); if (result_5 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_6 = device_clear_1(&device_clear_1_arg, clnt); if (result_6 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_7 = device_remote_1(&device_remote_1_arg, clnt); if (result_7 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_8 = device_local_1(&device_local_1_arg, clnt); if (result_8 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_9 = device_lock_1(&device_lock_1_arg, clnt); if (result_9 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_10 = device_unlock_1(&device_unlock_1_arg, clnt); if (result_10 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_11 = device_enable_srq_1(&device_enable_srq_1_arg, clnt); if (result_11 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_12 = device_docmd_1(&device_docmd_1_arg, clnt); if (result_12 == (Device_DocmdResp *) NULL) { clnt_perror (clnt, "call failed"); } result_13 = destroy_link_1(&destroy_link_1_arg, clnt); if (result_13 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_14 = create_intr_chan_1(&create_intr_chan_1_arg, clnt); if (result_14 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } result_15 = destroy_intr_chan_1((void*)&destroy_intr_chan_1_arg, clnt); if (result_15 == (Device_Error *) NULL) { clnt_perror (clnt, "call failed"); } #ifndef DEBUG clnt_destroy (clnt); #endif /* DEBUG */ }