]> jspc29.x-matter.uni-frankfurt.de Git - daqtools.git/commitdiff
added interface for VXI devices
authorJan Michel <j.michel@gsi.de>
Tue, 16 Jul 2013 09:40:14 +0000 (11:40 +0200)
committerJan Michel <j.michel@gsi.de>
Tue, 16 Jul 2013 09:40:14 +0000 (11:40 +0200)
16 files changed:
web/htdocs/index.html
web/htdocs/tools/pwr/pwr.htm
web/htdocs/tools/pwr/pwr_hmp.htm
web/htdocs/tools/scripts.js [moved from web/htdocs/tools/pwr/scripts.js with 89% similarity]
web/htdocs/tools/styles.css [moved from web/htdocs/tools/pwr/styles.css with 89% similarity]
web/htdocs/tools/vxi/index.html [new file with mode: 0644]
web/htdocs/tools/vxi/source/CHANGELOG.txt [new file with mode: 0644]
web/htdocs/tools/vxi/source/GNU_General_Public_License.txt [new file with mode: 0644]
web/htdocs/tools/vxi/source/Makefile [new file with mode: 0644]
web/htdocs/tools/vxi/source/README.txt [new file with mode: 0644]
web/htdocs/tools/vxi/source/vxi11.x [new file with mode: 0644]
web/htdocs/tools/vxi/source/vxi11_cmd.cc [new file with mode: 0644]
web/htdocs/tools/vxi/source/vxi11_user.cc [new file with mode: 0644]
web/htdocs/tools/vxi/source/vxi11_user.h [new file with mode: 0644]
web/htdocs/tools/vxi/vxi.pl [new file with mode: 0755]
web/htdocs/tools/vxi/vxi11_cmd [new file with mode: 0755]

index 4a2e2a15d6744d56814e4c02cd962ad32f7f2368..9f43836409557a406bd1b271553d646879dea99d 100755 (executable)
@@ -48,6 +48,7 @@ The main documentation of the network can be found in these two documents:
 <div class="index">
 <ul>
 <li><a href="tools/pwr/index.html" title="Currently supported: GW-Instek PSP-405 family, HMP2020 - HMP4040 family">Control for power supplies</a>
+<li><a href="tools/vxi/index.html" title="Tested with Tektronix AFG3000 function generator">Control for devices running the VXI-11 protocol</a>
 </ul>
 </div>
 
index f7cfd0f5ff7ef59627372b06430d80b3db271d81..e0f8079dc0d6f6138e14cb590083fcadc9c20753 100644 (file)
@@ -2,8 +2,8 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-<link href="styles.css" rel="stylesheet" type="text/css"/>
-<script src="scripts.js" type="text/javascript"></script>
+<link href="../styles.css" rel="stylesheet" type="text/css"/>
+<script src="../scripts.js" type="text/javascript"></script>
 <title>Power Supply Monitor and Access</title>
 </head>
 <body style="font-family: sans-serif;" >
index 36aa4bf156ff97bd933b7cf7efc8a63b41c0c608..381795b5ed454417a7dab941ac6abfba99d56c77 100644 (file)
@@ -2,14 +2,14 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-<link href="styles.css" rel="stylesheet" type="text/css"/>
-<script src="scripts.js" type="text/javascript"></script>
+<link href="../styles.css" rel="stylesheet" type="text/css"/>
+<script src="../scripts.js" type="text/javascript"></script>
 <title>Power Supply Monitor and Access</title>
 </head>
 <body style="font-family: sans-serif;" >
 
 
-<p style="bold" id="headline">Power Supply Access</p>
+<h3 id="headline">Power Supply Access</h3>
 
 
 
 </form>
 
 
-
-
-<div id="readings" width="300" >
-</div>
-
-
 <script language="javascript">
 var updaterate = 500;
 var updateTask;
@@ -125,7 +119,6 @@ function updatereads(data) {
     document.getElementById("vol"+(i+1)).value=e[i*3];
     document.getElementById("cur"+(i+1)).value=e[i*3+1];
     document.getElementById("chan"+(i+1)).style.background=(e[i*3+2]=="1")?"limegreen":"#C00";
-//     document.getElementById("pwr"+(i+1)).innerHTML=(e[i*3+2]);
     }
   updateTask = setTimeout("communication()",updaterate);
   }  
@@ -138,7 +131,6 @@ function updatesettings(data) {
     document.getElementById("form_v"+(i+1)).value=e[i*3];
     document.getElementById("form_c_lim"+(i+1)).value=e[i*3+1];
     document.getElementById("form_v_lim"+(i+1)).value=e[i*3+1];
-//     document.getElementById("pwr"+(i+1)).innerHTML=(e[i*3+2]);
     }
   updateTask = setTimeout("communication()",updaterate);
   }    
@@ -169,16 +161,6 @@ function communication() {
 }
 
 
