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