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;
257 /* This function translates GMT_MemoryType to N7110_MEMORY_xx */
258 int N7110_GetMemoryType(GSM_MemoryType memory_type)
263 switch (memory_type) {
266 // result = N7110_MEMORY_MT;
269 case GMT_ME: result = N7110_MEMORY_ME; break;
270 case GMT_SM: result = N7110_MEMORY_SM; break;
271 case GMT_FD: result = N7110_MEMORY_FD; break;
272 case GMT_ON: result = N7110_MEMORY_ON; break;
273 case GMT_EN: result = N7110_MEMORY_EN; break;
274 case GMT_DC: result = N7110_MEMORY_DC; break;
275 case GMT_RC: result = N7110_MEMORY_RC; break;
276 case GMT_MC: result = N7110_MEMORY_MC; break;
277 case GMT_CG: result = N7110_MEMORY_CG; break;
278 default : result = N6110_MEMORY_XX;
284 GSM_Error N7110_GetVoiceMailbox ( GSM_PhonebookEntry *entry)
286 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
289 0x00, 0x00, //location
292 CurrentPhonebookEntry = entry;
294 req[9] = N7110_MEMORY_VM;
298 return NULL_SendMessageSequence
299 (50, &CurrentPhonebookError, 14, 0x03, req);
302 void N7110_ReplyEnableWAPCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
304 switch(MessageBuffer[3]) {
308 fprintf(stdout, _("Message: WAP functions enabled\n"));
310 CurrentGetWAPBookmarkError=GE_NONE;
315 fprintf(stdout, _("Message: WAP functions enabled\n"));
317 CurrentGetWAPBookmarkError=GE_NONE;
323 /* To enable WAP frames in phone */
324 GSM_Error N7110_EnableWAPCommands ()
326 unsigned char req0[] = { N6110_FRAME_HEADER, 0x00 };
328 return NULL_SendMessageSequence
329 (50, &CurrentGetWAPBookmarkError, 4, 0x3f, req0);
332 void N7110_ReplyGetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
336 switch(MessageBuffer[3]) {
341 fprintf(stdout, _("Message: WAP bookmark received OK\n"));
344 DecodeUnicode(WAPBookmark->title, MessageBuffer + 7, MessageBuffer[6] );
347 fprintf(stdout, _(" Title: \"%s\"\n"),WAPBookmark->title);
350 tmp=MessageBuffer[6]*2+7;
352 DecodeUnicode(WAPBookmark->address, MessageBuffer + tmp+1, MessageBuffer[tmp] );
355 fprintf(stdout, _(" Address: \"%s\"\n"),WAPBookmark->address);
358 CurrentGetWAPBookmarkError=GE_NONE;
364 fprintf(stdout, _("Message: WAP bookmark receiving error\n"));
365 switch (MessageBuffer[4]) {
366 case 0x01:fprintf(stdout, _(" Inside Bookmarks menu. Must leave it\n"));break;
367 case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break;
368 default :fprintf(stdout, _(" Unknown error. Please report it\n"));
372 switch (MessageBuffer[4]) {
373 case 0x01:CurrentGetWAPBookmarkError=GE_INSIDEBOOKMARKSMENU;break;
374 case 0x02:CurrentGetWAPBookmarkError=GE_INVALIDBOOKMARKLOCATION;break;
375 default:CurrentGetWAPBookmarkError=GE_UNKNOWN;
382 GSM_Error N7110_GetWAPBookmark (GSM_WAPBookmark *bookmark)
384 unsigned char req[] = { N6110_FRAME_HEADER, 0x06, 0x00, 0x00};
388 /* We have to enable WAP frames in phone */
389 error=N7110_EnableWAPCommands ();
390 if (error!=GE_NONE) return error;
393 req[5]=bookmark->location-1;
395 WAPBookmark=bookmark;
397 return NULL_SendMessageSequence
398 (50, &CurrentGetWAPBookmarkError, 6, 0x3f, req);
401 void N7110_ReplySetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
403 switch(MessageBuffer[3]) {
408 fprintf(stdout, _("Message: WAP bookmark set OK\n"));
411 CurrentSetWAPBookmarkError=GE_NONE;
417 fprintf(stdout, _("Message: Error setting WAP bookmark\n"));
420 CurrentSetWAPBookmarkError=GE_UNKNOWN;
425 GSM_Error N7110_SetWAPBookmark (GSM_WAPBookmark *bookmark)
427 unsigned char req[64] = { N6110_FRAME_HEADER, 0x09 };
431 /* We have to enable WAP frames in phone */
432 error = N7110_EnableWAPCommands ();
433 if (error != GE_NONE)
437 req[count++] = (bookmark->location & 0xff00) >> 8;
438 req[count++] = (bookmark->location & 0x00ff);
440 req[count++] = strlen(bookmark->title);
441 EncodeUnicode (req+count,bookmark->title ,strlen(bookmark->title));
442 count=count+2*strlen(bookmark->title);
444 req[count++] = strlen(bookmark->address);
445 EncodeUnicode (req+count,bookmark->address ,strlen(bookmark->address));
446 count=count+2*strlen(bookmark->address);
449 req[count++] = 0x01; req[count++] = 0x80; req[count++] = 0x00;
450 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
451 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
453 WAPBookmark = bookmark;
455 return NULL_SendMessageSequence(50, &CurrentSetWAPBookmarkError,
459 void N7110_ReplyGetWAPSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
463 switch(MessageBuffer[3]) {
468 fprintf(stdout, _("Message: WAP settings received OK\n"));
471 DecodeUnicode(WAPSettings->title, MessageBuffer + 5, MessageBuffer[4] );
474 fprintf(stdout, _(" Title: \"%s\"\n"),WAPSettings->title);
477 tmp=5+MessageBuffer[4]*2;
479 DecodeUnicode(WAPSettings->homepage, MessageBuffer + tmp+1, MessageBuffer[tmp] );
482 fprintf(stdout, _(" Homepage: \"%s\"\n"),WAPSettings->homepage);
485 tmp=tmp+MessageBuffer[tmp]*2+1;
488 fprintf(stdout, _(" Connection type: "));
489 switch (MessageBuffer[tmp]) {
490 case 0x00: fprintf(stdout,_("temporary"));break;
491 case 0x01: fprintf(stdout,_("continuous"));break;
492 default: fprintf(stdout,_("unknown"));
494 fprintf(stdout, _("\n"));
496 fprintf(stdout, _(" Connection security: "));
497 switch (MessageBuffer[tmp+13]) {
498 case 0x00: fprintf(stdout,_("off"));break;
499 case 0x01: fprintf(stdout,_("on"));break;
500 default: fprintf(stdout,_("unknown"));
502 fprintf(stdout, _("\n"));
506 switch (MessageBuffer[tmp]) {
507 case 0x00: WAPSettings->iscontinuous=false;break;
508 case 0x01: WAPSettings->iscontinuous=true;break;
510 switch (MessageBuffer[tmp+13]) {
511 case 0x00: WAPSettings->issecurity=false;break;
512 case 0x01: WAPSettings->issecurity=true;break;
515 WAPSettings->location=MessageBuffer[tmp+7];//location for second part
517 CurrentGetWAPSettingsError=GE_NONE;
523 fprintf(stdout, _("Message: WAP settings receiving error\n"));
524 switch (MessageBuffer[4]) {
525 case 0x01:fprintf(stdout, _(" Inside Settings menu. Must leave it\n"));break;
526 case 0x02:fprintf(stdout, _(" Invalid or empty location\n"));break;
527 default :fprintf(stdout, _(" Unknown error. Please report it\n"));
531 switch (MessageBuffer[4]) {
532 case 0x01:CurrentGetWAPSettingsError=GE_INSIDESETTINGSMENU;break;
533 case 0x02:CurrentGetWAPSettingsError=GE_INVALIDSETTINGSLOCATION;break;
534 default :CurrentGetWAPSettingsError=GE_UNKNOWN;
542 fprintf(stdout, _("Message: WAP settings received OK\n"));
545 switch (MessageBuffer[5]) {
548 WAPSettings->bearer=WAPSETTINGS_BEARER_SMS;
551 fprintf(stdout, _(" Settings for SMS bearer:\n"));
556 DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1,
557 MessageBuffer[tmp] );
560 fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service);
563 tmp=tmp+MessageBuffer[tmp]*2+1;
565 DecodeUnicode(WAPSettings->server, MessageBuffer + tmp+ 1,
566 MessageBuffer[tmp] );
569 fprintf(stdout, _(" Server number: \"%s\"\n"),WAPSettings->server);
576 WAPSettings->bearer=WAPSETTINGS_BEARER_DATA;
579 fprintf(stdout, _(" Settings for data bearer:\n"));
584 DecodeUnicode(WAPSettings->ipaddress, MessageBuffer + tmp+ 1,
585 MessageBuffer[tmp] );
588 fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->ipaddress);
591 tmp=tmp+MessageBuffer[tmp]*2+1;
593 DecodeUnicode(WAPSettings->dialup, MessageBuffer + tmp+1,
594 MessageBuffer[tmp] );
597 fprintf(stdout, _(" Dial-up number: \"%s\"\n"),WAPSettings->dialup);
600 tmp=tmp+MessageBuffer[tmp]*2+1;
602 DecodeUnicode(WAPSettings->user, MessageBuffer + tmp+1,
603 MessageBuffer[tmp] );
606 fprintf(stdout, _(" User name: \"%s\"\n"),WAPSettings->user);
609 tmp=tmp+MessageBuffer[tmp]*2+1;
611 DecodeUnicode(WAPSettings->password, MessageBuffer + tmp+1,
612 MessageBuffer[tmp] );
615 fprintf(stdout, _(" Password: \"%s\"\n"),WAPSettings->password);
619 fprintf(stdout, _(" Authentication type: "));
620 switch (MessageBuffer[6]) {
621 case 0x00: fprintf(stdout,_("normal"));break;
622 case 0x01: fprintf(stdout,_("secure"));break;
623 default: fprintf(stdout,_("unknown"));break;
625 fprintf(stdout, _("\n"));
627 fprintf(stdout, _(" Data call type: "));
628 switch (MessageBuffer[7]) {
629 case 0x00: fprintf(stdout,_("analogue"));break;
630 case 0x01: fprintf(stdout,_("IDSN"));break;
631 default: fprintf(stdout,_("unknown"));break;
633 fprintf(stdout, _("\n"));
635 fprintf(stdout, _(" Data call speed: "));
636 switch (MessageBuffer[9]) {
637 case 0x01: fprintf(stdout,_("9600"));break;
638 case 0x02: fprintf(stdout,_("14400"));break;
639 default: fprintf(stdout,_("unknown"));break;
641 fprintf(stdout, _("\n"));
645 switch (MessageBuffer[6]) {
646 case 0x00: WAPSettings->isnormalauthentication=true;break;
647 case 0x01: WAPSettings->isnormalauthentication=false;break;
649 switch (MessageBuffer[7]) {
650 case 0x00: WAPSettings->isISDNcall=false;break;
651 case 0x01: WAPSettings->isISDNcall=true;break;
653 switch (MessageBuffer[9]) {
654 case 0x01: WAPSettings->isspeed14400=false;break;
655 case 0x02: WAPSettings->isspeed14400=true;break;
662 WAPSettings->bearer=WAPSETTINGS_BEARER_USSD;
665 fprintf(stdout, _(" Settings for USSD bearer:\n"));
670 DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1,
671 MessageBuffer[tmp] );
674 if (MessageBuffer[6]==0x01)
675 fprintf(stdout, _(" Service number: \"%s\"\n"),WAPSettings->service);
677 fprintf(stdout, _(" IP address: \"%s\"\n"),WAPSettings->service);
680 WAPSettings->isIP=true;
681 if (MessageBuffer[6]==0x01) WAPSettings->isIP=false;
683 tmp=tmp+MessageBuffer[tmp]*2+1;
685 DecodeUnicode(WAPSettings->code, MessageBuffer + tmp+1,
686 MessageBuffer[tmp] );
689 fprintf(stdout, _(" Service code: \"%s\"\n"),WAPSettings->code);
694 CurrentGetWAPSettingsError=GE_NONE;
699 GSM_Error N7110_GetWAPSettings (GSM_WAPSettings *settings)
701 unsigned char req[] = { N6110_FRAME_HEADER, 0x15, 0x00};
702 unsigned char req2[] = { N6110_FRAME_HEADER, 0x1b, 0x00};
706 /* We have to enable WAP frames in phone */
707 error=N7110_EnableWAPCommands ();
708 if (error!=GE_NONE) return error;
711 req[4]=settings->location-1;
713 WAPSettings=settings;
715 error=NULL_SendMessageSequence
716 (50, &CurrentGetWAPSettingsError, 6, 0x3f, req);
717 if (error!=GE_NONE) return error;
721 req2[4]=settings->location;
723 return NULL_SendMessageSequence
724 (50, &CurrentGetWAPSettingsError, 6, 0x3f, req2);
727 void N7110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
730 fprintf(stdout, _("Message: Memory status received:\n"));
733 if (CurrentMemoryStatus && CurrentMemoryStatusError == GE_BUSY) {
734 /* first Loc. (MessageBuffer[10]<<8) + MessageBuffer[11]; */
735 CurrentMemoryStatus->Free = (MessageBuffer[14]<<8) + MessageBuffer[15];
736 CurrentMemoryStatus->Used = (MessageBuffer[16]<<8) + MessageBuffer[17];
737 CurrentMemoryStatus->Free -= CurrentMemoryStatus->Used;
739 CurrentMemoryStatusError = GE_NONE;
742 fprintf(stdout, _(" Memory Type: %s\n"), N7110_MemoryType_String[MessageBuffer[5]]);
743 fprintf(stdout, _(" Used: %d\n"), CurrentMemoryStatus->Used);
744 fprintf(stdout, _(" Free: %d\n"), CurrentMemoryStatus->Free);
749 /* This function is used to get storage status from the phone. It currently
750 supports two different memory areas - internal and SIM. */
751 GSM_Error N7110_GetMemoryStatus(GSM_MemoryStatus *Status)
753 unsigned char req[] = { N6110_FRAME_HEADER,
754 0x03, /* MemoryStatus request */
756 0x05 /* MemoryType */
759 switch (Status->MemoryType) {
763 CurrentMemoryStatus = Status;
765 req[5] = N7110_GetMemoryType(Status->MemoryType);
767 return NULL_SendMessageSequence
768 (20, &CurrentMemoryStatusError, 6, 0x03, req);
779 return GE_NOTSUPPORTED;
783 void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
785 switch(MessageBuffer[3]) {
790 fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]);
793 switch (MessageBuffer[6]) {
794 case 0xff: /* Profile Name */
795 DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]);
797 fprintf(stdout,_(" Name \"%s\"\n"),CurrentProfile->Name);
802 case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */
803 switch( MessageBuffer[10] ) {
805 CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break;
809 CurrentProfile->KeypadTone = MessageBuffer[10]-1; break;
813 case 0x02: /* Call Alert type (Ringing, Ascending, ..., Off) */
814 /* I make it compatible with GetProfileCallAlertString */
815 switch( MessageBuffer[10] ) {
816 case 0: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGING; break;
817 case 1: CurrentProfile->CallAlert = PROFILE_CALLALERT_ASCENDING; break;
818 case 2: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGONCE; break;
819 case 3: CurrentProfile->CallAlert = PROFILE_CALLALERT_BEEPONCE; break;
820 case 5: CurrentProfile->CallAlert = PROFILE_CALLALERT_OFF; break;
823 case 0x03: /* Ringtone number */
824 CurrentProfile->Ringtone = MessageBuffer[10];
826 case 0x04: /* Ringtone volume (from level 1 to level 5) */
827 CurrentProfile->Volume = MessageBuffer[10] + 6;
829 case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */
830 CurrentProfile->MessageTone = MessageBuffer[10];
832 case 0x06: /* Vibration (On/Off) */
833 CurrentProfile->Vibration = MessageBuffer[10];
835 case 0x07: /* WarningTone (On/Off) */
836 switch( MessageBuffer[10] ) {
838 CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break;
840 CurrentProfile->WarningTone = PROFILE_WARNING_ON; break;
843 case 0x08: /* Alert for (caller groups) */
844 CurrentProfile->CallerGroups = MessageBuffer[10];
846 case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */
847 CurrentProfile->AutomaticAnswer = MessageBuffer[10];
851 CurrentProfileError=GE_NONE;
856 fprintf(stdout, _("Message: Unknown message of type 0x39\n"));
858 AppendLogText("Unknown msg\n",false);
859 break; /* Visual C Don't like empty cases */
864 GSM_Error N7110_GetProfile(GSM_Profile *Profile)
868 unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
869 0x00, //profile number
870 0xff}; //feature. Here 0xff=name
872 unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22,
877 CurrentProfile = Profile;
879 /* When after sending all frames feature==253, it means, that it is not
881 CurrentProfile->KeypadTone=253;
882 CurrentProfile->Lights=253;
883 CurrentProfile->CallAlert=253;
884 CurrentProfile->Ringtone=253;
885 CurrentProfile->Volume=253;
886 CurrentProfile->MessageTone=253;
887 CurrentProfile->WarningTone=253;
888 CurrentProfile->Vibration=253;
889 CurrentProfile->CallerGroups=253;
890 CurrentProfile->ScreenSaver=253;
891 CurrentProfile->AutomaticAnswer=253;
893 req[7] = Profile->Number+1;
895 error=NULL_SendMessageSequence
896 (20, &CurrentProfileError, 9, 0x39, req);
897 if (error!=GE_NONE) return error;
899 for (i = 0; i < 11; i++) {
901 req[7] = Profile->Number+1;
905 error=NULL_SendMessageSequence
906 (20, &CurrentProfileError, 9, 0x39, req);
907 if (error!=GE_NONE) return error;
913 void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
917 CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5];
918 CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany;
920 for(i=0;i<CurrentCalendarNotesInfo.HowMany && i<MAX_NOTES_INFO_ELEMS;i++) {
921 CurrentCalendarNotesInfo.Location[i] = MessageBuffer[8+i*2]*256+ MessageBuffer[8+i*2+1];
922 CurrentCalendarNotesInfo2->Location[i]=CurrentCalendarNotesInfo.Location[i];
925 CurrentCalendarNotesInfoError=GE_NONE;
928 GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo)
930 unsigned char req[] = { N6110_FRAME_HEADER,
931 0x3a, /* get notes info */
936 CurrentCalendarNotesInfo2=NotesInfo;
938 error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req);
943 void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2)
950 if (alarmdiff == 0xffff) fprintf(stdout," No alarm");
951 else fprintf(stdout," Alarm is %i seconds before date", alarmdiff*alarm2);
952 fprintf(stdout,"\n");
955 if (alarmdiff != 0xffff) {
957 memset(&tm_time, 0, sizeof(tm_time));
958 tm_time.tm_year = time->Year - 1900;
959 tm_time.tm_mon = time->Month - 1;
960 tm_time.tm_mday = time->Day;
961 tm_time.tm_hour = time->Hour;
962 tm_time.tm_min = time->Minute;
963 tm_time.tm_sec = time->Second;
966 t_alarm = mktime(&tm_time);
967 t_alarm -= alarmdiff*alarm2;
969 tm_alarm = localtime(&t_alarm);
971 alarm->Year = tm_alarm->tm_year + 1900;
972 alarm->Month = tm_alarm->tm_mon + 1;
973 alarm->Day = tm_alarm->tm_mday;
974 alarm->Hour = tm_alarm->tm_hour;
975 alarm->Minute = tm_alarm->tm_min;
976 alarm->Second = tm_alarm->tm_sec;
979 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
980 alarm->Day,alarm->Month,alarm->Year,
981 alarm->Hour,alarm->Minute,alarm->Second);
986 void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
990 c->Time.Year = block[8]*256+block[9];
991 c->Time.Month = block[10];
992 c->Time.Day = block[11];
993 if (c->Type != GCN_REMINDER) {
994 c->Time.Hour = block[12];
995 c->Time.Minute = block[13];
1003 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1004 c->Time.Day,c->Time.Month,c->Time.Year,
1005 c->Time.Hour,c->Time.Minute,c->Time.Second);
1008 if (c->Type != GCN_REMINDER) {
1009 alarmdiff = block[14]*256 + block[15];
1010 P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60);
1012 c->Recurrance = block[16]*256 + block[17];
1013 DecodeUnicode(c->Text, block+20, block[18]);
1015 c->Recurrance = block[12]*256 + block[13];
1016 DecodeUnicode(c->Text, block+16, block[14]);
1019 /* 0xffff -> 1 Year (8760 hours) */
1020 if (c->Recurrance == 0xffff) c->Recurrance=8760;
1023 fprintf(stdout, " Recurrance: %i hours\n Text: \"%s\"\n",
1024 c->Recurrance,c->Text);
1028 void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1032 CurrentCalendarNote->YearOfBirth=0; //for other than birthday
1033 CurrentCalendarNote->AlarmType=0x00;//for other than birthday
1034 CurrentCalendarNote->Phone[0]=0; //for other than call
1036 CurrentCalendarNote->Alarm.Year = 0;
1037 CurrentCalendarNote->Alarm.Month = 0;
1038 CurrentCalendarNote->Alarm.Day = 0;
1039 CurrentCalendarNote->Alarm.Hour = 0;
1040 CurrentCalendarNote->Alarm.Minute = 0;
1041 CurrentCalendarNote->Alarm.Second = 0;
1044 fprintf(stdout, "Message: calendar note received\n");
1047 switch (MessageBuffer[6]) /* entry type */ {
1048 case 0x01: /* Meeting */
1050 fprintf(stdout, " Note type: meeting\n");
1052 CurrentCalendarNote->Type = GCN_MEETING;
1053 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1054 CurrentCalendarNoteError=GE_NONE;
1057 case 0x02: /* Call */
1059 fprintf(stdout, " Note type: call\n");
1061 CurrentCalendarNote->Type = GCN_CALL;
1062 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1063 DecodeUnicode(CurrentCalendarNote->Phone,
1064 MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]);
1066 fprintf(stdout, " Phone number: \"%s\"\n",CurrentCalendarNote->Phone);
1068 CurrentCalendarNoteError=GE_NONE;
1071 case 0x04: /* Birthday */
1073 fprintf(stdout, " Note type: birthday\n");
1075 CurrentCalendarNote->Type = GCN_BIRTHDAY;
1077 alarm = ((unsigned int)MessageBuffer[14]) << 24;
1078 alarm += ((unsigned int)MessageBuffer[15]) << 16;
1079 alarm += ((unsigned int)MessageBuffer[16]) << 8;
1080 alarm += MessageBuffer[17];
1082 /* CurrentCalendarNote->Time.Year is set earlier */
1083 CurrentCalendarNote->Time.Month = MessageBuffer[10];
1084 CurrentCalendarNote->Time.Day = MessageBuffer[11];
1085 CurrentCalendarNote->Time.Hour = 23;
1086 CurrentCalendarNote->Time.Minute = 59;
1087 CurrentCalendarNote->Time.Second = 58;
1088 P7110_GetNoteAlarm(alarm, &(CurrentCalendarNote->Time), &(CurrentCalendarNote->Alarm) ,1);
1090 CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19];
1091 CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth;
1093 CurrentCalendarNote->AlarmType = MessageBuffer[20];
1096 fprintf(stdout,_(" Alarm type: %s\n"),
1097 (CurrentCalendarNote->AlarmType==0x00) ? "Tone " : "Silent");
1099 fprintf(stdout, " Birthday date: %02i-%02i-%04i (age %d)\n",CurrentCalendarNote->Time.Day,
1100 CurrentCalendarNote->Time.Month,CurrentCalendarNote->Time.Year,
1101 CurrentCalendarNote->Alarm.Year - CurrentCalendarNote->Time.Year);
1104 DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]);
1106 fprintf(stdout, " Text: \"%s\"\n",CurrentCalendarNote->Text);
1109 CurrentCalendarNote->Recurrance = 0;
1110 CurrentCalendarNoteError=GE_NONE;
1113 case 0x08: /* Reminder */
1115 fprintf(stdout, " Note type: reminder\n");
1117 CurrentCalendarNote->Type = GCN_REMINDER;
1118 P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1119 CurrentCalendarNoteError=GE_NONE;
1122 default: /* unknown */
1124 fprintf(stdout, " Note type: UNKNOWN\n");
1130 GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
1132 unsigned char req[] = { N6110_FRAME_HEADER,
1133 0x19, /* get calendar note */
1134 0x00, 0x00 //location
1138 GSM_DateTime date_time;
1142 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1143 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1144 if (error!=GE_NONE) return error;
1148 fprintf(stdout, _("Calendar Notes Location Logical = %d.\n"),
1149 CalendarNote->Location);
1150 fprintf(stdout, _("Calendar Notes Location Phisical = %d.\n"),
1151 CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]);
1154 /* this is for making xgnokii work.. */
1155 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1156 return GE_INVALIDCALNOTELOCATION;
1158 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1159 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1160 CurrentCalendarNote = CalendarNote;
1162 /* We have to get current year. It's NOT written in frame for Birthday */
1163 error=N7110_GetDateTime(&date_time);
1164 if (error!=GE_NONE) return error;
1165 if (!date_time.IsSet) {
1167 now=localtime(&nowh);
1169 /* I have 100 (for 2000) Year now :-) */
1170 if (now->tm_year>99 && now->tm_year<1900) {
1171 now->tm_year=now->tm_year+1900;
1173 date_time.Year=now->tm_year;
1175 CurrentCalendarNote->Time.Year = date_time.Year;
1177 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1179 CurrentCalendarNote = NULL;
1184 void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1187 char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" };
1190 "Succesfully written Calendar Note Type %s on location %d\n",
1191 kz_types[(MessageBuffer[3]/2)-1],
1192 MessageBuffer[4]*256+MessageBuffer[5] );
1194 fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n",
1195 MessageBuffer[6]*256+MessageBuffer[7] );
1197 CurrentCalendarNoteError=GE_NONE;
1200 long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm)
1209 tm_alarm.tm_year=alarm->Year-1900;
1210 tm_alarm.tm_mon=alarm->Month-1;
1211 tm_alarm.tm_mday=alarm->Day;
1212 tm_alarm.tm_hour=alarm->Hour;
1213 tm_alarm.tm_min=alarm->Minute;
1214 tm_alarm.tm_sec=alarm->Second;
1215 tm_alarm.tm_isdst=0;
1216 t_alarm = mktime(&tm_alarm);
1218 tm_time.tm_year=time->Year-1900;
1219 tm_time.tm_mon=time->Month-1;
1220 tm_time.tm_mday=time->Day;
1221 tm_time.tm_hour=time->Hour;
1222 tm_time.tm_min=time->Minute;
1223 tm_time.tm_sec=time->Second;
1225 t_time = mktime(&tm_time);
1228 fprintf(stdout, " Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
1229 alarm->Day,alarm->Month,alarm->Year,
1230 alarm->Hour,alarm->Minute,alarm->Second);
1231 fprintf(stdout, " Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1232 time->Day,time->Month,time->Year,
1233 time->Hour,time->Minute,time->Second);
1234 fprintf(stdout,_("Difference in alarm time is %f\n"),difftime( t_time, t_alarm )+3600);
1237 return difftime( t_time ,t_alarm )+3600;
1240 GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
1242 unsigned char req[200] = { N6110_FRAME_HEADER,
1243 0x01, /* note type ... */
1244 0x00, 0x00, /* location */
1245 0x00, /* entry type */
1247 0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */
1248 /* here starts block */
1249 0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */
1253 long seconds, minutes;
1256 int firstFreeLocation;
1259 * 6210/7110 needs to seek the first free pos to inhabit with next note
1261 error=N7110_FirstCalendarFreePos(&firstFreeLocation);
1262 if (error!=GE_NONE) return error;
1265 fprintf(stdout, _("First free calendar location is = %d.\n"),
1273 switch( CalendarNote->Type ) {
1274 case GCN_MEETING : req[6]=0x01; req[3]=0x01; break;
1275 case GCN_CALL : req[6]=0x02; req[3]=0x03; break;
1276 case GCN_BIRTHDAY: req[6]=0x04; req[3]=0x05; break;
1277 case GCN_REMINDER: req[6]=0x08; req[3]=0x07; break;
1280 req[8]=CalendarNote->Time.Year>>8;
1281 req[9]=CalendarNote->Time.Year&0xff;
1282 req[10]=CalendarNote->Time.Month;
1283 req[11]=CalendarNote->Time.Day;
1285 /* From here starts BLOCK */
1287 switch( CalendarNote->Type ) {
1290 req[count++]=CalendarNote->Time.Hour; // 12
1291 req[count++]=CalendarNote->Time.Minute; // 13
1293 req[count++]=0xff; // 14
1294 req[count++]=0xff; // 15
1295 if( CalendarNote->Alarm.Year )
1297 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1298 &CalendarNote->Alarm);
1299 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1300 minutes=seconds/60L;
1302 req[count++]=minutes>>8;
1303 req[count++]=minutes&0xff;
1307 if( CalendarNote->Recurrance >= 8760 )
1308 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1309 req[count++]=CalendarNote->Recurrance>>8; // 16
1310 req[count++]=CalendarNote->Recurrance&0xff; // 17
1312 req[count++]=strlen(CalendarNote->Text); // 18
1314 req[count++]=0x00; // 19
1317 fprintf(stdout, "Count before encode = %d\n", count );
1318 fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text );
1321 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1322 count=count+2*strlen(CalendarNote->Text);
1326 req[count++]=CalendarNote->Time.Hour; // 12
1327 req[count++]=CalendarNote->Time.Minute; // 13
1329 req[count++]=0xff; // 14
1330 req[count++]=0xff; // 15
1331 if( CalendarNote->Alarm.Year )
1333 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1334 &CalendarNote->Alarm);
1335 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1336 minutes=seconds/60L;
1338 req[count++]=minutes>>8;
1339 req[count++]=minutes&0xff;
1343 if( CalendarNote->Recurrance >= 8760 )
1344 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1345 req[count++]=CalendarNote->Recurrance>>8; // 16
1346 req[count++]=CalendarNote->Recurrance&0xff; // 17
1348 req[count++]=strlen(CalendarNote->Text); // 18
1350 req[count++]=strlen(CalendarNote->Phone); // 19
1352 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1353 count=count+2*strlen(CalendarNote->Text);
1354 EncodeUnicode (req+count,CalendarNote->Phone ,strlen(CalendarNote->Phone));// (N+1)->n
1355 count=count+2*strlen(CalendarNote->Phone);
1359 req[count++]=0x00; // 12 Fixed
1360 req[count++]=0x00; // 13 Fixed
1363 req[count++]=0x00; req[count++]=0x00; // 14, 15
1364 req[count++]=0xff; // 16
1365 req[count++]=0xff; // 17
1366 if( CalendarNote->Alarm.Year ) {
1367 // I try with Time.Year = Alarm.Year. If negative, I increase 1 year,
1368 // but only once ! This thing, because I may have Alarm period across
1369 // a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27)
1371 CalendarNote->Time.Year = CalendarNote->Alarm.Year;
1372 if( (seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1373 &CalendarNote->Alarm)) < 0L ) {
1374 CalendarNote->Time.Year++;
1375 seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1376 &CalendarNote->Alarm);
1378 if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1380 req[count++]=seconds>>24; // 14
1381 req[count++]=(seconds>>16) & 0xff; // 15
1382 req[count++]=(seconds>>8) & 0xff; // 16
1383 req[count++]=seconds&0xff; // 17
1387 req[count++]=CalendarNote->AlarmType; // 18
1390 req[count++]=strlen(CalendarNote->Text); // 19
1394 fprintf(stdout, "Count before encode = %d\n", count );
1395 fprintf(stdout, "Meeting Text is = \"%s\" Altype is 0x%02x \n", CalendarNote->Text , CalendarNote->AlarmType );
1397 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N
1398 count=count+2*strlen(CalendarNote->Text);
1403 if( CalendarNote->Recurrance >= 8760 )
1404 CalendarNote->Recurrance = 0xffff; /* setting 1 Year repeat */
1405 req[count++]=CalendarNote->Recurrance>>8; // 12
1406 req[count++]=CalendarNote->Recurrance&0xff; // 13
1408 req[count++]=strlen(CalendarNote->Text); // 14
1410 req[count++]=0x00; // 15
1412 EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N
1413 count=count+2*strlen(CalendarNote->Text);
1420 fprintf(stdout, "Count after padding = %d\n", count );
1423 CurrentCalendarNote = CalendarNote;
1425 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req);
1427 CurrentCalendarNote = NULL;
1432 void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1434 *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5];
1435 CurrentFirstCalendarFreePosError=GE_NONE;
1438 GSM_Error N7110_FirstCalendarFreePos(int *FreePos)
1440 unsigned char req[] = { N6110_FRAME_HEADER, 0x31 };
1444 CurrentFirstCalendarFreePos = FreePos;
1446 error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError,
1449 CurrentFirstCalendarFreePos = NULL;
1454 void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1458 "Succesfully Delete Calendar Note on location %d\n",
1459 MessageBuffer[4]*256+MessageBuffer[5] );
1461 fprintf(stdout, "--> Other data are :\n" );
1462 fprintf(stdout, " '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d)\n",
1463 MessageBuffer[6], MessageBuffer[6], MessageBuffer[6],
1464 MessageBuffer[7], MessageBuffer[7], MessageBuffer[7],
1465 MessageBuffer[8], MessageBuffer[8], MessageBuffer[8],
1466 MessageBuffer[9], MessageBuffer[9], MessageBuffer[9] );
1468 CurrentCalendarNoteError=GE_NONE;
1471 GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
1473 unsigned char req[] = { N6110_FRAME_HEADER,
1474 0x0b, /* delete calendar note */
1475 0x00, 0x00 //location
1480 if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1481 error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1482 if (error!=GE_NONE) return error;
1485 /* this is for making xgnokii work.. */
1486 if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1487 return GE_INVALIDCALNOTELOCATION;
1489 req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1490 req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1492 CurrentCalendarNote = CalendarNote;
1494 error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1496 CurrentCalendarNote = NULL;
1501 void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1508 fprintf(stdout, _("Message: SMS Folders received:\n"));
1513 CurrentSMSFoldersCount=MessageBuffer[4];
1515 for (j=0;j<MessageBuffer[4];j++) {
1516 strcpy(CurrentSMSFolders->Folder[j].Name," ");
1518 fprintf(stdout, _(" Folder Index: %d"),MessageBuffer[i]);
1520 CurrentSMSFolders->FoldersID[j]=MessageBuffer[i];
1525 fprintf(stdout, _(", folder name: "));
1528 while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) {
1530 wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8);
1532 CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc);
1534 fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]);
1540 fprintf(stdout, _("\n"));
1546 CurrentSMSFoldersError=GE_NONE;
1549 GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders)
1551 unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
1555 CurrentSMSFolders=folders;
1557 error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req);
1559 folders->number=CurrentSMSFoldersCount;
1564 void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1569 fprintf(stdout, _("Message: SMS Folder status received\n"));
1570 fprintf(stdout, _(" Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]);
1572 CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5];
1574 fprintf(stdout, _(" (indexes "));
1577 for (i=0;i<MessageBuffer[4]*256+MessageBuffer[5];i++) {
1579 fprintf(stdout, _("%i, "), MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7]);
1581 CurrentSMSFolder.locations[i]=MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7];
1585 fprintf(stdout, _(")\n"));
1588 CurrentSMSFolderError=GE_NONE;
1591 GSM_Error N7110_GetSMSFolderStatus ( GSM_OneSMSFolder *folder, u8 ID)
1593 unsigned char req[] = { N7110_FRAME_HEADER,
1601 CurrentSMSFolder = *folder;
1602 CurrentSMSFolderID = ID;
1605 error=NULL_SendMessageSequence(20, &CurrentSMSFolderError, 7, 0x14, req);
1607 *folder=CurrentSMSFolder;
1612 void N7110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1616 fprintf(stdout, _("Message: SMS deleted succesfully\n"));
1618 CurrentSMSMessageError = GE_NONE;
1621 GSM_Error N7110_DeleteSMSMessage(GSM_SMSMessage *message)
1623 unsigned char req[] = {
1624 N7110_FRAME_HEADER, 0x0a, /* delete SMS request */
1625 0x00, /* folder (req[4])*/
1626 0x00, /* location */
1627 0x00, /* location (req[6])*/
1631 int smsnum, location;
1634 smsnum = message->Location;
1635 /* We made "fake" SMS numbering for SMS in 7110/6210/etc. */
1636 if ((error = N7110_HandleSMSLocation(smsnum, &folderid, &location, NULL, GSH_DELETE))!=GE_NONE)
1640 req[5]=location / 256;
1644 printf("delete sms: folder %d, location %d\n",folderid,location);
1647 return NULL_SendMessageSequence
1648 (50, &CurrentSMSMessageError, 8, 0x14, req);
1651 GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message)
1654 unsigned char req[] = { N6110_FRAME_HEADER,
1657 0x00, 0x05, // location
1662 int smsnum, location;
1666 CurrentSMSMessage = message;
1667 CurrentSMSMessageError = GE_BUSY;
1670 smsnum = message->Location;
1672 /* we make central handling of real location */
1673 error = N7110_HandleSMSLocation(smsnum, &folderid, &location, message, GSH_GET);
1674 /* if smsnum is 0 (next sms) we need real smsnum */
1675 N7110_SMS2FakeLocation( &smsnum, folderid, location);
1676 message->Location = smsnum;
1679 case GE_SMSISINMEM: /* future use: get already reed sms from mem */
1682 case GE_NONE: req[4]=folderid;
1683 req[5]=location / 256;
1686 fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location);
1688 return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req);
1696 void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1700 switch (MessageBuffer[3]) {
1705 fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]);
1708 if (CurrentSMSMessage!=NULL) {
1709 N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]);
1710 CurrentSMSMessage->MessageNumber=smsnum;
1713 CurrentSMSMessageError = GE_NONE;
1716 /* save sms failed */
1720 fprintf(stdout, _("Message: SMS Message save failed\n"));
1722 CurrentSMSMessageError = GE_SMSSAVEFAILED;
1727 fprintf(stdout, _("Message: Changed name for SMS Message\n"));
1729 CurrentSMSMessageError = GE_NONE;
1735 GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS)
1737 unsigned char req[256] = {
1738 N6110_FRAME_HEADER, 0x04, /* SMS save request*/
1739 0x03, /* default: mark sms as GSS_NOTSENTREAD */
1740 0x10, /* folder (req[5])*/
1741 0x00, /* location */
1742 0x00, /* location (req[7])*/
1746 unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83};
1748 int length,smsnum,location;
1751 SMS_MessageType PDU;
1753 smsnum = SMS->Location;
1756 printf("save sms: smsnum is :%d\n",smsnum);
1759 if ( SMS->Status == GSS_SENTREAD) req[4] = 0x01;
1761 folderid = SMS->folder;
1765 error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU);
1766 if (error != GE_NONE) return error;
1768 CurrentSMSMessage = SMS;
1770 error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE);
1774 case GE_BUSYSMSLOCATION: /* delete old sms before save */
1775 error = N7110_DeleteSMSMessage(SMS);
1776 if (error != GE_NONE) return error;
1786 printf("save sms: want to save at folder:%d , location:%d\n",folderid,location);
1790 req[6]=location / 256;
1793 error=NULL_SendMessageSequence
1794 (70, &CurrentSMSMessageError, 40+length, 0x14, req);
1796 if (error==GE_NONE && SMS->Name[0]!=0) {
1798 N7110_Fake2SMSLocation(SMS->MessageNumber, &folderid, &location);
1799 req2[length++]=folderid;
1800 req2[length++]=location / 256;
1801 req2[length++]=location;
1802 EncodeUnicode(req2+length, SMS->Name, strlen(SMS->Name));
1803 length=length+strlen(SMS->Name)*2;
1806 error=NULL_SendMessageSequence
1807 (70, &CurrentSMSMessageError, length, 0x14, req2);
1813 /* handling for 7110 folders */
1814 GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action)
1817 static int nextSMSmessage = -1;
1818 static GSM_SMSStatus Status;
1822 GSM_OneSMSFolder onefolder;
1828 case GSH_DELETE: /* future use: delete sms in mem -> free memory */
1829 /* for now we make same as in GSH_GET */
1830 case GSH_GET: /* if smsnum == 0 user wants to read next sms */
1833 /* first time we read folderstatus */
1834 if ( nextSMSmessage == -1)
1837 error = N7110_GetSMSStatus( &Status);
1838 if (error!=GE_NONE) return error;
1840 ismsnum = Status.foldertable[nextSMSmessage].smsnum;
1841 N7110_Fake2SMSLocation( ismsnum, folder, location);
1843 if(nextSMSmessage >= Status.Number)
1845 nextSMSmessage = -1;
1847 printf("HandleSMS: setting nextSMSmessage to -1\n");
1850 } else /* user give location -> make fake location */
1852 /* future use: get already read sms from mem */
1853 N7110_Fake2SMSLocation( smsnum, folder, location);
1856 case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */
1859 /* calculate correct folderid */
1860 *folder = ( *folder + 1) * 8;
1863 } else /* user give location -> make fake location */
1865 N7110_Fake2SMSLocation( smsnum, folder, location);
1868 error=N7110_GetSMSFolderStatus(&onefolder, folderid );
1869 if (error!=GE_NONE) return error;
1871 /* is there a sms at that location ? */
1872 for (i=0; i<CurrentSMSFolder.number; i++)
1873 if ( CurrentSMSFolder.locations[i] == *location ) found = true;
1875 if (found == true) return GE_BUSYSMSLOCATION;
1876 else return GE_NONE;
1885 /* input: fake smsnum, output: folderid & location */
1886 void N7110_Fake2SMSLocation(int smsnum, u8 *folderid, int *location)
1890 ifolderid = smsnum / N7110_MAXSMSINFOLDER;
1891 *folderid = ifolderid * 0x08;
1892 *location = smsnum - ifolderid * N7110_MAXSMSINFOLDER;
1895 /* input; folderid & location, output: fake smsnum */
1896 void N7110_SMS2FakeLocation(int *smsnum, u8 folderid, int location)
1900 ifolderid = folderid / 0x08;
1901 *smsnum = ifolderid * N7110_MAXSMSINFOLDER + location;
1904 GSM_Error N7110_GetRFLevel(GSM_RFUnits *units, float *level)
1906 unsigned char request[] = {N6110_FRAME_HEADER, 0x81};
1913 Protocol->SendMessage(4, 0x0a, request);
1915 /* Wait for timeout or other error. */
1916 while (timeout != 0 && CurrentRFLevel == -1 ) {
1919 return (GE_TIMEOUT);
1924 /* Make copy in case it changes. */
1925 rf_level = CurrentRFLevel;
1930 /* Now convert between the different units we support. */
1932 /* Arbitrary units. */
1933 *units = GRF_Percentage;
1938 GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1940 unsigned char request[] = {N6110_FRAME_HEADER, 0x02};
1945 CurrentBatteryLevel=-1;
1947 Protocol->SendMessage(4, 0x17, request);
1949 /* Wait for timeout or other error. */
1950 while (timeout != 0 && CurrentBatteryLevel == -1 ) {
1953 return (GE_TIMEOUT);
1958 /* Take copy in case it changes. */
1959 batt_level = CurrentBatteryLevel;
1961 if (batt_level == -1)
1964 /* Only units we handle at present are GBU_Arbitrary */
1965 *units = GBU_Percentage;
1966 *level = batt_level;
1970 GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
1972 unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c};
1974 if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED;
1976 CurrentSecurityCode=SecurityCode;
1978 return NULL_SendMessageSequence
1979 (50, &CurrentSecurityCodeError, 5, 0x7a, req);
1982 GSM_Error N7110_GetDateTime(GSM_DateTime *date_time)
1984 return N6110_PrivGetDateTime(date_time,0x19);
1987 /* Needs SIM card with PIN in phone */
1988 GSM_Error N7110_SetDateTime(GSM_DateTime *date_time)
1990 return N6110_PrivSetDateTime(date_time,0x19);
1993 GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1995 return N6110_PrivGetAlarm(alarm_number,date_time,0x19);
1998 /* FIXME: we should also allow to set the alarm off :-) */
1999 GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
2001 return N6110_PrivSetAlarm(alarm_number,date_time, 0x19);
2004 void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2006 switch (MessageBuffer[3]) {
2012 fprintf(stdout, _("Message: SMS Status Received\n"));
2013 fprintf(stdout, _(" Used msg in phone memory: %i\n"),MessageBuffer[10]*256+MessageBuffer[11]);
2014 fprintf(stdout, _(" Unread msg in phone memory: %i\n"),MessageBuffer[12]*256+MessageBuffer[13]);
2015 fprintf(stdout, _(" Used msg in SIM: %i\n"),MessageBuffer[14]*256+MessageBuffer[15]);
2016 fprintf(stdout, _(" Unread msg in SIM: %i\n"),MessageBuffer[16]*256+MessageBuffer[17]);
2018 CurrentSMSStatus->UnRead = MessageBuffer[13];
2019 CurrentSMSStatusError = GE_NONE;
2025 fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
2027 CurrentSMSStatusError = GE_INTERNALERROR;
2033 GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status)
2035 /* RTH FIXME: what is exact meaning of 0x0037 answer ? */
2036 /* we check all folders, but get sum of unread sms via 0x0036 request */
2037 unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
2039 GSM_SMSFolders folders;
2040 GSM_OneSMSFolder folder;
2043 int ismsnum,ilocation;
2046 CurrentSMSStatus = Status;
2048 /* read all SMS folders */
2049 /* check for unread messages in folder 0xf8 */
2050 error = N7110_GetSMSFolderStatus(&folder, 0xf8);
2051 if (error != GE_NONE) return error;
2054 for(j=0; j<folder.number; j++)
2056 ifolder = 0; /*read unread messages from folder 0 */
2057 ilocation = folder.locations[j];
2058 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation) ;
2059 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2060 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2061 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2065 /* read standard folders */
2066 N7110_GetSMSFolders (&folders);
2067 for(i=0; i<CurrentSMSFoldersCount; i++)
2069 error = N7110_GetSMSFolderStatus(&CurrentSMSFolders->Folder[i], CurrentSMSFolders->FoldersID[i]);
2070 if (error != GE_NONE) return error;
2072 for(j=0; j<CurrentSMSFolders->Folder[i].number; j++)
2074 ifolder = CurrentSMSFolders->FoldersID[i];
2075 ilocation = CurrentSMSFolders->Folder[i].locations[j];
2076 N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation);
2077 CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum;
2078 CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder;
2079 CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation;
2083 CurrentSMSStatus->Number = smsmaxnum;
2085 return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req);
2088 void N7110_DecodePhonebookFrame(GSM_PhonebookEntry *entry,u8 *MessageBuffer,u16 MessageLength)
2091 unsigned char *pBlock;
2098 pBlock = &MessageBuffer[0];
2100 while (length!=MessageLength) {
2101 GSM_SubPhonebookEntry* pEntry = &entry->SubEntries[blockcount];
2104 fprintf(stdout,_(" "));
2105 for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]);
2106 fprintf(stdout,_("\n"));
2109 switch( pBlock[0] ) {
2110 case N7110_ENTRYTYPE_SPEEDDIAL:
2112 CurrentSpeedDialEntry->MemoryType = GMT_SM;
2113 if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME;
2115 CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256;
2118 fprintf(stdout, _(" Speed dial\n"));
2119 fprintf(stdout, _(" Location: %d\n"), CurrentSpeedDialEntry->Location);
2120 fprintf(stdout, _(" MemoryType: %i\n"), CurrentSpeedDialEntry->MemoryType);
2121 fprintf(stdout, _(" Number: %d\n"), CurrentSpeedDialEntry->Number);
2124 CurrentSpeedDialError=GE_NONE;
2127 case N7110_ENTRYTYPE_NAME:
2128 DecodeUnicode (entry->Name, pBlock+6, pBlock[5]/2);
2129 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2130 strncpy(CurrentGetBitmap->text,entry->Name,sizeof(CurrentGetBitmap->text));
2131 entry->Empty = false;
2133 fprintf(stdout, _(" Name:\n"));
2134 fprintf(stdout, _(" Name: %s\n"), entry->Name);
2138 case N7110_ENTRYTYPE_NUMBER:
2139 pEntry->EntryType = pBlock[0];
2140 pEntry->NumberType = pBlock[5];
2141 pEntry->BlockNumber = pBlock[4];
2143 DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2);
2146 fprintf(stdout, _(" Number:\n"));
2147 fprintf(stdout, _(" Type: %d (%02x)\n"),pEntry->NumberType,pEntry->NumberType);
2148 fprintf(stdout, _(" Number: %s\n"),pEntry->data.Number);
2150 if( pEntry->EntryType == GSM_Number &&
2151 ((pEntry->NumberType == GSM_General && !strcmp(entry->Number,""))
2152 || pEntry->NumberType == GSM_SIM)) {
2153 strcpy( entry->Number, pEntry->data.Number );
2154 *pEntry->data.Number = 0;
2158 case N7110_ENTRYTYPE_DATE:
2159 pEntry->EntryType = pBlock[0];
2160 pEntry->NumberType = pBlock[5];
2161 pEntry->BlockNumber = pBlock[4];
2162 DecodeDateTime(pBlock+6, &pEntry->data.Date);
2164 fprintf(stdout, _(" Date:\n"));
2165 fprintf(stdout, _(" Date: %02u.%02u.%04u\n"), pEntry->data.Date.Day,
2166 pEntry->data.Date.Month, pEntry->data.Date.Year );
2167 fprintf(stdout, _(" Time: %02u:%02u:%02u\n"), pEntry->data.Date.Hour,
2168 pEntry->data.Date.Minute, pEntry->data.Date.Second);
2172 case N7110_ENTRYTYPE_NOTE:
2173 case N7110_ENTRYTYPE_POSTAL:
2174 case N7110_ENTRYTYPE_EMAIL:
2175 pEntry->EntryType = pBlock[0];
2176 pEntry->NumberType = 0;
2177 pEntry->BlockNumber = pBlock[4];
2179 DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2);
2182 fprintf(stdout, _(" Email or note or postal:\n"));
2183 fprintf(stdout, _(" Type: %d (%02x)\n"),pEntry->EntryType,pEntry->EntryType);
2184 fprintf(stdout, _(" Text: %s\n"),pEntry->data.Number);
2188 case N7110_ENTRYTYPE_GROUP:
2189 entry->Group = pBlock[5]-1; /* 0 = family as for 6110 */
2190 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2191 CurrentGetBitmap->number = entry->Group;
2193 fprintf(stdout, _(" Group: %d\n"), entry->Group);
2196 case N7110_ENTRYTYPE_RINGTONE:
2197 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2198 CurrentGetBitmap->ringtone = pBlock[5];
2200 fprintf(stdout, _(" Group ringtone number %d received.\n"), pBlock[5]);
2203 case N7110_ENTRYTYPE_LOGOON:
2204 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2205 CurrentGetBitmap->enabled = pBlock[5];
2207 fprintf(stdout, _(" Logo enabled = %d received.\n"), pBlock[5]);
2210 case N7110_ENTRYTYPE_GROUPLOGO:
2212 fprintf(stdout, _(" Caller group logo received.\n"));
2214 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
2215 CurrentGetBitmap->width = pBlock[5];
2216 CurrentGetBitmap->height= pBlock[6];
2217 CurrentGetBitmap->size = pBlock[9];
2218 if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
2219 CurrentGetBitmap->size = CurrentGetBitmap->size;
2220 memcpy(CurrentGetBitmap->bitmap,pBlock+10,CurrentGetBitmap->size);
2226 fprintf(stdout, _(" Unknown Entry Code (%u) received.\n"), pBlock[0] );
2232 fprintf(stdout, _(" Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]);
2234 length=length+pBlock[3];
2236 pBlock = &pBlock[(int) pBlock[3]];
2239 entry->SubEntriesCount = blockcount;
2242 fprintf(stdout, _(" SubBlocks: %d\n"),entry->SubEntriesCount);
2246 void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2249 CurrentPhonebookEntry->Empty = true;
2250 CurrentPhonebookEntry->Group = 5; /* 5 = no group as 6110 */
2251 CurrentPhonebookEntry->Name[0] = '\0';
2252 CurrentPhonebookEntry->Number[0] = '\0';
2253 CurrentPhonebookEntry->SubEntriesCount = 0;
2256 fprintf(stdout, _("Message: Phonebook entry received:\n"));
2259 if( MessageBuffer[6] == 0x0f ) // not found
2262 fprintf(stdout, _(" Error %i\n"),MessageBuffer[10]);
2263 switch (MessageBuffer[10]) {
2264 case 0x34:fprintf(stdout,_(" Invalid phonebook location\n"));break;
2265 case 0x3b:fprintf(stdout,_(" Speed dial not assigned\n"));break;
2266 default :fprintf(stdout,_(" Unknown.Please report\n"));break;
2269 switch (MessageBuffer[10]) {
2270 case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break;
2271 case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break;
2272 default :CurrentPhonebookError = GE_UNKNOWN;
2274 CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
2277 CurrentPhonebookEntry->Location=MessageBuffer[13]+MessageBuffer[12]*256;
2280 fprintf(stdout,_(" Location: %i\n"),CurrentPhonebookEntry->Location);
2283 N7110_DecodePhonebookFrame(CurrentPhonebookEntry,MessageBuffer+18,MessageLength-18);
2285 CurrentPhonebookError = GE_NONE;
2289 /* Routine to get specifed phone book location. Designed to be called by
2290 application. Will block until location is retrieved or a timeout/error
2292 GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) {
2294 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2297 0x00, 0x00, //location
2300 CurrentPhonebookEntry = entry;
2302 req[9] = N7110_GetMemoryType(entry->MemoryType);
2303 req[10] = (entry->Location>>8);
2304 req[11] = entry->Location & 0xff;
2306 return NULL_SendMessageSequence
2307 (50, &CurrentPhonebookError, 14, 0x03, req);
2310 void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2312 // [12,13] = Location
2315 if( MessageBuffer[6] == 0x0f ) // ERROR
2318 /* I didn't find any error when the Text,Name or Number was too long
2319 My Phone 7110; NSE-5; SW 04.84 */
2320 switch( MessageBuffer[10] ) {
2321 case 0x3d: fprintf(stdout, _("Error: Wrong Entry Type.\n")); break;
2322 case 0x3e: fprintf(stdout, _("Error: Too much entries.\n")); break;
2323 default : fprintf(stdout, _("Error: Unknown error (%u).\n"), MessageBuffer[10]); break;
2326 CurrentPhonebookError = GE_NONE;
2329 fprintf(stdout, _("Message: Phonebook written correctly.\n"));
2332 CurrentPhonebookError = GE_NONE;
2336 int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block)
2339 fprintf(stdout,_("Adding block id:%i,number:%i,length:%i\n"),id,no+1,size+6);
2345 *(block++) = size + 6;
2346 *(block++) = no + 1;
2348 memcpy(block, buf, size);
2356 int N7110_EncodePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block2)
2358 int count=0, len, i, block=0;
2363 len = strlen(entry.Name);
2364 string[0] = len * 2; // Length ot the string (without Termination)
2365 EncodeUnicode((string + 1), entry.Name, len);
2366 string[len * 2 + 1] = 0; // Terminating 0
2367 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, len * 2 + 2, block++, string, req + count);
2369 if (*entry.Number) {
2370 len = strlen(entry.Number);
2371 string[0] = N7110_ENTRYTYPE_NUMBER;
2372 string[1] = string[2] = string[3] = 0;
2373 string[4] = len * 2; // length (without Termination)
2374 EncodeUnicode((string + 5), entry.Number, len);
2375 string[len * 2 + 5] = 0; // Terminating 0
2376 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, block++, string, req + count);
2379 /* Rest of the subentries */
2380 for (i = 0; i < entry.SubEntriesCount; i++) {
2381 len = strlen(entry.SubEntries[i].data.Number);
2382 if (entry.SubEntries[i].EntryType != GSM_Number) {
2383 string[0] = len * 2; // length (without Termination)
2384 EncodeUnicode((string + 1), entry.SubEntries[i].data.Number, len);
2385 string[len * 2 + 1] = 0; // Terminating 0
2386 count += N7110_PackPBKBlock(entry.SubEntries[i].EntryType, len * 2 + 2, block++, string, req + count);
2388 string[0] = entry.SubEntries[i].NumberType;
2389 string[1] = string[2] = string[3] = 0;
2390 string[4] = len * 2; //length (without Termination)
2391 EncodeUnicode((string + 5), entry.SubEntries[i].data.Number, len);
2392 string[len * 2 + 5] = 0; // Terminating 0
2393 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NUMBER, len * 2 + 6, block++, string, req + count);
2397 if (entry.Group != 5) {
2399 string[0] = entry.Group + 1;
2401 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2409 /* Routine to write phonebook location in phone. */
2410 GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
2412 unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2413 0x00, 0x00, /* memory type */
2414 0x00, 0x00, /* location */
2416 int count = 18, blocks;
2418 if (entry->Name[0] != '\0' || entry->Number[0] != '\0') {
2419 req[11] = N7110_GetMemoryType(entry->MemoryType);
2420 req[12] = (entry->Location >> 8);
2421 req[13] = entry->Location & 0xff;
2423 // if (entry->MemoryType == GMT_SM) entry->SubEntriesCount = 0;
2425 count=count+N7110_EncodePhonebookFrame(req+18, *entry, &blocks);
2430 fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name);
2433 return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req);
2437 /* empty name & number => we have to delete the phonebook record! */
2438 return N7110_DeletePhonebookLocation( entry );
2443 void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2446 fprintf(stdout, _("Message: Phonebook entry deleted correctly\n"));
2448 CurrentPhonebookError = GE_NONE;
2451 /* delete phonebookentry */
2452 /* Not used in this moment */
2453 GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry)
2455 unsigned char req[256] = {
2456 N7110_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04,
2457 0x00, 0x00, 0x0c, 0x01, 0xff,
2458 0x00, /* location low*/
2459 0x01, /* location high*/
2460 0x05, /* mem location low*/
2461 0x00, /* mem location high*/
2465 req[12] = (entry->Location >> 8);
2466 req[13] = entry->Location & 0xff;
2467 req[14] = N7110_GetMemoryType(entry->MemoryType);
2470 fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location);
2473 return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req);
2476 /* for saving group logos only */
2477 GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap)
2479 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2480 0x00, 0x10, /* memory type */
2481 0x00, 0x00, /* location */
2485 unsigned int count = 18;
2487 req[13] = bitmap->number + 1;
2490 string[0] = bitmap->enabled?1:0;
2492 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count);
2495 string[0] = bitmap->ringtone;
2497 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count);
2499 /* Number of group */
2500 string[0] = bitmap->number+1;
2502 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2505 if (*bitmap->text) {
2506 i = strlen(bitmap->text);
2507 string[0] = i * 2 + 2;
2508 EncodeUnicode((string + 1), bitmap->text, i);
2509 string[i * 2 + 1] = 0; // Terminating 0
2510 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 2, block++, string, req + count);
2514 string[0] = bitmap->width;
2515 string[1] = bitmap->height;
2518 string[4] = bitmap->size;
2519 memcpy(string + 5, bitmap->bitmap, bitmap->size);
2520 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUPLOGO, bitmap->size + 5, block++, string, req + count);
2522 req[17] = block; //number of blocks
2524 return NULL_SendMessageSequence
2525 (50, &CurrentPhonebookError, count, 0x03, req);
2528 GSM_Error N7110_GetSpeedDial(GSM_SpeedDial *entry)
2530 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2533 0x00, 0x00, //location
2536 GSM_PhonebookEntry entry2;
2539 CurrentPhonebookEntry = &entry2;
2541 CurrentSpeedDialEntry = entry;
2543 req[9] = N7110_MEMORY_SD;
2544 req[10] = (entry->Number>>8);
2545 req[11] = entry->Number & 0xff;
2547 error=NULL_SendMessageSequence
2548 (50, &CurrentSpeedDialError, 14, 0x03, req);
2550 /* Full compatibility with 6110 */
2551 if (error==GE_INVALIDSPEEDDIALLOCATION) {
2553 entry->MemoryType=GMT_MT;
2555 } else return error;
2558 /* Experimental ! */
2559 GSM_Error N7110_SetSpeedDial(GSM_SpeedDial *entry)
2561 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2562 0x00, 0x0e, /* memory type */
2563 0x00, 0x00, /* location */
2567 unsigned int count = 18;
2569 req[13] = entry->Number;
2572 string[1]= entry->Location/256;
2573 string[2]= entry->Location%256;
2575 string[4]= string[5] = 0;
2576 count += N7110_PackPBKBlock(N7110_ENTRYTYPE_SPEEDDIAL, 6, block++, string, req + count);
2578 req[17] = block - 1; //number of blocks
2580 return NULL_SendMessageSequence
2581 (50, &CurrentPhonebookError, count, 0x03, req);
2584 /* Set a bitmap or welcome-note */
2585 GSM_Error N7110_SetBitmap(GSM_Bitmap *Bitmap)
2587 unsigned char reqStartup[1000] = { N7110_FRAME_HEADER,
2588 0xec, 0x15, // Startup Logo
2589 0x00, 0x00, 0x00, 0x04,
2591 0x00, // Bitmap height
2593 0x00, // Bitmap width
2594 0xc0, 0x04, 0x03, 0x00
2595 }; // Bitmap following
2596 unsigned char reqOp[1000] = { N7110_FRAME_HEADER,
2598 0x00, // logo disabled
2599 0x00, 0xf0, 0x00, // network code (000 00)
2601 0x08, // length of rest
2602 0x00, 0x00, // Bitmap width / height
2604 0x00, // Bitmap size
2606 }; // Bitmap following
2608 /* Picture Images */
2609 unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2610 unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2611 unsigned char req4[500] = { N6110_FRAME_HEADER, 0x50, 0x07,
2616 unsigned char req5[120] = {0x00, 0x01, 0x01, 0xec, 0x02,0x00};
2618 unsigned char req6[]= {0x00,0x01,0x00,0xaf,0x00};
2626 CurrentSetBitmapError=GE_BUSY;
2628 switch (Bitmap->type) {
2629 case GSM_WelcomeNoteText:
2631 EncodeUnicode (req5+5, Bitmap->text, strlen(Bitmap->text));
2632 count=5+strlen(Bitmap->text)*2;
2635 Protocol->SendMessage(count, 0x7a, req5);
2638 case GSM_DealerNoteText:
2639 CurrentSetBitmapError = GE_NOTIMPLEMENTED;
2642 case GSM_StartupLogo:
2643 case GSM_7110StartupLogo:
2644 case GSM_6210StartupLogo:
2645 reqStartup[12] = Bitmap->height;
2646 reqStartup[16] = Bitmap->width;
2648 memcpy(reqStartup+count,Bitmap->bitmap,Bitmap->size);
2649 Protocol->SendMessage(count+Bitmap->size, 0x7a, reqStartup);
2652 case GSM_OperatorLogo:
2653 case GSM_7110OperatorLogo:
2657 if (strcmp(Bitmap->netcode,"000 00")) {
2658 reqOp[5] = 0x01; // Logo enabled
2659 EncodeNetworkCode(reqOp+6, Bitmap->netcode);
2660 reqOp[11] = 8+GSM_GetBitmapSize(Bitmap);
2661 reqOp[12]=Bitmap->width;
2662 reqOp[13]=Bitmap->height;
2663 reqOp[15]=GSM_GetBitmapSize(Bitmap);
2664 memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size);
2665 count += Bitmap->size;
2669 error=NULL_SendMessageSequence
2670 (50, &CurrentSetBitmapError, 5, 0x0a, req6);
2671 if (error!=GE_NONE) return error;
2674 Protocol->SendMessage(count, 0x0a, reqOp);
2677 case GSM_CallerLogo:
2678 CurrentSetBitmapError = N7110_WriteGroupDataLocation(Bitmap);
2681 case GSM_PictureImage:
2682 CurrentGetBitmap=Bitmap;
2686 req2[4]=req3[count];
2687 PictureImageLoc=req3[count];
2689 if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE) break;
2690 if (PictureImageNum==Bitmap->number+1) break;
2692 if (CurrentGetBitmapError!=GE_NONE) {
2697 req4[5]=PictureImageLoc;
2698 req4[6]=PictureImageIndex/256;
2699 req4[7]=PictureImageIndex%256;
2702 for (i=0;i<38;i++) req4[count++]=0x00;
2703 req4[count++]=Bitmap->width;
2704 req4[count++]=Bitmap->height;
2705 req4[count++]=Bitmap->size/256;
2706 req4[count++]=Bitmap->size%256;
2707 memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size);
2708 count += Bitmap->size;
2712 CurrentSetBitmapError = GE_BUSY;
2714 Protocol->SendMessage(count, 0x14, req4);
2720 /* Wait for timeout or other error. */
2721 while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
2724 return (GE_TIMEOUT);
2729 if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo)
2730 && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) {
2731 return N6110_Reset(0x03);
2734 return CurrentSetBitmapError;
2737 /* Get a bitmap from the phone */
2738 GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap)
2740 unsigned char req[10] = { N6110_FRAME_HEADER };
2742 /* Picture Images */
2743 unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2744 unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2745 unsigned char req4[9] = { N6110_FRAME_HEADER, 0x07,
2751 unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02};
2755 GSM_PhonebookEntry entry;
2757 CurrentGetBitmapError = GE_BUSY;
2759 CurrentGetBitmap=Bitmap;
2761 switch (CurrentGetBitmap->type) {
2762 case GSM_StartupLogo:
2763 case GSM_7110StartupLogo:
2764 case GSM_6210StartupLogo:
2765 req[count-1]=0x01; /* change FRAME_HEADER */
2766 req[count++]=0xee; /* to get 0x01ee */
2768 Protocol->SendMessage(count, 0x7a, req);
2771 case GSM_WelcomeNoteText:
2773 Protocol->SendMessage(5, 0x7a, req5);
2776 case GSM_DealerNoteText:
2778 return GE_NOTIMPLEMENTED;
2780 case GSM_OperatorLogo:
2781 case GSM_7110OperatorLogo:
2782 req[count++]=0x70; /* NetworkStatus */
2783 Protocol->SendMessage(count, 0x0a, req);
2786 case GSM_CallerLogo:
2787 entry.MemoryType = GMT_CG;
2788 entry.Location = Bitmap->number+1;
2790 Bitmap->ringtone=0xFF;
2791 Bitmap->enabled=true;
2792 CurrentGetBitmapError = N7110_GetMemoryLocation(&entry);
2793 CurrentGetBitmap=NULL;
2794 if (entry.Location!=Bitmap->number+1) return GE_UNKNOWN;
2795 if (!strcmp(Bitmap->text,"")) {
2796 switch(Bitmap->number) {
2797 case 0:strcpy(Bitmap->text,"Family\0");break;
2798 case 1:strcpy(Bitmap->text,"VIP\0");break;
2799 case 2:strcpy(Bitmap->text,"Friends\0");break;
2800 case 3:strcpy(Bitmap->text,"Colleagues\0");break;
2801 case 4:strcpy(Bitmap->text,"Other\0");break;
2806 case GSM_PictureImage:
2811 req2[4]=req3[count];
2812 PictureImageLoc=req3[count];
2814 if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE)
2815 return CurrentGetBitmapError;
2816 if (PictureImageNum==Bitmap->number+1) break;
2818 if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError;
2820 req4[4]=PictureImageLoc;
2821 req4[5]=PictureImageIndex/256;
2822 req4[6]=PictureImageIndex%256;
2824 CurrentGetBitmapError = GE_BUSY;
2826 Protocol->SendMessage(9, 0x14, req4);
2831 return GE_NOTSUPPORTED;
2836 while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) {
2839 return (GE_TIMEOUT);
2844 CurrentGetBitmap=NULL;
2846 return (CurrentGetBitmapError);
2849 int ReturnBinRingLocation()
2853 while (GSM->GetModel(model) != GE_NONE) sleep(1);
2855 if (strcmp(model,"NSE-5") == 0) return 0x74; //first 0x74 //7110
2856 if (strcmp(model,"NPE-3") == 0) return 0x89; //first is 0x89; //6210
2862 this works only for 6210, the 7110 needs upload to a location ?
2864 GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
2867 /* Buffer for preview uploading */
2868 unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D,
2869 0x00, 0x00, 0x00, 0x00,
2873 int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
2875 GSM_NetworkInfo NetworkInfo;
2877 char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
2879 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2887 /* Info from Till Toenshoff [till@uni.de]
2889 One improvement - for looping you can use an alternative header
2891 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2894 0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01
2902 char tail[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
2903 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
2904 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B // 20 Bytes tail
2907 //{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" };
2908 char N7110_notes[14] =
2909 { 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10 , 11, 11 };
2911 int current = 6, i, note, lastnote = 0, duration;
2913 /* Preview uploading */
2914 if (ringtone->location==255) {
2915 *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size);
2917 Protocol->SendMessage(size+11, 0x00, buffer);
2918 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
2920 return GE_NONE; //no answer from phone
2923 req[5]=ReturnBinRingLocation()+ringtone->location;
2925 EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name));
2929 for (i=0; i<ringtone->NrNotes; i++) {
2931 if (ringtone->notes[i].note == 255)
2934 note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14];
2936 duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256; // in 8 ms ticks of 7110
2938 switch (ringtone->notes[i].style) {
2941 req[current++] = note; // note only for one tick
2945 note = 0x40; // rest pause
2947 if (note != 0x40 && duration) {
2948 req[current++] = 0x40;
2949 req[current++] = 1; // small pause between notes
2953 if (note != 0x40 && note == lastnote && duration) {
2954 req[current++] = 0x40;
2955 req[current++] = 1; // small pause between same notes
2959 while (duration > 125) {
2960 req[current++] = note;
2961 req[current++] = 125;
2964 req[current++] = note;
2965 req[current++] = duration;
2970 for (i = 0; i < sizeof(tail); i++)
2971 req[current++] = tail[i];
2973 Protocol->SendMessage(current, 0x1F, req);
2977 return GE_NONE; //no answer from phone
2980 void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2984 switch (MessageBuffer[3]) {
2989 while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) {
2994 DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp);
2997 fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name);
3000 CurrentGetBinRingtone->frame[0]=0x00;
3001 CurrentGetBinRingtone->frame[1]=0x00;
3002 CurrentGetBinRingtone->frame[2]=0x0c;
3003 CurrentGetBinRingtone->frame[3]=0x01;
3004 CurrentGetBinRingtone->frame[4]=0x2c;
3006 memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name));
3008 CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name);
3010 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3011 CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3013 /* Looking for end */
3016 if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
3019 if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
3023 if (i==MessageLength) break;
3027 memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37);
3028 CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37;
3030 CurrentBinRingtoneError=GE_NONE;
3036 fprintf(stdout, _("Message: Received empty ringtone\n"));
3039 CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;
3044 GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone)
3047 unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 };
3051 req[5]=ReturnBinRingLocation()+ringtone->location;
3053 CurrentGetBinRingtone=ringtone;
3055 return NULL_SendMessageSequence
3056 (50, &CurrentBinRingtoneError, 6, 0x1f, req);
3060 GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone)
3062 unsigned char req[1000] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 };
3064 GSM_NetworkInfo NetworkInfo;
3070 req[5]=ReturnBinRingLocation()+ringtone->location;
3072 for (i=6;i<35;i++) req[i]=0x00;
3076 EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5));
3080 while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++;
3082 memcpy(req+35,ringtone->frame+i,ringtone->length-i);
3084 Protocol->SendMessage(35+ringtone->length-i, 0x1f, req);
3086 GSM->GetNetworkInfo(&NetworkInfo); //need to make something
3088 return GE_NONE; //no answer from phone
3091 void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3093 GSM_SMSMessage NullSMS;
3096 fprintf(stdout,_("Message: Incoming SMS\n"));
3099 GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5);
3102 fprintf(stdout, _("\n"));
3106 void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3114 GSM_NetworkInfo NullNetworkInfo;
3116 switch (MessageBuffer[3]) {
3121 fprintf(stdout, _("Message: Clearing operator logo msg\n"));
3123 CurrentSetBitmapError=GE_NONE;
3128 /* Make sure we are expecting NetworkInfo frame */
3129 if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) ||
3130 (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) {
3132 fprintf(stdout, _("Message: Network informations and operator logo:\n"));
3136 fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
3140 sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
3142 sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
3144 sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
3147 fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID);
3148 fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC);
3149 fprintf(stdout, _(" Network code: %s\n"), NullNetworkInfo.NetworkCode);
3150 fprintf(stdout, _(" Network name for gnokii: %s (%s)\n"),
3151 GSM_GetNetworkName(NullNetworkInfo.NetworkCode),
3152 GSM_GetCountryName(NullNetworkInfo.NetworkCode));
3154 DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]);
3155 fprintf(stdout, _(" Network name for phone: %s\n"),name);
3157 fprintf(stdout, _(" Status: "));
3158 switch (MessageBuffer[8]) {
3159 case 0x01: fprintf(stdout, _("home network selected")); break;
3160 case 0x02: fprintf(stdout, _("roaming network")); break;
3161 case 0x03: fprintf(stdout, _("requesting network")); break;
3162 case 0x04: fprintf(stdout, _("not registered in the network")); break;
3163 default: fprintf(stdout, _("unknown"));
3166 fprintf(stdout, "\n");
3168 fprintf(stdout, _(" Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
3171 /* Make sure we are expecting NetworkInfo frame */
3172 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
3173 *CurrentNetworkInfo=NullNetworkInfo;
3174 CurrentNetworkInfoError = GE_NONE;
3177 /* Make sure we are expecting an operator logo */
3178 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3180 strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode);
3183 if (MessageBuffer[4] == 0x02)
3184 fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),
3185 CurrentGetBitmap->netcode,
3186 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3188 fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"),
3189 CurrentGetBitmap->netcode,
3190 GSM_GetNetworkName(CurrentGetBitmap->netcode));
3193 CurrentGetBitmap->type=GSM_7110OperatorLogo;
3194 if (MessageBuffer[4] == 0x02) { /* logo present */
3196 count += MessageBuffer[count]; /* skip network info */
3198 CurrentGetBitmap->width=MessageBuffer[count++]; /* 78 */
3199 CurrentGetBitmap->height=MessageBuffer[count++]; /* 21 */
3201 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3202 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
3204 CurrentGetBitmap->width=78;
3205 CurrentGetBitmap->height=21;
3206 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3207 memset(CurrentGetBitmap->bitmap,0,CurrentGetBitmap->size);
3209 CurrentGetBitmapError=GE_NONE;
3216 fprintf(stdout, _("Message: Network Level received:\n"));
3218 fprintf(stdout, _(" Network Level: %d\n"), MessageBuffer[4]);
3221 CurrentRFLevel=MessageBuffer[4];
3227 fprintf(stdout, _("Message: Operator logo set correctly.\n"));
3229 CurrentSetBitmapError = GE_NONE;
3234 fprintf(stdout, _("Message: Unknown message of type 0x0a\n"));
3236 AppendLogText("Unknown msg\n",false);
3237 break; /* Visual C Don't like empty cases */
3241 void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3244 GSM_ETSISMSMessage ETSI;
3246 switch (MessageBuffer[3]) {
3248 /* We have requested invalid or empty location. */
3252 fprintf(stdout, _("Message: SMS reading failed\n"));
3255 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3256 CurrentGetBitmapError=GE_UNKNOWN;
3259 /* getsms or picture image */
3262 if (MessageBuffer[8]==0x07) {
3264 if (CurrentGetBitmap!=NULL) {
3266 for (i=0;i<MessageBuffer[9]+1;i++)
3267 ETSI.SMSCNumber[i]=MessageBuffer[i+9];
3269 for (i=0;i<((MessageBuffer[22]+1)/2+1)+1;i++)
3270 ETSI.Number[i]=MessageBuffer[22+i];
3273 fprintf(stdout, _("Message: Picture Image received\n"));
3274 fprintf(stdout, _(" SMS center number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.SMSCNumber,false));
3275 fprintf(stdout, _(" Sender number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3278 strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3280 CurrentGetBitmap->width=MessageBuffer[47];
3281 CurrentGetBitmap->height=MessageBuffer[48];
3282 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap);
3284 memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size);
3286 tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size,
3287 CurrentGetBitmap->text);
3289 CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0;
3291 CurrentGetBitmapError=GE_NONE;
3295 fprintf(stdout, _("Message: Picture Image received, but not reqested\n"));
3298 CurrentSMSMessageError = GE_SMSTOOLONG;
3304 /* status in byte 4 */
3305 CurrentSMSMessage->Status = MessageBuffer[4];
3307 CurrentSMSMessage->Type = GST_SMS;
3308 if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR;
3310 CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location;
3312 /* RTH FIXME: old folder stuff for xgnokii */
3313 CurrentSMSMessage->folder = (MessageBuffer[5] / 8)-1;
3314 /* if unreadMessage from folder 0, set INBOX folder */
3315 if (CurrentSMSMessage->folder==-1) CurrentSMSMessage->folder = 0;
3317 fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n")
3318 ,CurrentSMSMessage->Type, CurrentSMSMessage->folder, MessageBuffer[7]);
3321 GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9);
3323 /* Signal no error to calling code. */
3324 CurrentSMSMessageError = GE_NONE;
3331 fprintf(stdout, _("Message: Received index for Picture Images\n"));
3334 for (i=1;i<MessageBuffer[4]*256+MessageBuffer[5]+1;i++) {
3336 if (PictureImageNum==CurrentGetBitmap->number+1) {
3337 PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2];
3342 CurrentGetBitmapError=GE_NONE;
3343 CurrentSetBitmapError=GE_NONE;
3350 fprintf(stdout, _("Message: Unknown message of type 14\n"));
3352 AppendLogText("Unknown msg\n",false);
3353 break; /* Visual C Don't like empty cases */
3357 void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3359 switch (MessageBuffer[3]) {
3364 fprintf(stdout, _("Message: Battery status received:\n"));
3366 fprintf(stdout, _(" Battery Level: %d\n"), MessageBuffer[5]);
3369 CurrentBatteryLevel=MessageBuffer[5];
3375 fprintf(stdout, _("Message: Unknown message of type 0x17\n"));
3377 AppendLogText("Unknown msg\n",false);
3378 break; /* Visual C Don't like empty cases */
3382 void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3386 switch (MessageBuffer[3]) {
3388 /* Setting setting request */
3391 switch (MessageBuffer[4]) {
3395 fprintf(stdout, _("Message: Startup text set correctly.\n"));
3397 CurrentSetBitmapError = GE_NONE;
3402 fprintf(stdout, _("Message: Startup logo set correctly.\n"));
3404 CurrentSetBitmapError = GE_NONE;
3410 /* Setting received */
3413 switch (MessageBuffer[4]) {
3417 fprintf(stdout, _("Message: Startup text received.\n"));
3421 while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) {
3426 DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp);
3429 fprintf(stdout, _(" Text: \"%s\"\n"),CurrentGetBitmap->text);
3432 CurrentGetBitmapError = GE_NONE;
3437 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
3438 fprintf(stdout, _("Message: Startup logo received.\n"));
3440 fprintf(stdout, _("Message: Startup logo not requested, but received.\n"));
3443 /* Make sure we are expecting a startup logo */
3444 if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3445 CurrentGetBitmap->height=MessageBuffer[13]; /* 96 */
3446 CurrentGetBitmap->width=MessageBuffer[17]; /* 60/65 */
3447 CurrentGetBitmap->type=GSM_7110StartupLogo;
3448 if (CurrentGetBitmap->width==60) CurrentGetBitmap->type=GSM_6210StartupLogo;
3449 CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* 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);