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 (¤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
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