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 }