FreeCalypso > hg > fc-sim-tools
view calypso/tpinterf.c @ 4:deeeef558279
fcsim-calypso-be put together
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 14 Mar 2021 05:07:34 +0000 |
parents | |
children | b25d4dfe5798 |
line wrap: on
line source
/* * This code is based on loadtools/tpinterf.c from FC host tools, * modified for our different application of interfacing between * simagent below and fc-simtool above. */ #include <sys/types.h> #include <sys/time.h> #include <sys/errno.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <unistd.h> extern int errno; extern int target_fd; /* definition matches target-utils/libcommon/cmdentry.c */ #define MAXCMD 527 /* * static buffer between tpinterf_make_cmd and tpinterf_send_cmd * * We store the command with an ending \r\n so we can use it for * matching the received echo as well, hence the sizing of the * buffer. */ static char cmdbuf[MAXCMD+2]; static int cmdlen; static int arg_chars_valid(arg) char *arg; { char *cp; for (cp = arg; *cp; cp++) if (*cp < ' ' || *cp > '~') return(0); return(1); } /* * This function takes a command for the target in argv form and * converts it to a space-separated continuous string which can be * passed as tty "keyboard" input to the target, enforcing length * and character validity limits in the process. The output is * stored in an internal static buffer for subsequent * tpinterf_send_cmd(). * * Return value: 0 if everything OK, or -1 if some constraint is * violated. */ tpinterf_make_cmd(argv) char **argv; { int arglen; char **ap, *dp; dp = cmdbuf; cmdlen = 0; for (ap = argv; *ap; ap++) { arglen = strlen(*ap); if (ap != argv) arglen++; /* separating space */ if (arglen > MAXCMD - cmdlen) return(-1); if (!arg_chars_valid(*ap)) return(-1); if (ap != argv) *dp++ = ' '; strcpy(dp, *ap); dp += strlen(*ap); cmdlen += arglen; } *dp++ = '\r'; *dp = '\n'; return(0); } /* * This function sends the previously-constructed command to the target, * and collects the expected echo. * * Return value: 0 if successful, -1 on errors (timeout or wrong response) */ tpinterf_send_cmd() { char echobuf[MAXCMD+2]; fd_set fds; struct timeval tv; int rcvd, cc; write(target_fd, cmdbuf, cmdlen + 1); for (rcvd = 0; rcvd < cmdlen + 2; ) { FD_ZERO(&fds); FD_SET(target_fd, &fds); tv.tv_sec = 1; tv.tv_usec = 0; cc = select(target_fd+1, &fds, NULL, NULL, &tv); if (cc < 0) { if (errno == EINTR) continue; printf("back end error: failed select\n"); return(-1); } if (cc < 1) { printf( "back end error: timeout waiting for command echo\n"); return(-1); } cc = read(target_fd, echobuf + rcvd, cmdlen + 2 - rcvd); if (cc <= 0) { printf( "back end error: failed read after successful select\n"); return(-1); } rcvd += cc; } if (bcmp(echobuf, cmdbuf, cmdlen + 2)) { printf("back end error: command echo mismatch\n"); return(-1); } else return(0); } /* * This functions reads the serial output from the target until a * '=' prompt is received. All intermediate output is passed to * stdout, with some hacks specific to this SIM interface back end. */ tpinterf_pass_output(timeout) { char buf[1024], *cp; fd_set fds; struct timeval tv; int cc, newline = 1, termflag = 0; unsigned goodchar; for (goodchar = 0; ; ) { FD_ZERO(&fds); FD_SET(target_fd, &fds); tv.tv_sec = timeout; tv.tv_usec = 0; cc = select(target_fd+1, &fds, NULL, NULL, &tv); if (cc < 0) { if (errno == EINTR) continue; printf("back end error: failed select\n"); return(-1); } if (cc < 1) { printf( "back end error: timeout waiting for simagent response\n"); return(-1); } cc = read(target_fd, buf + goodchar, sizeof(buf) - goodchar); if (cc <= 0) { printf( "back end error: failed read after successful select\n"); return(-1); } for (cp = buf + goodchar; cc; cp++) { cc--; if (*cp == '=' && newline && !cc) break; if (*cp == '\n') { newline = 1; termflag = 1; continue; } newline = 0; if (*cp == '\r') termflag = 1; if (!termflag) goodchar++; if (goodchar >= 516) termflag = 1; } } if (!goodchar) { printf("back end error: empty output from simagent\n"); return(-1); } buf[goodchar] = '\0'; puts(buf); return(0); }