FreeCalypso > hg > fc-sim-tools
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/calypso/tpinterf.c Sun Mar 14 05:07:34 2021 +0000 @@ -0,0 +1,190 @@ +/* + * 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); +}