FreeCalypso > hg > freecalypso-tools
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 347:dd5bab5156bf | 348:64dcbabd48ca |
|---|---|
| 1 /* | |
| 2 * This module implements the interface functions to the AT command phone or | |
| 3 * modem to be used by the rest of the FreeCalypso User Phone tools suite. | |
| 4 */ | |
| 5 | |
| 6 #include <sys/types.h> | |
| 7 #include <stdio.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <string.h> | |
| 10 #include <strings.h> | |
| 11 #include <unistd.h> | |
| 12 #include "../../rvinterf/include/exitcodes.h" | |
| 13 | |
| 14 static char atinterf_pathname[] = "/opt/freecalypso/bin/fcup-atinterf"; | |
| 15 static char rvtat_pathname[] = "/opt/freecalypso/bin/fcup-rvtat"; | |
| 16 static char shell_pathname[] = "/bin/sh"; | |
| 17 | |
| 18 char *target_ttyport, *target_baud, *external_prog; | |
| 19 int rvtat_mode, no_target_mode; | |
| 20 static char *backend_prog, *backend_argv[6]; | |
| 21 | |
| 22 FILE *cpipeF, *rpipeF; | |
| 23 char at_response[514]; | |
| 24 | |
| 25 atinterf_cmdline_opt(opt) | |
| 26 { | |
| 27 extern char *optarg; | |
| 28 | |
| 29 switch (opt) { | |
| 30 case 'B': | |
| 31 target_baud = optarg; | |
| 32 return(1); | |
| 33 case 'n': | |
| 34 no_target_mode = 1; | |
| 35 return(1); | |
| 36 case 'p': | |
| 37 target_ttyport = optarg; | |
| 38 return(1); | |
| 39 case 'R': | |
| 40 rvtat_mode = 1; | |
| 41 return(1); | |
| 42 case 'X': | |
| 43 external_prog = optarg; | |
| 44 return(1); | |
| 45 } | |
| 46 return(0); | |
| 47 } | |
| 48 | |
| 49 static void | |
| 50 preen_port_baud_config() | |
| 51 { | |
| 52 if (!target_ttyport && target_baud) { | |
| 53 fprintf(stderr, "error: -B option invalid without -p\n"); | |
| 54 exit(ERROR_USAGE); | |
| 55 } | |
| 56 if (rvtat_mode) | |
| 57 return; | |
| 58 if (!target_ttyport) { | |
| 59 target_ttyport = getenv("FC_GSM_DEVICE"); | |
| 60 if (!target_ttyport) { | |
| 61 fprintf(stderr, | |
| 62 "error: no FC GSM device target specified\n"); | |
| 63 exit(ERROR_USAGE); | |
| 64 } | |
| 65 } | |
| 66 if (!target_baud) | |
| 67 target_baud = "115200"; | |
| 68 } | |
| 69 | |
| 70 static void | |
| 71 setup_be_native_at() | |
| 72 { | |
| 73 backend_prog = atinterf_pathname; | |
| 74 backend_argv[0] = "fcup-atinterf"; | |
| 75 backend_argv[1] = target_ttyport; | |
| 76 backend_argv[2] = target_baud; | |
| 77 backend_argv[3] = 0; | |
| 78 } | |
| 79 | |
| 80 static void | |
| 81 setup_be_rvtat() | |
| 82 { | |
| 83 char **ap; | |
| 84 | |
| 85 backend_prog = rvtat_pathname; | |
| 86 ap = backend_argv; | |
| 87 *ap++ = "fcup-rvtat"; | |
| 88 if (target_ttyport) { | |
| 89 *ap++ = "-p"; | |
| 90 *ap++ = target_ttyport; | |
| 91 } | |
| 92 if (target_baud) { | |
| 93 *ap++ = "-B"; | |
| 94 *ap++ = target_baud; | |
| 95 } | |
| 96 *ap = 0; | |
| 97 } | |
| 98 | |
| 99 static void | |
| 100 setup_be_external() | |
| 101 { | |
| 102 backend_prog = shell_pathname; | |
| 103 backend_argv[0] = "sh"; | |
| 104 backend_argv[1] = "-c"; | |
| 105 backend_argv[2] = external_prog; | |
| 106 backend_argv[3] = 0; | |
| 107 } | |
| 108 | |
| 109 atinterf_init() | |
| 110 { | |
| 111 int cpipe[2], rpipe[2], rc; | |
| 112 | |
| 113 if (!no_target_mode) | |
| 114 return(0); | |
| 115 if (external_prog) | |
| 116 setup_be_external(); | |
| 117 else { | |
| 118 preen_port_baud_config(); | |
| 119 if (rvtat_mode) | |
| 120 setup_be_rvtat(); | |
| 121 else | |
| 122 setup_be_native_at(); | |
| 123 } | |
| 124 if (pipe(cpipe) < 0 || pipe(rpipe) < 0) { | |
| 125 perror("pipe"); | |
| 126 exit(ERROR_UNIX); | |
| 127 } | |
| 128 rc = vfork(); | |
| 129 if (rc < 0) { | |
| 130 perror("vfork for launching back end"); | |
| 131 exit(ERROR_UNIX); | |
| 132 } | |
| 133 if (!rc) { | |
| 134 /* we are in the child - prepare to exec the BE */ | |
| 135 dup2(cpipe[0], 0); | |
| 136 dup2(rpipe[1], 1); | |
| 137 close(cpipe[0]); | |
| 138 close(cpipe[1]); | |
| 139 close(rpipe[0]); | |
| 140 close(rpipe[1]); | |
| 141 /* do the exec */ | |
| 142 execv(backend_prog, backend_argv); | |
| 143 perror(backend_prog); | |
| 144 _exit(1); | |
| 145 } | |
| 146 close(cpipe[0]); | |
| 147 close(rpipe[1]); | |
| 148 cpipeF = fdopen(cpipe[1], "w"); | |
| 149 if (!cpipeF) { | |
| 150 perror("fdopen"); | |
| 151 exit(ERROR_UNIX); | |
| 152 } | |
| 153 rpipeF = fdopen(rpipe[0], "r"); | |
| 154 if (!rpipeF) { | |
| 155 perror("fdopen"); | |
| 156 exit(ERROR_UNIX); | |
| 157 } | |
| 158 return(0); | |
| 159 } | |
| 160 | |
| 161 atinterf_exec_cmd(command, message, callback) | |
| 162 char *command, *message; | |
| 163 void (*callback)(); | |
| 164 { | |
| 165 char *nl; | |
| 166 | |
| 167 if (message) { | |
| 168 fputs("c+m\n", cpipeF); | |
| 169 fprintf(cpipeF, "%s\n", command); | |
| 170 fprintf(cpipeF, "%s\n", message); | |
| 171 } else | |
| 172 fprintf(cpipeF, "%s\n", command); | |
| 173 fflush(cpipeF); | |
| 174 for (;;) { | |
| 175 if (!fgets(at_response, sizeof at_response, rpipeF)) { | |
| 176 fprintf(stderr, | |
| 177 "error reading AT response from back end\n"); | |
| 178 exit(ERROR_RVINTERF); | |
| 179 } | |
| 180 nl = index(at_response, '\n'); | |
| 181 if (!nl) { | |
| 182 fprintf(stderr, | |
| 183 "error: back end response is too long or unterminated\n"); | |
| 184 exit(ERROR_RVINTERF); | |
| 185 } | |
| 186 *nl = '\0'; | |
| 187 switch (at_response[0]) { | |
| 188 case 'E': | |
| 189 fprintf(stderr, "error from back end: %s\n", | |
| 190 at_response + 1); | |
| 191 exit(ERROR_RVINTERF); | |
| 192 case 'F': | |
| 193 return(0); | |
| 194 case 'I': | |
| 195 if (callback) | |
| 196 callback(); | |
| 197 continue; | |
| 198 } | |
| 199 fprintf(stderr, "error: invalid response from back end\n"); | |
| 200 exit(ERROR_RVINTERF); | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 atinterf_exec_cmd_needok(command, message, callback) | |
| 205 char *command, *message; | |
| 206 void (*callback)(); | |
| 207 { | |
| 208 atinterf_exec_cmd(command, message, callback); | |
| 209 if (strcmp(at_response+1, "OK")) { | |
| 210 fprintf(stderr, "AT error: %s\n", at_response+1); | |
| 211 exit(ERROR_TARGET); | |
| 212 } | |
| 213 return(0); | |
| 214 } |
