00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <fcntl.h>
00018 #include <string.h>
00019 #include <strings.h>
00020 #include <errno.h>
00021 #include <termios.h>
00022 #include <stdio.h>
00023 #include <unistd.h>
00024 #include <syslog.h>
00025 #include <sys/ioctl.h>
00026 #ifdef __sun
00027 #include <sys/filio.h>
00028 #endif
00029 #include "libsms_modem.h"
00030 #include "../../dprint.h"
00031
00032 #define MAX_BUF 2048
00033 #define CDS_HDR "\r\n+CDS:"
00034 #define CDS_HDR_LEN (strlen(CDS_HDR))
00035 #define optz(_n,_l) (buf+buf_len-(((_n)+(_l)>buf_len)?buf_len:(_n)+(_l)))
00036
00037
00038 int sms_report_type;
00039 cds_report cds_report_func;
00040
00041
00042
00043 int put_command( struct modem *mdm, char* cmd, int cmd_len, char* answer,
00044 int max, int timeout,char* exp_end)
00045 {
00046 static char buf[MAX_BUF];
00047 static int buf_len = 0;
00048 char* pos;
00049 char* foo;
00050 char* ptr;
00051 char* to_move;
00052 char* answer_s;
00053 char* answer_e;
00054 int timeoutcounter;
00055 int available;
00056 int status;
00057 int exp_end_len;
00058 int n;
00059
00060
00061 timeoutcounter = 0;
00062 ioctl(mdm->fd,TIOCMGET,&status);
00063 while (!(status & TIOCM_CTS))
00064 {
00065 usleep( READ_SLEEP );
00066 timeoutcounter++;
00067 ioctl(mdm->fd,TIOCMGET,&status);
00068 if (timeoutcounter>=timeout) {
00069 LM_INFO("Modem is not clear to send\n");
00070 return 0;
00071 }
00072 }
00073 #ifdef SHOW_SMS_MODEM_COMMAND
00074 LM_DBG("<--<%d>-->[%.*s] \n",cmd_len,cmd_len,cmd);
00075 #endif
00076
00077 write(mdm->fd,cmd,cmd_len);
00078 tcdrain(mdm->fd);
00079
00080
00081 exp_end_len = exp_end?strlen(exp_end):0;
00082 answer_s = buf;
00083 answer_e = 0;
00084 to_move = 0;
00085 do
00086 {
00087
00088 ioctl(mdm->fd,FIONREAD,&available);
00089
00090 if (available<1)
00091 {
00092 usleep( READ_SLEEP );
00093 timeoutcounter++;
00094 ioctl(mdm->fd,FIONREAD,&available);
00095 }
00096 if (available>0)
00097 {
00098
00099
00100 n = (available>MAX_BUF-buf_len-1)?MAX_BUF-buf_len-1:available;
00101
00102 n = read( mdm->fd, buf+buf_len, n);
00103 if (n<0) {
00104 LM_ERR("error reading from modem: %s\n",
00105 strerror(errno));
00106 goto error;
00107 }
00108 if (n) {
00109 buf_len += n;
00110 buf[buf_len] = 0;
00111
00112 foo = pos = 0;
00113 if ( (!exp_end && ((pos=strstr(optz(n,4),"OK\r\n"))
00114 || (foo=strstr(optz(n,5),"ERROR"))))
00115 || (exp_end && (pos=strstr(optz(n,exp_end_len),exp_end)) )) {
00116
00117
00118
00119
00120 if (!foo || (foo=strstr(foo+5,"\r\n"))) {
00121 answer_e = foo?foo+2:(pos+(exp_end?exp_end_len:4));
00122 timeoutcounter = timeout;
00123 }
00124 }
00125 }
00126 }
00127
00128 }while (timeoutcounter<timeout);
00129
00130 if (!answer_e)
00131 answer_e = buf+buf_len;
00132
00133
00134 if (sms_report_type==CDS_REPORT) {
00135 to_move = 0;
00136 ptr = buf;
00137
00138 while ( (pos=strstr(ptr,CDS_HDR)) ) {
00139 if (pos!=ptr) {
00140 answer_s = ptr;
00141 }
00142
00143 ptr = pos+CDS_HDR_LEN;
00144 for( n=0 ; n<2&&(foo=strstr(ptr,"\r\n")) ; ptr=foo+2,n++ );
00145 if (n<2) {
00146 LM_DBG("CDS end not found!\n");
00147 to_move = pos;
00148 ptr = buf + buf_len;
00149 }else{
00150
00151 LM_DBG("CDS=[%.*s]\n",(int)(ptr-pos),pos);
00152 cds_report_func(mdm,pos,ptr-pos);
00153 }
00154 }
00155 if ((*ptr)) {
00156 answer_s = ptr;
00157 ptr = answer_e;
00158 }
00159 if (ptr!=buf+buf_len)
00160 to_move = ptr;
00161 }
00162
00163
00164 if (answer && max) {
00165 n = max-1<answer_e-answer_s?max-1:answer_e-answer_s;
00166 memcpy(answer,answer_s,n);
00167 answer[n] = 0;
00168 }
00169
00170 if (sms_report_type==CDS_REPORT && to_move) {
00171 buf_len = buf_len - (to_move-buf);
00172 memcpy(buf,to_move,buf_len);
00173 buf[buf_len] = 0;
00174 LM_DBG("buffer shifted left=[%d][%s]\n",buf_len,buf);
00175 } else {
00176 buf_len = 0;
00177 }
00178
00179 #ifdef SHOW_SMS_MODEM_COMMAND
00180 LM_DBG("<-[%s] \n",answer);
00181 #endif
00182 return answer_e-answer_s;
00183
00184 error:
00185 return 0;
00186 }
00187
00188
00189
00190
00191
00192 int setmodemparams( struct modem *mdm )
00193 {
00194 struct termios newtio;
00195
00196 bzero(&newtio, sizeof(newtio));
00197 newtio.c_cflag = mdm->baudrate | CRTSCTS | CS8 | CLOCAL | CREAD | O_NDELAY;
00198
00199
00200 newtio.c_iflag = IGNPAR;
00201 newtio.c_oflag = 0;
00202 newtio.c_lflag = 0;
00203 newtio.c_cc[VTIME] = 1;
00204 newtio.c_cc[VMIN] = 0;
00205 tcflush(mdm->fd, TCIOFLUSH);
00206 tcsetattr(mdm->fd,TCSANOW,&newtio);
00207 return 0;
00208 }
00209
00210
00211
00212
00213 int initmodem(struct modem *mdm, cds_report cds_report_f)
00214 {
00215 char command[100];
00216 char answer[100];
00217 int retries=0;
00218 int success=0;
00219 int clen=0;
00220 int n;
00221
00222 LM_INFO("init modem %s on %s.\n",mdm->name,mdm->device);
00223
00224 if (mdm->pin[0]) {
00225
00226 put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);
00227 if (strstr(answer,"+CPIN: SIM PIN")) {
00228 LM_INFO("Modem needs PIN, entering PIN...\n");
00229 clen=sprintf(command,"AT+CPIN=\"%s\"\r",mdm->pin);
00230 put_command(mdm,command,clen,answer,sizeof(answer),100,0);
00231 put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);
00232 if (!strstr(answer,"+CPIN: READY")) {
00233 if (strstr(answer,"+CPIN: SIM PIN")) {
00234 LM_ERR("Modem did not accept this PIN\n");
00235 goto error;
00236 } else if (strstr(answer,"+CPIN: SIM PUK")) {
00237 LM_ERR("YourPIN is locked! Unlock it manually!\n");
00238 goto error;
00239 } else {
00240 goto error;
00241 }
00242 }
00243 LM_INFO("INFO:initmodem: PIN Ready!\n");
00244 sleep(5);
00245 }
00246 }
00247
00248 if (mdm->mode==MODE_DIGICOM)
00249 success=1;
00250 else {
00251 LM_INFO("INFO:initmodem: Checking if Modem is registered to"
00252 " the network\n");
00253 success=0;
00254 retries=0;
00255 do
00256 {
00257 retries++;
00258 put_command(mdm,"AT+CREG?\r",9,answer,sizeof(answer),100,0);
00259 if (strchr(answer,'1') )
00260 {
00261 LM_INFO("INFO:initmodem: Modem is registered to the"
00262 " network\n");
00263 success=1;
00264 } else if (strchr(answer,'2')) {
00265
00266 LM_WARN("Modems seems to try to reach the network!"
00267 " Let's wait a little bit\n");
00268 retries--;
00269 sleep(2);
00270 } else if (strchr(answer,'5')) {
00271
00272 LM_INFO("Modem is registered to a roaming partner network\n");
00273 success=1;
00274 } else if (strstr(answer,"ERROR")) {
00275 LM_WARN("Ignoring that modem does not support +CREG command\n");
00276 success=1;
00277 } else {
00278 LM_NOTICE("NOTICE:initmodem: Waiting 2 sec. before retrying\n");
00279 sleep(2);
00280 }
00281 }while ((success==0)&&(retries<20));
00282 }
00283
00284 if (success==0) {
00285 LM_ERR("Modem is not registered to the network\n");
00286 goto error;
00287 }
00288
00289 for( n=0 ; n<2+2*(sms_report_type==CDS_REPORT) ; n++) {
00290
00291 switch (n) {
00292 case 0:
00293 strcpy(command,"AT+CMGF=0\r");
00294 command[8]+=(mdm->mode==MODE_ASCII || mdm->mode==MODE_DIGICOM);
00295 clen = 10;
00296 break;
00297 case 1:
00298 strcpy(command,"AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0\r");
00299 clen = 33;
00300 break;
00301 case 2:
00302 strcpy(command,"AT+CSMP=49,167,0,241\r");
00303 clen = 21;
00304 break;
00305 case 3:
00306 strcpy(command,"AT+CNMI=1,1,0,1,0\r");
00307 clen = 18;
00308 break;
00309 }
00310
00311 retries=0;
00312 success=0;
00313 do {
00314 retries++;
00315
00316 put_command(mdm,command,clen,answer,sizeof(answer),100,0);
00317
00318 if (strstr(answer,"ERROR")) {
00319 LM_NOTICE("Waiting 1 sec. before to retrying\n");
00320 sleep(1);
00321 } else
00322 success=1;
00323 }while ((success==0)&&(retries<3));
00324
00325 if (success==0) {
00326 LM_ERR("cmd [%.*s] returned ERROR\n", clen-1,command);
00327 goto error;
00328 }
00329 }
00330
00331 if ( sms_report_type==CDS_REPORT && !cds_report_f) {
00332 LM_ERR("no CDS_REPORT function given\n");
00333 goto error;
00334 }
00335 cds_report_func = cds_report_f;
00336
00337 if (mdm->smsc[0]) {
00338 LM_INFO("Changing SMSC to \"%s\"\n",mdm->smsc);
00339 setsmsc(mdm,mdm->smsc);
00340 }
00341
00342
00343
00344 return 0;
00345 error:
00346 return -1;
00347 }
00348
00349
00350
00351
00352 int checkmodem(struct modem *mdm)
00353 {
00354 char answer[500];
00355
00356
00357 put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);
00358 if (!strstr(answer,"+CPIN: READY")) {
00359 LM_WARN("modem wants the PIN again!\n");
00360 goto reinit;
00361 }
00362
00363 if (mdm->mode!=MODE_DIGICOM) {
00364 put_command(mdm,"AT+CREG?\r",9,answer,sizeof(answer),100,0);
00365 if (!strchr(answer,'1') ) {
00366 LM_WARN("Modem is not registered to the"
00367 " network\n");
00368 goto reinit;
00369 }
00370 }
00371
00372 return 1;
00373 reinit:
00374 LM_WARN("re -init the modem!!\n");
00375 initmodem(mdm,cds_report_func);
00376 return -1;
00377 }
00378
00379
00380
00381
00382 int setsmsc(struct modem *mdm, char *smsc)
00383 {
00384 char command[100];
00385 char answer[50];
00386 int clen;
00387
00388 if (smsc && smsc[0]) {
00389 clen=sprintf(command,"AT+CSCA=\"+%s\"\r",smsc);
00390 put_command(mdm,command,clen,answer,sizeof(answer),50,0);
00391 }
00392 return 0;
00393 }
00394
00395
00396
00397
00398 int openmodem( struct modem *mdm)
00399 {
00400 mdm->fd = open(mdm->device, O_RDWR | O_NOCTTY );
00401 if (mdm->fd <0)
00402 return -1;
00403
00404 tcgetattr(mdm->fd,&(mdm->oldtio));
00405 return 0;
00406 }
00407
00408
00409
00410
00411 int closemodem(struct modem *mdm)
00412 {
00413 tcsetattr(mdm->fd,TCSANOW,&(mdm->oldtio));
00414 close(mdm->fd);
00415 return 0;
00416 }
00417