http://marcin-wiacek.fkn.pl/english/zips/mygnokii.tar.gz
[gnokii.git] / smsd / lowlevel.c
1 /*
2
3   S M S D
4
5   A Linux/Unix GUI for Nokia mobile phones.
6   Copyright (C) 1999 Pavel Janík ml., Hugh Blemings
7   & Ján Derfiòák <ja@mail.upjs.sk>.
8
9   Released under the terms of the GNU GPL, see file COPYING for more details.
10
11   $Id$
12   
13   $Log$
14   Revision 1.1.1.2  2001/12/05 03:16:54  short
15   :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Dec  4 22:45 CET 2001
16
17   Revision 1.5  2001/12/03 15:34:54  pkot
18   Update to libsms and new structure
19
20   Revision 1.4  2001/05/30 14:36:47  pkot
21   Fix smsd to use StateMachine and let it compile.
22
23   Revision 1.3  2001/03/29 08:42:59  ja
24   Enabling compilation of smsd.
25
26   Revision 1.2  2001/02/02 08:09:57  ja
27   New dialogs for 6210/7110 in xgnokii. Fixed the smsd for new capabilty code.
28
29   
30 */
31
32 #include <unistd.h>
33 #include <pthread.h>
34 #include <string.h>
35 #include <glib.h>
36 #include "misc.h"
37 #include "gsm-common.h"
38 #include "gsm-api.h"
39 #include "phones/nk7110.h"
40 #include "phones/nk6100.h"
41 #include "phones/nk3110.h"
42 #include "phones/nk2110.h"
43 #include "smsd.h"
44 #include "lowlevel.h"
45
46 pthread_t monitor_th;
47 PhoneMonitor phoneMonitor;
48 pthread_mutex_t smsMutex;
49 pthread_cond_t  smsCond;
50 pthread_mutex_t sendSMSMutex;
51 pthread_cond_t  sendSMSCond;
52 static pthread_mutex_t eventsMutex;
53 static GSList *ScheduledEvents = NULL;
54
55
56 inline void InsertEvent (PhoneEvent *event)
57 {
58 # ifdef XDEBUG
59   g_print ("Inserting Event: %d\n", event->event);
60 # endif
61   pthread_mutex_lock (&eventsMutex);
62   ScheduledEvents = g_slist_prepend (ScheduledEvents, event);
63   pthread_mutex_unlock (&eventsMutex);
64 }
65
66
67 inline static PhoneEvent *RemoveEvent (void)
68 {
69   GSList *list;
70   PhoneEvent *event = NULL;
71
72   pthread_mutex_lock (&eventsMutex);
73   list = g_slist_last (ScheduledEvents);
74   if (list)
75   {
76     event = (PhoneEvent *) list->data;
77     ScheduledEvents = g_slist_remove_link (ScheduledEvents, list);
78     g_slist_free_1 (list);
79   }
80   pthread_mutex_unlock (&eventsMutex);
81
82   return (event);
83 }
84
85
86 static void InitModelInf (void)
87 {
88   gchar buf[64];
89   GSM_Error error;
90   register gint i = 0;
91
92   while ((error = GSM->GetModel(buf)) != GE_NONE && i++ < 15)
93     sleep(1);
94
95   if (error == GE_NONE)
96   {
97     g_free (phoneMonitor.phone.model);
98     phoneMonitor.phone.version = g_strdup (buf);
99     phoneMonitor.phone.model = GetModel (buf);
100     if (phoneMonitor.phone.model == NULL)
101       phoneMonitor.phone.model = g_strdup (_("unknown"));
102
103     phoneMonitor.supported = GetPhoneModel(buf)->flags;
104   }
105
106   i = 0;
107   while ((error = GSM->GetRevision (buf)) != GE_NONE && i++ < 5)
108     sleep(1);
109
110   if (error == GE_NONE)
111   {
112     g_free (phoneMonitor.phone.revision);
113     phoneMonitor.phone.revision = g_strdup (buf);
114   }
115
116   i = 0;
117   while ((error = GSM->GetIMEI (buf)) != GE_NONE && i++ < 5)
118     sleep(1);
119
120   if (error == GE_NONE)
121   {
122     g_free (phoneMonitor.phone.imei);
123     phoneMonitor.phone.imei = g_strdup (buf);
124   }
125
126
127 #ifdef XDEBUG
128   g_print ("Version: %s\n", phoneMonitor.phone.version);
129   g_print ("Model: %s\n", phoneMonitor.phone.model);
130   g_print ("IMEI: %s\n", phoneMonitor.phone.imei);
131   g_print ("Revision: %s\n", phoneMonitor.phone.revision);
132 #endif
133 }
134
135
136 static GSM_Error fbusinit(bool enable_monitoring)
137 {
138   int count=0;
139   static GSM_Error error=GE_NOLINK;
140   GSM_ConnectionType connection=GCT_Serial;
141   static GSM_Statemachine sm;
142
143   if (!strcmp(smsdConfig.connection, "infrared"))
144     connection = GCT_Infrared;
145
146   /* Initialise the code for the GSM interface. */     
147
148   if (error == GE_NOLINK)
149     error = GSM_Initialise (smsdConfig.model, smsdConfig.port,
150                             smsdConfig.initlength, connection, NULL, &sm);
151
152 #ifdef XDEBUG
153   g_print ("fbusinit: error %d\n", error);
154 #endif
155
156   if (error != GE_NONE) {
157     g_print (_("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
158     return (error);
159   }
160
161   while (count++ < 40 && *GSM_LinkOK == false)
162     usleep(50000);
163 #ifdef XDEBUG
164   g_print("After usleep. GSM_LinkOK: %d\n", *GSM_LinkOK);
165 #endif
166
167   if (*GSM_LinkOK == true)
168     InitModelInf ();
169
170   return *GSM_LinkOK;
171 }
172
173
174 void InitPhoneMonitor (void)
175 {
176   phoneMonitor.phone.model = g_strdup (_("unknown"));
177   phoneMonitor.phone.version = phoneMonitor.phone.model;
178   phoneMonitor.phone.revision = g_strdup (_("unknown"));
179   phoneMonitor.phone.imei = g_strdup (_("unknown"));
180   phoneMonitor.supported = 0;
181   phoneMonitor.working = FALSE;
182   phoneMonitor.sms.unRead = phoneMonitor.sms.number = 0;
183   phoneMonitor.sms.messages = NULL;
184   pthread_mutex_init (&smsMutex, NULL);
185   pthread_cond_init (&smsCond, NULL);
186   pthread_mutex_init (&sendSMSMutex, NULL);
187   pthread_cond_init (&sendSMSCond, NULL);
188   pthread_mutex_init (&eventsMutex, NULL);
189 }
190
191
192 static inline void FreeElement (gpointer data, gpointer userData)
193 {
194   g_free ((GSM_SMSMessage *) data);
195 }
196
197
198 static inline void FreeArray (GSList **array)
199 {
200   if (*array)
201   {
202     g_slist_foreach (*array, FreeElement, NULL);
203     g_slist_free (*array);
204     *array = NULL;
205   }
206 }
207
208
209 static void RefreshSMS (const gint number)
210 {
211   GSM_Error error;
212   GSM_SMSMessage *msg;
213   register gint i;
214
215 # ifdef XDEBUG
216   g_print ("RefreshSMS is running...\n");
217 # endif
218
219   pthread_mutex_lock (&smsMutex);
220   FreeArray (&(phoneMonitor.sms.messages));
221   phoneMonitor.sms.number = 0;
222 //  pthread_mutex_unlock (&smsMutex);
223
224   i = 0;
225   while (1)
226   {
227     msg = g_malloc (sizeof (GSM_SMSMessage));
228     msg->MemoryType = GMT_SM;
229     msg->Number = ++i;
230
231     if ((error = GSM->GetSMSMessage (msg)) == GE_NONE)
232     {
233   //    pthread_mutex_lock (&smsMutex);
234       phoneMonitor.sms.messages = g_slist_append (phoneMonitor.sms.messages, msg);
235       phoneMonitor.sms.number++;
236   //    pthread_mutex_unlock (&smsMutex);
237       if (phoneMonitor.sms.number == number)
238       {
239         pthread_cond_signal (&smsCond);
240         pthread_mutex_unlock (&smsMutex);
241         return;
242       }
243     }
244     else if (error == GE_INVALIDSMSLOCATION)  /* All positions are readed */
245     {
246       g_free (msg);
247       pthread_cond_signal (&smsCond);
248       pthread_mutex_unlock (&smsMutex);
249       break;
250     }
251     else
252       g_free (msg);
253
254     usleep (750000);
255   }
256 }
257
258
259 static gint A_SendSMSMessage (gpointer data)
260 {
261   D_SMSMessage *d = (D_SMSMessage *) data;
262   GSM_Error error;
263
264   error = d->status = GE_UNKNOWN;
265   if (d)
266   {
267     pthread_mutex_lock (&sendSMSMutex);
268     error = d->status = GSM->SendSMSMessage (d->sms, 0);
269     pthread_cond_signal (&sendSMSCond);
270     pthread_mutex_unlock (&sendSMSMutex);
271   }
272
273   if (d->status == GE_SMSSENDOK)
274     return (GE_NONE);
275   else
276     return (error);
277 }
278
279
280 static gint A_DeleteSMSMessage (gpointer data)
281 {
282   GSM_SMSMessage *sms = (GSM_SMSMessage *) data;
283   GSM_Error error = GE_UNKNOWN;
284
285   if (sms)
286   {
287     error = GSM->DeleteSMSMessage(sms);
288 //    I don't use copy, I don't need free message.
289 //    g_free (sms);
290   }
291
292   return (error);
293 }
294
295
296 static gint A_Exit (gpointer data)
297 {
298   pthread_exit (0);
299   return (0); /* just to be proper */
300 }
301
302
303 gint (*DoAction[])(gpointer) = {
304   A_SendSMSMessage,
305   A_DeleteSMSMessage,
306   A_Exit
307 };
308
309
310 void *Connect (void *a)
311 {
312   GSM_SMSMemoryStatus SMSStatus = {0, 0};
313   PhoneEvent *event;
314   GSM_Error error;
315
316
317 # ifdef XDEBUG
318   g_print ("Initializing connection...\n");
319 # endif
320
321   while (!fbusinit (true))
322     sleep (1);
323
324 # ifdef XDEBUG
325   g_print ("Phone connected. Starting monitoring...\n");
326 # endif
327
328   while (1)
329   {
330     phoneMonitor.working = FALSE;
331
332     if (GSM->GetSMSStatus (&SMSStatus) == GE_NONE)
333     {
334       if (phoneMonitor.sms.unRead != SMSStatus.Unread ||
335           phoneMonitor.sms.number != SMSStatus.Number)
336       {
337         phoneMonitor.working = TRUE;
338         RefreshSMS (SMSStatus.Number);
339         phoneMonitor.working = FALSE;
340       }
341
342       phoneMonitor.sms.unRead = SMSStatus.Unread;
343     }
344
345     while ((event = RemoveEvent ()) != NULL)
346     {
347 #     ifdef XDEBUG      
348       g_print ("Processing Event: %d\n", event->event);
349 #     endif
350       phoneMonitor.working = TRUE;
351       if (event->event <= Event_Exit)
352         if ((error = DoAction[event->event] (event->data)) != GE_NONE)
353           g_print (_("Event %d failed with return code %d!\n"), event->event, error);
354       g_free (event);
355     }
356   }
357 }