/* 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. This file provides an API for accessing functions on the 7110 and similar phones. */ /* "Turn on" prototypes in n-7110.h */ #define __n_7110_c /* System header files */ #include #include #include #include #ifndef WIN32 #include "devices/device.h" #endif #ifdef WIN32 #include "misc_win32.h" #endif /* Various header file */ #ifndef VC6 #include "config.h" #endif #include "gsm-api.h" #include "gsm-coding.h" #include "newmodules/n6110.h" #include "newmodules/n7110.h" #include "protocol/fbus.h" /* Global variables used by code in gsm-api.c to expose the functions supported by this model of phone. */ /* Here we initialise model specific functions. */ GSM_Functions N7110_Functions = { N7110_Initialise, N7110_DispatchMessage, NULL_Terminate, NULL_KeepAlive, N7110_GetMemoryLocation, N7110_WritePhonebookLocation, N7110_GetSpeedDial, N7110_SetSpeedDial, N7110_GetMemoryStatus, N7110_GetSMSStatus, N6110_GetSMSCenter, N6110_SetSMSCenter, N7110_GetSMSMessage, N7110_DeleteSMSMessage, N6110_SendSMSMessage, N7110_SaveSMSMessage, N7110_GetRFLevel, N7110_GetBatteryLevel, UNIMPLEMENTED, UNIMPLEMENTED, UNIMPLEMENTED, UNIMPLEMENTED, N7110_GetSecurityCode, N6110_GetIMEI, N6110_GetRevision, N6110_GetModel, N7110_GetDateTime, N7110_SetDateTime, N7110_GetAlarm, N7110_SetAlarm, N6110_DialVoice, N6110_DialData, N6110_GetIncomingCallNr, N6110_GetNetworkInfo, N7110_GetCalendarNote, N7110_WriteCalendarNote, N7110_DeleteCalendarNote, N6110_NetMonitor, UNIMPLEMENTED, N7110_GetBitmap, N7110_SetBitmap, N7110_SetRingTone, N7110_SetBinRingTone, N7110_GetBinRingTone, N6110_Reset, N7110_GetProfile, UNIMPLEMENTED, N6110_SendRLPFrame, N6110_CancelCall, UNIMPLEMENTED, UNIMPLEMENTED, UNIMPLEMENTED, N6110_EnableCellBroadcast, N6110_DisableCellBroadcast, N6110_ReadCellBroadcast, N6110_PlayTone, N6110_GetProductProfileSetting, N6110_SetProductProfileSetting, UNIMPLEMENTED, UNIMPLEMENTED, N7110_GetVoiceMailbox, N6110_Tests, N6110_SimlockInfo, N7110_GetCalendarNotesInfo, N7110_GetSMSFolders, UNIMPLEMENTED, N7110_GetWAPBookmark, N7110_SetWAPBookmark, N7110_GetWAPSettings, N6110_CallDivert, UNIMPLEMENTED, N6110_GetManufacturer }; /* Mobile phone information */ GSM_Information N7110_Information = { "6210|6250|7110", /* Supported models in FBUS */ "6210|6250|7110", /* Supported models in MBUS */ "", /* Supported models in FBUS over infrared */ "6210|6250|7110", /* Supported models in FBUS over DLR3 */ "", "6210|6250|7110", /* Supported models in FBUS over Irda sockets */ "", 5, /* Max RF Level */ 0, /* Min RF Level */ GRF_Arbitrary, /* RF level units */ 5, /* Max Battery Level */ 0, /* Min Battery Level */ GBU_Arbitrary, /* Battery level units */ GDT_DateTime, /* Have date/time support */ GDT_TimeOnly, /* Alarm supports time only */ 1 /* Only one alarm available */ }; const char *N7110_MemoryType_String [] = { "", /* 0x00 */ "DC", /* 0x01 */ "MC", /* 0x02 */ "RC", /* 0x03 */ "FD", /* 0x04 */ "ME", /* 0x05 */ "SM", /* 0x06 */ "ON", /* 0x07 */ "EN", /* 0x08 */ "MT", /* 0x09 */ }; int PictureImageNum; //required during reading Picture Images int PictureImageIndex; int PictureImageLoc; void N7110_ReplyEnableIncomingSMSInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch (MessageBuffer[3]) { case 0x0e: #ifdef DEBUG fprintf(stdout,_("Message: Enabled info for incoming SMS\n")); #endif /* DEBUG */ CurrentMagicError=GE_NONE; break; case 0x0f: #ifdef DEBUG fprintf(stdout,_("Message: error enabling for incoming SMS\n")); switch (MessageBuffer[4]) { case 0x0c:fprintf(stdout,_(" No PIN\n"));break; default :fprintf(stdout,_(" unknown\n"));break; } #endif /* DEBUG */ CurrentMagicError=GE_UNKNOWN; break; } } GSM_Error N7110_EnableIncomingSMSInfo () { unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02}; return NULL_SendMessageSequence (50, &CurrentMagicError, 8, 0x02, req); } /* Initialise variables and state machine. */ GSM_Error N7110_Initialise(char *port_device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) { unsigned char init_char = N6110_SYNC_BYTE; int count; int InitLength; if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE) { return GE_NOTSUPPORTED; } if (connection!=GCT_MBUS && connection!=GCT_Irda) { 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; if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT; if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT; // N7110_EnableIncomingSMSInfo(); if (connection==GCT_MBUS || connection==GCT_Irda) { /* In MBUS doesn't have any init strings, etc. Phone answered with frame, so connection should be enabled ;-) */ /* Similiar for Irda */ CurrentLinkOK = true; } CurrentSMSFoldersCount=1000; CurrentSMSMessage=NULL; return (GE_NONE); } /* This function translates GMT_MemoryType to N7110_MEMORY_xx */ int N7110_GetMemoryType(GSM_MemoryType memory_type) { int result; switch (memory_type) { // case GMT_MT: // result = N7110_MEMORY_MT; // break; case GMT_ME: result = N7110_MEMORY_ME; break; case GMT_SM: result = N7110_MEMORY_SM; break; case GMT_FD: result = N7110_MEMORY_FD; break; case GMT_ON: result = N7110_MEMORY_ON; break; case GMT_EN: result = N7110_MEMORY_EN; break; case GMT_DC: result = N7110_MEMORY_DC; break; case GMT_RC: result = N7110_MEMORY_RC; break; case GMT_MC: result = N7110_MEMORY_MC; break; case GMT_CG: result = N7110_MEMORY_CG; break; default : result = N6110_MEMORY_XX; } return (result); } GSM_Error N7110_GetVoiceMailbox ( GSM_PhonebookEntry *entry) { unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01, 0x02, //memory type 0x05, 0x00, 0x00, //location 0x00, 0x00}; CurrentPhonebookEntry = entry; req[9] = N7110_MEMORY_VM; req[10] = (1>>8); req[11] = 1 & 0xff; return NULL_SendMessageSequence (50, &CurrentPhonebookError, 14, 0x03, req); } void N7110_ReplyEnableWAPCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch(MessageBuffer[3]) { case 0x01: #ifdef DEBUG fprintf(stdout, _("Message: WAP functions enabled\n")); #endif /* DEBUG */ CurrentGetWAPBookmarkError=GE_NONE; break; case 0x02: #ifdef DEBUG fprintf(stdout, _("Message: WAP functions enabled\n")); #endif /* DEBUG */ CurrentGetWAPBookmarkError=GE_NONE; break; } } /* To enable WAP frames in phone */ GSM_Error N7110_EnableWAPCommands () { unsigned char req0[] = { N6110_FRAME_HEADER, 0x00 }; return NULL_SendMessageSequence (50, &CurrentGetWAPBookmarkError, 4, 0x3f, req0); } void N7110_ReplyGetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int tmp; switch(MessageBuffer[3]) { case 0x07: #ifdef DEBUG fprintf(stdout, _("Message: WAP bookmark received OK\n")); #endif /* DEBUG */ DecodeUnicode(WAPBookmark->title, MessageBuffer + 7, MessageBuffer[6] ); #ifdef DEBUG fprintf(stdout, _(" Title: \"%s\"\n"),WAPBookmark->title); #endif /* DEBUG */ tmp=MessageBuffer[6]*2+7; DecodeUnicode(WAPBookmark->address, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Address: \"%s\"\n"),WAPBookmark->address); #endif /* DEBUG */ CurrentGetWAPBookmarkError=GE_NONE; break; case 0x08: #ifdef DEBUG fprintf(stdout, _("Message: WAP bookmark receiving error\n")); switch (MessageBuffer[4]) { case 0x01:fprintf(stdout, _(" Inside Bookmarks menu. Must leave it\n"));break; case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break; default :fprintf(stdout, _(" Unknown error. Please report it\n")); } #endif /* DEBUG */ switch (MessageBuffer[4]) { case 0x01:CurrentGetWAPBookmarkError=GE_INSIDEBOOKMARKSMENU;break; case 0x02:CurrentGetWAPBookmarkError=GE_INVALIDBOOKMARKLOCATION;break; default:CurrentGetWAPBookmarkError=GE_UNKNOWN; } break; } } GSM_Error N7110_GetWAPBookmark (GSM_WAPBookmark *bookmark) { unsigned char req[] = { N6110_FRAME_HEADER, 0x06, 0x00, 0x00}; GSM_Error error; /* We have to enable WAP frames in phone */ error=N7110_EnableWAPCommands (); if (error!=GE_NONE) return error; req[2]=0x00; req[5]=bookmark->location-1; WAPBookmark=bookmark; return NULL_SendMessageSequence (50, &CurrentGetWAPBookmarkError, 6, 0x3f, req); } void N7110_ReplySetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch(MessageBuffer[3]) { case 0x0a: #ifdef DEBUG fprintf(stdout, _("Message: WAP bookmark set OK\n")); #endif /* DEBUG */ CurrentSetWAPBookmarkError=GE_NONE; break; case 0x0b: #ifdef DEBUG fprintf(stdout, _("Message: Error setting WAP bookmark\n")); #endif /* DEBUG */ CurrentSetWAPBookmarkError=GE_UNKNOWN; break; } } GSM_Error N7110_SetWAPBookmark (GSM_WAPBookmark *bookmark) { unsigned char req[64] = { N6110_FRAME_HEADER, 0x09 }; GSM_Error error; int count; /* We have to enable WAP frames in phone */ error = N7110_EnableWAPCommands (); if (error != GE_NONE) return error; count = 4; req[count++] = (bookmark->location & 0xff00) >> 8; req[count++] = (bookmark->location & 0x00ff); req[count++] = strlen(bookmark->title); EncodeUnicode (req+count,bookmark->title ,strlen(bookmark->title)); count=count+2*strlen(bookmark->title); req[count++] = strlen(bookmark->address); EncodeUnicode (req+count,bookmark->address ,strlen(bookmark->address)); count=count+2*strlen(bookmark->address); /* ??? */ req[count++] = 0x01; req[count++] = 0x80; req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00; WAPBookmark = bookmark; return NULL_SendMessageSequence(50, &CurrentSetWAPBookmarkError, count, 0x3f, req); } void N7110_ReplyGetWAPSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int tmp; switch(MessageBuffer[3]) { case 0x16: #ifdef DEBUG fprintf(stdout, _("Message: WAP settings received OK\n")); #endif /* DEBUG */ DecodeUnicode(WAPSettings->title, MessageBuffer + 5, MessageBuffer[4] ); #ifdef DEBUG fprintf(stdout, _(" Title: \"%s\"\n"),WAPSettings->title); #endif /* DEBUG */ tmp=5+MessageBuffer[4]*2; DecodeUnicode(WAPSettings->homepage, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Homepage: \"%s\"\n"),WAPSettings->homepage); #endif /* DEBUG */ tmp=tmp+MessageBuffer[tmp]*2+1; #ifdef DEBUG fprintf(stdout, _(" Connection type: ")); switch (MessageBuffer[tmp]) { case 0x00: fprintf(stdout,_("temporary"));break; case 0x01: fprintf(stdout,_("continuous"));break; default: fprintf(stdout,_("unknown")); } fprintf(stdout, _("\n")); fprintf(stdout, _(" Connection security: ")); switch (MessageBuffer[tmp+13]) { case 0x00: fprintf(stdout,_("off"));break; case 0x01: fprintf(stdout,_("on"));break; default: fprintf(stdout,_("unknown")); } fprintf(stdout, _("\n")); #endif /* DEBUG */ switch (MessageBuffer[tmp]) { case 0x00: WAPSettings->iscontinuous=false;break; case 0x01: WAPSettings->iscontinuous=true;break; } switch (MessageBuffer[tmp+13]) { case 0x00: WAPSettings->issecurity=false;break; case 0x01: WAPSettings->issecurity=true;break; } WAPSettings->location=MessageBuffer[tmp+7];//location for second part CurrentGetWAPSettingsError=GE_NONE; break; case 0x17: #ifdef DEBUG fprintf(stdout, _("Message: WAP settings receiving error\n")); switch (MessageBuffer[4]) { case 0x01:fprintf(stdout, _(" Inside Settings menu. Must leave it\n"));break; case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break; default :fprintf(stdout, _(" Unknown error. Please report it\n")); } #endif /* DEBUG */ switch (MessageBuffer[4]) { case 0x01:CurrentGetWAPSettingsError=GE_INSIDESETTINGSMENU;break; case 0x02:CurrentGetWAPSettingsError=GE_INVALIDSETTINGSLOCATION;break; default :CurrentGetWAPSettingsError=GE_UNKNOWN; } break; case 0x1c: #ifdef DEBUG fprintf(stdout, _("Message: WAP settings received OK\n")); #endif /* DEBUG */ switch (MessageBuffer[5]) { case 0x00: WAPSettings->bearer=WAPSETTINGS_BEARER_SMS; #ifdef DEBUG fprintf(stdout, _(" Settings for SMS bearer:\n")); #endif /* DEBUG */ tmp=6; DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service); #endif /* DEBUG */ tmp=tmp+MessageBuffer[tmp]*2+1; DecodeUnicode(WAPSettings->server, MessageBuffer + tmp+ 1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Server number: \"%s\"\n"),WAPSettings->server); #endif /* DEBUG */ break; case 0x01: WAPSettings->bearer=WAPSETTINGS_BEARER_DATA; #ifdef DEBUG fprintf(stdout, _(" Settings for data bearer:\n")); #endif /* DEBUG */ tmp=10; DecodeUnicode(WAPSettings->ipaddress, MessageBuffer + tmp+ 1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->ipaddress); #endif /* DEBUG */ tmp=tmp+MessageBuffer[tmp]*2+1; DecodeUnicode(WAPSettings->dialup, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Dial-up number: \"%s\"\n"),WAPSettings->dialup); #endif /* DEBUG */ tmp=tmp+MessageBuffer[tmp]*2+1; DecodeUnicode(WAPSettings->user, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" User name: \"%s\"\n"),WAPSettings->user); #endif /* DEBUG */ tmp=tmp+MessageBuffer[tmp]*2+1; DecodeUnicode(WAPSettings->password, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Password: \"%s\"\n"),WAPSettings->password); #endif /* DEBUG */ #ifdef DEBUG fprintf(stdout, _(" Authentication type: ")); switch (MessageBuffer[6]) { case 0x00: fprintf(stdout,_("normal"));break; case 0x01: fprintf(stdout,_("secure"));break; default: fprintf(stdout,_("unknown"));break; } fprintf(stdout, _("\n")); fprintf(stdout, _(" Data call type: ")); switch (MessageBuffer[7]) { case 0x00: fprintf(stdout,_("analogue"));break; case 0x01: fprintf(stdout,_("IDSN"));break; default: fprintf(stdout,_("unknown"));break; } fprintf(stdout, _("\n")); fprintf(stdout, _(" Data call speed: ")); switch (MessageBuffer[9]) { case 0x01: fprintf(stdout,_("9600"));break; case 0x02: fprintf(stdout,_("14400"));break; default: fprintf(stdout,_("unknown"));break; } fprintf(stdout, _("\n")); #endif /* DEBUG */ switch (MessageBuffer[6]) { case 0x00: WAPSettings->isnormalauthentication=true;break; case 0x01: WAPSettings->isnormalauthentication=false;break; } switch (MessageBuffer[7]) { case 0x00: WAPSettings->isISDNcall=false;break; case 0x01: WAPSettings->isISDNcall=true;break; } switch (MessageBuffer[9]) { case 0x01: WAPSettings->isspeed14400=false;break; case 0x02: WAPSettings->isspeed14400=true;break; } break; case 0x02: WAPSettings->bearer=WAPSETTINGS_BEARER_USSD; #ifdef DEBUG fprintf(stdout, _(" Settings for USSD bearer:\n")); #endif /* DEBUG */ tmp=7; DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG if (MessageBuffer[6]==0x01) fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service); else fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->service); #endif /* DEBUG */ WAPSettings->isIP=true; if (MessageBuffer[6]==0x01) WAPSettings->isIP=false; tmp=tmp+MessageBuffer[tmp]*2+1; DecodeUnicode(WAPSettings->code, MessageBuffer + tmp+1, MessageBuffer[tmp] ); #ifdef DEBUG fprintf(stdout, _(" Service code: \"%s\"\n"),WAPSettings->code); #endif /* DEBUG */ } CurrentGetWAPSettingsError=GE_NONE; break; } } GSM_Error N7110_GetWAPSettings (GSM_WAPSettings *settings) { unsigned char req[] = { N6110_FRAME_HEADER, 0x15, 0x00}; unsigned char req2[] = { N6110_FRAME_HEADER, 0x1b, 0x00}; GSM_Error error; /* We have to enable WAP frames in phone */ error=N7110_EnableWAPCommands (); if (error!=GE_NONE) return error; req[2]=0x00; req[4]=settings->location-1; WAPSettings=settings; error=NULL_SendMessageSequence (50, &CurrentGetWAPSettingsError, 6, 0x3f, req); if (error!=GE_NONE) return error; req2[2]=0x00; req2[4]=settings->location; return NULL_SendMessageSequence (50, &CurrentGetWAPSettingsError, 6, 0x3f, req2); } void N7110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { if (CurrentMemoryStatus && CurrentMemoryStatusError == GE_BUSY) { /* first Loc. (MessageBuffer[10]<<8) + MessageBuffer[11]; */ CurrentMemoryStatus->Free = (MessageBuffer[14]<<8) + MessageBuffer[15]; CurrentMemoryStatus->Used = (MessageBuffer[16]<<8) + MessageBuffer[17]; CurrentMemoryStatus->Free -= CurrentMemoryStatus->Used; CurrentMemoryStatusError = GE_NONE; #ifdef DEBUG fprintf(stdout, _("Message: Memory status received:\n")); fprintf(stdout, _(" Memory Type: %s\n"), N7110_MemoryType_String[MessageBuffer[5]]); fprintf(stdout, _(" Used: %d\n"), CurrentMemoryStatus->Used); fprintf(stdout, _(" Free: %d\n"), CurrentMemoryStatus->Free); #endif /* DEBUG */ } } /* This function is used to get storage status from the phone. It currently supports two different memory areas - internal and SIM. */ GSM_Error N7110_GetMemoryStatus(GSM_MemoryStatus *Status) { unsigned char req[] = { N6110_FRAME_HEADER, 0x03, /* MemoryStatus request */ 0x02, 0x05 /* MemoryType */ }; switch (Status->MemoryType) { case GMT_ME: case GMT_SM: CurrentMemoryStatus = Status; req[5] = N7110_GetMemoryType(Status->MemoryType); return NULL_SendMessageSequence (20, &CurrentMemoryStatusError, 6, 0x03, req); break; case GMT_DC: case GMT_RC: case GMT_MC: Status->Free = 0; Status->Used = 20; return GE_NONE; default: return GE_NOTSUPPORTED; } } void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch(MessageBuffer[3]) { case 0x02: #ifdef DEBUG fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]); #endif /* DEBUG */ switch (MessageBuffer[6]) { case 0xff: /* Profile Name */ DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]); #ifdef DEBUG fprintf(stdout,_(" Name \"%s\"\n"),CurrentProfile->Name); #endif /* DEBUG */ break; case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */ switch( MessageBuffer[10] ) { case 0: CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break; case 1: case 2: case 3: CurrentProfile->KeypadTone = MessageBuffer[10]-1; break; } break; case 0x02: /* Call Alert type (Ringing, Ascending, ..., Off) */ /* I make it compatible with GetProfileCallAlertString */ switch( MessageBuffer[10] ) { case 0: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGING; break; case 1: CurrentProfile->CallAlert = PROFILE_CALLALERT_ASCENDING; break; case 2: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGONCE; break; case 3: CurrentProfile->CallAlert = PROFILE_CALLALERT_BEEPONCE; break; case 5: CurrentProfile->CallAlert = PROFILE_CALLALERT_OFF; break; } break; case 0x03: /* Ringtone number */ CurrentProfile->Ringtone = MessageBuffer[10]; break; case 0x04: /* Ringtone volume (from level 1 to level 5) */ CurrentProfile->Volume = MessageBuffer[10] + 6; break; case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */ CurrentProfile->MessageTone = MessageBuffer[10]; break; case 0x06: /* Vibration (On/Off) */ CurrentProfile->Vibration = MessageBuffer[10]; break; case 0x07: /* WarningTone (On/Off) */ switch( MessageBuffer[10] ) { case 0: CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break; case 1: CurrentProfile->WarningTone = PROFILE_WARNING_ON; break; } break; case 0x08: /* Alert for (caller groups) */ CurrentProfile->CallerGroups = MessageBuffer[10]; break; case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */ CurrentProfile->AutomaticAnswer = MessageBuffer[10]; break; } CurrentProfileError=GE_NONE; break; default: #ifdef DEBUG fprintf(stdout, _("Message: Unknown message of type 0x39\n")); #endif /* DEBUG */ AppendLogText("Unknown msg\n",false); break; /* Visual C Don't like empty cases */ } } GSM_Error N7110_GetProfile(GSM_Profile *Profile) { int i; unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x00, //profile number 0xff}; //feature. Here 0xff=name unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22, 0x00,0x02,0x09 }; GSM_Error error; CurrentProfile = Profile; /* When after sending all frames feature==253, it means, that it is not supported */ CurrentProfile->KeypadTone=253; CurrentProfile->Lights=253; CurrentProfile->CallAlert=253; CurrentProfile->Ringtone=253; CurrentProfile->Volume=253; CurrentProfile->MessageTone=253; CurrentProfile->WarningTone=253; CurrentProfile->Vibration=253; CurrentProfile->CallerGroups=253; CurrentProfile->ScreenSaver=253; CurrentProfile->AutomaticAnswer=253; req[7] = Profile->Number+1; error=NULL_SendMessageSequence (20, &CurrentProfileError, 9, 0x39, req); if (error!=GE_NONE) return error; for (i = 0; i < 11; i++) { req[7] = Profile->Number+1; req[8] = req2[i]; error=NULL_SendMessageSequence (20, &CurrentProfileError, 9, 0x39, req); if (error!=GE_NONE) return error; } return (GE_NONE); } void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i; CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5]; CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany; for(i=0;iLocation[i]=CurrentCalendarNotesInfo.Location[i]; } CurrentCalendarNotesInfoError=GE_NONE; } GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo) { unsigned char req[] = { N6110_FRAME_HEADER, 0x3a, /* get notes info */ 0xFF, 0xFE //fixed }; GSM_Error error; CurrentCalendarNotesInfo2=NotesInfo; error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req); return error; } void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2) { time_t t_alarm; struct tm tm_time; struct tm *tm_alarm; #ifdef DEBUG if (alarmdiff == 0xffff) fprintf(stdout," No alarm"); else fprintf(stdout," Alarm is %i seconds before date", alarmdiff*alarm2); fprintf(stdout,"\n"); #endif if (alarmdiff != 0xffff) { memset(&tm_time, 0, sizeof(tm_time)); tm_time.tm_year = time->Year - 1900; tm_time.tm_mon = time->Month - 1; tm_time.tm_mday = time->Day; tm_time.tm_hour = time->Hour; tm_time.tm_min = time->Minute; tm_time.tm_sec = time->Second; tzset(); t_alarm = mktime(&tm_time); t_alarm -= alarmdiff*alarm2; tm_alarm = localtime(&t_alarm); alarm->Year = tm_alarm->tm_year + 1900; alarm->Month = tm_alarm->tm_mon + 1; alarm->Day = tm_alarm->tm_mday; alarm->Hour = tm_alarm->tm_hour; alarm->Minute = tm_alarm->tm_min; alarm->Second = tm_alarm->tm_sec; #ifdef DEBUG fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n", alarm->Day,alarm->Month,alarm->Year, alarm->Hour,alarm->Minute,alarm->Second); #endif } } void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c) { time_t alarmdiff; c->Time.Year = block[8]*256+block[9]; c->Time.Month = block[10]; c->Time.Day = block[11]; if (c->Type != GCN_REMINDER) { c->Time.Hour = block[12]; c->Time.Minute = block[13]; } else { c->Time.Hour = 0; c->Time.Minute = 0; } c->Time.Second = 0; #ifdef DEBUG fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n", c->Time.Day,c->Time.Month,c->Time.Year, c->Time.Hour,c->Time.Minute,c->Time.Second); #endif if (c->Type != GCN_REMINDER) { alarmdiff = block[14]*256 + block[15]; P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60); c->Recurrance = block[16]*256 + block[17]; DecodeUnicode(c->Text, block+20, block[18]); } else { c->Recurrance = block[12]*256 + block[13]; DecodeUnicode(c->Text, block+16, block[14]); } /* 0xffff -> 1 Year (8760 hours) */ if (c->Recurrance == 0xffff) c->Recurrance=8760; #ifdef DEBUG fprintf(stdout, " Recurrance: %i hours\n Text: \"%s\"\n", c->Recurrance,c->Text); #endif } void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int alarm; CurrentCalendarNote->YearOfBirth=0; //for other than birthday CurrentCalendarNote->AlarmType=0x00;//for other than birthday CurrentCalendarNote->Phone[0]=0; //for other than call CurrentCalendarNote->Alarm.Year = 0; CurrentCalendarNote->Alarm.Month = 0; CurrentCalendarNote->Alarm.Day = 0; CurrentCalendarNote->Alarm.Hour = 0; CurrentCalendarNote->Alarm.Minute = 0; CurrentCalendarNote->Alarm.Second = 0; #ifdef DEBUG fprintf(stdout, "Message: calendar note received\n"); #endif switch (MessageBuffer[6]) /* entry type */ { case 0x01: /* Meeting */ #ifdef DEBUG fprintf(stdout, " Note type: meeting\n"); #endif CurrentCalendarNote->Type = GCN_MEETING; P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote); CurrentCalendarNoteError=GE_NONE; break; case 0x02: /* Call */ #ifdef DEBUG fprintf(stdout, " Note type: call\n"); #endif CurrentCalendarNote->Type = GCN_CALL; P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote); DecodeUnicode(CurrentCalendarNote->Phone, MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]); #ifdef DEBUG fprintf(stdout, " Phone number: \"%s\"\n",CurrentCalendarNote->Phone); #endif CurrentCalendarNoteError=GE_NONE; break; case 0x04: /* Birthday */ #ifdef DEBUG fprintf(stdout, " Note type: birthday\n"); #endif CurrentCalendarNote->Type = GCN_BIRTHDAY; alarm = ((unsigned int)MessageBuffer[14]) << 24; alarm += ((unsigned int)MessageBuffer[15]) << 16; alarm += ((unsigned int)MessageBuffer[16]) << 8; alarm += MessageBuffer[17]; /* CurrentCalendarNote->Time.Year is set earlier */ CurrentCalendarNote->Time.Month = MessageBuffer[10]; CurrentCalendarNote->Time.Day = MessageBuffer[11]; CurrentCalendarNote->Time.Hour = 23; CurrentCalendarNote->Time.Minute = 59; CurrentCalendarNote->Time.Second = 58; P7110_GetNoteAlarm(alarm, &(CurrentCalendarNote->Time), &(CurrentCalendarNote->Alarm) ,1); CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19]; CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth; CurrentCalendarNote->AlarmType = MessageBuffer[20]; #ifdef DEBUG fprintf(stdout,_(" Alarm type: %s\n"), (CurrentCalendarNote->AlarmType==0x00) ? "Tone " : "Silent"); fprintf(stdout, " Birthday date: %02i-%02i-%04i (age %d)\n",CurrentCalendarNote->Time.Day, CurrentCalendarNote->Time.Month,CurrentCalendarNote->Time.Year, CurrentCalendarNote->Alarm.Year - CurrentCalendarNote->Time.Year); #endif DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]); #ifdef DEBUG fprintf(stdout, " Text: \"%s\"\n",CurrentCalendarNote->Text); #endif CurrentCalendarNote->Recurrance = 0; CurrentCalendarNoteError=GE_NONE; break; case 0x08: /* Reminder */ #ifdef DEBUG fprintf(stdout, " Note type: reminder\n"); #endif CurrentCalendarNote->Type = GCN_REMINDER; P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote); CurrentCalendarNoteError=GE_NONE; break; default: /* unknown */ #ifdef DEBUG fprintf(stdout, " Note type: UNKNOWN\n"); #endif break; } } GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote) { unsigned char req[] = { N6110_FRAME_HEADER, 0x19, /* get calendar note */ 0x00, 0x00 //location }; GSM_Error error; GSM_DateTime date_time; struct tm *now; time_t nowh; if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) { error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo); if (error!=GE_NONE) return error; } #ifdef DEBUG fprintf(stdout, _("Calendar Notes Location Logical = %d.\n"), CalendarNote->Location); fprintf(stdout, _("Calendar Notes Location Phisical = %d.\n"), CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]); #endif /* this is for making xgnokii work.. */ if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany ) return GE_INVALIDCALNOTELOCATION; req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8; req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff; CurrentCalendarNote = CalendarNote; /* We have to get current year. It's NOT written in frame for Birthday */ error=N7110_GetDateTime(&date_time); if (error!=GE_NONE) return error; if (!date_time.IsSet) { nowh=time(NULL); now=localtime(&nowh); /* I have 100 (for 2000) Year now :-) */ if (now->tm_year>99 && now->tm_year<1900) { now->tm_year=now->tm_year+1900; } date_time.Year=now->tm_year; } CurrentCalendarNote->Time.Year = date_time.Year; error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req); CurrentCalendarNote = NULL; return error; } void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { #ifdef DEBUG char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" }; fprintf(stdout, "Succesfully written Calendar Note Type %s on location %d\n", kz_types[(MessageBuffer[3]/2)-1], MessageBuffer[4]*256+MessageBuffer[5] ); fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n", MessageBuffer[6]*256+MessageBuffer[7] ); #endif CurrentCalendarNoteError=GE_NONE; } long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm) { time_t t_alarm; time_t t_time; struct tm tm_alarm; struct tm tm_time; tzset(); tm_alarm.tm_year=alarm->Year-1900; tm_alarm.tm_mon=alarm->Month-1; tm_alarm.tm_mday=alarm->Day; tm_alarm.tm_hour=alarm->Hour; tm_alarm.tm_min=alarm->Minute; tm_alarm.tm_sec=alarm->Second; tm_alarm.tm_isdst=0; t_alarm = mktime(&tm_alarm); tm_time.tm_year=time->Year-1900; tm_time.tm_mon=time->Month-1; tm_time.tm_mday=time->Day; tm_time.tm_hour=time->Hour; tm_time.tm_min=time->Minute; tm_time.tm_sec=time->Second; tm_time.tm_isdst=0; t_time = mktime(&tm_time); #ifdef DEBUG fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n", alarm->Day,alarm->Month,alarm->Year, alarm->Hour,alarm->Minute,alarm->Second); fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n", time->Day,time->Month,time->Year, time->Hour,time->Minute,time->Second); fprintf(stdout,_("Difference in alarm time is %f\n"),difftime( t_time, t_alarm )+3600); #endif return difftime( t_time ,t_alarm )+3600; } GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote) { unsigned char req[200] = { N6110_FRAME_HEADER, 0x01, /* note type ... */ 0x00, 0x00, /* location */ 0x00, /* entry type */ 0x00, //fixed 0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */ /* here starts block */ 0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */ }; int count=0; long seconds, minutes; GSM_Error error; int firstFreeLocation; /* * 6210/7110 needs to seek the first free pos to inhabit with next note */ error=N7110_FirstCalendarFreePos(&firstFreeLocation); if (error!=GE_NONE) return error; #ifdef DEBUG fprintf(stdout, _("First free calendar location is = %d.\n"), firstFreeLocation); #endif /* Location */ req[4]=0x00; req[5]=0x00; switch( CalendarNote->Type ) { case GCN_MEETING : req[6]=0x01; req[3]=0x01; break; case GCN_CALL : req[6]=0x02; req[3]=0x03; break; case GCN_BIRTHDAY: req[6]=0x04; req[3]=0x05; break; case GCN_REMINDER: req[6]=0x08; req[3]=0x07; break; } req[8]=CalendarNote->Time.Year>>8; req[9]=CalendarNote->Time.Year&0xff; req[10]=CalendarNote->Time.Month; req[11]=CalendarNote->Time.Day; /* From here starts BLOCK */ count=12; switch( CalendarNote->Type ) { case GCN_MEETING: req[count++]=CalendarNote->Time.Hour; // 12 req[count++]=CalendarNote->Time.Minute; // 13 /* Alarm .. */ req[count++]=0xff; // 14 req[count++]=0xff; // 15 if( CalendarNote->Alarm.Year ) { seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, &CalendarNote->Alarm); if( seconds>=0L ) { /* Otherwise it's an error condition.... */ minutes=seconds/60L; count-=2; req[count++]=minutes>>8; req[count++]=minutes&0xff; } } /* Recurrance */ if( CalendarNote->Recurrance >= 8760 ) CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */ req[count++]=CalendarNote->Recurrance>>8; // 16 req[count++]=CalendarNote->Recurrance&0xff; // 17 /* len of text */ req[count++]=strlen(CalendarNote->Text); // 18 /* fixed 0x00 */ req[count++]=0x00; // 19 /* Text */ #ifdef DEBUG fprintf(stdout, "Count before encode = %d\n", count ); fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text ); #endif EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N count=count+2*strlen(CalendarNote->Text); break; case GCN_CALL: req[count++]=CalendarNote->Time.Hour; // 12 req[count++]=CalendarNote->Time.Minute; // 13 /* Alarm .. */ req[count++]=0xff; // 14 req[count++]=0xff; // 15 if( CalendarNote->Alarm.Year ) { seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, &CalendarNote->Alarm); if( seconds>=0L ) { /* Otherwise it's an error condition.... */ minutes=seconds/60L; count-=2; req[count++]=minutes>>8; req[count++]=minutes&0xff; } } /* Recurrance */ if( CalendarNote->Recurrance >= 8760 ) CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */ req[count++]=CalendarNote->Recurrance>>8; // 16 req[count++]=CalendarNote->Recurrance&0xff; // 17 /* len of text */ req[count++]=strlen(CalendarNote->Text); // 18 /* fixed 0x00 */ req[count++]=strlen(CalendarNote->Phone); // 19 /* Text */ EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N count=count+2*strlen(CalendarNote->Text); EncodeUnicode (req+count,CalendarNote->Phone ,strlen(CalendarNote->Phone));// (N+1)->n count=count+2*strlen(CalendarNote->Phone); break; case GCN_BIRTHDAY: req[count++]=0x00; // 12 Fixed req[count++]=0x00; // 13 Fixed /* Alarm .. */ req[count++]=0x00; req[count++]=0x00; // 14, 15 req[count++]=0xff; // 16 req[count++]=0xff; // 17 if( CalendarNote->Alarm.Year ) { // I try with Time.Year = Alarm.Year. If negative, I increase 1 year, // but only once ! This thing, because I may have Alarm period across // a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27) CalendarNote->Time.Year = CalendarNote->Alarm.Year; if( (seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, &CalendarNote->Alarm)) < 0L ) { CalendarNote->Time.Year++; seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, &CalendarNote->Alarm); } if( seconds>=0L ) { /* Otherwise it's an error condition.... */ count-=4; req[count++]=seconds>>24; // 14 req[count++]=(seconds>>16) & 0xff; // 15 req[count++]=(seconds>>8) & 0xff; // 16 req[count++]=seconds&0xff; // 17 } } req[count++]=CalendarNote->AlarmType; // 18 /* len of text */ req[count++]=strlen(CalendarNote->Text); // 19 /* Text */ #ifdef DEBUG fprintf(stdout, "Count before encode = %d\n", count ); fprintf(stdout, "Meeting Text is = \"%s\" Altype is 0x%02x \n", CalendarNote->Text , CalendarNote->AlarmType ); #endif EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N count=count+2*strlen(CalendarNote->Text); break; case GCN_REMINDER: /* Recurrance */ if( CalendarNote->Recurrance >= 8760 ) CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */ req[count++]=CalendarNote->Recurrance>>8; // 12 req[count++]=CalendarNote->Recurrance&0xff; // 13 /* len of text */ req[count++]=strlen(CalendarNote->Text); // 14 /* fixed 0x00 */ req[count++]=0x00; // 15 /* Text */ EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N count=count+2*strlen(CalendarNote->Text); break; } /* padding */ req[count]=0x00; #ifdef DEBUG fprintf(stdout, "Count after padding = %d\n", count ); #endif CurrentCalendarNote = CalendarNote; error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req); CurrentCalendarNote = NULL; return error; } void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5]; CurrentFirstCalendarFreePosError=GE_NONE; } GSM_Error N7110_FirstCalendarFreePos(int *FreePos) { unsigned char req[] = { N6110_FRAME_HEADER, 0x31 }; GSM_Error error; CurrentFirstCalendarFreePos = FreePos; error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError, 4, 0x13, req); CurrentFirstCalendarFreePos = NULL; return error; } void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { #ifdef DEBUG fprintf(stdout, "Succesfully Delete Calendar Note on location %d\n", MessageBuffer[4]*256+MessageBuffer[5] ); fprintf(stdout, "--> Other data are :\n" ); fprintf(stdout, " '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d)\n", MessageBuffer[6], MessageBuffer[6], MessageBuffer[6], MessageBuffer[7], MessageBuffer[7], MessageBuffer[7], MessageBuffer[8], MessageBuffer[8], MessageBuffer[8], MessageBuffer[9], MessageBuffer[9], MessageBuffer[9] ); #endif CurrentCalendarNoteError=GE_NONE; } GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote) { unsigned char req[] = { N6110_FRAME_HEADER, 0x0b, /* delete calendar note */ 0x00, 0x00 //location }; GSM_Error error; if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) { error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo); if (error!=GE_NONE) return error; } /* this is for making xgnokii work.. */ if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany ) return GE_INVALIDCALNOTELOCATION; req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8; req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff; CurrentCalendarNote = CalendarNote; error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req); CurrentCalendarNote = NULL; return error; } void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { wchar_t wc; int i, j, tmp; #ifdef DEBUG fprintf(stdout, _("Message: SMS Folders received:\n")); #endif /* DEBUG */ i=5; CurrentSMSFoldersCount=MessageBuffer[4]; for (j=0;jFolder[j].Name," "); #ifdef DEBUG fprintf(stdout, _(" Folder Index: %d"),MessageBuffer[i]); #endif /* DEBUG */ CurrentSMSFolders->FoldersID[j]=MessageBuffer[i]; i=i+2; #ifdef DEBUG fprintf(stdout, _(", folder name: ")); #endif /* DEBUG */ tmp=0; while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) { wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8); CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc); #ifdef DEBUG fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]); #endif /* DEBUG */ tmp++; i=i+2; } #ifdef DEBUG fprintf(stdout, _("\n")); #endif /* DEBUG */ tmp=0; i=i+1; } CurrentSMSFoldersError=GE_NONE; } GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders) { unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00}; GSM_Error error; CurrentSMSFolders=folders; error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req); folders->number=CurrentSMSFoldersCount; return error; } void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i; #ifdef DEBUG fprintf(stdout, _("Message: SMS Folder status received\n")); fprintf(stdout, _(" Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]); #endif /* DEBUG */ CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5]; #ifdef DEBUG fprintf(stdout, _(" (indexes ")); #endif /* DEBUG */ for (i=0;iLocation; /* We made "fake" SMS numbering for SMS in 7110/6210/etc. */ if ((error = N7110_HandleSMSLocation(smsnum, &folderid, &location, NULL, GSH_DELETE))!=GE_NONE) return(error); req[4]=folderid; req[5]=location / 256; req[6]=location; #ifdef DEBUG printf("delete sms: folder %d, location %d\n",folderid,location); #endif return NULL_SendMessageSequence (50, &CurrentSMSMessageError, 8, 0x14, req); } GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message) { unsigned char req[] = { N6110_FRAME_HEADER, 0x07, 0x08, // folder ID 0x00, 0x05, // location 0x01, 0x65, 0x01}; int smsnum, location; u8 folderid; GSM_Error error; CurrentSMSMessage = message; CurrentSMSMessageError = GE_BUSY; smsnum = message->Location; /* we make central handling of real location */ error = N7110_HandleSMSLocation(smsnum, &folderid, &location, message, GSH_GET); /* if smsnum is 0 (next sms) we need real smsnum */ N7110_SMS2FakeLocation( &smsnum, folderid, location); message->Location = smsnum; switch(error) { case GE_SMSISINMEM: /* future use: get already reed sms from mem */ return GE_NONE; break; case GE_NONE: req[4]=folderid; req[5]=location / 256; req[6]=location; #ifdef DEBUG fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location); #endif return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req); break; default: break; } return(error); } void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int smsnum; switch (MessageBuffer[3]) { /* save sms */ case 0x05: #ifdef DEBUG fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]); #endif if (CurrentSMSMessage!=NULL) { N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]); CurrentSMSMessage->MessageNumber=smsnum; } CurrentSMSMessageError = GE_NONE; break; /* save sms failed */ case 0x06: #ifdef DEBUG fprintf(stdout, _("Message: SMS Message save failed\n")); #endif CurrentSMSMessageError = GE_SMSSAVEFAILED; break; case 0x84: #ifdef DEBUG fprintf(stdout, _("Message: Changed name for SMS Message\n")); #endif CurrentSMSMessageError = GE_NONE; break; } } GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS) { unsigned char req[256] = { N6110_FRAME_HEADER, 0x04, /* SMS save request*/ 0x03, /* default: mark sms as GSS_NOTSENTREAD */ 0x10, /* folder (req[5])*/ 0x00, /* location */ 0x00, /* location (req[7])*/ 0x00 /* ??? */ }; unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83}; int length,smsnum,location; u8 folderid; GSM_Error error; SMS_MessageType PDU; smsnum = SMS->Location; #ifdef DEBUG printf("save sms: smsnum is :%d\n",smsnum); #endif if ( SMS->Status == GSS_SENTREAD) req[4] = 0x01; folderid = SMS->folder; PDU=SMS_Deliver; error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU); if (error != GE_NONE) return error; CurrentSMSMessage = SMS; error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE); switch (error) { case GE_BUSYSMSLOCATION: /* delete old sms before save */ error = N7110_DeleteSMSMessage(SMS); if (error != GE_NONE) return error; break; case GE_NONE: break; default: return error; break; } #ifdef DEBUG printf("save sms: want to save at folder:%d , location:%d\n",folderid,location); #endif req[5]=folderid; req[6]=location / 256; req[7]=location; error=NULL_SendMessageSequence (70, &CurrentSMSMessageError, 40+length, 0x14, req); if (error==GE_NONE && SMS->Name[0]!=0) { length=4; N7110_Fake2SMSLocation(SMS->MessageNumber, &folderid, &location); req2[length++]=folderid; req2[length++]=location / 256; req2[length++]=location; EncodeUnicode(req2+length, SMS->Name, strlen(SMS->Name)); length=length+strlen(SMS->Name)*2; req2[length++]=0; req2[length++]=0; error=NULL_SendMessageSequence (70, &CurrentSMSMessageError, length, 0x14, req2); } return error; } /* handling for 7110 folders */ GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action) { /* remember me */ static int nextSMSmessage = -1; static GSM_SMSStatus Status; bool found = false; int folderid; GSM_OneSMSFolder onefolder; GSM_Error error; int ismsnum; int i; switch (action) { case GSH_DELETE: /* future use: delete sms in mem -> free memory */ /* for now we make same as in GSH_GET */ case GSH_GET: /* if smsnum == 0 user wants to read next sms */ if (smsnum == 0 ) { /* first time we read folderstatus */ if ( nextSMSmessage == -1) { nextSMSmessage = 0; error = N7110_GetSMSStatus( &Status); if (error!=GE_NONE) return error; } ismsnum = Status.foldertable[nextSMSmessage].smsnum; N7110_Fake2SMSLocation( ismsnum, folder, location); nextSMSmessage++; if(nextSMSmessage >= Status.Number) { nextSMSmessage = -1; #ifdef DEBUG printf("HandleSMS: setting nextSMSmessage to -1\n"); #endif } } else /* user give location -> make fake location */ { /* future use: get already read sms from mem */ N7110_Fake2SMSLocation( smsnum, folder, location); } break; case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */ if (smsnum == 0 ) { /* calculate correct folderid */ *folder = ( *folder + 1) * 8; *location = 0; } else /* user give location -> make fake location */ { N7110_Fake2SMSLocation( smsnum, folder, location); folderid = *folder; error=N7110_GetSMSFolderStatus(&onefolder, folderid ); if (error!=GE_NONE) return error; /* is there a sms at that location ? */ for (i=0; iSendMessage(4, 0x0a, request); /* Wait for timeout or other error. */ while (timeout != 0 && CurrentRFLevel == -1 ) { if (--timeout == 0) return (GE_TIMEOUT); usleep (100000); } /* Make copy in case it changes. */ rf_level = CurrentRFLevel; if (rf_level == -1) return (GE_NOLINK); /* Now convert between the different units we support. */ /* Arbitrary units. */ *units = GRF_Percentage; *level = rf_level; return (GE_NONE); } GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level) { unsigned char request[] = {N6110_FRAME_HEADER, 0x02}; int timeout=10; int batt_level; CurrentBatteryLevel=-1; Protocol->SendMessage(4, 0x17, request); /* Wait for timeout or other error. */ while (timeout != 0 && CurrentBatteryLevel == -1 ) { if (--timeout == 0) return (GE_TIMEOUT); usleep (100000); } /* Take copy in case it changes. */ batt_level = CurrentBatteryLevel; if (batt_level == -1) return (GE_NOLINK); /* Only units we handle at present are GBU_Arbitrary */ *units = GBU_Percentage; *level = batt_level; return (GE_NONE); } GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode) { unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c}; if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED; CurrentSecurityCode=SecurityCode; return NULL_SendMessageSequence (50, &CurrentSecurityCodeError, 5, 0x7a, req); } GSM_Error N7110_GetDateTime(GSM_DateTime *date_time) { return N6110_PrivGetDateTime(date_time,0x19); } /* Needs SIM card with PIN in phone */ GSM_Error N7110_SetDateTime(GSM_DateTime *date_time) { return N6110_PrivSetDateTime(date_time,0x19); } GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time) { return N6110_PrivGetAlarm(alarm_number,date_time,0x19); } /* FIXME: we should also allow to set the alarm off :-) */ GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time) { return N6110_PrivSetAlarm(alarm_number,date_time, 0x19); } void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch (MessageBuffer[3]) { /* sms status */ case 0x37: #ifdef DEBUG fprintf(stdout, _("Message: SMS Status Received\n")); fprintf(stdout, _(" Used msg in phone memory: %i\n"),MessageBuffer[10]*256+MessageBuffer[11]); fprintf(stdout, _(" Unread msg in phone memory: %i\n"),MessageBuffer[12]*256+MessageBuffer[13]); fprintf(stdout, _(" Used msg in SIM: %i\n"),MessageBuffer[14]*256+MessageBuffer[15]); fprintf(stdout, _(" Unread msg in SIM: %i\n"),MessageBuffer[16]*256+MessageBuffer[17]); #endif /* DEBUG */ CurrentSMSStatus->UnRead = MessageBuffer[13]; CurrentSMSStatusError = GE_NONE; break; case 0x38: #ifdef DEBUG fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n")); #endif /* DEBUG */ CurrentSMSStatusError = GE_INTERNALERROR; break; } } GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status) { /* RTH FIXME: what is exact meaning of 0x0037 answer ? */ /* we check all folders, but get sum of unread sms via 0x0036 request */ unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64}; GSM_SMSFolders folders; GSM_OneSMSFolder folder; GSM_Error error; u8 ifolder; int ismsnum,ilocation; int i,j,smsmaxnum; CurrentSMSStatus = Status; /* read all SMS folders */ /* check for unread messages in folder 0xf8 */ error = N7110_GetSMSFolderStatus(&folder, 0xf8); if (error != GE_NONE) return error; smsmaxnum=0; for(j=0; jfoldertable[smsmaxnum].smsnum = ismsnum; CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder; CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation; smsmaxnum++; } /* read standard folders */ N7110_GetSMSFolders (&folders); for(i=0; iFolder[i], CurrentSMSFolders->FoldersID[i]); if (error != GE_NONE) return error; for(j=0; jFolder[i].number; j++) { ifolder = CurrentSMSFolders->FoldersID[i]; ilocation = CurrentSMSFolders->Folder[i].locations[j]; N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation); CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum; CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder; CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation; smsmaxnum++; } } CurrentSMSStatus->Number = smsmaxnum; return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req); } void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i, count, blocks, blockcount; #ifdef DEBUG int j; #endif unsigned char *pBlock; CurrentPhonebookEntry->Empty = true; CurrentPhonebookEntry->Group = 5; /* 5 = no group as 6110 */ CurrentPhonebookEntry->Name[0] = '\0'; CurrentPhonebookEntry->Number[0] = '\0'; CurrentPhonebookEntry->SubEntriesCount = 0; #ifdef DEBUG fprintf(stdout, _("Message: Phonebook entry received:\n")); #endif if( MessageBuffer[6] == 0x0f ) // not found { #ifdef DEBUG fprintf(stdout, _(" Error %i\n"),MessageBuffer[10]); switch (MessageBuffer[10]) { case 0x34:fprintf(stdout,_(" Invalid phonebook location\n"));break; case 0x3b:fprintf(stdout,_(" Speed dial not assigned\n"));break; default :fprintf(stdout,_(" Unknown.Please report\n"));break; } #endif switch (MessageBuffer[10]) { case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break; case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break; default :CurrentPhonebookError = GE_UNKNOWN; } CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION; } else { CurrentPhonebookEntry->Location=MessageBuffer[13]; count = MessageBuffer[9]; blocks = MessageBuffer[17]; blockcount = 0; CurrentPhonebookEntry->SubEntriesCount = blocks - 1; #ifdef DEBUG fprintf(stdout, _(" Blocks: %d\n"),blocks); #endif /* DEBUG */ pBlock = &MessageBuffer[18]; for( i = 0; i < blocks; i++ ) { GSM_SubPhonebookEntry* pEntry = &CurrentPhonebookEntry->SubEntries[blockcount]; #ifdef DEBUG fprintf(stdout,_(" ")); for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]); fprintf(stdout,_("\n")); #endif switch( pBlock[0] ) { case N7110_ENTRYTYPE_SPEEDDIAL: CurrentSpeedDialEntry->MemoryType = GMT_SM; if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME; CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256; #ifdef DEBUG fprintf(stdout, _(" Speed dial\n")); fprintf(stdout, _(" Location: %d\n"), CurrentSpeedDialEntry->Location); fprintf(stdout, _(" MemoryType: %i\n"), CurrentSpeedDialEntry->MemoryType); fprintf(stdout, _(" Number: %d\n"), CurrentSpeedDialEntry->Number); #endif /* DEBUG */ CurrentSpeedDialError=GE_NONE; break; case N7110_ENTRYTYPE_NAME: DecodeUnicode (CurrentPhonebookEntry->Name, pBlock+6, pBlock[5]/2); if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) strncpy(CurrentGetBitmap->text,CurrentPhonebookEntry->Name,sizeof(CurrentGetBitmap->text)); CurrentPhonebookEntry->Empty = false; #ifdef DEBUG fprintf(stdout, _(" Name:\n")); fprintf(stdout, _(" Name: %s\n"), CurrentPhonebookEntry->Name); #endif /* DEBUG */ break; case N7110_ENTRYTYPE_NUMBER: pEntry->EntryType = pBlock[0]; pEntry->NumberType = pBlock[5]; pEntry->BlockNumber = pBlock[4]; DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2); #ifdef DEBUG fprintf(stdout, _(" Number:\n")); fprintf(stdout, _(" Type: %d (%02x)\n"), pEntry->NumberType, pEntry->NumberType); fprintf(stdout, _(" Number: %s\n"), pEntry->data.Number); #endif /* DEBUG */ if( pEntry->EntryType == GSM_Number && ((pEntry->NumberType == GSM_General && !strcmp(CurrentPhonebookEntry->Number,"")) || pEntry->NumberType == GSM_SIM)) { strcpy( CurrentPhonebookEntry->Number, pEntry->data.Number ); *pEntry->data.Number = 0; } else blockcount++; break; case N7110_ENTRYTYPE_DATE: pEntry->EntryType = pBlock[0]; pEntry->NumberType = pBlock[5]; pEntry->BlockNumber = pBlock[4]; DecodeDateTime(pBlock+6, &pEntry->data.Date); #ifdef DEBUG fprintf(stdout, _(" Date:\n")); fprintf(stdout, _(" Date: %02u.%02u.%04u\n"), pEntry->data.Date.Day, pEntry->data.Date.Month, pEntry->data.Date.Year ); fprintf(stdout, _(" Time: %02u:%02u:%02u\n"), pEntry->data.Date.Hour, pEntry->data.Date.Minute, pEntry->data.Date.Second); #endif /* DEBUG */ blockcount++; break; case N7110_ENTRYTYPE_NOTE: case N7110_ENTRYTYPE_POSTAL: case N7110_ENTRYTYPE_EMAIL: pEntry->EntryType = pBlock[0]; pEntry->NumberType = 0; pEntry->BlockNumber = pBlock[4]; DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2); #ifdef DEBUG fprintf(stdout, _(" Email or note or postal:\n")); fprintf(stdout, _(" Type: %d (%02x)\n"), pEntry->EntryType, pEntry->EntryType); fprintf(stdout, _(" Text: %s\n"), pEntry->data.Number); #endif /* DEBUG */ blockcount++; break; case N7110_ENTRYTYPE_GROUP: CurrentPhonebookEntry->Group = pBlock[5]-1; /* 0 = family as for 6110 */ if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) CurrentGetBitmap->number = CurrentPhonebookEntry->Group; #ifdef DEBUG fprintf(stdout, _(" Group: %d\n"), CurrentPhonebookEntry->Group); #endif /* DEBUG */ break; case N7110_ENTRYTYPE_RINGTONE: if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) CurrentGetBitmap->ringtone = pBlock[5]; #ifdef DEBUG fprintf(stdout, _(" Group ringtone number %d received.\n"), pBlock[5]); #endif /* DEBUG */ break; case N7110_ENTRYTYPE_LOGOON: if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) CurrentGetBitmap->enabled = pBlock[5]; #ifdef DEBUG fprintf(stdout, _(" Logo enabled = %d received.\n"), pBlock[5]); #endif /* DEBUG */ break; case N7110_ENTRYTYPE_GROUPLOGO: #ifdef DEBUG fprintf(stdout, _(" Caller group logo received.\n")); #endif /* DEBUG */ if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) { CurrentGetBitmap->width = pBlock[5]; CurrentGetBitmap->height= pBlock[6]; CurrentGetBitmap->size = pBlock[9]; if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap)) CurrentGetBitmap->size = CurrentGetBitmap->size; memcpy(CurrentGetBitmap->bitmap,pBlock+10,CurrentGetBitmap->size); } break; default: #ifdef DEBUG fprintf(stdout, _(" Unknown Entry Code (%u) received.\n"), pBlock[0] ); #endif /* DEBUG */ break; } #ifdef DEBUG fprintf(stdout, _(" Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]); #endif pBlock = &pBlock[(int) pBlock[3]]; } CurrentPhonebookEntry->SubEntriesCount = blockcount; CurrentPhonebookError = GE_NONE; } } /* Routine to get specifed phone book location. Designed to be called by application. Will block until location is retrieved or a timeout/error occurs. */ GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) { unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01, 0x02, //memory type 0x05, 0x00, 0x00, //location 0x00, 0x00}; CurrentPhonebookEntry = entry; req[9] = N7110_GetMemoryType(entry->MemoryType); req[10] = (entry->Location>>8); req[11] = entry->Location & 0xff; return NULL_SendMessageSequence (50, &CurrentPhonebookError, 14, 0x03, req); } void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { // [12,13] = Location // [14] = Memory if( MessageBuffer[6] == 0x0f ) // ERROR { #ifdef DEBUG /* I didn't find any error when the Text,Name or Number was too long My Phone 7110; NSE-5; SW 04.84 */ switch( MessageBuffer[10] ) { case 0x3d: fprintf(stdout, _("Error: Wrong Entry Type.\n")); break; case 0x3e: fprintf(stdout, _("Error: Too much entries.\n")); break; default : fprintf(stdout, _("Error: Unknown error (%u).\n"), MessageBuffer[10]); break; } #endif /* DEBUG */ CurrentPhonebookError = GE_NONE; } else { #ifdef DEBUG fprintf(stdout, _("Message: Phonebook written correctly.\n")); #endif /* DEBUG */ CurrentPhonebookError = GE_NONE; } } int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block) { #ifdef DEBUG fprintf(stdout,_("Adding block id:%i,length:%i\n"),no+1,size+6); #endif *(block++) = id; *(block++) = 0; *(block++) = 0; *(block++) = size + 6; *(block++) = no + 1; memcpy(block, buf, size); block += size; *(block++) = 0; return (size + 6); } int N7110_MakePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block) { int count=0, len, i; char string[500]; *block=0; /* Name */ len = strlen(entry.Name); string[0] = len * 2; // Length ot the string (without Termination) EncodeUnicode((string + 1), entry.Name, len); string[len * 2 + 1] = 0; // Terminating 0 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, len * 2 + 2, *block++, string, req + count); if (*entry.Number) { len = strlen(entry.Number); string[0] = N7110_ENTRYTYPE_NUMBER; string[1] = string[2] = string[3] = 0; string[4] = len * 2; // length (without Termination) EncodeUnicode((string + 5), entry.Number, len); string[len * 2 + 5] = 0; // Terminating 0 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, *block++, string, req + count); } /* Rest of the subentries */ for (i = 0; i < entry.SubEntriesCount; i++) { len = strlen(entry.SubEntries[i].data.Number); if (entry.SubEntries[i].EntryType != GSM_Number) { string[0] = len * 2; // length (without Termination) EncodeUnicode((string + 1), entry.SubEntries[i].data.Number, len); string[len * 2 + 1] = 0; // Terminating 0 count += N7110_PackPBKBlock(entry.SubEntries[i].EntryType, len * 2 + 2, *block++, string, req + count); } else { string[0] = entry.SubEntries[i].NumberType; string[1] = string[2] = string[3] = 0; string[4] = len * 2; //length (without Termination) EncodeUnicode((string + 5), entry.SubEntries[i].data.Number, len); string[len * 2 + 5] = 0; // Terminating 0 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, *block++, string, req + count); } } if (entry.Group != 5) { /* Group */ string[0] = entry.Group + 1; string[1] = 0; count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, *block++, string, req + count); } return count; } /* Routine to write phonebook location in phone. */ GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry) { unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, /* memory type */ 0x00, 0x00, /* location */ 0x00, 0x00, 0x00}; int count = 18, blocks; if (entry->Name[0] != '\0' || entry->Number[0] != '\0') { req[11] = N7110_GetMemoryType(entry->MemoryType); req[12] = (entry->Location >> 8); req[13] = entry->Location & 0xff; // If we had a file that contain data in entry style like from 6110 // we can import this too :) // no SubEntries in SIM (besides Name, Number, and Group) if (entry->MemoryType == GMT_SM) entry->SubEntriesCount = 0; count=count+N7110_MakePhonebookFrame(req+18, *entry, &blocks); req[17]=blocks; #ifdef DEBUG fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name); #endif return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req); } else { /* empty name & number => we have to delete the phonebook record! */ return N7110_DeletePhonebookLocation( entry ); } } void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { #ifdef DEBUG fprintf(stdout, _("Message: Phonebook entry deleted correctly\n")); #endif /* DEBUG */ CurrentPhonebookError = GE_NONE; } /* delete phonebookentry */ /* Not used in this moment */ GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry) { unsigned char req[256] = { N7110_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04, 0x00, 0x00, 0x0c, 0x01, 0xff, 0x00, /* location low*/ 0x01, /* location high*/ 0x05, /* mem location low*/ 0x00, /* mem location high*/ 0x00, 0x00 }; req[12] = (entry->Location >> 8); req[13] = entry->Location & 0xff; req[14] = N7110_GetMemoryType(entry->MemoryType); #ifdef DEBUG fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location); #endif return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req); } /* for saving group logos only */ GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap) { unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x10, /* memory type */ 0x00, 0x00, /* location */ 0x00, 0x00, 0x00}; char string[500]; int block=0, i; unsigned int count = 18; req[13] = bitmap->number + 1; /* Logo on/off */ string[0] = bitmap->enabled?1:0; string[1] = 0; count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count); /* Ringtone */ string[0] = bitmap->ringtone; string[1] = 0; count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count); /* Number of group */ string[0] = bitmap->number+1; string[1] = 0; count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count); /* Logo */ string[0] = bitmap->width; string[1] = bitmap->height; string[2] = 0; string[3] = 0; string[4] = bitmap->size; memcpy(string + 5, bitmap->bitmap, bitmap->size); count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUPLOGO, bitmap->size + 5, block++, string, req + count); /* Name */ if (*bitmap->text) { i = strlen(bitmap->text); string[0] = i * 2; EncodeUnicode((string + 1), bitmap->text, i); count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 1, block++, string, req + count); } req[17] = block; //number of blocks return NULL_SendMessageSequence (50, &CurrentPhonebookError, count, 0x03, req); } GSM_Error N7110_GetSpeedDial(GSM_SpeedDial *entry) { unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01, 0x02, //memory type 0x05, 0x00, 0x00, //location 0x00, 0x00}; GSM_PhonebookEntry entry2; GSM_Error error; CurrentPhonebookEntry = &entry2; CurrentSpeedDialEntry = entry; req[9] = N7110_MEMORY_SD; req[10] = (entry->Number>>8); req[11] = entry->Number & 0xff; error=NULL_SendMessageSequence (50, &CurrentSpeedDialError, 14, 0x03, req); /* Full compatibility with 6110 */ if (error==GE_INVALIDSPEEDDIALLOCATION) { entry->Location=0; entry->MemoryType=GMT_MT; return GE_NONE; } else return error; } /* Experimental ! */ GSM_Error N7110_SetSpeedDial(GSM_SpeedDial *entry) { unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x0e, /* memory type */ 0x00, 0x00, /* location */ 0x00, 0x00, 0x00}; char string[500]; int block=1; unsigned int count = 18; req[13] = entry->Number; string[0]= 0xff; string[1]= entry->Location/256; string[2]= entry->Location%256; string[3]= 0x05; string[4]= string[5] = 0; count += N7110_PackPBKBlock(N7110_ENTRYTYPE_SPEEDDIAL, 6, block++, string, req + count); req[17] = block - 1; //number of blocks return NULL_SendMessageSequence (50, &CurrentPhonebookError, count, 0x03, req); } /* Set a bitmap or welcome-note */ GSM_Error N7110_SetBitmap(GSM_Bitmap *Bitmap) { unsigned char reqStartup[1000] = { N7110_FRAME_HEADER, 0xec, 0x15, // Startup Logo 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00, 0x00, // Bitmap height 0xc0, 0x03, 0x00, 0x00, // Bitmap width 0xc0, 0x04, 0x03, 0x00 }; // Bitmap following unsigned char reqOp[1000] = { N7110_FRAME_HEADER, 0xa3, 0x01, 0x00, // logo disabled 0x00, 0xf0, 0x00, // network code (000 00) 0x00 ,0x04, 0x08, // length of rest 0x00, 0x00, // Bitmap width / height 0x00, 0x00, // Bitmap size 0x00, 0x00 }; // Bitmap following /* Picture Images */ unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 }; unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 }; unsigned char req4[500] = { N6110_FRAME_HEADER, 0x50, 0x07, 0x00, //location 0x00,0x00, //index 0x07}; unsigned char req5[120] = {0x00, 0x01, 0x01, 0xec, 0x02,0x00}; unsigned char req6[]= {0x00,0x01,0x00,0xaf,0x00}; u16 count,i; int timeout=60; GSM_Error error; CurrentSetBitmapError=GE_BUSY; switch (Bitmap->type) { case GSM_WelcomeNoteText: EncodeUnicode (req5+5, Bitmap->text, strlen(Bitmap->text)); count=5+strlen(Bitmap->text)*2; req5[count++]=0x00; req5[count++]=0x00; Protocol->SendMessage(count, 0x7a, req5); break; case GSM_DealerNoteText: CurrentSetBitmapError = GE_NOTIMPLEMENTED; break; case GSM_StartupLogo: case GSM_7110StartupLogo: case GSM_6210StartupLogo: reqStartup[12] = Bitmap->height; reqStartup[16] = Bitmap->width; count = 21; memcpy(reqStartup+count,Bitmap->bitmap,Bitmap->size); Protocol->SendMessage(count+Bitmap->size, 0x7a, reqStartup); break; case GSM_OperatorLogo: case GSM_7110OperatorLogo: count = 18; /* set logo */ if (strcmp(Bitmap->netcode,"000 00")) { reqOp[5] = 0x01; // Logo enabled EncodeNetworkCode(reqOp+5, Bitmap->netcode); reqOp[11] = 8+(Bitmap->width*Bitmap->height+7)/8; reqOp[12]=Bitmap->width; reqOp[13]=Bitmap->height; reqOp[15]=(Bitmap->width*Bitmap->height+7)/8; memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size); count += Bitmap->size; } else { for (i=0;i<5;i++) { req6[4]=i; error=NULL_SendMessageSequence (50, &CurrentSetBitmapError, 5, 0x0a, req6); if (error!=GE_NONE) return error; } } Protocol->SendMessage(count, 0x0a, reqOp); break; case GSM_CallerLogo: CurrentSetBitmapError = N7110_WriteGroupDataLocation(Bitmap); break; case GSM_PictureImage: CurrentGetBitmap=Bitmap; PictureImageNum=0; count=0; while (count!=9) { req2[4]=req3[count]; PictureImageLoc=req3[count]; count++; if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE) break; if (PictureImageNum==Bitmap->number+1) break; } if (CurrentGetBitmapError!=GE_NONE) { req4[5]=0x21; req4[6]=0; req4[7]=0; } else { req4[5]=PictureImageLoc; req4[6]=PictureImageIndex/256; req4[7]=PictureImageIndex%256; } count=7; for (i=0;i<38;i++) req4[count++]=0x00; req4[count++]=Bitmap->width; req4[count++]=Bitmap->height; req4[count++]=Bitmap->size/256; req4[count++]=Bitmap->size%256; memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size); count += Bitmap->size; req4[count++]=0x00; req4[count++]=0x00; CurrentSetBitmapError = GE_BUSY; Protocol->SendMessage(count, 0x14, req4); case GSM_None: return GE_NONE; } /* Wait for timeout or other error. */ while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) { if (--timeout == 0) return (GE_TIMEOUT); usleep (100000); } if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo) && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) { return N6110_Reset(0x03); } return CurrentSetBitmapError; } /* Get a bitmap from the phone */ GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap) { unsigned char req[10] = { N6110_FRAME_HEADER }; /* Picture Images */ unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 }; unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 }; unsigned char req4[9] = { N6110_FRAME_HEADER, 0x07, 0x00, //location 0x00,0x00, //index 0x00, 0x64}; /* Welcome note */ unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02}; u8 count=3; int timeout; GSM_PhonebookEntry entry; CurrentGetBitmapError = GE_BUSY; CurrentGetBitmap=Bitmap; switch (CurrentGetBitmap->type) { case GSM_StartupLogo: case GSM_7110StartupLogo: case GSM_6210StartupLogo: req[count-1]=0x01; /* change FRAME_HEADER */ req[count++]=0xee; /* to get 0x01ee */ req[count++]=0x15; Protocol->SendMessage(count, 0x7a, req); break; case GSM_WelcomeNoteText: Protocol->SendMessage(5, 0x7a, req5); break; case GSM_DealerNoteText: return GE_NOTIMPLEMENTED; case GSM_OperatorLogo: case GSM_7110OperatorLogo: req[count++]=0x70; /* NetworkStatus */ Protocol->SendMessage(count, 0x0a, req); break; case GSM_CallerLogo: entry.MemoryType = GMT_CG; entry.Location = Bitmap->number+1; *Bitmap->text=0; Bitmap->ringtone=0xFF; Bitmap->enabled=true; CurrentGetBitmapError = N7110_GetMemoryLocation(&entry); CurrentGetBitmap=NULL; if (entry.Location!=Bitmap->number+1) return GE_UNKNOWN; if (!strcmp(Bitmap->text,"")) { switch(Bitmap->number) { case 0:strcpy(Bitmap->text,"Family\0");break; case 1:strcpy(Bitmap->text,"VIP\0");break; case 2:strcpy(Bitmap->text,"Friends\0");break; case 3:strcpy(Bitmap->text,"Colleagues\0");break; case 4:strcpy(Bitmap->text,"Other\0");break; } } break; case GSM_PictureImage: PictureImageNum=0; count=0; while (count!=9) { req2[4]=req3[count]; PictureImageLoc=req3[count]; count++; if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE) return CurrentGetBitmapError; if (PictureImageNum==Bitmap->number+1) break; } if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError; req4[4]=PictureImageLoc; req4[5]=PictureImageIndex/256; req4[6]=PictureImageIndex%256; CurrentGetBitmapError = GE_BUSY; Protocol->SendMessage(9, 0x14, req4); break; default: return GE_NOTSUPPORTED; } timeout=150; while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) { if (--timeout == 0) return (GE_TIMEOUT); usleep (100000); } CurrentGetBitmap=NULL; return (CurrentGetBitmapError); } int ReturnBinRingLocation() { char model[64]; while (GSM->GetModel(model) != GE_NONE) sleep(1); if (strcmp(model,"NSE-5") == 0) return 0x74; //first 0x74 //7110 if (strcmp(model,"NPE-3") == 0) return 0x89; //first is 0x89; //6210 return 0; } /* this works only for 6210, the 7110 needs upload to a location ? */ GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength) { /* Buffer for preview uploading */ unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Length }; int size=FB61_MAX_RINGTONE_FRAME_LENGTH; GSM_NetworkInfo NetworkInfo; char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00, 0x87, // Location 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01 }; /* Info from Till Toenshoff [till@uni.de] One improvement - for looping you can use an alternative header normal 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01 loop 0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01 LL=0x01-0x10 0x01=loop once [...] 0x10=loop infinite */ char tail[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40, 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE, 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B // 20 Bytes tail }; //{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" }; char N7110_notes[14] = { 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10 , 11, 11 }; int current = 6, i, note, lastnote = 0, duration; /* Preview uploading */ if (ringtone->location==255) { *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size); buffer[10] = size; Protocol->SendMessage(size+11, 0x00, buffer); GSM->GetNetworkInfo(&NetworkInfo); //need to make something sleep(1); return GE_NONE; //no answer from phone } req[5]=ReturnBinRingLocation()+ringtone->location; EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name)); current = 43; for (i=0; iNrNotes; i++) { if (ringtone->notes[i].note == 255) note = 0x40; else note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14]; duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256; // in 8 ms ticks of 7110 switch (ringtone->notes[i].style) { case StaccatoStyle: if (duration) { req[current++] = note; // note only for one tick req[current++] = 1; duration--; } note = 0x40; // rest pause case NaturalStyle: if (note != 0x40 && duration) { req[current++] = 0x40; req[current++] = 1; // small pause between notes duration--; } default: if (note != 0x40 && note == lastnote && duration) { req[current++] = 0x40; req[current++] = 1; // small pause between same notes duration--; } while (duration > 125) { req[current++] = note; req[current++] = 125; duration -= 125; } req[current++] = note; req[current++] = duration; } lastnote = note; } for (i = 0; i < sizeof(tail); i++) req[current++] = tail[i]; Protocol->SendMessage(current, 0x1F, req); sleep(1); return GE_NONE; //no answer from phone } void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i, tmp; switch (MessageBuffer[3]) { case 0x23: tmp=0;i=4; while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) { tmp++; i=i+2; } DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp); #ifdef DEBUG fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name); #endif /* DEBUG */ CurrentGetBinRingtone->frame[0]=0x00; CurrentGetBinRingtone->frame[1]=0x00; CurrentGetBinRingtone->frame[2]=0x0c; CurrentGetBinRingtone->frame[3]=0x01; CurrentGetBinRingtone->frame[4]=0x2c; memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name)); CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name); CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00; CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00; /* Looking for end */ i=37; while (true) { if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) { i=i+2;break; } if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) { i=i+2;break; } i++; if (i==MessageLength) break; } /* Copying frame */ memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37); CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37; CurrentBinRingtoneError=GE_NONE; break; case 0x24: #ifdef DEBUG fprintf(stdout, _("Message: Received empty ringtone\n")); #endif /* DEBUG */ CurrentBinRingtoneError=GE_INVALIDRINGLOCATION; break; } } GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone) { unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 }; req[2]=0x01; req[5]=ReturnBinRingLocation()+ringtone->location; CurrentGetBinRingtone=ringtone; return NULL_SendMessageSequence (50, &CurrentBinRingtoneError, 6, 0x1f, req); } GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone) { unsigned char req[500] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 }; GSM_NetworkInfo NetworkInfo; int i; req[2]=0x01; req[5]=ReturnBinRingLocation()+ringtone->location; for (i=6;i<35;i++) req[i]=0x00; i=6; EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5)); i=5; while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++; memcpy(req+35,ringtone->frame+i,ringtone->length-i); Protocol->SendMessage(35+ringtone->length-i, 0x1f, req); GSM->GetNetworkInfo(&NetworkInfo); //need to make something return GE_NONE; //no answer from phone } void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { GSM_SMSMessage NullSMS; #ifdef DEBUG fprintf(stdout,_("Message: Incoming SMS\n")); #endif /* DEBUG */ GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5); #ifdef DEBUG fprintf(stdout, _("\n")); #endif /* DEBUG */ } void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int count; #ifdef DEBUG char name[100]; #endif GSM_NetworkInfo NullNetworkInfo; switch (MessageBuffer[3]) { case 0xb0: #ifdef DEBUG fprintf(stdout, _("Message: Clearing operator logo msg\n")); #endif CurrentSetBitmapError=GE_NONE; break; case 0x71: /* Make sure we are expecting NetworkInfo frame */ if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) || (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) { #ifdef DEBUG fprintf(stdout, _("Message: Network informations and operator logo:\n")); #endif } else { #ifdef DEBUG fprintf(stdout, _("Message: Network informations not requested, but received:\n")); #endif } sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4); sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]); sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]); #ifdef DEBUG fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID); fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC); fprintf(stdout, _(" Network code: %s\n"), NullNetworkInfo.NetworkCode); fprintf(stdout, _(" Network name for gnokii: %s (%s)\n"), GSM_GetNetworkName(NullNetworkInfo.NetworkCode), GSM_GetCountryName(NullNetworkInfo.NetworkCode)); DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]); fprintf(stdout, _(" Network name for phone: %s\n"),name); fprintf(stdout, _(" Status: ")); switch (MessageBuffer[8]) { case 0x01: fprintf(stdout, _("home network selected")); break; case 0x02: fprintf(stdout, _("roaming network")); break; case 0x03: fprintf(stdout, _("requesting network")); break; case 0x04: fprintf(stdout, _("not registered in the network")); break; default: fprintf(stdout, _("unknown")); } fprintf(stdout, "\n"); fprintf(stdout, _(" Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic")); #endif /* DEBUG */ /* Make sure we are expecting NetworkInfo frame */ if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) { *CurrentNetworkInfo=NullNetworkInfo; CurrentNetworkInfoError = GE_NONE; } /* Make sure we are expecting an operator logo */ if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) { strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode); #ifdef DEBUG if (MessageBuffer[4] == 0x02) fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"), CurrentGetBitmap->netcode, GSM_GetNetworkName(CurrentGetBitmap->netcode)); else fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"), CurrentGetBitmap->netcode, GSM_GetNetworkName(CurrentGetBitmap->netcode)); #endif if (MessageBuffer[4] == 0x02) { /* logo present */ count = 7; count += MessageBuffer[count]; /* skip network info */ CurrentGetBitmap->size=MessageBuffer[count++]; /* is too large */ CurrentGetBitmap->width=MessageBuffer[count++]; /* 78 */ CurrentGetBitmap->height=MessageBuffer[count++]; /* 21 */ count+=4; CurrentGetBitmap->size=(CurrentGetBitmap->height*CurrentGetBitmap->width+7)/8; /* packed size */ if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap)) CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap); memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size); } else { CurrentGetBitmap->width=78; CurrentGetBitmap->height=21; CurrentGetBitmap->size=(CurrentGetBitmap->height*CurrentGetBitmap->width+7)/8; /* packed size */ memset(CurrentGetBitmap->bitmap,0,CurrentGetBitmap->size); } CurrentGetBitmapError=GE_NONE; } break; case 0x82: #ifdef DEBUG fprintf(stdout, _("Message: Network Level received:\n")); fprintf(stdout, _(" Network Level: %d\n"), MessageBuffer[4]); #endif /* DEBUG */ CurrentRFLevel=MessageBuffer[4]; break; case 0xa4: #ifdef DEBUG fprintf(stdout, _("Message: Operator logo set correctly.\n")); #endif CurrentSetBitmapError = GE_NONE; break; default: #ifdef DEBUG fprintf(stdout, _("Message: Unknown message of type 0x0a\n")); #endif /* DEBUG */ AppendLogText("Unknown msg\n",false); break; /* Visual C Don't like empty cases */ } } void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i, tmp; GSM_ETSISMSMessage ETSI; switch (MessageBuffer[3]) { /* We have requested invalid or empty location. */ case 0x09: #ifdef DEBUG fprintf(stdout, _("Message: SMS reading failed\n")); #endif /* DEBUG */ CurrentSMSMessageError = GE_INVALIDSMSLOCATION; CurrentGetBitmapError=GE_UNKNOWN; break; /* getsms or picture image */ case 0x08: if (MessageBuffer[8]==0x07) { if (CurrentGetBitmap!=NULL) { for (i=0;iSender,GSM_UnpackSemiOctetNumber(ETSI.Number,true)); CurrentGetBitmap->width=MessageBuffer[47]; CurrentGetBitmap->height=MessageBuffer[48]; CurrentGetBitmap->size=CurrentGetBitmap->height*CurrentGetBitmap->width/8; memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size); tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size, CurrentGetBitmap->text); CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0; CurrentGetBitmapError=GE_NONE; } else { #ifdef DEBUG fprintf(stdout, _("Message: Picture Image received, but not reqested\n")); #endif /* DEBUG */ CurrentSMSMessageError = GE_SMSTOOLONG; } break; } else { /* sms message */ /* status in byte 4 */ CurrentSMSMessage->Status = MessageBuffer[4]; CurrentSMSMessage->Type = GST_SMS; if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR; CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location; /* RTH FIXME: old folder stuff for xgnokii */ CurrentSMSMessage->folder = (MessageBuffer[5] / 8)-1; /* if unreadMessage from folder 0, set INBOX folder */ if (CurrentSMSMessage->folder==-1) CurrentSMSMessage->folder = 0; #ifdef DEBUG fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n") ,CurrentSMSMessage->Type, CurrentSMSMessage->folder, MessageBuffer[7]); #endif /* DEBUG */ GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9); /* Signal no error to calling code. */ CurrentSMSMessageError = GE_NONE; break; } case 0x97: #ifdef DEBUG fprintf(stdout, _("Message: Received index for Picture Images\n")); #endif /* DEBUG */ for (i=1;inumber+1) { PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2]; break; } } CurrentGetBitmapError=GE_NONE; CurrentSetBitmapError=GE_NONE; break; default: #ifdef DEBUG fprintf(stdout, _("Message: Unknown message of type 14\n")); #endif /* DEBUG */ AppendLogText("Unknown msg\n",false); break; /* Visual C Don't like empty cases */ } } void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { switch (MessageBuffer[3]) { case 0x03: #ifdef DEBUG fprintf(stdout, _("Message: Battery status received:\n")); fprintf(stdout, _(" Battery Level: %d\n"), MessageBuffer[5]); #endif /* DEBUG */ CurrentBatteryLevel=MessageBuffer[5]; break; default: #ifdef DEBUG fprintf(stdout, _("Message: Unknown message of type 0x17\n")); #endif /* DEBUG */ AppendLogText("Unknown msg\n",false); break; /* Visual C Don't like empty cases */ } } void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { int i, tmp; switch (MessageBuffer[3]) { /* Setting setting request */ case 0xeb: switch (MessageBuffer[4]) { case 0x02: #ifdef DEBUG fprintf(stdout, _("Message: Startup text set correctly.\n")); #endif CurrentSetBitmapError = GE_NONE; break; case 0x15: #ifdef DEBUG fprintf(stdout, _("Message: Startup logo set correctly.\n")); #endif CurrentSetBitmapError = GE_NONE; break; } break; /* Setting received */ case 0xed: switch (MessageBuffer[4]) { case 0x02: #ifdef DEBUG fprintf(stdout, _("Message: Startup text received.\n")); #endif tmp=0;i=6; while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) { i=i+2; tmp++; } DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp); #ifdef DEBUG fprintf(stdout, _(" Text: \"%s\"\n"),CurrentGetBitmap->text); #endif CurrentGetBitmapError = GE_NONE; break; case 0x15: #ifdef DEBUG if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) fprintf(stdout, _("Message: Startup logo received.\n")); else fprintf(stdout, _("Message: Startup logo not requested, but received.\n")); #endif /* Make sure we are expecting a startup logo */ if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) { CurrentGetBitmap->height=MessageBuffer[13]; /* 96 */ CurrentGetBitmap->width=MessageBuffer[17]; /* 60 */ CurrentGetBitmap->size=(CurrentGetBitmap->height+7)/8*CurrentGetBitmap->width; /* unpacked size */ if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap)) CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap); memcpy(CurrentGetBitmap->bitmap,MessageBuffer+22,CurrentGetBitmap->size); CurrentGetBitmapError=GE_NONE; } break; case 0x1c: #ifdef DEBUG fprintf(stdout, _("Message: security code \"")); for (i=6;i<11;i++) { fprintf(stdout, _("%c"),MessageBuffer[i]); } fprintf(stdout,_("\"received.\n")); #endif strncpy(CurrentSecurityCode->Code,MessageBuffer+6,6); CurrentSecurityCodeError=GE_NONE; break; } break; default: #ifdef DEBUG fprintf(stdout, _("Unknown message of type 0x7a.\n")); #endif AppendLogText("Unknown msg\n",false); break; /* Visual C Don't like empty cases */ } } void N7110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { bool unknown=false; /* Switch on the basis of the message type byte */ switch (MessageType) { /* Call information */ /* Note, we use N6110_Dispatch0x40Message, but only some of 0x01 old msg are available in new phones - other returns generally only errors */ case 0x01: N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType); break; /* SMS handling */ case 0x02: switch (MessageBuffer[3]) { case 0x02: case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break; case 0x0e: case 0x0f:N7110_ReplyEnableIncomingSMSInfo(MessageLength,MessageBuffer,MessageType);break; case 0x11:N7110_ReplyIncomingSMS (MessageLength,MessageBuffer,MessageType);break; case 0x21:N6110_ReplySetCellBroadcast (MessageLength, MessageBuffer, MessageType);break; case 0x23:N6110_ReplyReadCellBroadcast (MessageLength, MessageBuffer, MessageType);break; case 0x31:N6110_ReplySetSMSCenter (MessageLength,MessageBuffer,MessageType);break; case 0x34: case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* Phonebook and speed dials */ case 0x03: switch (MessageBuffer[3]) { case 0x04:N7110_ReplyGetMemoryStatus (MessageLength,MessageBuffer,MessageType);break; case 0x08:N7110_ReplyGetMemoryLocation (MessageLength,MessageBuffer,MessageType);break; case 0x10:N7110_ReplyDeletePhonebookLocation(MessageLength,MessageBuffer,MessageType);break; case 0x0C:N7110_ReplyWritePhonebookLocation (MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* This is call forwarding stuff */ case 0x06: switch (MessageBuffer[3]) { case 0x02: case 0x03:N6110_ReplyCallDivert (MessageLength,MessageBuffer,MessageType);break; default :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break; } break; /* Network and operator logo */ case 0x0a: N7110_Dispatch0x0AMessage(MessageLength, MessageBuffer, MessageType); break; /* Calendar notes handling */ case 0x13: switch (MessageBuffer[3]) { case 0x02: case 0x04: case 0x06: case 0x08:N7110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break; case 0x0c:N7110_ReplyDeleteCalendarNote (MessageLength,MessageBuffer,MessageType);break; case 0x1A:N7110_ReplyGetCalendarNote (MessageLength,MessageBuffer,MessageType);break; case 0x32:N7110_ReplyFirstCalendarFreePos(MessageLength,MessageBuffer,MessageType);break; case 0x3b:N7110_ReplyGetCalendarNotesInfo(MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* SMS stuff */ case 0x14: switch (MessageBuffer[3]) { case 0x05: case 0x06:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break; case 0x0b:N7110_ReplyDeleteSMSMessage (MessageLength,MessageBuffer,MessageType);break; case 0x37: case 0x38:N7110_ReplyGetSMSStatus (MessageLength,MessageBuffer,MessageType);break; case 0x6C:N7110_ReplyGetSMSFolderStatus(MessageLength,MessageBuffer,MessageType);break; case 0x7B:N7110_ReplyGetSMSFolders (MessageLength,MessageBuffer,MessageType);break; case 0x84:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break; default :N7110_Dispatch0x14Message (MessageLength, MessageBuffer, MessageType);break; } break; /* Battery status */ case 0x17: N7110_Dispatch0x17Message(MessageLength, MessageBuffer, MessageType); break; /* Date and time */ case 0x19: switch (MessageBuffer[3]) { case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break; case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break; case 0x6c:N6110_ReplySetAlarm (MessageLength,MessageBuffer,MessageType);break; case 0x6e:N6110_ReplyGetAlarm (MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* Ringtones */ case 0x1f: switch (MessageBuffer[3]) { case 0x23: case 0x24:N7110_ReplyGetBinRingtone(MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* Profiles */ case 0x39: N7110_ReplyGetProfile(MessageLength, MessageBuffer, MessageType); break; /* WAP */ case 0x3f: switch (MessageBuffer[3]) { case 0x01: case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break; case 0x07: case 0x08:N7110_ReplyGetWAPBookmark (MessageLength,MessageBuffer,MessageType);break; case 0x0a: case 0x0b:N7110_ReplySetWAPBookmark (MessageLength,MessageBuffer,MessageType);break; case 0x16: case 0x17: case 0x1c:N7110_ReplyGetWAPSettings (MessageLength,MessageBuffer,MessageType);break; default :unknown=true;break; } break; /* Internal phone functions ? */ /* Note, we use N6110_Dispatch0x40Message, but only some of 0x40 old msg are available in new phones - other returns generally only errors */ case 0x40: switch (MessageBuffer[2]) { case 0x64:N6110_ReplyEnableExtendedCommands (MessageLength,MessageBuffer,MessageType);break; case 0x65:N6110_ReplyResetPhoneSettings (MessageLength,MessageBuffer,MessageType);break; case 0x66:N6110_ReplyIMEI (MessageLength,MessageBuffer,MessageType);break; case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break; case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break; case 0x7e:N6110_ReplyNetmonitor (MessageLength,MessageBuffer,MessageType);break; case 0x8a:N6110_ReplySimlockInfo (MessageLength,MessageBuffer,MessageType);break; case 0x8f:N6110_ReplyPlayTone (MessageLength,MessageBuffer,MessageType);break; case 0xc8:N6110_ReplyHW (MessageLength,MessageBuffer,MessageType);break; default :N6110_Dispatch0x40Message (MessageLength,MessageBuffer,MessageType);break; } break; /* Settings */ case 0x7a: N7110_Dispatch0x7AMessage(MessageLength, MessageBuffer, MessageType); break; /***** Acknowlegment of our frames. *****/ case FBUS_FRTYPE_ACK: N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType); break; case 0xd2: N6110_ReplyID(MessageLength, MessageBuffer, MessageType); break; /***** Unknown message *****/ /* If you think that you know the exact meaning of other messages - please let us know. */ default: #ifdef DEBUG fprintf(stdout, _("Message: Unknown message type.\n")); #endif /* DEBUG */ AppendLogText("Unknown msg type\n",false); break; } if (unknown) { #ifdef DEBUG fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType); #endif AppendLogText("Unknown msg\n",false); } }