default platform: i386 (not m68k)
[gnokii.git] / common / gsm-api.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8         
9   Provides a generic API for accessing functions on the phone, wherever
10   possible hiding the model specific details.
11
12   The underlying code should run in it's own thread to allow communications to
13   the phone to be run independantly of mailing code that calls these API
14   functions.
15
16   Unless otherwise noted, all functions herein block until they complete.  The
17   functions themselves are defined in a structure in gsm-common.h.
18
19 */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <time.h>
27
28 #ifdef WIN32
29   #include <windows.h>
30   #include "misc_win32.h"
31 #endif
32
33 #include "gsm-api.h"
34
35 #ifndef UCLINUX
36 #include "newmodules/n3110.h"
37 #include "newmodules/n6110.h"
38 #include "newmodules/n7110.h"
39 #include "newmodules/newat.h"
40 #ifdef DEBUG
41   #include "newmodules/sniff/sniff.h"
42 #endif
43 #include "protocol/fbusirda.h"
44 #endif /* UCLINUX */
45 #include "protocol/fbus.h"
46 #ifndef UCLINUX
47 #include "protocol/fbus3110.h"
48 #include "protocol/mbus.h"
49 #include "protocol/at.h"
50 #endif /* UCLINUX */
51 #include "files/cfgreader.h"
52
53 #ifndef WIN32
54   #include "devices/device.h"
55 #endif
56
57 #ifdef VC6
58   /* for VC6 make scripts save VERSION constant in mversion.h file */
59   #include "mversion.h"
60 #endif
61
62 /* GSM_LinkOK is set to true once normal communications with the phone have
63    been established. */
64
65 bool *GSM_LinkOK;
66
67 /* Define pointer to the GSM_Functions structure used by external code to call
68    relevant API functions. This structure is defined in gsm-common.h. */
69
70 GSM_Functions *GSM;
71
72 /* Define pointer to the GSM_Information structure used by external code to
73    obtain information that varies from model to model. This structure is also
74    defined in gsm-common.h */
75
76 GSM_Information         *GSM_Info;
77
78 /* Initialise interface to the phone. Model number should be a string such as
79    3810, 5110, 6110 etc. Device is the serial port to use e.g. /dev/ttyS0, the
80    user must have write permission to the device. */
81
82 GSM_Protocol *Protocol;
83
84 /* Local variables used by get/set phonebook entry code. Buffer is used as a
85    source or destination for phonebook data and other functions... Error is
86    set to GE_NONE by calling function, set to GE_COMPLETE or an error code by
87    handler routines as appropriate. */
88                                    
89 GSM_PhonebookEntry *CurrentPhonebookEntry;
90 GSM_Error          CurrentPhonebookError;
91
92 GSM_SpeedDial      *CurrentSpeedDialEntry;
93 GSM_Error          CurrentSpeedDialError;
94
95 unsigned char      Current_IMEI[GSM_MAX_IMEI_LENGTH];
96 unsigned char      Current_Revision[GSM_MAX_REVISION_LENGTH];
97 unsigned char      Current_Model[GSM_MAX_MODEL_LENGTH];
98
99 #ifndef UCLINUX
100 GSM_SMSMessage     *CurrentSMSMessage;
101 GSM_Error          CurrentSMSMessageError;
102 int                CurrentSMSPointer;
103
104 GSM_SMSFolders      *CurrentSMSFolders;
105 GSM_Error          CurrentSMSFoldersError;
106 int                CurrentSMSFoldersCount;
107
108 GSM_OneSMSFolder   CurrentSMSFolder;
109 GSM_Error          CurrentSMSFolderError;
110 int                CurrentSMSFolderID;
111 #endif /* UCLINUX */
112
113 GSM_MemoryStatus   *CurrentMemoryStatus;
114 GSM_Error          CurrentMemoryStatusError;
115
116 #ifndef UCLINUX
117 GSM_NetworkInfo    *CurrentNetworkInfo;
118 GSM_Error          CurrentNetworkInfoError;
119
120 GSM_SMSStatus      *CurrentSMSStatus;
121 GSM_Error          CurrentSMSStatusError;
122
123 GSM_MessageCenter  *CurrentMessageCenter;
124 GSM_Error          CurrentMessageCenterError;
125
126 int                *CurrentSecurityCodeStatus;
127 GSM_Error          CurrentSecurityCodeError;
128 GSM_SecurityCode   *CurrentSecurityCode;
129
130 GSM_DateTime       *CurrentDateTime;
131 GSM_Error          CurrentDateTimeError;
132
133 GSM_Error          CurrentResetPhoneSettingsError;
134
135 GSM_DateTime       *CurrentAlarm;
136 GSM_Error          CurrentAlarmError;
137
138 GSM_CalendarNote   *CurrentCalendarNote;
139 GSM_Error          CurrentCalendarNoteError;
140
141 GSM_NotesInfo      CurrentCalendarNotesInfo,*CurrentCalendarNotesInfo2;
142 GSM_Error          CurrentCalendarNotesInfoError;
143
144 GSM_Error          CurrentSetDateTimeError;
145 GSM_Error          CurrentSetAlarmError;
146
147 int                *CurrentFirstCalendarFreePos;
148 GSM_Error          CurrentFirstCalendarFreePosError;
149 #endif /* UCLINUX */
150
151 GSM_Error          CurrentEnableExtendedCommandsError;
152
153 int                CurrentRFLevel,
154                    CurrentBatteryLevel,
155                    CurrentPowerSource;
156
157 #ifndef UCLINUX
158 int                CurrentDisplayStatus;
159 GSM_Error          CurrentDisplayStatusError;
160
161 char               *CurrentNetmonitor;
162 GSM_Error          CurrentNetmonitorError;
163
164 GSM_Bitmap         *CurrentGetBitmap=NULL;
165 GSM_Error          CurrentGetBitmapError;
166
167 GSM_Error          CurrentSetBitmapError;
168
169 GSM_Error          CurrentSendDTMFError;
170
171 GSM_Profile        *CurrentProfile;
172 GSM_Error          CurrentProfileError;
173
174 GSM_Error          CurrentDisplayOutputError;
175
176 GSM_CBMessage      *CurrentCBMessage;
177 GSM_Error          CurrentCBError;
178
179 int                CurrentPressKeyEvent;
180 GSM_Error          CurrentPressKeyError;
181
182 GSM_Error          CurrentPlayToneError=GE_UNKNOWN;
183 #endif /* UCLINUX */
184
185 GSM_Error          CurrentDialVoiceError;
186
187 #ifndef UCLINUX
188 GSM_Error          CurrentGetOperatorNameError;
189 GSM_Network        *CurrentGetOperatorNameNetwork;
190 GSM_Error          CurrentSetOperatorNameError;
191 #endif /* UCLINUX */
192
193 GSM_Error          CurrentGetIMEIError;
194
195 GSM_Error          CurrentGetHWError;
196
197 #ifndef UCLINUX
198 unsigned char      CurrentPPS[4];
199 GSM_Error          CurrentProductProfileSettingsError;
200
201 char               CurrentIncomingCall[20];
202
203 GSM_Error          CurrentBinRingtoneError;
204 GSM_BinRingtone    *CurrentGetBinRingtone=NULL;
205
206 GSM_Error          CurrentRingtoneError;
207 #endif /* UCLINUX */
208
209 GSM_Error          CurrentMagicError;
210
211 #ifndef UCLINUX
212 GSM_Error          CurrentSimlockInfoError;
213 GSM_AllSimlocks    *CurrentSimLock;
214
215 GSM_Error          CurrentGetWAPBookmarkError;
216 GSM_Error          CurrentSetWAPBookmarkError;
217 GSM_WAPBookmark    *WAPBookmark;
218
219 GSM_Error          CurrentGetWAPSettingsError;
220 GSM_WAPSettings    *WAPSettings;
221
222 GSM_Error          CurrentCallDivertError;
223 GSM_CallDivert    *CurrentCallDivert;
224
225 char              *CurrentManufacturer;
226 #endif /* UCLINUX */
227
228 /* This is the connection type used in gnokii. */
229 GSM_ConnectionType CurrentConnectionType;
230
231 /* Pointer to a callback function used to return changes to a calls status */
232 /* This saves unreliable polling */
233 void (*CurrentCallPassup)(char c);
234
235 /* Pointer to callback function in user code to be called when RLP frames
236    are received. */
237 void (*CurrentRLP_RXCallback)(RLP_F96Frame *frame);
238
239 /* Used to disconnect the call */
240 u8 CurrentCallSequenceNumber;
241
242 bool CurrentLinkOK;
243
244 bool CurrentRequestTerminate;
245
246 #ifndef UCLINUX
247 bool CurrentDisableKeepAlive;
248 #endif /* UCLINUX */
249
250 #ifdef UCLINUX
251 static
252 #endif /* UCLINUX */
253 bool CheckModel (GSM_Information InfoToCheck, char *model, GSM_ConnectionType connection) {
254
255   bool found_match=false;
256
257   if (strstr(InfoToCheck.FBUSModels, model) != NULL) {
258     if (connection==GCT_FBUS) found_match=true;
259   }
260 #ifndef UCLINUX
261   if (strstr(InfoToCheck.MBUSModels, model) != NULL) {
262     if (connection==GCT_MBUS) found_match=true;
263   }
264   if (strstr(InfoToCheck.InfraredModels, model) != NULL) {
265     if (connection==GCT_Infrared) found_match=true;
266   }
267   if (strstr(InfoToCheck.DLR3Models, model) != NULL) {
268     if (connection==GCT_DLR3) found_match=true;
269   }
270   if (strstr(InfoToCheck.IrdaModels, model) != NULL) {
271     if (connection==GCT_Irda) found_match=true;
272   }
273   if (strstr(InfoToCheck.ATModels, model) != NULL) {
274     if (connection==GCT_AT) found_match=true;
275   }
276   if (strstr(InfoToCheck.TekramModels, model) != NULL) {
277     if (connection==GCT_Tekram) found_match=true;
278   }
279   if (strstr(InfoToCheck.FBUS3110Models, model) != NULL) {
280     if (connection==GCT_FBUS3110) found_match=true;
281   }
282 #endif /* UCLINUX */
283
284   return found_match;
285 }
286  
287 #ifndef UCLINUX
288
289 GSM_Error TryNewNokia(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) {
290   int InitLength;
291   int count;
292   unsigned char init_char = N6110_SYNC_BYTE;
293
294   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
295   char phonemodel[64];
296
297   if (Protocol->Initialise(device,initlength,connection,rlp_callback)!=GE_NONE)
298   {
299     return GE_NOTSUPPORTED; 
300   }
301
302   if (connection!=GCT_MBUS) {
303     InitLength = atoi(initlength);
304
305     if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
306       InitLength = 250; /* This is the usual value, lower may work. */
307     }
308
309 #ifdef DEBUG
310     fprintf(stdout,_("Writing init chars...."));
311 #endif
312
313     /* Initialise link with phone or what have you */
314     /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
315        empirical. */
316     for (count = 0; count < InitLength; count ++) {
317       usleep(100);
318       Protocol->WritePhone(1,&init_char);
319     }
320
321 #ifdef DEBUG
322     fprintf(stdout,_("Done\n"));  
323 #endif
324
325     N6110_SendStatusRequest();
326   }
327
328   usleep(100);
329
330   if (N6110_SendIDFrame()!=GE_NONE)
331     return GE_TIMEOUT;
332  
333   while (N6110_GetModel(phonemodel) != GE_NONE)
334     sleep(1);
335
336 #ifndef UCLINUX
337   if (!strcmp(phonemodel,"NPE-3") || !strcmp(phonemodel,"NSE-5") || 
338       !strcmp(phonemodel,"NHM-3"))
339   {
340     GSM->Terminate();      
341     
342     /* Set pointers to relevant addresses */
343     GSM = &N7110_Functions;
344     GSM_Info = &N7110_Information;
345     GSM_LinkOK = &CurrentLinkOK;
346     return GE_NONE;
347   }
348 #endif /* UCLINUX */
349
350   return GE_NONE;
351 }
352 #endif /* UCLINUX */
353
354 extern GSM_Information N6110_Information;
355 extern GSM_Functions   N6110_Functions;
356
357 GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), char* SynchronizeTime)
358 {
359   bool found_match=false;
360   
361   GSM_ConnectionType connection2;
362
363 #ifndef UCLINUX
364   struct tm *now;
365   time_t nowh;
366   GSM_DateTime Date;
367 #endif /* UCLINUX */
368   GSM_Error error;
369   
370   connection2=connection;
371
372   CurrentRLP_RXCallback = rlp_callback;
373   CurrentCallPassup=NULL;
374 #ifndef UCLINUX
375   CurrentCallDivert=NULL;
376 #endif /* UCLINUX */
377   CurrentPhonebookEntry=NULL;
378 #ifndef UCLINUX
379   CurrentNetworkInfo = NULL;
380   CurrentGetBitmap=NULL;
381   CurrentPlayToneError=GE_UNKNOWN;
382   strcpy(CurrentIncomingCall," ");
383   CurrentGetBinRingtone=NULL;
384   CurrentNetworkInfo=NULL;
385 #endif /* UCLINUX */
386   CurrentRequestTerminate=false;
387 #ifndef UCLINUX
388   CurrentDisableKeepAlive=false;
389   CurrentCalendarNotesInfo.HowMany=2000;
390   CurrentSMSMessage=NULL;
391 #endif /* UCLINUX */
392   CurrentMagicError = GE_BUSY;  
393   
394 #ifndef UCLINUX
395   if (!strcmp(model,"auto")) {
396
397     /* For now */
398     GSM = &N6110_Functions;
399     GSM_Info = &N6110_Information;
400     GSM_LinkOK = &CurrentLinkOK;
401 #ifdef DEBUG
402     fprintf(stdout,_("Trying FBUS for new Nokia phones...\n"));
403 #endif
404     /* Trying FBUS */
405     Protocol = &FBUS_Functions;
406     CurrentConnectionType=GCT_FBUS;    
407     connection2=GCT_FBUS;
408     if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
409     {
410       found_match=true;
411     } else {
412       GSM->Terminate();      
413     }
414
415     if (!found_match) {
416       usleep(100);          
417       
418       /* For now */
419       GSM = &N6110_Functions;
420       GSM_Info = &N6110_Information;
421       GSM_LinkOK = &CurrentLinkOK;
422 #ifdef DEBUG
423       fprintf(stdout,_("Trying DLR3 for new Nokia phones...\n"));
424 #endif
425       /* Trying DLR3 */
426       Protocol = &FBUS_Functions;
427       CurrentConnectionType=GCT_DLR3;    
428       connection2=GCT_DLR3;
429       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
430       {
431         found_match=true;
432       } else {
433         GSM->Terminate();      
434       }
435     }
436     
437     if (!found_match) {
438       usleep(100);          
439       
440       /* For now */
441       GSM = &N6110_Functions;
442       GSM_Info = &N6110_Information;
443       GSM_LinkOK = &CurrentLinkOK;
444 #ifdef DEBUG
445       fprintf(stdout,_("Trying MBUS for new Nokia phones...\n"));
446 #endif
447       /* Trying MBUS */
448       Protocol = &MBUS_Functions;
449       CurrentConnectionType=GCT_MBUS;    
450       connection2=GCT_MBUS;
451       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
452       {
453         found_match=true;
454       } else {
455         GSM->Terminate();      
456       }
457     }
458
459     if (!found_match) return GE_NOTSUPPORTED;
460
461     usleep(50);
462         
463   } else {
464     if (!strcmp(model,"modelauto")) {
465       /* For now */
466       GSM = &N6110_Functions;
467       GSM_Info = &N6110_Information;
468       GSM_LinkOK = &CurrentLinkOK;
469 #ifdef DEBUG
470       fprintf(stdout,_("Trying to find connected model...\n"));
471 #endif
472       switch (connection) {
473         case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
474         case GCT_Infrared: Protocol = &FBUS_Functions;    break;
475         case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
476         case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
477         case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
478         case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
479         case GCT_AT      : Protocol = &AT_Functions;      break;
480         case GCT_FBUS3110: Protocol = &FBUS3110_Functions;break;
481       }
482       CurrentConnectionType=connection;    
483       connection2=connection;
484       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
485       {
486         found_match=true;
487       } else {
488         GSM->Terminate();      
489       }
490
491       if (!found_match) return GE_NOTSUPPORTED;
492
493       usleep(50);
494
495   } else
496 #endif /* UCLINUX */
497                 {
498 #ifndef UCLINUX
499 #ifdef DEBUG
500       if (CheckModel (Nsniff_Information, model, connection)) {
501         /* Set pointers to relevant addresses */
502         GSM = &Nsniff_Functions;
503         GSM_Info = &Nsniff_Information;
504         GSM_LinkOK = &CurrentLinkOK;
505         found_match=true;
506       }
507 #endif
508
509       if (CheckModel (N3110_Information, model, connection)) {
510         /* Set pointers to relevant addresses */
511         GSM = &N3110_Functions;
512         GSM_Info = &N3110_Information;
513         GSM_LinkOK = &CurrentLinkOK;
514         found_match=true;
515       }
516 #endif /* UCLINUX */
517       if (CheckModel (N6110_Information, model, connection)) {
518         /* Set pointers to relevant addresses */
519         GSM = &N6110_Functions;
520         GSM_Info = &N6110_Information;
521         GSM_LinkOK = &CurrentLinkOK;
522         found_match=true;
523       }
524 #ifndef UCLINUX
525       if (CheckModel (N7110_Information, model, connection)) {
526         /* Set pointers to relevant addresses */
527         GSM = &N7110_Functions;
528         GSM_Info = &N7110_Information;
529         GSM_LinkOK = &CurrentLinkOK;
530         found_match=true;
531       }
532       if (CheckModel (Nat_Information, model, connection)) {
533         /* Set pointers to relevant addresses */
534         GSM = &Nat_Functions;
535         GSM_Info = &Nat_Information;
536         GSM_LinkOK = &CurrentLinkOK;
537         found_match=true;
538       }
539 #endif /* UCLINUX */
540
541       if (found_match) {
542         switch (connection) {
543           case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
544 #ifndef UCLINUX
545           case GCT_Infrared: Protocol = &FBUS_Functions;    break;
546           case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
547           case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
548           case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
549           case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
550           case GCT_AT      : Protocol = &AT_Functions;      break;
551           case GCT_FBUS3110: Protocol = &FBUS3110_Functions;break;
552 #endif /* UCLINUX */
553         }
554       } else
555         return GE_NOTSUPPORTED;
556     }
557 #ifndef UCLINUX
558   }
559 #endif /* UCLINUX */
560
561     
562   /* Now call model specific initialisation code. */
563   error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
564
565 #ifndef UCLINUX
566   /* RTH: FIXME: second try for Irda (6210 only?)*/
567   if ( error!=GE_NONE && connection == GCT_Irda)
568   {
569    #ifdef DEBUG
570      fprintf(stdout,"Irda connection: second try!\n");
571    #endif
572    device_close();
573    error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
574   }
575 #endif /* UCLINUX */
576
577 #ifndef UCLINUX
578   if (error==GE_NONE && !strcmp(SynchronizeTime,"yes"))
579   {
580     nowh=time(NULL);
581     now=localtime(&nowh);
582
583     Date.Year = now->tm_year;
584     Date.Month = now->tm_mon+1;
585     Date.Day = now->tm_mday;
586     Date.Hour = now->tm_hour;
587     Date.Minute = now->tm_min;
588     Date.Second = now->tm_sec;
589
590     if (Date.Year<1900)
591     {
592
593       /* Well, this thing is copyrighted in U.S. This technique is known as
594          Windowing and you can read something about it in LinuxWeekly News:
595          http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
596          written in Czech republic and Poland where algorithms are not allowed
597          to be patented. */
598
599       if (Date.Year>90)
600         Date.Year = Date.Year+1900;
601       else
602         Date.Year = Date.Year+2000;
603     }
604
605     /* FIXME: Error checking should be here. */
606     GSM->SetDateTime(&Date);
607   }
608 #endif /* UCLINUX */
609
610   return error;
611 }
612
613 #ifndef UCLINUX
614
615 GSM_Error Unimplemented(void)
616 {
617         return GE_NOTIMPLEMENTED;
618 }
619
620 GSM_Error NotSupported(void)
621 {
622         return GE_NOTSUPPORTED;
623 }
624
625 #endif /* UCLINUX */
626
627 /* Applications should call N6110_Terminate to shut down the N6110 thread and
628    close the serial port. */
629 void NULL_Terminate(void)
630 {
631   Protocol->Terminate();
632 }
633
634 #ifdef WIN32
635 /* Here are things made for keeping connecting */
636 void NULL_KeepAlive()
637 {
638 }
639 #else
640 /* Here are things made for keeping connecting */
641 void NULL_KeepAlive()
642 {
643 }
644 #endif
645
646 #ifdef DEBUG
647 void NULL_TX_DisplayMessage(u16 MessageLength, u8 *MessageBuffer)
648 {
649   fprintf(stdout, _("PC: "));
650
651   txhexdump(MessageLength,MessageBuffer);
652 }
653 #endif
654
655 bool NULL_WritePhone (u16 length, u8 *buffer) {
656   if (device_write(buffer,length)!=length) return false;
657                                       else return true;
658 }
659
660 GSM_Error NULL_WaitUntil (int time, GSM_Error *value)
661 {
662   int timeout;
663
664   timeout=time;
665   
666   /* Wait for timeout or other error. */
667   while (timeout != 0 && *value == GE_BUSY ) {
668           
669     if (--timeout == 0)
670       return (GE_TIMEOUT);
671                     
672     usleep (100000);
673   }
674
675   return *value;
676 }
677
678 GSM_Error NULL_SendMessageSequence (int time, GSM_Error *value,
679                  u16 message_length, u8 message_type, u8 *buffer)
680 {
681   *value=GE_BUSY;
682   
683   Protocol->SendMessage(message_length, message_type, buffer);  
684
685   return NULL_WaitUntil (time, value);
686 }
687
688 GSM_ConnectionType GetConnectionTypeFromString(char *Connection) {
689
690   GSM_ConnectionType connection=GCT_FBUS;
691
692 #ifndef UCLINUX
693   if (!strcmp(Connection, "irda"))     connection=GCT_Irda;
694   if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
695   if (!strcmp(Connection, "mbus"))     connection=GCT_MBUS;
696   if (!strcmp(Connection, "dlr3"))     connection=GCT_DLR3;
697   if (!strcmp(Connection, "fbus3110")) connection=GCT_FBUS3110;
698   if (!strcmp(Connection, "at"))       connection=GCT_AT;
699   if (!strcmp(Connection, "tekram210"))connection=GCT_Tekram;
700 #endif /* UCLINUX */
701   
702   return connection;
703 }
704
705 bool GetMemoryTypeString(char *memorytext, GSM_MemoryType *type)
706 {
707   int i=0;
708
709   typedef struct {
710     GSM_MemoryType type;
711     char *name;
712   } GSM_MTStrings;
713
714 static  GSM_MTStrings mystring[] = {
715     {GMT_ME,"ME"},
716     {GMT_SM,"SM"},
717     {GMT_FD,"FD"},
718     {GMT_ON,"ON"},
719     {GMT_EN,"EN"},
720     {GMT_DC,"DC"},
721     {GMT_RC,"RC"},  
722     {GMT_MC,"MC"},
723     {GMT_LD,"LD"},
724     {GMT_MT,"MT"},
725     {GMT_ME,"undefined"}
726   };
727
728   while (strcmp(mystring[i].name,"undefined")) {
729     if (*type==mystring[i].type) {
730       strcpy(memorytext,mystring[i].name);
731       return true;
732     }
733     i++;
734   }
735   return false;
736 }
737
738 bool GetMemoryTypeID(char *memorytext, GSM_MemoryType *type)
739 {
740   int i=0;
741
742   typedef struct {
743     GSM_MemoryType type;
744     char *name;
745   } GSM_MTStrings;
746
747 static  GSM_MTStrings mystring[] = {
748     {GMT_ME,"ME"},
749     {GMT_SM,"SM"},
750     {GMT_FD,"FD"},
751     {GMT_ON,"ON"},
752     {GMT_EN,"EN"},
753     {GMT_DC,"DC"},
754     {GMT_RC,"RC"},  
755     {GMT_MC,"MC"},
756     {GMT_LD,"LD"},
757     {GMT_MT,"MT"},
758     {GMT_ME,"undefined"}
759   };
760
761   while (strcmp(mystring[i].name,"undefined")) {
762     if (strcmp(mystring[i].name,memorytext)==0) {
763       *type=mystring[i].type;
764       return true;
765     }
766     i++;
767   }
768
769   return false;
770 }
771
772 char *GetMygnokiiVersion() {
773
774   static char Buffer[1000]="";
775
776   sprintf(Buffer, "%s",VERSION);
777
778   return Buffer;
779 }
780
781 /*
782 1.Name,2.CodeName,3.Calendar,4.Netmonitor,5.Caller groups,6.Phonebook,
783 7.Authentication 8.Datacalls 9.KeysPressing 10.SMSC Default Recipient
784 11.SpeedDials 12.ScreenSavers 13.DTMF 14.SMS 15.NoPowerFrame 16.StartUpLogo
785 17.Profiles 18.Ringtones 19.WAP 20.RIngtonesNumber
786 */
787
788 static OnePhoneModel allmodels[] = {
789
790 /*1,    2,       3,      4,       5,        6          7      8        9      10        11      12       13     14      15        16       17       18        19    20 */
791 {"3210","NSE-8",{      0,F_NETMON,        0,         0,     0,       0,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF51,F_RINGBIN,    0, 2}},
792 {"3210","NSE-9",{      0,F_NETMON,        0,         0,     0,       0,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF51,F_RINGBIN,    0, 2}},
793 {"3310","NHM-5",{F_CAL33,F_NETMON,        0,F_PBK33SIM,     0,       0,     0,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF33,F_RING_SM,    0, 7}},
794 {"3330","NHM-6",{F_CAL33,F_NETMON,        0,F_PBK33INT,     0,       0,F_KEYB,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,        0,F_STANIM,F_PROF33,F_RING_SM,F_WAP, 7}},
795 {"5110","NSE-1",{      0,F_NETMON,        0,         0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0, 0}},
796 {"5130","NSK-1",{      0,F_NETMON,        0,         0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0, 0}},
797 {"5190","NSB-1",{      0,F_NETMON,        0,         0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0, 0}},
798 {"6110","NSE-3",{F_CAL61,F_NETMON,F_CALER61,F_PBK61INT,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
799 {"6130","NSK-3",{F_CAL61,F_NETMON,F_CALER61,F_PBK61INT,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
800 {"6150","NSM-1",{F_CAL61,F_NETMON,F_CALER61,F_PBK61INT,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
801 {"6190","NSB-3",{F_CAL61,F_NETMON,F_CALER61,F_PBK61INT,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
802 {"6210","NPE-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71INT,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP, 5}},
803 {"6250","NHM-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71INT,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP, 5}},       
804 {"7110","NSE-5",{F_CAL71,F_NETMON,F_CALER61,F_PBK71INT,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA71 ,F_PROF61,F_RINGBIN,F_WAP, 5}},
805 {"8210","NSM-3",{      0,F_NETMON,F_CALER61,F_PBK61INT,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
806 {"8850","NSM-2",{      0,F_NETMON,F_CALER61,F_PBK61INT,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 1}},
807 {"9210","RAE-3",{      0,F_NETMON,F_CALER61,         0,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0, 0}},//quesses only !
808 {""    ,""     ,{      0,       0,        0,         0,     0,       0,     0,        0,      0,       0,     0,      0,        0,       0,       0,        0,    0, 0}}
809 };
810
811 static OnePhoneModel *GetPhoneModelData (const char *num)
812 {
813         register int i = 0;
814
815         while (allmodels[i].number != "") {
816                 if (strcmp (num, allmodels[i].number) == 0) {
817                         return (&allmodels[i]);
818                 }
819                 i++;
820         }
821
822         return (&allmodels[i]);
823 }
824
825 char *GetModelName ()
826 {
827   static char model[64];
828
829   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
830
831   return (GetPhoneModelData(model)->model);
832 }
833
834 int GetModelFeature (featnum_index num)
835 {
836   static char model[64];
837
838   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
839
840   return (GetPhoneModelData(model)->features[num]);
841 }
842
843 #ifndef UCLINUX
844 int LogAvailable=-1; //-1 not checked earlier, 0 not, 1 yes
845 char *logfilename;
846
847 bool AppendLog(u8 *buffer, int length,bool format)
848 {
849   FILE *file=NULL;
850   char buffer2[50001];
851   int i;
852
853   struct CFG_Header *cfg_info;
854   char *LogFile;        
855
856   if (LogAvailable==-1) {
857
858     LogAvailable=0;
859
860     cfg_info=CFG_FindGnokiirc();
861     if (cfg_info==NULL) return false;
862
863     LogFile = CFG_Get(cfg_info, "global", "logfile");
864     if (LogFile) {
865       LogAvailable=1;
866       logfilename=LogFile;
867
868       file=fopen(logfilename, "a+");
869
870       /* We have first entry in this session and too large file */
871       if (fread( buffer2, 1, 50000,file )==50000) {
872         fclose(file);
873         file=fopen(logfilename, "w");
874       }
875     }
876   } else {
877     if (LogAvailable==1) {
878       file=fopen(logfilename, "a");
879     }
880   }
881   
882   if (LogAvailable==1) {
883     for (i=0;i<length;i++) {
884       if (format) {
885         fprintf(file, "%02x",buffer[i]);
886         switch (buffer[i]) {
887           case 0x09:fprintf(file,_(" |"));break;
888           default:
889             if (isprint(buffer[i])) fprintf(file, _("%c|"),buffer[i]);
890                                else fprintf(file, _(" |"));
891             break;
892         } 
893       } else {
894         fprintf(file, "%c",buffer[i]);
895       }
896     }
897     if (format) fprintf(file, "\n");
898     fclose(file);
899   }
900
901   return (LogAvailable==1);
902 }
903
904 bool AppendLogText(u8 *buffer,bool format)
905 {
906   return AppendLog(buffer,strlen(buffer),format);
907 }
908 #endif /* UCLINUX */