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