http://marcin-wiacek.fkn.pl/english/zips/mygnokii.tar.gz
[gnokii.git] / common / newmodules / n6110.c
1 /*\r
2 \r
3   G N O K I I\r
4 \r
5   A Linux/Unix toolset and driver for Nokia mobile phones.\r
6 \r
7   Released under the terms of the GNU GPL, see file COPYING for more details.\r
8 \r
9   This file provides an API for accessing functions on the 6110 and similar\r
10   phones.\r
11 \r
12 */\r
13 \r
14 /* "Turn on" prototypes in n-6110.h */\r
15 \r
16 #define __n_6110_c \r
17 \r
18 /* System header files */\r
19 #include <stdio.h>\r
20 #include <string.h>\r
21 #include <stdlib.h>\r
22 \r
23 #ifdef WIN32\r
24   #include "misc_win32.h"\r
25 #endif\r
26  \r
27 /* Various header file */\r
28 #ifndef VC6\r
29   #include "config.h"\r
30 #endif\r
31 \r
32 #include "gsm-api.h"\r
33 #include "gsm-coding.h"\r
34 #include "newmodules/n6110.h"\r
35 #include "newmodules/n7110.h"\r
36 #include "protocol/fbus.h"\r
37 #include "devices/device.h"\r
38 \r\r/* Global variables used by code in gsm-api.c to expose the functions\r
39    supported by this model of phone. */\r
40 \r
41 \r
42 \r
43 \r
44 \r
45 \r
46 \r
47 /* Here we initialise model specific functions. */\r
48 GSM_Functions N6110_Functions = {\r
49   N6110_Initialise,\r
50   N6110_DispatchMessage,\r
51   NULL_Terminate,\r
52   NULL_KeepAlive,\r
53   N6110_GetMemoryLocation,\r
54   N6110_WritePhonebookLocation,\r
55   N6110_GetSpeedDial,\r
56   N6110_SetSpeedDial,\r
57   N6110_GetMemoryStatus,\r
58   N6110_GetSMSStatus,\r
59   N6110_GetSMSCenter,\r
60   N6110_SetSMSCenter,\r
61   N6110_GetSMSMessage,\r
62   N6110_DeleteSMSMessage,\r
63   N6110_SendSMSMessage,\r
64   N6110_SaveSMSMessage,\r
65   N6110_GetRFLevel,\r
66   N6110_GetBatteryLevel,\r
67   N6110_GetPowerSource,\r
68   N6110_GetDisplayStatus,\r
69   N6110_EnterSecurityCode,\r
70   N6110_GetSecurityCodeStatus,\r
71   N6110_GetSecurityCode,\r
72   N6110_GetIMEI,\r
73   N6110_GetRevision,\r
74   N6110_GetModel,\r
75   N6110_GetDateTime,\r
76   N6110_SetDateTime,\r
77   N6110_GetAlarm,\r
78   N6110_SetAlarm,\r
79   N6110_DialVoice,\r
80   N6110_DialData,\r
81   N6110_GetIncomingCallNr,\r
82   N6110_GetNetworkInfo,\r
83   N6110_GetCalendarNote,\r
84   N6110_WriteCalendarNote,\r
85   N6110_DeleteCalendarNote,\r
86   N6110_NetMonitor,\r
87   N6110_SendDTMF,\r
88   N6110_GetBitmap,\r
89   N6110_SetBitmap,\r
90   N6110_SetRingTone,\r
91   N6110_SetBinRingTone,\r
92   N6110_GetBinRingTone,\r
93   N6110_Reset,\r
94   N6110_GetProfile,\r
95   N6110_SetProfile,\r
96   N6110_SendRLPFrame,\r
97   N6110_CancelCall,\r
98   N6110_PressKey,\r
99   N6110_EnableDisplayOutput,\r
100   N6110_DisableDisplayOutput,\r
101   N6110_EnableCellBroadcast,\r
102   N6110_DisableCellBroadcast,\r
103   N6110_ReadCellBroadcast,\r
104   N6110_PlayTone,\r
105   N6110_GetProductProfileSetting,\r
106   N6110_SetProductProfileSetting,\r
107   N6110_GetOperatorName,\r
108   N6110_SetOperatorName,\r
109   N6110_GetVoiceMailbox,\r  N6110_Tests,
110   N6110_SimlockInfo,
111   UNIMPLEMENTED,                 //GetCalendarNotesInfo
112   N6110_GetSMSFolders,
113   N6110_ResetPhoneSettings,
114   N7110_GetWAPBookmark,
115   N7110_SetWAPBookmark,
116   N7110_GetWAPSettings,
117   N6110_CallDivert,
118   N6110_AnswerCall,
119   N6110_GetManufacturer
120 };\r
121 \r
122 /* Mobile phone information */\r
123 \r
124 GSM_Information N6110_Information = {\r
125   "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850",\r
126      /* Supported models in FBUS */\r
127   "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850",\r
128      /* Supported models in MBUS */\r
129   "6110|6130|6150|8210|8850",\r
130      /* Supported models in FBUS over infrared */\r
131   "",\r
132      /* Supported models in FBUS over DLR3 */\r
133   "",
134      /* AT commands */
135   "8210|8850",
136      /* infrared sockets */
137   "6110|6130|6150|8210|8850",
138      /* Supported models in FBUS over infrared with Tekram device */\r  
139   4,                     /* Max RF Level */\r
140   0,                     /* Min RF Level */\r
141   GRF_Arbitrary,         /* RF level units */\r
142   4,                     /* Max Battery Level */\r
143   0,                     /* Min Battery Level */\r
144   GBU_Arbitrary,         /* Battery level units */\r
145   GDT_DateTime,          /* Have date/time support */\r
146   GDT_TimeOnly,          /* Alarm supports time only */\r
147   1                      /* Only one alarm available */\r
148 };\r
149 \r
150 const char *N6110_MemoryType_String [] = {\r
151   "",   /* 0x00 */\r
152   "MT", /* 0x01 */\r
153   "ME", /* 0x02 */\r
154   "SM", /* 0x03 */\r
155   "FD", /* 0x04 */\r
156   "ON", /* 0x05 */\r
157   "EN", /* 0x06 */\r
158   "DC", /* 0x07 */\r
159   "RC", /* 0x08 */\r
160   "MC", /* 0x09 */\r
161 };\r
162 \r
163 /* Magic bytes from the phone. */\r
164 unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };\r
165 \r
166 /* For DisplayOutput */\r
167 char               PhoneScreen[5+1][27+1];\r
168 int                OldX=1000,OldY=0,NewX=0,NewY=0;\r
169 \r
170 void N6110_ReplyEnableExtendedCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
171 \r
172 #ifdef DEBUG\r
173   fprintf(stdout, _("Message: Answer for EnableExtendedSecurityCommands frame, meaning not known :-(\n"));\r
174 #endif /* DEBUG */\r
175 \r
176   CurrentEnableExtendedCommandsError=GE_NONE;   \r
177 }\r
178 \r
179 /* If you set make some things (for example,\r
180    change Security Code from phone's menu, disable and enable\r
181    phone), it won't answer for 0x40 frame - you won't be able\r
182    to play tones, get netmonitor, etc.\r
183 \r
184    This function do thing called "Enabling extended security commands" -\r
185    it enables 0x40 frame functions.\r
186 \r
187    This frame can also some other things - see below */\r
188 GSM_Error N6110_EnableExtendedCommands (unsigned char status)\r
189 {\r
190   unsigned char req[4] = { 0x00,\r
191                            0x01,0x64, /* Enable extended commands request */\r
192                            0x01 };    /* 0x01 - on, 0x00 - off,\r
193                                          0x03 & 0x04 - soft & hard reset,\r
194                                          0x06 - CONTACT SERVICE */\r
195 \r
196   /* 0x06 MAKES CONTACT SERVICE! BE CAREFULL! */\r
197   /* When use 0x03 and had during session changed time & date
198      some phones (like 6150 or 6210) can ask for time & date after reset
199      or disable clock on the screen */
200   if (status!=0x06) req[3] = status;\r
201 \r
202   return NULL_SendMessageSequence\r
203     (50, &CurrentEnableExtendedCommandsError, 4, 0x40, req);\r
204 }\r
205 \r
206 void N6110_ReplyIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
207 \r
208 #if defined WIN32 || !defined HAVE_SNPRINTF\r
209   sprintf(Current_IMEI, "%s", MessageBuffer+4);\r
210 #else\r
211   snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+4);\r
212 #endif\r
213 \r
214 #ifdef DEBUG\r
215   fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI);\r
216 #endif\r
217 \r
218   CurrentGetIMEIError=GE_NONE;       \r
219 }\r
220 \r
221 GSM_Error N6110_SendIMEIFrame()\r
222 {\r
223   unsigned char req[4] = {0x00, 0x01, 0x66, 0x00};  \r
224 \r
225   GSM_Error error;\r
226 \r
227   error=N6110_EnableExtendedCommands(0x01);\r
228   if (error!=GE_NONE) return error;\r
229   \r
230   return NULL_SendMessageSequence (20, &CurrentGetIMEIError, 4, 0x40, req);\r
231 }\r
232 \r
233 void N6110_ReplyHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
234 \r
235   int i, j;\r
236     \r
237   if (MessageBuffer[3]==0x05) {\r
238 \r
239 #ifdef DEBUG\r
240     fprintf(stdout,_("Message: Hardware version received: "));\r
241 #endif\r
242 \r
243     j=strlen(Current_Revision);\r
244     Current_Revision[j++]=',';\r
245     Current_Revision[j++]=' ';\r
246     Current_Revision[j++]='H';\r
247     Current_Revision[j++]='W';\r
248             \r
249     for (i=5;i<9;i++) {\r
250 #ifdef DEBUG\r
251       fprintf(stdout,_("%c"), MessageBuffer[i]);\r
252 #endif\r
253       Current_Revision[j++]=MessageBuffer[i];\r
254     }\r
255 \r
256 #ifdef DEBUG\r
257     fprintf(stdout,_("\n"));\r
258 #endif\r
259 \r
260     CurrentGetHWError=GE_NONE;\r
261   }\r
262 }\r
263 \r
264 GSM_Error N6110_SendHWFrame()\r
265 {\r
266   unsigned char req[4] = {0x00, 0x01, 0xc8, 0x05};  \r
267 \r
268   GSM_Error error;\r
269 \r
270   error=N6110_EnableExtendedCommands(0x01);\r
271   if (error!=GE_NONE) return error;\r
272   \r
273   return NULL_SendMessageSequence (20, &CurrentGetHWError, 4, 0x40, req);\r
274 }\r
275 \r
276 void N6110_ReplyID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
277 \r
278   int i, j;\r
279  \r
280 #ifdef DEBUG\r
281   fprintf(stdout, _("Message: Mobile phone model identification received:\n"));\r
282   fprintf(stdout, _("   Firmware: "));\r
283 #endif\r
284 \r
285   strcpy(Current_Revision,"SW");\r
286     \r
287   i=6;j=2;\r
288   while (MessageBuffer[i]!=0x0a) {\r
289     Current_Revision[j]=MessageBuffer[i];\r
290 #ifdef DEBUG\r
291     fprintf(stdout, _("%c"),MessageBuffer[i]);\r
292 #endif\r
293     if (j==GSM_MAX_REVISION_LENGTH-1) {\r
294 #ifdef DEBUG\r
295       fprintf(stderr,_("ERROR: increase GSM_MAX_REVISION_LENGTH!\n"));\r
296 #endif  \r
297       break;\r
298     }\r
299     j++;\r
300     i++;\r
301   }\r
302   Current_Revision[j+1]=0;\r
303 \r
304 #ifdef DEBUG\r
305   fprintf(stdout, _("\n   Firmware date: "));\r
306 #endif\r
307 \r
308   i++;\r
309   while (MessageBuffer[i]!=0x0a) {\r
310 #ifdef DEBUG\r
311     fprintf(stdout, _("%c"),MessageBuffer[i]);\r
312 #endif\r
313     i++;\r
314   }\r
315 \r
316 #ifdef DEBUG\r
317   fprintf(stdout, _("\n   Model: "));\r
318 #endif /* DEBUG */\r
319 \r
320   i++;j=0;\r
321   while (MessageBuffer[i]!=0x0a) {\r
322     Current_Model[j]=MessageBuffer[i];\r
323 #ifdef DEBUG\r
324     fprintf(stdout, _("%c"),MessageBuffer[i]);\r
325 #endif\r
326     if (j==GSM_MAX_MODEL_LENGTH-1) {\r
327 #ifdef DEBUG\r
328       fprintf(stderr,_("ERROR: increase GSM_MAX_MODEL_LENGTH!\n"));\r
329 #endif  \r
330       break;\r
331     }\r
332     j++;\r
333     i++;\r
334   }\r
335   Current_Model[j+1]=0;\r
336 \r
337 #ifdef DEBUG\r
338   fprintf(stdout, _("\n"));\r
339 #endif /* DEBUG */\r
340     \r
341   CurrentMagicError=GE_NONE;\r
342 }\r
343 \r
344 GSM_Error N6110_SendIDFrame()\r
345 {\r
346   unsigned char req[5] = {N6110_FRAME_HEADER, 0x03, 0x00};  \r
347 \r
348   return NULL_SendMessageSequence (50, &CurrentMagicError, 5, 0xd1, req);\r
349 }\r
350 \r
351 /* This function send the status request to the phone. */\r
352 /* Seems to be ignored in N3210 */\r
353 GSM_Error N6110_SendStatusRequest(void)\r
354 {\r
355   unsigned char req[] = {N6110_FRAME_HEADER, 0x01};\r
356 \r
357   Protocol->SendMessage(4, 0x04, req);\r
358 \r
359   return (GE_NONE);\r
360 }\r
361 \r
362 void N6110_ReplyGetAuthentication(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
363 \r
364 #if defined WIN32 || !defined HAVE_SNPRINTF\r
365   sprintf(Current_IMEI, "%s", MessageBuffer+9);\r
366   sprintf(Current_Model, "%s", MessageBuffer+25);\r
367   sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39);\r
368 #else\r
369   snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+9);\r
370   snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+25);\r
371   snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39);\r
372 #endif\r
373 \r
374 #ifdef DEBUG\r
375   fprintf(stdout, _("Message: Mobile phone identification received:\n"));\r
376   fprintf(stdout, _("   IMEI: %s\n"), Current_IMEI);\r
377   fprintf(stdout, _("   Model: %s\n"), Current_Model);\r
378   fprintf(stdout, _("   Production Code: %s\n"), MessageBuffer+31);\r
379   fprintf(stdout, _("   HW: %s\n"), MessageBuffer+39);\r
380   fprintf(stdout, _("   Firmware: %s\n"), MessageBuffer+44);\r
381 \r
382   /* These bytes are probably the source of the "Accessory not connected"\r
383      messages on the phone when trying to emulate NCDS... I hope....\r
384      UPDATE: of course, now we have the authentication algorithm. */\r
385   fprintf(stdout, _("   Magic bytes: %02x %02x %02x %02x\n"), MessageBuffer[50], MessageBuffer[51], MessageBuffer[52], MessageBuffer[53]);\r
386 #endif /* DEBUG */\r
387 \r
388   MagicBytes[0]=MessageBuffer[50];\r
389   MagicBytes[1]=MessageBuffer[51];\r
390   MagicBytes[2]=MessageBuffer[52];\r
391   MagicBytes[3]=MessageBuffer[53];\r
392 \r
393   CurrentMagicError=GE_NONE;\r
394 }\r
395 \r
396 /* This function provides Nokia authentication protocol.\r
397 \r
398    This code is written specially for gnokii project by Odinokov Serge.\r
399    If you have some special requests for Serge just write him to\r
400    apskaita@post.omnitel.net or serge@takas.lt\r
401 \r
402    Reimplemented in C by Pavel Janík ml.\r
403 \r
404    Nokia authentication protocol is used in the communication between Nokia\r
405    mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software,\r
406    commercially sold by Nokia Corp.\r
407 \r
408    The authentication scheme is based on the token send by the phone to the\r
409    software. The software does it's magic (see the function\r
410    FB61_GetNokiaAuth()) and returns the result back to the phone. If the\r
411    result is correct the phone responds with the message "Accessory\r
412    connected!" displayed on the LCD. Otherwise it will display "Accessory not\r
413    supported" and some functions will not be available for use.\r
414 \r
415    The specification of the protocol is not publicly available, no comment. */\r
416 void N6110_GetNokiaAuth(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse)\r
417 {\r
418 \r
419   int i, j, CRC=0;\r
420 \r
421   /* This is our temporary working area. */\r
422 \r
423   unsigned char Temp[16];\r
424 \r
425   /* Here we put FAC (Final Assembly Code) and serial number into our area. */\r
426 \r
427   Temp[0]  = Imei[6];\r
428   Temp[1]  = Imei[7];\r
429   Temp[2]  = Imei[8];\r
430   Temp[3]  = Imei[9];\r
431   Temp[4]  = Imei[10];\r
432   Temp[5]  = Imei[11];\r
433   Temp[6]  = Imei[12];\r
434   Temp[7]  = Imei[13];\r
435 \r
436   /* And now the TAC (Type Approval Code). */\r
437 \r
438   Temp[8]  = Imei[2];\r
439   Temp[9]  = Imei[3];\r
440   Temp[10] = Imei[4];\r
441   Temp[11] = Imei[5];\r
442 \r
443   /* And now we pack magic bytes from the phone. */\r
444 \r
445   Temp[12] = MagicBytes[0];\r
446   Temp[13] = MagicBytes[1];\r
447   Temp[14] = MagicBytes[2];\r
448   Temp[15] = MagicBytes[3];\r
449 \r
450   for (i=0; i<=11; i++)\r
451     if (Temp[i + 1]& 1)\r
452       Temp[i]<<=1;\r
453 \r
454   switch (Temp[15] & 0x03) {\r
455 \r
456   case 1:\r
457   case 2:\r
458     j = Temp[13] & 0x07;\r
459 \r
460     for (i=0; i<=3; i++)\r
461       Temp[i+j] ^= Temp[i+12];\r
462 \r
463     break;\r
464 \r
465   default:\r
466     j = Temp[14] & 0x07;\r
467 \r
468     for (i=0; i<=3; i++)\r
469       Temp[i + j] |= Temp[i + 12];\r
470   }\r
471 \r
472   for (i=0; i<=15; i++)\r
473     CRC ^= Temp[i];\r
474 \r
475   for (i=0; i<=15; i++) {\r
476 \r
477     switch (Temp[15 - i] & 0x06) {\r
478 \r
479     case 0:\r
480       j = Temp[i] | CRC;\r
481       break;\r
482 \r
483     case 2:\r
484     case 4:\r
485       j = Temp[i] ^ CRC;\r
486       break;\r
487 \r
488     case 6:\r
489       j = Temp[i] & CRC;\r
490       break;\r
491     }\r
492   \r
493     if (j == CRC)\r
494       j = 0x2c;\r
495 \r
496     if (Temp[i] == 0)\r
497       j = 0;\r
498 \r
499     MagicResponse[i] = j;\r
500 \r
501   }\r
502 }\r
503 \r
504 GSM_Error N6110_Authentication()\r
505 {\r
506   unsigned char connect1[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};\r
507   unsigned char connect2[] = {N6110_FRAME_HEADER, 0x20, 0x02};\r
508   unsigned char connect3[] = {N6110_FRAME_HEADER, 0x0d, 0x01, 0x00, 0x02};\r
509   unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10};\r
510   \r
511   unsigned char magic_connect[] = {N6110_FRAME_HEADER,\r
512   0x12,\r
513 \r
514   /* The real magic goes here ... These bytes are filled in with the\r
515      function N6110_GetNokiaAuth(). */\r
516 \r
517   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
518   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
519 \r
520   /* NOKIA&GNOKII Accessory */\r
521 \r
522   0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x26, 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x20,\r
523   0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79,\r
524   \r
525   0x00, 0x00, 0x00, 0x00};\r
526 \r
527 #ifdef DEBUG\r
528   fprintf(stdout,_("Making authentication!\n"));\r
529 #endif\r
530 \r
531   usleep(100); Protocol->SendMessage(7, 0x02, connect1);\r
532   usleep(100); Protocol->SendMessage(5, 0x02, connect2);\r
533   usleep(100); Protocol->SendMessage(7, 0x02, connect3);\r
534       \r
535   CurrentMagicError = GE_BUSY;\r
536 \r
537   usleep(100); Protocol->SendMessage(4, 0x64, connect4);\r
538   if (NULL_WaitUntil(50,&CurrentMagicError)!=GE_NONE) return GE_TIMEOUT;\r
539 \r
540   N6110_GetNokiaAuth(Current_IMEI, MagicBytes, magic_connect+4);\r
541 \r
542   Protocol->SendMessage(45, 0x64, magic_connect);\r
543 \r
544 #ifdef DEBUG\r
545   fprintf(stdout,_("End of authentication!\n"));\r
546 #endif\r
547 \r
548   return GE_NONE;\r
549 }\r
550 \r
551 /* Initialise variables and state machine. */\r
552 GSM_Error N6110_Initialise(char *port_device, char *initlength,\r
553                           GSM_ConnectionType connection,\r
554                           void (*rlp_callback)(RLP_F96Frame *frame))\r
555 {\r
556   unsigned char init_char = N6110_SYNC_BYTE;\r
557   unsigned char end_init_char = N6110_IR_END_SYNC_BYTE;\r
558 \r
559   int count;\r
560   int InitLength;\r
561   \r
562   if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)\r
563   {\r
564     return GE_NOTSUPPORTED;\r
565   }\r
566
567   switch (CurrentConnectionType) {
568     case GCT_Irda:
569     case GCT_MBUS:
570       /* We don't think about authentication in Irda, because
571          AFAIK there are no phones working over sockets
572          and having authentication. In MBUS it doesn't work */
573       usleep(100);\r
574 \r
575       if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;\r
576     \r
577       if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    \r
578 \r
579       if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;    \r
580
581       CurrentLinkOK = true;                           \r      \r
582       break;
583       
584     case GCT_FBUS:
585     case GCT_Infrared:
586     case GCT_Tekram:
587       InitLength = atoi(initlength);\r
588 \r
589       if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {\r
590         InitLength = 250;       /* This is the usual value, lower may work. */\r
591       }\r
592 \r
593       if (CurrentConnectionType==GCT_Infrared ||
594           CurrentConnectionType==GCT_Tekram) {\r
595 #ifdef DEBUG\r
596         fprintf(stdout,_("Setting infrared for FBUS communication...\n"));\r
597 #endif\r
598         device_changespeed(9600);\r
599       }\r
600
601 #ifdef DEBUG\r
602       fprintf(stdout,_("Writing init chars...."));\r
603 #endif\r
604 \r
605       /* Initialise link with phone or what have you */\r
606       /* Send init string to phone, this is a bunch of 0x55 characters. Timing is\r
607          empirical. */\r
608       for (count = 0; count < InitLength; count ++) {\r
609         if (CurrentConnectionType!=GCT_Infrared &&
610             CurrentConnectionType!=GCT_Tekram) \r        usleep(100);\r
611         Protocol->WritePhone(1,&init_char);\r
612       }\r
613 \r
614       if (CurrentConnectionType==GCT_Infrared ||
615           CurrentConnectionType==GCT_Tekram)\r      {
616         Protocol->WritePhone(1,&end_init_char);\r
617         usleep(200000);
618       }
619
620 #ifdef DEBUG\r
621       fprintf(stdout,_("Done\n"));  \r
622 #endif\r
623
624       if (CurrentConnectionType==GCT_Infrared ||
625           CurrentConnectionType==GCT_Tekram)\r      {
626         device_changespeed(115200);    \r
627       }
628
629       N6110_SendStatusRequest();\r
630     \r
631       usleep(100);\r
632 \r
633       if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;\r
634     \r
635       /* N51xx/61xx have something called authentication.\r
636          After making it phone display "Accessory connected"\r
637          and probably give access to some function (I'm not too sure about it !)\r
638          Anyway, I make it now for N51xx/61xx */\r
639       if (GetModelFeature (FN_AUTHENTICATION)!=0) {\r
640         if (N6110_Authentication()!=GE_NONE) return GE_TIMEOUT;\r
641       } else {\r        /* No authentication */
642         if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;    \r
643 \r
644         if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;    \r
645       }\r
646       
647       break;
648     default:
649 #ifdef DEBUG\r
650       fprintf(stdout,_("Unknown connection type in n6110.c!\n"));\r
651 #endif\r
652       break;
653   }
654
655   return (GE_NONE);\r
656 }\r
657 \r
658 /* This function translates GMT_MemoryType to N6110_MEMORY_xx */\r
659 int N6110_GetMemoryType(GSM_MemoryType memory_type)\r
660 {\r
661 \r
662   int result;\r
663 \r
664   switch (memory_type) {\r
665 \r
666      case GMT_MT: result = N6110_MEMORY_MT; break;\r
667      case GMT_ME: result = N6110_MEMORY_ME; break;\r
668      case GMT_SM: result = N6110_MEMORY_SM; break;\r
669      case GMT_FD: result = N6110_MEMORY_FD; break;\r
670      case GMT_ON: result = N6110_MEMORY_ON; break;\r
671      case GMT_EN: result = N6110_MEMORY_EN; break;\r
672      case GMT_DC: result = N6110_MEMORY_DC; break;\r
673      case GMT_RC: result = N6110_MEMORY_RC; break;\r
674      case GMT_MC: result = N6110_MEMORY_MC; break;\r
675      default    : result = N6110_MEMORY_XX;\r
676 \r
677    }\r
678 \r
679    return (result);\r
680 }\r
681
682 void N6110_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
683
684   switch (MessageBuffer[3]) {
685
686   case 0x02:
687
688 #ifdef DEBUG\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:\r
3683         fprintf(stdout, _("   Invalid location!\n"));break;\r
3684       case 0x07:\r
3685         fprintf(stdout, _("   Empty SMS location.\n"));break;\r
3686       case 0x0c:\r
3687         fprintf(stdout, _("   No access to memory (no PIN on card ?)\n"));break;\r
3688       default:      \r
3689         fprintf(stdout, _("   Error code %i - please report it \n"),MessageBuffer[4]);break;\r
3690     }\r
3691 #endif /* DEBUG */\r
3692 \r
3693     switch (MessageBuffer[4]) {\r
3694       case 0x02:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break;\r
3695       case 0x07:CurrentSMSMessageError = GE_EMPTYSMSLOCATION;break;\r
3696       case 0x0c:CurrentSMSMessageError = GE_NOACCESS;break;\r
3697       default  :CurrentSMSMessageError = GE_UNKNOWN;break;\r
3698     }\r
3699 \r
3700     break;\r
3701 \r
3702   }\r
3703 }\r
3704 \r
3705 GSM_Error N6110_GetSMSMessage(GSM_SMSMessage *message)\r
3706 {\r
3707 \r
3708   unsigned char req[] = { N6110_FRAME_HEADER,\r
3709                           0x07,\r
3710                           0x02, /* Unknown */\r
3711                           0x00, /* Location */\r
3712                           0x01, 0x64};\r
3713 \r
3714   int timeout = 60;\r
3715 \r
3716   /* State machine code writes data to these variables when it comes in. */\r
3717 \r
3718   CurrentSMSMessage = message;\r
3719   CurrentSMSMessageError = GE_BUSY;\r
3720 \r
3721   req[5] = message->Location;\r
3722 \r
3723   /* Send request */\r
3724   Protocol->SendMessage(8, 0x02, req);\r
3725 \r
3726   /* Wait for timeout or other error. */\r
3727   while (timeout != 0 && (CurrentSMSMessageError == GE_BUSY || CurrentSMSMessageError == GE_SMSWAITING)) {\r
3728 \r
3729     if (--timeout == 0)\r
3730       return (GE_TIMEOUT);\r
3731 \r
3732     usleep (100000);\r
3733   }\r
3734 \r
3735   return (CurrentSMSMessageError);\r
3736 }\r
3737 \r
3738 void N6110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
3739 \r
3740 #ifdef DEBUG\r
3741   fprintf(stdout, _("Message: SMS deleted successfully.\n"));\r
3742 #endif /* DEBUG */\r
3743 \r
3744   CurrentSMSMessageError = GE_NONE;     \r
3745 }\r
3746 \r
3747 GSM_Error N6110_DeleteSMSMessage(GSM_SMSMessage *message)\r
3748 {\r
3749   unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02, 0x00};\r
3750 \r
3751   req[5] = message->Location;\r
3752 \r
3753   return NULL_SendMessageSequence\r
3754     (50, &CurrentSMSMessageError, 6, 0x14, req);\r
3755 }\r
3756
3757 /* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */
3758 GSM_Error GSM_EncodeNokiaSMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int *length, SMS_MessageType PDU)
3759 {
3760   GSM_ETSISMSMessage ETSI;
3761   int i,offset=0;
3762
3763   GSM_EncodeETSISMS(SMS, &ETSI, PDU, length);
3764
3765   /* Cleaning */
3766   for (i=0;i<36;i++) req[i]=0;
3767
3768   req[12]=ETSI.firstbyte;
3769
3770   for (i=0;i<ETSI.SMSCNumber[0]+1;i++)
3771     req[i]=ETSI.SMSCNumber[i];
3772
3773   switch (PDU) {
3774     case SMS_Submit:
3775       offset=5;
3776       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++)
3777         req[i+12+offset]=ETSI.Number[i];
3778       req[10+offset]=ETSI.TPDCS;
3779       req[11+offset]=ETSI.TPUDL;
3780       req[24+offset]=ETSI.TPVP;
3781 #ifdef DEBUG
3782 //      fprintf(stdout,_("   First byte: %02x\n"),ETSI.firstbyte);
3783 //      fprintf(stdout,_("   TP-VP: %02x\n"),ETSI.TPVP);
3784 //      fprintf(stdout,_("   TP-DCS: %02x\n"),ETSI.TPDCS);
3785 #endif
3786 //    req[]=ETSI.TPPID;
3787       for(i=0;i<*length;i++)
3788         req[i+31+offset]=ETSI.MessageText[i];
3789       break;
3790
3791     case SMS_Deliver:
3792       offset=4;
3793       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++)
3794         req[i+12+offset]=ETSI.Number[i];
3795       req[10+offset]=ETSI.TPDCS;
3796       req[11+offset]=ETSI.TPUDL;
3797 //    req[]=ETSI.TPPID;
3798       for(i=0;i<*length;i++)
3799         req[i+31+offset]=ETSI.MessageText[i];
3800       for (i=0;i<7;i++)
3801         req[24+offset+i]=ETSI.DeliveryDateTime[i];
3802       break;
3803     default:
3804       break;
3805   }
3806   
3807   *length=*length+offset;
3808   
3809   return GE_NONE;
3810 }
3811 \r
3812 void N6110_ReplySendSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
3813     \r
3814   switch (MessageBuffer[3]) {\r
3815 \r
3816   /* SMS message correctly sent to the network */\r
3817   case 0x02:\r
3818 #ifdef DEBUG\r
3819     fprintf(stdout, _("Message: SMS Message correctly sent.\n"));\r
3820 #endif /* DEBUG */\r
3821     CurrentSMSMessageError = GE_SMSSENDOK;\r
3822     break;\r
3823 \r
3824   /* SMS message send to the network failed */\r
3825   case 0x03:\r
3826 \r
3827 #ifdef DEBUG\r
3828     fprintf(stdout, _("Message: Sending SMS Message failed, error: %i"),MessageBuffer[6]);\r
3829       \r
3830     switch (MessageBuffer[6]) {\r
3831       case 1: fprintf(stdout,_(" (info \"Number not in use\")"));break;\r
3832       case 21: fprintf(stdout,_(" (info \"Message not sent this time\")"));break;\r
3833       case 28: fprintf(stdout,_(" (info \"Number not in use\")"));break;\r
3834       case 38: fprintf(stdout,_(" (info \"Message not sent this time\")"));break;       case 50: fprintf(stdout,_(" (info \"Check operator services\")"));break;        \r
3835       case 96: fprintf(stdout,_(" (info \"Message sending failed\")"));break;   \r
3836       case 111: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  \r
3837       case 166: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  \r
3838       case 178: fprintf(stdout,_(" (info \"Message sending failed\")"));break;  \r
3839       case 252: fprintf(stdout,_(" (info \"Message sending failed\")"));break;         case 253: fprintf(stdout,_(" (info \"Message sending failed\")"));break; \r
3840     }\r
3841 \r
3842     fprintf(stdout,_("\n   For more details with errors see netmonitor manual (test 65) on www.marcin-wiacek.topnet.pl"));\r
3843     fprintf(stdout,_("\n   If know their meaning, GSM specs decribing them, contact with me on marcin-wiacek@topnet.pl. THX\n"));\r
3844 #endif /* DEBUG */\r
3845 \r
3846     CurrentSMSMessageError = GE_SMSSENDFAILED;\r
3847     break;\r
3848 \r
3849   }\r
3850 }\r
3851 \r
3852 GSM_Error N6110_SendSMSMessage(GSM_SMSMessage *SMS)\r
3853 {\r
3854   GSM_Error error;\r
3855 \r
3856   unsigned char req[256] = {\r
3857     N6110_FRAME_HEADER,\r
3858     0x01, 0x02, 0x00, /* SMS send request*/\r
3859   };\r
3860 \r
3861   int length;\r
3862 \r
3863   error=GSM_EncodeNokiaSMSFrame(SMS, req+6, &length, SMS_Submit);    \r
3864   if (error != GE_NONE) return error;\r
3865 \r
3866   return NULL_SendMessageSequence\r
3867     (200, &CurrentSMSMessageError, 42+length, 0x02, req);\r
3868 }\r
3869 \r
3870 void N6110_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
3871 \r
3872   switch (MessageBuffer[3]) {\r
3873 \r
3874   case 0x05:\r
3875       \r
3876 #ifdef DEBUG\r
3877     fprintf(stdout, _("SMS Message stored at %d\n"), MessageBuffer[5]);\r
3878 #endif\r
3879       \r
3880     CurrentSMSMessage->MessageNumber=MessageBuffer[5];\r
3881       \r
3882     CurrentSMSMessageError = GE_NONE;\r
3883     break;\r
3884 \r
3885   case 0x06:\r
3886 #ifdef DEBUG\r
3887     fprintf(stdout, _("SMS saving failed\n"));\r
3888     switch (MessageBuffer[4]) {\r
3889       case 0x02:fprintf(stdout, _("   All locations busy.\n"));break;\r
3890       case 0x03:fprintf(stdout, _("   Invalid location!\n"));break;\r
3891       default  :fprintf(stdout, _("   Unknown error.\n"));break;\r
3892     }\r
3893 #endif      \r
3894       \r
3895     switch (MessageBuffer[4]) {\r
3896       case 0x02:CurrentSMSMessageError = GE_MEMORYFULL;break;\r
3897       case 0x03:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break;\r
3898       default  :CurrentSMSMessageError = GE_UNKNOWN;break;\r
3899     }\r
3900   }\r
3901 }\r
3902 \r
3903 /* GST_DR and GST_UN not supported ! */\r
3904 GSM_Error N6110_SaveSMSMessage(GSM_SMSMessage *SMS)\r
3905 {\r
3906   unsigned char req[256] = {\r
3907     N6110_FRAME_HEADER, 0x04, /* SMS save request*/\r
3908     0x00, /* SMS Status. Different for Inbox and Outbox */\r
3909     0x02, /* ?? */\r
3910     0x00, /* SMS Location */\r
3911     0x02, /* SMS Type */\r
3912   };\r
3913 \r
3914   int length;\r
3915   SMS_MessageType PDU;\r
3916   GSM_Error error;\r
3917 \r
3918   if (SMS->Location) req[6] = SMS->Location;\r
3919     \r
3920   if (SMS->folder==0) { /*Inbox*/\r
3921     req[4]=1;      /* SMS Status */\r
3922     req[7] = 0x00; /* SMS Type */\r
3923     PDU=SMS_Deliver;\r
3924   } else {\r
3925     req[4]=5;      /* SMS Status */\r
3926     req[7] = 0x02; /* SMS Type */\r
3927     PDU=SMS_Submit;\r
3928   }\r
3929   \r
3930   if (SMS->Status == GSS_NOTSENTREAD) req[4] |= 0x02;  \r
3931 \r
3932   error=GSM_EncodeNokiaSMSFrame(SMS, req+8, &length, PDU);  \r
3933   if (error != GE_NONE) return error;\r
3934 \r
3935   CurrentSMSMessage = SMS;\r
3936 \r
3937   return NULL_SendMessageSequence\r
3938     (70, &CurrentSMSMessageError, 39+length, 0x14, req);\r
3939 }\r
3940 \r
3941 void N6110_ReplySetCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
3942 \r
3943 #ifdef DEBUG\r
3944   fprintf(stdout, _("Message: Cell Broadcast enabled/disabled successfully.\n")); fflush (stdout);\r
3945 #endif\r
3946 \r
3947   CurrentCBError = GE_NONE;\r
3948 }\r
3949 \r
3950 /* Enable and disable Cell Broadcasting */\r
3951 GSM_Error N6110_EnableCellBroadcast(void)\r
3952 {\r
3953   unsigned char req[] = {N6110_FRAME_HEADER, 0x20,\r
3954                          0x01, 0x01, 0x00, 0x00, 0x01, 0x01};\r
3955 \r
3956 #ifdef DEBUG\r
3957   fprintf (stdout,"Enabling CB\n");\r
3958 #endif\r
3959 \r
3960   CurrentCBMessage = (GSM_CBMessage *)malloc(sizeof (GSM_CBMessage));\r
3961   CurrentCBMessage->Channel = 0;\r
3962   CurrentCBMessage->New = false;\r
3963   strcpy (CurrentCBMessage->Message,"");\r
3964 \r
3965   return NULL_SendMessageSequence\r
3966     (10, &CurrentCBError, 10, 0x02, req);\r
3967 }\r
3968 \r
3969 \r
3970 GSM_Error N6110_DisableCellBroadcast(void)\r
3971 {\r
3972   /* Should work, but not tested fully */\r
3973 \r
3974   unsigned char req[] = {N6110_FRAME_HEADER, 0x20,\r
3975                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /*VERIFY*/\r
3976 \r
3977   return NULL_SendMessageSequence\r
3978     (10, &CurrentCBError, 10, 0x02, req);\r
3979 }\r
3980 \r
3981 void N6110_ReplyReadCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
3982 \r
3983   int i, tmp;\r
3984   unsigned char output[160];\r
3985   \r
3986   CurrentCBMessage->Channel = MessageBuffer[7];\r
3987   CurrentCBMessage->New = true;\r
3988   tmp=GSM_UnpackEightBitsToSeven(0, MessageBuffer[9], MessageBuffer[9], MessageBuffer+10, output);\r
3989 \r
3990 #ifdef DEBUG\r
3991   fprintf(stdout, _("Message: CB received.\n")); fflush (stdout);\r
3992 \r
3993   fprintf(stdout, _("Message: channel number %i\n"),MessageBuffer[7]);\r
3994 \r
3995   fflush (stdout);\r
3996 \r
3997   for (i=0; i<tmp;i++) {\r
3998     fprintf(stdout, "%c", DecodeWithDefaultAlphabet(output[i]));\r
3999   }\r
4000 \r
4001   fprintf(stdout, "\n");\r
4002 #endif\r
4003    \r
4004   for (i=0; i<tmp; i++) {\r
4005     CurrentCBMessage->Message[i] = DecodeWithDefaultAlphabet(output[i]);\r
4006   }\r
4007   CurrentCBMessage->Message[i]=0;\r
4008 }\r
4009 \r
4010 GSM_Error N6110_ReadCellBroadcast(GSM_CBMessage *Message)\r
4011 {\r
4012 #ifdef DEBUG\r
4013    fprintf(stdout,"Reading CB\n");\r
4014 #endif\r
4015 \r
4016   if (CurrentCBMessage != NULL) \r
4017   {\r
4018     if (CurrentCBMessage->New == true)\r
4019     {\r
4020 #ifdef DEBUG\r
4021   fprintf(stdout,"New CB received\n");\r
4022 #endif\r
4023       Message->Channel = CurrentCBMessage->Channel;\r
4024       strcpy(Message->Message,CurrentCBMessage->Message);\r
4025       CurrentCBMessage->New = false;\r
4026       return (GE_NONE);\r
4027     }\r
4028   }\r
4029   return (GE_NONEWCBRECEIVED);\r
4030 }\r
4031 \r
4032 int N6110_MakeCallerGroupFrame(unsigned char *req,GSM_Bitmap Bitmap)\r
4033 {\r
4034   int count=0;\r
4035 \r
4036   req[count++]=Bitmap.number;\r
4037   req[count++]=strlen(Bitmap.text);\r
4038   memcpy(req+count,Bitmap.text,req[count-1]);\r
4039   count+=req[count-1];\r
4040   req[count++]=Bitmap.ringtone;\r
4041 \r
4042   /* Setting for graphic:\r
4043      0x00 - Off\r
4044      0x01 - On\r
4045      0x02 - View Graphics\r
4046      0x03 - Send Graphics\r
4047      0x04 - Send via IR\r
4048      You can even set it higher but Nokia phones (my\r
4049      6110 at least) will not show you the name of this\r
4050      item in menu ;-)) Nokia is really joking here. */\r
4051   if (Bitmap.enabled) req[count++]=0x01;\r
4052                  else req[count++]=0x00;\r
4053 \r
4054   req[count++]=(Bitmap.size+4)>>8;\r
4055   req[count++]=(Bitmap.size+4)%0xff;\r
4056   req[count++]=0x00;  /* Future extensions! */\r
4057   req[count++]=Bitmap.width;\r
4058   req[count++]=Bitmap.height;\r
4059   req[count++]=0x01;  /* Just BW */\r
4060   memcpy(req+count,Bitmap.bitmap,Bitmap.size);\r
4061 \r
4062   return count+Bitmap.size;\r
4063 }\r
4064 \r
4065 int N6110_MakeOperatorLogoFrame(unsigned char *req,GSM_Bitmap Bitmap)\r
4066 {\r
4067   int count=0;\r
4068 \r
4069   EncodeNetworkCode(req+count, Bitmap.netcode);\r
4070   count=count+3;\r
4071 \r
4072   req[count++]=(Bitmap.size+4)>>8;\r
4073   req[count++]=(Bitmap.size+4)%0xff;\r
4074   req[count++]=0x00;  /* Infofield */\r
4075   req[count++]=Bitmap.width;\r
4076   req[count++]=Bitmap.height;\r
4077   req[count++]=0x01;  /* Just BW */    \r
4078   memcpy(req+count,Bitmap.bitmap,Bitmap.size);\r
4079 \r
4080   return count+Bitmap.size;\r
4081 }\r
4082 \r
4083 int N6110_MakeStartupLogoFrame(unsigned char *req,GSM_Bitmap Bitmap)\r
4084 {\r
4085   int count=0;\r
4086 \r
4087   req[count++]=0x01;\r
4088   req[count++]=Bitmap.height;\r
4089   req[count++]=Bitmap.width;\r
4090   memcpy(req+count,Bitmap.bitmap,Bitmap.size);\r
4091 \r
4092   return count+Bitmap.size;\r
4093 }\r
4094 \r
4095 /* Set a bitmap or welcome-note */\r
4096 GSM_Error N6110_SetBitmap(GSM_Bitmap *Bitmap) {\r
4097 \r
4098   unsigned char req[600] = { N6110_FRAME_HEADER };\r
4099   u16 count=3;\r
4100   u8 textlen;\r
4101   \r
4102   int timeout=50;\r
4103
4104   /* Direct uploading variables */
4105   GSM_MultiSMSMessage SMS;
4106   unsigned char buffer[1000] = {0x0c,0x01};
4107   GSM_NetworkInfo NetworkInfo;
4108
4109   GSM_Error error;\r
4110  
4111   /* Uploading with preview */
4112   if (Bitmap->number==255 &&
4113      (Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_CallerLogo)) {
4114     GSM_SaveBitmapToSMS(&SMS,Bitmap,false,false);
4115     memcpy(buffer+2,SMS.SMS[0].UDH,SMS.SMS[0].UDH[0]+1);
4116
4117     memcpy(buffer+2+SMS.SMS[0].UDH[0]+1,SMS.SMS[0].MessageText,SMS.SMS[0].Length);
4118
4119     buffer[2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length]=0x00;
4120
4121     Protocol->SendMessage(2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length+1, 0x12, buffer);
4122
4123     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
4124     return GE_NONE; //no answer from phone
4125   }
4126  \r
4127   CurrentSetBitmapError = GE_BUSY;  \r
4128   \r
4129   switch (Bitmap->type) {\r
4130   case GSM_WelcomeNoteText:\r
4131   case GSM_DealerNoteText:\r
4132     req[count++]=0x18;\r
4133     req[count++]=0x01; /* Only one block */\r
4134 \r
4135     if (Bitmap->type==GSM_WelcomeNoteText)\r
4136       req[count++]=0x02; /* Welcome text */\r
4137     else\r
4138       req[count++]=0x03; /* Dealer Welcome Note */\r
4139 \r
4140     textlen=strlen(Bitmap->text);\r
4141     req[count++]=textlen;\r
4142     memcpy(req+count,Bitmap->text,textlen);\r
4143       \r
4144     count+=textlen;\r
4145 \r
4146     Protocol->SendMessage(count, 0x05, req);\r
4147     \r
4148     break;\r
4149 \r
4150   case GSM_StartupLogo:\r
4151     if (Bitmap->number==0) {\r
4152 \r
4153       /* For 33xx we first set animated logo to default */\r
4154       if (GetModelFeature (FN_STARTUP)==F_STANIM) {\r
4155         error=N6110_SetProfileFeature(0, 0x29, Bitmap->number);\r
4156         if (error!=GE_NONE) return error;\r
4157       }\r
4158 \r
4159       req[count++]=0x18;\r
4160       req[count++]=0x01; /* Only one block */\r
4161       count=count+N6110_MakeStartupLogoFrame(req+5,*Bitmap); \r
4162       Protocol->SendMessage(count, 0x05, req);\r
4163     } else {\r
4164       return N6110_SetProfileFeature(0, 0x29, Bitmap->number);\r
4165     }\r
4166     break;\r
4167 \r
4168   case GSM_OperatorLogo:\r
4169     req[count++]=0x30;  /* Store Op Logo */\r
4170     req[count++]=0x01;  /* Location */\r
4171     count=count+N6110_MakeOperatorLogoFrame(req+5,*Bitmap); 
4172     Protocol->SendMessage(count, 0x05, req);\r
4173     break;\r
4174 \r
4175   case GSM_CallerLogo:\r
4176     req[count++]=0x13;\r
4177     count=count+N6110_MakeCallerGroupFrame(req+4,*Bitmap);\r
4178     Protocol->SendMessage(count, 0x03, req);\r
4179     break;\r
4180 \r
4181   case GSM_PictureImage:\r
4182     req[count++]=0x03;\r
4183     req[count++]=Bitmap->number;\r
4184     if (strcmp(Bitmap->Sender,"")) {\r
4185        req[count]=GSM_PackSemiOctetNumber(Bitmap->Sender, req+count+1,true);\r
4186 \r
4187        /* Convert number of semioctets to number of chars and add count */\r
4188        textlen=req[count];\r
4189        if (textlen % 2) textlen++;\r
4190        count+=textlen / 2 + 1;\r
4191 \r
4192        count++;\r
4193     } else {\r
4194       req[count++]=0x00;\r
4195       req[count++]=0x00;\r
4196     }\r
4197     req[count++]=0x00;\r
4198     req[count++]=strlen(Bitmap->text);\r
4199     memcpy(req+count,Bitmap->text,strlen(Bitmap->text));\r
4200     count+=strlen(Bitmap->text);\r
4201     req[count++]=0x00;\r
4202     req[count++]=Bitmap->width;\r
4203     req[count++]=Bitmap->height;\r
4204     req[count++]=0x01;\r
4205     memcpy(req+count,Bitmap->bitmap,Bitmap->size);\r
4206     Protocol->SendMessage(count+Bitmap->size, 0x47, req);\r
4207     break;\r
4208 \r
4209   case GSM_7110OperatorLogo:\r
4210   case GSM_7110StartupLogo:\r
4211   case GSM_6210StartupLogo:\r
4212     return GE_NOTSUPPORTED;\r
4213 \r
4214   case GSM_None:\r
4215     return GE_NONE;\r
4216   }\r
4217 \r
4218   /* Wait for timeout or other error. */\r
4219   while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) {\r
4220           \r
4221     if (--timeout == 0)\r
4222       return (GE_TIMEOUT);\r
4223                     \r
4224     usleep (100000);\r
4225   }\r
4226 \r
4227   return CurrentSetBitmapError;\r
4228 }\r
4229 \r
4230 /* Get a bitmap from the phone */\r
4231 GSM_Error N6110_GetBitmap(GSM_Bitmap *Bitmap) {\r
4232 \r
4233   unsigned char req[10] = { N6110_FRAME_HEADER };\r
4234   u8 count=3;\r
4235   \r
4236   int timeout=100;\r
4237   \r
4238   CurrentGetBitmap=Bitmap; \r
4239   CurrentGetBitmapError = GE_BUSY;  \r
4240   \r
4241   switch (CurrentGetBitmap->type) {\r
4242   case GSM_StartupLogo:\r
4243   case GSM_WelcomeNoteText:\r
4244   case GSM_DealerNoteText:\r
4245     req[count++]=0x16;\r
4246     Protocol->SendMessage(count, 0x05, req);\r
4247     break;\r
4248   case GSM_OperatorLogo:\r
4249     req[count++]=0x33;\r
4250     req[count++]=0x01; /* Location 1 */\r
4251     Protocol->SendMessage(count, 0x05, req);\r
4252     break;\r
4253   case GSM_CallerLogo:\r
4254     req[count++]=0x10;\r
4255     req[count++]=Bitmap->number;\r
4256     Protocol->SendMessage(count, 0x03, req);\r
4257     break;\r
4258   case GSM_PictureImage:\r
4259     req[count++]=0x01;\r
4260     req[count++]=Bitmap->number;\r
4261     Protocol->SendMessage(count, 0x47, req);\r
4262     break;\r
4263   case GSM_7110OperatorLogo:\r
4264   case GSM_7110StartupLogo:\r
4265   case GSM_6210StartupLogo:\r
4266   default:\r
4267     return GE_NOTSUPPORTED;\r
4268   }\r
4269 \r
4270   /* Wait for timeout or other error. */\r
4271   while (timeout != 0 && CurrentGetBitmapError == GE_BUSY ) {\r
4272           \r
4273     if (--timeout == 0)\r
4274       return (GE_TIMEOUT);\r
4275                     \r
4276     usleep (100000);\r
4277   }\r
4278 \r
4279   CurrentGetBitmap=NULL;\r
4280 \r
4281   return CurrentGetBitmapError;\r
4282 }\r
4283 \r
4284 void N6110_ReplySetRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4285 \r
4286   switch (MessageBuffer[3]) {\r
4287 \r
4288   /* Set ringtone OK */\r
4289   case 0x37:       \r
4290 #ifdef DEBUG\r
4291     fprintf(stdout, _("Message: Ringtone set OK!\n"));\r
4292 #endif  \r
4293     CurrentRingtoneError=GE_NONE; \r
4294     break;      \r
4295 \r
4296   /* Set ringtone error */\r
4297   case 0x38:       \r
4298 #ifdef DEBUG\r
4299     fprintf(stdout, _("Message: Ringtone setting error !\n"));\r
4300 #endif  \r
4301     CurrentRingtoneError=GE_NOTSUPPORTED; \r
4302     break;      \r
4303   }\r
4304 }\r
4305 \r
4306 GSM_Error N6110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength)\r
4307 {\r
4308   \r
4309   char req[FB61_MAX_RINGTONE_FRAME_LENGTH+10] =\r
4310       {N6110_FRAME_HEADER,\r
4311        0x36,\r
4312        0x00,  /* Location */\r
4313        0x00,0x78};\r
4314 \r
4315   int size=FB61_MAX_RINGTONE_FRAME_LENGTH;\r
4316  
4317   /* Variables for preview uploading */
4318   unsigned char buffer[FB61_MAX_RINGTONE_FRAME_LENGTH+50];
4319   unsigned char buffer2[20];
4320   GSM_NetworkInfo NetworkInfo;
4321
4322   /* Setting ringtone with preview */
4323   if (ringtone->location==255) {
4324     buffer[0]=0x0c;
4325     buffer[1]=0x01;
4326     EncodeUDHHeader(buffer2, GSM_RingtoneUDH);
4327     memcpy(buffer+2,buffer2,buffer2[0]+1); //copying UDH
4328     *maxlength=GSM_PackRingtone(ringtone, buffer+2+buffer2[0]+1, &size); //packing ringtone
4329     Protocol->SendMessage(2+buffer2[0]+1+size, 0x12, buffer); //sending frame
4330     GSM->GetNetworkInfo(&NetworkInfo); //need to make something
4331     sleep(1);
4332     return GE_NONE; //no answer from phone
4333   }
4334   \r
4335   *maxlength=GSM_PackRingtone(ringtone, req+7, &size);\r
4336 \r
4337   req[4]=ringtone->location-1;\r
4338 \r
4339   return NULL_SendMessageSequence\r
4340     (50, &CurrentRingtoneError, (size+7), 0x05, req);\r
4341 }\r
4342 \r
4343 void N6110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4344 \r
4345   int i;\r
4346   \r
4347   switch (MessageBuffer[4]) {\r
4348     case 0x00: /* location supported. We have ringtone */\r
4349 \r
4350       /* Binary format used in N6150 */\r
4351       if (MessageBuffer[5]==0x0c && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) {\r
4352 #ifdef DEBUG\r
4353         fprintf(stdout,_("Message: ringtone \""));\r
4354 #endif      \r
4355 \r
4356         /* Copying name */\r
4357         i=8;\r
4358         while (true) {\r
4359 #ifdef DEBUG\r
4360           if (MessageBuffer[i]!=0)\r
4361             fprintf(stdout,_("%c"),MessageBuffer[i]);\r
4362 #endif\r
4363           CurrentGetBinRingtone->name[i-8]=MessageBuffer[i];\r
4364           if (MessageBuffer[i]==0) break;\r
4365           i++;\r
4366         }\r
4367 \r
4368 #ifdef DEBUG    \r
4369         fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1);\r
4370 #endif\r
4371       \r
4372         /* Looking for end */\r
4373         i=0;\r
4374         while (true) {\r
4375           if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {\r
4376             i=i+2;break;\r
4377           }\r
4378           if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {\r
4379             i=i+2;break;\r
4380           }\r
4381           i++;\r
4382           if (i==MessageLength) break;\r
4383         }\r
4384           \r
4385         /* Copying frame */\r
4386         memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3);\r
4387         CurrentGetBinRingtone->length=i-3;\r
4388       \r
4389         CurrentBinRingtoneError=GE_NONE;\r
4390         break;\r
4391       }\r
4392           \r
4393       /* Binary format used in N3210 */\r
4394       if (MessageBuffer[5]==0x10 && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) {      \r
4395 \r
4396 #ifdef DEBUG\r
4397         fprintf(stdout,_("Message: ringtone \""));\r
4398 #endif      \r
4399 \r
4400         /* Copying name */\r
4401         i=8;\r
4402         while (true) {\r
4403 #ifdef DEBUG\r
4404           if (MessageBuffer[i]!=0)\r
4405             fprintf(stdout,_("%c"),MessageBuffer[i]);\r
4406 #endif\r
4407           CurrentGetBinRingtone->name[i-8]=MessageBuffer[i];\r
4408           if (MessageBuffer[i]==0) break;\r
4409           i++;\r
4410         }\r
4411 \r
4412 #ifdef DEBUG    \r
4413         fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1);\r
4414 #endif\r
4415 \r
4416         /* Here changes to get full compatibility with binary format used in N6150 */\r
4417         MessageBuffer[3]=0;\r
4418         MessageBuffer[4]=0;\r
4419         MessageBuffer[5]=0x0c;\r
4420         MessageBuffer[6]=0x01;\r
4421         MessageBuffer[7]=0x2c;\r
4422 \r
4423         /* Looking for end */\r
4424         i=0;\r
4425         while (true) {\r
4426           if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) {\r
4427             i=i+2;break;\r
4428           }\r
4429           if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) {\r
4430             i=i+2;break;\r
4431           }\r
4432           i++;\r
4433           if (i==MessageLength) break;\r
4434         }\r
4435           \r
4436         /* Copying frame */\r
4437         memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3);\r
4438 \r
4439         CurrentGetBinRingtone->length=i-3;\r
4440             \r
4441         CurrentBinRingtoneError=GE_NONE;          \r
4442         break;\r
4443       }\r
4444 \r
4445       /* Copying frame */\r
4446       memcpy(CurrentGetBinRingtone->frame,MessageBuffer,MessageLength);\r
4447 \r
4448       CurrentGetBinRingtone->length=MessageLength;\r
4449 \r
4450 #ifdef DEBUG    \r
4451       fprintf(stdout,_("Message: unknown binary format for ringtone received from location %i\n"),MessageBuffer[3]+1);\r
4452 #endif\r
4453       CurrentBinRingtoneError=GE_UNKNOWNMODEL;\r
4454       break;\r
4455 \r
4456     default:\r
4457 \r
4458 #ifdef DEBUG\r
4459       fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1);\r
4460 #endif\r
4461 \r
4462       CurrentBinRingtoneError=GE_INVALIDRINGLOCATION;  \r
4463   }\r
4464 }\r
4465 \r
4466 GSM_Error N6110_GetBinRingTone(GSM_BinRingtone *ringtone)\r
4467 {\r
4468   unsigned char req[] = { 0x00,0x01,0x9e,\r
4469                           0x00 }; //location\r
4470 \r
4471   GSM_Error error;\r
4472   \r
4473   CurrentGetBinRingtone=ringtone;\r
4474   \r
4475   error=N6110_EnableExtendedCommands(0x01);\r
4476   if (error!=GE_NONE) return error;\r
4477 \r
4478   req[3]=ringtone->location-1;\r
4479   \r
4480   return NULL_SendMessageSequence\r
4481     (50, &CurrentBinRingtoneError, 4, 0x40, req);\r
4482 }\r
4483 \r
4484 void N6110_ReplySetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4485 \r
4486   switch (MessageBuffer[4]) {\r
4487     case 0x00: /* location supported. We set ringtone */\r
4488 #ifdef DEBUG\r
4489       fprintf(stdout,_("Message: downloaded ringtone set at location %i\n"),MessageBuffer[3]+1);\r
4490 #endif\r
4491       CurrentBinRingtoneError=GE_NONE;\r
4492       break;\r
4493 \r
4494     default:\r
4495 #ifdef DEBUG\r
4496       fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1);\r
4497 #endif\r
4498       CurrentBinRingtoneError=GE_NOTSUPPORTED;    \r
4499       break;\r
4500   }\r
4501 }\r
4502 \r
4503 GSM_Error N6110_SetBinRingTone(GSM_BinRingtone *ringtone)\r
4504 {\r
4505   unsigned char req[1000] = { 0x00,0x01,0xa0};\r
4506 \r
4507   GSM_Error error;\r
4508 \r
4509   GSM_BinRingtone ring;\r
4510 \r
4511   /* Must be sure, that can upload ringtone to this phone */\r
4512   ring.location=ringtone->location;\r
4513   error=N6110_GetBinRingTone(&ring);\r
4514   if (error!=GE_NONE) return error;\r
4515     \r
4516   error=N6110_EnableExtendedCommands(0x01);\r
4517   if (error!=GE_NONE) return error;\r
4518   \r
4519   memcpy(req+3,ringtone->frame,ringtone->length);\r
4520 \r
4521   req[3]=ringtone->location-1;\r
4522   \r
4523   return NULL_SendMessageSequence\r
4524     (50, &CurrentBinRingtoneError, ringtone->length+3, 0x40, req);\r
4525 }\r
4526 \r
4527 GSM_Error N6110_Reset(unsigned char type)\r
4528 {  \r
4529   return N6110_EnableExtendedCommands(type);\r
4530 }\r
4531 \r
4532 void N6110_Dispatch0x01Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4533 \r
4534   int tmp, count;\r
4535           \r
4536   switch (MessageBuffer[3]) {\r
4537 \r
4538   /* Unknown message - it has been seen after the 0x07 message (call\r
4539      answered). Probably it has similar meaning. If you can solve\r
4540      this - just mail me. Pavel Janík ml.\r
4541 \r
4542      The message looks like this:\r
4543 \r
4544      Msg Destination: PC\r
4545      Msg Source: Phone\r
4546      Msg Type: 01\r
4547      Msg Unknown: 00\r
4548      Msg Len: 0e\r
4549 \r
4550      Phone: [01 ][08 ][00 ] is the header of the frame\r
4551 \r
4552      [03 ] is the call message subtype\r
4553 \r
4554      [05 ] is the call sequence number\r
4555 \r
4556      [05 ] unknown \r
4557 \r
4558      [00 ][01 ][03 ][02 ][91][00] are unknown but has been\r
4559      seen in the Incoming call message (just after the\r
4560      caller's name from the phonebook). But never change\r
4561      between phone calls :-(\r
4562   */\r
4563 \r
4564   /* This may mean sequence number of 'just made' call - CK */\r
4565   case 0x02:\r
4566 \r
4567 #ifdef DEBUG\r
4568     fprintf(stdout, _("Message: Call message, type 0x02:"));\r
4569     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));\r
4570 #endif /* DEBUG */\r
4571 \r
4572     break;\r
4573 \r
4574   /* Possibly call OK */\r
4575   /* JD: I think that this means "call in progress" (incomming or outgoing) */\r
4576   case 0x03:\r
4577     \r
4578 #ifdef DEBUG\r
4579     fprintf(stdout, _("Message: Call message, type 0x03:"));\r
4580     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);\r
4581     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));\r
4582 #endif /* DEBUG */\r
4583     \r
4584     CurrentCallSequenceNumber=MessageBuffer[4];\r
4585     CurrentIncomingCall[0]='D';\r
4586     if (CurrentCallPassup) CurrentCallPassup('D');\r
4587 \r
4588     break;\r
4589 \r
4590   /* Remote end has gone away before you answer the call.  Probably your\r
4591      mother-in-law or banker (which is worse?) ... */\r
4592   case 0x04:\r
4593 \r
4594 #ifdef DEBUG\r
4595     fprintf(stdout, _("Message: Remote end hang up.\n"));\r
4596     fprintf(stdout, _("   Sequence nr. of the call: %d, error: %i"), MessageBuffer[4],MessageBuffer[6]);\r
4597 \r
4598     switch (MessageBuffer[6]) {\r
4599       case 28: fprintf(stdout,_(" (info \"Invalid phone number\")"));break;\r
4600       case 34: fprintf(stdout,_(" (info \"Network busy\")"));break;\r
4601       case 42: fprintf(stdout,_(" (info \"Network busy\")"));break;\r
4602       case 47: fprintf(stdout,_(" (info \"Error in connection\")"));break;\r
4603       case 50: fprintf(stdout,_(" (info \"Check operator services\")"));break;       case 76: fprintf(stdout,_(" (info \"Check operator services\")"));break;\r
4604       case 111: fprintf(stdout,_(" (info \"Error in connection\")"));break;\r
4605     }\r
4606       \r
4607     fprintf(stdout,_("\n   For more details with errors see netmonitor manual (test 39) on www.marcin-wiacek.topnet.pl"));\r
4608     fprintf(stdout,_("\n   If know their meaning, GSM specs decribing them, contact with me on marcin-wiacek@topnet.pl. THX\n"));\r
4609 #endif /* DEBUG */\r
4610 \r
4611     CurrentIncomingCall[0] = ' ';\r
4612     if (CurrentCallPassup) CurrentCallPassup(' ');\r
4613 \r
4614     break;\r
4615 \r
4616   /* Incoming call alert */\r
4617   case 0x05:\r
4618 \r
4619 #ifdef DEBUG\r
4620     fprintf(stdout, _("Message: Incoming call alert:\n"));\r
4621 \r
4622     /* We can have more then one call ringing - we can distinguish between\r
4623        them */\r
4624 \r
4625     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);\r
4626     fprintf(stdout, _("   Number: "));\r
4627 \r
4628     count=MessageBuffer[6];\r
4629 \r
4630     for (tmp=0; tmp <count; tmp++)\r
4631       fprintf(stdout, "%c", MessageBuffer[7+tmp]);\r
4632 \r
4633     fprintf(stdout, "\n");\r
4634 \r
4635     fprintf(stdout, _("   Name: "));\r
4636 \r
4637     for (tmp=0; tmp <MessageBuffer[7+count]; tmp++)\r
4638       fprintf(stdout, "%c", MessageBuffer[8+count+tmp]);\r
4639 \r
4640     fprintf(stdout, "\n");\r
4641 #endif /* DEBUG */\r
4642 \r
4643     count=MessageBuffer[6];\r
4644 \r
4645     CurrentIncomingCall[0] = 0;\r
4646     for (tmp=0; tmp <count; tmp++)\r
4647       sprintf(CurrentIncomingCall, "%s%c", CurrentIncomingCall, MessageBuffer[7+tmp]);\r
4648 \r
4649     break;\r
4650 \r
4651   /* Call answered. Probably your girlfriend...*/\r
4652   case 0x07:\r
4653 \r
4654 #ifdef DEBUG\r
4655     fprintf(stdout, _("Message: Call answered.\n"));\r
4656     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);\r
4657 #endif /* DEBUG */\r
4658 \r
4659     break;\r
4660 \r
4661   /* Call ended. Girlfriend is girlfriend, but time is money :-) */\r
4662   case 0x09:\r
4663 \r
4664 #ifdef DEBUG\r
4665     fprintf(stdout, _("Message: Call ended by your phone.\n"));\r
4666     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);\r
4667 #endif /* DEBUG */\r
4668 \r
4669     break;\r
4670 \r
4671   /* This message has been seen with the message of subtype 0x09\r
4672      after I hang the call.\r
4673 \r
4674   Msg Destination: PC\r
4675   Msg Source: Phone\r
4676   Msg Type: 01 \r
4677   Msg Unknown: 00\r
4678   Msg Len: 08\r
4679   Phone: [01 ][08 ][00 ][0a ][04 ][87 ][01 ][42B][1a ][c2 ]\r
4680 \r
4681   What is the meaning of 87? Can you spell some magic light into\r
4682   this issue?\r
4683 \r
4684   */\r
4685 \r
4686   /* Probably means call over - CK */\r
4687   case 0x0a:\r
4688 \r
4689 #ifdef DEBUG\r
4690     fprintf(stdout, _("Message: Call message, type 0x0a:"));\r
4691     fprintf(stdout, _("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);\r
4692     fprintf(stdout, _("   Exact meaning not known yet, sorry :-(\n"));\r
4693 #endif /* DEBUG */\r
4694 \r
4695     CurrentIncomingCall[0] = ' ';\r
4696     if (CurrentCallPassup) CurrentCallPassup(' ');\r
4697 \r
4698     break;\r
4699 \r
4700   case 0x40:\r
4701 \r
4702 #ifdef DEBUG\r
4703       fprintf(stdout, _("Message: Answer for send DTMF or dial voice command\n"));\r
4704 #endif\r
4705 \r
4706     if (CurrentSendDTMFError!=GE_NONE) CurrentSendDTMFError=GE_NONE;\r
4707 \r
4708     if (CurrentDialVoiceError!=GE_NONE) CurrentDialVoiceError=GE_NONE;\r
4709 \r
4710     break;\r
4711      \r
4712   default:\r
4713 \r
4714 #ifdef DEBUG\r
4715     fprintf(stdout, _("Message: Unknown message of type 0x01\n"));\r
4716 #endif /* DEBUG */\r
4717     AppendLogText("Unknown msg\n",false);\r
4718 \r
4719     break;      /* Visual C Don't like empty cases */\r
4720   }\r
4721 }\r
4722 \r
4723 void N6110_Dispatch0x03Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4724 \r
4725   int tmp, count;\r
4726     \r
4727   switch (MessageBuffer[3]) {\r
4728 \r
4729   case 0x04:\r
4730 \r
4731     /* AFAIK, this frame isn't used anywhere - it's rather for testing :-) */\r
4732     /* If you want see, if it works with your phone make something like that: */\r
4733 \r
4734     /* unsigned char connect5[] = {N6110_FRAME_HEADER, 0x03}; */\r
4735     /* Protocol->SendMessage(4, 0x04, connect5); */\r
4736 \r
4737     /*                                        Marcin-Wiacek@TopNet.PL */\r
4738     \r
4739 #ifdef WIN32\r
4740     sprintf(Current_IMEI, "%s", MessageBuffer+5);\r
4741     sprintf(Current_Model, "%s", MessageBuffer+21);\r
4742     sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35);\r
4743 #else\r
4744     snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+5);\r
4745     snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+21);\r
4746     snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35);\r
4747 #endif\r
4748 \r
4749 #ifdef DEBUG\r
4750     fprintf(stdout, _("Message: Mobile phone identification received:\n"));\r
4751     fprintf(stdout, _("   IMEI: %s\n"), Current_IMEI);\r
4752     fprintf(stdout, _("   Model: %s\n"), Current_Model);\r
4753     fprintf(stdout, _("   Production Code: %s\n"), MessageBuffer+27);\r
4754     fprintf(stdout, _("   HW: %s\n"), MessageBuffer+35);\r
4755     fprintf(stdout, _("   Firmware: %s\n"), MessageBuffer+41);\r
4756 #endif /* DEBUG */\r
4757 \r
4758     break;\r
4759 \r
4760   /* Get group data */    \r
4761   /* [ID],[name_len],[name].,[ringtone],[graphicon],[lenhi],[lenlo],[bitmap] */\r
4762   case 0x11:   \r
4763  \r
4764     if (CurrentGetBitmap!=NULL) {\r
4765       if (CurrentGetBitmap->number==MessageBuffer[4]) {\r
4766         count=MessageBuffer[5];\r
4767         memcpy(CurrentGetBitmap->text,MessageBuffer+6,count);\r
4768         CurrentGetBitmap->text[count]=0;\r
4769 \r
4770 #ifdef DEBUG    \r
4771         fprintf(stdout, _("Message: Caller group datas\n"));\r
4772         fprintf(stdout, _("Caller group name: %s\n"),CurrentGetBitmap->text);\r
4773 #endif /* DEBUG */\r
4774 \r
4775         count+=6;\r
4776 \r
4777         CurrentGetBitmap->ringtone=MessageBuffer[count++];\r
4778 #ifdef DEBUG    \r
4779         fprintf(stdout, _("Caller group ringtone ID: %i"),CurrentGetBitmap->ringtone);\r
4780         if (CurrentGetBitmap->ringtone==16) fprintf(stdout,_(" (default)"));\r
4781         fprintf(stdout,_("\n"));\r
4782 #endif /* DEBUG */\r
4783 \r
4784         CurrentGetBitmap->enabled=(MessageBuffer[count++]==1);\r
4785 #ifdef DEBUG    \r
4786         fprintf(stdout, _("Caller group logo "));\r
4787         if (CurrentGetBitmap->enabled)\r
4788           fprintf(stdout, _("enabled \n"));\r
4789         else\r
4790           fprintf(stdout, _("disabled \n"));\r
4791 #endif /* DEBUG */      \r
4792 \r
4793         CurrentGetBitmap->size=MessageBuffer[count++]<<8;\r
4794         CurrentGetBitmap->size+=MessageBuffer[count++];\r
4795 #ifdef DEBUG    \r
4796         fprintf(stdout, _("Bitmap size=%i\n"),CurrentGetBitmap->size);\r
4797 #endif /* DEBUG */\r
4798 \r
4799         count++;\r
4800         CurrentGetBitmap->width=MessageBuffer[count++];\r
4801         CurrentGetBitmap->height=MessageBuffer[count++];\r
4802         count++;\r
4803         tmp=GSM_GetBitmapSize(CurrentGetBitmap);\r
4804         if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp;\r
4805         memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);\r
4806         CurrentGetBitmapError=GE_NONE;\r
4807       } else {\r
4808 #ifdef DEBUG    \r
4809         fprintf(stdout, _("Message: Caller group datas received, but group number does not match (%i is not %i)\n"),MessageBuffer[4],CurrentGetBitmap->number);\r
4810 #endif\r
4811       }\r
4812     } else {\r
4813 #ifdef DEBUG\r
4814       fprintf(stdout, _("Message: Caller group data received but not requested!\n"));\r
4815 #endif\r
4816     }\r
4817     break;\r
4818 \r
4819   /* Get group data error */\r
4820   case 0x12:   \r
4821       \r
4822     CurrentGetBitmapError=GE_UNKNOWN;   \r
4823 #ifdef DEBUG\r
4824     fprintf(stdout, _("Message: Error attempting to get caller group data.\n"));\r
4825 #endif   \r
4826     break;\r
4827 \r
4828   /* Set group data OK */      \r
4829   case 0x14:   \r
4830       \r
4831     CurrentSetBitmapError=GE_NONE;      \r
4832 #ifdef DEBUG\r
4833     fprintf(stdout, _("Message: Caller group data set correctly.\n"));\r
4834 #endif\r
4835     break;\r
4836 \r
4837   /* Set group data error */\r
4838   case 0x15:   \r
4839       \r
4840     CurrentSetBitmapError=GE_UNKNOWN;      \r
4841 #ifdef DEBUG\r
4842     fprintf(stdout, _("Message: Error attempting to set caller group data\n"));\r
4843 #endif\r
4844     break;  \r
4845   \r
4846   default:\r
4847 \r
4848 #ifdef DEBUG\r
4849     fprintf(stdout, _("Message: Unknown message of type 0x03\n"));\r
4850 #endif /* DEBUG */\r
4851     AppendLogText("Unknown msg\n",false);\r
4852 \r
4853     break;      /* Visual C Don't like empty cases */\r
4854   }\r
4855 }\r
4856 \r
4857 void N6110_Dispatch0x05Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
4858 \r
4859   int tmp, count, length;\r
4860   bool issupported;\r
4861
4862 #ifdef DEBUG
4863   int i;
4864 #endif
4865
4866   switch (MessageBuffer[3]) {\r
4867 \r
4868   /* Startup Logo */\r
4869   case 0x17:  \r
4870 \r
4871 #ifdef DEBUG\r
4872     fprintf(stdout, _("Message: Startup Logo, welcome note and dealer welcome note received.\n"));\r
4873 #endif\r
4874 \r
4875     if (CurrentGetBitmap!=NULL) {\r
4876        \r
4877       issupported=false;\r
4878        \r
4879       count=5;\r
4880        \r
4881       for (tmp=0;tmp<MessageBuffer[4];tmp++){\r
4882         switch (MessageBuffer[count++]) {\r
4883         case 0x01:\r
4884           if (CurrentGetBitmap->type==GSM_StartupLogo) {\r
4885             CurrentGetBitmap->height=MessageBuffer[count++];\r
4886             CurrentGetBitmap->width=MessageBuffer[count++];\r
4887             CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap);\r
4888             length=CurrentGetBitmap->size;\r
4889             memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,length);\r
4890           } else {\r
4891             //bitmap size\r
4892             length=MessageBuffer[count++];\r
4893             length=length*MessageBuffer[count++]/8;\r
4894           }\r
4895           count+=length;\r
4896 #ifdef DEBUG\r
4897           fprintf(stdout, _("Startup logo supported - "));\r
4898           if (length!=0) { fprintf(stdout, _("currently set\n"));   }\r
4899                     else { fprintf(stdout, _("currently empty\n")); }\r
4900 #endif\r
4901           if (CurrentGetBitmap->type==GSM_StartupLogo) issupported=true;\r
4902           break;\r
4903         case 0x02:\r
4904           length=MessageBuffer[count];\r
4905           if (CurrentGetBitmap->type==GSM_WelcomeNoteText) {\r
4906             memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length);\r
4907             CurrentGetBitmap->text[length]=0;\r
4908           }\r
4909 #ifdef DEBUG\r
4910           fprintf(stdout, _("Startup Text supported - "));\r
4911           if (length!=0)\r
4912           {\r
4913             fprintf(stdout, _("currently set to \""));\r
4914             for (i=0;i<length;i++) fprintf(stdout, _("%c"),MessageBuffer[count+1+i]);\r
4915             fprintf(stdout, _("\"\n"));\r
4916           } else {\r
4917             fprintf(stdout, _("currently empty\n"));\r
4918           }\r
4919 #endif\r
4920           count+=length+1;\r
4921           if (CurrentGetBitmap->type==GSM_WelcomeNoteText) issupported=true;\r
4922           break;\r
4923         case 0x03:\r
4924           length=MessageBuffer[count];\r
4925           if (CurrentGetBitmap->type==GSM_DealerNoteText) {\r
4926             memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length);\r
4927             CurrentGetBitmap->text[length]=0;\r
4928           }\r
4929 #ifdef DEBUG\r
4930           fprintf(stdout, _("Dealer Welcome supported - "));\r
4931           if (length!=0)\r
4932           {\r
4933             fprintf(stdout, _("currently set to \""));\r
4934             for (i=0;i<length;i++) fprintf(stdout, _("%c"),MessageBuffer[count+1+i]);\r
4935             fprintf(stdout, _("\"\n"));\r
4936           } else {\r
4937             fprintf(stdout, _("currently empty\n"));\r
4938           }\r
4939 #endif\r
4940           count+=length+1;\r
4941           if (CurrentGetBitmap->type==GSM_DealerNoteText) issupported=true;\r
4942           break;\r
4943         }\r
4944       }\r
4945       if (issupported) CurrentGetBitmapError=GE_NONE;\r
4946                   else CurrentGetBitmapError=GE_NOTSUPPORTED;\r
4947     } else {\r
4948 #ifdef DEBUG\r
4949       fprintf(stdout, _("Message: Startup logo received but not requested!\n"));\r
4950 #endif\r
4951     }\r
4952     break;\r
4953 \r
4954   /* Set startup OK */\r
4955   case 0x19:   \r
4956     \r
4957     CurrentSetBitmapError=GE_NONE;    \r
4958 #ifdef DEBUG\r
4959     fprintf(stdout, _("Message: Startup logo, welcome note or dealer welcome note correctly set.\n"));\r
4960 #endif  \r
4961     break;      \r
4962 \r
4963   /* Set Operator Logo OK */\r
4964   case 0x31:   \r
4965       \r
4966 #ifdef DEBUG\r
4967     fprintf(stdout, _("Message: Operator logo correctly set.\n"));\r
4968 #endif  \r
4969 \r
4970     CurrentSetBitmapError=GE_NONE;      \r
4971     break;\r
4972 \r
4973   /* Set Operator Logo Error */      \r
4974   case 0x32:  \r
4975       \r
4976 #ifdef DEBUG\r
4977     fprintf(stdout, _("Message: Error setting operator logo!\n"));\r
4978 #endif\r
4979 \r
4980     CurrentSetBitmapError=GE_UNKNOWN;        \r
4981     break;\r
4982 \r
4983   /* Operator Logo */\r
4984   /* [location],[netcode x 3],[lenhi],[lenlo],[bitmap] */ \r
4985   case 0x34:\r
4986  \r
4987     if (CurrentGetBitmap!=NULL) {\r
4988 \r
4989       count=5;  /* Location ignored. */\r
4990 \r
4991       DecodeNetworkCode(MessageBuffer+count, CurrentGetBitmap->netcode);
4992       count=count+3;
4993 \r
4994 #ifdef DEBUG\r
4995       fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"),\r
4996                            CurrentGetBitmap->netcode,\r
4997                            GSM_GetNetworkName(CurrentGetBitmap->netcode));\r
4998 #endif  \r
4999 \r
5000       CurrentGetBitmap->size=MessageBuffer[count++]<<8;\r
5001       CurrentGetBitmap->size+=MessageBuffer[count++];\r
5002       count++;\r
5003       CurrentGetBitmap->width=MessageBuffer[count++];\r
5004       CurrentGetBitmap->height=MessageBuffer[count++];\r
5005       count++;\r
5006       tmp=GSM_GetBitmapSize(CurrentGetBitmap);\r
5007       if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp;\r
5008       memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size);\r
5009       CurrentGetBitmapError=GE_NONE;\r
5010     } else {\r
5011 #ifdef DEBUG\r
5012       fprintf(stdout, _("Message: Operator logo received but not requested!\n"));\r
5013 #endif\r
5014     }\r
5015       \r
5016     break;\r
5017 \r
5018   /* Get op logo error */      \r
5019   case 0x35:\r
5020      \r
5021 #ifdef DEBUG\r
5022     fprintf(stdout, _("Message: Error getting operator logo!\n"));\r
5023 #endif  \r
5024     CurrentGetBitmapError=GE_UNKNOWN; \r
5025     break;\r
5026 \r
5027   default:\r
5028 \r
5029 #ifdef DEBUG\r
5030     fprintf(stdout, _("Message: Unknown message of type 0x05\n"));\r
5031 #endif /* DEBUG */\r
5032     AppendLogText("Unknown msg\n",false);\r
5033 \r
5034     break;\r
5035   }\r
5036 }\r
5037 \r
5038 void N6110_Dispatch0x06Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5039 \r
5040   int tmp;\r
5041   unsigned char output[160];\r
5042
5043 #ifdef DEBUG
5044   int i;
5045 #endif
5046     \r
5047   switch (MessageBuffer[3]) {\r
5048
5049   case 0x05:\r
5050 \r
5051     /* MessageBuffer[3] = 0x05\r
5052        MessageBuffer[4] = 0x00\r
5053        MessageBuffer[5] = 0x0f\r
5054        MessageBuffer[6] = 0x03\r
5055        MessageBuffer[7] = length of packed message\r
5056 \r
5057        This is all I have seen - Gerry Anderson */\r
5058 \r
5059     tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, MessageBuffer+8, output);\r
5060 \r
5061 #ifdef DEBUG\r
5062 \r
5063     fprintf(stdout, _("Message from Network operator: "));\r
5064 \r
5065     for (i=0; i<tmp; i++)\r
5066        fprintf(stdout, "%c", DecodeWithDefaultAlphabet(output[i]));\r
5067 \r
5068     fprintf(stdout, "\n");\r
5069 \r
5070 #endif /* DEBUG */\r
5071 \r
5072     break;\r
5073 \r
5074   default:\r
5075 \r
5076 #ifdef DEBUG\r
5077     fprintf(stdout, _("Message: Unknown message of type 0x06\n"));\r
5078 #endif /* DEBUG */\r
5079     AppendLogText("Unknown msg\n",false);\r
5080 \r
5081     break;\r
5082   }\r
5083 }\r
5084 \r
5085 void N6110_Dispatch0x09Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5086     \r
5087   switch (MessageBuffer[3]) {\r
5088     \r
5089   case 0x80:    \r
5090 #ifdef DEBUG\r
5091     fprintf(stdout, _("Message: SIM card login\n"));\r
5092 #endif\r
5093     break;\r
5094 \r
5095   case 0x81:    \r
5096 #ifdef DEBUG\r
5097     fprintf(stdout, _("Message: SIM card logout\n"));\r
5098 #endif\r
5099     break;\r
5100       \r
5101   default:\r
5102 #ifdef DEBUG\r
5103     fprintf(stdout, _("Unknown message of type 0x09.\n"));      \r
5104 #endif\r
5105     AppendLogText("Unknown msg\n",false);\r
5106     break;\r
5107   }\r
5108 }\r
5109 \r
5110 void N6110_Dispatch0x13Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5111 \r
5112   switch(MessageBuffer[3]) {\r
5113     \r
5114   case 0x6a:\r
5115 \r
5116 #ifdef DEBUG\r
5117     fprintf(stdout, _("Message: Calendar Alarm active\n"));\r
5118     fprintf(stdout, _("   Item number: %d\n"), MessageBuffer[4]);\r
5119 #endif /* DEBUG */\r
5120 \r
5121   default:\r
5122 #ifdef DEBUG\r
5123     fprintf(stdout, _("Unknown message of type 0x13.\n"));      \r
5124 #endif\r
5125     AppendLogText("Unknown msg\n",false);\r
5126     break;\r
5127   }\r
5128 }\r
5129 \r
5130 void N6110_Dispatch0x40Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5131 \r
5132   int i;\r
5133   \r
5134   switch(MessageBuffer[2]) {\r
5135 \r
5136   case 0x02:\r
5137 \r
5138 #ifdef DEBUG\r
5139     fprintf(stdout, _("Message: ACK for simlock opening part 1\n"));\r
5140 #endif /* DEBUG */\r
5141     \r
5142     CurrentMagicError=GE_NONE;\r
5143     break;\r
5144     \r
5145   case 0x7c:\r
5146 \r
5147 #ifdef DEBUG\r
5148     fprintf(stdout, _("Message: Answer for call commands.\n"));\r
5149 #endif\r
5150     \r
5151     CurrentDialVoiceError=GE_NONE;      \r
5152     break;\r
5153       \r
5154   case 0x81:\r
5155 \r
5156 #ifdef DEBUG\r
5157     fprintf(stdout, _("Message: ACK for simlock opening part 2\n"));\r
5158 #endif /* DEBUG */\r
5159     \r
5160     CurrentMagicError=GE_NONE;\r
5161     break;\r
5162 \r
5163   case 0x82:\r
5164 \r
5165 #ifdef DEBUG\r
5166       fprintf(stdout, _("Message: ACK for simlock closing\n"));\r
5167 #endif /* DEBUG */\r
5168     \r
5169     CurrentMagicError=GE_NONE;\r
5170     break;\r
5171 \r
5172   case 0xd4:\r
5173 \r
5174     switch (MessageBuffer[5]) {\r
5175       case 0xa0:\r
5176 #ifdef DEBUG\r
5177         fprintf(stdout,_("Message: EEPROM contest received\n"));\r
5178 #endif\r
5179 \r
5180         if (MessageBuffer[8]!=0x00) {\r
5181           for (i=9;i<MessageLength;i++) {\r
5182             fprintf(stdout,_("%c"), MessageBuffer[i]);\r
5183         }\r
5184 \r
5185         CurrentMagicError=GE_NONE;\r
5186       }\r
5187       \r
5188       break;\r
5189     }\r
5190       \r
5191 #ifdef DEBUG\r
5192     fprintf(stdout, _("Unknown message of type 0x40.\n"));\r
5193 #endif /* DEBUG */\r
5194     AppendLogText("Unknown msg\n",false);      \r
5195     break;\r
5196 \r
5197   case 0xcf:\r
5198 \r
5199     N6110_DisplayTestsInfo(MessageBuffer);\r
5200     break;\r
5201       \r
5202   default:\r
5203 \r
5204 #ifdef DEBUG\r
5205     fprintf(stdout, _("Unknown message of type 0x40.\n"));\r
5206 #endif /* DEBUG */\r
5207     AppendLogText("Unknown msg\n",false);\r
5208     break;      /* Visual C Don't like empty cases */\r
5209   }\r
5210 }\r
5211 \r
5212 void N6110_Dispatch0x47Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5213 \r
5214   int count;\r
5215   \r
5216   switch(MessageBuffer[3]) {\r
5217     \r
5218   case 0x02:\r
5219 \r
5220     count=5;\r
5221     \r
5222     if (MessageBuffer[5]!=0) {\r
5223       strcpy(CurrentGetBitmap->Sender,GSM_UnpackSemiOctetNumber(MessageBuffer+5,true));\r
5224 \r
5225       while (MessageBuffer[count]!=0) {\r
5226         count++;\r
5227       }\r
5228 \r
5229       count++;\r
5230     } else {\r
5231       strcpy(CurrentGetBitmap->Sender,"\0");\r
5232 \r
5233       count+=3;\r
5234     }\r
5235 \r
5236     memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,MessageBuffer[count]);\r
5237     CurrentGetBitmap->text[MessageBuffer[count]]=0;\r
5238 \r
5239     if (MessageBuffer[count]!=0)\r
5240       count+=MessageBuffer[count];\r
5241 \r
5242     count++;\r
5243 \r
5244 #ifdef DEBUG\r
5245     fprintf(stdout,_("Picture Image received, text \"%s\", sender %s\n"),CurrentGetBitmap->text,CurrentGetBitmap->Sender);\r
5246 #endif\r
5247 \r
5248     CurrentGetBitmap->width=MessageBuffer[count+1];\r
5249     CurrentGetBitmap->height=MessageBuffer[count+2]; \r
5250     CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap);\r
5251       \r
5252     memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count+4,CurrentGetBitmap->size);\r
5253       \r
5254     CurrentGetBitmapError=GE_NONE;\r
5255     break;\r
5256 \r
5257   case 0x04:\r
5258 \r
5259 #ifdef DEBUG\r
5260     fprintf(stdout,_("Getting or setting Picture Image - OK\n"));\r
5261 #endif\r
5262     CurrentSetBitmapError=GE_NONE;\r
5263     CurrentGetBitmapError=GE_NONE;\r
5264     break;      \r
5265 \r
5266   case 0x05:\r
5267 \r
5268 #ifdef DEBUG\r
5269     fprintf(stdout,_("Setting Picture Image - invalid location or other error\n"));\r
5270 #endif\r
5271     CurrentSetBitmapError=GE_UNKNOWN;\r
5272     break;      \r
5273 \r
5274   case 0x06:\r
5275 \r
5276 #ifdef DEBUG\r
5277     fprintf(stdout,_("Getting Picture Image - invalid location or other error\n"));\r
5278 #endif\r
5279     CurrentGetBitmapError=GE_UNKNOWN;\r
5280     break;      \r
5281 \r
5282   default:\r
5283 \r
5284 #ifdef DEBUG\r
5285     fprintf(stdout, _("Unknown message of type 0x47.\n"));\r
5286 #endif /* DEBUG */\r
5287     AppendLogText("Unknown msg\n",false);\r
5288     break;      /* Visual C Don't like empty cases */\r
5289   }\r
5290 }\r
5291 \r
5292 void N6110_DispatchACKMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5293   char buffer[50];\r
5294   \r
5295   sprintf(buffer,"Received ACK %02x %02x\n",MessageBuffer[0],MessageBuffer[1]);\r
5296   AppendLog(buffer,strlen(buffer),false);\r
5297 \r
5298 #ifdef DEBUG\r
5299   fprintf(stdout, _("[Received Ack of type %02x, seq: %2x]\n"), MessageBuffer[0],\r
5300                                                                 MessageBuffer[1]);\r
5301 #endif /* DEBUG */\r
5302   \r
5303   CurrentLinkOK = true;\r
5304 }\r
5305 \r
5306 void N6110_Dispatch0xD0Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5307    \r
5308 #ifdef DEBUG\r
5309   fprintf(stdout, _("Message: The phone is powered on - seq 1.\n"));\r
5310 #endif /* DEBUG */\r
5311 \r
5312 }\r
5313 \r
5314 /* This function is used for parsing the RLP frame into fields. */\r
5315 void N6110_RX_HandleRLPMessage(u8 *MessageBuffer)\r
5316 {\r
5317 \r
5318   RLP_F96Frame frame;\r
5319   int count;\r
5320   int valid = true;\r
5321 \r
5322   /* We do not need RLP frame parsing to be done when we do not have callback\r
5323      specified. */\r
5324   if (CurrentRLP_RXCallback == NULL)\r
5325     exit;\r
5326     \r
5327   /* Anybody know the official meaning of the first two bytes?\r
5328      Nokia 6150 sends junk frames starting D9 01, and real frames starting\r
5329      D9 00. We'd drop the junk frames anyway because the FCS is bad, but\r
5330      it's tidier to do it here. We still need to call the callback function\r
5331      to give it a chance to handle timeouts and/or transmit a frame */\r
5332   if (MessageBuffer[0] == 0xd9 && MessageBuffer[1] == 0x01)\r
5333     valid = false;\r
5334 \r
5335   /* Nokia uses 240 bit frame size of RLP frames as per GSM 04.22\r
5336      specification, so Header consists of 16 bits (2 bytes). See section 4.1\r
5337      of the specification. */\r
5338     \r
5339   frame.Header[0] = MessageBuffer[2];\r
5340   frame.Header[1] = MessageBuffer[3];\r
5341 \r
5342   /* Next 200 bits (25 bytes) contain the Information. We store the\r
5343      information in the Data array. */\r
5344 \r
5345   for (count = 0; count < 25; count ++)\r
5346     frame.Data[count] = MessageBuffer[4 + count];\r
5347 \r
5348   /* The last 24 bits (3 bytes) contain FCS. */\r
5349 \r
5350   frame.FCS[0] = MessageBuffer[29];\r
5351   frame.FCS[1] = MessageBuffer[30];\r
5352   frame.FCS[2] = MessageBuffer[31];\r
5353 \r
5354   /* Here we pass the frame down in the input stream. */\r
5355   CurrentRLP_RXCallback(valid ? &frame : NULL);\r
5356 }\r
5357 \r
5358 void N6110_Dispatch0xF4Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5359 \r
5360 #ifdef DEBUG\r
5361   fprintf(stdout, _("Message: The phone is powered on - seq 2.\n"));\r
5362 #endif /* DEBUG */\r
5363 \r
5364 }\r
5365 \r
5366 void N6110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5367 \r
5368   GSM_SMSMessage NullSMS;\r
5369 \r
5370   switch (MessageBuffer[6]) {\r
5371 \r
5372     case 0x00: NullSMS.Type = GST_SMS; NullSMS.folder = GST_INBOX; break;\r
5373     case 0x01: NullSMS.Type = GST_DR;  NullSMS.folder = GST_INBOX; break;\r
5374 \r
5375     /* Is it possible ? */\r
5376     case 0x02: NullSMS.Type = GST_SMS; NullSMS.folder = GST_OUTBOX; break;      \r
5377     default:   NullSMS.Type = GST_UN;                               break;\r
5378   }\r
5379 \r
5380 #ifdef DEBUG\r
5381   if (NullSMS.Type == GST_DR)\r
5382     fprintf(stdout, _("Message: SMS Message (Report) Received\n"));\r
5383   else \r
5384     fprintf(stdout, _("Message: SMS Message Received\n"));  \r
5385 #endif /* DEBUG */\r
5386 \r
5387   GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+7, MessageLength-7);\r
5388 \r
5389 #ifdef DEBUG\r
5390   fprintf(stdout, _("\n"));      \r
5391 #endif /* DEBUG */\r
5392 }\r
5393 \r
5394 void N6110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {\r
5395
5396   bool unknown=false;
5397
5398   /* Switch on the basis of the message type byte */\r
5399   switch (MessageType) {\r
5400           \r
5401   /* Call information */\r
5402   case 0x01:\r
5403 \r
5404     N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType);\r
5405     break;\r
5406 \r
5407   /* SMS handling */\r
5408   case 0x02:\r
5409     switch (MessageBuffer[3]) {\r
5410       case 0x02:\r
5411       case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break;\r
5412       case 0x10:N6110_ReplyIncomingSMS(MessageLength,MessageBuffer,MessageType);break;\r
5413       case 0x21:N6110_ReplySetCellBroadcast(MessageLength, MessageBuffer, MessageType);break;\r
5414       case 0x23:N6110_ReplyReadCellBroadcast(MessageLength, MessageBuffer, MessageType);break;\r
5415       case 0x31:N6110_ReplySetSMSCenter(MessageLength,MessageBuffer,MessageType);break;\r
5416       case 0x34:\r
5417       case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break;\r
5418       default  :unknown=true;break;\r
5419     }\r
5420     break;\r
5421 \r
5422   /* Phonebook handling */\r
5423   case 0x03:\r
5424     switch (MessageBuffer[3]) {\r
5425       case 0x02:\r
5426       case 0x03:N6110_ReplyGetMemoryLocation(MessageLength,MessageBuffer,MessageType);break;\r
5427       case 0x05:\r
5428       case 0x06:N6110_ReplyWritePhonebookLocation(MessageLength,MessageBuffer,MessageType);break;\r
5429       case 0x08:\r
5430       case 0x09:N6110_ReplyGetMemoryStatus(MessageLength,MessageBuffer,MessageType);break;\r
5431       case 0x17:\r
5432       case 0x18:N6110_ReplyGetSpeedDial(MessageLength,MessageBuffer,MessageType);break;\r
5433       case 0x1a:\r
5434       case 0x1b:N6110_ReplySetSpeedDial(MessageLength,MessageBuffer,MessageType);break;\r
5435       default  :N6110_Dispatch0x03Message(MessageLength,MessageBuffer,MessageType);break;\r
5436     }\r
5437     break;\r
5438 \r
5439   /* Phone status */     \r
5440   case 0x04:\r
5441     switch (MessageBuffer[3]) {\r
5442       case 0x02:N6110_ReplyRFBatteryLevel(MessageLength,MessageBuffer,MessageType);break;\r
5443       default  :unknown=true;break;\r
5444     }\r
5445     break;\r
5446       \r
5447   /* Startup Logo, Operator Logo and Profiles. */\r
5448   case 0x05:\r
5449     switch (MessageBuffer[3]) {\r
5450       case 0x11:N6110_ReplySetProfile    (MessageLength,MessageBuffer,MessageType);break;\r
5451       case 0x14:N6110_ReplyGetProfile    (MessageLength,MessageBuffer,MessageType);break;\r
5452       case 0x1b:N6110_ReplyGetProfile    (MessageLength,MessageBuffer,MessageType);break;\r
5453       case 0x1d:N6110_ReplySetProfile    (MessageLength,MessageBuffer,MessageType);break;\r
5454       case 0x37:N6110_ReplySetRingtone   (MessageLength,MessageBuffer,MessageType);break;\r
5455       case 0x38:N6110_ReplySetRingtone   (MessageLength,MessageBuffer,MessageType);break;\r
5456       default  :N6110_Dispatch0x05Message(MessageLength,MessageBuffer,MessageType);break;\r
5457     }\r
5458     break;\r
5459 \r
5460   /* Network Operator Message to handset -> Gerry Anderson & prepaid info */
5461   /* Call diverts */
5462   case 0x06:\r
5463     switch (MessageBuffer[3]) {\r
5464       case 0x02:\r
5465       case 0x03:N6110_ReplyCallDivert    (MessageLength,MessageBuffer,MessageType);break;\r
5466       default  :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break;\r
5467     }\r
5468     break;\r
5469 \r
5470   /* Security code requests */\r
5471   case 0x08:\r
5472     switch (MessageBuffer[3]) {\r
5473       case 0x08:N6110_ReplyGetSecurityCodeStatus(MessageLength,MessageBuffer,MessageType);break;\r
5474       case 0x0b:N6110_ReplyEnterSecurityCode    (MessageLength,MessageBuffer,MessageType);break;\r
5475       default  :N6110_ReplyEnterSecurityCode    (MessageLength,MessageBuffer,MessageType);break;\r
5476     }\r
5477     break;\r
5478 \r
5479   /* SIM login */\r
5480   case 0x09:\r
5481 \r
5482     N6110_Dispatch0x09Message(MessageLength, MessageBuffer, MessageType);\r
5483     break;\r
5484 \r
5485   /* Network info */\r
5486   case 0x0a:\r
5487     switch (MessageBuffer[3]) {\r
5488       case 0x71:N6110_ReplyGetNetworkInfo(MessageLength,MessageBuffer,MessageType);break;\r
5489       default  :unknown=true;break;\r
5490     }\r
5491     break;\r
5492 \r
5493   /* Simulating key pressing */\r
5494   case 0x0c:\r
5495     switch (MessageBuffer[3]) {\r
5496       case 0x43:N6110_ReplyPressKey(MessageLength,MessageBuffer,MessageType);break;\r
5497       default  :unknown=true;break;\r
5498     }\r
5499     break;\r
5500 \r
5501   /* Display */\r
5502   case 0x0d:\r
5503     switch (MessageBuffer[3]) {\r
5504       case 0x50:N6110_ReplyDisplayOutput   (MessageLength,MessageBuffer,MessageType);break;\r
5505       case 0x52:N6110_ReplyGetDisplayStatus(MessageLength,MessageBuffer,MessageType);break;\r
5506       case 0x54:N6110_ReplyDisplayOutput   (MessageLength,MessageBuffer,MessageType);break;\r
5507       default  :unknown=true;break;\r
5508     }\r
5509     break;\r
5510 \r
5511   /* Phone Clock and Alarm */\r
5512   case 0x11:\r
5513     switch (MessageBuffer[3]) {\r
5514       case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break;\r
5515       case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break;\r
5516       case 0x6c:N6110_ReplySetAlarm   (MessageLength,MessageBuffer,MessageType);break;\r
5517       case 0x6e:N6110_ReplyGetAlarm   (MessageLength,MessageBuffer,MessageType);break;\r
5518       default  :unknown=true;break;\r
5519     }\r
5520     break;\r
5521 \r
5522   /* Calendar notes handling */\r
5523   case 0x13:\r
5524     switch (MessageBuffer[3]) {\r
5525       case 0x65:N6110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break;\r
5526       case 0x67:N6110_ReplyGetCalendarNote   (MessageLength,MessageBuffer,MessageType);break;\r
5527       case 0x69:N6110_ReplyDeleteCalendarNote(MessageLength,MessageBuffer,MessageType);break;\r
5528       default  :N6110_Dispatch0x13Message    (MessageLength,MessageBuffer,MessageType);break;\r
5529     }\r
5530     break;\r
5531 \r
5532   /* SMS Messages */\r
5533   case 0x14:\r
5534     switch (MessageBuffer[3]) {\r
5535       case 0x05:\r
5536       case 0x06:N6110_ReplySaveSMSMessage  (MessageLength,MessageBuffer,MessageType);break;\r
5537       case 0x08:\r
5538       case 0x09:N6110_ReplyGetSMSMessage   (MessageLength,MessageBuffer,MessageType);break;\r
5539       case 0x0b:N6110_ReplyDeleteSMSMessage(MessageLength,MessageBuffer,MessageType);break;\r
5540       case 0x37:\r
5541       case 0x38:N6110_ReplyGetSMSStatus    (MessageLength,MessageBuffer,MessageType);break;\r
5542       default  :unknown=true;break;\r
5543     }\r
5544     break;\r
5545 \r
5546   /* WAP */\r
5547   case 0x3f:\r
5548     switch (MessageBuffer[3]) {\r
5549       case 0x01:\r
5550       case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break;\r
5551       case 0x07:\r
5552       case 0x08:N7110_ReplyGetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
5553       case 0x0a:
5554       case 0x0b:N7110_ReplySetWAPBookmark   (MessageLength,MessageBuffer,MessageType);break;
5555       case 0x16:
5556       case 0x17:
5557       case 0x1c:N7110_ReplyGetWAPSettings   (MessageLength,MessageBuffer,MessageType);break;
5558       default  :unknown=true;break;\r
5559     }\r
5560     break;\r
5561 \r
5562   /* Internal phone functions? */\r
5563   case 0x40:\r
5564     switch (MessageBuffer[2]) {\r
5565       case 0x64:N6110_ReplyEnableExtendedCommands  (MessageLength,MessageBuffer,MessageType);break;\r
5566       case 0x65:N6110_ReplyResetPhoneSettings      (MessageLength,MessageBuffer,MessageType);break;\r
5567       case 0x66:N6110_ReplyIMEI                    (MessageLength,MessageBuffer,MessageType);break;\r
5568       case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;\r
5569       case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break;\r
5570       case 0x6e:N6110_ReplyGetSecurityCode         (MessageLength,MessageBuffer,MessageType);break;\r
5571       case 0x7e:N6110_ReplyNetmonitor              (MessageLength,MessageBuffer,MessageType);break;\r
5572       case 0x8a:N6110_ReplySimlockInfo             (MessageLength,MessageBuffer,MessageType);break;\r
5573       case 0x8b:N6110_ReplySetOperatorName         (MessageLength,MessageBuffer,MessageType);break;\r
5574       case 0x8c:N6110_ReplyGetOperatorName         (MessageLength,MessageBuffer,MessageType);break;\r
5575       case 0x8f:N6110_ReplyPlayTone                (MessageLength,MessageBuffer,MessageType);break;\r
5576       case 0x9e:N6110_ReplyGetBinRingtone          (MessageLength,MessageBuffer,MessageType);break;\r
5577       case 0xa0:N6110_ReplySetBinRingtone          (MessageLength,MessageBuffer,MessageType);break;\r
5578       case 0xc8:N6110_ReplyHW                      (MessageLength,MessageBuffer,MessageType);break;\r
5579       default  :N6110_Dispatch0x40Message          (MessageLength,MessageBuffer,MessageType);break;\r
5580     }\r
5581     break;\r
5582 \r
5583   /* Picture Images */\r
5584   case 0x47:\r
5585 \r
5586     N6110_Dispatch0x47Message(MessageLength, MessageBuffer, MessageType);\r
5587     break;\r
5588 \r
5589   /* Mobile phone identification */\r
5590   case 0x64:\r
5591 \r
5592     N6110_ReplyGetAuthentication(MessageLength, MessageBuffer, MessageType);\r
5593     break;\r
5594 \r
5595   /***** Acknowlegment of our frames. *****/\r
5596   case FBUS_FRTYPE_ACK:\r
5597 \r
5598     N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType);\r
5599     break;\r
5600 \r
5601   /***** Power on message. *****/\r
5602   case 0xd0:\r
5603 \r
5604     N6110_Dispatch0xD0Message(MessageLength, MessageBuffer, MessageType);\r
5605     break;\r
5606 \r
5607   case 0xd2:\r
5608 \r
5609     N6110_ReplyID(MessageLength, MessageBuffer, MessageType);\r
5610     break;\r
5611   \r
5612   /***** RLP frame received. *****/\r
5613   case 0xf1:\r
5614 \r
5615     N6110_RX_HandleRLPMessage(MessageBuffer);\r
5616     break;\r
5617 \r
5618   /***** Power on message. *****/\r
5619   case 0xf4:\r
5620 \r
5621     N6110_Dispatch0xF4Message(MessageLength, MessageBuffer, MessageType);\r
5622     break;\r
5623 \r
5624   /***** Unknown message *****/\r
5625   /* If you think that you know the exact meaning of other messages - please\r
5626      let us know. */\r
5627   default:\r
5628 \r
5629 #ifdef DEBUG\r
5630     fprintf(stdout, _("Message: Unknown message type.\n"));\r
5631 #endif /* DEBUG */\r
5632     AppendLogText("Unknown msg type\n",false);\r
5633 \r
5634     unknown=false;\r
5635     break;\r
5636 \r
5637   }\r
5638 \r
5639   if (unknown) {\r
5640 #ifdef DEBUG\r
5641     fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType);\r
5642 #endif\r
5643     AppendLogText("Unknown msg\n",false);\r
5644   }\r
5645 }\r