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