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
00028
00029
00030
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <stdarg.h>
00035 #include <string.h>
00036 #include <ctype.h>
00037 #include <unistd.h>
00038 #include <sys/socket.h>
00039 #include <sys/types.h>
00040 #include <netdb.h>
00041 #include <arpa/inet.h>
00042
00043 #include "pigpio.h"
00044 #include "command.h"
00045 #include "pigs.h"
00046
00047
00048
00049
00050
00051
00052 char command_buf[CMD_MAX_EXTENSION];
00053 char response_buf[CMD_MAX_EXTENSION];
00054
00055 int printFlags = 0;
00056
00057 int status = PIGS_OK;
00058
00059 #define SOCKET_OPEN_FAILED -1
00060
00061 #define PRINT_HEX 1
00062 #define PRINT_ASCII 2
00063
00064 void report(int err, char *fmt, ...)
00065 {
00066 char buf[128];
00067 va_list ap;
00068
00069 if (err > status) status = err;
00070
00071 va_start(ap, fmt);
00072 vsnprintf(buf, sizeof(buf), fmt, ap);
00073 va_end(ap);
00074
00075 fprintf(stderr, "%s\n", buf);
00076
00077 fflush(stderr);
00078 }
00079
00080 static int initOpts(int argc, char *argv[])
00081 {
00082 int opt, args;
00083
00084 opterr = 0;
00085
00086 args = 1;
00087
00088 while ((opt = getopt(argc, argv, "ax")) != -1)
00089 {
00090 switch (opt)
00091 {
00092 case 'a':
00093 printFlags |= PRINT_ASCII;
00094 args++;
00095 break;
00096
00097 case 'x':
00098 printFlags |= PRINT_HEX;
00099 args++;
00100 break;
00101
00102 default:
00103 args++;
00104 report(PIGS_OPTION_ERR, "ERROR: bad option %c", optopt);
00105 }
00106 }
00107 return args;
00108 }
00109
00110 static int openSocket(void)
00111 {
00112 int sock, err;
00113 struct addrinfo hints, *res, *rp;
00114 const char *addrStr, *portStr;
00115
00116 portStr = getenv(PI_ENVPORT);
00117
00118 if (!portStr) portStr = PI_DEFAULT_SOCKET_PORT_STR;
00119
00120 addrStr = getenv(PI_ENVADDR);
00121
00122 if (!addrStr) addrStr = PI_DEFAULT_SOCKET_ADDR_STR;
00123
00124 memset (&hints, 0, sizeof (hints));
00125
00126 hints.ai_family = PF_UNSPEC;
00127 hints.ai_socktype = SOCK_STREAM;
00128 hints.ai_flags |= AI_CANONNAME;
00129
00130 err = getaddrinfo(addrStr, portStr, &hints, &res);
00131
00132 if (err) return SOCKET_OPEN_FAILED;
00133
00134 for (rp=res; rp!=NULL; rp=rp->ai_next)
00135 {
00136 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
00137
00138 if (sock == -1) continue;
00139
00140 if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
00141 }
00142
00143 freeaddrinfo(res);
00144
00145 if (rp == NULL) return SOCKET_OPEN_FAILED;
00146
00147 return sock;
00148 }
00149
00150 void print_result(int sock, int rv, cmdCmd_t cmd)
00151 {
00152 int i, r, ch;
00153 uint32_t *p;
00154
00155 r = cmd.res;
00156
00157 switch (rv)
00158 {
00159 case 0:
00160 case 1:
00161 if (r < 0)
00162 {
00163 printf("%d\n", r);
00164 report(PIGS_SCRIPT_ERR, "ERROR: %s", cmdErrStr(r));
00165 }
00166 break;
00167
00168 case 2:
00169 printf("%d\n", r);
00170 if (r < 0) report(PIGS_SCRIPT_ERR, "ERROR: %s", cmdErrStr(r));
00171 break;
00172
00173 case 3:
00174 printf("%08X\n", cmd.res);
00175 break;
00176
00177 case 4:
00178 printf("%u\n", cmd.res);
00179 break;
00180
00181 case 5:
00182 printf("%s", cmdUsage);
00183 break;
00184
00185 case 6:
00186
00187
00188
00189 printf("%d", r);
00190 if (r < 0) report(PIGS_SCRIPT_ERR, "ERROR: %s", cmdErrStr(r));
00191 if (r > 0)
00192 {
00193 if (printFlags == PRINT_ASCII) printf(" ");
00194
00195 for (i=0; i<r; i++)
00196 {
00197 ch = response_buf[i];
00198
00199 if (printFlags & PRINT_HEX) printf(" %hhx", ch);
00200
00201 else if (printFlags & PRINT_ASCII)
00202 {
00203 if (isprint(ch) || (ch == '\n') || (ch == '\r'))
00204 printf("%c", ch);
00205 else printf("\\x%02hhx", ch);
00206 }
00207 else printf(" %hhu", response_buf[i]);
00208 }
00209 }
00210 printf("\n");
00211 break;
00212
00213 case 7:
00214 if (r != (4 + (4*PI_MAX_SCRIPT_PARAMS)))
00215 {
00216 printf("%d", r);
00217 report(PIGS_SCRIPT_ERR, "ERROR: %s", cmdErrStr(r));
00218 }
00219 else
00220 {
00221 p = (uint32_t *)response_buf;
00222 printf("%d", p[0]);
00223 for (i=0; i<PI_MAX_SCRIPT_PARAMS; i++)
00224 {
00225 printf(" %d", p[i+1]);
00226 }
00227 }
00228 printf("\n");
00229 break;
00230
00231 case 8:
00232
00233
00234 if (r < 0)
00235 {
00236 printf("%d", r);
00237 report(PIGS_SCRIPT_ERR, "ERROR: %s", cmdErrStr(r));
00238 }
00239
00240 p = (uint32_t *)response_buf;
00241 printf("%d %d", r-3, p[0]);
00242
00243 if (r > 4)
00244 {
00245 if (printFlags == PRINT_ASCII) printf(" ");
00246
00247 for (i=4; i<r; i++)
00248 {
00249 ch = response_buf[i];
00250
00251 if (printFlags & PRINT_HEX) printf(" %hhx", ch);
00252
00253 else if (printFlags & PRINT_ASCII)
00254 {
00255 if (isprint(ch) || (ch == '\n') || (ch == '\r'))
00256 printf("%c", ch);
00257 else printf("\\x%02hhx", ch);
00258 }
00259 else printf(" %hhu", response_buf[i]);
00260 }
00261 }
00262 printf("\n");
00263 break;
00264
00265 }
00266 }
00267
00268 void get_extensions(int sock, int command, int res)
00269 {
00270 switch (command)
00271 {
00272 case PI_CMD_BI2CZ:
00273 case PI_CMD_BSCX:
00274 case PI_CMD_BSPIX:
00275 case PI_CMD_CF2:
00276 case PI_CMD_FL:
00277 case PI_CMD_FR:
00278 case PI_CMD_I2CPK:
00279 case PI_CMD_I2CRD:
00280 case PI_CMD_I2CRI:
00281 case PI_CMD_I2CRK:
00282 case PI_CMD_I2CZ:
00283 case PI_CMD_PROCP:
00284 case PI_CMD_SERR:
00285 case PI_CMD_SLR:
00286 case PI_CMD_SPIX:
00287 case PI_CMD_SPIR:
00288
00289 if (res > 0)
00290 {
00291 recv(sock, response_buf, res, MSG_WAITALL);
00292 response_buf[res] = 0;
00293 }
00294 break;
00295 }
00296 }
00297
00298 int main(int argc , char *argv[])
00299 {
00300 int sock, command;
00301 int args, idx, i, pp, l, len;
00302 cmdCmd_t cmd;
00303 uint32_t p[CMD_P_ARR];
00304 cmdCtlParse_t ctl;
00305 cmdScript_t s;
00306 char v[CMD_MAX_EXTENSION];
00307
00308 sock = openSocket();
00309
00310 args = initOpts(argc, argv);
00311
00312 command_buf[0] = 0;
00313 l = 0;
00314 pp = 0;
00315
00316 for (i=args; i<argc; i++)
00317 {
00318 l += (strlen(argv[i]) + 1);
00319 if (l < sizeof(command_buf))
00320 {sprintf(command_buf+pp, "%s ", argv[i]); pp=l;}
00321 }
00322
00323 if (pp) {command_buf[--pp] = 0;}
00324
00325 ctl.eaten = 0;
00326
00327 len = strlen(command_buf);
00328 idx = 0;
00329
00330 while ((idx >= 0) && (ctl.eaten < len))
00331 {
00332 if ((idx=cmdParse(command_buf, p, CMD_MAX_EXTENSION, v, &ctl)) >= 0)
00333 {
00334 command = p[0];
00335
00336 if (command < PI_CMD_SCRIPT)
00337 {
00338 if (command == PI_CMD_HELP)
00339 {
00340 printf("%s", cmdUsage);
00341 }
00342 else if (command == PI_CMD_PARSE)
00343 {
00344 cmdParseScript(v, &s, 1);
00345 if (s.par) free (s.par);
00346 }
00347 else
00348 {
00349 cmd.cmd = command;
00350 cmd.p1 = p[1];
00351 cmd.p2 = p[2];
00352 cmd.p3 = p[3];
00353
00354 if (sock != SOCKET_OPEN_FAILED)
00355 {
00356 if (send(sock, &cmd, sizeof(cmdCmd_t), 0) ==
00357 sizeof(cmdCmd_t))
00358 {
00359 if (p[3]) send(sock, v, p[3], 0);
00360
00361 if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) ==
00362 sizeof(cmdCmd_t))
00363 {
00364 get_extensions(sock, command, cmd.res);
00365
00366 print_result(sock, cmdInfo[idx].rv, cmd);
00367 }
00368 else report(PIGS_CONNECT_ERR, "socket receive failed");
00369 }
00370 else report(PIGS_CONNECT_ERR, "socket send failed");
00371 }
00372 else report(PIGS_CONNECT_ERR, "socket connect failed");
00373 }
00374 }
00375 else report(PIGS_SCRIPT_ERR,
00376 "%s only allowed within a script", cmdInfo[idx].name);
00377 }
00378 else
00379 {
00380 if (idx == CMD_UNKNOWN_CMD)
00381 report(PIGS_SCRIPT_ERR,
00382 "%s? unknown command, pigs h for help", cmdStr());
00383 else
00384 report(PIGS_SCRIPT_ERR,
00385 "%s: bad parameter, pigs h for help", cmdStr());
00386 }
00387 }
00388
00389 if (sock >= 0) close(sock);
00390
00391 return status;
00392 }
00393