FreeCalypso > hg > freecalypso-sw
view loadtools/tpinterf.c @ 117:e40d8661ecab
nuc-fw: low-level serial code should be complete
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 28 Oct 2013 07:35:47 +0000 |
parents | 05af070c4b60 |
children |
line wrap: on
line source
/* * Target program interface - this module provides some primitives * for communicating programmatically with loadagent and possibly * other target-utils. This module will be linked by both * fc-loadtool and fc-chainload. */ #include <sys/types.h> #include <sys/time.h> #include <sys/errno.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.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; perror("select"); return(-1); } if (cc < 1) { fprintf(stderr, "error: timeout waiting for command echo\n"); return(-1); } cc = read(target_fd, echobuf + rcvd, cmdlen + 2 - rcvd); if (cc <= 0) { perror("read after successful select"); return(-1); } rcvd += cc; } if (bcmp(echobuf, cmdbuf, cmdlen + 2)) { fprintf(stderr, "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. * * Return value: 0 if '=' prompt received immediately, * positive if some scribble came before the prompt, -1 on errors * (timeout, read errors, etc). */ tpinterf_pass_output(timeout) { char buf[512], *cp; fd_set fds; struct timeval tv; int cc, newline = 1, totout = 0; for (;;) { 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; perror("select"); return(-1); } if (cc < 1) { fprintf(stderr, "error: timeout waiting for \'=\' prompt from target\n"); return(-1); } cc = read(target_fd, buf, sizeof buf); if (cc <= 0) { perror("read after successful select"); return(-1); } for (cp = buf; cc; cp++) { cc--; if (*cp == '=' && newline && !cc) return(totout); putchar(*cp); totout++; if (*cp == '\n') newline = 1; else newline = 0; } } }