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 */
135 4, /* Max RF Level */
136 0, /* Min RF Level */
137 GRF_Arbitrary, /* RF level units */
138 4, /* Max Battery Level */
139 0, /* Min Battery Level */
140 GBU_Arbitrary, /* Battery level units */
141 GDT_None, /* No date/time support */
142 GDT_None, /* No alarm support */
143 0 /* Max alarms = 0 */
146 /* Type of SMS mode. 0=PDU mode; 1=text mode */
147 int SMSATCMGF=-1; //-1 when not used earlier
149 #define SMS_AT_TEXT 1
151 /* Type of charset for phonebook 0=GSM; 1=HEX */
152 int PBKATCSCS=-1; //-1 when not used earlier
156 /* Manufacturer of connected AT compatible phone */
157 int ATMan=-1; // -1 when not used earlier
158 #define AT_MAN_NOKIA 0
159 #define AT_MAN_SIEMENS 1
161 int ExtractOneParameter(unsigned char *input, unsigned char *output)
165 while (*input!=',' && *input!=0x0d) {
176 void ATDecodeDateTime(GSM_DateTime *dt, unsigned char *input)
178 dt->Year=2000+(*input-'0')*10; input++;
179 dt->Year=dt->Year+(*input-'0'); input++;
182 dt->Month=(*input-'0')*10; input++;
183 dt->Month=dt->Month+(*input-'0'); input++;
186 dt->Day=(*input-'0')*10; input++;
187 dt->Day=dt->Day+(*input-'0'); input++;
190 dt->Hour=(*input-'0')*10; input++;
191 dt->Hour=dt->Hour+(*input-'0'); input++;
194 dt->Minute=(*input-'0')*10; input++;
195 dt->Minute=dt->Minute+(*input-'0');input++;
198 dt->Second=(*input-'0')*10; input++;
199 dt->Second=dt->Second+(*input-'0');input++;
203 dt->Timezone=(*input-'0')*10; input++;
204 dt->Timezone=dt->Timezone+(*input-'0');input++;
206 if (*input=='-') dt->Timezone=-dt->Timezone;
210 void Nat_ReplyGetIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
212 strncpy(Current_IMEI,MessageBuffer+10,15);
215 fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI);
218 CurrentGetIMEIError=GE_NONE;
221 GSM_Error Nat_SendIMEIFrame()
223 unsigned char req[8] = {"AT+CGSN\r"};
225 return NULL_SendMessageSequence
226 (50, &CurrentGetIMEIError, 8, 0x00, req);
229 void Nat_ReplyGetID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
234 if (strncmp("Nokia Communicator GSM900/1800",MessageBuffer+i,30)==0) {
236 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
237 fprintf(stdout, _(" Model: RAE-3\n"));
239 strcpy(Current_Model,"RAE-3");
242 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
243 Current_Model[i-10]=MessageBuffer[i];
246 Current_Model[i-9]=0;
249 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
250 fprintf(stdout, _(" Model: %s\n"),Current_Model);
254 CurrentMagicError=GE_NONE;
257 GSM_Error Nat_SendIDFrame()
259 unsigned char req[8] = {"AT+CGMM\r"};
261 return NULL_SendMessageSequence
262 (50, &CurrentMagicError, 8, 0x00, req);
265 void Nat_ReplyGetHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
270 fprintf(stdout, _("Message: Mobile phone model identification received:\n"));
276 fprintf(stdout, _(" Firmware: "));
277 for (i=12;i<17;i++) fprintf(stdout,_("%c"),MessageBuffer[i]);
278 fprintf(stdout, _("\n"));
279 /* Some Nokia phones like 9210 return only firmware */
280 if (MessageLength>22) {
281 fprintf(stdout, _(" Hardware: "));
282 for (i=21;i<25;i++) fprintf(stdout,_("%c"),MessageBuffer[i]);
283 fprintf(stdout, _("\n"));
287 strcpy(Current_Revision,"SW");current=2;
288 for (i=12;i<17;i++) Current_Revision[current++]=MessageBuffer[i];
289 Current_Revision[current++]=',';
290 Current_Revision[current++]=' ';
291 Current_Revision[current++]='H';
292 Current_Revision[current++]='W';
293 if (MessageLength>22) {
294 for (i=21;i<25;i++) Current_Revision[current++]=MessageBuffer[i];
296 /* Some Nokia phones like 9210 return only firmware */
297 /* Here we copy firmware as hardware */
298 for (i=12;i<17;i++) Current_Revision[current++]=MessageBuffer[i];
303 strcpy(Current_Revision,"SW");current=2;
304 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
305 Current_Revision[current++]=MessageBuffer[i];
308 Current_Revision[current++]=',';
309 Current_Revision[current++]=' ';
310 Current_Revision[current++]='H';
311 Current_Revision[current++]='W';
313 while (MessageBuffer[i]!=0x0d && MessageBuffer[i]!=0x0a) {
314 Current_Revision[current++]=MessageBuffer[i];
320 strcpy(Current_Revision,"SWxx.xx, HWxxxx");
324 CurrentGetHWError=GE_NONE;
327 GSM_Error Nat_SendHWFrame()
329 unsigned char req[8] = {"AT+CGMR\r"};
331 return NULL_SendMessageSequence
332 (50, &CurrentGetHWError, 8, 0x00, req);
335 void Nat_ReplyGetManufacturer(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
338 fprintf(stdout, _("Message: phone manufacturer received\n"));
341 if (strstr(MessageBuffer,"Nokia")) {
343 fprintf(stdout, _(" Nokia\n"));
348 if (strstr(MessageBuffer,"SIEMENS")) {
350 fprintf(stdout, _(" Siemens\n"));
352 ATMan=AT_MAN_SIEMENS;
355 CurrentMagicError=GE_NONE;
358 GSM_Error Nat_SendManufacturerFrame()
360 unsigned char req[8] = {"AT+CGMI\r"};
362 return NULL_SendMessageSequence
363 (50, &CurrentMagicError, 8, 0x00, req);
366 /* Initialise variables and state machine. */
367 GSM_Error Nat_Initialise(char *port_device, char *initlength,
368 GSM_ConnectionType connection,
369 void (*rlp_callback)(RLP_F96Frame *frame))
371 if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE)
373 return GE_NOTSUPPORTED;
377 /* We try to escape AT+CMGS mode, at least Siemens M20 then needs to get some rest
379 // WRITEPHONE(PortFD,"\x1B\r",2);
384 if (Nat_SendManufacturerFrame()!=GE_NONE) return GE_TIMEOUT;
386 if (Nat_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT;
388 if (Nat_SendHWFrame()!=GE_NONE) return GE_TIMEOUT;
390 if (Nat_SendIDFrame()!=GE_NONE) return GE_TIMEOUT;
392 /* In AT doesn't have any init strings, etc. Phone answered with frame,
393 so connection should be enabled ;-) */
394 CurrentLinkOK = true;
399 GSM_Error Nat_GetManufacturer(char* manufacturer)
402 case AT_MAN_NOKIA :strcpy (manufacturer, "Nokia"); break;
403 case AT_MAN_SIEMENS:strcpy (manufacturer, "Siemens");break;
404 default :strcpy (manufacturer, "unknown");break;
410 void Nat_ReplyPBKSetMemoryType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
413 fprintf(stdout, _("Message: memory type set OK\n"));
416 CurrentPhonebookError=GE_NONE;
419 static GSM_Error PBKSetMemoryType(GSM_MemoryType type)
421 char req[] = "AT+CPBS=\"XX\"\r";
424 GetMemoryTypeString(req2, &type);
429 return NULL_SendMessageSequence
430 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
433 void Nat_ReplySetCharset(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
435 if (strncmp("AT+CSCS=\"HEX\"",MessageBuffer,13)==0) {
437 fprintf(stdout, _("Message: charset set to HEX\n"));
439 CurrentPhonebookError=GE_NONE;
441 if (strncmp("AT+CSCS=\"GSM\"",MessageBuffer,13)==0) {
443 fprintf(stdout, _("Message: charset set to GSM\n"));
445 CurrentPhonebookError=GE_NONE;
449 GSM_Error SetCharset()
451 unsigned char req [14] = {"AT+CSCS=\"HEX\"\r"}; // HEX charset
452 unsigned char req2[14] = {"AT+CSCS=\"GSM\"\r"}; // GSM charset
455 error=NULL_SendMessageSequence
456 (50, &CurrentPhonebookError, 14, 0x00, req);
457 if (error==GE_NONE) {
458 PBKATCSCS=PBK_AT_HEX;
462 error=NULL_SendMessageSequence
463 (50, &CurrentPhonebookError, 14, 0x00, req2);
464 if (error==GE_NONE) {
465 PBKATCSCS=PBK_AT_GSM;
472 /* FIXME: M20 can have " inside name. We can't get endpos by finding first " */
473 void Nat_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
479 fprintf(stdout, _("Message: phonebook entry received\n"));
482 CurrentPhonebookEntry->Empty = true;
483 *(CurrentPhonebookEntry->Name) = '\0';
484 *(CurrentPhonebookEntry->Number) = '\0';
485 CurrentPhonebookEntry->SubEntriesCount=0;
486 CurrentPhonebookEntry->Group = 0;
488 pos = strchr(MessageBuffer, '\"');
491 endpos = strchr(++pos, '\"');
494 strcpy(CurrentPhonebookEntry->Number, pos);
497 if (endpos) pos = strchr(++endpos, '\"');
501 l = pos - (char *)MessageBuffer;
502 endpos = memchr(pos, '\"', MessageLength - l);
508 DecodeDefault(CurrentPhonebookEntry->Name, pos, l);
511 DecodeHexBin(CurrentPhonebookEntry->Name, pos, l);
517 CurrentPhonebookError=GE_NONE;
520 GSM_Error Nat_GetMemoryLocation(GSM_PhonebookEntry *entry)
523 char req[] = "AT+CPBR=00000\r";
527 if (error!=GE_NONE) return error;
530 error = PBKSetMemoryType(entry->MemoryType);
531 if (error != GE_NONE) return error;
533 CurrentPhonebookEntry = entry;
535 sprintf(req + 8, "%5d\r", entry->Location);
537 return NULL_SendMessageSequence
538 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
541 void Nat_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
544 fprintf(stdout, _("Message: phonebook entry set OK\n"));
547 CurrentPhonebookError=GE_NONE;
550 GSM_Error Nat_WritePhonebookLocation(GSM_PhonebookEntry * entry)
558 switch (entry->MemoryType) {
560 /* FIXME: the 7110, 6210... supports long phonebookentries. in lack
561 of documentation we only support SIM memory */
562 if(GetModelFeature (FN_PHONEBOOK)==F_PBK71INT) return GE_NOTIMPLEMENTED;
571 if (error!=GE_NONE) return error;
574 error = PBKSetMemoryType(entry->MemoryType);
575 if (error != GE_NONE) return error;
579 EncodeHexBin (Name, entry->Name, strlen(entry->Name));
580 Name[strlen(entry->Name)*2]=0;
583 EncodeDefault (Name, entry->Name, strlen(entry->Name));
584 Name[strlen(entry->Name)]=0;
588 GSM_PackSemiOctetNumber(entry->Number,Number,false);
591 sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"%s\"\r",
592 entry->Location, entry->Number, i, Name);
594 return NULL_SendMessageSequence
595 (50, &CurrentPhonebookError, strlen(req), 0x00, req);
598 void Nat_ReplyGetMemoryStatusCPBS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
603 fprintf(stdout, _("Message: memory status received\n"));
606 CurrentMemoryStatus->Used = 0;
607 CurrentMemoryStatus->Free = 0;
609 start = strchr(MessageBuffer, ',');
613 CurrentMemoryStatus->Used = atoi(start);
614 start = strchr(start, ',');
617 CurrentMemoryStatus->Free = atoi(start) - CurrentMemoryStatus->Used;
618 CurrentMemoryStatusError=GE_NONE;
619 } else CurrentMemoryStatusError=GE_UNKNOWN;
620 } else CurrentMemoryStatusError=GE_UNKNOWN;
623 void Nat_ReplyGetMemoryStatusCPBR(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
628 fprintf(stdout, _("Message: memory size received\n"));
631 CurrentMemoryStatus->Used = 0;
632 CurrentMemoryStatus->Free = 0;
634 start = strchr(MessageBuffer, '-');
638 /* Parse +CPBR: (first-last),max_number_len,max_name_len */
639 /* We cannot get Used/Free info. We can get only size of memory
640 we don't have size in memory status and because of it
641 we make assigment used=size_of_memory, free=0.
642 It's better than nothing */
643 CurrentMemoryStatus->Used = atoi(start);
644 CurrentMemoryStatusError=GE_NONE;
645 } else CurrentMemoryStatusError=GE_UNKNOWN;
648 GSM_Error Nat_GetMemoryStatus(GSM_MemoryStatus *Status)
651 char req [] ="AT+CPBS?\r"; /* in some phones doesn't work or doesn't return
652 memory status inside */
653 char req2[] ="AT+CPBR=?\r";
655 error = PBKSetMemoryType(Status->MemoryType);
656 if (error != GE_NONE) return error;
658 CurrentMemoryStatus = Status;
660 error=NULL_SendMessageSequence
661 (20, &CurrentMemoryStatusError, strlen(req), 0x00, req);
662 if (error==GE_NONE) {
663 CurrentMemoryStatus = NULL;
667 error=NULL_SendMessageSequence
668 (20, &CurrentMemoryStatusError, strlen(req2), 0x00, req2);
670 CurrentMemoryStatus = NULL;
675 void Nat_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
679 fprintf(stdout, _("Message: call forwarding info\n"));
681 if (MessageLength>0x20) {
683 while (MessageBuffer[current]!='"') {
684 CurrentCallDivert->Number[current-27]=MessageBuffer[current];
687 CurrentCallDivert->Enabled=true;
688 CurrentCallDivert->Number[current-27]=0x00;
689 CurrentCallDivert->Timeout=999;//where is it in frame ?
691 CurrentCallDivert->Enabled=false;
693 CurrentCallDivertError=GE_NONE;
696 GSM_Error Nat_CallDivert(GSM_CallDivert *cd)
703 sprintf(req, "AT+CCFC=");
706 case GSM_CDV_AllTypes : strcat(req, "4"); break;
707 case GSM_CDV_Busy : strcat(req, "1"); break;
708 case GSM_CDV_NoAnswer : strcat(req, "2"); break;
709 case GSM_CDV_OutOfReach: strcat(req, "3"); break;
710 default : return GE_NOTIMPLEMENTED;
713 if (cd->Operation == GSM_CDV_Register) {
714 GSM_PackSemiOctetNumber(cd->Number,Number,false);
717 sprintf(req, "%s,%d,\"%s\",%i,,,%d", req,
718 cd->Operation,cd->Number,i,cd->Timeout);
720 sprintf(req, "%s,%d", req, cd->Operation);
724 CurrentCallDivert = cd;
726 error=NULL_SendMessageSequence
727 (100, &CurrentCallDivertError, strlen(req), 0x00, req);
729 CurrentCallDivert = NULL;
734 void Nat_ReplyGetNetworkInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
736 GSM_NetworkInfo NullNetworkInfo;
738 /* TODO: checking if phone really registered to network */
742 /* Make sure we are expecting NetworkInfo frame */
743 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
745 fprintf(stdout, _("Message: network info received\n"));
748 NullNetworkInfo.NetworkCode[0]=0; //no exist
750 for (i=0;i<4;i++) NullNetworkInfo.CellID[i]=MessageBuffer[i+current];
752 NullNetworkInfo.CellID[4]=0;
756 for (i=0;i<4;i++) NullNetworkInfo.LAC[i]=MessageBuffer[i+current];
758 NullNetworkInfo.LAC[4]=0;
761 fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID);
762 fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC);
767 /* Make sure we are expecting NetworkInfo frame */
768 if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY)
769 *CurrentNetworkInfo=NullNetworkInfo;
771 CurrentNetworkInfoError = GE_NONE;
774 GSM_Error Nat_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
778 Protocol->SendMessage(10, 0x00, "AT+CREG=2\r");
780 CurrentNetworkInfo = NetworkInfo;
782 error=NULL_SendMessageSequence
783 (20, &CurrentNetworkInfoError, 9, 0x00, "AT+CREG?\r");
785 CurrentNetworkInfo = NULL;
790 void Nat_ReplyGetBatteryLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
793 fprintf(stdout, _("Message: power source and battery info received\n"));
796 CurrentPowerSource=atoi(MessageBuffer+15);
797 CurrentBatteryLevel=atoi(MessageBuffer+17);
800 GSM_Error Nat_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
805 CurrentBatteryLevel=-1;
807 Protocol->SendMessage(7, 0x00, "AT+CBC\r");
809 /* Wait for timeout or other error. */
810 while (timeout != 0 && CurrentBatteryLevel == -1 ) {
818 /* Take copy in case it changes. */
819 batt_level = CurrentBatteryLevel;
821 if (batt_level != -1) {
823 /* Only units we handle at present are GBU_Arbitrary */
824 if (*units == GBU_Arbitrary) {
825 if (batt_level >= 70) { *level = 4; return (GE_NONE); }
826 if (batt_level >= 50) { *level = 3; return (GE_NONE); }
827 if (batt_level >= 30) { *level = 2; return (GE_NONE); }
828 if (batt_level >= 10) { *level = 1; return (GE_NONE); }
833 return (GE_INTERNALERROR);
839 GSM_Error Nat_GetPowerSource(GSM_PowerSource * source)
841 *source = CurrentPowerSource;
845 void Nat_ReplyGetRFLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
848 fprintf(stdout, _("Message: RF level info received\n"));
850 CurrentRFLevel=atoi(MessageBuffer+15);
853 GSM_Error Nat_GetRFLevel(GSM_RFUnits *units, float *level)
860 Protocol->SendMessage(7, 0x00, "AT+CSQ\r");
862 /* Wait for timeout or other error. */
863 while (timeout != 0 && CurrentRFLevel == -1 ) {
871 /* Make copy in case it changes. */
872 rf_level = CurrentRFLevel;
877 /* Now convert between the different units we support. */
879 if (*units == GRF_Arbitrary) {
880 if (CurrentRFLevel == 99) { *level = 0;return (GE_NONE); }
881 if (CurrentRFLevel > 23) { *level = 4;return (GE_NONE); }
882 if (CurrentRFLevel > 17) { *level = 3;return (GE_NONE); }
883 if (CurrentRFLevel > 11) { *level = 2;return (GE_NONE); }
884 if (CurrentRFLevel > 5) { *level = 1;return (GE_NONE); }
890 if (*units == GRF_CSQ) {
891 if ((CurrentRFLevel <= 31) || (CurrentRFLevel >= 0))
892 *level = CurrentRFLevel;
894 *level = 99; /* Unknown/undefined */
898 /* Unit type is one we don't handle so return error */
899 return (GE_INTERNALERROR);
902 GSM_Error Nat_GetDisplayStatus(int *Status) {
905 sprintf(req, "AT+CIND?\r");
907 return NULL_SendMessageSequence
908 (50, &CurrentDisplayStatusError, strlen(req), 0x00, req);
911 GSM_Error Nat_PressKey(int key, int event)
915 sprintf(req, "AT+CKPD=?\r");
917 return NULL_SendMessageSequence
918 (50, &CurrentPressKeyError, strlen(req), 0x00, req);
921 GSM_Error Nat_DialVoice(char *Number) {
922 char req[39] = "ATDT";
924 if (strlen(Number) > 32)
925 return (GE_INTERNALERROR);
930 return NULL_SendMessageSequence
931 (50, &CurrentDialVoiceError, 4+2+strlen(Number), 0x00, req);
934 void Nat_ReplyCancelCall(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
937 fprintf(stdout, _("Message: call hangup OK\n"));
940 CurrentDialVoiceError=GE_NONE;
943 GSM_Error Nat_CancelCall(void)
945 char req[] = "AT+CHUP\r";
947 return NULL_SendMessageSequence
948 (50, &CurrentDialVoiceError, strlen(req), 0x00, req);
951 GSM_Error Nat_SendDTMF(char *String)
954 char req[80] = "AT+VTS=";
956 for (n = 0; n < 32; n++) {
957 if (String[n] == '\0') break;
958 if (n != 0) req[6 + 2 * n] = ',';
959 req[7 + 2 * n] = String[n];
964 return NULL_SendMessageSequence
965 (50, &CurrentSendDTMFError,7+2+2*strlen(String) , 0x00, req);
968 GSM_Error Nat_EnterSecurityCode(GSM_SecurityCode SecurityCode)
972 if ((SecurityCode.Type != GSCT_Pin)
973 && (SecurityCode.Type != GSCT_Pin2)) return (GE_NOTIMPLEMENTED);
975 sprintf(req, "AT+CPIN=\"%s\"\r", SecurityCode.Code);
977 return NULL_SendMessageSequence
978 (20, &CurrentSecurityCodeError, strlen(req), 0x00, req);
981 void Nat_ReplyGetSecurityCodeStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
986 fprintf(stdout, _("Message: security code status received\n"));
989 start = strchr(MessageBuffer, ':');
992 *CurrentSecurityCodeStatus = 0;
994 if (!strncmp(start, "READY", 5)) *CurrentSecurityCodeStatus = GSCT_None;
996 if (!strncmp(start, "SIM ", 4)) {
998 if (!strncmp(start, "PIN2", 4)) *CurrentSecurityCodeStatus = GSCT_Pin2;
999 if (!strncmp(start, "PUK2", 4)) *CurrentSecurityCodeStatus = GSCT_Puk2;
1000 if (!strncmp(start, "PIN", 3)) *CurrentSecurityCodeStatus = GSCT_Pin;
1001 if (!strncmp(start, "PUK", 3)) *CurrentSecurityCodeStatus = GSCT_Puk;
1004 CurrentSecurityCodeError=GE_NONE;
1007 GSM_Error Nat_GetSecurityCodeStatus(int *Status)
1009 CurrentSecurityCodeStatus = Status;
1011 return NULL_SendMessageSequence
1012 (20, &CurrentSecurityCodeError, 9, 0x00, "AT+CPIN?\r");
1015 void Nat_ReplyGetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1021 fprintf(stdout,_("Message: date/time received\n"));
1024 if (MessageBuffer[current]==0x0d) {
1025 CurrentDateTime->IsSet=false;
1027 CurrentDateTime->IsSet=true;
1029 ATDecodeDateTime(CurrentDateTime, MessageBuffer+(current));
1032 fprintf(stdout,_(" %i/%i/%i %i:%i:%i\n"),
1033 CurrentDateTime->Day,CurrentDateTime->Month,CurrentDateTime->Year,
1034 CurrentDateTime->Hour,CurrentDateTime->Minute,CurrentDateTime->Second);
1037 CurrentDateTimeError=GE_NONE;
1040 GSM_Error Nat_GetDateTime(GSM_DateTime *date_time)
1042 unsigned char req[9] = {"AT+CCLK?\r"};
1044 CurrentDateTime=date_time;
1046 return NULL_SendMessageSequence
1047 (50, &CurrentDateTimeError, 9, 0x00, req);
1050 void Nat_ReplySetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1053 fprintf(stdout,_("Message: date/time set OK\n"));
1055 CurrentSetDateTimeError=GE_NONE;
1058 GSM_Error Nat_SetDateTime(GSM_DateTime *date_time)
1062 sprintf(req, "AT+CCLK=\"%02i/%02i/%02i,%02i:%02i:%02i+00\"\r",
1063 date_time->Year-2000,date_time->Month,date_time->Day,
1064 date_time->Hour,date_time->Minute,date_time->Second);
1066 return NULL_SendMessageSequence
1067 (20, &CurrentSetDateTimeError, strlen(req), 0x00, req);
1070 void Nat_ReplyGetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1075 fprintf(stdout,_("Message: alarm info received\n"));
1077 if (MessageBuffer[current-1]==0x0d) {
1078 CurrentAlarm->IsSet=false;
1079 CurrentAlarm->Hour=0;
1080 CurrentAlarm->Minute=0;
1082 CurrentAlarm->IsSet=true;
1084 ATDecodeDateTime(CurrentAlarm, MessageBuffer+(current));
1087 fprintf(stdout,_(" %i:%i\n"),CurrentAlarm->Hour,CurrentAlarm->Minute);
1090 CurrentAlarmError=GE_NONE;
1093 GSM_Error Nat_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1095 unsigned char req[9] = {"AT+CALA?\r"};
1097 CurrentAlarm=date_time;
1099 return NULL_SendMessageSequence
1100 (50, &CurrentAlarmError, 9, 0x00, req);
1103 /* FIXME: we should also allow to set the alarm off :-) */
1104 /* Doesn't work ? */
1105 GSM_Error Nat_SetAlarm(int alarm_number, GSM_DateTime *date_time)
1110 sprintf(req, "AT+CALA=\"%02i/%02i/%02i,%02i:%02i:%02i+00\",0,1\r",
1111 i,i,i,date_time->Hour,date_time->Minute,i);
1113 return NULL_SendMessageSequence
1114 (50, &CurrentSetAlarmError, strlen(req), 0x00, req);
1117 void Nat_ReplyGetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1119 unsigned char buffer[300];
1123 /* FIXME: support for all formats */
1124 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1125 for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1128 /* FIXME: when SMSC in empty, I set default (for my network) */
1129 /* Any better solution ? */
1130 // if (buffer[0]==0) strcpy(buffer,"+48602951111");
1131 if (buffer[0]==0) strcpy(buffer,"+48601000310");
1133 strcpy(CurrentMessageCenter->Number,buffer);
1135 /* Some default values. Is it possible to get them ? */
1136 CurrentMessageCenter->Name[0]=0;
1137 CurrentMessageCenter->DefaultRecipient[0]=0;
1138 CurrentMessageCenter->Format=GSMF_Text;
1139 CurrentMessageCenter->Validity=GSMV_Max_Time;
1142 fprintf(stdout, _("Message: SMSC number received\n Number: '%s'\n"),buffer);
1145 CurrentMessageCenterError=GE_NONE;
1148 /* We only get SMSC number */
1149 /* Is it possible to get more ? */
1150 GSM_Error Nat_GetSMSCenter(GSM_MessageCenter *MessageCenter)
1152 unsigned char req[] = {"AT+CSCA?\r"};
1154 if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1156 CurrentMessageCenter=MessageCenter;
1158 return NULL_SendMessageSequence
1159 (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1162 void Nat_ReplySetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1165 fprintf(stdout, _("Message: SMSC number set OK\n"));
1168 CurrentMessageCenterError=GE_NONE;
1171 GSM_Error Nat_SetSMSCenter(GSM_MessageCenter *MessageCenter)
1173 unsigned char req[50];
1175 if (MessageCenter->No!=1) return GE_NOTSUPPORTED;
1177 sprintf(req, "AT+CSCA=\"%s\"\r",MessageCenter->Number);
1179 return NULL_SendMessageSequence
1180 (50, &CurrentMessageCenterError, strlen(req), 0x00, req);
1183 void Nat_ReplySMSGetPDUType(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1185 if (strncmp("AT+CSDH=1\r",MessageBuffer,10)==0) {
1187 fprintf(stdout, _("Message: all SMS parameters will be displayed in text mode\n"));
1189 CurrentSMSMessageError=GE_NONE;
1191 if (strncmp("AT+CMGF=0\r",MessageBuffer,10)==0) {
1193 fprintf(stdout, _("Message: set PDU mode for SMS\n"));
1195 CurrentSMSMessageError=GE_NONE;
1197 if (strncmp("AT+CMGF=1\r",MessageBuffer,10)==0) {
1199 fprintf(stdout, _("Message: set text mode for SMS\n"));
1201 CurrentSMSMessageError=GE_NONE;
1205 GSM_Error SMSGetPDUType()
1207 unsigned char req [10] = {"AT+CMGF=0\r"}; //sets PDU mode
1209 unsigned char req2[10] = {"AT+CMGF=1\r"}; //sets text mode
1210 unsigned char req3[10] = {"AT+CSDH=1\r"}; //shows all parameters in text mode
1214 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req);
1215 if (error==GE_NONE) {
1216 SMSATCMGF=SMS_AT_PDU;
1220 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req2);
1221 if (error==GE_NONE) {
1222 SMSATCMGF=SMS_AT_TEXT;
1224 error=NULL_SendMessageSequence (50, &CurrentSMSMessageError, 10, 0x00, req3);
1230 GSM_Error GSM_DecodeETSISMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int length)
1232 SMS_MessageType PDU=SMS_Deliver;
1233 GSM_ETSISMSMessage ETSI;
1234 int i,current=0,current2=0;
1236 for(i=0;i<req[0]+1;i++) ETSI.SMSCNumber[i]=req[current++];
1238 ETSI.firstbyte=req[current++];
1240 /* See GSM 03.40 section 9.2.3.1 */
1241 if ((ETSI.firstbyte & 0x03) == 0x01) PDU=SMS_Submit;
1242 if ((ETSI.firstbyte & 0x03) == 0x02) PDU=SMS_Status_Report;
1246 SMS->Type = GST_SMS;
1247 SMS->folder= GST_OUTBOX;
1248 current++; //TPMR is ignored now
1249 current2=((req[current])+1)/2+1;
1250 for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1251 ETSI.TPPID=req[current++];
1252 ETSI.TPDCS=req[current++];
1254 /* See GSM 03.40 9.2.3.3 TPVP can not exist in frame */
1255 if ((ETSI.firstbyte & 0x18)!=0) current++; //TPVP is ignored now
1257 ETSI.TPUDL=req[current++];
1259 for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
1263 SMS->Type = GST_SMS;
1264 SMS->folder= GST_INBOX;
1265 current2=((req[current])+1)/2+1;
1266 for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1267 ETSI.TPPID=req[current++];
1268 ETSI.TPDCS=req[current++];
1269 for(i=0;i<7;i++) ETSI.DeliveryDateTime[i]=req[current++];
1270 ETSI.TPUDL=req[current++];
1272 for(i=current2;i<length;i++) ETSI.MessageText[i-current2]=req[current++];
1274 case SMS_Status_Report:
1277 SMS->folder= GST_INBOX;
1278 current++; //TPMR is ignored now
1279 current2=((req[current])+1)/2+1;
1280 for(i=0;i<current2+1;i++) ETSI.Number[i]=req[current++];
1281 for(i=0;i<7;i++) ETSI.DeliveryDateTime[i]=req[current++];
1282 for(i=0;i<7;i++) ETSI.SMSCDateTime[i]=req[current++];
1283 ETSI.TPStatus=req[current];
1290 GSM_DecodeETSISMS(SMS, &ETSI);
1295 void Nat_ReplyGetSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1297 unsigned char buffer[300],buffer2[300];
1298 GSM_ETSISMSMessage ETSISMS;
1302 fprintf(stdout, _("Message: SMS Message Received\n"));
1304 switch (SMSATCMGF) {
1305 case SMS_AT_PDU: /* PDU mode */
1309 if (MessageBuffer[start]==' ' ) break;
1314 if (MessageBuffer[start]=='0' || MessageBuffer[start]=='2')
1315 CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1316 if (MessageBuffer[start]=='1' || MessageBuffer[start]=='3')
1317 CurrentSMSMessage->Status=GSS_SENTREAD;
1320 if (MessageBuffer[start]==0x0a) break;
1325 /* We need to find last char of PDU text. We can't use MessageLength,
1326 because sometimes some phones (like Siemens M20) return
1327 some strange things after main PDU */
1330 if (MessageBuffer[end]==0x0a) break;
1334 DecodeHexBin (buffer, MessageBuffer+start, end-start-1);
1336 GSM_DecodeETSISMSFrame(CurrentSMSMessage,buffer,(end-start-1)/2);
1338 CurrentSMSMessageError=GE_NONE;
1343 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1345 if (!strcmp(buffer,"\"0\"") || !strcmp(buffer,"\"REC UNREAD\"")) {
1346 CurrentSMSMessage->Type=GST_SMS;
1347 CurrentSMSMessage->folder=GST_INBOX;
1348 CurrentSMSMessage->SMSData=true;
1349 CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1350 } else if (!strcmp(buffer,"\"1\"") || !strcmp(buffer,"\"REC READ\"")) {
1351 CurrentSMSMessage->Type=GST_SMS;
1352 CurrentSMSMessage->folder=GST_INBOX;
1353 CurrentSMSMessage->SMSData=true;
1354 CurrentSMSMessage->Status=GSS_SENTREAD;
1355 } else if (!strcmp(buffer,"\"2\"") || !strcmp(buffer,"\"STO UNSENT\"")) {
1356 CurrentSMSMessage->Type=GST_SMS;
1357 CurrentSMSMessage->folder=GST_OUTBOX;
1358 CurrentSMSMessage->SMSData=false;
1359 CurrentSMSMessage->Status=GSS_NOTSENTREAD;
1360 } else if (!strcmp(buffer,"\"3\"") || !strcmp(buffer,"\"STO SENT\"")) {
1361 CurrentSMSMessage->Type=GST_SMS;
1362 CurrentSMSMessage->folder=GST_OUTBOX;
1363 CurrentSMSMessage->SMSData=false;
1364 CurrentSMSMessage->Status=GSS_SENTREAD;
1367 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1369 /* It's delivery report according to Nokia AT standards */
1370 if (CurrentSMSMessage->folder==0 && buffer[0]!=0 && //GST_INBOX
1374 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1377 /* FIXME: support for all formats */
1378 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1379 for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1381 strcpy(CurrentSMSMessage->Sender,buffer);
1384 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1386 /* Sending datetime */
1387 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1388 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1390 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1394 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1397 ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1399 /* Date of SMSC response */
1400 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1401 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1403 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1407 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1410 ATDecodeDateTime(&DT, buffer);
1412 /* for compatiblity with GSM_DecodeETSISMSStatusReportData */
1413 /* FIXME: TimeZone is cut */
1414 DT.Year=DT.Year-2000;
1415 GSM_EncodeSMSDateTime(&DT,ETSISMS.SMSCDateTime);
1418 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1421 for (i=strlen(buffer)-1;i>=0;i--) {
1422 ETSISMS.TPStatus=ETSISMS.TPStatus+(buffer[i]-'0')*j;
1426 GSM_DecodeETSISMSStatusReportData(CurrentSMSMessage, &ETSISMS);
1428 /* NO SMSC number */
1429 CurrentSMSMessage->MessageCenter.Number[0]=0;
1431 CurrentSMSMessage->Type = GST_DR;
1433 /* FIXME: make support for it */
1434 CurrentSMSMessage->ReplyViaSameSMSC=false;
1437 /* FIXME: support for all formats */
1438 for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1440 strcpy(CurrentSMSMessage->Sender,buffer);
1442 /* Sender number in alphanumeric format ? */
1443 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1444 if (strlen(buffer)!=0) strcpy(CurrentSMSMessage->Sender,buffer);
1446 /* Sending datetime */
1447 if (CurrentSMSMessage->folder==0) { //GST_INBOX
1448 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1449 start+=ExtractOneParameter(MessageBuffer+start, buffer2);
1451 for (i=1;i<strlen(buffer)+1;i++) buffer[i-1]=buffer[i];
1455 for (j=0;j<strlen(buffer2);j++) buffer[i++]=buffer2[j];
1458 ATDecodeDateTime(&CurrentSMSMessage->Time, buffer);
1461 /* Sender number format */
1462 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1465 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1466 ETSISMS.firstbyte=0;
1468 for (i=strlen(buffer)-1;i>=0;i--) {
1469 ETSISMS.firstbyte=ETSISMS.firstbyte+(buffer[i]-'0')*j;
1473 CurrentSMSMessage->ReplyViaSameSMSC=false;
1474 /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
1475 if ((ETSISMS.firstbyte & 128)==128)
1476 CurrentSMSMessage->ReplyViaSameSMSC=true;
1478 /* TP PID.No support now */
1479 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1482 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1485 for (i=strlen(buffer)-1;i>=0;i--) {
1486 ETSISMS.TPDCS=ETSISMS.TPDCS+(buffer[i]-'0')*j;
1490 if (CurrentSMSMessage->folder==1) { //GST_OUTBOX
1492 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1496 /* FIXME: support for all formats */
1497 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1498 for (i=1;i<strlen(buffer)-1;i++) buffer[i-1]=buffer[i];
1500 strcpy(CurrentSMSMessage->MessageCenter.Number,buffer);
1502 /* Format of SMSC number */
1503 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1506 start+=ExtractOneParameter(MessageBuffer+start, buffer);
1509 for (i=strlen(buffer)-1;i>=0;i--) {
1510 ETSISMS.TPUDL=ETSISMS.TPUDL+(buffer[i]-'0')*j;
1516 CurrentSMSMessage->Coding = GSM_Coding_Default;
1518 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
1519 if ((ETSISMS.TPDCS & 0xf4) == 0xf4) CurrentSMSMessage->Coding=GSM_Coding_8bit;
1520 if ((ETSISMS.TPDCS & 0x08) == 0x08) CurrentSMSMessage->Coding=GSM_Coding_Unicode;
1522 switch (CurrentSMSMessage->Coding) {
1523 case GSM_Coding_Default:
1524 /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
1525 /* If not SMS with UDH, it's coded normal */
1526 /* If UDH available, treat it as Unicode or 8 bit */
1527 if ((ETSISMS.firstbyte & 0x40)!=0x40) {
1528 CurrentSMSMessage->UDHType=GSM_NoUDH;
1529 for (i=0;i<ETSISMS.TPUDL;i++) {
1530 if (i>GSM_MAX_SMS_LENGTH) break;
1531 CurrentSMSMessage->MessageText[i]=MessageBuffer[i+start];
1533 CurrentSMSMessage->Length=ETSISMS.TPUDL;
1536 case GSM_Coding_Unicode:
1537 case GSM_Coding_8bit:
1538 DecodeHexBin (ETSISMS.MessageText, MessageBuffer+start, ETSISMS.TPUDL*2);
1539 GSM_DecodeETSISMSSubmitData(CurrentSMSMessage, &ETSISMS);
1542 CurrentSMSMessage->MessageText[CurrentSMSMessage->Length]=0;
1545 CurrentSMSMessageError=GE_NONE;
1549 GSM_Error Nat_GetSMSMessage(GSM_SMSMessage *message)
1551 unsigned char req2[20];
1554 if (SMSATCMGF==-1) {
1555 error=SMSGetPDUType();
1556 if (error!=GE_NONE) return error;
1559 CurrentSMSMessage = message;
1561 sprintf(req2, "AT+CMGR=%i\r",message->Location); //gets SMS
1563 CurrentSMSMessage->MessageNumber=CurrentSMSMessage->Location;
1565 return NULL_SendMessageSequence
1566 (50, &CurrentSMSMessageError, strlen(req2), 0x00, req2);
1569 /* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */
1570 GSM_Error GSM_EncodeETSISMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int *length, SMS_MessageType PDU)
1572 GSM_ETSISMSMessage ETSI;
1575 GSM_EncodeETSISMS(SMS, &ETSI, PDU, length);
1577 for (i=0;i<ETSI.SMSCNumber[0]+1;i++)
1578 req[current++]=ETSI.SMSCNumber[i];
1580 req[current++]=ETSI.firstbyte;
1585 req[current++]=0; //TPMR ignored now
1586 for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++) req[current++]=ETSI.Number[i];
1587 req[current++]=0; //ETSI.TPPID;
1588 req[current++]=ETSI.TPDCS;
1589 req[current++]=ETSI.TPVP;
1590 req[current++]=ETSI.TPUDL;
1591 for(i=0;i<*length;i++) req[current++]=ETSI.MessageText[i];
1595 for (i=0;i<((ETSI.Number[0]+1)/2+1)+1;i++) req[current++]=ETSI.Number[i];
1596 req[current++]=0; //ETSI.TPPID;
1597 req[current++]=ETSI.TPDCS;
1598 for(i=0;i<7;i++) req[current++]=ETSI.DeliveryDateTime[i];
1599 req[current++]=ETSI.TPUDL;
1600 for(i=0;i<*length;i++) req[current++]=ETSI.MessageText[i];
1612 void Nat_ReplyCSMP(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1615 fprintf(stdout, _("Message: SMS parameters set OK\n"));
1618 CurrentSMSMessageError=GE_NONE;
1621 GSM_Error Nat_SendSaveSMSMessage(GSM_SMSMessage *message,bool savesms)
1623 unsigned char req2[500];
1624 unsigned char req3[256];
1625 unsigned char req4[256];
1626 unsigned char endchar[1];
1628 int length,stat,current=0;
1629 SMS_MessageType PDU;
1630 GSM_ETSISMSMessage ETSISMS;
1631 GSM_MessageCenter SMSC;
1633 if (SMSATCMGF==-1) {
1634 error=SMSGetPDUType();
1635 if (error!=GE_NONE) return error;
1638 CurrentSMSMessage = message;
1640 if (message->folder==0x00) { //GST_INBOX
1643 if (message->Status==GSS_NOTSENTREAD) stat=0;
1647 if (message->Status==GSS_NOTSENTREAD) stat=2;
1650 endchar[0]=26; //ctrl+z;
1652 switch (SMSATCMGF) {
1653 case SMS_AT_PDU: /* PDU mode */
1654 GSM_EncodeETSISMSFrame(message, req3, &length, PDU);
1657 sprintf(req2, "AT+CMGW=%i,%i\r",(length-(req3[0]+1)),stat); //saves SMS
1659 sprintf(req2, "AT+CMGS=%i\r",(length-(req3[0]+1))); //sends SMS
1661 EncodeHexBin (req4, req3, length);
1664 Protocol->SendMessage(strlen(req2), 0x00, req2); usleep(500);
1669 if (ATMan!=AT_MAN_NOKIA) {
1670 switch (CurrentSMSMessage->Coding) {
1671 case GSM_Coding_Unicode:
1672 case GSM_Coding_8bit:
1673 return GE_NOTSUPPORTED;
1679 GSM_EncodeETSISMS(message, &ETSISMS, PDU, &length);
1681 sprintf(req4, "AT+CSMP=%i,%i,%i,%i\r",
1682 ETSISMS.firstbyte, ETSISMS.TPVP,
1683 ETSISMS.TPPID, ETSISMS.TPDCS);
1685 error=NULL_SendMessageSequence
1686 (50, &CurrentSMSMessageError, strlen(req4), 0x00, req4);
1687 if (error!=GE_NONE) return error;
1689 strcpy(SMSC.Number,message->MessageCenter.Number);
1691 error=Nat_SetSMSCenter(&SMSC);
1692 if (error!=GE_NONE) return error;
1695 /* Tested AT implementations don't support alphanumeric numbers */
1696 if ((CurrentSMSMessage->Destination[0]<'0' ||
1697 CurrentSMSMessage->Destination[0]>'9') &&
1698 CurrentSMSMessage->Destination[0]!='+')
1700 CurrentSMSMessage->Destination[0]='1';
1701 CurrentSMSMessage->Destination[1]=0;
1704 sprintf(req4, "AT+CMGW=\"%s\"\r",CurrentSMSMessage->Destination);
1706 /* Tested AT implementations don't support alphanumeric numbers */
1707 if ((CurrentSMSMessage->Destination[0]<'0' ||
1708 CurrentSMSMessage->Destination[0]>'9') &&
1709 CurrentSMSMessage->Destination[0]!='+')
1710 return GE_NOTSUPPORTED;
1712 sprintf(req4, "AT+CMGS=\"%s\"\r",CurrentSMSMessage->Destination);
1715 Protocol->SendMessage(strlen(req4), 0x00, req4); usleep(500);
1717 switch (CurrentSMSMessage->Coding) {
1718 case GSM_Coding_Default:
1719 /* If not SMS with UDH, it's as normal text */
1720 if (CurrentSMSMessage->UDHType==GSM_NoUDH) {
1721 strcpy(req4,CurrentSMSMessage->MessageText);
1722 current=strlen(req4);
1725 case GSM_Coding_Unicode:
1726 case GSM_Coding_8bit:
1728 EncodeHexBin (req4, ETSISMS.MessageText, length);
1736 Protocol->SendMessage(current, 0x00, req4); usleep(500);
1738 return NULL_SendMessageSequence
1739 (500, &CurrentSMSMessageError, 1, 0x00, endchar);
1742 void Nat_ReplySaveSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1746 fprintf(stdout, _("Message: SMS Message saved\n"));
1750 while(MessageBuffer[i]!=0x20) { i++; }
1753 CurrentSMSMessage->MessageNumber=MessageBuffer[i]-'0';
1756 if (MessageBuffer[i]!=0x0d)
1757 CurrentSMSMessage->MessageNumber=
1758 CurrentSMSMessage->MessageNumber*10+MessageBuffer[i]-'0';
1761 fprintf(stdout, _(" location: %i\n"),CurrentSMSMessage->MessageNumber);
1764 CurrentSMSMessageError=GE_NONE;
1767 GSM_Error Nat_SaveSMSMessage(GSM_SMSMessage *message)
1769 return Nat_SendSaveSMSMessage(message,true);
1772 void Nat_ReplySendSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1775 fprintf(stdout, _("Message: SMS Message sent OK\n"));
1778 CurrentSMSMessageError=GE_SMSSENDOK;
1781 GSM_Error Nat_SendSMSMessage(GSM_SMSMessage *message)
1783 return Nat_SendSaveSMSMessage(message,false);
1786 void Nat_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1789 fprintf(stdout, _("Message: SMS deleted OK\n"));
1792 CurrentSMSMessageError=GE_NONE;
1795 GSM_Error Nat_DeleteSMSMessage(GSM_SMSMessage * message)
1799 sprintf(req, "AT+CMGD=%d\r", message->Location);
1801 return NULL_SendMessageSequence
1802 (50, &CurrentSMSMessageError, strlen(req), 0x00, req);
1805 void Nat_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1809 fprintf(stdout, _("Message: SMS status received\n"));
1812 CurrentSMSStatus->UnRead=0;
1813 CurrentSMSStatus->Number=0;
1815 start2 = strstr(MessageBuffer, "+CPMS: ");
1818 CurrentSMSStatus->Number=atoi(start2);
1820 CurrentSMSStatusError=GE_NONE;
1823 GSM_Error Nat_GetSMSStatus(GSM_SMSStatus *Status)
1825 CurrentSMSStatus=Status;
1827 return NULL_SendMessageSequence
1828 (10, &CurrentSMSStatusError, 13, 0x00, "AT+CPMS=\"SM\"\r");
1831 struct AT_OneReply ATRepliesOK[] = {
1833 {"AT+CCFC=" ,Nat_ReplyCallDivert },
1834 {"AT+CGMI\r",Nat_ReplyGetManufacturer },
1835 {"AT+CPBS?" ,Nat_ReplyGetMemoryStatusCPBS },
1836 {"AT+CPBR=?",Nat_ReplyGetMemoryStatusCPBR },
1837 {"AT+CPBR=" ,Nat_ReplyGetMemoryLocation },
1838 {"AT+CPBW=" ,Nat_ReplyWritePhonebookLocation},
1839 {"AT+CPBS=" ,Nat_ReplyPBKSetMemoryType },
1840 {"AT+CSCS=\"HEX\"",Nat_ReplySetCharset },
1841 {"AT+CSCS=\"GSM\"",Nat_ReplySetCharset },
1842 {"AT+CSCA?" ,Nat_ReplyGetSMSCenter },
1843 {"AT+CSCA=" ,Nat_ReplySetSMSCenter },
1844 {"AT+CSDH=1\r",Nat_ReplySMSGetPDUType },
1845 {"AT+CMGF=0\r",Nat_ReplySMSGetPDUType },
1846 {"AT+CMGF=1\r",Nat_ReplySMSGetPDUType },
1847 {"AT+CMGR=" ,Nat_ReplyGetSMSMessage },
1848 {"AT+CSMP=" ,Nat_ReplyCSMP },
1849 {"AT+CMGW=" ,Nat_ReplySaveSMSMessage },
1850 {"AT+CMGS=" ,Nat_ReplySendSMSMessage },
1851 {"AT+CMGD=" ,Nat_ReplyDeleteSMSMessage },
1852 {"AT+CPMS=\"SM\"",Nat_ReplyGetSMSStatus },
1853 {"AT+CPIN?\r",Nat_ReplyGetSecurityCodeStatus},
1854 {"AT+CCLK?" ,Nat_ReplyGetDateTime },
1855 {"AT+CCLK=" ,Nat_ReplySetDateTime },
1856 {"AT+CALA?" ,Nat_ReplyGetAlarm },
1857 {"AT+CGMM\r",Nat_ReplyGetID },
1858 {"AT+CGMR\r",Nat_ReplyGetHW },
1859 {"AT+CREG?" ,Nat_ReplyGetNetworkInfo },
1860 {"AT+CGSN\r",Nat_ReplyGetIMEI },
1861 {"AT+CHUP" ,Nat_ReplyCancelCall },
1862 {"AT+CBC" ,Nat_ReplyGetBatteryLevel },
1863 {"AT+CSQ" ,Nat_ReplyGetRFLevel },
1868 void Nat_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) {
1870 bool AnswerOK,AnswerError; //if last part is OK or ERROR
1874 /* In 9210 first answer start with different, random bytes.
1875 Here we try to find first AT to find start byte */
1876 for (i=0;i<MessageLength-1;i++) {
1877 if (strncmp("AT",MessageBuffer+i,2)==0) {
1884 if (strncmp("ERROR\r",MessageBuffer+(MessageLength-6),6)==0) AnswerError=true;
1887 if (strncmp("OK\r",MessageBuffer+(MessageLength-3),3)==0) AnswerOK=true;
1892 if (ATRepliesOK[i].ReplyFunction==NULL) break;
1893 if (strncmp(ATRepliesOK[i].ReplyString,MessageBuffer+start,
1894 strlen(ATRepliesOK[i].ReplyString))==0) {
1895 ATRepliesOK[i].ReplyFunction(MessageLength-start,MessageBuffer+start,MessageType);
1902 if (ATRepliesOK[i].ReplyFunction==NULL)
1903 fprintf(stdout,_("Message: unknown AT command\n"));
1906 if (strncmp("AT\r",MessageBuffer+start,3)==0) {
1908 fprintf(stdout, _("Message: used for setting DLR3 to FBUS - part 1 OK\n"));
1910 CurrentGetHWError=GE_NONE;
1912 if (strncmp("AT&F\r",MessageBuffer+start,5)==0) {
1914 fprintf(stdout, _("Message: used for setting DLR3 to FBUS - part 2 OK\n"));
1916 CurrentGetHWError=GE_NONE;
1918 if (strncmp("AT*NOKIAFBUS\r",MessageBuffer+start,13)==0) {
1920 fprintf(stdout, _("Message: Setting DLR3 to FBUS - part 3 OK\n"));
1922 CurrentGetHWError=GE_NONE;
1927 if (strncmp("AT*NOKIAFBUS\r",MessageBuffer+start,13)==0) {
1929 fprintf(stdout, _("Message: Setting DLR3 to FBUS - part 3 ERROR\n"));
1932 CurrentGetHWError=GE_INTERNALERROR;