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