00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <sys/types.h>
00017 #include <sys/stat.h>
00018 #include <fcntl.h>
00019 #include <termios.h>
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023 #include <syslog.h>
00024 #include "../../ut.h"
00025 #include "libsms_charset.h"
00026 #include "libsms_modem.h"
00027 #include "libsms_sms.h"
00028 #include "sms_funcs.h"
00029
00030
00031
00032 #define set_date(_date,_Pointer) {\
00033 (_date)[0] = (_Pointer)[3];\
00034 (_date)[1] = (_Pointer)[2];\
00035 (_date)[2] = '-';\
00036 (_date)[3] = (_Pointer)[5];\
00037 (_date)[4] = (_Pointer)[4];\
00038 (_date)[5] = '-';\
00039 (_date)[6] = (_Pointer)[1];\
00040 (_date)[7] = (_Pointer)[0];}
00041
00042 #define set_time( _time , _Pointer) {\
00043 (_time)[0] = (_Pointer)[1];\
00044 (_time)[1] = (_Pointer)[0];\
00045 (_time)[2] = ':';\
00046 (_time)[3] = (_Pointer)[3];\
00047 (_time)[4] = (_Pointer)[2];\
00048 (_time)[5] = ':';\
00049 (_time)[6] = (_Pointer)[5];\
00050 (_time)[7] = (_Pointer)[4];}
00051
00052
00053
00054
00055
00056 static inline int octet2bin(char* octet)
00057 {
00058 int result=0;
00059
00060 if (octet[0]>57)
00061 result=octet[0]-55;
00062 else
00063 result=octet[0]-48;
00064 result=result<<4;
00065 if (octet[1]>57)
00066 result+=octet[1]-55;
00067 else
00068 result+=octet[1]-48;
00069 return result;
00070 }
00071
00072
00073
00074
00075
00076
00077 static int pdu2ascii(char* pdu, char* ascii)
00078 {
00079 int bitposition=0;
00080 int byteposition;
00081 int byteoffset;
00082 int charcounter;
00083 int bitcounter;
00084 int count;
00085 int octetcounter;
00086 char c;
00087 char binary[500];
00088
00089
00090 count=octet2bin(pdu);
00091 for (octetcounter=0; octetcounter<count; octetcounter++)
00092 binary[octetcounter]=octet2bin(pdu+(octetcounter<<1)+2);
00093
00094
00095 for (charcounter=0; charcounter<count; charcounter++) {
00096 c=0;
00097 for (bitcounter=0; bitcounter<7; bitcounter++) {
00098 byteposition=bitposition/8;
00099 byteoffset=bitposition%8;
00100 if (binary[byteposition]&(1<<byteoffset))
00101 c=c|128;
00102 bitposition++;
00103 c=(c>>1)&127;
00104 }
00105 if (1)
00106 ascii[charcounter]=sms2ascii(c);
00107 else if (c==0)
00108 ascii[charcounter]=183;
00109 else
00110 ascii[charcounter]=c;
00111 }
00112 ascii[count]=0;
00113 return count;
00114 }
00115
00116
00117
00118
00119 static int pdu2binary(char* pdu, char* binary)
00120 {
00121 int count;
00122 int octetcounter;
00123
00124 count=octet2bin(pdu);
00125 for (octetcounter=0; octetcounter<count; octetcounter++)
00126 binary[octetcounter]=octet2bin(pdu+(octetcounter<<1)+2);
00127 binary[count]=0;
00128 return count;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 static int fetchsms(struct modem *mdm, int sim, char* pdu)
00138 {
00139 char command[16];
00140 char answer[512];
00141 char* position;
00142 char* beginning;
00143 char* end;
00144 int foo,err;
00145 int clen;
00146
00147
00148 if (mdm->mode==MODE_DIGICOM) {
00149 put_command(mdm,"AT+CMGL=\"ALL\"\r",14,answer,
00150 sizeof(answer),200,0);
00151
00152 position=strstr(answer,"+CMGL: ");
00153 if (position) {
00154 end=position+7;
00155 while (*end<'9' && *end>'0') end++;
00156 if (end==position+7) {
00157 foo = str2s(position+7,end-position-7,&err);
00158 if (!err) {
00159 LM_DBG("Found a message at memory %i\n",foo);
00160 sim=foo;
00161 }
00162 position = 0;
00163 }
00164 position = 0;
00165 }
00166 } else {
00167 LM_DBG("Trying to get stored message %i\n",sim);
00168 clen=sprintf(command,"AT+CMGR=%i\r",sim);
00169 put_command(mdm,command,clen,answer,sizeof(answer),50,0);
00170
00171 position=strstr(answer,"+CMGR:");
00172 }
00173
00174
00175
00176 if (position==0)
00177 return 0;
00178 beginning=position+7;
00179
00180 if (strstr(answer,",,0\r"))
00181 return 0;
00182
00183
00184 for( end=beginning ; *end && *end!='\r' ; end++ );
00185 if ( !*end || end-beginning<4)
00186 return 0;
00187 for( end=end+1 ; *end && *end!='\r' ; end++ );
00188 if ( !*end || end-beginning<4)
00189 return 0;
00190
00191 *end=0;
00192 strcpy(pdu,beginning);
00193
00194 return sim;
00195 }
00196
00197
00198
00199
00200
00201 static void deletesms(struct modem *mdm, int sim) {
00202 char command[32];
00203 char answer[128];
00204 int clen;
00205
00206 LM_DBG("Deleting message %i !\n",sim);
00207 clen = sprintf(command,"AT+CMGD=%i\r",sim);
00208 put_command(mdm, command, clen, answer, sizeof(answer), 50, 0);
00209 }
00210
00211
00212
00213
00214
00215 int check_memory(struct modem *mdm, int flag)
00216 {
00217 char answer[500];
00218 char* posi;
00219 int laenge;
00220 int err,foo;
00221 int j, out;
00222
00223 for(out=0,j=0;!out && j<10; j++)
00224 {
00225 if (put_command(mdm,"AT+CPMS?\r",9,answer,sizeof(answer),50,0)
00226 && (posi=strstr(answer,"+CPMS:"))!=0 )
00227 {
00228
00229 if ( (posi=strchr(posi,','))!=0 ) {
00230 posi++;
00231 if ( (laenge=strcspn(posi,",\r"))!=0 ) {
00232 if (flag==USED_MEM ) {
00233 foo = str2s(posi,laenge,&err);
00234 if (err) {
00235 LM_ERR("unable to convert into integer used_memory from CPMS"
00236 " response\n");
00237 } else {
00238 return foo;
00239 }
00240 }
00241 posi+=laenge+1;
00242 if ( (laenge=strcspn(posi,",\r"))!=0 ) {
00243 foo = str2s(posi,laenge,&err);
00244 if (err) {
00245 LM_ERR("unable to convert into integer max_memory from CPMS"
00246 " response\n");
00247 } else {
00248 return foo;
00249 }
00250 }
00251 }
00252 }
00253 }
00254
00255 if (checkmodem(mdm)!=0) {
00256 LM_WARN("something happend with the modem -> was reinit -> let's retry\n");
00257 } else {
00258 LM_ERR("modem seems to be ok, but we had an error? I give up!\n");
00259 out = 1;
00260 }
00261 }
00262
00263 if (out==0)
00264 LM_ERR("modem does not respond after 10 retries, give up!\n");
00265
00266 return -1;
00267 }
00268
00269
00270
00271
00272
00273
00274 static int splitascii(struct modem *mdm, char *source, struct incame_sms *sms)
00275 {
00276 char* start;
00277 char* end;
00278
00279
00280 for( start=source ; *start && *start!='\r' ; start++ );
00281 if (!*start)
00282 return 1;
00283 start++;
00284 strcpy(sms->ascii,start);
00285
00286 start=strstr(source,"\",\"");
00287 if (start==0) {
00288 sms->userdatalength=strlen(sms->ascii);
00289 return 1;
00290 }
00291 start+=3;
00292 end=strstr(start,"\",");
00293 if (end==0) {
00294 sms->userdatalength=strlen(sms->ascii);
00295 return 1;
00296 }
00297 *end=0;
00298 strcpy(sms->sender,start);
00299
00300 start=end+3;
00301
00302 if (start[0]=='\"')
00303 start++;
00304 if (start[2]!='/') {
00305 end=strstr(start,"\",");
00306 if (end==0) {
00307 sms->userdatalength=strlen(sms->ascii);
00308 return 1;
00309 }
00310 *end=0;
00311 strcpy(sms->name,start);
00312 }
00313
00314 start=end+3;
00315 sprintf(sms->date,"%c%c-%c%c-%c%c",start[3],start[4],start[0],start[1],
00316 start[6],start[7]);
00317
00318 start+=9;
00319 sprintf(sms->time,"%c%c:%c%c:%c%c",start[0],start[1],start[3],start[4],
00320 start[7],start[7]);
00321 sms->userdatalength=strlen(sms->ascii);
00322 return 1;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 static int split_type_0( char* Pointer,struct incame_sms *sms)
00332 {
00333 int Length;
00334 int padding;
00335 int is_binary;
00336
00337 Length=octet2bin(Pointer);
00338 padding=Length%2;
00339 Pointer+=4;
00340 memcpy(sms->sender,Pointer,Length+padding);
00341 swapchars(sms->sender,Length+padding);
00342
00343 sms->sender[Length]=0;
00344 Pointer=Pointer+Length+padding+3;
00345 is_binary = ((Pointer[0] & 4)==4);
00346 Pointer++;
00347 set_date(sms->date,Pointer);
00348 Pointer=Pointer+6;
00349 set_time(sms->time,Pointer);
00350 Pointer=Pointer+8;
00351 if (is_binary)
00352 sms->userdatalength = pdu2binary(Pointer,sms->ascii);
00353 else
00354 sms->userdatalength = pdu2ascii(Pointer,sms->ascii);
00355 return 1;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364 static int split_type_2( char* position, struct incame_sms *sms)
00365 {
00366 int length;
00367 int padding;
00368 char *p;
00369
00370
00371 sms->sms_id = octet2bin(position);
00372 position+=2;
00373
00374 length=octet2bin(position);
00375 padding=length%2;
00376 position+=4;
00377 memcpy(sms->sender,position,length+padding);
00378 sms->sender[length]=0;
00379 swapchars(sms->sender,length);
00380
00381 position+=length+padding;
00382 set_date(sms->date,position);
00383 set_time(sms->time,position+6);
00384
00385 position+=14;
00386 p = sms->ascii + 2;
00387 set_date(p,position);
00388 *(p+DATE_LEN) = ' ';
00389 set_time(p+DATE_LEN+1,position+6);
00390
00391 position+=14;
00392 sms->ascii[0] = (unsigned char)octet2bin(position);
00393 sms->ascii[1] = ' ';
00394 sms->ascii[2+DATE_LEN+1+TIME_LEN] = 0;
00395
00396 sms->userdatalength=2+DATE_LEN+1+TIME_LEN;
00397 return 1;
00398 }
00399
00400
00401
00402
00403
00404
00405 static int splitpdu(struct modem *mdm, char* pdu, struct incame_sms *sms)
00406 {
00407 int Length;
00408 int Type;
00409 char* Pointer;
00410 char* start;
00411 char* end;
00412
00413
00414 start=strstr(pdu,"\",\"");
00415 if (start!=0) {
00416 start+=3;
00417 end=strstr(start,"\",");
00418 if (end!=0) {
00419 memcpy(sms->name,start,end-start);
00420 sms->name[end-start]=0;
00421 }
00422 } else
00423 end=pdu;
00424
00425
00426 for( start=end+1 ; *start && *start!='\r' ; start++ );
00427 if (!*start)
00428 return 0;
00429 pdu=++start;
00430
00431 while ( *pdu && (*pdu<=' '))
00432 pdu++;
00433 Pointer=pdu;
00434 if (mdm->mode!=MODE_OLD) {
00435
00436 Length=octet2bin(pdu)*2-2;
00437 if (Length>0) {
00438 Pointer=pdu+4;
00439 memcpy(sms->smsc,Pointer,Length);
00440 swapchars(sms->smsc,Length);
00441
00442 if (sms->smsc[Length-1]=='F')
00443 sms->smsc[Length-1]=0;
00444 else
00445 sms->smsc[Length] = 0;
00446 }
00447 Pointer=pdu+Length+4;
00448 }
00449
00450 Type=octet2bin(Pointer) & 3;
00451 Pointer+=2;
00452 if (Type==0) {
00453 sms->is_statusreport = 0;
00454 return split_type_0( Pointer, sms);
00455 } else if (Type==2) {
00456 sms->is_statusreport = 1;
00457 return split_type_2( Pointer, sms);
00458 }
00459
00460 return -1;
00461 }
00462
00463
00464
00465
00466 static inline int decode_pdu( struct modem *mdm, char *pdu, struct incame_sms *sms)
00467 {
00468 int ret;
00469
00470 memset( sms, 0, sizeof(struct incame_sms) );
00471
00472 if (mdm->mode==MODE_ASCII || mdm->mode==MODE_DIGICOM)
00473 ret = splitascii(mdm, pdu, sms);
00474 else
00475 ret = splitpdu(mdm, pdu, sms);
00476
00477 if (ret==-1) {
00478 LM_ERR("unable split pdu/ascii!\n");
00479 return -1;
00480 }
00481 return 1;
00482 }
00483
00484
00485
00486
00487 int getsms( struct incame_sms *sms, struct modem *mdm, int sim)
00488 {
00489 char pdu[512];
00490 int found;
00491 int ret;
00492
00493 found = fetchsms(mdm,sim,pdu);
00494 if ( !found ) {
00495 LM_ERR("unable to fetch sms %d!\n",sim);
00496 return -1;
00497 }
00498
00499
00500 ret = decode_pdu(mdm,pdu,sms);
00501
00502
00503 deletesms(mdm,found);
00504
00505 return ret;
00506 }
00507
00508
00509
00510
00511 int cds2sms(struct incame_sms *sms, struct modem *mdm, char *s, int s_len)
00512 {
00513 char *data;
00514 char *ptr;
00515 char tmp;
00516 int n;
00517
00518
00519 ptr = s;
00520 for ( n=0 ; n<2 && (ptr=strstr(ptr,"\r\n")) ; n++,ptr+=2 );
00521 if (n<2) {
00522 LM_ERR("failed to find pdu beginning in CDS!\n");
00523 goto error;
00524 }
00525 data = ptr;
00526
00527
00528 if (!(ptr=strstr(data,"\r\n"))) {
00529 LM_ERR("failed to find pdu end in CDS!\n");
00530 goto error;
00531 }
00532 tmp = ptr[0];
00533 ptr[0] = 0;
00534
00535
00536 n = decode_pdu(mdm,data-3,sms);
00537 ptr[0] = tmp;
00538 if (n==-1)
00539 goto error;
00540
00541 return 1;
00542 error:
00543 return -1;
00544 }
00545