📄 modeminit.c
字号:
/*SMS Server Tools 3Copyright (C) Keijo Kasvihttp://smstools3.kekekasvi.com/Based on SMS Server Tools 2 from Stefan Fringshttp://www.meinemullemaus.de/This 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.*/#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <regex.h>#include "logging.h"#include "alarm.h"#ifdef SOLARIS#include <sys/filio.h>#include <strings.h> // for bzero().#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <syslog.h>#include <sys/ioctl.h>#include <errno.h>#include "extras.h"#include "modeminit.h"#include "smsd_cfg.h"#include "version.h"// Define a dummy if the OS does not support hardware handshake#ifndef CRTSCTS#define CRTSCTS 0#endiftypedef struct { int code; char *text;} _gsm_general_error; _gsm_general_error gsm_cme_errors[] ={ // 3GPP TS 07.07 version 7.8.0 Release 1998 (page 90) ETSI TS 100 916 V7.8.0 (2003-03) {0, "phone failure"}, {1, "no connection to phone"}, {2, "phone-adaptor link reserved"}, {3, "operation not allowed"}, {4, "operation not supported"}, {5, "PH-SIM PIN required"}, {6, "PH-FSIM PIN required"}, {7, "PH-FSIM PUK required"}, {10, "SIM not inserted"}, {11, "SIM PIN required"}, {12, "SIM PUK required"}, {13, "SIM failure"}, {14, "SIM busy"}, {15, "SIM wrong"}, {16, "incorrect password"}, {17, "SIM PIN2 required"}, {18, "SIM PUK2 required"}, {20, "memory full"}, {21, "invalid index"}, {22, "not found"}, {23, "memory failure"}, {24, "text string too long"}, {25, "invalid characters in text string"}, {26, "dial string too long"}, {27, "invalid characters in dial string"}, {30, "no network service"}, {31, "network timeout"}, {32, "network not allowed - emergency calls only"}, {40, "network personalisation PIN required"}, {41, "network personalisation PUK required"}, {42, "network subset personalisation PIN required"}, {43, "network subset personalisation PUK required"}, {44, "service provider personalisation PIN required"}, {45, "service provider personalisation PUK required"}, {46, "corporate personalisation PIN required"}, {47, "corporate personalisation PUK required"}, {100, "unknown"}// Some other possible errors (source document?)://CME ERROR: 48 PH-SIM PUK required//CME ERROR: 256 Operation temporarily not allowed//CME ERROR: 257 Call barred//CME ERROR: 258 Phone is busy//CME ERROR: 259 User abort//CME ERROR: 260 Invalid dial string//CME ERROR: 261 SS not executed//CME ERROR: 262 SIM Blocked};_gsm_general_error gsm_cms_errors[] ={ // Table 8.4/GSM 04.11 (part 1): {1, "Unassigned (unallocated) number"}, {8, "Operator determined barring"}, {10, "Call barred"}, {21, "Short message transfer rejected"}, {27, "Destination out of order"}, {28, "Unindentified subscriber"}, {29, "Facility rejected"}, {30, "Unknown subscriber"}, {38, "Network out of order"}, {41, "Temporary failure"}, {42, "Congestion"}, {47, "Recources unavailable, unspecified"}, {50, "Requested facility not subscribed"}, {69, "Requested facility not implemented"}, {81, "Invalid short message transfer reference value"}, {95, "Semantically incorrect message"}, {96, "Invalid mandatory information"}, {97, "Message type non-existent or not implemented"}, {98, "Message not compatible with short message protocol state"}, {99, "Information element non-existent or not implemented"}, {111, "Protocol error, unspecified"}, {127, "Internetworking , unspecified"}, // Table 8.4/GSM 04.11 (part 2): {22, "Memory capacity exceeded"}, // GSM 03.40 subclause 9.2.3.22 values. {128, "Telematic internetworking not supported"}, {129, "Short message type 0 not supported"}, {130, "Cannot replace short message"}, {143, "Unspecified TP-PID error"}, {144, "Data code scheme (alphabet) not supported"}, {145, "Message class not supported"}, {159, "Unspecified TP-DCS error"}, {160, "Command cannot be actioned"}, {161, "Command unsupported"}, {175, "Unspecified TP-Command error"}, {176, "Transfer Protocol Data Unit (TPDU) not supported"}, {192, "Service Center (SC) busy"}, {193, "No SC subscription"}, {194, "SC System failure"}, {195, "Invalid Short Message Entity (SME) address"}, {196, "Destination SME barred"}, {197, "SM Rejected-Duplicate SM"}, {198, "Validity Period Format (TP-VPF) not supported"}, {199, "Validity Period) TP-VP not supported"}, {208, "SIM SMS Storage full"}, {209, "No SMS Storage capability in SIM"}, {210, "Error in MS"}, {211, "Memory capacity exceeded"}, {212, "Sim Application Toolkit busy"}, {213, "SIM data download error"}, {255, "Unspecified error cause"}, // 3GPP TS 27.005 subclause 3.2.5 values /3/. {300, "ME Failure"}, {301, "SMS service of ME reserved"}, {302, "Operation not allowed"}, {303, "Operation not supported"}, {304, "Invalid PDU mode parameter"}, {305, "Invalid Text mode parameter"}, {310, "(U)SIM not inserted"}, {311, "(U)SIM PIN required"}, {312, "PH-(U)SIM PIN required"}, {313, "(U)SIM failure"}, {314, "(U)SIM busy"}, {315, "(U)SIM wrong"}, {316, "(U)SIM PUK required"}, {317, "(U)SIM PIN2 required"}, {318, "(U)SIM PUK2 required"}, {320, "Memory failure"}, {321, "Invalid memory index"}, {322, "Memory full"}, {330, "SMSC address unknown"}, {331, "No network service"}, {332, "Network timeout"}, {340, "No +CNMA acknowledgement expected"}, {500, "Unknown error"}};char *get_gsm_cme_error(int code){ int i; int m = sizeof gsm_cme_errors / sizeof *gsm_cme_errors; for (i = 0; i < m; i++) if (code == gsm_cme_errors[i].code) return gsm_cme_errors[i].text; return "";}char *get_gsm_cms_error(int code){ int i; int m = sizeof gsm_cms_errors / sizeof *gsm_cms_errors; for (i = 0; i < m; i++) if (code == gsm_cms_errors[i].code) return gsm_cms_errors[i].text; return "";}char *get_gsm_error(char *answer){ char *p; if (answer && *answer) { if ((p = strstr(answer, "+CME ERROR: "))) return get_gsm_cme_error(atoi(p +12)); if ((p = strstr(answer, "+CMS ERROR: "))) return get_gsm_cms_error(atoi(p +12)); } return "";}int write_to_modem(int modem, char *modemname, int send_delay, char *command, int timeout, int log_command, int print_error){ int status=0; int timeoutcounter=0; int x=0; struct termios tio; tcgetattr(modem,&tio); if (command && command[0]) { if (tio.c_cflag & CRTSCTS) { ioctl(modem,TIOCMGET,&status); while (!(status & TIOCM_CTS)) { usleep(100000); timeoutcounter++; ioctl(modem,TIOCMGET,&status); if (timeoutcounter>timeout) { if (print_error) printf("\nModem is not clear to send.\n"); else { writelogfile0(LOG_ERR,modemname, tb_sprintf("Modem is not clear to send")); alarm_handler0(LOG_ERR,modemname, tb); } return 0; } } } if (log_command) writelogfile(LOG_DEBUG,modemname,"-> %s",command); for(x=0;x<strlen(command);x++) { if (write(modem,command+x,1)<1) { if (print_error) printf("\nCould not send character %c, cause: %s\n",command[x],strerror(errno)); else { writelogfile0(LOG_ERR,modemname, tb_sprintf("Could not send character %c, cause: %s", command[x], strerror(errno))); alarm_handler0(LOG_ERR,modemname, tb); } return 0; } if (send_delay) usleep(send_delay*1000); tcdrain(modem); } } return 1;}// Read max characters from modem. The function returns when it received at // least 1 character and then the modem is quiet for timeout*0.1s.// The answer might contain already a string. In this case, the answer // gets appended to this string.int read_from_modem(int modem, char *modemname, int send_delay, char *answer, int max, int timeout){ int count=0; int got=0; int timeoutcounter=0; int success=0; int toread=0; // Cygwin does not support TIOC functions, so we cannot use it. // ioctl(modem,FIONREAD,&available); // how many bytes are available to read? do { // How many bytes do I want to read maximum? Not more than buffer size -1 for termination character. count=strlen(answer); toread=max-count-1; if (toread<=0) break; // read data got=read(modem,answer+count,toread); // if nothing received ... if (got<=0) { // wait a litte bit and then repeat this loop got=0; usleep(100000); timeoutcounter++; } else { // restart timout counter timeoutcounter=0; // append a string termination character answer[count+got]=0; success=1; } } while (timeoutcounter < timeout); return success;}// 3.1beta7: Not waiting any answer if answer is NULL. Return value is then 1/0.int put_command(int modem, char *modemname, int send_delay, char *command, char *answer, int max, int timeout, char *expect){ char loganswer[2048]; int timeoutcounter = 0; regex_t re; int got_timeout = 1; int regex_allocated = 0; // compile regular expressions if (expect && expect[0]) { if (regcomp(&re, expect, REG_EXTENDED|REG_NOSUB) != 0) { fprintf(stderr, "Programming error: Expected answer %s is not a valid regepr\n", expect); writelogfile(LOG_CRIT, modemname, "Programming error: Expected answer %s is not a valid regepr", expect); exit(1); } regex_allocated = 1; } // clean input buffer // It seems that this command does not do anything because actually it // does not clear the input buffer. However I do not remove it until I // know why it does not work. tcflush(modem,TCIFLUSH); // send command if (write_to_modem(modem, modemname, send_delay, command, 30, 1, 0) == 0) { t_sleep(errorsleeptime); // Free memory used by regexp if (regex_allocated) regfree(&re); return 0; } if (!answer) writelogfile(LOG_DEBUG, modemname, "Command is sent"); else { writelogfile(LOG_DEBUG, modemname, "Command is sent, waiting for the answer"); // wait for the modem-answer answer[0] = 0; timeoutcounter = 0; do { read_from_modem(modem, modemname, send_delay, answer, max, 2); // One read attempt is 200ms // check if it's the expected answer if (expect && expect[0] && (regexec(&re, answer, (size_t) 0, NULL, 0) == 0)) { got_timeout = 0; put_command_timeouts = 0; break; } timeoutcounter += 2; } // repeat until timout while (timeoutcounter < timeout); if (got_timeout) { put_command_timeouts++; if (expect && expect[0]) writelogfile(LOG_DEBUG, modemname, "put_command expected %s, timeout occurred.", expect); } strncpy(loganswer, answer, sizeof(loganswer) -1); loganswer[sizeof(loganswer) -1] = 0; cutspaces(loganswer); cut_emptylines(loganswer); writelogfile(LOG_DEBUG, modemname, "<- %s", loganswer); } // Free memory used by regexp if (regex_allocated) regfree(&re); if (answer) return strlen(answer); return 1;}void setmodemparams(int modem, char* modemname, int rtscts,int baudrate) /* setup serial port */{ struct termios newtio; bzero(&newtio, sizeof(newtio)); newtio.c_cflag = CS8 | CLOCAL | CREAD | O_NDELAY | O_NONBLOCK; if (rtscts) newtio.c_cflag |= CRTSCTS; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; switch (baudrate) { case 300: baudrate=B300; break; case 1200: baudrate=B1200; break; case 2400: baudrate=B2400; break; case 9600: baudrate=B9600; break; case 19200: baudrate=B19200; break; case 38400: baudrate=B38400; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -