📄 modem.cpp
字号:
/* * kPPP: A pppd Front End for the KDE project * * $Id: modem.cpp,v 1.1 2001/02/16 13:02:25 matze Exp $ * * Copyright (C) 1997 Bernd Johannes Wuebben * wuebben@math.cornell.edu * * This file was added by Harri Porten <porten@tu-harburg.de> * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <errno.h>#include <stdlib.h>#include <fcntl.h>#include <signal.h>#include <sys/ioctl.h>#include <setjmp.h>#include <qregexp.h>#include <qtimer.h>#include <assert.h>#include "modem.h"#include <klocale.h>#include <kmessagebox.h>#include <kdebug.h>#include <config.h>static sigjmp_buf jmp_buffer;Modem::Modem() { modemfd = -1; sn = NULL; data_mode = false; // S25/S35 specific configuration m_lineTerminator = "CR"; m_modemEscapeGuardTime = 1000; // 1 second m_modemEscapeString = "+++"; m_modemHangupString = "ATH0"; m_modemInitDelay = 100; // 0.1 sec m_flowControl = "None"; m_modemSpeed = B115200;}Modem::~Modem() {}speed_t Modem::modemSpeed() { return m_modemSpeed;}bool Modem::opentty(const QString& ttyDevice) { if (sigsetjmp(jmp_buffer, 1) == 0) { // set alarm in case open() hangs, might happen with IrDA signal(SIGALRM, alarm_handler); alarm(2); if ((modemfd = ::open(ttyDevice.data(), O_RDWR)) < 0) { errmsg = i18n("cannot open the modem device"); alarm(0); signal(SIGALRM, SIG_IGN); return false; } alarm(0); signal(SIGALRM, SIG_IGN); } else { errmsg = i18n("Sorry, the modem does not respond."); return false; } tcdrain (modemfd); tcflush (modemfd, TCIOFLUSH); if(tcgetattr(modemfd, &tty) < 0){ // this helps in some cases tcsendbreak(modemfd, 0); sleep(1); if(tcgetattr(modemfd, &tty) < 0){ errmsg = i18n("Sorry, the modem is busy."); ::close(modemfd); modemfd = -1; return false; } } memset(&initial_tty,'\0',sizeof(initial_tty)); initial_tty = tty; tty.c_cc[VMIN] = 0; // nonblocking tty.c_cc[VTIME] = 0; tty.c_oflag = 0; tty.c_lflag = 0; tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB); tty.c_cflag |= CS8 | CREAD; tty.c_cflag |= CLOCAL; // ignore modem status lines tty.c_iflag = IGNBRK | IGNPAR /* | ISTRIP */ ; tty.c_lflag &= ~ICANON; // non-canonical mode tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE); if(flowControl() != "None") { if(flowControl() == "CRTSCTS") { tty.c_cflag |= CRTSCTS; } else { tty.c_iflag |= IXON | IXOFF; tty.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ tty.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ } } else { tty.c_cflag &= ~CRTSCTS; tty.c_iflag &= ~(IXON | IXOFF); } cfsetospeed(&tty, modemSpeed()); cfsetispeed(&tty, modemSpeed()); tcdrain(modemfd); if(tcsetattr(modemfd, TCSANOW, &tty) < 0){ errmsg = i18n("Sorry, the modem is busy."); ::close(modemfd); modemfd=-1; return false; } errmsg = i18n("Modem Ready."); return true;}bool Modem::closetty() { if(modemfd >=0 ) { stop(); /* discard data not read or transmitted */ tcflush(modemfd, TCIOFLUSH); if(tcsetattr(modemfd, TCSANOW, &initial_tty) < 0){ errmsg = i18n("Can't restore tty settings: tcsetattr()\n"); ::close(modemfd); modemfd = -1; return false; } ::close(modemfd); modemfd = -1; } return true;}void Modem::readtty(int) { char buffer[200]; unsigned char c; int len; // read data in chunks of up to 200 bytes if((len = ::read(modemfd, buffer, 200)) > 0) { // split buffer into single characters for further processing for(int i = 0; i < len; i++) { c = buffer[i] /* & 0x7F */; emit charWaiting(c); } }}void Modem::notify(const QObject *receiver, const char *member) { connect(this, SIGNAL(charWaiting(unsigned char)), receiver, member); startNotifier();}void Modem::stop() { disconnect(SIGNAL(charWaiting(unsigned char))); stopNotifier();}void Modem::startNotifier() { if(modemfd >= 0) { if(sn == 0) { sn = new QSocketNotifier(modemfd, QSocketNotifier::Read, this); connect(sn, SIGNAL(activated(int)), SLOT(readtty(int))); kdDebug(5002) << "QSocketNotifier started!" << endl; } else { // Debug("QSocketNotifier re-enabled!"); sn->setEnabled(true); } }}void Modem::stopNotifier() { if(sn != 0) { sn->setEnabled(false); disconnect(sn); delete sn; sn = 0; kdDebug(5002) << "QSocketNotifier stopped!" << endl; }}void Modem::flush() { char c; while(read(modemfd, &c, 1) == 1);}bool Modem::writeChar(unsigned char c) { return write(modemfd, &c, 1) == 1;}bool Modem::writeLine(const char *buf) { int len = strlen(buf); char* bp = buf; int l = len; while (l) { int wr = write(modemfd, bp, l); if(wr < 0) { kdError(5002) << "write() in Modem::writeLine failed" << endl; return false; } l -= wr; bp += wr; } return true;}bool Modem::hangup() { // this should really get the modem to hang up and go into command mode // If anyone sees a fault in the following please let me know, since // this is probably the most imporant snippet of code in the whole of // kppp. If people complain about kppp being stuck, this piece of code // is most likely the reason. struct termios temptty; if(modemfd >= 0) { // is this Escape & HangupStr stuff really necessary ? (Harri) if (data_mode) escape_to_command_mode(); // Then hangup command writeLine(modemHangupString().local8Bit()); usleep(modemInitDelay() * 10);#ifndef DEBUG_WO_DIALING if (sigsetjmp(jmp_buffer, 1) == 0) { // set alarm in case tcsendbreak() hangs signal(SIGALRM, alarm_handler); alarm(2); tcsendbreak(modemfd, 0); alarm(0); signal(SIGALRM, SIG_IGN); } else { // we reach this point if the alarm handler got called closetty(); close(modemfd); modemfd = -1; errmsg = i18n("Sorry, the modem doesn't respond."); return false; } tcgetattr(modemfd, &temptty); cfsetospeed(&temptty, B0); cfsetispeed(&temptty, B0); tcsetattr(modemfd, TCSAFLUSH, &temptty); usleep(modemInitDelay() * 10000); // 0.01 - 3.0 secs cfsetospeed(&temptty, modemSpeed()); cfsetispeed(&temptty, modemSpeed()); tcsetattr(modemfd, TCSAFLUSH, &temptty);#endif return true; } else return false;}void Modem::escape_to_command_mode() { // Send Properly bracketed escape code to put the modem back into command state. // A modem will accept AT commands only when it is in command state. // When a modem sends the host the CONNECT string, that signals // that the modem is now in the connect state (no long accepts AT commands.) // Need to send properly timed escape sequence to put modem in command state. // Escape codes and guard times are controlled by S2 and S12 values. // tcflush(modemfd, TCIOFLUSH); // +3 because quiet time must be greater than guard time. usleep(modemEscapeGuardTime() * 10); QCString tmp = modemEscapeString().local8Bit(); write(modemfd, tmp.data(), tmp.length()); tcflush(modemfd, TCIOFLUSH); usleep(modemEscapeGuardTime() * 10); data_mode = false;}const QString& Modem::modemMessage() { return errmsg;}void alarm_handler(int) { // fprintf(stderr, "alarm_handler(): Received SIGALRM\n"); // jump siglongjmp(jmp_buffer, 1);}/** return the flow control setting of the modem device */const QString & Modem::flowControl() const{ return m_flowControl;}/** return the current line termination character, which is either "CR", "LF" or "CR/LF" */const QString& Modem::lineTerminator() const{ return m_lineTerminator;}/** returns the current modem hangup string (e.g. "ATH0") */const QString& Modem::modemHangupString() const{ return m_modemHangupString;}/** returns the modem init delay, in milliseconds */int Modem::modemInitDelay() const{ return m_modemInitDelay;}/** return the guard time after sending the escape sequence to the modem in milliseconds */int Modem::modemEscapeGuardTime() const{ return m_modemEscapeGuardTime;}/** return the escape sequence of the modem */const QString& Modem::modemEscapeString() const{ return m_modemEscapeString;}/** set the line terminator. valid are "CR", "CR/LF", "ESC". */void Modem::setLineTerminator(QString string){ m_lineTerminator = string;}#include "modem.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -