Untested patch for Ir (NOT IrDA!) connections
[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 #endif /* UCLINUX */
265   if (strstr(InfoToCheck.InfraredModels, model) != NULL) {
266     if (connection==GCT_Infrared) found_match=true;
267   }
268 #ifndef UCLINUX
269   if (strstr(InfoToCheck.DLR3Models, model) != NULL) {
270     if (connection==GCT_DLR3) found_match=true;
271   }
272   if (strstr(InfoToCheck.IrdaModels, model) != NULL) {
273     if (connection==GCT_Irda) found_match=true;
274   }
275   if (strstr(InfoToCheck.ATModels, model) != NULL) {
276     if (connection==GCT_AT) found_match=true;
277   }
278   if (strstr(InfoToCheck.TekramModels, model) != NULL) {
279     if (connection==GCT_Tekram) found_match=true;
280   }
281   if (strstr(InfoToCheck.FBUS3110Models, model) != NULL) {
282     if (connection==GCT_FBUS3110) found_match=true;
283   }
284 #endif /* UCLINUX */
285
286   return found_match;
287 }
288  
289 #ifndef UCLINUX
290
291 GSM_Error TryNewNokia(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) {
292   int InitLength;
293   int count;
294   unsigned char init_char = N6110_SYNC_BYTE;
295
296   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
297   char phonemodel[64];
298
299   if (Protocol->Initialise(device,initlength,connection,rlp_callback)!=GE_NONE)
300   {
301     return GE_NOTSUPPORTED; 
302   }
303
304   if (connection!=GCT_MBUS) {
305     InitLength = atoi(initlength);
306
307     if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
308       InitLength = 250; /* This is the usual value, lower may work. */
309     }
310
311 #ifdef DEBUG
312     fprintf(stdout,_("Writing init chars...."));
313 #endif
314
315     /* Initialise link with phone or what have you */
316     /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
317        empirical. */
318     for (count = 0; count < InitLength; count ++) {
319       usleep(100);
320       Protocol->WritePhone(1,&init_char);
321     }
322
323 #ifdef DEBUG
324     fprintf(stdout,_("Done\n"));  
325 #endif
326
327     N6110_SendStatusRequest();
328   }
329
330   usleep(100);
331
332   if (N6110_SendIDFrame()!=GE_NONE)
333     return GE_TIMEOUT;
334  
335   while (N6110_GetModel(phonemodel) != GE_NONE)
336     sleep(1);
337
338 #ifndef UCLINUX
339   if (!strcmp(phonemodel,"NPE-3") || !strcmp(phonemodel,"NSE-5") || 
340       !strcmp(phonemodel,"NHM-3"))
341   {
342     GSM->Terminate();      
343     
344     /* Set pointers to relevant addresses */
345     GSM = &N7110_Functions;
346     GSM_Info = &N7110_Information;
347     GSM_LinkOK = &CurrentLinkOK;
348     return GE_NONE;
349   }
350 #endif /* UCLINUX */
351
352   return GE_NONE;
353 }
354 #endif /* UCLINUX */
355
356 extern GSM_Information N6110_Information;
357 extern GSM_Functions   N6110_Functions;
358
359 GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), char* SynchronizeTime)
360 {
361   bool found_match=false;
362   
363   GSM_ConnectionType connection2;
364
365 #ifndef UCLINUX
366   struct tm *now;
367   time_t nowh;
368   GSM_DateTime Date;
369 #endif /* UCLINUX */
370   GSM_Error error;
371   
372   connection2=connection;
373
374   CurrentRLP_RXCallback = rlp_callback;
375   CurrentCallPassup=NULL;
376 #ifndef UCLINUX
377   CurrentCallDivert=NULL;
378 #endif /* UCLINUX */
379   CurrentPhonebookEntry=NULL;
380 #ifndef UCLINUX
381   CurrentNetworkInfo = NULL;
382   CurrentGetBitmap=NULL;
383   CurrentPlayToneError=GE_UNKNOWN;
384   strcpy(CurrentIncomingCall," ");
385   CurrentGetBinRingtone=NULL;
386   CurrentNetworkInfo=NULL;
387 #endif /* UCLINUX */
388   CurrentRequestTerminate=false;
389 #ifndef UCLINUX
390   CurrentDisableKeepAlive=false;
391   CurrentCalendarNotesInfo.HowMany=2000;
392   CurrentSMSMessage=NULL;
393 #endif /* UCLINUX */
394   CurrentMagicError = GE_BUSY;  
395   
396 #ifndef UCLINUX
397   if (!strcmp(model,"auto")) {
398
399     /* For now */
400     GSM = &N6110_Functions;
401     GSM_Info = &N6110_Information;
402     GSM_LinkOK = &CurrentLinkOK;
403 #ifdef DEBUG
404     fprintf(stdout,_("Trying FBUS for new Nokia phones...\n"));
405 #endif
406     /* Trying FBUS */
407     Protocol = &FBUS_Functions;
408     CurrentConnectionType=GCT_FBUS;    
409     connection2=GCT_FBUS;
410     if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
411     {
412       found_match=true;
413     } else {
414       GSM->Terminate();      
415     }
416
417     if (!found_match) {
418       usleep(100);          
419       
420       /* For now */
421       GSM = &N6110_Functions;
422       GSM_Info = &N6110_Information;
423       GSM_LinkOK = &CurrentLinkOK;
424 #ifdef DEBUG
425       fprintf(stdout,_("Trying DLR3 for new Nokia phones...\n"));
426 #endif
427       /* Trying DLR3 */
428       Protocol = &FBUS_Functions;
429       CurrentConnectionType=GCT_DLR3;    
430       connection2=GCT_DLR3;
431       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
432       {
433         found_match=true;
434       } else {
435         GSM->Terminate();      
436       }
437     }
438     
439     if (!found_match) {
440       usleep(100);          
441       
442       /* For now */
443       GSM = &N6110_Functions;
444       GSM_Info = &N6110_Information;
445       GSM_LinkOK = &CurrentLinkOK;
446 #ifdef DEBUG
447       fprintf(stdout,_("Trying MBUS for new Nokia phones...\n"));
448 #endif
449       /* Trying MBUS */
450       Protocol = &MBUS_Functions;
451       CurrentConnectionType=GCT_MBUS;    
452       connection2=GCT_MBUS;
453       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
454       {
455         found_match=true;
456       } else {
457         GSM->Terminate();      
458       }
459     }
460
461     if (!found_match) return GE_NOTSUPPORTED;
462
463     usleep(50);
464         
465   } else {
466     if (!strcmp(model,"modelauto")) {
467       /* For now */
468       GSM = &N6110_Functions;
469       GSM_Info = &N6110_Information;
470       GSM_LinkOK = &CurrentLinkOK;
471 #ifdef DEBUG
472       fprintf(stdout,_("Trying to find connected model...\n"));
473 #endif
474       switch (connection) {
475         case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
476         case GCT_Infrared: Protocol = &FBUS_Functions;    break;
477         case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
478         case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
479         case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
480         case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
481         case GCT_AT      : Protocol = &AT_Functions;      break;
482         case GCT_FBUS3110: Protocol = &FBUS3110_Functions;break;
483       }
484       CurrentConnectionType=connection;    
485       connection2=connection;
486       if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
487       {
488         found_match=true;
489       } else {
490         GSM->Terminate();      
491       }
492
493       if (!found_match) return GE_NOTSUPPORTED;
494
495       usleep(50);
496
497   } else
498 #endif /* UCLINUX */
499                 {
500 #ifndef UCLINUX
501 #ifdef DEBUG
502       if (CheckModel (Nsniff_Information, model, connection)) {
503         /* Set pointers to relevant addresses */
504         GSM = &Nsniff_Functions;
505         GSM_Info = &Nsniff_Information;
506         GSM_LinkOK = &CurrentLinkOK;
507         found_match=true;
508       }
509 #endif
510
511       if (CheckModel (N3110_Information, model, connection)) {
512         /* Set pointers to relevant addresses */
513         GSM = &N3110_Functions;
514         GSM_Info = &N3110_Information;
515         GSM_LinkOK = &CurrentLinkOK;
516         found_match=true;
517       }
518 #endif /* UCLINUX */
519       if (CheckModel (N6110_Information, model, connection)) {
520         /* Set pointers to relevant addresses */
521         GSM = &N6110_Functions;
522         GSM_Info = &N6110_Information;
523         GSM_LinkOK = &CurrentLinkOK;
524         found_match=true;
525       }
526 #ifndef UCLINUX
527       if (CheckModel (N7110_Information, model, connection)) {
528         /* Set pointers to relevant addresses */
529         GSM = &N7110_Functions;
530         GSM_Info = &N7110_Information;
531         GSM_LinkOK = &CurrentLinkOK;
532         found_match=true;
533       }
534       if (CheckModel (Nat_Information, model, connection)) {
535         /* Set pointers to relevant addresses */
536         GSM = &Nat_Functions;
537         GSM_Info = &Nat_Information;
538         GSM_LinkOK = &CurrentLinkOK;
539         found_match=true;
540       }
541 #endif /* UCLINUX */
542
543       if (found_match) {
544         switch (connection) {
545           case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
546           case GCT_Infrared: Protocol = &FBUS_Functions;    break;
547 #ifndef UCLINUX
548           case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
549           case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
550           case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
551           case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
552           case GCT_AT      : Protocol = &AT_Functions;      break;
553           case GCT_FBUS3110: Protocol = &FBUS3110_Functions;break;
554 #endif /* UCLINUX */
555         }
556       } else
557         return GE_NOTSUPPORTED;
558     }
559 #ifndef UCLINUX
560   }
561 #endif /* UCLINUX */
562
563     
564   /* Now call model specific initialisation code. */
565   error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
566
567 #ifndef UCLINUX
568   /* RTH: FIXME: second try for Irda (6210 only?)*/
569   if ( error!=GE_NONE && connection == GCT_Irda)
570   {
571    #ifdef DEBUG
572      fprintf(stdout,"Irda connection: second try!\n");
573    #endif
574    device_close();
575    error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
576   }
577 #endif /* UCLINUX */
578
579 #ifndef UCLINUX
580   if (error==GE_NONE && !strcmp(SynchronizeTime,"yes"))
581   {
582     nowh=time(NULL);
583     now=localtime(&nowh);
584
585     Date.Year = now->tm_year;
586     Date.Month = now->tm_mon+1;
587     Date.Day = now->tm_mday;
588     Date.Hour = now->tm_hour;
589     Date.Minute = now->tm_min;
590     Date.Second = now->tm_sec;
591
592     if (Date.Year<1900)
593     {
594
595       /* Well, this thing is copyrighted in U.S. This technique is known as
596          Windowing and you can read something about it in LinuxWeekly News:
597          http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
598          written in Czech republic and Poland where algorithms are not allowed
599          to be patented. */
600
601       if (Date.Year>90)
602         Date.Year = Date.Year+1900;
603       else
604         Date.Year = Date.Year+2000;
605     }
606
607     /* FIXME: Error checking should be here. */
608     GSM->SetDateTime(&Date);
609   }
610 #endif /* UCLINUX */
611
612   return error;
613 }
614
615 #ifndef UCLINUX
616
617 GSM_Error Unimplemented(void)
618 {
619         return GE_NOTIMPLEMENTED;
620 }
621
622 GSM_Error NotSupported(void)
623 {
624         return GE_NOTSUPPORTED;
625 }
626
627 #endif /* UCLINUX */
628
629 /* Applications should call N6110_Terminate to shut down the N6110 thread and
630    close the serial port. */
631 void NULL_Terminate(void)
632 {
633   Protocol->Terminate();
634 }
635
636 #ifdef WIN32
637 /* Here are things made for keeping connecting */
638 void NULL_KeepAlive()
639 {
640 }
641 #else
642 /* Here are things made for keeping connecting */
643 void NULL_KeepAlive()
644 {
645 }
646 #endif
647
648 #ifdef DEBUG
649 void NULL_TX_DisplayMessage(u16 MessageLength, u8 *MessageBuffer)
650 {
651   fprintf(stdout, _("PC: "));
652
653   txhexdump(MessageLength,MessageBuffer);
654 }
655 #endif
656
657 bool NULL_WritePhone (u16 length, u8 *buffer) {
658   if (device_write(buffer,length)!=length) return false;
659                                       else return true;
660 }
661
662 GSM_Error NULL_WaitUntil (int time, GSM_Error *value)
663 {
664   int timeout;
665
666   timeout=time;
667   
668   /* Wait for timeout or other error. */
669   while (timeout != 0 && *value == GE_BUSY ) {
670           
671     if (--timeout == 0)
672       return (GE_TIMEOUT);
673                     
674     usleep (100000);
675   }
676
677   return *value;
678 }
679
680 GSM_Error NULL_SendMessageSequence (int time, GSM_Error *value,
681                  u16 message_length, u8 message_type, u8 *buffer)
682 {
683   *value=GE_BUSY;
684   
685   Protocol->SendMessage(message_length, message_type, buffer);  
686
687   return NULL_WaitUntil (time, value);
688 }
689
690 GSM_ConnectionType GetConnectionTypeFromString(char *Connection) {
691
692   GSM_ConnectionType connection=GCT_FBUS;
693
694 #ifndef UCLINUX
695   if (!strcmp(Connection, "irda"))     connection=GCT_Irda;
696 #endif /* UCLINUX */
697   if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
698 #ifndef UCLINUX
699   if (!strcmp(Connection, "mbus"))     connection=GCT_MBUS;
700   if (!strcmp(Connection, "dlr3"))     connection=GCT_DLR3;
701   if (!strcmp(Connection, "fbus3110")) connection=GCT_FBUS3110;
702   if (!strcmp(Connection, "at"))       connection=GCT_AT;
703   if (!strcmp(Connection, "tekram210"))connection=GCT_Tekram;
704 #endif /* UCLINUX */
705   
706   return connection;
707 }
708
709 bool GetMemoryTypeString(char *memorytext, GSM_MemoryType *type)
710 {
711   int i=0;
712
713   typedef struct {
714     GSM_MemoryType type;
715     char *name;
716   } GSM_MTStrings;
717
718 static  GSM_MTStrings mystring[] = {
719     {GMT_ME,"ME"},
720     {GMT_SM,"SM"},
721     {GMT_FD,"FD"},
722     {GMT_ON,"ON"},
723     {GMT_EN,"EN"},
724     {GMT_DC,"DC"},
725     {GMT_RC,"RC"},  
726     {GMT_MC,"MC"},
727     {GMT_LD,"LD"},
728     {GMT_MT,"MT"},
729     {GMT_ME,"undefined"}
730   };
731
732   while (strcmp(mystring[i].name,"undefined")) {
733     if (*type==mystring[i].type) {
734       strcpy(memorytext,mystring[i].name);
735       return true;
736     }
737     i++;
738   }
739   return false;
740 }
741
742 bool GetMemoryTypeID(char *memorytext, GSM_MemoryType *type)
743 {
744   int i=0;
745
746   typedef struct {
747     GSM_MemoryType type;
748     char *name;
749   } GSM_MTStrings;
750
751 static  GSM_MTStrings mystring[] = {
752     {GMT_ME,"ME"},
753     {GMT_SM,"SM"},
754     {GMT_FD,"FD"},
755     {GMT_ON,"ON"},
756     {GMT_EN,"EN"},
757     {GMT_DC,"DC"},
758     {GMT_RC,"RC"},  
759     {GMT_MC,"MC"},
760     {GMT_LD,"LD"},
761     {GMT_MT,"MT"},
762     {GMT_ME,"undefined"}
763   };
764
765   while (strcmp(mystring[i].name,"undefined")) {
766     if (strcmp(mystring[i].name,memorytext)==0) {
767       *type=mystring[i].type;
768       return true;
769     }
770     i++;
771   }
772
773   return false;
774 }
775
776 char *GetMygnokiiVersion() {
777
778   static char Buffer[1000]="";
779
780   sprintf(Buffer, "%s",VERSION);
781
782   return Buffer;
783 }
784
785 /*
786 1.Name,2.CodeName,3.Calendar,4.Netmonitor,5.Caller groups,6.Phonebook,
787 7.Authentication 8.Datacalls 9.KeysPressing 10.SMSC Default Recipient
788 11.SpeedDials 12.ScreenSavers 13.DTMF 14.SMS 15.NoPowerFrame 16.StartUpLogo
789 17.Profiles 18.Ringtones 19.WAP 20.RIngtonesNumber
790 */
791
792 static OnePhoneModel allmodels[] = {
793
794 /*1,    2,       3,      4,       5,        6          7      8        9      10        11      12       13     14      15        16       17       18        19    20 */
795 {"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}},
796 {"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}},
797 {"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}},
798 {"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}},
799 {"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}},
800 {"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}},
801 {"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}},
802 {"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}},
803 {"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}},
804 {"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}},
805 {"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}},
806 {"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}},
807 {"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}},       
808 {"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}},
809 {"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}},
810 {"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}},
811 {"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 !
812 {""    ,""     ,{      0,       0,        0,         0,     0,       0,     0,        0,      0,       0,     0,      0,        0,       0,       0,        0,    0, 0}}
813 };
814
815 static OnePhoneModel *GetPhoneModelData (const char *num)
816 {
817         register int i = 0;
818
819         while (allmodels[i].number != "") {
820                 if (strcmp (num, allmodels[i].number) == 0) {
821                         return (&allmodels[i]);
822                 }
823                 i++;
824         }
825
826         return (&allmodels[i]);
827 }
828
829 char *GetModelName ()
830 {
831   static char model[64];
832
833   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
834
835   return (GetPhoneModelData(model)->model);
836 }
837
838 int GetModelFeature (featnum_index num)
839 {
840   static char model[64];
841
842   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
843
844   return (GetPhoneModelData(model)->features[num]);
845 }
846
847 #ifndef UCLINUX
848 int LogAvailable=-1; //-1 not checked earlier, 0 not, 1 yes
849 char *logfilename;
850
851 bool AppendLog(u8 *buffer, int length,bool format)
852 {
853   FILE *file=NULL;
854   char buffer2[50001];
855   int i;
856
857   struct CFG_Header *cfg_info;
858   char *LogFile;        
859
860   if (LogAvailable==-1) {
861
862     LogAvailable=0;
863
864     cfg_info=CFG_FindGnokiirc();
865     if (cfg_info==NULL) return false;
866
867     LogFile = CFG_Get(cfg_info, "global", "logfile");
868     if (LogFile) {
869       LogAvailable=1;
870       logfilename=LogFile;
871
872       file=fopen(logfilename, "a+");
873
874       /* We have first entry in this session and too large file */
875       if (fread( buffer2, 1, 50000,file )==50000) {
876         fclose(file);
877         file=fopen(logfilename, "w");
878       }
879     }
880   } else {
881     if (LogAvailable==1) {
882       file=fopen(logfilename, "a");
883     }
884   }
885   
886   if (LogAvailable==1) {
887     for (i=0;i<length;i++) {
888       if (format) {
889         fprintf(file, "%02x",buffer[i]);
890         switch (buffer[i]) {
891           case 0x09:fprintf(file,_(" |"));break;
892           default:
893             if (isprint(buffer[i])) fprintf(file, _("%c|"),buffer[i]);
894                                else fprintf(file, _(" |"));
895             break;
896         } 
897       } else {
898         fprintf(file, "%c",buffer[i]);
899       }
900     }
901     if (format) fprintf(file, "\n");
902     fclose(file);
903   }
904
905   return (LogAvailable==1);
906 }
907
908 bool AppendLogText(u8 *buffer,bool format)
909 {
910   return AppendLog(buffer,strlen(buffer),format);
911 }
912 #endif /* UCLINUX */