FreeCalypso > hg > freecalypso-tools
view uptools/atcmd/atinterf.c @ 913:1b8929cb7371
doc/Host-tools-overview: document fc-vm2gsmx
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 29 Dec 2022 21:36:37 +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); }