5 A Linux/Unix toolset and driver for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
9 This file provides an API for accessing functions on the at and similar
14 /* "Turn on" prototypes in n-at.h */
18 /* System header files */
24 #include "devices/device.h"
28 #include "misc_win32.h"
31 /* Various header file */
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. */
48 /* Here we initialise model specific functions. */
50 GSM_Functions Nat_Functions = {
55 Nat_GetMemoryLocation,
56 Nat_WritePhonebookLocation,
70 Nat_GetDisplayStatus, //fill it
71 Nat_EnterSecurityCode,
72 Nat_GetSecurityCodeStatus,
80 Nat_SetAlarm, //doesn't work correctly...
100 Nat_PressKey, //fill it
101 UNIMPLEMENTED, //DisplayOutput= AT+CDIS
125 /* Mobile phone information */
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 */
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 */
147 /* Type of SMS mode. 0=PDU mode; 1=text mode */
148 int SMSATCMGF=-1; //-1 when not used earlier
150 #define SMS_AT_TEXT 1
152 /* Type of charset for phonebook 0=GSM; 1=HEX */
153 int PBKATCSCS=-1; //-1 when not used earlier
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
162 int ExtractOneParameter(unsigned char *input, unsigned char *output)
166 while (*input!=',' && *input!=0x0d) {
177 void ATDecodeDateTime(GSM_DateTime *dt, unsigned char *input)
179 dt->Year=2000+(*input-'0')*10; input++;
180 dt->Year=dt->Year+(*input-'0'); input++;
183 dt->Month=(*input-'0')*10; input++;
184 dt->Month=dt->Month+(*input-'0'); input++;
187 dt->Day=(*input-'0')*10; input++;
188 dt->Day=dt->Day+(*input-'0'); input++;
191 dt->Hour=(*input-'0')*10; input++;
192 dt->Hour=dt->Hour+(*input-'0'); input++;
195 dt->Minute=(*input-'0')*10; input++;
196 dt->Minute=dt->Minute+(*input-'0');input++;
199 dt->Second=(*input-'0')*10; input++;
200 dt->Second=dt->Second+(*input-'0');input++;
204 dt->Timezone=(*input-'0')*10; input++;
205 dt->Timezone=dt->Timezone+(*input-'0');input++;
207 if (*input=='-') dt->Timezone=-dt->Timezone;
211 void Nat_ReplyGetIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
213 strncpy(Current_IMEI,MessageBuffer+10,15);
216 fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI);
219 CurrentGetIMEIError=GE_NONE;
222 GSM_Error Nat_SendIMEIFrame()
224 unsigned char req[8] = {"AT+CGSN\r"};
226 return NULL_SendMessageSequence
227 (50, &CurrentGetIMEIError, 8, 0x00, req);
230 void Nat_ReplyGetID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
235 if (strncmp("Nokia Communicator GSM900/1800",MessageBuffer+i,30)==0) {
237 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
238 fprintf(stdout, _(" Model: RAE-3\n"));
240 strcpy(Current_Model,"RAE-3");
241 CurrentMagicError=GE_NONE;
244 if (strncmp("Nokia 6210",MessageBuffer+i,10)==0) {
246 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
247 fprintf(stdout, _(" Model: NPE-3\n"));
249 strcpy(Current_Model,"NPE-3");
250 CurrentMagicError=GE_NONE;
254 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
255 Current_Model[i-10]=MessageBuffer[i];
258 Current_Model[i-9]=0;
261 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
262 fprintf(stdout, _(" Model: %s\n"),Current_Model);
265 CurrentMagicError=GE_NONE;
268 GSM_Error Nat_SendIDFrame()
270 unsigned char req[8] = {"AT+CGMM\r"};
272 return NULL_SendMessageSequence
273 (50, &CurrentMagicError, 8, 0x00, req);
276 void Nat_ReplyGetHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
281 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
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"));
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];
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];
314 strcpy(Current_Revision,"SW");current=2;
315 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
316 Current_Revision[current++]=MessageBuffer[i];
319 Current_Revision[current++]=',';
320 Current_Revision[current++]=' ';
321 Current_Revision[current++]='H';
322 Current_Revision[current++]='W';
324 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
325 Current_Revision[current++]=MessageBuffer[i];
331 strcpy(Current_Revision,"SWxx.xx, HWxxxx");
335 CurrentGetHWError=GE_NONE;
338 GSM_Error Nat_SendHWFrame()
340 unsigned char req[8] = {"AT+CGMR\r"};
342 return NULL_SendMessageSequence
343 (50, &CurrentGetHWError, 8, 0x00, req);
346 void Nat_ReplyGetManufacturer(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
349 fprintf(stdout, _("Message: phone manufacturer received\n"));
352 if (strstr(MessageBuffer,"Nokia")) {
354 fprintf(stdout, _(" Nokia\n"));
359 if (strstr(MessageBuffer,"SIEMENS")) {
361 fprintf(stdout, _(" Siemens\n"));
363 ATMan=AT_MAN_SIEMENS;
366 CurrentMagicError=GE_NONE;
369 GSM_Error Nat_SendManufacturerFrame()
371 unsigned char req[8] = {"AT+CGMI\r"};
373 return NULL_SendMessageSequence
374 (50, &CurrentMagicError, 8, 0x00, req);
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))
382 if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
384 return GE_NOTSUPPORTED;
388 /* We try to escape AT+CMGS mode, at least Siemens M20 then needs to get some rest
390 // WRITEPHONE(PortFD,"\x1B\r",2);
395 if (Nat_SendManufacturerFrame()!=GE_NONE) return GE_TIMEOUT;
397 if (Nat_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;
399 if (Nat_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
401 if (Nat_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;
403 /* In AT doesn't have any init strings, etc. Phone answered with frame,
404 so connection should be enabled ;-) */
405 CurrentLinkOK = true;
410 GSM_Error Nat_GetManufacturer(char* manufacturer)
413 case AT_MAN_NOKIA :strcpy (manufacturer, "Nokia"); break;
414 case AT_MAN_SIEMENS:strcpy (manufacturer, "Siemens");break;
415 default :strcpy (manufacturer, "unknown");break;
421 void Nat_ReplyPBKSetMemoryTypeError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
424 fprintf(stdout, _("Message: memory setting error\n"));
427 CurrentPhonebookError=GE_UNKNOWN;
430 void Nat_ReplyPBKSetMemoryType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
433 fprintf(stdout, _("Message: memory type set OK\n"));
436 CurrentPhonebookError=GE_NONE;
439 static GSM_Error PBKSetMemoryType(GSM_MemoryType type)
441 char req[] = "AT+CPBS=\"XX\"\r";
444 GetMemoryTypeString(req2, &type);
449 return NULL_SendMessageSequence
450 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
453 void Nat_ReplySetCharset(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
455 if (strncmp("AT+CSCS=\"HEX\"",MessageBuffer,13)==0) {
457 fprintf(stdout, _("Message: charset set to HEX\n"));
459 CurrentPhonebookError=GE_NONE;
461 if (strncmp("AT+CSCS=\"GSM\"",MessageBuffer,13)==0) {
463 fprintf(stdout, _("Message: charset set to GSM\n"));
465 CurrentPhonebookError=GE_NONE;
469 GSM_Error SetCharset()
471 unsigned char req [14] = {"AT+CSCS=\"HEX\"\r"}; // HEX charset
472 unsigned char req2[14] = {"AT+CSCS=\"GSM\"\r"}; // GSM charset
475 error=NULL_SendMessageSequence
476 (50, &CurrentPhonebookError, 14, 0x00, req);
477 if (error==GE_NONE) {
478 PBKATCSCS=PBK_AT_HEX;
482 error=NULL_SendMessageSequence
483 (50, &CurrentPhonebookError, 14, 0x00, req2);
484 if (error==GE_NONE) {
485 PBKATCSCS=PBK_AT_GSM;
492 void Nat_ReplyGetMemoryLocationError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
495 fprintf(stdout, _("Message: phonebook entry receiving error\n"));
498 CurrentPhonebookError=GE_UNKNOWN;
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) {
508 fprintf(stdout, _("Message: phonebook entry received\n"));
511 CurrentPhonebookEntry->Empty = true;
512 *(CurrentPhonebookEntry->Name) = '\0';
513 *(CurrentPhonebookEntry->Number) = '\0';
514 CurrentPhonebookEntry->SubEntriesCount=0;
515 CurrentPhonebookEntry->Group = 0;
517 pos = strchr(MessageBuffer, '\"');
520 endpos = strchr(++pos, '\"');
523 strcpy(CurrentPhonebookEntry->Number, pos);
526 if (endpos) pos = strchr(++endpos, '\"');
530 l = pos - (char *)MessageBuffer;
531 endpos = memchr(pos, '\"', MessageLength - l);
537 DecodeDefault(CurrentPhonebookEntry->Name, pos, l);
540 DecodeHexBin(CurrentPhonebookEntry->Name, pos, l);
546 CurrentPhonebookError=GE_NONE;
549 GSM_Error Nat_GetMemoryLocation(GSM_PhonebookEntry *entry)
552 char req[] = "AT+CPBR=00000\r";
556 if (error!=GE_NONE) return error;
559 error = PBKSetMemoryType(entry->MemoryType);
560 if (error != GE_NONE) return error;
562 CurrentPhonebookEntry = entry;
564 sprintf(req + 8, "%5d\r", entry->Location);
566 return NULL_SendMessageSequence
567 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
570 void Nat_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
573 fprintf(stdout, _("Message: phonebook entry set OK\n"));
576 CurrentPhonebookError=GE_NONE;
579 GSM_Error Nat_WritePhonebookLocation(GSM_PhonebookEntry * entry)
587 switch (entry->MemoryType) {
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;
600 if (error!=GE_NONE) return error;
603 error = PBKSetMemoryType(entry->MemoryType);
604 if (error != GE_NONE) return error;
608 EncodeHexBin (Name, entry->Name, strlen(entry->Name));
609 Name[strlen(entry->Name)*2]=0;
612 EncodeDefault (Name, entry->Name, strlen(entry->Name));
613 Name[strlen(entry->Name)]=0;
617 GSM_PackSemiOctetNumber(entry->Number,Number,false);
620 sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"%s\"\r",
621 entry->Location, entry->Number, i, Name);
623 return NULL_SendMessageSequence
624 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
627 void Nat_ReplyGetMemoryStatusCPBS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
632 fprintf(stdout, _("Message: memory status received\n"));
635 CurrentMemoryStatus->Used = 0;
636 CurrentMemoryStatus->Free = 0;
638 start = strchr(MessageBuffer, ',');
642 CurrentMemoryStatus->Used = atoi(start);
643 start = strchr(start, ',');
646 CurrentMemoryStatus->Free = atoi(start) - CurrentMemoryStatus->Used;
647 CurrentMemoryStatusError=GE_NONE;
648 } else CurrentMemoryStatusError=GE_UNKNOWN;
649 } else CurrentMemoryStatusError=GE_UNKNOWN;
652 void Nat_ReplyGetMemoryStatusCPBSError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
654 fprintf(stdout, _("Message: memory status receiving error\n"));
656 CurrentMemoryStatusError=GE_UNKNOWN;
659 void Nat_ReplyGetMemoryStatusCPBR(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
664 fprintf(stdout, _("Message: memory size received\n"));
667 CurrentMemoryStatus->Used = 0;
668 CurrentMemoryStatus->Free = 0;
670 start = strchr(MessageBuffer, '-');
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;
684 GSM_Error Nat_GetMemoryStatus(GSM_MemoryStatus *Status)
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";
691 error = PBKSetMemoryType(Status->MemoryType);
692 if (error != GE_NONE) return error;
694 CurrentMemoryStatus = Status;
696 error=NULL_SendMessageSequence
697 (20, &CurrentMemoryStatusError, strlen(req), 0x00, req);
698 if (error==GE_NONE) {
699 CurrentMemoryStatus = NULL;
703 error=NULL_SendMessageSequence
704 (20, &CurrentMemoryStatusError, strlen(req2), 0x00, req2);
706 CurrentMemoryStatus = NULL;
711 void Nat_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
715 fprintf(stdout, _("Message: call forwarding info\n"));
717 if (MessageLength>0x20) {
719 while (MessageBuffer[current]!='"') {
720 CurrentCallDivert->Number[current-27]=MessageBuffer[current];
723 CurrentCallDivert->Enabled=true;
724 CurrentCallDivert->Number[current-27]=0x00;
725 CurrentCallDivert->Timeout=999;//where is it in frame ?
727 CurrentCallDivert->Enabled=false;
729 CurrentCallDivertError=GE_NONE;
732 GSM_Error Nat_CallDivert(GSM_CallDivert *cd)
739 sprintf(req, "AT+CCFC=");
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;
749 if (cd->Operation == GSM_CDV_Register) {
750 GSM_PackSemiOctetNumber(cd->Number,Number,false);
753 sprintf(req, "%s,%d,\"%s\",%i,,,%d", req,
754 cd->Operation,cd->Number,i,cd->Timeout);
756 sprintf(req, "%s,%d", req, cd->Operation);
760 CurrentCallDivert = cd;
762 error=NULL_SendMessageSequence
763 (100, &CurrentCallDivertError, strlen(req), 0x00, req);
765 CurrentCallDivert = NULL;
770 void Nat_ReplyGetNetworkInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
772 GSM_NetworkInfo NullNetworkInfo;
774 if (!strncmp(MessageBuffer,"AT+CREG=",8)) return;
776 /* TODO: checking if phone really registered to network */
780 /* Make sure we are expecting NetworkInfo frame */
781 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
783 fprintf(stdout, _("Message: network info received\n"));
786 NullNetworkInfo.NetworkCode[0]=0; //no exist
788 for (i=0;i<4;i++) NullNetworkInfo.CellID[i]=MessageBuffer[i+current];
790 NullNetworkInfo.CellID[4]=0;
794 for (i=0;i<4;i++) NullNetworkInfo.LAC[i]=MessageBuffer[i+current];
796 NullNetworkInfo.LAC[4]=0;
799 fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID);
800 fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC);
805 /* Make sure we are expecting NetworkInfo frame */
806 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY)
807 *CurrentNetworkInfo=NullNetworkInfo;
809 CurrentNetworkInfoError = GE_NONE;
812 void Nat_ReplyGetNetworkInfoCOPS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
813 /* Make sure we are expecting NetworkInfo frame */
814 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
816 fprintf(stdout, _("Message: network info received\n"));
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;
827 CurrentNetworkInfoError = GE_NONE;
832 GSM_Error Nat_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
836 Protocol->SendMessage(10, 0x00, "AT+CREG=2\r");
838 CurrentNetworkInfo = NetworkInfo;
840 error=NULL_SendMessageSequence
841 (20, &CurrentNetworkInfoError, 9, 0x00, "AT+CREG?\r");
842 if (error!=GE_NONE) return error;
844 error=NULL_SendMessageSequence
845 (20, &CurrentNetworkInfoError, 9, 0x00, "AT+COPS?\r");
847 CurrentNetworkInfo = NULL;
852 void Nat_ReplyGetBatteryLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
855 fprintf(stdout, _("Message: power source and battery info received\n"));
858 CurrentPowerSource=atoi(MessageBuffer+15);
859 CurrentBatteryLevel=atoi(MessageBuffer+17);
862 GSM_Error Nat_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
867 CurrentBatteryLevel=-1;
869 Protocol->SendMessage(7, 0x00, "AT+CBC\r");
871 /* Wait for timeout or other error. */
872 while (timeout != 0 && CurrentBatteryLevel == -1 ) {
880 /* Take copy in case it changes. */
881 batt_level = CurrentBatteryLevel;
883 if (batt_level != -1) {
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); }
895 return (GE_INTERNALERROR);
901 GSM_Error Nat_GetPowerSource(GSM_PowerSource * source)
903 *source = CurrentPowerSource;
907 void Nat_ReplyGetRFLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
910 fprintf(stdout, _("Message: RF level info received\n"));
912 CurrentRFLevel=atoi(MessageBuffer+15);
915 GSM_Error Nat_GetRFLevel(GSM_RFUnits *units, float *level)
922 Protocol->SendMessage(7, 0x00, "AT+CSQ\r");
924 /* Wait for timeout or other error. */
925 while (timeout != 0 && CurrentRFLevel == -1 ) {
933 /* Make copy in case it changes. */
934 rf_level = CurrentRFLevel;
939 /* Now convert between the different units we support. */
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); }
952 if (*units == GRF_CSQ) {
953 if ((CurrentRFLevel <= 31) || (CurrentRFLevel >= 0))
954 *level = CurrentRFLevel;
956 *level = 99; /* Unknown/undefined */
960 /* Unit type is one we don't handle so return error */
961 return (GE_INTERNALERROR);
964 GSM_Error Nat_GetDisplayStatus(int *Status) {
967 sprintf(req, "AT+CIND?\r");
969 return NULL_SendMessageSequence
970 (50, &CurrentDisplayStatusError, strlen(req), 0x00, req);
973 GSM_Error Nat_PressKey(int key, int event)
977 sprintf(req, "AT+CKPD=\"1\",\"20\"\r");
979 return NULL_SendMessageSequence
980 (50, &CurrentPressKeyError, strlen(req), 0x00, req);
981 // return GE_NOTSUPPORTED;
984 GSM_Error Nat_DialVoice(char *Number) {
985 char req[39] = "ATDT";
987 if (strlen(Number) > 32)
988 return (GE_INTERNALERROR);
993 return NULL_SendMessageSequence
994 (50, &CurrentDialVoiceError, 4+2+strlen(Number), 0x00, req);
997 void Nat_ReplyCancelCall(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1000 fprintf(stdout, _("Message: call hangup OK\n"));
1003 CurrentDialVoiceError=GE_NONE;
1006 GSM_Error Nat_CancelCall(void)
1008 char req[] = "AT+CHUP\r";
1010 return NULL_SendMessageSequence
1011 (50, &CurrentDialVoiceError, strlen(req), 0x00, req);
1014 GSM_Error Nat_SendDTMF(char *String)
1017 char req[80] = "AT+VTS=";
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];
1027 return NULL_SendMessageSequence
1028 (50, &CurrentSendDTMFError,7+2+2*strlen(String) , 0x00, req);
1031 GSM_Error Nat_EnterSecurityCode(GSM_SecurityCode SecurityCode)
1035 if ((SecurityCode.Type != GSCT_Pin)
1036 && (SecurityCode.Type != GSCT_Pin2)) return (GE_NOTIMPLEMENTED);
1038 sprintf(req, "AT+CPIN=\"%s\"\r", SecurityCode.Code);
1040 return NULL_SendMessageSequence
1041 (20, &CurrentSecurityCodeError, strlen(req), 0x00, req);
1044 void Nat_ReplyGetSecurityCodeStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1049 fprintf(stdout, _("Message: security code status received\n"));
1052 start = strchr(MessageBuffer, ':');
1055 *CurrentSecurityCodeStatus = 0;
1057 if (!strncmp(start, "READY", 5)) *CurrentSecurityCodeStatus = GSCT_None;
1059 if (!strncmp(start, "SIM ", 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;
1067 CurrentSecurityCodeError=GE_NONE;
1070 GSM_Error Nat_GetSecurityCodeStatus(int *Status)
1072 CurrentSecurityCodeStatus = Status;
1074 return NULL_SendMessageSequence
1075 (20, &CurrentSecurityCodeError, 9, 0x00, "AT+CPIN?\r");
1078 void Nat_ReplyGetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1084 fprintf(stdout,_("Message: date/time received\n"));
1087 if (MessageBuffer[current]==0x0d) {
1088 CurrentDateTime->IsSet=false;
1090 CurrentDateTime->IsSet=true;
1092 ATDecodeDateTime(CurrentDateTime, MessageBuffer+(current));
1095 fprintf(stdout,_(" %i/%i/%i %i:%i:%i\n"),
1096 CurrentDateTime->Day,CurrentDateTime->Month,CurrentDateTime->Year,
1097 CurrentDateTime->Hour,CurrentDateTime->Minute,CurrentDateTime->Second);
1100 CurrentDateTimeError=GE_NONE;
1103 GSM_Error Nat_GetDateTime(GSM_DateTime *date_time)
1105 unsigned char req[9] = {"AT+CCLK?\r"};
1107 CurrentDateTime=date_time;
1109 return NULL_SendMessageSequence
1110 (50, &CurrentDateTimeError, 9, 0x00, req);
1113 void Nat_ReplySetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1116 fprintf(stdout,_("Message: date/time set OK\n"));
1118 CurrentSetDateTimeError=GE_NONE;
1121 void Nat_ReplyDateTimeError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1123 fprintf(stdout,_("Message: date & time functions error\n"));
1125 CurrentSetDateTimeError=GE_UNKNOWN;
1126 CurrentDateTimeError=GE_UNKNOWN;
1129 GSM_Error Nat_SetDateTime(GSM_DateTime *date_time)
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);
1137 return NULL_SendMessageSequence
1138 (20, &CurrentSetDateTimeError, strlen(req), 0x00, req);
1141 void Nat_ReplyGetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1146 fprintf(stdout,_("Message: alarm info received\n"));
1148 if (MessageBuffer[current-1]==0x0d) {
1149 CurrentAlarm->IsSet=false;
1150 CurrentAlarm->Hour=0;
1151 CurrentAlarm->Minute=0;
1153 CurrentAlarm->IsSet=true;
1155 ATDecodeDateTime(CurrentAlarm, MessageBuffer+(current));
1158 fprintf(stdout,_(" %i:%i\n"),CurrentAlarm->Hour,CurrentAlarm->Minute);
1161 CurrentAlarmError=GE_NONE;
1164 GSM_Error Nat_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1166 unsigned char req[9] = {"AT+CALA?\r"};
1168 CurrentAlarm=date_time;
1170 return NULL_SendMessageSequence
1171 (50, &CurrentAlarmError, 9, 0x00, req);
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)
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);
1184 return NULL_SendMessageSequence
1185 (50, &CurrentSetAlarmError, strlen(req), 0x00, req);
1188 void Nat_ReplyAlarmError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1190 fprintf(stdout,_("Message: alarm functions error\n"));
1192 CurrentSetAlarmError=GE_UNKNOWN;
1193 CurrentAlarmError=GE_UNKNOWN;
1196 void Nat_ReplyGetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1198 unsigned char buffer[300];
1203 fprintf(stdout, _("Message: SMSC data received\n"));
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];
1211 if (buffer[0]==0) CurrentMessageCenterError=GE_EMPTYSMSC;
1213 strcpy(CurrentMessageCenter->Number,buffer);
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;
1222 fprintf(stdout, _(" Number: '%s'\n"),buffer);
1225 CurrentMessageCenterError=GE_NONE;
1229 /* We only get SMSC number */
1230 /* Is it possible to get more ? */
1231 GSM_Error Nat_GetSMSCenter(GSM_MessageCenter *MessageCenter)
1233 unsigned char req[] = {"AT+CSCA?\r"};
1235 if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1237 CurrentMessageCenter=MessageCenter;
1239 return NULL_SendMessageSequence
1240 (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1243 void Nat_ReplySetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1246 fprintf(stdout, _("Message: SMSC number set OK\n"));
1249 CurrentMessageCenterError=GE_NONE;
1252 GSM_Error Nat_SetSMSCenter(GSM_MessageCenter *MessageCenter)
1254 unsigned char req[50];
1256 if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1258 sprintf(req, "AT+CSCA=\"%s\"\r",MessageCenter->Number);
1260 return NULL_SendMessageSequence
1261 (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1264 void Nat_ReplySMSGetPDUType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1266 if (strncmp("AT+CSDH=1\r",MessageBuffer,10)==0) {
1268 fprintf(stdout, _("Message: all SMS parameters will be displayed in text mode\n"));
1270 CurrentSMSMessageError=GE_NONE;
1272 if (strncmp("AT+CMGF=0\r",MessageBuffer,10)==0) {
1274 fprintf(stdout, _("Message: set PDU mode for SMS\n"));
1276 CurrentSMSMessageError=GE_NONE;
1278 if (strncmp("AT+CMGF=1\r",MessageBuffer,10)==0) {
1280 fprintf(stdout, _("Message: set text mode for SMS\n"));
1282 CurrentSMSMessageError=GE_NONE;
1286 GSM_Error SMSGetPDUType()
1288 unsigned char req [10] = {"AT+CMGF=0\r"}; //sets PDU mode
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
1295 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req);
1296 if (error==GE_NONE) {
1297 SMSATCMGF=SMS_AT_PDU;
1301 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req2);
1302 if (error==GE_NONE) {
1303 SMSATCMGF=SMS_AT_TEXT;
1305 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req3);
1311 GSM_Error GSM_DecodeETSISMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int length)
1313 SMS_MessageType PDU=SMS_Deliver;
1314 GSM_ETSISMSMessage ETSI;
1315 int i,current=0,current2=0;
1318 for(i=0;i<req[0]+1;i++) ETSI.SMSCNumber[i]=req[current++];
1320 ETSI.firstbyte=req[current++];
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;
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++];
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
1339 ETSI.TPUDL=req[current++];
1341 for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
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++];
1354 for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
1356 case SMS_Status_Report:
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];
1372 error=GSM_DecodeETSISMS(SMS, &ETSI);
1373 if (error!=GE_NONE) return error;
1378 void Nat_ReplyGetSMSMessageError(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1381 error=MessageBuffer[MessageLength-2]-'0';
1382 error=error+(MessageBuffer[MessageLength-3]-'0')*10;
1383 error=error+(MessageBuffer[MessageLength-4]-'0')*100;
1386 fprintf(stdout, _("Message: SMS Reading failed\n"));
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;
1397 case 311:CurrentSMSMessageError = GE_NOACCESS;break;
1398 case 321:CurrentSMSMessageError = GE_EMPTYSMSLOCATION;break;
1399 default :CurrentSMSMessageError = GE_UNKNOWN;break;
1403 void Nat_ReplyGetSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1405 unsigned char buffer[300],buffer2[300];
1406 GSM_ETSISMSMessage ETSISMS;
1410 fprintf(stdout, _("Message: SMS Message Received\n"));
1412 switch (SMSATCMGF) {
1413 case SMS_AT_PDU: /* PDU mode */
1417 if (MessageBuffer[start]==' ' ) break;
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;
1428 if (MessageBuffer[start]==0x0a) break;
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 */
1438 if (MessageBuffer[end]==0x0a) break;
1442 DecodeHexBin (buffer, MessageBuffer+start, end-start-1);
1444 GSM_DecodeETSISMSFrame(CurrentSMSMessage,buffer,(end-start-1)/2);
1446 CurrentSMSMessageError=GE_NONE;
1451 start+=ExtractOneParameter(MessageBuffer+start, buffer);
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;
1475 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1477 /* It's delivery report according to Nokia AT standards */
1478 if (CurrentSMSMessage->folder==0 && buffer[0]!=0 && //GST_INBOX
1482 start+=ExtractOneParameter(MessageBuffer+start, buffer);
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];
1489 strcpy(CurrentSMSMessage->Sender,buffer);
1492 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1494 /* Sending datetime */
1495 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1496 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1498 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1502 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1505 ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1507 /* Date of SMSC response */
1508 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1509 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1511 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1515 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1518 ATDecodeDateTime(&DT, buffer);
1520 /* for compatiblity with GSM_DecodeETSISMSStatusReportData */
1521 /* FIXME: TimeZone is cut */
1522 DT.Year=DT.Year-2000;
1523 GSM_EncodeSMSDateTime(&DT,ETSISMS.SMSCDateTime);
1526 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1529 for (i=strlen(buffer)-1;i>=0;i--) {
1530 ETSISMS.TPStatus=ETSISMS.TPStatus+(buffer[i]-'0')*j;
1534 GSM_DecodeETSISMSStatusReportData(CurrentSMSMessage, &ETSISMS);
1536 /* NO SMSC number */
1537 CurrentSMSMessage->MessageCenter.Number[0]=0;
1539 CurrentSMSMessage->Type = GST_DR;
1541 /* FIXME: make support for it */
1542 CurrentSMSMessage->ReplyViaSameSMSC=false;
1545 /* FIXME: support for all formats */
1546 for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1548 strcpy(CurrentSMSMessage->Sender,buffer);
1550 /* Sender number in alphanumeric format ? */
1551 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1552 if (strlen(buffer)!=0) strcpy(CurrentSMSMessage->Sender,buffer);
1554 /* Sending datetime */
1555 if (CurrentSMSMessage->folder==0) { //GST_INBOX
1556 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1557 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1559 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1563 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1566 ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1569 /* Sender number format */
1570 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1573 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1574 ETSISMS.firstbyte=0;
1576 for (i=strlen(buffer)-1;i>=0;i--) {
1577 ETSISMS.firstbyte=ETSISMS.firstbyte+(buffer[i]-'0')*j;
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;
1586 /* TP PID.No support now */
1587 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1590 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1593 for (i=strlen(buffer)-1;i>=0;i--) {
1594 ETSISMS.TPDCS=ETSISMS.TPDCS+(buffer[i]-'0')*j;
1598 if (CurrentSMSMessage->folder==1) { //GST_OUTBOX
1600 start+=ExtractOneParameter(MessageBuffer+start, buffer);
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];
1608 strcpy(CurrentSMSMessage->MessageCenter.Number,buffer);
1610 /* Format of SMSC number */
1611 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1614 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1617 for (i=strlen(buffer)-1;i>=0;i--) {
1618 ETSISMS.TPUDL=ETSISMS.TPUDL+(buffer[i]-'0')*j;
1624 CurrentSMSMessage->Coding = GSM_Coding_Default;
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;
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];
1641 CurrentSMSMessage->Length=ETSISMS.TPUDL;
1644 case GSM_Coding_Unicode:
1645 case GSM_Coding_8bit:
1646 DecodeHexBin (ETSISMS.MessageText, MessageBuffer+start, ETSISMS.TPUDL*2);
1647 GSM_DecodeETSISMSSubmitData(CurrentSMSMessage, &ETSISMS);
1650 CurrentSMSMessage->MessageText[CurrentSMSMessage->Length]=0;
1653 CurrentSMSMessageError=GE_NONE;
1657 GSM_Error Nat_GetSMSMessage(GSM_SMSMessage *message)
1659 unsigned char req2[20];
1662 if (SMSATCMGF==-1) {
1663 error=SMSGetPDUType();
1664 if (error!=GE_NONE) return error;
1667 CurrentSMSMessage = message;
1669 sprintf(req2, "AT+CMGR=%i\r",message->Location); //gets SMS
1671 CurrentSMSMessage->MessageNumber=CurrentSMSMessage->Location;
1673 return NULL_SendMessageSequence
1674 (50, &CurrentSMSMessageError, strlen(req2), 0x00, req2);
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)
1680 GSM_ETSISMSMessage ETSI;
1684 error=GSM_EncodeETSISMS(SMS, &ETSI, PDU, length);
1685 if (error!=GE_NONE) return error;
1687 for (i=0;i<ETSI.SMSCNumber[0]+1;i++)
1688 req[current++]=ETSI.SMSCNumber[i];
1690 req[current++]=ETSI.firstbyte;
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];
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];
1722 void Nat_ReplyCSMP(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1725 fprintf(stdout, _("Message: SMS parameters set OK\n"));
1728 CurrentSMSMessageError=GE_NONE;
1731 GSM_Error Nat_SendSaveSMSMessage(GSM_SMSMessage *message,bool savesms)
1733 unsigned char req2[500];
1734 unsigned char req3[256];
1735 unsigned char req4[256];
1736 unsigned char endchar[1];
1738 int length,stat,current=0;
1739 SMS_MessageType PDU;
1740 GSM_ETSISMSMessage ETSISMS;
1741 GSM_MessageCenter SMSC;
1743 if (SMSATCMGF==-1) {
1744 error=SMSGetPDUType();
1745 if (error!=GE_NONE) return error;
1748 CurrentSMSMessage = message;
1750 if (message->folder==0x00) { //GST_INBOX
1753 if (message->Status==GSS_NOTSENTREAD) stat=0;
1757 if (message->Status==GSS_NOTSENTREAD) stat=2;
1760 endchar[0]=26; //ctrl+z;
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;
1768 sprintf(req2, "AT+CMGW=%i,%i\r",(length-(req3[0]+1)),stat); //saves SMS
1770 sprintf(req2, "AT+CMGS=%i\r",(length-(req3[0]+1))); //sends SMS
1772 EncodeHexBin (req4, req3, length);
1775 Protocol->SendMessage(strlen(req2), 0x00, req2); usleep(500);
1780 if (ATMan!=AT_MAN_NOKIA) {
1781 switch (CurrentSMSMessage->Coding) {
1782 case GSM_Coding_Unicode:
1783 case GSM_Coding_8bit:
1784 return GE_NOTSUPPORTED;
1790 error=GSM_EncodeETSISMS(message, &ETSISMS, PDU, &length);
1791 if (error!=GE_NONE) return error;
1793 sprintf(req4, "AT+CSMP=%i,%i,%i,%i\r",
1794 ETSISMS.firstbyte, ETSISMS.TPVP,
1795 ETSISMS.TPPID, ETSISMS.TPDCS);
1797 error=NULL_SendMessageSequence
1798 (50, &CurrentSMSMessageError, strlen(req4), 0x00, req4);
1799 if (error!=GE_NONE) return error;
1801 strcpy(SMSC.Number,message->MessageCenter.Number);
1803 error=Nat_SetSMSCenter(&SMSC);
1804 if (error!=GE_NONE) return error;
1807 /* Tested AT implementations don't support alphanumeric numbers */
1808 if ((CurrentSMSMessage->Destination[0]<'0' ||
1809 CurrentSMSMessage->Destination[0]>'9') &&
1810 CurrentSMSMessage->Destination[0]!='+')
1812 CurrentSMSMessage->Destination[0]='1';
1813 CurrentSMSMessage->Destination[1]=0;
1816 sprintf(req4, "AT+CMGW=\"%s\"\r",CurrentSMSMessage->Destination);
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;
1824 sprintf(req4, "AT+CMGS=\"%s\"\r",CurrentSMSMessage->Destination);
1827 Protocol->SendMessage(strlen(req4), 0x00, req4); usleep(500);
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);
1837 case GSM_Coding_Unicode:
1838 case GSM_Coding_8bit:
1840 EncodeHexBin (req4, ETSISMS.MessageText, length);
1848 Protocol->SendMessage(current, 0x00, req4); usleep(500);
1850 return NULL_SendMessageSequence
1851 (500, &CurrentSMSMessageError, 1, 0x00, endchar);
1854 void Nat_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1858 fprintf(stdout, _("Message: SMS Message saved\n"));
1862 while(MessageBuffer[i]!=0x20) { i++; }
1865 CurrentSMSMessage->MessageNumber=MessageBuffer[i]-'0';
1868 if (MessageBuffer[i]!=0x0d)
1869 CurrentSMSMessage->MessageNumber=
1870 CurrentSMSMessage->MessageNumber*10+MessageBuffer[i]-'0';
1873 fprintf(stdout, _(" location: %i\n"),CurrentSMSMessage->MessageNumber);
1876 CurrentSMSMessageError=GE_NONE;
1879 GSM_Error Nat_SaveSMSMessage(GSM_SMSMessage *message)
1881 return Nat_SendSaveSMSMessage(message,true);
1884 void Nat_ReplySendSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1887 fprintf(stdout, _("Message: SMS Message sent OK\n"));
1890 CurrentSMSMessageError=GE_SMSSENDOK;
1893 GSM_Error Nat_SendSMSMessage(GSM_SMSMessage *message)
1895 return Nat_SendSaveSMSMessage(message,false);
1898 void Nat_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1901 fprintf(stdout, _("Message: SMS deleted OK\n"));
1904 CurrentSMSMessageError=GE_NONE;
1907 GSM_Error Nat_DeleteSMSMessage(GSM_SMSMessage * message)
1911 sprintf(req, "AT+CMGD=%d\r", message->Location);
1913 return NULL_SendMessageSequence
1914 (50, &CurrentSMSMessageError, strlen(req), 0x00, req);
1917 void Nat_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1921 fprintf(stdout, _("Message: SMS status received\n"));
1924 CurrentSMSStatus->UnRead=0;
1925 CurrentSMSStatus->Number=0;
1927 start2 = strstr(MessageBuffer, "+CPMS: ");
1930 CurrentSMSStatus->Number=atoi(start2);
1932 CurrentSMSStatusError=GE_NONE;
1935 GSM_Error Nat_GetSMSStatus(GSM_SMSStatus *Status)
1937 CurrentSMSStatus=Status;
1939 return NULL_SendMessageSequence
1940 (10, &CurrentSMSStatusError, 13, 0x00, "AT+CPMS=\"SM\"\r");
1943 struct AT_OneReply ATRepliesError[] = {
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 },
1955 struct AT_OneReply ATRepliesOK[] = {
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 },
1993 void Nat_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1995 bool AnswerOK,AnswerError; //if last part is OK or ERROR
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) {
2009 if (strncmp("ERROR\r",MessageBuffer+(MessageLength-6),6)==0) AnswerError=true;
2010 if (strncmp("+CMS ERROR: ",MessageBuffer+(MessageLength-16),12)==0) AnswerError=true;
2013 if (strncmp("OK\r",MessageBuffer+(MessageLength-3),3)==0) AnswerOK=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);
2028 if (ATRepliesOK[i].ReplyFunction==NULL)
2029 fprintf(stdout,_("Message: unknown AT command\n"));
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);
2046 if (ATRepliesError[i].ReplyFunction==NULL)
2047 fprintf(stdout,_("Message: unknown error AT command\n"));