1 /*
2 
3   X G N O K I I
4 
5   A Linux/Unix GUI for the mobile phones.
6 
7   This file is part of gnokii.
8 
9   Gnokii is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13 
14   Gnokii is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with gnokii; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23   Copyright (C) 1999      Pavel Janik ml., Hugh Blemings
24   Copyright (C) 1999-2005 Jan Derfinak
25   Copyright (C) 2002-2004 Pawel Kot, BORBELY Zoltan
26   Copyright (C) 2002      Markus Plail, Manfred Jonsson, Pavel Machek
27   Copyright (C) 2003      Tomi Ollila, Uli Hopp
28 
29 */
30 
31 #include "config.h"
32 
33 #ifndef WIN32
34 #  include <unistd.h>
35 #endif
36 #include <pthread.h>
37 #include <string.h>
38 #include <glib.h>
39 #include "misc.h"
40 #include "gnokii.h"
41 #include "xgnokii_lowlevel.h"
42 #include "xgnokii.h"
43 #include "xgnokii_common.h"
44 
45 pthread_t monitor_th;
46 PhoneMonitor phoneMonitor;
47 pthread_mutex_t memoryMutex;
48 pthread_cond_t memoryCond;
49 pthread_mutex_t calendarMutex;
50 pthread_cond_t calendarCond;
51 pthread_mutex_t smsMutex;
52 pthread_mutex_t sendSMSMutex;
53 pthread_cond_t sendSMSCond;
54 pthread_mutex_t callMutex;
55 pthread_mutex_t netMonMutex;
56 pthread_mutex_t speedDialMutex;
57 pthread_cond_t speedDialCond;
58 pthread_mutex_t callerGroupMutex;
59 pthread_cond_t callerGroupCond;
60 pthread_mutex_t smsCenterMutex;
61 pthread_cond_t smsCenterCond;
62 pthread_mutex_t alarmMutex;
63 pthread_cond_t alarmCond;
64 pthread_mutex_t getBitmapMutex;
65 pthread_cond_t getBitmapCond;
66 pthread_mutex_t setBitmapMutex;
67 pthread_cond_t setBitmapCond;
68 pthread_mutex_t getNetworkInfoMutex;
69 pthread_cond_t getNetworkInfoCond;
70 pthread_mutex_t ringtoneMutex;
71 pthread_cond_t ringtoneCond;
72 static pthread_mutex_t eventsMutex;
73 static GSList *ScheduledEvents = NULL;
74 
75 gn_sms_status SMSStatus = {0,0,0,0};
76 gn_sms_folder_stats FolderStats[GN_SMS_FOLDER_MAX_NUMBER];
77 gn_sms_message_list MessagesList[GN_SMS_MESSAGE_MAX_NUMBER][GN_SMS_FOLDER_MAX_NUMBER];
78 
79 struct gn_statemachine *statemachine;
80 /* FIXME - don't really know what should own the statemachine in */
81 /* the xgnokii scheme of things - Chris */
82 int isSMSactivated = 0;
83 
84 
85 
GUI_InsertEvent(PhoneEvent * event)86 inline void GUI_InsertEvent(PhoneEvent * event)
87 {
88 	gn_log_xdebug("Inserting Event: %d\n", event->event);
89 	pthread_mutex_lock(&eventsMutex);
90 	ScheduledEvents = g_slist_prepend(ScheduledEvents, event);
91 	pthread_mutex_unlock(&eventsMutex);
92 }
93 
94 
RemoveEvent(void)95 inline static PhoneEvent *RemoveEvent(void)
96 {
97 	GSList *list;
98 	PhoneEvent *event = NULL;
99 
100 	pthread_mutex_lock(&eventsMutex);
101 	list = g_slist_last(ScheduledEvents);
102 	if (list) {
103 		event = (PhoneEvent *) list->data;
104 		ScheduledEvents = g_slist_remove_link(ScheduledEvents, list);
105 		g_slist_free_1(list);
106 	}
107 	pthread_mutex_unlock(&eventsMutex);
108 
109 	return (event);
110 }
111 
GUI_InitSMSFolders(void)112 gn_error GUI_InitSMSFolders(void)
113 {
114 	gn_data gdat;
115 	gn_error error;
116 	gn_sms_folder_list list;
117 	gint i;
118 
119 	gn_data_clear(&gdat);
120 	if (phoneMonitor.supported & PM_FOLDERS) {
121 
122 		gdat.sms_folder_list = &list;
123 
124 		if ((error = gn_sm_functions(GN_OP_GetSMSFolders, &gdat, statemachine)) != GN_ERR_NONE)
125 			return error;
126 		foldercount = gdat.sms_folder_list->number;
127 		for (i = 0; i < gdat.sms_folder_list->number; i++) {
128 			strcpy(folders[i], gdat.sms_folder_list->folder[i].name);
129 		}
130 	} else {
131 		foldercount = 2;
132 		strcpy(folders[0], "Inbox");
133 		strcpy(folders[1], "Outbox");
134 	}
135 	return GN_ERR_NONE;
136 }
137 
FreeElement(gpointer data,gpointer userData)138 static inline void FreeElement(gpointer data, gpointer userData)
139 {
140 	g_free((gn_sms *) data);
141 }
142 
FreeArray(GSList ** array)143 static inline void FreeArray(GSList ** array)
144 {
145 	if (*array) {
146 		g_slist_foreach(*array, FreeElement, NULL);
147 		g_slist_free(*array);
148 		*array = NULL;
149 	}
150 }
151 
InitModelInf(void)152 static gn_error InitModelInf(void)
153 {
154 	gint i, j;
155 
156 	phoneMonitor.phone.model = g_strdup(gn_lib_get_phone_model(statemachine));
157 	if (gn_lib_lasterror(statemachine) != GN_ERR_NONE)
158 		return gn_lib_lasterror(statemachine);
159 
160 	phoneMonitor.phone.product_name = g_strdup(gn_lib_get_phone_product_name(statemachine));
161 	phoneMonitor.phone.revision = g_strdup(gn_lib_get_phone_revision(statemachine));
162 	phoneMonitor.phone.imei = g_strdup(gn_lib_get_phone_imei(statemachine));
163 	phoneMonitor.supported = gn_phone_model_get(phoneMonitor.phone.product_name)->flags;
164 
165 	for (i = 0; i < GN_SMS_FOLDER_MAX_NUMBER; i++) {
166 		FolderStats[i].number = 0;
167 		FolderStats[i].changed = 0;
168 		FolderStats[i].unread = 0;
169 		FolderStats[i].used = 0;
170 		for (j = 0; j < GN_SMS_MESSAGE_MAX_NUMBER; j++) {
171 			MessagesList[j][i].status = GN_SMS_FLD_Old;
172 			MessagesList[j][i].location = 0;
173 			MessagesList[j][i].message_type = GN_SMS_MT_Deliver;
174 		}
175 	}
176 
177 	gn_log_xdebug("Model: %s\n", phoneMonitor.phone.model);
178 	gn_log_xdebug("Product: %s\n", phoneMonitor.phone.product_name);
179 	gn_log_xdebug("IMEI: %s\n", phoneMonitor.phone.imei);
180 	gn_log_xdebug("Revision: %s\n", phoneMonitor.phone.revision);
181 	return GN_ERR_NONE;
182 }
183 
184 
busterminate(void)185 static void busterminate(void)
186 {
187 	gn_lib_phone_close(statemachine);
188 	gn_lib_phoneprofile_free(&statemachine);
189 	gn_lib_library_free();
190 }
191 
fbusinit()192 static gn_error fbusinit()
193 {
194 	gn_error error;
195 
196 	error = gn_lib_phoneprofile_load(NULL, &statemachine);
197 	gn_log_xdebug("fbusinit: error %d\n", error);
198 
199 	if (error != GN_ERR_NONE) {
200 		g_print(_("GSM/FBUS init failed! (Unknown model?). Quitting.\n"));
201 		/* FIXME: should popup some message... */
202 		return (error);
203 	}
204 
205 	/* register cleanup function */
206 	atexit(busterminate);
207 
208 	error = gn_lib_phone_open(statemachine);
209 	if (error != GN_ERR_NONE) {
210 		g_print(_("Failed to open the phone. Quitting.\n"));
211 		return (error);
212 	}
213 
214 	return InitModelInf();
215 }
216 
217 
GUI_InitPhoneMonitor(void)218 void GUI_InitPhoneMonitor(void)
219 {
220 	phoneMonitor.phone.model = g_strdup(_("unknown"));
221 	phoneMonitor.phone.product_name = g_strdup(_("unknown"));
222 	phoneMonitor.phone.revision = g_strdup(_("unknown"));
223 	phoneMonitor.phone.imei = g_strdup(_("unknown"));
224 	phoneMonitor.supported = 0;
225 	phoneMonitor.rfLevel = phoneMonitor.batteryLevel = -1;
226 	phoneMonitor.powerSource = GN_PS_BATTERY;
227 	phoneMonitor.working = NULL;
228 	phoneMonitor.alarm = FALSE;
229 	phoneMonitor.sms.changed = phoneMonitor.sms.unRead = phoneMonitor.sms.number = 0;
230 	phoneMonitor.sms.messages = NULL;
231 	phoneMonitor.call.callInProgress = CS_Idle;
232 	*phoneMonitor.call.callNum = '\0';
233 	phoneMonitor.netmonitor.number = 0;
234 	*phoneMonitor.netmonitor.screen = *phoneMonitor.netmonitor.screen3 =
235 	    *phoneMonitor.netmonitor.screen4 = *phoneMonitor.netmonitor.screen5 = '\0';
236 	pthread_mutex_init(&memoryMutex, NULL);
237 	pthread_cond_init(&memoryCond, NULL);
238 	pthread_mutex_init(&calendarMutex, NULL);
239 	pthread_cond_init(&calendarCond, NULL);
240 	pthread_mutex_init(&smsMutex, NULL);
241 	pthread_mutex_init(&sendSMSMutex, NULL);
242 	pthread_cond_init(&sendSMSCond, NULL);
243 	pthread_mutex_init(&callMutex, NULL);
244 	pthread_mutex_init(&eventsMutex, NULL);
245 	pthread_mutex_init(&callMutex, NULL);
246 	pthread_mutex_init(&netMonMutex, NULL);
247 	pthread_mutex_init(&speedDialMutex, NULL);
248 	pthread_cond_init(&speedDialCond, NULL);
249 	pthread_mutex_init(&callerGroupMutex, NULL);
250 	pthread_cond_init(&callerGroupCond, NULL);
251 	pthread_mutex_init(&smsCenterMutex, NULL);
252 	pthread_cond_init(&smsCenterCond, NULL);
253 	pthread_mutex_init(&getBitmapMutex, NULL);
254 	pthread_cond_init(&getBitmapCond, NULL);
255 	pthread_mutex_init(&setBitmapMutex, NULL);
256 	pthread_cond_init(&setBitmapCond, NULL);
257 	pthread_mutex_init(&getNetworkInfoMutex, NULL);
258 	pthread_cond_init(&getNetworkInfoCond, NULL);
259 	pthread_mutex_init(&ringtoneMutex, NULL);
260 	pthread_cond_init(&ringtoneCond, NULL);
261 }
262 
compare_folder_and_number(const gn_sms * a,const gn_sms * b)263 static gint compare_folder_and_number(const gn_sms *a, const gn_sms *b)
264 {
265 	gn_log_xdebug("memory type a: %i memory type b: %i\n", a->memory_type, b->memory_type);
266 	gn_log_xdebug("message number a: %i message number b: %i\n", a->number, b->number);
267 	if (a->memory_type == b->memory_type)
268 		if (a->number == b->number)
269 			return 0;
270 		else
271 			return 1;
272 	else
273 		return 1;
274 }
275 
276 
RefreshSMS(const gint number)277 static void RefreshSMS(const gint number)
278 {
279 	gn_data gdat;
280 	gn_error error;
281 	gn_sms *msg, *tmp_msg;
282 	gn_sms_folder *fld;
283 	gn_sms_folder_list *list;
284 	gn_sms_raw *raw;
285 	GSList *tmp_list;
286 	gint i, j, dummy;
287 
288 	gn_log_xdebug("RefreshSMS is running...\n");
289 
290 	gn_data_clear(&gdat);
291 
292 	gn_log_xdebug("RefreshSMS: changed: %i\n", SMSStatus.changed);
293 	gn_log_xdebug("RefreshSMS: unread: %i, total: %i\n", SMSStatus.unread,
294 		SMSStatus.number);
295 	for (i = 0; i < SMSStatus.folders_count; i++) {
296 		dummy = 0;
297 		for (j = 0; j < FolderStats[i].used; j++) {
298 			if ((MessagesList[j][i].status == GN_SMS_FLD_Changed) ||
299 			    (MessagesList[j][i].status == GN_SMS_FLD_NotRead) ||
300 			    (MessagesList[j][i].status == GN_SMS_FLD_New))
301 				gn_log_xdebug("RefreshSMS: change #%i in folder %i at location %i!\n",
302 					++dummy, i, MessagesList[j][i].location);
303 		}
304 	}
305 	if (phoneMonitor.supported & PM_FOLDERS) {
306 
307 		for (i = 0; i < SMSStatus.folders_count; i++) {
308 			for (j = 0; j < FolderStats[i].used; j++) {
309 				if (MessagesList[j][i].status == GN_SMS_FLD_Deleted ||
310 				    MessagesList[j][i].status == GN_SMS_FLD_Changed) {
311 					gn_log_xdebug("We got a deleted message here to handle!\n");
312 					pthread_mutex_lock(&smsMutex);
313 					msg = g_malloc0(sizeof(gn_sms));
314 
315 /* 0 + 12 = GN_MT_IN, 1 + 12 = GN_MT_OU ... => gsm-common.h definition of gn_memory_type */
316 					msg->memory_type = i + 12;
317 					msg->number = MessagesList[j][i].location;
318 					tmp_list =
319 					    g_slist_find_custom(phoneMonitor.sms.messages, msg,
320 								(GCompareFunc) compare_folder_and_number);
321 					tmp_msg = (gn_sms *) tmp_list->data;
322 					phoneMonitor.sms.messages =
323 					    g_slist_remove(phoneMonitor.sms.messages, tmp_msg);
324 					g_free(tmp_msg);
325 					pthread_mutex_unlock(&smsMutex);
326 					if (MessagesList[j][i].status == GN_SMS_FLD_Deleted)
327 						MessagesList[j][i].status = GN_SMS_FLD_ToBeRemoved;	/* FreeDeletedMessages has to find it */
328 				}
329 				if (MessagesList[j][i].status == GN_SMS_FLD_New ||
330 				    MessagesList[j][i].status == GN_SMS_FLD_NotRead ||
331 				    MessagesList[j][i].status == GN_SMS_FLD_Changed) {
332 					msg = g_malloc0(sizeof(gn_sms));
333 					list = g_malloc(sizeof(gn_sms_folder_list));
334 					raw = g_malloc(sizeof(gn_sms_raw));
335 					gdat.sms = msg;
336 					gdat.sms_folder = NULL;
337 					gdat.sms_folder_list = list;
338 					gdat.raw_sms = raw;
339 
340 					gdat.sms->number = MessagesList[j][i].location;
341 					gdat.sms->memory_type =(gn_memory_type) i + 12;
342 					gn_log_xdebug("#: %i, mt: %i\n", gdat.sms->number, gdat.sms->memory_type);
343 					if ((error = gn_sms_get_no_validate(&gdat, statemachine)) == GN_ERR_NONE) {
344 						gn_log_xdebug("Found valid SMS ...\n %s\n",
345 							msg->user_data[0].u.text);
346 						pthread_mutex_lock(&smsMutex);
347 						phoneMonitor.sms.messages =
348 						    g_slist_append(phoneMonitor.sms.messages, msg);
349 						pthread_mutex_unlock(&smsMutex);
350 					}
351 					if (MessagesList[j][i].status == GN_SMS_FLD_New ||
352 					    MessagesList[j][i].status == GN_SMS_FLD_Changed)
353 						MessagesList[j][i].status = GN_SMS_FLD_Old;
354 					if (MessagesList[j][i].status == GN_SMS_FLD_NotRead)
355 						MessagesList[j][i].status = GN_SMS_FLD_NotReadHandled;
356 				}
357 			}
358 			FolderStats[i].changed = 0;	/* now we handled the changes and can reset */
359 		}
360 		SMSStatus.changed = 0;	/* now we handled the changes and can reset */
361 
362 	} else {
363 		pthread_mutex_lock(&smsMutex);
364 		FreeArray(&(phoneMonitor.sms.messages));
365 		phoneMonitor.sms.number = 0;
366 		pthread_mutex_unlock(&smsMutex);
367 
368 		fld = g_malloc(sizeof(gn_sms_folder));
369 		list = g_malloc(sizeof(gn_sms_folder_list));
370 		gdat.sms_folder = fld;
371 		gdat.sms_folder_list = list;
372 
373 		i = 0;
374 		while (1) {
375 			i++;
376 			msg = g_malloc0(sizeof(gn_sms));
377 
378 			msg->memory_type = GN_MT_SM;
379 			msg->number = i;
380 
381 			gdat.sms = msg;
382 			if ((error = gn_sms_get(&gdat, statemachine)) == GN_ERR_NONE) {
383 				gn_log_xdebug("Found valid SMS ...\n");
384 				pthread_mutex_lock(&smsMutex);
385 				phoneMonitor.sms.messages =
386 				    g_slist_append(phoneMonitor.sms.messages, msg);
387 				phoneMonitor.sms.number++;
388 				pthread_mutex_unlock(&smsMutex);
389 				if (phoneMonitor.sms.number == number) {
390 					g_free(list);
391 					g_free(fld);
392 					break;
393 				}
394 			} else if (error == GN_ERR_INVALIDLOCATION) {
395 				/* All positions are read */
396 				g_free(list);
397 				g_free(fld);
398 				g_free(msg);
399 				break;
400 			} else if (error == GN_ERR_INVALIDMEMORYTYPE) {
401 				/* We have some misconfiguration: phone doesn't handle
402 				   neither folders nor SIM */
403 				fprintf(stderr, _("Misconfiguration detected: phone handles neither folders nor sim.\n"
404 						  "Contact gnokii developers to fix the issue.\n"));
405 				break;
406 			} else {
407 				g_free(msg);
408 				usleep(750000);
409 			}
410 		}
411 	}
412 }
413 
A_GetMemoryStatus(gpointer data)414 static gint A_GetMemoryStatus(gpointer data)
415 {
416 	gn_error error = GN_ERR_UNKNOWN;
417 	D_MemoryStatus *ms = (D_MemoryStatus *) data;
418 	gn_data gdat;
419 
420 	if (!ms)
421 		return error;
422 
423 	gn_data_clear(&gdat);
424 
425 	pthread_mutex_lock(&memoryMutex);
426 	gdat.memory_status = &(ms->memoryStatus);
427 	error = ms->status = gn_sm_functions(GN_OP_GetMemoryStatus, &gdat, statemachine);
428 	pthread_cond_signal(&memoryCond);
429 	pthread_mutex_unlock(&memoryMutex);
430 
431 	return (error);
432 }
433 
434 
A_GetMemoryLocation(gpointer data)435 static gint A_GetMemoryLocation(gpointer data)
436 {
437 	gn_error error = GN_ERR_UNKNOWN;
438 	D_MemoryLocation *ml = (D_MemoryLocation *) data;
439 	gn_data gdat;
440 
441 	if (!ml)
442 		return error;
443 
444 	gn_data_clear(&gdat);
445 
446 	pthread_mutex_lock(&memoryMutex);
447 	gdat.phonebook_entry = (ml->entry);
448 	error = ml->status = gn_sm_functions(GN_OP_ReadPhonebook, &gdat, statemachine);
449 	pthread_cond_signal(&memoryCond);
450 	pthread_mutex_unlock(&memoryMutex);
451 
452 	return (error);
453 }
454 
455 
A_GetMemoryLocationAll(gpointer data)456 static gint A_GetMemoryLocationAll(gpointer data)
457 {
458 	gn_phonebook_entry entry;
459 	gn_error error;
460 	D_MemoryLocationAll *mla = (D_MemoryLocationAll *)data;
461 	register gint i, j, read = 0;
462 	gn_data gdat;
463 
464 	gn_data_clear(&gdat);
465 
466 	error = mla->status = GN_ERR_NONE;
467 	gdat.phonebook_entry = &entry;
468 
469 	pthread_mutex_lock(&memoryMutex);
470 	for (i = mla->min; i <= mla->max; i++) {
471 		memset(&entry, 0, sizeof(entry));
472 		entry.memory_type = mla->type;
473 		entry.location = i;
474 		error = gn_sm_functions(GN_OP_ReadPhonebook, &gdat, statemachine);
475 		if (error != GN_ERR_NONE && error != GN_ERR_INVALIDLOCATION &&
476 		    error != GN_ERR_EMPTYLOCATION && error != GN_ERR_INVALIDMEMORYTYPE) {
477 			gint err_count = 0;
478 
479 			while (error != GN_ERR_NONE) {
480 				g_print(_
481 					("%s: line %d: Can't get memory entry number %d from memory %d! %d\n"),
482 					__FILE__, __LINE__, i, entry.memory_type, error);
483 				if (err_count++ > 3) {
484 					mla->ReadFailed(i);
485 					mla->status = error;
486 					pthread_cond_signal(&memoryCond);
487 					pthread_mutex_unlock(&memoryMutex);
488 					return (error);
489 				}
490 				error = gn_sm_functions(GN_OP_ReadPhonebook, &gdat, statemachine);
491 				sleep(2);
492 			}
493 		} else {
494 			if (error == GN_ERR_INVALIDMEMORYTYPE) {
495 
496 		/* If the memory type was invalid - just fill up the rest */
497 		/* (Markus) */
498 
499 				entry.empty = true;
500 				entry.name[0] = 0;
501 				entry.number[0] = 0;
502 				for (j = mla->min; j <= mla->max; j++) error = mla->InsertEntry(&entry);
503 				pthread_cond_signal(&memoryCond);
504 				pthread_mutex_unlock(&memoryMutex);
505 				return GN_ERR_NONE;
506 			}
507 		}
508 		if ((error == GN_ERR_NONE) && (entry.empty == false)) read++;
509 		gn_log_xdebug("Name: %s\n", entry.name);
510 		error = mla->InsertEntry(&entry);
511 		/* FIXME: It only works this way at the moment */
512 		/*		if (error != GN_ERR_NONE)
513 				break;*/
514 		if (read == mla->used) {
515 			mla->status = error;
516 			entry.empty = true;
517 			entry.name[0] = 0;
518 			entry.number[0] = 0;
519 			for (j = i + 1; j <= mla->max; j++) error = mla->InsertEntry(&entry);
520 			pthread_cond_signal(&memoryCond);
521 			pthread_mutex_unlock(&memoryMutex);
522 			return GN_ERR_NONE;
523 		}
524 
525 	}
526 	mla->status = error;
527 	pthread_cond_signal(&memoryCond);
528 	pthread_mutex_unlock(&memoryMutex);
529 	return (error);
530 }
531 
532 
A_WriteMemoryLocation(gpointer data)533 static gint A_WriteMemoryLocation(gpointer data)
534 {
535 	gn_error error;
536 	D_MemoryLocation *ml = (D_MemoryLocation *) data;
537 	gn_data gdat;
538 
539 	if (!data) return GN_ERR_INTERNALERROR;
540 
541 	gn_data_clear(&gdat);
542 
543 	error = ml->status = GN_ERR_UNKNOWN;
544 
545 	if (ml->entry) {
546 		gn_phonebook_entry_sanitize(ml->entry);
547 		gdat.phonebook_entry = (ml->entry);
548 		pthread_mutex_lock(&memoryMutex);
549 		error = ml->status = gn_sm_functions(GN_OP_WritePhonebook, &gdat, statemachine);
550 		pthread_cond_signal(&memoryCond);
551 		pthread_mutex_unlock(&memoryMutex);
552 	}
553 
554 	return (error);
555 }
556 
A_WriteMemoryLocationAll(gpointer data)557 static gint A_WriteMemoryLocationAll(gpointer data)
558 {
559 	gn_error error;
560 	D_MemoryLocationAll *mla = (D_MemoryLocationAll *) data;
561 	gn_data gdat;
562 
563 	gn_data_clear(&gdat);
564 
565 	error = mla->status = GN_ERR_UNKNOWN;
566 
567 	return error;
568 }
569 
570 
A_DeleteMemoryLocation(gpointer data)571 static gint A_DeleteMemoryLocation(gpointer data)
572 {
573 	gn_error error = GN_ERR_UNKNOWN;
574 	D_MemoryLocation *ml = (D_MemoryLocation *) data;
575 	gn_data gdat;
576 
577 	if (!ml)
578 		return GN_ERR_INTERNALERROR;
579 
580 	gn_data_clear(&gdat);
581 
582 	error = ml->status = GN_ERR_UNKNOWN;
583 
584 	if (ml->entry) {
585 		gn_phonebook_entry_sanitize(ml->entry);
586 		gdat.phonebook_entry = (ml->entry);
587 		pthread_mutex_lock(&memoryMutex);
588 		error = ml->status = gn_sm_functions(GN_OP_DeletePhonebook, &gdat, statemachine);
589 		pthread_cond_signal(&memoryCond);
590 		pthread_mutex_unlock(&memoryMutex);
591 	}
592 
593 	return (error);
594 }
595 
A_GetCalendarNote(gpointer data)596 static gint A_GetCalendarNote(gpointer data)
597 {
598 	gn_error error = GN_ERR_UNKNOWN;
599 	D_CalendarNote *cn = (D_CalendarNote *) data;
600 	gn_data gdat;
601 
602 	if (!cn)
603 		return error;
604 
605 	gn_data_clear(&gdat);
606 
607 	pthread_mutex_lock(&calendarMutex);
608 	gdat.calnote = cn->entry;
609 	error = cn->status = gn_sm_functions(GN_OP_GetCalendarNote, &gdat, statemachine);
610 	pthread_cond_signal(&calendarCond);
611 	pthread_mutex_unlock(&calendarMutex);
612 
613 	return (error);
614 }
615 
616 
A_GetCalendarNoteAll(gpointer data)617 static gint A_GetCalendarNoteAll(gpointer data)
618 {
619 	gn_calnote_list list;
620 	gn_calnote entry;
621 	D_CalendarNoteAll *cna = (D_CalendarNoteAll *) data;
622 	gn_error error;
623 	register gint i = 1;
624 	gn_data gdat;
625 
626 	gn_data_clear(&gdat);
627 
628 	memset(&entry, 0, sizeof(entry));
629 	memset(&list, 0, sizeof(list));
630 
631 	pthread_mutex_lock(&calendarMutex);
632 	while (1) {
633 		entry.location = i;
634 
635 		gdat.calnote = &entry;
636 		gdat.calnote_list = &list;
637 		if ((error = gn_sm_functions(GN_OP_GetCalendarNote, &gdat, statemachine)) != GN_ERR_NONE)
638 			break;
639 		/* This is necessary for phones with calendar notes index (7110/6510) */
640 		entry.location = i++;
641 		if (cna->InsertEntry(&entry) != GN_ERR_NONE)
642 			break;
643 	}
644 
645 	pthread_mutex_unlock(&calendarMutex);
646 	g_free(cna);
647 	if (error == GN_ERR_INVALIDLOCATION)
648 		return GN_ERR_NONE;
649 	else
650 		return error;
651 }
652 
653 
A_WriteCalendarNote(gpointer data)654 static gint A_WriteCalendarNote(gpointer data)
655 {
656 	gn_error error = GN_ERR_UNKNOWN;
657 	D_CalendarNote *cn = (D_CalendarNote *) data;
658 	gn_data gdat;
659 
660 	if (!cn)
661 		return error;
662 
663 	gn_data_clear(&gdat);
664 
665 	pthread_mutex_lock(&calendarMutex);
666 	gdat.calnote = cn->entry;
667 	error = cn->status = gn_sm_functions(GN_OP_WriteCalendarNote, &gdat, statemachine);
668 	pthread_cond_signal(&calendarCond);
669 	pthread_mutex_unlock(&calendarMutex);
670 
671 	return (error);
672 }
673 
674 
A_DeleteCalendarNote(gpointer data)675 static gint A_DeleteCalendarNote(gpointer data)
676 {
677 	gn_calnote *note = (gn_calnote *) data;
678 	gn_error error = GN_ERR_UNKNOWN;
679 	gn_data gdat;
680 
681 	gn_data_clear(&gdat);
682 
683 	if (note) {
684 		gdat.calnote = note;
685 		error = gn_sm_functions(GN_OP_DeleteCalendarNote, &gdat, statemachine);
686 		g_free(note);
687 	}
688 
689 	return (error);
690 }
691 
A_GetCallerGroup(gpointer data)692 static gint A_GetCallerGroup(gpointer data)
693 {
694 	gn_bmp bitmap;
695 	gn_error error = GN_ERR_UNKNOWN;
696 	D_CallerGroup *cg = (D_CallerGroup *) data;
697 	gn_data gdat;
698 
699 	if (!cg)
700 		return error;
701 
702 	gn_data_clear(&gdat);
703 
704 	bitmap.type = GN_BMP_CallerLogo;
705 	bitmap.number = cg->number;
706 	pthread_mutex_lock(&callerGroupMutex);
707 	gdat.bitmap = &bitmap;
708 	error = cg->status = gn_sm_functions(GN_OP_GetBitmap, &gdat, statemachine);
709 	snprintf(cg->text, sizeof(cg->text), "%s", bitmap.text);
710 	pthread_cond_signal(&callerGroupCond);
711 	pthread_mutex_unlock(&callerGroupMutex);
712 
713 	return (error);
714 }
715 
716 
A_SendCallerGroup(gpointer data)717 static gint A_SendCallerGroup(gpointer data)
718 {
719 	gn_bmp bitmap;
720 	D_CallerGroup *cg = (D_CallerGroup *) data;
721 	gn_error error;
722 	gn_data gdat;
723 
724 	if (!cg)
725 		return GN_ERR_UNKNOWN;
726 
727 	gn_data_clear(&gdat);
728 
729 	bitmap.type = GN_BMP_CallerLogo;
730 	bitmap.number = cg->number;
731 	gdat.bitmap = &bitmap;
732 	if ((error = gn_sm_functions(GN_OP_GetBitmap, &gdat, statemachine)) != GN_ERR_NONE) {
733 		g_free(cg);
734 		return (error);
735 	}
736 	strncpy(bitmap.text, cg->text, 256);
737 	bitmap.text[255] = '\0';
738 	g_free(cg);
739 	return (gn_sm_functions(GN_OP_SetBitmap, &gdat, statemachine));
740 }
741 
742 
A_GetSMSCenter(gpointer data)743 static gint A_GetSMSCenter(gpointer data)
744 {
745 	D_SMSCenter *c = (D_SMSCenter *) data;
746 	gn_error error = GN_ERR_UNKNOWN;
747 	gn_data gdat;
748 
749 	if (!c)
750 		return error;
751 
752 	gn_data_clear(&gdat);
753 
754 	pthread_mutex_lock(&smsCenterMutex);
755 	gdat.message_center = c->center;
756 	error = c->status = gn_sm_functions(GN_OP_GetSMSCenter, &gdat, statemachine);
757 	pthread_cond_signal(&smsCenterCond);
758 	pthread_mutex_unlock(&smsCenterMutex);
759 
760 	return (error);
761 }
762 
763 
A_SetSMSCenter(gpointer data)764 static gint A_SetSMSCenter(gpointer data)
765 {
766 	D_SMSCenter *smsc = (D_SMSCenter *) data;
767 	gn_error error = GN_ERR_UNKNOWN;
768 	gn_data gdat;
769 
770 	if (!smsc)
771 		return error;
772 
773 	gn_data_clear(&gdat);
774 
775 	gdat.message_center = smsc->center;
776 	pthread_mutex_lock(&smsCenterMutex);
777 	error = smsc->status = gn_sm_functions(GN_OP_GetSMSCenter, &gdat, statemachine);
778 	g_free(smsc);
779 	pthread_cond_signal(&smsCenterCond);
780 	pthread_mutex_unlock(&smsCenterMutex);
781 
782 	return (error);
783 }
784 
785 
A_SendSMSMessage(gpointer data)786 static gint A_SendSMSMessage(gpointer data)
787 {
788 	D_SMSMessage *d = (D_SMSMessage *) data;
789 	gn_error error = GN_ERR_UNKNOWN;
790 	gn_data gdat;
791 
792 	if (!d)
793 		return error;
794 
795 	gn_data_clear(&gdat);
796 
797 	gdat.sms = d->sms;
798 	pthread_mutex_lock(&sendSMSMutex);
799 	error = d->status = gn_sms_send(&gdat, statemachine);
800 	/* we do not use sms reference numbers in xgnokii */
801 	free(gdat.sms->reference);
802 	pthread_cond_signal(&sendSMSCond);
803 	pthread_mutex_unlock(&sendSMSMutex);
804 
805 	return (error);
806 }
807 
808 
A_DeleteSMSMessage(gpointer data)809 static gint A_DeleteSMSMessage(gpointer data)
810 {
811 	gn_sms *sms = (gn_sms *) data;
812 	gn_error error = GN_ERR_UNKNOWN;
813 	gn_data gdat;
814 
815 	gn_data_clear(&gdat);
816 
817 	if (sms) {
818 		gdat.sms = sms;
819 		if (phoneMonitor.supported & PM_FOLDERS)
820 			error = gn_sms_delete_no_validate(&gdat, statemachine);
821 		else
822 			error = gn_sms_delete(&gdat, statemachine);
823 		g_free(sms);
824 	}
825 	return (error);
826 }
827 
828 
A_GetSpeedDial(gpointer data)829 static gint A_GetSpeedDial(gpointer data)
830 {
831 	D_SpeedDial *d = (D_SpeedDial *) data;
832 	gn_error error = GN_ERR_UNKNOWN;
833 	gn_data gdat;
834 
835 	if (!d)
836 		return error;
837 
838 	gn_data_clear(&gdat);
839 
840 	gdat.speed_dial = &d->entry;
841 	pthread_mutex_lock(&speedDialMutex);
842 	error = d->status = gn_sm_functions(GN_OP_GetSpeedDial, &gdat, statemachine);
843 	pthread_cond_signal(&speedDialCond);
844 	pthread_mutex_unlock(&speedDialMutex);
845 
846 	return (error);
847 }
848 
849 
A_SendSpeedDial(gpointer data)850 static gint A_SendSpeedDial(gpointer data)
851 {
852 	D_SpeedDial *d = (D_SpeedDial *) data;
853 	gn_error error = GN_ERR_UNKNOWN;
854 	gn_data gdat;
855 
856 	if (!d)
857 		return error;
858 
859 	gn_data_clear(&gdat);
860 
861 	gdat.speed_dial = &d->entry;
862 	pthread_mutex_lock(&speedDialMutex);
863 	error = d->status = gn_sm_functions(GN_OP_SetSpeedDial, &gdat, statemachine);
864 	pthread_cond_signal(&speedDialCond);
865 	pthread_mutex_unlock(&speedDialMutex);
866 
867 	return (error);
868 }
869 
870 
A_SendDTMF(gpointer data)871 static gint A_SendDTMF(gpointer data)
872 {
873 	gchar *buf = (gchar *) data;
874 	gn_error error = GN_ERR_UNKNOWN;
875 	gn_data gdat;
876 
877 	gn_data_clear(&gdat);
878 
879 	if (buf) {
880 		gdat.dtmf_string = buf;
881 		error = gn_sm_functions(GN_OP_SendDTMF, &gdat, statemachine);
882 		gdat.dtmf_string = NULL;
883 		g_free(buf);
884 	}
885 
886 	return (error);
887 }
888 
889 
A_NetMonOnOff(gpointer data)890 static gint A_NetMonOnOff(gpointer data)
891 {
892 	gint mode = GPOINTER_TO_INT(data);
893 	gn_netmonitor nm;
894 	gn_data gdat;
895 
896 	gn_data_clear(&gdat);
897 
898 	gdat.netmonitor = &nm;
899 	if (mode)
900 		nm.field = 0xf3;
901 	else
902 		nm.field = 0xf1;
903 	return gn_sm_functions(GN_OP_NetMonitor, &gdat, statemachine);
904 }
905 
906 
A_NetMonitor(gpointer data)907 static gint A_NetMonitor(gpointer data)
908 {
909 	gint number = GPOINTER_TO_INT(data);
910 
911 	if (data == 0)
912 		phoneMonitor.netmonitor.number = 0;
913 	else
914 		phoneMonitor.netmonitor.number = number;
915 
916 	return (0);
917 }
918 
919 
A_DialVoice(gpointer data)920 static gint A_DialVoice(gpointer data)
921 {
922 	gchar *number = (gchar *) data;
923 	gn_error error;
924 	gn_call_info CallInfo;
925 	int CallId;
926 	gn_data gdat;
927 
928 	gn_data_clear(&gdat);
929 
930 	if (!number) return GN_ERR_UNKNOWN;
931 
932 	memset(&CallInfo, 0, sizeof(CallInfo));
933 	snprintf(CallInfo.number, sizeof(CallInfo.number), "%s", number);
934 	CallInfo.type = GN_CALL_Voice;
935 	CallInfo.send_number = GN_CALL_Default;
936 	g_free(number);
937 
938 	gdat.call_info = &CallInfo;
939 	error = gn_call_dial(&CallId, &gdat, statemachine);
940 	gdat.call_info = NULL;
941 
942 	return (error);
943 }
944 
945 
A_GetAlarm(gpointer data)946 static gint A_GetAlarm(gpointer data)
947 {
948 	D_Alarm *a = (D_Alarm *) data;
949 	gn_error error;
950 	gn_data gdat;
951 
952 	gn_data_clear(&gdat);
953 
954 	error = GN_ERR_UNKNOWN;
955 
956 	if (a) {
957 		a->status = GN_ERR_UNKNOWN;
958 		pthread_mutex_lock(&alarmMutex);
959 		gdat.datetime = &a->alarm.timestamp;
960 		gdat.alarm = &a->alarm;
961 		error = a->status = gn_sm_functions(GN_OP_GetAlarm, &gdat, statemachine);
962 		pthread_cond_signal(&alarmCond);
963 		pthread_mutex_unlock(&alarmMutex);
964 	}
965 
966 	return (error);
967 }
968 
969 
A_SetAlarm(gpointer data)970 static gint A_SetAlarm(gpointer data)
971 {
972 	D_Alarm *a = (D_Alarm *) data;
973 	gn_error error = GN_ERR_UNKNOWN;
974 	gn_data gdat;
975 
976 	if (!a)
977 		return GN_ERR_UNKNOWN;
978 
979 	gn_data_clear(&gdat);
980 
981 	gdat.alarm = &a->alarm;
982 	error = a->status = gn_sm_functions(GN_OP_SetAlarm, &gdat, statemachine);
983 	g_free(a);
984 
985 	return (error);
986 }
987 
988 
A_PressKey(gpointer data)989 static gint A_PressKey(gpointer data)
990 {
991 	gn_data gdat;
992 
993 	gn_data_clear(&gdat);
994 	gdat.key_code = GPOINTER_TO_INT(data);
995 
996 	return gn_sm_functions(GN_OP_PressPhoneKey, &gdat, statemachine);
997 }
998 
A_ReleaseKey(gpointer data)999 static gint A_ReleaseKey(gpointer data)
1000 {
1001 	gn_data gdat;
1002 
1003 	gn_data_clear(&gdat);
1004 	gdat.key_code = GPOINTER_TO_INT(data);
1005 
1006 	return gn_sm_functions(GN_OP_ReleasePhoneKey, &gdat, statemachine);
1007 }
1008 
A_GetBitmap(gpointer data)1009 static gint A_GetBitmap(gpointer data)
1010 {
1011 	gn_error error;
1012 	D_Bitmap *d = (D_Bitmap *) data;
1013 	gn_data gdat;
1014 
1015 	gn_data_clear(&gdat);
1016 
1017 	pthread_mutex_lock(&getBitmapMutex);
1018 	gdat.bitmap = d->bitmap;
1019 	error = d->status = gn_sm_functions(GN_OP_GetBitmap, &gdat, statemachine);
1020 	pthread_cond_signal(&getBitmapCond);
1021 	pthread_mutex_unlock(&getBitmapMutex);
1022 	return error;
1023 }
1024 
A_SetBitmap(gpointer data)1025 static gint A_SetBitmap(gpointer data)
1026 {
1027 	gn_error error;
1028 	D_Bitmap *d = (D_Bitmap *) data;
1029 	gn_bmp bitmap;
1030 	gn_data gdat;
1031 
1032 	gn_data_clear(&gdat);
1033 
1034 	pthread_mutex_lock(&setBitmapMutex);
1035 	if (d->bitmap->type == GN_BMP_CallerLogo) {
1036 		bitmap.type = d->bitmap->type;
1037 		bitmap.number = d->bitmap->number;
1038 		gdat.bitmap = &bitmap;
1039 		error = d->status = gn_sm_functions(GN_OP_GetBitmap, &gdat, statemachine);
1040 		if (error == GN_ERR_NONE) {
1041 			strncpy(d->bitmap->text, bitmap.text, sizeof(bitmap.text));
1042 			d->bitmap->ringtone = bitmap.ringtone;
1043 			gdat.bitmap = d->bitmap;
1044 			error = d->status = gn_sm_functions(GN_OP_SetBitmap, &gdat, statemachine);
1045 		}
1046 	} else {
1047 		gdat.bitmap = d->bitmap;
1048 		error = d->status = gn_sm_functions(GN_OP_SetBitmap, &gdat, statemachine);
1049 	}
1050 	pthread_cond_signal(&setBitmapCond);
1051 	pthread_mutex_unlock(&setBitmapMutex);
1052 	return error;
1053 }
1054 
A_GetNetworkInfo(gpointer data)1055 static gint A_GetNetworkInfo(gpointer data)
1056 {
1057 	gn_error error;
1058 	D_NetworkInfo *d = (D_NetworkInfo *) data;
1059 	gn_data gdat;
1060 
1061 	gn_data_clear(&gdat);
1062 
1063 	pthread_mutex_lock(&getNetworkInfoMutex);
1064 	gdat.network_info = d->info;
1065 	gdat.reg_notification = NULL;
1066 	gdat.callback_data = NULL;
1067 	error = d->status = gn_sm_functions(GN_OP_GetNetworkInfo, &gdat, statemachine);
1068 	pthread_cond_signal(&getNetworkInfoCond);
1069 	pthread_mutex_unlock(&getNetworkInfoMutex);
1070 	return error;
1071 }
1072 
A_PlayTone(gpointer data)1073 static gint A_PlayTone(gpointer data)
1074 {
1075 	D_PlayTone *d = (D_PlayTone *) data;
1076 	gn_tone tone;
1077 	gn_data gdat;
1078 	gn_error error;
1079 	static int uadj = -1;
1080 
1081 	gn_data_clear(&gdat);
1082 
1083 	pthread_mutex_lock(&ringtoneMutex);
1084 	tone.frequency = d->frequency;
1085 	tone.volume = d->volume;
1086 	gdat.tone = &tone;
1087 
1088 	if (uadj < 0) {
1089 		struct timeval t1, t2, dt;
1090 
1091 		gettimeofday(&t1, NULL);
1092 		error = gn_sm_functions(GN_OP_PlayTone, &gdat, statemachine);
1093 		gettimeofday(&t2, NULL);
1094 		timersub(&t2, &t1, &dt);
1095 		uadj = 2 * dt.tv_usec;
1096 	} else {
1097 		error = gn_sm_functions(GN_OP_PlayTone, &gdat, statemachine);
1098 	}
1099 	if (d->usec > 0) {
1100 		if (d->usec > uadj) usleep(d->usec - uadj);
1101 		tone.frequency = 0;
1102 		tone.volume = 0;
1103 		gn_sm_functions(GN_OP_PlayTone, &gdat, statemachine);
1104 	}
1105 
1106 	pthread_cond_signal(&ringtoneCond);
1107 	pthread_mutex_unlock(&ringtoneMutex);
1108 
1109 	return error;
1110 }
1111 
A_GetRingtone(gpointer data)1112 static gint A_GetRingtone(gpointer data)
1113 {
1114 	D_Ringtone *d = (D_Ringtone *) data;
1115 	gn_data gdat;
1116 
1117 	gn_data_clear(&gdat);
1118 
1119 	pthread_mutex_lock(&ringtoneMutex);
1120 	gdat.ringtone = d->ringtone;
1121 
1122 	d->status = gn_sm_functions(GN_OP_GetRingtone, &gdat, statemachine);
1123 
1124 	pthread_cond_signal(&ringtoneCond);
1125 	pthread_mutex_unlock(&ringtoneMutex);
1126 
1127 	return d->status;
1128 }
1129 
A_SetRingtone(gpointer data)1130 static gint A_SetRingtone(gpointer data)
1131 {
1132 	D_Ringtone *d = (D_Ringtone *) data;
1133 	gn_data gdat;
1134 
1135 	gn_data_clear(&gdat);
1136 
1137 	pthread_mutex_lock(&ringtoneMutex);
1138 	gdat.ringtone = d->ringtone;
1139 
1140 	d->status = gn_sm_functions(GN_OP_SetRingtone, &gdat, statemachine);
1141 
1142 	pthread_cond_signal(&ringtoneCond);
1143 	pthread_mutex_unlock(&ringtoneMutex);
1144 
1145 	return d->status;
1146 }
1147 
A_DeleteRingtone(gpointer data)1148 static gint A_DeleteRingtone(gpointer data)
1149 {
1150 	D_Ringtone *d = (D_Ringtone *) data;
1151 	gn_data gdat;
1152 
1153 	gn_data_clear(&gdat);
1154 
1155 	pthread_mutex_lock(&ringtoneMutex);
1156 	gdat.ringtone = d->ringtone;
1157 
1158 	d->status = gn_sm_functions(GN_OP_DeleteRingtone, &gdat, statemachine);
1159 
1160 	pthread_cond_signal(&ringtoneCond);
1161 	pthread_mutex_unlock(&ringtoneMutex);
1162 
1163 	return d->status;
1164 }
1165 
A_GetRingtoneList(gpointer data)1166 static gint A_GetRingtoneList(gpointer data)
1167 {
1168 	gn_ringtone_list *d = (gn_ringtone_list *) data;
1169 	gn_data gdat;
1170 
1171 	gn_data_clear(&gdat);
1172 
1173 	pthread_mutex_lock(&ringtoneMutex);
1174 	gdat.ringtone_list = d;
1175 
1176 	if (gn_sm_functions(GN_OP_GetRingtoneList, &gdat, statemachine) != GN_ERR_NONE) {
1177 		d->count = 0;
1178 		d->userdef_location = 0;
1179 		d->userdef_count = 0;
1180 	}
1181 
1182 	pthread_cond_signal(&ringtoneCond);
1183 	pthread_mutex_unlock(&ringtoneMutex);
1184 
1185 	return GN_ERR_NONE;
1186 }
1187 
A_Exit(gpointer data)1188 static gint A_Exit(gpointer data)
1189 {
1190 	pthread_exit(0);
1191 	return (0);		/* just to be proper */
1192 }
1193 
1194 gint(*DoAction[])(gpointer) = {
1195 	    A_GetMemoryStatus,
1196 	    A_GetMemoryLocation,
1197 	    A_GetMemoryLocationAll,
1198 	    A_WriteMemoryLocation,
1199 	    A_WriteMemoryLocationAll,
1200 	    A_DeleteMemoryLocation,
1201 	    A_GetCalendarNote,
1202 	    A_GetCalendarNoteAll,
1203 	    A_WriteCalendarNote,
1204 	    A_DeleteCalendarNote,
1205 	    A_GetCallerGroup,
1206 	    A_SendCallerGroup,
1207 	    A_GetSMSCenter,
1208 	    A_SetSMSCenter,
1209 	    A_SendSMSMessage,
1210 	    A_DeleteSMSMessage,
1211 	    A_GetSpeedDial,
1212 	    A_SendSpeedDial,
1213 	    A_SendDTMF,
1214 	    A_NetMonOnOff,
1215 	    A_NetMonitor,
1216 	    A_DialVoice,
1217 	    A_GetAlarm,
1218 	    A_SetAlarm,
1219 	    A_PressKey,
1220 	    A_ReleaseKey,
1221 	    A_GetBitmap,
1222 	    A_SetBitmap,
1223 	    A_GetNetworkInfo,
1224 	    A_PlayTone,
1225 	    A_GetRingtone,
1226 	    A_SetRingtone,
1227 	    A_DeleteRingtone,
1228 	    A_GetRingtoneList,
1229 	    A_Exit};
1230 
1231 
GUI_Connect(void * a)1232 void *GUI_Connect(void *a)
1233 {
1234 	/* Define required unit types for RF and Battery level meters. */
1235 	gn_rf_unit rf_units = GN_RF_Percentage;
1236 	gn_battery_unit batt_units = GN_BU_Percentage;
1237 	gn_calnote_alarm Alarm;
1238 	gn_netmonitor netmonitor;
1239 	gn_data gdat;
1240 	gint displaystatus, i, j;
1241 	time_t newtime, oldtime;
1242 
1243 	gn_call *call;
1244 	PhoneEvent *event;
1245 	gn_error error;
1246 
1247 	gn_log_xdebug("Initializing connection...\n");
1248 
1249 	phoneMonitor.working = _("Connecting...");
1250 	if (fbusinit() != GN_ERR_NONE) {
1251 		gn_log_xdebug("Initialization failed...\n");
1252 		MainExit(NULL);
1253 		return NULL;
1254 	}
1255 
1256 	if (!xgnokiiConfig.allowBreakage &&				/* User did not allow to break the phone */
1257 		(phoneMonitor.supported & PM_XGNOKIIBREAKAGE) &&	/* Phone is known to be on the black list */
1258 		strncmp(xgnokiiConfig.model, "AT", 2)) {		/* We're not using it in AT mode */
1259 		gn_log_xdebug("Detected phone known to be broken using xgnokii\n");
1260 		MainExit(_("It has been reported that your phone is known to be broken by xgnokii.\n"
1261 			   "Exiting application to avoid breakage. If you want to take a risk and\n"
1262 			   "run xgnokii anyway, set:\n\n"
1263 			   "\tallow_breakage = 1\n\n"
1264 			   "in xgnokii section in your config file.\n"
1265 			   "See http://thread.gmane.org/gmane.linux.drivers.gnokii/3195 for details.\n"));
1266 		return NULL;
1267 	}
1268 
1269 	gn_log_xdebug("Phone connected. Starting monitoring...\n");
1270 
1271 	sleep(1);
1272 
1273 	gn_data_clear(&gdat);
1274 
1275 	gdat.rf_level = &phoneMonitor.rfLevel;
1276 	gdat.rf_unit = &rf_units;
1277 	gdat.power_source = &phoneMonitor.powerSource;
1278 	gdat.battery_unit = &batt_units;
1279 	gdat.battery_level = &phoneMonitor.batteryLevel;
1280 	gdat.datetime = &Alarm.timestamp;
1281 	gdat.alarm = &Alarm;
1282 	oldtime = time(&oldtime);
1283 	oldtime += 2;
1284 
1285 	while (1) {
1286 		phoneMonitor.working = NULL;
1287 
1288 /* FIXME - this loop goes mad on my 7110 - so I've put in a usleep */
1289 		usleep(50000);
1290 
1291 		if ((call = gn_call_get_active(0)) != NULL) {
1292 			gn_log_xdebug("Call in progress: %s\n", phoneMonitor.call.callNum);
1293 			gdat.display_status = &displaystatus;
1294 			gn_sm_functions(GN_OP_GetDisplayStatus, &gdat, statemachine);
1295 			if (displaystatus & (1<<GN_DISP_Call_In_Progress)) {
1296 				pthread_mutex_lock (&callMutex);
1297 				phoneMonitor.call.callInProgress = CS_InProgress;
1298 				pthread_mutex_unlock (&callMutex);
1299 			} else {
1300 				pthread_mutex_lock (&callMutex);
1301 				phoneMonitor.call.callInProgress = CS_Waiting;
1302 				strncpy (phoneMonitor.call.callNum, call->remote_number, INCALL_NUMBER_LENGTH);
1303 				pthread_mutex_unlock (&callMutex);
1304 			}
1305 		} else {
1306 			pthread_mutex_lock(&callMutex);
1307 			phoneMonitor.call.callInProgress = CS_Idle;
1308 			*phoneMonitor.call.callNum = '\0';
1309 			pthread_mutex_unlock(&callMutex);
1310 		}
1311 
1312 		pthread_mutex_lock(&netMonMutex);
1313 
1314 		if (phoneMonitor.netmonitor.number) {
1315 
1316 			gdat.netmonitor = &netmonitor;
1317 			gdat.netmonitor->field = phoneMonitor.netmonitor.number;
1318 			gn_sm_functions(GN_OP_NetMonitor, &gdat, statemachine);
1319 			memcpy(phoneMonitor.netmonitor.screen, gdat.netmonitor->screen,
1320 			       sizeof(gdat.netmonitor->screen));
1321 
1322 			gdat.netmonitor->field = 3;
1323 			gn_sm_functions(GN_OP_NetMonitor, &gdat, statemachine);
1324 			memcpy(phoneMonitor.netmonitor.screen3, gdat.netmonitor->screen,
1325 			       sizeof(gdat.netmonitor->screen));
1326 
1327 			gdat.netmonitor->field = 4;
1328 			gn_sm_functions(GN_OP_NetMonitor, &gdat, statemachine);
1329 			memcpy(phoneMonitor.netmonitor.screen4, gdat.netmonitor->screen,
1330 			       sizeof(gdat.netmonitor->screen));
1331 
1332 			gdat.netmonitor->field = 5;
1333 			gn_sm_functions(GN_OP_NetMonitor, &gdat, statemachine);
1334 			memcpy(phoneMonitor.netmonitor.screen5, gdat.netmonitor->screen,
1335 			       sizeof(gdat.netmonitor->screen));
1336 
1337 		} else {
1338 			*phoneMonitor.netmonitor.screen = *phoneMonitor.netmonitor.screen3 =
1339 			    *phoneMonitor.netmonitor.screen4 = *phoneMonitor.netmonitor.screen5 =
1340 			    '\0';
1341 		}
1342 		pthread_mutex_unlock(&netMonMutex);
1343 
1344 		while ((event = RemoveEvent()) != NULL) {
1345 			gn_log_xdebug("Processing Event: %d\n", event->event);
1346 			phoneMonitor.working = _("Working...");
1347 			if (event->event <= Event_Exit)
1348 				if ((error = DoAction[event->event] (event->data)) != GN_ERR_NONE)
1349 					g_print(_("Event %d failed with return code %d!\n"),
1350 						event->event, error);
1351 			g_free(event);
1352 		}
1353 
1354 		/* two seconds delay for SMS, RF/power level */
1355 		newtime = time(&newtime);
1356 		if (newtime < oldtime + 2)  continue;
1357 		oldtime = newtime;
1358 
1359 		if (gn_sm_functions(GN_OP_GetRFLevel, &gdat, statemachine) != GN_ERR_NONE)
1360 			phoneMonitor.rfLevel = -1;
1361 
1362 		if (gn_sm_functions(GN_OP_GetPowersource, &gdat, statemachine) == GN_ERR_NONE
1363 		    && phoneMonitor.powerSource == GN_PS_ACDC)
1364 			phoneMonitor.batteryLevel = ((gint) phoneMonitor.batteryLevel + 25) % 125;
1365 		else {
1366 			if (gn_sm_functions(GN_OP_GetBatteryLevel, &gdat, statemachine) != GN_ERR_NONE)
1367 				phoneMonitor.batteryLevel = -1;
1368 			if (batt_units == GN_BU_Arbitrary)
1369 				phoneMonitor.batteryLevel *= 25;
1370 		}
1371 
1372 		if (rf_units == GN_RF_Arbitrary)
1373 			phoneMonitor.rfLevel *= 25;
1374 
1375 		if (gn_sm_functions(GN_OP_GetAlarm, &gdat, statemachine) == GN_ERR_NONE &&
1376 		    Alarm.enabled != 0)
1377 			phoneMonitor.alarm = TRUE;
1378 		else
1379 			phoneMonitor.alarm = FALSE;
1380 
1381 		/* only do SMS monitoring when activated */
1382 		if (!isSMSactivated) continue;
1383 		gdat.sms_status = &SMSStatus;
1384 		/* FIXME: This can surely be done easier */
1385 		for (i = 0; i < GN_SMS_FOLDER_MAX_NUMBER; i++) {
1386 			gdat.folder_stats[i] = &FolderStats[i];
1387 			for (j = 0; j < GN_SMS_MESSAGE_MAX_NUMBER; j++)
1388 				gdat.message_list[j][i] = &MessagesList[j][i];
1389 		}
1390 
1391 		if ((gn_sms_get_folder_changes(&gdat, statemachine, (phoneMonitor.supported & PM_FOLDERS))) == GN_ERR_NONE) {
1392 			gn_log_xdebug("old UR: %i, new UR: %i, old total: %i, new total: %i\n",
1393 				phoneMonitor.sms.unRead, gdat.sms_status->unread,
1394 				phoneMonitor.sms.number, gdat.sms_status->number);
1395 			phoneMonitor.sms.changed += gdat.sms_status->changed;
1396 			if (gdat.sms_status->changed) {
1397 				phoneMonitor.working = _("Refreshing SMSes...");
1398 				RefreshSMS(gdat.sms_status->number);
1399 				phoneMonitor.working = NULL;
1400 				GUIEventSend(GUI_EVENT_SMS_NUMBER_CHANGED);
1401 			}
1402 			phoneMonitor.sms.unRead = gdat.sms_status->unread;
1403 		}
1404 
1405 	}
1406 }
1407