Branch update for mygnokii2002_03_17_19_29nl
[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,
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   "",
134   5,                     /* Max RF Level */
135   0,                     /* Min RF Level */
136   GRF_Arbitrary,         /* RF level units */
137   5,                     /* Max Battery Level */
138   0,                     /* Min Battery Level */
139   GBU_Arbitrary,         /* Battery level units */
140   GDT_DateTime,          /* Have date/time support */
141   GDT_TimeOnly,          /* Alarm supports time only */
142   1                      /* Only one alarm available */
143 };
144
145 const char *N7110_MemoryType_String [] = {
146   "",   /* 0x00 */
147   "DC", /* 0x01 */
148   "MC", /* 0x02 */
149   "RC", /* 0x03 */
150   "FD", /* 0x04 */
151   "ME", /* 0x05 */
152   "SM", /* 0x06 */
153   "ON", /* 0x07 */
154   "EN", /* 0x08 */
155   "MT", /* 0x09 */
156 };
157
158 int PictureImageNum; //required during reading Picture Images
159 int PictureImageIndex;
160 int PictureImageLoc;
161
162 void N7110_ReplyEnableIncomingSMSInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
163   switch (MessageBuffer[3]) {
164   case 0x0e:
165 #ifdef DEBUG
166     fprintf(stdout,_("Message: Enabled info for incoming SMS\n"));
167 #endif /* DEBUG */
168
169     CurrentMagicError=GE_NONE;
170     break;
171   case 0x0f:
172 #ifdef DEBUG
173     fprintf(stdout,_("Message: error enabling for incoming SMS\n"));
174     switch (MessageBuffer[4]) {
175       case 0x0c:fprintf(stdout,_("   No PIN\n"));break;
176       default  :fprintf(stdout,_("   unknown\n"));break;
177     }
178 #endif /* DEBUG */
179
180     CurrentMagicError=GE_UNKNOWN;
181     break;
182   }
183 }
184
185 GSM_Error N7110_EnableIncomingSMSInfo ()
186 {
187   unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
188
189   return NULL_SendMessageSequence
190     (50, &CurrentMagicError, 8, 0x02, req);
191 }
192
193 /* Initialise variables and state machine. */
194 GSM_Error N7110_Initialise(char *port_device, char *initlength,
195                           GSM_ConnectionType connection,
196                           void (*rlp_callback)(RLP_F96Frame *frame))
197 {
198
199   unsigned char init_char = N6110_SYNC_BYTE;
200   int count;
201   int InitLength;
202     
203   if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
204   {
205     return GE_NOTSUPPORTED;
206   }
207   
208   if (connection!=GCT_MBUS && connection!=GCT_Irda) {
209
210     InitLength = atoi(initlength);
211
212     if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
213       InitLength = 250; /* This is the usual value, lower may work. */
214     }
215
216 #ifdef DEBUG
217     fprintf(stdout,_("Writing init chars...."));
218 #endif
219     
220     /* Initialise link with phone or what have you */
221     /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
222        empirical. */
223     for (count = 0; count < InitLength; count ++) {
224       usleep(100);
225       Protocol->WritePhone(1,&init_char);
226     }
227
228 #ifdef DEBUG
229     fprintf(stdout,_("Done\n"));  
230 #endif
231
232     N6110_SendStatusRequest();
233     
234   }
235
236   usleep(100);
237
238   if (N6110_SendIDFrame()!=GE_NONE)   return GE_TIMEOUT;
239
240   if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    
241
242   if (N6110_SendHWFrame()!=GE_NONE)   return GE_TIMEOUT;    
243
244 //  N7110_EnableIncomingSMSInfo();
245     
246   if (connection==GCT_MBUS || connection==GCT_Irda) {
247     /* In MBUS doesn't have any init strings, etc. Phone answered with frame,
248        so connection should be enabled ;-) */
249     /* Similiar for Irda */
250     CurrentLinkOK = true;                           
251   }
252   
253   CurrentSMSFoldersCount=1000;
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 #ifdef DEBUG
731   fprintf(stdout, _("Message: Memory status received:\n"));
732 #endif
733
734   if (CurrentMemoryStatus && CurrentMemoryStatusError == GE_BUSY) {
735     /* first Loc. (MessageBuffer[10]<<8) + MessageBuffer[11]; */
736     CurrentMemoryStatus->Free = (MessageBuffer[14]<<8) + MessageBuffer[15];
737     CurrentMemoryStatus->Used = (MessageBuffer[16]<<8) + MessageBuffer[17];
738     CurrentMemoryStatus->Free -= CurrentMemoryStatus->Used;
739
740     CurrentMemoryStatusError = GE_NONE;
741
742 #ifdef DEBUG
743     fprintf(stdout, _("   Memory Type: %s\n"), N7110_MemoryType_String[MessageBuffer[5]]);
744     fprintf(stdout, _("   Used: %d\n"), CurrentMemoryStatus->Used);
745     fprintf(stdout, _("   Free: %d\n"), CurrentMemoryStatus->Free);
746 #endif /* DEBUG */
747   }
748 }
749
750 /* This function is used to get storage status from the phone. It currently
751    supports two different memory areas - internal and SIM. */
752 GSM_Error N7110_GetMemoryStatus(GSM_MemoryStatus *Status)
753 {
754   unsigned char req[] = { N6110_FRAME_HEADER,
755                           0x03, /* MemoryStatus request */
756                           0x02,
757                           0x05  /* MemoryType */
758                         };
759
760   switch (Status->MemoryType) {
761
762      case GMT_ME:
763      case GMT_SM:
764        CurrentMemoryStatus = Status;
765
766        req[5] = N7110_GetMemoryType(Status->MemoryType);
767
768        return NULL_SendMessageSequence
769          (20, &CurrentMemoryStatusError, 6, 0x03, req);
770        break;
771
772      case GMT_DC:
773      case GMT_RC:
774      case GMT_MC:
775        Status->Free = 0;
776        Status->Used = 20;
777        return GE_NONE;
778
779      default:
780        return GE_NOTSUPPORTED;
781    }
782 }
783
784 void N7110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
785 {
786   switch(MessageBuffer[3]) {
787
788   case 0x02:
789
790 #ifdef DEBUG
791      fprintf(stdout,_("Profile feature %02x received\n"),MessageBuffer[6]);
792 #endif /* DEBUG */
793
794      switch (MessageBuffer[6]) {
795        case 0xff: /* Profile Name */
796          DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]);      
797 #ifdef DEBUG
798          fprintf(stdout,_("   Name \"%s\"\n"),CurrentProfile->Name);
799 #endif /* DEBUG */
800
801          break;
802
803        case 0x00: /* Keypad tone (Off, Level 1 ... Level 3) */
804          switch( MessageBuffer[10] ) {
805            case 0:
806              CurrentProfile->KeypadTone = PROFILE_KEYPAD_OFF; break;
807            case 1:
808            case 2:
809            case 3:
810              CurrentProfile->KeypadTone = MessageBuffer[10]-1; break;
811          }
812          break;
813
814        case 0x02: /* Call Alert type (Ringing, Ascending, ..., Off) */
815          /* I make it compatible with GetProfileCallAlertString */
816          switch( MessageBuffer[10] ) {
817            case 0: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGING; break;
818            case 1: CurrentProfile->CallAlert = PROFILE_CALLALERT_ASCENDING; break;
819            case 2: CurrentProfile->CallAlert = PROFILE_CALLALERT_RINGONCE; break;
820            case 3: CurrentProfile->CallAlert = PROFILE_CALLALERT_BEEPONCE; break;
821            case 5: CurrentProfile->CallAlert = PROFILE_CALLALERT_OFF; break;
822          }
823          break;
824        case 0x03: /* Ringtone number */
825          CurrentProfile->Ringtone = MessageBuffer[10];
826          break;
827        case 0x04: /* Ringtone volume (from level 1 to level 5) */
828          CurrentProfile->Volume = MessageBuffer[10] + 6;
829          break;
830        case 0x05: /* MessageTone Type (Off,Standard,...,Ascending) */
831          CurrentProfile->MessageTone = MessageBuffer[10];
832          break;
833        case 0x06: /* Vibration (On/Off) */
834          CurrentProfile->Vibration = MessageBuffer[10];
835          break;
836        case 0x07: /* WarningTone (On/Off) */
837          switch( MessageBuffer[10] ) {
838            case 0:
839              CurrentProfile->WarningTone = PROFILE_WARNING_OFF; break;
840            case 1:
841              CurrentProfile->WarningTone = PROFILE_WARNING_ON; break;
842          }
843          break;
844        case 0x08: /* Alert for (caller groups) */
845          CurrentProfile->CallerGroups = MessageBuffer[10];
846          break;
847        case 0x09: /* Auto Answer for Handsfree and Headset (On/Off) */
848          CurrentProfile->AutomaticAnswer = MessageBuffer[10];
849          break;
850      }
851
852      CurrentProfileError=GE_NONE;
853      break;
854    default:
855
856 #ifdef DEBUG
857     fprintf(stdout, _("Message: Unknown message of type 0x39\n"));
858 #endif /* DEBUG */
859     AppendLogText("Unknown msg\n",false);
860     break;      /* Visual C Don't like empty cases */
861
862   }
863 }
864
865 GSM_Error N7110_GetProfile(GSM_Profile *Profile)
866 {
867   int i;
868   
869   unsigned char req[] = { N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
870                           0x00,  //profile number
871                           0xff}; //feature. Here 0xff=name
872
873   unsigned char req2[11] = {0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x22,
874                                                                                                                 0x00,0x02,0x09 };
875
876   GSM_Error error;
877   
878   CurrentProfile = Profile;
879
880   /* When after sending all frames feature==253, it means, that it is not
881      supported */
882   CurrentProfile->KeypadTone=253;
883   CurrentProfile->Lights=253;    
884   CurrentProfile->CallAlert=253; 
885   CurrentProfile->Ringtone=253;  
886   CurrentProfile->Volume=253;    
887   CurrentProfile->MessageTone=253;
888   CurrentProfile->WarningTone=253;
889   CurrentProfile->Vibration=253;  
890   CurrentProfile->CallerGroups=253;
891   CurrentProfile->ScreenSaver=253; 
892   CurrentProfile->AutomaticAnswer=253;
893
894   req[7] = Profile->Number+1;
895
896   error=NULL_SendMessageSequence
897     (20, &CurrentProfileError, 9, 0x39, req);
898   if (error!=GE_NONE) return error;
899
900   for (i = 0; i < 11; i++) {
901
902     req[7] = Profile->Number+1;
903     
904     req[8] = req2[i];
905
906     error=NULL_SendMessageSequence
907       (20, &CurrentProfileError, 9, 0x39, req);
908     if (error!=GE_NONE) return error;
909   }
910   
911   return (GE_NONE);
912 }
913
914 void N7110_ReplyGetCalendarNotesInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
915 {
916   int i;
917
918   CurrentCalendarNotesInfo.HowMany = MessageBuffer[4]*256+MessageBuffer[5];
919   CurrentCalendarNotesInfo2->HowMany = CurrentCalendarNotesInfo.HowMany;
920
921   for(i=0;i<CurrentCalendarNotesInfo.HowMany && i<MAX_NOTES_INFO_ELEMS;i++) {
922     CurrentCalendarNotesInfo.Location[i] = MessageBuffer[8+i*2]*256+ MessageBuffer[8+i*2+1];
923     CurrentCalendarNotesInfo2->Location[i]=CurrentCalendarNotesInfo.Location[i];
924   }
925
926   CurrentCalendarNotesInfoError=GE_NONE;
927 }
928
929 GSM_Error N7110_GetCalendarNotesInfo(GSM_NotesInfo *NotesInfo)
930 {
931   unsigned char req[] = { N6110_FRAME_HEADER,
932         0x3a, /* get notes info */
933         0xFF, 0xFE //fixed
934   };
935   GSM_Error error;
936
937   CurrentCalendarNotesInfo2=NotesInfo;
938   
939   error=NULL_SendMessageSequence(50, &CurrentCalendarNotesInfoError, 6, 0x13, req);
940
941   return error;
942 }
943
944 void P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm, int alarm2)
945 {
946   time_t     t_alarm;
947   struct tm  tm_time;
948   struct tm  *tm_alarm;
949
950 #ifdef DEBUG                    
951   if (alarmdiff == 0xffff) fprintf(stdout,"   No alarm");
952                       else fprintf(stdout,"   Alarm is %i seconds before date", alarmdiff*alarm2);
953   fprintf(stdout,"\n");
954 #endif
955
956   if (alarmdiff != 0xffff) {    
957
958     memset(&tm_time, 0, sizeof(tm_time));
959     tm_time.tm_year = time->Year - 1900;
960     tm_time.tm_mon = time->Month - 1;
961     tm_time.tm_mday = time->Day;
962     tm_time.tm_hour = time->Hour;
963     tm_time.tm_min = time->Minute;
964     tm_time.tm_sec = time->Second;
965
966     tzset();
967     t_alarm = mktime(&tm_time);
968     t_alarm -= alarmdiff*alarm2;
969
970     tm_alarm = localtime(&t_alarm);
971
972     alarm->Year = tm_alarm->tm_year + 1900;
973     alarm->Month = tm_alarm->tm_mon + 1;
974     alarm->Day = tm_alarm->tm_mday;
975     alarm->Hour = tm_alarm->tm_hour;
976     alarm->Minute = tm_alarm->tm_min;
977     alarm->Second = tm_alarm->tm_sec;
978
979 #ifdef DEBUG
980     fprintf(stdout, "   Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
981                  alarm->Day,alarm->Month,alarm->Year,
982                  alarm->Hour,alarm->Minute,alarm->Second);
983 #endif
984   }
985 }
986
987 void P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
988 {
989   time_t     alarmdiff;
990         
991   c->Time.Year = block[8]*256+block[9];
992   c->Time.Month = block[10];
993   c->Time.Day = block[11];
994   if (c->Type != GCN_REMINDER) {
995     c->Time.Hour = block[12];
996     c->Time.Minute = block[13];
997   } else {
998     c->Time.Hour = 0;
999     c->Time.Minute = 0;
1000   }
1001   c->Time.Second = 0;
1002
1003 #ifdef DEBUG
1004   fprintf(stdout, "   Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1005               c->Time.Day,c->Time.Month,c->Time.Year,
1006               c->Time.Hour,c->Time.Minute,c->Time.Second);
1007 #endif
1008
1009   if (c->Type != GCN_REMINDER) {
1010     alarmdiff = block[14]*256 + block[15];
1011     P7110_GetNoteAlarm(alarmdiff, &(c->Time), &(c->Alarm), 60);
1012
1013     c->Recurrance = block[16]*256 + block[17];
1014     DecodeUnicode(c->Text, block+20, block[18]);
1015   } else {
1016     c->Recurrance = block[12]*256 + block[13];
1017     DecodeUnicode(c->Text, block+16, block[14]);
1018   }
1019
1020   /* 0xffff -> 1 Year (8760 hours) */
1021   if (c->Recurrance == 0xffff) c->Recurrance=8760;
1022
1023 #ifdef DEBUG
1024   fprintf(stdout, "   Recurrance: %i hours\n   Text: \"%s\"\n",
1025             c->Recurrance,c->Text);
1026 #endif
1027 }
1028
1029 void N7110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1030 {
1031   int alarm;
1032
1033   CurrentCalendarNote->YearOfBirth=0; //for other than birthday
1034   CurrentCalendarNote->AlarmType=0x00;//for other than birthday
1035   CurrentCalendarNote->Phone[0]=0;    //for other than call
1036
1037   CurrentCalendarNote->Alarm.Year = 0;
1038   CurrentCalendarNote->Alarm.Month = 0;
1039   CurrentCalendarNote->Alarm.Day = 0;
1040   CurrentCalendarNote->Alarm.Hour = 0;
1041   CurrentCalendarNote->Alarm.Minute = 0;
1042   CurrentCalendarNote->Alarm.Second = 0;
1043
1044 #ifdef DEBUG
1045   fprintf(stdout, "Message: calendar note received\n");
1046 #endif
1047
1048   switch (MessageBuffer[6]) /* entry type */ {
1049     case 0x01: /* Meeting */
1050 #ifdef DEBUG
1051       fprintf(stdout, "   Note type: meeting\n");
1052 #endif
1053       CurrentCalendarNote->Type = GCN_MEETING;
1054       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1055       CurrentCalendarNoteError=GE_NONE;
1056       break;
1057
1058     case 0x02: /* Call */
1059 #ifdef DEBUG
1060       fprintf(stdout, "   Note type: call\n");
1061 #endif
1062       CurrentCalendarNote->Type = GCN_CALL;
1063       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1064       DecodeUnicode(CurrentCalendarNote->Phone,
1065             MessageBuffer + 20 + MessageBuffer[18] * 2, MessageBuffer[19]);
1066 #ifdef DEBUG
1067       fprintf(stdout, "   Phone number: \"%s\"\n",CurrentCalendarNote->Phone);
1068 #endif
1069       CurrentCalendarNoteError=GE_NONE;
1070       break;
1071
1072     case 0x04: /* Birthday */
1073 #ifdef DEBUG
1074       fprintf(stdout, "   Note type: birthday\n");
1075 #endif
1076       CurrentCalendarNote->Type = GCN_BIRTHDAY;
1077
1078       alarm  = ((unsigned int)MessageBuffer[14]) << 24;
1079       alarm += ((unsigned int)MessageBuffer[15]) << 16;
1080       alarm += ((unsigned int)MessageBuffer[16]) << 8;
1081       alarm += MessageBuffer[17];
1082
1083       /* CurrentCalendarNote->Time.Year is set earlier */
1084       CurrentCalendarNote->Time.Month = MessageBuffer[10];
1085       CurrentCalendarNote->Time.Day = MessageBuffer[11];
1086       CurrentCalendarNote->Time.Hour = 23;
1087       CurrentCalendarNote->Time.Minute = 59;
1088       CurrentCalendarNote->Time.Second = 58;
1089       P7110_GetNoteAlarm(alarm, &(CurrentCalendarNote->Time), &(CurrentCalendarNote->Alarm) ,1);
1090
1091       CurrentCalendarNote->YearOfBirth = MessageBuffer[18]*256 + MessageBuffer[19];
1092       CurrentCalendarNote->Time.Year = CurrentCalendarNote->YearOfBirth;
1093
1094       CurrentCalendarNote->AlarmType = MessageBuffer[20];
1095
1096 #ifdef DEBUG
1097       fprintf(stdout,_("   Alarm type: %s\n"), 
1098         (CurrentCalendarNote->AlarmType==0x00) ? "Tone  " : "Silent");
1099
1100       fprintf(stdout, "   Birthday date: %02i-%02i-%04i (age %d)\n",CurrentCalendarNote->Time.Day,
1101               CurrentCalendarNote->Time.Month,CurrentCalendarNote->Time.Year,
1102               CurrentCalendarNote->Alarm.Year - CurrentCalendarNote->Time.Year);
1103 #endif
1104
1105       DecodeUnicode( CurrentCalendarNote->Text,MessageBuffer+22,MessageBuffer[21]);
1106 #ifdef DEBUG
1107       fprintf(stdout, "   Text: \"%s\"\n",CurrentCalendarNote->Text);
1108 #endif
1109
1110       CurrentCalendarNote->Recurrance = 0;
1111       CurrentCalendarNoteError=GE_NONE;
1112       break;
1113
1114     case 0x08: /* Reminder */
1115 #ifdef DEBUG
1116       fprintf(stdout, "   Note type: reminder\n");
1117 #endif
1118       CurrentCalendarNote->Type = GCN_REMINDER;
1119       P7110_GetNoteTimes(MessageBuffer, CurrentCalendarNote);
1120       CurrentCalendarNoteError=GE_NONE;
1121       break;
1122
1123     default: /* unknown */
1124 #ifdef DEBUG
1125       fprintf(stdout, "   Note type: UNKNOWN\n");
1126 #endif
1127       break;
1128   }
1129 }
1130   
1131 GSM_Error N7110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
1132 {
1133   unsigned char req[] = { N6110_FRAME_HEADER,
1134         0x19, /* get calendar note */
1135         0x00, 0x00 //location
1136   };
1137  
1138   GSM_Error error;
1139   GSM_DateTime date_time;
1140   struct tm *now;
1141   time_t nowh;
1142   
1143   if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1144     error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1145     if (error!=GE_NONE) return error;
1146   }
1147
1148 #ifdef DEBUG
1149   fprintf(stdout, _("Calendar Notes Location Logical = %d.\n"),
1150              CalendarNote->Location);
1151   fprintf(stdout, _("Calendar Notes Location Phisical = %d.\n"),
1152              CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]);
1153 #endif
1154
1155   /* this is for making xgnokii work.. */
1156   if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1157     return GE_INVALIDCALNOTELOCATION;
1158   
1159   req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1160   req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1161   CurrentCalendarNote = CalendarNote;
1162
1163   /* We have to get current year. It's NOT written in frame for Birthday */
1164   error=N7110_GetDateTime(&date_time);
1165   if (error!=GE_NONE) return error;
1166   if (!date_time.IsSet) {
1167     nowh=time(NULL);
1168     now=localtime(&nowh);
1169
1170     /* I have 100 (for 2000) Year now :-) */
1171     if (now->tm_year>99 && now->tm_year<1900) {
1172       now->tm_year=now->tm_year+1900;
1173     }
1174     date_time.Year=now->tm_year;
1175   }
1176   CurrentCalendarNote->Time.Year = date_time.Year;
1177   
1178   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1179   
1180   CurrentCalendarNote = NULL;
1181   
1182   return error;
1183 }
1184
1185 void N7110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1186 {
1187 #ifdef DEBUG
1188   char kz_types[][6] = { "MEET", "CALL", "BIRTH", "REM" };
1189
1190   fprintf(stdout, 
1191       "Succesfully written Calendar Note Type %s on location %d\n",
1192         kz_types[(MessageBuffer[3]/2)-1], 
1193         MessageBuffer[4]*256+MessageBuffer[5] );
1194
1195   fprintf(stdout, "--> Exit Status is %d (maybe is the size of buffer written to phone)\n", 
1196         MessageBuffer[6]*256+MessageBuffer[7] );
1197 #endif
1198   CurrentCalendarNoteError=GE_NONE;
1199 }
1200
1201 long P7110_GetNoteAlarmDiff(GSM_DateTime *time, GSM_DateTime *alarm)
1202 {
1203   time_t     t_alarm;
1204   time_t     t_time;
1205   struct tm  tm_alarm;
1206   struct tm  tm_time;
1207
1208   tzset();
1209
1210   tm_alarm.tm_year=alarm->Year-1900;
1211   tm_alarm.tm_mon=alarm->Month-1;
1212   tm_alarm.tm_mday=alarm->Day;
1213   tm_alarm.tm_hour=alarm->Hour;
1214   tm_alarm.tm_min=alarm->Minute;
1215   tm_alarm.tm_sec=alarm->Second;
1216   tm_alarm.tm_isdst=0;
1217   t_alarm = mktime(&tm_alarm);
1218
1219   tm_time.tm_year=time->Year-1900;
1220   tm_time.tm_mon=time->Month-1;
1221   tm_time.tm_mday=time->Day;
1222   tm_time.tm_hour=time->Hour;
1223   tm_time.tm_min=time->Minute;
1224   tm_time.tm_sec=time->Second;
1225   tm_time.tm_isdst=0;
1226   t_time = mktime(&tm_time);
1227
1228 #ifdef DEBUG
1229   fprintf(stdout, "   Alarm: %02i-%02i-%04i %02i:%02i:%02i\n",
1230                  alarm->Day,alarm->Month,alarm->Year,
1231                  alarm->Hour,alarm->Minute,alarm->Second);
1232   fprintf(stdout, "   Date: %02i-%02i-%04i %02i:%02i:%02i\n",
1233                  time->Day,time->Month,time->Year,
1234                  time->Hour,time->Minute,time->Second);
1235   fprintf(stdout,_("Difference in alarm time is %f\n"),difftime( t_time, t_alarm )+3600);
1236 #endif
1237
1238   return difftime( t_time ,t_alarm )+3600;
1239 }
1240
1241 GSM_Error N7110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
1242 {
1243   unsigned char req[200] = { N6110_FRAME_HEADER,
1244                              0x01,       /* note type ... */
1245                              0x00, 0x00, /* location */
1246                              0x00,       /* entry type */
1247                              0x00,       //fixed
1248                              0x00, 0x00, 0x00, 0x00, /* Year(2bytes), Month, Day */
1249                              /* here starts block */
1250                              0x00, 0x00, 0x00, 0x00,0x00, 0x00 /* ... depends on note type ... */
1251                            };
1252
1253   int count=0;
1254   long seconds, minutes;
1255  
1256   GSM_Error error;
1257   int firstFreeLocation;
1258
1259   /*
1260    * 6210/7110 needs to seek the first free pos to inhabit with next note
1261    */
1262   error=N7110_FirstCalendarFreePos(&firstFreeLocation);
1263   if (error!=GE_NONE) return error;
1264
1265 #ifdef DEBUG
1266   fprintf(stdout, _("First free calendar location is = %d.\n"),
1267              firstFreeLocation);
1268 #endif
1269
1270   /* Location */
1271   req[4]=0x00;
1272   req[5]=0x00;
1273
1274   switch( CalendarNote->Type ) {
1275     case GCN_MEETING : req[6]=0x01; req[3]=0x01; break;
1276     case GCN_CALL    : req[6]=0x02; req[3]=0x03; break;
1277     case GCN_BIRTHDAY: req[6]=0x04; req[3]=0x05; break;
1278     case GCN_REMINDER: req[6]=0x08; req[3]=0x07; break;
1279   }
1280
1281   req[8]=CalendarNote->Time.Year>>8;
1282   req[9]=CalendarNote->Time.Year&0xff;
1283   req[10]=CalendarNote->Time.Month;
1284   req[11]=CalendarNote->Time.Day;
1285
1286   /* From here starts BLOCK */
1287   count=12;
1288   switch( CalendarNote->Type ) {
1289
1290     case GCN_MEETING:
1291       req[count++]=CalendarNote->Time.Hour;   // 12
1292       req[count++]=CalendarNote->Time.Minute; // 13
1293       /* Alarm .. */
1294       req[count++]=0xff; // 14
1295       req[count++]=0xff; // 15
1296       if( CalendarNote->Alarm.Year )
1297       {
1298         seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, 
1299                                         &CalendarNote->Alarm);
1300         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1301           minutes=seconds/60L;
1302           count-=2;
1303           req[count++]=minutes>>8;
1304           req[count++]=minutes&0xff;
1305         }
1306       }
1307       /* Recurrance */
1308       if( CalendarNote->Recurrance >= 8760 )
1309         CalendarNote->Recurrance = 0xffff; /* setting  1 Year repeat */
1310       req[count++]=CalendarNote->Recurrance>>8;   // 16
1311       req[count++]=CalendarNote->Recurrance&0xff; // 17
1312       /* len of text */
1313       req[count++]=strlen(CalendarNote->Text);    // 18
1314       /* fixed 0x00 */
1315       req[count++]=0x00; // 19
1316       /* Text */
1317 #ifdef DEBUG
1318       fprintf(stdout, "Count before encode = %d\n", count );
1319       fprintf(stdout, "Meeting Text is = \"%s\"\n", CalendarNote->Text );
1320 #endif
1321
1322       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1323       count=count+2*strlen(CalendarNote->Text);
1324       break;
1325
1326     case GCN_CALL:
1327       req[count++]=CalendarNote->Time.Hour;   // 12
1328       req[count++]=CalendarNote->Time.Minute; // 13
1329       /* Alarm .. */
1330       req[count++]=0xff; // 14
1331       req[count++]=0xff; // 15
1332       if( CalendarNote->Alarm.Year )
1333       {
1334         seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, 
1335                                         &CalendarNote->Alarm);
1336         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1337           minutes=seconds/60L;
1338           count-=2;
1339           req[count++]=minutes>>8;
1340           req[count++]=minutes&0xff;
1341         }
1342       }
1343       /* Recurrance */
1344       if( CalendarNote->Recurrance >= 8760 )
1345         CalendarNote->Recurrance = 0xffff; /* setting  1 Year repeat */
1346       req[count++]=CalendarNote->Recurrance>>8;   // 16
1347       req[count++]=CalendarNote->Recurrance&0xff; // 17
1348       /* len of text */
1349       req[count++]=strlen(CalendarNote->Text);    // 18
1350       /* fixed 0x00 */
1351       req[count++]=strlen(CalendarNote->Phone);   // 19
1352       /* Text */
1353       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 20->N
1354       count=count+2*strlen(CalendarNote->Text);
1355       EncodeUnicode (req+count,CalendarNote->Phone ,strlen(CalendarNote->Phone));// (N+1)->n
1356       count=count+2*strlen(CalendarNote->Phone);
1357       break;
1358
1359     case GCN_BIRTHDAY:
1360       req[count++]=0x00; // 12 Fixed
1361       req[count++]=0x00; // 13 Fixed
1362
1363       /* Alarm .. */
1364       req[count++]=0x00; req[count++]=0x00; // 14, 15
1365       req[count++]=0xff; // 16
1366       req[count++]=0xff; // 17
1367       if( CalendarNote->Alarm.Year ) {
1368         // I try with Time.Year = Alarm.Year. If negative, I increase 1 year,
1369         // but only once ! This thing, because I may have Alarm period across
1370         // a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27)
1371
1372         CalendarNote->Time.Year = CalendarNote->Alarm.Year;
1373         if( (seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time, 
1374                                         &CalendarNote->Alarm)) < 0L ) {
1375           CalendarNote->Time.Year++;
1376           seconds= P7110_GetNoteAlarmDiff(&CalendarNote->Time,
1377               &CalendarNote->Alarm);
1378         }
1379         if( seconds>=0L ) { /* Otherwise it's an error condition.... */
1380           count-=4;
1381           req[count++]=seconds>>24;              // 14
1382           req[count++]=(seconds>>16) & 0xff;     // 15
1383           req[count++]=(seconds>>8) & 0xff;      // 16
1384           req[count++]=seconds&0xff;             // 17
1385         }
1386       }
1387
1388       req[count++]=CalendarNote->AlarmType; // 18
1389
1390       /* len of text */
1391       req[count++]=strlen(CalendarNote->Text); // 19
1392
1393       /* Text */
1394 #ifdef DEBUG
1395       fprintf(stdout, "Count before encode = %d\n", count );
1396       fprintf(stdout, "Meeting Text is = \"%s\" Altype is 0x%02x \n", CalendarNote->Text , CalendarNote->AlarmType );
1397 #endif
1398       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 22->N
1399       count=count+2*strlen(CalendarNote->Text);
1400       break;
1401
1402     case GCN_REMINDER:
1403       /* Recurrance */
1404       if( CalendarNote->Recurrance >= 8760 )
1405         CalendarNote->Recurrance = 0xffff; /* setting  1 Year repeat */
1406       req[count++]=CalendarNote->Recurrance>>8;   // 12
1407       req[count++]=CalendarNote->Recurrance&0xff; // 13
1408       /* len of text */
1409       req[count++]=strlen(CalendarNote->Text);    // 14
1410       /* fixed 0x00 */
1411       req[count++]=0x00; // 15
1412       /* Text */
1413       EncodeUnicode (req+count,CalendarNote->Text ,strlen(CalendarNote->Text));// 16->N
1414       count=count+2*strlen(CalendarNote->Text);
1415       break;
1416   }
1417
1418   /* padding */
1419   req[count]=0x00;
1420 #ifdef DEBUG
1421   fprintf(stdout, "Count after padding = %d\n", count );
1422 #endif
1423   
1424   CurrentCalendarNote = CalendarNote;
1425   
1426   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, count, 0x13, req);
1427   
1428   CurrentCalendarNote = NULL;
1429
1430   return error;
1431 }
1432
1433 void N7110_ReplyFirstCalendarFreePos(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1434 {
1435   *CurrentFirstCalendarFreePos = MessageBuffer[4]*256+MessageBuffer[5];
1436   CurrentFirstCalendarFreePosError=GE_NONE;
1437 }
1438
1439 GSM_Error N7110_FirstCalendarFreePos(int *FreePos)
1440 {
1441   unsigned char req[] = { N6110_FRAME_HEADER, 0x31 };
1442  
1443   GSM_Error error;
1444
1445   CurrentFirstCalendarFreePos = FreePos;
1446   
1447   error=NULL_SendMessageSequence(50, &CurrentFirstCalendarFreePosError, 
1448       4, 0x13, req);
1449   
1450   CurrentFirstCalendarFreePos = NULL;
1451   
1452   return error;
1453 }
1454
1455 void N7110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1456 {
1457 #ifdef DEBUG
1458   fprintf(stdout, 
1459        "Succesfully Delete Calendar Note on location %d\n",
1460        MessageBuffer[4]*256+MessageBuffer[5] );
1461
1462   fprintf(stdout, "--> Other data are :\n" );
1463   fprintf(stdout, " '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d), '%c'[0x%02x](%3d)\n",
1464       MessageBuffer[6], MessageBuffer[6], MessageBuffer[6],
1465       MessageBuffer[7], MessageBuffer[7], MessageBuffer[7],
1466       MessageBuffer[8], MessageBuffer[8], MessageBuffer[8],
1467       MessageBuffer[9], MessageBuffer[9], MessageBuffer[9] );
1468 #endif
1469   CurrentCalendarNoteError=GE_NONE;
1470 }
1471
1472 GSM_Error N7110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
1473 {
1474   unsigned char req[] = { N6110_FRAME_HEADER,
1475                           0x0b,      /* delete calendar note */
1476                           0x00, 0x00 //location
1477   };
1478  
1479   GSM_Error error;
1480   
1481   if (CalendarNote->ReadNotesInfo || CurrentCalendarNotesInfo.HowMany==2000) {
1482     error=N7110_GetCalendarNotesInfo(&CurrentCalendarNotesInfo);
1483     if (error!=GE_NONE) return error;
1484   }
1485
1486   /* this is for making xgnokii work.. */
1487   if (CalendarNote->Location > CurrentCalendarNotesInfo.HowMany )
1488     return GE_INVALIDCALNOTELOCATION;
1489   
1490   req[4] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]>>8;
1491   req[5] = CurrentCalendarNotesInfo.Location[CalendarNote->Location-1]&0xff;
1492
1493   CurrentCalendarNote = CalendarNote;
1494   
1495   error=NULL_SendMessageSequence(50, &CurrentCalendarNoteError, 6, 0x13, req);
1496   
1497   CurrentCalendarNote = NULL;
1498   
1499   return error;
1500 }
1501
1502 void N7110_ReplyGetSMSFolders(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1503 {
1504   wchar_t wc;
1505
1506   int i, j, tmp;
1507
1508 #ifdef DEBUG
1509   fprintf(stdout, _("Message: SMS Folders received:\n"));
1510 #endif /* DEBUG */
1511  
1512   i=5;
1513       
1514   CurrentSMSFoldersCount=MessageBuffer[4];
1515       
1516   for (j=0;j<MessageBuffer[4];j++) {
1517     strcpy(CurrentSMSFolders->Folder[j].Name,"               ");
1518 #ifdef DEBUG
1519     fprintf(stdout, _("   Folder Index: %d"),MessageBuffer[i]);
1520 #endif /* DEBUG */
1521     CurrentSMSFolders->FoldersID[j]=MessageBuffer[i];
1522
1523     i=i+2;
1524
1525 #ifdef DEBUG
1526     fprintf(stdout, _(", folder name: "));
1527 #endif /* DEBUG */
1528     tmp=0;
1529     while ((MessageBuffer[i]!=0x00) & (MessageBuffer[i+1]==0x00)) {
1530
1531       wc = MessageBuffer[i] | (MessageBuffer[i+1] << 8);
1532         
1533       CurrentSMSFolders->Folder[j].Name[tmp]=DecodeWithUnicodeAlphabet(wc);
1534 #ifdef DEBUG
1535       fprintf(stdout, _("%c"),CurrentSMSFolders->Folder[j].Name[tmp]);
1536 #endif /* DEBUG */
1537       tmp++;
1538       i=i+2;
1539     }
1540 #ifdef DEBUG
1541     fprintf(stdout, _("\n"));
1542 #endif /* DEBUG */
1543     tmp=0;
1544     i=i+1;
1545   }
1546       
1547   CurrentSMSFoldersError=GE_NONE;      
1548 }
1549
1550 GSM_Error N7110_GetSMSFolders ( GSM_SMSFolders *folders)
1551 {
1552   unsigned char req[] = { N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
1553   
1554   GSM_Error error;
1555   
1556   CurrentSMSFolders=folders;
1557   
1558   error=NULL_SendMessageSequence(20, &CurrentSMSFoldersError, 6, 0x14, req);
1559
1560   folders->number=CurrentSMSFoldersCount;
1561     
1562   return error;
1563 }
1564
1565 void N7110_ReplyGetSMSFolderStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1566 {
1567   int i;
1568
1569 #ifdef DEBUG
1570   fprintf(stdout, _("Message: SMS Folder status received\n"));
1571   fprintf(stdout, _("   Number of Entries: %i"),MessageBuffer[4]*256+MessageBuffer[5]);
1572 #endif /* DEBUG */
1573   CurrentSMSFolder.number=MessageBuffer[4]*256+MessageBuffer[5];
1574 #ifdef DEBUG
1575   fprintf(stdout, _(" (indexes "));
1576 #endif /* DEBUG */
1577
1578   for (i=0;i<MessageBuffer[4]*256+MessageBuffer[5];i++) {
1579 #ifdef DEBUG
1580     fprintf(stdout, _("%i, "), MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7]);
1581 #endif /* DEBUG */
1582     CurrentSMSFolder.locations[i]=MessageBuffer[6+(i*2)]*256+MessageBuffer[(i*2)+7];
1583   }
1584
1585 #ifdef DEBUG
1586   fprintf(stdout, _(")\n"));
1587 #endif /* DEBUG */
1588       
1589   CurrentSMSFolderError=GE_NONE;      
1590 }
1591
1592 GSM_Error N7110_GetSMSFolderStatus ( GSM_OneSMSFolder *folder, u8 ID)
1593 {
1594         unsigned char req[] = { N7110_FRAME_HEADER, 
1595                           0x6b, 
1596                           0x08, //folderID 
1597                           0x0F, 
1598                           0x01};
1599   
1600         GSM_Error error;
1601   
1602         CurrentSMSFolder = *folder;
1603         CurrentSMSFolderID = ID;
1604         req[4] = ID;
1605   
1606         error=NULL_SendMessageSequence(20, &CurrentSMSFolderError, 7, 0x14, req);
1607
1608         *folder=CurrentSMSFolder;
1609
1610         return error;
1611 }
1612
1613 void N7110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1614 {
1615
1616 #ifdef DEBUG
1617   fprintf(stdout, _("Message: SMS deleted succesfully\n"));
1618 #endif /* DEBUG */
1619   CurrentSMSMessageError = GE_NONE;
1620 }
1621
1622 GSM_Error N7110_DeleteSMSMessage(GSM_SMSMessage *message)
1623 {
1624   unsigned char req[] = {
1625     N7110_FRAME_HEADER, 0x0a, /* delete SMS request */
1626     0x00, /* folder (req[4])*/
1627     0x00, /* location */
1628     0x00, /* location (req[6])*/
1629     0x01 };
1630
1631     GSM_Error error;
1632     int smsnum, location;
1633     u8 folderid;
1634
1635     smsnum = message->Location;
1636     /* We made "fake" SMS numbering for SMS in 7110/6210/etc. */
1637     if ((error = N7110_HandleSMSLocation(smsnum, &folderid, &location, NULL, GSH_DELETE))!=GE_NONE)
1638             return(error);
1639  
1640     req[4]=folderid;
1641     req[5]=location / 256;
1642     req[6]=location;
1643
1644 #ifdef DEBUG
1645     printf("delete sms: folder %d, location %d\n",folderid,location);
1646 #endif
1647
1648     return NULL_SendMessageSequence
1649       (50, &CurrentSMSMessageError, 8, 0x14, req);
1650 }
1651
1652 GSM_Error N7110_GetSMSMessage(GSM_SMSMessage *message)
1653 {
1654
1655         unsigned char req[] = { N6110_FRAME_HEADER,
1656                           0x07, 
1657                           0x08, // folder ID
1658                           0x00, 0x05, // location
1659                           0x01, 
1660                           0x65, 
1661                           0x01};
1662
1663         int smsnum, location;
1664         u8 folderid;
1665
1666         GSM_Error error;
1667         CurrentSMSMessage = message;
1668         CurrentSMSMessageError = GE_BUSY;
1669
1670
1671         smsnum = message->Location;
1672
1673         /* we make central handling of real location */
1674         error = N7110_HandleSMSLocation(smsnum, &folderid, &location, message, GSH_GET);
1675         /* if smsnum is 0 (next sms) we need real smsnum */
1676         N7110_SMS2FakeLocation( &smsnum, folderid, location);
1677         message->Location = smsnum;
1678         switch(error)
1679         {
1680          case GE_SMSISINMEM: /* future use: get already reed sms from mem */
1681                                 return GE_NONE;
1682                                 break;
1683          case GE_NONE:          req[4]=folderid;
1684                                 req[5]=location / 256;
1685                                 req[6]=location;
1686 #ifdef DEBUG
1687     fprintf(stdout, _("GetSMSMessage: read folder %d, location %d\n"),folderid,location);
1688 #endif
1689                                 return NULL_SendMessageSequence(100, &CurrentSMSMessageError, 10, 0x14, req);
1690                                 break;
1691          default:               break;
1692          }
1693
1694     return(error);
1695 }
1696
1697 void N7110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
1698 {
1699   int smsnum;
1700
1701   switch (MessageBuffer[3]) {
1702
1703   /* save sms */
1704   case 0x05:      
1705 #ifdef DEBUG
1706     fprintf(stdout, _("Message: SMS Message stored at folder %d, location %d\n"), MessageBuffer[4], MessageBuffer[6]);
1707 #endif
1708
1709     if (CurrentSMSMessage!=NULL) {     
1710       N7110_SMS2FakeLocation(&smsnum, (u8) MessageBuffer[4], (int) MessageBuffer[6]);
1711       CurrentSMSMessage->MessageNumber=smsnum;
1712     }
1713     
1714     CurrentSMSMessageError = GE_NONE;
1715     break;
1716
1717   /* save sms failed */
1718   case 0x06:
1719       
1720 #ifdef DEBUG
1721     fprintf(stdout, _("Message: SMS Message save failed\n"));
1722 #endif
1723     CurrentSMSMessageError = GE_SMSSAVEFAILED;
1724     break;
1725
1726   case 0x84:
1727 #ifdef DEBUG
1728     fprintf(stdout, _("Message: Changed name for SMS Message\n"));
1729 #endif
1730     CurrentSMSMessageError = GE_NONE;
1731     break;
1732
1733   }
1734 }
1735
1736 GSM_Error N7110_SaveSMSMessage(GSM_SMSMessage *SMS)
1737 {
1738   unsigned char req[256] = {
1739     N6110_FRAME_HEADER, 0x04, /* SMS save request*/
1740     0x03, /* default: mark sms as  GSS_NOTSENTREAD */
1741     0x10, /* folder (req[5])*/
1742     0x00, /* location */
1743     0x00, /* location (req[7])*/
1744     0x00  /* ??? */
1745   };
1746
1747   unsigned char req2[200] = {N6110_FRAME_HEADER, 0x83};
1748
1749   int length,smsnum,location;
1750   u8 folderid;
1751   GSM_Error error;
1752   SMS_MessageType PDU;
1753
1754   smsnum = SMS->Location;
1755   
1756 #ifdef DEBUG
1757   printf("save sms: smsnum is :%d\n",smsnum);
1758 #endif
1759
1760   if ( SMS->Status ==  GSS_SENTREAD) req[4] = 0x01;
1761
1762   folderid = SMS->folder;
1763
1764   PDU=SMS_Deliver;
1765   
1766   error=GSM_EncodeNokiaSMSFrame(SMS, req+9, &length, PDU);
1767   if (error != GE_NONE) return error;
1768  
1769   CurrentSMSMessage = SMS;
1770
1771   error=N7110_HandleSMSLocation(smsnum, &folderid, &location, SMS, GSH_SAVE);
1772   switch (error)
1773   {
1774
1775     case  GE_BUSYSMSLOCATION: /* delete old sms before save */
1776       error = N7110_DeleteSMSMessage(SMS);      
1777       if (error != GE_NONE) return error;
1778       break;
1779     case  GE_NONE:
1780       break;
1781     default:
1782       return error;
1783       break;
1784   }
1785     
1786 #ifdef DEBUG
1787   printf("save sms: want to save at folder:%d , location:%d\n",folderid,location);
1788 #endif
1789
1790   req[5]=folderid;
1791   req[6]=location / 256;
1792   req[7]=location;
1793  
1794   error=NULL_SendMessageSequence
1795     (70, &CurrentSMSMessageError, 40+length, 0x14, req);
1796
1797   if (error==GE_NONE && SMS->Name[0]!=0) {
1798     length=4;
1799     N7110_Fake2SMSLocation(SMS->MessageNumber, &folderid, &location);
1800     req2[length++]=folderid;
1801     req2[length++]=location / 256;
1802     req2[length++]=location;
1803     EncodeUnicode(req2+length, SMS->Name, strlen(SMS->Name));
1804     length=length+strlen(SMS->Name)*2;
1805     req2[length++]=0;
1806     req2[length++]=0;
1807     error=NULL_SendMessageSequence
1808       (70, &CurrentSMSMessageError, length, 0x14, req2);
1809   }
1810
1811   return error;
1812 }
1813
1814 /* handling for 7110 folders */
1815 GSM_Error N7110_HandleSMSLocation(int smsnum, u8 *folder, int *location, GSM_SMSMessage *message, GSM_SMSHandleAction action)
1816 {
1817     /* remember me */
1818     static int nextSMSmessage = -1;
1819     static GSM_SMSStatus Status;
1820
1821     bool found = false;
1822     int folderid;
1823     GSM_OneSMSFolder onefolder;
1824     GSM_Error error;
1825     int ismsnum;  
1826     int i;
1827
1828     switch (action) {
1829         case GSH_DELETE: /* future use: delete sms in mem -> free memory */
1830                          /* for now we make same as in GSH_GET           */
1831         case GSH_GET:    /* if smsnum == 0 user wants to read next sms   */
1832           if (smsnum == 0 )
1833           {
1834             /* first time we read folderstatus */
1835             if (  nextSMSmessage == -1)
1836             {
1837                nextSMSmessage = 0;
1838                error =  N7110_GetSMSStatus( &Status);
1839                if (error!=GE_NONE) return error;
1840             }
1841             ismsnum = Status.foldertable[nextSMSmessage].smsnum;
1842             N7110_Fake2SMSLocation( ismsnum, folder, location);
1843             nextSMSmessage++;
1844             if(nextSMSmessage >= Status.Number)
1845             { 
1846               nextSMSmessage = -1;
1847 #ifdef DEBUG
1848               printf("HandleSMS: setting nextSMSmessage to -1\n");
1849 #endif
1850             }
1851           } else /* user give location -> make fake location */
1852           {
1853             /* future use: get already read sms from mem */
1854             N7110_Fake2SMSLocation( smsnum, folder, location);
1855           }
1856           break;
1857         case GSH_SAVE: /* if smsnum == 0 user wants to save in specific folder */
1858           if (smsnum == 0 )
1859           {
1860             /* calculate correct folderid */
1861             *folder = ( *folder + 1) * 8;
1862
1863             *location = 0;
1864           } else /* user give location -> make fake location */
1865           {
1866             N7110_Fake2SMSLocation( smsnum, folder, location);
1867             folderid = *folder;
1868
1869             error=N7110_GetSMSFolderStatus(&onefolder, folderid );
1870             if (error!=GE_NONE) return error;
1871
1872             /* is there a sms at that location ? */
1873             for (i=0; i<CurrentSMSFolder.number; i++)
1874               if ( CurrentSMSFolder.locations[i] == *location ) found = true;
1875     
1876             if (found == true) return GE_BUSYSMSLOCATION;
1877                           else return GE_NONE;
1878           }
1879           break;  
1880         default:
1881           return GE_UNKNOWN;
1882     } //switch
1883     return GE_NONE;
1884 }
1885
1886 /* input: fake smsnum, output: folderid & location */
1887 void  N7110_Fake2SMSLocation(int smsnum, u8 *folderid, int *location)
1888 {
1889   int ifolderid;
1890
1891   ifolderid = smsnum / N7110_MAXSMSINFOLDER;
1892   *folderid = ifolderid * 0x08;
1893   *location = smsnum -  ifolderid * N7110_MAXSMSINFOLDER;
1894 }
1895
1896 /* input; folderid & location, output: fake smsnum */
1897 void N7110_SMS2FakeLocation(int *smsnum, u8 folderid, int location)
1898 {
1899   int ifolderid;
1900   
1901   ifolderid = folderid / 0x08;
1902   *smsnum = ifolderid * N7110_MAXSMSINFOLDER + location;
1903 }
1904
1905 GSM_Error N7110_GetRFLevel(GSM_RFUnits *units, float *level)
1906 {
1907   unsigned char request[] = {N6110_FRAME_HEADER, 0x81};
1908
1909   int timeout=10;
1910   int rf_level;
1911
1912   CurrentRFLevel=-1;
1913
1914   Protocol->SendMessage(4, 0x0a, request);
1915
1916   /* Wait for timeout or other error. */
1917   while (timeout != 0 && CurrentRFLevel == -1 ) {
1918
1919     if (--timeout == 0)
1920       return (GE_TIMEOUT);
1921
1922     usleep (100000);
1923   }
1924
1925   /* Make copy in case it changes. */
1926   rf_level = CurrentRFLevel;
1927
1928   if (rf_level == -1)
1929     return (GE_NOLINK);
1930
1931   /* Now convert between the different units we support. */
1932
1933   /* Arbitrary units. */
1934   *units = GRF_Percentage;
1935   *level = rf_level;
1936   return (GE_NONE);
1937 }
1938
1939 GSM_Error N7110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1940 {
1941   unsigned char request[] = {N6110_FRAME_HEADER, 0x02};
1942
1943   int timeout=10;
1944   int batt_level;
1945
1946   CurrentBatteryLevel=-1;
1947
1948   Protocol->SendMessage(4, 0x17, request);
1949
1950   /* Wait for timeout or other error. */
1951   while (timeout != 0 && CurrentBatteryLevel == -1 ) {
1952
1953     if (--timeout == 0)
1954       return (GE_TIMEOUT);
1955
1956     usleep (100000);
1957   }
1958
1959   /* Take copy in case it changes. */
1960   batt_level = CurrentBatteryLevel;
1961
1962   if (batt_level == -1)
1963     return (GE_NOLINK);
1964     
1965   /* Only units we handle at present are GBU_Arbitrary */
1966   *units = GBU_Percentage;
1967   *level = batt_level;
1968   return (GE_NONE);
1969 }
1970
1971 GSM_Error N7110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
1972 {
1973   unsigned char req[] = {0x00, 0x01, 0x01, 0xee, 0x1c};
1974
1975   if (SecurityCode->Type!=GSCT_SecurityCode) return GE_NOTSUPPORTED;
1976
1977   CurrentSecurityCode=SecurityCode;
1978
1979   return NULL_SendMessageSequence
1980     (50, &CurrentSecurityCodeError, 5, 0x7a, req);
1981 }
1982
1983 GSM_Error N7110_GetDateTime(GSM_DateTime *date_time)
1984 {
1985   return N6110_PrivGetDateTime(date_time,0x19);
1986 }
1987
1988 /* Needs SIM card with PIN in phone */
1989 GSM_Error N7110_SetDateTime(GSM_DateTime *date_time)
1990 {
1991   return N6110_PrivSetDateTime(date_time,0x19);
1992 }
1993
1994 GSM_Error N7110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1995 {
1996   return N6110_PrivGetAlarm(alarm_number,date_time,0x19);
1997 }
1998
1999 /* FIXME: we should also allow to set the alarm off :-) */
2000 GSM_Error N7110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
2001 {
2002   return N6110_PrivSetAlarm(alarm_number,date_time, 0x19);
2003 }
2004
2005 void N7110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2006 {
2007   switch (MessageBuffer[3]) {
2008
2009   /* sms status */
2010   case 0x37:
2011
2012 #ifdef DEBUG
2013     fprintf(stdout, _("Message: SMS Status Received\n"));
2014     fprintf(stdout, _("  Used msg in phone memory: %i\n"),MessageBuffer[10]*256+MessageBuffer[11]);
2015     fprintf(stdout, _("  Unread msg in phone memory: %i\n"),MessageBuffer[12]*256+MessageBuffer[13]);
2016     fprintf(stdout, _("  Used msg in SIM: %i\n"),MessageBuffer[14]*256+MessageBuffer[15]);
2017     fprintf(stdout, _("  Unread msg in SIM: %i\n"),MessageBuffer[16]*256+MessageBuffer[17]);
2018 #endif /* DEBUG */
2019     CurrentSMSStatus->UnRead = MessageBuffer[13];
2020     CurrentSMSStatusError = GE_NONE;
2021     break;
2022
2023   case 0x38:
2024
2025 #ifdef DEBUG
2026     fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
2027 #endif /* DEBUG */
2028     CurrentSMSStatusError = GE_INTERNALERROR;
2029     break;
2030
2031   }
2032 }
2033
2034 GSM_Error N7110_GetSMSStatus(GSM_SMSStatus *Status)
2035 {
2036   /* RTH FIXME: what is exact meaning of 0x0037 answer ? */
2037   /* we check all folders, but get sum of unread sms via 0x0036 request */
2038   unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
2039
2040   GSM_SMSFolders folders;
2041   GSM_OneSMSFolder folder;
2042   GSM_Error error;
2043   u8 ifolder;
2044   int ismsnum,ilocation;
2045   int i,j,smsmaxnum;
2046
2047   CurrentSMSStatus = Status;
2048
2049   /* read all SMS folders */
2050   /* check for unread messages in folder 0xf8 */
2051   error = N7110_GetSMSFolderStatus(&folder, 0xf8);
2052   if (error != GE_NONE) return error;
2053     
2054   smsmaxnum=0;
2055   for(j=0; j<folder.number; j++)
2056   {
2057     ifolder = 0; /*read unread messages from folder 0 */
2058     ilocation = folder.locations[j];
2059     N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation) ;
2060     CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum; 
2061     CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder; 
2062     CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation; 
2063     smsmaxnum++;
2064   } 
2065  
2066   /* read standard folders */
2067   N7110_GetSMSFolders (&folders);
2068   for(i=0; i<CurrentSMSFoldersCount; i++)
2069   {
2070     error = N7110_GetSMSFolderStatus(&CurrentSMSFolders->Folder[i], CurrentSMSFolders->FoldersID[i]);
2071     if (error != GE_NONE) return error;
2072      
2073     for(j=0; j<CurrentSMSFolders->Folder[i].number; j++)
2074     {
2075       ifolder = CurrentSMSFolders->FoldersID[i];
2076       ilocation = CurrentSMSFolders->Folder[i].locations[j];
2077       N7110_SMS2FakeLocation( &ismsnum, ifolder, ilocation);
2078       CurrentSMSStatus->foldertable[smsmaxnum].smsnum = ismsnum; 
2079       CurrentSMSStatus->foldertable[smsmaxnum].folder = ifolder; 
2080       CurrentSMSStatus->foldertable[smsmaxnum].location = ilocation; 
2081       smsmaxnum++;
2082     }
2083   }
2084   CurrentSMSStatus->Number = smsmaxnum;
2085
2086   return NULL_SendMessageSequence(10, &CurrentSMSStatusError, 5, 0x14, req);
2087 }
2088
2089 void N7110_DecodePhonebookFrame(GSM_PhonebookEntry *entry,u8 *MessageBuffer,u16 MessageLength)
2090 {
2091   int blockcount=0;
2092   unsigned char *pBlock;
2093   int length=0;
2094
2095 #ifdef DEBUG
2096   int j;
2097 #endif
2098
2099   pBlock = &MessageBuffer[0];
2100
2101   while (length!=MessageLength) {
2102     GSM_SubPhonebookEntry* pEntry = &entry->SubEntries[blockcount];
2103
2104 #ifdef DEBUG
2105     fprintf(stdout,_("    "));
2106     for (j=5;j<(pBlock[3]-6)+5;j++) fprintf(stdout,_("%02x "),pBlock[j]);
2107     fprintf(stdout,_("\n"));
2108 #endif
2109
2110     switch( pBlock[0] ) {
2111     case N7110_ENTRYTYPE_SPEEDDIAL:
2112     
2113       CurrentSpeedDialEntry->MemoryType = GMT_SM;
2114       if (pBlock[4]==0x02) CurrentSpeedDialEntry->MemoryType = GMT_ME;
2115       
2116       CurrentSpeedDialEntry->Location = pBlock[7]+pBlock[6]*256;
2117
2118 #ifdef DEBUG
2119       fprintf(stdout, _("    Speed dial\n"));
2120       fprintf(stdout, _("      Location: %d\n"), CurrentSpeedDialEntry->Location);
2121       fprintf(stdout, _("      MemoryType: %i\n"), CurrentSpeedDialEntry->MemoryType);
2122       fprintf(stdout, _("      Number: %d\n"), CurrentSpeedDialEntry->Number);
2123 #endif /* DEBUG */
2124
2125       CurrentSpeedDialError=GE_NONE;
2126       break;
2127
2128     case N7110_ENTRYTYPE_NAME:
2129       DecodeUnicode (entry->Name, pBlock+6, pBlock[5]/2);
2130       if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2131         strncpy(CurrentGetBitmap->text,entry->Name,sizeof(CurrentGetBitmap->text));
2132       entry->Empty = false;
2133 #ifdef DEBUG
2134       fprintf(stdout, _("    Name:\n"));
2135       fprintf(stdout, _("      Name: %s\n"), entry->Name);
2136 #endif /* DEBUG */
2137       break;
2138
2139     case N7110_ENTRYTYPE_NUMBER:
2140       pEntry->EntryType   = pBlock[0];
2141       pEntry->NumberType  = pBlock[5];
2142       pEntry->BlockNumber = pBlock[4];
2143
2144       DecodeUnicode (pEntry->data.Number, pBlock+10, pBlock[9]/2);
2145
2146 #ifdef DEBUG
2147       fprintf(stdout, _("    Number:\n"));
2148       fprintf(stdout, _("      Type: %d (%02x)\n"),pEntry->NumberType,pEntry->NumberType);
2149       fprintf(stdout, _("      Number: %s\n"),pEntry->data.Number);
2150 #endif /* DEBUG */
2151       if( pEntry->EntryType == GSM_Number &&
2152          ((pEntry->NumberType == GSM_General && !strcmp(entry->Number,""))
2153              || pEntry->NumberType == GSM_SIM)) {
2154         strcpy( entry->Number, pEntry->data.Number );
2155         *pEntry->data.Number = 0;
2156       } else
2157         blockcount++;
2158       break;
2159     case N7110_ENTRYTYPE_DATE:
2160       pEntry->EntryType        = pBlock[0];
2161       pEntry->NumberType       = pBlock[5];
2162       pEntry->BlockNumber      = pBlock[4];
2163       DecodeDateTime(pBlock+6, &pEntry->data.Date);
2164 #ifdef DEBUG
2165       fprintf(stdout, _("    Date:\n"));
2166       fprintf(stdout, _("      Date: %02u.%02u.%04u\n"), pEntry->data.Date.Day,
2167         pEntry->data.Date.Month, pEntry->data.Date.Year );
2168       fprintf(stdout, _("      Time: %02u:%02u:%02u\n"), pEntry->data.Date.Hour,
2169         pEntry->data.Date.Minute, pEntry->data.Date.Second);
2170 #endif /* DEBUG */
2171       blockcount++;
2172       break;
2173     case N7110_ENTRYTYPE_NOTE:
2174     case N7110_ENTRYTYPE_POSTAL:
2175     case N7110_ENTRYTYPE_EMAIL:
2176       pEntry->EntryType   = pBlock[0];
2177       pEntry->NumberType  = 0;
2178       pEntry->BlockNumber = pBlock[4];
2179
2180       DecodeUnicode (pEntry->data.Number, pBlock+6, pBlock[5]/2);
2181
2182 #ifdef DEBUG
2183       fprintf(stdout, _("    Email or note or postal:\n"));
2184       fprintf(stdout, _("      Type: %d (%02x)\n"),pEntry->EntryType,pEntry->EntryType);
2185       fprintf(stdout, _("      Text: %s\n"),pEntry->data.Number);
2186 #endif /* DEBUG */
2187       blockcount++;
2188       break;
2189     case N7110_ENTRYTYPE_GROUP:
2190       entry->Group = pBlock[5]-1;  /* 0 = family as for 6110 */
2191       if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2192         CurrentGetBitmap->number = entry->Group;
2193 #ifdef DEBUG
2194       fprintf(stdout, _("    Group: %d\n"), entry->Group);
2195 #endif /* DEBUG */
2196       break;
2197     case N7110_ENTRYTYPE_RINGTONE:
2198       if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2199         CurrentGetBitmap->ringtone = pBlock[5];
2200 #ifdef DEBUG
2201       fprintf(stdout, _("    Group ringtone number %d received.\n"), pBlock[5]);
2202 #endif /* DEBUG */
2203       break;
2204     case N7110_ENTRYTYPE_LOGOON:
2205       if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
2206         CurrentGetBitmap->enabled = pBlock[5];
2207 #ifdef DEBUG
2208       fprintf(stdout, _("    Logo enabled = %d received.\n"), pBlock[5]);
2209 #endif /* DEBUG */
2210       break;
2211     case N7110_ENTRYTYPE_GROUPLOGO:
2212 #ifdef DEBUG
2213       fprintf(stdout, _("    Caller group logo received.\n"));
2214 #endif /* DEBUG */
2215       if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
2216         CurrentGetBitmap->width = pBlock[5];
2217         CurrentGetBitmap->height= pBlock[6];
2218         CurrentGetBitmap->size  = pBlock[9];
2219         if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
2220           CurrentGetBitmap->size = CurrentGetBitmap->size;
2221         memcpy(CurrentGetBitmap->bitmap,pBlock+10,CurrentGetBitmap->size);
2222       }
2223       break;
2224
2225     default:
2226 #ifdef DEBUG
2227       fprintf(stdout, _("    Unknown Entry Code (%u) received.\n"), pBlock[0] );
2228 #endif /* DEBUG */
2229       break;
2230     }
2231        
2232 #ifdef DEBUG
2233     fprintf(stdout, _("    Blocksize was: %d (%02x)\n"), (int) pBlock[3], pBlock[3]);
2234 #endif
2235     length=length+pBlock[3];
2236
2237     pBlock = &pBlock[(int) pBlock[3]];
2238   }
2239
2240   entry->SubEntriesCount = blockcount;
2241
2242 #ifdef DEBUG
2243   fprintf(stdout, _("  SubBlocks: %d\n"),entry->SubEntriesCount);
2244 #endif /* DEBUG */
2245 }
2246
2247 void N7110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2248 {
2249
2250   CurrentPhonebookEntry->Empty = true;
2251   CurrentPhonebookEntry->Group = 5;     /* 5 = no group as 6110 */
2252   CurrentPhonebookEntry->Name[0] = '\0';
2253   CurrentPhonebookEntry->Number[0] = '\0';
2254   CurrentPhonebookEntry->SubEntriesCount = 0;
2255
2256 #ifdef DEBUG
2257   fprintf(stdout, _("Message: Phonebook entry received:\n"));
2258 #endif
2259
2260   if( MessageBuffer[6] == 0x0f ) // not found
2261   {
2262 #ifdef DEBUG
2263     fprintf(stdout, _("   Error %i\n"),MessageBuffer[10]);
2264     switch (MessageBuffer[10]) {
2265       case 0x34:fprintf(stdout,_("   Invalid phonebook location\n"));break;
2266       case 0x3b:fprintf(stdout,_("   Speed dial not assigned\n"));break;
2267       default  :fprintf(stdout,_("   Unknown.Please report\n"));break;
2268     }
2269 #endif
2270     switch (MessageBuffer[10]) {
2271       case 0x34:CurrentPhonebookError = GE_INVALIDPHBOOKLOCATION;break;
2272       case 0x3b:CurrentPhonebookError = GE_INVALIDSPEEDDIALLOCATION;break;
2273       default  :CurrentPhonebookError = GE_UNKNOWN;
2274     }
2275     CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
2276
2277   } else {
2278     CurrentPhonebookEntry->Location=MessageBuffer[13]+MessageBuffer[12]*256;
2279
2280 #ifdef DEBUG
2281     fprintf(stdout,_("  Location: %i\n"),CurrentPhonebookEntry->Location);
2282 #endif
2283
2284     N7110_DecodePhonebookFrame(CurrentPhonebookEntry,MessageBuffer+18,MessageLength-18);
2285
2286     CurrentPhonebookError = GE_NONE;
2287   }
2288 }
2289
2290 /* Routine to get specifed phone book location.  Designed to be called by
2291    application.  Will block until location is retrieved or a timeout/error
2292    occurs. */
2293 GSM_Error N7110_GetMemoryLocation(GSM_PhonebookEntry *entry) {
2294
2295   unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
2296                          0x02, //memory type
2297                          0x05,
2298                          0x00, 0x00, //location
2299                          0x00, 0x00};
2300
2301   CurrentPhonebookEntry = entry;
2302
2303   req[9] = N7110_GetMemoryType(entry->MemoryType);
2304   req[10] = (entry->Location>>8);
2305   req[11] = entry->Location & 0xff;
2306
2307   return NULL_SendMessageSequence
2308     (50, &CurrentPhonebookError, 14, 0x03, req);
2309 }
2310
2311 void N7110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2312 {
2313   // [12,13] = Location
2314   // [14] = Memory
2315
2316   if( MessageBuffer[6] == 0x0f ) // ERROR
2317   {
2318 #ifdef DEBUG
2319     /* I didn't find any error when the Text,Name or Number was too long
2320        My Phone 7110; NSE-5; SW 04.84 */
2321     switch( MessageBuffer[10] ) {
2322       case 0x3d: fprintf(stdout, _("Error: Wrong Entry Type.\n")); break;
2323       case 0x3e: fprintf(stdout, _("Error: Too much entries.\n")); break;
2324       default  : fprintf(stdout, _("Error: Unknown error (%u).\n"), MessageBuffer[10]); break;
2325     }
2326 #endif /* DEBUG */
2327     CurrentPhonebookError = GE_NONE;
2328   } else {
2329 #ifdef DEBUG
2330     fprintf(stdout, _("Message: Phonebook written correctly.\n"));
2331 #endif /* DEBUG */
2332
2333     CurrentPhonebookError = GE_NONE;
2334   }
2335 }
2336
2337 int N7110_PackPBKBlock(int id, int size, int no, unsigned char *buf, unsigned char *block)
2338 {
2339 #ifdef DEBUG
2340   fprintf(stdout,_("Adding block id:%i,number:%i,length:%i\n"),id,no+1,size+6);
2341 #endif
2342
2343   *(block++) = id;
2344   *(block++) = 0;
2345   *(block++) = 0;
2346   *(block++) = size + 6;
2347   *(block++) = no + 1;
2348
2349   memcpy(block, buf, size);
2350   block += size;
2351
2352   *(block++) = 0;
2353
2354   return (size + 6);
2355 }
2356
2357 int N7110_EncodePhonebookFrame(unsigned char *req, GSM_PhonebookEntry entry, int *block2)
2358 {
2359   int count=0, len, i, block=0;
2360
2361   char string[500];
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   *block2=block;
2406
2407   return count;
2408 }
2409  
2410 /* Routine to write phonebook location in phone. */
2411 GSM_Error N7110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
2412 {
2413   unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2414                                    0x00, 0x00,  /* memory type */
2415                                    0x00, 0x00,  /* location */
2416                                    0x00, 0x00, 0x00};
2417   int count = 18, blocks;
2418
2419   if (entry->Name[0] != '\0' || entry->Number[0] != '\0') {
2420     req[11] = N7110_GetMemoryType(entry->MemoryType); 
2421     req[12] = (entry->Location >> 8);
2422     req[13] = entry->Location & 0xff;
2423
2424 //    if (entry->MemoryType == GMT_SM) entry->SubEntriesCount = 0; 
2425
2426     count=count+N7110_EncodePhonebookFrame(req+18, *entry, &blocks);
2427
2428     req[17]=blocks;
2429
2430 #ifdef DEBUG
2431     fprintf(stdout, _("Writing phonebook entry %s...\n"),entry->Name);
2432 #endif
2433
2434     return NULL_SendMessageSequence(50, &CurrentPhonebookError, count, 0x03, req);
2435
2436   } else {
2437
2438     /* empty name & number => we have to delete the phonebook record! */
2439     return N7110_DeletePhonebookLocation( entry );
2440
2441   }  
2442 }
2443
2444 void N7110_ReplyDeletePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
2445 {
2446 #ifdef DEBUG
2447   fprintf(stdout, _("Message: Phonebook entry deleted correctly\n"));
2448 #endif /* DEBUG */
2449   CurrentPhonebookError = GE_NONE;
2450 }
2451
2452 /* delete phonebookentry */
2453 /* Not used in this moment */
2454 GSM_Error N7110_DeletePhonebookLocation(GSM_PhonebookEntry *entry)
2455 {
2456   unsigned char req[256] = {
2457     N7110_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04,
2458     0x00, 0x00, 0x0c, 0x01, 0xff,
2459     0x00, /* location low*/
2460     0x01, /* location high*/
2461     0x05, /* mem location low*/
2462     0x00, /* mem location high*/
2463     0x00, 0x00
2464   };
2465
2466   req[12] = (entry->Location >> 8);
2467   req[13] = entry->Location & 0xff;
2468   req[14] = N7110_GetMemoryType(entry->MemoryType);
2469  
2470 #ifdef DEBUG
2471   fprintf(stdout, _("Deleting phonebook entry at location %d...\n"),entry->Location);
2472 #endif
2473   
2474   return NULL_SendMessageSequence(50, &CurrentPhonebookError, 18, 0x03, req);
2475 }
2476
2477 /* for saving group logos only */
2478 GSM_Error N7110_WriteGroupDataLocation(GSM_Bitmap *bitmap)
2479 {
2480   unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
2481                             0x00, 0x10,  /* memory type */
2482                             0x00, 0x00,  /* location */
2483                             0x00, 0x00, 0x00};
2484   char string[500];
2485   int block=0, i;
2486   unsigned int count = 18;
2487
2488   req[13] = bitmap->number + 1;
2489
2490   /* Logo on/off */
2491   string[0] = bitmap->enabled?1:0;
2492   string[1] = 0;
2493   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_LOGOON, 2, block++, string, req + count);
2494
2495   /* Ringtone */
2496   string[0] = bitmap->ringtone;
2497   string[1] = 0;
2498   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_RINGTONE, 2, block++, string, req + count);
2499
2500   /* Number of group */
2501   string[0] = bitmap->number+1;
2502   string[1] = 0;
2503   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUP, 2, block++, string, req + count);
2504
2505   /* Name */
2506   if (*bitmap->text) {
2507     i = strlen(bitmap->text);
2508     string[0] = i * 2 + 2;
2509     EncodeUnicode((string + 1), bitmap->text, i);
2510     string[i * 2 + 1] = 0;   // Terminating 0
2511     count += N7110_PackPBKBlock(N7110_ENTRYTYPE_NAME, i * 2 + 2, block++, string, req + count);
2512   }
2513
2514   /* Logo */
2515   string[0] = bitmap->width;
2516   string[1] = bitmap->height;
2517   string[2] = 0;
2518   string[3] = 0;
2519   string[4] = bitmap->size;
2520   memcpy(string + 5, bitmap->bitmap, bitmap->size);
2521   count += N7110_PackPBKBlock(N7110_ENTRYTYPE_GROUPLOGO, bitmap->size + 5, block++, string, req + count);
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+6, Bitmap->netcode);
2661       reqOp[11] = 8+GSM_GetBitmapSize(Bitmap);
2662       reqOp[12]=Bitmap->width;
2663       reqOp[13]=Bitmap->height;
2664       reqOp[15]=GSM_GetBitmapSize(Bitmap);
2665       memcpy(reqOp+count,Bitmap->bitmap,Bitmap->size);
2666       count += Bitmap->size;
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 (PictureImageNum!=Bitmap->number+1) {
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
2703     /* Cleaning */
2704     for (i=0;i<36;i++) req4[i+9]=0;
2705
2706     count=8;
2707     if (strlen(Bitmap->text)==0) {
2708       count+=2 ;req4[count]=0x0c;
2709       count+=2 ;req4[count]=0x0d;
2710       count+=2 ;req4[count]=0x0e;
2711       count+=2 ;req4[count]=0x0f;
2712       count+=2 ;req4[count]=0x10;
2713       count+=2 ;req4[count]=0x11;
2714       count+=23;req4[count]=0x02;
2715       count++  ;req4[count]=0x01;
2716       count+=2;
2717     } else {
2718       count+=2 ;req4[count]=0x54;
2719       count++  ;req4[count]=0xd4;
2720       count++  ;req4[count]=0x0d;
2721       count+=2 ;req4[count]=0x0e;
2722       count+=2 ;req4[count]=0x0f;
2723       count+=2 ;req4[count]=0x10;
2724       count+=2 ;req4[count]=0x11;
2725       count+=21;req4[count]=0x01;
2726       count+=3 ;req4[count]=0x01;
2727       count+=2;
2728     }
2729
2730     req4[count++]=0x01;
2731     req4[count++]=Bitmap->width;
2732     req4[count++]=Bitmap->height;
2733     req4[count++]=Bitmap->size/256;
2734     req4[count++]=Bitmap->size%256;
2735     memcpy(req4+count,Bitmap->bitmap,Bitmap->size);
2736     count += Bitmap->size;
2737
2738     if (strlen(Bitmap->text)!=0) {
2739       req4[count] = strlen(Bitmap->text);
2740       GSM_PackSevenBitsToEight(0, Bitmap->text, req4+count+1);
2741       count=count+req4[count];
2742     } else {
2743       req4[count++]=0x00;
2744     }
2745     req4[count++]=0x00;
2746
2747     CurrentSetBitmapError = GE_BUSY;
2748
2749     Protocol->SendMessage(count, 0x14, req4);
2750
2751   case GSM_None:
2752     return GE_NONE;
2753   }
2754
2755   /* Wait for timeout or other error. */
2756   while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
2757           
2758     if (--timeout == 0)
2759       return (GE_TIMEOUT);
2760                     
2761     usleep (100000);
2762   }
2763
2764   if ((Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_7110OperatorLogo)
2765      && CurrentSetBitmapError==GE_NONE && !strcmp(Bitmap->netcode,"000 00")) {
2766     return N6110_Reset(0x03);
2767   }
2768
2769   return CurrentSetBitmapError;
2770 }
2771
2772 /* Get a bitmap from the phone */
2773 GSM_Error N7110_GetBitmap(GSM_Bitmap *Bitmap)
2774 {
2775   unsigned char req[10] = { N6110_FRAME_HEADER };
2776
2777   /* Picture Images */
2778   unsigned char req2[7] = { N6110_FRAME_HEADER, 0x96,0x00,0x0f,0x07 };
2779   unsigned char req3[9] = { 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39, 0x41, 0x49 };
2780   unsigned char req4[9] = { N6110_FRAME_HEADER, 0x07,
2781                                 0x00,  //location
2782                                 0x00,0x00, //index
2783                                 0x00, 0x64};
2784
2785   /* Welcome note */
2786   unsigned char req5[] = {0x00, 0x01, 0x01, 0xee, 0x02};
2787
2788   u8 count=3;
2789   int timeout;
2790   GSM_PhonebookEntry entry;
2791
2792   CurrentGetBitmapError = GE_BUSY;
2793
2794   CurrentGetBitmap=Bitmap;
2795
2796   switch (CurrentGetBitmap->type) {
2797   case GSM_StartupLogo:
2798   case GSM_7110StartupLogo:
2799   case GSM_6210StartupLogo:
2800     req[count-1]=0x01;  /* change FRAME_HEADER */
2801     req[count++]=0xee;  /* to get 0x01ee */
2802     req[count++]=0x15;
2803     Protocol->SendMessage(count, 0x7a, req);
2804     break;
2805
2806   case GSM_WelcomeNoteText:
2807
2808     Protocol->SendMessage(5, 0x7a, req5);
2809     break;
2810
2811   case GSM_DealerNoteText:
2812
2813     return GE_NOTIMPLEMENTED;
2814     
2815   case GSM_OperatorLogo:
2816   case GSM_7110OperatorLogo:
2817     req[count++]=0x70; /* NetworkStatus */
2818     Protocol->SendMessage(count, 0x0a, req);
2819     break;
2820
2821   case GSM_CallerLogo:
2822     entry.MemoryType = GMT_CG;
2823     entry.Location = Bitmap->number+1;
2824     *Bitmap->text=0;
2825     Bitmap->ringtone=0xFF;
2826     Bitmap->enabled=true;
2827     CurrentGetBitmapError = N7110_GetMemoryLocation(&entry);
2828     CurrentGetBitmap=NULL;
2829     if (entry.Location!=Bitmap->number+1) return GE_UNKNOWN;
2830     if (!strcmp(Bitmap->text,"")) {
2831       switch(Bitmap->number) {
2832         case 0:strcpy(Bitmap->text,"Family\0");break;
2833         case 1:strcpy(Bitmap->text,"VIP\0");break;
2834         case 2:strcpy(Bitmap->text,"Friends\0");break;
2835         case 3:strcpy(Bitmap->text,"Colleagues\0");break;
2836         case 4:strcpy(Bitmap->text,"Other\0");break;
2837       }
2838     }
2839     break;
2840
2841   case GSM_PictureImage:
2842
2843     PictureImageNum=0;
2844     count=0;
2845     while (count!=9) {
2846       req2[4]=req3[count];
2847       PictureImageLoc=req3[count];
2848       count++;
2849       if (NULL_SendMessageSequence (50, &CurrentGetBitmapError, 7, 0x14, req2)!=GE_NONE)
2850         return CurrentGetBitmapError;
2851       if (PictureImageNum==Bitmap->number+1) break;
2852     }
2853     if (CurrentGetBitmapError!=GE_NONE) return CurrentGetBitmapError;
2854
2855     req4[4]=PictureImageLoc;
2856     req4[5]=PictureImageIndex/256;
2857     req4[6]=PictureImageIndex%256;
2858
2859     CurrentGetBitmapError = GE_BUSY;
2860
2861     Protocol->SendMessage(9, 0x14, req4);
2862
2863     break;
2864   
2865   default:
2866     return GE_NOTSUPPORTED;
2867   }
2868
2869   timeout=150;
2870
2871   while (timeout != 0 && CurrentGetBitmapError == GE_BUSY) {
2872
2873     if (--timeout == 0)
2874       return (GE_TIMEOUT);
2875
2876     usleep (100000);
2877   }
2878
2879   CurrentGetBitmap=NULL;
2880
2881   return (CurrentGetBitmapError);
2882 }
2883
2884 int ReturnBinRingLocation()
2885 {
2886   char model[64];
2887
2888   while (GSM->GetModel(model) != GE_NONE) sleep(1);
2889
2890   if (strcmp(model,"NSE-5") == 0) return 0x74; //first 0x74 //7110
2891   if (strcmp(model,"NPE-3") == 0) return 0x89; //first is 0x89; //6210
2892   if (strcmp(model,"NHM-3") == 0) return 0x89; //quess for 6250
2893     
2894   return 0;
2895 }
2896
2897 /*
2898 this works only for 6210, the 7110 needs upload to a location ? 
2899 */
2900 GSM_Error N7110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
2901 {  
2902
2903   /* Buffer for preview uploading */
2904   unsigned char buffer[1000] = {0x7C, 0x01, 0x00, 0x0D,
2905                                 0x00, 0x00, 0x00, 0x00,
2906                                 0x00, 0x00,
2907                                 0x00  // Length
2908                                };
2909   int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
2910
2911   GSM_NetworkInfo NetworkInfo;
2912
2913   char req[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
2914                     0x87,  // Location
2915                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2916                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2917                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2918                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2919                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2920                     0x00, 0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2921                    };
2922
2923   /* Info from Till Toenshoff [till@uni.de]
2924
2925      One improvement - for looping you can use an alternative header
2926      normal
2927      0x02, 0xFC, 0x09, 0x00, 0x0A, 0x01
2928
2929      loop
2930      0x02, 0xFC, 0x09, 0x00, 0x05, 0xLL, 0x0A, 0x01
2931
2932      LL=0x01-0x10
2933
2934      0x01=loop once
2935      [...]
2936      0x10=loop infinite
2937   */
2938   char tail[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
2939                  0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
2940                  0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B         // 20 Bytes tail
2941                 };
2942
2943 //{ "c", "c#", "d", "d#", "e",      "f", "f#", "g", "g#", "a", "a#", "h" };
2944   char N7110_notes[14] =
2945   { 0,    1,    2,   3,    4,   4,   5,   6,    7,   8,    9,  10 ,   11,   11 };
2946
2947   int current = 6, i, note, lastnote = 0, duration;
2948
2949   /* Preview uploading */
2950   if (ringtone->location==255) {
2951     *maxlength=GSM_PackRingtone(ringtone, buffer+11, &size);
2952     buffer[10] = size;
2953     Protocol->SendMessage(size+11, 0x00, buffer);
2954     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
2955     sleep(1);
2956     return GE_NONE; //no answer from phone
2957   }
2958
2959   req[5]=ReturnBinRingLocation()+ringtone->location;
2960
2961   EncodeUnicode (req+current,ringtone->name ,strlen(ringtone->name));
2962
2963   current = 43;
2964
2965   for (i=0; i<ringtone->NrNotes; i++) {
2966
2967     if (ringtone->notes[i].note == 255)
2968       note = 0x40;
2969     else
2970       note = 114+12*((ringtone->notes[i].note/14)%4) + N7110_notes[ringtone->notes[i].note%14];
2971
2972     duration = 60000*ringtone->notes[i].duration/ringtone->notes[i].tempo/256;  // in 8 ms ticks of 7110
2973
2974     switch (ringtone->notes[i].style) {
2975       case StaccatoStyle:
2976         if (duration) {
2977           req[current++] = note;   // note only for one tick
2978           req[current++] = 1;
2979           duration--;
2980         }
2981         note = 0x40;               // rest pause
2982       case NaturalStyle:
2983         if (note != 0x40 && duration) {
2984           req[current++] = 0x40;
2985           req[current++] = 1;      // small pause between notes
2986           duration--;
2987         }
2988       default:
2989         if (note != 0x40 && note == lastnote && duration) {
2990           req[current++] = 0x40;
2991           req[current++] = 1;      // small pause between same notes
2992           duration--;
2993         }
2994
2995         while (duration > 125) {
2996           req[current++] = note;
2997           req[current++] = 125;
2998           duration -= 125;
2999         }
3000         req[current++] = note;
3001         req[current++] = duration;
3002     }
3003     lastnote = note;
3004   }
3005
3006   for (i = 0; i < sizeof(tail); i++)
3007     req[current++] = tail[i];
3008
3009   Protocol->SendMessage(current, 0x1F, req);
3010
3011   sleep(1);  
3012
3013   return GE_NONE; //no answer from phone
3014 }
3015
3016 void N7110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3017 {
3018   int i, tmp;
3019
3020   switch (MessageBuffer[3]) {
3021
3022   case 0x23:
3023
3024     tmp=0;i=4;
3025     while (MessageBuffer[i]!=0 || MessageBuffer[i+1]!=0) {
3026       tmp++;
3027       i=i+2;
3028     }
3029
3030     DecodeUnicode(CurrentGetBinRingtone->name,MessageBuffer+6,tmp);
3031
3032 #ifdef DEBUG
3033     fprintf(stdout, _("Message: Received ringtone \"%s\"\n"),CurrentGetBinRingtone->name);
3034 #endif /* DEBUG */
3035
3036     CurrentGetBinRingtone->frame[0]=0x00;
3037     CurrentGetBinRingtone->frame[1]=0x00;
3038     CurrentGetBinRingtone->frame[2]=0x0c;
3039     CurrentGetBinRingtone->frame[3]=0x01;
3040     CurrentGetBinRingtone->frame[4]=0x2c;
3041
3042     memcpy(CurrentGetBinRingtone->frame+5,CurrentGetBinRingtone->name,strlen(CurrentGetBinRingtone->name));
3043
3044     CurrentGetBinRingtone->length=5+strlen(CurrentGetBinRingtone->name);
3045
3046     CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3047     CurrentGetBinRingtone->frame[CurrentGetBinRingtone->length++]=0x00;
3048
3049     /* Looking for end */
3050     i=37;
3051     while (true) {
3052       if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
3053         i=i+2;break;
3054       }
3055       if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
3056         i=i+2;break;
3057       }
3058       i++;
3059       if (i==MessageLength) break;
3060     }
3061           
3062     /* Copying frame */
3063     memcpy(CurrentGetBinRingtone->frame+CurrentGetBinRingtone->length,MessageBuffer+37,i-37);
3064     CurrentGetBinRingtone->length=CurrentGetBinRingtone->length+i-37;
3065       
3066     CurrentBinRingtoneError=GE_NONE;
3067     break;
3068
3069   case 0x24:
3070
3071 #ifdef DEBUG
3072     fprintf(stdout, _("Message: Received empty ringtone\n"));
3073 #endif /* DEBUG */
3074
3075     CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;
3076     break;
3077   }
3078 }
3079
3080 GSM_Error N7110_GetBinRingTone(GSM_BinRingtone *ringtone)
3081 {
3082
3083   unsigned char req[6] = { N6110_FRAME_HEADER, 0x22, 0x00, 0x00 };
3084
3085   req[2]=0x01;
3086
3087   req[5]=ReturnBinRingLocation()+ringtone->location;
3088
3089   CurrentGetBinRingtone=ringtone;
3090
3091   return NULL_SendMessageSequence
3092     (50, &CurrentBinRingtoneError, 6, 0x1f, req);
3093
3094 }
3095
3096 GSM_Error N7110_SetBinRingTone(GSM_BinRingtone *ringtone)
3097 {
3098   unsigned char req[1000] = { N6110_FRAME_HEADER, 0x1f, 0x00, 0x00 };
3099
3100   GSM_NetworkInfo NetworkInfo;
3101   
3102   int i;
3103
3104   req[2]=0x01;
3105
3106   req[5]=ReturnBinRingLocation()+ringtone->location;
3107
3108   for (i=6;i<35;i++) req[i]=0x00;
3109
3110   i=6;
3111
3112   EncodeUnicode (req+i,ringtone->frame+5 ,strlen(ringtone->frame+5));
3113
3114   i=5;
3115
3116   while (ringtone->frame[i]!=0 || ringtone->frame[i+1]!=0) i++;
3117
3118   memcpy(req+35,ringtone->frame+i,ringtone->length-i);
3119
3120   Protocol->SendMessage(35+ringtone->length-i, 0x1f, req);  
3121
3122   GSM->GetNetworkInfo(&NetworkInfo); //need to make something    
3123   
3124   return GE_NONE; //no answer from phone
3125 }
3126
3127 void N7110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3128   
3129   GSM_SMSMessage NullSMS;
3130     
3131 #ifdef DEBUG
3132   fprintf(stdout,_("Message: Incoming SMS\n"));
3133 #endif /* DEBUG */
3134
3135   GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+5, MessageLength-5);
3136
3137 #ifdef DEBUG
3138   fprintf(stdout, _("\n"));      
3139 #endif /* DEBUG */      
3140 }
3141
3142 void N7110_Dispatch0x0AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3143 {
3144   int count;
3145
3146 #ifdef DEBUG  
3147   char name[100];
3148 #endif
3149   
3150   GSM_NetworkInfo NullNetworkInfo;
3151
3152   switch (MessageBuffer[3]) {
3153
3154   case 0xb0:
3155
3156 #ifdef DEBUG
3157     fprintf(stdout, _("Message: Clearing operator logo msg\n"));
3158 #endif
3159     CurrentSetBitmapError=GE_NONE;
3160     break;
3161
3162   case 0x71:
3163
3164     /* Make sure we are expecting NetworkInfo frame */
3165     if ((CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) ||
3166         (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)) {
3167 #ifdef DEBUG
3168       fprintf(stdout, _("Message: Network informations and operator logo:\n"));
3169 #endif
3170     } else {
3171 #ifdef DEBUG
3172       fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
3173 #endif
3174     }
3175
3176     sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
3177
3178     sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
3179
3180     sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
3181
3182 #ifdef DEBUG
3183     fprintf(stdout, _("   CellID: %s\n"), NullNetworkInfo.CellID);
3184     fprintf(stdout, _("   LAC: %s\n"), NullNetworkInfo.LAC);
3185     fprintf(stdout, _("   Network code: %s\n"), NullNetworkInfo.NetworkCode);
3186     fprintf(stdout, _("   Network name for gnokii: %s (%s)\n"),
3187                   GSM_GetNetworkName(NullNetworkInfo.NetworkCode),
3188                   GSM_GetCountryName(NullNetworkInfo.NetworkCode));
3189
3190     DecodeUnicode(name,MessageBuffer+18,MessageBuffer[17]);
3191     fprintf(stdout, _("   Network name for phone: %s\n"),name);
3192
3193     fprintf(stdout, _("   Status: "));
3194     switch (MessageBuffer[8]) {
3195       case 0x01: fprintf(stdout, _("home network selected")); break;
3196       case 0x02: fprintf(stdout, _("roaming network")); break;
3197       case 0x03: fprintf(stdout, _("requesting network")); break;
3198       case 0x04: fprintf(stdout, _("not registered in the network")); break;
3199       default:   fprintf(stdout, _("unknown"));
3200     }
3201
3202     fprintf(stdout, "\n");
3203
3204     fprintf(stdout, _("   Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
3205 #endif /* DEBUG */
3206
3207     /* Make sure we are expecting NetworkInfo frame */
3208     if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
3209       *CurrentNetworkInfo=NullNetworkInfo;
3210       CurrentNetworkInfoError = GE_NONE;
3211     }
3212
3213     /* Make sure we are expecting an operator logo */
3214     if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3215
3216       strcpy(CurrentGetBitmap->netcode,NullNetworkInfo.NetworkCode);
3217
3218 #ifdef DEBUG
3219       if (MessageBuffer[4] == 0x02)
3220         fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),
3221                            CurrentGetBitmap->netcode,
3222                            GSM_GetNetworkName(CurrentGetBitmap->netcode));
3223       else
3224         fprintf(stdout, _("Message: No Operator Logo for %s (%s) network received.\n"),
3225                            CurrentGetBitmap->netcode,
3226                            GSM_GetNetworkName(CurrentGetBitmap->netcode));
3227 #endif
3228
3229       CurrentGetBitmap->type=GSM_7110OperatorLogo;
3230       if (MessageBuffer[4] == 0x02) {   /* logo present */
3231         count = 7;
3232         count += MessageBuffer[count];  /* skip network info */
3233         count ++;
3234         CurrentGetBitmap->width=MessageBuffer[count++];  /* 78 */
3235         CurrentGetBitmap->height=MessageBuffer[count++]; /* 21 */
3236         count+=4;
3237         CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3238         memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
3239       } else {
3240         CurrentGetBitmap->width=78;
3241         CurrentGetBitmap->height=21;
3242         CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* packed size */
3243         memset(CurrentGetBitmap->bitmap,0,CurrentGetBitmap->size);
3244       }
3245       CurrentGetBitmapError=GE_NONE;
3246     }
3247
3248     break;
3249
3250   case 0x82:
3251 #ifdef DEBUG
3252     fprintf(stdout, _("Message: Network Level received:\n"));
3253
3254     fprintf(stdout, _("   Network Level: %d\n"), MessageBuffer[4]);
3255 #endif /* DEBUG */
3256
3257     CurrentRFLevel=MessageBuffer[4];
3258     break;
3259
3260   case 0xa4:
3261
3262 #ifdef DEBUG
3263     fprintf(stdout, _("Message: Operator logo set correctly.\n"));
3264 #endif
3265     CurrentSetBitmapError = GE_NONE;      
3266     break;
3267
3268   default:
3269 #ifdef DEBUG
3270     fprintf(stdout, _("Message: Unknown message of type 0x0a\n"));
3271 #endif /* DEBUG */
3272     AppendLogText("Unknown msg\n",false);
3273     break;      /* Visual C Don't like empty cases */
3274   }
3275 }
3276
3277 void N7110_Dispatch0x14Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3278 {
3279   int i, tmp;
3280   GSM_ETSISMSMessage ETSI;
3281
3282   switch (MessageBuffer[3]) {
3283
3284   /* We have requested invalid or empty location. */
3285   case 0x09:
3286
3287 #ifdef DEBUG
3288     fprintf(stdout, _("Message: SMS reading failed\n"));
3289 #endif /* DEBUG */
3290
3291    CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3292    CurrentGetBitmapError=GE_UNKNOWN;
3293    break;
3294
3295   /* getsms or picture image */    
3296   case 0x08:
3297
3298     if (MessageBuffer[8]==0x07) {
3299
3300       if (CurrentGetBitmap!=NULL) {
3301
3302         for (i=0;i<MessageBuffer[9]+1;i++)
3303           ETSI.SMSCNumber[i]=MessageBuffer[i+9];
3304
3305         for (i=0;i<((MessageBuffer[22]+1)/2+1)+1;i++)
3306            ETSI.Number[i]=MessageBuffer[22+i];
3307
3308 #ifdef DEBUG
3309         fprintf(stdout, _("Message: Picture Image received\n"));
3310         fprintf(stdout, _("   SMS center number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.SMSCNumber,false));
3311         fprintf(stdout, _("   Sender number: %s\n"), GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3312 #endif /* DEBUG */
3313
3314         strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(ETSI.Number,true));
3315
3316         CurrentGetBitmap->width=MessageBuffer[47];
3317         CurrentGetBitmap->height=MessageBuffer[48];
3318         CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap);
3319       
3320         memcpy(CurrentGetBitmap->bitmap,MessageBuffer+51,CurrentGetBitmap->size);
3321
3322         tmp=GSM_UnpackEightBitsToSeven(0, 121, 121, MessageBuffer+52+CurrentGetBitmap->size,
3323                                        CurrentGetBitmap->text);
3324
3325         CurrentGetBitmap->text[MessageBuffer[51+CurrentGetBitmap->size]]=0;
3326  
3327         CurrentGetBitmapError=GE_NONE;
3328           
3329       } else {
3330 #ifdef DEBUG
3331         fprintf(stdout, _("Message: Picture Image received, but not reqested\n"));
3332 #endif /* DEBUG */
3333
3334         CurrentSMSMessageError = GE_SMSTOOLONG;
3335       }
3336         
3337       break;
3338     } else {
3339       /* sms message */
3340       /* status in byte 4 */
3341       CurrentSMSMessage->Status = MessageBuffer[4];
3342
3343       CurrentSMSMessage->Type = GST_SMS;
3344       if (MessageBuffer[8]==0x01) CurrentSMSMessage->Type = GST_DR;
3345       
3346       CurrentSMSMessage->MessageNumber = CurrentSMSMessage->Location;
3347         
3348       /* RTH FIXME: old folder stuff for xgnokii */     
3349       CurrentSMSMessage->folder = (MessageBuffer[5] / 8)-1;
3350       /* if unreadMessage from folder 0, set INBOX folder */
3351       if (CurrentSMSMessage->folder==-1) CurrentSMSMessage->folder = 0;
3352 #ifdef DEBUG
3353       fprintf(stdout, _("Message: SMS Message received: Type: %i Folder: %i Location: %i\n")
3354                 ,CurrentSMSMessage->Type, CurrentSMSMessage->folder,  MessageBuffer[7]);
3355 #endif /* DEBUG */
3356
3357       GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+9, MessageLength-9);    
3358
3359       /* Signal no error to calling code. */
3360       CurrentSMSMessageError = GE_NONE;
3361       break;
3362     }
3363   case 0x51:
3364 #ifdef DEBUG
3365     fprintf(stdout, _("Message: Picture Image saved OK\n"));
3366     fprintf(stdout, _("  folder  : %02x\n"),MessageBuffer[4]);
3367     fprintf(stdout, _("  location: %02x\n"),MessageBuffer[5]*256+MessageBuffer[6]);
3368 #endif /* DEBUG */
3369     CurrentSetBitmapError=GE_NONE;
3370     break;
3371
3372   case 0x97:
3373
3374 #ifdef DEBUG
3375     fprintf(stdout, _("Message: Received index for Picture Images\n"));
3376 #endif /* DEBUG */
3377
3378     for (i=1;i<MessageBuffer[4]*256+MessageBuffer[5]+1;i++) {
3379       PictureImageNum++;
3380       if (PictureImageNum==CurrentGetBitmap->number+1) {
3381         PictureImageIndex=MessageBuffer[4+i*2]*256+MessageBuffer[5+i*2];
3382         break;
3383       }
3384     }
3385
3386     CurrentGetBitmapError=GE_NONE;    
3387     CurrentSetBitmapError=GE_NONE;    
3388
3389     break;
3390     
3391   default:
3392
3393 #ifdef DEBUG
3394     fprintf(stdout, _("Message: Unknown message of type 14\n"));
3395 #endif /* DEBUG */
3396     AppendLogText("Unknown msg\n",false);
3397     break;      /* Visual C Don't like empty cases */
3398   }
3399 }
3400
3401 void N7110_Dispatch0x17Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3402 {
3403   switch (MessageBuffer[3]) {
3404
3405   case 0x03:
3406
3407 #ifdef DEBUG
3408     fprintf(stdout, _("Message: Battery status received:\n"));
3409
3410     fprintf(stdout, _("   Battery Level: %d\n"), MessageBuffer[5]);
3411 #endif /* DEBUG */
3412
3413     CurrentBatteryLevel=MessageBuffer[5];
3414     break;
3415
3416   default:
3417
3418 #ifdef DEBUG
3419     fprintf(stdout, _("Message: Unknown message of type 0x17\n"));
3420 #endif /* DEBUG */
3421     AppendLogText("Unknown msg\n",false);
3422     break;      /* Visual C Don't like empty cases */
3423   }
3424 }
3425
3426 void N7110_Dispatch0x7AMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3427 {
3428   int i, tmp;
3429
3430   switch (MessageBuffer[3]) {
3431
3432   /* Setting setting request */
3433   case 0xeb:
3434
3435     switch (MessageBuffer[4]) {
3436       case 0x02:
3437
3438 #ifdef DEBUG
3439         fprintf(stdout, _("Message: Startup text set correctly.\n"));
3440 #endif
3441         CurrentSetBitmapError = GE_NONE;
3442         break;
3443
3444       case 0x15:
3445 #ifdef DEBUG
3446         fprintf(stdout, _("Message: Startup logo set correctly.\n"));
3447 #endif
3448         CurrentSetBitmapError = GE_NONE;
3449         break;
3450     }
3451
3452     break;
3453
3454   /* Setting received */
3455   case 0xed:
3456
3457     switch (MessageBuffer[4]) {
3458       case 0x02:
3459
3460 #ifdef DEBUG
3461         fprintf(stdout, _("Message: Startup text received.\n"));
3462 #endif
3463
3464         tmp=0;i=6;
3465         while (MessageBuffer[i]!=0||MessageBuffer[i+1]!=0) {
3466           i=i+2;
3467           tmp++;
3468         }
3469
3470         DecodeUnicode (CurrentGetBitmap->text, MessageBuffer+6, tmp);
3471
3472 #ifdef DEBUG
3473         fprintf(stdout, _("   Text: \"%s\"\n"),CurrentGetBitmap->text);
3474 #endif
3475
3476         CurrentGetBitmapError = GE_NONE;
3477         break;
3478
3479       case 0x15:
3480 #ifdef DEBUG
3481         if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY)
3482           fprintf(stdout, _("Message: Startup logo received.\n"));
3483         else
3484           fprintf(stdout, _("Message: Startup logo not requested, but received.\n"));
3485 #endif
3486
3487         /* Make sure we are expecting a startup logo */
3488         if (CurrentGetBitmap && CurrentGetBitmapError == GE_BUSY) {
3489           CurrentGetBitmap->height=MessageBuffer[13];  /* 96 */
3490           CurrentGetBitmap->width=MessageBuffer[17];   /* 60/65 */
3491           CurrentGetBitmap->type=GSM_7110StartupLogo;
3492           if (CurrentGetBitmap->width==60) CurrentGetBitmap->type=GSM_6210StartupLogo;
3493           CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); /* unpacked size */
3494           if (CurrentGetBitmap->size > sizeof(CurrentGetBitmap->bitmap))
3495             CurrentGetBitmap->size=sizeof(CurrentGetBitmap->bitmap);
3496           memcpy(CurrentGetBitmap->bitmap,MessageBuffer+22,CurrentGetBitmap->size);
3497           CurrentGetBitmapError=GE_NONE;
3498         }
3499         break;
3500       case 0x1c:
3501 #ifdef DEBUG
3502         fprintf(stdout, _("Message: security code \""));
3503
3504         for (i=6;i<11;i++) {
3505           fprintf(stdout, _("%c"),MessageBuffer[i]);
3506         }
3507           
3508         fprintf(stdout,_("\"received.\n"));
3509 #endif
3510         strncpy(CurrentSecurityCode->Code,MessageBuffer+6,6);
3511           
3512         CurrentSecurityCodeError=GE_NONE;         
3513         break;
3514     }
3515     break;
3516       
3517   default:
3518 #ifdef DEBUG
3519     fprintf(stdout, _("Unknown message of type 0x7a.\n"));
3520 #endif
3521     AppendLogText("Unknown msg\n",false);
3522     break;      /* Visual C Don't like empty cases */
3523   }
3524 }
3525
3526 void N7110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType)
3527 {
3528   bool unknown=false;
3529
3530   /* Switch on the basis of the message type byte */
3531   switch (MessageType) {
3532
3533   /* Call information */
3534   /* Note, we use N6110_Dispatch0x40Message, but only some of 0x01
3535      old msg are available in new phones - other returns generally only
3536      errors */
3537   case 0x01:
3538           
3539     N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);
3540     break;
3541
3542   /* SMS handling */
3543   case 0x02:
3544     switch (MessageBuffer[3]) {
3545       case 0x02:
3546       case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;
3547       case 0x0e:
3548       case 0x0f:N7110_ReplyEnableIncomingSMSInfo(MessageLength,MessageBuffer,MessageType);break;
3549       case 0x11:N7110_ReplyIncomingSMS          (MessageLength,MessageBuffer,MessageType);break;
3550       case 0x21:N6110_ReplySetCellBroadcast     (MessageLength, MessageBuffer, MessageType);break;
3551       case 0x23:N6110_ReplyReadCellBroadcast    (MessageLength, MessageBuffer, MessageType);break;
3552       case 0x31:N6110_ReplySetSMSCenter         (MessageLength,MessageBuffer,MessageType);break;
3553       case 0x34:
3554       case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
3555       default  :unknown=true;break;
3556     }
3557     break;
3558
3559   /* Phonebook and speed dials */
3560   case 0x03:
3561     switch (MessageBuffer[3]) {
3562       case 0x04:N7110_ReplyGetMemoryStatus        (MessageLength,MessageBuffer,MessageType);break;
3563       case 0x08:N7110_ReplyGetMemoryLocation      (MessageLength,MessageBuffer,MessageType);break;
3564       case 0x10:N7110_ReplyDeletePhonebookLocation(MessageLength,MessageBuffer,MessageType);break;
3565       case 0x0C:N7110_ReplyWritePhonebookLocation (MessageLength,MessageBuffer,MessageType);break;
3566       default  :unknown=true;break;
3567     }
3568     break;
3569
3570   /* This is call forwarding stuff */
3571   case 0x06:
3572     switch (MessageBuffer[3]) {
3573       case 0x02:
3574       case 0x03:N6110_ReplyCallDivert    (MessageLength,MessageBuffer,MessageType);break;
3575       default  :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;
3576     }
3577     break;
3578
3579   /* Network and operator logo */
3580   case 0x0a:
3581
3582     N7110_Dispatch0x0AMessage(MessageLength, MessageBuffer, MessageType);
3583     break;
3584
3585   /* Calendar notes handling */
3586   case 0x13:
3587     switch (MessageBuffer[3]) {
3588       case 0x02:
3589       case 0x04:
3590       case 0x06:
3591       case 0x08:N7110_ReplyWriteCalendarNote   (MessageLength,MessageBuffer,MessageType);break;
3592       case 0x0c:N7110_ReplyDeleteCalendarNote  (MessageLength,MessageBuffer,MessageType);break;
3593       case 0x1A:N7110_ReplyGetCalendarNote     (MessageLength,MessageBuffer,MessageType);break;
3594       case 0x32:N7110_ReplyFirstCalendarFreePos(MessageLength,MessageBuffer,MessageType);break;
3595       case 0x3b:N7110_ReplyGetCalendarNotesInfo(MessageLength,MessageBuffer,MessageType);break;
3596       default  :unknown=true;break;
3597     }
3598     break;
3599
3600   /* SMS stuff */
3601   case 0x14:
3602     switch (MessageBuffer[3]) {
3603       case 0x05:
3604       case 0x06:N7110_ReplySaveSMSMessage    (MessageLength,MessageBuffer,MessageType);break;
3605       case 0x0b:N7110_ReplyDeleteSMSMessage  (MessageLength,MessageBuffer,MessageType);break;
3606       case 0x37:
3607       case 0x38:N7110_ReplyGetSMSStatus      (MessageLength,MessageBuffer,MessageType);break;
3608       case 0x6C:N7110_ReplyGetSMSFolderStatus(MessageLength,MessageBuffer,MessageType);break;
3609       case 0x7B:N7110_ReplyGetSMSFolders     (MessageLength,MessageBuffer,MessageType);break;
3610       case 0x84:N7110_ReplySaveSMSMessage    (MessageLength,MessageBuffer,MessageType);break;
3611       default  :N7110_Dispatch0x14Message    (MessageLength, MessageBuffer, MessageType);break;
3612     }
3613     break;
3614  
3615   /* Battery status */
3616   case 0x17:
3617
3618     N7110_Dispatch0x17Message(MessageLength, MessageBuffer, MessageType);
3619     break;
3620
3621   /* Date and time */
3622   case 0x19:
3623     switch (MessageBuffer[3]) {
3624       case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break;
3625       case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break;
3626       case 0x6c:N6110_ReplySetAlarm   (MessageLength,MessageBuffer,MessageType);break;
3627       case 0x6e:N6110_ReplyGetAlarm   (MessageLength,MessageBuffer,MessageType);break;
3628       default  :unknown=true;break;
3629     }
3630     break;
3631
3632   /* Ringtones */
3633   case 0x1f:
3634     switch (MessageBuffer[3]) {
3635       case 0x23:
3636       case 0x24:N7110_ReplyGetBinRingtone(MessageLength,MessageBuffer,MessageType);break;
3637       default  :unknown=true;break;
3638     }
3639     break;
3640
3641   /* Profiles */
3642   case 0x39:
3643
3644     N7110_ReplyGetProfile(MessageLength, MessageBuffer, MessageType);
3645     break;
3646
3647   /* WAP */
3648   case 0x3f:
3649     switch (MessageBuffer[3]) {
3650       case 0x01:
3651       case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;
3652       case 0x07:
3653       case 0x08:N7110_ReplyGetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
3654       case 0x0a:
3655       case 0x0b:N7110_ReplySetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
3656       case 0x16:
3657       case 0x17:
3658       case 0x1c:N7110_ReplyGetWAPSettings   (MessageLength,MessageBuffer,MessageType);break;
3659       default  :unknown=true;break;
3660     }
3661     break;
3662
3663   /* Internal phone functions ? */
3664   /* Note, we use N6110_Dispatch0x40Message, but only some of 0x40
3665      old msg are available in new phones - other returns generally only
3666      errors */
3667   case 0x40:
3668     switch (MessageBuffer[2]) {
3669       case 0x64:N6110_ReplyEnableExtendedCommands  (MessageLength,MessageBuffer,MessageType);break;
3670       case 0x65:N6110_ReplyResetPhoneSettings      (MessageLength,MessageBuffer,MessageType);break;
3671       case 0x66:N6110_ReplyIMEI                    (MessageLength,MessageBuffer,MessageType);break;
3672       case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3673       case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
3674       case 0x7e:N6110_ReplyNetmonitor              (MessageLength,MessageBuffer,MessageType);break;
3675       case 0x8a:N6110_ReplySimlockInfo             (MessageLength,MessageBuffer,MessageType);break;
3676       case 0x8f:N6110_ReplyPlayTone                (MessageLength,MessageBuffer,MessageType);break;
3677       case 0xc8:N6110_ReplyHW                      (MessageLength,MessageBuffer,MessageType);break;
3678       default  :N6110_Dispatch0x40Message          (MessageLength,MessageBuffer,MessageType);break;
3679     }
3680     break;
3681
3682   /* Settings */
3683   case 0x7a:
3684
3685     N7110_Dispatch0x7AMessage(MessageLength, MessageBuffer, MessageType);
3686     break;
3687
3688   /***** Acknowlegment of our frames. *****/
3689   case FBUS_FRTYPE_ACK:
3690
3691     N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);
3692     break;
3693
3694   case 0xd2:
3695
3696     N6110_ReplyID(MessageLength, MessageBuffer, MessageType);
3697     break;
3698
3699   /***** Unknown message *****/
3700   /* If you think that you know the exact meaning of other messages - please
3701      let us know. */
3702   default:
3703
3704 #ifdef DEBUG
3705     fprintf(stdout, _("Message: Unknown message type.\n"));
3706 #endif /* DEBUG */
3707     AppendLogText("Unknown msg type\n",false);
3708     break;
3709
3710   }
3711
3712   if (unknown) {
3713 #ifdef DEBUG
3714     fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);
3715 #endif
3716     AppendLogText("Unknown msg\n",false);
3717   }
3718 }