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

📄 smsc_at.c

📁 gnu的专业网关smpp协议支持源代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * smsc_at.c - implement interface to wireless modems using AT commands * * Yann Muller, Nick Clarey - 3G Lab, 2001. *  * Ericsson code by Chris Blown 30/01/2001 - Hinterlands Aust. * * Make sure your kannel configuration file contains the following lines * to be able to use the AT SMSC: *     group = smsc *     smsc = at *     modemtype = wavecom | premicell | siemens | siemens-tc35 | falcom | *                 nokiaphone | ericsson *     device = /dev/xxx  */#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <ctype.h>#include <termios.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <sys/ioctl.h>#include <time.h>#include "gwlib/gwlib.h"#include "gwlib/charset.h"#include "smsc.h"#include "smsc_p.h"#include "sms.h"#ifndef CRTSCTS#define CRTSCTS 0#endif/* The number of times to attempt to send a message should sending fail */#define RETRY_SEND 3/****************************************************************************** * Prototypes for private functions */static int at_data_read(int fd, Octstr *ostr);static int send_modem_command(int fd, char *cmd, int multiline);static int pdu_extract(SMSCenter *smsc, Octstr **ostr);static Msg *pdu_decode(Octstr *data);static Msg *pdu_decode_deliver_sm(Octstr *data);static int pdu_encode(Msg *msg, unsigned char *pdu, SMSCenter *smsc);static Octstr *convertpdu(Octstr *pdutext);static int hexchar(int hexc);static int encode7bituncompressed(Octstr *input, unsigned char *encoded, int offset);static int encode8bituncompressed(Octstr *input, unsigned char *encoded);static void decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset);static int numtext(int num);/****************************************************************************** * Types of GSM modems (as used in kannel.conf: at_type=xxxx) */#define WAVECOM         "wavecom"#define PREMICELL       "premicell"#define SIEMENS         "siemens"#define SIEMENS_TC35	"siemens-tc35"#define FALCOM          "falcom"#define NOKIAPHONE      "nokiaphone"#define ERICSSON        "ericsson"/****************************************************************************** * Message types defines */#define AT_DELIVER_SM   0#define AT_SUBMIT_SM    1/****************************************************************************** * type of phone number defines */#define PNT_UNKNOWN     0#define PNT_INTER       1#define PNT_NATIONAL    2/****************************************************************************** * Open the connection * * returns the file descriptor (fd) if ok, -1 on failure */static int at_open_connection(SMSCenter *smsc) {        int fd = -1;        struct termios tios;        int ret;                fd = open(smsc->at_serialdevice, O_RDWR|O_NONBLOCK|O_NOCTTY);        if(fd == -1) {                error(errno, "at_open_data_link: error opening the character device <%s>",                      smsc->at_serialdevice);                return -1;        }        tcgetattr(fd, &tios);        if((strcmp(smsc->at_modemtype, SIEMENS) == 0) 	   || (strcmp(smsc->at_modemtype, SIEMENS_TC35) == 0)           || (strcmp(smsc->at_modemtype, NOKIAPHONE) == 0)) {                cfsetospeed(&tios, B19200);  /* check radio pad parameter*/                cfsetispeed(&tios, B19200);        } else {                cfsetospeed(&tios, B9600);  /* check radio pad parameter*/                cfsetispeed(&tios, B9600);        }        kannel_cfmakeraw(&tios);        /* parameters:         * IGNBRK, IGNPAR: ignore BREAK and PARITY errors         * INPCK: enable parity check         * CSIZE: for CS8         * HUPCL: hang up on close         * CREAD: enable receiver         * CRTSCTS: enable flow control */        tios.c_iflag |= IGNBRK | IGNPAR | INPCK;        tios.c_cflag |= CSIZE | HUPCL | CREAD | CRTSCTS;        if (strcmp(smsc->at_modemtype, NOKIAPHONE) == 0)                tios.c_cflag ^= PARODD;        tios.c_cflag |=CS8;        ret = tcsetattr(fd, TCSANOW, &tios); /* apply changes now */        if(ret == -1){                error(errno,"at_data_link: fail to set termios attribute");                goto error;        }        tcflush(fd, TCIOFLUSH);        return fd;   error:        return -1;}/****************************************************************************** * Open the (Virtual) SMSCenter */SMSCenter *at_open(char *serialdevice, char *modemtype, char *pin,                   char *validityperiod, int alt_dcs) {        SMSCenter *smsc;        char setpin[20];        int ret;                smsc = smscenter_construct();        if(smsc == NULL)                goto error;        smsc->type = SMSC_TYPE_AT;        smsc->at_serialdevice = gw_strdup(serialdevice);        if (validityperiod != NULL)                smsc->at_validityperiod = gw_strdup(validityperiod);        smsc->at_modemtype = gw_strdup(modemtype);        if(pin)                smsc->at_pin = gw_strdup(pin);        smsc->at_received = list_create();        smsc->at_inbuffer = octstr_create("");	smsc->at_alt_dcs = alt_dcs;                smsc->at_fd = at_open_connection(smsc);        if (smsc->at_fd < 0)                goto error;        /* Nokia 7110 and 6210 need some time between opening         * the connection and sending the first AT commands */        if (strcmp(smsc->at_modemtype, NOKIAPHONE) == 0)                 sleep(1);	/* lets initialize the modem to a safe state */        send_modem_command(smsc->at_fd, "AT", 0);        send_modem_command(smsc->at_fd, "AT&F", 0);        send_modem_command(smsc->at_fd, "AT", 0);	        /* Turn Echo off on the modem: we don't need it */        if(send_modem_command(smsc->at_fd, "ATE0", 0) == -1) 	{ 		/* ok that was the first command we tried. */                goto error;	}	/* Let's collect some information from modem */	if(send_modem_command(smsc->at_fd, "ATI", 0) == -1)	    goto error;	sleep(1);	if(send_modem_command(smsc->at_fd, "ATI1", 0) == -1)	    goto error;	sleep(1);	if(send_modem_command(smsc->at_fd, "ATI2", 0) == -1)	    goto error;	sleep(1);	if(send_modem_command(smsc->at_fd, "ATI3", 0) == -1)	    goto error;	sleep(1);	if(send_modem_command(smsc->at_fd, "ATI4", 0) == -1)	    goto error;	sleep(1);        /* Check does the modem require a PIN and, if so, send it         * This is not supported by the Nokia Premicell */        if(strcmp(smsc->at_modemtype, PREMICELL) != 0) {                ret = send_modem_command(smsc->at_fd, "AT+CPIN?", 0);                 if(ret == -1)                        goto error;                if(ret == -2) {                        if(smsc->at_pin == NULL)                                goto error;                        sprintf(setpin, "AT+CPIN=%s", smsc->at_pin);                        if(send_modem_command(smsc->at_fd, setpin, 0) == -1)                                goto error;                }        }        /* Set the modem to PDU mode and autodisplay of new messages */        if(send_modem_command(smsc->at_fd, "AT+CMGF=0", 0) == -1)                goto error;	sleep(1);        /* The Ericsson GM12 modem requires different new message          * indication options from the other modems */         if(strcmp(smsc->at_modemtype, ERICSSON) == 0) {                if(send_modem_command(smsc->at_fd, "AT+CNMI=3,2,0,0", 0) == -1)                        goto error;        }        else if(strcmp(smsc->at_modemtype, SIEMENS_TC35) == 0) {                if(send_modem_command(smsc->at_fd, "AT+CSMS=1", 0) == -1)                        goto error;                if(send_modem_command(smsc->at_fd, "AT+CNMI=1,2,0,0,1",0)== -1)			goto error;	}        else {                if(send_modem_command(smsc->at_fd, "AT+CNMI=1,2,0,0,0", 0) == -1)                        goto error;        }                        sprintf(smsc->name, "AT: %s", smsc->at_serialdevice);                 info(0, "AT SMSC successfully opened.");        return smsc;   error:        return NULL;}/****************************************************************************** * Re-Open the AT (Virtual) SMSCenter */int at_reopen(SMSCenter *smsc) {        /* Do we really have an open connection to start with? */        if (smsc->at_fd == -1) {                info(0, "trying to close already closed AT, ignoring");        }        /* If we do, then try to close the file descriptor */        else if (close(smsc->at_fd) == -1) {                /* This situation could occur as a result of errors not being reported until                   the serial connection is closed. Supposing we do get here, we                   should reset the at_fd value to -1 to stop infinitely retrying the close. We                   also need to printing out the error message reported, just in case it's                   significant.                */                smsc->at_fd = -1;                error(errno, "Attempt to close connection to modem `%s' failed. Forcing reset.",                      smsc->at_serialdevice);        }        /* Reopen the connection. Note that the at_open_connection call returns           a file descriptor, which we should set in the smsc structure */        smsc->at_fd = at_open_connection(smsc);        /* Supposing that failed */        if (smsc->at_fd == -1) {                error(0, "Attempt to open connection to modem '%s' failed.",                      smsc->at_serialdevice);                /* Give up */                return -1;        }        /* Report success */        return 0;}/****************************************************************************** * Close the SMSCenter */int at_close(SMSCenter *smsc) {        /* Do we really have an open connection to start with? */        if (smsc->at_fd == -1) {                info(0, "trying to close already closed AT, ignoring");        }        /* If we do, then try to close the file descriptor */        else if (close(smsc->at_fd) == -1) {                error(errno, "Attempt to close connection to modem `%s' failed. Forcing reset.",                      smsc->at_serialdevice);        }                /* Our file descriptor can now be safely declared closed */        smsc->at_fd = -1;                /* Deallocate any miscellany */        smscenter_destruct(smsc);        /* Report success */        return 0;}/****************************************************************************** * Check for pending messages */int at_pending_smsmessage(SMSCenter *smsc) {        Octstr *pdu = NULL;        int ret=0;        Msg *msg = NULL;        /* Receive raw data */        ret = at_data_read(smsc->at_fd, smsc->at_inbuffer);        if(ret == -1) {                ret = at_reopen(smsc);                if(ret == -1) goto error;                return 0;        }         ret = 0;        while( pdu_extract(smsc, &pdu) == 1) {                msg = pdu_decode(pdu);                if(msg != NULL) {                        list_append(smsc->at_received, (void *)msg);                        ret = 1;                }                octstr_destroy(pdu);        }        if(list_len(smsc->at_received) > 0)                ret = 1;        return ret;  error:        error(errno,"at_pending message: device error");        return -1;}/****************************************************************************** * Send a message */int at_submit_msg(SMSCenter *smsc, Msg *msg) {        unsigned char command[500], pdu[500];        int ret = -1;         char sc[3];        int retries = RETRY_SEND;        /* Some modem types need a '00' prepended to the PDU         * to indicate to use the default SC.         * NB: This extra padding is not counted in the CMGS byte count */        sc[0] = '\0';        if((strcmp(smsc->at_modemtype, WAVECOM ) == 0) ||            (strcmp(smsc->at_modemtype, SIEMENS ) == 0) ||           (strcmp(smsc->at_modemtype, SIEMENS_TC35 ) == 0) ||

⌨️ 快捷键说明

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