1 /***************************************************************************
2 * copyright : (C) 2002 by Hendrik Sattler *
3 * mail : post@hendrik-sattler.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 ***************************************************************************/
11
12 #include <atcommand.h>
13 #include <helper.h>
14 #include <gtincl.h>
15 #include <pinfile.h>
16 #include <w32compat.h>
17
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <strings.h>
22 #include <errno.h>
23
24 static char* at_last_command;
25 static char* at_last_parameter;
26 static int at_last_was_syntax_request;
27 static char* PIN;
28 static struct at_hw_access at_tty;
29
at_init(struct at_hw_access * tty,char * pin)30 void at_init (struct at_hw_access* tty, char* pin) {
31 at_last_command = NULL;
32 at_last_parameter = NULL;
33 at_last_was_syntax_request = 0;
34 PIN = str_dup(pin);
35 at_set_tty(tty);
36 }
37
at_set_tty(struct at_hw_access * tty)38 void at_set_tty(struct at_hw_access* tty) {
39 at_tty.read = tty->read;
40 at_tty.write = tty->write;
41 }
42
at_check_line_end(const char * input,const size_t len)43 int at_check_line_end (const char* input, const size_t len) {
44 return ((len >= 2 && input[len-2] == '\r' && input[len-1] == '\n') ||
45 (input[0] == '>' && len > 1));
46 }
47
at_read_line_raw()48 char* at_read_line_raw () {
49 char* value;
50 char* temp;
51 int repeat;
52 int estatus;
53
54 value = NULL;
55 do {
56 repeat = 0;
57 value = at_tty.read(at_check_line_end);
58 if (str_len(value) == 0) {
59 if (value == NULL) {
60 estatus = errno;
61 } else {
62 estatus = ETIMEDOUT;
63 }
64 errexit("%s: %s\n",_("Cannot read from device"),strerror(estatus));
65 } else {
66 if ((temp=strchr(value,'\r')) != NULL ||
67 (temp=strchr(value,'\n')) != NULL) {
68 //we do not want values 13=<CR>='\r' and 10=<LF>='\n' in our strings
69 memset(temp,0,1);
70 //we do not want to return empty strings
71 //we do not accept the at_command_p as answer
72 if (strlen(value) == 0 ||
73 (strncmp(value,AT_PREFIX,sizeof(AT_PREFIX)-1) == 0 &&
74 strncmp(value+sizeof(AT_PREFIX)-1,
75 at_last_command,
76 str_len(at_last_command)) == 0)) {
77 value = mem_realloc(value,0);
78 repeat = 1;
79 }
80 }
81 }
82 } while (repeat);
83 print_message(2,_("Received"),"%s\n",value);
84 return value;
85 }
86
at_read_line()87 char* at_read_line () {
88 char* value;
89 char* temp;
90 char* ctemp;
91 char* ptemp;
92 char* pintype;
93 int srtemp;
94
95 value = at_read_line_raw();
96
97 //PIN handling for all function is done transparently here
98 if (at_line_type(value,NULL,&temp) == AT_RET_ERROR_CME) {
99 if (strstr(temp,"PIN") != NULL ||
100 strstr(temp,"PUK") != NULL) {
101 //save previous command
102 ctemp = str_dup(at_last_command);
103 ptemp = str_dup(at_last_parameter);
104 srtemp = at_last_was_syntax_request;
105
106 /* On first PIN usage, the command line option overrides
107 * pin file usage, subsequent request are always answered
108 * by pin file.
109 */
110 if (str_len(PIN) == 0) {
111 at_syntax_request(AT_GEN_PIN);
112 pintype = at_read_line_raw();
113 if (at_line_type(pintype,AT_GEN_PIN,&temp) == AT_RET_ANSWER)
114 mem_realloc(at_read_line_raw(),0);
115 PIN = pinfile_get(temp);
116 mem_realloc(pintype,0);
117 }
118 if (str_len(PIN) == 0) {
119 //fail if pin file lookup failed and nothing was specified at command line
120 ctemp = mem_realloc(ctemp,0);
121 ptemp = mem_realloc(ptemp,0);
122 if (PIN != NULL) mem_realloc(PIN,0);
123 at_line_type(value,NULL,&temp);
124 errexit("%s\n%s\n",temp,_("Use the --pin parameter or edit the pin file."));
125 } else {
126 //resend command to be sure to be allowed to enter the pin
127 if (srtemp) at_syntax_request(ctemp);
128 else at_command_send(ctemp,ptemp);
129 mem_realloc(at_read_line_raw(),0);
130
131 //enter the pin
132 at_gen_pin(PIN);
133 mem_realloc(value,0);
134 value = at_read_line_raw();
135 if (at_line_type(value,AT_GEN_PIN,&temp) != AT_RET_OK)
136 errexit("%s: %s\n",_("Using PIN failed"),temp);
137 mem_realloc(value,0);
138
139 //prevent a loop, use pin file for multiple usages
140 PIN = mem_realloc(PIN,0);
141
142 //resend previous command
143 if (srtemp) at_syntax_request(ctemp);
144 else at_command_send(ctemp,ptemp);
145 ctemp = mem_realloc(ctemp,0);
146 ptemp = mem_realloc(ptemp,0);
147 value = at_read_line_raw();
148 }
149 }
150 } else if (strncmp(value,"RING",4) == 0 ||
151 strncmp(value,"NO CARRIER",10) == 0) {
152 mem_realloc(value,0);
153 value = at_read_line();
154 }
155 return mem_realloc(value,strlen(value)+1);
156 }
157
at_command_send(const char * command,const char * parmlist)158 void at_command_send (const char* command, const char* parmlist) {
159 if (command == NULL) return;
160
161 print_message(2,_("\nSending command"),"%s%s",AT_PREFIX,command);
162 if (str_len(parmlist) > 0) {
163 print_verbose(2,"%s%s\n",AT_WRITE_DELIM,parmlist);
164 } else {
165 print_verbose(2,"%s","\n");
166 }
167
168 if (at_tty.write(AT_PREFIX,sizeof(AT_PREFIX)-1) == 0 ||
169 at_tty.write(command,strlen(command)) == 0 ||
170 (str_len(parmlist) != 0 &&
171 (at_tty.write(AT_WRITE_DELIM,sizeof(AT_WRITE_DELIM)-1) == 0 ||
172 at_tty.write(parmlist,strlen(parmlist)) == 0)) ||
173 at_tty.write("\r",1) == 0) {
174 errexit("%s: %s\n",_("Cannot send at command"),strerror(errno));
175 } else {
176 at_last_command = mem_realloc(at_last_command,0);
177 at_last_command = str_dup(command);
178 at_last_parameter = mem_realloc(at_last_parameter,0);
179 at_last_parameter = str_dup(parmlist);
180 at_last_was_syntax_request = 0;
181 }
182 }
183
at_syntax_request(const char * command)184 void at_syntax_request (const char* command) {
185 if (command == NULL) return;
186
187 print_message(2,_("\nSending command"),"%s%s%s\n",
188 AT_PREFIX, command, AT_READ_SUFFIX);
189 if (at_tty.write(AT_PREFIX,sizeof(AT_PREFIX)-1) == 0 ||
190 at_tty.write(command,strlen(command)) == 0 ||
191 at_tty.write(AT_READ_SUFFIX,strlen(AT_READ_SUFFIX)) == 0 ||
192 at_tty.write("\r",1) == 0) {
193 errexit("%s: %s\n",_("Cannot send at command"),strerror(errno));
194 } else {
195 at_last_command = mem_realloc(at_last_command,0);
196 at_last_command = str_dup(command);
197 at_last_parameter = mem_realloc(at_last_parameter,0);
198 at_last_was_syntax_request = 1;
199 }
200 }
201
at_data_send(const char * data,size_t size)202 void at_data_send (const char* data, size_t size) {
203 /* 0x1a is Ctrl-Z (represents end of data stream) */
204 if (at_tty.write(data,size))
205 at_tty.write("\x1a",1);
206 }
207
208
at_get_value(const char * command)209 char* at_get_value (const char* command) {
210 char* temp;
211 char* temp2;
212
213 temp = at_read_line();
214 if (temp == NULL) return NULL;
215 switch (at_line_type(temp,command,&temp2)) {
216 case AT_RET_ANSWER:
217 memmove(temp,temp2,strlen(temp2)+1);
218 //no break
219 case AT_RET_OTHER:
220 temp2 = at_read_line();
221 if (at_line_type(temp2,NULL,NULL) == AT_RET_OK) {
222 mem_realloc(temp2,0);
223 return temp;
224 }
225 mem_realloc(temp2,0);
226 //no break
227 default:
228 mem_realloc(temp,0);
229 return NULL;
230 }
231 }
232
233
at_parse_stringlist(char * stringlist)234 char** at_parse_stringlist (char* stringlist) {
235 char* temp = stringlist;
236
237 if (*temp == '(') ++temp;
238 if (*temp == '"') ++temp;
239 memmove(stringlist,temp,strlen(temp)+1);
240 temp = stringlist+strlen(stringlist)-1;
241 if (*temp == ')') --temp;
242 if (*temp != '"') ++temp;
243 memset(temp,0,1);
244 return str_split(stringlist,"\",\"",0);
245 }
246
at_line_type(const char * response,const char * command,char ** content)247 enum return_code at_line_type (const char* response,
248 const char* command,
249 char** content)
250 {
251 char* temp = NULL;
252 enum return_code retval = AT_RET_OTHER;
253
254 if (content != NULL) *content = (char*)response;
255 if (response == NULL) return retval;
256 if (strcasecmp(response,AT_OK) == 0) {
257 temp = "OK";
258 retval = AT_RET_OK;
259 } else if (strcasecmp(response,AT_ERROR) == 0) {
260 temp = "ERROR";
261 retval = AT_RET_ERROR;
262 } else if (strncasecmp(response,AT_ERROR_CME,
263 str_len(AT_ERROR_CME)) == 0) {
264 temp = "CME ERROR";
265 if (content != NULL) *content = (char*)response + str_len(AT_ERROR_CME);
266 retval = AT_RET_ERROR_CME;
267 } else if (strncasecmp(response,AT_ERROR_CMS,
268 str_len(AT_ERROR_CMS)) == 0) {
269 temp = "CMS ERROR";
270 if (content != NULL) *content = (char*)response + str_len(AT_ERROR_CMS);
271 retval = AT_RET_ERROR_CMS;
272 } else if (command != NULL &&
273 strncasecmp(response,command,strlen(command)) == 0 &&
274 strncasecmp(response+str_len(command),
275 AT_REPLY_SEPERATOR,
276 str_len(AT_REPLY_SEPERATOR)) == 0) {
277 temp = _("command return value");
278 if (content != NULL) {
279 *content = (char*)response + str_len(command) + str_len(AT_REPLY_SEPERATOR);
280 }
281 retval = AT_RET_ANSWER;
282 } else {
283 temp = _("nothing");
284 retval = AT_RET_OTHER;
285 }
286 print_verbose(3,_("Value matched %s.\n"),temp);
287 return retval;
288 }
289