SDDSlib
Loading...
Searching...
No Matches
agilentcomm.cpp
1/*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * This file is distributed subject to a Software License Agreement found
7 * in the file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/*
11 *
12 $Log: not supported by cvs2svn $
13 Revision 1.2 2009/10/26 18:40:26 soliday
14 Fixed issue on Mac computers.
15
16 Revision 1.1 2009/08/18 19:12:42 soliday
17 Agilent scope communication software based off of software from Steve Sharples
18 of the Univ. of Nottingham
19
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <rpc/rpc.h>
27#include <pthread.h>
28
29typedef long Device_Link;
30typedef long Device_Flags;
31typedef long Device_ErrorCode;
32
34 Device_ErrorCode error;
35};
36typedef struct Device_Error Device_Error;
37
39 long clientId;
40 bool_t lockDevice;
41 u_long lock_timeout;
42 char *device;
43};
45
47 Device_ErrorCode error;
48 Device_Link lid;
49 u_short abortPort;
50 u_long maxRecvSize;
51};
52typedef struct Create_LinkResp Create_LinkResp;
53
55 Device_Link lid;
56 u_long io_timeout;
57 u_long lock_timeout;
58 Device_Flags flags;
59 struct {
60 u_int data_len;
61 char *data_val;
62 } data;
63};
65
67 Device_ErrorCode error;
68 u_long size;
69};
71
73 Device_Link lid;
74 u_long requestSize;
75 u_long io_timeout;
76 u_long lock_timeout;
77 Device_Flags flags;
78 char termChar;
79};
81
83 Device_ErrorCode error;
84 long reason;
85 struct {
86 u_int data_len;
87 char *data_val;
88 } data;
89};
90typedef struct Device_ReadResp Device_ReadResp;
91
92#define create_link 10
93#define device_write 11
94#define device_read 12
95#define destroy_link 23
96
97#define VXI11_DEFAULT_TIMEOUT 10000 /* in ms */
98#define VXI11_READ_TIMEOUT 2000 /* in ms */
99#define VXI11_CLIENT CLIENT
100#define VXI11_LINK Create_LinkResp
101#define VXI11_MAX_CLIENTS 256 /* maximum no of unique IP addresses/clients */
102#define VXI11_NULL_READ_RESP 50 /* vxi11_receive() return value if a query
103 * times out ON THE INSTRUMENT (and so we have
104 * to resend the query again) */
105#define VXI11_NULL_WRITE_RESP 51 /* vxi11_send() return value if a sent command
106 * times out ON THE INSTURMENT. */
107
108struct CLINK {
109 VXI11_CLIENT *client;
110 VXI11_LINK *link;
111} ;
112typedef struct CLINK CLINK;
113
114#define DEVICE_CORE 0x0607AF
115#define DEVICE_CORE_VERSION 1
116#define RCV_END_BIT 0x04 // An end indicator has been read
117#define RCV_CHR_BIT 0x02 // A termchr is set in flags and a character which matches termChar is transferred
118
119
120char VXI11_IP_ADDRESS[VXI11_MAX_CLIENTS][20];
121CLIENT *VXI11_CLIENT_ADDRESS[VXI11_MAX_CLIENTS];
122int VXI11_DEVICE_NO = 0;
123int VXI11_LINK_COUNT[VXI11_MAX_CLIENTS];
124
125static struct timeval TIMEOUT = { 25, 0 };
126
127
128#ifndef BOOL
129#define BOOL int
130#endif
131#ifndef TRUE
132#define TRUE 1
133#endif
134#ifndef FALSE
135#define FALSE 0
136#endif
137
138BOOL sc(char *con,char *var);
139
140int vxi11_open_device(const char *ip,
141 CLINK *clink);
142int vxi11_open_device(const char *ip,
143 CLINK *clink,
144 char *device);
145int vxi11_open_device(const char *ip,
146 CLIENT **client,
147 VXI11_LINK **link,
148 char *device);
149int vxi11_open_link(const char *ip,
150 CLIENT **client,
151 VXI11_LINK **link,
152 char *device);
153int vxi11_send(CLINK *clink,
154 const char *cmd);
155int vxi11_send(CLINK *clink,
156 const char *cmd,
157 unsigned long len);
158int vxi11_send(CLIENT *client,
159 VXI11_LINK *link,
160 const char *cmd);
161int vxi11_send(CLIENT *client,
162 VXI11_LINK *link,
163 const char *cmd,
164 unsigned long len);
165int vxi11_close_device(const char *ip,
166 CLINK *clink);
167int vxi11_close_device(const char *ip,
168 CLIENT *client,
169 VXI11_LINK *link);
170int vxi11_close_link(const char *ip,
171 CLIENT *client,
172 VXI11_LINK *link);
173double vxi11_obtain_double_value(CLINK *clink,
174 const char *cmd);
175double vxi11_obtain_double_value(CLINK *clink,
176 const char *cmd,
177 unsigned long timeout);
178long vxi11_send_and_receive(CLINK *clink,
179 const char *cmd,
180 char *buf,
181 unsigned long buf_len,
182 unsigned long timeout);
183long vxi11_receive(CLINK *clink,
184 char *buffer,
185 unsigned long len);
186long vxi11_receive(CLIENT *client,
187 VXI11_LINK *link,
188 char *buffer,
189 unsigned long len,
190 unsigned long timeout);
191long vxi11_receive(CLINK *clink,
192 char *buffer,
193 unsigned long len,
194 unsigned long timeout);
195long vxi11_obtain_long_value(CLINK *clink,
196 const char *cmd,
197 unsigned long timeout);
198long vxi11_obtain_long_value(CLINK *clink,
199 const char *cmd);
200long vxi11_receive_data_block(CLINK *clink,
201 char *buffer,
202 unsigned long len,
203 unsigned long timeout);
204
205enum clnt_stat create_link_1(Create_LinkParms *argp,
206 Create_LinkResp *clnt_res,
207 CLIENT *clnt);
208enum clnt_stat device_write_1(Device_WriteParms *argp,
209 Device_WriteResp *clnt_res,
210 CLIENT *clnt);
211enum clnt_stat destroy_link_1(Device_Link *argp,
212 Device_Error *clnt_res,
213 CLIENT *clnt);
214enum clnt_stat device_read_1(Device_ReadParms *argp,
215 Device_ReadResp *clnt_res,
216 CLIENT *clnt);
217
218bool_t xdr_Create_LinkParms (XDR *xdrs,
219 Create_LinkParms *objp);
220bool_t xdr_Create_LinkResp (XDR *xdrs,
221 Create_LinkResp *objp);
222bool_t xdr_Device_ErrorCode (XDR *xdrs,
223 Device_ErrorCode *objp);
224bool_t xdr_Device_Link (XDR *xdrs,
225 Device_Link *objp);
226bool_t xdr_Device_WriteParms (XDR *xdrs,
227 Device_WriteParms *objp);
228bool_t xdr_Device_WriteResp (XDR *xdrs,
229 Device_WriteResp *objp);
230bool_t xdr_Device_Flags (XDR *xdrs,
231 Device_Flags *objp);
232bool_t xdr_Device_Error (XDR *xdrs,
233 Device_Error *objp);
234bool_t xdr_Device_ReadParms (XDR *xdrs,
235 Device_ReadParms *objp);
236bool_t xdr_Device_ReadResp (XDR *xdrs,
237 Device_ReadResp *objp);
238
239#define BUF_LEN 1000000
240
241int main(int argc,char **argv)
242{
243 static char *progname;
244 static char *serverIP;
245
246 char comm[256];
247
248 long bytes_returned;
249 BOOL got_ip=FALSE;
250 BOOL got_comm=FALSE;
251 int index=1;
252 CLINK *clink; /* client link (actually a structure contining CLIENT and VXI11_LINK pointers) */
253
254 char outputbuf[BUF_LEN];
255
256
257
258 clink = new CLINK; /* allocate some memory */
259 progname = argv[0];
260
261 while(index<argc){
262 if(sc(argv[index],(char*)"-ip")||sc(argv[index],(char*)"-ip_address")||sc(argv[index],(char*)"-IP")){
263 serverIP = argv[++index];
264 got_ip = TRUE;
265 }
266
267 if(sc(argv[index],(char*)"-command")||sc(argv[index],(char*)"-c")||sc(argv[index],(char*)"-comm")){
268 snprintf(comm,256,"%s",argv[++index]);
269 got_comm=TRUE;
270 }
271
272 index++;
273 }
274
275 if(got_ip==FALSE||got_comm==FALSE){
276 printf("%s: sends commands to an Agilent scope via ethernet\n",progname);
277 printf("Run using %s [arguments]\n\n",progname);
278 printf("REQUIRED ARGUMENTS:\n");
279 printf("-ip -ip_address -IP : IP address of scope (eg 128.243.74.232)\n");
280 printf("-c -command -comm : command or query to send\n\n");
281 printf("DOCUMENTATION:\n");
282 printf("http://cp.literature.agilent.com/litweb/pdf/54855-97017.pdf\n");
283 exit(1);
284 }
285
286 if (vxi11_open_device(serverIP,clink) != 0) {
287 printf("Quitting...\n");
288 exit(2);
289 }
290
291 vxi11_send(clink, comm);
292 if (strstr(comm, "?") != 0) {
293 bytes_returned = vxi11_receive(clink, outputbuf, BUF_LEN);
294 vxi11_close_device(serverIP,clink);
295
296 if (bytes_returned > 0) {
297 printf("%s",outputbuf);
298 } else if (bytes_returned == -15) {
299 printf("Error: Nothing received after sending scope command %s\n", comm);
300 return(1);
301 }
302 } else {
303 vxi11_close_device(serverIP,clink);
304 }
305}
306
307/* string compare (sc) function for parsing... ignore */
308BOOL sc(char *con,char *var) {
309 if(strcmp(con,var)==0){
310 return TRUE;
311 }
312 return FALSE;
313}
314
315int vxi11_open_device(const char *ip, CLINK *clink) {
316 char device[6];
317 strncpy(device,"inst0",6);
318 return vxi11_open_device(ip, clink, device);
319}
320
321int vxi11_open_device(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
322
323#ifdef darwin
324 *client = clnt_create((char*)ip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
325#else
326 *client = clnt_create(ip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
327#endif
328
329 if (*client == NULL) {
330#ifdef darwin
331 clnt_pcreateerror((char*)ip);
332#else
333 clnt_pcreateerror(ip);
334#endif
335 return -1;
336 }
337
338 return vxi11_open_link(ip, client, link, device);
339}
340
341int vxi11_open_device(const char *ip, CLINK *clink, char *device) {
342 int ret;
343 int l;
344 int device_no=-1;
345
346 for (l=0; l<VXI11_MAX_CLIENTS; l++){
347 if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
348 device_no=l;
349 }
350 }
351
352 if (device_no < 0) {
353 if (VXI11_DEVICE_NO >= VXI11_MAX_CLIENTS) {
354 printf("Error: maximum of %d clients allowed\n",VXI11_MAX_CLIENTS);
355 ret = -VXI11_MAX_CLIENTS;
356 } else {
357 ret = vxi11_open_device(ip, &(clink->client), &(clink->link), device);
358 strncpy(VXI11_IP_ADDRESS[VXI11_DEVICE_NO],ip,20);
359 VXI11_CLIENT_ADDRESS[VXI11_DEVICE_NO] = clink->client;
360 VXI11_LINK_COUNT[VXI11_DEVICE_NO]=1;
361 VXI11_DEVICE_NO++;
362 }
363 } else {
364 clink->client = VXI11_CLIENT_ADDRESS[device_no];
365 ret = vxi11_open_link(ip, &(clink->client), &(clink->link), device);
366 VXI11_LINK_COUNT[device_no]++;
367 }
368 return ret;
369}
370
371int vxi11_open_link(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
372
373 Create_LinkParms link_parms;
374
375 /* Set link parameters */
376 link_parms.clientId = (long) *client;
377 link_parms.lockDevice = 0;
378 link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
379 link_parms.device = device;
380
381 *link = (Create_LinkResp *) calloc(1, sizeof(Create_LinkResp));
382
383 if (create_link_1(&link_parms, *link, *client) != RPC_SUCCESS) {
384#ifdef darwin
385 clnt_perror(*client, (char*)ip);
386#else
387 clnt_perror(*client, ip);
388#endif
389 return -2;
390 }
391 return 0;
392}
393
394enum clnt_stat create_link_1(Create_LinkParms *argp, Create_LinkResp *clnt_res, CLIENT *clnt)
395{
396 return (clnt_call(clnt, create_link,
397 (xdrproc_t) xdr_Create_LinkParms, (caddr_t) argp,
398 (xdrproc_t) xdr_Create_LinkResp, (caddr_t) clnt_res,
399 TIMEOUT));
400}
401
402bool_t xdr_Create_LinkParms (XDR *xdrs, Create_LinkParms *objp)
403{
404#if defined(SOLARIS) && !defined(_LP64)
405 register long *buf;
406#else
407 register int32_t *buf;
408#endif
409
410 if (xdrs->x_op == XDR_ENCODE) {
411 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
412 if (buf == NULL) {
413 if (!xdr_long (xdrs, &objp->clientId))
414 return FALSE;
415 if (!xdr_bool (xdrs, &objp->lockDevice))
416 return FALSE;
417 if (!xdr_u_long (xdrs, &objp->lock_timeout))
418 return FALSE;
419
420 } else {
421 IXDR_PUT_INT32(buf, objp->clientId);
422 IXDR_PUT_BOOL(buf, objp->lockDevice);
423 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
424 }
425 if (!xdr_string (xdrs, &objp->device, ~0))
426 return FALSE;
427 return TRUE;
428 } else if (xdrs->x_op == XDR_DECODE) {
429 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
430 if (buf == NULL) {
431 if (!xdr_long (xdrs, &objp->clientId))
432 return FALSE;
433 if (!xdr_bool (xdrs, &objp->lockDevice))
434 return FALSE;
435 if (!xdr_u_long (xdrs, &objp->lock_timeout))
436 return FALSE;
437
438 } else {
439 objp->clientId = IXDR_GET_INT32(buf);
440 objp->lockDevice = IXDR_GET_BOOL(buf);
441 objp->lock_timeout = IXDR_GET_U_INT32(buf);
442 }
443 if (!xdr_string (xdrs, &objp->device, ~0))
444 return FALSE;
445 return TRUE;
446 }
447
448 if (!xdr_long (xdrs, &objp->clientId))
449 return FALSE;
450 if (!xdr_bool (xdrs, &objp->lockDevice))
451 return FALSE;
452 if (!xdr_u_long (xdrs, &objp->lock_timeout))
453 return FALSE;
454 if (!xdr_string (xdrs, &objp->device, ~0))
455 return FALSE;
456 return TRUE;
457}
458
459bool_t xdr_Create_LinkResp (XDR *xdrs, Create_LinkResp *objp)
460{
461 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
462 return FALSE;
463 if (!xdr_Device_Link (xdrs, &objp->lid))
464 return FALSE;
465 if (!xdr_u_short (xdrs, &objp->abortPort))
466 return FALSE;
467 if (!xdr_u_long (xdrs, &objp->maxRecvSize))
468 return FALSE;
469 return TRUE;
470}
471
472bool_t xdr_Device_ErrorCode (XDR *xdrs, Device_ErrorCode *objp)
473{
474 if (!xdr_long (xdrs, objp))
475 return FALSE;
476 return TRUE;
477}
478
479bool_t xdr_Device_Link (XDR *xdrs, Device_Link *objp)
480{
481 if (!xdr_long (xdrs, objp))
482 return FALSE;
483 return TRUE;
484}
485
486int vxi11_send(CLINK *clink, const char *cmd) {
487 return vxi11_send(clink, cmd, strlen(cmd));
488}
489
490int vxi11_send(CLINK *clink, const char *cmd, unsigned long len) {
491 return vxi11_send(clink->client, clink->link, cmd, len);
492}
493
494int vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd) {
495 return vxi11_send(client, link, cmd, strlen(cmd));
496}
497
498int vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd, unsigned long len) {
499 Device_WriteParms write_parms;
500 int bytes_left = (int)len;
501 char *send_cmd;
502
503 send_cmd = new char[len];
504 memcpy(send_cmd, cmd, len);
505
506 write_parms.lid = link->lid;
507 write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT;
508 write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
509
510 /* We can only write (link->maxRecvSize) bytes at a time, so we sit in a loop,
511 * writing a chunk at a time, until we're done. */
512
513 do {
514 Device_WriteResp write_resp;
515 memset(&write_resp, 0, sizeof(write_resp));
516
517 if ((unsigned int)bytes_left <= link->maxRecvSize) {
518 write_parms.flags = 8;
519 write_parms.data.data_len = bytes_left;
520 }
521 else {
522 write_parms.flags = 0;
523 /* We need to check that maxRecvSize is a sane value (ie >0). Believe it
524 * or not, on some versions of Agilent Infiniium scope firmware the scope
525 * returned "0", which breaks Rule B.6.3 of the VXI-11 protocol. Nevertheless
526 * we need to catch this, otherwise the program just hangs. */
527 if (link->maxRecvSize > 0) {
528 write_parms.data.data_len = link->maxRecvSize;
529 }
530 else {
531 write_parms.data.data_len = 4096; /* pretty much anything should be able to cope with 4kB */
532 }
533 }
534 write_parms.data.data_val = send_cmd + (len - bytes_left);
535
536 if(device_write_1(&write_parms, &write_resp, client) != RPC_SUCCESS) {
537 delete[] send_cmd;
538 return -VXI11_NULL_WRITE_RESP; /* The instrument did not acknowledge the write, just completely
539 dropped it. There was no vxi11 comms error as such, the
540 instrument is just being rude. Usually occurs when the instrument
541 is busy. If we don't check this first, then the following
542 line causes a seg fault */
543 }
544 if (write_resp . error != 0) {
545 printf("vxi11_user: write error: %d\n",(int)(write_resp . error));
546 delete[] send_cmd;
547 return -(write_resp . error);
548 }
549 bytes_left -= write_resp . size;
550 } while (bytes_left > 0);
551
552 delete[] send_cmd;
553 return 0;
554}
555
556enum clnt_stat device_write_1(Device_WriteParms *argp, Device_WriteResp *clnt_res, CLIENT *clnt)
557{
558 return (clnt_call(clnt, device_write,
559 (xdrproc_t) xdr_Device_WriteParms, (caddr_t) argp,
560 (xdrproc_t) xdr_Device_WriteResp, (caddr_t) clnt_res,
561 TIMEOUT));
562}
563
564bool_t xdr_Device_WriteParms (XDR *xdrs, Device_WriteParms *objp)
565{
566 if (!xdr_Device_Link (xdrs, &objp->lid))
567 return FALSE;
568 if (!xdr_u_long (xdrs, &objp->io_timeout))
569 return FALSE;
570 if (!xdr_u_long (xdrs, &objp->lock_timeout))
571 return FALSE;
572 if (!xdr_Device_Flags (xdrs, &objp->flags))
573 return FALSE;
574 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
575 return FALSE;
576 return TRUE;
577}
578
579bool_t xdr_Device_WriteResp (XDR *xdrs, Device_WriteResp *objp)
580{
581 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
582 return FALSE;
583 if (!xdr_u_long (xdrs, &objp->size))
584 return FALSE;
585 return TRUE;
586}
587
588bool_t xdr_Device_Flags (XDR *xdrs, Device_Flags *objp)
589{
590 if (!xdr_long (xdrs, objp))
591 return FALSE;
592 return TRUE;
593}
594
595int vxi11_close_device(const char *ip, CLINK *clink) {
596 int l,ret;
597 int device_no = -1;
598
599 /* Which instrument are we referring to? */
600 for (l=0; l<VXI11_MAX_CLIENTS; l++){
601 if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
602 device_no=l;
603 }
604 }
605 /* Something's up if we can't find the IP address! */
606 if (device_no == -1) {
607 printf("vxi11_close_device: error: I have no record of you ever opening device\n");
608 printf(" with IP address %s\n",ip);
609 ret = -4;
610 }
611 else { /* Found the IP, there's more than one link to that instrument,
612 * so keep track and just close the link */
613 if (VXI11_LINK_COUNT[device_no] > 1 ) {
614 ret = vxi11_close_link(ip,clink->client, clink->link);
615 VXI11_LINK_COUNT[device_no]--;
616 }
617 /* Found the IP, it's the last link, so close the device (link
618 * AND client) */
619 else {
620 ret = vxi11_close_device(ip, clink->client, clink->link);
621 }
622 }
623 return ret;
624}
625
626int vxi11_close_device(const char *ip, CLIENT *client, VXI11_LINK *link) {
627 int ret;
628
629 ret = vxi11_close_link(ip, client, link);
630
631 clnt_destroy(client);
632
633 return ret;
634}
635
636int vxi11_close_link(const char *ip, CLIENT *client, VXI11_LINK *link) {
637 Device_Error dev_error;
638 memset(&dev_error, 0, sizeof(dev_error));
639
640 if (destroy_link_1(&link->lid, &dev_error, client) != RPC_SUCCESS) {
641#ifdef darwin
642 clnt_perror(client,(char*)ip);
643#else
644 clnt_perror(client,ip);
645#endif
646 return -1;
647 }
648
649 return 0;
650}
651
652enum clnt_stat destroy_link_1(Device_Link *argp, Device_Error *clnt_res, CLIENT *clnt)
653{
654 return (clnt_call(clnt, destroy_link,
655 (xdrproc_t) xdr_Device_Link, (caddr_t) argp,
656 (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res,
657 TIMEOUT));
658}
659
660bool_t xdr_Device_Error (XDR *xdrs, Device_Error *objp)
661{
662 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
663 return FALSE;
664 return TRUE;
665}
666
667double vxi11_obtain_double_value(CLINK *clink, const char *cmd) {
668 return vxi11_obtain_double_value(clink, cmd, VXI11_READ_TIMEOUT);
669}
670
671double vxi11_obtain_double_value(CLINK *clink, const char *cmd, unsigned long timeout) {
672 char buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
673 double val;
674 memset(buf, 0, 50);
675 if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
676 printf("Returning 0.0\n");
677 return 0.0;
678 }
679 val = strtod(buf, (char **)NULL);
680 return val;
681}
682
683long vxi11_send_and_receive(CLINK *clink, const char *cmd, char *buf, unsigned long buf_len, unsigned long timeout) {
684 int ret;
685 long bytes_returned;
686 do {
687 ret = vxi11_send(clink, cmd);
688 if (ret != 0) {
689 if (ret != -VXI11_NULL_WRITE_RESP) {
690 printf("Error: vxi11_send_and_receive: could not send cmd.\n");
691 printf(" The function vxi11_send returned %d. ",ret);
692 return -1;
693 }
694 else printf("(Info: VXI11_NULL_WRITE_RESP in vxi11_send_and_receive, resending query)\n");
695 }
696
697 bytes_returned = vxi11_receive(clink, buf, buf_len, timeout);
698 if (bytes_returned <= 0) {
699 if (bytes_returned >-VXI11_NULL_READ_RESP) {
700 printf("Error: vxi11_send_and_receive: problem reading reply.\n");
701 printf(" The function vxi11_receive returned %ld. ",bytes_returned);
702 return -2;
703 }
704 else printf("(Info: VXI11_NULL_READ_RESP in vxi11_send_and_receive, resending query)\n");
705 }
706 } while (bytes_returned == -VXI11_NULL_READ_RESP || ret == -VXI11_NULL_WRITE_RESP);
707 return 0;
708}
709
710long vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout) {
711 Device_ReadParms read_parms;
712 Device_ReadResp read_resp;
713 long curr_pos = 0;
714
715 read_parms.lid = link->lid;
716 read_parms.requestSize = len;
717 read_parms.io_timeout = timeout; /* in ms */
718 read_parms.lock_timeout = timeout; /* in ms */
719 read_parms.flags = 0;
720 read_parms.termChar = 0;
721
722 do {
723 memset(&read_resp, 0, sizeof(read_resp));
724
725 read_resp.data.data_val = buffer + curr_pos;
726 read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len
727
728 if(device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) {
729 return -VXI11_NULL_READ_RESP; /* there is nothing to read. Usually occurs after sending a query
730 which times out on the instrument. If we don't check this first,
731 then the following line causes a seg fault */
732 }
733 if (read_resp . error != 0) {
734 /* Read failed for reason specified in error code.
735 * 0 no error
736 * 4 invalid link identifier
737 * 11 device locked by another link
738 * 15 I/O timeout
739 * 17 I/O error
740 * 23 abort
741 */
742
743 printf("vxi11_user: read error: %d\n",(int)(read_resp . error));
744 return -(read_resp . error);
745 }
746
747 if((unsigned long)(curr_pos + read_resp . data.data_len) <= len) {
748 curr_pos += read_resp . data.data_len;
749 }
750 if( (read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT) ) {
751 break;
752 }
753 else if( (unsigned long)curr_pos == len ) {
754 printf("xvi11_user: read error: buffer too small. Read %ld bytes without hitting terminator.\n", curr_pos );
755 return -100;
756 }
757 } while(1);
758 return (curr_pos); /*actual number of bytes received*/
759
760}
761
762long vxi11_receive(CLINK *clink, char *buffer, unsigned long len) {
763 return vxi11_receive(clink, buffer, len, VXI11_READ_TIMEOUT);
764}
765
766long vxi11_receive(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
767 return vxi11_receive(clink->client, clink->link, buffer, len, timeout);
768}
769
770enum clnt_stat device_read_1(Device_ReadParms *argp, Device_ReadResp *clnt_res, CLIENT *clnt)
771{
772 return (clnt_call(clnt, device_read,
773 (xdrproc_t) xdr_Device_ReadParms, (caddr_t) argp,
774 (xdrproc_t) xdr_Device_ReadResp, (caddr_t) clnt_res,
775 TIMEOUT));
776}
777
778bool_t xdr_Device_ReadParms (XDR *xdrs, Device_ReadParms *objp)
779{
780#if defined(SOLARIS) && !defined(_LP64)
781 register long *buf;
782#else
783 register int32_t *buf;
784#endif
785
786 if (xdrs->x_op == XDR_ENCODE) {
787 if (!xdr_Device_Link (xdrs, &objp->lid))
788 return FALSE;
789 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
790 if (buf == NULL) {
791 if (!xdr_u_long (xdrs, &objp->requestSize))
792 return FALSE;
793 if (!xdr_u_long (xdrs, &objp->io_timeout))
794 return FALSE;
795 if (!xdr_u_long (xdrs, &objp->lock_timeout))
796 return FALSE;
797
798 } else {
799 IXDR_PUT_U_INT32(buf, objp->requestSize);
800 IXDR_PUT_U_INT32(buf, objp->io_timeout);
801 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
802 }
803 if (!xdr_Device_Flags (xdrs, &objp->flags))
804 return FALSE;
805 if (!xdr_char (xdrs, &objp->termChar))
806 return FALSE;
807 return TRUE;
808 } else if (xdrs->x_op == XDR_DECODE) {
809 if (!xdr_Device_Link (xdrs, &objp->lid))
810 return FALSE;
811 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
812 if (buf == NULL) {
813 if (!xdr_u_long (xdrs, &objp->requestSize))
814 return FALSE;
815 if (!xdr_u_long (xdrs, &objp->io_timeout))
816 return FALSE;
817 if (!xdr_u_long (xdrs, &objp->lock_timeout))
818 return FALSE;
819
820 } else {
821 objp->requestSize = IXDR_GET_U_INT32(buf);
822 objp->io_timeout = IXDR_GET_U_INT32(buf);
823 objp->lock_timeout = IXDR_GET_U_INT32(buf);
824 }
825 if (!xdr_Device_Flags (xdrs, &objp->flags))
826 return FALSE;
827 if (!xdr_char (xdrs, &objp->termChar))
828 return FALSE;
829 return TRUE;
830 }
831
832 if (!xdr_Device_Link (xdrs, &objp->lid))
833 return FALSE;
834 if (!xdr_u_long (xdrs, &objp->requestSize))
835 return FALSE;
836 if (!xdr_u_long (xdrs, &objp->io_timeout))
837 return FALSE;
838 if (!xdr_u_long (xdrs, &objp->lock_timeout))
839 return FALSE;
840 if (!xdr_Device_Flags (xdrs, &objp->flags))
841 return FALSE;
842 if (!xdr_char (xdrs, &objp->termChar))
843 return FALSE;
844 return TRUE;
845}
846
847bool_t xdr_Device_ReadResp (XDR *xdrs, Device_ReadResp *objp)
848{
849 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
850 return FALSE;
851 if (!xdr_long (xdrs, &objp->reason))
852 return FALSE;
853 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
854 return FALSE;
855 return TRUE;
856}
857
858long vxi11_obtain_long_value(CLINK *clink, const char *cmd, unsigned long timeout) {
859 char buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
860 memset(buf, 0, 50);
861 if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
862 printf("Returning 0\n");
863 return 0;
864 }
865 return strtol(buf, (char **)NULL, 10);
866}
867
868/* Lazy wrapper function with default read timeout */
869long vxi11_obtain_long_value(CLINK *clink, const char *cmd) {
870 return vxi11_obtain_long_value(clink, cmd, VXI11_READ_TIMEOUT);
871}
872
873long vxi11_receive_data_block(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
874 /* I'm not sure what the maximum length of this header is, I'll assume it's
875 * 11 (#9 + 9 digits) */
876 unsigned long necessary_buffer_size;
877 char *in_buffer;
878 int ret;
879 int ndigits;
880 unsigned long returned_bytes;
881 int l;
882 char scan_cmd[20];
883 necessary_buffer_size=len+12;
884 in_buffer=new char[necessary_buffer_size];
885 ret=vxi11_receive(clink, in_buffer, necessary_buffer_size, timeout);
886 if (ret < 0) return ret;
887 if (in_buffer[0] != '#') {
888 printf("vxi11_user: data block error: data block does not begin with '#'\n");
889 printf("First 20 characters received were: '");
890 for(l=0;l<20;l++) {
891 printf("%c",in_buffer[l]);
892 }
893 printf("'\n");
894 return -3;
895 }
896
897 /* first find out how many digits */
898 sscanf(in_buffer,"#%1d",&ndigits);
899 /* some instruments, if there is a problem acquiring the data, return only "#0" */
900 if (ndigits > 0) {
901 /* now that we know, we can convert the next <ndigits> bytes into an unsigned long */
902 sprintf(scan_cmd,"#%%1d%%%dlu",ndigits);
903 sscanf(in_buffer,scan_cmd,&ndigits,&returned_bytes);
904 memcpy(buffer, in_buffer+(ndigits+2), returned_bytes);
905 delete[] in_buffer;
906 return (long) returned_bytes;
907 }
908 else return 0;
909}
910
911
912
913
914
915
916
917