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 } |