Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

wvmodem.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *   Copyright (C) 1999 Red Hat, Inc.
00005  *
00006  * Implementation of the WvModem class. Inherits from WvFile, but
00007  * handles various important details related to modems, like setting
00008  * the baud rate, checking carrier detect, and dropping DTR.
00009  *
00010  */
00011 
00012 #include "wvmodem.h"
00013 #include <sys/ioctl.h>
00014         
00015 
00016 struct SpeedLookup {
00017     int baud;
00018     speed_t speedt;
00019 };
00020 
00021 
00022 static SpeedLookup speeds[] = {
00023 #ifdef B460800
00024     {460800, B460800},
00025 #endif
00026 #ifdef B230400
00027     {230400, B230400},
00028 #endif
00029     {115200, B115200},
00030     { 57600, B57600},
00031     { 38400, B38400},
00032     { 19200, B19200},
00033     {  9600, B9600},
00034     {  4800, B4800},
00035     {  2400, B2400},
00036     {  1200, B1200},
00037     {   300, B300}
00038 };
00039 
00040 
00041 WvModemBase::WvModemBase(int _fd) : WvFile(_fd)
00042 {
00043     get_real_speed();
00044 }
00045 
00046 
00047 WvModemBase::~WvModemBase()
00048 {
00049     // nothing needed
00050 }
00051 
00052 
00053 int WvModemBase::get_real_speed()
00054 {
00055     speed_t s;
00056     
00057     if (!isok()) return 0;
00058 
00059     tcgetattr( getrfd(), &t );
00060     s = cfgetospeed( &t );
00061     for (unsigned int i = 0; i < sizeof(speeds) / sizeof(*speeds); i++)
00062     {
00063         if (speeds[i].speedt == s)
00064         {
00065             baud = speeds[i].baud;
00066             break;
00067         }
00068     }
00069 
00070     return baud;
00071 }
00072 
00073 
00074 void WvModemBase::close()
00075 {
00076     // no file open, no need to close it
00077 }
00078 
00079 
00080 bool WvModemBase::carrier()
00081 {
00082     return true;
00083 }
00084 
00085 
00086 int WvModemBase::speed(int)
00087 {
00088     return baud;
00089 }
00090 
00091 
00092 void WvModemBase::hangup()
00093 {
00094     int i, oldbaud = baud;
00095     
00096     if (die_fast || !isok()) return;
00097 
00098     // politely abort any dial in progress, to avoid locking USR modems.
00099     // we should only do this if we have received any response from the modem,
00100     // so that WvModemScan can run faster.
00101     drain();
00102     write( "\r", 1 );
00103     for (i = 0; !select(200) && i < 10; i++)
00104         write( "\r", 1 );
00105     drain();
00106 
00107     // drop DTR for a while, if still online
00108     if (carrier())
00109     {
00110         cfsetospeed( &t, B0 );
00111         tcsetattr( getrfd(), TCSANOW, &t );
00112         for (i = 0; carrier() && i < 10; i++)
00113             usleep( 100 * 1000 );
00114 
00115         // raise DTR again, restoring the old baud rate
00116         speed(oldbaud);
00117     }
00118     
00119     if (carrier())
00120     {
00121         // need to do +++ manual-disconnect stuff
00122         write( "+++", 3 );
00123         usleep( 1500 * 1000 );
00124         write( "ATH\r", 4 );
00125         
00126         for (i = 0; carrier() && i < 5; i++)
00127             usleep( 100 * 1000 );
00128     }
00129 }
00130 
00131 
00132 
00133 WvModem::WvModem(const char * filename, int _baud, bool rtscts)
00134         : WvModemBase(), lock(filename)
00135 {
00136     closing = false;
00137     baud = _baud;
00138     die_fast = false;
00139     
00140     if (!lock.lock())
00141     {
00142         errnum = EBUSY;
00143         return;
00144     }
00145     
00146     // note: if CLOCAL is not set on the modem, open will
00147     // block until a carrier detect.  Since we have to open the modem to
00148     // generate a carrier detect, we have a problem.  So we open the modem
00149     // nonblocking.  It would then be safe to switch to blocking mode,
00150     // but that is no longer recommended for WvStream.
00151     open(filename, O_RDWR|O_NONBLOCK|O_NOCTTY);
00152     
00153     if (isok())
00154         setup_modem(rtscts);
00155 }
00156 
00157 
00158 WvModem::~WvModem()
00159 {
00160     close();
00161 }
00162 
00163 
00164 void WvModem::setup_modem(bool rtscts)
00165 {
00166     if (!isok()) return;
00167 
00168     if (tcgetattr( getrfd(), &t ) || tcgetattr( getrfd(), &old_t ))
00169     {
00170         closing = true;
00171         seterr(errno);
00172         return;
00173     }
00174     
00175     drain();
00176     
00177     // set up the terminal characteristics.
00178     // see "man tcsetattr" for more information about these options.
00179     t.c_iflag &= ~(BRKINT | ISTRIP | IUCLC | IXON | IXANY | IXOFF | IMAXBEL);
00180     t.c_iflag |= (IGNBRK | IGNPAR);
00181     t.c_oflag &= ~(OLCUC);
00182     t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
00183     t.c_cflag |= (CS8 | CREAD | HUPCL | CLOCAL);
00184     if( rtscts )
00185         t.c_cflag |= CRTSCTS;
00186     t.c_lflag &= ~(ISIG | XCASE | ECHO);
00187     tcsetattr( getrfd(), TCSANOW, &t );
00188     
00189     // make sure we leave the modem in CLOCAL when we exit, so normal user
00190     // tasks can open the modem without using nonblocking.
00191     old_t.c_cflag |= CLOCAL;
00192     
00193     // Send a few returns to make sure the modem is "good and zonked".
00194     if (cfgetospeed(&t) != B0)
00195     {
00196         for( int i=0; i<5; i++ ) {
00197             write( "\r", 1 );
00198             usleep( 10 * 1000 );
00199         }
00200     }
00201     
00202     // Set the baud rate to 0 for half a second to drop DTR...
00203     cfsetispeed( &t, B0 );
00204     cfsetospeed( &t, B0 );
00205     cfmakeraw( &t );
00206     tcsetattr( getrfd(), TCSANOW, &t );
00207     if (carrier())
00208         usleep( 500 * 1000 );
00209     
00210     speed(baud);
00211     usleep( 10 * 1000 );
00212     
00213     drain();
00214 }
00215 
00216 
00217 void WvModem::close()
00218 {
00219     if (isok())
00220     {
00221         if (!closing)
00222         {
00223             closing = true;
00224             hangup();
00225         }
00226         closing = true;
00227         tcflush(getrfd(), TCIOFLUSH);
00228         tcsetattr(getrfd(), TCSANOW, &old_t);
00229         WvFile::close();
00230         closing = false;
00231     }
00232 }
00233 
00234 
00235 int WvModem::speed(int _baud)
00236 {
00237     speed_t s = B0;
00238     baud = 0;
00239     for (unsigned int i = 0; i < sizeof(speeds) / sizeof(*speeds); i++)
00240     {
00241         if (speeds[i].baud <= _baud)
00242         {
00243             s = speeds[i].speedt;
00244             break;
00245         }
00246     }
00247 
00248     cfsetispeed( &t, B0 ); // auto-match to output speed
00249     cfsetospeed( &t, s );
00250     tcsetattr( getrfd(), TCSANOW, &t );
00251 
00252     return get_real_speed();
00253 }
00254 
00255 
00256 int WvModem::getstatus()
00257 {
00258     if (!isok()) return 0;
00259     int status = 0;
00260     ioctl(getrfd(), TIOCMGET, &status);
00261     return status;
00262 }
00263 
00264 
00265 bool WvModem::carrier()
00266 {
00267     return (getstatus() & TIOCM_CD) ? 1 : 0;
00268 }

Generated on Sat Aug 24 21:37:01 2002 for WvStreams by doxygen1.2.15