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