view loadtools/tpinterf2.c @ 248:cb1ba53a1106

beginning of factored-out libserial
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 21 Sep 2017 21:43:34 +0000
parents e7502631a0f9
children 8d7dcfd9df53
line wrap: on
line source

/*
 * This module provides a more advanced target interface function
 * than tpinterf.c - programmatic capture of target responses,
 * for dumps etc.  It will be linked by fc-loadtool, but not 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;

/*
 * This functions reads the serial output from the target until a
 * '=' prompt is received.  All intermediate output is parsed into
 * lines and passed to a callback function.
 *
 * The callback function is called with a pointer to each received
 * line, stored in a buffer ending in NUL, with CRLF stripped.
 * The callback function is expected to return an int.  If the
 * callback return value is negative, this function returns immediately
 * with that negative value.  If the callback return value is positive
 * or zero, it is added to an accumulator.
 *
 * Termination: this function returns when it has received a '=' at
 * the beginning of a line (return value is the callback return
 * accumulator, or 0 if no lines came), if the callback returns a
 * negative value (that value is returned), or if an error is detected
 * within this function (return value -1, and an error message
 * printed on stderr).
 */
tpinterf_capture_output(timeout, callback)
	int timeout;	/* seconds */
	int (*callback)();
{
	char buf[512], *cp;
	char line[1024], *dp = line;
	fd_set fds;
	struct timeval tv;
	int cc, linelen = 0;
	int totout = 0, cbret;

	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 == '=' && !linelen && !cc)
				return(totout);
			if (*cp == '\r')
				continue;
			if (*cp == '\n') {
				*dp = '\0';
				cbret = callback(line);
				if (cbret < 0)
					return(cbret);
				totout += cbret;
				dp = line;
				linelen = 0;
				continue;
			}
			*dp++ = *cp;
			linelen++;
			if (linelen >= sizeof line) {
				fprintf(stderr,
			"error: target response line length exceeds buffer\n");
				return(-1);
			}
		}
	}
}

/* single line response capture mechanism */
/* same line buffer size as in tpinterf_capture_output() */
char target_response_line[1024];

static
oneline_catcher(linein)
	char *linein;
{
	strcpy(target_response_line, linein);
	return(1);
}

tpinterf_capture_output_oneline(timeout)
{
	return tpinterf_capture_output(timeout, oneline_catcher);
}