changeset 348:64dcbabd48ca

uptools/atcmd framework started
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 04 Feb 2018 18:38:20 +0000
parents dd5bab5156bf
children b0cb465290f7
files .hgignore uptools/atcmd/Makefile uptools/atcmd/atcmd.c uptools/atcmd/atinterf.c
diffstat 4 files changed, 272 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Feb 04 17:05:35 2018 +0000
+++ b/.hgignore	Sun Feb 04 18:38:20 2018 +0000
@@ -60,5 +60,6 @@
 ^toolchain/newlib-2\.0\.0/
 ^toolchain/newlib-build/
 
+^uptools/atcmd/fcup-at$
 ^uptools/atinterf/fcup-atinterf$
 ^uptools/sms-pdu-decode/sms-pdu-decode$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uptools/atcmd/Makefile	Sun Feb 04 18:38:20 2018 +0000
@@ -0,0 +1,20 @@
+CC=	gcc
+CFLAGS=	-O2
+PROGS=	fcup-at
+INSTBIN=/opt/freecalypso/bin
+
+LIBCODING=	../libcoding/libcoding.a
+
+ATCMD_OBJS=	atcmd.o atinterf.o
+
+all:	${PROGS}
+
+fcup-at:	${ATCMD_OBJS}
+	${CC} ${CFLAGS} -o $@ ${ATCMD_OBJS}
+
+install:	${PROGS}
+	mkdir -p ${INSTBIN}
+	install -c ${PROGS} ${INSTBIN}
+
+clean:
+	rm -f *.o *.out *errs ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uptools/atcmd/atcmd.c	Sun Feb 04 18:38:20 2018 +0000
@@ -0,0 +1,37 @@
+/*
+ * This utility allows a single AT command to be issued
+ * through the atinterf framework.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "../../rvinterf/include/exitcodes.h"
+
+extern char at_response[];
+
+int_callback()
+{
+	puts(at_response+1);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	int c;
+	extern int optind;
+
+	while ((c = getopt(argc, argv, "B:np:RX:")) != EOF)
+		if (!atinterf_cmdline_opt(c)) {
+			/* error msg already printed */
+			exit(ERROR_USAGE);
+		}
+	if (argc != optind + 1 || strncasecmp(argv[optind], "AT", 2)) {
+		fprintf(stderr, "usage: %s [options] at-cmd\n", argv[0]);
+		exit(ERROR_USAGE);
+	}
+	atinterf_init();
+	atinterf_exec_cmd(argv[optind], 0, int_callback);
+	puts(at_response+1);
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uptools/atcmd/atinterf.c	Sun Feb 04 18:38:20 2018 +0000
@@ -0,0 +1,214 @@
+/*
+ * This module implements the interface functions to the AT command phone or
+ * modem to be used by the rest of the FreeCalypso User Phone tools suite.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include "../../rvinterf/include/exitcodes.h"
+
+static char atinterf_pathname[] = "/opt/freecalypso/bin/fcup-atinterf";
+static char rvtat_pathname[] = "/opt/freecalypso/bin/fcup-rvtat";
+static char shell_pathname[] = "/bin/sh";
+
+char *target_ttyport, *target_baud, *external_prog;
+int rvtat_mode, no_target_mode;
+static char *backend_prog, *backend_argv[6];
+
+FILE *cpipeF, *rpipeF;
+char at_response[514];
+
+atinterf_cmdline_opt(opt)
+{
+	extern char *optarg;
+
+	switch (opt) {
+	case 'B':
+		target_baud = optarg;
+		return(1);
+	case 'n':
+		no_target_mode = 1;
+		return(1);
+	case 'p':
+		target_ttyport = optarg;
+		return(1);
+	case 'R':
+		rvtat_mode = 1;
+		return(1);
+	case 'X':
+		external_prog = optarg;
+		return(1);
+	}
+	return(0);
+}
+
+static void
+preen_port_baud_config()
+{
+	if (!target_ttyport && target_baud) {
+		fprintf(stderr, "error: -B option invalid without -p\n");
+		exit(ERROR_USAGE);
+	}
+	if (rvtat_mode)
+		return;
+	if (!target_ttyport) {
+		target_ttyport = getenv("FC_GSM_DEVICE");
+		if (!target_ttyport) {
+			fprintf(stderr,
+				"error: no FC GSM device target specified\n");
+			exit(ERROR_USAGE);
+		}
+	}
+	if (!target_baud)
+		target_baud = "115200";
+}
+
+static void
+setup_be_native_at()
+{
+	backend_prog = atinterf_pathname;
+	backend_argv[0] = "fcup-atinterf";
+	backend_argv[1] = target_ttyport;
+	backend_argv[2] = target_baud;
+	backend_argv[3] = 0;
+}
+
+static void
+setup_be_rvtat()
+{
+	char **ap;
+
+	backend_prog = rvtat_pathname;
+	ap = backend_argv;
+	*ap++ = "fcup-rvtat";
+	if (target_ttyport) {
+		*ap++ = "-p";
+		*ap++ = target_ttyport;
+	}
+	if (target_baud) {
+		*ap++ = "-B";
+		*ap++ = target_baud;
+	}
+	*ap = 0;
+}
+
+static void
+setup_be_external()
+{
+	backend_prog = shell_pathname;
+	backend_argv[0] = "sh";
+	backend_argv[1] = "-c";
+	backend_argv[2] = external_prog;
+	backend_argv[3] = 0;
+}
+
+atinterf_init()
+{
+	int cpipe[2], rpipe[2], rc;
+
+	if (!no_target_mode)
+		return(0);
+	if (external_prog)
+		setup_be_external();
+	else {
+		preen_port_baud_config();
+		if (rvtat_mode)
+			setup_be_rvtat();
+		else
+			setup_be_native_at();
+	}
+	if (pipe(cpipe) < 0 || pipe(rpipe) < 0) {
+		perror("pipe");
+		exit(ERROR_UNIX);
+	}
+	rc = vfork();
+	if (rc < 0) {
+		perror("vfork for launching back end");
+		exit(ERROR_UNIX);
+	}
+	if (!rc) {
+		/* we are in the child - prepare to exec the BE */
+		dup2(cpipe[0], 0);
+		dup2(rpipe[1], 1);
+		close(cpipe[0]);
+		close(cpipe[1]);
+		close(rpipe[0]);
+		close(rpipe[1]);
+		/* do the exec */
+		execv(backend_prog, backend_argv);
+		perror(backend_prog);
+		_exit(1);
+	}
+	close(cpipe[0]);
+	close(rpipe[1]);
+	cpipeF = fdopen(cpipe[1], "w");
+	if (!cpipeF) {
+		perror("fdopen");
+		exit(ERROR_UNIX);
+	}
+	rpipeF = fdopen(rpipe[0], "r");
+	if (!rpipeF) {
+		perror("fdopen");
+		exit(ERROR_UNIX);
+	}
+	return(0);
+}
+
+atinterf_exec_cmd(command, message, callback)
+	char *command, *message;
+	void (*callback)();
+{
+	char *nl;
+
+	if (message) {
+		fputs("c+m\n", cpipeF);
+		fprintf(cpipeF, "%s\n", command);
+		fprintf(cpipeF, "%s\n", message);
+	} else
+		fprintf(cpipeF, "%s\n", command);
+	fflush(cpipeF);
+	for (;;) {
+		if (!fgets(at_response, sizeof at_response, rpipeF)) {
+			fprintf(stderr,
+				"error reading AT response from back end\n");
+			exit(ERROR_RVINTERF);
+		}
+		nl = index(at_response, '\n');
+		if (!nl) {
+			fprintf(stderr,
+		"error: back end response is too long or unterminated\n");
+			exit(ERROR_RVINTERF);
+		}
+		*nl = '\0';
+		switch (at_response[0]) {
+		case 'E':
+			fprintf(stderr, "error from back end: %s\n",
+				at_response + 1);
+			exit(ERROR_RVINTERF);
+		case 'F':
+			return(0);
+		case 'I':
+			if (callback)
+				callback();
+			continue;
+		}
+		fprintf(stderr, "error: invalid response from back end\n");
+		exit(ERROR_RVINTERF);
+	}
+}
+
+atinterf_exec_cmd_needok(command, message, callback)
+	char *command, *message;
+	void (*callback)();
+{
+	atinterf_exec_cmd(command, message, callback);
+	if (strcmp(at_response+1, "OK")) {
+		fprintf(stderr, "AT error: %s\n", at_response+1);
+		exit(ERROR_TARGET);
+	}
+	return(0);
+}