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