4546e1438eeed5ba432f3f13d79beada5ab8a7d2
[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/n6110.h"
37 #include "newmodules/n7110.h"
38 #include "newmodules/newat.h"
39 #ifdef DEBUG
40   #include "newmodules/sniff/sniff.h"
41 #endif
42 #include "protocol/fbusirda.h"
43 #endif /* UCLINUX */
44 #include "protocol/fbus.h"
45 #ifndef UCLINUX
46 #include "protocol/mbus.h"
47 #include "protocol/at.h"
48 #endif /* UCLINUX */
49 #include "files/cfgreader.h"
50
51 #ifndef WIN32
52   #include "devices/device.h"
53 #endif
54
55 #ifdef VC6
56   /* for VC6 make scripts save VERSION constant in mversion.h file */
57   #include "mversion.h"
58 #endif
59
60 /* GSM_LinkOK is set to true once normal communications with the phone have
61    been established. */
62
63 bool *GSM_LinkOK;
64
65 /* Define pointer to the GSM_Functions structure used by external code to call
66    relevant API functions. This structure is defined in gsm-common.h. */
67
68 GSM_Functions *GSM;
69
70 /* Define pointer to the GSM_Information structure used by external code to
71    obtain information that varies from model to model. This structure is also
72    defined in gsm-common.h */
73
74 GSM_Information         *GSM_Info;
75
76 /* Initialise interface to the phone. Model number should be a string such as
77    3810, 5110, 6110 etc. Device is the serial port to use e.g. /dev/ttyS0, the
78    user must have write permission to the device. */
79
80 GSM_Protocol *Protocol;
81
82 /* Local variables used by get/set phonebook entry code. Buffer is used as a
83    source or destination for phonebook data and other functions... Error is
84    set to GE_NONE by calling function, set to GE_COMPLETE or an error code by
85    handler routines as appropriate. */
86                                    
87 GSM_PhonebookEntry *CurrentPhonebookEntry;
88 GSM_Error          CurrentPhonebookError;
89
90 #ifndef UCLINUX
91 GSM_SpeedDial      *CurrentSpeedDialEntry;
92 GSM_Error          CurrentSpeedDialError;
93 #endif /* UCLINUX */
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 #endif /* UCLINUX */
280
281   return found_match;
282 }
283  
284 #ifndef UCLINUX
285
286 GSM_Error TryNewNokia(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) {
287   int InitLength;
288   int count;
289   unsigned char init_char = N6110_SYNC_BYTE;
290
291   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
292   char phonemodel[64];
293
294   if (Protocol->Initialise(device,initlength,connection,rlp_callback)!=GE_NONE)
295   {
296     return GE_NOTSUPPORTED; 
297   }
298
299   if (connection!=GCT_MBUS) {
300     InitLength = atoi(initlength);
301
302     if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
303       InitLength = 250; /* This is the usual value, lower may work. */
304     }
305
306 #ifdef DEBUG
307     fprintf(stdout,_("Writing init chars...."));
308 #endif
309
310     /* Initialise link with phone or what have you */
311     /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
312        empirical. */
313     for (count = 0; count < InitLength; count ++) {
314       usleep(100);
315       Protocol->WritePhone(1,&init_char);
316     }
317
318 #ifdef DEBUG
319     fprintf(stdout,_("Done\n"));  
320 #endif
321
322     N6110_SendStatusRequest();
323   }
324
325   usleep(100);
326
327   if (N6110_SendIDFrame()!=GE_NONE)
328     return GE_TIMEOUT;
329  
330   while (N6110_GetModel(phonemodel) != GE_NONE)
331     sleep(1);
332
333 #ifndef UCLINUX
334   if (!strcmp(phonemodel,"NPE-3") || !strcmp(phonemodel,"NSE-5"))
335   {
336     GSM->Terminate();      
337     
338     /* Set pointers to relevant addresses */
339     GSM = &N7110_Functions;
340     GSM_Info = &N7110_Information;
341     GSM_LinkOK = &CurrentLinkOK;
342     return GE_NONE;
343   }
344 #endif /* UCLINUX */
345
346   return GE_NONE;
347 }
348 #endif /* UCLINUX */
349
350 extern GSM_Information N6110_Information;
351 extern GSM_Functions   N6110_Functions;
352
353 GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), char* SynchronizeTime)
354 {
355   bool found_match=false;
356   
357   GSM_ConnectionType connection2;
358
359 #ifndef UCLINUX
360   struct tm *now;
361   time_t nowh;
362   GSM_DateTime Date;
363 #endif /* UCLINUX */
364   GSM_Error error;
365   
366   connection2=connection;
367
368   CurrentRLP_RXCallback = rlp_callback;
369   CurrentCallPassup=NULL;
370   CurrentPhonebookEntry=NULL;
371 #ifndef UCLINUX
372   CurrentNetworkInfo = NULL;
373   CurrentGetBitmap=NULL;
374   CurrentPlayToneError=GE_UNKNOWN;
375   strcpy(CurrentIncomingCall," ");
376   CurrentGetBinRingtone=NULL;
377   CurrentNetworkInfo=NULL;
378 #endif /* UCLINUX */
379   CurrentRequestTerminate=false;
380 #ifndef UCLINUX
381   CurrentDisableKeepAlive=false;
382   CurrentCalendarNotesInfo.HowMany=2000;
383 #endif /* UCLINUX */
384   CurrentMagicError = GE_BUSY;  
385   
386 #ifndef UCLINUX
387   if (!strcmp(model,"auto")) {
388
389     /* For now */
390     GSM = &N6110_Functions;
391     GSM_Info = &N6110_Information;
392     GSM_LinkOK = &CurrentLinkOK;
393 #ifdef DEBUG
394     fprintf(stdout,_("Trying FBUS for new Nokia phones...\n"));
395 #endif
396     /* Trying FBUS */
397     Protocol = &FBUS_Functions;
398     CurrentConnectionType=GCT_FBUS;    
399     connection2=GCT_FBUS;
400     if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
401     {
402       found_match=true;
403     } else {
404       GSM->Terminate();      
405     }
406
407     if (!found_match) {
408       usleep(100);          
409       
410       /* For now */
411       GSM = &N6110_Functions;
412       GSM_Info = &N6110_Information;
413       GSM_LinkOK = &CurrentLinkOK;
414 #ifdef DEBUG
415       fprintf(stdout,_("Trying DLR3 for new Nokia phones...\n"));
416 #endif
417       /* Trying DLR3 */
418       Protocol = &FBUS_Functions;
419       CurrentConnectionType=GCT_DLR3;    
420       connection2=GCT_DLR3;
421       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
422       {
423         found_match=true;
424       } else {
425         GSM->Terminate();      
426       }
427     }
428     
429     if (!found_match) {
430       usleep(100);          
431       
432       /* For now */
433       GSM = &N6110_Functions;
434       GSM_Info = &N6110_Information;
435       GSM_LinkOK = &CurrentLinkOK;
436 #ifdef DEBUG
437       fprintf(stdout,_("Trying MBUS for new Nokia phones...\n"));
438 #endif
439       /* Trying MBUS */
440       Protocol = &MBUS_Functions;
441       CurrentConnectionType=GCT_MBUS;    
442       connection2=GCT_MBUS;
443 #ifndef UCLINUX
444       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
445       {
446         found_match=true;
447       } else
448 #endif /* UCLINUX */
449                                 {
450         GSM->Terminate();      
451       }
452     }
453
454     if (!found_match) return GE_NOTSUPPORTED;
455
456     usleep(50);
457         
458   } else
459 #endif /* UCLINUX */
460                 {
461 #ifndef UCLINUX
462 #ifdef DEBUG
463     if (CheckModel (Nsniff_Information, model, connection)) {
464       /* Set pointers to relevant addresses */
465       GSM = &Nsniff_Functions;
466       GSM_Info = &Nsniff_Information;
467       GSM_LinkOK = &CurrentLinkOK;
468       found_match=true;
469     }
470 #endif
471 #endif /* UCLINUX */
472
473     if (CheckModel (N6110_Information, model, connection)) {
474       /* Set pointers to relevant addresses */
475       GSM = &N6110_Functions;
476       GSM_Info = &N6110_Information;
477       GSM_LinkOK = &CurrentLinkOK;
478       found_match=true;
479     }
480 #ifndef UCLINUX
481     if (CheckModel (N7110_Information, model, connection)) {
482       /* Set pointers to relevant addresses */
483       GSM = &N7110_Functions;
484       GSM_Info = &N7110_Information;
485       GSM_LinkOK = &CurrentLinkOK;
486       found_match=true;
487     }
488     if (CheckModel (Nat_Information, model, connection)) {
489       /* Set pointers to relevant addresses */
490       GSM = &Nat_Functions;
491       GSM_Info = &Nat_Information;
492       GSM_LinkOK = &CurrentLinkOK;
493       found_match=true;
494     }
495 #endif /* UCLINUX */
496
497     if (found_match) {
498       switch (connection) {
499         case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
500 #ifndef UCLINUX
501         case GCT_Infrared: Protocol = &FBUS_Functions;    break;
502         case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
503         case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
504         case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
505         case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
506         case GCT_AT      : Protocol = &AT_Functions;      break;
507         case GCT_Default : Protocol = NULL;               break;
508 #endif /* UCLINUX */
509       }
510     } else
511       return GE_NOTSUPPORTED;
512   }
513
514     
515   /* Now call model specific initialisation code. */
516   error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
517
518 #ifndef UCLINUX
519   /* RTH: FIXME: second try for Irda (6210 only?)*/
520   if ( error!=GE_NONE && connection == GCT_Irda)
521   {
522    #ifdef DEBUG
523      fprintf(stdout,"Irda connection: second try!\n");
524    #endif
525    device_close();
526    error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
527   }
528 #endif /* UCLINUX */
529
530 #ifndef UCLINUX
531   if (error==GE_NONE && !strcmp(SynchronizeTime,"yes"))
532   {
533     nowh=time(NULL);
534     now=localtime(&nowh);
535
536     Date.Year = now->tm_year;
537     Date.Month = now->tm_mon+1;
538     Date.Day = now->tm_mday;
539     Date.Hour = now->tm_hour;
540     Date.Minute = now->tm_min;
541     Date.Second = now->tm_sec;
542
543     if (Date.Year<1900)
544     {
545
546       /* Well, this thing is copyrighted in U.S. This technique is known as
547          Windowing and you can read something about it in LinuxWeekly News:
548          http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
549          written in Czech republic and Poland where algorithms are not allowed
550          to be patented. */
551
552       if (Date.Year>90)
553         Date.Year = Date.Year+1900;
554       else
555         Date.Year = Date.Year+2000;
556     }
557
558     /* FIXME: Error checking should be here. */
559     GSM->SetDateTime(&Date);
560   }
561 #endif /* UCLINUX */
562
563   return error;
564 }
565
566 #ifndef UCLINUX
567
568 GSM_Error Unimplemented(void)
569 {
570         return GE_NOTIMPLEMENTED;
571 }
572
573 GSM_Error NotSupported(void)
574 {
575         return GE_NOTSUPPORTED;
576 }
577
578 #endif /* UCLINUX */
579
580 /* Applications should call N6110_Terminate to shut down the N6110 thread and
581    close the serial port. */
582 void NULL_Terminate(void)
583 {
584   Protocol->Terminate();
585 }
586
587 #ifdef WIN32
588 /* Here are things made for keeping connecting */
589 void NULL_KeepAlive()
590 {
591 }
592 #else
593 /* Here are things made for keeping connecting */
594 void NULL_KeepAlive()
595 {
596 }
597 #endif
598
599 #ifdef DEBUG
600 void NULL_TX_DisplayMessage(u16 MessageLength, u8 *MessageBuffer)
601 {
602   fprintf(stdout, _("PC: "));
603
604   txhexdump(MessageLength,MessageBuffer);
605 }
606 #endif
607
608 bool NULL_WritePhone (u16 length, u8 *buffer) {
609   if (device_write(buffer,length)!=length) return false;
610                                       else return true;
611 }
612
613 GSM_Error NULL_WaitUntil (int time, GSM_Error *value)
614 {
615   int timeout;
616
617   timeout=time;
618   
619   /* Wait for timeout or other error. */
620   while (timeout != 0 && *value == GE_BUSY ) {
621           
622     if (--timeout == 0)
623       return (GE_TIMEOUT);
624                     
625     usleep (100000);
626   }
627
628   return *value;
629 }
630
631 GSM_Error NULL_SendMessageSequence (int time, GSM_Error *value,
632                  u16 message_length, u8 message_type, u8 *buffer)
633 {
634   *value=GE_BUSY;
635   
636   Protocol->SendMessage(message_length, message_type, buffer);  
637
638   return NULL_WaitUntil (time, value);
639 }
640
641 GSM_ConnectionType GetConnectionTypeFromString(char *Connection) {
642
643   GSM_ConnectionType connection=GCT_FBUS;
644
645 #ifndef UCLINUX
646   if (!strcmp(Connection, "irda"))     connection=GCT_Irda;
647   if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
648   if (!strcmp(Connection, "mbus"))     connection=GCT_MBUS;
649   if (!strcmp(Connection, "dlr3"))     connection=GCT_DLR3;
650   if (!strcmp(Connection, "at"))       connection=GCT_AT;
651   if (!strcmp(Connection, "tekram210"))connection=GCT_Tekram;
652 #endif /* UCLINUX */
653   
654   return connection;
655 }
656
657 bool GetMemoryTypeString(char *memorytext, GSM_MemoryType *type)
658 {
659   int i=0;
660
661   typedef struct {
662     GSM_MemoryType type;
663     char *name;
664   } GSM_MTStrings;
665
666   GSM_MTStrings mystring[] = {
667     {GMT_ME,"ME"},
668     {GMT_SM,"SM"},
669     {GMT_FD,"FD"},
670     {GMT_ON,"ON"},
671     {GMT_EN,"EN"},
672     {GMT_DC,"DC"},
673     {GMT_RC,"RC"},  
674     {GMT_MC,"MC"},
675     {GMT_LD,"LD"},
676     {GMT_MT,"MT"},
677     {GMT_ME,"undefined"}
678   };
679
680   while (strcmp(mystring[i].name,"undefined")) {
681     if (*type==mystring[i].type) {
682       strcpy(memorytext,mystring[i].name);
683       return true;
684     }
685     i++;
686   }
687   return false;
688 }
689
690 bool GetMemoryTypeID(char *memorytext, GSM_MemoryType *type)
691 {
692   int i=0;
693
694   typedef struct {
695     GSM_MemoryType type;
696     char *name;
697   } GSM_MTStrings;
698
699   GSM_MTStrings mystring[] = {
700     {GMT_ME,"ME"},
701     {GMT_SM,"SM"},
702     {GMT_FD,"FD"},
703     {GMT_ON,"ON"},
704     {GMT_EN,"EN"},
705     {GMT_DC,"DC"},
706     {GMT_RC,"RC"},  
707     {GMT_MC,"MC"},
708     {GMT_LD,"LD"},
709     {GMT_MT,"MT"},
710     {GMT_ME,"undefined"}
711   };
712
713   while (strcmp(mystring[i].name,"undefined")) {
714     if (strcmp(mystring[i].name,memorytext)==0) {
715       *type=mystring[i].type;
716       return true;
717     }
718     i++;
719   }
720
721   return false;
722 }
723
724 char *GetMygnokiiVersion() {
725
726   static char Buffer[1000]="";
727
728   sprintf(Buffer, "%s",VERSION);
729
730   return Buffer;
731 }
732
733 /*
734 1.Name,2.CodeName,3.Calendar,4.Netmonitor,5.Caller groups,6.Phonebook,
735 7.Authentication 8.Datacalls 9.KeysPressing 10.SMSC Default Recipient
736 11.SpeedDials 12.ScreenSavers 13.DTMF 14.SMS 15.NoPowerFrame 16.StartUpLogo
737 17.Profiles 18.Ringtones 19.WAP
738 */
739
740 static OnePhoneModel allmodels[] = {
741
742 /*1,    2,       3,      4,       5,        6       7      8        9      10        11      12       13     14      15        16       17       18        19 */
743 {"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}},
744 {"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}},
745 {"3310","NHM-5",{F_CAL33,F_NETMON,        0,F_PBK33,     0,       0,     0,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF33,F_RING_SM,    0}},
746 {"3330","NHM-6",{F_CAL33,F_NETMON,        0,F_PBK33,     0,       0,F_KEYB,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,        0,F_STANIM,F_PROF33,F_RING_SM,F_WAP}},
747 {"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}},
748 {"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}},
749 {"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}},
750 {"6110","NSE-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
751 {"6130","NSK-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
752 {"6150","NSM-1",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
753 {"6190","NSB-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
754 {"6210","NPE-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP}},
755 {"6250","NHM-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP}},     
756 {"7110","NSE-5",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA71 ,F_PROF61,F_RINGBIN,F_WAP}},
757 {"8210","NSM-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}},
758 {"8850","NSM-2",{      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}},
759 {"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}},//quesses only !
760 {""    ,""     ,{      0,       0,        0,      0,     0,       0,     0,        0,      0,       0,     0,      0,        0,       0,       0,        0,    0}}
761 };
762
763 static OnePhoneModel *GetPhoneModelData (const char *num)
764 {
765         register int i = 0;
766
767         while (allmodels[i].number != "") {
768                 if (strcmp (num, allmodels[i].number) == 0) {
769                         return (&allmodels[i]);
770                 }
771                 i++;
772         }
773
774         return (&allmodels[i]);
775 }
776
777 char *GetModelName ()
778 {
779   static char model[64];
780
781   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
782
783   return (GetPhoneModelData(model)->model);
784 }
785
786 int GetModelFeature (featnum_index num)
787 {
788   static char model[64];
789
790   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
791
792   return (GetPhoneModelData(model)->features[num]);
793 }
794
795 #ifndef UCLINUX
796 int LogAvailable=-1; //-1 not checked earlier, 0 not, 1 yes
797 char *logfilename;
798
799 bool AppendLog(u8 *buffer, int length,bool format)
800 {
801   FILE *file=NULL;
802   char buffer2[50001];
803   int i;
804
805   struct CFG_Header *cfg_info;
806   char *LogFile;        
807
808   if (LogAvailable==-1) {
809
810     LogAvailable=0;
811
812     cfg_info=CFG_FindGnokiirc();
813     if (cfg_info==NULL) return false;
814
815     LogFile = CFG_Get(cfg_info, "global", "logfile");
816     if (LogFile) {
817       LogAvailable=1;
818       logfilename=LogFile;
819
820       file=fopen(logfilename, "a+");
821
822       /* We have first entry in this session and too large file */
823       if (fread( buffer2, 1, 50000,file )==50000) {
824         fclose(file);
825         file=fopen(logfilename, "w");
826       }
827     }
828   } else {
829     if (LogAvailable==1) {
830       file=fopen(logfilename, "a");
831     }
832   }
833   
834   if (LogAvailable==1) {
835     for (i=0;i<length;i++) {
836       if (format) {
837         fprintf(file, "%02x",buffer[i]);
838         switch (buffer[i]) {
839           case 0x09:fprintf(file,_(" |"));break;
840           default:
841             if (isprint(buffer[i])) fprintf(file, _("%c|"),buffer[i]);
842                                else fprintf(file, _(" |"));
843             break;
844         } 
845       } else {
846         fprintf(file, "%c",buffer[i]);
847       }
848     }
849     if (format) fprintf(file, "\n");
850     fclose(file);
851   }
852
853   return (LogAvailable==1);
854 }
855
856 bool AppendLogText(u8 *buffer,bool format)
857 {
858   return AppendLog(buffer,strlen(buffer),format);
859 }
860 #endif /* UCLINUX */