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 */
133 5, /* Max RF Level */
134 0, /* Min RF Level */
135 GRF_Arbitrary, /* RF level units */
136 5, /* Max Battery Level */
137 0, /* Min Battery Level */
138 GBU_Arbitrary, /* Battery level units */
139 GDT_DateTime, /* Have date/time support */
140 GDT_TimeOnly, /* Alarm supports time only */
141 1 /* Only one alarm available */
144 const char *N7110_MemoryType_String [] = {
157 int PictureImageNum; //required during reading Picture Images
158 int PictureImageIndex;
161 void N7110_ReplyEnableIncomingSMSInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
162 switch (MessageBuffer[3]) {
165 fprintf(stdout,_("Message: Enabled info for incoming SMS\n"));
168 CurrentMagicError=GE_NONE;
172 fprintf(stdout,_("Message: error enabling for incoming SMS\n"));
173 switch (MessageBuffer[4]) {
174 case 0x0c:fprintf(stdout,_(" No PIN\n"));break;
175 default :fprintf(stdout,_(" unknown\n"));break;
179 CurrentMagicError=GE_UNKNOWN;
184 GSM_Error N7110_EnableIncomingSMSInfo ()
186 unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
188 return NULL_SendMessageSequence
189 (50, &CurrentMagicError, 8, 0x02, req);
192 /* Initialise variables and state machine. */
193 GSM_Error N7110_Initialise(char *port_device, char *initlength,
194 GSM_ConnectionType connection,
195 void (*rlp_callback)(RLP_F96Frame *frame))
198 unsigned char init_char = N6110_SYNC_BYTE;
202 if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
204 return GE_NOTSUPPORTED;
207 if (connection!=GCT_MBUS && connection!=GCT_Irda) {
209 InitLength = atoi(initlength);
211 if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
212 InitLength = 250; /* This is the usual value, lower may work. */
216 fprintf(stdout,_("Writing init chars...."));
219 /* Initialise link with phone or what have you */
220 /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
222 for (count = 0; count < InitLength; count ++) {
224 Protocol->WritePhone(1,&init_char);
228 fprintf(stdout,_("Done\n"));
231 N6110_SendStatusRequest();
237 if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
239 if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;
241 if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;
243 // N7110_EnableIncomingSMSInfo();
245 if (connection==GCT_MBUS || connection==GCT_Irda) {
246 /* In MBUS doesn't have any init strings, etc. Phone answered with frame,
247 so connection should be enabled ;-) */
248 /* Similiar for Irda */
249 CurrentLinkOK = true;
252 CurrentSMSFoldersCount=1000;
253 CurrentSMSMessage=NULL;
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)
730 if (CurrentMemoryStatus && CurrentMemoryStatusError == GE_BUSY) {
731 /* first Loc. (MessageBuffer[10]<<8) + MessageBuffer[11]; */
732 CurrentMemoryStatus->Free = (MessageBuffer[14]<<8) + MessageBuffer[15];
733 CurrentMemoryStatus->Used = (MessageBuffer[16]<<8) + MessageBuffer[17];
734 CurrentMemoryStatus->Free -= CurrentMemoryStatus->Used;
736 CurrentMemoryStatusError = GE_NONE;
739 fprintf(stdout, _("Message: Memory status received:\n"));
741 fprintf(stdout, _(" Memory Type: %s\n"), N7110_MemoryType_String[MessageBuffer[5]]);
742 fprintf(stdout, _(" Used: %d\n"), CurrentMemoryStatus->Used);
743 fprintf(stdout, _(" Free: %d\n"), CurrentMemoryStatus->Free);
748 /* This function is used to get storage status from the phone. It currently
749 supports two different memory areas - internal and SIM. */
750 GSM_Error N7110_GetMemoryStatus(GSM_MemoryStatus *Status)
752 unsigned char req[] = { N6110_FRAME_HEADER,
753 0x03, /* MemoryStatus request */
755 0x05 /* MemoryType */
758 switch (Status->MemoryType) {
762 CurrentMemoryStatus = Status;
764 req[5] = N7110_GetMemoryType(Status->MemoryType);
766 return NULL_SendMessageSequence
767 (20, &CurrentMemoryStatusError, 6, 0x03, req);
778 return GE_NOTSUPPORTED;
782 void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
784 switch(MessageBuffer[3]) {
789 fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]);
792 switch (MessageBuffer[6]) {
793 case 0xff: /* Profile Name */
794 DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]);
796 fprintf(stdout,_(" Name \"%s\"\n"),CurrentProfile->Name);
801 case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */
802 switch( MessageBuffer[10] ) {
804 CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break;
808 CurrentProfile->KeypadTone = MessageBuffer[10]-1; break;
812 case 0x02: /* Call Alert type (Ringing, Ascending, ..., Off) */
813 /* I make it compatible with GetProfileCallAlertString */
814 switch( MessageBuffer[10] ) {
815 case 0: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGING; break;
816 case 1: CurrentProfile->CallAlert = PROFILE_CALLALERT_ASCENDING; break;
817 case 2: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGONCE; break;
818 case 3: CurrentProfile->CallAlert = PROFILE_CALLALERT_BEEPONCE; break;
819 case 5: CurrentProfile->CallAlert = PROFILE_CALLALERT_OFF; break;
822 case 0x03: /* Ringtone number */
823 CurrentProfile->Ringtone = MessageBuffer[10];
825 case 0x04: /* Ringtone volume (from level 1 to level 5) */
826 CurrentProfile->Volume = MessageBuffer[10] + 6;
828 case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */
829 CurrentProfile->MessageTone = MessageBuffer[10];
831 case 0x06: /* Vibration (On/Off) */
832 CurrentProfile->Vibration = MessageBuffer[10];
834 case 0x07: /* WarningTone (On/Off) */
835 switch( MessageBuffer[10] ) {
837 CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break;
839 CurrentProfile->WarningTone = PROFILE_WARNING_ON; break;
842 case 0x08: /* Alert for (caller groups) */
843 CurrentProfile->CallerGroups = MessageBuffer[10];
845 case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */
846 CurrentProfile->AutomaticAnswer = MessageBuffer[10];
850 CurrentProfileError=GE_NONE;
855 fprintf(stdout, _("Message: Unknown message of type 0x39\n"));
857 AppendLogText("Unknown msg\n",false);
858 break; /* Visual C Don't like empty cases */
863 GSM_Error N7110_GetProfile(GSM_Profile *Profile)
867 unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
868 0x00, //profile number
869 0xff}; //feature. Here 0xff=name
871 unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22,
876 CurrentProfile = Profile;
878 /* When after sending all frames feature==253, it means, that it is not
880 CurrentProfile->KeypadTone=253;
881 CurrentProfile->Lights=253;
882 CurrentProfile->CallAlert=253;
883 CurrentProfile->Ringtone=253;
884 CurrentProfile->Volume=253;
885 CurrentProfile->MessageTone=253;
886 CurrentProfile->WarningTone=253;
887 CurrentProfile->Vibration=253;
888 CurrentProfile->CallerGroups=253;
889 CurrentProfile->ScreenSaver=253;
890 CurrentProfile->AutomaticAnswer=253;
892 req[7] = Profile->Number+1;
894 error=NULL_SendMessageSequence
895 (20, &CurrentProfileError, 9, 0x39, req);
896 if (error!=GE_NONE) return error;
898 for (i = 0; i < 11; i++) {
900 req[7] = Profile->Number+1;
904 error=NULL_SendMessageSequence
905 (20, &CurrentProfileError, 9, 0x39, req);
906 if (error!=GE_NONE) return error;
912 void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
916 CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5];
917 CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany;
919 for(i=0;i<CurrentCalendarNotesInfo.HowMany && i<MAX_NOTES_INFO_ELEMS;i++) {
920 CurrentCalendarNotesInfo.Location[i] = MessageBuffer[8+i*2]*256+ MessageBuffer[8+i*2+1];
921 CurrentCalendarNotesInfo2->Location[i]=CurrentCalendarNotesInfo.Location[i];
924 CurrentCalendarNotesInfoError=GE_NONE;
927 GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo)
929 unsigned char req[] = { N6110_FRAME_HEADER,
930 0x3a, /* get notes info */
935 CurrentCalendarNotesInfo2=NotesInfo;
937 error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req);
942 void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2)
949 if (alarmdiff == 0xffff) fprintf(stdout," No alarm");
950 else fprintf(stdout," Alarm is %i seconds before date", alarmdiff*alarm2);
951 fprintf(stdout,"\n");
954 if (alarmdiff != 0xffff) {
956 memset(&tm_time, 0, sizeof(tm_time));
957 tm_time.tm_year = time->Year - 1900;
958 tm_time.tm_mon = time->Month - 1;
959 tm_time.tm_mday = time->Day;
960 tm_time.tm_hour = time->Hour;
961 tm_time.tm_min = time->Minute;
962 tm_time.tm_sec = time->Second;
965 t_alarm = mktime(&tm_time);
966 t_alarm -= alarmdiff*alarm2;
968 tm_alarm = localtime(&t_alarm);
970 alarm->Year = tm_alarm->tm_year + 1900;
971 alarm->Month = tm_alarm->tm_mon + 1;
972 alarm->Day = tm_alarm->tm_mday;
973 alarm->Hour = tm_alarm->tm_hour;
974 alarm->Minute = tm_alarm->tm_min;
975 alarm->Second = tm_alarm->tm_sec;
978 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
979 alarm->Day,alarm->Month,alarm->Year,
980 alarm->Hour,alarm->Minute,alarm->Second);
985 void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
989 c->Time.Year = block[8]*256+block[9];
990 c->Time.Month = block[10];
991 c->Time.Day = block[11];
992 if (c->Type != GCN_REMINDER) {
993 c->Time.Hour = block[12];
994 c->Time.Minute = block[13];
1002 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1003 c->Time.Day,c->Time.Month,c->Time.Year,
1004 c->Time.Hour,c->Time.Minute,c->Time.Second);
1007 if (c->Type != GCN_REMINDER) {
1008 alarmdiff = block[14]*256 + block[15];
1009 P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60);
1011 c->Recurrance = block[16]*256 + block[17];
1012 DecodeUnicode(c->Text, block+20, block[18]);
1014 c->Recurrance = block[12]*256 + block[13];
1015 DecodeUnicode(c->Text, block+16, block[14]);
1018 /* 0xffff -> 1 Year (8760 hours) */
1019 if (c->Recurrance == 0xffff) c->Recurrance=8760;
1022 fprintf(stdout, " Recurrance: %i hours\n Text: \"%s\"\n",
1023 c->Recurrance,c->Text);
1027 void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1031 CurrentCalendarNote->YearOfBirth=0; //for other than birthday
1032 CurrentCalendarNote->AlarmType=0x00;//for other than birthday
1033 CurrentCalendarNote->Phone[0]=0; //for other than call
1035 CurrentCalendarNote->Alarm.Year = 0;
1036 CurrentCalendarNote->Alarm.Month = 0;
1037 CurrentCalendarNote->Alarm.Day = 0;
1038 CurrentCalendarNote->Alarm.Hour = 0;
1039 CurrentCalendarNote->Alarm.Minute = 0;
1040 CurrentCalendarNote->Alarm.Second = 0;
1043 fprintf(stdout, "Message: calendar note received\n");
1046 switch (MessageBuffer[6]) /* entry type */ {
1047 case 0x01: /* Meeting */
1049 fprintf(stdout, " Note type: meeting\n");
1051 CurrentCalendarNote->Type = GCN_MEETING;
1052 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1053 CurrentCalendarNoteError=GE_NONE;
1056 case 0x02: /* Call */
1058 fprintf(stdout, " Note type: call\n");
1060 CurrentCalendarNote->Type = GCN_CALL;
1061 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1062 DecodeUnicode(CurrentCalendarNote->Phone,
1063 MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]);
1065 fprintf(stdout, " Phone number: \"%s\"\n",CurrentCalendarNote->Phone);
1067 CurrentCalendarNoteError=GE_NONE;
1070 case 0x04: /* Birthday */
1072 fprintf(stdout, " Note type: birthday\n");
1074 CurrentCalendarNote->Type = GCN_BIRTHDAY;
1076 alarm = ((unsigned int)MessageBuffer[14]) << 24;
1077 alarm += ((unsigned int)MessageBuffer[15]) << 16;
1078 alarm += ((unsigned int)MessageBuffer[16]) << 8;
1079 alarm += MessageBuffer[17];
1081 /* CurrentCalendarNote->Time.Year is set earlier */
1082 CurrentCalendarNote->Time.Month = MessageBuffer[10];
1083 CurrentCalendarNote->Time.Day = MessageBuffer[11];
1084 CurrentCalendarNote->Time.Hour = 23;
1085 CurrentCalendarNote->Time.Minute = 59;
1086 CurrentCalendarNote->Time.Second = 58;
1087 P7110_GetNoteAlarm(alarm, &(CurrentCalendarNote->Time), &(CurrentCalendarNote->Alarm) ,1);
1089 CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19];
1090 CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth;
1092 CurrentCalendarNote->AlarmType = MessageBuffer[20];
1095 fprintf(stdout,_(" Alarm type: %s\n"),
1096 (CurrentCalendarNote->AlarmType==0x00) ? "Tone " : "Silent");
1098 fprintf(stdout, " Birthday date: %02i-%02i-%04i (age %d)\n",CurrentCalendarNote->Time.Day,
1099 CurrentCalendarNote->Time.Month,CurrentCalendarNote->Time.Year,
1100 CurrentCalendarNote->Alarm.Year - CurrentCalendarNote->Time.Year);
1103 DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]);
1105 fprintf(stdout, " Text: \"%s\"\n",CurrentCalendarNote->Text);
1108 CurrentCalendarNote->Recurrance = 0;
1109 CurrentCalendarNoteError=GE_NONE;
1112 case 0x08: /* Reminder */
1114 fprintf(stdout, " Note type: reminder\n");
1116 CurrentCalendarNote->Type = GCN_REMINDER;
1117 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1118 CurrentCalendarNoteError=GE_NONE;
1121 default: /* unknown */
1123 fprintf(stdout, " Note type: UNKNOWN\n");
1129 GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
1131 unsigned char req[] = { N6110_FRAME_HEADER,
1132 0x19, /* get calendar note */
1133 0x00, 0x00 //location
1137 GSM_DateTime date_time;
1141 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1142 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1143 if (error!=GE_NONE) return error;
1147 fprintf(stdout, _("Calendar Notes Location Logical = %d.\n"),
1148 CalendarNote->Location);
1149 fprintf(stdout, _("Calendar Notes Location Phisical = %d.\n"),
1150 CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]);
1153 /* this is for making xgnokii work.. */
1154 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1155 return GE_INVALIDCALNOTELOCATION;
1157 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1158 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1159 CurrentCalendarNote = CalendarNote;
1161 /* We have to get current year. It's NOT written in frame for Birthday */
1162 error=N7110_GetDateTime(&date_time);
1163 if (error!=GE_NONE) return error;
1164 if (!date_time.IsSet) {
1166 now=localtime(&nowh);
1168 /* I have 100 (for 2000) Year now :-) */
1169 if (now->tm_year>99 && now->tm_year<1900) {
1170 now->tm_year=now->tm_year+1900;
1172 date_time.Year=now->tm_year;
1174 CurrentCalendarNote->Time.Year = date_time.Year;
1176 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1178 CurrentCalendarNote = NULL;
1183 void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1186 char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" };
1189 "Succesfully written Calendar Note Type %s on location %d\n",
1190 kz_types[(MessageBuffer[3]/2)-1],
1191 MessageBuffer[4]*256+MessageBuffer[5] );
1193 fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n",
1194 MessageBuffer[6]*256+MessageBuffer[7] );
1196 CurrentCalendarNoteError=GE_NONE;
1199 long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm)
1208 tm_alarm.tm_year=alarm->Year-1900;
1209 tm_alarm.tm_mon=alarm->Month-1;
1210 tm_alarm.tm_mday=alarm->Day;
1211 tm_alarm.tm_hour=alarm->Hour;
1212 tm_alarm.tm_min=alarm->Minute;
1213 tm_alarm.tm_sec=alarm->Second;
1214 tm_alarm.tm_isdst=0;
1215 t_alarm = mktime(&tm_alarm);
1217 tm_time.tm_year=time->Year-1900;
1218 tm_time.tm_mon=time->Month-1;
1219 tm_time.tm_mday=time->Day;
1220 tm_time.tm_hour=time->Hour;
1221 tm_time.tm_min=time->Minute;
1222 tm_time.tm_sec=time->Second;
1224 t_time = mktime(&tm_time);
1227 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
1228 alarm->Day,alarm->Month,alarm->Year,
1229 alarm->Hour,alarm->Minute,alarm->Second);
1230 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1231 time->Day,time->Month,time->Year,
1232 time->Hour,time->Minute,time->Second);
1233 fprintf(stdout,_("Difference in alarm time is %f\n"),difftime( t_time, t_alarm )+3600);
1236 return difftime( t_time ,t_alarm )+3600;
1239 GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
1241 unsigned char req[200] = { N6110_FRAME_HEADER,
1242 0x01, /* note type ... */
1243 0x00, 0x00, /* location */
1244 0x00, /* entry type */
1246 0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */
1247 /* here starts block */
1248 0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */
1252 long seconds, minutes;
1255 int firstFreeLocation;
1258 * 6210/7110 needs to seek the first free pos to inhabit with next note
1260 error=N7110_FirstCalendarFreePos(&firstFreeLocation);
1261 if (error!=GE_NONE) return error;
1264 fprintf(stdout, _("First free calendar location is = %d.\n"),
1272 switch( CalendarNote->Type ) {
1273 case GCN_MEETING : req[6]=0x01; req[3]=0x01; break;
1274 case GCN_CALL : req[6]=0x02; req[3]=0x03; break;
1275 case GCN_BIRTHDAY: req[6]=0x04; req[3]=0x05; break;
1276 case GCN_REMINDER: req[6]=0x08; req[3]=0x07; break;
1279 req[8]=CalendarNote->Time.Year>>8;
1280 req[9]=CalendarNote->Time.Year&0xff;
1281 req[10]=CalendarNote->Time.Month;
1282 req[11]=CalendarNote->Time.Day;
1284 /* From here starts BLOCK */
1286 switch( CalendarNote->Type ) {
1289 req[count++]=CalendarNote->Time.Hour; // 12
1290 req[count++]=CalendarNote->Time.Minute; // 13
1292 req[count++]=0xff; // 14
1293 req[count++]=0xff; // 15
1294 if( CalendarNote->Alarm.Year )
1296 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1297 &CalendarNote->Alarm);
1298 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1299 minutes=seconds/60L;
1301 req[count++]=minutes>>8;
1302 req[count++]=minutes&0xff;
1306 if( CalendarNote->Recurrance >= 8760 )
1307 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1308 req[count++]=CalendarNote->Recurrance>>8; // 16
1309 req[count++]=CalendarNote->Recurrance&0xff; // 17
1311 req[count++]=strlen(CalendarNote->Text); // 18
1313 req[count++]=0x00; // 19
1316 fprintf(stdout, "Count before encode = %d\n", count );
1317 fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text );
1320 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1321 count=count+2*strlen(CalendarNote->Text);
1325 req[count++]=CalendarNote->Time.Hour; // 12
1326 req[count++]=CalendarNote->Time.Minute; // 13
1328 req[count++]=0xff; // 14
1329 req[count++]=0xff; // 15
1330 if( CalendarNote->Alarm.Year )
1332 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1333 &CalendarNote->Alarm);
1334 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1335 minutes=seconds/60L;
1337 req[count++]=minutes>>8;
1338 req[count++]=minutes&0xff;
1342 if( CalendarNote->Recurrance >= 8760 )
1343 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1344 req[count++]=CalendarNote->Recurrance>>8; // 16
1345 req[count++]=CalendarNote->Recurrance&0xff; // 17
1347 req[count++]=strlen(CalendarNote->Text); // 18
1349 req[count++]=strlen(CalendarNote->Phone); // 19
1351 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1352 count=count+2*strlen(CalendarNote->Text);
1353 EncodeUnicode (req+count,CalendarNote->Phone ,strlen(CalendarNote->Phone));// (N+1)->n
1354 count=count+2*strlen(CalendarNote->Phone);
1358 req[count++]=0x00; // 12 Fixed
1359 req[count++]=0x00; // 13 Fixed
1362 req[count++]=0x00; req[count++]=0x00; // 14, 15
1363 req[count++]=0xff; // 16
1364 req[count++]=0xff; // 17
1365 if( CalendarNote->Alarm.Year ) {
1366 // I try with Time.Year = Alarm.Year. If negative, I increase 1 year,
1367 // but only once ! This thing, because I may have Alarm period across
1368 // a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27)
1370 CalendarNote->Time.Year = CalendarNote->Alarm.Year;
1371 if( (seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1372 &CalendarNote->Alarm)) < 0L ) {
1373 CalendarNote->Time.Year++;
1374 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1375 &CalendarNote->Alarm);
1377 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1379 req[count++]=seconds>>24; // 14
1380 req[count++]=(seconds>>16) & 0xff; // 15
1381 req[count++]=(seconds>>8) & 0xff; // 16
1382 req[count++]=seconds&0xff; // 17
1386 req[count++]=CalendarNote->AlarmType; // 18
1389 req[count++]=strlen(CalendarNote->Text); // 19
1393 fprintf(stdout, "Count before encode = %d\n", count );
1394 fprintf(stdout, "Meeting Text is = \"%s\" Altype is 0x%02x \n", CalendarNote->Text , CalendarNote->AlarmType );
1396 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N
1397 count=count+2*strlen(CalendarNote->Text);
1402 if( CalendarNote->Recurrance >= 8760 )
1403 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1404 req[count++]=CalendarNote->Recurrance>>8; // 12
1405 req[count++]=CalendarNote->Recurrance&0xff; // 13
1407 req[count++]=strlen(CalendarNote->Text); // 14
1409 req[count++]=0x00; // 15
1411 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N
1412 count=count+2*strlen(CalendarNote->Text);
1419 fprintf(stdout, "Count after padding = %d\n", count );
1422 CurrentCalendarNote = CalendarNote;
1424 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req);
1426 CurrentCalendarNote = NULL;
1431 void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1433 *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5];
1434 CurrentFirstCalendarFreePosError=GE_NONE;
1437 GSM_Error N7110_FirstCalendarFreePos(int *FreePos)
1439 unsigned char req[] = { N6110_FRAME_HEADER, 0x31 };
1443 CurrentFirstCalendarFreePos = FreePos;
1445 error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError,
1448 CurrentFirstCalendarFreePos = NULL;
1453 void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1457 "Succesfully Delete Calendar Note on location %d\n",
1458 MessageBuffer[4]*256+MessageBuffer[5] );
1460 fprintf(stdout, "--> Other data are :\n" );
1461 fprintf(stdout, " '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d)\n",
1462 MessageBuffer[6], MessageBuffer[6], MessageBuffer[6],
1463 MessageBuffer[7], MessageBuffer[7], MessageBuffer[7],
1464 MessageBuffer[8], MessageBuffer[8], MessageBuffer[8],
1465 MessageBuffer[9], MessageBuffer[9], MessageBuffer[9] );
1467 CurrentCalendarNoteError=GE_NONE;
1470 GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
1472 unsigned char req[] = { N6110_FRAME_HEADER,
1473 0x0b, /* delete calendar note */
1474 0x00, 0x00 //location
1479 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1480 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1481 if (error!=GE_NONE) return error;
1484 /* this is for making xgnokii work.. */
1485 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1486 return GE_INVALIDCALNOTELOCATION;
1488 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1489 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1491 CurrentCalendarNote = CalendarNote;
1493 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1495 CurrentCalendarNote = NULL;
1500 void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1507 fprintf(stdout, _("Message: SMS Folders received:\n"));
1512 CurrentSMSFoldersCount=MessageBuffer[4];
1514 for (j=0;j<MessageBuffer[4];j++) {
1515 strcpy(CurrentSMSFolders->Folder[j].Name," ");
1517 fprintf(stdout, _(" Folder Index: %d"),MessageBuffer[i]);
1519 CurrentSMSFolders->FoldersID[j]=MessageBuffer[i];
1524 fprintf(stdout, _(", folder name: "));
1527 while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) {
1529 wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8);
1531 CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc);
1533 fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]);
1539 fprintf(stdout, _("\n"));
1545 CurrentSMSFoldersError=GE_NONE;
1548 GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders)
1550 unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
1554 CurrentSMSFolders=folders;
1556 error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req);
1558 folders->number=CurrentSMSFoldersCount;
1563 void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1568 fprintf(stdout, _("Message: SMS Folder status received\n"));
1569 fprintf(stdout, _(" Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]);
1571 CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5];
1573 fprintf(stdout, _(" (indexes "));
1576 for (i=0;i<MessageBuffer[4]*256+MessageBuffer[5];i++) {
1578 fprintf(stdout, _("%i, "), MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7]);
1580 CurrentSMSFolder.locations[i]=MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7];
1584 fprintf(stdout, _(")\n"));
1587 CurrentSMSFolderError=GE_NONE;
1590 GSM_Error N7110_GetSMSFolderStatus ( GSM_OneSMSFolder *folder, u8 ID)
1592 unsigned char req[] = { N7110_FRAME_HEADER,
1600 CurrentSMSFolder = *folder;
1601 CurrentSMSFolderID = ID;
1604 error=NULL_SendMessageSequence(20, &CurrentSMSFolderError, 7, 0x14, req);
1606 *folder=CurrentSMSFolder;
1611 void N7110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1615 fprintf(stdout, _("Message: SMS deleted succesfully\n"));
1617 CurrentSMSMessageError = GE_NONE;
1620 GSM_Error N7110_DeleteSMSMessage(GSM_SMSMessage *message)
1622 unsigned char req[] = {
1623 N7110_FRAME_HEADER, 0x0a, /* delete SMS request */
1624 0x00, /* folder (req[4])*/
1625 0x00, /* location */
1626 0x00, /* location (req[6])*/
1630 int smsnum, location;
1633 smsnum = message->Location;
1634 /* We made "fake" SMS numbering for SMS in 7110/6210/etc. */
1635 if ((error = N7110_HandleSMSLocation(smsnum, &folderid, &location, NULL, GSH_DELETE))!=GE_NONE)
1639 req[5]=location / 256;
1643 printf("delete sms: folder %d, location %d\n",folderid,location);
1646 return NULL_SendMessageSequence
1647 (50, &CurrentSMSMessageError, 8, 0x14, req);
1650 GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message)
1653 unsigned char req[] = { N6110_FRAME_HEADER,
1656 0x00, 0x05, // location
1661 int smsnum, location;
1665 CurrentSMSMessage = message;
1666 CurrentSMSMessageError = GE_BUSY;
1669 smsnum = message->Location;
1671 /* we make central handling of real location */
1672 error = N7110_HandleSMSLocation(smsnum, &folderid, &location, message, GSH_GET);
1673 /* if smsnum is 0 (next sms) we need real smsnum */
1674 N7110_SMS2FakeLocation( &smsnum, folderid, location);
1675 message->Location = smsnum;
1678 case GE_SMSISINMEM: /* future use: get already reed sms from mem */
1681 case GE_NONE: req[4]=folderid;
1682 req[5]=location / 256;
1685 fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location);
1687 return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req);
1695 void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1699 switch (MessageBuffer[3]) {
1704 fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]);
1707 if (CurrentSMSMessage!=NULL) {
1708 N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]);
1709 CurrentSMSMessage->MessageNumber=smsnum;
1712 CurrentSMSMessageError = GE_NONE;
1715 /* save sms failed */
1719 fprintf(stdout, _("Message: SMS Message save failed\n"));
1721 CurrentSMSMessageError = GE_SMSSAVEFAILED;
1726 fprintf(stdout, _("Message: Changed name for SMS Message\n"));
1728 CurrentSMSMessageError = GE_NONE;
1734 GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS)
1736 unsigned char req[256] = {
1737 N6110_FRAME_HEADER, 0x04, /* SMS save request*/
1738 0x03, /* default: mark sms as GSS_NOTSENTREAD */
1739 0x10, /* folder (req[5])*/
1740 0x00, /* location */
1741 0x00, /* location (req[7])*/
1745 unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83};
1747 int length,smsnum,location;
1750 SMS_MessageType PDU;
1752 smsnum = SMS->Location;
1755 printf("save sms: smsnum is :%d\n",smsnum);
1758 if ( SMS->Status == GSS_SENTREAD) req[4] = 0x01;
1760 folderid = SMS->folder;
1764 error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU);
1765 if (error != GE_NONE) return error;
1767 CurrentSMSMessage = SMS;
1769 error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE);
1773 case GE_BUSYSMSLOCATION: /* delete old sms before save */
1774 error = N7110_DeleteSMSMessage(SMS);
1775 if (error != GE_NONE) return error;
1785 printf("save sms: want to save at folder:%d , location:%d\n",folderid,location);
1789 req[6]=location / 256;
1792 error=NULL_SendMessageSequence
1793 (70, &CurrentSMSMessageError, 40+length, 0x14, req);
1795 if (error==GE_NONE && SMS->Name[0]!=0) {
1797 N7110_Fake2SMSLocation(SMS->MessageNumber, &folderid, &location);
1798 req2[length++]=folderid;
1799 req2[length++]=location / 256;
1800 req2[length++]=location;
1801 EncodeUnicode(req2+length, SMS->Name, strlen(SMS->Name));
1802 length=length+strlen(SMS->Name)*2;
1805 error=NULL_SendMessageSequence
1806 (70, &CurrentSMSMessageError, length, 0x14, req2);
1812 /* handling for 7110 folders */
1813 GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action)
1816 static int nextSMSmessage = -1;
1817 static GSM_SMSStatus Status;
1821 GSM_OneSMSFolder onefolder;
1827 case GSH_DELETE: /* future use: delete sms in mem -> free memory */
1828 /* for now we make same as in GSH_GET */
1829 case GSH_GET: /* if smsnum == 0 user wants to read next sms */
1832 /* first time we read folderstatus */
1833 if ( nextSMSmessage == -1)
1836 error = N7110_GetSMSStatus( &Status);
1837 if (error!=GE_NONE) return error;
1839 ismsnum = Status.foldertable[nextSMSmessage].smsnum;
1840 N7110_Fake2SMSLocation( ismsnum, folder, location);
1842 if(nextSMSmessage >= Status.Number)
1844 nextSMSmessage = -1;
1846 printf("HandleSMS: setting nextSMSmessage to -1\n");
1849 } else /* user give location -> make fake location */
1851 /* future use: get already read sms from mem */
1852 N7110_Fake2SMSLocation( smsnum, folder, location);
1855 case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */
1858 /* calculate correct folderid */
1859 *folder = ( *folder + 1) * 8;
1862 } else /* user give location -> make fake location */
1864 N7110_Fake2SMSLocation( smsnum, folder, location);
1867 error=N7110_GetSMSFolderStatus(&onefolder, folderid );
1868 if (error!=GE_NONE) return error;
1870 /* is there a sms at that location ? */
1871 for (i=0; i<CurrentSMSFolder.number; i++)
1872 if ( CurrentSMSFolder.locations[i] == *location ) found = true;
1874 if (found == true) return GE_BUSYSMSLOCATION;
1875 else return GE_NONE;
1884 /* input: fake smsnum, output: folderid & location */
1885 void N7110_Fake2SMSLocation(int smsnum, u8 *folderid, int *location)
1889 ifolderid = smsnum / N7110_MAXSMSINFOLDER;
1890 *folderid = ifolderid * 0x08;
1891 *location = smsnum - ifolderid * N7110_MAXSMSINFOLDER;
1894 /* input; folderid & location, output: fake smsnum */
1895 void N7110_SMS2FakeLocation(int *smsnum, u8 folderid, int location)
1899 ifolderid = folderid / 0x08;
1900 *smsnum = ifolderid * N7110_MAXSMSINFOLDER + location;
1903 GSM_Error N7110_GetRFLevel(GSM_RFUnits *units, float *level)
1905 unsigned char request[] = {N6110_FRAME_HEADER, 0x81};
1912 Protocol->SendMessage(4, 0x0a, request);
1914 /* Wait for timeout or other error. */
1915 while (timeout != 0 && CurrentRFLevel == -1 ) {
1918 return (GE_TIMEOUT);
1923 /* Make copy in case it changes. */
1924 rf_level = CurrentRFLevel;
1929 /* Now convert between the different units we support. */
1931 /* Arbitrary units. */
1932 *units = GRF_Percentage;
1937 GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1939 unsigned char request[] = {N6110_FRAME_HEADER, 0x02};
1944 CurrentBatteryLevel=-1;
1946 Protocol->SendMessage(4, 0x17, request);
1948 /* Wait for timeout or other error. */
1949 while (timeout != 0 && CurrentBatteryLevel == -1 ) {
1952 return (GE_TIMEOUT);
1957 /* Take copy in case it changes. */
1958 batt_level = CurrentBatteryLevel;
1960 if (batt_level == -1)
1963 /* Only units we handle at present are GBU_Arbitrary */
1964 *units = GBU_Percentage;
1965 *level = batt_level;
1969 GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
1971 unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c};
1973 if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED;
1975 CurrentSecurityCode=SecurityCode;
1977 return NULL_SendMessageSequence
1978 (50, &CurrentSecurityCodeError, 5, 0x7a, req);
1981 GSM_Error N7110_GetDateTime(GSM_DateTime *date_time)
1983 return N6110_PrivGetDateTime(date_time,0x19);
1986 /* Needs SIM card with PIN in phone */
1987 GSM_Error N7110_SetDateTime(GSM_DateTime *date_time)
1989 return N6110_PrivSetDateTime(date_time,0x19);
1992 GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1994 return N6110_PrivGetAlarm(alarm_number,date_time,0x19);
1997 /* FIXME: we should also allow to set the alarm off :-) */
1998 GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
2000 return N6110_PrivSetAlarm(alarm_number,date_time, 0x19);
2003 void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2005 switch (MessageBuffer[3]) {
2011 fprintf(stdout, _("Message: SMS Status Received\n"));
2012 fprintf(stdout, _(" Used msg in phone memory: %i\n"),MessageBuffer[10]*256+MessageBuffer[11]);
2013 fprintf(stdout, _(" Unread msg in phone memory: %i\n"),MessageBuffer[12]*256+MessageBuffer[13]);
2014 fprintf(stdout, _(" Used msg in SIM: %i\n"),MessageBuffer[14]*256+MessageBuffer[15]);
2015 fprintf(stdout, _(" Unread msg in SIM: %i\n"),MessageBuffer[16]*256+MessageBuffer[17]);
2017 CurrentSMSStatus->UnRead = MessageBuffer[13];
2018 CurrentSMSStatusError = GE_NONE;
2024 fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
2026 CurrentSMSStatusError = GE_INTERNALERROR;
2032 GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status)
2034 /* RTH FIXME: what is exact meaning of 0x0037 answer ? */
2035 /* we check all folders, but get sum of unread sms via 0x0036 request */
2036 unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
2038 GSM_SMSFolders folders;
2039 GSM_OneSMSFolder folder;
2042 int ismsnum,ilocation;
2045 CurrentSMSStatus = Status;
2047 /* read all SMS folders */
2048 /* check for unread messages in folder 0xf8 */
2049 error = N7110_GetSMSFolderStatus(&folder, 0xf8);
2050 if (error != GE_NONE) return error;
2053 for(j=0; j<folder.number; j++)
2055 ifolder = 0; /*read unread messages from folder 0 */
2056 ilocation = folder.locations[j];
2057 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation) ;
2058 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2059 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2060 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2064 /* read standard folders */
2065 N7110_GetSMSFolders (&folders);
2066 for(i=0; i<CurrentSMSFoldersCount; i++)
2068 error = N7110_GetSMSFolderStatus(&CurrentSMSFolders->Folder[i], CurrentSMSFolders->FoldersID[i]);
2069 if (error != GE_NONE) return error;
2071 for(j=0; j<CurrentSMSFolders->Folder[i].number; j++)
2073 ifolder = CurrentSMSFolders->FoldersID[i];
2074 ilocation = CurrentSMSFolders->Folder[i].locations[j];
2075 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation);
2076 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2077 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2078 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2082 CurrentSMSStatus->Number = smsmaxnum;
2084 return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req);
2087 void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2089 int i, count, blocks, blockcount;
2093 unsigned char *pBlock;
2095 CurrentPhonebookEntry->Empty = true;
2096 CurrentPhonebookEntry->Group = 5; /* 5 = no group as 6110 */
2097 CurrentPhonebookEntry->Name[0] = '\0';
2098 CurrentPhonebookEntry->Number[0] = '\0';
2099 CurrentPhonebookEntry->SubEntriesCount = 0;
2102 fprintf(stdout, _("Message: Phonebook entry received:\n"));
2105 if( MessageBuffer[6] == 0x0f ) // not found
2108 fprintf(stdout, _(" Error %i\n"),MessageBuffer[10]);
2109 switch (MessageBuffer[10]) {
2110 case 0x34:fprintf(stdout,_(" Invalid phonebook location\n"));break;
2111 case 0x3b:fprintf(stdout,_(" Speed dial not assigned\n"));break;
2112 default :fprintf(stdout,_(" Unknown.Please report\n"));break;
2115 switch (MessageBuffer[10]) {
2116 case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break;
2117 case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break;
2118 default :CurrentPhonebookError = GE_UNKNOWN;
2120 CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
2124 CurrentPhonebookEntry->Location=MessageBuffer[13];
2126 count = MessageBuffer[9];
2127 blocks = MessageBuffer[17];
2130 CurrentPhonebookEntry->SubEntriesCount = blocks - 1;
2133 fprintf(stdout, _(" Blocks: %d\n"),blocks);
2136 pBlock = &MessageBuffer[18];
2138 for( i = 0; i < blocks; i++ )
2140 GSM_SubPhonebookEntry* pEntry = &CurrentPhonebookEntry->SubEntries[blockcount];
2143 fprintf(stdout,_(" "));
2144 for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]);
2145 fprintf(stdout,_("\n"));
2148 switch( pBlock[0] ) {
2149 case N7110_ENTRYTYPE_SPEEDDIAL:
2151 CurrentSpeedDialEntry->MemoryType = GMT_SM;
2152 if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME;
2154 CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256;
2157 fprintf(stdout, _(" Speed dial\n"));
2158 fprintf(stdout, _(" Location: %d\n"), CurrentSpeedDialEntry->Location);
2159 fprintf(stdout, _(" MemoryType: %i\n"), CurrentSpeedDialEntry->MemoryType);
2160 fprintf(stdout, _(" Number: %d\n"), CurrentSpeedDialEntry->Number);
2163 CurrentSpeedDialError=GE_NONE;
2166 case N7110_ENTRYTYPE_NAME:
2167 DecodeUnicode (CurrentPhonebookEntry->Name, pBlock+6, pBlock[5]/2);
2168 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2169 strncpy(CurrentGetBitmap->text,CurrentPhonebookEntry->Name,sizeof(CurrentGetBitmap->text));
2170 CurrentPhonebookEntry->Empty = false;
2172 fprintf(stdout, _(" Name:\n"));
2173 fprintf(stdout, _(" Name: %s\n"), CurrentPhonebookEntry->Name);
2177 case N7110_ENTRYTYPE_NUMBER:
2178 pEntry->EntryType = pBlock[0];
2179 pEntry->NumberType = pBlock[5];
2180 pEntry->BlockNumber = pBlock[4];
2182 DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2);
2185 fprintf(stdout, _(" Number:\n"));
2186 fprintf(stdout, _(" Type: %d (%02x)\n"),
2188 pEntry->NumberType);
2189 fprintf(stdout, _(" Number: %s\n"),
2190 pEntry->data.Number);
2192 if( pEntry->EntryType == GSM_Number &&
2193 ((pEntry->NumberType == GSM_General &&
2194 !strcmp(CurrentPhonebookEntry->Number,""))
2195 || pEntry->NumberType == GSM_SIM)) {
2196 strcpy( CurrentPhonebookEntry->Number, pEntry->data.Number );
2197 *pEntry->data.Number = 0;
2201 case N7110_ENTRYTYPE_DATE:
2202 pEntry->EntryType = pBlock[0];
2203 pEntry->NumberType = pBlock[5];
2204 pEntry->BlockNumber = pBlock[4];
2205 DecodeDateTime(pBlock+6, &pEntry->data.Date);
2207 fprintf(stdout, _(" Date:\n"));
2208 fprintf(stdout, _(" Date: %02u.%02u.%04u\n"), pEntry->data.Date.Day,
2209 pEntry->data.Date.Month, pEntry->data.Date.Year );
2210 fprintf(stdout, _(" Time: %02u:%02u:%02u\n"), pEntry->data.Date.Hour,
2211 pEntry->data.Date.Minute, pEntry->data.Date.Second);
2215 case N7110_ENTRYTYPE_NOTE:
2216 case N7110_ENTRYTYPE_POSTAL:
2217 case N7110_ENTRYTYPE_EMAIL:
2218 pEntry->EntryType = pBlock[0];
2219 pEntry->NumberType = 0;
2220 pEntry->BlockNumber = pBlock[4];
2222 DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2);
2225 fprintf(stdout, _(" Email or note or postal:\n"));
2226 fprintf(stdout, _(" Type: %d (%02x)\n"),
2229 fprintf(stdout, _(" Text: %s\n"),
2230 pEntry->data.Number);
2234 case N7110_ENTRYTYPE_GROUP:
2235 CurrentPhonebookEntry->Group = pBlock[5]-1; /* 0 = family as for 6110 */
2236 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2237 CurrentGetBitmap->number = CurrentPhonebookEntry->Group;
2239 fprintf(stdout, _(" Group: %d\n"), CurrentPhonebookEntry->Group);
2242 case N7110_ENTRYTYPE_RINGTONE:
2243 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2244 CurrentGetBitmap->ringtone = pBlock[5];
2246 fprintf(stdout, _(" Group ringtone number %d received.\n"), pBlock[5]);
2249 case N7110_ENTRYTYPE_LOGOON:
2250 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2251 CurrentGetBitmap->enabled = pBlock[5];
2253 fprintf(stdout, _(" Logo enabled = %d received.\n"), pBlock[5]);
2256 case N7110_ENTRYTYPE_GROUPLOGO:
2258 fprintf(stdout, _(" Caller group logo received.\n"));
2260 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
2261 CurrentGetBitmap->width = pBlock[5];
2262 CurrentGetBitmap->height= pBlock[6];
2263 CurrentGetBitmap->size = pBlock[9];
2264 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
2265 CurrentGetBitmap->size = CurrentGetBitmap->size;
2266 memcpy(CurrentGetBitmap->bitmap,pBlock+10,CurrentGetBitmap->size);
2272 fprintf(stdout, _(" Unknown Entry Code (%u) received.\n"), pBlock[0] );
2278 fprintf(stdout, _(" Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]);
2280 pBlock = &pBlock[(int) pBlock[3]];
2283 CurrentPhonebookEntry->SubEntriesCount = blockcount;
2284 CurrentPhonebookError = GE_NONE;
2288 /* Routine to get specifed phone book location. Designed to be called by
2289 application. Will block until location is retrieved or a timeout/error
2291 GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) {
2293 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2296 0x00, 0x00, //location
2299 CurrentPhonebookEntry = entry;
2301 req[9] = N7110_GetMemoryType(entry->MemoryType);
2302 req[10] = (entry->Location>>8);
2303 req[11] = entry->Location & 0xff;
2305 return NULL_SendMessageSequence
2306 (50, &CurrentPhonebookError, 14, 0x03, req);
2309 void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2311 // [12,13] = Location
2314 if( MessageBuffer[6] == 0x0f ) // ERROR
2317 /* I didn't find any error when the Text,Name or Number was too long
2318 My Phone 7110; NSE-5; SW 04.84 */
2319 switch( MessageBuffer[10] ) {
2320 case 0x3d: fprintf(stdout, _("Error: Wrong Entry Type.\n")); break;
2321 case 0x3e: fprintf(stdout, _("Error: Too much entries.\n")); break;
2322 default : fprintf(stdout, _("Error: Unknown error (%u).\n"), MessageBuffer[10]); break;
2325 CurrentPhonebookError = GE_NONE;
2328 fprintf(stdout, _("Message: Phonebook written correctly.\n"));
2331 CurrentPhonebookError = GE_NONE;
2335 int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block)
2338 fprintf(stdout,_("Adding block id:%i,length:%i\n"),no+1,size+6);
2344 *(block++) = size + 6;
2345 *(block++) = no + 1;
2347 memcpy(block, buf, size);
2355 int N7110_MakePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block)
2357 int count=0, len, i;
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);
2408 /* Routine to write phonebook location in phone. */
2409 GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
2411 unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2412 0x00, 0x00, /* memory type */
2413 0x00, 0x00, /* location */
2415 int count = 18, blocks;
2417 if (entry->Name[0] != '\0' || entry->Number[0] != '\0') {
2418 req[11] = N7110_GetMemoryType(entry->MemoryType);
2419 req[12] = (entry->Location >> 8);
2420 req[13] = entry->Location & 0xff;
2422 // If we had a file that contain data in entry style like from 6110
2423 // we can import this too :)
2424 // no SubEntries in SIM (besides Name, Number, and Group)
2425 if (entry->MemoryType == GMT_SM) entry->SubEntriesCount = 0;
2427 count=count+N7110_MakePhonebookFrame(req+18, *entry, &blocks);
2432 fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name);
2435 return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req);
2439 /* empty name & number => we have to delete the phonebook record! */
2440 return N7110_DeletePhonebookLocation( entry );
2445 void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2448 fprintf(stdout, _("Message: Phonebook entry deleted correctly\n"));
2450 CurrentPhonebookError = GE_NONE;
2453 /* delete phonebookentry */
2454 /* Not used in this moment */
2455 GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry)
2457 unsigned char req[256] = {
2458 N7110_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04,
2459 0x00, 0x00, 0x0c, 0x01, 0xff,
2460 0x00, /* location low*/
2461 0x01, /* location high*/
2462 0x05, /* mem location low*/
2463 0x00, /* mem location high*/
2467 req[12] = (entry->Location >> 8);
2468 req[13] = entry->Location & 0xff;
2469 req[14] = N7110_GetMemoryType(entry->MemoryType);
2472 fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location);
2475 return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req);
2478 /* for saving group logos only */
2479 GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap)
2481 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2482 0x00, 0x10, /* memory type */
2483 0x00, 0x00, /* location */
2487 unsigned int count = 18;
2489 req[13] = bitmap->number + 1;
2492 string[0] = bitmap->enabled?1:0;
2494 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count);
2497 string[0] = bitmap->ringtone;
2499 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count);
2501 /* Number of group */
2502 string[0] = bitmap->number+1;
2504 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2507 string[0] = bitmap->width;
2508 string[1] = bitmap->height;
2511 string[4] = bitmap->size;
2512 memcpy(string + 5, bitmap->bitmap, bitmap->size);
2513 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUPLOGO, bitmap->size + 5, block++, string, req + count);
2516 if (*bitmap->text) {
2517 i = strlen(bitmap->text);
2519 EncodeUnicode((string + 1), bitmap->text, i);
2520 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 1, 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+5, Bitmap->netcode);
2661 reqOp[11] = 8+(Bitmap->width*Bitmap->height+7)/8;
2662 reqOp[12]=Bitmap->width;
2663 reqOp[13]=Bitmap->height;
2664 reqOp[15]=(Bitmap->width*Bitmap->height+7)/8;
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 (CurrentGetBitmapError!=GE_NONE) {
2698 req4[5]=PictureImageLoc;
2699 req4[6]=PictureImageIndex/256;
2700 req4[7]=PictureImageIndex%256;
2703 for (i=0;i<38;i++) req4[count++]=0x00;
2704 req4[count++]=Bitmap->width;
2705 req4[count++]=Bitmap->height;
2706 req4[count++]=Bitmap->size/256;
2707 req4[count++]=Bitmap->size%256;
2708 memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size);
2709 count += Bitmap->size;
2713 CurrentSetBitmapError = GE_BUSY;
2715 Protocol->SendMessage(count, 0x14, req4);
2721 /* Wait for timeout or other error. */
2722 while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
2725 return (GE_TIMEOUT);
2730 if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo)
2731 && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) {
2732 return N6110_Reset(0x03);
2735 return CurrentSetBitmapError;
2738 /* Get a bitmap from the phone */
2739 GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap)
2741 unsigned char req[10] = { N6110_FRAME_HEADER };
2743 /* Picture Images */
2744 unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2745 unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2746 unsigned char req4[9] = { N6110_FRAME_HEADER, 0x07,
2752 unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02};
2756 GSM_PhonebookEntry entry;
2758 CurrentGetBitmapError = GE_BUSY;
2760 CurrentGetBitmap=Bitmap;
2762 switch (CurrentGetBitmap->type) {
2763 case GSM_StartupLogo:
2764 case GSM_7110StartupLogo:
2765 case GSM_6210StartupLogo:
2766 req[count-1]=0x01; /* change FRAME_HEADER */
2767 req[count++]=0xee; /* to get 0x01ee */
2769 Protocol->SendMessage(count, 0x7a, req);
2772 case GSM_WelcomeNoteText:
2774 Protocol->SendMessage(5, 0x7a, req5);
2777 case GSM_DealerNoteText:
2779 return GE_NOTIMPLEMENTED;
2781 case GSM_OperatorLogo:
2782 case GSM_7110OperatorLogo:
2783 req[count++]=0x70; /* NetworkStatus */
2784 Protocol->SendMessage(count, 0x0a, req);
2787 case GSM_CallerLogo:
2788 entry.MemoryType = GMT_CG;
2789 entry.Location = Bitmap->number+1;
2791 Bitmap->ringtone=0xFF;
2792 Bitmap->enabled=true;
2793 CurrentGetBitmapError = N7110_GetMemoryLocation(&entry);
2794 CurrentGetBitmap=NULL;
2795 if (entry.Location!=Bitmap->number+1) return GE_UNKNOWN;
2796 if (!strcmp(Bitmap->text,"")) {
2797 switch(Bitmap->number) {
2798 case 0:strcpy(Bitmap->text,"Family\0");break;
2799 case 1:strcpy(Bitmap->text,"VIP\0");break;
2800 case 2:strcpy(Bitmap->text,"Friends\0");break;
2801 case 3:strcpy(Bitmap->text,"Colleagues\0");break;
2802 case 4:strcpy(Bitmap->text,"Other\0");break;
2807 case GSM_PictureImage:
2812 req2[4]=req3[count];
2813 PictureImageLoc=req3[count];
2815 if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE)
2816 return CurrentGetBitmapError;
2817 if (PictureImageNum==Bitmap->number+1) break;
2819 if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError;
2821 req4[4]=PictureImageLoc;
2822 req4[5]=PictureImageIndex/256;
2823 req4[6]=PictureImageIndex%256;
2825 CurrentGetBitmapError = GE_BUSY;
2827 Protocol->SendMessage(9, 0x14, req4);
2832 return GE_NOTSUPPORTED;
2837 while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) {
2840 return (GE_TIMEOUT);
2845 CurrentGetBitmap=NULL;
2847 return (CurrentGetBitmapError);
2850 int ReturnBinRingLocation()
2854 while (GSM->GetModel(model) != GE_NONE) sleep(1);
2856 if (strcmp(model,"NSE-5") == 0) return 0x74; //first 0x74 //7110
2857 if (strcmp(model,"NPE-3") == 0) return 0x89; //first is 0x89; //6210
2863 this works only for 6210, the 7110 needs upload to a location ?
2865 GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
2868 /* Buffer for preview uploading */
2869 unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D,
2870 0x00, 0x00, 0x00, 0x00,
2874 int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
2876 GSM_NetworkInfo NetworkInfo;
2878 char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
2880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2885 0x00, 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2888 /* Info from Till Toenshoff [till@uni.de]
2890 One improvement - for looping you can use an alternative header
2892 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2895 0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01
2903 char tail[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
2904 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
2905 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B // 20 Bytes tail
2908 //{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" };
2909 char N7110_notes[14] =
2910 { 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10 , 11, 11 };
2912 int current = 6, i, note, lastnote = 0, duration;
2914 /* Preview uploading */
2915 if (ringtone->location==255) {
2916 *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size);
2918 Protocol->SendMessage(size+11, 0x00, buffer);
2919 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
2921 return GE_NONE; //no answer from phone
2924 req[5]=ReturnBinRingLocation()+ringtone->location;
2926 EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name));
2930 for (i=0; i<ringtone->NrNotes; i++) {
2932 if (ringtone->notes[i].note == 255)
2935 note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14];
2937 duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256; // in 8 ms ticks of 7110
2939 switch (ringtone->notes[i].style) {
2942 req[current++] = note; // note only for one tick
2946 note = 0x40; // rest pause
2948 if (note != 0x40 && duration) {
2949 req[current++] = 0x40;
2950 req[current++] = 1; // small pause between notes
2954 if (note != 0x40 && note == lastnote && duration) {
2955 req[current++] = 0x40;
2956 req[current++] = 1; // small pause between same notes
2960 while (duration > 125) {
2961 req[current++] = note;
2962 req[current++] = 125;
2965 req[current++] = note;
2966 req[current++] = duration;
2971 for (i = 0; i < sizeof(tail); i++)
2972 req[current++] = tail[i];
2974 Protocol->SendMessage(current, 0x1F, req);
2978 return GE_NONE; //no answer from phone
2981 void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2985 switch (MessageBuffer[3]) {
2990 while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) {
2995 DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp);
2998 fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name);
3001 CurrentGetBinRingtone->frame[0]=0x00;
3002 CurrentGetBinRingtone->frame[1]=0x00;
3003 CurrentGetBinRingtone->frame[2]=0x0c;
3004 CurrentGetBinRingtone->frame[3]=0x01;
3005 CurrentGetBinRingtone->frame[4]=0x2c;
3007 memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name));
3009 CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name);
3011 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3012 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3014 /* Looking for end */
3017 if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
3020 if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
3024 if (i==MessageLength) break;
3028 memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37);
3029 CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37;
3031 CurrentBinRingtoneError=GE_NONE;
3037 fprintf(stdout, _("Message: Received empty ringtone\n"));
3040 CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;
3045 GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone)
3048 unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 };
3052 req[5]=ReturnBinRingLocation()+ringtone->location;
3054 CurrentGetBinRingtone=ringtone;
3056 return NULL_SendMessageSequence
3057 (50, &CurrentBinRingtoneError, 6, 0x1f, req);
3061 GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone)
3063 unsigned char req[500] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 };
3065 GSM_NetworkInfo NetworkInfo;
3071 req[5]=ReturnBinRingLocation()+ringtone->location;
3073 for (i=6;i<35;i++) req[i]=0x00;
3077 EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5));
3081 while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++;
3083 memcpy(req+35,ringtone->frame+i,ringtone->length-i);
3085 Protocol->SendMessage(35+ringtone->length-i, 0x1f, req);
3087 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
3089 return GE_NONE; //no answer from phone
3092 void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3094 GSM_SMSMessage NullSMS;
3097 fprintf(stdout,_("Message: Incoming SMS\n"));
3100 GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5);
3103 fprintf(stdout, _("\n"));
3107 void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3115 GSM_NetworkInfo NullNetworkInfo;
3117 switch (MessageBuffer[3]) {
3122 fprintf(stdout, _("Message: Clearing operator logo msg\n"));
3124 CurrentSetBitmapError=GE_NONE;
3129 /* Make sure we are expecting NetworkInfo frame */
3130 if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) ||
3131 (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) {
3133 fprintf(stdout, _("Message: Network informations and operator logo:\n"));
3137 fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
3141 sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
3143 sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
3145 sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
3148 fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID);
3149 fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC);
3150 fprintf(stdout, _(" Network code: %s\n"), NullNetworkInfo.NetworkCode);
3151 fprintf(stdout, _(" Network name for gnokii: %s (%s)\n"),
3152 GSM_GetNetworkName(NullNetworkInfo.NetworkCode),
3153 GSM_GetCountryName(NullNetworkInfo.NetworkCode));
3155 DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]);
3156 fprintf(stdout, _(" Network name for phone: %s\n"),name);
3158 fprintf(stdout, _(" Status: "));
3159 switch (MessageBuffer[8]) {
3160 case 0x01: fprintf(stdout, _("home network selected")); break;
3161 case 0x02: fprintf(stdout, _("roaming network")); break;
3162 case 0x03: fprintf(stdout, _("requesting network")); break;
3163 case 0x04: fprintf(stdout, _("not registered in the network")); break;
3164 default: fprintf(stdout, _("unknown"));
3167 fprintf(stdout, "\n");
3169 fprintf(stdout, _(" Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
3172 /* Make sure we are expecting NetworkInfo frame */
3173 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
3174 *CurrentNetworkInfo=NullNetworkInfo;
3175 CurrentNetworkInfoError = GE_NONE;
3178 /* Make sure we are expecting an operator logo */
3179 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3181 strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode);
3184 if (MessageBuffer[4] == 0x02)
3185 fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),
3186 CurrentGetBitmap->netcode,
3187 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3189 fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"),
3190 CurrentGetBitmap->netcode,
3191 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3194 if (MessageBuffer[4] == 0x02) { /* logo present */
3196 count += MessageBuffer[count]; /* skip network info */
3197 CurrentGetBitmap->size=MessageBuffer[count++]; /* is too large */
3198 CurrentGetBitmap->width=MessageBuffer[count++]; /* 78 */
3199 CurrentGetBitmap->height=MessageBuffer[count++]; /* 21 */
3201 CurrentGetBitmap->size=(CurrentGetBitmap->height*CurrentGetBitmap->width+7)/8; /* packed size */
3202 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
3203 CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap);
3204 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
3206 CurrentGetBitmap->width=78;
3207 CurrentGetBitmap->height=21;
3208 CurrentGetBitmap->size=(CurrentGetBitmap->height*CurrentGetBitmap->width+7)/8; /* packed size */
3209 memset(CurrentGetBitmap->bitmap,0,CurrentGetBitmap->size);
3211 CurrentGetBitmapError=GE_NONE;
3218 fprintf(stdout, _("Message: Network Level received:\n"));
3220 fprintf(stdout, _(" Network Level: %d\n"), MessageBuffer[4]);
3223 CurrentRFLevel=MessageBuffer[4];
3229 fprintf(stdout, _("Message: Operator logo set correctly.\n"));
3231 CurrentSetBitmapError = GE_NONE;
3236 fprintf(stdout, _("Message: Unknown message of type 0x0a\n"));
3238 AppendLogText("Unknown msg\n",false);
3239 break; /* Visual C Don't like empty cases */
3243 void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3246 GSM_ETSISMSMessage ETSI;
3248 switch (MessageBuffer[3]) {
3250 /* We have requested invalid or empty location. */
3254 fprintf(stdout, _("Message: SMS reading failed\n"));
3257 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3258 CurrentGetBitmapError=GE_UNKNOWN;
3261 /* getsms or picture image */
3264 if (MessageBuffer[8]==0x07) {
3266 if (CurrentGetBitmap!=NULL) {
3268 for (i=0;i<MessageBuffer[9]+1;i++)
3269 ETSI.SMSCNumber[i]=MessageBuffer[i+9];
3271 for (i=0;i<((MessageBuffer[22]+1)/2+1)+1;i++)
3272 ETSI.Number[i]=MessageBuffer[22+i];
3275 fprintf(stdout, _("Message: Picture Image received\n"));
3276 fprintf(stdout, _(" SMS center number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.SMSCNumber,false));
3277 fprintf(stdout, _(" Sender number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3280 strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3282 CurrentGetBitmap->width=MessageBuffer[47];
3283 CurrentGetBitmap->height=MessageBuffer[48];
3284 CurrentGetBitmap->size=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
3286 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size);
3288 tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size,
3289 CurrentGetBitmap->text);
3291 CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0;
3293 CurrentGetBitmapError=GE_NONE;
3297 fprintf(stdout, _("Message: Picture Image received, but not reqested\n"));
3300 CurrentSMSMessageError = GE_SMSTOOLONG;
3306 /* status in byte 4 */
3307 CurrentSMSMessage->Status = MessageBuffer[4];
3309 CurrentSMSMessage->Type = GST_SMS;
3310 if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR;
3312 CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location;
3314 /* RTH FIXME: old folder stuff for xgnokii */
3315 CurrentSMSMessage->folder = (MessageBuffer[5] / 8)-1;
3316 /* if unreadMessage from folder 0, set INBOX folder */
3317 if (CurrentSMSMessage->folder==-1) CurrentSMSMessage->folder = 0;
3319 fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n")
3320 ,CurrentSMSMessage->Type, CurrentSMSMessage->folder, MessageBuffer[7]);
3323 GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9);
3325 /* Signal no error to calling code. */
3326 CurrentSMSMessageError = GE_NONE;
3333 fprintf(stdout, _("Message: Received index for Picture Images\n"));
3336 for (i=1;i<MessageBuffer[4]*256+MessageBuffer[5]+1;i++) {
3338 if (PictureImageNum==CurrentGetBitmap->number+1) {
3339 PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2];
3344 CurrentGetBitmapError=GE_NONE;
3345 CurrentSetBitmapError=GE_NONE;
3352 fprintf(stdout, _("Message: Unknown message of type 14\n"));
3354 AppendLogText("Unknown msg\n",false);
3355 break; /* Visual C Don't like empty cases */
3359 void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3361 switch (MessageBuffer[3]) {
3366 fprintf(stdout, _("Message: Battery status received:\n"));
3368 fprintf(stdout, _(" Battery Level: %d\n"), MessageBuffer[5]);
3371 CurrentBatteryLevel=MessageBuffer[5];
3377 fprintf(stdout, _("Message: Unknown message of type 0x17\n"));
3379 AppendLogText("Unknown msg\n",false);
3380 break; /* Visual C Don't like empty cases */
3384 void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3388 switch (MessageBuffer[3]) {
3390 /* Setting setting request */
3393 switch (MessageBuffer[4]) {
3397 fprintf(stdout, _("Message: Startup text set correctly.\n"));
3399 CurrentSetBitmapError = GE_NONE;
3404 fprintf(stdout, _("Message: Startup logo set correctly.\n"));
3406 CurrentSetBitmapError = GE_NONE;
3412 /* Setting received */
3415 switch (MessageBuffer[4]) {
3419 fprintf(stdout, _("Message: Startup text received.\n"));
3423 while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) {
3428 DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp);
3431 fprintf(stdout, _(" Text: \"%s\"\n"),CurrentGetBitmap->text);
3434 CurrentGetBitmapError = GE_NONE;
3439 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
3440 fprintf(stdout, _("Message: Startup logo received.\n"));
3442 fprintf(stdout, _("Message: Startup logo not requested, but received.\n"));
3445 /* Make sure we are expecting a startup logo */
3446 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3447 CurrentGetBitmap->height=MessageBuffer[13]; /* 96 */
3448 CurrentGetBitmap->width=MessageBuffer[17]; /* 60 */
3449 CurrentGetBitmap->size=(CurrentGetBitmap->height+7)/8*CurrentGetBitmap->width; /* unpacked size */
3450 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
3451 CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap);
3452 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+22,CurrentGetBitmap->size);
3453 CurrentGetBitmapError=GE_NONE;
3458 fprintf(stdout, _("Message: security code \""));
3460 for (i=6;i<11;i++) {
3461 fprintf(stdout, _("%c"),MessageBuffer[i]);
3464 fprintf(stdout,_("\"received.\n"));
3466 strncpy(CurrentSecurityCode->Code,MessageBuffer+6,6);
3468 CurrentSecurityCodeError=GE_NONE;
3475 fprintf(stdout, _("Unknown message of type 0x7a.\n"));
3477 AppendLogText("Unknown msg\n",false);
3478 break; /* Visual C Don't like empty cases */
3482 void N7110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3486 /* Switch on the basis of the message type byte */
3487 switch (MessageType) {
3489 /* Call information */
3490 /* Note, we use N6110_Dispatch0x40Message, but only some of 0x01
3491 old msg are available in new phones - other returns generally only
3495 N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);
3500 switch (MessageBuffer[3]) {
3502 case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;
3504 case 0x0f:N7110_ReplyEnableIncomingSMSInfo(MessageLength,MessageBuffer,MessageType);break;
3505 case 0x11:N7110_ReplyIncomingSMS (MessageLength,MessageBuffer,MessageType);break;
3506 case 0x21:N6110_ReplySetCellBroadcast (MessageLength, MessageBuffer, MessageType);break;
3507 case 0x23:N6110_ReplyReadCellBroadcast (MessageLength, MessageBuffer, MessageType);break;
3508 case 0x31:N6110_ReplySetSMSCenter (MessageLength,MessageBuffer,MessageType);break;
3510 case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
3511 default :unknown=true;break;
3515 /* Phonebook and speed dials */
3517 switch (MessageBuffer[3]) {
3518 case 0x04:N7110_ReplyGetMemoryStatus (MessageLength,MessageBuffer,MessageType);break;
3519 case 0x08:N7110_ReplyGetMemoryLocation (MessageLength,MessageBuffer,MessageType);break;
3520 case 0x10:N7110_ReplyDeletePhonebookLocation(MessageLength,MessageBuffer,MessageType);break;
3521 case 0x0C:N7110_ReplyWritePhonebookLocation (MessageLength,MessageBuffer,MessageType);break;
3522 default :unknown=true;break;
3526 /* This is call forwarding stuff */
3528 switch (MessageBuffer[3]) {
3530 case 0x03:N6110_ReplyCallDivert (MessageLength,MessageBuffer,MessageType);break;
3531 default :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;
3535 /* Network and operator logo */
3538 N7110_Dispatch0x0AMessage(MessageLength, MessageBuffer, MessageType);
3541 /* Calendar notes handling */
3543 switch (MessageBuffer[3]) {
3547 case 0x08:N7110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3548 case 0x0c:N7110_ReplyDeleteCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3549 case 0x1A:N7110_ReplyGetCalendarNote (MessageLength,MessageBuffer,MessageType);break;
3550 case 0x32:N7110_ReplyFirstCalendarFreePos(MessageLength,MessageBuffer,MessageType);break;
3551 case 0x3b:N7110_ReplyGetCalendarNotesInfo(MessageLength,MessageBuffer,MessageType);break;
3552 default :unknown=true;break;
3558 switch (MessageBuffer[3]) {
3560 case 0x06:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3561 case 0x0b:N7110_ReplyDeleteSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3563 case 0x38:N7110_ReplyGetSMSStatus (MessageLength,MessageBuffer,MessageType);break;
3564 case 0x6C:N7110_ReplyGetSMSFolderStatus(MessageLength,MessageBuffer,MessageType);break;
3565 case 0x7B:N7110_ReplyGetSMSFolders (MessageLength,MessageBuffer,MessageType);break;
3566 case 0x84:N7110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break;
3567 default :N7110_Dispatch0x14Message (MessageLength, MessageBuffer, MessageType);break;
3571 /* Battery status */
3574 N7110_Dispatch0x17Message(MessageLength, MessageBuffer, MessageType);
3579 switch (MessageBuffer[3]) {
3580 case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break;
3581 case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break;
3582 case 0x6c:N6110_ReplySetAlarm (MessageLength,MessageBuffer,MessageType);break;
3583 case 0x6e:N6110_ReplyGetAlarm (MessageLength,MessageBuffer,MessageType);break;
3584 default :unknown=true;break;
3590 switch (MessageBuffer[3]) {
3592 case 0x24:N7110_ReplyGetBinRingtone(MessageLength,MessageBuffer,MessageType);break;
3593 default :unknown=true;break;
3600 N7110_ReplyGetProfile(MessageLength, MessageBuffer, MessageType);
3605 switch (MessageBuffer[3]) {
3607 case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;
3609 case 0x08:N7110_ReplyGetWAPBookmark (MessageLength,MessageBuffer,MessageType);break;
3611 case 0x0b:N7110_ReplySetWAPBookmark (MessageLength,MessageBuffer,MessageType);break;
3614 case 0x1c:N7110_ReplyGetWAPSettings (MessageLength,MessageBuffer,MessageType);break;
3615 default :unknown=true;break;
3619 /* Internal phone functions ? */
3620 /* Note, we use N6110_Dispatch0x40Message, but only some of 0x40
3621 old msg are available in new phones - other returns generally only
3624 switch (MessageBuffer[2]) {
3625 case 0x64:N6110_ReplyEnableExtendedCommands (MessageLength,MessageBuffer,MessageType);break;
3626 case 0x65:N6110_ReplyResetPhoneSettings (MessageLength,MessageBuffer,MessageType);break;
3627 case 0x66:N6110_ReplyIMEI (MessageLength,MessageBuffer,MessageType);break;
3628 case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3629 case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3630 case 0x7e:N6110_ReplyNetmonitor (MessageLength,MessageBuffer,MessageType);break;
3631 case 0x8a:N6110_ReplySimlockInfo (MessageLength,MessageBuffer,MessageType);break;
3632 case 0x8f:N6110_ReplyPlayTone (MessageLength,MessageBuffer,MessageType);break;
3633 case 0xc8:N6110_ReplyHW (MessageLength,MessageBuffer,MessageType);break;
3634 default :N6110_Dispatch0x40Message (MessageLength,MessageBuffer,MessageType);break;
3641 N7110_Dispatch0x7AMessage(MessageLength, MessageBuffer, MessageType);
3644 /***** Acknowlegment of our frames. *****/
3645 case FBUS_FRTYPE_ACK:
3647 N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);
3652 N6110_ReplyID(MessageLength, MessageBuffer, MessageType);
3655 /***** Unknown message *****/
3656 /* If you think that you know the exact meaning of other messages - please
3661 fprintf(stdout, _("Message: Unknown message type.\n"));
3663 AppendLogText("Unknown msg type\n",false);
3670 fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);
3672 AppendLogText("Unknown msg\n",false);