Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2. lecroy_tcp.c
  3. Version 1.00
  4. Copyright (C) 2003  Steve D. Sharples
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. The author's email address is steve.sharples@nottingham.ac.uk
  21.  
  22. ***************************************************************************
  23.  
  24. Libraries for communicating with a LeCroy scope (and perhaps other things)
  25. via TCP/IP. Based on "net_con.cpp" by LeCroy, also using bits of code from
  26. an ariticle in October 2001 issue of "Linux Magazine" see:
  27. http://www.linux-mag.com/2001-10/compile_01.html
  28.  
  29. The original "net_con.cpp" code was Copyright 1998 LeCroy Corporation, and
  30. written by Ricardo Palacio. This code was passed on to me (Steve
  31. Sharples) by LeCroy so that I could write drivers to communicate with my
  32. new LT584L DSO from my Linux machine. LeCroy corporation have agreed to
  33. allow the release of the UNIX/Linux code (since it is based on their code)
  34. under the GNU General Public License in the hope that it will be useful
  35. to others. THEY (LECROY) OBVIOUSLY CANNOT SUPPORT THIS CODE, although if
  36. I were them I'd be starting to think seriously about supporting the Linux/
  37. UNIX architectures.
  38.  
  39. See "lecroy_tcp.h" for additional comments and usage
  40.  
  41. **************************************************************************/
  42. // modified for LabWindows CVI by Samo 23. 5. 2013
  43.  
  44. #include <ansi_c.h>
  45. #include <stdlib.h>
  46. #include <winsock2.h>
  47. #include "lecroy_tcp.h"
  48.  
  49. //#define DEBUG
  50.  
  51. static WSADATA WSA_data;
  52. static BOOL     LECROY_TCP_connected_flag = FALSE;
  53.  
  54. typedef struct {        /* defines LeCroy VICP protocol (TCP header) */
  55.   unsigned char bEOI_Flag;
  56.   unsigned char reserved[3];
  57.   int           iLength;
  58. } LECROY_TCP_HEADER;
  59.  
  60. int LECROY_TCP_write(int sockfd, char *buf) {
  61.  
  62.   LECROY_TCP_HEADER header;
  63.   int result, bytes_more, bytes_xferd,tmp;
  64.   char *idxPtr;
  65.  
  66.   BOOL eoi_flag = TRUE;
  67.   int len               = strlen(buf);
  68.  
  69.   if (LECROY_TCP_connected_flag != TRUE) return -1;
  70. #ifdef DEBUG
  71.   printf("Sending %s\n",buf);
  72. #endif
  73.   /* set the header info */
  74.   header.bEOI_Flag = LECROY_DATA_FLAG;
  75.   /* following line retained because the original "write" function
  76.      contained an extra argument of eoi_flag, which I've set to
  77.      be always TRUE */
  78.   header.bEOI_Flag |= (eoi_flag)? LECROY_EOI_FLAG:0;
  79.   header.reserved[0] = 1; /* see LeCroy documentation about these */
  80.   header.reserved[1] = 0;
  81.   header.reserved[2] = 0;
  82.   header.iLength = htonl(len);
  83.  
  84.  
  85.   /* write the header first */
  86.   //tmp=write(sockfd, (char *) &header, sizeof(LECROY_TCP_HEADER));
  87.   tmp=send(sockfd, (char *) &header, sizeof(LECROY_TCP_HEADER),0);
  88.   if (tmp!=sizeof(LECROY_TCP_HEADER)) {
  89.     printf("Could not write the header successfully, returned: %d\n",tmp);
  90.         return -1;
  91.   }
  92.  
  93.   bytes_more = len;
  94.   idxPtr = buf;
  95.   bytes_xferd = 0;
  96.   while (1) {
  97.     /* then write the rest of the block */
  98.     idxPtr = buf + bytes_xferd;
  99.         //result=write (sockfd, (char *) idxPtr, bytes_more);
  100.         result=send (sockfd, (char *) idxPtr, bytes_more,0);
  101.         if (result<0) {
  102.       printf("Could not write the rest of the block successfully, returned: %d\n",tmp);
  103.       return -1;
  104.     }
  105.     bytes_xferd += result;
  106.     bytes_more -= result;
  107.     if (bytes_more <= 0) break;
  108.   }
  109.   return 0;
  110. }
  111.  
  112. int LECROY_TCP_read(int sockfd, char *buf, int len, int allowable_time) {
  113.  
  114.   LECROY_TCP_HEADER header;
  115.   char tmpStr[512];
  116.   int result, accum, space_left, bytes_more, buf_count;
  117.   char *idxPtr;
  118.  
  119.   fd_set rfds;
  120.   struct timeval tval;
  121.  
  122.   tval.tv_sec = allowable_time;
  123.   tval.tv_usec = 0;
  124.  
  125.   if (LECROY_TCP_connected_flag != TRUE) return -1;
  126.   FD_ZERO(&rfds);
  127.   FD_SET(sockfd, &rfds);
  128.  
  129.   if (buf==NULL) return -1;
  130.  
  131.   memset(buf, 0, len);
  132.   buf_count = 0;
  133.   space_left = len;
  134.  
  135.   while (1) {
  136.     /* block here until data is received of timeout expires */
  137.     result = select((sockfd+1), &rfds, NULL, NULL, &tval);
  138.     if (result < 0) {
  139.       LECROY_TCP_disconnect(sockfd);                   
  140.       printf("Read timeout\n");
  141.       return -1;
  142.     }
  143.     /* get the header info first */
  144.     accum = 0;
  145.     while (1) {
  146.       memset(&header, 0, sizeof(LECROY_TCP_HEADER));
  147.  
  148.       if ((result = recv(sockfd, (char *) &header + accum, sizeof(header) - accum, 0)) < 0) {
  149.         LECROY_TCP_disconnect(sockfd);                 
  150.         printf("Unable to receive header info from the server.\n");
  151.         return -1;
  152.       }
  153.       accum += result;
  154.       if (accum>=sizeof(header)) break;
  155.     }
  156.  
  157.     header.iLength = ntohl(header.iLength);
  158.     if (header.iLength < 1) return 0;
  159.  
  160.     /* only read to len amount */
  161.     if (header.iLength > space_left) {
  162.       header.iLength = space_left;
  163.       sprintf(tmpStr, "Read buffer size (%d bytes) is too small\n", len);
  164.       printf(tmpStr);
  165.     }
  166.  
  167.     /* read the rest of the block */
  168.     accum = 0;
  169.     while (1) {
  170.       idxPtr = buf + (buf_count + accum);
  171.       bytes_more = header.iLength - accum;
  172.       if ((space_left-accum) < LECROY_TCP_MINIMUM_PACKET_SIZE) {
  173.         LECROY_TCP_disconnect(sockfd);                 
  174.         printf("Read buffer needs to be adjusted, must be minimum of %d bytes\n",
  175.                LECROY_TCP_MINIMUM_PACKET_SIZE);
  176.         return -1;
  177.       }
  178.  
  179.       if ((result = recv(sockfd, (char *) idxPtr, (bytes_more>2048)?2048:bytes_more,0)) < 0) {
  180.         LECROY_TCP_disconnect(sockfd);                 
  181.         printf("Unable to receive data from the server.\n");
  182.         return -1;
  183.       }
  184.  
  185.  
  186.       accum += result;
  187.       if (accum >= header.iLength) break;
  188.       if ((accum + buf_count) >= len) break;
  189.     }
  190.     buf_count += accum;
  191.     space_left -= accum;
  192.  
  193.     if (header.bEOI_Flag & LECROY_EOI_FLAG) break;
  194.     if (space_left <= 0) break;
  195.   }
  196. #ifdef DEBUG
  197.   printf("Received %s\n",buf);
  198. #endif
  199.   return 0;
  200. }
  201.  
  202. int LECROY_TCP_connect(char *ip_address, int allowable_delay) {
  203.  
  204.   int sockfd;
  205.   int tmp;
  206.   const int disable=1;
  207.  
  208.   struct sockaddr_in addr;
  209.  
  210.   /* bomb out if we've already connected. At time of coding, many LeCroy
  211.    instruments (including my own scope) can support only one client at
  212.    a time */
  213.   if (LECROY_TCP_connected_flag==TRUE) {
  214.     printf("ERROR! lecroy_tcp: LECROY_TCP_connected_flag==TRUE!\n");
  215.     return -2;
  216.   }
  217.  
  218.   tmp=WSAStartup(2,&WSA_data);
  219.   if (tmp!=0) {
  220.     printf("ERROR! Socket library ...!\n");
  221.     return -1;
  222.   }
  223.   //printf("Socket library ...\n");
  224.  
  225.   sockfd = socket (PF_INET, SOCK_STREAM, 0);
  226.   /* Clear out the address struct. */
  227.   /* not sure this is entirely necessary.... */
  228.   // samo bzero (&addr, sizeof (addr));
  229.  
  230.   /* Initialize the values of the address struct including
  231.      port number and IP address. */
  232.   addr.sin_family = AF_INET;
  233.   addr.sin_port = htons (LECROY_SERVER_PORT);
  234.   addr.sin_addr.s_addr = inet_addr(ip_address);
  235.  
  236.   /* The following two lines are necessary so that the program doesn't
  237.      hang around waiting forever if the scope is turned off. You'd
  238.      think there would be something you could set in the socket options,
  239.      wouldn't you? Well, there is, but to quote the socket(7) man pages:
  240.  
  241. ------------------------------------------------------------------------------
  242.      SOCKET OPTIONS
  243.      SO_RCVTIMEO and SO_SNDTIMEO
  244.      Specify  the  sending  or  receiving timeouts until reporting an
  245.      error.  They are fixed to a protocol specific setting  in  Linux
  246.      and  cannot  be read or written. Their functionality can be emu-
  247.      lated using alarm(2) or setitimer(2).
  248. ------------------------------------------------------------------------------
  249.  
  250.          So, a timer is set with alarm(), and SIGALRM is caught by the
  251.          "LECROY_TCP_bored_now(int sig)" function. Upon successful
  252.      connection, however, the alarm is cancelled with "alarm(0)" */
  253.  
  254.          // samo signal(SIGALRM,LECROY_TCP_bored_now);
  255.          // samo alarm(allowable_delay);
  256.  
  257.          /* Connect to the server. */
  258.   tmp=connect(sockfd, (struct sockaddr *)&addr, sizeof (addr));
  259.   // samo alarm(0);
  260.   if (tmp<0){
  261.     tmp=WSACleanup();
  262.     printf("ERROR! lecroy_tcp: could not connect to the scope!\n");
  263.     return -1;
  264.   }
  265.   LECROY_TCP_connected_flag=TRUE;
  266.  
  267.   /* Ok, now we're all connected */
  268.  
  269.   /* THE FOLLOWING LINE IS ARCHITECTURE DEPENDENT
  270.      and is not at all necessary to make a connection and may be
  271.      safely removed */
  272.  
  273.   LECROY_TCP_write(sockfd,"CORD LO\n");
  274.  
  275.   /* It sets the 16-bit word transfer byte order to LSB,MSB (ie native
  276.      Intel format). This makes things easier to interpret, so it's a
  277.      sufficiently-useful thing to add in the connect function. Can be
  278.      commented out obviously. For motorola-based systems, use:
  279.      LECROY_TCP_write(sockfd,"CORD HI\n");
  280.      Obviously there'll be some way of working out at compile-time, but
  281.      I don't know how! --- sds, 6/5/03 */
  282.  
  283.   return sockfd;
  284. }
  285. /*
  286. void LECROY_TCP_bored_now(int sig) {
  287.  
  288.   printf("Well, I got bored waiting to connect, so I'm going to quit. Bye!\n");
  289.   exit(1);
  290.   }
  291. */
  292. int LECROY_TCP_disconnect(int sockfd) {
  293.  
  294.   if (LECROY_TCP_connected_flag !=TRUE) return -1;
  295.   closesocket(sockfd);
  296.   WSACleanup();
  297.   LECROY_TCP_connected_flag=FALSE;
  298.   return 0;
  299. }
  300.  
  301.