FreeCalypso > hg > freecalypso-tools
view uptools/atcmd/atinterf.c @ 926:6a0aa8d36d06
rvinterf backslash escape: introduce libprint
The new helper function library named libprint is meant to replace
the badly misnamed libg23, and will soon contain functions for
printing all of the same kinds of GPF TST packets that are now handled
in libg23. However, we are also moving safe_print_trace() from libasync
to this new library, and changing it to emit our new backslash escape
format.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 23 May 2023 03:47:46 +0000 |
parents | f0e9bb28b4d6 |
children |
line wrap: on
line source
/* * 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 (no_target_mode) { puts(command); if (message) puts(message); strcpy(at_response, "FOK"); return(0); } 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); }