5 A Linux/Unix toolset and driver for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
9 This file provides an API for accessing functions on the 7110 and similar
14 /* "Turn on" prototypes in n-7110.h */
18 /* System header files */
25 #include "devices/device.h"
29 #include "misc_win32.h"
32 /* Various header file */
38 #include "gsm-coding.h"
39 #include "newmodules/n6110.h"
40 #include "newmodules/n7110.h"
41 #include "protocol/fbus.h"
43 /* Global variables used by code in gsm-api.c to expose the functions
44 supported by this model of phone. */
46 /* Here we initialise model specific functions. */
48 GSM_Functions N7110_Functions = {
50 N7110_DispatchMessage,
53 N7110_GetMemoryLocation,
54 N7110_WritePhonebookLocation,
57 N7110_GetMemoryStatus,
62 N7110_DeleteSMSMessage,
66 N7110_GetBatteryLevel,
71 N7110_GetSecurityCode,
81 N6110_GetIncomingCallNr,
83 N7110_GetCalendarNote,
84 N7110_WriteCalendarNote,
85 N7110_DeleteCalendarNote,
101 N6110_EnableCellBroadcast,
102 N6110_DisableCellBroadcast,
103 N6110_ReadCellBroadcast,
105 N6110_GetProductProfileSetting,
106 N6110_SetProductProfileSetting,
109 N7110_GetVoiceMailbox,
112 N7110_GetCalendarNotesInfo,
115 N7110_GetWAPBookmark,
116 N7110_SetWAPBookmark,
117 N7110_GetWAPSettings,
120 N6110_GetManufacturer
123 /* Mobile phone information */
125 GSM_Information N7110_Information = {
126 "6210|6250|7110", /* Supported models in FBUS */
127 "6210|6250|7110", /* Supported models in MBUS */
128 "", /* Supported models in FBUS over infrared */
129 "6210|6250|7110", /* Supported models in FBUS over DLR3 */
131 "6210|6250|7110", /* Supported models in FBUS over Irda sockets */
134 5, /* Max RF Level */
135 0, /* Min RF Level */
136 GRF_Arbitrary, /* RF level units */
137 5, /* Max Battery Level */
138 0, /* Min Battery Level */
139 GBU_Arbitrary, /* Battery level units */
140 GDT_DateTime, /* Have date/time support */
141 GDT_TimeOnly, /* Alarm supports time only */
142 1 /* Only one alarm available */
145 const char *N7110_MemoryType_String [] = {
158 int PictureImageNum; //required during reading Picture Images
159 int PictureImageIndex;
162 void N7110_ReplyEnableIncomingSMSInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
163 switch (MessageBuffer[3]) {
166 fprintf(stdout,_("Message: Enabled info for incoming SMS\n"));
169 CurrentMagicError=GE_NONE;
173 fprintf(stdout,_("Message: error enabling for incoming SMS\n"));
174 switch (MessageBuffer[4]) {
175 case 0x0c:fprintf(stdout,_(" No PIN\n"));break;
176 default :fprintf(stdout,_(" unknown\n"));break;
180 CurrentMagicError=GE_UNKNOWN;
185 GSM_Error N7110_EnableIncomingSMSInfo ()
187 unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
189 return NULL_SendMessageSequence
190 (50, &CurrentMagicError, 8, 0x02, req);
193 /* Initialise variables and state machine. */
194 GSM_Error N7110_Initialise(char *port_device, char *initlength,
195 GSM_ConnectionType connection,
196 void (*rlp_callback)(RLP_F96Frame *frame))
199 unsigned char init_char = N6110_SYNC_BYTE;
203 if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
205 return GE_NOTSUPPORTED;
208 if (connection!=GCT_MBUS && connection!=GCT_Irda) {
210 InitLength = atoi(initlength);
212 if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
213 InitLength = 250; /* This is the usual value, lower may work. */
217 fprintf(stdout,_("Writing init chars...."));
220 /* Initialise link with phone or what have you */
221 /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
223 for (count = 0; count < InitLength; count ++) {
225 Protocol->WritePhone(1,&init_char);
229 fprintf(stdout,_("Done\n"));
232 N6110_SendStatusRequest();
238 if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
240 if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;
242 if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;
244 // N7110_EnableIncomingSMSInfo();
246 if (connection==GCT_MBUS || connection==GCT_Irda) {
247 /* In MBUS doesn't have any init strings, etc. Phone answered with frame,
248 so connection should be enabled ;-) */
249 /* Similiar for Irda */
250 CurrentLinkOK = true;
253 CurrentSMSFoldersCount=1000;
258 /* This function translates GMT_MemoryType to N7110_MEMORY_xx */
259 int N7110_GetMemoryType(GSM_MemoryType memory_type)
264 switch (memory_type) {
267 // result = N7110_MEMORY_MT;
270 case GMT_ME: result = N7110_MEMORY_ME; break;
271 case GMT_SM: result = N7110_MEMORY_SM; break;
272 case GMT_FD: result = N7110_MEMORY_FD; break;
273 case GMT_ON: result = N7110_MEMORY_ON; break;
274 case GMT_EN: result = N7110_MEMORY_EN; break;
275 case GMT_DC: result = N7110_MEMORY_DC; break;
276 case GMT_RC: result = N7110_MEMORY_RC; break;
277 case GMT_MC: result = N7110_MEMORY_MC; break;
278 case GMT_CG: result = N7110_MEMORY_CG; break;
279 default : result = N6110_MEMORY_XX;
285 GSM_Error N7110_GetVoiceMailbox ( GSM_PhonebookEntry *entry)
287 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
290 0x00, 0x00, //location
293 CurrentPhonebookEntry = entry;
295 req[9] = N7110_MEMORY_VM;
299 return NULL_SendMessageSequence
300 (50, &CurrentPhonebookError, 14, 0x03, req);
303 void N7110_ReplyEnableWAPCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
305 switch(MessageBuffer[3]) {
309 fprintf(stdout, _("Message: WAP functions enabled\n"));
311 CurrentGetWAPBookmarkError=GE_NONE;
316 fprintf(stdout, _("Message: WAP functions enabled\n"));
318 CurrentGetWAPBookmarkError=GE_NONE;
324 /* To enable WAP frames in phone */
325 GSM_Error N7110_EnableWAPCommands ()
327 unsigned char req0[] = { N6110_FRAME_HEADER, 0x00 };
329 return NULL_SendMessageSequence
330 (50, &CurrentGetWAPBookmarkError, 4, 0x3f, req0);
333 void N7110_ReplyGetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
337 switch(MessageBuffer[3]) {
342 fprintf(stdout, _("Message: WAP bookmark received OK\n"));
345 DecodeUnicode(WAPBookmark->title, MessageBuffer + 7, MessageBuffer[6] );
348 fprintf(stdout, _(" Title: \"%s\"\n"),WAPBookmark->title);
351 tmp=MessageBuffer[6]*2+7;
353 DecodeUnicode(WAPBookmark->address, MessageBuffer + tmp+1, MessageBuffer[tmp] );
356 fprintf(stdout, _(" Address: \"%s\"\n"),WAPBookmark->address);
359 CurrentGetWAPBookmarkError=GE_NONE;
365 fprintf(stdout, _("Message: WAP bookmark receiving error\n"));
366 switch (MessageBuffer[4]) {
367 case 0x01:fprintf(stdout, _(" Inside Bookmarks menu. Must leave it\n"));break;
368 case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break;
369 default :fprintf(stdout, _(" Unknown error. Please report it\n"));
373 switch (MessageBuffer[4]) {
374 case 0x01:CurrentGetWAPBookmarkError=GE_INSIDEBOOKMARKSMENU;break;
375 case 0x02:CurrentGetWAPBookmarkError=GE_INVALIDBOOKMARKLOCATION;break;
376 default:CurrentGetWAPBookmarkError=GE_UNKNOWN;
383 GSM_Error N7110_GetWAPBookmark (GSM_WAPBookmark *bookmark)
385 unsigned char req[] = { N6110_FRAME_HEADER, 0x06, 0x00, 0x00};
389 /* We have to enable WAP frames in phone */
390 error=N7110_EnableWAPCommands ();
391 if (error!=GE_NONE) return error;
394 req[5]=bookmark->location-1;
396 WAPBookmark=bookmark;
398 return NULL_SendMessageSequence
399 (50, &CurrentGetWAPBookmarkError, 6, 0x3f, req);
402 void N7110_ReplySetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
404 switch(MessageBuffer[3]) {
409 fprintf(stdout, _("Message: WAP bookmark set OK\n"));
412 CurrentSetWAPBookmarkError=GE_NONE;
418 fprintf(stdout, _("Message: Error setting WAP bookmark\n"));
421 CurrentSetWAPBookmarkError=GE_UNKNOWN;
426 GSM_Error N7110_SetWAPBookmark (GSM_WAPBookmark *bookmark)
428 unsigned char req[64] = { N6110_FRAME_HEADER, 0x09 };
432 /* We have to enable WAP frames in phone */
433 error = N7110_EnableWAPCommands ();
434 if (error != GE_NONE)
438 req[count++] = (bookmark->location & 0xff00) >> 8;
439 req[count++] = (bookmark->location & 0x00ff);
441 req[count++] = strlen(bookmark->title);
442 EncodeUnicode (req+count,bookmark->title ,strlen(bookmark->title));
443 count=count+2*strlen(bookmark->title);
445 req[count++] = strlen(bookmark->address);
446 EncodeUnicode (req+count,bookmark->address ,strlen(bookmark->address));
447 count=count+2*strlen(bookmark->address);
450 req[count++] = 0x01; req[count++] = 0x80; req[count++] = 0x00;
451 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
452 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
454 WAPBookmark = bookmark;
456 return NULL_SendMessageSequence(50, &CurrentSetWAPBookmarkError,
460 void N7110_ReplyGetWAPSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
464 switch(MessageBuffer[3]) {
469 fprintf(stdout, _("Message: WAP settings received OK\n"));
472 DecodeUnicode(WAPSettings->title, MessageBuffer + 5, MessageBuffer[4] );
475 fprintf(stdout, _(" Title: \"%s\"\n"),WAPSettings->title);
478 tmp=5+MessageBuffer[4]*2;
480 DecodeUnicode(WAPSettings->homepage, MessageBuffer + tmp+1, MessageBuffer[tmp] );
483 fprintf(stdout, _(" Homepage: \"%s\"\n"),WAPSettings->homepage);
486 tmp=tmp+MessageBuffer[tmp]*2+1;
489 fprintf(stdout, _(" Connection type: "));
490 switch (MessageBuffer[tmp]) {
491 case 0x00: fprintf(stdout,_("temporary"));break;
492 case 0x01: fprintf(stdout,_("continuous"));break;
493 default: fprintf(stdout,_("unknown"));
495 fprintf(stdout, _("\n"));
497 fprintf(stdout, _(" Connection security: "));
498 switch (MessageBuffer[tmp+13]) {
499 case 0x00: fprintf(stdout,_("off"));break;
500 case 0x01: fprintf(stdout,_("on"));break;
501 default: fprintf(stdout,_("unknown"));
503 fprintf(stdout, _("\n"));
507 switch (MessageBuffer[tmp]) {
508 case 0x00: WAPSettings->iscontinuous=false;break;
509 case 0x01: WAPSettings->iscontinuous=true;break;
511 switch (MessageBuffer[tmp+13]) {
512 case 0x00: WAPSettings->issecurity=false;break;
513 case 0x01: WAPSettings->issecurity=true;break;
516 WAPSettings->location=MessageBuffer[tmp+7];//location for second part
518 CurrentGetWAPSettingsError=GE_NONE;
524 fprintf(stdout, _("Message: WAP settings receiving error\n"));
525 switch (MessageBuffer[4]) {
526 case 0x01:fprintf(stdout, _(" Inside Settings menu. Must leave it\n"));break;
527 case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break;
528 default :fprintf(stdout, _(" Unknown error. Please report it\n"));
532 switch (MessageBuffer[4]) {
533 case 0x01:CurrentGetWAPSettingsError=GE_INSIDESETTINGSMENU;break;
534 case 0x02:CurrentGetWAPSettingsError=GE_INVALIDSETTINGSLOCATION;break;
535 default :CurrentGetWAPSettingsError=GE_UNKNOWN;
543 fprintf(stdout, _("Message: WAP settings received OK\n"));
546 switch (MessageBuffer[5]) {
549 WAPSettings->bearer=WAPSETTINGS_BEARER_SMS;
552 fprintf(stdout, _(" Settings for SMS bearer:\n"));
557 DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1,
558 MessageBuffer[tmp] );
561 fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service);
564 tmp=tmp+MessageBuffer[tmp]*2+1;
566 DecodeUnicode(WAPSettings->server, MessageBuffer + tmp+ 1,
567 MessageBuffer[tmp] );
570 fprintf(stdout, _(" Server number: \"%s\"\n"),WAPSettings->server);
577 WAPSettings->bearer=WAPSETTINGS_BEARER_DATA;
580 fprintf(stdout, _(" Settings for data bearer:\n"));
585 DecodeUnicode(WAPSettings->ipaddress, MessageBuffer + tmp+ 1,
586 MessageBuffer[tmp] );
589 fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->ipaddress);
592 tmp=tmp+MessageBuffer[tmp]*2+1;
594 DecodeUnicode(WAPSettings->dialup, MessageBuffer + tmp+1,
595 MessageBuffer[tmp] );
598 fprintf(stdout, _(" Dial-up number: \"%s\"\n"),WAPSettings->dialup);
601 tmp=tmp+MessageBuffer[tmp]*2+1;
603 DecodeUnicode(WAPSettings->user, MessageBuffer + tmp+1,
604 MessageBuffer[tmp] );
607 fprintf(stdout, _(" User name: \"%s\"\n"),WAPSettings->user);
610 tmp=tmp+MessageBuffer[tmp]*2+1;
612 DecodeUnicode(WAPSettings->password, MessageBuffer + tmp+1,
613 MessageBuffer[tmp] );
616 fprintf(stdout, _(" Password: \"%s\"\n"),WAPSettings->password);
620 fprintf(stdout, _(" Authentication type: "));
621 switch (MessageBuffer[6]) {
622 case 0x00: fprintf(stdout,_("normal"));break;
623 case 0x01: fprintf(stdout,_("secure"));break;
624 default: fprintf(stdout,_("unknown"));break;
626 fprintf(stdout, _("\n"));
628 fprintf(stdout, _(" Data call type: "));
629 switch (MessageBuffer[7]) {
630 case 0x00: fprintf(stdout,_("analogue"));break;
631 case 0x01: fprintf(stdout,_("IDSN"));break;
632 default: fprintf(stdout,_("unknown"));break;
634 fprintf(stdout, _("\n"));
636 fprintf(stdout, _(" Data call speed: "));
637 switch (MessageBuffer[9]) {
638 case 0x01: fprintf(stdout,_("9600"));break;
639 case 0x02: fprintf(stdout,_("14400"));break;
640 default: fprintf(stdout,_("unknown"));break;
642 fprintf(stdout, _("\n"));
646 switch (MessageBuffer[6]) {
647 case 0x00: WAPSettings->isnormalauthentication=true;break;
648 case 0x01: WAPSettings->isnormalauthentication=false;break;
650 switch (MessageBuffer[7]) {
651 case 0x00: WAPSettings->isISDNcall=false;break;
652 case 0x01: WAPSettings->isISDNcall=true;break;
654 switch (MessageBuffer[9]) {
655 case 0x01: WAPSettings->isspeed14400=false;break;
656 case 0x02: WAPSettings->isspeed14400=true;break;
663 WAPSettings->bearer=WAPSETTINGS_BEARER_USSD;
666 fprintf(stdout, _(" Settings for USSD bearer:\n"));
671 DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1,
672 MessageBuffer[tmp] );
675 if (MessageBuffer[6]==0x01)
676 fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service);
678 fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->service);
681 WAPSettings->isIP=true;
682 if (MessageBuffer[6]==0x01) WAPSettings->isIP=false;
684 tmp=tmp+MessageBuffer[tmp]*2+1;
686 DecodeUnicode(WAPSettings->code, MessageBuffer + tmp+1,
687 MessageBuffer[tmp] );
690 fprintf(stdout, _(" Service code: \"%s\"\n"),WAPSettings->code);
695 CurrentGetWAPSettingsError=GE_NONE;
700 GSM_Error N7110_GetWAPSettings (GSM_WAPSettings *settings)
702 unsigned char req[] = { N6110_FRAME_HEADER, 0x15, 0x00};
703 unsigned char req2[] = { N6110_FRAME_HEADER, 0x1b, 0x00};
707 /* We have to enable WAP frames in phone */
708 error=N7110_EnableWAPCommands ();
709 if (error!=GE_NONE) return error;
712 req[4]=settings->location-1;
714 WAPSettings=settings;
716 error=NULL_SendMessageSequence
717 (50, &CurrentGetWAPSettingsError, 6, 0x3f, req);
718 if (error!=GE_NONE) return error;
722 req2[4]=settings->location;
724 return NULL_SendMessageSequence
725 (50, &CurrentGetWAPSettingsError, 6, 0x3f, req2);
728 void N7110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
731 fprintf(stdout, _("Message: Memory status received:\n"));
734 if (CurrentMemoryStatus && CurrentMemoryStatusError == GE_BUSY) {
735 /* first Loc. (MessageBuffer[10]<<8) + MessageBuffer[11]; */
736 CurrentMemoryStatus->Free = (MessageBuffer[14]<<8) + MessageBuffer[15];
737 CurrentMemoryStatus->Used = (MessageBuffer[16]<<8) + MessageBuffer[17];
738 CurrentMemoryStatus->Free -= CurrentMemoryStatus->Used;
740 CurrentMemoryStatusError = GE_NONE;
743 fprintf(stdout, _(" Memory Type: %s\n"), N7110_MemoryType_String[MessageBuffer[5]]);
744 fprintf(stdout, _(" Used: %d\n"), CurrentMemoryStatus->Used);
745 fprintf(stdout, _(" Free: %d\n"), CurrentMemoryStatus->Free);
750 /* This function is used to get storage status from the phone. It currently
751 supports two different memory areas - internal and SIM. */
752 GSM_Error N7110_GetMemoryStatus(GSM_MemoryStatus *Status)
754 unsigned char req[] = { N6110_FRAME_HEADER,
755 0x03, /* MemoryStatus request */
757 0x05 /* MemoryType */
760 switch (Status->MemoryType) {
764 CurrentMemoryStatus = Status;
766 req[5] = N7110_GetMemoryType(Status->MemoryType);
768 return NULL_SendMessageSequence
769 (20, &CurrentMemoryStatusError, 6, 0x03, req);
780 return GE_NOTSUPPORTED;
784 void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
786 switch(MessageBuffer[3]) {
791 fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]);
794 switch (MessageBuffer[6]) {
795 case 0xff: /* Profile Name */
796 DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]);
798 fprintf(stdout,_(" Name \"%s\"\n"),CurrentProfile->Name);
803 case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */
804 switch( MessageBuffer[10] ) {
806 CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break;
810 CurrentProfile->KeypadTone = MessageBuffer[10]-1; break;
814 case 0x02: /* Call Alert type (Ringing, Ascending, ..., Off) */
815 /* I make it compatible with GetProfileCallAlertString */
816 switch( MessageBuffer[10] ) {
817 case 0: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGING; break;
818 case 1: CurrentProfile->CallAlert = PROFILE_CALLALERT_ASCENDING; break;
819 case 2: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGONCE; break;
820 case 3: CurrentProfile->CallAlert = PROFILE_CALLALERT_BEEPONCE; break;
821 case 5: CurrentProfile->CallAlert = PROFILE_CALLALERT_OFF; break;
824 case 0x03: /* Ringtone number */
825 CurrentProfile->Ringtone = MessageBuffer[10];
827 case 0x04: /* Ringtone volume (from level 1 to level 5) */
828 CurrentProfile->Volume = MessageBuffer[10] + 6;
830 case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */
831 CurrentProfile->MessageTone = MessageBuffer[10];
833 case 0x06: /* Vibration (On/Off) */
834 CurrentProfile->Vibration = MessageBuffer[10];
836 case 0x07: /* WarningTone (On/Off) */
837 switch( MessageBuffer[10] ) {
839 CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break;
841 CurrentProfile->WarningTone = PROFILE_WARNING_ON; break;
844 case 0x08: /* Alert for (caller groups) */
845 CurrentProfile->CallerGroups = MessageBuffer[10];
847 case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */
848 CurrentProfile->AutomaticAnswer = MessageBuffer[10];
852 CurrentProfileError=GE_NONE;
857 fprintf(stdout, _("Message: Unknown message of type 0x39\n"));
859 AppendLogText("Unknown msg\n",false);
860 break; /* Visual C Don't like empty cases */
865 GSM_Error N7110_GetProfile(GSM_Profile *Profile)
869 unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
870 0x00, //profile number
871 0xff}; //feature. Here 0xff=name
873 unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22,
878 CurrentProfile = Profile;
880 /* When after sending all frames feature==253, it means, that it is not
882 CurrentProfile->KeypadTone=253;
883 CurrentProfile->Lights=253;
884 CurrentProfile->CallAlert=253;
885 CurrentProfile->Ringtone=253;
886 CurrentProfile->Volume=253;
887 CurrentProfile->MessageTone=253;
888 CurrentProfile->WarningTone=253;
889 CurrentProfile->Vibration=253;
890 CurrentProfile->CallerGroups=253;
891 CurrentProfile->ScreenSaver=253;
892 CurrentProfile->AutomaticAnswer=253;
894 req[7] = Profile->Number+1;
896 error=NULL_SendMessageSequence
897 (20, &CurrentProfileError, 9, 0x39, req);
898 if (error!=GE_NONE) return error;
900 for (i = 0; i < 11; i++) {
902 req[7] = Profile->Number+1;
906 error=NULL_SendMessageSequence
907 (20, &CurrentProfileError, 9, 0x39, req);
908 if (error!=GE_NONE) return error;
914 void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
918 CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5];
919 CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany;
921 for(i=0;i<CurrentCalendarNotesInfo.HowMany && i<MAX_NOTES_INFO_ELEMS;i++) {
922 CurrentCalendarNotesInfo.Location[i] = MessageBuffer[8+i*2]*256+ MessageBuffer[8+i*2+1];
923 CurrentCalendarNotesInfo2->Location[i]=CurrentCalendarNotesInfo.Location[i];
926 CurrentCalendarNotesInfoError=GE_NONE;
929 GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo)
931 unsigned char req[] = { N6110_FRAME_HEADER,
932 0x3a, /* get notes info */
937 CurrentCalendarNotesInfo2=NotesInfo;
939 error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req);
944 void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2)
951 if (alarmdiff == 0xffff) fprintf(stdout," No alarm");
952 else fprintf(stdout," Alarm is %i seconds before date", alarmdiff*alarm2);
953 fprintf(stdout,"\n");
956 if (alarmdiff != 0xffff) {
958 memset(&tm_time, 0, sizeof(tm_time));
959 tm_time.tm_year = time->Year - 1900;
960 tm_time.tm_mon = time->Month - 1;
961 tm_time.tm_mday = time->Day;
962 tm_time.tm_hour = time->Hour;
963 tm_time.tm_min = time->Minute;
964 tm_time.tm_sec = time->Second;
967 t_alarm = mktime(&tm_time);
968 t_alarm -= alarmdiff*alarm2;
970 tm_alarm = localtime(&t_alarm);
972 alarm->Year = tm_alarm->tm_year + 1900;
973 alarm->Month = tm_alarm->tm_mon + 1;
974 alarm->Day = tm_alarm->tm_mday;
975 alarm->Hour = tm_alarm->tm_hour;
976 alarm->Minute = tm_alarm->tm_min;
977 alarm->Second = tm_alarm->tm_sec;
980 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
981 alarm->Day,alarm->Month,alarm->Year,
982 alarm->Hour,alarm->Minute,alarm->Second);
987 void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
991 c->Time.Year = block[8]*256+block[9];
992 c->Time.Month = block[10];
993 c->Time.Day = block[11];
994 if (c->Type != GCN_REMINDER) {
995 c->Time.Hour = block[12];
996 c->Time.Minute = block[13];
1004 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1005 c->Time.Day,c->Time.Month,c->Time.Year,
1006 c->Time.Hour,c->Time.Minute,c->Time.Second);
1009 if (c->Type != GCN_REMINDER) {
1010 alarmdiff = block[14]*256 + block[15];
1011 P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60);
1013 c->Recurrance = block[16]*256 + block[17];
1014 DecodeUnicode(c->Text, block+20, block[18]);
1016 c->Recurrance = block[12]*256 + block[13];
1017 DecodeUnicode(c->Text, block+16, block[14]);
1020 /* 0xffff -> 1 Year (8760 hours) */
1021 if (c->Recurrance == 0xffff) c->Recurrance=8760;
1024 fprintf(stdout, " Recurrance: %i hours\n Text: \"%s\"\n",
1025 c->Recurrance,c->Text);
1029 void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1033 CurrentCalendarNote->YearOfBirth=0; //for other than birthday
1034 CurrentCalendarNote->AlarmType=0x00;//for other than birthday
1035 CurrentCalendarNote->Phone[0]=0; //for other than call
1037 CurrentCalendarNote->Alarm.Year = 0;
1038 CurrentCalendarNote->Alarm.Month = 0;
1039 CurrentCalendarNote->Alarm.Day = 0;
1040 CurrentCalendarNote->Alarm.Hour = 0;
1041 CurrentCalendarNote->Alarm.Minute = 0;
1042 CurrentCalendarNote->Alarm.Second = 0;
1045 fprintf(stdout, "Message: calendar note received\n");
1048 switch (MessageBuffer[6]) /* entry type */ {
1049 case 0x01: /* Meeting */
1051 fprintf(stdout, " Note type: meeting\n");
1053 CurrentCalendarNote->Type = GCN_MEETING;
1054 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1055 CurrentCalendarNoteError=GE_NONE;
1058 case 0x02: /* Call */
1060 fprintf(stdout, " Note type: call\n");
1062 CurrentCalendarNote->Type = GCN_CALL;
1063 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1064 DecodeUnicode(CurrentCalendarNote->Phone,
1065 MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]);
1067 fprintf(stdout, " Phone number: \"%s\"\n",CurrentCalendarNote->Phone);
1069 CurrentCalendarNoteError=GE_NONE;
1072 case 0x04: /* Birthday */
1074 fprintf(stdout, " Note type: birthday\n");
1076 CurrentCalendarNote->Type = GCN_BIRTHDAY;
1078 alarm = ((unsigned int)MessageBuffer[14]) << 24;
1079 alarm += ((unsigned int)MessageBuffer[15]) << 16;
1080 alarm += ((unsigned int)MessageBuffer[16]) << 8;
1081 alarm += MessageBuffer[17];
1083 /* CurrentCalendarNote->Time.Year is set earlier */
1084 CurrentCalendarNote->Time.Month = MessageBuffer[10];
1085 CurrentCalendarNote->Time.Day = MessageBuffer[11];
1086 CurrentCalendarNote->Time.Hour = 23;
1087 CurrentCalendarNote->Time.Minute = 59;
1088 CurrentCalendarNote->Time.Second = 58;
1089 P7110_GetNoteAlarm(alarm, &(CurrentCalendarNote->Time), &(CurrentCalendarNote->Alarm) ,1);
1091 CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19];
1092 CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth;
1094 CurrentCalendarNote->AlarmType = MessageBuffer[20];
1097 fprintf(stdout,_(" Alarm type: %s\n"),
1098 (CurrentCalendarNote->AlarmType==0x00) ? "Tone " : "Silent");
1100 fprintf(stdout, " Birthday date: %02i-%02i-%04i (age %d)\n",CurrentCalendarNote->Time.Day,
1101 CurrentCalendarNote->Time.Month,CurrentCalendarNote->Time.Year,
1102 CurrentCalendarNote->Alarm.Year - CurrentCalendarNote->Time.Year);
1105 DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]);
1107 fprintf(stdout, " Text: \"%s\"\n",CurrentCalendarNote->Text);
1110 CurrentCalendarNote->Recurrance = 0;
1111 CurrentCalendarNoteError=GE_NONE;
1114 case 0x08: /* Reminder */
1116 fprintf(stdout, " Note type: reminder\n");
1118 CurrentCalendarNote->Type = GCN_REMINDER;
1119 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1120 CurrentCalendarNoteError=GE_NONE;
1123 default: /* unknown */
1125 fprintf(stdout, " Note type: UNKNOWN\n");
1131 GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
1133 unsigned char req[] = { N6110_FRAME_HEADER,
1134 0x19, /* get calendar note */
1135 0x00, 0x00 //location
1139 GSM_DateTime date_time;
1143 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1144 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1145 if (error!=GE_NONE) return error;
1149 fprintf(stdout, _("Calendar Notes Location Logical = %d.\n"),
1150 CalendarNote->Location);
1151 fprintf(stdout, _("Calendar Notes Location Phisical = %d.\n"),
1152 CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]);
1155 /* this is for making xgnokii work.. */
1156 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1157 return GE_INVALIDCALNOTELOCATION;
1159 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1160 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1161 CurrentCalendarNote = CalendarNote;
1163 /* We have to get current year. It's NOT written in frame for Birthday */
1164 error=N7110_GetDateTime(&date_time);
1165 if (error!=GE_NONE) return error;
1166 if (!date_time.IsSet) {
1168 now=localtime(&nowh);
1170 /* I have 100 (for 2000) Year now :-) */
1171 if (now->tm_year>99 && now->tm_year<1900) {
1172 now->tm_year=now->tm_year+1900;
1174 date_time.Year=now->tm_year;
1176 CurrentCalendarNote->Time.Year = date_time.Year;
1178 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1180 CurrentCalendarNote = NULL;
1185 void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1188 char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" };
1191 "Succesfully written Calendar Note Type %s on location %d\n",
1192 kz_types[(MessageBuffer[3]/2)-1],
1193 MessageBuffer[4]*256+MessageBuffer[5] );
1195 fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n",
1196 MessageBuffer[6]*256+MessageBuffer[7] );
1198 CurrentCalendarNoteError=GE_NONE;
1201 long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm)
1210 tm_alarm.tm_year=alarm->Year-1900;
1211 tm_alarm.tm_mon=alarm->Month-1;
1212 tm_alarm.tm_mday=alarm->Day;
1213 tm_alarm.tm_hour=alarm->Hour;
1214 tm_alarm.tm_min=alarm->Minute;
1215 tm_alarm.tm_sec=alarm->Second;
1216 tm_alarm.tm_isdst=0;
1217 t_alarm = mktime(&tm_alarm);
1219 tm_time.tm_year=time->Year-1900;
1220 tm_time.tm_mon=time->Month-1;
1221 tm_time.tm_mday=time->Day;
1222 tm_time.tm_hour=time->Hour;
1223 tm_time.tm_min=time->Minute;
1224 tm_time.tm_sec=time->Second;
1226 t_time = mktime(&tm_time);
1229 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
1230 alarm->Day,alarm->Month,alarm->Year,
1231 alarm->Hour,alarm->Minute,alarm->Second);
1232 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1233 time->Day,time->Month,time->Year,
1234 time->Hour,time->Minute,time->Second);
1235 fprintf(stdout,_("Difference in alarm time is %f\n"),difftime( t_time, t_alarm )+3600);
1238 return difftime( t_time ,t_alarm )+3600;
1241 GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
1243 unsigned char req[200] = { N6110_FRAME_HEADER,
1244 0x01, /* note type ... */
1245 0x00, 0x00, /* location */
1246 0x00, /* entry type */
1248 0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */
1249 /* here starts block */
1250 0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */
1254 long seconds, minutes;
1257 int firstFreeLocation;
1260 * 6210/7110 needs to seek the first free pos to inhabit with next note
1262 error=N7110_FirstCalendarFreePos(&firstFreeLocation);
1263 if (error!=GE_NONE) return error;
1266 fprintf(stdout, _("First free calendar location is = %d.\n"),
1274 switch( CalendarNote->Type ) {
1275 case GCN_MEETING : req[6]=0x01; req[3]=0x01; break;
1276 case GCN_CALL : req[6]=0x02; req[3]=0x03; break;
1277 case GCN_BIRTHDAY: req[6]=0x04; req[3]=0x05; break;
1278 case GCN_REMINDER: req[6]=0x08; req[3]=0x07; break;
1281 req[8]=CalendarNote->Time.Year>>8;
1282 req[9]=CalendarNote->Time.Year&0xff;
1283 req[10]=CalendarNote->Time.Month;
1284 req[11]=CalendarNote->Time.Day;
1286 /* From here starts BLOCK */
1288 switch( CalendarNote->Type ) {
1291 req[count++]=CalendarNote->Time.Hour; // 12
1292 req[count++]=CalendarNote->Time.Minute; // 13
1294 req[count++]=0xff; // 14
1295 req[count++]=0xff; // 15
1296 if( CalendarNote->Alarm.Year )
1298 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1299 &CalendarNote->Alarm);
1300 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1301 minutes=seconds/60L;
1303 req[count++]=minutes>>8;
1304 req[count++]=minutes&0xff;
1308 if( CalendarNote->Recurrance >= 8760 )
1309 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1310 req[count++]=CalendarNote->Recurrance>>8; // 16
1311 req[count++]=CalendarNote->Recurrance&0xff; // 17
1313 req[count++]=strlen(CalendarNote->Text); // 18
1315 req[count++]=0x00; // 19
1318 fprintf(stdout, "Count before encode = %d\n", count );
1319 fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text );
1322 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1323 count=count+2*strlen(CalendarNote->Text);
1327 req[count++]=CalendarNote->Time.Hour; // 12
1328 req[count++]=CalendarNote->Time.Minute; // 13
1330 req[count++]=0xff; // 14
1331 req[count++]=0xff; // 15
1332 if( CalendarNote->Alarm.Year )
1334 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1335 &CalendarNote->Alarm);
1336 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1337 minutes=seconds/60L;
1339 req[count++]=minutes>>8;
1340 req[count++]=minutes&0xff;
1344 if( CalendarNote->Recurrance >= 8760 )
1345 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1346 req[count++]=CalendarNote->Recurrance>>8; // 16
1347 req[count++]=CalendarNote->Recurrance&0xff; // 17
1349 req[count++]=strlen(CalendarNote->Text); // 18
1351 req[count++]=strlen(CalendarNote->Phone); // 19
1353 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1354 count=count+2*strlen(CalendarNote->Text);
1355 EncodeUnicode (req+count,CalendarNote->Phone ,strlen(CalendarNote->Phone));// (N+1)->n
1356 count=count+2*strlen(CalendarNote->Phone);
1360 req[count++]=0x00; // 12 Fixed
1361 req[count++]=0x00; // 13 Fixed
1364 req[count++]=0x00; req[count++]=0x00; // 14, 15
1365 req[count++]=0xff; // 16
1366 req[count++]=0xff; // 17
1367 if( CalendarNote->Alarm.Year ) {
1368 // I try with Time.Year = Alarm.Year. If negative, I increase 1 year,
1369 // but only once ! This thing, because I may have Alarm period across
1370 // a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27)
1372 CalendarNote->Time.Year = CalendarNote->Alarm.Year;
1373 if( (seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1374 &CalendarNote->Alarm)) < 0L ) {
1375 CalendarNote->Time.Year++;
1376 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1377 &CalendarNote->Alarm);
1379 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1381 req[count++]=seconds>>24; // 14
1382 req[count++]=(seconds>>16) & 0xff; // 15
1383 req[count++]=(seconds>>8) & 0xff; // 16
1384 req[count++]=seconds&0xff; // 17
1388 req[count++]=CalendarNote->AlarmType; // 18
1391 req[count++]=strlen(CalendarNote->Text); // 19
1395 fprintf(stdout, "Count before encode = %d\n", count );
1396 fprintf(stdout, "Meeting Text is = \"%s\" Altype is 0x%02x \n", CalendarNote->Text , CalendarNote->AlarmType );
1398 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N
1399 count=count+2*strlen(CalendarNote->Text);
1404 if( CalendarNote->Recurrance >= 8760 )
1405 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1406 req[count++]=CalendarNote->Recurrance>>8; // 12
1407 req[count++]=CalendarNote->Recurrance&0xff; // 13
1409 req[count++]=strlen(CalendarNote->Text); // 14
1411 req[count++]=0x00; // 15
1413 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N
1414 count=count+2*strlen(CalendarNote->Text);
1421 fprintf(stdout, "Count after padding = %d\n", count );
1424 CurrentCalendarNote = CalendarNote;
1426 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req);
1428 CurrentCalendarNote = NULL;
1433 void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1435 *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5];
1436 CurrentFirstCalendarFreePosError=GE_NONE;
1439 GSM_Error N7110_FirstCalendarFreePos(int *FreePos)
1441 unsigned char req[] = { N6110_FRAME_HEADER, 0x31 };
1445 CurrentFirstCalendarFreePos = FreePos;
1447 error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError,
1450 CurrentFirstCalendarFreePos = NULL;
1455 void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1459 "Succesfully Delete Calendar Note on location %d\n",
1460 MessageBuffer[4]*256+MessageBuffer[5] );
1462 fprintf(stdout, "--> Other data are :\n" );
1463 fprintf(stdout, " '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d)\n",
1464 MessageBuffer[6], MessageBuffer[6], MessageBuffer[6],
1465 MessageBuffer[7], MessageBuffer[7], MessageBuffer[7],
1466 MessageBuffer[8], MessageBuffer[8], MessageBuffer[8],
1467 MessageBuffer[9], MessageBuffer[9], MessageBuffer[9] );
1469 CurrentCalendarNoteError=GE_NONE;
1472 GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
1474 unsigned char req[] = { N6110_FRAME_HEADER,
1475 0x0b, /* delete calendar note */
1476 0x00, 0x00 //location
1481 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1482 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1483 if (error!=GE_NONE) return error;
1486 /* this is for making xgnokii work.. */
1487 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1488 return GE_INVALIDCALNOTELOCATION;
1490 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1491 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1493 CurrentCalendarNote = CalendarNote;
1495 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1497 CurrentCalendarNote = NULL;
1502 void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1509 fprintf(stdout, _("Message: SMS Folders received:\n"));
1514 CurrentSMSFoldersCount=MessageBuffer[4];
1516 for (j=0;j<MessageBuffer[4];j++) {
1517 strcpy(CurrentSMSFolders->Folder[j].Name," ");
1519 fprintf(stdout, _(" Folder Index: %d"),MessageBuffer[i]);
1521 CurrentSMSFolders->FoldersID[j]=MessageBuffer[i];
1526 fprintf(stdout, _(", folder name: "));
1529 while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) {
1531 wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8);
1533 CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc);
1535 fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]);
1541 fprintf(stdout, _("\n"));
1547 CurrentSMSFoldersError=GE_NONE;
1550 GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders)
1552 unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
1556 CurrentSMSFolders=folders;
1558 error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req);
1560 folders->number=CurrentSMSFoldersCount;
1565 void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1570 fprintf(stdout, _("Message: SMS Folder status received\n"));
1571 fprintf(stdout, _(" Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]);
1573 CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5];
1575 fprintf(stdout, _(" (indexes "));
1578 for (i=0;i<MessageBuffer[4]*256+MessageBuffer[5];i++) {
1580 fprintf(stdout, _("%i, "), MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7]);
1582 CurrentSMSFolder.locations[i]=MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7];
1586 fprintf(stdout, _(")\n"));
1589 CurrentSMSFolderError=GE_NONE;
1592 GSM_Error N7110_GetSMSFolderStatus ( GSM_OneSMSFolder *folder, u8 ID)
1594 unsigned char req[] = { N7110_FRAME_HEADER,
1602 CurrentSMSFolder = *folder;
1603 CurrentSMSFolderID = ID;
1606 error=NULL_SendMessageSequence(20, &CurrentSMSFolderError, 7, 0x14, req);
1608 *folder=CurrentSMSFolder;
1613 void N7110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1617 fprintf(stdout, _("Message: SMS deleted succesfully\n"));
1619 CurrentSMSMessageError = GE_NONE;
1622 GSM_Error N7110_DeleteSMSMessage(GSM_SMSMessage *message)
1624 unsigned char req[] = {
1625 N7110_FRAME_HEADER, 0x0a, /* delete SMS request */
1626 0x00, /* folder (req[4])*/
1627 0x00, /* location */
1628 0x00, /* location (req[6])*/
1632 int smsnum, location;
1635 smsnum = message->Location;
1636 /* We made "fake" SMS numbering for SMS in 7110/6210/etc. */
1637 if ((error = N7110_HandleSMSLocation(smsnum, &folderid, &location, NULL, GSH_DELETE))!=GE_NONE)
1641 req[5]=location / 256;
1645 printf("delete sms: folder %d, location %d\n",folderid,location);
1648 return NULL_SendMessageSequence
1649 (50, &CurrentSMSMessageError, 8, 0x14, req);
1652 GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message)
1655 unsigned char req[] = { N6110_FRAME_HEADER,
1658 0x00, 0x05, // location
1663 int smsnum, location;
1667 CurrentSMSMessage = message;
1668 CurrentSMSMessageError = GE_BUSY;
1671 smsnum = message->Location;
1673 /* we make central handling of real location */
1674 error = N7110_HandleSMSLocation(smsnum, &folderid, &location, message, GSH_GET);
1675 /* if smsnum is 0 (next sms) we need real smsnum */
1676 N7110_SMS2FakeLocation( &smsnum, folderid, location);
1677 message->Location = smsnum;
1680 case GE_SMSISINMEM: /* future use: get already reed sms from mem */
1683 case GE_NONE: req[4]=folderid;
1684 req[5]=location / 256;
1687 fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location);
1689 return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req);
1697 void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1701 switch (MessageBuffer[3]) {
1706 fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]);
1709 if (CurrentSMSMessage!=NULL) {
1710 N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]);
1711 CurrentSMSMessage->MessageNumber=smsnum;
1714 CurrentSMSMessageError = GE_NONE;
1717 /* save sms failed */
1721 fprintf(stdout, _("Message: SMS Message save failed\n"));
1723 CurrentSMSMessageError = GE_SMSSAVEFAILED;
1728 fprintf(stdout, _("Message: Changed name for SMS Message\n"));
1730 CurrentSMSMessageError = GE_NONE;
1736 GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS)
1738 unsigned char req[256] = {
1739 N6110_FRAME_HEADER, 0x04, /* SMS save request*/
1740 0x03, /* default: mark sms as GSS_NOTSENTREAD */
1741 0x10, /* folder (req[5])*/
1742 0x00, /* location */
1743 0x00, /* location (req[7])*/
1747 unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83};
1749 int length,smsnum,location;
1752 SMS_MessageType PDU;
1754 smsnum = SMS->Location;
1757 printf("save sms: smsnum is :%d\n",smsnum);
1760 if ( SMS->Status == GSS_SENTREAD) req[4] = 0x01;
1762 folderid = SMS->folder;
1766 error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU);
1767 if (error != GE_NONE) return error;
1769 CurrentSMSMessage = SMS;
1771 error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE);
1775 case GE_BUSYSMSLOCATION: /* delete old sms before save */
1776 error = N7110_DeleteSMSMessage(SMS);
1777 if (error != GE_NONE) return error;
1787 printf("save sms: want to save at folder:%d , location:%d\n",folderid,location);
1791 req[6]=location / 256;
1794 error=NULL_SendMessageSequence
1795 (70, &CurrentSMSMessageError, 40+length, 0x14, req);
1797 if (error==GE_NONE && SMS->Name[0]!=0) {
1799 N7110_Fake2SMSLocation(SMS->MessageNumber, &folderid, &location);
1800 req2[length++]=folderid;
1801 req2[length++]=location / 256;
1802 req2[length++]=location;
1803 EncodeUnicode(req2+length, SMS->Name, strlen(SMS->Name));
1804 length=length+strlen(SMS->Name)*2;
1807 error=NULL_SendMessageSequence
1808 (70, &CurrentSMSMessageError, length, 0x14, req2);
1814 /* handling for 7110 folders */
1815 GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action)
1818 static int nextSMSmessage = -1;
1819 static GSM_SMSStatus Status;
1823 GSM_OneSMSFolder onefolder;
1829 case GSH_DELETE: /* future use: delete sms in mem -> free memory */
1830 /* for now we make same as in GSH_GET */
1831 case GSH_GET: /* if smsnum == 0 user wants to read next sms */
1834 /* first time we read folderstatus */
1835 if ( nextSMSmessage == -1)
1838 error = N7110_GetSMSStatus( &Status);
1839 if (error!=GE_NONE) return error;
1841 ismsnum = Status.foldertable[nextSMSmessage].smsnum;
1842 N7110_Fake2SMSLocation( ismsnum, folder, location);
1844 if(nextSMSmessage >= Status.Number)
1846 nextSMSmessage = -1;
1848 printf("HandleSMS: setting nextSMSmessage to -1\n");
1851 } else /* user give location -> make fake location */
1853 /* future use: get already read sms from mem */
1854 N7110_Fake2SMSLocation( smsnum, folder, location);
1857 case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */
1860 /* calculate correct folderid */
1861 *folder = ( *folder + 1) * 8;
1864 } else /* user give location -> make fake location */
1866 N7110_Fake2SMSLocation( smsnum, folder, location);
1869 error=N7110_GetSMSFolderStatus(&onefolder, folderid );
1870 if (error!=GE_NONE) return error;
1872 /* is there a sms at that location ? */
1873 for (i=0; i<CurrentSMSFolder.number; i++)
1874 if ( CurrentSMSFolder.locations[i] == *location ) found = true;
1876 if (found == true) return GE_BUSYSMSLOCATION;
1877 else return GE_NONE;
1886 /* input: fake smsnum, output: folderid & location */
1887 void N7110_Fake2SMSLocation(int smsnum, u8 *folderid, int *location)
1891 ifolderid = smsnum / N7110_MAXSMSINFOLDER;
1892 *folderid = ifolderid * 0x08;
1893 *location = smsnum - ifolderid * N7110_MAXSMSINFOLDER;
1896 /* input; folderid & location, output: fake smsnum */
1897 void N7110_SMS2FakeLocation(int *smsnum, u8 folderid, int location)
1901 ifolderid = folderid / 0x08;
1902 *smsnum = ifolderid * N7110_MAXSMSINFOLDER + location;
1905 GSM_Error N7110_GetRFLevel(GSM_RFUnits *units, float *level)
1907 unsigned char request[] = {N6110_FRAME_HEADER, 0x81};
1914 Protocol->SendMessage(4, 0x0a, request);
1916 /* Wait for timeout or other error. */
1917 while (timeout != 0 && CurrentRFLevel == -1 ) {
1920 return (GE_TIMEOUT);
1925 /* Make copy in case it changes. */
1926 rf_level = CurrentRFLevel;
1931 /* Now convert between the different units we support. */
1933 /* Arbitrary units. */
1934 *units = GRF_Percentage;
1939 GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1941 unsigned char request[] = {N6110_FRAME_HEADER, 0x02};
1946 CurrentBatteryLevel=-1;
1948 Protocol->SendMessage(4, 0x17, request);
1950 /* Wait for timeout or other error. */
1951 while (timeout != 0 && CurrentBatteryLevel == -1 ) {
1954 return (GE_TIMEOUT);
1959 /* Take copy in case it changes. */
1960 batt_level = CurrentBatteryLevel;
1962 if (batt_level == -1)
1965 /* Only units we handle at present are GBU_Arbitrary */
1966 *units = GBU_Percentage;
1967 *level = batt_level;
1971 GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
1973 unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c};
1975 if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED;
1977 CurrentSecurityCode=SecurityCode;
1979 return NULL_SendMessageSequence
1980 (50, &CurrentSecurityCodeError, 5, 0x7a, req);
1983 GSM_Error N7110_GetDateTime(GSM_DateTime *date_time)
1985 return N6110_PrivGetDateTime(date_time,0x19);
1988 /* Needs SIM card with PIN in phone */
1989 GSM_Error N7110_SetDateTime(GSM_DateTime *date_time)
1991 return N6110_PrivSetDateTime(date_time,0x19);
1994 GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1996 return N6110_PrivGetAlarm(alarm_number,date_time,0x19);
1999 /* FIXME: we should also allow to set the alarm off :-) */
2000 GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
2002 return N6110_PrivSetAlarm(alarm_number,date_time, 0x19);
2005 void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2007 switch (MessageBuffer[3]) {
2013 fprintf(stdout, _("Message: SMS Status Received\n"));
2014 fprintf(stdout, _(" Used msg in phone memory: %i\n"),MessageBuffer[10]*256+MessageBuffer[11]);
2015 fprintf(stdout, _(" Unread msg in phone memory: %i\n"),MessageBuffer[12]*256+MessageBuffer[13]);
2016 fprintf(stdout, _(" Used msg in SIM: %i\n"),MessageBuffer[14]*256+MessageBuffer[15]);
2017 fprintf(stdout, _(" Unread msg in SIM: %i\n"),MessageBuffer[16]*256+MessageBuffer[17]);
2019 CurrentSMSStatus->UnRead = MessageBuffer[13];
2020 CurrentSMSStatusError = GE_NONE;
2026 fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
2028 CurrentSMSStatusError = GE_INTERNALERROR;
2034 GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status)
2036 /* RTH FIXME: what is exact meaning of 0x0037 answer ? */
2037 /* we check all folders, but get sum of unread sms via 0x0036 request */
2038 unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
2040 GSM_SMSFolders folders;
2041 GSM_OneSMSFolder folder;
2044 int ismsnum,ilocation;
2047 CurrentSMSStatus = Status;
2049 /* read all SMS folders */
2050 /* check for unread messages in folder 0xf8 */
2051 error = N7110_GetSMSFolderStatus(&folder, 0xf8);
2052 if (error != GE_NONE) return error;
2055 for(j=0; j<folder.number; j++)
2057 ifolder = 0; /*read unread messages from folder 0 */
2058 ilocation = folder.locations[j];
2059 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation) ;
2060 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2061 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2062 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2066 /* read standard folders */
2067 N7110_GetSMSFolders (&folders);
2068 for(i=0; i<CurrentSMSFoldersCount; i++)
2070 error = N7110_GetSMSFolderStatus(&CurrentSMSFolders->Folder[i], CurrentSMSFolders->FoldersID[i]);
2071 if (error != GE_NONE) return error;
2073 for(j=0; j<CurrentSMSFolders->Folder[i].number; j++)
2075 ifolder = CurrentSMSFolders->FoldersID[i];
2076 ilocation = CurrentSMSFolders->Folder[i].locations[j];
2077 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation);
2078 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2079 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2080 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2084 CurrentSMSStatus->Number = smsmaxnum;
2086 return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req);
2089 void N7110_DecodePhonebookFrame(GSM_PhonebookEntry *entry,u8 *MessageBuffer,u16 MessageLength)
2092 unsigned char *pBlock;
2099 pBlock = &MessageBuffer[0];
2101 while (length!=MessageLength) {
2102 GSM_SubPhonebookEntry* pEntry = &entry->SubEntries[blockcount];
2105 fprintf(stdout,_(" "));
2106 for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]);
2107 fprintf(stdout,_("\n"));
2110 switch( pBlock[0] ) {
2111 case N7110_ENTRYTYPE_SPEEDDIAL:
2113 CurrentSpeedDialEntry->MemoryType = GMT_SM;
2114 if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME;
2116 CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256;
2119 fprintf(stdout, _(" Speed dial\n"));
2120 fprintf(stdout, _(" Location: %d\n"), CurrentSpeedDialEntry->Location);
2121 fprintf(stdout, _(" MemoryType: %i\n"), CurrentSpeedDialEntry->MemoryType);
2122 fprintf(stdout, _(" Number: %d\n"), CurrentSpeedDialEntry->Number);
2125 CurrentSpeedDialError=GE_NONE;
2128 case N7110_ENTRYTYPE_NAME:
2129 DecodeUnicode (entry->Name, pBlock+6, pBlock[5]/2);
2130 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2131 strncpy(CurrentGetBitmap->text,entry->Name,sizeof(CurrentGetBitmap->text));
2132 entry->Empty = false;
2134 fprintf(stdout, _(" Name:\n"));
2135 fprintf(stdout, _(" Name: %s\n"), entry->Name);
2139 case N7110_ENTRYTYPE_NUMBER:
2140 pEntry->EntryType = pBlock[0];
2141 pEntry->NumberType = pBlock[5];
2142 pEntry->BlockNumber = pBlock[4];
2144 DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2);
2147 fprintf(stdout, _(" Number:\n"));
2148 fprintf(stdout, _(" Type: %d (%02x)\n"),pEntry->NumberType,pEntry->NumberType);
2149 fprintf(stdout, _(" Number: %s\n"),pEntry->data.Number);
2151 if( pEntry->EntryType == GSM_Number &&
2152 ((pEntry->NumberType == GSM_General && !strcmp(entry->Number,""))
2153 || pEntry->NumberType == GSM_SIM)) {
2154 strcpy( entry->Number, pEntry->data.Number );
2155 *pEntry->data.Number = 0;
2159 case N7110_ENTRYTYPE_DATE:
2160 pEntry->EntryType = pBlock[0];
2161 pEntry->NumberType = pBlock[5];
2162 pEntry->BlockNumber = pBlock[4];
2163 DecodeDateTime(pBlock+6, &pEntry->data.Date);
2165 fprintf(stdout, _(" Date:\n"));
2166 fprintf(stdout, _(" Date: %02u.%02u.%04u\n"), pEntry->data.Date.Day,
2167 pEntry->data.Date.Month, pEntry->data.Date.Year );
2168 fprintf(stdout, _(" Time: %02u:%02u:%02u\n"), pEntry->data.Date.Hour,
2169 pEntry->data.Date.Minute, pEntry->data.Date.Second);
2173 case N7110_ENTRYTYPE_NOTE:
2174 case N7110_ENTRYTYPE_POSTAL:
2175 case N7110_ENTRYTYPE_EMAIL:
2176 pEntry->EntryType = pBlock[0];
2177 pEntry->NumberType = 0;
2178 pEntry->BlockNumber = pBlock[4];
2180 DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2);
2183 fprintf(stdout, _(" Email or note or postal:\n"));
2184 fprintf(stdout, _(" Type: %d (%02x)\n"),pEntry->EntryType,pEntry->EntryType);
2185 fprintf(stdout, _(" Text: %s\n"),pEntry->data.Number);
2189 case N7110_ENTRYTYPE_GROUP:
2190 entry->Group = pBlock[5]-1; /* 0 = family as for 6110 */
2191 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2192 CurrentGetBitmap->number = entry->Group;
2194 fprintf(stdout, _(" Group: %d\n"), entry->Group);
2197 case N7110_ENTRYTYPE_RINGTONE:
2198 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2199 CurrentGetBitmap->ringtone = pBlock[5];
2201 fprintf(stdout, _(" Group ringtone number %d received.\n"), pBlock[5]);
2204 case N7110_ENTRYTYPE_LOGOON:
2205 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2206 CurrentGetBitmap->enabled = pBlock[5];
2208 fprintf(stdout, _(" Logo enabled = %d received.\n"), pBlock[5]);
2211 case N7110_ENTRYTYPE_GROUPLOGO:
2213 fprintf(stdout, _(" Caller group logo received.\n"));
2215 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
2216 CurrentGetBitmap->width = pBlock[5];
2217 CurrentGetBitmap->height= pBlock[6];
2218 CurrentGetBitmap->size = pBlock[9];
2219 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
2220 CurrentGetBitmap->size = CurrentGetBitmap->size;
2221 memcpy(CurrentGetBitmap->bitmap,pBlock+10,CurrentGetBitmap->size);
2227 fprintf(stdout, _(" Unknown Entry Code (%u) received.\n"), pBlock[0] );
2233 fprintf(stdout, _(" Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]);
2235 length=length+pBlock[3];
2237 pBlock = &pBlock[(int) pBlock[3]];
2240 entry->SubEntriesCount = blockcount;
2243 fprintf(stdout, _(" SubBlocks: %d\n"),entry->SubEntriesCount);
2247 void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2250 CurrentPhonebookEntry->Empty = true;
2251 CurrentPhonebookEntry->Group = 5; /* 5 = no group as 6110 */
2252 CurrentPhonebookEntry->Name[0] = '\0';
2253 CurrentPhonebookEntry->Number[0] = '\0';
2254 CurrentPhonebookEntry->SubEntriesCount = 0;
2257 fprintf(stdout, _("Message: Phonebook entry received:\n"));
2260 if( MessageBuffer[6] == 0x0f ) // not found
2263 fprintf(stdout, _(" Error %i\n"),MessageBuffer[10]);
2264 switch (MessageBuffer[10]) {
2265 case 0x34:fprintf(stdout,_(" Invalid phonebook location\n"));break;
2266 case 0x3b:fprintf(stdout,_(" Speed dial not assigned\n"));break;
2267 default :fprintf(stdout,_(" Unknown.Please report\n"));break;
2270 switch (MessageBuffer[10]) {
2271 case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break;
2272 case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break;
2273 default :CurrentPhonebookError = GE_UNKNOWN;
2275 CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
2278 CurrentPhonebookEntry->Location=MessageBuffer[13]+MessageBuffer[12]*256;
2281 fprintf(stdout,_(" Location: %i\n"),CurrentPhonebookEntry->Location);
2284 N7110_DecodePhonebookFrame(CurrentPhonebookEntry,MessageBuffer+18,MessageLength-18);
2286 CurrentPhonebookError = GE_NONE;
2290 /* Routine to get specifed phone book location. Designed to be called by
2291 application. Will block until location is retrieved or a timeout/error
2293 GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) {
2295 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2298 0x00, 0x00, //location
2301 CurrentPhonebookEntry = entry;
2303 req[9] = N7110_GetMemoryType(entry->MemoryType);
2304 req[10] = (entry->Location>>8);
2305 req[11] = entry->Location & 0xff;
2307 return NULL_SendMessageSequence
2308 (50, &CurrentPhonebookError, 14, 0x03, req);
2311 void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2313 // [12,13] = Location
2316 if( MessageBuffer[6] == 0x0f ) // ERROR
2319 /* I didn't find any error when the Text,Name or Number was too long
2320 My Phone 7110; NSE-5; SW 04.84 */
2321 switch( MessageBuffer[10] ) {
2322 case 0x3d: fprintf(stdout, _("Error: Wrong Entry Type.\n")); break;
2323 case 0x3e: fprintf(stdout, _("Error: Too much entries.\n")); break;
2324 default : fprintf(stdout, _("Error: Unknown error (%u).\n"), MessageBuffer[10]); break;
2327 CurrentPhonebookError = GE_NONE;
2330 fprintf(stdout, _("Message: Phonebook written correctly.\n"));
2333 CurrentPhonebookError = GE_NONE;
2337 int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block)
2340 fprintf(stdout,_("Adding block id:%i,number:%i,length:%i\n"),id,no+1,size+6);
2346 *(block++) = size + 6;
2347 *(block++) = no + 1;
2349 memcpy(block, buf, size);
2357 int N7110_EncodePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block2)
2359 int count=0, len, i, block=0;
2364 len = strlen(entry.Name);
2365 string[0] = len * 2; // Length ot the string (without Termination)
2366 EncodeUnicode((string + 1), entry.Name, len);
2367 string[len * 2 + 1] = 0; // Terminating 0
2368 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, len * 2 + 2, block++, string, req + count);
2370 if (*entry.Number) {
2371 len = strlen(entry.Number);
2372 string[0] = N7110_ENTRYTYPE_NUMBER;
2373 string[1] = string[2] = string[3] = 0;
2374 string[4] = len * 2; // length (without Termination)
2375 EncodeUnicode((string + 5), entry.Number, len);
2376 string[len * 2 + 5] = 0; // Terminating 0
2377 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, block++, string, req + count);
2380 /* Rest of the subentries */
2381 for (i = 0; i < entry.SubEntriesCount; i++) {
2382 len = strlen(entry.SubEntries[i].data.Number);
2383 if (entry.SubEntries[i].EntryType != GSM_Number) {
2384 string[0] = len * 2; // length (without Termination)
2385 EncodeUnicode((string + 1), entry.SubEntries[i].data.Number, len);
2386 string[len * 2 + 1] = 0; // Terminating 0
2387 count += N7110_PackPBKBlock(entry.SubEntries[i].EntryType, len * 2 + 2, block++, string, req + count);
2389 string[0] = entry.SubEntries[i].NumberType;
2390 string[1] = string[2] = string[3] = 0;
2391 string[4] = len * 2; //length (without Termination)
2392 EncodeUnicode((string + 5), entry.SubEntries[i].data.Number, len);
2393 string[len * 2 + 5] = 0; // Terminating 0
2394 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, block++, string, req + count);
2398 if (entry.Group != 5) {
2400 string[0] = entry.Group + 1;
2402 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2410 /* Routine to write phonebook location in phone. */
2411 GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
2413 unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2414 0x00, 0x00, /* memory type */
2415 0x00, 0x00, /* location */
2417 int count = 18, blocks;
2419 if (entry->Name[0] != '\0' || entry->Number[0] != '\0') {
2420 req[11] = N7110_GetMemoryType(entry->MemoryType);
2421 req[12] = (entry->Location >> 8);
2422 req[13] = entry->Location & 0xff;
2424 // if (entry->MemoryType == GMT_SM) entry->SubEntriesCount = 0;
2426 count=count+N7110_EncodePhonebookFrame(req+18, *entry, &blocks);
2431 fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name);
2434 return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req);
2438 /* empty name & number => we have to delete the phonebook record! */
2439 return N7110_DeletePhonebookLocation( entry );
2444 void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2447 fprintf(stdout, _("Message: Phonebook entry deleted correctly\n"));
2449 CurrentPhonebookError = GE_NONE;
2452 /* delete phonebookentry */
2453 /* Not used in this moment */
2454 GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry)
2456 unsigned char req[256] = {
2457 N7110_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04,
2458 0x00, 0x00, 0x0c, 0x01, 0xff,
2459 0x00, /* location low*/
2460 0x01, /* location high*/
2461 0x05, /* mem location low*/
2462 0x00, /* mem location high*/
2466 req[12] = (entry->Location >> 8);
2467 req[13] = entry->Location & 0xff;
2468 req[14] = N7110_GetMemoryType(entry->MemoryType);
2471 fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location);
2474 return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req);
2477 /* for saving group logos only */
2478 GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap)
2480 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2481 0x00, 0x10, /* memory type */
2482 0x00, 0x00, /* location */
2486 unsigned int count = 18;
2488 req[13] = bitmap->number + 1;
2491 string[0] = bitmap->enabled?1:0;
2493 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count);
2496 string[0] = bitmap->ringtone;
2498 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count);
2500 /* Number of group */
2501 string[0] = bitmap->number+1;
2503 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2506 if (*bitmap->text) {
2507 i = strlen(bitmap->text);
2508 string[0] = i * 2 + 2;
2509 EncodeUnicode((string + 1), bitmap->text, i);
2510 string[i * 2 + 1] = 0; // Terminating 0
2511 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 2, block++, string, req + count);
2515 string[0] = bitmap->width;
2516 string[1] = bitmap->height;
2519 string[4] = bitmap->size;
2520 memcpy(string + 5, bitmap->bitmap, bitmap->size);
2521 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUPLOGO, bitmap->size + 5, block++, string, req + count);
2523 req[17] = block; //number of blocks
2525 return NULL_SendMessageSequence
2526 (50, &CurrentPhonebookError, count, 0x03, req);
2529 GSM_Error N7110_GetSpeedDial(GSM_SpeedDial *entry)
2531 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2534 0x00, 0x00, //location
2537 GSM_PhonebookEntry entry2;
2540 CurrentPhonebookEntry = &entry2;
2542 CurrentSpeedDialEntry = entry;
2544 req[9] = N7110_MEMORY_SD;
2545 req[10] = (entry->Number>>8);
2546 req[11] = entry->Number & 0xff;
2548 error=NULL_SendMessageSequence
2549 (50, &CurrentSpeedDialError, 14, 0x03, req);
2551 /* Full compatibility with 6110 */
2552 if (error==GE_INVALIDSPEEDDIALLOCATION) {
2554 entry->MemoryType=GMT_MT;
2556 } else return error;
2559 /* Experimental ! */
2560 GSM_Error N7110_SetSpeedDial(GSM_SpeedDial *entry)
2562 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2563 0x00, 0x0e, /* memory type */
2564 0x00, 0x00, /* location */
2568 unsigned int count = 18;
2570 req[13] = entry->Number;
2573 string[1]= entry->Location/256;
2574 string[2]= entry->Location%256;
2576 string[4]= string[5] = 0;
2577 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_SPEEDDIAL, 6, block++, string, req + count);
2579 req[17] = block - 1; //number of blocks
2581 return NULL_SendMessageSequence
2582 (50, &CurrentPhonebookError, count, 0x03, req);
2585 /* Set a bitmap or welcome-note */
2586 GSM_Error N7110_SetBitmap(GSM_Bitmap *Bitmap)
2588 unsigned char reqStartup[1000] = { N7110_FRAME_HEADER,
2589 0xec, 0x15, // Startup Logo
2590 0x00, 0x00, 0x00, 0x04,
2592 0x00, // Bitmap height
2594 0x00, // Bitmap width
2595 0xc0, 0x04, 0x03, 0x00
2596 }; // Bitmap following
2597 unsigned char reqOp[1000] = { N7110_FRAME_HEADER,
2599 0x00, // logo disabled
2600 0x00, 0xf0, 0x00, // network code (000 00)
2602 0x08, // length of rest
2603 0x00, 0x00, // Bitmap width / height
2605 0x00, // Bitmap size
2607 }; // Bitmap following
2609 /* Picture Images */
2610 unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2611 unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2612 unsigned char req4[500] = { N6110_FRAME_HEADER, 0x50, 0x07,
2617 unsigned char req5[120] = {0x00, 0x01, 0x01, 0xec, 0x02,0x00};
2619 unsigned char req6[]= {0x00,0x01,0x00,0xaf,0x00};
2627 CurrentSetBitmapError=GE_BUSY;
2629 switch (Bitmap->type) {
2630 case GSM_WelcomeNoteText:
2632 EncodeUnicode (req5+5, Bitmap->text, strlen(Bitmap->text));
2633 count=5+strlen(Bitmap->text)*2;
2636 Protocol->SendMessage(count, 0x7a, req5);
2639 case GSM_DealerNoteText:
2640 CurrentSetBitmapError = GE_NOTIMPLEMENTED;
2643 case GSM_StartupLogo:
2644 case GSM_7110StartupLogo:
2645 case GSM_6210StartupLogo:
2646 reqStartup[12] = Bitmap->height;
2647 reqStartup[16] = Bitmap->width;
2649 memcpy(reqStartup+count,Bitmap->bitmap,Bitmap->size);
2650 Protocol->SendMessage(count+Bitmap->size, 0x7a, reqStartup);
2653 case GSM_OperatorLogo:
2654 case GSM_7110OperatorLogo:
2658 if (strcmp(Bitmap->netcode,"000 00")) {
2659 reqOp[5] = 0x01; // Logo enabled
2660 EncodeNetworkCode(reqOp+6, Bitmap->netcode);
2661 reqOp[11] = 8+GSM_GetBitmapSize(Bitmap);
2662 reqOp[12]=Bitmap->width;
2663 reqOp[13]=Bitmap->height;
2664 reqOp[15]=GSM_GetBitmapSize(Bitmap);
2665 memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size);
2666 count += Bitmap->size;
2670 error=NULL_SendMessageSequence
2671 (50, &CurrentSetBitmapError, 5, 0x0a, req6);
2672 if (error!=GE_NONE) return error;
2675 Protocol->SendMessage(count, 0x0a, reqOp);
2678 case GSM_CallerLogo:
2679 CurrentSetBitmapError = N7110_WriteGroupDataLocation(Bitmap);
2682 case GSM_PictureImage:
2683 CurrentGetBitmap=Bitmap;
2687 req2[4]=req3[count];
2688 PictureImageLoc=req3[count];
2690 if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE) break;
2691 if (PictureImageNum==Bitmap->number+1) break;
2693 if (PictureImageNum!=Bitmap->number+1) {
2698 req4[5]=PictureImageLoc;
2699 req4[6]=PictureImageIndex/256;
2700 req4[7]=PictureImageIndex%256;
2704 for (i=0;i<36;i++) req4[i+9]=0;
2707 if (strlen(Bitmap->text)==0) {
2708 count+=2 ;req4[count]=0x0c;
2709 count+=2 ;req4[count]=0x0d;
2710 count+=2 ;req4[count]=0x0e;
2711 count+=2 ;req4[count]=0x0f;
2712 count+=2 ;req4[count]=0x10;
2713 count+=2 ;req4[count]=0x11;
2714 count+=23;req4[count]=0x02;
2715 count++ ;req4[count]=0x01;
2718 count+=2 ;req4[count]=0x54;
2719 count++ ;req4[count]=0xd4;
2720 count++ ;req4[count]=0x0d;
2721 count+=2 ;req4[count]=0x0e;
2722 count+=2 ;req4[count]=0x0f;
2723 count+=2 ;req4[count]=0x10;
2724 count+=2 ;req4[count]=0x11;
2725 count+=21;req4[count]=0x01;
2726 count+=3 ;req4[count]=0x01;
2731 req4[count++]=Bitmap->width;
2732 req4[count++]=Bitmap->height;
2733 req4[count++]=Bitmap->size/256;
2734 req4[count++]=Bitmap->size%256;
2735 memcpy(req4+count,Bitmap->bitmap,Bitmap->size);
2736 count += Bitmap->size;
2738 if (strlen(Bitmap->text)!=0) {
2739 req4[count] = strlen(Bitmap->text);
2740 GSM_PackSevenBitsToEight(0, Bitmap->text, req4+count+1);
2741 count=count+req4[count];
2747 CurrentSetBitmapError = GE_BUSY;
2749 Protocol->SendMessage(count, 0x14, req4);
2755 /* Wait for timeout or other error. */
2756 while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
2759 return (GE_TIMEOUT);
2764 if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo)
2765 && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) {
2766 return N6110_Reset(0x03);
2769 return CurrentSetBitmapError;
2772 /* Get a bitmap from the phone */
2773 GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap)
2775 unsigned char req[10] = { N6110_FRAME_HEADER };
2777 /* Picture Images */
2778 unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2779 unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2780 unsigned char req4[9] = { N6110_FRAME_HEADER, 0x07,
2786 unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02};
2790 GSM_PhonebookEntry entry;
2792 CurrentGetBitmapError = GE_BUSY;
2794 CurrentGetBitmap=Bitmap;
2796 switch (CurrentGetBitmap->type) {
2797 case GSM_StartupLogo:
2798 case GSM_7110StartupLogo:
2799 case GSM_6210StartupLogo:
2800 req[count-1]=0x01; /* change FRAME_HEADER */
2801 req[count++]=0xee; /* to get 0x01ee */
2803 Protocol->SendMessage(count, 0x7a, req);
2806 case GSM_WelcomeNoteText:
2808 Protocol->SendMessage(5, 0x7a, req5);
2811 case GSM_DealerNoteText:
2813 return GE_NOTIMPLEMENTED;
2815 case GSM_OperatorLogo:
2816 case GSM_7110OperatorLogo:
2817 req[count++]=0x70; /* NetworkStatus */
2818 Protocol->SendMessage(count, 0x0a, req);
2821 case GSM_CallerLogo:
2822 entry.MemoryType = GMT_CG;
2823 entry.Location = Bitmap->number+1;
2825 Bitmap->ringtone=0xFF;
2826 Bitmap->enabled=true;
2827 CurrentGetBitmapError = N7110_GetMemoryLocation(&entry);
2828 CurrentGetBitmap=NULL;
2829 if (entry.Location!=Bitmap->number+1) return GE_UNKNOWN;
2830 if (!strcmp(Bitmap->text,"")) {
2831 switch(Bitmap->number) {
2832 case 0:strcpy(Bitmap->text,"Family\0");break;
2833 case 1:strcpy(Bitmap->text,"VIP\0");break;
2834 case 2:strcpy(Bitmap->text,"Friends\0");break;
2835 case 3:strcpy(Bitmap->text,"Colleagues\0");break;
2836 case 4:strcpy(Bitmap->text,"Other\0");break;
2841 case GSM_PictureImage:
2846 req2[4]=req3[count];
2847 PictureImageLoc=req3[count];
2849 if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE)
2850 return CurrentGetBitmapError;
2851 if (PictureImageNum==Bitmap->number+1) break;
2853 if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError;
2855 req4[4]=PictureImageLoc;
2856 req4[5]=PictureImageIndex/256;
2857 req4[6]=PictureImageIndex%256;
2859 CurrentGetBitmapError = GE_BUSY;
2861 Protocol->SendMessage(9, 0x14, req4);
2866 return GE_NOTSUPPORTED;
2871 while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) {
2874 return (GE_TIMEOUT);
2879 CurrentGetBitmap=NULL;
2881 return (CurrentGetBitmapError);
2884 int ReturnBinRingLocation()
2888 while (GSM->GetModel(model) != GE_NONE) sleep(1);
2890 if (strcmp(model,"NSE-5") == 0) return 0x74; //first 0x74 //7110
2891 if (strcmp(model,"NPE-3") == 0) return 0x89; //first is 0x89; //6210
2892 if (strcmp(model,"NHM-3") == 0) return 0x89; //quess for 6250
2898 this works only for 6210, the 7110 needs upload to a location ?
2900 GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
2903 /* Buffer for preview uploading */
2904 unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D,
2905 0x00, 0x00, 0x00, 0x00,
2909 int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
2911 GSM_NetworkInfo NetworkInfo;
2913 char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
2915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2917 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2920 0x00, 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2923 /* Info from Till Toenshoff [till@uni.de]
2925 One improvement - for looping you can use an alternative header
2927 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2930 0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01
2938 char tail[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
2939 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
2940 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B // 20 Bytes tail
2943 //{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" };
2944 char N7110_notes[14] =
2945 { 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10 , 11, 11 };
2947 int current = 6, i, note, lastnote = 0, duration;
2949 /* Preview uploading */
2950 if (ringtone->location==255) {
2951 *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size);
2953 Protocol->SendMessage(size+11, 0x00, buffer);
2954 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
2956 return GE_NONE; //no answer from phone
2959 req[5]=ReturnBinRingLocation()+ringtone->location;
2961 EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name));
2965 for (i=0; i<ringtone->NrNotes; i++) {
2967 if (ringtone->notes[i].note == 255)
2970 note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14];
2972 duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256; // in 8 ms ticks of 7110
2974 switch (ringtone->notes[i].style) {
2977 req[current++] = note; // note only for one tick
2981 note = 0x40; // rest pause
2983 if (note != 0x40 && duration) {
2984 req[current++] = 0x40;
2985 req[current++] = 1; // small pause between notes
2989 if (note != 0x40 && note == lastnote && duration) {
2990 req[current++] = 0x40;
2991 req[current++] = 1; // small pause between same notes
2995 while (duration > 125) {
2996 req[current++] = note;
2997 req[current++] = 125;
3000 req[current++] = note;
3001 req[current++] = duration;
3006 for (i = 0; i < sizeof(tail); i++)
3007 req[current++] = tail[i];
3009 Protocol->SendMessage(current, 0x1F, req);
3013 return GE_NONE; //no answer from phone
3016 void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3020 switch (MessageBuffer[3]) {
3025 while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) {
3030 DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp);
3033 fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name);
3036 CurrentGetBinRingtone->frame[0]=0x00;
3037 CurrentGetBinRingtone->frame[1]=0x00;
3038 CurrentGetBinRingtone->frame[2]=0x0c;
3039 CurrentGetBinRingtone->frame[3]=0x01;
3040 CurrentGetBinRingtone->frame[4]=0x2c;
3042 memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name));
3044 CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name);
3046 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3047 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3049 /* Looking for end */
3052 if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
3055 if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
3059 if (i==MessageLength) break;
3063 memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37);
3064 CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37;
3066 CurrentBinRingtoneError=GE_NONE;
3072 fprintf(stdout, _("Message: Received empty ringtone\n"));
3075 CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;
3080 GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone)
3083 unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 };
3087 req[5]=ReturnBinRingLocation()+ringtone->location;
3089 CurrentGetBinRingtone=ringtone;
3091 return NULL_SendMessageSequence
3092 (50, &CurrentBinRingtoneError, 6, 0x1f, req);
3096 GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone)
3098 unsigned char req[1000] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 };
3100 GSM_NetworkInfo NetworkInfo;
3106 req[5]=ReturnBinRingLocation()+ringtone->location;
3108 for (i=6;i<35;i++) req[i]=0x00;
3112 EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5));
3116 while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++;
3118 memcpy(req+35,ringtone->frame+i,ringtone->length-i);
3120 Protocol->SendMessage(35+ringtone->length-i, 0x1f, req);
3122 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
3124 return GE_NONE; //no answer from phone
3127 void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3129 GSM_SMSMessage NullSMS;
3132 fprintf(stdout,_("Message: Incoming SMS\n"));
3135 GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5);
3138 fprintf(stdout, _("\n"));
3142 void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3150 GSM_NetworkInfo NullNetworkInfo;
3152 switch (MessageBuffer[3]) {
3157 fprintf(stdout, _("Message: Clearing operator logo msg\n"));
3159 CurrentSetBitmapError=GE_NONE;
3164 /* Make sure we are expecting NetworkInfo frame */
3165 if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) ||
3166 (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) {
3168 fprintf(stdout, _("Message: Network informations and operator logo:\n"));
3172 fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
3176 sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
3178 sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
3180 sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
3183 fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID);
3184 fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC);
3185 fprintf(stdout, _(" Network code: %s\n"), NullNetworkInfo.NetworkCode);
3186 fprintf(stdout, _(" Network name for gnokii: %s (%s)\n"),
3187 GSM_GetNetworkName(NullNetworkInfo.NetworkCode),
3188 GSM_GetCountryName(NullNetworkInfo.NetworkCode));
3190 DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]);
3191 fprintf(stdout, _(" Network name for phone: %s\n"),name);
3193 fprintf(stdout, _(" Status: "));
3194 switch (MessageBuffer[8]) {
3195 case 0x01: fprintf(stdout, _("home network selected")); break;
3196 case 0x02: fprintf(stdout, _("roaming network")); break;
3197 case 0x03: fprintf(stdout, _("requesting network")); break;
3198 case 0x04: fprintf(stdout, _("not registered in the network")); break;
3199 default: fprintf(stdout, _("unknown"));
3202 fprintf(stdout, "\n");
3204 fprintf(stdout, _(" Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
3207 /* Make sure we are expecting NetworkInfo frame */
3208 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
3209 *CurrentNetworkInfo=NullNetworkInfo;
3210 CurrentNetworkInfoError = GE_NONE;
3213 /* Make sure we are expecting an operator logo */
3214 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3216 strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode);
3219 if (MessageBuffer[4] == 0x02)
3220 fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),
3221 CurrentGetBitmap->netcode,
3222 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3224 fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"),
3225 CurrentGetBitmap->netcode,
3226 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3229 CurrentGetBitmap->type=GSM_7110OperatorLogo;
3230 if (MessageBuffer[4] == 0x02) { /* logo present */
3232 count += MessageBuffer[count]; /* skip network info */
3234 CurrentGetBitmap->width=MessageBuffer[count++]; /* 78 */
3235 CurrentGetBitmap->height=MessageBuffer[count++]; /* 21 */
3237 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3238 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
3240 CurrentGetBitmap->width=78;
3241 CurrentGetBitmap->height=21;
3242 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3243 memset(CurrentGetBitmap->bitmap,0,CurrentGetBitmap->size);
3245 CurrentGetBitmapError=GE_NONE;
3252 fprintf(stdout, _("Message: Network Level received:\n"));
3254 fprintf(stdout, _(" Network Level: %d\n"), MessageBuffer[4]);
3257 CurrentRFLevel=MessageBuffer[4];
3263 fprintf(stdout, _("Message: Operator logo set correctly.\n"));
3265 CurrentSetBitmapError = GE_NONE;
3270 fprintf(stdout, _("Message: Unknown message of type 0x0a\n"));
3272 AppendLogText("Unknown msg\n",false);
3273 break; /* Visual C Don't like empty cases */
3277 void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3280 GSM_ETSISMSMessage ETSI;
3282 switch (MessageBuffer[3]) {
3284 /* We have requested invalid or empty location. */
3288 fprintf(stdout, _("Message: SMS reading failed\n"));
3291 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3292 CurrentGetBitmapError=GE_UNKNOWN;
3295 /* getsms or picture image */
3298 if (MessageBuffer[8]==0x07) {
3300 if (CurrentGetBitmap!=NULL) {
3302 for (i=0;i<MessageBuffer[9]+1;i++)
3303 ETSI.SMSCNumber[i]=MessageBuffer[i+9];
3305 for (i=0;i<((MessageBuffer[22]+1)/2+1)+1;i++)
3306 ETSI.Number[i]=MessageBuffer[22+i];
3309 fprintf(stdout, _("Message: Picture Image received\n"));
3310 fprintf(stdout, _(" SMS center number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.SMSCNumber,false));
3311 fprintf(stdout, _(" Sender number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3314 strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3316 CurrentGetBitmap->width=MessageBuffer[47];
3317 CurrentGetBitmap->height=MessageBuffer[48];
3318 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap);
3320 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size);
3322 tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size,
3323 CurrentGetBitmap->text);
3325 CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0;
3327 CurrentGetBitmapError=GE_NONE;
3331 fprintf(stdout, _("Message: Picture Image received, but not reqested\n"));
3334 CurrentSMSMessageError = GE_SMSTOOLONG;
3340 /* status in byte 4 */
3341 CurrentSMSMessage->Status = MessageBuffer[4];
3343 CurrentSMSMessage->Type = GST_SMS;
3344 if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR;
3346 CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location;
3348 /* RTH FIXME: old folder stuff for xgnokii */
3349 CurrentSMSMessage->folder = (MessageBuffer[5] / 8)-1;
3350 /* if unreadMessage from folder 0, set INBOX folder */
3351 if (CurrentSMSMessage->folder==-1) CurrentSMSMessage->folder = 0;
3353 fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n")
3354 ,CurrentSMSMessage->Type, CurrentSMSMessage->folder, MessageBuffer[7]);
3357 GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9);
3359 /* Signal no error to calling code. */
3360 CurrentSMSMessageError = GE_NONE;
3365 fprintf(stdout, _("Message: Picture Image saved OK\n"));
3366 fprintf(stdout, _(" folder : %02x\n"),MessageBuffer[4]);
3367 fprintf(stdout, _(" location: %02x\n"),MessageBuffer[5]*256+MessageBuffer[6]);
3369 CurrentSetBitmapError=GE_NONE;
3375 fprintf(stdout, _("Message: Received index for Picture Images\n"));
3378 for (i=1;i<MessageBuffer[4]*256+MessageBuffer[5]+1;i++) {
3380 if (PictureImageNum==CurrentGetBitmap->number+1) {
3381 PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2];
3386 CurrentGetBitmapError=GE_NONE;
3387 CurrentSetBitmapError=GE_NONE;
3394 fprintf(stdout, _("Message: Unknown message of type 14\n"));
3396 AppendLogText("Unknown msg\n",false);
3397 break; /* Visual C Don't like empty cases */
3401 void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3403 switch (MessageBuffer[3]) {
3408 fprintf(stdout, _("Message: Battery status received:\n"));
3410 fprintf(stdout, _(" Battery Level: %d\n"), MessageBuffer[5]);
3413 CurrentBatteryLevel=MessageBuffer[5];
3419 fprintf(stdout, _("Message: Unknown message of type 0x17\n"));
3421 AppendLogText("Unknown msg\n",false);
3422 break; /* Visual C Don't like empty cases */
3426 void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3430 switch (MessageBuffer[3]) {
3432 /* Setting setting request */
3435 switch (MessageBuffer[4]) {
3439 fprintf(stdout, _("Message: Startup text set correctly.\n"));
3441 CurrentSetBitmapError = GE_NONE;
3446 fprintf(stdout, _("Message: Startup logo set correctly.\n"));
3448 CurrentSetBitmapError = GE_NONE;
3454 /* Setting received */
3457 switch (MessageBuffer[4]) {
3461 fprintf(stdout, _("Message: Startup text received.\n"));
3465 while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) {
3470 DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp);
3473 fprintf(stdout, _(" Text: \"%s\"\n"),CurrentGetBitmap->text);
3476 CurrentGetBitmapError = GE_NONE;
3481 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
3482 fprintf(stdout, _("Message: Startup logo received.\n"));
3484 fprintf(stdout, _("Message: Startup logo not requested, but received.\n"));
3487 /* Make sure we are expecting a startup logo */
3488 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3489 CurrentGetBitmap->height=MessageBuffer[13]; /* 96 */
3490 CurrentGetBitmap->width=MessageBuffer[17]; /* 60/65 */
3491 CurrentGetBitmap->type=GSM_7110StartupLogo;
3492 if (CurrentGetBitmap->width==60) CurrentGetBitmap->type=GSM_6210StartupLogo;
3493 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* unpacked size */
3494 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
3495 CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap);
3496 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+22,CurrentGetBitmap->size);
3497 CurrentGetBitmapError=GE_NONE;
3502 fprintf(stdout, _("Message: security code \""));
3504 for (i=6;i<11;i++) {
3505 fprintf(stdout, _("%c"),MessageBuffer[i]);
3508 fprintf(stdout,_("\"received.\n"));
3510 strncpy(CurrentSecurityCode->Code,MessageBuffer+6,6);
3512 CurrentSecurityCodeError=GE_NONE;
3519 fprintf(stdout, _("Unknown message of type 0x7a.\n"));
3521 AppendLogText("Unknown msg\n",false);
3522 break; /* Visual C Don't like empty cases */
3526 void N7110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3530 /* Switch on the basis of the message type byte */
3531 switch (MessageType) {
3533 /* Call information */
3534 /* Note, we use N6110_Dispatch0x40Message, but only some of 0x01
3535 old msg are available in new phones - other returns generally only
3539 N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);
3544 switch (MessageBuffer[3]) {
3546 case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;
3548 case 0x0f:N7110_ReplyEnableIncomingSMSInfo(MessageLength,MessageBuffer,MessageType);break;
3549 case 0x11:N7110_ReplyIncomingSMS (MessageLength,MessageBuffer,MessageType);break;
3550 case 0x21:N6110_ReplySetCellBroadcast (MessageLength, MessageBuffer, MessageType);break;
3551 case 0x23:N6110_ReplyReadCellBroadcast (MessageLength, MessageBuffer, MessageType);break;
3552 case 0x31:N6110_ReplySetSMSCenter (MessageLength,MessageBuffer,MessageType);break;
3554 case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
3555 default :unknown=true;break;
3559 /* Phonebook and speed dials */
3561 switch (MessageBuffer[3]) {
3562 case 0x04:N7110_ReplyGetMemoryStatus (MessageLength,MessageBuffer,MessageType);break;
3563 case 0x08:N7110_ReplyGetMemoryLocation (MessageLength,MessageBuffer,MessageType);break;
3564 case 0x10:N7110_ReplyDeletePhonebookLocation(MessageLength,MessageBuffer,MessageType);break;
3565 case 0x0C:N7110_ReplyWritePhonebookLocation (MessageLength,MessageBuffer,MessageType);break;
3566 default :unknown=true;break;
3570 /* This is call forwarding stuff */
3572 switch (MessageBuffer[3]) {
3574 case 0x03:N6110_ReplyCallDivert (MessageLength,MessageBuffer,MessageType);break;
3575 default :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;
3579 /* Network and operator logo */
3582 N7110_Dispatch0x0AMessage(MessageLength, MessageBuffer, MessageType);
3585 /* Calendar notes handling */
3587 switch (MessageBuffer[3]) {
3591 case 0x08:N7110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3592 case 0x0c:N7110_ReplyDeleteCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3593 case 0x1A:N7110_ReplyGetCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3594 case 0x32:N7110_ReplyFirstCalendarFreePos(MessageLength,MessageBuffer,MessageType);break;
3595 case 0x3b:N7110_ReplyGetCalendarNotesInfo(MessageLength,MessageBuffer,MessageType);break;
3596 default :unknown=true;break;
3602 switch (MessageBuffer[3]) {
3604 case 0x06:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3605 case 0x0b:N7110_ReplyDeleteSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3607 case 0x38:N7110_ReplyGetSMSStatus (MessageLength,MessageBuffer,MessageType);break;
3608 case 0x6C:N7110_ReplyGetSMSFolderStatus(MessageLength,MessageBuffer,MessageType);break;
3609 case 0x7B:N7110_ReplyGetSMSFolders (MessageLength,MessageBuffer,MessageType);break;
3610 case 0x84:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3611 default :N7110_Dispatch0x14Message (MessageLength, MessageBuffer, MessageType);break;
3615 /* Battery status */
3618 N7110_Dispatch0x17Message(MessageLength, MessageBuffer, MessageType);
3623 switch (MessageBuffer[3]) {
3624 case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break;
3625 case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break;
3626 case 0x6c:N6110_ReplySetAlarm (MessageLength,MessageBuffer,MessageType);break;
3627 case 0x6e:N6110_ReplyGetAlarm (MessageLength,MessageBuffer,MessageType);break;
3628 default :unknown=true;break;
3634 switch (MessageBuffer[3]) {
3636 case 0x24:N7110_ReplyGetBinRingtone(MessageLength,MessageBuffer,MessageType);break;
3637 default :unknown=true;break;
3644 N7110_ReplyGetProfile(MessageLength, MessageBuffer, MessageType);
3649 switch (MessageBuffer[3]) {
3651 case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;
3653 case 0x08:N7110_ReplyGetWAPBookmark (MessageLength,MessageBuffer,MessageType);break;
3655 case 0x0b:N7110_ReplySetWAPBookmark (MessageLength,MessageBuffer,MessageType);break;
3658 case 0x1c:N7110_ReplyGetWAPSettings (MessageLength,MessageBuffer,MessageType);break;
3659 default :unknown=true;break;
3663 /* Internal phone functions ? */
3664 /* Note, we use N6110_Dispatch0x40Message, but only some of 0x40
3665 old msg are available in new phones - other returns generally only
3668 switch (MessageBuffer[2]) {
3669 case 0x64:N6110_ReplyEnableExtendedCommands (MessageLength,MessageBuffer,MessageType);break;
3670 case 0x65:N6110_ReplyResetPhoneSettings (MessageLength,MessageBuffer,MessageType);break;
3671 case 0x66:N6110_ReplyIMEI (MessageLength,MessageBuffer,MessageType);break;
3672 case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3673 case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3674 case 0x7e:N6110_ReplyNetmonitor (MessageLength,MessageBuffer,MessageType);break;
3675 case 0x8a:N6110_ReplySimlockInfo (MessageLength,MessageBuffer,MessageType);break;
3676 case 0x8f:N6110_ReplyPlayTone (MessageLength,MessageBuffer,MessageType);break;
3677 case 0xc8:N6110_ReplyHW (MessageLength,MessageBuffer,MessageType);break;
3678 default :N6110_Dispatch0x40Message (MessageLength,MessageBuffer,MessageType);break;
3685 N7110_Dispatch0x7AMessage(MessageLength, MessageBuffer, MessageType);
3688 /***** Acknowlegment of our frames. *****/
3689 case FBUS_FRTYPE_ACK:
3691 N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);
3696 N6110_ReplyID(MessageLength, MessageBuffer, MessageType);
3699 /***** Unknown message *****/
3700 /* If you think that you know the exact meaning of other messages - please
3705 fprintf(stdout, _("Message: Unknown message type.\n"));
3707 AppendLogText("Unknown msg type\n",false);
3714 fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);
3716 AppendLogText("Unknown msg\n",false);