📄 smsc_at2.c
字号:
/* * smsc_at2.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_at2.h"static int at2_open_device1(PrivAT2data *privdata){ info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name)); 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;}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; 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 (1) { errno = 0; s = write(privdata->fd, octstr_get_cstr(linestr), count); if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { gwthread_sleep(1); ++write_count; } else break; }; O_DESTROY(linestr); if (s < 0) { debug("bb.smsc.at2", 0, "AT2[%s]: write failed with errno %d", octstr_get_cstr(privdata->name), errno); 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) { debug("bb.smsc.at2", 0, "AT2[%s]: write failed with errno %d", octstr_get_cstr(privdata->name), errno); return s; } tcdrain(privdata->fd); gwthread_sleep((double) privdata->modem->sendline_sleep / 1000); return s;} int at2_write(PrivAT2data *privdata, char *line){ int count; int s; count = strlen(line); debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line); s = write(privdata->fd, line, count); tcdrain(privdata->fd); return s;}void at2_flush_buffer(PrivAT2data *privdata){ at2_read_buffer(privdata); octstr_destroy(privdata->ilb); privdata->ilb = octstr_create("");}int at2_init_device(PrivAT2data *privdata){ int res; int ret; Octstr *setpin; info(0, "AT2[%s]: init device", octstr_get_cstr(privdata->name)); at2_set_speed(privdata, privdata->speed); res = at2_send_modem_command(privdata, "AT", 0, 0); if (res == -1) { /* * first try failed, maybe we need another one * after just having changed the speed */ res = at2_send_modem_command(privdata, "AT", 0, 0); } if (res == -1) { error(0, "AT2[%s]: no answer from modem", octstr_get_cstr(privdata->name)); return -1; } at2_flush_buffer(privdata); if (at2_send_modem_command(privdata, "AT&F", 0, 0) == -1) return -1; if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) return -1; at2_flush_buffer(privdata); /* enable hardware handshake */ if (octstr_len(privdata->modem->enable_hwhs)) { if (at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->enable_hwhs), 0, 0) == -1) info(0, "AT2[%s]: cannot enable hardware handshake", octstr_get_cstr(privdata->name)); } /* * Check does the modem require a PIN and, if so, send it. * This is not supported by the Nokia Premicell */ if (!privdata->modem->no_pin) { ret = at2_send_modem_command(privdata, "AT+CPIN?", 10, 0); if (!privdata->pin_ready) { if (ret == 2) { if (privdata->pin == NULL) return -1; setpin = octstr_format("AT+CPIN=%s", octstr_get_cstr(privdata->pin)); ret = at2_send_modem_command(privdata, octstr_get_cstr(setpin), 0, 0); octstr_destroy(setpin); if (ret != 0 ) return -1; } else if (ret == -1) return -1; } /* * we have to wait until +CPIN: READY appears before issuing * the next command. 10 sec should be suficient */ if (!privdata->pin_ready) { at2_wait_modem_command(privdata, 10, 0, NULL); if (!privdata->pin_ready) { at2_send_modem_command(privdata, "AT+CPIN?", 10, 0); if (!privdata->pin_ready) { return -1; /* give up */ } } } } /* * Set the GSM SMS message center address if supplied */ if (octstr_len(privdata->sms_center)) { Octstr *temp; temp = octstr_create("AT+CSCA="); octstr_append_char(temp, 34); octstr_append(temp, privdata->sms_center); octstr_append_char(temp, 34); /* * XXX If some modem don't process the +, remove it and add ",145" * and ",129" to national numbers */ ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0); octstr_destroy(temp); if (ret == -1) return -1; if (ret > 0) { info(0, "AT2[%s]: Cannot set SMS message center, continuing", octstr_get_cstr(privdata->name)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -