FreeCalypso > hg > freecalypso-tools
diff uptools/atcmd/atinterf.c @ 348:64dcbabd48ca
uptools/atcmd framework started
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 04 Feb 2018 18:38:20 +0000 |
parents | |
children | 9ffaeb6fea1a |
line wrap: on
line diff
--- /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); +}