392837eca80e5f07f9e58278d764d779d8b29f6f
[gnokii.git] / common / newmodules / newat.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9   This file provides an API for accessing functions on the at and similar
10   phones.
11
12 */
13
14 /* "Turn on" prototypes in n-at.h */
15
16 #define __n_at_c 
17
18 /* System header files */
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22  
23 #ifndef WIN32
24   #include "devices/device.h"
25 #endif
26
27 #ifdef WIN32
28   #include "misc_win32.h"
29 #endif
30
31 /* Various header file */
32 #ifndef VC6
33   #include "config.h"
34 #endif
35
36 #include "gsm-api.h"
37 #include "gsm-coding.h"
38 #include "newmodules/newat.h"
39 #include "newmodules/n6110.h"
40 /* Global variables used by code in gsm-api.c to expose the functions
41    supported by this model of phone. */
42
43
44
45
46
47
48 /* Here we initialise model specific functions. */
49
50 GSM_Functions Nat_Functions = {
51   Nat_Initialise,
52   Nat_DispatchMessage,
53   NULL_Terminate,
54   NULL_KeepAlive,
55   Nat_GetMemoryLocation,
56   Nat_WritePhonebookLocation,
57   UNIMPLEMENTED,
58   UNIMPLEMENTED,
59   Nat_GetMemoryStatus,
60   Nat_GetSMSStatus,
61   Nat_GetSMSCenter,
62   Nat_SetSMSCenter,
63   Nat_GetSMSMessage,
64   Nat_DeleteSMSMessage,
65   Nat_SendSMSMessage,
66   Nat_SaveSMSMessage,
67   Nat_GetRFLevel,
68   Nat_GetBatteryLevel,
69   Nat_GetPowerSource,
70   Nat_GetDisplayStatus, //fill it
71   Nat_EnterSecurityCode,
72   Nat_GetSecurityCodeStatus,
73   UNIMPLEMENTED,
74   N6110_GetIMEI,
75   N6110_GetRevision,
76   N6110_GetModel,
77   Nat_GetDateTime,
78   Nat_SetDateTime,
79   Nat_GetAlarm,
80   Nat_SetAlarm, //doesn't work correctly...
81   Nat_DialVoice,
82   UNIMPLEMENTED,
83   UNIMPLEMENTED,
84   Nat_GetNetworkInfo,
85   UNIMPLEMENTED,
86   UNIMPLEMENTED,
87   UNIMPLEMENTED,
88   UNIMPLEMENTED,
89   Nat_SendDTMF,
90   UNIMPLEMENTED,
91   UNIMPLEMENTED,
92   UNIMPLEMENTED,
93   UNIMPLEMENTED,
94   UNIMPLEMENTED,
95   UNIMPLEMENTED,
96   UNIMPLEMENTED,
97   UNIMPLEMENTED,
98   UNIMPLEMENTED,
99   Nat_CancelCall,
100   Nat_PressKey,  //fill it
101   UNIMPLEMENTED, //DisplayOutput= AT+CDIS
102   UNIMPLEMENTED,
103   UNIMPLEMENTED,
104   UNIMPLEMENTED,
105   UNIMPLEMENTED,
106   UNIMPLEMENTED,
107   UNIMPLEMENTED,
108   UNIMPLEMENTED,
109   UNIMPLEMENTED,
110   UNIMPLEMENTED,
111   UNIMPLEMENTED,
112   UNIMPLEMENTED,
113   UNIMPLEMENTED,
114   UNIMPLEMENTED,
115   N6110_GetSMSFolders,
116   UNIMPLEMENTED,
117   UNIMPLEMENTED,
118   UNIMPLEMENTED,
119   UNIMPLEMENTED,
120   Nat_CallDivert,
121   UNIMPLEMENTED,
122   Nat_GetManufacturer
123 };
124
125 /* Mobile phone information */
126
127 GSM_Information Nat_Information = {
128   "",   /* Supported models in FBUS */
129   "at", /* Supported models in MBUS */
130   "",   /* Supported models in FBUS over infrared */
131   "",   /* Supported models in FBUS over DLR3 */
132   "at", /* Supported models in AT commands mode */
133   "",
134   "",
135   4,                     /* Max RF Level */
136   0,                     /* Min RF Level */
137   GRF_Arbitrary,         /* RF level units */
138   4,                     /* Max Battery Level */
139   0,                     /* Min Battery Level */
140   GBU_Arbitrary,         /* Battery level units */
141   GDT_None,              /* No date/time support */
142   GDT_None,              /* No alarm support */
143   0                      /* Max alarms = 0 */
144 };
145
146 /* Type of SMS mode. 0=PDU mode; 1=text mode */
147 int SMSATCMGF=-1; //-1 when not used earlier
148 #define SMS_AT_PDU  0
149 #define SMS_AT_TEXT 1
150
151 /* Type of charset for phonebook 0=GSM; 1=HEX */
152 int PBKATCSCS=-1; //-1 when not used earlier
153 #define PBK_AT_GSM 0
154 #define PBK_AT_HEX 1
155
156 /* Manufacturer of connected AT compatible phone */
157 int ATMan=-1; // -1 when not used earlier
158 #define AT_MAN_NOKIA   0
159 #define AT_MAN_SIEMENS 1
160
161 int ExtractOneParameter(unsigned char *input, unsigned char *output)
162 {
163   int position=0;
164
165   while (*input!=',' && *input!=0x0d) {
166     *output=*input;
167     input++;
168     output++;
169     position++;
170   }
171   *output=0;
172   position++;
173   return position;
174 }
175
176 void ATDecodeDateTime(GSM_DateTime *dt, unsigned char *input)
177 {
178   dt->Year=2000+(*input-'0')*10;     input++;
179   dt->Year=dt->Year+(*input-'0');    input++;
180
181   input++;
182   dt->Month=(*input-'0')*10;         input++;
183   dt->Month=dt->Month+(*input-'0');  input++;
184
185   input++;
186   dt->Day=(*input-'0')*10;           input++;
187   dt->Day=dt->Day+(*input-'0');      input++;
188
189   input++;
190   dt->Hour=(*input-'0')*10;          input++;
191   dt->Hour=dt->Hour+(*input-'0');    input++;
192
193   input++;
194   dt->Minute=(*input-'0')*10;        input++;
195   dt->Minute=dt->Minute+(*input-'0');input++;
196
197   input++;
198   dt->Second=(*input-'0')*10;        input++;
199   dt->Second=dt->Second+(*input-'0');input++;
200
201   if (input!=NULL) {
202     input++;
203     dt->Timezone=(*input-'0')*10;          input++;
204     dt->Timezone=dt->Timezone+(*input-'0');input++;
205     input=input-2;
206     if (*input=='-') dt->Timezone=-dt->Timezone;
207   }
208 }
209
210 void Nat_ReplyGetIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
211
212   strncpy(Current_IMEI,MessageBuffer+10,15);
213
214 #ifdef DEBUG
215   fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI);
216 #endif
217
218   CurrentGetIMEIError=GE_NONE;
219 }
220
221 GSM_Error Nat_SendIMEIFrame()
222 {
223   unsigned char req[8] = {"AT+CGSN\r"};  
224
225   return NULL_SendMessageSequence
226     (50, &CurrentGetIMEIError, 8, 0x00, req);
227 }
228
229 void Nat_ReplyGetID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
230
231   int i;
232
233   i=10;
234   if (strncmp("Nokia Communicator GSM900/1800",MessageBuffer+i,30)==0) {
235 #ifdef DEBUG
236     fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
237     fprintf(stdout, _("   Model: RAE-3\n"));
238 #endif
239     strcpy(Current_Model,"RAE-3");
240
241   } else {
242     while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
243       Current_Model[i-10]=MessageBuffer[i];
244       i++;
245     }
246     Current_Model[i-9]=0;
247
248 #ifdef DEBUG
249     fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
250     fprintf(stdout, _("   Model: %s\n"),Current_Model);
251 #endif
252   }
253
254   CurrentMagicError=GE_NONE;
255 }
256
257 GSM_Error Nat_SendIDFrame()
258 {
259   unsigned char req[8] = {"AT+CGMM\r"};  
260
261   return NULL_SendMessageSequence
262     (50, &CurrentMagicError, 8, 0x00, req);
263 }
264
265 void Nat_ReplyGetHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
266
267   int i,current;
268
269 #ifdef DEBUG
270   fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
271 #endif
272
273   switch (ATMan) {
274     case AT_MAN_NOKIA:
275 #ifdef DEBUG
276       fprintf(stdout, _("   Firmware: "));
277       for (i=12;i<17;i++) fprintf(stdout,_("%c"),MessageBuffer[i]);
278       fprintf(stdout, _("\n"));
279       /* Some Nokia phones like 9210 return only firmware */
280       if (MessageLength>22) {
281         fprintf(stdout, _("   Hardware: "));
282         for (i=21;i<25;i++) fprintf(stdout,_("%c"),MessageBuffer[i]);
283         fprintf(stdout, _("\n"));
284       }
285 #endif
286
287       strcpy(Current_Revision,"SW");current=2;
288       for (i=12;i<17;i++) Current_Revision[current++]=MessageBuffer[i];
289       Current_Revision[current++]=',';
290       Current_Revision[current++]=' ';
291       Current_Revision[current++]='H';
292       Current_Revision[current++]='W';
293       if (MessageLength>22) {
294         for (i=21;i<25;i++) Current_Revision[current++]=MessageBuffer[i];
295       } else {
296         /* Some Nokia phones like 9210 return only firmware */
297         /* Here we copy firmware as hardware */
298         for (i=12;i<17;i++) Current_Revision[current++]=MessageBuffer[i];
299       }
300       break;
301     case AT_MAN_SIEMENS:
302       current=0;i=18;
303       strcpy(Current_Revision,"SW");current=2;
304       while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
305         Current_Revision[current++]=MessageBuffer[i];
306         i++;
307       }
308       Current_Revision[current++]=',';
309       Current_Revision[current++]=' ';
310       Current_Revision[current++]='H';
311       Current_Revision[current++]='W';
312       i=18;
313       while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
314         Current_Revision[current++]=MessageBuffer[i];
315         i++;
316       }
317
318       break;
319     default:
320       strcpy(Current_Revision,"SWxx.xx, HWxxxx");
321       break;
322   }
323
324   CurrentGetHWError=GE_NONE;
325 }
326
327 GSM_Error Nat_SendHWFrame()
328 {
329   unsigned char req[8] = {"AT+CGMR\r"};  
330
331   return NULL_SendMessageSequence
332     (50, &CurrentGetHWError, 8, 0x00, req);
333 }
334
335 void Nat_ReplyGetManufacturer(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
336
337 #ifdef DEBUG
338   fprintf(stdout, _("Message: phone manufacturer received\n"));
339 #endif
340
341   if (strstr(MessageBuffer,"Nokia")) {
342 #ifdef DEBUG
343     fprintf(stdout, _("   Nokia\n"));
344 #endif
345     ATMan=AT_MAN_NOKIA;
346   }
347
348   if (strstr(MessageBuffer,"SIEMENS")) {
349 #ifdef DEBUG
350     fprintf(stdout, _("   Siemens\n"));
351 #endif
352     ATMan=AT_MAN_SIEMENS;
353   }
354
355   CurrentMagicError=GE_NONE;
356 }
357
358 GSM_Error Nat_SendManufacturerFrame()
359 {
360   unsigned char req[8] = {"AT+CGMI\r"};
361
362   return NULL_SendMessageSequence
363     (50, &CurrentMagicError, 8, 0x00, req);
364 }
365
366 /* Initialise variables and state machine. */
367 GSM_Error Nat_Initialise(char *port_device, char *initlength,
368                           GSM_ConnectionType connection,
369                           void (*rlp_callback)(RLP_F96Frame *frame))
370 {
371   if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
372   {
373     return GE_NOTSUPPORTED;
374   }
375
376   usleep(100);
377
378   if (Nat_SendManufacturerFrame()!=GE_NONE) return GE_TIMEOUT;
379
380   if (Nat_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;
381
382   if (Nat_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;
383
384   if (Nat_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
385
386   /* In AT doesn't have any init strings, etc. Phone answered with frame,
387      so connection should be enabled ;-) */
388   CurrentLinkOK = true;                           
389
390   return (GE_NONE);
391 }
392
393 GSM_Error Nat_GetManufacturer(char* manufacturer)
394 {
395   switch (ATMan) {
396     case AT_MAN_NOKIA  :strcpy (manufacturer, "Nokia");  break;
397     case AT_MAN_SIEMENS:strcpy (manufacturer, "Siemens");break;
398     default            :strcpy (manufacturer, "unknown");break;
399   }
400
401   return GE_NONE;
402 }
403
404 void Nat_ReplyPBKSetMemoryType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
405
406 #ifdef DEBUG
407   fprintf(stdout, _("Message: memory type set OK\n"));
408 #endif
409
410   CurrentPhonebookError=GE_NONE;
411 }
412
413 static GSM_Error PBKSetMemoryType(GSM_MemoryType type)
414 {
415   char req[] = "AT+CPBS=\"XX\"\r";
416   char req2[10];
417
418   GetMemoryTypeString(req2, &type);
419
420   req[9]=req2[0];
421   req[10]=req2[1];
422
423   return NULL_SendMessageSequence
424     (50, &CurrentPhonebookError, strlen(req), 0x00, req);
425 }
426
427 void Nat_ReplySetCharset(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
428
429   if (strncmp("AT+CSCS=\"HEX\"",MessageBuffer,13)==0) {
430 #ifdef DEBUG
431     fprintf(stdout, _("Message: charset set to HEX\n"));
432 #endif
433     CurrentPhonebookError=GE_NONE;
434   }
435   if (strncmp("AT+CSCS=\"GSM\"",MessageBuffer,13)==0) {
436 #ifdef DEBUG
437     fprintf(stdout, _("Message: charset set to GSM\n"));
438 #endif
439     CurrentPhonebookError=GE_NONE;
440   }
441 }
442
443 GSM_Error SetCharset()
444 {
445   unsigned char req [14] = {"AT+CSCS=\"HEX\"\r"};  // HEX charset
446   unsigned char req2[14] = {"AT+CSCS=\"GSM\"\r"};  // GSM charset
447   GSM_Error error;
448
449   error=NULL_SendMessageSequence
450     (50, &CurrentPhonebookError, 14, 0x00, req);
451   if (error==GE_NONE) {
452     PBKATCSCS=PBK_AT_HEX;
453     return GE_NONE;
454   }
455
456   error=NULL_SendMessageSequence
457     (50, &CurrentPhonebookError, 14, 0x00, req2);
458   if (error==GE_NONE) {
459     PBKATCSCS=PBK_AT_GSM;
460     return GE_NONE;
461   }
462
463   return error;
464 }
465
466 void Nat_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
467
468   char *pos, *endpos;
469   int l;
470
471 #ifdef DEBUG
472   fprintf(stdout, _("Message: phonebook entry received\n"));
473 #endif
474
475   CurrentPhonebookEntry->Empty = true;
476   *(CurrentPhonebookEntry->Name) = '\0';
477   *(CurrentPhonebookEntry->Number) = '\0';
478   CurrentPhonebookEntry->SubEntriesCount=0;
479   CurrentPhonebookEntry->Group = 0;
480
481   pos = strchr(MessageBuffer, '\"');
482   endpos = NULL;
483   if (pos) {    
484     endpos = strchr(++pos, '\"');
485     if (endpos) {
486       *endpos = '\0';
487       strcpy(CurrentPhonebookEntry->Number, pos);
488     }
489     pos = NULL;
490     if (endpos) pos = strchr(++endpos, '\"');
491     endpos = NULL;
492     if (pos) {
493       pos++;
494       l = pos - (char *)MessageBuffer;
495       endpos = memchr(pos, '\"', MessageLength - l);
496     }
497     if (endpos) {
498       l = endpos - pos;
499       switch (PBKATCSCS) {
500         case PBK_AT_GSM:
501           DecodeDefault(CurrentPhonebookEntry->Name, pos, l);
502           break;
503         case PBK_AT_HEX:
504           DecodeHexBin(CurrentPhonebookEntry->Name, pos, l);
505           break;
506       }
507     }
508   }
509
510   CurrentPhonebookError=GE_NONE;
511 }
512
513 GSM_Error Nat_GetMemoryLocation(GSM_PhonebookEntry *entry)
514 {
515   GSM_Error error;
516   char req[] = "AT+CPBR=00000\r";
517
518   if (PBKATCSCS==-1) {
519     error=SetCharset();
520     if (error!=GE_NONE) return error;
521   }
522
523   error = PBKSetMemoryType(entry->MemoryType);
524   if (error != GE_NONE) return error;
525
526   CurrentPhonebookEntry = entry;
527
528   sprintf(req + 8, "%5d\r", entry->Location);
529
530   return NULL_SendMessageSequence
531     (50, &CurrentPhonebookError, strlen(req), 0x00, req);
532 }
533
534 void Nat_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
535
536 #ifdef DEBUG
537   fprintf(stdout, _("Message: phonebook entry set OK\n"));
538 #endif
539
540   CurrentPhonebookError=GE_NONE;
541 }
542
543 GSM_Error Nat_WritePhonebookLocation(GSM_PhonebookEntry * entry)
544 {
545   GSM_Error error;
546   char req[128];
547   char Name[128];
548   char Number[100];
549   u8 i;
550
551   switch (entry->MemoryType) {
552     case GMT_ME:
553       /* FIXME: the 7110, 6210... supports long phonebookentries. in lack
554          of documentation we only support SIM memory */
555       if(GetModelFeature (FN_PHONEBOOK)==F_PBK71) return GE_NOTIMPLEMENTED;
556
557       break;
558     default:
559       break;
560   }
561
562   if (PBKATCSCS==-1) {
563     error=SetCharset();
564     if (error!=GE_NONE) return error;
565   }
566
567   error = PBKSetMemoryType(entry->MemoryType);
568   if (error != GE_NONE) return error;
569
570   switch (PBKATCSCS) {
571     case PBK_AT_HEX:
572       EncodeHexBin (Name, entry->Name, strlen(entry->Name));
573       Name[strlen(entry->Name)*2]=0;
574       break;
575     case PBK_AT_GSM:
576       EncodeDefault (Name, entry->Name, strlen(entry->Name));
577       Name[strlen(entry->Name)]=0;
578       break;
579   }
580
581   GSM_PackSemiOctetNumber(entry->Number,Number,false);
582   i=Number[0];
583
584   sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"%s\"\r",
585                 entry->Location, entry->Number, i, Name);
586
587   return NULL_SendMessageSequence
588     (50, &CurrentPhonebookError, strlen(req), 0x00, req);
589 }
590
591 void Nat_ReplyGetMemoryStatusCPBS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
592
593   char *start;
594
595 #ifdef DEBUG
596   fprintf(stdout, _("Message: memory status received\n"));
597 #endif
598
599   CurrentMemoryStatus->Used = 0;
600   CurrentMemoryStatus->Free = 0;
601
602   start = strchr(MessageBuffer, ',');
603
604   if (start) {
605     start++;
606     CurrentMemoryStatus->Used = atoi(start);
607     start = strchr(start, ',');
608     if (start) {
609       start++;
610       CurrentMemoryStatus->Free = atoi(start) - CurrentMemoryStatus->Used;
611       CurrentMemoryStatusError=GE_NONE;
612     } else CurrentMemoryStatusError=GE_UNKNOWN;
613   } else CurrentMemoryStatusError=GE_UNKNOWN;
614 }
615
616 void Nat_ReplyGetMemoryStatusCPBR(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
617
618   char *start;
619
620 #ifdef DEBUG
621   fprintf(stdout, _("Message: memory size received\n"));
622 #endif
623
624   CurrentMemoryStatus->Used = 0;
625   CurrentMemoryStatus->Free = 0;
626  
627   start = strchr(MessageBuffer, '-');
628
629   if (start) {
630     start++;
631     /* Parse +CPBR: (first-last),max_number_len,max_name_len */ 
632     /* We cannot get Used/Free info. We can get only size of memory
633        we don't have size in memory status and because of it
634        we make assigment used=size_of_memory, free=0.
635        It's better than nothing */
636     CurrentMemoryStatus->Used = atoi(start);
637     CurrentMemoryStatusError=GE_NONE;
638   } else CurrentMemoryStatusError=GE_UNKNOWN;
639 }
640
641 GSM_Error Nat_GetMemoryStatus(GSM_MemoryStatus *Status)
642 {
643   GSM_Error error;
644   char req [] ="AT+CPBS?\r"; /* in some phones doesn't work or doesn't return
645                                 memory status inside */
646   char req2[] ="AT+CPBR=?\r";
647
648   error = PBKSetMemoryType(Status->MemoryType);
649   if (error != GE_NONE) return error;
650
651   CurrentMemoryStatus = Status;
652
653   error=NULL_SendMessageSequence
654     (20, &CurrentMemoryStatusError, strlen(req), 0x00, req);
655   if (error==GE_NONE) {
656     CurrentMemoryStatus = NULL;
657     return error;
658   }
659
660   error=NULL_SendMessageSequence
661     (20, &CurrentMemoryStatusError, strlen(req2), 0x00, req2);
662
663   CurrentMemoryStatus = NULL;
664
665   return error;
666 }
667
668 void Nat_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
669   int current;
670
671 #ifdef DEBUG
672   fprintf(stdout, _("Message: call forwarding info\n"));
673 #endif
674   if (MessageLength>0x20) {
675     current=27;
676     while (MessageBuffer[current]!='"') {
677       CurrentCallDivert->Number[current-27]=MessageBuffer[current];
678       current++;
679     }
680     CurrentCallDivert->Enabled=true;
681     CurrentCallDivert->Number[current-27]=0x00;
682     CurrentCallDivert->Timeout=999;//where is it in frame ?
683   } else {
684     CurrentCallDivert->Enabled=false;
685   }
686   CurrentCallDivertError=GE_NONE;
687 }
688
689 GSM_Error Nat_CallDivert(GSM_CallDivert *cd)
690 {
691   char req[64];
692   GSM_Error error;
693   char Number[100];
694   int i;
695
696   sprintf(req, "AT+CCFC=");
697
698   switch (cd->DType) {
699     case GSM_CDV_AllTypes  : strcat(req, "4"); break;
700     case GSM_CDV_Busy      : strcat(req, "1"); break;
701     case GSM_CDV_NoAnswer  : strcat(req, "2"); break;
702     case GSM_CDV_OutOfReach: strcat(req, "3"); break;
703     default                : return GE_NOTIMPLEMENTED;
704   }
705
706   if (cd->Operation == GSM_CDV_Register) {
707     GSM_PackSemiOctetNumber(cd->Number,Number,false);
708     i=Number[0];
709
710     sprintf(req, "%s,%d,\"%s\",%i,,,%d", req,
711         cd->Operation,cd->Number,i,cd->Timeout);
712   } else
713     sprintf(req, "%s,%d", req, cd->Operation);
714
715   strcat(req, "\r\n");
716
717   CurrentCallDivert = cd;
718
719   error=NULL_SendMessageSequence
720     (100, &CurrentCallDivertError, strlen(req), 0x00, req);
721
722   CurrentCallDivert = NULL;
723
724   return error;
725 }
726
727 void Nat_ReplyGetNetworkInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
728   int i,current;
729   GSM_NetworkInfo NullNetworkInfo;
730
731   /* TODO: checking if phone really registered to network */
732
733   current=23;
734
735   /* Make sure we are expecting NetworkInfo frame */
736   if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
737 #ifdef DEBUG
738     fprintf(stdout, _("Message: network info received\n"));
739 #endif
740
741     NullNetworkInfo.NetworkCode[0]=0; //no exist
742
743     for (i=0;i<4;i++) NullNetworkInfo.CellID[i]=MessageBuffer[i+current];
744
745     NullNetworkInfo.CellID[4]=0;
746
747     current=current+7;
748
749     for (i=0;i<4;i++) NullNetworkInfo.LAC[i]=MessageBuffer[i+current];
750
751     NullNetworkInfo.LAC[4]=0;
752
753 #ifdef DEBUG
754     fprintf(stdout, _("   CellID: %s\n"), NullNetworkInfo.CellID);
755     fprintf(stdout, _("   LAC: %s\n"), NullNetworkInfo.LAC);
756 #endif
757
758   }
759       
760   /* Make sure we are expecting NetworkInfo frame */
761   if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY)
762      *CurrentNetworkInfo=NullNetworkInfo;
763
764   CurrentNetworkInfoError = GE_NONE;      
765 }
766
767 GSM_Error Nat_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
768 {
769   GSM_Error error;
770
771   Protocol->SendMessage(10, 0x00, "AT+CREG=2\r");
772   
773   CurrentNetworkInfo = NetworkInfo;
774   
775   error=NULL_SendMessageSequence
776     (20, &CurrentNetworkInfoError, 9, 0x00, "AT+CREG?\r");
777
778   CurrentNetworkInfo = NULL;
779
780   return error;
781 }
782
783 void Nat_ReplyGetBatteryLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
784
785 #ifdef DEBUG
786   fprintf(stdout, _("Message: power source and battery info received\n"));
787 #endif
788
789   CurrentPowerSource=atoi(MessageBuffer+15);
790   CurrentBatteryLevel=atoi(MessageBuffer+17);
791 }
792
793 GSM_Error Nat_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
794 {
795   int timeout=10;
796   int batt_level;
797
798   CurrentBatteryLevel=-1;
799
800   Protocol->SendMessage(7, 0x00, "AT+CBC\r");
801
802   /* Wait for timeout or other error. */
803   while (timeout != 0 && CurrentBatteryLevel == -1 ) {
804
805     if (--timeout == 0)
806       return (GE_TIMEOUT);
807
808     usleep (100000);
809   }
810
811   /* Take copy in case it changes. */
812   batt_level = CurrentBatteryLevel;
813
814   if (batt_level != -1) {
815
816     /* Only units we handle at present are GBU_Arbitrary */
817     if (*units == GBU_Arbitrary) {
818       if (batt_level >= 70) { *level = 4; return (GE_NONE); }
819       if (batt_level >= 50) { *level = 3; return (GE_NONE); }
820       if (batt_level >= 30) { *level = 2; return (GE_NONE); }
821       if (batt_level >= 10) { *level = 1; return (GE_NONE); }
822       *level = 0;
823       return (GE_NONE);
824     }
825
826     return (GE_INTERNALERROR);
827   }
828   else
829     return (GE_NOLINK);
830 }
831
832 GSM_Error Nat_GetPowerSource(GSM_PowerSource * source)
833 {
834   *source = CurrentPowerSource;
835   return (GE_NONE);
836
837
838 void Nat_ReplyGetRFLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
839
840 #ifdef DEBUG
841   fprintf(stdout, _("Message: RF level info received\n"));
842 #endif
843   CurrentRFLevel=atoi(MessageBuffer+15);
844 }
845
846 GSM_Error Nat_GetRFLevel(GSM_RFUnits *units, float *level)
847 {
848   int timeout=10;
849   int rf_level;
850   
851   CurrentRFLevel=-1;
852     
853   Protocol->SendMessage(7, 0x00, "AT+CSQ\r");
854
855   /* Wait for timeout or other error. */
856   while (timeout != 0 && CurrentRFLevel == -1 ) {
857
858     if (--timeout == 0)
859       return (GE_TIMEOUT);
860
861     usleep (100000);
862   }
863
864   /* Make copy in case it changes. */
865   rf_level = CurrentRFLevel;
866
867   if (rf_level == -1)
868     return (GE_NOLINK);
869
870   /* Now convert between the different units we support. */
871
872   if (*units == GRF_Arbitrary) {
873     if (CurrentRFLevel == 99) { *level = 0;return (GE_NONE); }
874     if (CurrentRFLevel  > 23) { *level = 4;return (GE_NONE); }
875     if (CurrentRFLevel  > 17) { *level = 3;return (GE_NONE); }
876     if (CurrentRFLevel  > 11) { *level = 2;return (GE_NONE); }
877     if (CurrentRFLevel  >  5) { *level = 1;return (GE_NONE); }
878     *level = 0;
879     return (GE_NONE);
880   }
881
882   /* CSQ units. */
883   if (*units == GRF_CSQ) {
884     if ((CurrentRFLevel <= 31) || (CurrentRFLevel >= 0))
885       *level = CurrentRFLevel;
886     else
887       *level = 99;      /* Unknown/undefined */
888     return (GE_NONE);
889   }
890
891   /* Unit type is one we don't handle so return error */
892   return (GE_INTERNALERROR);
893 }
894
895 GSM_Error Nat_GetDisplayStatus(int *Status) {
896   char req[128];
897
898   sprintf(req, "AT+CIND?\r");
899
900   return NULL_SendMessageSequence
901     (50, &CurrentDisplayStatusError, strlen(req), 0x00, req);
902 }
903
904 GSM_Error Nat_PressKey(int key, int event)
905 {
906   char req[128];
907
908   sprintf(req, "AT+CKPD=?\r");
909
910   return NULL_SendMessageSequence
911     (50, &CurrentPressKeyError, strlen(req), 0x00, req);
912 }
913
914 GSM_Error Nat_DialVoice(char *Number) {
915   char req[39] = "ATDT";  
916
917   if (strlen(Number) > 32)
918     return (GE_INTERNALERROR);
919
920   strcat(req, Number);
921   strcat(req, ";\r");
922
923   return NULL_SendMessageSequence
924     (50, &CurrentDialVoiceError, 4+2+strlen(Number), 0x00, req);
925 }
926
927 void Nat_ReplyCancelCall(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
928
929 #ifdef DEBUG
930   fprintf(stdout, _("Message: call hangup OK\n"));
931 #endif
932
933   CurrentDialVoiceError=GE_NONE;
934 }
935
936 GSM_Error Nat_CancelCall(void)
937 {
938   char req[] = "AT+CHUP\r";  
939
940   return NULL_SendMessageSequence
941     (50, &CurrentDialVoiceError, strlen(req), 0x00, req);
942 }  
943
944 GSM_Error Nat_SendDTMF(char *String)
945 {
946   int n;
947   char req[80] = "AT+VTS=";
948
949   for (n = 0; n < 32; n++) {
950      if (String[n] == '\0') break;
951      if (n != 0) req[6 + 2 * n] = ',';
952      req[7 + 2 * n] = String[n];
953   }
954
955   strcat(req, ";\r");
956
957   return NULL_SendMessageSequence
958     (50, &CurrentSendDTMFError,7+2+2*strlen(String) , 0x00, req);
959 }
960
961 GSM_Error Nat_EnterSecurityCode(GSM_SecurityCode SecurityCode)
962 {
963   char req[128];
964
965   if   ((SecurityCode.Type != GSCT_Pin)
966      && (SecurityCode.Type != GSCT_Pin2)) return (GE_NOTIMPLEMENTED);
967
968   sprintf(req, "AT+CPIN=\"%s\"\r", SecurityCode.Code);
969
970   return NULL_SendMessageSequence
971     (20, &CurrentSecurityCodeError, strlen(req), 0x00, req);
972 }
973
974 void Nat_ReplyGetSecurityCodeStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
975
976   char *start;
977
978 #ifdef DEBUG
979   fprintf(stdout, _("Message: security code status received\n"));
980 #endif
981
982   start = strchr(MessageBuffer, ':');
983   start+=2;
984
985   *CurrentSecurityCodeStatus = 0;
986
987   if (!strncmp(start, "READY", 5)) *CurrentSecurityCodeStatus = GSCT_None;
988
989   if (!strncmp(start, "SIM ", 4)) {
990     start += 4;
991     if (!strncmp(start, "PIN2", 4)) *CurrentSecurityCodeStatus = GSCT_Pin2;
992     if (!strncmp(start, "PUK2", 4)) *CurrentSecurityCodeStatus = GSCT_Puk2;
993     if (!strncmp(start, "PIN",  3)) *CurrentSecurityCodeStatus = GSCT_Pin;
994     if (!strncmp(start, "PUK",  3)) *CurrentSecurityCodeStatus = GSCT_Puk;
995   }
996
997   CurrentSecurityCodeError=GE_NONE;
998 }
999
1000 GSM_Error Nat_GetSecurityCodeStatus(int *Status)
1001 {
1002   CurrentSecurityCodeStatus = Status;
1003
1004   return NULL_SendMessageSequence
1005     (20, &CurrentSecurityCodeError, 9, 0x00, "AT+CPIN?\r");
1006 }
1007
1008 void Nat_ReplyGetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1009   int current;
1010
1011   current=19;
1012
1013 #ifdef DEBUG
1014   fprintf(stdout,_("Message: date/time received\n"));
1015 #endif
1016
1017   if (MessageBuffer[current]==0x0d) {
1018     CurrentDateTime->IsSet=false;
1019   } else {
1020     CurrentDateTime->IsSet=true;
1021
1022     ATDecodeDateTime(CurrentDateTime, MessageBuffer+(current));
1023
1024 #ifdef DEBUG
1025     fprintf(stdout,_("   %i/%i/%i %i:%i:%i\n"),
1026        CurrentDateTime->Day,CurrentDateTime->Month,CurrentDateTime->Year,
1027        CurrentDateTime->Hour,CurrentDateTime->Minute,CurrentDateTime->Second);
1028 #endif
1029   }
1030   CurrentDateTimeError=GE_NONE;
1031 }
1032
1033 GSM_Error Nat_GetDateTime(GSM_DateTime *date_time)
1034 {
1035   unsigned char req[9] = {"AT+CCLK?\r"};  
1036
1037   CurrentDateTime=date_time;
1038
1039   return NULL_SendMessageSequence
1040     (50, &CurrentDateTimeError, 9, 0x00, req);
1041 }
1042
1043 void Nat_ReplySetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1044
1045 #ifdef DEBUG
1046   fprintf(stdout,_("Message: date/time set OK\n"));
1047 #endif
1048   CurrentSetDateTimeError=GE_NONE;
1049 }
1050
1051 GSM_Error Nat_SetDateTime(GSM_DateTime *date_time)
1052 {
1053   char req[128];
1054
1055   sprintf(req, "AT+CCLK=\"%02i/%02i/%02i,%02i:%02i:%02i+00\"\r",
1056      date_time->Year-2000,date_time->Month,date_time->Day,
1057      date_time->Hour,date_time->Minute,date_time->Second);
1058
1059   return NULL_SendMessageSequence
1060     (20, &CurrentSetDateTimeError, strlen(req), 0x00, req);
1061 }
1062
1063 void Nat_ReplyGetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1064   int current;
1065
1066   current=19;
1067 #ifdef DEBUG
1068   fprintf(stdout,_("Message: alarm info received\n"));
1069 #endif
1070   if (MessageBuffer[current-1]==0x0d) {
1071     CurrentAlarm->IsSet=false;
1072     CurrentAlarm->Hour=0;
1073     CurrentAlarm->Minute=0;
1074   } else {
1075     CurrentAlarm->IsSet=true;
1076
1077     ATDecodeDateTime(CurrentAlarm, MessageBuffer+(current));
1078
1079 #ifdef DEBUG
1080     fprintf(stdout,_("   %i:%i\n"),CurrentAlarm->Hour,CurrentAlarm->Minute);
1081 #endif
1082   }
1083   CurrentAlarmError=GE_NONE;
1084 }
1085
1086 GSM_Error Nat_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1087 {
1088   unsigned char req[9] = {"AT+CALA?\r"};  
1089
1090   CurrentAlarm=date_time;
1091
1092   return NULL_SendMessageSequence
1093     (50, &CurrentAlarmError, 9, 0x00, req);
1094 }
1095
1096 /* FIXME: we should also allow to set the alarm off :-) */
1097 /* Doesn't work ? */
1098 GSM_Error Nat_SetAlarm(int alarm_number, GSM_DateTime *date_time)
1099 {
1100   char req[128];
1101   int i=0;
1102
1103   sprintf(req, "AT+CALA=\"%02i/%02i/%02i,%02i:%02i:%02i+00\",0,1\r",
1104      i,i,i,date_time->Hour,date_time->Minute,i);
1105
1106   return NULL_SendMessageSequence
1107     (50, &CurrentSetAlarmError, strlen(req), 0x00, req);
1108 }
1109
1110 void Nat_ReplyGetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1111   int i,start;
1112   unsigned char buffer[300];
1113
1114   start=18;
1115
1116   /* FIXME: support for all formats */        
1117   start+=ExtractOneParameter(MessageBuffer+start, buffer);
1118   for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1119   buffer[i-1]=0;
1120
1121   /* FIXME: when SMSC in empty, I set default (for my network) */
1122   /* Any better solution ? */
1123 //  if (buffer[0]==0) strcpy(buffer,"+48602951111");
1124   if (buffer[0]==0) strcpy(buffer,"+48601000310");
1125
1126   strcpy(CurrentMessageCenter->Number,buffer);
1127
1128   /* Some default values. Is it possible to get them ? */
1129   CurrentMessageCenter->Name[0]=0;
1130   CurrentMessageCenter->DefaultRecipient[0]=0;
1131   CurrentMessageCenter->Format=GSMF_Text;
1132   CurrentMessageCenter->Validity=GSMV_Max_Time;
1133
1134 #ifdef DEBUG
1135   fprintf(stdout, _("Message: SMSC number received\n   Number: '%s'\n"),buffer);
1136 #endif
1137
1138   CurrentMessageCenterError=GE_NONE;
1139 }
1140
1141 /* We only get SMSC number */
1142 /* Is it possible to get more ? */
1143 GSM_Error Nat_GetSMSCenter(GSM_MessageCenter *MessageCenter)
1144 {
1145   unsigned char req[] = {"AT+CSCA?\r"};  
1146
1147   if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1148
1149   CurrentMessageCenter=MessageCenter;
1150
1151   return NULL_SendMessageSequence
1152     (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1153 }
1154
1155 void Nat_ReplySetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1156
1157 #ifdef DEBUG
1158   fprintf(stdout, _("Message: SMSC number set OK\n"));
1159 #endif
1160
1161   CurrentMessageCenterError=GE_NONE;
1162 }
1163
1164 GSM_Error Nat_SetSMSCenter(GSM_MessageCenter *MessageCenter)
1165 {
1166   unsigned char req[50];  
1167
1168   if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1169
1170   sprintf(req, "AT+CSCA=\"%s\"\r",MessageCenter->Number);
1171
1172   return NULL_SendMessageSequence
1173     (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1174 }
1175
1176 void Nat_ReplySMSGetPDUType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1177
1178   if (strncmp("AT+CSDH=1\r",MessageBuffer,10)==0) {
1179 #ifdef DEBUG
1180     fprintf(stdout, _("Message: all SMS parameters will be displayed in text mode\n"));
1181 #endif
1182     CurrentSMSMessageError=GE_NONE;
1183   }
1184   if (strncmp("AT+CMGF=0\r",MessageBuffer,10)==0) {
1185 #ifdef DEBUG
1186     fprintf(stdout, _("Message: set PDU mode for SMS\n"));
1187 #endif
1188     CurrentSMSMessageError=GE_NONE;
1189   }
1190   if (strncmp("AT+CMGF=1\r",MessageBuffer,10)==0) {
1191 #ifdef DEBUG
1192     fprintf(stdout, _("Message: set text mode for SMS\n"));
1193 #endif
1194     CurrentSMSMessageError=GE_NONE;
1195   }
1196 }
1197
1198 GSM_Error SMSGetPDUType()
1199 {
1200   unsigned char req [10] = {"AT+CMGF=0\r"};  //sets PDU mode
1201
1202   unsigned char req2[10] = {"AT+CMGF=1\r"};  //sets text mode
1203   unsigned char req3[10] = {"AT+CSDH=1\r"};  //shows all parameters in text mode
1204
1205   GSM_Error error;
1206
1207   error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req);
1208   if (error==GE_NONE) {
1209     SMSATCMGF=SMS_AT_PDU;
1210     return GE_NONE;
1211   }
1212
1213   error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req2);
1214   if (error==GE_NONE) {
1215     SMSATCMGF=SMS_AT_TEXT;
1216
1217     error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req3);
1218   }
1219
1220   return error;
1221 }
1222
1223 GSM_Error GSM_DecodeETSISMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int length)
1224 {
1225   SMS_MessageType PDU=SMS_Deliver;
1226   GSM_ETSISMSMessage ETSI;
1227   int i,current=0,current2=0;
1228
1229   for(i=0;i<req[0]+1;i++) ETSI.SMSCNumber[i]=req[current++];
1230
1231   ETSI.firstbyte=req[current++];
1232
1233   /* See GSM 03.40 section 9.2.3.1 */
1234   if ((ETSI.firstbyte & 0x03) == 0x01) PDU=SMS_Submit;
1235   if ((ETSI.firstbyte & 0x03) == 0x02) PDU=SMS_Status_Report;
1236
1237   switch (PDU) {
1238     case SMS_Submit:
1239       SMS->Type = GST_SMS;
1240       SMS->folder= GST_OUTBOX;
1241       current++; //TPMR is ignored now
1242       current2=((req[current])+1)/2+1;
1243       for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1244       ETSI.TPPID=req[current++];
1245       ETSI.TPDCS=req[current++];
1246
1247       /* See GSM 03.40 9.2.3.3 TPVP can not exist in frame */
1248       if ((ETSI.firstbyte & 0x18)!=0) current++; //TPVP is ignored now
1249
1250       ETSI.TPUDL=req[current++];
1251       current2=current;
1252       for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
1253       break;
1254     case SMS_Deliver:
1255
1256       SMS->Type = GST_SMS;
1257       SMS->folder= GST_INBOX;
1258       current2=((req[current])+1)/2+1;
1259       for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1260       ETSI.TPPID=req[current++];
1261       ETSI.TPDCS=req[current++];
1262       for(i=0;i<7;i++) ETSI.DeliveryDateTime[i]=req[current++];
1263       ETSI.TPUDL=req[current++];
1264       current2=current;
1265       for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
1266       break;
1267     case SMS_Status_Report: 
1268
1269       SMS->Type = GST_DR;
1270       SMS->folder= GST_INBOX;
1271       current++; //TPMR is ignored now
1272       current2=((req[current])+1)/2+1;
1273       for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1274       for(i=0;i<7;i++) ETSI.DeliveryDateTime[i]=req[current++];
1275       for(i=0;i<7;i++) ETSI.SMSCDateTime[i]=req[current++];
1276       ETSI.TPStatus=req[current];
1277       break;
1278     default:
1279
1280       break;
1281   }
1282
1283   GSM_DecodeETSISMS(SMS, &ETSI);
1284
1285   return GE_NONE;
1286 }
1287
1288 void Nat_ReplyGetSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1289   int i,start,j,end;
1290   unsigned char buffer[300],buffer2[300];
1291   GSM_ETSISMSMessage ETSISMS;
1292   GSM_DateTime DT;
1293
1294 #ifdef DEBUG
1295   fprintf(stdout, _("Message: SMS Message Received\n"));
1296 #endif
1297   switch (SMSATCMGF) {
1298     case SMS_AT_PDU: /* PDU mode */
1299
1300       start=5;
1301       while(true) {
1302         if (MessageBuffer[start]==' ' ) break;
1303         start++;
1304       }
1305       start++;
1306
1307       if (MessageBuffer[start]=='0' || MessageBuffer[start]=='2')
1308         CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1309       if (MessageBuffer[start]=='1' || MessageBuffer[start]=='3')
1310         CurrentSMSMessage->Status=GSS_SENTREAD;
1311
1312       while(true) {
1313         if (MessageBuffer[start]==0x0a) break;
1314         start++;
1315       }
1316       start++;
1317
1318       /* We need to find last char of PDU text. We can't use MessageLength,
1319          because sometimes some phones (like Siemens M20) return
1320          some strange things after main PDU */
1321       end=start+1;
1322       while(true) {
1323         if (MessageBuffer[end]==0x0a) break;
1324         end++;
1325       }
1326
1327       DecodeHexBin (buffer, MessageBuffer+start, end-start-1);
1328
1329       GSM_DecodeETSISMSFrame(CurrentSMSMessage,buffer,(end-start-1)/2);
1330
1331       CurrentSMSMessageError=GE_NONE;
1332       break;
1333     case SMS_AT_TEXT:
1334       start=19;
1335         
1336       start+=ExtractOneParameter(MessageBuffer+start, buffer);
1337
1338       if (!strcmp(buffer,"\"0\"") || !strcmp(buffer,"\"REC UNREAD\"")) {
1339         CurrentSMSMessage->Type=GST_SMS;
1340         CurrentSMSMessage->folder=GST_INBOX;
1341         CurrentSMSMessage->SMSData=true;
1342         CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1343       } else if (!strcmp(buffer,"\"1\"") || !strcmp(buffer,"\"REC READ\"")) {
1344         CurrentSMSMessage->Type=GST_SMS;
1345         CurrentSMSMessage->folder=GST_INBOX;
1346         CurrentSMSMessage->SMSData=true;
1347         CurrentSMSMessage->Status=GSS_SENTREAD;
1348       } else if (!strcmp(buffer,"\"2\"") || !strcmp(buffer,"\"STO UNSENT\"")) {
1349         CurrentSMSMessage->Type=GST_SMS;
1350         CurrentSMSMessage->folder=GST_OUTBOX;
1351         CurrentSMSMessage->SMSData=false;
1352         CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1353       } else if (!strcmp(buffer,"\"3\"") || !strcmp(buffer,"\"STO SENT\"")) {
1354         CurrentSMSMessage->Type=GST_SMS;
1355         CurrentSMSMessage->folder=GST_OUTBOX;
1356         CurrentSMSMessage->SMSData=false;
1357         CurrentSMSMessage->Status=GSS_SENTREAD;
1358       }
1359
1360       start+=ExtractOneParameter(MessageBuffer+start, buffer);
1361
1362       /* It's delivery report according to Nokia AT standards */
1363       if (CurrentSMSMessage->folder==0 && buffer[0]!=0 && //GST_INBOX
1364           buffer[0]!='"') {
1365
1366         /* ??? */
1367         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1368
1369         /* Sender number */
1370         /* FIXME: support for all formats */
1371         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1372         for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1373         buffer[i-1]=0;
1374         strcpy(CurrentSMSMessage->Sender,buffer);
1375
1376         /* ??? */
1377         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1378
1379         /* Sending datetime */
1380         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1381         start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1382
1383         for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1384
1385         i=strlen(buffer);
1386         buffer[i++]=',';
1387         for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1388         buffer[i]=0;
1389
1390         ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1391
1392         /* Date of SMSC response */
1393         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1394         start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1395
1396         for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1397
1398         i=strlen(buffer);
1399         buffer[i++]=',';
1400         for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1401         buffer[i]=0;
1402
1403         ATDecodeDateTime(&DT, buffer);
1404
1405         /* for compatiblity with GSM_DecodeETSISMSStatusReportData */
1406         /* FIXME: TimeZone is cut */
1407         DT.Year=DT.Year-2000;
1408         GSM_EncodeSMSDateTime(&DT,ETSISMS.SMSCDateTime);
1409
1410         /* TPStatus */
1411         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1412         ETSISMS.TPStatus=0;
1413         j=1;
1414         for (i=strlen(buffer)-1;i>=0;i--) {
1415           ETSISMS.TPStatus=ETSISMS.TPStatus+(buffer[i]-'0')*j;
1416           j=j*10;
1417         }
1418
1419         GSM_DecodeETSISMSStatusReportData(CurrentSMSMessage, &ETSISMS);
1420
1421         /* NO SMSC number */
1422         CurrentSMSMessage->MessageCenter.Number[0]=0;
1423
1424         CurrentSMSMessage->Type = GST_DR;
1425
1426         /* FIXME: make support for it */
1427         CurrentSMSMessage->ReplyViaSameSMSC=false;
1428       } else {
1429         /* Sender number */
1430         /* FIXME: support for all formats */
1431         for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1432         buffer[i-1]=0;
1433         strcpy(CurrentSMSMessage->Sender,buffer);
1434
1435         /* Sender number in alphanumeric format ? */
1436         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1437         if (strlen(buffer)!=0) strcpy(CurrentSMSMessage->Sender,buffer);
1438
1439         /* Sending datetime */
1440         if (CurrentSMSMessage->folder==0) { //GST_INBOX
1441           start+=ExtractOneParameter(MessageBuffer+start, buffer);
1442           start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1443
1444           for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1445
1446           i=strlen(buffer);
1447           buffer[i++]=',';
1448           for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1449           buffer[i]=0;
1450
1451           ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1452         }
1453
1454         /* Sender number format */
1455         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1456
1457         /* First byte */
1458         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1459         ETSISMS.firstbyte=0;
1460         j=1;
1461         for (i=strlen(buffer)-1;i>=0;i--) {
1462           ETSISMS.firstbyte=ETSISMS.firstbyte+(buffer[i]-'0')*j;
1463           j=j*10;
1464         }
1465
1466         CurrentSMSMessage->ReplyViaSameSMSC=false;
1467         /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
1468         if ((ETSISMS.firstbyte & 128)==128)
1469           CurrentSMSMessage->ReplyViaSameSMSC=true;
1470
1471         /* TP PID.No support now */        
1472         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1473
1474         /* TP DCS */
1475         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1476         ETSISMS.TPDCS=0;
1477         j=1;
1478         for (i=strlen(buffer)-1;i>=0;i--) {
1479           ETSISMS.TPDCS=ETSISMS.TPDCS+(buffer[i]-'0')*j;
1480           j=j*10;
1481         }
1482
1483         if (CurrentSMSMessage->folder==1) { //GST_OUTBOX
1484           /*TP VP */
1485           start+=ExtractOneParameter(MessageBuffer+start, buffer);
1486         }
1487
1488         /* SMSC number */
1489         /* FIXME: support for all formats */
1490         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1491         for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1492         buffer[i-1]=0;
1493         strcpy(CurrentSMSMessage->MessageCenter.Number,buffer);
1494
1495         /* Format of SMSC number */
1496         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1497
1498         /* TPUDL */
1499         start+=ExtractOneParameter(MessageBuffer+start, buffer);
1500         ETSISMS.TPUDL=0;
1501         j=1;
1502         for (i=strlen(buffer)-1;i>=0;i--) {
1503           ETSISMS.TPUDL=ETSISMS.TPUDL+(buffer[i]-'0')*j;
1504           j=j*10;
1505         }
1506
1507         start++;
1508
1509         CurrentSMSMessage->Coding = GSM_Coding_Default;
1510
1511         /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
1512         if ((ETSISMS.TPDCS & 0xf4) == 0xf4) CurrentSMSMessage->Coding=GSM_Coding_8bit;
1513         if ((ETSISMS.TPDCS & 0x08) == 0x08) CurrentSMSMessage->Coding=GSM_Coding_Unicode;
1514
1515         switch (CurrentSMSMessage->Coding) {          
1516           case GSM_Coding_Default:
1517             /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
1518             /* If not SMS with UDH, it's coded normal */
1519             /* If UDH available, treat it as Unicode or 8 bit */
1520             if ((ETSISMS.firstbyte & 0x40)!=0x40) {
1521               CurrentSMSMessage->UDHType=GSM_NoUDH;
1522               for (i=0;i<ETSISMS.TPUDL;i++) {
1523                 if (i>GSM_MAX_SMS_LENGTH) break;
1524                 CurrentSMSMessage->MessageText[i]=MessageBuffer[i+start];
1525               }
1526               CurrentSMSMessage->Length=ETSISMS.TPUDL;
1527               break;
1528             }
1529           case GSM_Coding_Unicode:
1530           case GSM_Coding_8bit:
1531             DecodeHexBin (ETSISMS.MessageText, MessageBuffer+start, ETSISMS.TPUDL*2);
1532             GSM_DecodeETSISMSSubmitData(CurrentSMSMessage, &ETSISMS);
1533             break;
1534         }
1535         CurrentSMSMessage->MessageText[CurrentSMSMessage->Length]=0;
1536       }
1537
1538       CurrentSMSMessageError=GE_NONE;
1539   }
1540 }
1541
1542 GSM_Error Nat_GetSMSMessage(GSM_SMSMessage *message)
1543 {
1544   unsigned char req2[20];
1545   GSM_Error error;
1546
1547   if (SMSATCMGF==-1) {
1548     error=SMSGetPDUType();
1549     if (error!=GE_NONE) return error;
1550   }
1551
1552   CurrentSMSMessage = message;
1553
1554   sprintf(req2, "AT+CMGR=%i\r",message->Location); //gets SMS
1555
1556   CurrentSMSMessage->MessageNumber=CurrentSMSMessage->Location;
1557
1558   return NULL_SendMessageSequence
1559     (50, &CurrentSMSMessageError, strlen(req2), 0x00, req2);
1560 }
1561
1562 /* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */
1563 GSM_Error GSM_EncodeETSISMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int *length, SMS_MessageType PDU)
1564 {
1565   GSM_ETSISMSMessage ETSI;
1566   int i,current=0;
1567
1568   GSM_EncodeETSISMS(SMS, &ETSI, PDU, length);
1569
1570   for (i=0;i<ETSI.SMSCNumber[0]+1;i++)
1571     req[current++]=ETSI.SMSCNumber[i];
1572
1573   req[current++]=ETSI.firstbyte;
1574
1575   switch (PDU) {
1576     case SMS_Submit:
1577
1578       req[current++]=0; //TPMR ignored now
1579       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++) req[current++]=ETSI.Number[i];
1580       req[current++]=0; //ETSI.TPPID;
1581       req[current++]=ETSI.TPDCS;
1582       req[current++]=ETSI.TPVP;
1583       req[current++]=ETSI.TPUDL;
1584       for(i=0;i<*length;i++) req[current++]=ETSI.MessageText[i];
1585       break;
1586     case SMS_Deliver:
1587
1588       for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++) req[current++]=ETSI.Number[i];
1589       req[current++]=0; //ETSI.TPPID;
1590       req[current++]=ETSI.TPDCS;
1591       for(i=0;i<7;i++) req[current++]=ETSI.DeliveryDateTime[i];
1592       req[current++]=ETSI.TPUDL;
1593       for(i=0;i<*length;i++) req[current++]=ETSI.MessageText[i];
1594       break;
1595     default:
1596
1597       break;
1598   }
1599
1600   *length=current;
1601
1602   return GE_NONE;
1603 }
1604
1605 void Nat_ReplyCSMP(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1606
1607 #ifdef DEBUG
1608   fprintf(stdout, _("Message: SMS parameters set OK\n"));
1609 #endif
1610
1611   CurrentSMSMessageError=GE_NONE;
1612 }
1613
1614 GSM_Error Nat_SendSaveSMSMessage(GSM_SMSMessage *message,bool savesms)
1615 {
1616   unsigned char req2[500];
1617   unsigned char req3[256];
1618   unsigned char req4[256];
1619   unsigned char endchar[1];
1620   GSM_Error error;
1621   int length,stat,current=0;
1622   SMS_MessageType PDU;
1623   GSM_ETSISMSMessage ETSISMS;
1624   GSM_MessageCenter SMSC;
1625
1626   if (SMSATCMGF==-1) {
1627     error=SMSGetPDUType();
1628     if (error!=GE_NONE) return error;
1629   }
1630
1631   CurrentSMSMessage = message;
1632
1633   if (message->folder==0x00) { //GST_INBOX
1634     PDU=SMS_Deliver;
1635     stat=1;
1636     if (message->Status==GSS_NOTSENTREAD) stat=0;
1637   } else {
1638     PDU=SMS_Submit;
1639     stat=3;
1640     if (message->Status==GSS_NOTSENTREAD) stat=2;
1641   }
1642
1643   endchar[0]=26; //ctrl+z;
1644
1645   switch (SMSATCMGF) {
1646     case SMS_AT_PDU: /* PDU mode */
1647       GSM_EncodeETSISMSFrame(message, req3, &length, PDU);
1648
1649       if (savesms) 
1650         sprintf(req2, "AT+CMGW=%i,%i\r",(length-(req3[0]+1)),stat); //saves SMS
1651       else
1652         sprintf(req2, "AT+CMGS=%i\r",(length-(req3[0]+1))); //sends SMS
1653
1654       EncodeHexBin (req4, req3, length);
1655       current=length*2;
1656
1657       Protocol->SendMessage(strlen(req2), 0x00, req2);  usleep(500);
1658
1659       break;
1660     case SMS_AT_TEXT:
1661
1662       GSM_EncodeETSISMS(message, &ETSISMS, PDU, &length);
1663
1664       sprintf(req4, "AT+CSMP=%i,%i,%i,%i\r",
1665                 ETSISMS.firstbyte, ETSISMS.TPVP,
1666                 ETSISMS.TPPID, ETSISMS.TPDCS);
1667
1668       error=NULL_SendMessageSequence
1669         (50, &CurrentSMSMessageError, strlen(req4), 0x00, req4);
1670       if (error!=GE_NONE) return error;
1671
1672       strcpy(SMSC.Number,message->MessageCenter.Number);
1673       SMSC.No=1;
1674       error=Nat_SetSMSCenter(&SMSC);
1675       if (error!=GE_NONE) return error;
1676
1677       if (savesms) {
1678         /* Tested AT implementations don't support alphanumeric numbers */
1679         if ((CurrentSMSMessage->Destination[0]<'0'  ||
1680              CurrentSMSMessage->Destination[0]>'9') && 
1681              CurrentSMSMessage->Destination[0]!='+')
1682         {
1683           CurrentSMSMessage->Destination[0]='1';
1684           CurrentSMSMessage->Destination[1]=0;
1685         }
1686
1687         sprintf(req4, "AT+CMGW=\"%s\"\r",CurrentSMSMessage->Destination);
1688       } else {
1689         /* Tested AT implementations don't support alphanumeric numbers */
1690         if ((CurrentSMSMessage->Destination[0]<'0'  ||
1691              CurrentSMSMessage->Destination[0]>'9') && 
1692              CurrentSMSMessage->Destination[0]!='+')
1693           return GE_NOTSUPPORTED;
1694
1695         sprintf(req4, "AT+CMGS=\"%s\"\r",CurrentSMSMessage->Destination);
1696       }
1697
1698       Protocol->SendMessage(strlen(req4), 0x00, req4);  usleep(500);
1699
1700       switch (CurrentSMSMessage->Coding) {
1701         case GSM_Coding_Default:
1702           /* If not SMS with UDH, it's as normal text */
1703           if (CurrentSMSMessage->UDHType==GSM_NoUDH) {
1704             strcpy(req4,CurrentSMSMessage->MessageText);
1705             current=strlen(req4);
1706             break;
1707           }
1708         case GSM_Coding_Unicode:        
1709         case GSM_Coding_8bit:
1710
1711           EncodeHexBin (req4, ETSISMS.MessageText, length);
1712           current=length*2;
1713           break;
1714       }
1715
1716       break;
1717   }
1718
1719   Protocol->SendMessage(current, 0x00, req4);  usleep(500);
1720
1721   return NULL_SendMessageSequence
1722     (500, &CurrentSMSMessageError, 1, 0x00, endchar);
1723 }
1724
1725 void Nat_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1726   int i;
1727
1728 #ifdef DEBUG
1729   fprintf(stdout, _("Message: SMS Message saved\n"));
1730 #endif
1731
1732   i=MessageLength-10;
1733   while(MessageBuffer[i]!=0x20) { i++; }
1734
1735   i++;
1736   CurrentSMSMessage->MessageNumber=MessageBuffer[i]-'0';
1737
1738   i++;
1739   if (MessageBuffer[i]!=0x0d)
1740     CurrentSMSMessage->MessageNumber=
1741       CurrentSMSMessage->MessageNumber*10+MessageBuffer[i]-'0';
1742
1743 #ifdef DEBUG
1744   fprintf(stdout, _("   location: %i\n"),CurrentSMSMessage->MessageNumber);
1745 #endif
1746
1747   CurrentSMSMessageError=GE_NONE;
1748 }
1749
1750 GSM_Error Nat_SaveSMSMessage(GSM_SMSMessage *message)
1751 {
1752   return Nat_SendSaveSMSMessage(message,true);
1753 }
1754
1755 void Nat_ReplySendSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1756
1757 #ifdef DEBUG
1758   fprintf(stdout, _("Message: SMS Message sent OK\n"));
1759 #endif
1760
1761   CurrentSMSMessageError=GE_SMSSENDOK;
1762 }
1763
1764 GSM_Error Nat_SendSMSMessage(GSM_SMSMessage *message)
1765 {
1766   return Nat_SendSaveSMSMessage(message,false);
1767 }
1768
1769 void Nat_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1770
1771 #ifdef DEBUG
1772   fprintf(stdout, _("Message: SMS deleted OK\n"));
1773 #endif
1774
1775   CurrentSMSMessageError=GE_NONE;
1776 }
1777
1778 GSM_Error Nat_DeleteSMSMessage(GSM_SMSMessage * message)
1779 {
1780   char req[128];
1781
1782   sprintf(req, "AT+CMGD=%d\r", message->Location);
1783
1784   return NULL_SendMessageSequence
1785     (50, &CurrentSMSMessageError, strlen(req), 0x00, req);
1786 }
1787
1788 void Nat_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1789   char *start2;
1790
1791 #ifdef DEBUG
1792   fprintf(stdout, _("Message: SMS status received\n"));
1793 #endif
1794
1795   CurrentSMSStatus->UnRead=0;
1796   CurrentSMSStatus->Number=0;
1797
1798   start2 = strstr(MessageBuffer, "+CPMS: ");
1799   start2 += 7;
1800     
1801   CurrentSMSStatus->Number=atoi(start2);
1802
1803   CurrentSMSStatusError=GE_NONE;
1804 }
1805
1806 GSM_Error Nat_GetSMSStatus(GSM_SMSStatus *Status)
1807 {
1808   CurrentSMSStatus=Status;
1809
1810   return NULL_SendMessageSequence
1811     (10, &CurrentSMSStatusError, 13, 0x00, "AT+CPMS=\"SM\"\r");
1812 }
1813
1814 struct AT_OneReply ATRepliesOK[] = {
1815
1816 {"AT+CCFC=" ,Nat_ReplyCallDivert            },
1817 {"AT+CGMI\r",Nat_ReplyGetManufacturer       },
1818 {"AT+CPBS?" ,Nat_ReplyGetMemoryStatusCPBS   },
1819 {"AT+CPBR=?",Nat_ReplyGetMemoryStatusCPBR   },
1820 {"AT+CPBR=" ,Nat_ReplyGetMemoryLocation     },
1821 {"AT+CPBW=" ,Nat_ReplyWritePhonebookLocation},
1822 {"AT+CPBS=" ,Nat_ReplyPBKSetMemoryType      },
1823 {"AT+CSCS=\"HEX\"",Nat_ReplySetCharset      },
1824 {"AT+CSCS=\"GSM\"",Nat_ReplySetCharset      },
1825 {"AT+CSCA?" ,Nat_ReplyGetSMSCenter          },
1826 {"AT+CSCA=" ,Nat_ReplySetSMSCenter          },
1827 {"AT+CSDH=1\r",Nat_ReplySMSGetPDUType       },
1828 {"AT+CMGF=0\r",Nat_ReplySMSGetPDUType       },
1829 {"AT+CMGF=1\r",Nat_ReplySMSGetPDUType       },
1830 {"AT+CMGR=" ,Nat_ReplyGetSMSMessage         },
1831 {"AT+CSMP=" ,Nat_ReplyCSMP                  },
1832 {"AT+CMGW=" ,Nat_ReplySaveSMSMessage        },
1833 {"AT+CMGS=" ,Nat_ReplySendSMSMessage        },
1834 {"AT+CMGD=" ,Nat_ReplyDeleteSMSMessage      },
1835 {"AT+CPMS=\"SM\"",Nat_ReplyGetSMSStatus     },
1836 {"AT+CPIN?\r",Nat_ReplyGetSecurityCodeStatus},
1837 {"AT+CCLK?" ,Nat_ReplyGetDateTime           },
1838 {"AT+CCLK=" ,Nat_ReplySetDateTime           },
1839 {"AT+CALA?" ,Nat_ReplyGetAlarm              },
1840 {"AT+CGMM\r",Nat_ReplyGetID                 },
1841 {"AT+CGMR\r",Nat_ReplyGetHW                 },
1842 {"AT+CREG?" ,Nat_ReplyGetNetworkInfo        },
1843 {"AT+CGSN\r",Nat_ReplyGetIMEI               },
1844 {"AT+CHUP"  ,Nat_ReplyCancelCall            },
1845 {"AT+CBC"   ,Nat_ReplyGetBatteryLevel       },
1846 {"AT+CSQ"   ,Nat_ReplyGetRFLevel            },
1847
1848 {"",NULL}
1849 };
1850
1851 void Nat_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1852
1853   bool AnswerOK,AnswerError; //if last part is OK or ERROR
1854
1855   int i,start=0;
1856
1857   /* In 9210 first answer start with different, random bytes.
1858      Here we try to find first AT to find start byte */
1859   for (i=0;i<MessageLength-1;i++) {
1860     if (strncmp("AT",MessageBuffer+i,2)==0) {
1861       start=i;
1862       break;
1863     }
1864   }
1865
1866   AnswerError=false;
1867   if (strncmp("ERROR\r",MessageBuffer+(MessageLength-6),6)==0) AnswerError=true;
1868
1869   AnswerOK=false;
1870   if (strncmp("OK\r",MessageBuffer+(MessageLength-3),3)==0) AnswerOK=true;
1871   
1872   if (AnswerOK) {
1873     i=0;
1874     while (true) {
1875       if (ATRepliesOK[i].ReplyFunction==NULL) break;
1876       if (strncmp(ATRepliesOK[i].ReplyString,MessageBuffer+start,
1877            strlen(ATRepliesOK[i].ReplyString))==0) {
1878         ATRepliesOK[i].ReplyFunction(MessageLength-start,MessageBuffer+start,MessageType);
1879         break;
1880       }
1881       i++;
1882     }
1883
1884 #ifdef DEBUG
1885     if (ATRepliesOK[i].ReplyFunction==NULL)
1886       fprintf(stdout,_("Message: unknown AT command\n"));
1887 #endif
1888    
1889     if (strncmp("AT\r",MessageBuffer+start,3)==0) {
1890 #ifdef DEBUG
1891       fprintf(stdout, _("Message: used for setting DLR3 to FBUS - part 1 OK\n"));
1892 #endif
1893       CurrentGetHWError=GE_NONE;
1894     }
1895     if (strncmp("AT&F\r",MessageBuffer+start,5)==0) {
1896 #ifdef DEBUG
1897       fprintf(stdout, _("Message: used for setting DLR3 to FBUS - part 2 OK\n"));
1898 #endif
1899       CurrentGetHWError=GE_NONE;
1900     }
1901     if (strncmp("AT*NOKIAFBUS\r",MessageBuffer+start,13)==0) {
1902 #ifdef DEBUG
1903       fprintf(stdout, _("Message: Setting DLR3 to FBUS - part 3 OK\n"));
1904 #endif
1905       CurrentGetHWError=GE_NONE;
1906     }
1907   }
1908
1909   if (AnswerError) {
1910     if (strncmp("AT*NOKIAFBUS\r",MessageBuffer+start,13)==0) {
1911 #ifdef DEBUG
1912       fprintf(stdout, _("Message: Setting DLR3 to FBUS - part 3 ERROR\n"));
1913 #endif
1914
1915       CurrentGetHWError=GE_INTERNALERROR;
1916     }
1917   }
1918 }