Cosmetic unused variable
[gnokii.git] / common / newmodules / n6110.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 6110 and similar
10   phones.
11
12 */
13
14 #include "config.h"
15
16 /* "Turn on" prototypes in n-6110.h */
17
18 #define __n_6110_c 
19
20 /* System header files */
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #ifdef WIN32
26   #include "misc_win32.h"
27 #endif
28  
29 /* Various header file */
30 #ifndef VC6
31   #include "config.h"
32 #endif
33
34 #include "gsm-api.h"
35 #include "gsm-coding.h"
36 #include "newmodules/n6110.h"
37 #include "newmodules/n7110.h"
38 #include "protocol/fbus.h"
39 #include "devices/device.h"
40 /* Global variables used by code in gsm-api.c to expose the functions
41    supported by this model of phone. */
42
43
44 /* Here we initialise model specific functions. */
45 GSM_Functions N6110_Functions = {
46   N6110_Initialise,
47   N6110_DispatchMessage,
48   NULL_Terminate,
49   NULL_KeepAlive,
50   N6110_GetMemoryLocation,
51   N6110_WritePhonebookLocation,
52   N6110_GetSpeedDial,
53   N6110_SetSpeedDial,
54   N6110_GetMemoryStatus,
55 #ifndef UCLINUX
56   N6110_GetSMSStatus,
57   N6110_GetSMSCenter,
58   N6110_SetSMSCenter,
59   N6110_GetSMSMessage,
60   N6110_DeleteSMSMessage,
61   N6110_SendSMSMessage,
62   N6110_SaveSMSMessage,
63 #else /* UCLINUX */
64   NULL,
65   NULL,
66   NULL,
67   NULL,
68   NULL,
69   NULL,
70   NULL,
71 #endif /* UCLINUX */
72   N6110_GetRFLevel,
73   N6110_GetBatteryLevel,
74   N6110_GetPowerSource,
75 #ifndef UCLINUX
76   N6110_GetDisplayStatus,
77   N6110_EnterSecurityCode,
78   N6110_GetSecurityCodeStatus,
79   N6110_GetSecurityCode,
80 #else /* UCLINUX */
81   NULL,
82   NULL,
83   NULL,
84   NULL,
85 #endif /* UCLINUX */
86   N6110_GetIMEI,
87   N6110_GetRevision,
88   N6110_GetModel,
89 #ifndef UCLINUX
90   N6110_GetDateTime,
91   N6110_SetDateTime,
92   N6110_GetAlarm,
93   N6110_SetAlarm,
94   N6110_DialVoice,
95 #else /* UCLINUX */
96   NULL,
97   NULL,
98   NULL,
99   NULL,
100   NULL,
101 #endif /* UCLINUX */
102   N6110_DialData,
103 #ifndef UCLINUX
104   N6110_GetIncomingCallNr,
105   N6110_GetNetworkInfo,
106   N6110_GetCalendarNote,
107   N6110_WriteCalendarNote,
108   N6110_DeleteCalendarNote,
109   N6110_NetMonitor,
110   N6110_SendDTMF,
111   N6110_GetBitmap,
112   N6110_SetBitmap,
113   N6110_SetRingTone,
114   N6110_SetBinRingTone,
115   N6110_GetBinRingTone,
116 #else /* UCLINUX */
117   NULL,
118   NULL,
119   NULL,
120   NULL,
121   NULL,
122   NULL,
123   NULL,
124   NULL,
125   NULL,
126   NULL,
127   NULL,
128   NULL,
129 #endif /* UCLINUX */
130   N6110_Reset,
131 #ifndef UCLINUX
132   N6110_GetProfile,
133   N6110_SetProfile,
134 #else /* UCLINUX */
135   NULL,
136   NULL,
137 #endif /* UCLINUX */
138   N6110_SendRLPFrame,
139   N6110_CancelCall,
140 #ifndef UCLINUX
141   N6110_PressKey,
142   N6110_EnableDisplayOutput,
143   N6110_DisableDisplayOutput,
144   N6110_EnableCellBroadcast,
145   N6110_DisableCellBroadcast,
146   N6110_ReadCellBroadcast,
147   N6110_PlayTone,
148   N6110_GetProductProfileSetting,
149   N6110_SetProductProfileSetting,
150   N6110_GetOperatorName,
151   N6110_SetOperatorName,
152   N6110_GetVoiceMailbox,  N6110_Tests,
153   N6110_SimlockInfo,
154   UNIMPLEMENTED,                 //GetCalendarNotesInfo
155   N6110_GetSMSFolders,
156   N6110_ResetPhoneSettings,
157   N7110_GetWAPBookmark,
158   N7110_SetWAPBookmark,
159   N7110_GetWAPSettings,
160   N6110_CallDivert,
161   N6110_AnswerCall,
162 #else /* UCLINUX */
163   NULL,
164   NULL,
165   NULL,
166   NULL,
167   NULL,
168   NULL,
169   NULL,
170   NULL,
171   NULL,
172   NULL,
173   NULL,
174   NULL,  NULL,
175   NULL,
176   NULL,                 //GetCalendarNotesInfo
177   NULL,
178   NULL,
179   NULL,
180   NULL,
181   NULL,
182   NULL,
183   NULL,
184 #endif /* UCLINUX */
185   N6110_GetManufacturer
186 };
187
188 /* Mobile phone information */
189
190 GSM_Information N6110_Information = {
191   "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850",
192      /* Supported models in FBUS */
193   "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850",
194      /* Supported models in MBUS */
195   "6110|6130|6150|8210|8850",
196      /* Supported models in FBUS over infrared */
197   "",
198      /* Supported models in FBUS over DLR3 */
199   "",
200      /* AT commands */
201   "8210|8850",
202      /* infrared sockets */
203   "6110|6130|6150|8210|8850",
204      /* Supported models in FBUS over infrared with Tekram device */  
205   4,                     /* Max RF Level */
206   0,                     /* Min RF Level */
207   GRF_Arbitrary,         /* RF level units */
208   4,                     /* Max Battery Level */
209   0,                     /* Min Battery Level */
210   GBU_Arbitrary,         /* Battery level units */
211   GDT_DateTime,          /* Have date/time support */
212   GDT_TimeOnly,          /* Alarm supports time only */
213   1                      /* Only one alarm available */
214 };
215
216 #ifdef DEBUG
217 static const char *N6110_MemoryType_String [] = {
218   "",   /* 0x00 */
219   "MT", /* 0x01 */
220   "ME", /* 0x02 */
221   "SM", /* 0x03 */
222   "FD", /* 0x04 */
223   "ON", /* 0x05 */
224   "EN", /* 0x06 */
225   "DC", /* 0x07 */
226   "RC", /* 0x08 */
227   "MC", /* 0x09 */
228 };
229 #endif /* DEBUG */
230
231 /* Magic bytes from the phone. */
232 static unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };
233
234 /* For DisplayOutput */
235 #ifndef UCLINUX
236 static char               PhoneScreen[5+1][27+1];
237 static int                OldX=1000,OldY=0,NewX=0,NewY=0;
238 #endif /* UCLINUX */
239
240 void N6110_ReplyEnableExtendedCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
241
242 #ifdef DEBUG
243   fprintf(stdout, _("Message: Answer for EnableExtendedSecurityCommands frame, meaning not known :-(\n"));
244 #endif /* DEBUG */
245
246   CurrentEnableExtendedCommandsError=GE_NONE;   
247 }
248
249 /* If you set make some things (for example,
250    change Security Code from phone's menu, disable and enable
251    phone), it won't answer for 0x40 frame - you won't be able
252    to play tones, get netmonitor, etc.
253
254    This function do thing called "Enabling extended security commands" -
255    it enables 0x40 frame functions.
256
257    This frame can also some other things - see below */
258 GSM_Error N6110_EnableExtendedCommands (unsigned char status)
259 {
260   unsigned char req[4] = { 0x00,
261                            0x01,0x64, /* Enable extended commands request */
262                            0x01 };    /* 0x01 - on, 0x00 - off,
263                                          0x03 & 0x04 - soft & hard reset,
264                                          0x06 - CONTACT SERVICE */
265
266   /* 0x06 MAKES CONTACT SERVICE! BE CAREFULL! */
267   /* When use 0x03 and had during session changed time & date
268      some phones (like 6150 or 6210) can ask for time & date after reset
269      or disable clock on the screen */
270   if (status!=0x06) req[3] = status;
271
272   return NULL_SendMessageSequence
273     (50, &CurrentEnableExtendedCommandsError, 4, 0x40, req);
274 }
275
276 void N6110_ReplyIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
277
278 #if defined WIN32 || !defined HAVE_SNPRINTF
279   sprintf(Current_IMEI, "%s", MessageBuffer+4);
280 #else
281   snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+4);
282 #endif
283
284 #ifdef DEBUG
285   fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI);
286 #endif
287
288   CurrentGetIMEIError=GE_NONE;       
289 }
290
291 GSM_Error N6110_SendIMEIFrame()
292 {
293   unsigned char req[4] = {0x00, 0x01, 0x66, 0x00};  
294
295   GSM_Error error;
296
297   error=N6110_EnableExtendedCommands(0x01);
298   if (error!=GE_NONE) return error;
299   
300   return NULL_SendMessageSequence (20, &CurrentGetIMEIError, 4, 0x40, req);
301 }
302
303 void N6110_ReplyHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
304
305   int i, j;
306     
307   if (MessageBuffer[3]==0x05) {
308
309 #ifdef DEBUG
310     fprintf(stdout,_("Message: Hardware version received: "));
311 #endif
312
313     j=strlen(Current_Revision);
314     Current_Revision[j++]=',';
315     Current_Revision[j++]=' ';
316     Current_Revision[j++]='H';
317     Current_Revision[j++]='W';
318             
319     for (i=5;i<9;i++) {
320 #ifdef DEBUG
321       fprintf(stdout,_("%c"), MessageBuffer[i]);
322 #endif
323       Current_Revision[j++]=MessageBuffer[i];
324     }
325
326 #ifdef DEBUG
327     fprintf(stdout,_("\n"));
328 #endif
329
330     CurrentGetHWError=GE_NONE;
331   }
332 }
333
334 GSM_Error N6110_SendHWFrame()
335 {
336   unsigned char req[4] = {0x00, 0x01, 0xc8, 0x05};  
337
338   GSM_Error error;
339
340   error=N6110_EnableExtendedCommands(0x01);
341   if (error!=GE_NONE) return error;
342   
343   return NULL_SendMessageSequence (20, &CurrentGetHWError, 4, 0x40, req);
344 }
345
346 void N6110_ReplyID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
347
348   int i, j;
349  
350 #ifdef DEBUG
351   fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
352   fprintf(stdout, _("   Firmware: "));
353 #endif
354
355   strcpy(Current_Revision,"SW");
356     
357   i=6;j=2;
358   while (MessageBuffer[i]!=0x0a) {
359     Current_Revision[j]=MessageBuffer[i];
360 #ifdef DEBUG
361     fprintf(stdout, _("%c"),MessageBuffer[i]);
362 #endif
363     if (j==GSM_MAX_REVISION_LENGTH-1) {
364 #ifdef DEBUG
365       fprintf(stderr,_("ERROR: increase GSM_MAX_REVISION_LENGTH!\n"));
366 #endif  
367       break;
368     }
369     j++;
370     i++;
371   }
372   Current_Revision[j+1]=0;
373
374 #ifdef DEBUG
375   fprintf(stdout, _("\n   Firmware date: "));
376 #endif
377
378   i++;
379   while (MessageBuffer[i]!=0x0a) {
380 #ifdef DEBUG
381     fprintf(stdout, _("%c"),MessageBuffer[i]);
382 #endif
383     i++;
384   }
385
386 #ifdef DEBUG
387   fprintf(stdout, _("\n   Model: "));
388 #endif /* DEBUG */
389
390   i++;j=0;
391   while (MessageBuffer[i]!=0x0a) {
392     Current_Model[j]=MessageBuffer[i];
393 #ifdef DEBUG
394     fprintf(stdout, _("%c"),MessageBuffer[i]);
395 #endif
396     if (j==GSM_MAX_MODEL_LENGTH-1) {
397 #ifdef DEBUG
398       fprintf(stderr,_("ERROR: increase GSM_MAX_MODEL_LENGTH!\n"));
399 #endif  
400       break;
401     }
402     j++;
403     i++;
404   }
405   Current_Model[j+1]=0;
406
407 #ifdef DEBUG
408   fprintf(stdout, _("\n"));
409 #endif /* DEBUG */
410     
411   CurrentMagicError=GE_NONE;
412 }
413
414 GSM_Error N6110_SendIDFrame()
415 {
416   unsigned char req[5] = {N6110_FRAME_HEADER, 0x03, 0x00};  
417
418   return NULL_SendMessageSequence (50, &CurrentMagicError, 5, 0xd1, req);
419 }
420
421 /* This function send the status request to the phone. */
422 /* Seems to be ignored in N3210 */
423 GSM_Error N6110_SendStatusRequest(void)
424 {
425   unsigned char req[] = {N6110_FRAME_HEADER, 0x01};
426
427   Protocol->SendMessage(4, 0x04, req);
428
429   return (GE_NONE);
430 }
431
432 static void N6110_ReplyGetAuthentication(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
433
434   LIVE;
435
436 #if defined WIN32 || !defined HAVE_SNPRINTF
437   sprintf(Current_IMEI, "%s", MessageBuffer+9);
438   sprintf(Current_Model, "%s", MessageBuffer+25);
439   sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39);
440 #else
441   snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+9);
442   snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+25);
443   snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39);
444 #endif
445
446 #ifdef DEBUG
447   fprintf(stdout, _("Message: Mobile phone identification received:\n"));
448   fprintf(stdout, _("   IMEI: %s\n"), Current_IMEI);
449   fprintf(stdout, _("   Model: %s\n"), Current_Model);
450   fprintf(stdout, _("   Production Code: %s\n"), MessageBuffer+31);
451   fprintf(stdout, _("   HW: %s\n"), MessageBuffer+39);
452   fprintf(stdout, _("   Firmware: %s\n"), MessageBuffer+44);
453
454   /* These bytes are probably the source of the "Accessory not connected"
455      messages on the phone when trying to emulate NCDS... I hope....
456      UPDATE: of course, now we have the authentication algorithm. */
457   fprintf(stdout, _("   Magic bytes: %02x %02x %02x %02x\n"), MessageBuffer[50], MessageBuffer[51], MessageBuffer[52], MessageBuffer[53]);
458 #endif /* DEBUG */
459
460   MagicBytes[0]=MessageBuffer[50];
461   MagicBytes[1]=MessageBuffer[51];
462   MagicBytes[2]=MessageBuffer[52];
463   MagicBytes[3]=MessageBuffer[53];
464
465   CurrentMagicError=GE_NONE;
466 }
467
468 /* This function provides Nokia authentication protocol.
469
470    This code is written specially for gnokii project by Odinokov Serge.
471    If you have some special requests for Serge just write him to
472    apskaita@post.omnitel.net or serge@takas.lt
473
474    Reimplemented in C by Pavel Janík ml.
475
476    Nokia authentication protocol is used in the communication between Nokia
477    mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software,
478    commercially sold by Nokia Corp.
479
480    The authentication scheme is based on the token send by the phone to the
481    software. The software does it's magic (see the function
482    FB61_GetNokiaAuth()) and returns the result back to the phone. If the
483    result is correct the phone responds with the message "Accessory
484    connected!" displayed on the LCD. Otherwise it will display "Accessory not
485    supported" and some functions will not be available for use.
486
487    The specification of the protocol is not publicly available, no comment. */
488 static void N6110_GetNokiaAuth(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse)
489 {
490
491   int i, j, CRC=0;
492
493   /* This is our temporary working area. */
494
495   unsigned char Temp[16];
496
497   /* Here we put FAC (Final Assembly Code) and serial number into our area. */
498
499   Temp[0]  = Imei[6];
500   Temp[1]  = Imei[7];
501   Temp[2]  = Imei[8];
502   Temp[3]  = Imei[9];
503   Temp[4]  = Imei[10];
504   Temp[5]  = Imei[11];
505   Temp[6]  = Imei[12];
506   Temp[7]  = Imei[13];
507
508   /* And now the TAC (Type Approval Code). */
509
510   Temp[8]  = Imei[2];
511   Temp[9]  = Imei[3];
512   Temp[10] = Imei[4];
513   Temp[11] = Imei[5];
514
515   /* And now we pack magic bytes from the phone. */
516
517   Temp[12] = MagicBytes[0];
518   Temp[13] = MagicBytes[1];
519   Temp[14] = MagicBytes[2];
520   Temp[15] = MagicBytes[3];
521
522   for (i=0; i<=11; i++)
523     if (Temp[i + 1]& 1)
524       Temp[i]<<=1;
525
526   switch (Temp[15] & 0x03) {
527
528   case 1:
529   case 2:
530     j = Temp[13] & 0x07;
531
532     for (i=0; i<=3; i++)
533       Temp[i+j] ^= Temp[i+12];
534
535     break;
536
537   default:
538     j = Temp[14] & 0x07;
539
540     for (i=0; i<=3; i++)
541       Temp[i + j] |= Temp[i + 12];
542   }
543
544   for (i=0; i<=15; i++)
545     CRC ^= Temp[i];
546
547   for (i=0; i<=15; i++) {
548
549     switch (Temp[15 - i] & 0x06) {
550
551     case 0:
552       j = Temp[i] | CRC;
553       break;
554
555     case 2:
556     case 4:
557       j = Temp[i] ^ CRC;
558       break;
559
560     case 6:
561       j = Temp[i] & CRC;
562       break;
563     }
564   
565     if (j == CRC)
566       j = 0x2c;
567
568     if (Temp[i] == 0)
569       j = 0;
570
571     MagicResponse[i] = j;
572
573   }
574 }
575
576 static GSM_Error N6110_Authentication()
577 {
578   unsigned char connect1[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
579   unsigned char connect2[] = {N6110_FRAME_HEADER, 0x20, 0x02};
580   unsigned char connect3[] = {N6110_FRAME_HEADER, 0x0d, 0x01, 0x00, 0x02};
581   unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10};
582   
583   unsigned char magic_connect[] = {N6110_FRAME_HEADER,
584   0x12,
585
586   /* The real magic goes here ... These bytes are filled in with the
587      function N6110_GetNokiaAuth(). */
588
589   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
591
592   /* NOKIA&GNOKII Accessory */
593
594   0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x26, 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x20,
595   0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79,
596   
597   0x00, 0x00, 0x00, 0x00};
598
599   unsigned char req3_55[]  = { N6110_FRAME_HEADER, 0x42,0x05,0x01,
600                                0x07,0xa2,0x88,0x81,0x21,0x55,0x63,0xa8,0x00,0x00,
601                                0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80 };
602   unsigned char req3[]     = { N6110_FRAME_HEADER, 0x42,0x05,0x01,
603                                0x07,0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
604                                0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80 };
605   unsigned char unknown_05[] = {N6110_FRAME_HEADER, 0x05};
606
607 #ifdef DEBUG
608   fprintf(stdout,_("Making authentication!\n"));
609 #endif
610
611   usleep(100); Protocol->SendMessage(7, 0x02, connect1);
612   usleep(100); Protocol->SendMessage(5, 0x02, connect2);
613   usleep(100); Protocol->SendMessage(7, 0x02, connect3);
614       
615   usleep(100); Protocol->SendMessage(sizeof(req3_55), 0x01, req3_55);   /* Lace */
616
617   CurrentMagicError = GE_BUSY;
618
619   usleep(100); Protocol->SendMessage(4, 0x64, connect4);
620
621   usleep(100); Protocol->SendMessage(sizeof(req3_55), 0x01, req3_55);   /* Lace */
622   usleep(100); Protocol->SendMessage(sizeof(req3), 0x01, req3); /* Lace */
623
624   if (NULL_WaitUntil(50,&CurrentMagicError)!=GE_NONE) return GE_TIMEOUT;
625
626   N6110_GetNokiaAuth(Current_IMEI, MagicBytes, magic_connect+4);
627
628   Protocol->SendMessage(45, 0x64, magic_connect);
629
630   usleep(100); Protocol->SendMessage(4, 0x04, unknown_05); /* Lace */
631
632 #ifdef DEBUG
633   fprintf(stdout,_("End of authentication!\n"));
634 #endif
635
636   return GE_NONE;
637 }
638
639 /* Initialise variables and state machine. */
640 GSM_Error N6110_Initialise(char *port_device, char *initlength,
641                           GSM_ConnectionType connection,
642                           void (*rlp_callback)(RLP_F96Frame *frame))
643 {
644   unsigned char init_char = N6110_SYNC_BYTE;
645 #ifndef UCLINUX
646   unsigned char end_init_char = N6110_IR_END_SYNC_BYTE;
647 #endif /* UCLINUX */
648
649   int count;
650   int InitLength;
651   
652   if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
653   {
654     return GE_NOTSUPPORTED;
655   }
656
657   switch (CurrentConnectionType) {
658 #ifndef UCLINUX
659     case GCT_Irda:
660     case GCT_MBUS:
661       /* We don't think about authentication in Irda, because
662          AFAIK there are no phones working over sockets
663          and having authentication. In MBUS it doesn't work */
664       usleep(100);
665
666       if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
667     
668       if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    
669
670       if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;    
671
672       CurrentLinkOK = true;                                 
673       break;
674 #endif /* UCLINUX */
675       
676     case GCT_FBUS:
677 #ifndef UCLINUX
678     case GCT_Infrared:
679     case GCT_Tekram:
680 #endif /* UCLINUX */
681       InitLength = atoi(initlength);
682
683       if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
684         InitLength = 250;       /* This is the usual value, lower may work. */
685       }
686
687 #ifndef UCLINUX
688       if (CurrentConnectionType==GCT_Infrared ||
689           CurrentConnectionType==GCT_Tekram) {
690 #ifdef DEBUG
691         fprintf(stdout,_("Setting infrared for FBUS communication...\n"));
692 #endif
693         device_changespeed(9600);
694       }
695 #endif /* UCLINUX */
696
697 #ifdef DEBUG
698       fprintf(stdout,_("Writing init chars...."));
699 #endif
700
701       /* Initialise link with phone or what have you */
702       /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
703          empirical. */
704       for (count = 0; count < InitLength; count ++) {
705 #ifndef UCLINUX
706         if (CurrentConnectionType!=GCT_Infrared &&
707             CurrentConnectionType!=GCT_Tekram)
708 #endif /* UCLINUX */
709                                         usleep(100);
710         Protocol->WritePhone(1,&init_char);
711       }
712
713 #ifndef UCLINUX
714       if (CurrentConnectionType==GCT_Infrared ||
715           CurrentConnectionType==GCT_Tekram)      {
716         Protocol->WritePhone(1,&end_init_char);
717         usleep(200000);
718       }
719 #endif /* UCLINUX */
720
721 #ifdef DEBUG
722       fprintf(stdout,_("Done\n"));  
723 #endif
724
725 #ifndef UCLINUX
726       if (CurrentConnectionType==GCT_Infrared ||
727           CurrentConnectionType==GCT_Tekram)      {
728         device_changespeed(115200);    
729       }
730 #endif /* UCLINUX */
731
732       N6110_SendStatusRequest();
733     
734       usleep(100);
735
736       if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
737     
738       /* N51xx/61xx have something called authentication.
739          After making it phone display "Accessory connected"
740          and probably give access to some function (I'm not too sure about it !)
741          Anyway, I make it now for N51xx/61xx */
742 #if 1
743       if (GetModelFeature (FN_AUTHENTICATION)!=0)
744 #else
745       if (0/*Lace-hack:GetModelFeature (FN_AUTHENTICATION)!=0*/)
746 #endif
747         {
748         if (N6110_Authentication()!=GE_NONE) return GE_TIMEOUT;
749       } else {        /* No authentication */
750         if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    
751
752         if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;    
753       }
754       
755       break;
756     default:
757 #ifdef DEBUG
758       fprintf(stdout,_("Unknown connection type in n6110.c!\n"));
759 #endif
760       break;
761   }
762
763   return (GE_NONE);
764 }
765
766 /* This function translates GMT_MemoryType to N6110_MEMORY_xx */
767 int N6110_GetMemoryType(GSM_MemoryType memory_type)
768 {
769
770   int result;
771
772   switch (memory_type) {
773
774      case GMT_MT: result = N6110_MEMORY_MT; break;
775      case GMT_ME: result = N6110_MEMORY_ME; break;
776      case GMT_SM: result = N6110_MEMORY_SM; break;
777      case GMT_FD: result = N6110_MEMORY_FD; break;
778      case GMT_ON: result = N6110_MEMORY_ON; break;
779      case GMT_EN: result = N6110_MEMORY_EN; break;
780      case GMT_DC: result = N6110_MEMORY_DC; break;
781      case GMT_RC: result = N6110_MEMORY_RC; break;
782      case GMT_MC: result = N6110_MEMORY_MC; break;
783      default    : result = N6110_MEMORY_XX;
784
785    }
786
787    return (result);
788 }
789
790 #ifndef UCLINUX
791
792 void N6110_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
793
794   switch (MessageBuffer[3]) {
795
796   case 0x02:
797
798 #ifdef DEBUG
799     fprintf(stdout, _("Message: Call divert status received\n"));
800     fprintf(stdout, _("   Divert type: "));
801     switch (MessageBuffer[6]) {
802       case 0x43: fprintf(stdout, _("when busy"));break;
803       case 0x3d: fprintf(stdout, _("when not answered"));break;
804       case 0x3e: fprintf(stdout, _("when phone off or no coverage"));break;
805       case 0x15: fprintf(stdout, _("all types of diverts"));break; //?
806       case 0x02: fprintf(stdout, _("all types of diverts"));break; //?
807       default:   fprintf(stdout, _("unknown %i"),MessageBuffer[6]);break;
808     }
809     fprintf(stdout, _("\n   Calls type : "));
810     if (MessageBuffer[6]==0x02)
811       fprintf(stdout, _("voice, fax & data")); //?
812     else {
813       switch (MessageBuffer[8]) {
814         case 0x0b: fprintf(stdout, _("voice"));break;
815         case 0x0d: fprintf(stdout, _("fax"));break;
816         case 0x19: fprintf(stdout, _("data"));break;
817         default:   fprintf(stdout, _("unknown %i"),MessageBuffer[8]);break;
818       }
819     }
820     fprintf(stdout, _("\n"));     
821     if (MessageBuffer[10]==0x01) {
822       fprintf(stdout, _("   Status     : active\n"));
823       fprintf(stdout, _("   Timeout    : %i seconds\n"),MessageBuffer[45]);
824       fprintf(stdout, _("   Number     : %s\n"),GSM_UnpackSemiOctetNumber(MessageBuffer+12,true));
825     } else {
826       fprintf(stdout, _("   Status     : deactivated\n"));     
827     }
828 #endif /* DEBUG */
829  
830     switch (MessageBuffer[6]) {
831       case 0x43: CurrentCallDivert->DType=GSM_CDV_Busy;break;
832       case 0x3d: CurrentCallDivert->DType=GSM_CDV_NoAnswer;break;
833       case 0x3e: CurrentCallDivert->DType=GSM_CDV_OutOfReach;break;
834       case 0x15: CurrentCallDivert->DType=GSM_CDV_AllTypes;break; //?
835       case 0x02: CurrentCallDivert->DType=GSM_CDV_AllTypes;break; //?
836     }
837
838     if (MessageBuffer[6]==0x02) //?
839       CurrentCallDivert->CType=GSM_CDV_AllCalls;
840     else {
841       switch (MessageBuffer[8]) {
842         case 0x0b: CurrentCallDivert->CType=GSM_CDV_VoiceCalls;break;
843         case 0x0d: CurrentCallDivert->CType=GSM_CDV_FaxCalls;  break;
844         case 0x19: CurrentCallDivert->CType=GSM_CDV_DataCalls; break;
845       }
846     }
847
848     if (MessageBuffer[10]==0x01) {
849       CurrentCallDivert->Enabled=true;
850       CurrentCallDivert->Timeout=MessageBuffer[45];
851       strcpy(CurrentCallDivert->Number,GSM_UnpackSemiOctetNumber(MessageBuffer+12,true));
852     } else {
853       CurrentCallDivert->Enabled=false;
854     }
855
856     CurrentCallDivertError=GE_NONE;
857     break;
858
859   case 0x03:
860 #ifdef DEBUG
861     fprintf(stdout, _("Message: Call divert status receiving error ?\n"));
862 #endif
863     CurrentCallDivertError=GE_UNKNOWN;
864     break;
865   }
866 }
867
868 GSM_Error N6110_CallDivert(GSM_CallDivert *cd)
869 {
870   char req[55] = { N6110_FRAME_HEADER, 0x01,
871                                        0x00, /* operation */
872                                        0x00,
873                                        0x00, /* divert type */
874                                        0x00, /* call type */
875                                        0x00 };
876   GSM_Error error;
877
878   int length = 0x09;
879
880   switch (cd->Operation) {
881     case GSM_CDV_Register:
882     case GSM_CDV_Enable:
883       req[4] = 0x03;
884       req[8] = 0x01;
885       req[29]= GSM_PackSemiOctetNumber(cd->Number, req + 9, false);
886       req[52]= cd->Timeout;
887       length = 55;
888       break;
889     case GSM_CDV_Erasure:
890     case GSM_CDV_Disable:
891       req[4] = 0x04;
892       break;
893     case GSM_CDV_Query:
894       req[4] = 0x05;
895       break;
896     default:
897       return GE_NOTIMPLEMENTED;
898   }
899
900   switch (cd->DType) {
901     case GSM_CDV_AllTypes  : req[6] = 0x15; break;
902     case GSM_CDV_Busy      : req[6] = 0x43; break;
903     case GSM_CDV_NoAnswer  : req[6] = 0x3d; break;
904     case GSM_CDV_OutOfReach: req[6] = 0x3e; break;
905     default:                 return GE_NOTIMPLEMENTED;
906   }
907
908   if ((cd->DType == GSM_CDV_AllTypes) &&
909       (cd->CType == GSM_CDV_AllCalls))
910     req[6] = 0x02;
911
912   switch (cd->CType) {
913     case GSM_CDV_AllCalls  :                break;
914     case GSM_CDV_VoiceCalls: req[7] = 0x0b; break;
915     case GSM_CDV_FaxCalls  : req[7] = 0x0d; break;
916     case GSM_CDV_DataCalls : req[7] = 0x19; break;
917     default:                 return GE_NOTIMPLEMENTED;
918   }
919
920   CurrentCallDivert = cd;
921
922   error=NULL_SendMessageSequence
923     (100, &CurrentCallDivertError, length, 0x06, req);
924
925   CurrentCallDivert = NULL;
926
927   return error;
928 }
929
930 GSM_Error N6110_Tests()
931 {
932   unsigned char buffer[3]={0x00,0x01,0xcf};
933   unsigned char buffer3[8]={0x00,0x01,0xce,0x1d,0xfe,0x23,0x00,0x00};
934   
935   GSM_Error error;
936
937   error=N6110_EnableExtendedCommands(0x01);
938   if (error!=GE_NONE) return error;
939
940   //make almost all tests
941   Protocol->SendMessage(8, 0x40, buffer3);
942
943   while (GSM->Initialise(PortDevice, "50", CurrentConnectionType, CurrentRLP_RXCallback)!=GE_NONE) {};
944
945   sleep(2);
946
947   return NULL_SendMessageSequence
948     (200, &CurrentNetworkInfoError, 3, 0x40, buffer);  
949 }
950
951 void N6110_DisplayTestsInfo(u8 *MessageBuffer) {
952
953   int i;
954
955   CurrentNetworkInfoError=GE_NONE;
956
957   for (i=0;i<MessageBuffer[3];i++) {
958     switch (i) {
959       case 0: fprintf(stdout,_("Unknown(%i)              "),i);break;
960       case 1: fprintf(stdout,_("MCU ROM checksum        "));break;
961       case 2: fprintf(stdout,_("MCU RAM interface       "));break;
962       case 3: fprintf(stdout,_("MCU RAM component       "));break;
963       case 4: fprintf(stdout,_("MCU EEPROM interface    "));break;
964       case 5: fprintf(stdout,_("MCU EEPROM component    "));break;
965       case 6: fprintf(stdout,_("Real Time Clock battery "));break;
966       case 7: fprintf(stdout,_("CCONT interface         "));break;
967       case 8: fprintf(stdout,_("AD converter            "));break;
968       case 9: fprintf(stdout,_("SW Reset                "));break;
969       case 10:fprintf(stdout,_("Power Off               "));break;
970       case 11:fprintf(stdout,_("Security Data           "));break;
971       case 12:fprintf(stdout,_("EEPROM Tune checksum    "));break;
972       case 13:fprintf(stdout,_("PPM checksum            "));break;
973       case 14:fprintf(stdout,_("MCU download DSP        "));break;
974       case 15:fprintf(stdout,_("DSP alive               "));break;
975       case 16:fprintf(stdout,_("COBBA serial            "));break;
976       case 17:fprintf(stdout,_("COBBA paraller          "));break;
977       case 18:fprintf(stdout,_("EEPROM security checksum"));break;
978       case 19:fprintf(stdout,_("PPM validity            "));break;
979       case 20:fprintf(stdout,_("Warranty state          "));break;
980       case 21:fprintf(stdout,_("Simlock check           "));break;
981       case 22:fprintf(stdout,_("IMEI check?             "));break;//from PC-Locals.is OK?
982       default:fprintf(stdout,_("Unknown(%i)             "),i);break;
983     }
984     switch (MessageBuffer[4+i]) {
985       case 0:   fprintf(stdout,_(" : done, result OK"));break;
986       case 0xff:fprintf(stdout,_(" : not done, result unknown"));break;
987       case 254: fprintf(stdout,_(" : done, result NOT OK"));break;
988       default:  fprintf(stdout,_(" : result unknown(%i)"),MessageBuffer[4+i]);break;
989     }
990     fprintf(stdout,_("\n"));
991   }
992 }
993
994 void N6110_ReplySimlockInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
995
996   int i, j;
997   
998   char uni[100];
999     
1000 #ifdef DEBUG
1001   fprintf(stdout, _("Message: Simlock info received\n"));
1002
1003   j=0;
1004   for (i=0; i < 12; i++)
1005   {
1006     if (j<24) {
1007       fprintf(stdout,_("%c"), ('0' + (MessageBuffer[9+i] >> 4)));
1008       j++;
1009     }
1010     if (j==5 || j==15) fprintf(stdout, _("\n"));
1011     if (j!=15) {
1012       if (j<24) {
1013         fprintf(stdout,_("%c"), ('0' + (MessageBuffer[9+i] & 0x0f)));
1014         j++;
1015       }
1016     } else j++;
1017     if (j==20 || j==24) fprintf(stdout, _("\n"));
1018   }
1019       
1020   if ((MessageBuffer[6] & 1) == 1) fprintf(stdout,_("lock 1 closed\n"));
1021   if ((MessageBuffer[6] & 2) == 2) fprintf(stdout,_("lock 2 closed\n"));
1022   if ((MessageBuffer[6] & 4) == 4) fprintf(stdout,_("lock 3 closed\n"));
1023   if ((MessageBuffer[6] & 8) == 8) fprintf(stdout,_("lock 4 closed\n"));
1024
1025   /* I'm not sure here at all */
1026   if ((MessageBuffer[5] & 1) == 1) fprintf(stdout,_("lock 1 - user\n"));
1027   if ((MessageBuffer[5] & 2) == 2) fprintf(stdout,_("lock 2 - user\n"));
1028   if ((MessageBuffer[5] & 4) == 4) fprintf(stdout,_("lock 3 - user\n"));
1029   if ((MessageBuffer[5] & 8) == 8) fprintf(stdout,_("lock 4 - user\n"));
1030
1031   fprintf(stdout,_("counter for lock1: %i\n"),MessageBuffer[21]);
1032   fprintf(stdout,_("counter for lock2: %i\n"),MessageBuffer[22]);
1033   fprintf(stdout,_("counter for lock3: %i\n"),MessageBuffer[23]);
1034   fprintf(stdout,_("counter for lock4: %i\n"),MessageBuffer[24]);
1035
1036 #endif
1037
1038   j=0;
1039   for (i=0; i < 12; i++)
1040   {
1041     if (j<24) {
1042       uni[j]='0' + (MessageBuffer[9+i] >> 4);
1043       j++;
1044     }
1045     if (j!=15) {
1046       if (j<24) {
1047         uni[j]='0' + (MessageBuffer[9+i] & 0x0f);
1048         j++;
1049       }
1050     } else j++;
1051   }
1052
1053   strncpy(CurrentSimLock->simlocks[0].data,uni,5);
1054   CurrentSimLock->simlocks[0].data[5]=0;
1055   strncpy(CurrentSimLock->simlocks[3].data,uni+5,10);
1056   CurrentSimLock->simlocks[3].data[10]=0;
1057   strncpy(CurrentSimLock->simlocks[1].data,uni+16,4);
1058   CurrentSimLock->simlocks[1].data[4]=0;
1059   strncpy(CurrentSimLock->simlocks[2].data,uni+20,4);
1060   CurrentSimLock->simlocks[2].data[4]=0;                                    
1061
1062   CurrentSimLock->simlocks[0].enabled=((MessageBuffer[6] & 1) == 1);
1063   CurrentSimLock->simlocks[1].enabled=((MessageBuffer[6] & 2) == 2);
1064   CurrentSimLock->simlocks[2].enabled=((MessageBuffer[6] & 4) == 4);
1065   CurrentSimLock->simlocks[3].enabled=((MessageBuffer[6] & 8) == 8);
1066
1067   CurrentSimLock->simlocks[0].factory=((MessageBuffer[5] & 1) != 1);
1068   CurrentSimLock->simlocks[1].factory=((MessageBuffer[5] & 2) != 2);
1069   CurrentSimLock->simlocks[2].factory=((MessageBuffer[5] & 4) != 4);
1070   CurrentSimLock->simlocks[3].factory=((MessageBuffer[5] & 8) != 8);
1071
1072   CurrentSimLock->simlocks[0].counter=MessageBuffer[21];
1073   CurrentSimLock->simlocks[1].counter=MessageBuffer[22];
1074   CurrentSimLock->simlocks[2].counter=MessageBuffer[23];
1075   CurrentSimLock->simlocks[3].counter=MessageBuffer[24];
1076
1077   CurrentSimlockInfoError=GE_NONE;
1078 }
1079
1080 GSM_Error N6110_SimlockInfo(GSM_AllSimlocks *siml)
1081 {
1082   GSM_Error error;
1083   unsigned char req[] = {0x00,0x01,0x8a,0x00};
1084   error=N6110_EnableExtendedCommands(0x01);
1085   if (error!=GE_NONE) return error;
1086
1087   CurrentSimLock=siml;
1088  
1089   return NULL_SendMessageSequence (50, &CurrentSimlockInfoError, 4, 0x40, req);  
1090 }
1091
1092 void N6110_ReplyResetPhoneSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1093
1094 #ifdef DEBUG
1095   fprintf(stdout, _("Message: Resetting phone settings\n"));
1096 #endif /* DEBUG */
1097
1098   CurrentResetPhoneSettingsError=GE_NONE;
1099 }
1100
1101 GSM_Error N6110_ResetPhoneSettings()
1102 {
1103   GSM_Error error;
1104   unsigned char req[] = {0x00,0x01,0x65,0x08,0x00};  
1105   error=N6110_EnableExtendedCommands(0x01);
1106   if (error!=GE_NONE) return error;
1107
1108   return NULL_SendMessageSequence
1109     (50, &CurrentResetPhoneSettingsError, 5, 0x40, req);  
1110 }
1111
1112 #endif /* UCLINUX */
1113
1114 GSM_Error N6110_GetManufacturer(char *manufacturer)
1115 {
1116         strcpy (manufacturer, "Nokia");
1117         return (GE_NONE);
1118 }
1119
1120 #ifndef UCLINUX
1121
1122 GSM_Error N6110_GetVoiceMailbox ( GSM_PhonebookEntry *entry)
1123 {
1124   unsigned char req[] = {N6110_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00};
1125
1126   GSM_Error error;
1127   
1128   CurrentPhonebookEntry = entry;
1129
1130   req[4] = N6110_MEMORY_VOICE;
1131   req[5] = 0x00; /* Location - isn't important, but... */
1132
1133   error=NULL_SendMessageSequence
1134     (20, &CurrentPhonebookError, 7, 0x03, req);
1135     
1136   CurrentPhonebookEntry = NULL;
1137   
1138   return error;
1139 }
1140
1141 void N6110_ReplyGetOperatorName(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1142
1143   int i, count;
1144   
1145   GSM_Bitmap NullBitmap;
1146
1147   DecodeNetworkCode(MessageBuffer+5, NullBitmap.netcode);
1148   
1149   count=8;
1150
1151 #ifdef DEBUG
1152   fprintf(stdout, _("Message: Info about downloaded operator name received: %s network (for gnokii \"%s\", for phone \""),
1153           NullBitmap.netcode,
1154           GSM_GetNetworkName(NullBitmap.netcode));      
1155 #endif
1156       
1157   i=count;
1158   while (MessageBuffer[count]!=0) {
1159 #ifdef DEBUG
1160     fprintf(stdout,_("%c"),MessageBuffer[count]);
1161 #endif
1162     count++;
1163   }
1164       
1165  strcpy(CurrentGetOperatorNameNetwork->Code, NullBitmap.netcode);
1166  strncpy(CurrentGetOperatorNameNetwork->Name, MessageBuffer+i,count-i+1);
1167
1168 #ifdef DEBUG
1169   fprintf(stdout,_("\")\n"));
1170 #endif
1171           
1172   CurrentGetOperatorNameError=GE_NONE;
1173 }
1174
1175 GSM_Error N6110_GetOperatorName (GSM_Network *operator)
1176 {
1177   unsigned char req[] = { 0x00,0x01,0x8c,0x00};
1178
1179   GSM_Error error;
1180
1181   error=N6110_EnableExtendedCommands(0x01);
1182   if (error!=GE_NONE) return error;
1183
1184   CurrentGetOperatorNameNetwork = operator;
1185
1186   error=NULL_SendMessageSequence
1187     (20, &CurrentGetOperatorNameError, 4, 0x40, req);
1188
1189   CurrentGetOperatorNameNetwork = NULL;
1190   
1191   return error;
1192 }
1193
1194 void N6110_ReplySetOperatorName(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1195     
1196 #ifdef DEBUG
1197   fprintf(stdout, _("Message: Downloaded operator name changed\n"));
1198 #endif    
1199
1200   CurrentSetOperatorNameError=GE_NONE;      
1201 }
1202
1203 GSM_Error N6110_SetOperatorName (GSM_Network *operator)
1204 {
1205   unsigned char req[256] = { 0x00,0x01,0x8b,0x00,
1206                              0x00,0x00, /* MCC */
1207                              0x00};     /* MNC */
1208
1209   GSM_Error error;
1210
1211   error=N6110_EnableExtendedCommands(0x01);
1212   if (error!=GE_NONE) return error;
1213
1214   EncodeNetworkCode(req+4,operator->Code);
1215
1216   strncpy(req+7,operator->Name,200);
1217     
1218   return NULL_SendMessageSequence
1219     (20, &CurrentSetOperatorNameError, 8+strlen(operator->Name), 0x40, req);
1220 }
1221
1222 #endif /* UCLINUX */
1223
1224 static void N6110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1225
1226   switch (MessageBuffer[3]) {
1227
1228   case 0x08:
1229
1230 #ifdef DEBUG
1231     fprintf(stdout, _("Message: Memory status received:\n"));
1232
1233     fprintf(stdout, _("   Memory Type: %s\n"), N6110_MemoryType_String[MessageBuffer[4]]);
1234     fprintf(stdout, _("   Used: %d\n"), MessageBuffer[6]);
1235     fprintf(stdout, _("   Free: %d\n"), MessageBuffer[5]);
1236 #endif /* DEBUG */
1237
1238     CurrentMemoryStatus->Used = MessageBuffer[6];
1239     CurrentMemoryStatus->Free = MessageBuffer[5];
1240     CurrentMemoryStatusError = GE_NONE;
1241
1242     break;
1243
1244   case 0x09:
1245
1246 #ifdef DEBUG
1247     switch (MessageBuffer[4]) {
1248       case 0x6f:
1249         fprintf(stdout, _("Message: Memory status error, phone is probably powered off.\n"));break;
1250       case 0x7d:
1251         fprintf(stdout, _("Message: Memory status error, memory type not supported by phone model.\n"));break;
1252       case 0x8d:
1253         fprintf(stdout, _("Message: Memory status error, waiting for security code.\n"));break;
1254       default:
1255         fprintf(stdout, _("Message: Unknown Memory status error, subtype (MessageBuffer[4]) = %02x\n"),MessageBuffer[4]);break;
1256     }
1257 #endif
1258
1259     switch (MessageBuffer[4]) {
1260       case 0x6f:CurrentMemoryStatusError = GE_TIMEOUT;break;
1261       case 0x7d:CurrentMemoryStatusError = GE_INTERNALERROR;break;
1262       case 0x8d:CurrentMemoryStatusError = GE_INVALIDSECURITYCODE;break;
1263       default:break;
1264     }
1265
1266     break;
1267
1268   }
1269 }
1270
1271 /* This function is used to get storage status from the phone. It currently
1272    supports two different memory areas - internal and SIM. */
1273 GSM_Error N6110_GetMemoryStatus(GSM_MemoryStatus *Status)
1274 {
1275   unsigned char req[] = { N6110_FRAME_HEADER,
1276                           0x07, /* MemoryStatus request */
1277                           0x00  /* MemoryType */
1278                         };
1279
1280   GSM_Error error;
1281   
1282   CurrentMemoryStatus = Status;
1283
1284   req[4] = N6110_GetMemoryType(Status->MemoryType);
1285
1286   error=NULL_SendMessageSequence
1287     (20, &CurrentMemoryStatusError, 5, 0x03, req);
1288
1289   CurrentMemoryStatus = NULL;
1290
1291   return error;
1292 }
1293
1294 #ifndef UCLINUX
1295
1296 void N6110_ReplyGetNetworkInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1297
1298   GSM_NetworkInfo NullNetworkInfo;
1299   
1300   /* Make sure we are expecting NetworkInfo frame */
1301   if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
1302 #ifdef DEBUG
1303     fprintf(stdout, _("Message: Network informations:\n"));
1304 #endif
1305   } else {
1306 #ifdef DEBUG
1307     fprintf(stdout, _("Message: Network informations not requested, but received:\n"));
1308 #endif
1309   }
1310       
1311   sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4);
1312
1313   sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
1314
1315   sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
1316
1317 #ifdef DEBUG
1318   fprintf(stdout, _("   CellID: %s\n"), NullNetworkInfo.CellID);
1319   fprintf(stdout, _("   LAC: %s\n"), NullNetworkInfo.LAC);
1320   fprintf(stdout, _("   Network code: %s\n"), NullNetworkInfo.NetworkCode);
1321   fprintf(stdout, _("   Network name: %s (%s)\n"),
1322                      GSM_GetNetworkName(NullNetworkInfo.NetworkCode),
1323                      GSM_GetCountryName(NullNetworkInfo.NetworkCode));
1324   fprintf(stdout, _("   Status: "));
1325
1326   switch (MessageBuffer[8]) {
1327     case 0x01: fprintf(stdout, _("home network selected")); break;
1328     case 0x02: fprintf(stdout, _("roaming network")); break;
1329     case 0x03: fprintf(stdout, _("requesting network")); break;
1330     case 0x04: fprintf(stdout, _("not registered in the network")); break;
1331     default: fprintf(stdout, _("unknown"));
1332   }
1333
1334   fprintf(stdout, "\n");
1335
1336   fprintf(stdout, _("   Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic"));
1337 #endif /* DEBUG */
1338
1339   /* Make sure we are expecting NetworkInfo frame */
1340   if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY)
1341     *CurrentNetworkInfo=NullNetworkInfo;
1342
1343   CurrentNetworkInfoError = GE_NONE;      
1344 }
1345
1346 GSM_Error N6110_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
1347 {
1348   unsigned char req[] = { N6110_FRAME_HEADER,
1349                           0x70
1350                         };
1351
1352   GSM_Error error;
1353   
1354   CurrentNetworkInfo = NetworkInfo;
1355   
1356   error=NULL_SendMessageSequence
1357     (20, &CurrentNetworkInfoError, 4, 0x0a, req);
1358
1359   CurrentNetworkInfo = NULL;
1360
1361   return error;
1362 }
1363
1364 void N6110_ReplyGetProductProfileSetting(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1365
1366   int i;
1367   
1368 #ifdef DEBUG
1369   fprintf(stdout, _("Message: Product Profile Settings received -"));
1370   for (i=0;i<4;i++) fprintf(stdout, _(" %02x"),MessageBuffer[3+i]);
1371   fprintf(stdout, _("\n"));  
1372 #endif
1373
1374   for (i=0;i<4;i++) CurrentPPS[i]=MessageBuffer[3+i];
1375
1376   CurrentProductProfileSettingsError=GE_NONE;      
1377 }
1378
1379 GSM_Error N6110_GetProductProfileSetting (GSM_PPS *PPS)
1380 {
1381   unsigned char req[] = { 0x00, 0x01,0x6a };
1382   
1383   int i,j;
1384
1385   GSM_Error error;
1386
1387   error=N6110_EnableExtendedCommands(0x01);
1388   if (error!=GE_NONE) return error;
1389
1390   error=NULL_SendMessageSequence
1391     (20, &CurrentProductProfileSettingsError, 3, 0x40, req);
1392   if (error!=GE_NONE) return error;    
1393   
1394   switch (PPS->Name) {
1395     case PPS_ALS      : PPS->bool_value=(CurrentPPS[1]&32); break;
1396     case PPS_GamesMenu: PPS->bool_value=(CurrentPPS[3]&64); break;
1397     case PPS_HRData   : PPS->bool_value=(CurrentPPS[0]&64); break;
1398     case PPS_14400Data: PPS->bool_value=(CurrentPPS[0]&128);break;
1399     case PPS_EFR      : PPS->int_value =(CurrentPPS[0]&1)    +(CurrentPPS[0]&2);    break;
1400     case PPS_FR       : PPS->int_value =(CurrentPPS[0]&16)/16+(CurrentPPS[0]&32)/16;break;
1401     case PPS_HR       : PPS->int_value =(CurrentPPS[0]&4)/4  +(CurrentPPS[0]&8)/4;  break;
1402     case PPS_VibraMenu: PPS->bool_value=(CurrentPPS[4]&64); break;
1403     case PPS_LCDContrast:
1404          PPS->int_value=0;
1405          j=1;
1406          for (i=0;i<5;i++) {
1407            if (CurrentPPS[3]&j) PPS->int_value=PPS->int_value+j;
1408            j=j*2;
1409          }
1410          PPS->int_value=PPS->int_value*100/32;
1411          break;
1412
1413   }
1414   
1415   return (GE_NONE);
1416 }
1417
1418 void N6110_ReplySetProductProfileSetting(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1419
1420 #ifdef DEBUG
1421   int i;
1422   
1423   fprintf(stdout, _("Message: Product Profile Settings set to"));
1424   for (i=0;i<4;i++) fprintf(stdout, _(" %02x"),CurrentPPS[i]);
1425   fprintf(stdout, _("\n"));  
1426 #endif
1427      
1428   CurrentProductProfileSettingsError=GE_NONE;     
1429 }
1430
1431 GSM_Error N6110_SetProductProfileSetting (GSM_PPS *PPS)
1432 {
1433   unsigned char req[] = { 0x00, 0x01,0x6b, 
1434                           0x00, 0x00, 0x00, 0x00 }; /* bytes with Product Profile Setings */
1435   unsigned char settings[32];
1436   
1437   GSM_PPS OldPPS;
1438   
1439   int i,j,z;
1440   
1441   GSM_Error error;
1442
1443   error=N6110_EnableExtendedCommands(0x01);
1444   if (error!=GE_NONE) return error;
1445   
1446   OldPPS.Name=PPS_ALS;
1447   error=N6110_GetProductProfileSetting(&OldPPS);
1448   if (error!=GE_NONE) return error;
1449   
1450   j=128;z=0;
1451   for (i=0;i<32;i++) {
1452     if (CurrentPPS[z]&j)
1453       settings[i]='1';
1454     else
1455       settings[i]='0';    
1456     if (j==1) {
1457       j=128;
1458       z++;
1459     } else j=j/2;
1460   }
1461   
1462 #ifdef DEBUG
1463   fprintf(stdout,_("Current settings: "));
1464   for (i=0;i<32;i++) {
1465     fprintf(stdout,_("%c"),settings[i]);    
1466   }
1467   fprintf(stdout,_("\n"));
1468 #endif
1469
1470   switch (PPS->Name) {
1471     case PPS_ALS      :settings[10]=PPS->bool_value?'1':'0';break;
1472     case PPS_HRData   :settings[ 5]=PPS->bool_value?'1':'0';break;
1473     case PPS_14400Data:settings[ 6]=PPS->bool_value?'1':'0';break;
1474     default           :break;
1475   }
1476     
1477   j=128;z=0;
1478   for (i=0;i<32;i++) {
1479     if (settings[i]=='1') req[z+3]=req[z+3]+j;
1480     if (j==1) {
1481       j=128;
1482       z++;
1483     } else j=j/2;
1484   }  
1485
1486 #ifdef DEBUG
1487   fprintf(stdout,_("Current settings: "));
1488   for (i=0;i<4;i++) {
1489     fprintf(stdout,_("%i "),req[i+3]);    
1490   }
1491   fprintf(stdout,_("\n"));
1492 #endif
1493
1494   for (i=0;i<4;i++) {
1495    CurrentPPS[i]=req[i+3];    
1496   }
1497
1498   return NULL_SendMessageSequence
1499     (20, &CurrentProductProfileSettingsError, 7, 0x40, req);
1500 }
1501
1502 void N6110_ReplyPressKey(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1503
1504     if (MessageBuffer[4]==CurrentPressKeyEvent) CurrentPressKeyError=GE_NONE;
1505                                            else CurrentPressKeyError=GE_UNKNOWN; /* MessageBuffer[4] = 0x05 */
1506 #ifdef DEBUG
1507     fprintf(stdout, _("Message: Result of key "));
1508     switch (MessageBuffer[4])
1509     {
1510       case PRESSPHONEKEY:   fprintf(stdout, _("press OK\n"));break;
1511       case RELEASEPHONEKEY: fprintf(stdout, _("release OK\n"));break;
1512       default:              fprintf(stdout, _("press or release - error\n"));break;
1513     }
1514 #endif /* DEBUG */
1515 }
1516
1517 GSM_Error N6110_PressKey(int key, int event)
1518 {
1519   unsigned char req[] = {N6110_FRAME_HEADER, 0x42, 0x01, 0x00, 0x01};
1520   
1521   req[4]=event; /* if we press or release key */
1522   req[5]=key;
1523   
1524   CurrentPressKeyEvent=event;
1525   
1526   return NULL_SendMessageSequence
1527     (10, &CurrentPressKeyError, 7, 0x0c, req);
1528 }
1529
1530 void N6110_ReplyDisplayOutput(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1531
1532   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
1533   char model[64];
1534
1535   int i, j;
1536
1537   char uni[100];
1538     
1539   switch(MessageBuffer[3]) {
1540
1541   /* Phone sends displayed texts */
1542   case 0x50:
1543     NewX=MessageBuffer[6];
1544     NewY=MessageBuffer[5];
1545
1546     DecodeUnicode (uni, MessageBuffer+8, MessageBuffer[7]);
1547
1548 #ifdef DEBUG
1549     fprintf(stdout, _("New displayed text (%i %i): \"%s\"\n"),NewX,NewY,uni);      
1550 #endif /* DEBUG */
1551
1552     while (N6110_GetModel(model)  != GE_NONE)
1553       sleep(1);
1554
1555     /* With these rules it works almost excellent with my N5110 */
1556     /* I don't have general rule :-(, that's why you must experiment */
1557     /* with your phone. Nokia could make it better. MW */
1558     /* It's almost OK for N5110*/
1559     /* FIX ME: it will be the same for N5130 and 3210 too*/
1560     if (!strcmp(model,"NSE-1"))
1561     {
1562       /* OldX==1000 means - it's first time */
1563       if (OldX==1000) {
1564       
1565         /* Clean table */
1566         for (i=0;i<5+1;i++) {
1567           for (j=0;j<27+1;j++) {PhoneScreen[i][j]=' ';}
1568       }
1569       OldX=0;
1570     }
1571
1572     if ((OldX==0 && OldY==31 && NewX==29 && NewY==46) ||
1573         (OldX==0 && OldY==13 && NewX==23 && NewY==46)) {
1574       /* Clean the line with current text */
1575       for (j=0;j<27+1;j++) {PhoneScreen[NewY/(47/5)][j]=' ';}
1576       
1577       /* Inserts text into table */
1578       for (i=0; i<MessageBuffer[7];i++) {       
1579         PhoneScreen[NewY/(47/5)][NewX/(84/27)+i]=uni[i];
1580       }
1581
1582     }
1583
1584     if ((OldX==0 && OldY==21 && NewX==0 && NewY==10) ||
1585         (OldX==0 && OldY==10 && NewX==35 && NewY==46)) {
1586     } else {
1587       if ((OldX!=0 && NewX==0 && NewY!=6) ||
1588           (OldX==0 && NewX!=0 && OldY!=13 && OldY!=22) ||
1589           (OldX==0 && NewX==0 && NewY<OldY && (NewY!=13 || OldY!=26)) ||
1590           (OldY==5 && NewY!=5) ||
1591           (OldX==0 && OldY==13 && NewX==23 && NewY==46)) {
1592
1593         /* Writes "old" screen */
1594         for (i=0;i<5+1;i++) {
1595           for (j=0;j<27+1;j++) {fprintf(stdout,_("%c"),PhoneScreen[i][j]);}
1596             fprintf(stdout,_("\n"));
1597           }
1598         
1599           /* Clean table */
1600           for (i=0;i<5+1;i++) {
1601             for (j=0;j<27+1;j++) {PhoneScreen[i][j]=' ';}
1602           }
1603         }
1604       }
1605       
1606       /* Clean the line with current text */
1607       for (j=0;j<27+1;j++) {PhoneScreen[NewY/(47/5)][j]=' ';}
1608       
1609       /* Inserts text into table */
1610       for (i=0; i<MessageBuffer[7];i++) {       
1611         PhoneScreen[NewY/(47/5)][NewX/(84/27)+i]=uni[i];
1612       }
1613       
1614       OldY=NewY;
1615       OldX=NewX;
1616     } else {
1617 #ifndef DEBUG
1618       fprintf(stdout, _("%s\n"),uni);      
1619 #endif
1620     }
1621
1622     break;
1623  
1624   case 0x54:
1625       
1626     if (MessageBuffer[4]==1)
1627     {
1628       
1629 #ifdef DEBUG
1630       fprintf(stdout, _("Display output successfully disabled/enabled.\n"));
1631 #endif /* DEBUG */
1632
1633       CurrentDisplayOutputError=GE_NONE;
1634     }
1635        
1636     break;
1637   }
1638 }
1639
1640 GSM_Error SetDisplayOutput(unsigned char state)
1641 {
1642   unsigned char req[] = { N6110_FRAME_HEADER,
1643                           0x53, 0x00};
1644
1645   req[4]=state;
1646   
1647   return NULL_SendMessageSequence
1648     (30, &CurrentDisplayOutputError, 5, 0x0d, req);
1649 }
1650
1651 GSM_Error N6110_EnableDisplayOutput()
1652 {
1653   return SetDisplayOutput(0x01);
1654 }
1655  
1656 GSM_Error N6110_DisableDisplayOutput()
1657 {
1658   return SetDisplayOutput(0x02);
1659 }
1660
1661 /* If it is interesting for somebody: we can use 0x40 msg for it
1662    and it will work for all phones. See n6110.txt for details */
1663 GSM_Error N6110_AnswerCall(char s)
1664 {
1665         unsigned char req0[] = { N6110_FRAME_HEADER, 0x42,0x05,0x01,0x07,                                0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
1666                             0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80};
1667         unsigned char req[] = { N6110_FRAME_HEADER, 0x06, 0x00, 0x00};
1668
1669         req[4]=s;
1670
1671 #ifdef DEBUG
1672         fprintf(stdout,_("Answering call %d\n\r"),s);
1673 #endif
1674
1675         Protocol->SendMessage(sizeof(req0), 0x01, req0);
1676         sleep(1);
1677
1678         return NULL_SendMessageSequence
1679                 (20, &CurrentMagicError, sizeof(req) , 0x01, req);
1680 }
1681
1682 void N6110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1683
1684   switch (MessageBuffer[3]) {
1685
1686   /* Profile feature */
1687   case 0x14:   
1688
1689     switch(GetModelFeature (FN_PROFILES)) {
1690       case F_PROF33:
1691         switch (MessageBuffer[6]) {
1692           case 0x00: CurrentProfile->KeypadTone  = MessageBuffer[8]; break;
1693           case 0x01: CurrentProfile->CallAlert   = MessageBuffer[8]; break;
1694           case 0x02: CurrentProfile->Ringtone    = MessageBuffer[8]; break;
1695           case 0x03: CurrentProfile->Volume      = MessageBuffer[8]; break;
1696           case 0x04: CurrentProfile->MessageTone = MessageBuffer[8]; break;
1697           case 0x05: CurrentProfile->Vibration   = MessageBuffer[8]; break;
1698           case 0x06: CurrentProfile->WarningTone = MessageBuffer[8]; break;
1699           case 0x07: CurrentProfile->ScreenSaver = MessageBuffer[8]; break;       
1700           default:
1701 #ifdef DEBUG
1702             fprintf(stdout,_("feature %i = value %i\n\n"),MessageBuffer[6],MessageBuffer[8]);
1703 #endif
1704             break;
1705         }
1706         break;
1707       default:
1708         switch (MessageBuffer[6]) {
1709           case 0x00: CurrentProfile->KeypadTone      = MessageBuffer[8];break;
1710           case 0x01: CurrentProfile->Lights          = MessageBuffer[8];break;
1711           case 0x02: CurrentProfile->CallAlert       = MessageBuffer[8];break;
1712           case 0x03: CurrentProfile->Ringtone        = MessageBuffer[8];break;
1713           case 0x04: CurrentProfile->Volume          = MessageBuffer[8];break;
1714           case 0x05: CurrentProfile->MessageTone     = MessageBuffer[8];break;
1715           case 0x06: CurrentProfile->Vibration       = MessageBuffer[8];break;
1716           case 0x07: CurrentProfile->WarningTone     = MessageBuffer[8];break;
1717           case 0x08: CurrentProfile->CallerGroups    = MessageBuffer[8];break;
1718           case 0x09: CurrentProfile->AutomaticAnswer = MessageBuffer[8];break;
1719           default:
1720 #ifdef DEBUG
1721             fprintf(stdout,_("feature %i = value %i\n\n"),MessageBuffer[6],MessageBuffer[8]);
1722 #endif
1723             break;
1724         }
1725         break;
1726     }
1727
1728     CurrentProfileError = GE_NONE;
1729     break;
1730
1731   /* Incoming profile name */
1732   case 0x1b:   
1733
1734     if (MessageBuffer[9] == 0x00) {
1735       CurrentProfile->DefaultName=MessageBuffer[8];
1736     } else {
1737       CurrentProfile->DefaultName=-1;      
1738         
1739       /* Here name is in Unicode */
1740       if (GetModelFeature (FN_PROFILES)==F_PROF33) {
1741         DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]/2);
1742       } else {
1743         /* ...here not */
1744         sprintf(CurrentProfile->Name, MessageBuffer + 10, MessageBuffer[9]);
1745         CurrentProfile->Name[MessageBuffer[9]] = '\0';
1746       }
1747     }
1748
1749     CurrentProfileError = GE_NONE;
1750     break;
1751
1752   }
1753 }
1754
1755 /* Needs SIM card with PIN in phone */
1756 GSM_Error N6110_GetProfile(GSM_Profile *Profile)
1757 {
1758   int i;
1759   
1760   unsigned char name_req[] = { N6110_FRAME_HEADER, 0x1a, 0x00};
1761   unsigned char feat_req[] = { N6110_FRAME_HEADER, 0x13, 0x01, 0x00, 0x00};
1762
1763   GSM_Error error;
1764   
1765   CurrentProfile = Profile;
1766
1767   /* When after sending all frames feature==253, it means, that it is not
1768      supported */
1769   CurrentProfile->KeypadTone=253;
1770   CurrentProfile->Lights=253;    
1771   CurrentProfile->CallAlert=253; 
1772   CurrentProfile->Ringtone=253;  
1773   CurrentProfile->Volume=253;    
1774   CurrentProfile->MessageTone=253;
1775   CurrentProfile->WarningTone=253;
1776   CurrentProfile->Vibration=253;  
1777   CurrentProfile->CallerGroups=253;
1778   CurrentProfile->ScreenSaver=253; 
1779   CurrentProfile->AutomaticAnswer=253;
1780
1781   name_req[4] = Profile->Number;
1782
1783   error=NULL_SendMessageSequence
1784     (20, &CurrentProfileError, 5, 0x05, name_req);
1785   if (error!=GE_NONE) return error;
1786
1787   for (i = 0x00; i <= 0x09; i++) {
1788
1789     feat_req[5] = Profile->Number;
1790     
1791     feat_req[6] = i;
1792
1793     error=NULL_SendMessageSequence
1794       (20, &CurrentProfileError, 7, 0x05, feat_req);
1795     if (error!=GE_NONE) return error;
1796   }
1797
1798   if (Profile->DefaultName > -1)
1799   {
1800     switch(GetModelFeature (FN_PROFILES)) {
1801       case F_PROF33:
1802         switch (Profile->DefaultName) {
1803           case 0x00: sprintf(Profile->Name, "General");break;
1804           case 0x01: sprintf(Profile->Name, "Silent");break;
1805           case 0x02: sprintf(Profile->Name, "Descreet");break;
1806           case 0x03: sprintf(Profile->Name, "Loud");break;
1807           case 0x04: sprintf(Profile->Name, "My style");break;
1808           case 0x05: Profile->Name[0]=0;break;
1809           default  : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break;
1810         }
1811         break;
1812       case F_PROF51:
1813         switch (Profile->DefaultName) {
1814           case 0x00: sprintf(Profile->Name, "Personal");break;
1815           case 0x01: sprintf(Profile->Name, "Car");break;
1816           case 0x02: sprintf(Profile->Name, "Headset");break;
1817           default  : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break;
1818         }
1819         break;
1820       case F_PROF61:
1821         switch (Profile->DefaultName) {
1822           case 0x00: sprintf(Profile->Name, "General");break;
1823           case 0x01: sprintf(Profile->Name, "Silent");break;
1824           case 0x02: sprintf(Profile->Name, "Meeting");break;
1825           case 0x03: sprintf(Profile->Name, "Outdoor");break;
1826           case 0x04: sprintf(Profile->Name, "Pager");break;
1827           case 0x05: sprintf(Profile->Name, "Car");break;
1828           case 0x06: sprintf(Profile->Name, "Headset");break;
1829           default  : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break;
1830         }
1831         break;
1832     }
1833   }
1834   
1835   return (GE_NONE);
1836
1837 }
1838
1839 void N6110_ReplySetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1840
1841   switch (MessageBuffer[3]) {
1842
1843   /* Profile feature change result */
1844   case 0x11:   
1845 #ifdef DEBUG
1846     fprintf(stdout, _("Message: Profile feature change result.\n"));
1847 #endif /* DEBUG */
1848     CurrentProfileError = GE_NONE;
1849     break;
1850
1851   /* Profile name set result */
1852   case 0x1d:   
1853 #ifdef DEBUG
1854     fprintf(stdout, _("Message: Profile name change result.\n"));
1855 #endif /* DEBUG */
1856     CurrentProfileError = GE_NONE;
1857     break;
1858
1859   }
1860 }
1861
1862 GSM_Error N6110_SetProfileFeature(u8 profile, u8 feature, u8 value)
1863 {
1864   unsigned char feat_req[] = { N6110_FRAME_HEADER, 0x10, 0x01,
1865                                0x00, 0x00, 0x00};
1866
1867   feat_req[5]=profile;
1868   feat_req[6]=feature;
1869   feat_req[7]=value;
1870
1871   return NULL_SendMessageSequence
1872     (20, &CurrentProfileError, 8, 0x05, feat_req);
1873 }
1874
1875 GSM_Error N6110_SetProfile(GSM_Profile *Profile)
1876 {
1877   int i,value;
1878
1879   unsigned char name_req[40] = { N6110_FRAME_HEADER, 0x1c, 0x01, 0x03,
1880                                  0x00, 0x00, 0x00};
1881
1882   GSM_Error error;
1883   
1884   name_req[7] = Profile->Number;
1885   name_req[8] = strlen(Profile->Name);
1886   name_req[6] = name_req[8] + 2;
1887
1888   for (i = 0; i < name_req[8]; i++)
1889     name_req[9 + i] = Profile->Name[i];
1890
1891   error=NULL_SendMessageSequence
1892     (20, &CurrentProfileError, name_req[8] + 9, 0x05, name_req);
1893   if (error!=GE_NONE) return error;
1894
1895   for (i = 0x00; i <= 0x09; i++) {
1896
1897     switch (i) {
1898       case 0x00: value = Profile->KeypadTone; break;
1899       case 0x01: value = Profile->Lights; break;
1900       case 0x02: value = Profile->CallAlert; break;
1901       case 0x03: value = Profile->Ringtone; break;
1902       case 0x04: value = Profile->Volume; break;
1903       case 0x05: value = Profile->MessageTone; break;
1904       case 0x06: value = Profile->Vibration; break;
1905       case 0x07: value = Profile->WarningTone; break;
1906       case 0x08: value = Profile->CallerGroups; break;
1907       case 0x09: value = Profile->AutomaticAnswer; break;
1908       default  : value = 0; break;
1909     }
1910
1911     error=N6110_SetProfileFeature(Profile->Number,i,value);
1912     if (error!=GE_NONE) return error;
1913   }
1914
1915   return (GE_NONE);
1916 }
1917
1918 #endif /* UCLINUX */
1919
1920 bool N6110_SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
1921 {
1922   u8 req[60] = { 0x00, 0xd9 };
1923                 
1924   /* Discontinuos transmission (DTX).  See section 5.6 of GSM 04.22 version
1925      7.0.1. */
1926        
1927   if (out_dtx)
1928     req[1]=0x01;
1929
1930   memcpy(req+2, (u8 *) frame, 32);
1931
1932   return (Protocol->SendFrame(32, 0xf0, req));
1933 }
1934
1935 #ifndef UCLINUX
1936
1937 void N6110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1938
1939   int i, j;
1940
1941   u8 mychar1;
1942
1943   wchar_t wc;  
1944     
1945   switch (MessageBuffer[4]) {
1946
1947     case 0x01:
1948       
1949       CurrentCalendarNote->Type=MessageBuffer[8];
1950
1951       DecodeDateTime(MessageBuffer+9, &CurrentCalendarNote->Time);
1952
1953       DecodeDateTime(MessageBuffer+16, &CurrentCalendarNote->Alarm);
1954
1955       CurrentCalendarNote->Text[0]=0;
1956       
1957       if (GetModelFeature (FN_CALENDAR)==F_CAL33) {
1958         i=0;
1959         if (CurrentCalendarNote->Type == GCN_REMINDER) i=1; //first char is subset
1960         switch (MessageBuffer[24]) {
1961           case 3:
1962 #ifdef DEBUG
1963             fprintf(stdout,_("Subset 3 in reminder note !\n"));
1964 #endif
1965             while (i!=MessageBuffer[23]) {
1966               j=0;
1967               if (i!=MessageBuffer[23]-1) {
1968                 if (MessageBuffer[24+i]>=0xc2) {
1969                   DecodeWithUTF8Alphabet(MessageBuffer[24+i], MessageBuffer[24+i+1], &mychar1);
1970                   CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0;
1971                   CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]=mychar1;
1972                   j=-1;
1973                   i++;
1974                 }
1975               }
1976               if (j!=-1) {
1977                 CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0;
1978                 CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]=MessageBuffer[24+i];
1979               }
1980               i++;
1981             }
1982             break;
1983           case 2:
1984 #ifdef DEBUG
1985             fprintf(stdout,_("Subset 2 in reminder note !\n"));
1986 #endif
1987             while (i!=MessageBuffer[23]) {
1988               wc = MessageBuffer[24+i] | (0x00 << 8);
1989               CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0;
1990               CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]=
1991                       DecodeWithUnicodeAlphabet(wc);
1992               i++;
1993             }
1994             break;
1995           case 1:
1996 #ifdef DEBUG
1997             fprintf(stdout,_("Subset 1 in reminder note !\n"));
1998 #endif
1999             memcpy(CurrentCalendarNote->Text,MessageBuffer+24+i,MessageBuffer[23]-i);
2000             CurrentCalendarNote->Text[MessageBuffer[23]-i]=0;
2001             break;
2002           default:
2003 #ifdef DEBUG
2004             fprintf(stdout,_("Unknown subset in reminder note !\n"));
2005 #endif
2006             memcpy(CurrentCalendarNote->Text,MessageBuffer+24+i,MessageBuffer[23]-i);
2007             CurrentCalendarNote->Text[MessageBuffer[23]-i]=0;
2008             break;
2009         }
2010       } else {
2011         memcpy(CurrentCalendarNote->Text,MessageBuffer+24,MessageBuffer[23]);
2012         CurrentCalendarNote->Text[MessageBuffer[23]]=0;
2013       }
2014       
2015       if (CurrentCalendarNote->Type == GCN_CALL) {
2016         memcpy(CurrentCalendarNote->Phone,MessageBuffer+24+MessageBuffer[23]+1,MessageBuffer[24+MessageBuffer[23]]);
2017         CurrentCalendarNote->Phone[MessageBuffer[24+MessageBuffer[23]]]=0;
2018       }
2019
2020       CurrentCalendarNote->Recurrance=0;
2021
2022       CurrentCalendarNote->AlarmType=0;
2023
2024 #ifdef DEBUG
2025       fprintf(stdout, _("Message: Calendar note received.\n"));
2026
2027       fprintf(stdout, _("   Date: %d-%02d-%02d\n"), CurrentCalendarNote->Time.Year,
2028                                            CurrentCalendarNote->Time.Month,
2029                                            CurrentCalendarNote->Time.Day);
2030
2031       fprintf(stdout, _("   Time: %02d:%02d:%02d\n"), CurrentCalendarNote->Time.Hour,
2032                                            CurrentCalendarNote->Time.Minute,
2033                                            CurrentCalendarNote->Time.Second);
2034
2035       /* Some messages do not have alarm set up */
2036       if (CurrentCalendarNote->Alarm.Year != 0) {
2037         fprintf(stdout, _("   Alarm date: %d-%02d-%02d\n"), CurrentCalendarNote->Alarm.Year,
2038                                                  CurrentCalendarNote->Alarm.Month,
2039                                                  CurrentCalendarNote->Alarm.Day);
2040
2041         fprintf(stdout, _("   Alarm time: %02d:%02d:%02d\n"), CurrentCalendarNote->Alarm.Hour,
2042                                                  CurrentCalendarNote->Alarm.Minute,
2043                                                  CurrentCalendarNote->Alarm.Second);
2044       }
2045
2046       fprintf(stdout, _("   Type: %d\n"), CurrentCalendarNote->Type);
2047       fprintf(stdout, _("   Text: %s\n"), CurrentCalendarNote->Text);
2048
2049       if (CurrentCalendarNote->Type == GCN_CALL)
2050         fprintf(stdout, _("   Phone: %s\n"), CurrentCalendarNote->Phone);
2051 #endif /* DEBUG */
2052
2053       CurrentCalendarNoteError=GE_NONE;
2054       break;
2055
2056     case 0x93:
2057
2058 #ifdef DEBUG
2059       fprintf(stdout, _("Message: Calendar note not available\n"));
2060 #endif /* DEBUG */
2061
2062       CurrentCalendarNoteError=GE_INVALIDCALNOTELOCATION;
2063       break;
2064
2065     default:
2066
2067 #ifdef DEBUG
2068       fprintf(stdout, _("Message: Calendar note error\n"));
2069 #endif /* DEBUG */
2070
2071       CurrentCalendarNoteError=GE_INTERNALERROR;
2072       break;
2073
2074   }
2075 }
2076
2077 GSM_Error N6110_GetCalendarNote(GSM_CalendarNote *CalendarNote)
2078 {
2079
2080   unsigned char req[] = { N6110_FRAME_HEADER,
2081                           0x66, 0x00
2082                         };
2083   GSM_Error error;
2084
2085   req[4]=CalendarNote->Location;
2086
2087   CurrentCalendarNote = CalendarNote;
2088
2089   error=NULL_SendMessageSequence
2090     (20, &CurrentCalendarNoteError, 5, 0x13, req);
2091
2092   CurrentCalendarNote = NULL;
2093
2094   return error;
2095 }
2096
2097 void N6110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2098
2099 #ifdef DEBUG
2100   switch(MessageBuffer[4]) {
2101     /* This message is also sent when the user enters the new entry on keypad */
2102     case 0x01:
2103       fprintf(stdout, _("Message: Calendar note write succesfull!\n"));break;      
2104     case 0x73:
2105       fprintf(stdout, _("Message: Calendar note write failed!\n"));break;
2106     case 0x7d:
2107       fprintf(stdout, _("Message: Calendar note write failed!\n"));break;
2108     default:
2109       fprintf(stdout, _("Unknown message of type 0x13 and subtype 0x65\n"));break;
2110   }
2111 #endif
2112
2113   switch(MessageBuffer[4]) {
2114     case 0x01: CurrentCalendarNoteError=GE_NONE; break;      
2115     case 0x73: CurrentCalendarNoteError=GE_INTERNALERROR; break;
2116     case 0x7d: CurrentCalendarNoteError=GE_INTERNALERROR; break;
2117     default  : AppendLogText("Unknown msg\n",false); break;
2118   }
2119 }
2120
2121 GSM_Error N6110_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
2122 {
2123
2124   unsigned char req[200] = { N6110_FRAME_HEADER,
2125                              0x64, 0x01, 0x10,
2126                              0x00, /* Length of the rest of the frame. */
2127                              0x00, /* The type of calendar note */
2128                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2129                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2130                         };
2131
2132   typedef struct {
2133     char *model;
2134     unsigned char call;
2135     unsigned char meeting;
2136     unsigned char birthday;
2137     unsigned char reminder;
2138   } calendar_model_length;
2139   
2140   /* Length of entries */
2141   calendar_model_length calendar_lengths[] =
2142   {
2143     /*model,CallTo,Meeting,Birthday,Reminder*/
2144     {"NHM-5",0x24,0x24,0x24,0x24}, //Reminder from phone, other quesses
2145     {"NHM-6",0x24,0x24,0x24,0x24}, //Reminder from phone, other quesses
2146     {"NSE-3",0x1e,0x14,0x14,0x1e}, //from NCDS3 [HKEY_LOCAL_MACHINE\Software\Nokia\Data Suite\3.0\Calendar]
2147     {"NSM-1",0x1e,0x18,0x18,0x24}, //from NCDS3 
2148     {"NSK-3",0x1e,0x14,0x14,0x1e}, //from NCDS3 
2149     {"NSB-3",0x20,0x14,0x14,0x1e}, //from NCDS3
2150     {"",     0,   0,   0,   0   }  //end of table
2151   };
2152
2153   int i, j, current;
2154
2155   u8 mychar;
2156   
2157   u8 mychar1,mychar2;
2158   
2159   GSM_Error error;
2160   
2161   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
2162   char model[64];
2163
2164   req[7]=CalendarNote->Type;
2165
2166   EncodeDateTime(req+8, &CalendarNote->Time);
2167   req[14] = CalendarNote->Time.Timezone;
2168
2169   if (CalendarNote->Alarm.Year) {
2170     EncodeDateTime(req+15, &CalendarNote->Alarm);
2171     req[21] = CalendarNote->Alarm.Timezone;
2172   }
2173
2174   req[22]=strlen(CalendarNote->Text);
2175   
2176   current=23;
2177
2178   if (GetModelFeature (FN_CALENDAR)==F_CAL33 && CalendarNote->Type==GCN_REMINDER) {
2179     req[22]++;           // one additional char
2180     req[current++]=0x01; //we use now subset 1
2181   }
2182     
2183   for (i=0; i<strlen(CalendarNote->Text); i++) {
2184     j=0;
2185     mychar=CalendarNote->Text[i];
2186     if (GetModelFeature (FN_CALENDAR)==F_CAL33 && CalendarNote->Type==GCN_REMINDER) {
2187       if (EncodeWithUTF8Alphabet(mychar,&mychar1,&mychar2)) {
2188           req[current++]=mychar1;
2189           req[current++]=mychar2;
2190           req[23]=0x03; //use subset 3
2191           req[22]++;    // one additional char
2192           j=-1;
2193       }
2194     }
2195     if (j!=-1) {
2196       /* Enables/disables blinking */
2197       if (mychar=='~') req[current++]=0x01;
2198                   else req[current++]=mychar;
2199     }
2200   }
2201
2202   req[current++]=strlen(CalendarNote->Phone);
2203
2204   for (i=0; i<strlen(CalendarNote->Phone); i++)
2205     req[current++]=CalendarNote->Phone[i];
2206
2207   while (N6110_GetModel(model)  != GE_NONE)
2208     sleep(1);
2209
2210   /* Checking maximal length */
2211   i=0;
2212   while (strcmp(calendar_lengths[i].model,"")) {
2213     if (!strcmp(calendar_lengths[i].model,model)) {
2214       switch (CalendarNote->Type) {
2215         case GCN_REMINDER:if (req[22]>calendar_lengths[i].reminder) return GE_TOOLONG;break;
2216         case GCN_MEETING :if (req[22]>calendar_lengths[i].meeting)  return GE_TOOLONG;break;
2217         case GCN_BIRTHDAY:if (req[22]>calendar_lengths[i].birthday) return GE_TOOLONG;break;
2218         case GCN_CALL    :if (strlen(CalendarNote->Phone)>calendar_lengths[i].call) return GE_TOOLONG;break;
2219       }
2220       break;
2221     }
2222     i++;
2223   }
2224
2225   CurrentCalendarNote = CalendarNote;
2226
2227   error=NULL_SendMessageSequence
2228     (20, &CurrentCalendarNoteError, current, 0x13, req);
2229
2230   CurrentCalendarNote = NULL;
2231
2232   return error;
2233 }
2234
2235 void N6110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2236
2237 #ifdef DEBUG
2238   switch (MessageBuffer[4]) {
2239     /* This message is also sent when the user deletes an old entry on
2240        keypad or moves an old entry somewhere (there is also `write'
2241        message). */
2242     case 0x01:fprintf(stdout, _("Message: Calendar note deleted\n"));break;
2243     case 0x93:fprintf(stdout, _("Message: Calendar note can't be deleted\n"));break;
2244     default  :fprintf(stdout, _("Message: Calendar note deleting error\n"));break;
2245   }
2246 #endif
2247
2248   switch (MessageBuffer[4]) {
2249     case 0x01:CurrentCalendarNoteError=GE_NONE;break;
2250     case 0x93:CurrentCalendarNoteError=GE_INVALIDCALNOTELOCATION;break;
2251     default  :CurrentCalendarNoteError=GE_INTERNALERROR;break;
2252   }
2253 }
2254
2255 GSM_Error N6110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
2256 {
2257
2258   unsigned char req[] = { N6110_FRAME_HEADER,
2259                           0x68, 0x00
2260                         };
2261
2262   req[4]=CalendarNote->Location;
2263
2264   return NULL_SendMessageSequence (20, &CurrentCalendarNoteError, 5, 0x13, req);
2265 }
2266
2267 #endif /* UCLINUX */
2268
2269 static void N6110_ReplyRFBatteryLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2270
2271 #ifdef DEBUG
2272     fprintf(stdout, _("Message: Phone status received:\n"));
2273     fprintf(stdout, _("   Mode: "));
2274
2275     switch (MessageBuffer[4]) {
2276
2277       case 0x01:
2278
2279         fprintf(stdout, _("registered within the network\n"));
2280         break;
2281               
2282       /* I was really amazing why is there a hole in the type of 0x02, now I
2283          know... */
2284       case 0x02: fprintf(stdout, _("call in progress\n"));          break; /* ringing or already answered call */
2285       case 0x03: fprintf(stdout, _("waiting for security code\n")); break;
2286       case 0x04: fprintf(stdout, _("powered off\n"));               break;
2287       default  : fprintf(stdout, _("unknown\n"));
2288
2289     }
2290
2291     fprintf(stdout, _("   Power source: "));
2292
2293     switch (MessageBuffer[7]) {
2294
2295       case 0x01: fprintf(stdout, _("AC/DC\n"));   break;
2296       case 0x02: fprintf(stdout, _("battery\n")); break;
2297       default  : fprintf(stdout, _("unknown\n"));
2298
2299     }
2300
2301     fprintf(stdout, _("   Battery Level: %d\n"), MessageBuffer[8]);
2302     fprintf(stdout, _("   Signal strength: %d\n"), MessageBuffer[5]);
2303 #endif /* DEBUG */
2304
2305     CurrentRFLevel=MessageBuffer[5];
2306     CurrentBatteryLevel=MessageBuffer[8];
2307     CurrentPowerSource=MessageBuffer[7];
2308 }
2309
2310
2311 GSM_Error N6110_GetRFLevel(GSM_RFUnits *units, float *level)
2312 {
2313
2314   /* FIXME - these values are from 3810 code, may be incorrect.  Map from
2315      values returned in status packet to the the values returned by the AT+CSQ
2316      command. */
2317   float csq_map[5] = {0, 8, 16, 24, 31};
2318
2319   int timeout=10;
2320   int rf_level;
2321   
2322   char screen[NM_MAX_SCREEN_WIDTH];
2323
2324   CurrentRFLevel=-1;
2325     
2326   if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) {
2327
2328 #ifndef UCLINUX
2329     if (N6110_NetMonitor(1, screen)!=GE_NONE)
2330       return GE_INTERNALERROR;
2331 #endif /* UCLINUX */
2332     
2333     rf_level=4;
2334     
2335     if (screen[4]!='-') {
2336       if (screen[5]=='9' && screen[6]>'4') rf_level=1;
2337       if (screen[5]=='9' && screen[6]<'5') rf_level=2;
2338       if (screen[5]=='8' && screen[6]>'4') rf_level=3;      
2339     } else rf_level=0;
2340
2341     /* Arbitrary units. */
2342     if (*units == GRF_Arbitrary) {
2343       *level = rf_level;
2344       return (GE_NONE);
2345     }
2346     
2347   } else {
2348     N6110_SendStatusRequest();
2349
2350     /* Wait for timeout or other error. */
2351     while (timeout != 0 && CurrentRFLevel == -1 ) {
2352
2353       if (--timeout == 0)
2354         return (GE_TIMEOUT);
2355
2356       usleep (100000);
2357     }
2358
2359     /* Make copy in case it changes. */
2360     rf_level = CurrentRFLevel;
2361
2362     if (rf_level == -1)
2363       return (GE_NOLINK);
2364
2365     /* Now convert between the different units we support. */
2366
2367     /* Arbitrary units. */
2368     if (*units == GRF_Arbitrary) {
2369       *level = rf_level;
2370       return (GE_NONE);
2371     }
2372
2373     /* CSQ units. */
2374     if (*units == GRF_CSQ) {
2375
2376       if (rf_level <=4)
2377         *level = csq_map[rf_level];
2378       else
2379         *level = 99; /* Unknown/undefined */
2380
2381       return (GE_NONE);
2382     }
2383   }
2384
2385   /* Unit type is one we don't handle so return error */
2386   return (GE_INTERNALERROR);
2387 }
2388
2389
2390 GSM_Error N6110_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
2391 {
2392   int timeout=10;
2393   int batt_level;
2394
2395   char screen[NM_MAX_SCREEN_WIDTH];
2396
2397   CurrentBatteryLevel=-1;
2398
2399   if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) {
2400
2401 #ifndef UCLINUX
2402     if (N6110_NetMonitor(23, screen)!=GE_NONE)
2403       return GE_NOLINK;
2404 #endif /* UCLINUX */
2405     
2406     batt_level=4;
2407     
2408     if (screen[29]=='7') batt_level=3;
2409     if (screen[29]=='5') batt_level=2;
2410     if (screen[29]=='2') batt_level=1;
2411     
2412     /* Only units we handle at present are GBU_Arbitrary */
2413     if (*units == GBU_Arbitrary) {
2414       *level = batt_level;
2415       return (GE_NONE);
2416     }
2417
2418     return (GE_INTERNALERROR);    
2419     
2420   } else {
2421     N6110_SendStatusRequest();
2422
2423     /* Wait for timeout or other error. */
2424     while (timeout != 0 && CurrentBatteryLevel == -1 ) {
2425
2426       if (--timeout == 0)
2427         return (GE_TIMEOUT);
2428
2429       usleep (100000);
2430     }
2431
2432     /* Take copy in case it changes. */
2433     batt_level = CurrentBatteryLevel;
2434
2435     if (batt_level != -1) {
2436
2437       /* Only units we handle at present are GBU_Arbitrary */
2438       if (*units == GBU_Arbitrary) {
2439         *level = batt_level;
2440         return (GE_NONE);
2441       }
2442
2443       return (GE_INTERNALERROR);
2444     }
2445     else
2446       return (GE_NOLINK);
2447   }
2448 }
2449
2450 GSM_Error N6110_GetPowerSource(GSM_PowerSource *source)
2451 {
2452
2453   int timeout=10;
2454
2455   char screen[NM_MAX_SCREEN_WIDTH];
2456
2457   CurrentPowerSource=-1;
2458
2459   if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) {    
2460
2461 #ifndef UCLINUX
2462     if (N6110_NetMonitor(20, screen)!=GE_NONE)
2463       return GE_NOLINK;
2464 #endif /* UCLINUX */
2465     
2466     CurrentPowerSource=GPS_ACDC;
2467
2468     if (screen[6]=='x') CurrentPowerSource=GPS_BATTERY;
2469
2470     *source=CurrentPowerSource;        
2471     
2472     return GE_NONE;    
2473   } else {
2474     N6110_SendStatusRequest();
2475
2476     /* Wait for timeout or other error. */
2477     while (timeout != 0 && CurrentPowerSource == -1 ) {
2478
2479       if (--timeout == 0)
2480         return (GE_TIMEOUT);
2481
2482       usleep (100000);
2483     }
2484
2485     if (CurrentPowerSource != -1) {
2486       *source=CurrentPowerSource;
2487       return (GE_NONE);
2488     }
2489     else
2490       return (GE_NOLINK);
2491   }
2492 }
2493
2494 #ifndef UCLINUX
2495
2496 static void N6110_ReplyGetDisplayStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2497
2498   int i;
2499
2500   for (i=0; i<MessageBuffer[4];i++)
2501     if (MessageBuffer[2*i+6]==2)
2502       CurrentDisplayStatus|=1<<(MessageBuffer[2*i+5]-1);
2503     else
2504       CurrentDisplayStatus&= (0xff - (1<<(MessageBuffer[2*i+5]-1)));
2505
2506 #ifdef DEBUG
2507   fprintf(stdout, _("Call in progress: %s\n"), CurrentDisplayStatus & (1<<DS_Call_In_Progress)?"on":"off");
2508   fprintf(stdout, _("Unknown: %s\n"),          CurrentDisplayStatus & (1<<DS_Unknown)?"on":"off");
2509   fprintf(stdout, _("Unread SMS: %s\n"),       CurrentDisplayStatus & (1<<DS_Unread_SMS)?"on":"off");
2510   fprintf(stdout, _("Voice call: %s\n"),       CurrentDisplayStatus & (1<<DS_Voice_Call)?"on":"off");
2511   fprintf(stdout, _("Fax call active: %s\n"),  CurrentDisplayStatus & (1<<DS_Fax_Call)?"on":"off");
2512   fprintf(stdout, _("Data call active: %s\n"), CurrentDisplayStatus & (1<<DS_Data_Call)?"on":"off");
2513   fprintf(stdout, _("Keyboard lock: %s\n"),    CurrentDisplayStatus & (1<<DS_Keyboard_Lock)?"on":"off");
2514   fprintf(stdout, _("SMS storage full: %s\n"), CurrentDisplayStatus & (1<<DS_SMS_Storage_Full)?"on":"off");
2515 #endif /* DEBUG */
2516
2517   CurrentDisplayStatusError=GE_NONE;
2518 }
2519
2520 GSM_Error N6110_GetDisplayStatus(int *Status) {
2521
2522   unsigned char req[4]={ N6110_FRAME_HEADER, 0x51 };
2523
2524   GSM_Error error;
2525
2526   error=NULL_SendMessageSequence
2527     (10, &CurrentDisplayStatusError, 4, 0x0d, req);
2528   if (error!=GE_NONE) return error;
2529   
2530   *Status=CurrentDisplayStatus;
2531
2532   return GE_NONE;
2533 }
2534
2535 GSM_Error N6110_DialVoice(char *Number) {
2536 /* This commented sequence doesn't work on N3210/3310/6210/7110 */
2537 //  unsigned char req[64]={N6110_FRAME_HEADER, 0x01};
2538 //  unsigned char req_end[]={0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
2539 //  int i=0;
2540 //  req[4]=strlen(Number);
2541 //  for(i=0; i < strlen(Number) ; i++)
2542 //   req[5+i]=Number[i];
2543 //  memcpy(req+5+strlen(Number), req_end, 10);
2544 //  return NULL_SendMessageSequence
2545 //    (20, &CurrentDialVoiceError, 13+strlen(Number), 0x01, req);
2546
2547   unsigned char req[64]={0x00,0x01,0x7c,
2548                          0x01}; //call command
2549
2550   int i=0;                       
2551   
2552   GSM_Error error;
2553
2554   error=N6110_EnableExtendedCommands(0x01);
2555   if (error!=GE_NONE) return error;
2556
2557   for(i=0; i < strlen(Number) ; i++) req[4+i]=Number[i];
2558   
2559   req[4+i+1]=0;
2560   
2561   return NULL_SendMessageSequence
2562     (20, &CurrentDialVoiceError, 4+strlen(Number)+1, 0x40, req);  
2563 }
2564
2565 #endif /* UCLINUX */
2566
2567 /* Dial a data call - type specifies request to use: 
2568      type 0 should normally be used
2569      type 1 should be used when calling a digital line - corresponds to ats35=0
2570      Maybe one day we'll know what they mean!
2571 */
2572 GSM_Error N6110_DialData(char *Number, char type, void (* callpassup)(char c))
2573 {
2574         unsigned char req[100]   = { N6110_FRAME_HEADER, 0x01 };
2575         unsigned char *req_end;
2576         unsigned char req_end0[] = { 0x01,  /* make a data call = type 0x01 */
2577                                      0x02,0x01,0x05,0x81,0x01,0x00,0x00,0x01,0x02,0x0a,
2578                                      0x07,0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00 };
2579         unsigned char req_end1[] = { 0x01,
2580                                      0x02,0x01,0x05,0x81,0x01,0x00,0x00,0x01,0x02,0x0a,
2581                                      0x07,0xa1,0x88,0x89,0x21,0x15,0x63,0xa0,0x00,0x06,
2582                                      0x88,0x90,0x21,0x48,0x40,0xbb };
2583 #if 0
2584         unsigned char req2[]     = { N6110_FRAME_HEADER, 0x42,0x05,0x01,
2585                                      0x07,0xa2,0xc8,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
2586                                      0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80,0x01,0x60 };
2587 #endif
2588         unsigned char req3[]     = { N6110_FRAME_HEADER, 0x42,0x05,0x01,
2589                                      0x07,0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
2590                                      0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80 };
2591         unsigned char req4[]     = { N6110_FRAME_HEADER, 0x42,0x05,0x81,
2592                                      0x07,0xa1,0x88,0x89,0x21,0x15,0x63,0xa0,0x00,0x06,
2593                                      0x88,0x90,0x21,0x48,0x40,0xbb,0x07,0xa3,0xb8,0x81,
2594                                      0x20,0x15,0x63,0x80 };
2595
2596         int i = 0;
2597         u8 size;
2598
2599         CurrentCallPassup=callpassup;
2600
2601         switch (type) {
2602         case 0:
2603                 usleep(100); Protocol->SendMessage(sizeof(req3), 0x01, req3);   /* Lace */
2604                 usleep(100);
2605                 req_end = req_end0;
2606                 size = sizeof(req_end0);
2607                 break;
2608         case 1:
2609                 Protocol->SendMessage(sizeof(req3), 0x01, req3);
2610                 usleep(1000000);
2611                 Protocol->SendMessage(sizeof(req4), 0x01, req4);
2612                 usleep(1000000);
2613                 req_end = req_end1;
2614                 size = sizeof(req_end1);
2615                 break;
2616         case -1:   /* Just used to set the call passup */
2617                 return GE_NONE;
2618                 break;
2619         default:
2620                 req_end = req_end0;
2621                 size = sizeof(req_end0);
2622                 break;
2623         }
2624
2625         req[4] = strlen(Number);
2626
2627         for(i = 0; i < strlen(Number) ; i++)
2628                 req[5+i] = Number[i];
2629
2630         memcpy(req + 5 + strlen(Number), req_end, size);
2631
2632         Protocol->SendMessage(5 + size + strlen(Number), 0x01, req);
2633         usleep(1000000);
2634
2635 #if 0
2636         if (type != 1) Protocol->SendMessage(26, 0x01, req2);
2637 #endif
2638
2639         return (GE_NONE);
2640 }
2641
2642 #ifndef UCLINUX
2643
2644 GSM_Error N6110_GetIncomingCallNr(char *Number)
2645 {
2646
2647   if (*CurrentIncomingCall != ' ') {
2648     strcpy(Number, CurrentIncomingCall);
2649     return GE_NONE;
2650   }
2651   else
2652     return GE_BUSY;
2653 }
2654
2655 #endif /* UCLINUX */
2656
2657 GSM_Error N6110_CancelCall(void)
2658 {
2659 //  This frame & method works only on 61xx/51xx
2660 //  unsigned char req[] = { N6110_FRAME_HEADER, 0x08, 0x00, 0x85};
2661 //  req[4]=CurrentCallSequenceNumber;
2662 //  Protocol->SendMessage(6, 0x01, req);
2663 //  return GE_NONE;
2664  
2665   GSM_Error error;
2666
2667   unsigned char req[]={0x00,0x01,0x7c,0x03};
2668     
2669   /* Checking */
2670   error=N6110_EnableExtendedCommands(0x01);
2671   if (error!=GE_NONE) return error;
2672
2673   return NULL_SendMessageSequence (20, &CurrentDialVoiceError, 4, 0x40, req);   
2674 }  
2675
2676 #ifndef UCLINUX
2677
2678 void N6110_ReplyEnterSecurityCode(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2679     
2680   switch(MessageBuffer[3]) {
2681
2682   case 0x0b:
2683 #ifdef DEBUG
2684     fprintf(stdout, _("Message: Security code accepted.\n"));
2685 #endif /* DEBUG */
2686     CurrentSecurityCodeError = GE_NONE;
2687     break;
2688
2689   default:
2690 #ifdef DEBUG
2691     fprintf(stdout, _("Message: Security code is wrong. You're not my big owner :-)\n"));
2692 #endif /* DEBUG */
2693     CurrentSecurityCodeError = GE_INVALIDSECURITYCODE;
2694   }
2695 }
2696
2697 GSM_Error N6110_EnterSecurityCode(GSM_SecurityCode SecurityCode)
2698 {
2699
2700   unsigned char req[15] = { N6110_FRAME_HEADER,
2701                             0x0a, /* Enter code request. */
2702                             0x00  /* Type of the entered code. */
2703                             };
2704   int i=0;
2705
2706   req[4]=SecurityCode.Type;
2707
2708   for (i=0; i<strlen(SecurityCode.Code);i++)
2709     req[5+i]=SecurityCode.Code[i];
2710
2711   req[5+strlen(SecurityCode.Code)]=0x00;
2712   req[6+strlen(SecurityCode.Code)]=0x00;
2713
2714   return NULL_SendMessageSequence
2715     (20, &CurrentSecurityCodeError, 7+strlen(SecurityCode.Code), 0x08, req);
2716 }
2717
2718 void N6110_ReplyGetSecurityCodeStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2719     
2720   *CurrentSecurityCodeStatus = MessageBuffer[4];
2721
2722 #ifdef DEBUG
2723   fprintf(stdout, _("Message: Security Code status received: "));
2724
2725   switch(*CurrentSecurityCodeStatus) {
2726
2727     case GSCT_SecurityCode: fprintf(stdout, _("waiting for Security Code.\n")); break;
2728     case GSCT_Pin         : fprintf(stdout, _("waiting for PIN.\n")); break;
2729     case GSCT_Pin2        : fprintf(stdout, _("waiting for PIN2.\n")); break;
2730     case GSCT_Puk         : fprintf(stdout, _("waiting for PUK.\n")); break;
2731     case GSCT_Puk2        : fprintf(stdout, _("waiting for PUK2.\n")); break;
2732     case GSCT_None        : fprintf(stdout, _("nothing to enter.\n")); break;
2733     default               : fprintf(stdout, _("Unknown!\n"));
2734   }
2735       
2736 #endif /* DEBUG */
2737
2738   CurrentSecurityCodeError = GE_NONE;
2739 }
2740
2741 GSM_Error N6110_GetSecurityCodeStatus(int *Status)
2742 {
2743
2744   unsigned char req[4] = { N6110_FRAME_HEADER,
2745                            0x07
2746                          };
2747
2748   CurrentSecurityCodeStatus=Status;
2749
2750   return NULL_SendMessageSequence
2751     (20, &CurrentSecurityCodeError, 4, 0x08, req);
2752 }
2753
2754 void N6110_ReplyGetSecurityCode(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2755
2756   int i;
2757   
2758 #ifdef DEBUG
2759   fprintf(stdout, _("Message: Security code received: "));
2760   switch (MessageBuffer[3]) {
2761     case GSCT_SecurityCode: fprintf(stdout, _("Security code"));break;
2762     case GSCT_Pin:  fprintf(stdout, _("PIN"));break;
2763     case GSCT_Pin2: fprintf(stdout, _("PIN2"));break;
2764     case GSCT_Puk:  fprintf(stdout, _("PUK"));break;
2765     case GSCT_Puk2: fprintf(stdout, _("PUK2"));break;
2766     default: fprintf(stdout, _("unknown !"));break;
2767   }
2768   if (MessageBuffer[4]==1) {
2769     fprintf(stdout, _(" allowed, value \""));
2770     if (MessageBuffer[3]==GSCT_SecurityCode) {
2771       for (i=0;i<5;i++) {fprintf(stdout, _("%c"), MessageBuffer[5+i]);}
2772     }
2773     if (MessageBuffer[3]==GSCT_Pin || MessageBuffer[3]==GSCT_Pin2 ||
2774         MessageBuffer[3]==GSCT_Puk || MessageBuffer[3]==GSCT_Puk2) {
2775       for (i=0;i<4;i++) {fprintf(stdout, _("%c"), MessageBuffer[5+i]);}
2776     }
2777     fprintf(stdout, _("\""));
2778   } else {
2779     fprintf(stdout, _(" not allowed"));  
2780   }
2781   fprintf(stdout, _("\n"));  
2782 #endif /* DEBUG */
2783       
2784   if (CurrentSecurityCode->Type==MessageBuffer[3] /* We wanted this code */
2785           && MessageBuffer[4]==1) {                      /* It's allowed */
2786     if (MessageBuffer[3]==GSCT_SecurityCode) {
2787       for (i=0;i<5;i++) {CurrentSecurityCode->Code[i]=MessageBuffer[5+i];}
2788       CurrentSecurityCode->Code[5]=0;
2789     }
2790     if (MessageBuffer[3]==GSCT_Pin || MessageBuffer[3]==GSCT_Pin2 ||
2791         MessageBuffer[3]==GSCT_Puk || MessageBuffer[3]==GSCT_Puk2) {
2792       for (i=0;i<4;i++) {CurrentSecurityCode->Code[i]=MessageBuffer[5+i];}
2793       CurrentSecurityCode->Code[4]=0;
2794     }
2795     CurrentSecurityCodeError=GE_NONE;
2796   } else
2797     CurrentSecurityCodeError=GE_INVALIDSECURITYCODE;
2798 }
2799
2800 GSM_Error N6110_GetSecurityCode(GSM_SecurityCode *SecurityCode)
2801 {
2802
2803   unsigned char req[4] = { 0x00,
2804                            0x01,0x6e, /* Get code request. */
2805                            0x00 };    /* Type of the requested code. */
2806
2807   GSM_Error error;
2808   
2809   error=N6110_EnableExtendedCommands(0x01);
2810   if (error!=GE_NONE) return error;
2811   
2812   req[3]=SecurityCode->Type;
2813
2814   CurrentSecurityCode=SecurityCode;
2815
2816   return NULL_SendMessageSequence
2817     (20, &CurrentSecurityCodeError, 4, 0x40, req);
2818 }
2819
2820 void N6110_ReplyPlayTone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2821
2822 #ifdef DEBUG
2823   fprintf(stdout, _("Message: answer for PlayTone frame\n"));      
2824 #endif
2825       
2826   CurrentPlayToneError=GE_NONE;      
2827 }
2828
2829 GSM_Error N6110_PlayTone(int Herz, u8 Volume)
2830 {
2831   unsigned char req[6] = { 0x00,0x01,0x8f,
2832                            0x00,   /* Volume */
2833                            0x00,   /* HerzLo */
2834                            0x00 }; /* HerzHi */
2835
2836   GSM_Error error;
2837
2838   /* PlayTone wasn't used earlier */
2839   if (CurrentPlayToneError==GE_UNKNOWN) {
2840     if (CurrentConnectionType!=GCT_MBUS)
2841       CurrentDisableKeepAlive=true;
2842
2843     error=N6110_EnableExtendedCommands(0x01);
2844     if (error!=GE_NONE) return error;
2845   }
2846
2847   /* For Herz==255*255 we have silent */  
2848   if (Herz!=255*255) {
2849     req[3]=Volume;
2850
2851     req[5]=Herz%256;
2852     req[4]=Herz/256;
2853   } else {
2854     req[3]=0;
2855
2856     req[5]=0;
2857     req[4]=0;
2858   }
2859
2860 #ifdef WIN32
2861   /* For Herz==255*255 we have silent and additionaly
2862      we wait for phone answer - it's important for MBUS */
2863   if (Herz==255*255) {
2864     error=NULL_SendMessageSequence
2865       (20, &CurrentPlayToneError, 6, 0x40, req);
2866
2867     CurrentPlayToneError=GE_UNKNOWN;
2868     CurrentDisableKeepAlive=false;
2869
2870     if (error!=GE_NONE) return error;
2871   } else {
2872     Protocol->SendMessage(6,0x40,req);
2873   }
2874 #else
2875   error=NULL_SendMessageSequence
2876     (20, &CurrentPlayToneError, 6, 0x40, req);
2877
2878   /* For Herz==255*255 we wait for phone answer - it's important for MBUS */
2879   if (Herz==255*255) {
2880     CurrentPlayToneError=GE_UNKNOWN;
2881     CurrentDisableKeepAlive=false;
2882   }
2883   
2884   if (error!=GE_NONE) return error;
2885
2886 #endif
2887     
2888   return(GE_NONE);
2889 }
2890
2891 void N6110_ReplyGetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2892
2893   if (MessageBuffer[4]==0x01) {
2894     DecodeDateTime(MessageBuffer+8, CurrentDateTime);
2895
2896 #ifdef DEBUG
2897     fprintf(stdout, _("Message: Date and time\n"));
2898     fprintf(stdout, _("   Time: %02d:%02d:%02d\n"), CurrentDateTime->Hour, CurrentDateTime->Minute, CurrentDateTime->Second);
2899     fprintf(stdout, _("   Date: %4d/%02d/%02d\n"), CurrentDateTime->Year, CurrentDateTime->Month, CurrentDateTime->Day);
2900 #endif /* DEBUG */
2901
2902     CurrentDateTime->IsSet=true;
2903   } else {
2904
2905 #ifdef DEBUG
2906     fprintf(stdout, _("Message: Date and time not set in phone\n"));
2907 #endif
2908
2909     CurrentDateTime->IsSet=false;
2910   }
2911       
2912   CurrentDateTimeError=GE_NONE;
2913 }
2914
2915 GSM_Error N6110_GetDateTime(GSM_DateTime *date_time)
2916 {
2917   return N6110_PrivGetDateTime(date_time,0x11);
2918 }
2919
2920 GSM_Error N6110_PrivGetDateTime(GSM_DateTime *date_time, int msgtype)
2921 {
2922   unsigned char req[] = {N6110_FRAME_HEADER, 0x62};
2923
2924   CurrentDateTime=date_time;
2925
2926   return NULL_SendMessageSequence
2927     (50, &CurrentDateTimeError, 4, msgtype, req);
2928 }
2929
2930 void N6110_ReplyGetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2931
2932 #ifdef DEBUG
2933   fprintf(stdout, _("Message: Alarm\n"));
2934   fprintf(stdout, _("   Alarm: %02d:%02d\n"), MessageBuffer[9], MessageBuffer[10]);
2935   fprintf(stdout, _("   Alarm is %s\n"), (MessageBuffer[8]==2) ? _("on"):_("off"));
2936 #endif /* DEBUG */
2937
2938   CurrentAlarm->Hour=MessageBuffer[9];
2939   CurrentAlarm->Minute=MessageBuffer[10];
2940   CurrentAlarm->Second=0;
2941
2942   CurrentAlarm->IsSet=(MessageBuffer[8]==2);
2943
2944   CurrentAlarmError=GE_NONE;
2945 }
2946
2947 GSM_Error N6110_GetAlarm(int alarm_number, GSM_DateTime *date_time)
2948 {
2949   return N6110_PrivGetAlarm(alarm_number,date_time,0x11);
2950 }
2951
2952 GSM_Error N6110_PrivGetAlarm(int alarm_number, GSM_DateTime *date_time, int msgtype)
2953 {
2954   unsigned char req[] = {N6110_FRAME_HEADER, 0x6d};
2955
2956   CurrentAlarm=date_time;
2957
2958   return NULL_SendMessageSequence
2959     (50, &CurrentAlarmError, 4, msgtype, req);
2960 }
2961
2962 void N6110_ReplyGetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
2963   
2964   switch (MessageBuffer[3]) {
2965
2966   case 0x34:
2967
2968     CurrentMessageCenter->No=MessageBuffer[4];
2969     CurrentMessageCenter->Format=MessageBuffer[6];
2970     CurrentMessageCenter->Validity=MessageBuffer[8];
2971     sprintf(CurrentMessageCenter->Name, "%s", MessageBuffer+33);
2972
2973     sprintf(CurrentMessageCenter->DefaultRecipient, "%s", GSM_UnpackSemiOctetNumber(MessageBuffer+9,false));
2974
2975     sprintf(CurrentMessageCenter->Number, "%s", GSM_UnpackSemiOctetNumber(MessageBuffer+21,false));
2976       
2977 #ifdef DEBUG
2978     fprintf(stdout, _("Message: SMS Center received:\n"));
2979     fprintf(stdout, _("   %d. SMS Center name is %s\n"), CurrentMessageCenter->No, CurrentMessageCenter->Name);
2980     fprintf(stdout, _("   SMS Center number is %s\n"), CurrentMessageCenter->Number);
2981     fprintf(stdout, _("   Default recipient number is %s\n"), CurrentMessageCenter->DefaultRecipient);
2982       
2983     fprintf(stdout, _("   SMS Center message format is "));
2984
2985     switch (CurrentMessageCenter->Format) {
2986
2987       case GSMF_Text  : fprintf(stdout, _("Text"));   break;
2988       case GSMF_Paging: fprintf(stdout, _("Paging")); break;
2989       case GSMF_Fax   : fprintf(stdout, _("Fax"));    break;
2990       case GSMF_Email : fprintf(stdout, _("Email"));  break;
2991       default         : fprintf(stdout, _("Unknown"));
2992     }
2993
2994     fprintf(stdout, "\n");
2995
2996     fprintf(stdout, _("   SMS Center message validity is "));
2997
2998     switch (CurrentMessageCenter->Validity) {
2999
3000       case GSMV_1_Hour  : fprintf(stdout, _("1 hour"));      break;
3001       case GSMV_6_Hours : fprintf(stdout, _("6 hours"));     break;
3002       case GSMV_24_Hours: fprintf(stdout, _("24 hours"));    break;
3003       case GSMV_72_Hours: fprintf(stdout, _("72 hours"));    break;
3004       case GSMV_1_Week  : fprintf(stdout, _("1 week"));      break;
3005       case GSMV_Max_Time: fprintf(stdout, _("Maximum time"));break;
3006       default           : fprintf(stdout, _("Unknown"));
3007     }
3008
3009     fprintf(stdout, "\n");
3010
3011 #endif /* DEBUG */
3012
3013     CurrentMessageCenterError=GE_NONE;
3014
3015     break;
3016
3017   case 0x35:
3018
3019     /* Number of entries depends on SIM card */
3020
3021 #ifdef DEBUG
3022     fprintf(stdout, _("Message: SMS Center error received:\n"));
3023     fprintf(stdout, _("   The request for SMS Center failed.\n"));
3024 #endif /* DEBUG */
3025
3026     /* FIXME: appropriate error. */
3027     CurrentMessageCenterError=GE_INTERNALERROR;
3028
3029     break;  
3030
3031   }
3032 }
3033
3034 /* This function sends to the mobile phone a request for the SMS Center */
3035 GSM_Error N6110_GetSMSCenter(GSM_MessageCenter *MessageCenter)
3036 {
3037   unsigned char req[] = { N6110_FRAME_HEADER, 0x33, 0x64,
3038                           0x00 /* SMS Center Number. */
3039                         };
3040
3041   req[5]=MessageCenter->No;
3042
3043   CurrentMessageCenter=MessageCenter;
3044
3045   return NULL_SendMessageSequence
3046     (50, &CurrentMessageCenterError, 6, 0x02, req);
3047 }
3048
3049 void N6110_ReplySetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3050
3051 #ifdef DEBUG
3052   fprintf(stdout, _("Message: SMS Center correctly set.\n"));
3053 #endif
3054   CurrentMessageCenterError=GE_NONE;
3055 }
3056
3057 /* This function set the SMS Center profile on the phone. */
3058 GSM_Error N6110_SetSMSCenter(GSM_MessageCenter *MessageCenter)
3059 {
3060   unsigned char req[64] = { N6110_FRAME_HEADER, 0x30, 0x64,
3061                             0x00, /* SMS Center Number. */
3062                             0x00, /* Unknown. */
3063                             0x00, /* SMS Message Format. */
3064                             0x00, /* Unknown. */
3065                             0x00, /* Validity. */
3066                             0,0,0,0,0,0,0,0,0,0,0,0, /* Default recipient number */
3067                             0,0,0,0,0,0,0,0,0,0,0,0 /* Message Center Number. */
3068                             /* Message Center Name. */
3069                           };
3070
3071   req[5]=MessageCenter->No;
3072   req[7]=MessageCenter->Format;
3073   req[9]=MessageCenter->Validity;
3074
3075   req[10]=GSM_PackSemiOctetNumber(MessageCenter->DefaultRecipient, req+11, false);
3076
3077   req[22]=GSM_PackSemiOctetNumber(MessageCenter->Number, req+23, false);
3078
3079   sprintf(req+34, "%s", MessageCenter->Name);
3080
3081   CurrentMessageCenter=MessageCenter;
3082
3083   return NULL_SendMessageSequence
3084     (50, &CurrentMessageCenterError, 35+strlen(MessageCenter->Name), 0x02, req);
3085 }
3086
3087 void N6110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3088
3089   switch (MessageBuffer[3]) {
3090
3091   case 0x37:
3092
3093 #ifdef DEBUG
3094     fprintf(stdout, _("Message: SMS Status Received\n"));
3095     fprintf(stdout, _("   The number of messages: %d\n"), MessageBuffer[10]);
3096     fprintf(stdout, _("   Unread messages: %d\n"), MessageBuffer[11]);
3097 #endif /* DEBUG */
3098
3099     CurrentSMSStatus->UnRead = MessageBuffer[11];
3100     CurrentSMSStatus->Number = MessageBuffer[10];
3101     
3102     CurrentSMSStatusError = GE_NONE;
3103     break;
3104
3105   case 0x38:
3106
3107 #ifdef DEBUG
3108     fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n"));
3109 #endif /* DEBUG */
3110
3111     CurrentSMSStatusError = GE_INTERNALERROR;
3112     break;
3113           
3114   }
3115 }
3116
3117 GSM_Error N6110_GetSMSStatus(GSM_SMSStatus *Status)
3118 {
3119   unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
3120
3121   CurrentSMSStatus = Status;
3122
3123   return NULL_SendMessageSequence
3124     (10, &CurrentSMSStatusError, 5, 0x14, req);
3125 }
3126
3127 GSM_Error N6110_GetSMSFolders ( GSM_SMSFolders *folders)
3128 {
3129   folders->number=2;
3130
3131   strcpy(folders->Folder[0].Name,"Inbox");
3132   strcpy(folders->Folder[1].Name,"Outbox");
3133   
3134   return GE_NONE;
3135 }
3136
3137 #endif /* UCLINUX */
3138
3139 GSM_Error N6110_GetIMEI(char *imei)
3140 {
3141   if (strlen(Current_IMEI)>0) {
3142     strncpy (imei, Current_IMEI, GSM_MAX_IMEI_LENGTH);
3143     return (GE_NONE);
3144   }
3145   else
3146     return (GE_TRYAGAIN);
3147 }
3148
3149 GSM_Error N6110_GetRevision(char *revision)
3150 {
3151
3152   if (strlen(Current_Revision)>0) {
3153     strncpy (revision, Current_Revision, GSM_MAX_REVISION_LENGTH);
3154     return (GE_NONE);
3155   }
3156   else
3157     return (GE_TRYAGAIN);
3158 }
3159
3160 static GSM_Error N6110_GetModel(char *model)
3161 {
3162   if (strlen(Current_Model)>0) {
3163     strncpy (model, Current_Model, GSM_MAX_MODEL_LENGTH);
3164     return (GE_NONE);
3165   }
3166   else
3167     return (GE_TRYAGAIN);
3168 }
3169
3170 #ifndef UCLINUX
3171
3172 void N6110_ReplySetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3173
3174   switch (MessageBuffer[4]) {
3175
3176     case 0x01:
3177 #ifdef DEBUG
3178       fprintf(stdout, _("Message: Date and time set correctly\n"));
3179 #endif /* DEBUG */
3180       CurrentSetDateTimeError=GE_NONE;
3181       break;
3182       
3183     default:
3184 #ifdef DEBUG
3185       fprintf(stdout, _("Message: Date and time setting error\n"));
3186 #endif /* DEBUG */
3187       CurrentSetDateTimeError=GE_INVALIDDATETIME;
3188
3189   }
3190 }
3191
3192 /* Needs SIM card with PIN in phone */
3193 GSM_Error N6110_SetDateTime(GSM_DateTime *date_time)
3194 {
3195   return N6110_PrivSetDateTime(date_time,0x11);
3196 }
3197
3198 /* Needs SIM card with PIN in phone */
3199 GSM_Error N6110_PrivSetDateTime(GSM_DateTime *date_time, int msgtype)
3200 {
3201
3202   unsigned char req[] = { N6110_FRAME_HEADER,
3203                           0x60, /* set-time subtype */
3204                           0x01, 0x01, 0x07, /* unknown */
3205                           0x00, 0x00, /* Year (0x07cf = 1999) */
3206                           0x00, 0x00, /* Month Day */
3207                           0x00, 0x00, /* Hours Minutes */
3208                           0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */
3209                         };
3210
3211   EncodeDateTime(req+7, date_time);
3212
3213   return NULL_SendMessageSequence
3214     (20, &CurrentSetDateTimeError, 14, msgtype, req);
3215 }
3216
3217 void N6110_ReplySetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3218
3219   switch (MessageBuffer[4]) {
3220
3221     case 0x01:
3222 #ifdef DEBUG
3223       fprintf(stdout, _("Message: Alarm set correctly\n"));
3224 #endif /* DEBUG */
3225       CurrentSetAlarmError=GE_NONE;
3226       break;
3227       
3228     default:
3229 #ifdef DEBUG
3230       fprintf(stdout, _("Message: Alarm setting error\n"));
3231 #endif /* DEBUG */
3232       CurrentSetAlarmError=GE_INVALIDDATETIME;
3233
3234   }
3235 }
3236
3237 /* FIXME: we should also allow to set the alarm off :-) */
3238 GSM_Error N6110_SetAlarm(int alarm_number, GSM_DateTime *date_time)
3239 {
3240   return N6110_PrivSetAlarm(alarm_number,date_time, 0x11);
3241 }
3242
3243 /* FIXME: we should also allow to set the alarm off :-) */
3244 GSM_Error N6110_PrivSetAlarm(int alarm_number, GSM_DateTime *date_time, int msgtype)
3245 {
3246
3247   unsigned char req[] = { N6110_FRAME_HEADER,
3248                           0x6b, /* set-alarm subtype */
3249                           0x01, 0x20, 0x03, /* unknown */
3250                           0x02,       /* should be alarm on/off, but it don't works */
3251                           0x00, 0x00, /* Hours Minutes */
3252                           0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */
3253                         };
3254
3255   req[8] = date_time->Hour;
3256   req[9] = date_time->Minute;
3257
3258   return NULL_SendMessageSequence
3259     (50, &CurrentSetAlarmError, 11, msgtype, req);
3260 }
3261
3262 #endif /* UCLINUX */
3263
3264 static void N6110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3265
3266   /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
3267   char model[64];
3268
3269   int i, tmp, count;
3270     
3271   switch (MessageBuffer[3]) {
3272
3273   case 0x02:
3274
3275     CurrentPhonebookEntry->Empty = true;
3276
3277     count=MessageBuffer[5];
3278           
3279 #ifdef DEBUG
3280     fprintf(stdout, _("Message: Phonebook entry received:\n"));
3281     fprintf(stdout, _("   Name: "));
3282
3283     for (tmp=0; tmp <count; tmp++)
3284     {
3285       if (MessageBuffer[6+tmp]==1) fprintf(stdout, "%c", '~'); else //enables/disables blinking
3286       if (MessageBuffer[6+tmp]==0) fprintf(stdout, "%c", '`'); else //hides rest ot contents
3287       fprintf(stdout, "%c", MessageBuffer[6+tmp]);
3288     }
3289
3290     fprintf(stdout, "\n");
3291 #endif /* DEBUG */
3292
3293     while (N6110_GetModel(model)  != GE_NONE)
3294       sleep(1);
3295         
3296     if (GetModelFeature (FN_PHONEBOOK)==F_PBK33) {//pbk with Unicode
3297 #ifndef UCLINUX
3298       DecodeUnicode (CurrentPhonebookEntry->Name, MessageBuffer+6, count/2);
3299       CurrentPhonebookEntry->Name[count/2] = 0x00;
3300 #else /* UCLINUX */
3301       fprintf(stderr,"FATAL ERROR: DecodeUnicode disabled!\n");
3302       exit(1);
3303 #endif /* UCLINUX */
3304     } else {
3305       memcpy(CurrentPhonebookEntry->Name, MessageBuffer + 6, count);
3306       CurrentPhonebookEntry->Name[count] = 0x00;
3307     }
3308
3309     CurrentPhonebookEntry->Empty = false;
3310
3311     for (tmp=0; tmp <count; tmp++)
3312     {
3313       if (GetModelFeature (FN_PHONEBOOK)==F_PBK33) {//pbk with Unicode
3314         /* We check only 1'st, 3'rd, ... char */
3315         if (tmp%2!=0 && MessageBuffer[6+tmp]==1) CurrentPhonebookEntry->Name[tmp/2]='~'; //enables/disables blinking
3316         if (tmp%2!=0 && MessageBuffer[6+tmp]==0) CurrentPhonebookEntry->Name[tmp/2]='`'; //hides rest ot contents
3317       } else {
3318         if (MessageBuffer[6+tmp]==1) CurrentPhonebookEntry->Name[tmp]='~'; //enables/disables blinking
3319         if (MessageBuffer[6+tmp]==0) CurrentPhonebookEntry->Name[tmp]='`'; //hides rest ot contents
3320       }
3321     }
3322
3323     i=7+count;
3324     count=MessageBuffer[6+count];
3325
3326 #ifdef DEBUG
3327     fprintf(stdout, _("   Number: "));
3328
3329     for (tmp=0; tmp <count; tmp++)
3330       fprintf(stdout, "%c", MessageBuffer[i+tmp]);
3331
3332     fprintf(stdout, "\n");
3333 #endif /* DEBUG */
3334
3335     memcpy(CurrentPhonebookEntry->Number, MessageBuffer + i, count);
3336     CurrentPhonebookEntry->Number[count] = 0x00;
3337     CurrentPhonebookEntry->Group = MessageBuffer[i+count];
3338       
3339     /* Phone doesn't have entended phonebook */
3340     CurrentPhonebookEntry->SubEntriesCount = 0;
3341
3342     /* But for these memories data is saved and we can save it using 7110/6210 style */
3343     if (CurrentPhonebookEntry->MemoryType==GMT_DC ||
3344         CurrentPhonebookEntry->MemoryType==GMT_RC ||
3345         CurrentPhonebookEntry->MemoryType==GMT_MC) {
3346         CurrentPhonebookEntry->SubEntriesCount = 1;
3347         CurrentPhonebookEntry->SubEntries[0].EntryType=N7110_ENTRYTYPE_DATE;
3348         CurrentPhonebookEntry->SubEntries[0].NumberType=0;
3349         CurrentPhonebookEntry->SubEntries[0].BlockNumber=1;
3350         DecodeDateTime(MessageBuffer+(i+count+2),&CurrentPhonebookEntry->SubEntries[0].data.Date);
3351
3352 #ifdef DEBUG
3353       fprintf(stdout, _("   Date: "));
3354       fprintf(stdout, "%02u.%02u.%04u\n",
3355           CurrentPhonebookEntry->SubEntries[0].data.Date.Day,
3356           CurrentPhonebookEntry->SubEntries[0].data.Date.Month,
3357           CurrentPhonebookEntry->SubEntries[0].data.Date.Year);
3358       fprintf(stdout, _("   Time: "));
3359       fprintf(stdout, "%02u:%02u:%02u\n",
3360           CurrentPhonebookEntry->SubEntries[0].data.Date.Hour,
3361           CurrentPhonebookEntry->SubEntries[0].data.Date.Minute,
3362           CurrentPhonebookEntry->SubEntries[0].data.Date.Second);
3363 #endif /* DEBUG */
3364
3365       /* These values are set, when date and time unavailable in phone.
3366          Values from 3310 - in other can be different */
3367       if (CurrentPhonebookEntry->SubEntries[0].data.Date.Day==20 &&
3368           CurrentPhonebookEntry->SubEntries[0].data.Date.Month==1 &&
3369           CurrentPhonebookEntry->SubEntries[0].data.Date.Year==2118 &&
3370           CurrentPhonebookEntry->SubEntries[0].data.Date.Hour==3 &&
3371           CurrentPhonebookEntry->SubEntries[0].data.Date.Minute==14 &&
3372           CurrentPhonebookEntry->SubEntries[0].data.Date.Second==7)
3373           CurrentPhonebookEntry->SubEntriesCount = 0;
3374     }
3375
3376     /* Signal no error to calling code. */
3377     CurrentPhonebookError = GE_NONE;
3378
3379     break;
3380
3381   case 0x03:
3382
3383 #ifdef DEBUG
3384     fprintf(stdout, _("Message: Phonebook read entry error received:\n"));
3385 #endif /* DEBUG */
3386
3387     switch (MessageBuffer[4]) {
3388
3389       case 0x7d:
3390 #ifdef DEBUG
3391         fprintf(stdout, _("   Invalid memory type!\n"));
3392 #endif /* DEBUG */
3393         CurrentPhonebookError = GE_INVALIDMEMORYTYPE;
3394         break;
3395
3396       default:
3397 #ifdef DEBUG
3398         fprintf(stdout, _("   Unknown error!\n"));
3399 #endif /* DEBUG */
3400         CurrentPhonebookError = GE_INTERNALERROR;
3401     }
3402
3403     break;
3404
3405   }
3406 }
3407
3408 /* Routine to get specifed phone book location.  Designed to be called by
3409    application.  Will block until location is retrieved or a timeout/error
3410    occurs. */
3411 GSM_Error N6110_GetMemoryLocation(GSM_PhonebookEntry *entry)
3412 {
3413   unsigned char req[] = {N6110_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00};
3414
3415   CurrentPhonebookEntry = entry;
3416
3417   req[4] = N6110_GetMemoryType(entry->MemoryType);
3418   req[5] = entry->Location;
3419
3420   return NULL_SendMessageSequence
3421     (50, &CurrentPhonebookError, 7, 0x03, req);
3422 }
3423
3424 static void N6110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3425
3426   switch (MessageBuffer[3]) {
3427
3428   case 0x05:
3429
3430 #ifdef DEBUG
3431     fprintf(stdout, _("Message: Phonebook written correctly.\n"));
3432 #endif /* DEBUG */
3433     CurrentPhonebookError = GE_NONE;
3434     break;
3435
3436   case 0x06:
3437
3438     switch (MessageBuffer[4]) {
3439       /* FIXME: other errors? When I send the phonebook with index of 350 it
3440          still report error 0x7d :-( */
3441       case 0x7d:
3442 #ifdef DEBUG
3443         fprintf(stdout, _("Message: Phonebook not written - name is too long.\n"));
3444 #endif /* DEBUG */
3445         CurrentPhonebookError = GE_PHBOOKNAMETOOLONG;
3446         break;
3447
3448       default:
3449 #ifdef DEBUG
3450         fprintf(stdout, _("   Unknown error!\n"));
3451 #endif /* DEBUG */
3452         CurrentPhonebookError = GE_INTERNALERROR;
3453     }
3454   }
3455 }
3456
3457 /* Routine to write phonebook location in phone. Designed to be called by
3458    application code. Will block until location is written or timeout
3459    occurs. */
3460 GSM_Error N6110_WritePhonebookLocation(GSM_PhonebookEntry *entry)
3461 {
3462   unsigned char req[128] = { N6110_FRAME_HEADER, 0x04, 0x00, 0x00 };
3463   int i=0, current=0;
3464
3465   req[4] = N6110_GetMemoryType(entry->MemoryType);
3466   req[5] = entry->Location;
3467
3468   current=7;
3469
3470   if (GetModelFeature (FN_PHONEBOOK)==F_PBK33) {
3471 #ifndef UCLINUX
3472
3473      req[6] = strlen(entry->Name)*2;
3474
3475      EncodeUnicode (req+current,entry->Name ,strlen(entry->Name));
3476      
3477      for (i=0; i<strlen(entry->Name); i++)
3478      {
3479        /* here we encode "special" chars */
3480        if (entry->Name[i]=='~') req[current+i*2]=1; //enables/disables blinking
3481        if (entry->Name[i]=='`') req[current+i*2]=0; //hides rest ot contents
3482      }
3483
3484      current+=strlen(entry->Name)*2;
3485
3486 #else /* UCLINUX */
3487
3488      fprintf(stderr,"FATAL ERROR: EncodeUnicode disabled!\n");
3489      exit(1);
3490
3491 #endif /* UCLINUX */
3492   } else {
3493
3494     req[6] = strlen(entry->Name);
3495
3496     for (i=0; i<strlen(entry->Name); i++)
3497     {
3498       req[current+i] = entry->Name[i];
3499
3500       /* here we encode "special" chars */
3501       if (entry->Name[i]=='~') req[current+i]=1; //enables/disables blinking
3502       if (entry->Name[i]=='`') req[current+i]=0; //hides rest ot contents
3503     }
3504
3505     current+=strlen(entry->Name);
3506   }
3507
3508   req[current++]=strlen(entry->Number);
3509
3510   for (i=0; i<strlen(entry->Number); i++)
3511     req[current+i] = entry->Number[i];
3512
3513   current+=strlen(entry->Number);
3514
3515   /* Jano: This allow to save 14 characters name into SIM memory, when
3516      No Group is selected. */
3517   if (entry->Group == 5)
3518     req[current++]=0xff;
3519   else
3520     req[current++]=entry->Group;
3521
3522   return NULL_SendMessageSequence
3523     (50, &CurrentPhonebookError, current, 0x03, req);
3524 }
3525
3526 #ifndef UCLINUX
3527
3528 void N6110_ReplyNetmonitor(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3529
3530   switch(MessageBuffer[3]) {
3531
3532     case 0x00:
3533 #ifdef DEBUG
3534       fprintf(stdout, _("Message: Netmonitor correctly set.\n"));
3535 #endif /* DEBUG */
3536       CurrentNetmonitorError=GE_NONE;  
3537       break;
3538       
3539     default:
3540 #ifdef DEBUG
3541       fprintf(stdout, _("Message: Netmonitor menu %d received:\n"), MessageBuffer[3]);
3542       fprintf(stdout, "%s\n", MessageBuffer+4);
3543 #endif /* DEBUG */
3544
3545       strcpy(CurrentNetmonitor, MessageBuffer+4);
3546
3547       CurrentNetmonitorError=GE_NONE;  
3548   }
3549 }
3550
3551 GSM_Error N6110_NetMonitor(unsigned char mode, char *Screen)
3552 {
3553   unsigned char req[] = { 0x00, 0x01, 0x7e, 0x00 };
3554   
3555   GSM_Error error;
3556   
3557   error=N6110_EnableExtendedCommands(0x01);
3558   if (error!=GE_NONE) return error;
3559
3560   CurrentNetmonitor=Screen;
3561
3562   req[3]=mode;
3563
3564   return NULL_SendMessageSequence
3565     (20, &CurrentNetmonitorError, 4, 0x40, req);
3566 }
3567
3568 /* Doesn't work in N3210. */
3569 /* In other allow to access phone menu without SIM card (just send any sequence) */
3570 GSM_Error N6110_SendDTMF(char *String)
3571 {
3572   unsigned char req[64] = { N6110_FRAME_HEADER, 0x50,
3573                             0x00 /* Length of DTMF string. */
3574                           };
3575                           
3576   u8 length=strlen(String);
3577
3578   if (length>59) length=59;
3579   
3580   req[4] = length;
3581   
3582   memcpy(req+5,String,length);
3583
3584   return NULL_SendMessageSequence
3585     (20, &CurrentSendDTMFError, 5+length, 0x01, req);
3586 }
3587
3588 #endif /* UCLINUX */
3589
3590 static void N6110_ReplyGetSpeedDial(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3591
3592   switch (MessageBuffer[3]) {
3593
3594   case 0x17:
3595
3596     switch (MessageBuffer[4]) {
3597       case 0x02: CurrentSpeedDialEntry->MemoryType = GMT_ME;
3598       default  : CurrentSpeedDialEntry->MemoryType = GMT_SM;
3599     }
3600       
3601     CurrentSpeedDialEntry->Location = MessageBuffer[5];
3602
3603 #ifdef DEBUG
3604     fprintf(stdout, _("Message: Speed dial entry received:\n"));
3605     fprintf(stdout, _("   Location: %d\n"), CurrentSpeedDialEntry->Location);
3606     fprintf(stdout, _("   MemoryType: %s\n"), N6110_MemoryType_String[CurrentSpeedDialEntry->MemoryType]);
3607     fprintf(stdout, _("   Number: %d\n"), CurrentSpeedDialEntry->Number);
3608 #endif /* DEBUG */
3609
3610     CurrentSpeedDialError=GE_NONE;
3611     break;
3612
3613   case 0x18:
3614
3615 #ifdef DEBUG
3616     fprintf(stdout, _("Message: Speed dial entry error\n"));
3617 #endif /* DEBUG */
3618     CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
3619     break;
3620
3621   }
3622 }
3623
3624 GSM_Error N6110_GetSpeedDial(GSM_SpeedDial *entry)
3625 {
3626
3627   unsigned char req[] = { N6110_FRAME_HEADER,
3628                           0x16,
3629                           0x00  /* The number of speed dial. */
3630                         };
3631
3632   CurrentSpeedDialEntry = entry;
3633
3634   req[4] = entry->Number;
3635
3636   return NULL_SendMessageSequence
3637     (20, &CurrentSpeedDialError, 5, 0x03, req);
3638 }
3639
3640 static void N6110_ReplySetSpeedDial(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3641
3642   switch (MessageBuffer[3]) {
3643
3644   case 0x1a:
3645
3646 #ifdef DEBUG
3647     fprintf(stdout, _("Message: Speed dial entry set.\n"));
3648 #endif /* DEBUG */
3649     CurrentSpeedDialError=GE_NONE;
3650     break;
3651
3652   case 0x1b:
3653
3654 #ifdef DEBUG
3655     fprintf(stdout, _("Message: Speed dial entry setting error.\n"));
3656 #endif /* DEBUG */
3657     CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION;
3658     break;
3659
3660   }
3661 }
3662
3663 GSM_Error N6110_SetSpeedDial(GSM_SpeedDial *entry)
3664 {
3665
3666   unsigned char req[] = { N6110_FRAME_HEADER,
3667                           0x19,
3668                           0x00, /* Number */
3669                           0x00, /* Memory Type */
3670                           0x00  /* Location */
3671                         };
3672
3673   req[4] = entry->Number;
3674
3675   switch (entry->MemoryType) {
3676     case GMT_ME: req[5] = 0x02;
3677     default    : req[5] = 0x03;
3678   }
3679
3680   req[6] = entry->Location;
3681
3682   return NULL_SendMessageSequence
3683     (20, &CurrentSpeedDialError, 7, 0x03, req);
3684 }
3685
3686 #ifndef UCLINUX
3687
3688 /* This function finds parts of SMS in frame used in new Nokia phones
3689    in internal protocols (they're coded according to GSM 03.40), copies them
3690    to GSM_ETSISMSMessage and calls GSM_DecodeETSISMS to decode
3691    GSM_ETSISMSMessage to GSM_SMSMessage structure */
3692 GSM_Error GSM_DecodeNokiaSMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int length)
3693 {
3694   SMS_MessageType PDU=SMS_Deliver;
3695   GSM_ETSISMSMessage ETSI;
3696   int offset=0,i;
3697
3698   ETSI.firstbyte=req[12];
3699
3700   /* See GSM 03.40 section 9.2.3.1 */
3701   if ((ETSI.firstbyte & 0x03) == 0x01) PDU=SMS_Submit;
3702   if ((ETSI.firstbyte & 0x03) == 0x02) PDU=SMS_Status_Report;
3703
3704   switch (PDU) {
3705     case SMS_Submit       : offset=5;break;
3706     case SMS_Deliver      : offset=4;break;
3707     case SMS_Status_Report: offset=3;break;
3708     default:                break;
3709   }
3710
3711   for (i=0;i<req[0]+1;i++)
3712     ETSI.SMSCNumber[i]=req[i];
3713
3714   for (i=0;i<((req[12+offset]+1)/2+1)+1;i++)
3715     ETSI.Number[i]=req[i+12+offset];
3716
3717   switch (PDU) {
3718     case SMS_Submit:
3719       ETSI.TPDCS=req[10+offset];
3720       ETSI.TPUDL=req[11+offset];
3721       ETSI.TPVP=0;  //no support for now
3722       ETSI.TPPID=0; //no support for now
3723       for(i=31+offset;i<length;i++)
3724         ETSI.MessageText[i-31-offset]=req[i];
3725       break;
3726     case SMS_Deliver:
3727       ETSI.TPDCS=req[10+offset];
3728       ETSI.TPUDL=req[11+offset];
3729       ETSI.TPPID=0; //no support for now
3730       for(i=31+offset;i<length;i++)
3731         ETSI.MessageText[i-31-offset]=req[i];
3732       for(i=0;i<7;i++)
3733         ETSI.DeliveryDateTime[i]=req[i+24+offset];
3734       break;
3735     case SMS_Status_Report:
3736       for(i=0;i<7;i++)
3737         ETSI.DeliveryDateTime[i]=req[i+24+offset];
3738       ETSI.TPStatus=req[14];
3739       for(i=0;i<7;i++)
3740         ETSI.SMSCDateTime[i]=req[i+34];
3741       break;
3742     default:
3743       break;
3744   }
3745
3746   GSM_DecodeETSISMS(SMS, &ETSI);
3747
3748   SMS->Name[0]=0;
3749
3750   return GE_NONE;
3751 }
3752
3753 void N6110_ReplyGetSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3754
3755   int offset;
3756   
3757   switch (MessageBuffer[3]) {
3758
3759   case 0x08:
3760
3761     switch (MessageBuffer[7]) {
3762
3763       case 0x00:
3764         CurrentSMSMessage->Type = GST_SMS;
3765         CurrentSMSMessage->folder=GST_INBOX;
3766         offset=4;
3767         break;
3768
3769       case 0x01:
3770         CurrentSMSMessage->Type = GST_DR;
3771         CurrentSMSMessage->folder=GST_INBOX;
3772         offset=3;
3773         break;
3774
3775       case 0x02:
3776         CurrentSMSMessage->Type = GST_SMS;
3777         CurrentSMSMessage->folder=GST_OUTBOX;
3778         offset=5;
3779         break;
3780
3781       default:
3782         CurrentSMSMessage->Type = GST_UN;
3783         offset=4;
3784         break;
3785
3786     }
3787
3788     /* Field Short Message Status - MessageBuffer[4] seems not to be
3789        compliant with GSM 07.05 spec.
3790        Meaning     Nokia protocol       GMS spec
3791        ----------------------------------------------------
3792        MO Sent     0x05                 0x07 or 0x01
3793        MO Not sent 0x07                 0x06 or 0x00
3794        MT Read     0x01                 0x05 or 0x01
3795        MT Not read 0x03                 0x04 or 0x00
3796        ----------------------------------------------------
3797        See GSM 07.05 section 2.5.2.6 and correct me if I'm wrong.
3798        
3799                                          Pawel Kot */
3800
3801     if (MessageBuffer[4] & 0x02) CurrentSMSMessage->Status = GSS_NOTSENTREAD;
3802                             else CurrentSMSMessage->Status = GSS_SENTREAD;
3803
3804 #ifdef DEBUG
3805     fprintf(stdout, _("Number: %d\n"), MessageBuffer[6]);
3806
3807     if (CurrentSMSMessage->folder!=1) { //GST_OUTBOX
3808       fprintf(stdout, _("Message: Received SMS (mobile terminated)\n"));
3809     } else {
3810       fprintf(stdout, _("Message: Outbox message (mobile originated)\n"));
3811     }
3812
3813     if (CurrentSMSMessage->Type == GST_DR) fprintf(stdout, _("   Delivery Report\n"));
3814     if (CurrentSMSMessage->Type == GST_UN) fprintf(stdout, _("   Unknown type\n"));
3815
3816     if (CurrentSMSMessage->folder==1) { //GST_OUTBOX
3817       if (CurrentSMSMessage->Status) fprintf(stdout, _("   Sent\n"));
3818                                 else fprintf(stdout, _("   Not sent\n"));
3819     } else {
3820       if (CurrentSMSMessage->Status) fprintf(stdout, _("   Read\n"));
3821                                 else fprintf(stdout, _("   Not read\n"));
3822     }
3823 #endif
3824
3825     CurrentSMSPointer=GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+8, MessageLength-8);
3826
3827     CurrentSMSMessage->MemoryType = MessageBuffer[5];
3828     CurrentSMSMessage->MessageNumber = MessageBuffer[6];
3829  
3830     /* Signal no error to calling code. */
3831     CurrentSMSMessageError = GE_NONE;
3832
3833 #ifdef DEBUG
3834     fprintf(stdout, "\n");
3835 #endif
3836
3837     break;
3838
3839   case 0x09:
3840
3841     /* We have requested invalid or empty location. */
3842
3843 #ifdef DEBUG
3844     fprintf(stdout, _("Message: SMS reading failed\n"));
3845
3846     switch (MessageBuffer[4]) {
3847       case 0x02:
3848         fprintf(stdout, _("   Invalid location!\n"));break;
3849       case 0x07:
3850         fprintf(stdout, _("   Empty SMS location.\n"));break;
3851       case 0x0c:
3852         fprintf(stdout, _("   No access to memory (no PIN on card ?)\n"));break;
3853       default:      
3854         fprintf(stdout, _("   Error code %i - please report it \n"),MessageBuffer[4]);break;
3855     }
3856 #endif /* DEBUG */
3857
3858     switch (MessageBuffer[4]) {
3859       case 0x02:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break;
3860       case 0x07:CurrentSMSMessageError = GE_EMPTYSMSLOCATION;break;
3861       case 0x0c:CurrentSMSMessageError = GE_NOACCESS;break;
3862       default  :CurrentSMSMessageError = GE_UNKNOWN;break;
3863     }
3864
3865     break;
3866
3867   }
3868 }
3869
3870 GSM_Error N6110_GetSMSMessage(GSM_SMSMessage *message)
3871 {
3872
3873   unsigned char req[] = { N6110_FRAME_HEADER,
3874                           0x07,
3875                           0x02, /* Unknown */
3876                           0x00, /* Location */
3877                           0x01, 0x64};
3878
3879   int timeout = 60;
3880
3881   /* State machine code writes data to these variables when it comes in. */
3882
3883   CurrentSMSMessage = message;
3884   CurrentSMSMessageError = GE_BUSY;
3885
3886   req[5] = message->Location;
3887
3888   /* Send request */
3889   Protocol->SendMessage(8, 0x02, req);
3890
3891   /* Wait for timeout or other error. */
3892   while (timeout != 0 && (CurrentSMSMessageError == GE_BUSY || CurrentSMSMessageError == GE_SMSWAITING)) {
3893
3894     if (--timeout == 0)
3895       return (GE_TIMEOUT);
3896
3897     usleep (100000);
3898   }
3899
3900   return (CurrentSMSMessageError);
3901 }
3902
3903 void N6110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3904
3905 #ifdef DEBUG
3906   fprintf(stdout, _("Message: SMS deleted successfully.\n"));
3907 #endif /* DEBUG */
3908
3909   CurrentSMSMessageError = GE_NONE;     
3910 }
3911
3912 GSM_Error N6110_DeleteSMSMessage(GSM_SMSMessage *message)
3913 {
3914   unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02, 0x00};
3915
3916   req[5] = message->Location;
3917
3918   return NULL_SendMessageSequence
3919     (50, &CurrentSMSMessageError, 6, 0x14, req);
3920 }
3921
3922 /* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */
3923 GSM_Error GSM_EncodeNokiaSMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int *length, SMS_MessageType PDU)
3924 {
3925   GSM_ETSISMSMessage ETSI;
3926   int i,offset=0;
3927
3928   GSM_EncodeETSISMS(SMS, &ETSI, PDU, length);
3929
3930   /* Cleaning */
3931   for (i=0;i<36;i++) req[i]=0;
3932
3933   req[12]=ETSI.firstbyte;
3934
3935   for (i=0;i<ETSI.SMSCNumber[0]+1;i++)
3936     req[i]=ETSI.SMSCNumber[i];
3937
3938   switch (PDU) {
3939     case SMS_Submit:
3940       offset=5;
3941       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++)
3942         req[i+12+offset]=ETSI.Number[i];
3943       req[10+offset]=ETSI.TPDCS;
3944       req[11+offset]=ETSI.TPUDL;
3945       req[24+offset]=ETSI.TPVP;
3946 #ifdef DEBUG
3947 //      fprintf(stdout,_("   First byte: %02x\n"),ETSI.firstbyte);
3948 //      fprintf(stdout,_("   TP-VP: %02x\n"),ETSI.TPVP);
3949 //      fprintf(stdout,_("   TP-DCS: %02x\n"),ETSI.TPDCS);
3950 #endif
3951 //    req[]=ETSI.TPPID;
3952       for(i=0;i<*length;i++)
3953         req[i+31+offset]=ETSI.MessageText[i];
3954       break;
3955
3956     case SMS_Deliver:
3957       offset=4;
3958       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++)
3959         req[i+12+offset]=ETSI.Number[i];
3960       req[10+offset]=ETSI.TPDCS;
3961       req[11+offset]=ETSI.TPUDL;
3962 //    req[]=ETSI.TPPID;
3963       for(i=0;i<*length;i++)
3964         req[i+31+offset]=ETSI.MessageText[i];
3965       for (i=0;i<7;i++)
3966         req[24+offset+i]=ETSI.DeliveryDateTime[i];
3967       break;
3968     default:
3969       break;
3970   }
3971   
3972   *length=*length+offset;
3973   
3974   return GE_NONE;
3975 }
3976
3977 void N6110_ReplySendSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
3978     
3979   switch (MessageBuffer[3]) {
3980
3981   /* SMS message correctly sent to the network */
3982   case 0x02:
3983 #ifdef DEBUG
3984     fprintf(stdout, _("Message: SMS Message correctly sent.\n"));
3985 #endif /* DEBUG */
3986     CurrentSMSMessageError = GE_SMSSENDOK;
3987     break;
3988
3989   /* SMS message send to the network failed */
3990   case 0x03:
3991
3992 #ifdef DEBUG
3993     fprintf(stdout, _("Message: Sending SMS Message failed, error: %i"),MessageBuffer[6]);
3994       
3995     switch (MessageBuffer[6]) {
3996       case 1: fprintf(stdout,_(" (info \"Number not in use\")"));break;
3997       case 21: fprintf(stdout,_(" (info \"Message not sent this time\")"));break;
3998       case 28: fprintf(stdout,_(" (info \"Number not in use\")"));break;
3999       case 38: fprintf(stdout,_(" (info \"Message not sent this time\")"));break;       case 50: fprintf(stdout,_(" (info \"Check operator services\")"));break;        
4000       case 96: fprintf(stdout,_(" (info \"Message sending failed\")"));break;   
4001       case 111: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  
4002       case 166: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  
4003       case 178: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  
4004       case 252: fprintf(stdout,_(" (info \"Message sending failed\")"));break;         case 253: fprintf(stdout,_(" (info \"Message sending failed\")"));break; 
4005     }
4006
4007     fprintf(stdout,_("\n   For more details with errors see netmonitor manual (test 65) on www.marcin-wiacek.topnet.pl"));
4008     fprintf(stdout,_("\n   If know their meaning, GSM specs decribing them, contact with me on marcin-wiacek@topnet.pl. THX\n"));
4009 #endif /* DEBUG */
4010
4011     CurrentSMSMessageError = GE_SMSSENDFAILED;
4012     break;
4013
4014   }
4015 }
4016
4017 GSM_Error N6110_SendSMSMessage(GSM_SMSMessage *SMS)
4018 {
4019   GSM_Error error;
4020
4021   unsigned char req[256] = {
4022     N6110_FRAME_HEADER,
4023     0x01, 0x02, 0x00, /* SMS send request*/
4024   };
4025
4026   int length;
4027
4028   error=GSM_EncodeNokiaSMSFrame(SMS, req+6, &length, SMS_Submit);    
4029   if (error != GE_NONE) return error;
4030
4031   return NULL_SendMessageSequence
4032     (200, &CurrentSMSMessageError, 42+length, 0x02, req);
4033 }
4034
4035 void N6110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4036
4037   switch (MessageBuffer[3]) {
4038
4039   case 0x05:
4040       
4041 #ifdef DEBUG
4042     fprintf(stdout, _("SMS Message stored at %d\n"), MessageBuffer[5]);
4043 #endif
4044       
4045     CurrentSMSMessage->MessageNumber=MessageBuffer[5];
4046       
4047     CurrentSMSMessageError = GE_NONE;
4048     break;
4049
4050   case 0x06:
4051 #ifdef DEBUG
4052     fprintf(stdout, _("SMS saving failed\n"));
4053     switch (MessageBuffer[4]) {
4054       case 0x02:fprintf(stdout, _("   All locations busy.\n"));break;
4055       case 0x03:fprintf(stdout, _("   Invalid location!\n"));break;
4056       default  :fprintf(stdout, _("   Unknown error.\n"));break;
4057     }
4058 #endif      
4059       
4060     switch (MessageBuffer[4]) {
4061       case 0x02:CurrentSMSMessageError = GE_MEMORYFULL;break;
4062       case 0x03:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break;
4063       default  :CurrentSMSMessageError = GE_UNKNOWN;break;
4064     }
4065   }
4066 }
4067
4068 /* GST_DR and GST_UN not supported ! */
4069 GSM_Error N6110_SaveSMSMessage(GSM_SMSMessage *SMS)
4070 {
4071   unsigned char req[256] = {
4072     N6110_FRAME_HEADER, 0x04, /* SMS save request*/
4073     0x00, /* SMS Status. Different for Inbox and Outbox */
4074     0x02, /* ?? */
4075     0x00, /* SMS Location */
4076     0x02, /* SMS Type */
4077   };
4078
4079   int length;
4080   SMS_MessageType PDU;
4081   GSM_Error error;
4082
4083   if (SMS->Location) req[6] = SMS->Location;
4084     
4085   if (SMS->folder==0) { /*Inbox*/
4086     req[4]=1;      /* SMS Status */
4087     req[7] = 0x00; /* SMS Type */
4088     PDU=SMS_Deliver;
4089   } else {
4090     req[4]=5;      /* SMS Status */
4091     req[7] = 0x02; /* SMS Type */
4092     PDU=SMS_Submit;
4093   }
4094   
4095   if (SMS->Status == GSS_NOTSENTREAD) req[4] |= 0x02;  
4096
4097   error=GSM_EncodeNokiaSMSFrame(SMS, req+8, &length, PDU);  
4098   if (error != GE_NONE) return error;
4099
4100   CurrentSMSMessage = SMS;
4101
4102   return NULL_SendMessageSequence
4103     (70, &CurrentSMSMessageError, 39+length, 0x14, req);
4104 }
4105
4106 void N6110_ReplySetCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4107
4108 #ifdef DEBUG
4109   fprintf(stdout, _("Message: Cell Broadcast enabled/disabled successfully.\n")); fflush (stdout);
4110 #endif
4111
4112   CurrentCBError = GE_NONE;
4113 }
4114
4115 /* Enable and disable Cell Broadcasting */
4116 GSM_Error N6110_EnableCellBroadcast(void)
4117 {
4118   unsigned char req[] = {N6110_FRAME_HEADER, 0x20,
4119                          0x01, 0x01, 0x00, 0x00, 0x01, 0x01};
4120
4121 #ifdef DEBUG
4122   fprintf (stdout,"Enabling CB\n");
4123 #endif
4124
4125   CurrentCBMessage = (GSM_CBMessage *)malloc(sizeof (GSM_CBMessage));
4126   CurrentCBMessage->Channel = 0;
4127   CurrentCBMessage->New = false;
4128   strcpy (CurrentCBMessage->Message,"");
4129
4130   return NULL_SendMessageSequence
4131     (10, &CurrentCBError, 10, 0x02, req);
4132 }
4133
4134
4135 GSM_Error N6110_DisableCellBroadcast(void)
4136 {
4137   /* Should work, but not tested fully */
4138
4139   unsigned char req[] = {N6110_FRAME_HEADER, 0x20,
4140                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /*VERIFY*/
4141
4142   return NULL_SendMessageSequence
4143     (10, &CurrentCBError, 10, 0x02, req);
4144 }
4145
4146 void N6110_ReplyReadCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4147
4148   int i, tmp;
4149   unsigned char output[160];
4150   
4151   CurrentCBMessage->Channel = MessageBuffer[7];
4152   CurrentCBMessage->New = true;
4153   tmp=GSM_UnpackEightBitsToSeven(0, MessageBuffer[9], MessageBuffer[9], MessageBuffer+10, output);
4154
4155 #ifdef DEBUG
4156   fprintf(stdout, _("Message: CB received.\n")); fflush (stdout);
4157
4158   fprintf(stdout, _("Message: channel number %i\n"),MessageBuffer[7]);
4159
4160   fflush (stdout);
4161
4162   for (i=0; i<tmp;i++) {
4163     fprintf(stdout, "%c", DecodeWithDefaultAlphabet(output[i]));
4164   }
4165
4166   fprintf(stdout, "\n");
4167 #endif
4168    
4169   for (i=0; i<tmp; i++) {
4170     CurrentCBMessage->Message[i] = DecodeWithDefaultAlphabet(output[i]);
4171   }
4172   CurrentCBMessage->Message[i]=0;
4173 }
4174
4175 GSM_Error N6110_ReadCellBroadcast(GSM_CBMessage *Message)
4176 {
4177 #ifdef DEBUG
4178    fprintf(stdout,"Reading CB\n");
4179 #endif
4180
4181   if (CurrentCBMessage != NULL) 
4182   {
4183     if (CurrentCBMessage->New == true)
4184     {
4185 #ifdef DEBUG
4186   fprintf(stdout,"New CB received\n");
4187 #endif
4188       Message->Channel = CurrentCBMessage->Channel;
4189       strcpy(Message->Message,CurrentCBMessage->Message);
4190       CurrentCBMessage->New = false;
4191       return (GE_NONE);
4192     }
4193   }
4194   return (GE_NONEWCBRECEIVED);
4195 }
4196
4197 int N6110_MakeCallerGroupFrame(unsigned char *req,GSM_Bitmap Bitmap)
4198 {
4199   int count=0;
4200
4201   req[count++]=Bitmap.number;
4202   req[count++]=strlen(Bitmap.text);
4203   memcpy(req+count,Bitmap.text,req[count-1]);
4204   count+=req[count-1];
4205   req[count++]=Bitmap.ringtone;
4206
4207   /* Setting for graphic:
4208      0x00 - Off
4209      0x01 - On
4210      0x02 - View Graphics
4211      0x03 - Send Graphics
4212      0x04 - Send via IR
4213      You can even set it higher but Nokia phones (my
4214      6110 at least) will not show you the name of this
4215      item in menu ;-)) Nokia is really joking here. */
4216   if (Bitmap.enabled) req[count++]=0x01;
4217                  else req[count++]=0x00;
4218
4219   req[count++]=(Bitmap.size+4)>>8;
4220   req[count++]=(Bitmap.size+4)%0xff;
4221   req[count++]=0x00;  /* Future extensions! */
4222   req[count++]=Bitmap.width;
4223   req[count++]=Bitmap.height;
4224   req[count++]=0x01;  /* Just BW */
4225   memcpy(req+count,Bitmap.bitmap,Bitmap.size);
4226
4227   return count+Bitmap.size;
4228 }
4229
4230 int N6110_MakeOperatorLogoFrame(unsigned char *req,GSM_Bitmap Bitmap)
4231 {
4232   int count=0;
4233
4234   EncodeNetworkCode(req+count, Bitmap.netcode);
4235   count=count+3;
4236
4237   req[count++]=(Bitmap.size+4)>>8;
4238   req[count++]=(Bitmap.size+4)%0xff;
4239   req[count++]=0x00;  /* Infofield */
4240   req[count++]=Bitmap.width;
4241   req[count++]=Bitmap.height;
4242   req[count++]=0x01;  /* Just BW */    
4243   memcpy(req+count,Bitmap.bitmap,Bitmap.size);
4244
4245   return count+Bitmap.size;
4246 }
4247
4248 int N6110_MakeStartupLogoFrame(unsigned char *req,GSM_Bitmap Bitmap)
4249 {
4250   int count=0;
4251
4252   req[count++]=0x01;
4253   req[count++]=Bitmap.height;
4254   req[count++]=Bitmap.width;
4255   memcpy(req+count,Bitmap.bitmap,Bitmap.size);
4256
4257   return count+Bitmap.size;
4258 }
4259
4260 /* Set a bitmap or welcome-note */
4261 GSM_Error N6110_SetBitmap(GSM_Bitmap *Bitmap) {
4262
4263   unsigned char req[600] = { N6110_FRAME_HEADER };
4264   u16 count=3;
4265   u8 textlen;
4266   
4267   int timeout=50;
4268
4269   /* Direct uploading variables */
4270   GSM_MultiSMSMessage SMS;
4271   unsigned char buffer[1000] = {0x0c,0x01};
4272   GSM_NetworkInfo NetworkInfo;
4273
4274   GSM_Error error;
4275  
4276   /* Uploading with preview */
4277   if (Bitmap->number==255 &&
4278      (Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_CallerLogo)) {
4279     GSM_SaveBitmapToSMS(&SMS,Bitmap,false,false);
4280     memcpy(buffer+2,SMS.SMS[0].UDH,SMS.SMS[0].UDH[0]+1);
4281
4282     memcpy(buffer+2+SMS.SMS[0].UDH[0]+1,SMS.SMS[0].MessageText,SMS.SMS[0].Length);
4283
4284     buffer[2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length]=0x00;
4285
4286     Protocol->SendMessage(2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length+1, 0x12, buffer);
4287
4288     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
4289     return GE_NONE; //no answer from phone
4290   }
4291  
4292   CurrentSetBitmapError = GE_BUSY;  
4293   
4294   switch (Bitmap->type) {
4295   case GSM_WelcomeNoteText:
4296   case GSM_DealerNoteText:
4297     req[count++]=0x18;
4298     req[count++]=0x01; /* Only one block */
4299
4300     if (Bitmap->type==GSM_WelcomeNoteText)
4301       req[count++]=0x02; /* Welcome text */
4302     else
4303       req[count++]=0x03; /* Dealer Welcome Note */
4304
4305     textlen=strlen(Bitmap->text);
4306     req[count++]=textlen;
4307     memcpy(req+count,Bitmap->text,textlen);
4308       
4309     count+=textlen;
4310
4311     Protocol->SendMessage(count, 0x05, req);
4312     
4313     break;
4314
4315   case GSM_StartupLogo:
4316     if (Bitmap->number==0) {
4317
4318       /* For 33xx we first set animated logo to default */
4319       if (GetModelFeature (FN_STARTUP)==F_STANIM) {
4320         error=N6110_SetProfileFeature(0, 0x29, Bitmap->number);
4321         if (error!=GE_NONE) return error;
4322       }
4323
4324       req[count++]=0x18;
4325       req[count++]=0x01; /* Only one block */
4326       count=count+N6110_MakeStartupLogoFrame(req+5,*Bitmap); 
4327       Protocol->SendMessage(count, 0x05, req);
4328     } else {
4329       return N6110_SetProfileFeature(0, 0x29, Bitmap->number);
4330     }
4331     break;
4332
4333   case GSM_OperatorLogo:
4334     req[count++]=0x30;  /* Store Op Logo */
4335     req[count++]=0x01;  /* Location */
4336     count=count+N6110_MakeOperatorLogoFrame(req+5,*Bitmap); 
4337     Protocol->SendMessage(count, 0x05, req);
4338     break;
4339
4340   case GSM_CallerLogo:
4341     req[count++]=0x13;
4342     count=count+N6110_MakeCallerGroupFrame(req+4,*Bitmap);
4343     Protocol->SendMessage(count, 0x03, req);
4344     break;
4345
4346   case GSM_PictureImage:
4347     req[count++]=0x03;
4348     req[count++]=Bitmap->number;
4349     if (strcmp(Bitmap->Sender,"")) {
4350        req[count]=GSM_PackSemiOctetNumber(Bitmap->Sender, req+count+1,true);
4351
4352        /* Convert number of semioctets to number of chars and add count */
4353        textlen=req[count];
4354        if (textlen % 2) textlen++;
4355        count+=textlen / 2 + 1;
4356
4357        count++;
4358     } else {
4359       req[count++]=0x00;
4360       req[count++]=0x00;
4361     }
4362     req[count++]=0x00;
4363     req[count++]=strlen(Bitmap->text);
4364     memcpy(req+count,Bitmap->text,strlen(Bitmap->text));
4365     count+=strlen(Bitmap->text);
4366     req[count++]=0x00;
4367     req[count++]=Bitmap->width;
4368     req[count++]=Bitmap->height;
4369     req[count++]=0x01;
4370     memcpy(req+count,Bitmap->bitmap,Bitmap->size);
4371     Protocol->SendMessage(count+Bitmap->size, 0x47, req);
4372     break;
4373
4374   case GSM_7110OperatorLogo:
4375   case GSM_7110StartupLogo:
4376   case GSM_6210StartupLogo:
4377     return GE_NOTSUPPORTED;
4378
4379   case GSM_None:
4380     return GE_NONE;
4381   }
4382
4383   /* Wait for timeout or other error. */
4384   while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {
4385           
4386     if (--timeout == 0)
4387       return (GE_TIMEOUT);
4388                     
4389     usleep (100000);
4390   }
4391
4392   return CurrentSetBitmapError;
4393 }
4394
4395 /* Get a bitmap from the phone */
4396 GSM_Error N6110_GetBitmap(GSM_Bitmap *Bitmap) {
4397
4398   unsigned char req[10] = { N6110_FRAME_HEADER };
4399   u8 count=3;
4400   
4401   int timeout=100;
4402   
4403   CurrentGetBitmap=Bitmap; 
4404   CurrentGetBitmapError = GE_BUSY;  
4405   
4406   switch (CurrentGetBitmap->type) {
4407   case GSM_StartupLogo:
4408   case GSM_WelcomeNoteText:
4409   case GSM_DealerNoteText:
4410     req[count++]=0x16;
4411     Protocol->SendMessage(count, 0x05, req);
4412     break;
4413   case GSM_OperatorLogo:
4414     req[count++]=0x33;
4415     req[count++]=0x01; /* Location 1 */
4416     Protocol->SendMessage(count, 0x05, req);
4417     break;
4418   case GSM_CallerLogo:
4419     req[count++]=0x10;
4420     req[count++]=Bitmap->number;
4421     Protocol->SendMessage(count, 0x03, req);
4422     break;
4423   case GSM_PictureImage:
4424     req[count++]=0x01;
4425     req[count++]=Bitmap->number;
4426     Protocol->SendMessage(count, 0x47, req);
4427     break;
4428   case GSM_7110OperatorLogo:
4429   case GSM_7110StartupLogo:
4430   case GSM_6210StartupLogo:
4431   default:
4432     return GE_NOTSUPPORTED;
4433   }
4434
4435   /* Wait for timeout or other error. */
4436   while (timeout != 0 && CurrentGetBitmapError == GE_BUSY ) {
4437           
4438     if (--timeout == 0)
4439       return (GE_TIMEOUT);
4440                     
4441     usleep (100000);
4442   }
4443
4444   CurrentGetBitmap=NULL;
4445
4446   return CurrentGetBitmapError;
4447 }
4448
4449 void N6110_ReplySetRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4450
4451   switch (MessageBuffer[3]) {
4452
4453   /* Set ringtone OK */
4454   case 0x37:       
4455 #ifdef DEBUG
4456     fprintf(stdout, _("Message: Ringtone set OK!\n"));
4457 #endif  
4458     CurrentRingtoneError=GE_NONE; 
4459     break;      
4460
4461   /* Set ringtone error */
4462   case 0x38:       
4463 #ifdef DEBUG
4464     fprintf(stdout, _("Message: Ringtone setting error !\n"));
4465 #endif  
4466     CurrentRingtoneError=GE_NOTSUPPORTED; 
4467     break;      
4468   }
4469 }
4470
4471 GSM_Error N6110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)
4472 {
4473   
4474   char req[FB61_MAX_RINGTONE_FRAME_LENGTH+10] =
4475       {N6110_FRAME_HEADER,
4476        0x36,
4477        0x00,  /* Location */
4478        0x00,0x78};
4479
4480   int size=FB61_MAX_RINGTONE_FRAME_LENGTH;
4481  
4482   /* Variables for preview uploading */
4483   unsigned char buffer[FB61_MAX_RINGTONE_FRAME_LENGTH+50];
4484   unsigned char buffer2[20];
4485   GSM_NetworkInfo NetworkInfo;
4486
4487   /* Setting ringtone with preview */
4488   if (ringtone->location==255) {
4489     buffer[0]=0x0c;
4490     buffer[1]=0x01;
4491     EncodeUDHHeader(buffer2, GSM_RingtoneUDH);
4492     memcpy(buffer+2,buffer2,buffer2[0]+1); //copying UDH
4493     *maxlength=GSM_PackRingtone(ringtone, buffer+2+buffer2[0]+1, &size); //packing ringtone
4494     Protocol->SendMessage(2+buffer2[0]+1+size, 0x12, buffer); //sending frame
4495     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
4496     sleep(1);
4497     return GE_NONE; //no answer from phone
4498   }
4499   
4500   *maxlength=GSM_PackRingtone(ringtone, req+7, &size);
4501
4502   req[4]=ringtone->location-1;
4503
4504   return NULL_SendMessageSequence
4505     (50, &CurrentRingtoneError, (size+7), 0x05, req);
4506 }
4507
4508 void N6110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4509
4510   int i;
4511   
4512   switch (MessageBuffer[4]) {
4513     case 0x00: /* location supported. We have ringtone */
4514
4515       /* Binary format used in N6150 */
4516       if (MessageBuffer[5]==0x0c && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) {
4517 #ifdef DEBUG
4518         fprintf(stdout,_("Message: ringtone \""));
4519 #endif      
4520
4521         /* Copying name */
4522         i=8;
4523         while (true) {
4524 #ifdef DEBUG
4525           if (MessageBuffer[i]!=0)
4526             fprintf(stdout,_("%c"),MessageBuffer[i]);
4527 #endif
4528           CurrentGetBinRingtone->name[i-8]=MessageBuffer[i];
4529           if (MessageBuffer[i]==0) break;
4530           i++;
4531         }
4532
4533 #ifdef DEBUG    
4534         fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1);
4535 #endif
4536       
4537         /* Looking for end */
4538         i=0;
4539         while (true) {
4540           if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
4541             i=i+2;break;
4542           }
4543           if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
4544             i=i+2;break;
4545           }
4546           i++;
4547           if (i==MessageLength) break;
4548         }
4549           
4550         /* Copying frame */
4551         memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3);
4552         CurrentGetBinRingtone->length=i-3;
4553       
4554         CurrentBinRingtoneError=GE_NONE;
4555         break;
4556       }
4557           
4558       /* Binary format used in N3210 */
4559       if (MessageBuffer[5]==0x10 && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) {      
4560
4561 #ifdef DEBUG
4562         fprintf(stdout,_("Message: ringtone \""));
4563 #endif      
4564
4565         /* Copying name */
4566         i=8;
4567         while (true) {
4568 #ifdef DEBUG
4569           if (MessageBuffer[i]!=0)
4570             fprintf(stdout,_("%c"),MessageBuffer[i]);
4571 #endif
4572           CurrentGetBinRingtone->name[i-8]=MessageBuffer[i];
4573           if (MessageBuffer[i]==0) break;
4574           i++;
4575         }
4576
4577 #ifdef DEBUG    
4578         fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1);
4579 #endif
4580
4581         /* Here changes to get full compatibility with binary format used in N6150 */
4582         MessageBuffer[3]=0;
4583         MessageBuffer[4]=0;
4584         MessageBuffer[5]=0x0c;
4585         MessageBuffer[6]=0x01;
4586         MessageBuffer[7]=0x2c;
4587
4588         /* Looking for end */
4589         i=0;
4590         while (true) {
4591           if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {
4592             i=i+2;break;
4593           }
4594           if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {
4595             i=i+2;break;
4596           }
4597           i++;
4598           if (i==MessageLength) break;
4599         }
4600           
4601         /* Copying frame */
4602         memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3);
4603
4604         CurrentGetBinRingtone->length=i-3;
4605             
4606         CurrentBinRingtoneError=GE_NONE;          
4607         break;
4608       }
4609
4610       /* Copying frame */
4611       memcpy(CurrentGetBinRingtone->frame,MessageBuffer,MessageLength);
4612
4613       CurrentGetBinRingtone->length=MessageLength;
4614
4615 #ifdef DEBUG    
4616       fprintf(stdout,_("Message: unknown binary format for ringtone received from location %i\n"),MessageBuffer[3]+1);
4617 #endif
4618       CurrentBinRingtoneError=GE_UNKNOWNMODEL;
4619       break;
4620
4621     default:
4622
4623 #ifdef DEBUG
4624       fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1);
4625 #endif
4626
4627       CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;  
4628   }
4629 }
4630
4631 GSM_Error N6110_GetBinRingTone(GSM_BinRingtone *ringtone)
4632 {
4633   unsigned char req[] = { 0x00,0x01,0x9e,
4634                           0x00 }; //location
4635
4636   GSM_Error error;
4637   
4638   CurrentGetBinRingtone=ringtone;
4639   
4640   error=N6110_EnableExtendedCommands(0x01);
4641   if (error!=GE_NONE) return error;
4642
4643   req[3]=ringtone->location-1;
4644   
4645   return NULL_SendMessageSequence
4646     (50, &CurrentBinRingtoneError, 4, 0x40, req);
4647 }
4648
4649 void N6110_ReplySetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4650
4651   switch (MessageBuffer[4]) {
4652     case 0x00: /* location supported. We set ringtone */
4653 #ifdef DEBUG
4654       fprintf(stdout,_("Message: downloaded ringtone set at location %i\n"),MessageBuffer[3]+1);
4655 #endif
4656       CurrentBinRingtoneError=GE_NONE;
4657       break;
4658
4659     default:
4660 #ifdef DEBUG
4661       fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1);
4662 #endif
4663       CurrentBinRingtoneError=GE_NOTSUPPORTED;    
4664       break;
4665   }
4666 }
4667
4668 GSM_Error N6110_SetBinRingTone(GSM_BinRingtone *ringtone)
4669 {
4670   unsigned char req[1000] = { 0x00,0x01,0xa0};
4671
4672   GSM_Error error;
4673
4674   GSM_BinRingtone ring;
4675
4676   /* Must be sure, that can upload ringtone to this phone */
4677   ring.location=ringtone->location;
4678   error=N6110_GetBinRingTone(&ring);
4679   if (error!=GE_NONE) return error;
4680     
4681   error=N6110_EnableExtendedCommands(0x01);
4682   if (error!=GE_NONE) return error;
4683   
4684   memcpy(req+3,ringtone->frame,ringtone->length);
4685
4686   req[3]=ringtone->location-1;
4687   
4688   return NULL_SendMessageSequence
4689     (50, &CurrentBinRingtoneError, ringtone->length+3, 0x40, req);
4690 }
4691
4692 #endif /* UCLINUX */
4693
4694 GSM_Error N6110_Reset(unsigned char type)
4695 {  
4696   return N6110_EnableExtendedCommands(type);
4697 }
4698
4699 void N6110_Dispatch0x01Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4700
4701   int count;
4702 #ifdef DEBUG
4703         int tmp;
4704 #endif
4705           
4706   switch (MessageBuffer[3]) {
4707
4708   /* Unknown message - it has been seen after the 0x07 message (call
4709      answered). Probably it has similar meaning. If you can solve
4710      this - just mail me. Pavel Janík ml.
4711
4712      The message looks like this:
4713
4714      Msg Destination: PC
4715      Msg Source: Phone
4716      Msg Type: 01
4717      Msg Unknown: 00
4718      Msg Len: 0e
4719
4720      Phone: [01 ][08 ][00 ] is the header of the frame
4721
4722      [03 ] is the call message subtype
4723
4724      [05 ] is the call sequence number
4725
4726      [05 ] unknown 
4727
4728      [00 ][01 ][03 ][02 ][91][00] are unknown but has been
4729      seen in the Incoming call message (just after the
4730      caller's name from the phonebook). But never change
4731      between phone calls :-(
4732   */
4733
4734   /* This may mean sequence number of 'just made' call - CK */
4735   case 0x02:
4736
4737 #ifdef DEBUG
4738     fprintf(stdout, _("Message: Call message, type 0x02:"));
4739     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));
4740 #endif /* DEBUG */
4741
4742     break;
4743
4744   /* Possibly call OK */
4745   /* JD: I think that this means "call in progress" (incomming or outgoing) */
4746   case 0x03:
4747     
4748 #ifdef DEBUG
4749     fprintf(stdout, _("Message: Call message, type 0x03:"));
4750     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
4751     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));
4752 #endif /* DEBUG */
4753     
4754     CurrentCallSequenceNumber=MessageBuffer[4];
4755 #ifndef UCLINUX
4756     CurrentIncomingCall[0]='D';
4757 #endif /* UCLINUX */
4758     if (CurrentCallPassup) CurrentCallPassup('D');
4759
4760     break;
4761
4762   /* Remote end has gone away before you answer the call.  Probably your
4763      mother-in-law or banker (which is worse?) ... */
4764   case 0x04:
4765
4766 #ifdef DEBUG
4767     fprintf(stdout, _("Message: Remote end hang up.\n"));
4768     fprintf(stdout, _("   Sequence nr. of the call: %d, error: %i"), MessageBuffer[4],MessageBuffer[6]);
4769
4770     switch (MessageBuffer[6]) {
4771       case 28: fprintf(stdout,_(" (info \"Invalid phone number\")"));break;
4772       case 34: fprintf(stdout,_(" (info \"Network busy\")"));break;
4773       case 42: fprintf(stdout,_(" (info \"Network busy\")"));break;
4774       case 47: fprintf(stdout,_(" (info \"Error in connection\")"));break;
4775       case 50: fprintf(stdout,_(" (info \"Check operator services\")"));break;       case 76: fprintf(stdout,_(" (info \"Check operator services\")"));break;
4776       case 111: fprintf(stdout,_(" (info \"Error in connection\")"));break;
4777     }
4778       
4779     fprintf(stdout,_("\n   For more details with errors see netmonitor manual (test 39) on www.marcin-wiacek.topnet.pl"));
4780     fprintf(stdout,_("\n   If know their meaning, GSM specs decribing them, contact with me on marcin-wiacek@topnet.pl. THX\n"));
4781 #endif /* DEBUG */
4782
4783 #ifndef UCLINUX
4784     CurrentIncomingCall[0] = ' ';
4785 #endif /* UCLINUX */
4786     if (CurrentCallPassup) CurrentCallPassup(' ');
4787
4788     break;
4789
4790   /* Incoming call alert */
4791   case 0x05:
4792
4793 #ifdef DEBUG
4794     fprintf(stdout, _("Message: Incoming call alert:\n"));
4795
4796     /* We can have more then one call ringing - we can distinguish between
4797        them */
4798
4799     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
4800     fprintf(stdout, _("   Number: "));
4801
4802     count=MessageBuffer[6];
4803
4804     for (tmp=0; tmp <count; tmp++)
4805       fprintf(stdout, "%c", MessageBuffer[7+tmp]);
4806
4807     fprintf(stdout, "\n");
4808
4809     fprintf(stdout, _("   Name: "));
4810
4811     for (tmp=0; tmp <MessageBuffer[7+count]; tmp++)
4812       fprintf(stdout, "%c", MessageBuffer[8+count+tmp]);
4813
4814     fprintf(stdout, "\n");
4815 #endif /* DEBUG */
4816
4817     count=MessageBuffer[6];
4818
4819 #ifndef UCLINUX
4820     CurrentIncomingCall[0] = 0;
4821     for (tmp=0; tmp <count; tmp++)
4822       sprintf(CurrentIncomingCall, "%s%c", CurrentIncomingCall, MessageBuffer[7+tmp]);
4823 #endif /* UCLINUX */
4824
4825     break;
4826
4827   /* Call answered. Probably your girlfriend...*/
4828   case 0x07:
4829
4830 #ifdef DEBUG
4831     fprintf(stdout, _("Message: Call answered.\n"));
4832     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
4833 #endif /* DEBUG */
4834
4835     break;
4836
4837   /* Call ended. Girlfriend is girlfriend, but time is money :-) */
4838   case 0x09:
4839
4840 #ifdef DEBUG
4841     fprintf(stdout, _("Message: Call ended by your phone.\n"));
4842     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
4843 #endif /* DEBUG */
4844
4845     break;
4846
4847   /* This message has been seen with the message of subtype 0x09
4848      after I hang the call.
4849
4850   Msg Destination: PC
4851   Msg Source: Phone
4852   Msg Type: 01 
4853   Msg Unknown: 00
4854   Msg Len: 08
4855   Phone: [01 ][08 ][00 ][0a ][04 ][87 ][01 ][42B][1a ][c2 ]
4856
4857   What is the meaning of 87? Can you spell some magic light into
4858   this issue?
4859
4860   */
4861
4862   /* Probably means call over - CK */
4863   case 0x0a:
4864
4865 #ifdef DEBUG
4866     fprintf(stdout, _("Message: Call message, type 0x0a:"));
4867     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
4868     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));
4869 #endif /* DEBUG */
4870
4871 #ifndef UCLINUX
4872     CurrentIncomingCall[0] = ' ';
4873 #endif /* UCLINUX */
4874     if (CurrentCallPassup) CurrentCallPassup(' ');
4875
4876     break;
4877
4878   case 0x40:
4879
4880 #ifdef DEBUG
4881       fprintf(stdout, _("Message: Answer for send DTMF or dial voice command\n"));
4882 #endif
4883
4884 #ifndef UCLINUX
4885     if (CurrentSendDTMFError!=GE_NONE) CurrentSendDTMFError=GE_NONE;
4886 #endif /* UCLINUX */
4887
4888     if (CurrentDialVoiceError!=GE_NONE) CurrentDialVoiceError=GE_NONE;
4889
4890     break;
4891      
4892   default:
4893
4894 #ifdef DEBUG
4895     fprintf(stdout, _("Message: Unknown message of type 0x01\n"));
4896 #endif /* DEBUG */
4897     AppendLogText("Unknown msg\n",false);
4898
4899     break;      /* Visual C Don't like empty cases */
4900   }
4901 }
4902
4903 #ifndef UCLINUX
4904
4905 static void N6110_Dispatch0x03Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
4906
4907   int tmp, count;
4908     
4909   switch (MessageBuffer[3]) {
4910
4911   case 0x04:
4912
4913     /* AFAIK, this frame isn't used anywhere - it's rather for testing :-) */
4914     /* If you want see, if it works with your phone make something like that: */
4915
4916     /* unsigned char connect5[] = {N6110_FRAME_HEADER, 0x03}; */
4917     /* Protocol->SendMessage(4, 0x04, connect5); */
4918
4919     /*                                        Marcin-Wiacek@TopNet.PL */
4920     
4921 #if defined(WIN32) || defined(UCLINUX)
4922     sprintf(Current_IMEI, "%s", MessageBuffer+5);
4923     sprintf(Current_Model, "%s", MessageBuffer+21);
4924     sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35);
4925 #else
4926     snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+5);
4927     snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+21);
4928     snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35);
4929 #endif
4930
4931 #ifdef DEBUG
4932     fprintf(stdout, _("Message: Mobile phone identification received:\n"));
4933     fprintf(stdout, _("   IMEI: %s\n"), Current_IMEI);
4934     fprintf(stdout, _("   Model: %s\n"), Current_Model);
4935     fprintf(stdout, _("   Production Code: %s\n"), MessageBuffer+27);
4936     fprintf(stdout, _("   HW: %s\n"), MessageBuffer+35);
4937     fprintf(stdout, _("   Firmware: %s\n"), MessageBuffer+41);
4938 #endif /* DEBUG */
4939
4940     break;
4941
4942   /* Get group data */    
4943   /* [ID],[name_len],[name].,[ringtone],[graphicon],[lenhi],[lenlo],[bitmap] */
4944   case 0x11:   
4945  
4946     if (CurrentGetBitmap!=NULL) {
4947       if (CurrentGetBitmap->number==MessageBuffer[4]) {
4948         count=MessageBuffer[5];
4949         memcpy(CurrentGetBitmap->text,MessageBuffer+6,count);
4950         CurrentGetBitmap->text[count]=0;
4951
4952 #ifdef DEBUG    
4953         fprintf(stdout, _("Message: Caller group datas\n"));
4954         fprintf(stdout, _("Caller group name: %s\n"),CurrentGetBitmap->text);
4955 #endif /* DEBUG */
4956
4957         count+=6;
4958
4959         CurrentGetBitmap->ringtone=MessageBuffer[count++];
4960 #ifdef DEBUG    
4961         fprintf(stdout, _("Caller group ringtone ID: %i"),CurrentGetBitmap->ringtone);
4962         if (CurrentGetBitmap->ringtone==16) fprintf(stdout,_(" (default)"));
4963         fprintf(stdout,_("\n"));
4964 #endif /* DEBUG */
4965
4966         CurrentGetBitmap->enabled=(MessageBuffer[count++]==1);
4967 #ifdef DEBUG    
4968         fprintf(stdout, _("Caller group logo "));
4969         if (CurrentGetBitmap->enabled)
4970           fprintf(stdout, _("enabled \n"));
4971         else
4972           fprintf(stdout, _("disabled \n"));
4973 #endif /* DEBUG */      
4974
4975         CurrentGetBitmap->size=MessageBuffer[count++]<<8;
4976         CurrentGetBitmap->size+=MessageBuffer[count++];
4977 #ifdef DEBUG    
4978         fprintf(stdout, _("Bitmap size=%i\n"),CurrentGetBitmap->size);
4979 #endif /* DEBUG */
4980
4981         count++;
4982         CurrentGetBitmap->width=MessageBuffer[count++];
4983         CurrentGetBitmap->height=MessageBuffer[count++];
4984         count++;
4985         tmp=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
4986         if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp;
4987         memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
4988         CurrentGetBitmapError=GE_NONE;
4989       } else {
4990 #ifdef DEBUG    
4991         fprintf(stdout, _("Message: Caller group datas received, but group number does not match (%i is not %i)\n"),MessageBuffer[4],CurrentGetBitmap->number);
4992 #endif
4993       }
4994     } else {
4995 #ifdef DEBUG
4996       fprintf(stdout, _("Message: Caller group data received but not requested!\n"));
4997 #endif
4998     }
4999     break;
5000
5001   /* Get group data error */
5002   case 0x12:   
5003       
5004     CurrentGetBitmapError=GE_UNKNOWN;   
5005 #ifdef DEBUG
5006     fprintf(stdout, _("Message: Error attempting to get caller group data.\n"));
5007 #endif   
5008     break;
5009
5010   /* Set group data OK */      
5011   case 0x14:   
5012       
5013     CurrentSetBitmapError=GE_NONE;      
5014 #ifdef DEBUG
5015     fprintf(stdout, _("Message: Caller group data set correctly.\n"));
5016 #endif
5017     break;
5018
5019   /* Set group data error */
5020   case 0x15:   
5021       
5022     CurrentSetBitmapError=GE_UNKNOWN;      
5023 #ifdef DEBUG
5024     fprintf(stdout, _("Message: Error attempting to set caller group data\n"));
5025 #endif
5026     break;  
5027   
5028   default:
5029
5030 #ifdef DEBUG
5031     fprintf(stdout, _("Message: Unknown message of type 0x03\n"));
5032 #endif /* DEBUG */
5033     AppendLogText("Unknown msg\n",false);
5034
5035     break;      /* Visual C Don't like empty cases */
5036   }
5037 }
5038
5039 static void N6110_Dispatch0x05Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5040
5041   int tmp, count, length;
5042   bool issupported;
5043
5044 #ifdef DEBUG
5045   int i;
5046 #endif
5047
5048   switch (MessageBuffer[3]) {
5049
5050   /* Startup Logo */
5051   case 0x17:  
5052
5053 #ifdef DEBUG
5054     fprintf(stdout, _("Message: Startup Logo, welcome note and dealer welcome note received.\n"));
5055 #endif
5056
5057     if (CurrentGetBitmap!=NULL) {
5058        
5059       issupported=false;
5060        
5061       count=5;
5062        
5063       for (tmp=0;tmp<MessageBuffer[4];tmp++){
5064         switch (MessageBuffer[count++]) {
5065         case 0x01:
5066           if (CurrentGetBitmap->type==GSM_StartupLogo) {
5067             CurrentGetBitmap->height=MessageBuffer[count++];
5068             CurrentGetBitmap->width=MessageBuffer[count++];
5069             CurrentGetBitmap->size=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
5070             length=CurrentGetBitmap->size;
5071             memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,length);
5072           } else {
5073             length=MessageBuffer[count++];
5074             length=length*MessageBuffer[count++]/8;
5075           }
5076           count+=length;
5077 #ifdef DEBUG
5078           fprintf(stdout, _("Startup logo supported - "));
5079           if (length!=0) { fprintf(stdout, _("currently set\n"));   }
5080                     else { fprintf(stdout, _("currently empty\n")); }
5081 #endif
5082           if (CurrentGetBitmap->type==GSM_StartupLogo) issupported=true;
5083           break;
5084         case 0x02:
5085           length=MessageBuffer[count];
5086           if (CurrentGetBitmap->type==GSM_WelcomeNoteText) {
5087             memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length);
5088             CurrentGetBitmap->text[length]=0;
5089           }
5090 #ifdef DEBUG
5091           fprintf(stdout, _("Startup Text supported - "));
5092           if (length!=0)
5093           {
5094             fprintf(stdout, _("currently set to \""));
5095             for (i=0;i<length;i++) fprintf(stdout, _("%c"),MessageBuffer[count+1+i]);
5096             fprintf(stdout, _("\"\n"));
5097           } else {
5098             fprintf(stdout, _("currently empty\n"));
5099           }
5100 #endif
5101           count+=length+1;
5102           if (CurrentGetBitmap->type==GSM_WelcomeNoteText) issupported=true;
5103           break;
5104         case 0x03:
5105           length=MessageBuffer[count];
5106           if (CurrentGetBitmap->type==GSM_DealerNoteText) {
5107             memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length);
5108             CurrentGetBitmap->text[length]=0;
5109           }
5110 #ifdef DEBUG
5111           fprintf(stdout, _("Dealer Welcome supported - "));
5112           if (length!=0)
5113           {
5114             fprintf(stdout, _("currently set to \""));
5115             for (i=0;i<length;i++) fprintf(stdout, _("%c"),MessageBuffer[count+1+i]);
5116             fprintf(stdout, _("\"\n"));
5117           } else {
5118             fprintf(stdout, _("currently empty\n"));
5119           }
5120 #endif
5121           count+=length+1;
5122           if (CurrentGetBitmap->type==GSM_DealerNoteText) issupported=true;
5123           break;
5124         }
5125       }
5126       if (issupported) CurrentGetBitmapError=GE_NONE;
5127                   else CurrentGetBitmapError=GE_NOTSUPPORTED;
5128     } else {
5129 #ifdef DEBUG
5130       fprintf(stdout, _("Message: Startup logo received but not requested!\n"));
5131 #endif
5132     }
5133     break;
5134
5135   /* Set startup OK */
5136   case 0x19:   
5137     
5138     CurrentSetBitmapError=GE_NONE;    
5139 #ifdef DEBUG
5140     fprintf(stdout, _("Message: Startup logo, welcome note or dealer welcome note correctly set.\n"));
5141 #endif  
5142     break;      
5143
5144   /* Set Operator Logo OK */
5145   case 0x31:   
5146       
5147 #ifdef DEBUG
5148     fprintf(stdout, _("Message: Operator logo correctly set.\n"));
5149 #endif  
5150
5151     CurrentSetBitmapError=GE_NONE;      
5152     break;
5153
5154   /* Set Operator Logo Error */      
5155   case 0x32:  
5156       
5157 #ifdef DEBUG
5158     fprintf(stdout, _("Message: Error setting operator logo!\n"));
5159 #endif
5160
5161     CurrentSetBitmapError=GE_UNKNOWN;        
5162     break;
5163
5164   /* Operator Logo */
5165   /* [location],[netcode x 3],[lenhi],[lenlo],[bitmap] */ 
5166   case 0x34:
5167  
5168     if (CurrentGetBitmap!=NULL) {
5169
5170       count=5;  /* Location ignored. */
5171
5172       DecodeNetworkCode(MessageBuffer+count, CurrentGetBitmap->netcode);
5173       count=count+3;
5174
5175 #ifdef DEBUG
5176       fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),
5177                            CurrentGetBitmap->netcode,
5178                            GSM_GetNetworkName(CurrentGetBitmap->netcode));
5179 #endif  
5180
5181       CurrentGetBitmap->size=MessageBuffer[count++]<<8;
5182       CurrentGetBitmap->size+=MessageBuffer[count++];
5183       count++;
5184       CurrentGetBitmap->width=MessageBuffer[count++];
5185       CurrentGetBitmap->height=MessageBuffer[count++];
5186       count++;
5187       tmp=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
5188       if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp;
5189       memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);
5190       CurrentGetBitmapError=GE_NONE;
5191     } else {
5192 #ifdef DEBUG
5193       fprintf(stdout, _("Message: Operator logo received but not requested!\n"));
5194 #endif
5195     }
5196       
5197     break;
5198
5199   /* Get op logo error */      
5200   case 0x35:
5201      
5202 #ifdef DEBUG
5203     fprintf(stdout, _("Message: Error getting operator logo!\n"));
5204 #endif  
5205     CurrentGetBitmapError=GE_UNKNOWN; 
5206     break;
5207
5208   default:
5209
5210 #ifdef DEBUG
5211     fprintf(stdout, _("Message: Unknown message of type 0x05\n"));
5212 #endif /* DEBUG */
5213     AppendLogText("Unknown msg\n",false);
5214
5215     break;
5216   }
5217 }
5218
5219 static void N6110_Dispatch0x06Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5220
5221   int tmp;
5222   unsigned char output[160];
5223
5224 #ifdef DEBUG
5225   int i;
5226 #endif
5227     
5228   switch (MessageBuffer[3]) {
5229
5230   case 0x05:
5231
5232     /* MessageBuffer[3] = 0x05
5233        MessageBuffer[4] = 0x00
5234        MessageBuffer[5] = 0x0f
5235        MessageBuffer[6] = 0x03
5236        MessageBuffer[7] = length of packed message
5237
5238        This is all I have seen - Gerry Anderson */
5239
5240     tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, MessageBuffer+8, output);
5241
5242 #ifdef DEBUG
5243
5244     fprintf(stdout, _("Message from Network operator: "));
5245
5246     for (i=0; i<tmp; i++)
5247        fprintf(stdout, "%c", DecodeWithDefaultAlphabet(output[i]));
5248
5249     fprintf(stdout, "\n");
5250
5251 #endif /* DEBUG */
5252
5253     break;
5254
5255   default:
5256
5257 #ifdef DEBUG
5258     fprintf(stdout, _("Message: Unknown message of type 0x06\n"));
5259 #endif /* DEBUG */
5260     AppendLogText("Unknown msg\n",false);
5261
5262     break;
5263   }
5264 }
5265
5266 static void N6110_Dispatch0x09Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5267     
5268   switch (MessageBuffer[3]) {
5269     
5270   case 0x80:    
5271 #ifdef DEBUG
5272     fprintf(stdout, _("Message: SIM card login\n"));
5273 #endif
5274     break;
5275
5276   case 0x81:    
5277 #ifdef DEBUG
5278     fprintf(stdout, _("Message: SIM card logout\n"));
5279 #endif
5280     break;
5281       
5282   default:
5283 #ifdef DEBUG
5284     fprintf(stdout, _("Unknown message of type 0x09.\n"));      
5285 #endif
5286     AppendLogText("Unknown msg\n",false);
5287     break;
5288   }
5289 }
5290
5291 static void N6110_Dispatch0x13Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5292
5293   switch(MessageBuffer[3]) {
5294     
5295   case 0x6a:
5296
5297 #ifdef DEBUG
5298     fprintf(stdout, _("Message: Calendar Alarm active\n"));
5299     fprintf(stdout, _("   Item number: %d\n"), MessageBuffer[4]);
5300 #endif /* DEBUG */
5301
5302   default:
5303 #ifdef DEBUG
5304     fprintf(stdout, _("Unknown message of type 0x13.\n"));      
5305 #endif
5306     AppendLogText("Unknown msg\n",false);
5307     break;
5308   }
5309 }
5310
5311 #endif /* UCLINUX */
5312
5313 void N6110_Dispatch0x40Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5314
5315   int i;
5316   
5317   switch(MessageBuffer[2]) {
5318
5319   case 0x02:
5320
5321 #ifdef DEBUG
5322     fprintf(stdout, _("Message: ACK for simlock opening part 1\n"));
5323 #endif /* DEBUG */
5324     
5325     CurrentMagicError=GE_NONE;
5326     break;
5327     
5328   case 0x7c:
5329
5330 #ifdef DEBUG
5331     fprintf(stdout, _("Message: Answer for call commands.\n"));
5332 #endif
5333     
5334     CurrentDialVoiceError=GE_NONE;      
5335     break;
5336       
5337   case 0x81:
5338
5339 #ifdef DEBUG
5340     fprintf(stdout, _("Message: ACK for simlock opening part 2\n"));
5341 #endif /* DEBUG */
5342     
5343     CurrentMagicError=GE_NONE;
5344     break;
5345
5346   case 0x82:
5347
5348 #ifdef DEBUG
5349       fprintf(stdout, _("Message: ACK for simlock closing\n"));
5350 #endif /* DEBUG */
5351     
5352     CurrentMagicError=GE_NONE;
5353     break;
5354
5355   case 0xd4:
5356
5357     switch (MessageBuffer[5]) {
5358       case 0xa0:
5359 #ifdef DEBUG
5360         fprintf(stdout,_("Message: EEPROM contest received\n"));
5361 #endif
5362
5363         if (MessageBuffer[8]!=0x00) {
5364           for (i=9;i<MessageLength;i++) {
5365             fprintf(stdout,_("%c"), MessageBuffer[i]);
5366         }
5367
5368         CurrentMagicError=GE_NONE;
5369       }
5370       
5371       break;
5372     }
5373       
5374 #ifdef DEBUG
5375     fprintf(stdout, _("Unknown message of type 0x40.\n"));
5376 #endif /* DEBUG */
5377     AppendLogText("Unknown msg\n",false);      
5378     break;
5379
5380 #ifndef UCLINUX
5381   case 0xcf:
5382
5383     N6110_DisplayTestsInfo(MessageBuffer);
5384     break;
5385 #endif /* UCLINUX */
5386       
5387   default:
5388
5389 #ifdef DEBUG
5390     fprintf(stdout, _("Unknown message of type 0x40.\n"));
5391 #endif /* DEBUG */
5392     AppendLogText("Unknown msg\n",false);
5393     break;      /* Visual C Don't like empty cases */
5394   }
5395 }
5396
5397 #ifndef UCLINUX
5398
5399 static void N6110_Dispatch0x47Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5400
5401   int count;
5402   
5403   switch(MessageBuffer[3]) {
5404     
5405   case 0x02:
5406
5407     count=5;
5408     
5409     if (MessageBuffer[5]!=0) {
5410       strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(MessageBuffer+5,true));
5411
5412       while (MessageBuffer[count]!=0) {
5413         count++;
5414       }
5415
5416       count++;
5417     } else {
5418       strcpy(CurrentGetBitmap->Sender,"\0");
5419
5420       count+=3;
5421     }
5422
5423     memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,MessageBuffer[count]);
5424     CurrentGetBitmap->text[MessageBuffer[count]]=0;
5425
5426     if (MessageBuffer[count]!=0)
5427       count+=MessageBuffer[count];
5428
5429     count++;
5430
5431 #ifdef DEBUG
5432     fprintf(stdout,_("Picture Image received, text \"%s\", sender %s\n"),CurrentGetBitmap->text,CurrentGetBitmap->Sender);
5433 #endif
5434
5435     CurrentGetBitmap->width=MessageBuffer[count+1];
5436     CurrentGetBitmap->height=MessageBuffer[count+2]; 
5437     CurrentGetBitmap->size=CurrentGetBitmap->height*CurrentGetBitmap->width/8;
5438       
5439     memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count+4,CurrentGetBitmap->size);
5440       
5441     CurrentGetBitmapError=GE_NONE;
5442     break;
5443
5444   case 0x04:
5445
5446 #ifdef DEBUG
5447     fprintf(stdout,_("Getting or setting Picture Image - OK\n"));
5448 #endif
5449     CurrentSetBitmapError=GE_NONE;
5450     CurrentGetBitmapError=GE_NONE;
5451     break;      
5452
5453   case 0x05:
5454
5455 #ifdef DEBUG
5456     fprintf(stdout,_("Setting Picture Image - invalid location or other error\n"));
5457 #endif
5458     CurrentSetBitmapError=GE_UNKNOWN;
5459     break;      
5460
5461   case 0x06:
5462
5463 #ifdef DEBUG
5464     fprintf(stdout,_("Getting Picture Image - invalid location or other error\n"));
5465 #endif
5466     CurrentGetBitmapError=GE_UNKNOWN;
5467     break;      
5468
5469   default:
5470
5471 #ifdef DEBUG
5472     fprintf(stdout, _("Unknown message of type 0x47.\n"));
5473 #endif /* DEBUG */
5474     AppendLogText("Unknown msg\n",false);
5475     break;      /* Visual C Don't like empty cases */
5476   }
5477 }
5478
5479 #endif /* UCLINUX */
5480
5481 void N6110_DispatchACKMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5482   char buffer[50];
5483   
5484   sprintf(buffer,"Received ACK %02x %02x\n",MessageBuffer[0],MessageBuffer[1]);
5485   AppendLog(buffer,strlen(buffer),false);
5486
5487 #ifdef DEBUG
5488   fprintf(stdout, _("[Received Ack of type %02x, seq: %2x]\n"), MessageBuffer[0],
5489                                                                 MessageBuffer[1]);
5490 #endif /* DEBUG */
5491   
5492   CurrentLinkOK = true;
5493 }
5494
5495 static void N6110_Dispatch0xD0Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5496    
5497 #ifdef DEBUG
5498   fprintf(stdout, _("Message: The phone is powered on - seq 1.\n"));
5499 #endif /* DEBUG */
5500
5501 }
5502
5503 /* This function is used for parsing the RLP frame into fields. */
5504 void N6110_RX_HandleRLPMessage(u8 *MessageBuffer)
5505 {
5506
5507   RLP_F96Frame frame;
5508   int count;
5509   int valid = true;
5510
5511   /* We do not need RLP frame parsing to be done when we do not have callback
5512      specified. */
5513   if (CurrentRLP_RXCallback == NULL)
5514     return;
5515     
5516   /* Anybody know the official meaning of the first two bytes?
5517      Nokia 6150 sends junk frames starting D9 01, and real frames starting
5518      D9 00. We'd drop the junk frames anyway because the FCS is bad, but
5519      it's tidier to do it here. We still need to call the callback function
5520      to give it a chance to handle timeouts and/or transmit a frame */
5521   if (MessageBuffer[0] == 0xd9 && MessageBuffer[1] == 0x01)
5522     valid = false;
5523
5524   /* Nokia uses 240 bit frame size of RLP frames as per GSM 04.22
5525      specification, so Header consists of 16 bits (2 bytes). See section 4.1
5526      of the specification. */
5527     
5528   frame.Header[0] = MessageBuffer[2];
5529   frame.Header[1] = MessageBuffer[3];
5530
5531   /* Next 200 bits (25 bytes) contain the Information. We store the
5532      information in the Data array. */
5533
5534   for (count = 0; count < 25; count ++)
5535     frame.Data[count] = MessageBuffer[4 + count];
5536
5537   /* The last 24 bits (3 bytes) contain FCS. */
5538
5539   frame.FCS[0] = MessageBuffer[29];
5540   frame.FCS[1] = MessageBuffer[30];
5541   frame.FCS[2] = MessageBuffer[31];
5542
5543   /* Here we pass the frame down in the input stream. */
5544   CurrentRLP_RXCallback(valid ? &frame : NULL);
5545 }
5546
5547 static void N6110_Dispatch0xF4Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5548
5549 #ifdef DEBUG
5550   fprintf(stdout, _("Message: The phone is powered on - seq 2.\n"));
5551 #endif /* DEBUG */
5552
5553 }
5554
5555 #ifndef UCLINUX
5556
5557 void N6110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5558
5559   GSM_SMSMessage NullSMS;
5560
5561   switch (MessageBuffer[6]) {
5562
5563     case 0x00: NullSMS.Type = GST_SMS; NullSMS.folder = GST_INBOX; break;
5564     case 0x01: NullSMS.Type = GST_DR;  NullSMS.folder = GST_INBOX; break;
5565
5566     /* Is it possible ? */
5567     case 0x02: NullSMS.Type = GST_SMS; NullSMS.folder = GST_OUTBOX; break;      
5568     default:   NullSMS.Type = GST_UN;                               break;
5569   }
5570
5571 #ifdef DEBUG
5572   if (NullSMS.Type == GST_DR)
5573     fprintf(stdout, _("Message: SMS Message (Report) Received\n"));
5574   else 
5575     fprintf(stdout, _("Message: SMS Message Received\n"));  
5576 #endif /* DEBUG */
5577
5578   GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+7, MessageLength-7);
5579
5580 #ifdef DEBUG
5581   fprintf(stdout, _("\n"));      
5582 #endif /* DEBUG */
5583 }
5584
5585 #endif /* UCLINUX */
5586
5587 void N6110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
5588
5589   bool unknown=false;
5590
5591   /* Switch on the basis of the message type byte */
5592   switch (MessageType) {
5593           
5594   /* Call information */
5595   case 0x01:
5596
5597     N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);
5598     break;
5599
5600 #ifndef UCLINUX
5601   /* SMS handling */
5602   case 0x02:
5603     switch (MessageBuffer[3]) {
5604       case 0x02:
5605       case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;
5606       case 0x10:N6110_ReplyIncomingSMS(MessageLength,MessageBuffer,MessageType);break;
5607       case 0x21:N6110_ReplySetCellBroadcast(MessageLength, MessageBuffer, MessageType);break;
5608       case 0x23:N6110_ReplyReadCellBroadcast(MessageLength, MessageBuffer, MessageType);break;
5609       case 0x31:N6110_ReplySetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
5610       case 0x34:
5611       case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;
5612       default  :unknown=true;break;
5613     }
5614     break;
5615 #endif /* UCLINUX */
5616
5617   /* Phonebook handling */
5618   case 0x03:
5619     switch (MessageBuffer[3]) {
5620       case 0x02:
5621       case 0x03:N6110_ReplyGetMemoryLocation(MessageLength,MessageBuffer,MessageType);break;
5622       case 0x05:
5623       case 0x06:N6110_ReplyWritePhonebookLocation(MessageLength,MessageBuffer,MessageType);break;
5624       case 0x08:
5625       case 0x09:N6110_ReplyGetMemoryStatus(MessageLength,MessageBuffer,MessageType);break;
5626       case 0x17:
5627       case 0x18:N6110_ReplyGetSpeedDial(MessageLength,MessageBuffer,MessageType);break;
5628       case 0x1a:
5629       case 0x1b:N6110_ReplySetSpeedDial(MessageLength,MessageBuffer,MessageType);break;
5630 #ifndef UCLINUX
5631       default  :N6110_Dispatch0x03Message(MessageLength,MessageBuffer,MessageType);break;
5632 #endif /* UCLINUX */
5633     }
5634     break;
5635
5636   /* Phone status */     
5637   case 0x04:
5638     switch (MessageBuffer[3]) {
5639       case 0x02:N6110_ReplyRFBatteryLevel(MessageLength,MessageBuffer,MessageType);break;
5640       default  :unknown=true;break;
5641     }
5642     break;
5643       
5644 #ifndef UCLINUX
5645   /* Startup Logo, Operator Logo and Profiles. */
5646   case 0x05:
5647     switch (MessageBuffer[3]) {
5648       case 0x11:N6110_ReplySetProfile    (MessageLength,MessageBuffer,MessageType);break;
5649       case 0x14:N6110_ReplyGetProfile    (MessageLength,MessageBuffer,MessageType);break;
5650       case 0x1b:N6110_ReplyGetProfile    (MessageLength,MessageBuffer,MessageType);break;
5651       case 0x1d:N6110_ReplySetProfile    (MessageLength,MessageBuffer,MessageType);break;
5652       case 0x37:N6110_ReplySetRingtone   (MessageLength,MessageBuffer,MessageType);break;
5653       case 0x38:N6110_ReplySetRingtone   (MessageLength,MessageBuffer,MessageType);break;
5654       default  :N6110_Dispatch0x05Message(MessageLength,MessageBuffer,MessageType);break;
5655     }
5656     break;
5657
5658   /* Network Operator Message to handset -> Gerry Anderson & prepaid info */
5659   /* Call diverts */
5660   case 0x06:
5661     switch (MessageBuffer[3]) {
5662       case 0x02:
5663       case 0x03:N6110_ReplyCallDivert    (MessageLength,MessageBuffer,MessageType);break;
5664       default  :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;
5665     }
5666     break;
5667
5668   /* Security code requests */
5669   case 0x08:
5670     switch (MessageBuffer[3]) {
5671       case 0x08:N6110_ReplyGetSecurityCodeStatus(MessageLength,MessageBuffer,MessageType);break;
5672       case 0x0b:N6110_ReplyEnterSecurityCode    (MessageLength,MessageBuffer,MessageType);break;
5673       default  :N6110_ReplyEnterSecurityCode    (MessageLength,MessageBuffer,MessageType);break;
5674     }
5675     break;
5676
5677   /* SIM login */
5678   case 0x09:
5679
5680     N6110_Dispatch0x09Message(MessageLength, MessageBuffer, MessageType);
5681     break;
5682
5683   /* Network info */
5684   case 0x0a:
5685     switch (MessageBuffer[3]) {
5686       case 0x71:N6110_ReplyGetNetworkInfo(MessageLength,MessageBuffer,MessageType);break;
5687       default  :unknown=true;break;
5688     }
5689     break;
5690
5691   /* Simulating key pressing */
5692   case 0x0c:
5693     switch (MessageBuffer[3]) {
5694       case 0x43:N6110_ReplyPressKey(MessageLength,MessageBuffer,MessageType);break;
5695       default  :unknown=true;break;
5696     }
5697     break;
5698
5699   /* Display */
5700   case 0x0d:
5701     switch (MessageBuffer[3]) {
5702       case 0x50:N6110_ReplyDisplayOutput   (MessageLength,MessageBuffer,MessageType);break;
5703       case 0x52:N6110_ReplyGetDisplayStatus(MessageLength,MessageBuffer,MessageType);break;
5704       case 0x54:N6110_ReplyDisplayOutput   (MessageLength,MessageBuffer,MessageType);break;
5705       default  :unknown=true;break;
5706     }
5707     break;
5708
5709   /* Phone Clock and Alarm */
5710   case 0x11:
5711     switch (MessageBuffer[3]) {
5712       case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break;
5713       case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break;
5714       case 0x6c:N6110_ReplySetAlarm   (MessageLength,MessageBuffer,MessageType);break;
5715       case 0x6e:N6110_ReplyGetAlarm   (MessageLength,MessageBuffer,MessageType);break;
5716       default  :unknown=true;break;
5717     }
5718     break;
5719
5720   /* Calendar notes handling */
5721   case 0x13:
5722     switch (MessageBuffer[3]) {
5723       case 0x65:N6110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break;
5724       case 0x67:N6110_ReplyGetCalendarNote   (MessageLength,MessageBuffer,MessageType);break;
5725       case 0x69:N6110_ReplyDeleteCalendarNote(MessageLength,MessageBuffer,MessageType);break;
5726       default  :N6110_Dispatch0x13Message    (MessageLength,MessageBuffer,MessageType);break;
5727     }
5728     break;
5729
5730   /* SMS Messages */
5731   case 0x14:
5732     switch (MessageBuffer[3]) {
5733       case 0x05:
5734       case 0x06:N6110_ReplySaveSMSMessage  (MessageLength,MessageBuffer,MessageType);break;
5735       case 0x08:
5736       case 0x09:N6110_ReplyGetSMSMessage   (MessageLength,MessageBuffer,MessageType);break;
5737       case 0x0b:N6110_ReplyDeleteSMSMessage(MessageLength,MessageBuffer,MessageType);break;
5738       case 0x37:
5739       case 0x38:N6110_ReplyGetSMSStatus    (MessageLength,MessageBuffer,MessageType);break;
5740       default  :unknown=true;break;
5741     }
5742     break;
5743
5744   /* WAP */
5745   case 0x3f:
5746     switch (MessageBuffer[3]) {
5747       case 0x01:
5748       case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;
5749       case 0x07:
5750       case 0x08:N7110_ReplyGetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
5751       case 0x0a:
5752       case 0x0b:N7110_ReplySetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
5753       case 0x16:
5754       case 0x17:
5755       case 0x1c:N7110_ReplyGetWAPSettings   (MessageLength,MessageBuffer,MessageType);break;
5756       default  :unknown=true;break;
5757     }
5758     break;
5759 #endif /* UCLINUX */
5760
5761   /* Internal phone functions? */
5762   case 0x40:
5763     switch (MessageBuffer[2]) {
5764       case 0x64:N6110_ReplyEnableExtendedCommands  (MessageLength,MessageBuffer,MessageType);break;
5765 #ifndef UCLINUX
5766       case 0x65:N6110_ReplyResetPhoneSettings      (MessageLength,MessageBuffer,MessageType);break;
5767 #endif /* UCLINUX */
5768       case 0x66:N6110_ReplyIMEI                    (MessageLength,MessageBuffer,MessageType);break;
5769 #ifndef UCLINUX
5770       case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
5771       case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;
5772       case 0x6e:N6110_ReplyGetSecurityCode         (MessageLength,MessageBuffer,MessageType);break;
5773       case 0x7e:N6110_ReplyNetmonitor              (MessageLength,MessageBuffer,MessageType);break;
5774       case 0x8a:N6110_ReplySimlockInfo             (MessageLength,MessageBuffer,MessageType);break;
5775       case 0x8b:N6110_ReplySetOperatorName         (MessageLength,MessageBuffer,MessageType);break;
5776       case 0x8c:N6110_ReplyGetOperatorName         (MessageLength,MessageBuffer,MessageType);break;
5777       case 0x8f:N6110_ReplyPlayTone                (MessageLength,MessageBuffer,MessageType);break;
5778       case 0x9e:N6110_ReplyGetBinRingtone          (MessageLength,MessageBuffer,MessageType);break;
5779       case 0xa0:N6110_ReplySetBinRingtone          (MessageLength,MessageBuffer,MessageType);break;
5780 #endif /* UCLINUX */
5781       case 0xc8:N6110_ReplyHW                      (MessageLength,MessageBuffer,MessageType);break;
5782       default  :N6110_Dispatch0x40Message          (MessageLength,MessageBuffer,MessageType);break;
5783     }
5784     break;
5785
5786 #ifndef UCLINUX
5787   /* Picture Images */
5788   case 0x47:
5789
5790     N6110_Dispatch0x47Message(MessageLength, MessageBuffer, MessageType);
5791     break;
5792 #endif /* UCLINUX */
5793
5794   /* Mobile phone identification */
5795   case 0x64:
5796
5797     N6110_ReplyGetAuthentication(MessageLength, MessageBuffer, MessageType);
5798     break;
5799
5800   /***** Acknowlegment of our frames. *****/
5801   case FBUS_FRTYPE_ACK:
5802
5803     N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);
5804     break;
5805
5806   /***** Power on message. *****/
5807   case 0xd0:
5808
5809     N6110_Dispatch0xD0Message(MessageLength, MessageBuffer, MessageType);
5810     break;
5811
5812   case 0xd2:
5813
5814     N6110_ReplyID(MessageLength, MessageBuffer, MessageType);
5815     break;
5816   
5817   /***** RLP frame received. *****/
5818   case 0xf1:
5819
5820     N6110_RX_HandleRLPMessage(MessageBuffer);
5821     break;
5822
5823   /***** Power on message. *****/
5824   case 0xf4:
5825
5826     N6110_Dispatch0xF4Message(MessageLength, MessageBuffer, MessageType);
5827     break;
5828
5829   /***** Unknown message *****/
5830   /* If you think that you know the exact meaning of other messages - please
5831      let us know. */
5832   default:
5833
5834 #ifdef DEBUG
5835     fprintf(stdout, _("Message: Unknown message type.\n"));
5836 #endif /* DEBUG */
5837     AppendLogText("Unknown msg type\n",false);
5838
5839     unknown=false;
5840     break;
5841
5842   }
5843
5844   if (unknown) {
5845 #ifdef DEBUG
5846     fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);
5847 #endif
5848     AppendLogText("Unknown msg\n",false);
5849   }
5850 }