Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

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 Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7