view calypso/tpinterf.c @ 93:6041c601304d

fcsim1-mkprov: revert OTA key addition It appears that GrcardSIM2 cards (which is what we got for FCSIM1) do not support OTA after all, contrary to what we were previously led to believe by some tech support emails from Grcard - apparently those support emails and OTA descriptions referred to some other card model(s).
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 21 Apr 2021 05:38:39 +0000
parents b25d4dfe5798
children
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, finish = 0;
	unsigned goodchar;

	for (goodchar = 0; !finish; ) {
		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) {
				finish = 1;
				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);
}