<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>
<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;" >
<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;
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);
}
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);
}
}
-function padZeros(theNumber, max) {
- var numStr = String(theNumber);
-
- while ( numStr.length < max) {
- numStr = '0' + numStr;
- }
-
- return numStr;
-}
-
function getParameterByName(name)
{
-function getdata(command,callback) {
+function getdata(command,callback,option) {
var xmlhttp = null;
var cb = null;
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4) {
- if(cb)
+ if(cb && option)
+ cb(xmlhttp.responseText,option);
+ else if(cb)
cb(xmlhttp.responseText);
}
}
}
+#headline {
+font-weight:normal;
+font-size:90%;
+}
+
.smallboxes input {
width:50px;
--- /dev/null
+<!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>
+
+
+
+
+
+
+
+
--- /dev/null
+------------------------------------------------------------------------------
+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.
+
+------------------------------------------------------------------------------
+
--- /dev/null
+ 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.
--- /dev/null
+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
--- /dev/null
+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!)
--- /dev/null
+/* 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;
--- /dev/null
+/* 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;
+ }
+
--- /dev/null
+/* 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*/
+
+ }
+
--- /dev/null
+/* 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
--- /dev/null
+#!/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