⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libsms_modem.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/*SMS Server ToolsCopyright (C) 2000 Stefan FringsThis program is free software unless you got it under another license directlyfrom the author. You can redistribute it and/or modify it under the terms ofthe GNU General Public License as published by the Free Software Foundation.Either version 2 of the License, or (at your option) any later version.http://www.isis.de/members/~s.fringsmailto:s.frings@mail.isis.de */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <strings.h>#include <errno.h>#include <termios.h>#include <stdio.h>#include <unistd.h>#include <syslog.h>#include <sys/ioctl.h>#ifdef __sun#include <sys/filio.h>#endif#include "libsms_modem.h"#include "../../dprint.h"#define  MAX_BUF        2048#define  CDS_HDR        "\r\n+CDS:"#define  CDS_HDR_LEN    (strlen(CDS_HDR))#define optz(_n,_l)     (buf+buf_len-(((_n)+(_l)>buf_len)?buf_len:(_n)+(_l)))/* global variables */int         sms_report_type;cds_report  cds_report_func;int put_command( struct modem *mdm, char* cmd, int cmd_len, char* answer,											int max, int timeout,char* exp_end){	static char buf[MAX_BUF];	static int  buf_len = 0;	char* pos;	char* foo;	char* ptr;	char* to_move;	char* answer_s;	char* answer_e;	int   timeoutcounter;	int   available;	int   status;	int   exp_end_len;	int   n;	/* check if fd is "clean" for reading */	timeoutcounter = 0;	ioctl(mdm->fd,TIOCMGET,&status);	while (!(status & TIOCM_CTS))	{		usleep( READ_SLEEP );		timeoutcounter++;		ioctl(mdm->fd,TIOCMGET,&status);		if (timeoutcounter>=timeout) {			LOG(L_INFO,"INFO:put_command: Modem is not clear to send\n");			return 0;		}	}#ifdef SHOW_SMS_MODEM_COMMAND	DBG("DEBUG: put_command: -<%d>-->[%.*s] \n",cmd_len,cmd_len,cmd);#endif	/* send the command to the modem */	write(mdm->fd,cmd,cmd_len);	tcdrain(mdm->fd);	/* read from the modem */	exp_end_len = exp_end?strlen(exp_end):0;	answer_s = buf;	answer_e = 0;	to_move = 0;	do	{		/* try to read some bytes */		ioctl(mdm->fd,FIONREAD,&available);		/* how many bytes are available to read? */		if (available<1)  /* if 0 then wait a little bit and retry */		{			usleep( READ_SLEEP );			timeoutcounter++;			ioctl(mdm->fd,FIONREAD,&available);		}		if (available>0)		{			/* How many bytes do I want to read maximum?			Not more than buffer size. And how many bytes are available? */			n = (available>MAX_BUF-buf_len-1)?MAX_BUF-buf_len-1:available;			/* read data */			n = read( mdm->fd, buf+buf_len, n);			if (n<0) {				LOG(L_ERR,"ERROR:put_command: error reading from modem: %s\n",					strerror(errno));				goto error;			}			if (n) {				buf_len += n;				buf[buf_len] = 0;				//DBG("DEBUG:put_commnad: read = [%s]\n",buf+buf_len-n);				foo = pos = 0;				if ( (!exp_end && ((pos=strstr(optz(n,4),"OK\r\n"))				|| (foo=strstr(optz(n,5),"ERROR"))))				|| (exp_end && (pos=strstr(optz(n,exp_end_len),exp_end)) )) {					/* we found the end */					//DBG("DEBUG:put_commnad: end found = %s\n",					//	(foo?"ERROR":(exp_end?exp_end:"OK")));					/* for ERROR we still have to read EOL */					if (!foo || (foo=strstr(foo+5,"\r\n"))) {						answer_e = foo?foo+2:(pos+(exp_end?exp_end_len:4));						timeoutcounter = timeout;					}				}			}		}	/* repeat until timout */	}while (timeoutcounter<timeout);	if (!answer_e)		answer_e = buf+buf_len;	/* CDS report is activ? */	if (sms_report_type==CDS_REPORT) {		to_move = 0;		ptr = buf;		/* do we have a CDS reply inside? */		while ( (pos=strstr(ptr,CDS_HDR)) ) {			if (pos!=ptr) {  /* here we have the command response */				answer_s = ptr;			}			/* look for the end of CDS response */			ptr = pos+CDS_HDR_LEN;			for( n=0 ; n<2&&(foo=strstr(ptr,"\r\n")) ; ptr=foo+2,n++ );			if (n<2) { /* we haven't read the entire CDS response */				DBG("DEBUG:put_command: CDS end not found!\n");				to_move = pos;				ptr = buf + buf_len;			}else{				/* process the CDS */				DBG("DEBUG:put_command:CDS=[%.*s]\n",(int)(ptr-pos),pos);				cds_report_func(mdm,pos,ptr-pos);			}		}		if ((*ptr)) {			answer_s = ptr;			ptr = answer_e;		}		if (ptr!=buf+buf_len)			to_move = ptr;	}	/* copy the response in answer buffer - as much as fits */	if (answer && max) {		n = max-1<answer_e-answer_s?max-1:answer_e-answer_s;		memcpy(answer,answer_s,n);		answer[n] = 0;	}	/* shift left the remaining data into the buffer - if needs */	if (sms_report_type==CDS_REPORT && to_move) {		buf_len = buf_len - (to_move-buf);		memcpy(buf,to_move,buf_len);		buf[buf_len] = 0;		DBG("DEBUG:put_commnad: buffer shifted left=[%d][%s]\n",buf_len,buf);	} else {		buf_len = 0;	}#ifdef SHOW_SMS_MODEM_COMMAND	DBG("DEBUG:put_command: <-[%s] \n",answer);#endif	return answer_e-answer_s;error:	return 0;}/* setup serial port */int setmodemparams( struct modem *mdm ){	struct termios newtio;	bzero(&newtio, sizeof(newtio));	newtio.c_cflag = mdm->baudrate | CRTSCTS | CS8 | CLOCAL | CREAD | O_NDELAY;	//uncomment next line to disable hardware handshake	//newtio.c_cflag &= ~CRTSCTS;	newtio.c_iflag = IGNPAR;	newtio.c_oflag = 0;	newtio.c_lflag = 0;	newtio.c_cc[VTIME]    = 1;	newtio.c_cc[VMIN]     = 0;	tcflush(mdm->fd, TCIOFLUSH);	tcsetattr(mdm->fd,TCSANOW,&newtio);	return 0;}int initmodem(struct modem *mdm, cds_report cds_report_f){	char command[100];	char answer[100];	int retries=0;	int success=0;	int clen=0;	int n;	LOG(L_INFO,"INFO:initmodem: init modem %s on %s.\n",mdm->name,mdm->device);	if (mdm->pin[0]) {		/* Checking if modem needs PIN */		put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);		if (strstr(answer,"+CPIN: SIM PIN")) {			LOG(L_INFO,"INFO:initmodem: Modem needs PIN, entering PIN...\n");			clen=sprintf(command,"AT+CPIN=\"%s\"\r",mdm->pin);			put_command(mdm,command,clen,answer,sizeof(answer),100,0);			put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);			if (!strstr(answer,"+CPIN: READY")) {				if (strstr(answer,"+CPIN: SIM PIN")) {					LOG(L_ERR,"ERROR:initmodem: Modem did not accept"						" this PIN\n");					goto error;				} else if (strstr(answer,"+CPIN: SIM PUK")) {					LOG(L_ERR,"ERROR:initmodem: YourPIN is locked!"						" Unlock it manually!\n");					goto error;				} else {					goto error;				}			}			LOG(L_INFO,"INFO:initmodem: PIN Ready!\n");			sleep(5);		}	}	if (mdm->mode==MODE_DIGICOM)		success=1;	else {		LOG(L_INFO,"INFO:initmodem: Checking if Modem is registered to"			" the network\n");		success=0;		retries=0;		do		{			retries++;			put_command(mdm,"AT+CREG?\r",9,answer,sizeof(answer),100,0);			if (strchr(answer,'1') )			{				LOG(L_INFO,"INFO:initmodem: Modem is registered to the"					" network\n");				success=1;			} else if (strchr(answer,'2')) {				// added by bogdan				LOG(L_WARN,"WARNING:initmodem: Modems seems to try to "					"reach the network! Let's wait a little bit\n");				retries--;				sleep(2);			} else if (strchr(answer,'5')) {				// added by Thomas Stoeckel				LOG(L_INFO,"INFO:initmodem: Modem is registered to a"					" roaming partner network\n");				success=1;			} else if (strstr(answer,"ERROR")) {				LOG(L_WARN,"WARNING:initmodem: Ignoring that modem does"					" not support +CREG command.\n");				success=1;			} else {				LOG(L_NOTICE,"NOTICE:initmodem: Waiting 2 sec. before"					" retrying\n");				sleep(2);			}		}while ((success==0)&&(retries<20));	}	if (success==0) {		LOG(L_ERR,"ERROR:initmodem: Modem is not registered to the network\n");		goto error;	}	for( n=0 ; n<2+2*(sms_report_type==CDS_REPORT) ; n++) {		/* build the command */		switch (n) {			case 0:				strcpy(command,"AT+CMGF=0\r");				command[8]+=(mdm->mode==MODE_ASCII || mdm->mode==MODE_DIGICOM);				clen = 10;				break;			case 1:				strcpy(command,"AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0\r");				clen = 33;				break;			case 2:				strcpy(command,"AT+CSMP=49,167,0,241\r");				clen = 21;				break;			case 3:				strcpy(command,"AT+CNMI=1,1,0,1,0\r");				clen = 18;				break;		}		/* send it to modem */		retries=0;		success=0;		do {			retries++;			/*querying the modem*/			put_command(mdm,command,clen,answer,sizeof(answer),100,0);			/*dealing with the answer*/			if (strstr(answer,"ERROR")) {				LOG(L_NOTICE,"NOTICE:initmodem: Waiting 1 sec. before to"					" retrying\n");				sleep(1);			} else				success=1;		}while ((success==0)&&(retries<3));		/* have we succeeded? */		if (success==0) {			LOG(L_ERR,"ERROR:initmodem: cmd [%.*s] returned ERROR\n",				clen-1,command);			goto error;		}	} /* end for */	if ( sms_report_type==CDS_REPORT && !cds_report_f) {		LOG(L_ERR,"ERROR:initmodem:no CDS_REPORT function given\n");		goto error;	}	cds_report_func = cds_report_f;	if (mdm->smsc[0]) {		LOG(L_INFO,"INFO:initmodem: Changing SMSC to \"%s\"\n",mdm->smsc);		setsmsc(mdm,mdm->smsc);	}	return 0;error:	return -1;}int checkmodem(struct modem *mdm){	char answer[500];	/* Checking if modem needs PIN */	put_command(mdm,"AT+CPIN?\r",9,answer,sizeof(answer),50,0);	if (!strstr(answer,"+CPIN: READY")) {		LOG(L_WARN,"WARNING:sms_checkmodem: modem wants the PIN again!\n");		goto reinit;	}	if (mdm->mode!=MODE_DIGICOM) {		put_command(mdm,"AT+CREG?\r",9,answer,sizeof(answer),100,0);		if (!strchr(answer,'1') ) {			LOG(L_WARN,"WARNING:sms_checkmodem: Modem is not registered to the"					" network\n");			goto reinit;		}	}	return 1;reinit:	LOG(L_WARN,"WARNING:sms_checkmodem: re -init the modem!!\n");	initmodem(mdm,cds_report_func);	return -1;}int setsmsc(struct modem *mdm, char *smsc){	char command[100];	char answer[50];	int  clen;	if (smsc && smsc[0]) {		clen=sprintf(command,"AT+CSCA=\"+%s\"\r",smsc);		put_command(mdm,command,clen,answer,sizeof(answer),50,0);	}	return 0;}int openmodem( struct modem *mdm){	mdm->fd = open(mdm->device, O_RDWR | O_NOCTTY );	if (mdm->fd <0)		return -1;	tcgetattr(mdm->fd,&(mdm->oldtio));	return 0;}int closemodem(struct modem *mdm){	tcsetattr(mdm->fd,TCSANOW,&(mdm->oldtio));	close(mdm->fd);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -