00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
00099
00100
00101 drain();
00102 write( "\r", 1 );
00103 for (i = 0; !select(200) && i < 10; i++)
00104 write( "\r", 1 );
00105 drain();
00106
00107
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
00116 speed(oldbaud);
00117 }
00118
00119 if (carrier())
00120 {
00121
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
00147
00148
00149
00150
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
00178
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
00190
00191 old_t.c_cflag |= CLOCAL;
00192
00193
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
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 );
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 }