"Fossies" - the Fresh Open Source Software Archive 
Member "gammu-1.42.0/libgammu/gsmstate.c" (3 Oct 2020, 51314 Bytes) of package /linux/privat/gammu-1.42.0.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "gsmstate.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.41.0_vs_1.42.0.
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 */
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
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
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
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 */
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 */
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 */
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 */
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
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 (¤t_time);
879 s->Phone.Functions->SetDateTime(s,¤t_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
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
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
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
985 gboolean GSM_IsConnected(GSM_StateMachine *s) {
986 return (s != NULL) && s->Phone.Functions != NULL && s->opened;
987 }
988
989 GSM_Error GSM_AbortOperation(GSM_StateMachine * s)
990 {
991 s->Abort = TRUE;
992 return ERR_NONE;
993 }
994
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
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
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
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
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
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
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
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
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
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
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
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
1425 int GSM_GetConfigNum(const GSM_StateMachine *s)
1426 {
1427 return s->ConfigNum;
1428 }
1429
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 */
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 */
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
1520 GSM_Error GSM_ReadCNMIParams(int out_params[5], const char *args)
1521 {
1522 return GSM_ReadParams(out_params, 5, args);
1523 }
1524
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
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
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
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
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 }
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
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
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
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
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
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
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
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
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
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
1893 GSM_ConnectionType GSM_GetUsedConnection(GSM_StateMachine *s)
1894 {
1895 return s->ConnectionType;
1896 }
1897
1898 GSM_PhoneModel *GSM_GetModelInfo(GSM_StateMachine *s)
1899 {
1900 return s->Phone.Data.ModelInfo;
1901 }
1902
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 */