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 }