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