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