/* G N O K I I A Linux/Unix toolset and driver for Nokia mobile phones. Released under the terms of the GNU GPL, see file COPYING for more details. Provides a generic API for accessing functions on the phone, wherever possible hiding the model specific details. The underlying code should run in it's own thread to allow communications to the phone to be run independantly of mailing code that calls these API functions. Unless otherwise noted, all functions herein block until they complete. The functions themselves are defined in a structure in gsm-common.h. */ #include "config.h" #include #include #include #include #ifdef WIN32 #include #include "misc_win32.h" #endif #include "gsm-api.h" #ifndef UCLINUX #include "newmodules/n6110.h" #include "newmodules/n7110.h" #include "newmodules/newat.h" #ifdef DEBUG #include "newmodules/sniff/sniff.h" #endif #include "protocol/fbusirda.h" #endif /* UCLINUX */ #include "protocol/fbus.h" #ifndef UCLINUX #include "protocol/mbus.h" #include "protocol/at.h" #endif /* UCLINUX */ #include "files/cfgreader.h" #ifndef WIN32 #include "devices/device.h" #endif #ifdef VC6 /* for VC6 make scripts save VERSION constant in mversion.h file */ #include "mversion.h" #endif /* GSM_LinkOK is set to true once normal communications with the phone have been established. */ bool *GSM_LinkOK; /* Define pointer to the GSM_Functions structure used by external code to call relevant API functions. This structure is defined in gsm-common.h. */ GSM_Functions *GSM; /* Define pointer to the GSM_Information structure used by external code to obtain information that varies from model to model. This structure is also defined in gsm-common.h */ GSM_Information *GSM_Info; /* Initialise interface to the phone. Model number should be a string such as 3810, 5110, 6110 etc. Device is the serial port to use e.g. /dev/ttyS0, the user must have write permission to the device. */ GSM_Protocol *Protocol; /* Local variables used by get/set phonebook entry code. Buffer is used as a source or destination for phonebook data and other functions... Error is set to GE_NONE by calling function, set to GE_COMPLETE or an error code by handler routines as appropriate. */ GSM_PhonebookEntry *CurrentPhonebookEntry; GSM_Error CurrentPhonebookError; GSM_SpeedDial *CurrentSpeedDialEntry; GSM_Error CurrentSpeedDialError; unsigned char Current_IMEI[GSM_MAX_IMEI_LENGTH]; unsigned char Current_Revision[GSM_MAX_REVISION_LENGTH]; unsigned char Current_Model[GSM_MAX_MODEL_LENGTH]; #ifndef UCLINUX GSM_SMSMessage *CurrentSMSMessage; GSM_Error CurrentSMSMessageError; int CurrentSMSPointer; GSM_SMSFolders *CurrentSMSFolders; GSM_Error CurrentSMSFoldersError; int CurrentSMSFoldersCount; GSM_OneSMSFolder CurrentSMSFolder; GSM_Error CurrentSMSFolderError; int CurrentSMSFolderID; #endif /* UCLINUX */ GSM_MemoryStatus *CurrentMemoryStatus; GSM_Error CurrentMemoryStatusError; #ifndef UCLINUX GSM_NetworkInfo *CurrentNetworkInfo; GSM_Error CurrentNetworkInfoError; GSM_SMSStatus *CurrentSMSStatus; GSM_Error CurrentSMSStatusError; GSM_MessageCenter *CurrentMessageCenter; GSM_Error CurrentMessageCenterError; int *CurrentSecurityCodeStatus; GSM_Error CurrentSecurityCodeError; GSM_SecurityCode *CurrentSecurityCode; GSM_DateTime *CurrentDateTime; GSM_Error CurrentDateTimeError; GSM_Error CurrentResetPhoneSettingsError; GSM_DateTime *CurrentAlarm; GSM_Error CurrentAlarmError; GSM_CalendarNote *CurrentCalendarNote; GSM_Error CurrentCalendarNoteError; GSM_NotesInfo CurrentCalendarNotesInfo,*CurrentCalendarNotesInfo2; GSM_Error CurrentCalendarNotesInfoError; GSM_Error CurrentSetDateTimeError; GSM_Error CurrentSetAlarmError; int *CurrentFirstCalendarFreePos; GSM_Error CurrentFirstCalendarFreePosError; #endif /* UCLINUX */ GSM_Error CurrentEnableExtendedCommandsError; int CurrentRFLevel, CurrentBatteryLevel, CurrentPowerSource; #ifndef UCLINUX int CurrentDisplayStatus; GSM_Error CurrentDisplayStatusError; char *CurrentNetmonitor; GSM_Error CurrentNetmonitorError; GSM_Bitmap *CurrentGetBitmap=NULL; GSM_Error CurrentGetBitmapError; GSM_Error CurrentSetBitmapError; GSM_Error CurrentSendDTMFError; GSM_Profile *CurrentProfile; GSM_Error CurrentProfileError; GSM_Error CurrentDisplayOutputError; GSM_CBMessage *CurrentCBMessage; GSM_Error CurrentCBError; int CurrentPressKeyEvent; GSM_Error CurrentPressKeyError; GSM_Error CurrentPlayToneError=GE_UNKNOWN; #endif /* UCLINUX */ GSM_Error CurrentDialVoiceError; #ifndef UCLINUX GSM_Error CurrentGetOperatorNameError; GSM_Network *CurrentGetOperatorNameNetwork; GSM_Error CurrentSetOperatorNameError; #endif /* UCLINUX */ GSM_Error CurrentGetIMEIError; GSM_Error CurrentGetHWError; #ifndef UCLINUX unsigned char CurrentPPS[4]; GSM_Error CurrentProductProfileSettingsError; char CurrentIncomingCall[20]; GSM_Error CurrentBinRingtoneError; GSM_BinRingtone *CurrentGetBinRingtone=NULL; GSM_Error CurrentRingtoneError; #endif /* UCLINUX */ GSM_Error CurrentMagicError; #ifndef UCLINUX GSM_Error CurrentSimlockInfoError; GSM_AllSimlocks *CurrentSimLock; GSM_Error CurrentGetWAPBookmarkError; GSM_Error CurrentSetWAPBookmarkError; GSM_WAPBookmark *WAPBookmark; GSM_Error CurrentGetWAPSettingsError; GSM_WAPSettings *WAPSettings; GSM_Error CurrentCallDivertError; GSM_CallDivert *CurrentCallDivert; char *CurrentManufacturer; #endif /* UCLINUX */ /* This is the connection type used in gnokii. */ GSM_ConnectionType CurrentConnectionType; /* Pointer to a callback function used to return changes to a calls status */ /* This saves unreliable polling */ void (*CurrentCallPassup)(char c); /* Pointer to callback function in user code to be called when RLP frames are received. */ void (*CurrentRLP_RXCallback)(RLP_F96Frame *frame); /* Used to disconnect the call */ u8 CurrentCallSequenceNumber; bool CurrentLinkOK; bool CurrentRequestTerminate; #ifndef UCLINUX bool CurrentDisableKeepAlive; #endif /* UCLINUX */ #ifdef UCLINUX static #endif /* UCLINUX */ bool CheckModel (GSM_Information InfoToCheck, char *model, GSM_ConnectionType connection) { bool found_match=false; if (strstr(InfoToCheck.FBUSModels, model) != NULL) { if (connection==GCT_FBUS) found_match=true; } #ifndef UCLINUX if (strstr(InfoToCheck.MBUSModels, model) != NULL) { if (connection==GCT_MBUS) found_match=true; } if (strstr(InfoToCheck.InfraredModels, model) != NULL) { if (connection==GCT_Infrared) found_match=true; } if (strstr(InfoToCheck.DLR3Models, model) != NULL) { if (connection==GCT_DLR3) found_match=true; } if (strstr(InfoToCheck.IrdaModels, model) != NULL) { if (connection==GCT_Irda) found_match=true; } if (strstr(InfoToCheck.ATModels, model) != NULL) { if (connection==GCT_AT) found_match=true; } if (strstr(InfoToCheck.TekramModels, model) != NULL) { if (connection==GCT_Tekram) found_match=true; } #endif /* UCLINUX */ return found_match; } #ifndef UCLINUX GSM_Error TryNewNokia(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) { int InitLength; int count; unsigned char init_char = N6110_SYNC_BYTE; /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */ char phonemodel[64]; if (Protocol->Initialise(device,initlength,connection,rlp_callback)!=GE_NONE) { return GE_NOTSUPPORTED; } if (connection!=GCT_MBUS) { InitLength = atoi(initlength); if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) { InitLength = 250; /* This is the usual value, lower may work. */ } #ifdef DEBUG fprintf(stdout,_("Writing init chars....")); #endif /* Initialise link with phone or what have you */ /* Send init string to phone, this is a bunch of 0x55 characters. Timing is empirical. */ for (count = 0; count < InitLength; count ++) { usleep(100); Protocol->WritePhone(1,&init_char); } #ifdef DEBUG fprintf(stdout,_("Done\n")); #endif N6110_SendStatusRequest(); } usleep(100); if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT; while (N6110_GetModel(phonemodel) != GE_NONE) sleep(1); #ifndef UCLINUX if (!strcmp(phonemodel,"NPE-3") || !strcmp(phonemodel,"NSE-5")) { GSM->Terminate(); /* Set pointers to relevant addresses */ GSM = &N7110_Functions; GSM_Info = &N7110_Information; GSM_LinkOK = &CurrentLinkOK; return GE_NONE; } #endif /* UCLINUX */ return GE_NONE; } #endif /* UCLINUX */ extern GSM_Information N6110_Information; extern GSM_Functions N6110_Functions; GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), char* SynchronizeTime) { bool found_match=false; GSM_ConnectionType connection2; #ifndef UCLINUX struct tm *now; time_t nowh; GSM_DateTime Date; #endif /* UCLINUX */ GSM_Error error; connection2=connection; CurrentRLP_RXCallback = rlp_callback; CurrentCallPassup=NULL; CurrentPhonebookEntry=NULL; #ifndef UCLINUX CurrentNetworkInfo = NULL; CurrentGetBitmap=NULL; CurrentPlayToneError=GE_UNKNOWN; strcpy(CurrentIncomingCall," "); CurrentGetBinRingtone=NULL; CurrentNetworkInfo=NULL; #endif /* UCLINUX */ CurrentRequestTerminate=false; #ifndef UCLINUX CurrentDisableKeepAlive=false; CurrentCalendarNotesInfo.HowMany=2000; #endif /* UCLINUX */ CurrentMagicError = GE_BUSY; #ifndef UCLINUX if (!strcmp(model,"auto")) { /* For now */ GSM = &N6110_Functions; GSM_Info = &N6110_Information; GSM_LinkOK = &CurrentLinkOK; #ifdef DEBUG fprintf(stdout,_("Trying FBUS for new Nokia phones...\n")); #endif /* Trying FBUS */ Protocol = &FBUS_Functions; CurrentConnectionType=GCT_FBUS; connection2=GCT_FBUS; if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE) { found_match=true; } else { GSM->Terminate(); } if (!found_match) { usleep(100); /* For now */ GSM = &N6110_Functions; GSM_Info = &N6110_Information; GSM_LinkOK = &CurrentLinkOK; #ifdef DEBUG fprintf(stdout,_("Trying DLR3 for new Nokia phones...\n")); #endif /* Trying DLR3 */ Protocol = &FBUS_Functions; CurrentConnectionType=GCT_DLR3; connection2=GCT_DLR3; if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE) { found_match=true; } else { GSM->Terminate(); } } if (!found_match) { usleep(100); /* For now */ GSM = &N6110_Functions; GSM_Info = &N6110_Information; GSM_LinkOK = &CurrentLinkOK; #ifdef DEBUG fprintf(stdout,_("Trying MBUS for new Nokia phones...\n")); #endif /* Trying MBUS */ Protocol = &MBUS_Functions; CurrentConnectionType=GCT_MBUS; connection2=GCT_MBUS; #ifndef UCLINUX if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE) { found_match=true; } else #endif /* UCLINUX */ { GSM->Terminate(); } } if (!found_match) return GE_NOTSUPPORTED; usleep(50); } else #endif /* UCLINUX */ { #ifndef UCLINUX #ifdef DEBUG if (CheckModel (Nsniff_Information, model, connection)) { /* Set pointers to relevant addresses */ GSM = &Nsniff_Functions; GSM_Info = &Nsniff_Information; GSM_LinkOK = &CurrentLinkOK; found_match=true; } #endif #endif /* UCLINUX */ if (CheckModel (N6110_Information, model, connection)) { /* Set pointers to relevant addresses */ GSM = &N6110_Functions; GSM_Info = &N6110_Information; GSM_LinkOK = &CurrentLinkOK; found_match=true; } #ifndef UCLINUX if (CheckModel (N7110_Information, model, connection)) { /* Set pointers to relevant addresses */ GSM = &N7110_Functions; GSM_Info = &N7110_Information; GSM_LinkOK = &CurrentLinkOK; found_match=true; } if (CheckModel (Nat_Information, model, connection)) { /* Set pointers to relevant addresses */ GSM = &Nat_Functions; GSM_Info = &Nat_Information; GSM_LinkOK = &CurrentLinkOK; found_match=true; } #endif /* UCLINUX */ if (found_match) { switch (connection) { case GCT_FBUS : Protocol = &FBUS_Functions; break; #ifndef UCLINUX case GCT_Infrared: Protocol = &FBUS_Functions; break; case GCT_Tekram : Protocol = &FBUS_Functions; break; case GCT_DLR3 : Protocol = &FBUS_Functions; break; case GCT_MBUS : Protocol = &MBUS_Functions; break; case GCT_Irda : Protocol = &FBUSIRDA_Functions;break; case GCT_AT : Protocol = &AT_Functions; break; case GCT_Default : Protocol = NULL; break; #endif /* UCLINUX */ } } else return GE_NOTSUPPORTED; } /* Now call model specific initialisation code. */ error=(GSM->Initialise(device, initlength, connection2, rlp_callback)); #ifndef UCLINUX /* RTH: FIXME: second try for Irda (6210 only?)*/ if ( error!=GE_NONE && connection == GCT_Irda) { #ifdef DEBUG fprintf(stdout,"Irda connection: second try!\n"); #endif device_close(); error=(GSM->Initialise(device, initlength, connection2, rlp_callback)); } #endif /* UCLINUX */ #ifndef UCLINUX if (error==GE_NONE && !strcmp(SynchronizeTime,"yes")) { nowh=time(NULL); now=localtime(&nowh); Date.Year = now->tm_year; Date.Month = now->tm_mon+1; Date.Day = now->tm_mday; Date.Hour = now->tm_hour; Date.Minute = now->tm_min; Date.Second = now->tm_sec; if (Date.Year<1900) { /* Well, this thing is copyrighted in U.S. This technique is known as Windowing and you can read something about it in LinuxWeekly News: http://lwn.net/1999/features/Windowing.phtml. This thing is beeing written in Czech republic and Poland where algorithms are not allowed to be patented. */ if (Date.Year>90) Date.Year = Date.Year+1900; else Date.Year = Date.Year+2000; } /* FIXME: Error checking should be here. */ GSM->SetDateTime(&Date); } #endif /* UCLINUX */ return error; } #ifndef UCLINUX GSM_Error Unimplemented(void) { return GE_NOTIMPLEMENTED; } GSM_Error NotSupported(void) { return GE_NOTSUPPORTED; } #endif /* UCLINUX */ /* Applications should call N6110_Terminate to shut down the N6110 thread and close the serial port. */ void NULL_Terminate(void) { Protocol->Terminate(); } #ifdef WIN32 /* Here are things made for keeping connecting */ void NULL_KeepAlive() { } #else /* Here are things made for keeping connecting */ void NULL_KeepAlive() { } #endif #ifdef DEBUG void NULL_TX_DisplayMessage(u16 MessageLength, u8 *MessageBuffer) { fprintf(stdout, _("PC: ")); txhexdump(MessageLength,MessageBuffer); } #endif bool NULL_WritePhone (u16 length, u8 *buffer) { if (device_write(buffer,length)!=length) return false; else return true; } GSM_Error NULL_WaitUntil (int time, GSM_Error *value) { int timeout; timeout=time; /* Wait for timeout or other error. */ while (timeout != 0 && *value == GE_BUSY ) { if (--timeout == 0) return (GE_TIMEOUT); usleep (100000); } return *value; } GSM_Error NULL_SendMessageSequence (int time, GSM_Error *value, u16 message_length, u8 message_type, u8 *buffer) { *value=GE_BUSY; Protocol->SendMessage(message_length, message_type, buffer); return NULL_WaitUntil (time, value); } GSM_ConnectionType GetConnectionTypeFromString(char *Connection) { GSM_ConnectionType connection=GCT_FBUS; #ifndef UCLINUX if (!strcmp(Connection, "irda")) connection=GCT_Irda; if (!strcmp(Connection, "infrared")) connection=GCT_Infrared; if (!strcmp(Connection, "mbus")) connection=GCT_MBUS; if (!strcmp(Connection, "dlr3")) connection=GCT_DLR3; if (!strcmp(Connection, "at")) connection=GCT_AT; if (!strcmp(Connection, "tekram210"))connection=GCT_Tekram; #endif /* UCLINUX */ return connection; } bool GetMemoryTypeString(char *memorytext, GSM_MemoryType *type) { int i=0; typedef struct { GSM_MemoryType type; char *name; } GSM_MTStrings; static GSM_MTStrings mystring[] = { {GMT_ME,"ME"}, {GMT_SM,"SM"}, {GMT_FD,"FD"}, {GMT_ON,"ON"}, {GMT_EN,"EN"}, {GMT_DC,"DC"}, {GMT_RC,"RC"}, {GMT_MC,"MC"}, {GMT_LD,"LD"}, {GMT_MT,"MT"}, {GMT_ME,"undefined"} }; while (strcmp(mystring[i].name,"undefined")) { if (*type==mystring[i].type) { strcpy(memorytext,mystring[i].name); return true; } i++; } return false; } bool GetMemoryTypeID(char *memorytext, GSM_MemoryType *type) { int i=0; typedef struct { GSM_MemoryType type; char *name; } GSM_MTStrings; static GSM_MTStrings mystring[] = { {GMT_ME,"ME"}, {GMT_SM,"SM"}, {GMT_FD,"FD"}, {GMT_ON,"ON"}, {GMT_EN,"EN"}, {GMT_DC,"DC"}, {GMT_RC,"RC"}, {GMT_MC,"MC"}, {GMT_LD,"LD"}, {GMT_MT,"MT"}, {GMT_ME,"undefined"} }; while (strcmp(mystring[i].name,"undefined")) { if (strcmp(mystring[i].name,memorytext)==0) { *type=mystring[i].type; return true; } i++; } return false; } char *GetMygnokiiVersion() { static char Buffer[1000]=""; sprintf(Buffer, "%s",VERSION); return Buffer; } /* 1.Name,2.CodeName,3.Calendar,4.Netmonitor,5.Caller groups,6.Phonebook, 7.Authentication 8.Datacalls 9.KeysPressing 10.SMSC Default Recipient 11.SpeedDials 12.ScreenSavers 13.DTMF 14.SMS 15.NoPowerFrame 16.StartUpLogo 17.Profiles 18.Ringtones 19.WAP */ static OnePhoneModel allmodels[] = { /*1, 2, 3, 4, 5, 6 7 8 9 10 11 12 13 14 15 16 17 18 19 */ {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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}}, {"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 ! {"" ,"" ,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} }; static OnePhoneModel *GetPhoneModelData (const char *num) { register int i = 0; while (allmodels[i].number != "") { if (strcmp (num, allmodels[i].number) == 0) { return (&allmodels[i]); } i++; } return (&allmodels[i]); } char *GetModelName () { static char model[64]; while (GSM->GetModel(model) != GE_NONE) sleep(1); return (GetPhoneModelData(model)->model); } int GetModelFeature (featnum_index num) { static char model[64]; while (GSM->GetModel(model) != GE_NONE) sleep(1); return (GetPhoneModelData(model)->features[num]); } #ifndef UCLINUX int LogAvailable=-1; //-1 not checked earlier, 0 not, 1 yes char *logfilename; bool AppendLog(u8 *buffer, int length,bool format) { FILE *file=NULL; char buffer2[50001]; int i; struct CFG_Header *cfg_info; char *LogFile; if (LogAvailable==-1) { LogAvailable=0; cfg_info=CFG_FindGnokiirc(); if (cfg_info==NULL) return false; LogFile = CFG_Get(cfg_info, "global", "logfile"); if (LogFile) { LogAvailable=1; logfilename=LogFile; file=fopen(logfilename, "a+"); /* We have first entry in this session and too large file */ if (fread( buffer2, 1, 50000,file )==50000) { fclose(file); file=fopen(logfilename, "w"); } } } else { if (LogAvailable==1) { file=fopen(logfilename, "a"); } } if (LogAvailable==1) { for (i=0;i