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