-function padZeros(theNumber, max) {
-    var numStr = String(theNumber);
-    
-    while ( numStr.length < max) {
-        numStr = '0' + numStr;
-    }
-    
-    return numStr;
-}
-
 
 function getParameterByName(name)
 {
similarity index 89%
rename from web/htdocs/tools/pwr/scripts.js
rename to web/htdocs/tools/scripts.js
index 016187c1a4ec4c4f8b46d016ecb339bdca7c36e5..3e2a5c1e34caab46ece9e74be00698c6877b7e8f 100644 (file)
@@ -1,6 +1,6 @@
 
 
-function getdata(command,callback) {
+function getdata(command,callback,option) {
   var xmlhttp = null;
   var cb = null;
   xmlhttp=new XMLHttpRequest();
@@ -8,7 +8,9 @@ function getdata(command,callback) {
   
   xmlhttp.onreadystatechange = function() {
     if(xmlhttp.readyState == 4) {
-      if(cb)
+      if(cb && option)
+        cb(xmlhttp.responseText,option);
+      else if(cb)
         cb(xmlhttp.responseText);
       }
     }
similarity index 89%
rename from web/htdocs/tools/pwr/styles.css
rename to web/htdocs/tools/styles.css
index d3529c116dd6652e021132f3daa8aff470eb29f9..e40f78639a22f907f710ddf074c5885622700835 100644 (file)
@@ -8,6 +8,11 @@ body {
 }
 
 
+#headline {
+font-weight:normal;
+font-size:90%;
+}
+
 
 .smallboxes input {
   width:50px;
diff --git a/web/htdocs/tools/vxi/index.html b/web/htdocs/tools/vxi/index.html
new file mode 100644 (file)
index 0000000..4af3768
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+       <html>
+         <head>
+         <link href="../../layout/styles.css" rel="stylesheet" type="text/css"/>
+    <script src="../scripts.js" type="text/javascript"></script>
+         <title>Access "all" Measuring Equipment</title>
+
+         </head>
+
+         <body>
+<h2>VXI-11 Lab Equipment Control</h2>
+<table>
+<tr><th>IP-Address<td><input type="text" id="dev_ip" name="voltage" value=""><td style="text-align:right"><input type="button" value="Who are you?" onClick="sendIDN()">
+<tr><th>Command(s)<td colspan=2><textarea rows=5 cols=80 id="commands"></textarea>
+<tr><th><td><td style="text-align:right" ><input type="button" value="Send" onClick="send()">
+<tr><th>Response<td colspan=2><textarea rows=5 cols=80 id="response"></textarea>
+</table>
+
+<p>
+This page allows to access any lab equipment that runs the VXI-11 protocol (such as (Tektronix|Agilent) (Scopes|SignalGenerators|MultiMeters)).
+The lib is C-based, so it needs to be recompiled if the available x64-binary does not work. The code was mainly downloaded from
+<a href="http://optics.eee.nottingham.ac.uk/vxi11">[VXI-11 library]</a>, but small changes were applied to the tool. The source code is included in the repository. Enter the IP of the device and any command and you'll receive the answer.
+
+
+
+
+
+
+
+<script language="javascript">
+function send() {
+  var cmd = "vxi.pl?";
+  cmd += document.getElementById("dev_ip").value + "&";
+  cmd += encodeURIComponent(document.getElementById("commands").value);
+  getdata(cmd,update,"response");
+  }
+
+
+function sendIDN() {
+  var cmd = "vxi.pl?";
+  cmd += document.getElementById("dev_ip").value + "&";
+  cmd += "*IDN%3F";
+  getdata(cmd,update,"response");
+  }
+
+  
+function update(data,id) {
+  document.getElementById(id).innerHTML = data;
+  }
+  
+</script>
+</body>
+</html>
+
+
+
+
+
+
+
+
diff --git a/web/htdocs/tools/vxi/source/CHANGELOG.txt b/web/htdocs/tools/vxi/source/CHANGELOG.txt
new file mode 100644 (file)
index 0000000..230d9dc
--- /dev/null
@@ -0,0 +1,218 @@
+------------------------------------------------------------------------------
+vxi11_1.10 - 9/09/2010
+
+Bug fix (thanks to Stephan Mahr): in vxi11_close(), remove the IP address
+from the global array that keeps track of them so that if the same device
+is opened again, then a new client is created, rather than it attempting 
+to use the old one (which was destroyed on the previous close).
+
+------------------------------------------------------------------------------
+vxi11_1.09 - 7/06/2010
+
+Moved over to bazaar VCS (from RCS).
+
+Makefile cleanups. Fixed signed/unsigned comparisons. Use consistent (and 
+sane) struct separator spacing in code.
+
+Fix int casting on printf statements to fix new compiler warnings/errors 
+(thanks to Shouri Chatterjee for pointing this out).
+
+------------------------------------------------------------------------------
+vxi11_1.08 - 3/09/2009
+
+Added a sanity check for link->maxRecvSize to make sure it's >0. This gets 
+around a bug in some versions of the Agilent Infiniium scope software.
+
+Changed the erroneous strncpy() to memcpy() in vxi11_send, as we could be
+sending binary data (not just strings).
+
+Changed a lot of char *'s to const char *'s in an attempt to get rid of
+pedantic gcc compiler warnings.
+
+------------------------------------------------------------------------------
+vxi11_1.07 - 9/10/2007
+
+Minor change to vxi11_receive_data_block(), this fn now copes with instruments
+that return just "#0" (for whatever reason). Suggestion by Jarek Sadowski,
+gratefully received.
+
+------------------------------------------------------------------------------
+vxi11_1.06 - 31/08/2007
+
+Bug fix in vxi11_receive(), to ensure that no more than "len" bytes are ever 
+received (and so avoiding a segmentation fault). This was a bug introduced in 
+release 1.04 whilst making some other changes to the vxi11_receive() fn.
+
+Many thanks to Rob Penny for spotting the bug and providing a patch.
+
+------------------------------------------------------------------------------
+vxi11_1.05 - 11/07/2007
+
+Added the ability to specify a "device name" when calling vxi11_open_device().
+For regular VXI11-based instruments, such as scopes and AFGs, the device name
+is usually "hard wired" to be "inst0", and up to now this has been hard wired
+into the vxi11_user code. However, devices such as LAN to GPIB gateways need
+some way of distinguishing between different devices... they are a single
+client (one IP address), with multiple devices.
+
+The vxi11_user fn, vxi11_open_device(), now takes a third argument
+(char *device).
+This gets passed to the core vxi11_open_device() fn (the one that deals with
+separate clients and links), and the core vxi11_open_link() fn; these two
+core functions have also had an extra parameter added accordingly. In order
+to not break the API, a wrapper function is provided in the form of the
+original vxi11_open_device() fn, that just takes 2 arguments
+(char *ip, CLINK *clink), this then passes "inst0" as the device argument.
+Backwards-compatible wrappers for the core functions have NOT been provided.
+These are generally not used from userland anyway. Hopefully this won't
+upset anyone!
+
+vxi11_cmd, the simple test utility, has also been updated. You can now,
+optionally, pass the device_name as a second argument (after the ip
+address). The source has been renamed to vxi11_cmd.cc (from vxi11_cmd.c), as
+it is C++ code not C.
+
+Some minor tidying up in vxi11_user.h
+
+With thanks to Oliver Schulz for bringing LAN to GPIB gateways to my
+attention, for suggesting changes to the vxi11_user library to allow them to
+be accommodated, and for tidying some things up.
+
+------------------------------------------------------------------------------
+vxi11_1.04 - 10/07/2007
+
+Patch applied, which was kindly provided by Robert Larice. This sorts out
+the confusion (on my part) about the structures returned by the rpcgen
+generated *_1() functions... these are statically allocated temporary structs,
+apparently. In the words of Robert Larice:
+
+******
+Hello Dr. Sharples,
+
+  I'm sending some patches for your nice gem "vxi11_1.03"
+
+  In the source code there were some strange comments, concerning
+   a commented free() around ... Manfred S. ...
+  and some notes, suggesting you had trouble to get more than one link
+    working.
+
+  I think thats caused by some misuse of the rpcgen generated subroutines.
+  1) those rpcgen generated *_1 functions returned pointers to
+       statically allocated temporary structs.
+     those where meant to be instantly copied to the user's space,
+       which wasn't done
+     thus instead of
+       Device_ReadResp  *read_resp;
+       read_resp = device_read_1(...)
+     one should have written someting like:
+       Device_ReadResp  *read_resp;
+       read_resp = malloc(...)
+       memcpy(read_resp, device_read_1(...), ...)
+  2) but a better fix is to use the rpcgen -M Flag
+       which allows to pass the memory space as a third argument
+     so one can write
+       Device_ReadResp  *read_resp;
+       read_resp = malloc(...)
+       device_read_1(..., read_resp, ...)
+     furthermore this is now automatically thread save
+  3) the rpcgen function device_read_1
+       expects a target buffer to be passed via read_resp
+     which was not done.
+  4) the return value of vxi11_receive() was computed incorrectly
+  5) minor,  Makefile typo's
+      CFLAGS versus
+      CLFAGS
+
+******
+
+Robert didn't have more than one device to try the patch with, but I've just
+tried it and everything seems fine. So I've removed all references to the
+VXI11_ENABLE_MULTIPLE_CLIENTS global variable, and removed the call to
+vxi11_open_link() from the vxi11_send() fn. There has been an associated
+tidying of functions, and removal of some comments.
+
+Thanks once again to Robert Larice for the patch and the explanation!
+
+------------------------------------------------------------------------------
+vxi11_1.03 - 29/01/2007
+
+Some bug-fixes (thanks to Manfred S.), and extra awareness of the
+possibility that instruments could time out after receiving a query WITHOUT
+causing an error condition. In some cases (prior to these changes) this
+could have resulted in a segmentation fault.
+
+Specifically:
+
+(1) removed call to ANSI free() fn in vxi11_receive, which according to
+    Manfred S. "is not necessary and wrong (crashes)".
+
+(2) added extra check in vxi11_receive() to see if read_resp==NULL.
+    read_resp can apparently be NULL if (eg) you send an instrument a
+    query, but the instrument is so busy with something else for so long
+    that it forgets the original query. So this extra check is for that
+    situation, and vxi11_receive returns -VXI11_NULL_READ_RESP to the
+    calling function.
+
+(3) vxi11_send_and_receive() is now aware of the possibility of being
+    returned -VXI11_NULL_READ_RESP. If so, it re-sends the query, until
+    either getting a "regular" read error (read_resp->error!=0) or a
+    successful read.
+
+(4) Similar to (2)... added extra check in vxi11_send() to see if
+    write_resp==NULL. If so, return -VXI11_NULL_WRITE_RESP. As with (3),
+    send_and_receive() is now aware of this possibility.
+
+------------------------------------------------------------------------------
+vxi11_1.02 - 25/08/2006
+
+Important changes to the core vxi11_send() function, which should be
+invisible to the user.
+
+For those interested, the function now takes note of the value of
+link->maxRecvSize, which is the maximum number of bytes that the vxi11
+intrument you're talking to can receive in one go. For many instruments
+this may be a few kB, which isn't a problem for sending short commands;
+however, sending large chunks of data (for example sending waveforms
+to instruments) may exceed this maxRecvSize. The core vxi11_send() function
+has been re-written to ensure that only a maximum of [maxRecvSize] bytes are
+written in one go... the function sits in a loop until all the message/
+data is written.
+
+Also tidied up some of the return values (specifically with regard to
+vxi11_send() and vxi11_send_data_block() ).
+
+------------------------------------------------------------------------------
+vxi11_1.01 - 06/07/2006
+
+Fair few changes since v1.00, all in vxi11_user.c and vxi11_user.h
+
+Found I was having problems talking to multiple links on the same
+client, if I created a different client for each one. So introduced
+a few global variables to keep track of all the ip addresses of
+clients that the library is asked to create, and only creating new
+clients if the ip address is different. This puts a limit of how
+many unique ip addresses (clients) a single process can connect to.
+Set this value at 256 (should hopefully be enough!).
+
+Next I found that talking to different clients on different ip
+addresses didn't work. It turns out that create_link_1() creates
+a static structure. This this link is associated with a given
+client (and hence a given IP address), then the only way I could
+think of making things work was to add a call to an
+vxi11_open_link() function before each send command (no idea what
+this adds to overheads and it's very messy!) - at least I was
+able to get this to only happen when we are using more than one
+client/ip address.
+
+Also, while I was at it, I re-ordered the functions a little -
+starts with core user functions, extra user functions, then core
+library functions at the end. Added a few more comments. Tidied
+up. Left some debugging info in, but commented out.
+
+------------------------------------------------------------------------------
+vxi11_1.00 - 23/06/2006
+
+Initial release.
+
+------------------------------------------------------------------------------
+
diff --git a/web/htdocs/tools/vxi/source/GNU_General_Public_License.txt b/web/htdocs/tools/vxi/source/GNU_General_Public_License.txt
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/web/htdocs/tools/vxi/source/Makefile b/web/htdocs/tools/vxi/source/Makefile
new file mode 100644 (file)
index 0000000..5963860
--- /dev/null
@@ -0,0 +1,40 @@
+VERSION=1.08
+
+#CFLAGS = -Wall -g
+CFLAGS = -g
+INSTALL = install
+prefix = /usr/local
+CXX = g++
+
+.PHONY : install clean dist distclean
+
+vxi11_cmd: vxi11_cmd.o vxi11_user.o vxi11_clnt.o vxi11_xdr.o
+       $(CXX) $(CFLAGS) -o $@ $^
+
+vxi11_cmd.o: vxi11_cmd.cc vxi11_user.cc vxi11.h
+       $(CXX) $(CFLAGS) -c $< -o $@
+
+vxi11_user.o: vxi11_user.cc vxi11.h
+       $(CXX) $(CFLAGS) -c $< -o $@
+
+vxi11.h vxi11_clnt.c vxi11_xdr.c : vxi11.x
+       rpcgen -M vxi11.x
+
+TAGS: $(wildcard *.c) $(wildcard *.h) $(wildcard *.cc)
+       etags $^
+
+clean:
+       rm -f *.o vxi11_cmd vxi11.h vxi11_svc.c vxi11_xdr.c vxi11_clnt.c TAGS
+
+install: vxi11_cmd
+       $(INSTALL) vxi11_cmd $(DESTDIR)$(prefix)/bin/
+
+dist : distclean
+       mkdir vxi11-$(VERSION)
+       cp -p vxi11_cmd.cc vxi11_user.cc vxi11_user.h vxi11.x vxi11-$(VERSION)/
+       cp -p Makefile CHANGELOG.txt README.txt GNU_General_Public_License.txt vxi11-$(VERSION)/
+       tar -zcf vxi11-$(VERSION).tar.gz vxi11-$(VERSION)
+
+distclean : 
+       rm -rf vxi11-$(VERSION)
+       rm -f vxi11-$(VERSION).tar.gz
diff --git a/web/htdocs/tools/vxi/source/README.txt b/web/htdocs/tools/vxi/source/README.txt
new file mode 100644 (file)
index 0000000..a75fda3
--- /dev/null
@@ -0,0 +1,98 @@
+RPC PROTOCOL FOR COMMUNICATING WITH VXI11-ENABLED DEVICES OVER ETHERNET FROM LINUX
+==================================================================================
+(including instruments such as oscilloscopes, by manufacturers such as
+Agilent and Tektronix, amongst others).
+
+By Steve D. Sharples, June 2006.
+
+This is a collection of source code that will allow you to talk to ethernet-
+enabled instruments that use the VXI11 protocol, from Linux. This includes
+a wide range of instruments (including oscilloscopes, logic analysers, 
+function generators etc) by a wide range of manufacturers (including 
+Tektronix and Agilent to name just a couple). An interactive "send and 
+receive" utility is included as an example.
+
+You may want to build on to this libraries for your specific instruments - 
+I'm currently working on libraries for talking to Agilent Infiniium scopes,
+and will probably do the same for Tektronix scopes too. Basically if you've
+got a Programmer's Reference for your instrument, and this code, you should
+be able to cobble something together.
+
+This collection of code has been produced because I grew frustrated at how
+difficult it seemed to be to do a relatively simple task. None of the 
+major manufacturers had any "out of the box" Linux solutions to talking to
+their instruments (although often I would talk to technical folks who would
+try their best to help). One of the solutions offered was to use something
+called NI VISA; parts of this are closed source, it was enormous, and I had
+worries about legacy issues with changing PC hardware.
+
+Via Guy McBride at Agilent, I obtained a copy of a vxi11.x RPC file similar
+to the one included here (although no-one at Agilent seemed to know or care
+where it came from). After lots of searching on the information superhighway
+I located what I believe is the original source (or something like it); see
+the section on vxi11.x below. This source seems to have literally been written
+from the published VXI11 protocol. I also received from Agilent a simple
+example program that showed you how to use the protocol; working from this 
+and the (open) source that uses the vxi11.x that is included here, I wrote
+vxi11_cmd and the user libraries.
+
+This collection of source code consists of:
+
+(1) vxi11.x
+This file, vxi11.x, is the amalgamation of vxi11core.rpcl and vxi11intr.rpcl
+which are part of the asynDriver (R4-5) EPICS module, which, at time of
+writing, is available from:
+http://www.aps.anl.gov/epics/modules/soft/asyn/index.html
+More general information about EPICS is available from:
+http://www.aps.anl.gov/epics/
+This code is open source, and is covered under the copyright notice and
+software license agreement shown below, and also at:
+http://www.aps.anl.gov/epics/license/open.php
+
+It is intended as a lightweight base for the vxi11 rpc protocol. If you
+run rpcgen on this file, it will generate C files and headers, from which
+it is relatively simple to write C programs to communicate with a range
+of ethernet-enabled instruments, such as oscilloscopes and function
+generators by manufacturers such as Agilent and Tektronix (amongst many
+others).
+
+(2) vxi11_user.cc (and vxi11_user.h)
+These are (fairly) friendly user libraries. At the core are 4 key functions:
+vxi11_open(), vxi11_close(), vxi11_send() and vxi11_receive(). These allow
+you to talk to your device. There are also some other functions that I
+considered to be generally useful (send_and_receive, functions for sending
+and receiving fixed length data blocks etc) that are all non-instrument-
+specific.
+
+(3) vxi11_cmd.c
+This is a fairly simple interactive utility that allows you to send
+commands and queries to your vxi11-enabled instrument, which you
+locate by way of IP address. I recommend you start with *IDN? It shows you
+how the vxi11_user library works
+
+(4) Makefile
+Type "make" to compile the source above. Type "make clean" to remove
+old object files and ./vxi11_cmd. Type "make install" to copy 
+./vxi11_cmd to /usr/local/bin/
+
+(5) GNU_General_Public_License.txt
+Fairly obvious. All programs, source, readme files etc NOT covered by any
+other license (e.g. vxi11.x, which is covered by its own open source 
+license) are covered by this license.
+
+These programs are free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+These programs are distributed in the hope that they will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+The author's email address is steve.no.spam.sharples@nottingham.ac.uk
+(you can work it out!)
diff --git a/web/htdocs/tools/vxi/source/vxi11.x b/web/htdocs/tools/vxi/source/vxi11.x
new file mode 100644 (file)
index 0000000..27f1293
--- /dev/null
@@ -0,0 +1,317 @@
+/* This file, vxi11.x, is the amalgamation of vxi11core.rpcl and vxi11intr.rpcl
+ * which are part of the asynDriver (R4-5) EPICS module, which, at time of
+ * writing, is available from:
+ * http://www.aps.anl.gov/epics/modules/soft/asyn/index.html
+ * More general information about EPICS is available from:
+ * http://www.aps.anl.gov/epics/
+ * This code is open source, and is covered under the copyright notice and
+ * software license agreement shown below, and also at:
+ * http://www.aps.anl.gov/epics/license/open.php
+ * 
+ * In order to comply with section 4.3 of the software license agreement, here
+ * is a PROMINENT NOTICE OF CHNAGES TO THE SOFTWARE
+ *      ===========================================
+ * (1) This file, vxi11.x, is the concatenation of the files vxi11core.rpcl and
+ *     vxi11intr.rpcl
+ * (2) Tab spacing has been tidied up
+ *
+ * It is intended as a lightweight base for the vxi11 rpc protocol. If you
+ * run rpcgen on this file, it will generate C files and headers, from which
+ * it is relatively simple to write C programs to communicate with a range
+ * of ethernet-enabled instruments, such as oscilloscopes and function 
+ * generated by manufacturers such as Agilent and Tektronix (amongst many
+ * others).
+ * 
+ * For what it's worth, this concatenation was done by Steve Sharples at
+ * the University of Nottingham, UK, on 1 June 2006.
+ *
+ * Copyright notice and software license agreement follow, then the
+ * original comments from vxi11core.rpcl etc.
+ *
+ ******************************************************************************
+ * Copyright Â© 2006 <University of Chicago and other copyright holders>. All
+ * rights reserved.
+ ******************************************************************************
+ * 
+ ******************************************************************************
+ * vxi11.x is distributed subject to the following license conditions:
+ * SOFTWARE LICENSE AGREEMENT
+ * Software: vxi11.x
+ * 
+ * 1. The "Software", below, refers to vxi11.x (in either source code, or
+ *    binary form and accompanying documentation). Each licensee is addressed
+ *    as "you" or "Licensee."
+ *
+ * 2. The copyright holders shown above and their third-party licensors hereby
+ *    grant Licensee a royalty-free nonexclusive license, subject to the
+ *    limitations stated herein and U.S. Government license rights.
+ *
+ * 3. You may modify and make a copy or copies of the Software for use within
+ *    your organization, if you meet the following conditions:
+ *       1. Copies in source code must include the copyright notice and this
+ *          Software License Agreement.
+ *       2. Copies in binary form must include the copyright notice and this
+ *           Software License Agreement in the documentation and/or other
+ *           materials provided with the copy.
+ *
+ * 4. You may modify a copy or copies of the Software or any portion of it,
+ *    thus forming a work based on the Software, and distribute copies of such
+ *     work outside your organization, if you meet all of the following
+ *     conditions:
+ *       1. Copies in source code must include the copyright notice and this
+ *          Software License Agreement;
+ *       2. Copies in binary form must include the copyright notice and this
+ *          Software License Agreement in the documentation and/or other
+ *          materials provided with the copy;
+ *       3. Modified copies and works based on the Software must carry
+ *          prominent notices stating that you changed specified portions of
+ *          the Software.
+ *
+ * 5. Portions of the Software resulted from work developed under a U.S.
+ *    Government contract and are subject to the following license: the
+ *    Government is granted for itself and others acting on its behalf a
+ *    paid-up, nonexclusive, irrevocable worldwide license in this computer
+ *    software to reproduce, prepare derivative works, and perform publicly
+ *    and display publicly.
+ * 
+ * 6. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF
+ *    ANY KIND. THE COPYRIGHT HOLDERS, THEIR THIRD PARTY LICENSORS, THE UNITED
+ *    STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND THEIR EMPLOYEES: (1) 
+ *    DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+ *    ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ *    PURPOSE, TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
+ *    OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF THE
+ *    SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE SOFTWARE WOULD NOT INFRINGE
+ *    PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
+ *    UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL BE CORRECTED.
+ *
+ * 7. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDERS, THEIR
+ *    THIRD PARTY LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
+ *    ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
+ *    CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF ANY KIND OR NATURE,
+ *    INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS OR LOSS OF DATA, FOR ANY
+ *    REASON WHATSOEVER, WHETHER SUCH LIABILITY IS ASSERTED ON THE BASIS OF
+ *    CONTRACT, TORT (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
+ *    EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE POSSIBILITY OF SUCH
+ *    LOSS OR DAMAGES.
+ ******************************************************************************
+ */
+
+/******************************************************************************
+ *
+ * vxi11core.rpcl
+ *
+ *     This file is best viewed with a tabwidth of 4
+ *
+ ******************************************************************************
+ *
+ * TODO:
+ *
+ ******************************************************************************
+ *
+ *     Original Author:        someone from VXIbus Consortium
+ *     Current Author:         Benjamin Franksen
+ *     Date:                   03-06-97
+ *
+ *     RPCL description of the core- and abort-channel of the TCP/IP Instrument 
+ *     Protocol Specification.
+ *
+ *
+ * Modification Log:
+ * -----------------
+ * .00 03-06-97        bfr             created this file
+ *
+ ******************************************************************************
+ *
+ * Notes: 
+ *
+ *     This stuff is literally from
+ *
+ *             VXI-11, Ref 1.0 : TCP/IP Instrument Protocol Specification
+ *
+ */
+
+typedef long Device_Link;
+
+enum Device_AddrFamily
+{
+       DEVICE_TCP,
+       DEVICE_UDP
+};
+
+typedef long Device_Flags;
+
+typedef long Device_ErrorCode;
+
+struct Device_Error
+{
+       Device_ErrorCode error;
+};
+
+struct Create_LinkParms
+{
+       long                    clientId;               /* implementation specific value */
+       bool                    lockDevice;             /* attempt to lock the device */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+       string                  device<>;               /* name of device */
+};
+struct Create_LinkResp
+{
+       Device_ErrorCode        error;
+       Device_Link             lid;
+       unsigned short          abortPort;              /* for the abort RPC */
+       unsigned long           maxRecvSize;            /* max # of bytes accepted on write */
+};
+struct Device_WriteParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       unsigned long           io_timeout;             /* time to wait for I/O */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+       Device_Flags            flags;                  /* flags with options */
+       opaque                  data<>;                 /* the data length and the data itself */
+};
+struct Device_WriteResp
+{
+       Device_ErrorCode        error;
+       unsigned long           size;                   /* # of bytes written */
+};
+struct Device_ReadParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       unsigned long           requestSize;            /* # of bytes requested */
+       unsigned long           io_timeout;             /* time to wait for I/O */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+       Device_Flags            flags;                  /* flags with options */
+       char                    termChar;               /* valid if flags & termchrset */
+};
+struct Device_ReadResp
+{
+       Device_ErrorCode        error;
+       long                    reason;                 /* why read completed */
+       opaque                  data<>;                 /* the data length and the data itself */
+};
+struct Device_ReadStbResp
+{
+       Device_ErrorCode        error;
+       unsigned char           stb;                    /* the returned status byte */
+};
+struct Device_GenericParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       Device_Flags            flags;                  /* flags with options */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+       unsigned long           io_timeout;             /* time to wait for I/O */
+};
+struct Device_RemoteFunc
+{
+       unsigned long           hostAddr;               /* host servicing interrupt */
+       unsigned long           hostPort;               /* valid port # on client */
+       unsigned long           progNum;                /* DEVICE_INTR */
+       unsigned long           progVers;               /* DEVICE_INTR_VERSION */
+       Device_AddrFamily       progFamily;             /* DEVICE_UDP | DEVICE_TCP */
+};
+struct Device_EnableSrqParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       bool                    enable;                 /* enable or disable intr's */
+       opaque                  handle<40>;             /* host specific data */
+};
+struct Device_LockParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       Device_Flags            flags;                  /* contains the waitlock flag */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+};
+struct Device_DocmdParms
+{
+       Device_Link             lid;                    /* link id from create_link */
+       Device_Flags            flags;                  /* flags with options */
+       unsigned long           io_timeout;             /* time to wait for I/O */
+       unsigned long           lock_timeout;           /* time to wait for lock */
+       long                    cmd;                    /* which command to execute */
+       bool                    network_order;          /* client's byte order */
+       long                    datasize;               /* size of individual data elements */
+       opaque                  data_in<>;              /* docmd data parameters */
+};
+struct Device_DocmdResp
+{
+       Device_ErrorCode        error;
+       opaque                  data_out<>;             /* returned data parameters */
+};
+
+program DEVICE_ASYNC
+{
+       version DEVICE_ASYNC_VERSION
+       {
+               Device_Error            device_abort            (Device_Link)           = 1;
+       } = 1;
+} = 0x0607B0;
+
+program DEVICE_CORE
+{
+       version DEVICE_CORE_VERSION
+       {
+               Create_LinkResp         create_link             (Create_LinkParms)      = 10;
+               Device_WriteResp        device_write            (Device_WriteParms)     = 11;
+               Device_ReadResp         device_read             (Device_ReadParms)      = 12;
+               Device_ReadStbResp      device_readstb          (Device_GenericParms)   = 13;
+               Device_Error            device_trigger          (Device_GenericParms)   = 14;
+               Device_Error            device_clear            (Device_GenericParms)   = 15;
+               Device_Error            device_remote           (Device_GenericParms)   = 16;
+               Device_Error            device_local            (Device_GenericParms)   = 17;
+               Device_Error            device_lock             (Device_LockParms)      = 18;
+               Device_Error            device_unlock           (Device_Link)           = 19;
+               Device_Error            device_enable_srq       (Device_EnableSrqParms) = 20;
+               Device_DocmdResp        device_docmd            (Device_DocmdParms)     = 22;
+               Device_Error            destroy_link            (Device_Link)           = 23;
+               Device_Error            create_intr_chan        (Device_RemoteFunc)     = 25;
+               Device_Error            destroy_intr_chan       (void)                  = 26;
+       } = 1;
+} = 0x0607AF;
+
+/******************************************************************************
+ *
+ * vxi11intr.rpcl
+ *
+ *     This file is best viewed with a tabwidth of 4
+ *
+ ******************************************************************************
+ *
+ * TODO:
+ *
+ ******************************************************************************
+ *
+ *     Original Author:        someone from VXIbus Consortium
+ *     Current Author:         Benjamin Franksen
+ *     Date:                           03-06-97
+ *
+ *     RPCL description of the intr-channel of the TCP/IP Instrument Protocol 
+ *     Specification.
+ *
+ *
+ * Modification Log:
+ * -----------------
+ * .00 03-06-97        bfr             created this file
+ *
+ ******************************************************************************
+ *
+ * Notes: 
+ *
+ *     This stuff is literally from
+ *
+ *             "VXI-11, Ref 1.0 : TCP/IP Instrument Protocol Specification"
+ *
+ */
+
+struct Device_SrqParms
+{
+       opaque  handle<>;
+};
+
+program DEVICE_INTR
+{
+       version DEVICE_INTR_VERSION
+       {
+               void                    device_intr_srq         (Device_SrqParms)       = 30;
+       } = 1;
+} = 0x0607B1;
diff --git a/web/htdocs/tools/vxi/source/vxi11_cmd.cc b/web/htdocs/tools/vxi/source/vxi11_cmd.cc
new file mode 100644 (file)
index 0000000..79e2a5e
--- /dev/null
@@ -0,0 +1,78 @@
+/* vxi11_cmd.c
+ * Copyright (C) 2006 Steve D. Sharples
+ *
+ * A simple interactive utility that allows you to send commands and queries to
+ * a device enabled with the VXI11 RPC ethernet protocol. Uses the files
+ * generated by rpcgen vxi11.x, and the vxi11_user.h user libraries.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * 
+ * The author's email address is steve.sharples@nottingham.ac.uk
+ */
+
+#include "vxi11_user.h"
+#define BUF_LEN 100000
+
+int    main(int argc, char *argv[]) {
+
+static char    *device_ip;
+static char    *device_name;
+static char    *cmd;
+char           buf[BUF_LEN];
+int            ret;
+long           bytes_returned;
+CLINK          *clink;
+
+       clink = new CLINK;
+
+       if (argc < 3) {
+               printf("usage: %s your.inst.ip.addr cmd [device_name]\n",argv[0]);
+               exit(1);
+               }
+
+       device_ip = argv[1];
+  cmd       = argv[2];
+       if (argc > 3) {
+               device_name = argv[3];
+               ret=vxi11_open_device(device_ip,clink,device_name);
+               }
+       else {
+               ret=vxi11_open_device(device_ip,clink);
+               }
+
+       if (ret != 0) {
+               printf("Error: could not open device %s, quitting\n",device_ip);
+               exit(2);
+               }
+
+               memset(buf, 0, BUF_LEN);        // initialize buffer
+//             printf("Input command or query ('q' to exit): ");
+//             fgets(cmd,256,stdin);
+               if (vxi11_send(clink, cmd) < 0) return -34;
+               if (strstr(cmd, "?") != 0) {
+                       bytes_returned = vxi11_receive(clink, buf, BUF_LEN);
+                       if (bytes_returned > 0) {
+                               printf("%s",buf);
+                               }
+                       else if (bytes_returned == -15) {
+                               printf("*** [ NOTHING RECEIVED ] ***\n");
+                               }
+//                     else    break;
+                       }
+
+       ret=vxi11_close_device(device_ip,clink);
+       return 0;
+       }
+
diff --git a/web/htdocs/tools/vxi/source/vxi11_user.cc b/web/htdocs/tools/vxi/source/vxi11_user.cc
new file mode 100644 (file)
index 0000000..c1510f2
--- /dev/null
@@ -0,0 +1,589 @@
+/* vxi11_user.cc
+ * Copyright (C) 2006 Steve D. Sharples
+ *
+ * User library for opening, closing, sending to and receiving from
+ * a device enabled with the VXI11 RPC ethernet protocol. Uses the files
+ * generated by rpcgen vxi11.x.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The author's email address is steve.sharples@nottingham.ac.uk
+ */
+
+#include "vxi11_user.h"
+
+/***************************************************************************** 
+ * GENERAL NOTES
+ *****************************************************************************
+ *
+ * There are four functions at the heart of this library:
+ *
+ * int vxi11_open_device(char *ip, CLIENT **client, VXI11_LINK **link)
+ * int vxi11_close_device(char *ip, CLIENT *client, VXI11_LINK *link)
+ * int vxi11_send(CLIENT *client, VXI11_LINK *link, char *cmd, unsigned long len)
+ * long        vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout)
+ *
+ * Note that all 4 of these use separate client and link structures. All the
+ * other functions are built on these four core functions, and the first layer
+ * of abstraction is to combine the CLIENT and VXI11_LINK structures into a
+ * single entity, which I've called a CLINK. For the send and receive
+ * functions, this is just a simple wrapper. For the open and close functions
+ * it's a bit more complicated, because we somehow have to keep track of
+ * whether we've already opened a device with the same IP address before (in
+ * which case we need to recycle a previously created client), or whether
+ * we've still got any other links to a given IP address left when we are 
+ * asked to close a clink (in which case we can sever the link, but have to
+ * keep the client open). This is so the person using this library from
+ * userland does not have to keep track of whether they are talking to a
+ * different physical instrument or not each time they establish a connection.
+ *
+ * So the base functions that the user will probably want to use are:
+ *
+ * int vxi11_open_device(char *ip, CLINK *clink)
+ * int vxi11_close_device(char *ip, CLINK *clink)
+ * int vxi11_send(CLINK *clink, char *cmd, unsigned long len)
+ *    --- or --- (if sending just text)
+ * int vxi11_send(CLINK *clink, char *cmd)
+ * long        vxi11_receive(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout)
+ *
+ * There are then useful (to me, anyway) more specific functions built on top
+ * of these:
+ *
+ * int vxi11_send_data_block(CLINK *clink, char *cmd, char *buffer, unsigned long len)
+ * long        vxi11_receive_data_block(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout)
+ * long        vxi11_send_and_receive(CLINK *clink, char *cmd, char *buf, unsigned long buf_len, unsigned long timeout)
+ * long        vxi11_obtain_long_value(CLINK *clink, char *cmd, unsigned long timeout)
+ * double vxi11_obtain_double_value(CLINK *clink, char *cmd, unsigned long timeout)
+ *
+ * (then there are some shorthand wrappers for the above without specifying
+ * the timeout due to sheer laziness---explore yourself)
+ */
+
+
+/* Global variables. Keep track of multiple links per client. We need this
+ * because:
+ * - we'd like the library to be able to cope with multiple links to a given
+ *   client AND multiple links to multiple clients
+ * - we'd like to just refer to a client/link ("clink") as a single
+ *   entity from user land, we don't want to worry about different
+ *   initialisation procedures, depending on whether it's an instrument
+ *   with the same IP address or not
+ */
+char   VXI11_IP_ADDRESS[VXI11_MAX_CLIENTS][20];
+CLIENT *VXI11_CLIENT_ADDRESS[VXI11_MAX_CLIENTS];
+int    VXI11_DEVICE_NO = 0;
+int    VXI11_LINK_COUNT[VXI11_MAX_CLIENTS];
+
+/*****************************************************************************
+ * KEY USER FUNCTIONS - USE THESE FROM YOUR PROGRAMS OR INSTRUMENT LIBRARIES *
+ *****************************************************************************/
+
+/* OPEN FUNCTIONS *
+ * ============== */
+
+/* Use this function from user land to open a device and create a link. Can be
+ * used multiple times for the same device (the library will keep track).*/
+int    vxi11_open_device(const char *ip, CLINK *clink, char *device) {
+int    ret;
+int    l;
+int    device_no=-1;
+
+//     printf("before doing anything, clink->link = %ld\n", clink->link);
+       /* Have a look to see if we've already initialised an instrument with
+        * this IP address */
+       for (l=0; l<VXI11_MAX_CLIENTS; l++){
+               if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
+                       device_no=l;
+//                     printf("Open function, search, found ip address %s, device no %d\n",ip,device_no);
+                       }
+               }
+
+       /* Couldn't find a match, must be a new IP address */
+       if (device_no < 0) {
+               /* Uh-oh, we're out of storage space. Increase the #define
+                * for VXI11_MAX_CLIENTS in vxi11_user.h */
+               if (VXI11_DEVICE_NO >= VXI11_MAX_CLIENTS) {
+                       printf("Error: maximum of %d clients allowed\n",VXI11_MAX_CLIENTS);
+                       ret = -VXI11_MAX_CLIENTS;
+                       }
+               /* Create a new client, keep a note of where the client pointer
+                * is, for this IP address. Because it's a new client, this
+                * must be link number 1. Keep track of how many devices we've
+                * opened so we don't run out of storage space. */
+               else {
+                       ret = vxi11_open_device(ip, &(clink->client), &(clink->link), device);
+                       strncpy(VXI11_IP_ADDRESS[VXI11_DEVICE_NO],ip,20);
+                       VXI11_CLIENT_ADDRESS[VXI11_DEVICE_NO] = clink->client;
+                       VXI11_LINK_COUNT[VXI11_DEVICE_NO]=1;
+//                     printf("Open function, could not find ip address %s.\n",ip);
+//                     printf("So now, VXI11_IP_ADDRESS[%d]=%s,\n",VXI11_DEVICE_NO,VXI11_IP_ADDRESS[VXI11_DEVICE_NO]);
+//                     printf("VXI11_CLIENT_ADDRESS[%d]=%ld,\n",VXI11_DEVICE_NO,VXI11_CLIENT_ADDRESS[VXI11_DEVICE_NO]);
+//                     printf("          clink->client=%ld,\n",clink->client);
+//                     printf("VXI11_LINK_COUNT[%d]=%d.\n",VXI11_DEVICE_NO,VXI11_LINK_COUNT[VXI11_DEVICE_NO]);
+                       VXI11_DEVICE_NO++;
+                       }
+               }
+       /* already got a client for this IP address */
+       else {
+               /* Copy the client pointer address. Just establish a new link
+                * (not a new client). Add one to the link count */
+               clink->client = VXI11_CLIENT_ADDRESS[device_no];
+               ret = vxi11_open_link(ip, &(clink->client), &(clink->link), device);
+//             printf("Found an ip address, copying client from VXI11_CLIENT_ADDRESS[%d]\n",device_no);
+               VXI11_LINK_COUNT[device_no]++;
+//             printf("Have just incremented VXI11_LINK_COUNT[%d], it's now %d\n",device_no,VXI11_LINK_COUNT[device_no]);
+               }
+//     printf("after creating link, clink->link = %ld\n", clink->link);
+       return ret;
+       }
+
+/* This is a wrapper function, used for the situations where there is only one
+ * "device" per client. This is the case for most (if not all) VXI11
+ * instruments; however, it is _not_ the case for devices such as LAN to GPIB
+ * gateways. These are single clients that communicate to many instruments
+ * (devices). In order to differentiate between them, we need to pass a device
+ * name. This gets used in the vxi11_open_link() fn, as the link_parms.device
+ * value. */
+int    vxi11_open_device(const char *ip, CLINK *clink) {
+       char device[6];
+       strncpy(device,"inst0",6);
+       return vxi11_open_device(ip, clink, device);
+       }
+
+
+
+/* CLOSE FUNCTION *
+ * ============== */
+
+/* Use this function from user land to close a device and/or sever a link. Can
+ * be used multiple times for the same device (the library will keep track).*/
+int     vxi11_close_device(const char *ip, CLINK *clink) {
+int     l,ret;
+int     device_no = -1;
+
+       /* Which instrument are we referring to? */
+       for (l=0; l<VXI11_MAX_CLIENTS; l++){
+               if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
+                       device_no=l;
+                       }
+               }
+       /* Something's up if we can't find the IP address! */
+       if (device_no == -1) {
+               printf("vxi11_close_device: error: I have no record of you ever opening device\n");
+               printf("                    with IP address %s\n",ip);
+               ret = -4;
+               }
+       else {  /* Found the IP, there's more than one link to that instrument,
+                * so keep track and just close the link */
+               if (VXI11_LINK_COUNT[device_no] > 1 ) {
+                       ret = vxi11_close_link(ip,clink->client, clink->link);
+                       VXI11_LINK_COUNT[device_no]--;
+                       }
+               /* Found the IP, it's the last link, so close the device (link
+                * AND client) */
+               else {
+                       ret = vxi11_close_device(ip, clink->client, clink->link);
+                       /* Remove the IP address, so that if we re-open the same device
+                        * we do it properly */
+                       memset(VXI11_IP_ADDRESS[device_no], 0, 20);
+                       }
+               }
+       return ret;
+       }
+
+
+/* SEND FUNCTIONS *
+ * ============== */
+
+/* A _lot_ of the time we are sending text strings, and can safely rely on
+ * strlen(cmd). */
+int    vxi11_send(CLINK *clink, const char *cmd) {
+       return vxi11_send(clink, 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(CLINK *clink, const char *cmd, unsigned long len) {
+       return vxi11_send(clink->client, clink->link, cmd, len);
+       }
+
+
+/* RECEIVE FUNCTIONS *
+ * ================= */
+
+/* Lazy wrapper for when I can't be bothered to specify a read timeout */
+long   vxi11_receive(CLINK *clink, char *buffer, unsigned long len) {
+       return vxi11_receive(clink, buffer, len, VXI11_READ_TIMEOUT);
+       }
+
+long   vxi11_receive(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
+       return vxi11_receive(clink->client, clink->link, buffer, len, timeout);
+       }
+
+
+
+/*****************************************************************************
+ * USEFUL ADDITIONAL HIGHER LEVER USER FUNCTIONS - USE THESE FROM YOUR       *
+ * PROGRAMS OR INSTRUMENT LIBRARIES                                          *
+ *****************************************************************************/
+
+/* SEND FIXED LENGTH DATA BLOCK FUNCTION *
+ * ===================================== */
+int    vxi11_send_data_block(CLINK *clink, const char *cmd, char *buffer, unsigned long len) {
+char   *out_buffer;
+int    cmd_len=strlen(cmd);
+int    ret;
+
+       out_buffer=new char[cmd_len+10+len];
+       sprintf(out_buffer,"%s#8%08lu",cmd,len);
+       memcpy(out_buffer+cmd_len+10,buffer,(unsigned long) len);
+       ret = vxi11_send(clink, out_buffer, (unsigned long) (cmd_len+10+len));
+       delete[] out_buffer;
+       return ret;
+       }
+       
+
+/* RECEIVE FIXED LENGTH DATA BLOCK FUNCTION *
+ * ======================================== */
+
+/* This function reads a response in the form of a definite-length block, such
+ * as when you ask for waveform data. The data is returned in the following
+ * format:
+ *   #800001000<1000 bytes of data>
+ *   ||\______/
+ *   ||    |
+ *   ||    \---- number of bytes of data
+ *   |\--------- number of digits that follow (in this case 8, with leading 0's)
+ *   \---------- always starts with #
+ */
+long   vxi11_receive_data_block(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
+/* I'm not sure what the maximum length of this header is, I'll assume it's 
+ * 11 (#9 + 9 digits) */
+unsigned long  necessary_buffer_size;
+char           *in_buffer;
+int            ret;
+int            ndigits;
+unsigned long  returned_bytes;
+int            l;
+char           scan_cmd[20];
+       necessary_buffer_size=len+12;
+       in_buffer=new char[necessary_buffer_size];
+       ret=vxi11_receive(clink, in_buffer, necessary_buffer_size, timeout);
+       if (ret < 0) return ret;
+       if (in_buffer[0] != '#') {
+               printf("vxi11_user: data block error: data block does not begin with '#'\n");
+               printf("First 20 characters received were: '");
+               for(l=0;l<20;l++) {
+                       printf("%c",in_buffer[l]);
+                       }
+               printf("'\n");
+               return -3;
+               }
+
+       /* first find out how many digits */
+       sscanf(in_buffer,"#%1d",&ndigits);
+       /* some instruments, if there is a problem acquiring the data, return only "#0" */
+       if (ndigits > 0) {
+               /* now that we know, we can convert the next <ndigits> bytes into an unsigned long */
+               sprintf(scan_cmd,"#%%1d%%%dlu",ndigits);
+               sscanf(in_buffer,scan_cmd,&ndigits,&returned_bytes);
+               memcpy(buffer, in_buffer+(ndigits+2), returned_bytes);
+               delete[] in_buffer;
+               return (long) returned_bytes;
+               }
+       else return 0;
+       }
+
+
+/* SEND AND RECEIVE FUNCTION *
+ * ========================= */
+
+/* This is mainly a useful function for the overloaded vxi11_obtain_value()
+ * fn's, but is also handy and useful for user and library use */
+long   vxi11_send_and_receive(CLINK *clink, const char *cmd, char *buf, unsigned long buf_len, unsigned long timeout) {
+int    ret;
+long   bytes_returned;
+       do {
+               ret = vxi11_send(clink, cmd);
+               if (ret != 0) {
+                       if (ret != -VXI11_NULL_WRITE_RESP) {
+                               printf("Error: vxi11_send_and_receive: could not send cmd.\n");
+                               printf("       The function vxi11_send returned %d. ",ret);
+                               return -1;
+                               }
+                       else printf("(Info: VXI11_NULL_WRITE_RESP in vxi11_send_and_receive, resending query)\n");
+                       }
+
+               bytes_returned = vxi11_receive(clink, buf, buf_len, timeout);
+               if (bytes_returned <= 0) {
+                       if (bytes_returned >-VXI11_NULL_READ_RESP) {
+                               printf("Error: vxi11_send_and_receive: problem reading reply.\n");
+                               printf("       The function vxi11_receive returned %ld. ",bytes_returned);
+                               return -2;
+                               }
+                       else printf("(Info: VXI11_NULL_READ_RESP in vxi11_send_and_receive, resending query)\n");
+                       }
+               } while (bytes_returned == -VXI11_NULL_READ_RESP || ret == -VXI11_NULL_WRITE_RESP);
+       return 0;
+       }
+
+
+/* FUNCTIONS TO RETURN A LONG INTEGER VALUE SENT AS RESPONSE TO A QUERY *
+ * ==================================================================== */
+long   vxi11_obtain_long_value(CLINK *clink, const char *cmd, unsigned long timeout) {
+char   buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
+       memset(buf, 0, 50);
+       if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
+               printf("Returning 0\n");
+               return 0;
+               }
+       return strtol(buf, (char **)NULL, 10);
+       }
+
+/* Lazy wrapper function with default read timeout */
+long   vxi11_obtain_long_value(CLINK *clink, const char *cmd) {
+       return vxi11_obtain_long_value(clink, cmd, VXI11_READ_TIMEOUT);
+       }
+
+
+/* FUNCTIONS TO RETURN A DOUBLE FLOAT VALUE SENT AS RESPONSE TO A QUERY *
+ * ==================================================================== */
+double vxi11_obtain_double_value(CLINK *clink, const char *cmd, unsigned long timeout) {
+char   buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
+double val;
+       memset(buf, 0, 50);
+       if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
+               printf("Returning 0.0\n");
+               return 0.0;
+               }
+       val = strtod(buf, (char **)NULL);
+       return val;
+       }
+
+/* Lazy wrapper function with default read timeout */
+double vxi11_obtain_double_value(CLINK *clink, const char *cmd) {
+       return vxi11_obtain_double_value(clink, cmd, VXI11_READ_TIMEOUT);
+       }
+
+
+/*****************************************************************************
+ * CORE FUNCTIONS - YOU SHOULDN'T NEED TO USE THESE FROM YOUR PROGRAMS OR    *
+ * INSTRUMENT LIBRARIES                                                      *
+ *****************************************************************************/
+
+/* OPEN FUNCTIONS *
+ * ============== */
+int    vxi11_open_device(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
+
+       *client = clnt_create(ip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
+
+       if (*client == NULL) {
+               clnt_pcreateerror(ip);
+               return -1;
+               }
+
+       return vxi11_open_link(ip, client, link, device);
+       }
+
+int    vxi11_open_link(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
+
+Create_LinkParms link_parms;
+
+       /* Set link parameters */
+       link_parms.clientId     = (long) *client;
+       link_parms.lockDevice   = 0;
+       link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
+       link_parms.device       = device;
+
+       *link = (Create_LinkResp *) calloc(1, sizeof(Create_LinkResp));
+
+       if (create_link_1(&link_parms, *link, *client) != RPC_SUCCESS) {
+               clnt_perror(*client, ip);
+               return -2;
+               }
+       return 0;
+       }
+
+
+/* CLOSE FUNCTIONS *
+ * =============== */
+int    vxi11_close_device(const char *ip, CLIENT *client, VXI11_LINK *link) {
+int    ret;
+
+       ret = vxi11_close_link(ip, client, link);
+
+       clnt_destroy(client);
+
+       return ret;
+       }
+
+int    vxi11_close_link(const char *ip, CLIENT *client, VXI11_LINK *link) {
+Device_Error dev_error;
+       memset(&dev_error, 0, sizeof(dev_error)); 
+
+       if (destroy_link_1(&link->lid, &dev_error, client) != RPC_SUCCESS) {
+               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, VXI11_LINK *link, const char *cmd) {
+       return vxi11_send(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(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 = new char[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);
+               
+               if(device_write_1(&write_parms, &write_resp, client) != RPC_SUCCESS) {
+                       delete[] 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 */
+                       }
+               if (write_resp.error != 0) {
+                       printf("vxi11_user: write error: %d\n", (int)write_resp.error);
+                       delete[] send_cmd;
+                       return -(write_resp.error);
+                       }
+               bytes_left -= write_resp.size;
+               } while (bytes_left > 0);
+
+       delete[] 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, VXI11_LINK *link, char *buffer, unsigned long len) { return vxi11_receive(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(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_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.
+                       *  (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*/
+
+       }
+
diff --git a/web/htdocs/tools/vxi/source/vxi11_user.h b/web/htdocs/tools/vxi/source/vxi11_user.h
new file mode 100644 (file)
index 0000000..07898e9
--- /dev/null
@@ -0,0 +1,87 @@
+/* vxi11_user.h
+ * Copyright (C) 2006 Steve D. Sharples
+ *
+ * User library for opening, closing, sending to and receiving from
+ * a device enabled with the VXI11 RPC ethernet protocol. Uses the files
+ * generated by rpcgen vxi11.x.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The author's email address is steve.sharples@nottingham.ac.uk
+ */
+
+#ifndef        __VXI11_USER__
+#define        __VXI11_USER__
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include "vxi11.h"
+
+#define        VXI11_DEFAULT_TIMEOUT   10000   /* in ms */
+#define        VXI11_READ_TIMEOUT      2000    /* in ms */
+#define        VXI11_CLIENT            CLIENT
+#define        VXI11_LINK              Create_LinkResp
+#define        VXI11_MAX_CLIENTS       256     /* maximum no of unique IP addresses/clients */
+#define        VXI11_NULL_READ_RESP    50      /* vxi11_receive() return value if a query
+                                        * times out ON THE INSTRUMENT (and so we have
+                                        * to resend the query again) */
+#define        VXI11_NULL_WRITE_RESP   51      /* vxi11_send() return value if a sent command
+                                        * times out ON THE INSTURMENT. */
+
+struct CLINK {
+       VXI11_CLIENT    *client;
+       VXI11_LINK      *link;
+       } ;
+typedef        struct  CLINK CLINK;
+
+/* The four main functions: open, close, send, receieve (plus a couple of wrappers) */
+/* In fact all 6 of these are wrappers to the original functions listed at the
+ * bottom, that use separate CLIENT and VXI11_LINK structures. It was easier to 
+ * write wrappers for these functions than to re-write the original functions
+ * themselves. These are the 4 (or 6 if you like) key user functions that you
+ * should probably be using. They all use the CLINK structure. */
+int    vxi11_open_device(const char *ip, CLINK *clink);
+int    vxi11_open_device(const char *ip, CLINK *clink, char *device);
+int    vxi11_close_device(const char *ip, CLINK *clink);
+int    vxi11_send(CLINK *clink, const char *cmd);
+int    vxi11_send(CLINK *clink, const char *cmd, unsigned long len);
+long   vxi11_receive(CLINK *clink, char *buffer, unsigned long len);
+long   vxi11_receive(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout);
+
+/* Utility functions, that use send() and receive(). Use these too. */
+int    vxi11_send_data_block(CLINK *clink, const char *cmd, char *buffer, unsigned long len);
+long   vxi11_receive_data_block(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout);
+long   vxi11_send_and_receive(CLINK *clink, const char *cmd, char *buf, unsigned long buf_len, unsigned long timeout);
+long   vxi11_obtain_long_value(CLINK *clink, const char *cmd, unsigned long timeout);
+double vxi11_obtain_double_value(CLINK *clink, const char *cmd, unsigned long timeout);
+long   vxi11_obtain_long_value(CLINK *clink, const char *cmd);
+double vxi11_obtain_double_value(CLINK *link, const char *cmd);
+
+/* When I first wrote this library I used separate client and links. I've
+ * retained the original functions and just written clink wrappers for them
+ * (see above) as it's perhaps a little clearer this way. Probably not worth
+ * delving this deep in use, but it's where the real nitty gritty is. */
+int    vxi11_open_device(const char *ip, CLIENT **client, VXI11_LINK **link, char *device);
+int    vxi11_open_link(const char *ip, CLIENT **client, VXI11_LINK **link, char *device);
+int    vxi11_close_device(const char *ip, CLIENT *client, VXI11_LINK *link);
+int    vxi11_close_link(const char *ip, CLIENT *client, VXI11_LINK *link);
+int    vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd);
+int    vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd, unsigned long len);
+long   vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len);
+long   vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout);
+
+#endif
diff --git a/web/htdocs/tools/vxi/vxi.pl b/web/htdocs/tools/vxi/vxi.pl
new file mode 100755 (executable)
index 0000000..9eb723c
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+#print "Content-type: text/html\n\n";
+
+
+use strict;
+use warnings;
+use URI::Escape;
+use Data::Dumper;
+
+my $executable = "./vxi11_cmd";
+if ($ENV{'SERVER_SOFTWARE'} =~ /HTTPi/i) {
+  $executable = "htdocs/tools/vxi/vxi11_cmd";
+  }
+
+my $envstring = $ENV{'QUERY_STRING'};
+$envstring =~ s/%20/ /g;
+
+my @new_command = split('&',$envstring); 
+my $dev_ip = shift(@new_command);
+my $cmds   = shift(@new_command);
+
+
+$cmds = uri_unescape($cmds);
+my @new_cmds = split('\n',$cmds); 
+
+foreach my $c (@new_cmds) {
+  chomp $c;
+  my $call = "$executable $dev_ip $c 2>&1";
+  my @o = qx($call);
+  if($c =~ /\?/) {
+    foreach my $l (@o) {
+      print $l;
+      }
+    }
+  print "---\n";
+  }
+  
+  
+  
+return 1;
\ No newline at end of file
diff --git a/web/htdocs/tools/vxi/vxi11_cmd b/web/htdocs/tools/vxi/vxi11_cmd
new file mode 100755 (executable)
index 0000000..5ce7ffa
Binary files /dev/null and b/web/htdocs/tools/vxi/vxi11_cmd differ