📄 smsc_at.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * smsc_at.c * * New driver for serial connected AT based * devices. * 4.9.2001 * Andreas Fink <afink@smsrelay.com> * */#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 <math.h>#include "gwlib/gwlib.h"#include "gwlib/charset.h"#include "smscconn.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "msg.h"#include "sms.h"#include "dlr.h"#include "smsc_at.h"static int at2_open_device1(PrivAT2data *privdata){ info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name)); if (privdata->fd > 0) { warning(0, "AT2[%s]: trying to open device with not closed device!!! Please report!!!", octstr_get_cstr(privdata->name)); at2_close_device(privdata); } privdata->fd = open(octstr_get_cstr(privdata->device), O_RDWR | O_NONBLOCK | O_NOCTTY); if (privdata->fd == -1) { error(errno, "AT2[%s]: open failed! ERRNO=%d", octstr_get_cstr(privdata->name), errno); privdata->fd = -1; return -1; } debug("bb.smsc.at2", 0, "AT2[%s]: device opened", octstr_get_cstr(privdata->name)); return 0;}int at2_open_device(PrivAT2data *privdata){ struct termios tios; int ret; if ((ret = at2_open_device1(privdata)) != 0) return ret; tcgetattr(privdata->fd, &tios); kannel_cfmakeraw(&tios); tios.c_iflag |= IGNBRK; /* ignore break & parity errors */ tios.c_iflag &= ~INPCK; /* INPCK: disable parity check */ tios.c_cflag |= HUPCL; /* hangup on close */ tios.c_cflag |= CREAD; /* enable receiver */ tios.c_cflag &= ~CSIZE; /* set to 8 bit */ tios.c_cflag |= CS8; tios.c_oflag &= ~ONLCR; /* no NL to CR-NL mapping outgoing */ tios.c_iflag |= IGNPAR; /* ignore parity */ tios.c_iflag &= ~INPCK; tios.c_cflag |= CRTSCTS; /* enable hardware flow control */ tios.c_cc[VSUSP] = 0; /* otherwhise we can not send CTRL Z */ /* if ( ModemTypes[privdata->modemid].enable_parity ) tios.c_cflag ^= PARODD; */ ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */ if (ret == -1) { error(errno, "AT2[%s]: at_data_link: fail to set termios attribute", octstr_get_cstr(privdata->name)); } tcflush(privdata->fd, TCIOFLUSH); /* * Nokia 7110 and 6210 need some time between opening * the connection and sending the first AT commands */ if (privdata->modem->need_sleep) sleep(1); debug("bb.smsc.at2", 0, "AT2[%s]: device opened", octstr_get_cstr(privdata->name)); return 0;}void at2_close_device(PrivAT2data *privdata){ info(0, "AT2[%s]: closing device", octstr_get_cstr(privdata->name)); close(privdata->fd); privdata->fd = -1; privdata->pin_ready = 0; privdata->phase2plus = 0; if (privdata->ilb != NULL) octstr_destroy(privdata->ilb); privdata->ilb = octstr_create("");}void at2_read_buffer(PrivAT2data *privdata){ char buf[MAX_READ + 1]; int s, ret; int count; fd_set read_fd; struct timeval tv; if (privdata->fd == -1) { error(errno, "AT2[%s]: at2_read_buffer: fd = -1. Can not read", octstr_get_cstr(privdata->name)); return ; } count = MAX_READ;#ifdef SSIZE_MAX if (count > SSIZE_MAX) count = SSIZE_MAX;#endif tv.tv_sec = 0; tv.tv_usec = 1000; FD_ZERO(&read_fd); FD_SET(privdata->fd, &read_fd); ret = select(privdata->fd + 1, &read_fd, NULL, NULL, &tv); if (ret == -1) { if (!(errno == EINTR || errno == EAGAIN)) error(errno, "AT2[%s]: error on select", octstr_get_cstr(privdata->name)); return; } s = read(privdata->fd, buf, count); if (s > 0) octstr_append_data(privdata->ilb, buf, s);}Octstr *at2_wait_line(PrivAT2data *privdata, time_t timeout, int gt_flag){ Octstr *line; time_t end_time; time_t cur_time; time(&end_time); if (timeout == 0) timeout = 3; end_time += timeout; if (privdata->lines != NULL) octstr_destroy(privdata->lines); privdata->lines = octstr_create(""); while (time(&cur_time) <= end_time) { line = at2_read_line(privdata, gt_flag); if (line) return line; } return NULL;}Octstr *at2_read_line(PrivAT2data *privdata, int gt_flag){ int eol; int gtloc; int len; Octstr *line; Octstr *buf2; int i; at2_read_buffer(privdata); len = octstr_len(privdata->ilb); if (len == 0) return NULL; if (gt_flag) /* looking for > if needed */ gtloc = octstr_search_char(privdata->ilb, '>', 0); else gtloc = -1; /* if (gt_flag && (gtloc != -1)) debug("bb.smsc.at2", 0, "in at2_read_line with gt_flag=1, gtloc=%d, ilb=%s", gtloc, octstr_get_cstr(privdata->ilb)); */ eol = octstr_search_char(privdata->ilb, '\r', 0); /* looking for CR */ if ( (gtloc != -1) && ( (eol == -1) || (eol > gtloc) ) ) eol = gtloc; if (eol == -1) return NULL; line = octstr_copy(privdata->ilb, 0, eol); buf2 = octstr_copy(privdata->ilb, eol + 1, len); octstr_destroy(privdata->ilb); privdata->ilb = buf2; /* remove any non printable chars (including linefeed for example) */ for (i = 0; i < octstr_len(line); i++) { if (octstr_get_char(line, i) < 32) octstr_set_char(line, i, ' '); } octstr_strip_blanks(line); /* empty line, skipping */ if ((strcmp(octstr_get_cstr(line), "") == 0) && ( gt_flag == 0)) { octstr_destroy(line); return NULL; } if ((gt_flag) && (gtloc != -1)) { /* got to re-add it again as the parser needs to see it */ octstr_append_cstr(line, ">"); } debug("bb.smsc.at2", 0, "AT2[%s]: <-- %s", octstr_get_cstr(privdata->name), octstr_get_cstr(line)); return line;}int at2_write_line(PrivAT2data *privdata, char *line){ int count; int s = 0; int write_count = 0, data_written = 0; Octstr *linestr = NULL; linestr = octstr_format("%s\r", line); debug("bb.smsc.at2", 0, "AT2[%s]: --> %s^M", octstr_get_cstr(privdata->name), line); count = octstr_len(linestr); while (count > data_written) { errno = 0; s = write(privdata->fd, octstr_get_cstr(linestr) + data_written, count - data_written); if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { gwthread_sleep(1); ++write_count; } else if (s > 0) { data_written += s; write_count = 0; } else break; }; O_DESTROY(linestr); if (s < 0) { error(errno, "AT2[%s]: Couldnot write to device.", octstr_get_cstr(privdata->name)); tcflush(privdata->fd, TCOFLUSH); return s; } tcdrain(privdata->fd); gwthread_sleep((double) (privdata->modem == NULL ? 100 : privdata->modem->sendline_sleep) / 1000); return s;}int at2_write_ctrlz(PrivAT2data *privdata){ int s; char *ctrlz = "\032" ; int write_count = 0; debug("bb.smsc.at2", 0, "AT2[%s]: --> ^Z", octstr_get_cstr(privdata->name)); while (1) { errno = 0; s = write(privdata->fd, ctrlz, 1); if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { gwthread_sleep(1); ++write_count; } else break; }; if (s < 0) { error(errno, "AT2[%s]: Couldnot write to device.", octstr_get_cstr(privdata->name)); tcflush(privdata->fd, TCOFLUSH); return s; } tcdrain(privdata->fd); gwthread_sleep((double) (privdata->modem == NULL ? 100 : privdata->modem->sendline_sleep) / 1000); return s;} int at2_write(PrivAT2data *privdata, char *line){ int count, data_written = 0, write_count = 0; int s = 0; debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line); count = strlen(line); while(count > data_written) { s = write(privdata->fd, line + data_written, count - data_written); if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { gwthread_sleep(1); ++write_count; } else if (s > 0) { data_written += s; write_count = 0; } else break; } if (s < 0) { error(errno, "AT2[%s]: Couldnot write to device.", octstr_get_cstr(privdata->name)); tcflush(privdata->fd, TCOFLUSH); return s; } tcdrain(privdata->fd); gwthread_sleep((double) (privdata->modem == NULL ? 100 : privdata->modem->sendline_sleep) / 1000); return s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -