00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <getopt.h>
00030 #include <string.h>
00031 #include <fcntl.h>
00032 #include <errno.h>
00033 #include <sys/socket.h>
00034 #include <netinet/in.h>
00035 #include <netinet/tcp.h>
00036 #include <arpa/inet.h>
00037 #include <sys/file.h>
00038
00039
00040 #define APP_VERSION "1.0.0"
00041 #define NET_NODELAY 1 // TCP nodelay enabled
00042 #define NET_TIMEOUT 4 // Network timeout in seconds (default)
00043 #define NET_MAX_NODES 256
00044 #define ERR -1
00045 #define NET_MAX_BUF 1500
00046 #define BROADCAST_ADDR "255.255.255.255"
00047 #define BROADCAST_PORT 111
00048
00049
00050 #define INFO(format, args...) \
00051 fprintf (stdout, "" format, ## args)
00052
00053 #define ERROR(format, args...) \
00054 fprintf (stderr, "Error: " format, ## args)
00055
00056 #define MODE_NORMAL 0
00057 #define MODE_DISCOVERY 1
00058
00059
00060 static struct {
00061 char *ip;
00062 unsigned int port;
00063 char *command;
00064 int socket;
00065 int mode;
00066 int timeout;
00067 } config = {
00068 NULL,
00069 9221,
00070 NULL,
00071 0,
00072 MODE_NORMAL,
00073 NET_TIMEOUT
00074 };
00075
00076
00077 char rpc_GETPORT_msg[] = {
00078 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00,
00079 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x86, 0xa0,
00080 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
00081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00083 0x00, 0x06, 0x07, 0xaf, 0x00, 0x00, 0x00, 0x01,
00084 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 };
00085
00086
00087
00088 void print_help(void)
00089 {
00090 INFO("Usage: lxi-control [options]\n");
00091 INFO("\n");
00092 INFO("Options:\n");
00093 INFO("--ip <ip> Remote device IP\n");
00094 INFO("--port <port> Remote device port (default: %d)\n",
00095 config.port);
00096 INFO("--scpi <command> SCPI command\n");
00097 INFO("--timeout <seconds> Network timeout (default: %d s)\n",
00098 config.timeout);
00099 INFO("--discover Discover LXI devices on hosts subnet\n");
00100 INFO("--version Display version\n");
00101 INFO("--help Display help\n");
00102 INFO("\n");
00103 }
00104
00105 static int parse_options(int argc, char *argv[])
00106 {
00107 static int c;
00108
00109
00110 if (argc == 1)
00111 {
00112 print_help();
00113 exit(0);
00114 }
00115
00116 while (1)
00117 {
00118 static struct option long_options[] =
00119 {
00120 {"ip", required_argument, 0, 'i'},
00121 {"port", required_argument, 0, 'p'},
00122 {"scpi", required_argument, 0, 's'},
00123 {"timeout", no_argument, 0, 't'},
00124 {"discover", no_argument, 0, 'd'},
00125 {"version", no_argument, 0, 'v'},
00126 {"help", no_argument, 0, 'h'},
00127 {0, 0, 0, 0}
00128 };
00129
00130
00131 int option_index = 0;
00132
00133
00134 c = getopt_long (argc, argv, "", long_options, &option_index);
00135
00136
00137 if (c == -1)
00138 break;
00139
00140 switch (c)
00141 {
00142 case 0:
00143
00144 if (long_options[option_index].flag != 0)
00145 break;
00146 INFO("option %s", long_options[option_index].name);
00147 if (optarg)
00148 INFO(" with arg %s", optarg);
00149 INFO("\n");
00150 break;
00151
00152 case 'i':
00153 config.ip = optarg;
00154 break;
00155
00156 case 'p':
00157 config.port = atoi(optarg);
00158 break;
00159
00160 case 's':
00161 config.command = optarg;
00162 break;
00163
00164 case 'v':
00165 INFO("lxi-control v%s\n", APP_VERSION);
00166 exit(0);
00167 break;
00168
00169 case 'd':
00170 config.mode = MODE_DISCOVERY;
00171 break;
00172
00173 case 'h':
00174 print_help();
00175 exit(0);
00176 break;
00177
00178 case '?':
00179
00180 break;
00181
00182 default:
00183 ERROR("End of options\n");
00184 exit(1);
00185 }
00186 }
00187
00188
00189 if ((config.ip == NULL) && (config.mode == MODE_NORMAL))
00190 {
00191 ERROR("Missing option: --ip\n");
00192 exit(1);
00193 }
00194
00195
00196 if (optind < argc)
00197 {
00198 ERROR("%s: unknown arguments: ", argv[0]);
00199 while (optind < argc)
00200 ERROR("%s ", argv[optind++]);
00201 ERROR("\n");
00202 exit(1);
00203 }
00204 }
00205
00206 static int disconnect_instrument(void)
00207 {
00208
00209 if(close(config.socket)==ERR)
00210 {
00211 ERROR("Error closing socket\n");
00212 exit(1);
00213 }
00214
00215 return 0;
00216 }
00217
00218 static int connect_instrument(void)
00219 {
00220 int retval = 0;
00221 struct sockaddr_in recv_addr = { 0 };
00222 int state_nodelay = NET_NODELAY;
00223 struct timeval tv;
00224
00225
00226 config.socket = socket(PF_INET,SOCK_STREAM,0);
00227
00228 if(config.socket == ERR)
00229 {
00230 ERROR("Error connecting socket\n");
00231 exit(1);
00232 }
00233
00234
00235 setsockopt(config.socket, IPPROTO_TCP, TCP_NODELAY,
00236 (void *)&state_nodelay,sizeof state_nodelay);
00237
00238
00239 tv.tv_sec = config.timeout;
00240 tv.tv_usec = 0;
00241 if ((setsockopt(config.socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) == ERR)
00242 {
00243 perror("setsockopt - SO_RCVTIMEO");
00244 exit(1);
00245 }
00246
00247
00248 memset(&recv_addr,0,sizeof(struct sockaddr_in));
00249 recv_addr.sin_family=PF_INET;
00250 recv_addr.sin_port=htons(config.port);
00251 inet_aton(config.ip, &recv_addr.sin_addr);
00252
00253
00254 retval = connect(config.socket,(struct sockaddr *)&recv_addr,
00255 sizeof(struct sockaddr_in));
00256 if(retval == ERR)
00257 {
00259 return 1;
00260 }
00261 return retval;
00262 }
00263
00264 static int send_command(void)
00265 {
00266 int retval = 0;
00267
00268
00269 config.command[strlen(config.command)] = 0;
00270
00271
00272 retval = send(config.socket,config.command,strlen(config.command)+1,0);
00273 if (retval == ERR)
00274 {
00275 ERROR("Error sending SCPI command\n");
00276 exit(1);
00277 }
00278
00279 return retval;
00280 }
00281
00282 static int receive_response(void)
00283 {
00284 char buffer[500];
00285 int length;
00286 int i, question = 0;
00287
00288
00289 for (i=0; i<strlen(config.command);i++)
00290 {
00291 if (config.command[i] == '?')
00292 question=1;
00293 }
00294 if (question == 0)
00295 return 0;
00296
00297
00298 if((length=recv(config.socket,&buffer[0],200,0))==ERR)
00299 {
00300 ERROR("Error reading response\n");
00301 exit(1);
00302 }
00303
00304
00305 buffer[length]=0;
00306
00307
00308 printf("%s",buffer);
00309
00310 return 0;
00311 }
00312
00313 static int discover_instruments(void)
00314 {
00315 int sockfd;
00316 struct sockaddr_in send_addr;
00317 struct sockaddr_in recv_addr;
00318 int broadcast = 1;
00319 int count;
00320 int addrlen;
00321 char buf[NET_MAX_BUF];
00322 struct timeval tv;
00323 struct in_addr ip_list[NET_MAX_NODES];
00324 int i = 0;
00325 int j = 0;
00326 char idn_command[] = "*IDN?";
00327
00328 INFO("\nDiscovering LXI devices on hosts subnet - please wait...\n");
00329
00330
00331 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
00332 if (sockfd == -1)
00333 {
00334 perror("Socket creation error");
00335 exit(1);
00336 }
00337
00338
00339 if((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
00340 &broadcast,sizeof (broadcast))) == ERR)
00341 {
00342 perror("setsockopt - SO_SOCKET");
00343 exit(1);
00344 }
00345
00346
00347 tv.tv_sec = config.timeout;
00348 tv.tv_usec = 0;
00349 if ((setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) == ERR)
00350 {
00351 perror("setsockopt - SO_RCVTIMEO");
00352 exit(1);
00353 }
00354
00355
00356 send_addr.sin_family = AF_INET;
00357 send_addr.sin_addr.s_addr = INADDR_ANY;
00358 send_addr.sin_port = 0;
00359
00360
00361 bind(sockfd, (struct sockaddr*)&send_addr, sizeof(send_addr));
00362
00363
00364 recv_addr.sin_family = AF_INET;
00365 recv_addr.sin_addr.s_addr = inet_addr(BROADCAST_ADDR);
00366 recv_addr.sin_port = htons(BROADCAST_PORT);
00367
00368
00369 sendto(sockfd, rpc_GETPORT_msg, sizeof(rpc_GETPORT_msg), 0,
00370 (struct sockaddr*)&recv_addr, sizeof(recv_addr));
00371
00372 addrlen = sizeof(recv_addr);
00373
00374
00375 do {
00376 count = recvfrom(sockfd, buf, NET_MAX_BUF, 0,
00377 (struct sockaddr*)&recv_addr, &addrlen);
00378 if (count > 0)
00379 {
00380 ip_list[i] = recv_addr.sin_addr;
00381 i++;
00382 }
00383 } while (count > 0);
00384
00385 INFO("\nDiscovered devices:\n");
00386
00387
00388 for (j=0; j<i; j++)
00389 {
00390 config.ip = inet_ntoa(ip_list[j]);
00391 if (connect_instrument() == 0)
00392 {
00393 config.command = idn_command;
00394
00395 send_command();
00396
00397 INFO("IP %s - ", config.ip);
00398
00399 receive_response();
00400
00401 disconnect_instrument();
00402 }
00403 }
00404
00405 INFO("\n");
00406
00407 return 0;
00408 }
00409 int lxi_control (int argc, char *argv[])
00410 {
00411
00412 parse_options(argc, argv);
00413
00414 if (config.mode == MODE_DISCOVERY)
00415 {
00416
00417 discover_instruments();
00418 }
00419 else
00420 {
00421
00422
00423 connect_instrument();
00424
00425
00426 send_command();
00427
00428
00429 receive_response();
00430
00431
00432 disconnect_instrument();
00433 }
00434
00435 return (0);
00436 }