1   /* (c) 2002-2005 by Marcin Wiacek and Michal Cihar */
2 /* Phones ID (c) partially by Walek */
3 
4 #include <stdarg.h>
5 #define _GNU_SOURCE /* For strcasestr */
6 #include <string.h>
7 #include <errno.h>
8 #include <limits.h>
9 #include <assert.h>
10 
11 #include <gammu-call.h>
12 #include <gammu-settings.h>
13 #include <gammu-unicode.h>
14 #include <gammu-config.h>
15 #include <gammu-misc.h>
16 
17 #include "debug.h"
18 #include "gsmcomon.h"
19 #include "gsmphones.h"
20 #include "gsmstate.h"
21 #include "misc/coding/coding.h"
22 #include "misc/misc.h"
23 #include "device/devfunc.h"
24 
25 #include "../libgammu/misc/string.h"
26 
27 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
28 #include <sys/types.h>
29 #include <pwd.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 
33 #endif
34 
35 #if defined(WIN32) || defined(DJGPP)
36 /* Needed for SHGFP_TYPE_CURRENT */
37 #ifndef _WIN32_IE
38 #define _WIN32_IE 0x0501
39 #endif
40 #include <shlobj.h>
41 
42 #define FALLBACK_GAMMURC "gammurc"
43 #define GAMMURC_NAME "\\gammurc"
44 #else
45 #define FALLBACK_GAMMURC "/etc/gammurc"
46 #define GAMMURC_NAME "/.gammurc"
47 #endif
48 #define XDG_GAMMURC_NAME "/gammu/config"
49 
50 /* Win32 compatibility */
51 #ifndef PATH_MAX
52 #define PATH_MAX (MAX_PATH)
53 #endif
54 
55 /* Default settings */
56 #if defined(WIN32) || defined(DJGPP)
57 #  define DEFAULT_DEVICE "com2:"
58 #else
59 #  define DEFAULT_DEVICE "/dev/ttyUSB0"
60 #endif
61 #define DEFAULT_MODEL ""
62 #define DEFAULT_CONNECTION "at"
63 #define DEFAULT_SYNCHRONIZE_TIME FALSE
64 #define DEFAULT_DEBUG_FILE ""
65 #define DEFAULT_DEBUG_LEVEL ""
66 #define DEFAULT_LOCK_DEVICE FALSE
67 #define DEFAULT_START_INFO FALSE
68 
69 /**
70  * Returns current debuging descriptor. It honors use_global
71  * flag.
72  */
GSM_GetDI(GSM_StateMachine * s)73 GSM_Debug_Info *GSM_GetDI(GSM_StateMachine *s)
74 {
75 	GSM_Debug_Info *curdi;
76 
77 	curdi = &GSM_global_debug;
78 	if (s != NULL && s->di.use_global == FALSE) {
79 		curdi = &(s->di);
80 	}
81 	return curdi;
82 }
83 
GSM_RegisterConnection(GSM_StateMachine * s,unsigned int connection,GSM_Device_Functions * device,GSM_Protocol_Functions * protocol)84 static void GSM_RegisterConnection(GSM_StateMachine *s, unsigned int connection,
85 		GSM_Device_Functions *device, GSM_Protocol_Functions *protocol)
86 {
87 	if ((unsigned int)s->ConnectionType == connection) {
88 		s->Device.Functions	= device;
89 		s->Protocol.Functions	= protocol;
90 	}
91 }
92 
93 /**
94  * Information about connection names and parameters.
95  */
96 typedef struct {
97 	/**
98 	 * Name of the connection used in config file.
99 	 */
100 	const char *Name;
101 	/**
102 	 * Connection type.
103 	 */
104 	const GSM_ConnectionType Connection;
105 	/**
106 	 * Whether to disable DTR/RTS handling on this connection.
107 	 */
108 	gboolean SkipDtrRts;
109 } GSM_ConnectionInfo;
110 
111 /**
112  * Mapping of connection names to internal identifications.
113  */
114 static const GSM_ConnectionInfo GSM_Connections[] = {
115 	{"at", GCT_AT, FALSE},
116 
117 	/* cables */
118 	{"mbus", GCT_MBUS2, FALSE},
119 
120 	{"fbus", GCT_FBUS2, FALSE},
121 
122 	{"fbususb", GCT_FBUS2USB, FALSE},
123 
124 	{"fbuspl2303", GCT_FBUS2PL2303, FALSE},
125 
126 	{"dlr3", GCT_FBUS2DLR3, FALSE},
127 	{"fbusdlr3", GCT_FBUS2DLR3, FALSE},
128 
129 	{"dku5", GCT_DKU5FBUS2, FALSE},
130 	{"fbusdku5", GCT_DKU5FBUS2, FALSE},
131 	{"dku5fbus", GCT_DKU5FBUS2, FALSE},
132 
133 	{"ark3116fbus", GCT_DKU5FBUS2, TRUE},
134 #ifdef WIN32
135 	{"dku2", GCT_DKU2PHONET, FALSE},
136 	{"dku2phonet", GCT_DKU2PHONET, FALSE},
137 #else
138 	{"dku2", GCT_FBUS2USB, FALSE},
139 	{"dku2phonet", GCT_FBUS2USB, FALSE},
140 #endif
141 	{"dku2at", GCT_DKU2AT, FALSE},
142 
143         /* for serial ports assigned by bt stack */
144 	{"fbusblue", GCT_FBUS2BLUE, FALSE},
145 	{"phonetblue", GCT_PHONETBLUE, FALSE},
146 
147 	/* bt */
148 	{"blueobex", GCT_BLUEOBEX, FALSE},
149 	{"bluephonet", GCT_BLUEPHONET, FALSE},
150 	{"blueat", GCT_BLUEAT, FALSE},
151 	{"bluerfobex", GCT_BLUEOBEX, FALSE},
152 	{"bluefbus", GCT_BLUEFBUS2, FALSE},
153 	{"bluerffbus", GCT_BLUEFBUS2, FALSE},
154 	{"bluerfphonet", GCT_BLUEPHONET, FALSE},
155 	{"bluerfat", GCT_BLUEAT, FALSE},
156 	{"bluerfgnapbus", GCT_BLUEGNAPBUS, FALSE},
157 	{"blues60", GCT_BLUES60, FALSE},
158 	{"bluerfs60", GCT_BLUES60, FALSE},
159 
160 	/* proxy */
161 	{"proxyobex", GCT_PROXYOBEX, FALSE},
162 	{"proxyphonet", GCT_PROXYPHONET, FALSE},
163 	{"proxyat", GCT_PROXYAT, FALSE},
164 	{"proxygnapbus", GCT_PROXYGNAPBUS, FALSE},
165 	{"proxyfbus", GCT_PROXYFBUS2, FALSE},
166 	{"proxys60", GCT_PROXYS60, FALSE},
167 
168 	/* old "serial" irda */
169 	{"infrared", GCT_FBUS2IRDA, FALSE},
170 	{"fbusirda", GCT_FBUS2IRDA, FALSE},
171 
172 	/* socket irda */
173 	{"irda", GCT_IRDAPHONET, FALSE},
174 	{"irdaphonet", GCT_IRDAPHONET, FALSE},
175 	{"irdaat", GCT_IRDAAT, FALSE},
176 	{"irdaobex", GCT_IRDAOBEX, FALSE},
177 	{"irdagnapbus", GCT_IRDAGNAPBUS, FALSE},
178 
179 	/* testing purposes */
180 	{"none", GCT_NONE, FALSE},
181 };
182 
183 GSM_Device_Functions NoneDevice = {
184 	NONEFUNCTION,
185 	NONEFUNCTION,
186 	NONEFUNCTION,
187 	NONEFUNCTION,
188 	NONEFUNCTION,
189 	NONEFUNCTION,
190 	NONEFUNCTION
191 };
192 
193 GSM_Protocol_Functions NoProtocol = {
194 	NONEFUNCTION,
195 	NONEFUNCTION,
196 	NONEFUNCTION,
197 	NONEFUNCTION
198 };
199 
GSM_RegisterAllConnections(GSM_StateMachine * s,const char * connection)200 static GSM_Error GSM_RegisterAllConnections(GSM_StateMachine *s, const char *connection)
201 {
202 	size_t i;
203 	char *buff, *nodtr_pos, *nopower_pos;
204 
205 	/* Copy connection name, so that we can play with it */
206 	buff = strdup(connection);
207 	if (buff == NULL) {
208 		return ERR_MOREMEMORY;
209 	}
210 
211 	/* We check here is used connection string type is correct for ANY
212 	 * OS. If not, we return with error, that string is incorrect at all
213 	 */
214 	s->ConnectionType = 0;
215 	s->SkipDtrRts = FALSE;
216 	s->NoPowerCable = FALSE;
217 
218 	/* Are we asked for connection using stupid cable? */
219 	nodtr_pos = strcasestr(buff, "-nodtr");
220 	if (nodtr_pos != NULL) {
221 		*nodtr_pos = 0;
222 	}
223 
224 	/* Are we asked for connection using cable which does not
225 	 * use DTR/RTS as power supply? */
226 	nopower_pos = strcasestr(buff, "-nopower");
227 	if (nopower_pos != NULL) {
228 		*nopower_pos = 0;
229 		s->NoPowerCable = TRUE;
230 	}
231 
232 	/* Compare known connections to what we got */
233 	for (i = 0; i < sizeof(GSM_Connections) / sizeof(GSM_Connections[0]); i++) {
234 		/* Check connection name */
235 		if (strcasecmp(GSM_Connections[i].Name, buff) == 0) {
236 			s->ConnectionType = GSM_Connections[i].Connection;
237 			s->SkipDtrRts = GSM_Connections[i].SkipDtrRts;
238 			break;
239 		}
240 	}
241 
242 	/* If we were forced, set this flag */
243 	if (nodtr_pos != NULL) {
244 		s->SkipDtrRts = TRUE;
245 	}
246 
247 	/* Special case - at can contains speed */
248 	if (s->ConnectionType == 0 && strncasecmp("at", buff, 2) == 0) {
249 		s->Speed = FindSerialSpeed(buff + 2);
250 		if (s->Speed != 0) {
251 			s->ConnectionType = GCT_AT;
252 		}
253 	}
254 
255 	/* Free allocated memory */
256 	free(buff);
257 	buff = NULL;
258 
259 	if (s->ConnectionType == 0) {
260 		return ERR_UNKNOWNCONNECTIONTYPESTRING;
261 	}
262 
263 	/* We check now if user gave connection type compiled & available
264 	 * for used OS (if not, we return, that source not available)
265 	 */
266 	s->Device.Functions	= NULL;
267 	s->Protocol.Functions	= NULL;
268 	GSM_RegisterConnection(s, GCT_NONE, 	  &NoneDevice,    &NoProtocol);
269 #ifdef GSM_ENABLE_MBUS2
270 	GSM_RegisterConnection(s, GCT_MBUS2, 	  &SerialDevice,  &MBUS2Protocol);
271 #endif
272 #ifdef GSM_ENABLE_FBUS2
273 	GSM_RegisterConnection(s, GCT_FBUS2,	  &SerialDevice,  &FBUS2Protocol);
274 #endif
275 #ifdef GSM_ENABLE_FBUS2DLR3
276 	GSM_RegisterConnection(s, GCT_FBUS2DLR3,  &SerialDevice,  &FBUS2Protocol);
277 #endif
278 #ifdef GSM_ENABLE_DKU5FBUS2
279 	GSM_RegisterConnection(s, GCT_DKU5FBUS2,  &SerialDevice,  &FBUS2Protocol);
280 #endif
281 #ifdef GSM_ENABLE_FBUS2PL2303
282 	GSM_RegisterConnection(s, GCT_FBUS2PL2303,&SerialDevice,  &FBUS2Protocol);
283 #endif
284 #ifdef GSM_ENABLE_FBUS2BLUE
285 	GSM_RegisterConnection(s, GCT_FBUS2BLUE,  &SerialDevice,  &FBUS2Protocol);
286 #endif
287 #ifdef GSM_ENABLE_FBUS2IRDA
288 	GSM_RegisterConnection(s, GCT_FBUS2IRDA,  &SerialDevice,  &FBUS2Protocol);
289 #endif
290 #if defined(GSM_ENABLE_DKU2PHONET) && defined(GSM_ENABLE_USBDEVICE)
291 	GSM_RegisterConnection(s, GCT_FBUS2USB,	  &FBUSUSBDevice,  &PHONETProtocol);
292 #endif
293 #ifdef GSM_ENABLE_DKU2PHONET
294 	GSM_RegisterConnection(s, GCT_DKU2PHONET, &SerialDevice,  &PHONETProtocol);
295 #endif
296 #ifdef GSM_ENABLE_DKU2AT
297 	GSM_RegisterConnection(s, GCT_DKU2AT,     &SerialDevice,  &ATProtocol);
298 #endif
299 #ifdef GSM_ENABLE_AT
300 	GSM_RegisterConnection(s, GCT_AT, 	  &SerialDevice,  &ATProtocol);
301 #endif
302 #ifdef GSM_ENABLE_PHONETBLUE
303 	GSM_RegisterConnection(s, GCT_PHONETBLUE, &SerialDevice,  &PHONETProtocol);
304 #endif
305 #ifdef GSM_ENABLE_IRDAGNAPBUS
306 	GSM_RegisterConnection(s, GCT_IRDAGNAPBUS,&IrdaDevice,    &GNAPBUSProtocol);
307 #endif
308 #ifdef GSM_ENABLE_IRDAPHONET
309 	GSM_RegisterConnection(s, GCT_IRDAPHONET, &IrdaDevice, 	  &PHONETProtocol);
310 #endif
311 #ifdef GSM_ENABLE_IRDAAT
312 	GSM_RegisterConnection(s, GCT_IRDAAT, 	  &IrdaDevice,    &ATProtocol);
313 #endif
314 #ifdef GSM_ENABLE_IRDAOBEX
315 	GSM_RegisterConnection(s, GCT_IRDAOBEX,   &IrdaDevice,    &OBEXProtocol);
316 #endif
317 #ifdef GSM_ENABLE_BLUEGNAPBUS
318 	GSM_RegisterConnection(s, GCT_BLUES60,	  &BlueToothDevice,&S60Protocol);
319 #endif
320 #ifdef GSM_ENABLE_BLUEGNAPBUS
321 	GSM_RegisterConnection(s, GCT_BLUEGNAPBUS,&BlueToothDevice,&GNAPBUSProtocol);
322 #endif
323 #ifdef GSM_ENABLE_BLUEFBUS2
324 	GSM_RegisterConnection(s, GCT_BLUEFBUS2,  &BlueToothDevice,&FBUS2Protocol);
325 #endif
326 #ifdef GSM_ENABLE_BLUEPHONET
327 	GSM_RegisterConnection(s, GCT_BLUEPHONET, &BlueToothDevice,&PHONETProtocol);
328 #endif
329 #ifdef GSM_ENABLE_BLUEAT
330 	GSM_RegisterConnection(s, GCT_BLUEAT, 	  &BlueToothDevice,&ATProtocol);
331 #endif
332 #ifdef GSM_ENABLE_BLUEOBEX
333 	GSM_RegisterConnection(s, GCT_BLUEOBEX,   &BlueToothDevice,&OBEXProtocol);
334 #endif
335 #ifdef GSM_ENABLE_PROXY
336 #ifdef GSM_ENABLE_S60
337 	GSM_RegisterConnection(s, GCT_PROXYS60,	  &ProxyDevice,&S60Protocol);
338 #endif
339 #ifdef GSM_ENABLE_BLUEGNAPBUS
340 	GSM_RegisterConnection(s, GCT_PROXYGNAPBUS,&ProxyDevice,&GNAPBUSProtocol);
341 #endif
342 #ifdef GSM_ENABLE_FBUS2
343 	GSM_RegisterConnection(s, GCT_PROXYFBUS2,  &ProxyDevice,&FBUS2Protocol);
344 #endif
345 #ifdef GSM_ENABLE_DKU2PHONET
346 	GSM_RegisterConnection(s, GCT_PROXYPHONET, &ProxyDevice,&PHONETProtocol);
347 #endif
348 #ifdef GSM_ENABLE_ATGEN
349 	GSM_RegisterConnection(s, GCT_PROXYAT, 	  &ProxyDevice,&ATProtocol);
350 #endif
351 #ifdef GSM_ENABLE_OBEXGEN
352 	GSM_RegisterConnection(s, GCT_PROXYOBEX,   &ProxyDevice,&OBEXProtocol);
353 #endif
354 #endif
355 	if (s->Device.Functions == NULL || s->Protocol.Functions == NULL) {
356 		smprintf(s, "Connection %s is know but was disabled on compile time\n", connection);
357 		return ERR_DISABLED;
358 	}
359 
360 	return ERR_NONE;
361 }
362 
GSM_RegisterModule(GSM_StateMachine * s,GSM_Phone_Functions * phone)363 static void GSM_RegisterModule(GSM_StateMachine *s,GSM_Phone_Functions *phone)
364 {
365 	/* Auto model */
366 	if (s->CurrentConfig->Model[0] == 0) {
367 		if (strstr(phone->models,GetModelData(s, NULL, s->Phone.Data.Model, NULL)->model) != NULL) {
368 			smprintf(s,"[Module           - \"%s\"]\n",phone->models);
369 			s->Phone.Functions = phone;
370 		}
371 	} else {
372 		if (strstr(phone->models,s->CurrentConfig->Model) != NULL) {
373 			smprintf(s,"[Module           - \"%s\"]\n",phone->models);
374 			s->Phone.Functions = phone;
375 		}
376 	}
377 }
378 
379 /**
380  * Tries to register all modules to find one matching current configuration.
381  *
382  * \param s State machine pointer.
383  *
384  * \return Error code, ERR_NONE on success.
385  */
GSM_RegisterAllPhoneModules(GSM_StateMachine * s)386 GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s)
387 {
388 	GSM_PhoneModel *model;
389 
390 	/* Auto model */
391 	if (s->CurrentConfig->Model[0] == 0) {
392 		model = GetModelData(s, NULL, s->Phone.Data.Model, NULL);
393 #ifdef GSM_ENABLE_ATGEN
394 		/* With ATgen and auto model we can work with unknown models too */
395 		if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) {
396 #ifdef GSM_ENABLE_ALCATEL
397 			/* If phone provides Alcatel specific functions, enable them */
398 			if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_ALCATEL)) {
399 				smprintf(s,"[Module           - \"%s\"]\n",ALCATELPhone.models);
400 				s->Phone.Functions = &ALCATELPhone;
401 				return ERR_NONE;
402 			}
403 #endif
404 #ifdef GSM_ENABLE_ATOBEX
405 			/* If phone provides Sony-Ericsson specific functions, enable them */
406 			if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_OBEX)) {
407 				smprintf(s,"[Module           - \"%s\"]\n",ATOBEXPhone.models);
408 				s->Phone.Functions = &ATOBEXPhone;
409 				return ERR_NONE;
410 			}
411 #endif
412 			smprintf(s,"[Module           - \"%s\"]\n",ATGENPhone.models);
413 			s->Phone.Functions = &ATGENPhone;
414 			return ERR_NONE;
415 		}
416 #endif
417 		/* With OBEXgen and auto model we can work with unknown models too */
418 #ifdef GSM_ENABLE_OBEXGEN
419 		if (s->ConnectionType==GCT_BLUEOBEX || s->ConnectionType==GCT_PROXYOBEX || s->ConnectionType==GCT_IRDAOBEX) {
420 			smprintf(s,"[Module           - \"%s\"]\n",OBEXGENPhone.models);
421 			s->Phone.Functions = &OBEXGENPhone;
422 			return ERR_NONE;
423 		}
424 #endif
425 
426 #ifdef GSM_ENABLE_BACKUP
427 		if (s->ConnectionType == GCT_NONE) {
428 			smprintf(s,"[Module           - \"%s\"]\n",DUMMYPhone.models);
429 			s->Phone.Functions = &DUMMYPhone;
430 			return ERR_NONE;
431 		}
432 #endif
433 
434 		/* With GNAPgen and auto model we can work with unknown models too */
435 #ifdef GSM_ENABLE_GNAPGEN
436 		if (s->ConnectionType == GCT_BLUEGNAPBUS || s->ConnectionType == GCT_PROXYGNAPBUS || s->ConnectionType == GCT_IRDAGNAPBUS) {
437 			smprintf(s,"[Module           - \"%s\"]\n",GNAPGENPhone.models);
438 			s->Phone.Functions = &GNAPGENPhone;
439 			return ERR_NONE;
440 		}
441 #endif
442 #ifdef GSM_ENABLE_S60
443 		if (s->ConnectionType == GCT_BLUES60 || s->ConnectionType == GCT_PROXYS60) {
444 			smprintf(s,"[Module           - \"%s\"]\n",S60Phone.models);
445 			s->Phone.Functions = &S60Phone;
446 			return ERR_NONE;
447 		}
448 #endif
449 
450 #ifdef GSM_ENABLE_NOKIA6510
451 		if ( s->ConnectionType ==  GCT_MBUS2 ||
452 				s->ConnectionType ==  GCT_FBUS2 ||
453 				s->ConnectionType ==  GCT_FBUS2USB ||
454 				s->ConnectionType ==  GCT_FBUS2DLR3 ||
455 				s->ConnectionType ==  GCT_FBUS2PL2303 ||
456 				s->ConnectionType ==  GCT_FBUS2BLUE ||
457 				s->ConnectionType ==  GCT_FBUS2IRDA ||
458 				s->ConnectionType ==  GCT_DKU5FBUS2 ||
459 				s->ConnectionType ==  GCT_DKU2PHONET ||
460 				s->ConnectionType ==  GCT_PHONETBLUE ||
461 				s->ConnectionType ==  GCT_IRDAPHONET ||
462 				s->ConnectionType ==  GCT_BLUEFBUS2 ||
463 				s->ConnectionType ==  GCT_PROXYFBUS2 ||
464 				s->ConnectionType ==  GCT_PROXYPHONET ||
465 				s->ConnectionType ==  GCT_BLUEPHONET) {
466 			/* Try to detect phone type */
467 			if (strcmp(model->model, "unknown") == 0 && model->features[0] == 0) {
468 				smprintf(s, "WARNING: phone not known, please report it to authors (see <https://wammu.eu/support/bugs/>). Thank you.\n");
469 				if (strncmp(s->Phone.Data.Model, "RM-", 3) == 0) {
470 					/* 167 is really a wild guess */
471 					if (atoi(s->Phone.Data.Model + 3) > 167) {
472 						smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RM series)!\n");
473 						GSM_AddPhoneFeature(model, F_SERIES40_30);
474 						GSM_AddPhoneFeature(model, F_FILES2);
475 						GSM_AddPhoneFeature(model, F_TODO66);
476 						GSM_AddPhoneFeature(model, F_RADIO);
477 						GSM_AddPhoneFeature(model, F_NOTES);
478 						GSM_AddPhoneFeature(model, F_SMS_FILES);
479 						GSM_AddPhoneFeature(model, F_6230iCALLER);
480 					}
481 				}
482 				if (strncmp(s->Phone.Data.Model, "RH-", 3) == 0) {
483 					/* 63 is really a wild guess */
484 					if (atoi(s->Phone.Data.Model + 3) > 63) {
485 						smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RH series)!\n");
486 						GSM_AddPhoneFeature(model, F_SERIES40_30);
487 						GSM_AddPhoneFeature(model, F_FILES2);
488 						GSM_AddPhoneFeature(model, F_TODO66);
489 						GSM_AddPhoneFeature(model, F_RADIO);
490 						GSM_AddPhoneFeature(model, F_NOTES);
491 						GSM_AddPhoneFeature(model, F_SMS_FILES);
492 					}
493 				}
494 			}
495 
496 			/* If phone is S40, use 6510 */
497 			if (GSM_IsPhoneFeatureAvailable(model, F_SERIES40_30)) {
498 				smprintf(s,"[Module           - \"%s\"]\n", N6510Phone.models);
499 				s->Phone.Functions = &N6510Phone;
500 				return ERR_NONE;
501 			}
502 		}
503 #endif
504 		if (model->model[0] == 0) return ERR_UNKNOWNMODELSTRING;
505 	}
506 	s->Phone.Functions = NULL;
507 #ifdef GSM_ENABLE_ATGEN
508 	/* AT module can have the same models ID to "normal" Nokia modules */
509 	if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) {
510 		GSM_RegisterModule(s,&ATGENPhone);
511 		if (s->Phone.Functions != NULL) return ERR_NONE;
512 	}
513 #endif
514 #ifdef GSM_ENABLE_BACKUP
515 	GSM_RegisterModule(s, &DUMMYPhone);
516 #endif
517 #ifdef GSM_ENABLE_OBEXGEN
518 	GSM_RegisterModule(s,&OBEXGENPhone);
519 #endif
520 #ifdef GSM_ENABLE_GNAPGEN
521 	GSM_RegisterModule(s,&GNAPGENPhone);
522 #endif
523 #ifdef GSM_ENABLE_S60
524 	GSM_RegisterModule(s,&S60Phone);
525 #endif
526 #ifdef GSM_ENABLE_NOKIA3320
527 	GSM_RegisterModule(s,&N3320Phone);
528 #endif
529 #ifdef GSM_ENABLE_NOKIA3650
530 	GSM_RegisterModule(s,&N3650Phone);
531 #endif
532 #ifdef GSM_ENABLE_NOKIA650
533 	GSM_RegisterModule(s,&N650Phone);
534 #endif
535 #ifdef GSM_ENABLE_NOKIA6110
536 	GSM_RegisterModule(s,&N6110Phone);
537 #endif
538 #ifdef GSM_ENABLE_NOKIA6510
539 	GSM_RegisterModule(s,&N6510Phone);
540 #endif
541 #ifdef GSM_ENABLE_NOKIA7110
542 	GSM_RegisterModule(s,&N7110Phone);
543 #endif
544 #ifdef GSM_ENABLE_NOKIA9210
545 	GSM_RegisterModule(s,&N9210Phone);
546 #endif
547 #ifdef GSM_ENABLE_ALCATEL
548 	GSM_RegisterModule(s,&ALCATELPhone);
549 #endif
550 #ifdef GSM_ENABLE_ATOBEX
551 	GSM_RegisterModule(s,&ATOBEXPhone);
552 #endif
553 	if (s->Phone.Functions == NULL) {
554 		return ERR_UNKNOWNMODELSTRING;
555 	}
556 	return ERR_NONE;
557 }
558 
559 
560 /**
561  * Opens connection to device and initiates protocol layer.
562  */
GSM_OpenConnection(GSM_StateMachine * s)563 GSM_Error GSM_OpenConnection(GSM_StateMachine *s)
564 {
565 	GSM_Error error;
566 
567 	if (s->CurrentConfig->LockDevice) {
568 		error = lock_device(s, s->CurrentConfig->Device, &(s->LockFile));
569 		if (error != ERR_NONE) return error;
570 	}
571 
572 	/* Irda devices can set now model to some specific and
573 	 * we don't have to make auto detection later */
574 	error=s->Device.Functions->OpenDevice(s);
575 	if (error!=ERR_NONE) {
576 		if (s->LockFile != NULL)
577 			unlock_device(s, &(s->LockFile));
578 		return error;
579 	}
580 
581 	s->opened = TRUE;
582 
583 	error=s->Protocol.Functions->Initialise(s);
584 	if (error!=ERR_NONE) return error;
585 
586 	return ERR_NONE;
587 }
588 
589 /**
590  * Internal function which just closes connection and cleans up structures.
591  */
GSM_CloseConnection(GSM_StateMachine * s)592 GSM_Error GSM_CloseConnection(GSM_StateMachine *s)
593 {
594 	GSM_Error error;
595 
596 	smprintf(s, "[Closing]\n");
597 
598 	/* Terminate protocol */
599 	error = s->Protocol.Functions->Terminate(s);
600 	if (error != ERR_NONE) return error;
601 
602 	/* Close the device */
603 	error = s->Device.Functions->CloseDevice(s);
604 	if (error != ERR_NONE) return error;
605 
606 	/* Release lock if there was any */
607 	if (s->LockFile != NULL) {
608 		unlock_device(s, &(s->LockFile));
609 	}
610 
611 	/* Null all structures in case we will be asked for new initialisation */
612 	s->Phone.Data.ModelInfo		  = NULL;
613 	s->Phone.Data.Manufacturer[0]	  = 0;
614 	s->Phone.Data.Model[0]		  = 0;
615 	s->Phone.Data.Version[0]	  = 0;
616 	s->Phone.Data.VerDate[0]	  = 0;
617 	s->Phone.Data.VerNum		  = 0;
618 
619 	return ERR_NONE;
620 }
621 
622 
623 /**
624  * Tries to read model using configured phone connection.
625  */
GSM_TryGetModel(GSM_StateMachine * s)626 GSM_Error GSM_TryGetModel(GSM_StateMachine *s)
627 {
628 	GSM_Error error;
629 
630 	error = GSM_OpenConnection(s);
631 	if (error != ERR_NONE) return error;
632 
633 	/* If still auto model, try to get model by asking phone for it */
634 	if (s->Phone.Data.Model[0]==0) {
635 		smprintf(s,"[Module           - \"auto\"]\n");
636 		switch (s->ConnectionType) {
637 #ifdef GSM_ENABLE_BACKUP
638 			case GCT_NONE:
639 				s->Phone.Functions = &DUMMYPhone;
640 				break;
641 #endif
642 #ifdef GSM_ENABLE_ATGEN
643 			case GCT_AT:
644 			case GCT_BLUEAT:
645 			case GCT_PROXYAT:
646 			case GCT_IRDAAT:
647 			case GCT_DKU2AT:
648 				s->Phone.Functions = &ATGENPhone;
649 				break;
650 #endif
651 #ifdef GSM_ENABLE_OBEXGEN
652 			case GCT_IRDAOBEX:
653 			case GCT_PROXYOBEX:
654 			case GCT_BLUEOBEX:
655 				s->Phone.Functions = &OBEXGENPhone;
656 				break;
657 #endif
658 #ifdef GSM_ENABLE_GNAPGEN
659 			case GCT_BLUEGNAPBUS:
660 			case GCT_PROXYGNAPBUS:
661 			case GCT_IRDAGNAPBUS:
662 				s->Phone.Functions = &GNAPGENPhone;
663 				break;
664 #endif
665 #ifdef GSM_ENABLE_S60
666 			case GCT_BLUES60:
667 			case GCT_PROXYS60:
668 				s->Phone.Functions = &S60Phone;
669 				break;
670 #endif
671 #if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
672 			case GCT_MBUS2:
673 			case GCT_FBUS2:
674 			case GCT_FBUS2USB:
675 			case GCT_FBUS2DLR3:
676 			case GCT_FBUS2PL2303:
677 			case GCT_FBUS2BLUE:
678 			case GCT_FBUS2IRDA:
679 			case GCT_DKU5FBUS2:
680 			case GCT_DKU2PHONET:
681 			case GCT_PHONETBLUE:
682 			case GCT_IRDAPHONET:
683 			case GCT_BLUEFBUS2:
684 			case GCT_PROXYFBUS2:
685 			case GCT_BLUEPHONET:
686 			case GCT_PROXYPHONET:
687 				s->Phone.Functions = &NAUTOPhone;
688 				break;
689 #endif
690 			default:
691 				s->Phone.Functions = NULL;
692 		}
693 		/* Did we find matching phone driver? */
694 		if (s->Phone.Functions == NULL) {
695 			smprintf(s, "ERROR: Could not find proper module for autodetection!\n");
696 			return ERR_UNKNOWN;
697 		}
698 
699 		/* Initialize the phone driver */
700 		error = s->Phone.Functions->Initialise(s);
701 		if (error != ERR_NONE) return error;
702 
703 		/* Get model name from phone */
704 		error = s->Phone.Functions->GetModel(s);
705 		if (error != ERR_NONE) return error;
706 
707 		/* And terminate it again */
708 		error = s->Phone.Functions->Terminate(s);
709 		if (error != ERR_NONE) return error;
710 	}
711 	return ERR_NONE;
712 }
713 
GSM_InitConnection_Log(GSM_StateMachine * s,int ReplyNum,GSM_Log_Function log_function,void * user_data)714 GSM_Error GSM_InitConnection_Log(GSM_StateMachine *s, int ReplyNum, GSM_Log_Function log_function, void *user_data)
715 {
716 	GSM_Error	error;
717 	GSM_DateTime	current_time;
718 	int		i;
719 
720 	for (i=0;i<s->ConfigNum;i++) {
721 		s->CurrentConfig		  = &s->Config[i];
722 
723 		/* Skip non configured sections */
724 		if (s->CurrentConfig->Connection == NULL) {
725 			smprintf_level(s, D_ERROR, "[Empty section    - %d]\n", i);
726 			continue;
727 		}
728 
729 		s->Speed			  = 0;
730 		s->ReplyNum			  = ReplyNum;
731 		s->Phone.Data.ModelInfo		  = GetModelData(s, "unknown", NULL, NULL);
732 		s->Phone.Data.Manufacturer[0]	  = 0;
733 		s->Phone.Data.Model[0]		  = 0;
734 		s->Phone.Data.Version[0]	  = 0;
735 		s->Phone.Data.VerDate[0]	  = 0;
736 		s->Phone.Data.VerNum		  = 0;
737 		s->Phone.Data.StartInfoCounter	  = 0;
738 		s->Phone.Data.SentMsg		  = NULL;
739 
740 		s->Phone.Data.HardwareCache[0]	  = 0;
741 		s->Phone.Data.ProductCodeCache[0] = 0;
742 		s->Phone.Data.EnableIncomingCall  = FALSE;
743 		s->Phone.Data.EnableIncomingSMS	  = FALSE;
744 		s->Phone.Data.EnableIncomingCB	  = FALSE;
745 		s->Phone.Data.EnableIncomingUSSD  = FALSE;
746 		s->User.UserReplyFunctions	  = NULL;
747 		s->User.IncomingCall		  = NULL;
748 		s->User.IncomingSMS		  = NULL;
749 		s->User.IncomingCB		  = NULL;
750 		s->User.IncomingUSSD		  = NULL;
751 		s->User.SendSMSStatus		  = NULL;
752 		s->LockFile			  = NULL;
753 		s->opened			  = FALSE;
754 		s->Phone.Functions		  = NULL;
755 
756 		s->di 				  = GSM_none_debug;
757 		s->di.use_global 		  = s->CurrentConfig->UseGlobalDebugFile;
758 		if (!s->di.use_global) {
759 			GSM_SetDebugFunction(log_function, user_data, &s->di);
760 			GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di);
761 			error = GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di);
762 			if (error != ERR_NONE) {
763 				GSM_LogError(s, "Init:GSM_SetDebugFile" , error);
764 				return error;
765 			}
766 		}
767 
768 		smprintf_level(s, D_ERROR, "[Gammu            - %s]\n", GAMMU_VERSION);
769 		StripSpaces(s->CurrentConfig->Connection);
770 		StripSpaces(s->CurrentConfig->Model);
771 		StripSpaces(s->CurrentConfig->Device);
772 		smprintf_level(s, D_ERROR, "[Connection       - \"%s\"]\n",
773 				s->CurrentConfig->Connection);
774 		smprintf_level(s, D_ERROR, "[Connection index - %d]\n", i);
775 		smprintf_level(s, D_ERROR, "[Model type       - \"%s\"]\n",
776 				s->CurrentConfig->Model);
777 		smprintf_level(s, D_ERROR, "[Device           - \"%s\"]\n",
778 				s->CurrentConfig->Device);
779 		if (strlen(GetOS()) != 0) {
780 			smprintf_level(s, D_ERROR, "[Running on       - %s]\n",
781 					GetOS());
782 		}
783 
784 		if (GSM_GetDI(s)->dl == DL_BINARY) {
785 			smprintf(s,"%c",((unsigned char)strlen(GAMMU_VERSION)));
786 			smprintf(s,"%s",GAMMU_VERSION);
787 		}
788 
789 		error = GSM_RegisterAllConnections(s, s->CurrentConfig->Connection);
790 		if (error != ERR_NONE) {
791 			GSM_LogError(s, "Init:GSM_RegisterAllConnections" , error);
792 			return error;
793 		}
794 
795 autodetect:
796 		/* Model auto */
797 		/* Try to guess correct driver based on model */
798 		if (s->CurrentConfig->Model[0] == 0 &&
799 				s->ConnectionType != GCT_NONE &&
800 				s->ConnectionType != GCT_IRDAOBEX &&
801 				s->ConnectionType != GCT_BLUEOBEX &&
802 				s->ConnectionType != GCT_PROXYOBEX &&
803 				s->ConnectionType != GCT_BLUEGNAPBUS &&
804 				s->ConnectionType != GCT_PROXYGNAPBUS &&
805 				s->ConnectionType != GCT_IRDAGNAPBUS &&
806 				s->ConnectionType != GCT_PROXYS60 &&
807 				s->ConnectionType != GCT_BLUES60) {
808 			error = GSM_TryGetModel(s);
809 			/* Fall back to other configuraitons if the device is not existing (or similar error) */
810 			if ((i != s->ConfigNum - 1) && (
811 				(error == ERR_DEVICEOPENERROR) ||
812 				(error == ERR_DEVICELOCKED) ||
813 				(error == ERR_DEVICENOTEXIST) ||
814 				(error == ERR_DEVICEBUSY) ||
815 				(error == ERR_DEVICENOPERMISSION) ||
816 				(error == ERR_DEVICENODRIVER) ||
817 				(error == ERR_DEVICENOTWORK))) {
818 				GSM_CloseConnection(s);
819 				continue;
820 			}
821 			if (error != ERR_NONE) {
822 				GSM_LogError(s, "Init:GSM_TryGetModel" , error);
823 				return error;
824 			}
825 		}
826 
827 		/* Switching to "correct" module */
828 		error = GSM_RegisterAllPhoneModules(s);
829 		/* If user selected soemthing which is not supported, try autodetection */
830 		if (s->CurrentConfig->Model[0] != 0 && error == ERR_UNKNOWNMODELSTRING) {
831 			smprintf(s, "Configured model %s is not known, retrying with autodetection!\n",
832 					s->CurrentConfig->Model);
833 			s->CurrentConfig->Model[0] = 0;
834 			goto autodetect;
835 		}
836 		if (error != ERR_NONE) {
837 			GSM_LogError(s, "Init:GSM_RegisterAllPhoneModules" , error);
838 			return error;
839 		}
840 
841 		/* We didn't open device earlier ? Make it now */
842 		if (!s->opened) {
843 			error = GSM_OpenConnection(s);
844 			if ((i != s->ConfigNum - 1) && (
845 				(error == ERR_DEVICEOPENERROR) ||
846 				(error == ERR_DEVICELOCKED) ||
847 				(error == ERR_DEVICENOTEXIST) ||
848 				(error == ERR_DEVICEBUSY) ||
849 				(error == ERR_DEVICENOPERMISSION) ||
850 				(error == ERR_DEVICENODRIVER) ||
851 				(error == ERR_DEVICENOTWORK))) {
852 				GSM_CloseConnection(s);
853 				continue;
854 			}
855 			if (error != ERR_NONE) {
856 				GSM_LogError(s, "Init:GSM_OpenConnection" , error);
857 				return error;
858 			}
859 		}
860 
861 		/* Initialize phone layer */
862 		error=s->Phone.Functions->Initialise(s);
863 		if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
864 			GSM_CloseConnection(s);
865 			continue;
866 		}
867 		if (error != ERR_NONE) {
868 			GSM_LogError(s, "Init:Phone->Initialise" , error);
869 			return error;
870 		}
871 
872 		if (s->CurrentConfig->StartInfo) {
873 			s->Phone.Functions->ShowStartInfo(s,TRUE);
874 			s->Phone.Data.StartInfoCounter = 30;
875 		}
876 
877 		if (s->CurrentConfig->SyncTime) {
878 			GSM_GetCurrentDateTime (&current_time);
879 			s->Phone.Functions->SetDateTime(s,&current_time);
880 		}
881 
882 		/* For debug it's good to have firmware and real model version and manufacturer */
883 		error=s->Phone.Functions->GetManufacturer(s);
884 		if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
885 			GSM_CloseConnection(s);
886 			continue;
887 		}
888 		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
889 			GSM_LogError(s, "Init:Phone->GetManufacturer" , error);
890 			return error;
891 		}
892 
893 		error=s->Phone.Functions->GetModel(s);
894 		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
895 			GSM_LogError(s, "Init:Phone->GetModel" , error);
896 			return error;
897 		}
898 
899 		error=s->Phone.Functions->GetFirmware(s);
900 		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
901 			GSM_LogError(s, "Init:Phone->GetFirmware" , error);
902 			return error;
903 		}
904 
905 		error=s->Phone.Functions->SetPower(s, 1);
906 		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
907 			GSM_LogError(s, "Init:Phone->SetPower" , error);
908 			return error;
909 		}
910 
911 		error=s->Phone.Functions->PostConnect(s);
912 		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
913 			GSM_LogError(s, "Init:Phone->PostConnect" , error);
914 			return error;
915 		}
916 
917 		smprintf(s,"[Connected]\n");
918 		return ERR_NONE;
919 	}
920 	return ERR_UNCONFIGURED;
921 }
922 
GSM_InitConnection(GSM_StateMachine * s,int ReplyNum)923 GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum)
924 {
925 	return GSM_InitConnection_Log(s, ReplyNum, GSM_none_debug.log_function, GSM_none_debug.user_data);
926 }
927 
GSM_ReadDevice(GSM_StateMachine * s,gboolean waitforreply)928 int GSM_ReadDevice (GSM_StateMachine *s, gboolean waitforreply)
929 {
930 	GSM_DateTime	Date;
931 	unsigned char	buff[65536]={'\0'};
932 	int		res=0,count=0,i=0;
933 
934 	if (!GSM_IsConnected(s)) {
935 		return -1;
936 	}
937 
938 	GSM_GetCurrentDateTime (&Date);
939 	i = Date.Second;
940 	while (i == Date.Second && !s->Abort) {
941 		res = s->Device.Functions->ReadDevice(s, buff, sizeof(buff));
942 
943 		if (!waitforreply) {
944 			break;
945 		}
946 		if (res > 0) {
947 			break;
948 		}
949 		usleep(5000);
950 		GSM_GetCurrentDateTime(&Date);
951 	}
952 	for (count = 0; count < res; count++) {
953 		s->Protocol.Functions->StateMachine(s, buff[count]);
954 	}
955 	return res;
956 }
957 
GSM_TerminateConnection(GSM_StateMachine * s)958 GSM_Error GSM_TerminateConnection(GSM_StateMachine *s)
959 {
960 	GSM_Error error;
961 
962 	if (!s->opened) return ERR_NONE;
963 
964 	smprintf(s,"[Terminating]\n");
965 
966 	if (s->CurrentConfig->StartInfo) {
967 		if (s->Phone.Data.StartInfoCounter > 0) s->Phone.Functions->ShowStartInfo(s,FALSE);
968 	}
969 
970 	if (s->Phone.Functions != NULL) {
971 		error=s->Phone.Functions->Terminate(s);
972 		if (error!=ERR_NONE) return error;
973 	}
974 
975 	error = GSM_CloseConnection(s);
976 	if (error != ERR_NONE) return error;
977 
978 	GSM_SetDebugFileDescriptor(NULL, FALSE, &(s->di));
979 
980 	s->opened = FALSE;
981 
982 	return ERR_NONE;
983 }
984 
GSM_IsConnected(GSM_StateMachine * s)985 gboolean GSM_IsConnected(GSM_StateMachine *s) {
986 	return (s != NULL) && s->Phone.Functions != NULL && s->opened;
987 }
988 
GSM_AbortOperation(GSM_StateMachine * s)989 GSM_Error GSM_AbortOperation(GSM_StateMachine * s)
990 {
991 	s->Abort = TRUE;
992 	return ERR_NONE;
993 }
994 
GSM_WaitForOnce(GSM_StateMachine * s,unsigned const char * buffer,size_t length,int type,int timeout)995 GSM_Error GSM_WaitForOnce(GSM_StateMachine *s, unsigned const char *buffer,
996 			  size_t length, int type, int timeout)
997 {
998 	GSM_Phone_Data *Phone = &s->Phone.Data;
999 	GSM_Protocol_Message sentmsg;
1000 	int i = 0;
1001 
1002 	do {
1003 		if (length != 0) {
1004 			sentmsg.Length 	= length;
1005 			sentmsg.Type	= type;
1006 			sentmsg.Buffer 	= (unsigned char *)malloc(length);
1007 			memcpy(sentmsg.Buffer, buffer, length);
1008 			Phone->SentMsg  = &sentmsg;
1009 		}
1010 
1011 		/* Some data received. Reset timer */
1012 		if (GSM_ReadDevice(s, TRUE) > 0) {
1013 			i = 0;
1014 		} else {
1015 			usleep(10000);
1016 		}
1017 
1018 		if (length != 0) {
1019 			free(sentmsg.Buffer);
1020 			sentmsg.Buffer = NULL;
1021 			Phone->SentMsg = NULL;
1022 		}
1023 
1024 		if (s->Abort) {
1025 			return ERR_ABORTED;
1026 		}
1027 
1028 		/* Request completed */
1029 		if (Phone->RequestID == ID_None) {
1030 			return Phone->DispatchError;
1031 		}
1032 		i++;
1033 	} while (i < timeout);
1034 
1035 	return ERR_TIMEOUT;
1036 }
1037 
GSM_WaitFor(GSM_StateMachine * s,unsigned const char * buffer,size_t length,int type,int timeout,GSM_Phone_RequestID request)1038 GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned const char *buffer,
1039 		       size_t length, int type, int timeout,
1040 		       GSM_Phone_RequestID request)
1041 {
1042 	GSM_Phone_Data		*Phone = &s->Phone.Data;
1043 	GSM_Error		error;
1044 	int			reply;
1045 
1046 	if (s->CurrentConfig->StartInfo) {
1047 		if (Phone->StartInfoCounter > 0) {
1048 			Phone->StartInfoCounter--;
1049 			if (Phone->StartInfoCounter == 0) {
1050 				s->Phone.Functions->ShowStartInfo(s,FALSE);
1051 			}
1052 		}
1053 	}
1054 
1055 	Phone->RequestID	= request;
1056 	Phone->DispatchError	= ERR_TIMEOUT;
1057 
1058 	for (reply = 0; reply < s->ReplyNum; reply++) {
1059 		if (reply != 0) {
1060 			smprintf_level(s, D_ERROR, "[Retrying %i type 0x%02X]\n", reply, type);
1061 		}
1062 		error = s->Protocol.Functions->WriteMessage(s, buffer, length, type);
1063 		if (error != ERR_NONE) {
1064 			return error;
1065 		}
1066 
1067 		/* Special case when no reply is expected */
1068 		if (request == ID_None) {
1069 			return ERR_NONE;
1070 		}
1071 
1072 		error = GSM_WaitForOnce(s, buffer, length, type, timeout);
1073 		if (error != ERR_TIMEOUT) {
1074 			return error;
1075 		}
1076   }
1077 
1078 	if (request != ID_Reset && GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RESET_AFTER_TIMEOUT)) {
1079 		smprintf_level(s, D_ERROR, "Performing device reset after timeout!\n");
1080 		GSM_Reset(s, FALSE);
1081 	}
1082 
1083 	return ERR_TIMEOUT;
1084 }
1085 
CheckReplyFunctions(GSM_StateMachine * s,GSM_Reply_Function * Reply,int * reply)1086 static GSM_Error CheckReplyFunctions(GSM_StateMachine *s, GSM_Reply_Function *Reply, int *reply)
1087 {
1088 	GSM_Phone_Data			*Data	  = &s->Phone.Data;
1089 	GSM_Protocol_Message		*msg	  = s->Phone.Data.RequestMsg;
1090 	gboolean				execute;
1091 	gboolean				available = FALSE;
1092 	int				i	  = 0;
1093 
1094 	while (Reply[i].requestID != ID_None) {
1095 		execute = FALSE;
1096 		/* Long ID frames like S60 */
1097 		if (Reply[i].msgtype[0] == 0 && Reply[i].subtypechar == 0) {
1098 			if (Reply[i].subtype == msg->Type) {
1099 				execute = TRUE;
1100 			}
1101 		/* Binary frames like in Nokia */
1102 		} else if (strlen(Reply[i].msgtype) < 2) {
1103 			if (Reply[i].msgtype[0]==msg->Type) {
1104 				if (Reply[i].subtypechar!=0) {
1105 					if (Reply[i].subtypechar<=msg->Length) {
1106 						if (msg->Buffer[Reply[i].subtypechar]==Reply[i].subtype)
1107 							execute=TRUE;
1108 					}
1109 				} else {
1110 					execute=TRUE;
1111 				}
1112 			}
1113 		} else {
1114 			if (strlen(Reply[i].msgtype) < msg->Length) {
1115 				if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) {
1116 					execute=TRUE;
1117 				}
1118 			}
1119 		}
1120 
1121 		if (execute) {
1122 			*reply = i;
1123 			if (Reply[i].requestID == ID_IncomingFrame ||
1124 			    Reply[i].requestID == Data->RequestID ||
1125 			    Data->RequestID    == ID_EachFrame) {
1126 				return ERR_NONE;
1127 			}
1128 			available = TRUE;
1129 		}
1130 		i++;
1131 	}
1132 
1133 	if (available) {
1134 		return ERR_FRAMENOTREQUESTED;
1135 	} else {
1136 		return ERR_UNKNOWNFRAME;
1137 	}
1138 }
1139 
EventQueue_Push(GSM_StateMachine * s,const EventBinding * binding)1140 GSM_Error EventQueue_Push(GSM_StateMachine *s, const EventBinding *binding)
1141 {
1142   DeferredEventQueue *Queue = &s->Phone.Data.DeferredEvents;
1143 
1144   assert(binding != NULL);
1145   assert(Queue->head < MAX_DEFERRED_EVENTS);
1146 
1147   if(Queue->entries == MAX_DEFERRED_EVENTS)
1148     return ERR_FULL;
1149 
1150   Queue->event_bindings[Queue->head] = *binding;
1151   Queue->head = (Queue->head + 1) % MAX_DEFERRED_EVENTS;
1152   ++Queue->entries;
1153 
1154   assert(Queue->entries <= MAX_DEFERRED_EVENTS);
1155 
1156   return ERR_NONE;
1157 }
1158 
EventQueue_Pop(GSM_StateMachine * s,EventBinding * binding)1159 GSM_Error EventQueue_Pop(GSM_StateMachine *s, EventBinding *binding)
1160 {
1161   DeferredEventQueue *Queue = &s->Phone.Data.DeferredEvents;
1162 
1163   assert(binding != NULL);
1164 
1165   if(Queue->entries == 0)
1166     return ERR_EMPTY;
1167 
1168   *binding = Queue->event_bindings[Queue->tail];
1169   Queue->tail = (Queue->tail + 1) % MAX_DEFERRED_EVENTS;
1170   --Queue->entries;
1171 
1172   assert(Queue->entries >= 0);
1173 
1174   return ERR_NONE;
1175 }
1176 
GSM_CancelEventsOfType(GSM_StateMachine * s,unsigned event_types)1177 void GSM_CancelEventsOfType(GSM_StateMachine *s, unsigned event_types)
1178 {
1179   DeferredEventQueue *q = &s->Phone.Data.DeferredEvents;
1180   int i = q->tail;
1181 
1182   while(i != q->head) {
1183     if(q->event_bindings[i].type & event_types)
1184       q->event_bindings[i].event_cancelled = TRUE;
1185 
1186     i = (i + 1) % MAX_DEFERRED_EVENTS;
1187   }
1188 }
1189 
GSM_DeferIncomingCallEvent(GSM_StateMachine * s,GSM_Call * call,BeforeDeferredEvent before_event)1190 GSM_Error GSM_DeferIncomingCallEvent(GSM_StateMachine *s, GSM_Call *call, BeforeDeferredEvent before_event)
1191 {
1192   GSM_Error error;
1193   EventBinding binding;
1194 
1195   if(s->Phone.Data.RequestID == ID_None) {
1196     s->User.IncomingCall(s, call, s->User.IncomingCallUserData);
1197     return ERR_NONE;
1198   }
1199 
1200   binding.type = GSM_EV_CALL;
1201   binding.handler = (EventHandler)s->User.IncomingCall;
1202   binding.before_event = before_event;
1203   binding.after_event = NULL;
1204   binding.event_cancelled = FALSE;
1205   binding.event_data.call = *call;
1206   binding.user_data = s->User.IncomingCallUserData;
1207 
1208   error = EventQueue_Push(s, &binding);
1209 
1210   if(error != ERR_NONE)
1211     smprintf_level(s, D_ERROR,
1212       "the incoming call handler could not be deferred.\n");
1213 
1214   return error;
1215 }
1216 
ProcessDeferredEvent(GSM_StateMachine * s)1217 GSM_Error ProcessDeferredEvent(GSM_StateMachine *s)
1218 {
1219   EventBinding binding;
1220   GSM_Error error = EventQueue_Pop(s, &binding);
1221 
1222   if(error != ERR_NONE)
1223     return error;
1224 
1225   assert(s->Phone.Data.RequestID == ID_None);
1226   assert(binding.handler != NULL);
1227   assert(binding.type != GSM_EV_UNSET);
1228 
1229   if(binding.event_cancelled == FALSE) {
1230     if (binding.before_event)
1231       error = binding.before_event(s);
1232 
1233     if(error == ERR_NONE)
1234       binding.handler(s, &binding.event_data, binding.user_data);
1235   }
1236 
1237   if(binding.after_event)
1238     binding.after_event(s, &binding);
1239 
1240   return error;
1241 }
1242 
GSM_DispatchMessage(GSM_StateMachine * s)1243 GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
1244 {
1245 	GSM_Error		error	= ERR_UNKNOWNFRAME;
1246 	GSM_Protocol_Message	*msg 	= s->Phone.Data.RequestMsg;
1247 	GSM_Phone_Data 		*Phone	= &s->Phone.Data;
1248 	gboolean			disp    = FALSE;
1249 	GSM_Reply_Function	*Reply;
1250 	int			reply;
1251 
1252 	s->MessagesCount++;
1253 
1254 	GSM_DumpMessageTextRecv(s, msg->Buffer, msg->Length, msg->Type);
1255 	GSM_DumpMessageBinaryRecv(s, msg->Buffer, msg->Length, msg->Type);
1256 
1257 	Reply = s->User.UserReplyFunctions;
1258 	if (Reply != NULL) {
1259 		error = CheckReplyFunctions(s, Reply, &reply);
1260 	}
1261 
1262 	if (error == ERR_UNKNOWNFRAME) {
1263 		Reply = s->Phone.Functions->ReplyFunctions;
1264 		error = CheckReplyFunctions(s, Reply, &reply);
1265 	}
1266 
1267 	if (error == ERR_NONE) {
1268 		error = Reply[reply].Function(msg, s);
1269 		if (Reply[reply].requestID == Phone->RequestID) {
1270 			if (error == ERR_NEEDANOTHERANSWER) {
1271 				error = ERR_NONE;
1272 			} else {
1273 				Phone->RequestID = ID_None;
1274         while(ProcessDeferredEvent(s) == ERR_NONE);
1275 			}
1276 		}
1277 	}
1278 
1279 	if (strcmp(s->Phone.Functions->models,"NAUTO")) {
1280 		disp = TRUE;
1281 		switch (error) {
1282 		case ERR_UNKNOWNRESPONSE:
1283 			smprintf_level(s, D_ERROR, "\nUNKNOWN response");
1284 			break;
1285 		case ERR_UNKNOWNFRAME:
1286 			smprintf_level(s, D_ERROR, "\nUNKNOWN frame");
1287 			break;
1288 		case ERR_FRAMENOTREQUESTED:
1289 			smprintf_level(s, D_ERROR, "\nFrame not request now");
1290 			break;
1291 		default:
1292 			disp = FALSE;
1293 		}
1294 
1295 		if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) {
1296 			error = ERR_TIMEOUT;
1297 		}
1298 	}
1299 
1300 	if (disp) {
1301 		smprintf(s,". Please report the error, see <https://wammu.eu/support/bugs/>. Thank you\n");
1302 		if (Phone->SentMsg != NULL) {
1303 			smprintf(s,"LAST SENT frame ");
1304 			smprintf(s, "type 0x%02X/length %ld", Phone->SentMsg->Type, (long)Phone->SentMsg->Length);
1305 			DumpMessage(GSM_GetDI(s), Phone->SentMsg->Buffer, Phone->SentMsg->Length);
1306 		}
1307 		smprintf(s, "RECEIVED frame ");
1308 		smprintf(s, "type 0x%02X/length 0x%lx/%ld", msg->Type, (long)msg->Length, (long)msg->Length);
1309 		DumpMessage(GSM_GetDI(s), msg->Buffer, msg->Length);
1310 		smprintf(s, "\n");
1311 	}
1312 
1313 	return error;
1314 }
1315 
GSM_TryReadGammuRC(const char * path,INI_Section ** result)1316 GSM_Error GSM_TryReadGammuRC (const char *path, INI_Section **result)
1317 {
1318 	dbgprintf(NULL, "Open config: \"%s\"\n", path);
1319 	return  INI_ReadFile(path, FALSE, result);
1320 }
1321 
GSM_FindGammuRC(INI_Section ** result,const char * force_config)1322 GSM_Error GSM_FindGammuRC (INI_Section **result, const char *force_config)
1323 {
1324 	char configfile[PATH_MAX + 1];
1325 	char *envpath;
1326 	GSM_Error error;
1327 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
1328 	struct passwd *pwent;
1329 #endif
1330 
1331 	*result = NULL;
1332 
1333 	if (force_config != NULL) {
1334 		return GSM_TryReadGammuRC(force_config, result);
1335 	}
1336 
1337 #ifdef WIN32
1338 	/* Get Windows application data path */
1339 	if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configfile))) {
1340 		strcat(configfile, GAMMURC_NAME);
1341 
1342 		error = GSM_TryReadGammuRC(configfile, result);
1343 		if (error == ERR_NONE) return ERR_NONE;
1344 	}
1345 #endif
1346 
1347 	/* XDG paths */
1348 	envpath = getenv("XDG_CONFIG_HOME");
1349 	if (envpath) {
1350 		strcpy(configfile, envpath);
1351 		strcat(configfile, XDG_GAMMURC_NAME);
1352 
1353 		error = GSM_TryReadGammuRC(configfile, result);
1354 		if (error == ERR_NONE) return ERR_NONE;
1355 	} else {
1356 		envpath  = getenv("HOME");
1357 		if (envpath) {
1358 			strcpy(configfile, envpath);
1359 			strcat(configfile, "/.config");
1360 			strcat(configfile, XDG_GAMMURC_NAME);
1361 
1362 			error = GSM_TryReadGammuRC(configfile, result);
1363 			if (error == ERR_NONE) return ERR_NONE;
1364 		}
1365 	}
1366 
1367 	/* Try home from environment */
1368 	envpath  = getenv("HOME");
1369 	if (envpath) {
1370 		strcpy(configfile, envpath);
1371 		strcat(configfile, GAMMURC_NAME);
1372 
1373 		error = GSM_TryReadGammuRC(configfile, result);
1374 		if (error == ERR_NONE) return ERR_NONE;
1375 	}
1376 
1377 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
1378 	/* Tru home from passwd */
1379 	pwent = getpwuid(getuid());
1380 	if (pwent != NULL) {
1381 		strcpy(configfile, pwent->pw_dir);
1382 		strcat(configfile, GAMMURC_NAME);
1383 
1384 		error = GSM_TryReadGammuRC(configfile, result);
1385 		if (error == ERR_NONE) return ERR_NONE;
1386 	}
1387 
1388 #endif
1389 
1390 #if defined(WIN32)
1391 	/* Reset as we're using strcat */
1392 	configfile[0] = 0;
1393 
1394 	/* This makes sense only on Windows */
1395 	envpath = getenv("HOMEDRIVE");
1396 	if (envpath) {
1397 		strcat(configfile, envpath);
1398 	}
1399 
1400 	envpath = getenv("HOMEPATH");
1401 	if (envpath) {
1402 		strcat(configfile, envpath);
1403 		strcat(configfile, GAMMURC_NAME);
1404 
1405 		error = GSM_TryReadGammuRC(configfile, result);
1406 		if (error == ERR_NONE) return ERR_NONE;
1407 	}
1408 #endif
1409 
1410 	/* Try fallback config as last */
1411 	return GSM_TryReadGammuRC(FALLBACK_GAMMURC, result);
1412 }
1413 
GSM_GetConfig(GSM_StateMachine * s,int num)1414 GSM_Config *GSM_GetConfig(GSM_StateMachine *s, int num)
1415 {
1416 	if (num == -1) {
1417 		return s->CurrentConfig;
1418 	} else {
1419 		if (num > MAX_CONFIG_NUM) return NULL;
1420 		return &(s->Config[num]);
1421 	}
1422 }
1423 
1424 
GSM_GetConfigNum(const GSM_StateMachine * s)1425 int GSM_GetConfigNum(const GSM_StateMachine *s)
1426 {
1427 	return s->ConfigNum;
1428 }
1429 
GSM_SetConfigNum(GSM_StateMachine * s,int sections)1430 void GSM_SetConfigNum(GSM_StateMachine *s, int sections)
1431 {
1432 	if (sections > MAX_CONFIG_NUM) return;
1433 	s->ConfigNum = sections;
1434 }
1435 
1436 /**
1437  * Expand path to user home.
1438  */
GSM_ExpandUserPath(char ** string)1439 void GSM_ExpandUserPath(char **string)
1440 {
1441 	char *tmp = NULL, *home = NULL;
1442 
1443 	/* Is there something to expand */
1444 	if (*string[0] != '~') return;
1445 
1446 	/* Grab home */
1447 	home = getenv("HOME");
1448 	if (home == NULL) return;
1449 
1450 	/* Allocate memory */
1451 	tmp = (char *)malloc(strlen(home) + strlen(*string) + 2);
1452 	if (tmp == NULL) return;
1453 
1454 	/* Create final path */
1455 	strcpy(tmp, home);
1456 	strcat(tmp, *string + 1);
1457 
1458 	/* Free old storage and replace it */
1459 	free(*string);
1460 	*string = tmp;
1461 }
1462 
1463 /**
1464  * Parses an ASCII string of comma delimited single digits into a set of integer
1465  * parameters, any whitespace is ignored.
1466  *
1467  * @param out_params array to receive the parsed parameters
1468  * @param num_params number of parameters out_params can hold
1469  * @param args string containing list of parameters to parse
1470  * @return ERR_NONE on success, otherwise ERR_INVALIDDATA
1471  */
GSM_ReadParams(int * out_params,const int num_params,const char * args)1472 GSM_Error GSM_ReadParams(int *out_params, const int num_params, const char *args)
1473 {
1474   int *params_ptr = out_params;
1475   const int *params_end = out_params + num_params * sizeof(int);
1476   const char *args_ptr = args;
1477   int whitespace_count = 0;
1478   gboolean expect_comma = 0;
1479 
1480   if (!args)
1481     return ERR_NONE;
1482 
1483   while (params_ptr < params_end) {
1484     while (isspace((unsigned char)*args_ptr)) {
1485       ++whitespace_count;
1486       ++args_ptr;
1487     }
1488 
1489     if(!*args_ptr)
1490       return ERR_NONE;
1491 
1492     switch (*args_ptr) {
1493       case '0': case '1': case '2': case '3': case '4':
1494       case '5': case '6': case '7': case '8': case '9':
1495         if (expect_comma) {
1496           printf("expected comma but got %c for parameter %d\n", *args_ptr, (int)(++params_ptr - out_params));
1497           return ERR_INVALIDDATA;
1498         }
1499         *params_ptr = *args_ptr - '0';
1500         expect_comma = TRUE;
1501         break;
1502 
1503       case ',':
1504         ++params_ptr;
1505         expect_comma = FALSE;
1506         break;
1507 
1508       default: {
1509         printf("error parsing parameters, unrecognized token '%c' in position %d\n",
1510                *args_ptr, (int)(++params_ptr - --out_params + ++whitespace_count));
1511         return ERR_INVALIDDATA; }
1512     }
1513 
1514     ++args_ptr;
1515   }
1516 
1517   return ERR_NONE;
1518 }
1519 
GSM_ReadCNMIParams(int out_params[5],const char * args)1520 GSM_Error GSM_ReadCNMIParams(int out_params[5], const char *args)
1521 {
1522   return GSM_ReadParams(out_params, 5, args);
1523 }
1524 
GSM_ReadConfig(INI_Section * cfg_info,GSM_Config * cfg,int num)1525 GSM_Error GSM_ReadConfig(INI_Section *cfg_info, GSM_Config *cfg, int num)
1526 {
1527 	INI_Section 	*h;
1528 	unsigned char 	section[50]={0};
1529 	gboolean	found = FALSE;
1530 	char		*Temp = NULL;
1531 	const int cnmi_default[5] = {-1,-1,-1,-1,-1};
1532 
1533 	GSM_Error error = ERR_UNKNOWN;
1534 	cfg->UseGlobalDebugFile	 = TRUE;
1535 	memcpy(cfg->CNMIParams, &cnmi_default, sizeof(cfg->CNMIParams));
1536 
1537 	/* If we don't have valid config, bail out */
1538 	if (cfg_info == NULL) {
1539 		error = ERR_UNCONFIGURED;
1540 		goto fail;
1541 	}
1542 
1543 	/* Which section should we read? */
1544 	if (num == 0) {
1545 		snprintf(section, sizeof(section) - 1, "gammu");
1546 	} else {
1547 		snprintf(section, sizeof(section) - 1, "gammu%i", num);
1548 	}
1549 
1550 	/* Scan for section */
1551         for (h = cfg_info; h != NULL; h = h->Next) {
1552                 if (strcasecmp(section, h->SectionName) == 0) {
1553 			found = TRUE;
1554 			break;
1555 		}
1556         }
1557 	if (!found) {
1558 		error = ERR_NONE_SECTION;
1559 		goto fail;
1560 	}
1561 
1562 	/* Set device name */
1563 	free(cfg->Device);
1564 	cfg->Device 	 = INI_GetValue(cfg_info, section, "device", 		FALSE);
1565 	if (!cfg->Device) {
1566 		cfg->Device 	 = INI_GetValue(cfg_info, section, "port", 		FALSE);
1567 		if (!cfg->Device) {
1568 			cfg->Device		 	 = strdup(DEFAULT_DEVICE);
1569 		} else {
1570 			cfg->Device			 = strdup(cfg->Device);
1571 		}
1572 	} else {
1573 		cfg->Device			 = strdup(cfg->Device);
1574 	}
1575 
1576 	/* Set connection type */
1577 	free(cfg->Connection);
1578 	cfg->Connection  = INI_GetValue(cfg_info, section, "connection", 	FALSE);
1579 	if (cfg->Connection == NULL) {
1580 		cfg->Connection	 		 = strdup(DEFAULT_CONNECTION);
1581 	} else {
1582 		cfg->Connection			 = strdup(cfg->Connection);
1583 	}
1584 
1585 	/* Set time sync */
1586 	cfg->SyncTime = INI_GetBool(cfg_info, section, "synchronizetime", DEFAULT_SYNCHRONIZE_TIME);
1587 
1588 	/* Set debug file */
1589 	free(cfg->DebugFile);
1590 	cfg->DebugFile   = INI_GetValue(cfg_info, section, "logfile", 		FALSE);
1591 	if (cfg->DebugFile == NULL) {
1592 		cfg->DebugFile		 	 = strdup(DEFAULT_DEBUG_FILE);
1593 	} else {
1594 		cfg->DebugFile			 = strdup(cfg->DebugFile);
1595 		GSM_ExpandUserPath(&cfg->DebugFile);
1596 	}
1597 
1598 	/* Set file locking */
1599 	cfg->LockDevice  = INI_GetBool(cfg_info, section, "use_locking", DEFAULT_LOCK_DEVICE);
1600 
1601 	/* Set model */
1602 	Temp		 = INI_GetValue(cfg_info, section, "model", 		FALSE);
1603 	if (Temp == NULL || strcmp(Temp, "auto") == 0) {
1604 		strcpy(cfg->Model,DEFAULT_MODEL);
1605 	} else {
1606 		if (strlen(Temp) >= sizeof(cfg->Model))
1607 			Temp[sizeof(cfg->Model) - 1] = '\0';
1608 		strcpy(cfg->Model,Temp);
1609 	}
1610 
1611 	/* Set Log format */
1612 	Temp		 = INI_GetValue(cfg_info, section, "logformat", 	FALSE);
1613 
1614 	if (Temp == NULL) {
1615 		strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL);
1616 	} else {
1617 		if (strlen(Temp) >= sizeof(cfg->DebugLevel))
1618 			Temp[sizeof(cfg->DebugLevel) - 1] = '\0';
1619 		strcpy(cfg->DebugLevel,Temp);
1620 	}
1621 
1622 	/* Set startup info */
1623 	cfg->StartInfo = INI_GetBool(cfg_info, section, "startinfo", DEFAULT_START_INFO);
1624 
1625 	/* Read localised strings for some phones */
1626 
1627 	Temp		 = INI_GetValue(cfg_info, section, "reminder", 		FALSE);
1628 
1629 	if (Temp == NULL) {
1630 		strcpy(cfg->TextReminder,"Reminder");
1631 	} else {
1632 		if (strlen(Temp) >= sizeof(cfg->TextReminder))
1633 			Temp[sizeof(cfg->TextReminder) - 1] = '\0';
1634 		strcpy(cfg->TextReminder,Temp);
1635 	}
1636 
1637 	Temp		 = INI_GetValue(cfg_info, section, "meeting", 		FALSE);
1638 
1639 	if (Temp == NULL) {
1640 		strcpy(cfg->TextMeeting,"Meeting");
1641 	} else {
1642 		if (strlen(Temp) >= sizeof(cfg->TextMeeting))
1643 			Temp[sizeof(cfg->TextMeeting) - 1] = '\0';
1644 		strcpy(cfg->TextMeeting,Temp);
1645 	}
1646 
1647 	Temp		 = INI_GetValue(cfg_info, section, "call", 		FALSE);
1648 
1649 	if (Temp == NULL) {
1650 		strcpy(cfg->TextCall,"Call");
1651 	} else {
1652 		if (strlen(Temp) >= sizeof(cfg->TextCall))
1653 			Temp[sizeof(cfg->TextCall) - 1] = '\0';
1654 		strcpy(cfg->TextCall,Temp);
1655 	}
1656 
1657 	Temp		 = INI_GetValue(cfg_info, section, "birthday", 		FALSE);
1658 
1659 	if (Temp == NULL) {
1660 		strcpy(cfg->TextBirthday,"Birthday");
1661 	} else {
1662 		if (strlen(Temp) >= sizeof(cfg->TextBirthday))
1663 			Temp[sizeof(cfg->TextBirthday) - 1] = '\0';
1664 		strcpy(cfg->TextBirthday,Temp);
1665 	}
1666 
1667 	Temp		 = INI_GetValue(cfg_info, section, "memo", 		FALSE);
1668 
1669 	if (Temp == NULL) {
1670 		strcpy(cfg->TextMemo,"Memo");
1671 	} else {
1672 		if (strlen(Temp) >= sizeof(cfg->TextMemo))
1673 			Temp[sizeof(cfg->TextMemo) - 1] = '\0';
1674 		strcpy(cfg->TextMemo,Temp);
1675 	}
1676 
1677 	/* Phone features */
1678 	Temp		 = INI_GetValue(cfg_info, section, "features", 		FALSE);
1679 
1680 	if (Temp == NULL) {
1681 		cfg->PhoneFeatures[0] = 0;
1682 	} else {
1683 		error = GSM_SetFeatureString(cfg->PhoneFeatures, Temp);
1684 
1685 		if (error != ERR_NONE) {
1686 			goto fail;
1687 		}
1688 	}
1689 
1690 	Temp = INI_GetValue(cfg_info, section, "atgen_setcnmi", FALSE);
1691 	if (Temp) {
1692     error = GSM_ReadCNMIParams(cfg->CNMIParams, Temp);
1693     if (error != ERR_NONE)
1694       goto fail;
1695   }
1696 
1697   return ERR_NONE;
1698 
1699 fail:
1700 	/* Special case, this config needs to be somehow valid */
1701 	if (num == 0) {
1702 		cfg->Device		 	 = strdup(DEFAULT_DEVICE);
1703 		cfg->Connection	 		 = strdup(DEFAULT_CONNECTION);
1704 		cfg->SyncTime		 	 = DEFAULT_SYNCHRONIZE_TIME;
1705 		cfg->DebugFile		 	 = strdup(DEFAULT_DEBUG_FILE);
1706 		cfg->LockDevice	 		 = DEFAULT_LOCK_DEVICE;
1707 		strcpy(cfg->Model,DEFAULT_MODEL);
1708 		strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL);
1709 		cfg->StartInfo	 		 = DEFAULT_START_INFO;
1710 		strcpy(cfg->TextReminder,"Reminder");
1711 		strcpy(cfg->TextMeeting,"Meeting");
1712 		strcpy(cfg->TextCall,"Call");
1713 		strcpy(cfg->TextBirthday,"Birthday");
1714 		strcpy(cfg->TextMemo,"Memo");
1715 		cfg->PhoneFeatures[0] = 0;
1716 		/* Indicate that we used defaults */
1717 		return ERR_USING_DEFAULTS;
1718 	}
1719 	return error;
1720 }
1721 
GSM_DumpMessageText_Custom(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type,const char * text)1722 void GSM_DumpMessageText_Custom(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type, const char *text)
1723 {
1724 	GSM_Debug_Info *curdi;
1725 
1726 	curdi = GSM_GetDI(s);
1727 
1728 	if (curdi->dl == DL_TEXT ||
1729 			curdi->dl == DL_TEXTALL ||
1730 			curdi->dl == DL_TEXTDATE ||
1731 			curdi->dl == DL_TEXTALLDATE) {
1732 		smprintf(s, "%s ", text);
1733 		smprintf(s, "type 0x%02X/length 0x%02lX/%ld",
1734 				type, (long)messagesize, (long)messagesize);
1735 		DumpMessage(curdi, message, messagesize);
1736 	}
1737 }
1738 
GSM_DumpMessageText(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type)1739 void GSM_DumpMessageText(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
1740 {
1741 	GSM_DumpMessageText_Custom(s, message, messagesize, type, "SENDING frame");
1742 }
1743 
GSM_DumpMessageTextRecv(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type)1744 void GSM_DumpMessageTextRecv(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
1745 {
1746 	GSM_DumpMessageText_Custom(s, message, messagesize, type, "RECEIVED frame");
1747 }
1748 
GSM_DumpMessageBinary_Custom(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type,int direction)1749 void GSM_DumpMessageBinary_Custom(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type, int direction)
1750 {
1751 	size_t i=0;
1752 	GSM_Debug_Info *curdi;
1753 
1754 	curdi = GSM_GetDI(s);
1755 
1756 	if (curdi->dl == DL_BINARY) {
1757 		smprintf(s,"%c", direction);
1758 		smprintf(s,"%c",type);
1759 		smprintf(s,"%c",(int)(messagesize/256));
1760 		smprintf(s,"%c",(int)(messagesize%256));
1761 
1762 		for (i=0;i<messagesize;i++) {
1763 			smprintf(s,"%c",message[i]);
1764 		}
1765 	}
1766 }
GSM_DumpMessageBinary(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type)1767 void GSM_DumpMessageBinary(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
1768 {
1769 	GSM_DumpMessageBinary_Custom(s, message, messagesize, type, 0x01);
1770 }
1771 
GSM_DumpMessageBinaryRecv(GSM_StateMachine * s,unsigned const char * message,size_t messagesize,int type)1772 void GSM_DumpMessageBinaryRecv(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
1773 {
1774 	GSM_DumpMessageBinary_Custom(s, message, messagesize, type, 0x02);
1775 }
1776 
GSM_OSErrorInfo(GSM_StateMachine * s,const char * description)1777 void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
1778 {
1779 #ifdef WIN32
1780 	int 		i=0;
1781 	unsigned char 	*lpMsgBuf = NULL;
1782 #endif
1783 	GSM_Debug_Info *curdi;
1784 
1785 	curdi = GSM_GetDI(s);
1786 
1787 #ifdef WIN32
1788 	/* We don't use errno in win32 - GetLastError gives better info */
1789 	if (GetLastError() != 0) {
1790 		if (curdi->dl == DL_TEXTERROR ||
1791 				curdi->dl == DL_TEXT ||
1792 				curdi->dl == DL_TEXTALL ||
1793 				curdi->dl == DL_TEXTERRORDATE ||
1794 				curdi->dl == DL_TEXTDATE ||
1795 				curdi->dl == DL_TEXTALLDATE) {
1796 			FormatMessage(
1797 				FORMAT_MESSAGE_ALLOCATE_BUFFER |
1798 				FORMAT_MESSAGE_FROM_SYSTEM |
1799 				FORMAT_MESSAGE_IGNORE_INSERTS,
1800 				NULL,
1801 				GetLastError(),
1802 				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
1803 				(LPTSTR) &lpMsgBuf,
1804 				0,
1805 				NULL
1806 			);
1807 			for (i=0;i<(int)strlen(lpMsgBuf);i++) {
1808 				if (lpMsgBuf[i] == 13 || lpMsgBuf[i] == 10) {
1809 					lpMsgBuf[i] = ' ';
1810 				}
1811 			}
1812 			smprintf(s,"[System error     - %s, %i, \"%s\"]\n", description, (int)GetLastError(), (LPCTSTR)lpMsgBuf);
1813 			LocalFree(lpMsgBuf);
1814 		}
1815 	}
1816 #else
1817 
1818 	if (errno!=-1) {
1819 		if (curdi->dl == DL_TEXTERROR ||
1820 				curdi->dl == DL_TEXT ||
1821 				curdi->dl == DL_TEXTALL ||
1822 				curdi->dl == DL_TEXTERRORDATE ||
1823 				curdi->dl == DL_TEXTDATE ||
1824 				curdi->dl == DL_TEXTALLDATE) {
1825 			smprintf(s,"[System error     - %s, %i, \"%s\"]\n",description,errno,strerror(errno));
1826 		}
1827 	}
1828 #endif
1829 }
1830 
GSM_SetIncomingCallCallback(GSM_StateMachine * s,IncomingCallCallback callback,void * user_data)1831 void GSM_SetIncomingCallCallback(GSM_StateMachine *s, IncomingCallCallback callback, void *user_data)
1832 {
1833 	s->User.IncomingCall = callback;
1834 	s->User.IncomingCallUserData = user_data;
1835 }
1836 
GSM_SetIncomingSMSCallback(GSM_StateMachine * s,IncomingSMSCallback callback,void * user_data)1837 void GSM_SetIncomingSMSCallback(GSM_StateMachine *s, IncomingSMSCallback callback, void *user_data)
1838 {
1839 	s->User.IncomingSMS = callback;
1840 	s->User.IncomingSMSUserData = user_data;
1841 }
1842 
GSM_SetIncomingCBCallback(GSM_StateMachine * s,IncomingCBCallback callback,void * user_data)1843 void GSM_SetIncomingCBCallback(GSM_StateMachine *s, IncomingCBCallback callback, void *user_data)
1844 {
1845 	s->User.IncomingCB = callback;
1846 	s->User.IncomingCBUserData = user_data;
1847 }
1848 
GSM_SetIncomingUSSDCallback(GSM_StateMachine * s,IncomingUSSDCallback callback,void * user_data)1849 void GSM_SetIncomingUSSDCallback(GSM_StateMachine *s, IncomingUSSDCallback callback, void *user_data)
1850 {
1851 	s->User.IncomingUSSD = callback;
1852 	s->User.IncomingUSSDUserData = user_data;
1853 }
1854 
GSM_SetSendSMSStatusCallback(GSM_StateMachine * s,SendSMSStatusCallback callback,void * user_data)1855 void GSM_SetSendSMSStatusCallback(GSM_StateMachine *s, SendSMSStatusCallback callback, void *user_data)
1856 {
1857 	s->User.SendSMSStatus = callback;
1858 	s->User.SendSMSStatusUserData = user_data;
1859 }
1860 
GSM_AllocStateMachine(void)1861 GSM_StateMachine *GSM_AllocStateMachine(void)
1862 {
1863 	GSM_StateMachine *ret;
1864 	ret = (GSM_StateMachine *)calloc(1, sizeof(GSM_StateMachine));
1865 	if (ret == NULL) {
1866 		return ret;
1867 	}
1868 	ret->CurrentConfig = &(ret->Config[0]);
1869 	ret->Abort = FALSE;
1870 	return ret;
1871 }
1872 
GSM_FreeStateMachine(GSM_StateMachine * s)1873 void GSM_FreeStateMachine(GSM_StateMachine *s)
1874 {
1875 	int i=0;
1876 
1877 	if (s == NULL) return;
1878 
1879 	/* Free allocated memory */
1880 	for (i = 0; i <= MAX_CONFIG_NUM; i++) {
1881 		free(s->Config[i].Device);
1882 		s->Config[i].Device = NULL;
1883 		free(s->Config[i].Connection);
1884 		s->Config[i].Connection = NULL;
1885 		free(s->Config[i].DebugFile);
1886 		s->Config[i].DebugFile = NULL;
1887 	}
1888 	free(s);
1889 	s = NULL;
1890 }
1891 
1892 
GSM_GetUsedConnection(GSM_StateMachine * s)1893 GSM_ConnectionType GSM_GetUsedConnection(GSM_StateMachine *s)
1894 {
1895 	return s->ConnectionType;
1896 }
1897 
GSM_GetModelInfo(GSM_StateMachine * s)1898 GSM_PhoneModel *GSM_GetModelInfo(GSM_StateMachine *s)
1899 {
1900 	return s->Phone.Data.ModelInfo;
1901 }
1902 
GSM_GetDebug(GSM_StateMachine * s)1903 GSM_Debug_Info *GSM_GetDebug(GSM_StateMachine *s)
1904 {
1905 	return s == NULL ? NULL : &(s->di);
1906 }
1907 
1908 
1909 /* How should editor hadle tabs in this file? Add editor commands here.
1910  * vim: noexpandtab sw=8 ts=8 sts=8:
1911  */
1912