This commit was manufactured by cvs2svn to create branch 'uc'.
[gnokii.git] / common / newmodules / n7110.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9   This file provides an API for accessing functions on the 7110 and similar
10   phones.
11
12 */
13
14 /* "Turn on" prototypes in n-7110.h */
15
16 #define __n_7110_c 
17
18 /* System header files */
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <time.h>
23  
24 #ifndef WIN32
25   #include "devices/device.h"
26 #endif
27
28 #ifdef WIN32
29   #include "misc_win32.h"
30 #endif
31
32 /* Various header file */
33 #ifndef VC6
34   #include "config.h"
35 #endif
36
37 #include "gsm-api.h"
38 #include "gsm-coding.h"
39 #include "newmodules/n6110.h"
40 #include "newmodules/n7110.h"
41 #include "protocol/fbus.h"
42
43 /* Global variables used by code in gsm-api.c to expose the functions
44    supported by this model of phone. */
45
46 /* Here we initialise model specific functions. */
47
48 GSM_Functions N7110_Functions = {
49   N7110_Initialise,
50   N7110_DispatchMessage,
51   NULL_Terminate,
52   NULL_KeepAlive,
53   N7110_GetMemoryLocation,
54   N7110_WritePhonebookLocation,
55   N7110_GetSpeedDial,
56   N7110_SetSpeedDial,
57   N7110_GetMemoryStatus,
58   N7110_GetSMSStatus,
59   N6110_GetSMSCenter,
60   N6110_SetSMSCenter,
61   N7110_GetSMSMessage,
62   N7110_DeleteSMSMessage,
63   N6110_SendSMSMessage,
64   N7110_SaveSMSMessage,
65   N7110_GetRFLevel,
66   N7110_GetBatteryLevel,
67   UNIMPLEMENTED,
68   UNIMPLEMENTED,
69   UNIMPLEMENTED,
70   UNIMPLEMENTED,
71   N7110_GetSecurityCode,
72   N6110_GetIMEI,
73   N6110_GetRevision,
74   N6110_GetModel,
75   N7110_GetDateTime,
76   N7110_SetDateTime,
77   N7110_GetAlarm,
78   N7110_SetAlarm,
79   N6110_DialVoice,
80   N6110_DialData,
81   N6110_GetIncomingCallNr,\r
82   N6110_GetNetworkInfo,
83   N7110_GetCalendarNote,
84   N7110_WriteCalendarNote,
85   N7110_DeleteCalendarNote,
86   N6110_NetMonitor,
87   UNIMPLEMENTED,
88   N7110_GetBitmap,
89   N7110_SetBitmap,
90   N7110_SetRingTone,
91   N7110_SetBinRingTone,
92   N7110_GetBinRingTone,
93   N6110_Reset,
94   N7110_GetProfile,
95   UNIMPLEMENTED,
96   N6110_SendRLPFrame,
97   N6110_CancelCall,
98   UNIMPLEMENTED,
99   UNIMPLEMENTED,
100   UNIMPLEMENTED,
101   N6110_EnableCellBroadcast,
102   N6110_DisableCellBroadcast,
103   N6110_ReadCellBroadcast,
104   N6110_PlayTone,
105   N6110_GetProductProfileSetting,
106   N6110_SetProductProfileSetting,
107   UNIMPLEMENTED,
108   UNIMPLEMENTED,
109   N7110_GetVoiceMailbox,
110   N6110_Tests,
111   N6110_SimlockInfo,
112   N7110_GetCalendarNotesInfo,
113   N7110_GetSMSFolders,
114   UNIMPLEMENTED,
115   N7110_GetWAPBookmark,
116   N7110_SetWAPBookmark,
117   N7110_GetWAPSettings,
118   N6110_CallDivert,
119   UNIMPLEMENTED,
120   N6110_GetManufacturer
121 };
122
123 /* Mobile phone information */
124
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 */
130   "",
131   "6210|6250|7110", /* Supported models in FBUS over Irda sockets */
132   "",
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 */
142 };
143
144 const char *N7110_MemoryType_String [] = {
145   "",   /* 0x00 */
146   "DC", /* 0x01 */
147   "MC", /* 0x02 */
148   "RC", /* 0x03 */
149   "FD", /* 0x04 */
150   "ME", /* 0x05 */
151   "SM", /* 0x06 */
152   "ON", /* 0x07 */
153   "EN", /* 0x08 */
154   "MT", /* 0x09 */
155 };
156
157 int PictureImageNum; //required during reading Picture Images
158 int PictureImageIndex;
159 int PictureImageLoc;
160
161 void N7110_ReplyEnableIncomingSMSInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
162   switch (MessageBuffer[3]) {
163   case 0x0e:
164 #ifdef DEBUG
165     fprintf(stdout,_("Message: Enabled info for incoming SMS\n"));
166 #endif /* DEBUG */
167
168     CurrentMagicError=GE_NONE;
169     break;
170   case 0x0f:
171 #ifdef DEBUG
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;
176     }
177 #endif /* DEBUG */
178
179     CurrentMagicError=GE_UNKNOWN;
180     break;
181   }
182 }
183
184 GSM_Error N7110_EnableIncomingSMSInfo ()
185 {
186   unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
187
188   return NULL_SendMessageSequence
189     (50, &CurrentMagicError, 8, 0x02, req);
190 }
191
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))
196 {
197
198   unsigned char init_char = N6110_SYNC_BYTE;
199   int count;
200   int InitLength;
201     
202   if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
203   {
204     return GE_NOTSUPPORTED;
205   }
206   
207   if (connection!=GCT_MBUS && connection!=GCT_Irda) {
208
209     InitLength = atoi(initlength);
210
211     if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
212       InitLength = 250; /* This is the usual value, lower may work. */
213     }
214
215 #ifdef DEBUG
216     fprintf(stdout,_("Writing init chars...."));
217 #endif
218     
219     /* Initialise link with phone or what have you */
220     /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
221        empirical. */
222     for (count = 0; count < InitLength; count ++) {
223       usleep(100);
224       Protocol->WritePhone(1,&init_char);
225     }
226
227 #ifdef DEBUG
228     fprintf(stdout,_("Done\n"));  
229 #endif
230
231     N6110_SendStatusRequest();
232     
233   }
234
235   usleep(100);
236
237   if (N6110_SendIDFrame()!=GE_NONE)   return GE_TIMEOUT;
238
239   if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    
240
241   if (N6110_SendHWFrame()!=GE_NONE)   return GE_TIMEOUT;    
242
243 //  N7110_EnableIncomingSMSInfo();
244     
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;                           
250   }
251   
252   CurrentSMSFoldersCount=1000;
253   CurrentSMSMessage=NULL;
254
255   return (GE_NONE);
256 }
257
258 /* This function translates GMT_MemoryType to N7110_MEMORY_xx */
259 int N7110_GetMemoryType(GSM_MemoryType memory_type)
260 {
261
262   int result;
263
264   switch (memory_type) {
265
266 //     case GMT_MT:
267 //      result = N7110_MEMORY_MT;
268 //        break;
269
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;
280    }
281
282    return (result);
283 }
284
285 GSM_Error N7110_GetVoiceMailbox ( GSM_PhonebookEntry *entry)
286 {
287   unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
288                          0x02, //memory type
289                          0x05,
290                          0x00, 0x00, //location
291                          0x00, 0x00};
292
293   CurrentPhonebookEntry = entry;
294
295   req[9] = N7110_MEMORY_VM;
296   req[10] = (1>>8);
297   req[11] = 1 & 0xff;
298
299   return NULL_SendMessageSequence
300     (50, &CurrentPhonebookError, 14, 0x03, req);
301 }
302
303 void N7110_ReplyEnableWAPCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
304 {
305   switch(MessageBuffer[3]) {
306
307   case 0x01:
308 #ifdef DEBUG
309     fprintf(stdout, _("Message: WAP functions enabled\n"));
310 #endif /* DEBUG */
311     CurrentGetWAPBookmarkError=GE_NONE;
312     break;
313     
314   case 0x02:
315 #ifdef DEBUG
316     fprintf(stdout, _("Message: WAP functions enabled\n"));
317 #endif /* DEBUG */
318     CurrentGetWAPBookmarkError=GE_NONE;
319     break;
320
321   }
322 }
323
324 /* To enable WAP frames in phone */
325 GSM_Error N7110_EnableWAPCommands ()
326 {
327   unsigned char req0[] = { N6110_FRAME_HEADER, 0x00 };
328
329   return NULL_SendMessageSequence
330     (50, &CurrentGetWAPBookmarkError, 4, 0x3f, req0);
331 }
332
333 void N7110_ReplyGetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
334 {
335   int tmp;
336
337   switch(MessageBuffer[3]) {
338
339   case 0x07:
340
341 #ifdef DEBUG
342     fprintf(stdout, _("Message: WAP bookmark received OK\n"));
343 #endif /* DEBUG */
344
345     DecodeUnicode(WAPBookmark->title, MessageBuffer + 7, MessageBuffer[6] );
346
347 #ifdef DEBUG
348     fprintf(stdout, _("   Title: \"%s\"\n"),WAPBookmark->title);      
349 #endif /* DEBUG */
350
351     tmp=MessageBuffer[6]*2+7;
352
353     DecodeUnicode(WAPBookmark->address, MessageBuffer + tmp+1, MessageBuffer[tmp] );
354
355 #ifdef DEBUG
356     fprintf(stdout, _("   Address: \"%s\"\n"),WAPBookmark->address);      
357 #endif /* DEBUG */
358
359     CurrentGetWAPBookmarkError=GE_NONE;
360     break;
361
362   case 0x08:
363
364 #ifdef DEBUG
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"));
370     }
371 #endif /* DEBUG */
372
373     switch (MessageBuffer[4]) {
374       case 0x01:CurrentGetWAPBookmarkError=GE_INSIDEBOOKMARKSMENU;break;
375       case 0x02:CurrentGetWAPBookmarkError=GE_INVALIDBOOKMARKLOCATION;break;
376       default:CurrentGetWAPBookmarkError=GE_UNKNOWN;
377     }
378
379     break;
380   }
381 }
382
383 GSM_Error N7110_GetWAPBookmark (GSM_WAPBookmark *bookmark)
384 {
385   unsigned char req[] = { N6110_FRAME_HEADER, 0x06, 0x00, 0x00};
386
387   GSM_Error error;
388
389   /* We have to enable WAP frames in phone */
390   error=N7110_EnableWAPCommands ();
391   if (error!=GE_NONE) return error;
392
393   req[2]=0x00;
394   req[5]=bookmark->location-1;
395
396   WAPBookmark=bookmark;
397   
398   return NULL_SendMessageSequence
399     (50, &CurrentGetWAPBookmarkError, 6, 0x3f, req);
400 }
401
402 void N7110_ReplySetWAPBookmark(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
403 {
404   switch(MessageBuffer[3]) {
405
406   case 0x0a:
407
408 #ifdef DEBUG
409     fprintf(stdout, _("Message: WAP bookmark set OK\n"));
410 #endif /* DEBUG */
411
412     CurrentSetWAPBookmarkError=GE_NONE;
413     break;
414     
415   case 0x0b:
416
417 #ifdef DEBUG
418     fprintf(stdout, _("Message: Error setting WAP bookmark\n"));
419 #endif /* DEBUG */
420
421     CurrentSetWAPBookmarkError=GE_UNKNOWN;
422     break;
423   }
424 }
425
426 GSM_Error N7110_SetWAPBookmark (GSM_WAPBookmark *bookmark)
427 {
428         unsigned char req[64] = { N6110_FRAME_HEADER, 0x09 };
429         GSM_Error error;
430         int count;
431
432         /* We have to enable WAP frames in phone */
433         error = N7110_EnableWAPCommands ();
434         if (error != GE_NONE)
435                 return error;
436
437         count = 4;
438         req[count++] = (bookmark->location & 0xff00) >> 8;
439         req[count++] = (bookmark->location & 0x00ff);
440
441         req[count++] = strlen(bookmark->title);
442         EncodeUnicode (req+count,bookmark->title ,strlen(bookmark->title));
443         count=count+2*strlen(bookmark->title);
444
445         req[count++] = strlen(bookmark->address);
446         EncodeUnicode (req+count,bookmark->address ,strlen(bookmark->address));
447         count=count+2*strlen(bookmark->address);
448
449         /* ??? */
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;
453
454         WAPBookmark = bookmark;
455
456         return NULL_SendMessageSequence(50, &CurrentSetWAPBookmarkError,
457                                         count, 0x3f, req);
458 }
459
460 void N7110_ReplyGetWAPSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
461 {
462   int tmp;
463
464   switch(MessageBuffer[3]) {
465
466   case 0x16:
467
468 #ifdef DEBUG
469     fprintf(stdout, _("Message: WAP settings received OK\n"));
470 #endif /* DEBUG */
471
472     DecodeUnicode(WAPSettings->title, MessageBuffer + 5, MessageBuffer[4] );
473
474 #ifdef DEBUG
475     fprintf(stdout, _("   Title: \"%s\"\n"),WAPSettings->title);      
476 #endif /* DEBUG */
477
478     tmp=5+MessageBuffer[4]*2;
479
480     DecodeUnicode(WAPSettings->homepage, MessageBuffer + tmp+1, MessageBuffer[tmp] );
481
482 #ifdef DEBUG
483     fprintf(stdout, _("   Homepage: \"%s\"\n"),WAPSettings->homepage);      
484 #endif /* DEBUG */
485
486     tmp=tmp+MessageBuffer[tmp]*2+1;
487
488 #ifdef DEBUG
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"));
494     }
495     fprintf(stdout, _("\n"));      
496
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"));
502     }
503     fprintf(stdout, _("\n"));      
504
505 #endif /* DEBUG */
506
507     switch (MessageBuffer[tmp]) {
508       case 0x00: WAPSettings->iscontinuous=false;break;
509       case 0x01: WAPSettings->iscontinuous=true;break;
510     }
511     switch (MessageBuffer[tmp+13]) {
512       case 0x00: WAPSettings->issecurity=false;break;
513       case 0x01: WAPSettings->issecurity=true;break;
514     }
515
516     WAPSettings->location=MessageBuffer[tmp+7];//location for second part
517
518     CurrentGetWAPSettingsError=GE_NONE;
519     break;
520
521   case 0x17:
522
523 #ifdef DEBUG
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"));
529     }
530 #endif /* DEBUG */
531
532     switch (MessageBuffer[4]) {
533       case 0x01:CurrentGetWAPSettingsError=GE_INSIDESETTINGSMENU;break;
534       case 0x02:CurrentGetWAPSettingsError=GE_INVALIDSETTINGSLOCATION;break;
535       default  :CurrentGetWAPSettingsError=GE_UNKNOWN;
536     }
537
538     break;
539
540   case 0x1c:
541
542 #ifdef DEBUG
543     fprintf(stdout, _("Message: WAP settings received OK\n"));
544 #endif /* DEBUG */
545
546     switch (MessageBuffer[5]) {
547       case 0x00:
548
549         WAPSettings->bearer=WAPSETTINGS_BEARER_SMS;
550         
551 #ifdef DEBUG
552         fprintf(stdout, _("  Settings for SMS bearer:\n"));
553 #endif /* DEBUG */
554
555         tmp=6;
556
557         DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1, 
558                        MessageBuffer[tmp] );
559
560 #ifdef DEBUG
561         fprintf(stdout, _("      Service number: \"%s\"\n"),WAPSettings->service);      
562 #endif /* DEBUG */
563
564         tmp=tmp+MessageBuffer[tmp]*2+1;
565
566         DecodeUnicode(WAPSettings->server, MessageBuffer + tmp+ 1, 
567                        MessageBuffer[tmp] );
568
569 #ifdef DEBUG
570         fprintf(stdout, _("      Server number: \"%s\"\n"),WAPSettings->server);      
571 #endif /* DEBUG */
572
573         break;
574
575       case 0x01:
576
577         WAPSettings->bearer=WAPSETTINGS_BEARER_DATA;
578         
579 #ifdef DEBUG
580         fprintf(stdout, _("  Settings for data bearer:\n"));
581 #endif /* DEBUG */
582
583         tmp=10;
584
585         DecodeUnicode(WAPSettings->ipaddress, MessageBuffer + tmp+ 1, 
586                        MessageBuffer[tmp] );
587
588 #ifdef DEBUG
589         fprintf(stdout, _("      IP address: \"%s\"\n"),WAPSettings->ipaddress);      
590 #endif /* DEBUG */
591
592         tmp=tmp+MessageBuffer[tmp]*2+1;
593
594         DecodeUnicode(WAPSettings->dialup, MessageBuffer + tmp+1, 
595                        MessageBuffer[tmp] );
596
597 #ifdef DEBUG
598         fprintf(stdout, _("      Dial-up number: \"%s\"\n"),WAPSettings->dialup);      
599 #endif /* DEBUG */
600
601         tmp=tmp+MessageBuffer[tmp]*2+1;
602
603         DecodeUnicode(WAPSettings->user, MessageBuffer + tmp+1, 
604                        MessageBuffer[tmp] );
605
606 #ifdef DEBUG
607         fprintf(stdout, _("      User name: \"%s\"\n"),WAPSettings->user);      
608 #endif /* DEBUG */
609
610         tmp=tmp+MessageBuffer[tmp]*2+1;
611
612         DecodeUnicode(WAPSettings->password, MessageBuffer + tmp+1, 
613                        MessageBuffer[tmp] );
614
615 #ifdef DEBUG
616         fprintf(stdout, _("      Password: \"%s\"\n"),WAPSettings->password);      
617 #endif /* DEBUG */
618
619 #ifdef DEBUG
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;
625         }
626         fprintf(stdout, _("\n"));      
627
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;
633         }
634         fprintf(stdout, _("\n"));      
635
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;
641         }
642         fprintf(stdout, _("\n"));      
643
644 #endif /* DEBUG */                             
645
646         switch (MessageBuffer[6]) {
647           case 0x00: WAPSettings->isnormalauthentication=true;break;
648           case 0x01: WAPSettings->isnormalauthentication=false;break;
649         }
650         switch (MessageBuffer[7]) {
651           case 0x00: WAPSettings->isISDNcall=false;break;
652           case 0x01: WAPSettings->isISDNcall=true;break;
653         }
654         switch (MessageBuffer[9]) {
655           case 0x01: WAPSettings->isspeed14400=false;break;
656           case 0x02: WAPSettings->isspeed14400=true;break;
657         }
658
659         break;
660         
661       case 0x02:
662
663         WAPSettings->bearer=WAPSETTINGS_BEARER_USSD;
664         
665 #ifdef DEBUG
666         fprintf(stdout, _("  Settings for USSD bearer:\n"));
667 #endif /* DEBUG */
668
669         tmp=7;
670
671         DecodeUnicode(WAPSettings->service, MessageBuffer + tmp+1, 
672                        MessageBuffer[tmp] );
673
674 #ifdef DEBUG
675         if (MessageBuffer[6]==0x01) 
676           fprintf(stdout, _("      Service number: \"%s\"\n"),WAPSettings->service);      
677         else 
678           fprintf(stdout, _("      IP address: \"%s\"\n"),WAPSettings->service);      
679 #endif /* DEBUG */
680
681         WAPSettings->isIP=true;
682         if (MessageBuffer[6]==0x01) WAPSettings->isIP=false;
683         
684         tmp=tmp+MessageBuffer[tmp]*2+1;
685
686         DecodeUnicode(WAPSettings->code, MessageBuffer + tmp+1, 
687                        MessageBuffer[tmp] );
688
689 #ifdef DEBUG
690         fprintf(stdout, _("      Service code: \"%s\"\n"),WAPSettings->code);      
691 #endif /* DEBUG */
692
693     }
694
695     CurrentGetWAPSettingsError=GE_NONE;
696     break;
697   }
698 }
699
700 GSM_Error N7110_GetWAPSettings (GSM_WAPSettings *settings)
701 {
702   unsigned char req[] = { N6110_FRAME_HEADER, 0x15, 0x00};
703   unsigned char req2[] = { N6110_FRAME_HEADER, 0x1b, 0x00};
704
705   GSM_Error error;
706
707   /* We have to enable WAP frames in phone */
708   error=N7110_EnableWAPCommands ();
709   if (error!=GE_NONE) return error;
710
711   req[2]=0x00;
712   req[4]=settings->location-1;
713
714   WAPSettings=settings;
715   
716   error=NULL_SendMessageSequence
717     (50, &CurrentGetWAPSettingsError, 6, 0x3f, req);
718   if (error!=GE_NONE) return error;
719
720   req2[2]=0x00;
721
722   req2[4]=settings->location;
723
724   return NULL_SendMessageSequence
725     (50, &CurrentGetWAPSettingsError, 6, 0x3f, req2);
726 }
727
728 void N7110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
729 {
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;
735
736     CurrentMemoryStatusError = GE_NONE;
737
738 #ifdef DEBUG
739     fprintf(stdout, _("Message: Memory status received:\n"));
740
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);
744 #endif /* DEBUG */
745   }
746 }
747
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)
751 {
752   unsigned char req[] = { N6110_FRAME_HEADER,
753                           0x03, /* MemoryStatus request */
754                           0x02,
755                           0x05  /* MemoryType */
756                         };
757
758   switch (Status->MemoryType) {
759
760      case GMT_ME:
761      case GMT_SM:
762        CurrentMemoryStatus = Status;
763
764        req[5] = N7110_GetMemoryType(Status->MemoryType);
765
766        return NULL_SendMessageSequence
767          (20, &CurrentMemoryStatusError, 6, 0x03, req);
768        break;
769
770      case GMT_DC:
771      case GMT_RC:
772      case GMT_MC:
773        Status->Free = 0;
774        Status->Used = 20;
775        return GE_NONE;
776
777      default:
778        return GE_NOTSUPPORTED;
779    }
780 }
781
782 void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
783 {
784   switch(MessageBuffer[3]) {
785
786   case 0x02:
787
788 #ifdef DEBUG
789      fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]);
790 #endif /* DEBUG */
791
792      switch (MessageBuffer[6]) {
793        case 0xff: /* Profile Name */
794          DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]);      
795 #ifdef DEBUG
796          fprintf(stdout,_("   Name \"%s\"\n"),CurrentProfile->Name);
797 #endif /* DEBUG */
798
799          break;
800
801        case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */
802          switch( MessageBuffer[10] ) {
803            case 0:
804              CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break;
805            case 1:
806            case 2:
807            case 3:
808              CurrentProfile->KeypadTone = MessageBuffer[10]-1; break;
809          }
810          break;
811
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;
820          }
821          break;
822        case 0x03: /* Ringtone number */
823          CurrentProfile->Ringtone = MessageBuffer[10];
824          break;
825        case 0x04: /* Ringtone volume (from level 1 to level 5) */
826          CurrentProfile->Volume = MessageBuffer[10] + 6;
827          break;
828        case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */
829          CurrentProfile->MessageTone = MessageBuffer[10];
830          break;
831        case 0x06: /* Vibration (On/Off) */
832          CurrentProfile->Vibration = MessageBuffer[10];
833          break;
834        case 0x07: /* WarningTone (On/Off) */
835          switch( MessageBuffer[10] ) {
836            case 0:
837              CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break;
838            case 1:
839              CurrentProfile->WarningTone = PROFILE_WARNING_ON; break;
840          }
841          break;
842        case 0x08: /* Alert for (caller groups) */
843          CurrentProfile->CallerGroups = MessageBuffer[10];
844          break;
845        case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */
846          CurrentProfile->AutomaticAnswer = MessageBuffer[10];
847          break;
848      }
849
850      CurrentProfileError=GE_NONE;
851      break;
852    default:
853
854 #ifdef DEBUG
855     fprintf(stdout, _("Message: Unknown message of type 0x39\n"));
856 #endif /* DEBUG */
857     AppendLogText("Unknown msg\n",false);
858     break;      /* Visual C Don't like empty cases */
859
860   }
861 }
862
863 GSM_Error N7110_GetProfile(GSM_Profile *Profile)
864 {
865   int i;
866   
867   unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
868                           0x00,  //profile number
869                           0xff}; //feature. Here 0xff=name
870
871   unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22,
872                                                                                                                 0x00,0x02,0x09 };
873
874   GSM_Error error;
875   
876   CurrentProfile = Profile;
877
878   /* When after sending all frames feature==253, it means, that it is not
879      supported */
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;
891
892   req[7] = Profile->Number+1;
893
894   error=NULL_SendMessageSequence
895     (20, &CurrentProfileError, 9, 0x39, req);
896   if (error!=GE_NONE) return error;
897
898   for (i = 0; i < 11; i++) {
899
900     req[7] = Profile->Number+1;
901     
902     req[8] = req2[i];
903
904     error=NULL_SendMessageSequence
905       (20, &CurrentProfileError, 9, 0x39, req);
906     if (error!=GE_NONE) return error;
907   }
908   
909   return (GE_NONE);
910 }
911
912 void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
913 {
914   int i;
915
916   CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5];
917   CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany;
918
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];
922   }
923
924   CurrentCalendarNotesInfoError=GE_NONE;
925 }
926
927 GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo)
928 {
929   unsigned char req[] = { N6110_FRAME_HEADER,
930         0x3a, /* get notes info */
931         0xFF, 0xFE //fixed
932   };
933   GSM_Error error;
934
935   CurrentCalendarNotesInfo2=NotesInfo;
936   
937   error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req);
938
939   return error;
940 }
941
942 void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2)
943 {
944   time_t     t_alarm;
945   struct tm  tm_time;
946   struct tm  *tm_alarm;
947
948 #ifdef DEBUG                    
949   if (alarmdiff == 0xffff) fprintf(stdout,"   No alarm");
950                       else fprintf(stdout,"   Alarm is %i seconds before date", alarmdiff*alarm2);
951   fprintf(stdout,"\n");
952 #endif
953
954   if (alarmdiff != 0xffff) {    
955
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;
963
964     tzset();
965     t_alarm = mktime(&tm_time);
966     t_alarm -= alarmdiff*alarm2;
967
968     tm_alarm = localtime(&t_alarm);
969
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;
976
977 #ifdef DEBUG
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);
981 #endif
982   }
983 }
984
985 void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
986 {
987   time_t     alarmdiff;
988         
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];
995   } else {
996     c->Time.Hour = 0;
997     c->Time.Minute = 0;
998   }
999   c->Time.Second = 0;
1000
1001 #ifdef DEBUG
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);
1005 #endif
1006
1007   if (c->Type != GCN_REMINDER) {
1008     alarmdiff = block[14]*256 + block[15];
1009     P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60);
1010
1011     c->Recurrance = block[16]*256 + block[17];
1012     DecodeUnicode(c->Text, block+20, block[18]);
1013   } else {
1014     c->Recurrance = block[12]*256 + block[13];
1015     DecodeUnicode(c->Text, block+16, block[14]);
1016   }
1017
1018   /* 0xffff -> 1 Year (8760 hours) */
1019   if (c->Recurrance == 0xffff) c->Recurrance=8760;
1020
1021 #ifdef DEBUG
1022   fprintf(stdout, "   Recurrance: %i hours\n   Text: \"%s\"\n",
1023             c->Recurrance,c->Text);
1024 #endif
1025 }
1026
1027 void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1028 {
1029   int alarm;
1030
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
1034
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;
1041
1042 #ifdef DEBUG
1043   fprintf(stdout, "Message: calendar note received\n");
1044 #endif
1045
1046   switch (MessageBuffer[6]) /* entry type */ {
1047     case 0x01: /* Meeting */
1048 #ifdef DEBUG
1049       fprintf(stdout, "   Note type: meeting\n");
1050 #endif
1051       CurrentCalendarNote->Type = GCN_MEETING;
1052       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1053       CurrentCalendarNoteError=GE_NONE;
1054       break;
1055
1056     case 0x02: /* Call */
1057 #ifdef DEBUG
1058       fprintf(stdout, "   Note type: call\n");
1059 #endif
1060       CurrentCalendarNote->Type = GCN_CALL;
1061       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1062       DecodeUnicode(CurrentCalendarNote->Phone,
1063             MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]);
1064 #ifdef DEBUG
1065       fprintf(stdout, "   Phone number: \"%s\"\n",CurrentCalendarNote->Phone);
1066 #endif
1067       CurrentCalendarNoteError=GE_NONE;
1068       break;
1069
1070     case 0x04: /* Birthday */
1071 #ifdef DEBUG
1072       fprintf(stdout, "   Note type: birthday\n");
1073 #endif
1074       CurrentCalendarNote->Type = GCN_BIRTHDAY;
1075
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];
1080
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);
1088
1089       CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19];
1090       CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth;
1091
1092       CurrentCalendarNote->AlarmType = MessageBuffer[20];
1093
1094 #ifdef DEBUG
1095       fprintf(stdout,_("   Alarm type: %s\n"), 
1096         (CurrentCalendarNote->AlarmType==0x00) ? "Tone  " : "Silent");
1097
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);
1101 #endif
1102
1103       DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]);
1104 #ifdef DEBUG
1105       fprintf(stdout, "   Text: \"%s\"\n",CurrentCalendarNote->Text);
1106 #endif
1107
1108       CurrentCalendarNote->Recurrance = 0;
1109       CurrentCalendarNoteError=GE_NONE;
1110       break;
1111
1112     case 0x08: /* Reminder */
1113 #ifdef DEBUG
1114       fprintf(stdout, "   Note type: reminder\n");
1115 #endif
1116       CurrentCalendarNote->Type = GCN_REMINDER;
1117       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1118       CurrentCalendarNoteError=GE_NONE;
1119       break;
1120
1121     default: /* unknown */
1122 #ifdef DEBUG
1123       fprintf(stdout, "   Note type: UNKNOWN\n");
1124 #endif
1125       break;
1126   }
1127 }
1128   
1129 GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
1130 {
1131   unsigned char req[] = { N6110_FRAME_HEADER,
1132         0x19, /* get calendar note */
1133         0x00, 0x00 //location
1134   };
1135  
1136   GSM_Error error;
1137   GSM_DateTime date_time;
1138   struct tm *now;
1139   time_t nowh;
1140   
1141   if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1142     error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1143     if (error!=GE_NONE) return error;
1144   }
1145
1146 #ifdef DEBUG
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]);
1151 #endif
1152
1153   /* this is for making xgnokii work.. */
1154   if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1155     return GE_INVALIDCALNOTELOCATION;
1156   
1157   req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1158   req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;\r
1159   CurrentCalendarNote = CalendarNote;
1160
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) {
1165     nowh=time(NULL);
1166     now=localtime(&nowh);
1167
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;
1171     }
1172     date_time.Year=now->tm_year;
1173   }
1174   CurrentCalendarNote->Time.Year = date_time.Year;
1175   
1176   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1177   
1178   CurrentCalendarNote = NULL;
1179   
1180   return error;
1181 }
1182
1183 void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1184 {
1185 #ifdef DEBUG
1186   char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" };
1187
1188   fprintf(stdout, 
1189       "Succesfully written Calendar Note Type %s on location %d\n",
1190         kz_types[(MessageBuffer[3]/2)-1], 
1191         MessageBuffer[4]*256+MessageBuffer[5] );
1192
1193   fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n", 
1194         MessageBuffer[6]*256+MessageBuffer[7] );
1195 #endif
1196   CurrentCalendarNoteError=GE_NONE;
1197 }
1198
1199 long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm)
1200 {
1201   time_t     t_alarm;
1202   time_t     t_time;
1203   struct tm  tm_alarm;
1204   struct tm  tm_time;
1205
1206   tzset();
1207
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);
1216
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;
1223   tm_time.tm_isdst=0;
1224   t_time = mktime(&tm_time);
1225
1226 #ifdef DEBUG
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);
1234 #endif
1235
1236   return difftime( t_time ,t_alarm )+3600;
1237 }
1238
1239 GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
1240 {
1241   unsigned char req[200] = { N6110_FRAME_HEADER,
1242                              0x01,       /* note type ... */
1243                              0x00, 0x00, /* location */
1244                              0x00,       /* entry type */
1245                              0x00,       //fixed
1246                              0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */
1247                              /* here starts block */
1248                              0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */
1249                            };
1250
1251   int count=0;
1252   long seconds, minutes;
1253  
1254   GSM_Error error;
1255   int firstFreeLocation;
1256
1257   /*
1258    * 6210/7110 needs to seek the first free pos to inhabit with next note
1259    */
1260   error=N7110_FirstCalendarFreePos(&firstFreeLocation);
1261   if (error!=GE_NONE) return error;
1262
1263 #ifdef DEBUG
1264   fprintf(stdout, _("First free calendar location is = %d.\n"),
1265              firstFreeLocation);
1266 #endif
1267
1268   /* Location */
1269   req[4]=0x00;
1270   req[5]=0x00;
1271
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;
1277   }
1278
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;
1283
1284   /* From here starts BLOCK */
1285   count=12;
1286   switch( CalendarNote->Type ) {
1287
1288     case GCN_MEETING:
1289       req[count++]=CalendarNote->Time.Hour;   // 12
1290       req[count++]=CalendarNote->Time.Minute; // 13
1291       /* Alarm .. */
1292       req[count++]=0xff; // 14
1293       req[count++]=0xff; // 15
1294       if( CalendarNote->Alarm.Year )
1295       {
1296         seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, 
1297                                         &CalendarNote->Alarm);
1298         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1299           minutes=seconds/60L;
1300           count-=2;
1301           req[count++]=minutes>>8;
1302           req[count++]=minutes&0xff;
1303         }
1304       }
1305       /* Recurrance */
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
1310       /* len of text */
1311       req[count++]=strlen(CalendarNote->Text);    // 18
1312       /* fixed 0x00 */
1313       req[count++]=0x00; // 19
1314       /* Text */
1315 #ifdef DEBUG
1316       fprintf(stdout, "Count before encode = %d\n", count );
1317       fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text );
1318 #endif
1319
1320       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1321       count=count+2*strlen(CalendarNote->Text);
1322       break;
1323
1324     case GCN_CALL:
1325       req[count++]=CalendarNote->Time.Hour;   // 12
1326       req[count++]=CalendarNote->Time.Minute; // 13
1327       /* Alarm .. */
1328       req[count++]=0xff; // 14
1329       req[count++]=0xff; // 15
1330       if( CalendarNote->Alarm.Year )
1331       {
1332         seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, 
1333                                         &CalendarNote->Alarm);
1334         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1335           minutes=seconds/60L;
1336           count-=2;
1337           req[count++]=minutes>>8;
1338           req[count++]=minutes&0xff;
1339         }
1340       }
1341       /* Recurrance */
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
1346       /* len of text */
1347       req[count++]=strlen(CalendarNote->Text);    // 18
1348       /* fixed 0x00 */
1349       req[count++]=strlen(CalendarNote->Phone);   // 19
1350       /* Text */
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);
1355       break;
1356
1357     case GCN_BIRTHDAY:
1358       req[count++]=0x00; // 12 Fixed
1359       req[count++]=0x00; // 13 Fixed
1360
1361       /* Alarm .. */
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)
1369
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);
1376         }
1377         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1378           count-=4;
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
1383         }
1384       }
1385
1386       req[count++]=CalendarNote->AlarmType; // 18
1387
1388       /* len of text */
1389       req[count++]=strlen(CalendarNote->Text); // 19
1390
1391       /* Text */
1392 #ifdef DEBUG
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 );
1395 #endif
1396       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N
1397       count=count+2*strlen(CalendarNote->Text);
1398       break;
1399
1400     case GCN_REMINDER:
1401       /* Recurrance */
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
1406       /* len of text */
1407       req[count++]=strlen(CalendarNote->Text);    // 14
1408       /* fixed 0x00 */
1409       req[count++]=0x00; // 15
1410       /* Text */
1411       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N
1412       count=count+2*strlen(CalendarNote->Text);
1413       break;
1414   }
1415
1416   /* padding */
1417   req[count]=0x00;
1418 #ifdef DEBUG
1419   fprintf(stdout, "Count after padding = %d\n", count );
1420 #endif
1421   
1422   CurrentCalendarNote = CalendarNote;
1423   
1424   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req);
1425   
1426   CurrentCalendarNote = NULL;
1427
1428   return error;
1429 }
1430
1431 void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1432 {
1433   *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5];
1434   CurrentFirstCalendarFreePosError=GE_NONE;
1435 }
1436
1437 GSM_Error N7110_FirstCalendarFreePos(int *FreePos)
1438 {
1439   unsigned char req[] = { N6110_FRAME_HEADER, 0x31 };
1440  
1441   GSM_Error error;
1442
1443   CurrentFirstCalendarFreePos = FreePos;
1444   
1445   error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError, 
1446       4, 0x13, req);
1447   
1448   CurrentFirstCalendarFreePos = NULL;
1449   
1450   return error;
1451 }
1452
1453 void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1454 {
1455 #ifdef DEBUG
1456   fprintf(stdout, 
1457        "Succesfully Delete Calendar Note on location %d\n",
1458        MessageBuffer[4]*256+MessageBuffer[5] );
1459
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] );
1466 #endif
1467   CurrentCalendarNoteError=GE_NONE;
1468 }
1469
1470 GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
1471 {
1472   unsigned char req[] = { N6110_FRAME_HEADER,
1473                           0x0b,      /* delete calendar note */
1474                           0x00, 0x00 //location
1475   };
1476  
1477   GSM_Error error;
1478   
1479   if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1480     error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1481     if (error!=GE_NONE) return error;
1482   }
1483
1484   /* this is for making xgnokii work.. */
1485   if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1486     return GE_INVALIDCALNOTELOCATION;
1487   
1488   req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1489   req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1490
1491   CurrentCalendarNote = CalendarNote;
1492   
1493   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1494   
1495   CurrentCalendarNote = NULL;
1496   
1497   return error;
1498 }
1499
1500 void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1501 {
1502   wchar_t wc;
1503
1504   int i, j, tmp;
1505
1506 #ifdef DEBUG
1507   fprintf(stdout, _("Message: SMS Folders received:\n"));
1508 #endif /* DEBUG */
1509  
1510   i=5;
1511       
1512   CurrentSMSFoldersCount=MessageBuffer[4];
1513       
1514   for (j=0;j<MessageBuffer[4];j++) {
1515     strcpy(CurrentSMSFolders->Folder[j].Name,"               ");
1516 #ifdef DEBUG
1517     fprintf(stdout, _("   Folder Index: %d"),MessageBuffer[i]);
1518 #endif /* DEBUG */
1519     CurrentSMSFolders->FoldersID[j]=MessageBuffer[i];
1520
1521     i=i+2;
1522
1523 #ifdef DEBUG
1524     fprintf(stdout, _(", folder name: "));
1525 #endif /* DEBUG */
1526     tmp=0;
1527     while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) {
1528
1529       wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8);
1530         
1531       CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc);
1532 #ifdef DEBUG
1533       fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]);
1534 #endif /* DEBUG */
1535       tmp++;
1536       i=i+2;
1537     }
1538 #ifdef DEBUG
1539     fprintf(stdout, _("\n"));
1540 #endif /* DEBUG */
1541     tmp=0;
1542     i=i+1;
1543   }
1544       
1545   CurrentSMSFoldersError=GE_NONE;      
1546 }
1547
1548 GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders)
1549 {
1550   unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
1551   
1552   GSM_Error error;
1553   
1554   CurrentSMSFolders=folders;
1555   
1556   error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req);
1557
1558   folders->number=CurrentSMSFoldersCount;
1559     
1560   return error;
1561 }
1562
1563 void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1564 {
1565   int i;
1566
1567 #ifdef DEBUG
1568   fprintf(stdout, _("Message: SMS Folder status received\n"));
1569   fprintf(stdout, _("   Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]);
1570 #endif /* DEBUG */
1571   CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5];
1572 #ifdef DEBUG
1573   fprintf(stdout, _(" (indexes "));
1574 #endif /* DEBUG */
1575
1576   for (i=0;i<MessageBuffer[4]*256+MessageBuffer[5];i++) {
1577 #ifdef DEBUG
1578     fprintf(stdout, _("%i, "), MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7]);
1579 #endif /* DEBUG */
1580     CurrentSMSFolder.locations[i]=MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7];
1581   }
1582
1583 #ifdef DEBUG
1584   fprintf(stdout, _(")\n"));
1585 #endif /* DEBUG */
1586       
1587   CurrentSMSFolderError=GE_NONE;      
1588 }
1589
1590 GSM_Error N7110_GetSMSFolderStatus ( GSM_OneSMSFolder *folder, u8 ID)
1591 {
1592         unsigned char req[] = { N7110_FRAME_HEADER, 
1593                           0x6b, 
1594                           0x08, //folderID 
1595                           0x0F, 
1596                           0x01};
1597   
1598         GSM_Error error;
1599   
1600         CurrentSMSFolder = *folder;
1601         CurrentSMSFolderID = ID;
1602         req[4] = ID;
1603   
1604         error=NULL_SendMessageSequence(20, &CurrentSMSFolderError, 7, 0x14, req);
1605
1606         *folder=CurrentSMSFolder;
1607
1608         return error;
1609 }
1610
1611 void N7110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1612 {
1613
1614 #ifdef DEBUG
1615   fprintf(stdout, _("Message: SMS deleted succesfully\n"));
1616 #endif /* DEBUG */
1617   CurrentSMSMessageError = GE_NONE;
1618 }
1619
1620 GSM_Error N7110_DeleteSMSMessage(GSM_SMSMessage *message)
1621 {
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])*/
1627     0x01 };
1628
1629     GSM_Error error;
1630     int smsnum, location;
1631     u8 folderid;
1632
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)
1636             return(error);
1637  
1638     req[4]=folderid;
1639     req[5]=location / 256;
1640     req[6]=location;
1641
1642 #ifdef DEBUG
1643     printf("delete sms: folder %d, location %d\n",folderid,location);
1644 #endif
1645
1646     return NULL_SendMessageSequence
1647       (50, &CurrentSMSMessageError, 8, 0x14, req);
1648 }
1649
1650 GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message)
1651 {
1652
1653         unsigned char req[] = { N6110_FRAME_HEADER,
1654                           0x07, 
1655                           0x08, // folder ID
1656                           0x00, 0x05, // location
1657                           0x01, 
1658                           0x65, 
1659                           0x01};
1660
1661         int smsnum, location;
1662         u8 folderid;
1663
1664         GSM_Error error;
1665         CurrentSMSMessage = message;
1666         CurrentSMSMessageError = GE_BUSY;
1667
1668
1669         smsnum = message->Location;
1670
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;
1676         switch(error)
1677         {
1678          case GE_SMSISINMEM: /* future use: get already reed sms from mem */
1679                                 return GE_NONE;
1680                                 break;
1681          case GE_NONE:          req[4]=folderid;
1682                                 req[5]=location / 256;
1683                                 req[6]=location;
1684 #ifdef DEBUG
1685     fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location);
1686 #endif
1687                                 return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req);
1688                                 break;
1689          default:               break;
1690          }
1691
1692     return(error);
1693 }
1694
1695 void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1696 {
1697   int smsnum;
1698
1699   switch (MessageBuffer[3]) {
1700
1701   /* save sms */
1702   case 0x05:      
1703 #ifdef DEBUG
1704     fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]);
1705 #endif
1706
1707     if (CurrentSMSMessage!=NULL) {     
1708       N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]);
1709       CurrentSMSMessage->MessageNumber=smsnum;
1710     }
1711     
1712     CurrentSMSMessageError = GE_NONE;
1713     break;
1714
1715   /* save sms failed */
1716   case 0x06:
1717       
1718 #ifdef DEBUG
1719     fprintf(stdout, _("Message: SMS Message save failed\n"));
1720 #endif
1721     CurrentSMSMessageError = GE_SMSSAVEFAILED;
1722     break;
1723
1724   case 0x84:
1725 #ifdef DEBUG
1726     fprintf(stdout, _("Message: Changed name for SMS Message\n"));
1727 #endif
1728     CurrentSMSMessageError = GE_NONE;
1729     break;
1730
1731   }
1732 }
1733
1734 GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS)
1735 {
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])*/
1742     0x00  /* ??? */
1743   };
1744
1745   unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83};
1746
1747   int length,smsnum,location;
1748   u8 folderid;
1749   GSM_Error error;
1750   SMS_MessageType PDU;
1751
1752   smsnum = SMS->Location;
1753   
1754 #ifdef DEBUG
1755   printf("save sms: smsnum is :%d\n",smsnum);
1756 #endif
1757
1758   if ( SMS->Status ==  GSS_SENTREAD) req[4] = 0x01;
1759
1760   folderid = SMS->folder;
1761
1762   PDU=SMS_Deliver;
1763   
1764   error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU);
1765   if (error != GE_NONE) return error;
1766  
1767   CurrentSMSMessage = SMS;
1768
1769   error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE);
1770   switch (error)
1771   {
1772
1773     case  GE_BUSYSMSLOCATION: /* delete old sms before save */
1774       error = N7110_DeleteSMSMessage(SMS);      
1775       if (error != GE_NONE) return error;
1776       break;
1777     case  GE_NONE:
1778       break;
1779     default:
1780       return error;
1781       break;
1782   }
1783     
1784 #ifdef DEBUG
1785   printf("save sms: want to save at folder:%d , location:%d\n",folderid,location);
1786 #endif
1787
1788   req[5]=folderid;
1789   req[6]=location / 256;
1790   req[7]=location;
1791  
1792   error=NULL_SendMessageSequence
1793     (70, &CurrentSMSMessageError, 40+length, 0x14, req);
1794
1795   if (error==GE_NONE && SMS->Name[0]!=0) {
1796     length=4;
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;
1803     req2[length++]=0;
1804     req2[length++]=0;
1805     error=NULL_SendMessageSequence
1806       (70, &CurrentSMSMessageError, length, 0x14, req2);
1807   }
1808
1809   return error;
1810 }
1811
1812 /* handling for 7110 folders */
1813 GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action)
1814 {
1815     /* remember me */
1816     static int nextSMSmessage = -1;
1817     static GSM_SMSStatus Status;
1818
1819     bool found = false;
1820     int folderid;
1821     GSM_OneSMSFolder onefolder;
1822     GSM_Error error;
1823     int ismsnum;  
1824     int i;
1825
1826     switch (action) {
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   */
1830           if (smsnum == 0 )
1831           {
1832             /* first time we read folderstatus */
1833             if (  nextSMSmessage == -1)
1834             {
1835                nextSMSmessage = 0;
1836                error =  N7110_GetSMSStatus( &Status);
1837                if (error!=GE_NONE) return error;
1838             }
1839             ismsnum = Status.foldertable[nextSMSmessage].smsnum;
1840             N7110_Fake2SMSLocation( ismsnum, folder, location);
1841             nextSMSmessage++;
1842             if(nextSMSmessage >= Status.Number)
1843             { 
1844               nextSMSmessage = -1;
1845 #ifdef DEBUG
1846               printf("HandleSMS: setting nextSMSmessage to -1\n");
1847 #endif
1848             }
1849           } else /* user give location -> make fake location */
1850           {
1851             /* future use: get already read sms from mem */
1852             N7110_Fake2SMSLocation( smsnum, folder, location);
1853           }
1854           break;
1855         case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */
1856           if (smsnum == 0 )
1857           {
1858             /* calculate correct folderid */
1859             *folder = ( *folder + 1) * 8;
1860
1861             *location = 0;
1862           } else /* user give location -> make fake location */
1863           {
1864             N7110_Fake2SMSLocation( smsnum, folder, location);
1865             folderid = *folder;
1866
1867             error=N7110_GetSMSFolderStatus(&onefolder, folderid );
1868             if (error!=GE_NONE) return error;
1869
1870             /* is there a sms at that location ? */
1871             for (i=0; i<CurrentSMSFolder.number; i++)
1872               if ( CurrentSMSFolder.locations[i] == *location ) found = true;
1873     
1874             if (found == true) return GE_BUSYSMSLOCATION;
1875                           else return GE_NONE;
1876           }
1877           break;  
1878         default:
1879           return GE_UNKNOWN;
1880     } //switch
1881     return GE_NONE;
1882 }
1883
1884 /* input: fake smsnum, output: folderid & location */
1885 void  N7110_Fake2SMSLocation(int smsnum, u8 *folderid, int *location)
1886 {
1887   int ifolderid;
1888
1889   ifolderid = smsnum / N7110_MAXSMSINFOLDER;
1890   *folderid = ifolderid * 0x08;
1891   *location = smsnum -  ifolderid * N7110_MAXSMSINFOLDER;
1892 }
1893
1894 /* input; folderid & location, output: fake smsnum */
1895 void N7110_SMS2FakeLocation(int *smsnum, u8 folderid, int location)
1896 {
1897   int ifolderid;
1898   
1899   ifolderid = folderid / 0x08;
1900   *smsnum = ifolderid * N7110_MAXSMSINFOLDER + location;
1901 }
1902
1903 GSM_Error N7110_GetRFLevel(GSM_RFUnits *units, float *level)
1904 {
1905   unsigned char request[] = {N6110_FRAME_HEADER, 0x81};
1906
1907   int timeout=10;
1908   int rf_level;
1909
1910   CurrentRFLevel=-1;
1911
1912   Protocol->SendMessage(4, 0x0a, request);
1913
1914   /* Wait for timeout or other error. */
1915   while (timeout != 0 && CurrentRFLevel == -1 ) {
1916
1917     if (--timeout == 0)
1918       return (GE_TIMEOUT);
1919
1920     usleep (100000);
1921   }
1922
1923   /* Make copy in case it changes. */
1924   rf_level = CurrentRFLevel;
1925
1926   if (rf_level == -1)
1927     return (GE_NOLINK);
1928
1929   /* Now convert between the different units we support. */
1930
1931   /* Arbitrary units. */
1932   *units = GRF_Percentage;
1933   *level = rf_level;
1934   return (GE_NONE);
1935 }
1936
1937 GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1938 {
1939   unsigned char request[] = {N6110_FRAME_HEADER, 0x02};
1940
1941   int timeout=10;
1942   int batt_level;
1943
1944   CurrentBatteryLevel=-1;
1945
1946   Protocol->SendMessage(4, 0x17, request);
1947
1948   /* Wait for timeout or other error. */
1949   while (timeout != 0 && CurrentBatteryLevel == -1 ) {
1950
1951     if (--timeout == 0)
1952       return (GE_TIMEOUT);
1953
1954     usleep (100000);
1955   }
1956
1957   /* Take copy in case it changes. */
1958   batt_level = CurrentBatteryLevel;
1959
1960   if (batt_level == -1)
1961     return (GE_NOLINK);
1962     
1963   /* Only units we handle at present are GBU_Arbitrary */
1964   *units = GBU_Percentage;
1965   *level = batt_level;
1966   return (GE_NONE);
1967 }
1968
1969 GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
1970 {
1971   unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c};
1972
1973   if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED;
1974
1975   CurrentSecurityCode=SecurityCode;
1976
1977   return NULL_SendMessageSequence
1978     (50, &CurrentSecurityCodeError, 5, 0x7a, req);
1979 }
1980
1981 GSM_Error N7110_GetDateTime(GSM_DateTime *date_time)
1982 {
1983   return N6110_PrivGetDateTime(date_time,0x19);
1984 }
1985
1986 /* Needs SIM card with PIN in phone */
1987 GSM_Error N7110_SetDateTime(GSM_DateTime *date_time)
1988 {
1989   return N6110_PrivSetDateTime(date_time,0x19);
1990 }
1991
1992 GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1993 {
1994   return N6110_PrivGetAlarm(alarm_number,date_time,0x19);
1995 }
1996
1997 /* FIXME: we should also allow to set the alarm off :-) */
1998 GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
1999 {
2000   return N6110_PrivSetAlarm(alarm_number,date_time, 0x19);
2001 }
2002
2003 void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2004 {
2005   switch (MessageBuffer[3]) {
2006
2007   /* sms status */
2008   case 0x37:
2009
2010 #ifdef DEBUG
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]);
2016 #endif /* DEBUG */
2017     CurrentSMSStatus->UnRead = MessageBuffer[13];
2018     CurrentSMSStatusError = GE_NONE;
2019     break;
2020
2021   case 0x38:
2022
2023 #ifdef DEBUG
2024     fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
2025 #endif /* DEBUG */
2026     CurrentSMSStatusError = GE_INTERNALERROR;
2027     break;
2028
2029   }
2030 }
2031
2032 GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status)
2033 {
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};
2037
2038   GSM_SMSFolders folders;
2039   GSM_OneSMSFolder folder;
2040   GSM_Error error;
2041   u8 ifolder;
2042   int ismsnum,ilocation;
2043   int i,j,smsmaxnum;
2044
2045   CurrentSMSStatus = Status;
2046
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;
2051     
2052   smsmaxnum=0;
2053   for(j=0; j<folder.number; j++)
2054   {
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; 
2061     smsmaxnum++;
2062   } 
2063  
2064   /* read standard folders */
2065   N7110_GetSMSFolders (&folders);
2066   for(i=0; i<CurrentSMSFoldersCount; i++)
2067   {
2068     error = N7110_GetSMSFolderStatus(&CurrentSMSFolders->Folder[i], CurrentSMSFolders->FoldersID[i]);
2069     if (error != GE_NONE) return error;
2070      
2071     for(j=0; j<CurrentSMSFolders->Folder[i].number; j++)
2072     {
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; 
2079       smsmaxnum++;
2080     }
2081   }
2082   CurrentSMSStatus->Number = smsmaxnum;
2083
2084   return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req);
2085 }
2086
2087 void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2088 {
2089   int i, count, blocks, blockcount;
2090 #ifdef DEBUG
2091   int j;
2092 #endif
2093   unsigned char *pBlock;
2094
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;
2100
2101 #ifdef DEBUG
2102   fprintf(stdout, _("Message: Phonebook entry received:\n"));
2103 #endif
2104
2105   if( MessageBuffer[6] == 0x0f ) // not found
2106   {
2107 #ifdef DEBUG
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;
2113     }
2114 #endif
2115     switch (MessageBuffer[10]) {
2116       case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break;
2117       case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break;
2118       default  :CurrentPhonebookError = GE_UNKNOWN;
2119     }
2120     CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
2121
2122   } else {
2123
2124     CurrentPhonebookEntry->Location=MessageBuffer[13];
2125
2126     count      = MessageBuffer[9];
2127     blocks     = MessageBuffer[17];
2128     blockcount = 0;
2129
2130     CurrentPhonebookEntry->SubEntriesCount = blocks - 1;
2131
2132 #ifdef DEBUG
2133     fprintf(stdout, _("  Blocks: %d\n"),blocks);
2134 #endif /* DEBUG */
2135
2136     pBlock = &MessageBuffer[18];
2137
2138     for( i = 0; i < blocks; i++ )
2139     {
2140       GSM_SubPhonebookEntry* pEntry = &CurrentPhonebookEntry->SubEntries[blockcount];
2141
2142 #ifdef DEBUG
2143       fprintf(stdout,_("   "));
2144       for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]);
2145       fprintf(stdout,_("\n"));
2146 #endif
2147
2148       switch( pBlock[0] ) {
2149       case N7110_ENTRYTYPE_SPEEDDIAL:
2150     
2151         CurrentSpeedDialEntry->MemoryType = GMT_SM;
2152         if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME;
2153       
2154         CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256;
2155
2156 #ifdef DEBUG
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);
2161 #endif /* DEBUG */
2162
2163         CurrentSpeedDialError=GE_NONE;
2164         break;
2165
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;
2171 #ifdef DEBUG
2172         fprintf(stdout, _("   Name:\n"));
2173         fprintf(stdout, _("     Name: %s\n"), CurrentPhonebookEntry->Name);
2174 #endif /* DEBUG */
2175         break;
2176
2177       case N7110_ENTRYTYPE_NUMBER:
2178         pEntry->EntryType   = pBlock[0];
2179         pEntry->NumberType  = pBlock[5];
2180         pEntry->BlockNumber = pBlock[4];
2181
2182         DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2);
2183
2184 #ifdef DEBUG
2185         fprintf(stdout, _("   Number:\n"));
2186         fprintf(stdout, _("     Type: %d (%02x)\n"),
2187           pEntry->NumberType,
2188           pEntry->NumberType);
2189         fprintf(stdout, _("     Number: %s\n"),
2190           pEntry->data.Number);
2191 #endif /* DEBUG */
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;
2198         } else
2199           blockcount++;
2200         break;
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);
2206 #ifdef DEBUG
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);
2212 #endif /* DEBUG */
2213         blockcount++;
2214         break;
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];
2221
2222         DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2);
2223
2224 #ifdef DEBUG
2225         fprintf(stdout, _("   Email or note or postal:\n"));
2226         fprintf(stdout, _("     Type: %d (%02x)\n"),
2227           pEntry->EntryType,
2228           pEntry->EntryType);
2229         fprintf(stdout, _("     Text: %s\n"),
2230           pEntry->data.Number);
2231 #endif /* DEBUG */
2232         blockcount++;
2233         break;
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;
2238 #ifdef DEBUG
2239         fprintf(stdout, _("   Group: %d\n"), CurrentPhonebookEntry->Group);
2240 #endif /* DEBUG */
2241         break;
2242       case N7110_ENTRYTYPE_RINGTONE:
2243         if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2244           CurrentGetBitmap->ringtone = pBlock[5];
2245 #ifdef DEBUG
2246         fprintf(stdout, _("   Group ringtone number %d received.\n"), pBlock[5]);
2247 #endif /* DEBUG */
2248         break;
2249       case N7110_ENTRYTYPE_LOGOON:
2250         if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2251           CurrentGetBitmap->enabled = pBlock[5];
2252 #ifdef DEBUG
2253         fprintf(stdout, _("   Logo enabled = %d received.\n"), pBlock[5]);
2254 #endif /* DEBUG */
2255         break;
2256       case N7110_ENTRYTYPE_GROUPLOGO:
2257 #ifdef DEBUG
2258         fprintf(stdout, _("   Caller group logo received.\n"));
2259 #endif /* DEBUG */
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);
2267         }
2268         break;
2269
2270       default:
2271 #ifdef DEBUG
2272         fprintf(stdout, _("   Unknown Entry Code (%u) received.\n"), pBlock[0] );
2273 #endif /* DEBUG */
2274         break;
2275       }
2276        
2277 #ifdef DEBUG
2278       fprintf(stdout, _("     Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]);
2279 #endif
2280       pBlock = &pBlock[(int) pBlock[3]];
2281     }
2282
2283     CurrentPhonebookEntry->SubEntriesCount = blockcount;
2284     CurrentPhonebookError = GE_NONE;
2285   }
2286 }
2287
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
2290    occurs. */
2291 GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) {
2292
2293   unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2294                          0x02, //memory type
2295                          0x05,
2296                          0x00, 0x00, //location
2297                          0x00, 0x00};
2298
2299   CurrentPhonebookEntry = entry;
2300
2301   req[9] = N7110_GetMemoryType(entry->MemoryType);
2302   req[10] = (entry->Location>>8);
2303   req[11] = entry->Location & 0xff;
2304
2305   return NULL_SendMessageSequence
2306     (50, &CurrentPhonebookError, 14, 0x03, req);
2307 }
2308
2309 void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2310 {
2311   // [12,13] = Location
2312   // [14] = Memory
2313
2314   if( MessageBuffer[6] == 0x0f ) // ERROR
2315   {
2316 #ifdef DEBUG
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;
2323     }
2324 #endif /* DEBUG */
2325     CurrentPhonebookError = GE_NONE;
2326   } else {
2327 #ifdef DEBUG
2328     fprintf(stdout, _("Message: Phonebook written correctly.\n"));
2329 #endif /* DEBUG */
2330
2331     CurrentPhonebookError = GE_NONE;
2332   }
2333 }
2334
2335 int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block)
2336 {
2337 #ifdef DEBUG
2338   fprintf(stdout,_("Adding block id:%i,length:%i\n"),no+1,size+6);
2339 #endif
2340
2341   *(block++) = id;
2342   *(block++) = 0;
2343   *(block++) = 0;
2344   *(block++) = size + 6;
2345   *(block++) = no + 1;
2346
2347   memcpy(block, buf, size);
2348   block += size;
2349
2350   *(block++) = 0;
2351
2352   return (size + 6);
2353 }
2354
2355 int N7110_MakePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block)
2356 {
2357   int count=0, len, i;
2358
2359   char string[500];
2360
2361   *block=0;
2362
2363   /* Name */
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);
2369
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);
2378   }
2379                 
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);
2388     } else {
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);
2395     }
2396   } 
2397
2398   if (entry.Group != 5) {
2399     /* Group */
2400     string[0] = entry.Group + 1;
2401     string[1] = 0;
2402     count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, *block++, string, req + count);
2403   }
2404
2405   return count;
2406 }
2407  
2408 /* Routine to write phonebook location in phone. */
2409 GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
2410 {
2411   unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2412                                    0x00, 0x00,  /* memory type */
2413                                    0x00, 0x00,  /* location */
2414                                    0x00, 0x00, 0x00};
2415   int count = 18, blocks;
2416
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;
2421
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; 
2426
2427     count=count+N7110_MakePhonebookFrame(req+18, *entry, &blocks);
2428
2429     req[17]=blocks;
2430
2431 #ifdef DEBUG
2432     fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name);
2433 #endif
2434
2435     return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req);
2436
2437   } else {
2438
2439     /* empty name & number => we have to delete the phonebook record! */
2440     return N7110_DeletePhonebookLocation( entry );
2441
2442   }  
2443 }
2444
2445 void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2446 {
2447 #ifdef DEBUG
2448   fprintf(stdout, _("Message: Phonebook entry deleted correctly\n"));
2449 #endif /* DEBUG */
2450   CurrentPhonebookError = GE_NONE;
2451 }
2452
2453 /* delete phonebookentry */
2454 /* Not used in this moment */
2455 GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry)
2456 {
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*/
2464     0x00, 0x00
2465       };
2466
2467    req[12] = (entry->Location >> 8);
2468    req[13] = entry->Location & 0xff;
2469    req[14] = N7110_GetMemoryType(entry->MemoryType);
2470  
2471 #ifdef DEBUG
2472         fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location);
2473 #endif
2474   
2475   return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req);
2476 }
2477
2478 /* for saving group logos only */
2479 GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap)
2480 {
2481   unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2482                             0x00, 0x10,  /* memory type */
2483                             0x00, 0x00,  /* location */
2484                             0x00, 0x00, 0x00};
2485   char string[500];
2486   int block=0, i;
2487   unsigned int count = 18;
2488
2489   req[13] = bitmap->number + 1;
2490
2491   /* Logo on/off */
2492   string[0] = bitmap->enabled?1:0;
2493   string[1] = 0;
2494   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count);
2495
2496   /* Ringtone */
2497   string[0] = bitmap->ringtone;
2498   string[1] = 0;
2499   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count);
2500
2501   /* Number of group */
2502   string[0] = bitmap->number+1;
2503   string[1] = 0;
2504   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2505
2506   /* Logo */
2507   string[0] = bitmap->width;
2508   string[1] = bitmap->height;
2509   string[2] = 0;
2510   string[3] = 0;
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);
2514
2515   /* Name */
2516   if (*bitmap->text) {
2517     i = strlen(bitmap->text);
2518     string[0] = i * 2;
2519     EncodeUnicode((string + 1), bitmap->text, i);
2520     count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 1, block++, string, req + count);
2521   }
2522
2523   req[17] = block; //number of blocks
2524
2525   return NULL_SendMessageSequence
2526     (50, &CurrentPhonebookError, count, 0x03, req);
2527 }
2528
2529 GSM_Error N7110_GetSpeedDial(GSM_SpeedDial *entry)
2530 {
2531   unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2532                          0x02, //memory type
2533                          0x05,
2534                          0x00, 0x00, //location
2535                          0x00, 0x00};
2536
2537   GSM_PhonebookEntry entry2;
2538   GSM_Error error;
2539
2540   CurrentPhonebookEntry = &entry2;
2541
2542   CurrentSpeedDialEntry = entry;
2543
2544   req[9] = N7110_MEMORY_SD;
2545   req[10] = (entry->Number>>8);
2546   req[11] = entry->Number & 0xff;
2547
2548   error=NULL_SendMessageSequence
2549     (50, &CurrentSpeedDialError, 14, 0x03, req);
2550
2551   /* Full compatibility with 6110 */
2552   if (error==GE_INVALIDSPEEDDIALLOCATION) {
2553     entry->Location=0;
2554     entry->MemoryType=GMT_MT;
2555     return GE_NONE;
2556   } else return error;
2557 }
2558
2559 /* Experimental ! */
2560 GSM_Error N7110_SetSpeedDial(GSM_SpeedDial *entry)
2561 {
2562   unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2563                             0x00, 0x0e,  /* memory type */
2564                             0x00, 0x00,  /* location */
2565                             0x00, 0x00, 0x00};
2566   char string[500];
2567   int block=1;
2568   unsigned int count = 18;
2569
2570   req[13] = entry->Number;
2571
2572   string[0]= 0xff;
2573   string[1]= entry->Location/256;
2574   string[2]= entry->Location%256;
2575   string[3]= 0x05;
2576   string[4]= string[5] = 0;
2577   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_SPEEDDIAL, 6, block++, string, req + count);
2578
2579   req[17] = block - 1; //number of blocks
2580
2581   return NULL_SendMessageSequence
2582     (50, &CurrentPhonebookError, count, 0x03, req);
2583 }
2584
2585 /* Set a bitmap or welcome-note */
2586 GSM_Error N7110_SetBitmap(GSM_Bitmap *Bitmap)
2587 {
2588   unsigned char reqStartup[1000] = { N7110_FRAME_HEADER,
2589                                      0xec, 0x15, // Startup Logo
2590                                      0x00, 0x00, 0x00, 0x04,
2591                                      0xc0, 0x02, 0x00,
2592                                      0x00,       // Bitmap height
2593                                      0xc0, 0x03, 0x00,
2594                                      0x00,       // Bitmap width
2595                                      0xc0, 0x04, 0x03, 0x00
2596                                    };            // Bitmap following
2597   unsigned char reqOp[1000] = { N7110_FRAME_HEADER,
2598                                 0xa3, 0x01,
2599                                 0x00,              // logo disabled
2600                                 0x00, 0xf0, 0x00,  // network code (000 00)
2601                                 0x00 ,0x04,
2602                                 0x08,              // length of rest
2603                                 0x00, 0x00,        // Bitmap width / height
2604                                 0x00,
2605                                 0x00,              // Bitmap size
2606                                 0x00, 0x00
2607                               };                   // Bitmap following
2608
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,
2613                                 0x00,  //location
2614                                 0x00,0x00, //index
2615                                 0x07};
2616
2617   unsigned char req5[120] = {0x00, 0x01, 0x01, 0xec, 0x02,0x00};
2618
2619   unsigned char req6[]= {0x00,0x01,0x00,0xaf,0x00};
2620
2621   u16 count,i;
2622
2623   int timeout=60;
2624   
2625   GSM_Error error;
2626
2627   CurrentSetBitmapError=GE_BUSY;
2628   
2629   switch (Bitmap->type) {
2630   case GSM_WelcomeNoteText:
2631
2632     EncodeUnicode (req5+5, Bitmap->text, strlen(Bitmap->text));
2633     count=5+strlen(Bitmap->text)*2;
2634     req5[count++]=0x00;
2635     req5[count++]=0x00;
2636     Protocol->SendMessage(count, 0x7a, req5);
2637     break;
2638
2639   case GSM_DealerNoteText:
2640     CurrentSetBitmapError = GE_NOTIMPLEMENTED;
2641     break;
2642
2643   case GSM_StartupLogo:
2644   case GSM_7110StartupLogo:
2645   case GSM_6210StartupLogo:
2646     reqStartup[12] = Bitmap->height;
2647     reqStartup[16] = Bitmap->width;
2648     count = 21;
2649     memcpy(reqStartup+count,Bitmap->bitmap,Bitmap->size);
2650     Protocol->SendMessage(count+Bitmap->size, 0x7a, reqStartup);
2651     break;
2652
2653   case GSM_OperatorLogo:
2654   case GSM_7110OperatorLogo:
2655     count = 18;
2656     
2657     /* set logo */
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;
2667     } else {
2668       for (i=0;i<5;i++) {
2669         req6[4]=i;
2670         error=NULL_SendMessageSequence
2671           (50, &CurrentSetBitmapError, 5, 0x0a, req6);
2672         if (error!=GE_NONE) return error;
2673       }
2674     }
2675     Protocol->SendMessage(count, 0x0a, reqOp);
2676     break;
2677
2678   case GSM_CallerLogo:
2679     CurrentSetBitmapError = N7110_WriteGroupDataLocation(Bitmap);
2680     break;
2681
2682   case GSM_PictureImage:
2683     CurrentGetBitmap=Bitmap;
2684     PictureImageNum=0;
2685     count=0;
2686     while (count!=9) {
2687       req2[4]=req3[count];
2688       PictureImageLoc=req3[count];
2689       count++;
2690       if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE) break;
2691       if (PictureImageNum==Bitmap->number+1) break;
2692     }
2693     if (CurrentGetBitmapError!=GE_NONE) {
2694       req4[5]=0x21;
2695       req4[6]=0;
2696       req4[7]=0;
2697     } else {
2698       req4[5]=PictureImageLoc;
2699       req4[6]=PictureImageIndex/256;
2700       req4[7]=PictureImageIndex%256;
2701     }
2702     count=7;
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;
2710     req4[count++]=0x00;
2711     req4[count++]=0x00;
2712
2713     CurrentSetBitmapError = GE_BUSY;
2714
2715     Protocol->SendMessage(count, 0x14, req4);
2716
2717   case GSM_None:
2718     return GE_NONE;
2719   }
2720
2721   /* Wait for timeout or other error. */
2722   while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
2723           
2724     if (--timeout == 0)
2725       return (GE_TIMEOUT);
2726                     
2727     usleep (100000);
2728   }
2729
2730   if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo)
2731      && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) {
2732     return N6110_Reset(0x03);
2733   }
2734
2735   return CurrentSetBitmapError;
2736 }
2737
2738 /* Get a bitmap from the phone */
2739 GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap)
2740 {
2741   unsigned char req[10] = { N6110_FRAME_HEADER };
2742
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,
2747                                 0x00,  //location
2748                                 0x00,0x00, //index
2749                                 0x00, 0x64};
2750
2751   /* Welcome note */
2752   unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02};
2753
2754   u8 count=3;
2755   int timeout;
2756   GSM_PhonebookEntry entry;
2757
2758   CurrentGetBitmapError = GE_BUSY;
2759
2760   CurrentGetBitmap=Bitmap;
2761
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 */
2768     req[count++]=0x15;
2769     Protocol->SendMessage(count, 0x7a, req);
2770     break;
2771
2772   case GSM_WelcomeNoteText:
2773
2774     Protocol->SendMessage(5, 0x7a, req5);
2775     break;
2776
2777   case GSM_DealerNoteText:
2778
2779     return GE_NOTIMPLEMENTED;
2780     
2781   case GSM_OperatorLogo:
2782   case GSM_7110OperatorLogo:
2783     req[count++]=0x70; /* NetworkStatus */
2784     Protocol->SendMessage(count, 0x0a, req);
2785     break;
2786
2787   case GSM_CallerLogo:
2788     entry.MemoryType = GMT_CG;
2789     entry.Location = Bitmap->number+1;
2790     *Bitmap->text=0;
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;
2803       }
2804     }
2805     break;
2806
2807   case GSM_PictureImage:
2808
2809     PictureImageNum=0;
2810     count=0;
2811     while (count!=9) {
2812       req2[4]=req3[count];
2813       PictureImageLoc=req3[count];
2814       count++;
2815       if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE)
2816         return CurrentGetBitmapError;
2817       if (PictureImageNum==Bitmap->number+1) break;
2818     }
2819     if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError;
2820
2821     req4[4]=PictureImageLoc;
2822     req4[5]=PictureImageIndex/256;
2823     req4[6]=PictureImageIndex%256;
2824
2825     CurrentGetBitmapError = GE_BUSY;
2826
2827     Protocol->SendMessage(9, 0x14, req4);
2828
2829     break;
2830   
2831   default:
2832     return GE_NOTSUPPORTED;
2833   }
2834
2835   timeout=150;
2836
2837   while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) {
2838
2839     if (--timeout == 0)
2840       return (GE_TIMEOUT);
2841
2842     usleep (100000);
2843   }
2844
2845   CurrentGetBitmap=NULL;
2846
2847   return (CurrentGetBitmapError);
2848 }
2849
2850 int ReturnBinRingLocation()
2851 {
2852   char model[64];
2853
2854   while (GSM->GetModel(model) != GE_NONE) sleep(1);
2855
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
2858     
2859   return 0;
2860 }
2861
2862 /*
2863 this works only for 6210, the 7110 needs upload to a location ? 
2864 */
2865 GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
2866 {  
2867
2868   /* Buffer for preview uploading */
2869   unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D,
2870                                 0x00, 0x00, 0x00, 0x00,
2871                                 0x00, 0x00,
2872                                 0x00  // Length
2873                                };
2874   int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
2875
2876   GSM_NetworkInfo NetworkInfo;
2877
2878   char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
2879                     0x87,  // Location
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
2886                    };
2887
2888   /* Info from Till Toenshoff [till@uni.de]
2889
2890      One improvement - for looping you can use an alternative header\r
2891      normal\r
2892      0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01\r
2893 \r
2894      loop\r
2895      0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01\r
2896 \r
2897      LL=0x01-0x10\r
2898 \r
2899      0x01=loop once\r
2900      [...]\r
2901      0x10=loop infinite\r
2902   */
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
2906                 };
2907
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 };
2911
2912   int current = 6, i, note, lastnote = 0, duration;
2913
2914   /* Preview uploading */
2915   if (ringtone->location==255) {
2916     *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size);
2917     buffer[10] = size;
2918     Protocol->SendMessage(size+11, 0x00, buffer);
2919     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
2920     sleep(1);
2921     return GE_NONE; //no answer from phone
2922   }
2923
2924   req[5]=ReturnBinRingLocation()+ringtone->location;
2925
2926   EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name));
2927
2928   current = 43;
2929
2930   for (i=0; i<ringtone->NrNotes; i++) {
2931
2932     if (ringtone->notes[i].note == 255)
2933       note = 0x40;
2934     else
2935       note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14];
2936
2937     duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256;  // in 8 ms ticks of 7110
2938
2939     switch (ringtone->notes[i].style) {
2940       case StaccatoStyle:
2941         if (duration) {
2942           req[current++] = note;   // note only for one tick
2943           req[current++] = 1;
2944           duration--;
2945         }
2946         note = 0x40;               // rest pause
2947       case NaturalStyle:
2948         if (note != 0x40 && duration) {
2949           req[current++] = 0x40;
2950           req[current++] = 1;      // small pause between notes
2951           duration--;
2952         }
2953       default:
2954         if (note != 0x40 && note == lastnote && duration) {
2955           req[current++] = 0x40;
2956           req[current++] = 1;      // small pause between same notes
2957           duration--;
2958         }
2959
2960         while (duration > 125) {
2961           req[current++] = note;
2962           req[current++] = 125;
2963           duration -= 125;
2964         }
2965         req[current++] = note;
2966         req[current++] = duration;
2967     }
2968     lastnote = note;
2969   }
2970
2971   for (i = 0; i < sizeof(tail); i++)
2972     req[current++] = tail[i];
2973
2974   Protocol->SendMessage(current, 0x1F, req);
2975
2976   sleep(1);  
2977
2978   return GE_NONE; //no answer from phone
2979 }
2980
2981 void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2982 {
2983   int i, tmp;
2984
2985   switch (MessageBuffer[3]) {
2986
2987   case 0x23:
2988
2989     tmp=0;i=4;
2990     while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) {
2991       tmp++;
2992       i=i+2;
2993     }
2994
2995     DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp);
2996
2997 #ifdef DEBUG
2998     fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name);
2999 #endif /* DEBUG */
3000
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;
3006
3007     memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name));
3008
3009     CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name);
3010
3011     CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3012     CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3013
3014     /* Looking for end */
3015     i=37;
3016     while (true) {
3017       if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
3018         i=i+2;break;
3019       }
3020       if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
3021         i=i+2;break;
3022       }
3023       i++;
3024       if (i==MessageLength) break;
3025     }
3026           
3027     /* Copying frame */
3028     memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37);
3029     CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37;
3030       
3031     CurrentBinRingtoneError=GE_NONE;
3032     break;
3033
3034   case 0x24:
3035
3036 #ifdef DEBUG
3037     fprintf(stdout, _("Message: Received empty ringtone\n"));
3038 #endif /* DEBUG */
3039
3040     CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;
3041     break;
3042   }
3043 }
3044
3045 GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone)
3046 {
3047
3048   unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 };
3049
3050   req[2]=0x01;
3051
3052   req[5]=ReturnBinRingLocation()+ringtone->location;
3053
3054   CurrentGetBinRingtone=ringtone;
3055
3056   return NULL_SendMessageSequence
3057     (50, &CurrentBinRingtoneError, 6, 0x1f, req);
3058
3059 }
3060
3061 GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone)
3062 {
3063   unsigned char req[500] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 };
3064
3065   GSM_NetworkInfo NetworkInfo;
3066   
3067   int i;
3068
3069   req[2]=0x01;
3070
3071   req[5]=ReturnBinRingLocation()+ringtone->location;
3072
3073   for (i=6;i<35;i++) req[i]=0x00;
3074
3075   i=6;
3076
3077   EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5));
3078
3079   i=5;
3080
3081   while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++;
3082
3083   memcpy(req+35,ringtone->frame+i,ringtone->length-i);
3084
3085   Protocol->SendMessage(35+ringtone->length-i, 0x1f, req);  \r
3086
3087   GSM->GetNetworkInfo(&NetworkInfo); //need to make something    
3088   
3089   return GE_NONE; //no answer from phone
3090 }
3091
3092 void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3093   
3094   GSM_SMSMessage NullSMS;
3095     
3096 #ifdef DEBUG
3097   fprintf(stdout,_("Message: Incoming SMS\n"));
3098 #endif /* DEBUG */
3099
3100   GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5);
3101
3102 #ifdef DEBUG
3103   fprintf(stdout, _("\n"));      
3104 #endif /* DEBUG */      
3105 }
3106
3107 void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3108 {
3109   int count;
3110
3111 #ifdef DEBUG  
3112   char name[100];
3113 #endif
3114   
3115   GSM_NetworkInfo NullNetworkInfo;
3116
3117   switch (MessageBuffer[3]) {
3118
3119   case 0xb0:
3120
3121 #ifdef DEBUG
3122     fprintf(stdout, _("Message: Clearing operator logo msg\n"));
3123 #endif
3124     CurrentSetBitmapError=GE_NONE;
3125     break;
3126
3127   case 0x71:
3128
3129     /* Make sure we are expecting NetworkInfo frame */
3130     if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) ||
3131         (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) {
3132 #ifdef DEBUG
3133       fprintf(stdout, _("Message: Network informations and operator logo:\n"));
3134 #endif
3135     } else {
3136 #ifdef DEBUG
3137       fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
3138 #endif
3139     }
3140
3141     sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
3142
3143     sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
3144
3145     sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
3146
3147 #ifdef DEBUG
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));
3154
3155     DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]);
3156     fprintf(stdout, _("   Network name for phone: %s\n"),name);
3157
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"));
3165     }
3166
3167     fprintf(stdout, "\n");
3168
3169     fprintf(stdout, _("   Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
3170 #endif /* DEBUG */
3171
3172     /* Make sure we are expecting NetworkInfo frame */
3173     if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
3174       *CurrentNetworkInfo=NullNetworkInfo;
3175       CurrentNetworkInfoError = GE_NONE;
3176     }
3177
3178     /* Make sure we are expecting an operator logo */
3179     if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3180
3181       strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode);
3182
3183 #ifdef DEBUG
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));
3188       else
3189         fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"),
3190                            CurrentGetBitmap->netcode,
3191                            GSM_GetNetworkName(CurrentGetBitmap->netcode));
3192 #endif
3193
3194       if (MessageBuffer[4] == 0x02) {   /* logo present */
3195         count = 7;
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 */
3200         count+=4;
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);
3205       } else {
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);
3210       }
3211       CurrentGetBitmapError=GE_NONE;
3212     }
3213
3214     break;
3215
3216   case 0x82:
3217 #ifdef DEBUG
3218     fprintf(stdout, _("Message: Network Level received:\n"));
3219
3220     fprintf(stdout, _("   Network Level: %d\n"), MessageBuffer[4]);
3221 #endif /* DEBUG */
3222
3223     CurrentRFLevel=MessageBuffer[4];
3224     break;
3225
3226   case 0xa4:
3227
3228 #ifdef DEBUG
3229     fprintf(stdout, _("Message: Operator logo set correctly.\n"));
3230 #endif
3231     CurrentSetBitmapError = GE_NONE;      
3232     break;
3233
3234   default:
3235 #ifdef DEBUG
3236     fprintf(stdout, _("Message: Unknown message of type 0x0a\n"));
3237 #endif /* DEBUG */
3238     AppendLogText("Unknown msg\n",false);
3239     break;      /* Visual C Don't like empty cases */
3240   }
3241 }
3242
3243 void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3244 {
3245   int i, tmp;
3246   GSM_ETSISMSMessage ETSI;
3247
3248   switch (MessageBuffer[3]) {
3249
3250   /* We have requested invalid or empty location. */
3251   case 0x09:
3252
3253 #ifdef DEBUG
3254     fprintf(stdout, _("Message: SMS reading failed\n"));
3255 #endif /* DEBUG */
3256
3257    CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3258    CurrentGetBitmapError=GE_UNKNOWN;
3259    break;
3260
3261   /* getsms or picture image */    
3262   case 0x08:
3263
3264     if (MessageBuffer[8]==0x07) {
3265
3266       if (CurrentGetBitmap!=NULL) {
3267
3268         for (i=0;i<MessageBuffer[9]+1;i++)
3269           ETSI.SMSCNumber[i]=MessageBuffer[i+9];
3270
3271         for (i=0;i<((MessageBuffer[22]+1)/2+1)+1;i++)
3272            ETSI.Number[i]=MessageBuffer[22+i];
3273
3274 #ifdef DEBUG
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));
3278 #endif /* DEBUG */
3279
3280         strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3281
3282         CurrentGetBitmap->width=MessageBuffer[47];
3283         CurrentGetBitmap->height=MessageBuffer[48];
3284         CurrentGetBitmap->size=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
3285       
3286         memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size);
3287
3288         tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size,
3289                                        CurrentGetBitmap->text);
3290
3291         CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0;
3292  
3293         CurrentGetBitmapError=GE_NONE;
3294           
3295       } else {
3296 #ifdef DEBUG
3297         fprintf(stdout, _("Message: Picture Image received, but not reqested\n"));
3298 #endif /* DEBUG */
3299
3300         CurrentSMSMessageError = GE_SMSTOOLONG;
3301       }
3302         
3303       break;
3304     } else {
3305       /* sms message */
3306       /* status in byte 4 */
3307       CurrentSMSMessage->Status = MessageBuffer[4];
3308
3309       CurrentSMSMessage->Type = GST_SMS;
3310       if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR;
3311       
3312       CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location;
3313         
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;
3318 #ifdef DEBUG
3319       fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n")
3320                 ,CurrentSMSMessage->Type, CurrentSMSMessage->folder,  MessageBuffer[7]);
3321 #endif /* DEBUG */
3322
3323       GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9);    
3324
3325       /* Signal no error to calling code. */
3326       CurrentSMSMessageError = GE_NONE;
3327       break;
3328     }
3329     
3330   case 0x97:
3331
3332 #ifdef DEBUG
3333     fprintf(stdout, _("Message: Received index for Picture Images\n"));
3334 #endif /* DEBUG */
3335
3336     for (i=1;i<MessageBuffer[4]*256+MessageBuffer[5]+1;i++) {
3337       PictureImageNum++;
3338       if (PictureImageNum==CurrentGetBitmap->number+1) {
3339         PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2];
3340         break;
3341       }
3342     }
3343
3344     CurrentGetBitmapError=GE_NONE;    
3345     CurrentSetBitmapError=GE_NONE;    
3346
3347     break;
3348     
3349   default:
3350
3351 #ifdef DEBUG
3352     fprintf(stdout, _("Message: Unknown message of type 14\n"));
3353 #endif /* DEBUG */
3354     AppendLogText("Unknown msg\n",false);
3355     break;      /* Visual C Don't like empty cases */
3356   }
3357 }
3358
3359 void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3360 {
3361   switch (MessageBuffer[3]) {
3362
3363   case 0x03:
3364
3365 #ifdef DEBUG
3366     fprintf(stdout, _("Message: Battery status received:\n"));
3367
3368     fprintf(stdout, _("   Battery Level: %d\n"), MessageBuffer[5]);
3369 #endif /* DEBUG */
3370
3371     CurrentBatteryLevel=MessageBuffer[5];
3372     break;
3373
3374   default:
3375
3376 #ifdef DEBUG
3377     fprintf(stdout, _("Message: Unknown message of type 0x17\n"));
3378 #endif /* DEBUG */
3379     AppendLogText("Unknown msg\n",false);
3380     break;      /* Visual C Don't like empty cases */
3381   }
3382 }
3383
3384 void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3385 {
3386   int i, tmp;
3387
3388   switch (MessageBuffer[3]) {
3389
3390   /* Setting setting request */
3391   case 0xeb:
3392
3393     switch (MessageBuffer[4]) {
3394       case 0x02:
3395
3396 #ifdef DEBUG
3397         fprintf(stdout, _("Message: Startup text set correctly.\n"));
3398 #endif
3399         CurrentSetBitmapError = GE_NONE;
3400         break;
3401
3402       case 0x15:
3403 #ifdef DEBUG
3404         fprintf(stdout, _("Message: Startup logo set correctly.\n"));
3405 #endif
3406         CurrentSetBitmapError = GE_NONE;
3407         break;
3408     }
3409
3410     break;
3411
3412   /* Setting received */
3413   case 0xed:
3414
3415     switch (MessageBuffer[4]) {
3416       case 0x02:
3417
3418 #ifdef DEBUG
3419         fprintf(stdout, _("Message: Startup text received.\n"));
3420 #endif
3421
3422         tmp=0;i=6;
3423         while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) {
3424           i=i+2;
3425           tmp++;
3426         }
3427
3428         DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp);
3429
3430 #ifdef DEBUG
3431         fprintf(stdout, _("   Text: \"%s\"\n"),CurrentGetBitmap->text);
3432 #endif
3433
3434         CurrentGetBitmapError = GE_NONE;
3435         break;
3436
3437       case 0x15:
3438 #ifdef DEBUG
3439         if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
3440           fprintf(stdout, _("Message: Startup logo received.\n"));
3441         else
3442           fprintf(stdout, _("Message: Startup logo not requested, but received.\n"));
3443 #endif
3444
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;
3454         }
3455         break;
3456       case 0x1c:
3457 #ifdef DEBUG
3458         fprintf(stdout, _("Message: security code \""));
3459
3460         for (i=6;i<11;i++) {
3461           fprintf(stdout, _("%c"),MessageBuffer[i]);
3462         }
3463           
3464         fprintf(stdout,_("\"received.\n"));
3465 #endif
3466         strncpy(CurrentSecurityCode->Code,MessageBuffer+6,6);
3467           
3468         CurrentSecurityCodeError=GE_NONE;         
3469         break;
3470     }
3471     break;
3472       
3473   default:
3474 #ifdef DEBUG
3475     fprintf(stdout, _("Unknown message of type 0x7a.\n"));
3476 #endif
3477     AppendLogText("Unknown msg\n",false);
3478     break;      /* Visual C Don't like empty cases */
3479   }
3480 }
3481
3482 void N7110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3483 {
3484   bool unknown=false;
3485
3486   /* Switch on the basis of the message type byte */
3487   switch (MessageType) {
3488
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
3492      errors */
3493   case 0x01:
3494           
3495     N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);
3496     break;
3497
3498   /* SMS handling */
3499   case 0x02:
3500     switch (MessageBuffer[3]) {
3501       case 0x02:
3502       case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;
3503       case 0x0e:
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;
3509       case 0x34:
3510       case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
3511       default  :unknown=true;break;
3512     }
3513     break;
3514
3515   /* Phonebook and speed dials */
3516   case 0x03:
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;
3523     }
3524     break;
3525
3526   /* This is call forwarding stuff */
3527   case 0x06:
3528     switch (MessageBuffer[3]) {
3529       case 0x02:
3530       case 0x03:N6110_ReplyCallDivert    (MessageLength,MessageBuffer,MessageType);break;
3531       default  :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;
3532     }
3533     break;
3534
3535   /* Network and operator logo */
3536   case 0x0a:
3537
3538     N7110_Dispatch0x0AMessage(MessageLength, MessageBuffer, MessageType);
3539     break;
3540
3541   /* Calendar notes handling */
3542   case 0x13:
3543     switch (MessageBuffer[3]) {
3544       case 0x02:
3545       case 0x04:
3546       case 0x06:
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;
3553     }
3554     break;
3555
3556   /* SMS stuff */
3557   case 0x14:
3558     switch (MessageBuffer[3]) {
3559       case 0x05:
3560       case 0x06:N7110_ReplySaveSMSMessage    (MessageLength,MessageBuffer,MessageType);break;
3561       case 0x0b:N7110_ReplyDeleteSMSMessage  (MessageLength,MessageBuffer,MessageType);break;
3562       case 0x37:
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;
3568     }
3569     break;
3570  
3571   /* Battery status */
3572   case 0x17:
3573
3574     N7110_Dispatch0x17Message(MessageLength, MessageBuffer, MessageType);
3575     break;
3576
3577   /* Date and time */
3578   case 0x19:
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;
3585     }
3586     break;
3587
3588   /* Ringtones */
3589   case 0x1f:
3590     switch (MessageBuffer[3]) {
3591       case 0x23:
3592       case 0x24:N7110_ReplyGetBinRingtone(MessageLength,MessageBuffer,MessageType);break;
3593       default  :unknown=true;break;
3594     }
3595     break;
3596
3597   /* Profiles */
3598   case 0x39:
3599
3600     N7110_ReplyGetProfile(MessageLength, MessageBuffer, MessageType);
3601     break;
3602
3603   /* WAP */
3604   case 0x3f:
3605     switch (MessageBuffer[3]) {
3606       case 0x01:
3607       case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;
3608       case 0x07:
3609       case 0x08:N7110_ReplyGetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
3610       case 0x0a:
3611       case 0x0b:N7110_ReplySetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
3612       case 0x16:
3613       case 0x17:
3614       case 0x1c:N7110_ReplyGetWAPSettings   (MessageLength,MessageBuffer,MessageType);break;
3615       default  :unknown=true;break;
3616     }
3617     break;
3618
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
3622      errors */
3623   case 0x40:
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;
3635     }
3636     break;
3637
3638   /* Settings */
3639   case 0x7a:
3640
3641     N7110_Dispatch0x7AMessage(MessageLength, MessageBuffer, MessageType);
3642     break;
3643
3644   /***** Acknowlegment of our frames. *****/
3645   case FBUS_FRTYPE_ACK:
3646
3647     N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);
3648     break;
3649
3650   case 0xd2:
3651
3652     N6110_ReplyID(MessageLength, MessageBuffer, MessageType);
3653     break;
3654
3655   /***** Unknown message *****/
3656   /* If you think that you know the exact meaning of other messages - please
3657      let us know. */
3658   default:
3659
3660 #ifdef DEBUG
3661     fprintf(stdout, _("Message: Unknown message type.\n"));
3662 #endif /* DEBUG */
3663     AppendLogText("Unknown msg type\n",false);
3664     break;
3665
3666   }
3667
3668   if (unknown) {
3669 #ifdef DEBUG
3670     fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);
3671 #endif
3672     AppendLogText("Unknown msg\n",false);
3673   }
3674 }