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