Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
65 f9daq 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