Fixed fatal linker error (global symbol conflict of "writephonebook")
[gnokii.git] / xgnokii / xgnokii_lowlevel.c
1 /*
2
3   $Id$
4   
5   X G N O K I I
6
7   A Linux/Unix GUI for Nokia mobile phones.
8   Copyright (C) 1999 Pavel Janík ml., Hugh Blemings
9   & Ján Derfiòák <ja@mail.upjs.sk>.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13 */
14
15 #include <unistd.h>
16 #include <pthread.h>
17 #include <string.h>
18 #include <glib.h>
19 #include "misc.h"
20 #include "gsm-common.h"
21 #include "gsm-api.h"
22 //#include "6110.h"
23 //#include "fbus-3810.h"
24 #include "xgnokii_lowlevel.h"
25 #include "xgnokii.h"
26 #include "gsm-statemachine.h"
27 //#include "xgnokii_common.h"
28
29 pthread_t monitor_th;
30 PhoneMonitor phoneMonitor;
31 pthread_mutex_t memoryMutex;
32 pthread_cond_t  memoryCond;
33 pthread_mutex_t calendarMutex;
34 pthread_cond_t  calendarCond;
35 pthread_mutex_t smsMutex;
36 pthread_mutex_t sendSMSMutex;
37 pthread_cond_t  sendSMSCond;
38 pthread_mutex_t callMutex;
39 pthread_mutex_t netMonMutex;
40 pthread_mutex_t speedDialMutex;
41 pthread_cond_t  speedDialCond;
42 pthread_mutex_t callerGroupMutex;
43 pthread_cond_t  callerGroupCond;
44 pthread_mutex_t smsCenterMutex;  
45 pthread_cond_t  smsCenterCond;
46 pthread_mutex_t alarmMutex;  
47 pthread_cond_t  alarmCond;
48 pthread_mutex_t getBitmapMutex;
49 pthread_cond_t  getBitmapCond;
50 pthread_mutex_t setBitmapMutex;
51 pthread_cond_t  setBitmapCond;
52 pthread_mutex_t getNetworkInfoMutex;
53 pthread_cond_t  getNetworkInfoCond;
54 static pthread_mutex_t eventsMutex;
55 static GSList *ScheduledEvents = NULL;
56
57 static GSM_Statemachine statemachine;
58 /* FIXME - don't really know what should own the statemachine in */
59 /* the xgnokii scheme of things - Chris */
60
61
62 inline void GUI_InsertEvent (PhoneEvent *event)
63 {
64 # ifdef XDEBUG
65   g_print ("Inserting Event: %d\n", event->event);
66 # endif
67   pthread_mutex_lock (&eventsMutex);
68   ScheduledEvents = g_slist_prepend (ScheduledEvents, event);
69   pthread_mutex_unlock (&eventsMutex);
70 }
71
72
73 inline static PhoneEvent *RemoveEvent (void)
74 {
75   GSList *list;
76   PhoneEvent *event = NULL;
77
78   pthread_mutex_lock (&eventsMutex);
79   list = g_slist_last (ScheduledEvents);
80   if (list)
81   {
82     event = (PhoneEvent *) list->data;
83     ScheduledEvents = g_slist_remove_link (ScheduledEvents, list);
84     g_slist_free_1 (list);
85   }
86   pthread_mutex_unlock (&eventsMutex);
87
88   return (event);
89 }
90
91
92 static void InitModelInf (void)
93 {
94   gchar buf[64];
95   GSM_Error error;
96   register gint i = 0;
97   GSM_Data data;
98
99   GSM_DataClear(&data);
100   data.Model=buf;
101   while ((error = SM_Functions(GOP_GetModel,&data,&statemachine)) != GE_NONE && i++ < 15)
102     sleep(1);
103
104   if (error == GE_NONE)
105   {
106     g_free (phoneMonitor.phone.model);
107     phoneMonitor.phone.version = g_strdup (buf);
108     phoneMonitor.phone.model = GetModel (buf);
109     if (phoneMonitor.phone.model == NULL)
110       phoneMonitor.phone.model = g_strdup (_("unknown"));
111
112     phoneMonitor.supported = GetPhoneModel(buf)->flags;
113   }
114
115   i = 0;
116   data.Revision=buf;
117   while ((error = SM_Functions(GOP_GetRevision,&data,&statemachine)) != GE_NONE && i++ < 5)
118     sleep(1);
119
120   if (error == GE_NONE)
121   {
122     g_free (phoneMonitor.phone.revision);
123     phoneMonitor.phone.revision = g_strdup (buf);
124   }
125
126   i = 0;
127   data.Imei=buf;
128   while ((error = SM_Functions(GOP_GetImei,&data,&statemachine)) != GE_NONE && i++ < 5)
129     sleep(1);
130
131   if (error == GE_NONE)
132   {
133     g_free (phoneMonitor.phone.imei);
134     phoneMonitor.phone.imei = g_strdup (buf);
135   }
136
137
138 #ifdef XDEBUG
139   g_print ("Version: %s\n", phoneMonitor.phone.version);
140   g_print ("Model: %s\n", phoneMonitor.phone.model);
141   g_print ("IMEI: %s\n", phoneMonitor.phone.imei);
142   g_print ("Revision: %s\n", phoneMonitor.phone.revision);
143 #endif
144 }
145
146
147 static GSM_Error fbusinit(bool enable_monitoring)
148 {
149   int count=0;
150   static GSM_Error error=GE_NOLINK;
151   GSM_ConnectionType connection=GCT_Serial;
152
153   if (!strcmp(xgnokiiConfig.connection, "infrared"))
154     connection = GCT_Infrared;
155
156   if (!strcmp(xgnokiiConfig.connection, "irda"))
157     connection = GCT_Irda;
158
159   /* Initialise the code for the GSM interface. */     
160
161   if (error == GE_NOLINK)
162     error = GSM_Initialise (xgnokiiConfig.model, xgnokiiConfig.port,
163                             xgnokiiConfig.initlength, connection, RLP_DisplayF96Frame, &statemachine);
164
165 #ifdef XDEBUG
166   g_print ("fbusinit: error %d\n", error);
167 #endif
168
169   if (error != GE_NONE) {
170     g_print (_("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
171     /* FIXME: should popup some message... */
172     return (error);
173   }
174
175   while (count++ < 40 && *GSM_LinkOK == false)
176     usleep(50000);
177 #ifdef XDEBUG
178   g_print("After usleep. GSM_LinkOK: %d\n", *GSM_LinkOK);
179 #endif
180
181   if (*GSM_LinkOK == true)
182     InitModelInf ();
183
184   return *GSM_LinkOK;
185 }
186
187
188 void GUI_InitPhoneMonitor (void)
189 {
190   phoneMonitor.phone.model = g_strdup (_("unknown"));
191   phoneMonitor.phone.version = phoneMonitor.phone.model;
192   phoneMonitor.phone.revision = g_strdup (_("unknown"));
193   phoneMonitor.phone.imei = g_strdup (_("unknown"));
194   phoneMonitor.supported = 0;
195   phoneMonitor.rfLevel = phoneMonitor.batteryLevel = -1;
196   phoneMonitor.powerSource = GPS_BATTERY;
197   phoneMonitor.working = NULL;
198   phoneMonitor.alarm = FALSE;
199   phoneMonitor.sms.unRead = phoneMonitor.sms.number = 0;
200   phoneMonitor.sms.messages = NULL;
201   phoneMonitor.call.callInProgress = CS_Idle;
202   *phoneMonitor.call.callNum = '\0';
203   phoneMonitor.netmonitor.number = 0;
204   *phoneMonitor.netmonitor.screen = *phoneMonitor.netmonitor.screen3 = 
205   *phoneMonitor.netmonitor.screen4 = *phoneMonitor.netmonitor.screen5 = '\0';
206   pthread_mutex_init (&memoryMutex, NULL);
207   pthread_cond_init (&memoryCond, NULL);
208   pthread_mutex_init (&calendarMutex, NULL);
209   pthread_cond_init (&calendarCond, NULL);
210   pthread_mutex_init (&smsMutex, NULL);
211   pthread_mutex_init (&sendSMSMutex, NULL);
212   pthread_cond_init (&sendSMSCond, NULL);
213   pthread_mutex_init (&callMutex, NULL);
214   pthread_mutex_init (&eventsMutex, NULL);
215   pthread_mutex_init (&callMutex, NULL);
216   pthread_mutex_init (&netMonMutex, NULL);
217   pthread_mutex_init (&speedDialMutex, NULL);
218   pthread_cond_init (&speedDialCond, NULL);
219   pthread_mutex_init (&callerGroupMutex, NULL);
220   pthread_cond_init (&callerGroupCond, NULL);
221   pthread_mutex_init (&smsCenterMutex, NULL);
222   pthread_cond_init (&smsCenterCond, NULL);
223   pthread_mutex_init (&getBitmapMutex, NULL);
224   pthread_cond_init (&getBitmapCond, NULL);
225   pthread_mutex_init (&setBitmapMutex, NULL);
226   pthread_cond_init (&setBitmapCond, NULL);
227   pthread_mutex_init (&getNetworkInfoMutex, NULL);
228   pthread_cond_init (&getNetworkInfoCond, NULL);
229 }
230
231
232 static inline void FreeElement (gpointer data, gpointer userData)
233 {
234   g_free ((GSM_SMSMessage *) data);
235 }
236
237
238 static inline void FreeArray (GSList **array)
239 {
240   if (*array)
241   {
242     g_slist_foreach (*array, FreeElement, NULL);
243     g_slist_free (*array);
244     *array = NULL;
245   }
246 }
247
248
249 static void RefreshSMS (const gint number)
250 {
251   GSM_Error error;
252   GSM_SMSMessage *msg;
253   register gint i;
254
255 # ifdef XDEBUG
256   g_print ("RefreshSMS is running...\n");
257 # endif
258
259   pthread_mutex_lock (&smsMutex);
260   FreeArray (&(phoneMonitor.sms.messages));
261   phoneMonitor.sms.number = 0;
262   pthread_mutex_unlock (&smsMutex);
263
264   i = 0;
265   while (1)
266   {
267     GSM_Data gdat;
268     GSM_DataClear(&gdat);
269     msg = g_malloc (sizeof (GSM_SMSMessage));
270     msg->MemoryType = GMT_SM;
271     msg->Number = ++i;
272     gdat.SMSMessage = msg;
273
274     if ((error = SM_Functions(GOP_GetSMS, &gdat, &statemachine)) == GE_NONE)
275     {
276       pthread_mutex_lock (&smsMutex);
277       phoneMonitor.sms.messages = g_slist_append (phoneMonitor.sms.messages, msg);
278       phoneMonitor.sms.number++;
279       pthread_mutex_unlock (&smsMutex);
280       if (phoneMonitor.sms.number == number)
281         return;
282     }
283     else if (error == GE_INVALIDSMSLOCATION)  /* All positions are readed */
284     {
285       g_free (msg);
286       break;
287     }
288     else
289       g_free (msg);
290
291     usleep (750000);
292   }
293 }
294
295
296 static gint A_GetMemoryStatus (gpointer data)
297 {
298   GSM_Error error;
299   D_MemoryStatus *ms = (D_MemoryStatus *) data;
300   GSM_Data gdat;
301
302   error = ms->status = GE_UNKNOWN;
303
304   if (ms)
305   {
306     GSM_DataClear(&gdat);         
307     pthread_mutex_lock (&memoryMutex);
308     gdat.MemoryStatus=&(ms->memoryStatus);
309     error = ms->status = SM_Functions(GOP_GetMemoryStatus,&gdat,&statemachine);
310     pthread_cond_signal (&memoryCond);
311     pthread_mutex_unlock (&memoryMutex);
312   }
313
314   return (error);
315 }
316
317
318 static gint A_GetMemoryLocation (gpointer data)
319 {
320   GSM_Error error;
321   D_MemoryLocation *ml = (D_MemoryLocation *) data;
322   GSM_Data gdat;
323
324   error = ml->status = GE_UNKNOWN;
325
326   if (ml)
327   {
328     GSM_DataClear(&gdat);
329     pthread_mutex_lock (&memoryMutex);
330     gdat.PhonebookEntry=(ml->entry);
331     error = ml->status = SM_Functions(GOP_ReadPhonebook,&gdat,&statemachine);
332     pthread_cond_signal (&memoryCond);
333     pthread_mutex_unlock (&memoryMutex);
334   }
335
336   return (error);
337 }
338
339
340 static gint A_GetMemoryLocationAll (gpointer data)
341 {
342   GSM_PhonebookEntry entry;
343   GSM_Error error;
344   D_MemoryLocationAll *mla = (D_MemoryLocationAll *) data;
345   register gint i;
346   GSM_Data gdat;
347
348   error = mla->status = GE_NONE;
349   entry.MemoryType = mla->type;
350   GSM_DataClear(&gdat);
351   gdat.PhonebookEntry=&entry;
352
353   pthread_mutex_lock (&memoryMutex);
354   for (i = mla->min; i <= mla->max; i++)
355   {
356     entry.Location = i;
357     error = SM_Functions(GOP_ReadPhonebook,&gdat,&statemachine);
358     if (error != GE_NONE && error!=GE_INVALIDPHBOOKLOCATION)
359     {
360       gint err_count = 0;
361
362       while (error != GE_NONE)
363       {
364         g_print (_("%s: line %d: Can't get memory entry number %d from memory %d! %d\n"),
365                  __FILE__, __LINE__, i, entry.MemoryType, error);
366         if (err_count++ > 3)
367         {
368           mla->ReadFailed (i);
369           mla->status = error;
370           pthread_cond_signal (&memoryCond);
371           pthread_mutex_unlock (&memoryMutex);
372           return (error);
373         }
374
375         error = SM_Functions(GOP_ReadPhonebook,&gdat,&statemachine);
376         sleep (2);
377       }
378     }
379
380     /* If the phonebook location was invalid - just fill up the rest */
381     /* This works on a 7110 anyway...*/
382
383     if (error==GE_INVALIDPHBOOKLOCATION) {
384         entry.Empty=true;
385         entry.Name[0]=0;
386         entry.Number[0]=0;
387         for (i = mla->min; i <= mla->max; i++) {
388                 error = mla->InsertEntry (&entry);
389                 if (error != GE_NONE) break;
390         }       
391     }
392
393     error = mla->InsertEntry (&entry);
394     if (error != GE_NONE)
395       break;
396   }
397   mla->status = error;
398   pthread_cond_signal (&memoryCond);
399   pthread_mutex_unlock (&memoryMutex);
400   return (error);
401 }
402
403
404 static gint A_WriteMemoryLocation (gpointer data)
405 {
406   GSM_Error error;
407   D_MemoryLocation *ml = (D_MemoryLocation *) data;
408   GSM_Data gdat;
409
410   error = ml->status = GE_UNKNOWN;
411
412   GSM_DataClear(&gdat);
413   gdat.PhonebookEntry=(ml->entry);
414
415   if (ml)
416   {
417     pthread_mutex_lock (&memoryMutex);
418     error = ml->status = SM_Functions(GOP_WritePhonebook,&gdat,&statemachine);
419     pthread_cond_signal (&memoryCond);
420     pthread_mutex_unlock (&memoryMutex);
421   }
422
423   return (error);
424 }
425
426
427 static gint A_WriteMemoryLocationAll (gpointer data)
428 {
429 /*  GSM_PhonebookEntry entry; */
430   GSM_Error error;
431   D_MemoryLocationAll *mla = (D_MemoryLocationAll *) data;
432 /*  register gint i;
433 */
434   error = mla->status = GE_NONE;
435 /*  entry.MemoryType = mla->type;
436
437   pthread_mutex_lock (&memoryMutex);
438   for (i = mla->min; i <= mla->max; i++)
439   {
440     entry.Location = i;
441     error = GSM->GetMemoryLocation (&entry);
442     if (error != GE_NONE)
443     {
444       gint err_count = 0;
445
446       while (error != GE_NONE)
447       {
448         g_print (_("%s: line %d: Can't get memory entry number %d from memory %d! %d\n"),
449                  __FILE__, __LINE__, i, entry.MemoryType, error);
450         if (err_count++ > 3)
451         {
452           mla->ReadFailed (i);
453           mla->status = error;
454           pthread_cond_signal (&memoryCond);
455           pthread_mutex_unlock (&memoryMutex);
456           return (error);
457         }
458
459         error = GSM->GetMemoryLocation (&entry);
460         sleep (2);
461       }
462     }
463     error = mla->InsertEntry (&entry);
464     if (error != GE_NONE)
465       break;
466   }
467   mla->status = error;
468   pthread_cond_signal (&memoryCond);
469   pthread_mutex_unlock (&memoryMutex); */
470   return (error);
471 }
472
473
474 static gint A_GetCalendarNote (gpointer data)
475 {
476   GSM_Error error;
477   D_CalendarNote *cn = (D_CalendarNote *) data;
478
479   error = cn->status = GE_UNKNOWN;
480
481   if (cn)
482   {
483     pthread_mutex_lock (&calendarMutex);
484     error = cn->status = GSM->GetCalendarNote (cn->entry);
485     pthread_cond_signal (&calendarCond);
486     pthread_mutex_unlock (&calendarMutex);
487   }
488
489   return (error);
490 }
491
492
493 static gint A_GetCalendarNoteAll (gpointer data)
494 {
495   GSM_CalendarNote entry;
496   D_CalendarNoteAll *cna = (D_CalendarNoteAll *) data;
497   GSM_Error e;
498   register gint i = 1;
499
500   pthread_mutex_lock (&calendarMutex);
501   while (1)
502   {
503     entry.Location = i++;
504
505     if ((e = GSM->GetCalendarNote (&entry)) != GE_NONE)
506       break;
507
508     if (cna->InsertEntry (&entry) != GE_NONE)
509       break;
510   }
511
512   pthread_mutex_unlock (&calendarMutex);
513   g_free (cna);
514   if (e == GE_INVALIDCALNOTELOCATION)
515     return (GE_NONE);
516   else
517     return (e);
518 }
519
520
521 static gint A_WriteCalendarNote (gpointer data)
522 {
523   GSM_Error error;
524   D_CalendarNote *cn = (D_CalendarNote *) data;
525
526   error = cn->status = GE_UNKNOWN;
527
528   if (cn)
529   {
530     pthread_mutex_lock (&calendarMutex);
531     error = cn->status = GSM->WriteCalendarNote (cn->entry);
532     pthread_cond_signal (&calendarCond);
533     pthread_mutex_unlock (&calendarMutex);
534   }
535
536   return (error);
537 }
538
539
540 static gint A_DeleteCalendarNote (gpointer data)
541 {
542   GSM_CalendarNote *note = (GSM_CalendarNote *) data;
543   GSM_Error error = GE_UNKNOWN;
544
545   if (note)
546   {
547     error = GSM->DeleteCalendarNote (note);
548     g_free (note);
549   }
550
551   return (error);
552 }
553
554 static gint A_GetCallerGroup (gpointer data)
555 {
556   GSM_Bitmap bitmap;
557   GSM_Error error;
558   D_CallerGroup *cg = (D_CallerGroup *) data;
559   GSM_Data gdat;
560
561   error = cg->status = GE_UNKNOWN;
562
563   if (cg)
564   {
565     bitmap.type = GSM_CallerLogo;
566     bitmap.number = cg->number;
567
568     pthread_mutex_lock (&callerGroupMutex);
569     GSM_DataClear(&gdat);
570     gdat.Bitmap=&bitmap;
571     error = cg->status = SM_Functions(GOP_GetBitmap,&gdat,&statemachine);
572     strncpy (cg->text, bitmap.text, 256);
573     cg->text[255] = '\0';
574     pthread_cond_signal (&callerGroupCond);
575     pthread_mutex_unlock (&callerGroupMutex);
576   }
577
578   return (error);
579 }
580
581
582 static gint A_SendCallerGroup (gpointer data)
583 {
584   GSM_Bitmap bitmap;
585   D_CallerGroup *cg = (D_CallerGroup *) data;
586   GSM_Error error;
587
588   if (!cg)
589     return (GE_UNKNOWN);
590
591   bitmap.type = GSM_CallerLogo;
592   bitmap.number = cg->number;
593   if ((error = GSM->GetBitmap (&bitmap)) != GE_NONE)
594   {
595     g_free (cg);
596     return (error);
597   }
598   strncpy (bitmap.text, cg->text, 256);
599   bitmap.text[255] = '\0';
600   g_free (cg);
601   return (GSM->SetBitmap (&bitmap));
602 }
603
604
605 static gint A_GetSMSCenter (gpointer data)
606 {
607   D_SMSCenter *c = (D_SMSCenter *) data;
608   GSM_Error error;
609
610   error = c->status = GE_UNKNOWN;
611   if (c)
612   {
613     pthread_mutex_lock (&smsCenterMutex);
614     error = c->status = GSM->GetSMSCenter (c->center);
615     pthread_cond_signal (&smsCenterCond);
616     pthread_mutex_unlock (&smsCenterMutex);
617   }
618
619   return (error);
620 }
621
622
623 static gint A_SetSMSCenter (gpointer data)
624 {
625   D_SMSCenter *c = (D_SMSCenter *) data;
626   GSM_Error error;
627
628   error = c->status = GE_UNKNOWN;
629   if (c)
630   {
631     //pthread_mutex_lock (&smsCenterMutex);
632     error = c->status = GSM->SetSMSCenter (c->center);
633     g_free (c);
634     //pthread_cond_signal (&smsCenterCond);
635     //pthread_mutex_unlock (&smsCenterMutex);
636   }
637
638   return (error);
639 }
640
641
642 static gint A_SendSMSMessage (gpointer data)
643 {
644   D_SMSMessage *d = (D_SMSMessage *) data;
645   GSM_Error error;
646
647   error = d->status = GE_UNKNOWN;
648   if (d)
649   {
650     pthread_mutex_lock (&sendSMSMutex);
651     error = d->status = GSM->SendSMSMessage (d->sms, 0);
652     pthread_cond_signal (&sendSMSCond);
653     pthread_mutex_unlock (&sendSMSMutex);
654   }
655
656   if (d->status == GE_SMSSENDOK)
657     return (GE_NONE);
658   else
659     return (error);
660 }
661
662
663 static gint A_DeleteSMSMessage (gpointer data)
664 {
665   GSM_SMSMessage *sms = (GSM_SMSMessage *) data;
666   GSM_Error error = GE_UNKNOWN;
667
668   if (sms)
669   {
670     GSM_Data gdat;
671     GSM_DataClear(&gdat);
672     gdat.SMSMessage = sms;
673     error = SM_Functions(GOP_DeleteSMS, &gdat, &statemachine);
674     g_free (sms);
675   }
676
677   return (error);
678 }
679
680
681 static gint A_GetSpeedDial (gpointer data)
682 {
683   D_SpeedDial *d = (D_SpeedDial *) data;
684   GSM_Error error;
685
686   error = d->status = GE_UNKNOWN;
687
688   if (d)
689   {
690     pthread_mutex_lock (&speedDialMutex);
691     error = d->status = GSM->GetSpeedDial (&(d->entry));
692     pthread_cond_signal (&speedDialCond);
693     pthread_mutex_unlock (&speedDialMutex);
694   }
695
696   return (error);
697 }
698
699
700 static gint A_SendSpeedDial (gpointer data)
701 {
702   D_SpeedDial *d = (D_SpeedDial *) data;
703   GSM_Error error;
704
705   error = d->status = GE_UNKNOWN;
706
707   if (d)
708   {
709     //pthread_mutex_lock (&speedDialMutex);
710     error = d->status = GSM->SetSpeedDial (&(d->entry));
711     g_free (d);
712     //pthread_cond_signal (&speedDialCond);
713     //pthread_mutex_unlock (&speedDialMutex);
714   }
715
716   return (error);
717 }
718
719
720 static gint A_SendDTMF (gpointer data)
721 {
722   gchar *buf = (gchar *) data;
723   GSM_Error error = GE_UNKNOWN;
724
725   if (buf) 
726   {
727     error = GSM->SendDTMF (buf);
728     g_free (buf);
729   }
730
731   return (error);
732 }
733
734
735 static gint A_NetMonOnOff (gpointer data)
736 {
737   gchar screen[50];
738   gint mode = GPOINTER_TO_INT (data);
739   GSM_Error error = GE_UNKNOWN;
740
741   if (mode)
742     error = GSM->NetMonitor (0xf3, screen);
743   else
744     error = GSM->NetMonitor (0xf1, screen);
745
746   return (error);
747 }
748
749
750 static gint A_NetMonitor (gpointer data)
751 {
752   gint number = GPOINTER_TO_INT (data);
753
754   if (data == 0)
755     phoneMonitor.netmonitor.number = 0;
756   else
757     phoneMonitor.netmonitor.number = number;
758     
759   return (0);
760 }
761
762
763 static gint A_DialVoice (gpointer data)
764 {
765   gchar *number = (gchar *) data;
766   GSM_Error error = GE_UNKNOWN;
767
768   if (number)
769   {
770     error = GSM->DialVoice (number);
771     g_free (number);
772   }
773
774   return (error);
775 }
776
777
778 static gint A_GetAlarm (gpointer data)
779 {
780   D_Alarm *a = (D_Alarm *) data;
781   GSM_Error error;
782
783   error = GE_UNKNOWN;
784
785   if (a)
786   {
787     a->status = GE_UNKNOWN;
788     pthread_mutex_lock (&alarmMutex);
789     error = a->status = GSM->GetAlarm (0, &(a->time));
790     pthread_cond_signal (&alarmCond);
791     pthread_mutex_unlock (&alarmMutex);
792   }
793
794   return (error);
795 }
796
797
798 static gint A_SetAlarm (gpointer data)
799 {
800   D_Alarm *a = (D_Alarm *) data;
801   GSM_Error error;
802
803   error = a->status = GE_UNKNOWN;
804
805   if (a)
806   {
807     error = a->status = GSM->SetAlarm (0, &(a->time));
808     g_free (a);
809   }
810
811   return (error);
812 }
813
814
815 static gint A_SendKeyStroke (gpointer data)
816 {
817   /*  gchar *buf = (gchar *) data;*/
818
819   /* This is wrong. FIX IT */
820   /*  if (buf) 
821   {
822     FB61_TX_SendMessage(0x07, 0x0c, buf);
823     g_free (buf);
824     }*/
825
826   return (0);
827 }
828
829 static gint A_GetBitmap(gpointer data) {
830   GSM_Error error;
831   D_Bitmap *d = (D_Bitmap *)data;
832   GSM_Data gdat;
833
834   GSM_DataClear(&gdat);
835   pthread_mutex_lock(&getBitmapMutex);
836   gdat.Bitmap=d->bitmap;
837   error = d->status = SM_Functions(GOP_GetBitmap,&gdat,&statemachine);
838   pthread_cond_signal(&getBitmapCond);
839   pthread_mutex_unlock(&getBitmapMutex);
840   return error;
841 }
842
843 static gint A_SetBitmap(gpointer data) {
844   GSM_Error error;
845   D_Bitmap *d = (D_Bitmap *)data;
846   GSM_Bitmap bitmap;
847   GSM_Data gdat;
848   
849   GSM_DataClear(&gdat);
850   pthread_mutex_lock(&setBitmapMutex);
851   if (d->bitmap->type == GSM_CallerLogo) {
852     bitmap.type = d->bitmap->type;
853     bitmap.number = d->bitmap->number;
854     gdat.Bitmap=&bitmap;
855     error = d->status = SM_Functions(GOP_GetBitmap,&gdat,&statemachine);
856     if (error == GE_NONE) {
857       strncpy(d->bitmap->text,bitmap.text,sizeof(bitmap.text));
858       d->bitmap->ringtone = bitmap.ringtone;
859       gdat.Bitmap=d->bitmap;
860       error = d->status = SM_Functions(GOP_SetBitmap,&gdat,&statemachine);
861     }
862   } else {
863     gdat.Bitmap=d->bitmap;
864     error = d->status = SM_Functions(GOP_SetBitmap,&gdat,&statemachine);
865   }
866   pthread_cond_signal(&setBitmapCond);
867   pthread_mutex_unlock(&setBitmapMutex);
868   return error;
869 }
870
871 static gint A_GetNetworkInfo(gpointer data) {
872   GSM_Error error;
873   D_NetworkInfo *d = (D_NetworkInfo *)data;
874   GSM_Data gdat;
875   
876   GSM_DataClear(&gdat);
877
878   pthread_mutex_lock(&getNetworkInfoMutex);
879   gdat.NetworkInfo=d->info;
880   error = d->status = SM_Functions(GOP_GetNetworkInfo,&gdat,&statemachine);
881   pthread_cond_signal(&getNetworkInfoCond);
882   pthread_mutex_unlock(&getNetworkInfoMutex);
883   return error;
884 }
885
886 static gint A_Exit (gpointer data)
887 {
888   pthread_exit (0);
889   return (0); /* just to be proper */
890 }
891
892
893 gint (*DoAction[])(gpointer) = {
894   A_GetMemoryStatus,
895   A_GetMemoryLocation,
896   A_GetMemoryLocationAll,
897   A_WriteMemoryLocation,
898   A_WriteMemoryLocationAll,
899   A_GetCalendarNote,
900   A_GetCalendarNoteAll,
901   A_WriteCalendarNote,
902   A_DeleteCalendarNote,
903   A_GetCallerGroup,
904   A_SendCallerGroup,
905   A_GetSMSCenter,
906   A_SetSMSCenter,
907   A_SendSMSMessage,
908   A_DeleteSMSMessage,
909   A_GetSpeedDial,
910   A_SendSpeedDial,
911   A_SendDTMF,
912   A_NetMonOnOff,
913   A_NetMonitor,
914   A_DialVoice,
915   A_GetAlarm,
916   A_SetAlarm,
917   A_SendKeyStroke,
918   A_GetBitmap,
919   A_SetBitmap,
920   A_GetNetworkInfo,
921   A_Exit
922 };
923
924
925 void *GUI_Connect (void *a)
926 {
927   /* Define required unit types for RF and Battery level meters. */
928   GSM_RFUnits rf_units = GRF_Percentage;
929   GSM_BatteryUnits batt_units = GBU_Percentage;
930
931   GSM_DateTime Alarm;
932   GSM_SMSMemoryStatus SMSStatus = {0, 0};
933   gchar number[INCALL_NUMBER_LENGTH];
934   PhoneEvent *event;
935   GSM_Error error;
936   gint status;
937   GSM_Data data;
938
939   GSM_DataClear(&data);
940
941 # ifdef XDEBUG
942   g_print ("Initializing connection...\n");
943 # endif
944
945   phoneMonitor.working = _("Connecting...");
946   while (!fbusinit (true))
947     sleep (1);
948
949 # ifdef XDEBUG
950   g_print ("Phone connected. Starting monitoring...\n");
951 # endif
952
953   sleep(1);
954
955   data.RFLevel=&phoneMonitor.rfLevel;
956   data.RFUnits=&rf_units;
957   data.PowerSource=&phoneMonitor.powerSource;
958   data.BatteryUnits=&batt_units; 
959   data.BatteryLevel=&phoneMonitor.batteryLevel;
960   data.DateTime=&Alarm;
961   data.SMSStatus=&SMSStatus;
962   data.IncomingCallNr=number;
963
964   while (1)
965   {
966     phoneMonitor.working = NULL;
967
968     /* FIXME - this loop goes mad on my 7110 - so I've put in a usleep */
969     usleep(50000);
970
971     if (SM_Functions(GOP_GetRFLevel,&data,&statemachine) != GE_NONE)
972       phoneMonitor.rfLevel = -1;
973
974     if (rf_units == GRF_Arbitrary)
975       phoneMonitor.rfLevel *= 25;
976
977     if (SM_Functions(GOP_GetPowersource,&data,&statemachine)  == GE_NONE 
978         && phoneMonitor.powerSource == GPS_ACDC)
979       phoneMonitor.batteryLevel = ((gint) phoneMonitor.batteryLevel + 25) % 125;
980     else
981     {
982       if (SM_Functions(GOP_GetBatteryLevel,&data,&statemachine) != GE_NONE)
983         phoneMonitor.batteryLevel = -1;
984       if (batt_units == GBU_Arbitrary)
985         phoneMonitor.batteryLevel *= 25;
986     }
987
988     if (SM_Functions(GOP_GetAlarm,&data,&statemachine) == GE_NONE && Alarm.AlarmEnabled != 0)
989       phoneMonitor.alarm = TRUE;
990     else
991       phoneMonitor.alarm = FALSE;
992
993     if (SM_Functions(GOP_GetSMSStatus,&data,&statemachine) == GE_NONE)
994     {
995       if (phoneMonitor.sms.unRead != SMSStatus.Unread ||
996           phoneMonitor.sms.number != SMSStatus.Number)
997       {
998         phoneMonitor.working = _("Refreshing SMSes...");
999         RefreshSMS (SMSStatus.Number);
1000         phoneMonitor.working = NULL;
1001       }
1002
1003       phoneMonitor.sms.unRead = SMSStatus.Unread;
1004     }
1005
1006     if (SM_Functions(GOP_GetIncomingCallNr,&data,&statemachine) == GE_NONE)
1007     {
1008 #   ifdef XDEBUG
1009       g_print ("Call in progress: %s\n", phoneMonitor.call.callNum);
1010 #   endif
1011
1012       GSM->GetDisplayStatus (&status);
1013       if (status & (1<<DS_Call_In_Progress))
1014       {
1015         pthread_mutex_lock (&callMutex);
1016         phoneMonitor.call.callInProgress = CS_InProgress;
1017         pthread_mutex_unlock (&callMutex);
1018       }
1019       else
1020       {
1021         pthread_mutex_lock (&callMutex);
1022         phoneMonitor.call.callInProgress = CS_Waiting;
1023         strncpy (phoneMonitor.call.callNum, number, INCALL_NUMBER_LENGTH);
1024         pthread_mutex_unlock (&callMutex);
1025       }
1026     }
1027     else
1028     {
1029       pthread_mutex_lock (&callMutex);
1030       phoneMonitor.call.callInProgress = CS_Idle;
1031       *phoneMonitor.call.callNum = '\0';
1032       pthread_mutex_unlock (&callMutex);
1033     }
1034
1035     pthread_mutex_lock (&netMonMutex);
1036     if (phoneMonitor.netmonitor.number)
1037     {
1038       GSM->NetMonitor (phoneMonitor.netmonitor.number,
1039                        phoneMonitor.netmonitor.screen);
1040       GSM->NetMonitor (3, phoneMonitor.netmonitor.screen3);
1041       GSM->NetMonitor (4, phoneMonitor.netmonitor.screen4);
1042       GSM->NetMonitor (5, phoneMonitor.netmonitor.screen5);
1043     }
1044     else
1045     {
1046       *phoneMonitor.netmonitor.screen = *phoneMonitor.netmonitor.screen3 = 
1047       *phoneMonitor.netmonitor.screen4 = *phoneMonitor.netmonitor.screen5 = '\0';
1048     }
1049     pthread_mutex_unlock (&netMonMutex);
1050
1051     while ((event = RemoveEvent ()) != NULL)
1052     {
1053 #     ifdef XDEBUG      
1054       g_print ("Processing Event: %d\n", event->event);
1055 #     endif
1056       phoneMonitor.working = _("Working...");
1057       if (event->event <= Event_Exit)
1058         if ((error = DoAction[event->event] (event->data)) != GE_NONE)
1059           g_print (_("Event %d failed with return code %d!\n"), event->event, error);
1060       g_free (event);
1061     }
1062   }
1063 }