diff loadtools/tpinterf2.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 8d7dcfd9df53
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/tpinterf2.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,113 @@
+/*
+ * 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);
+}