FreeCalypso > hg > freecalypso-tools
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); +}