// ********************** START OF MODEM.CPP **********************
//
//
// This file contains all of the code for the Modem class. It should
// be compile and linked with any program wanting to use the class.
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "rs232.h"
#include "modem.h"
// The modem capability database is used to define all of the
// attributes used by a particular brand of modem. These are
// stored in the application, which is practical when just a few
// are defined. A bigger database might have to be moved into a
// conventional file.
ModemCapabilities ModemDataBase[] = {
{ "Hayes Compatible",
"AT &F &C1 &D2",
"NO CARRIER\0ERROR\0NO DIALTONE\0BUSY\0NO ANSWER\0\0",
"",
"",
2400L,
0,
0
},
{ "Practical Peripherals V.34",
"AT &F0 &C1 &D2 S95=44",
"NO CARRIER\0ERROR\0NO DIALTONE\0BUSY\0NO ANSWER\0\0",
"CLASS 5\0V.42BIS\0\0",
"LAP-M\0ALT\0\0",
57600L,
1,
1
},
{ "Intel SatisFAXtion 400e",
"AT &F",
"NO CARRIER\0ERROR\0NO DIALTONE\0BUSY\0NO ANSWER\0\0",
"COMP\0\0",
"LAPM\0MNP\0REL\0\0",
57600L,
1,
1
},
{ ""
} };
// The modem constructur sets up the capability database for the
// modem of the particular name, but doesn't do much else. If the
// brand name mode is not found via an exact match, the generic Hayes
// compatible definition is used.
Modem::Modem( RS232 &rs232_port, char *modem_name )
{
int i;
port = &rs232_port;
modem_data = &ModemDataBase[ 0 ];
for ( i = 0 ; *ModemDataBase[ i ].name != '\0' ; i++ ) {
if ( strcmp( modem_name, ModemDataBase[ i ].name ) == 0 ) {
modem_data = &ModemDataBase[ i ];
break;
}
}
tone_dial = 1;
carrier_timeout = 60000L;
}
// The usual translation routine is used to print out the error
// names in more descriptive form.
char *Modem::ErrorName( ModemError status )
{
switch ( status ) {
case MODEM_SUCCESS : return "Success";
case MODEM_NO_RESPONSE : return "No Response";
case MODEM_NO_CONNECTION : return "No Connection";
case MODEM_DISCONNECT_FAILED : return "Disconnect failed";
case MODEM_USER_ABORT : return "User abort";
default : return "Unknown Error";
}
}
// The initialization routine just has to send out the initialization
// string, then wait for a response. It inserts an extra one second
// delay in this routine, because some modems need a little extra time
// to handle initialization.
ModemError Modem::Initialize( void )
{
long delay_time;
port->Set( modem_data->initial_baud_rate );
port->RtsCtsHandshaking( modem_data->handshaking );
port->Write( '\r' );
delay_time = ReadTime() + 1000;
while ( ReadTime() < delay_time )
port->IdleFunction();
port->Write( modem_data->initialization_string );
port->Write( '\r' );
return wait_for_response();
}
// This protected routine is used to read lines of data back from the
// modem, generally after a response to a command. It reads the
// characters in, echos them using the echo routine, and tries to
// assemble a complete line. A '\n' character is used to terminate the
// line, or a timeout.
void Modem::read_line( char *buffer, int buf_size )
{
int c;
for ( ; ; ) {
c = port->Read( 500 );
if ( c < 0 )
break;
echo( (char) c );
*buffer++ = (char) c;
if ( --buf_size <= 1 )
break;
if ( c == '\n' )
break;
}
*buffer = '\0';
}
// This protected routine is used to wait for an OK message
// after a modem command is sent. If it doesn't get it within
// 2 seconds, and error is returned. Most commands going to the
// modem can expect an OK response. The two notable exceptions
// are the dialing and answer commands.
ModemError Modem::wait_for_response( void )
{
long timeout;
char buffer[ 81 ];
ModemError status;
timeout = ReadTime() + 2000;
while ( ReadTime() < timeout ) {
read_line( buffer, 81 );
if ( strncmp( buffer, "OK", 2 ) == 0 )
return MODEM_SUCCESS;
if ( ( status = UserAbort() ) != MODEM_SUCCESS )
return status;
}
return MODEM_NO_RESPONSE;
}
// During dialing, the Dial routine has to scan the input stream for
// lots of different strings that can indicate various things about
// protocols, data compression, and connections. This command is used
// to scan for a list of strings stored in the format used by the
// modem capability database.
char *scan_strings( char *buffer, char *strings )
{
char *p;
while ( *strings ) {
if ( ( p = strstr( buffer, strings ) ) != 0 )
return p;
strings += strlen( strings ) + 1;
}
return p;
}
// This routine is called by both the Answer and Dial routines.
// It has to scan the incoming lines of data not just for the
// "CONNECT" message, but also the protocol and compression strings
// as well. Additionally, if the baud rate is not locked, it has
// to detect the new baud rate on connection.
ModemError Modem::wait_for_connection( void )
{
long timeout;
char *connect;
char buffer[ 81 ];
ModemError status;
compressing = 0;
protocol = 0;
timeout = ReadTime() + carrier_timeout;
while ( ReadTime() < timeout ) {
read_line( buffer, 81 );
if ( scan_strings( buffer, modem_data->fail_strings ) )
return MODEM_NO_CONNECTION;
if ( scan_strings( buffer, modem_data->compression_strings ) )
compressing = 1;
if ( scan_strings( buffer, modem_data->protocol_strings ) )
protocol = 1;
if ( ( connect = strstr( buffer, "CONNECT" ) ) != 0 ) {
if ( !modem_data->locked_baud_rate ) {
local_baud_rate = atol( connect + 8 );
if ( local_baud_rate !=0 )
port->Set( local_baud_rate );
} else
local_baud_rate = modem_data->initial_baud_rate;
return MODEM_SUCCESS;
}
if ( ( status = UserAbort() ) != MODEM_SUCCESS )
return status;
}
return MODEM_NO_CONNECTION;
}
// This routine dials and then has another routine do the hard work
// of waiting for a response.
ModemError Modem::Dial( char *dial_string )
{
port->Write( "ATD" );
if ( tone_dial )
port->Write( 'T' );
else
port->Write( 'P' );
port->Write( dial_string );
port->Write( '\r' );
return wait_for_connection();
}
// This routine sends the answer command, then lets the other routine
// wait for success or failure.
ModemError Modem::Answer( void )
{
port->Write( "ATA\r" );
return wait_for_connection();
}
// Although all of the modems in the database are supposed to be set
// up so that dropping DTR causes a disconnect, some may slip through
// the net. If dropping DTR doesn't cause a disconnect, the
// escape sequence is sent, followed by a Hangup message.
ModemError Modem::Disconnect( void )
{
long delay_time;
port->Dtr( 0 );
delay_time = ReadTime() + 1250;
while ( ReadTime() < delay_time )
port->IdleFunction();
port->Dtr( 1 );
port->Write( "AT\r" );
if ( wait_for_response() == MODEM_SUCCESS ) {
port->Set( modem_data->initial_baud_rate );
return MODEM_SUCCESS;
}
port->Write( "+++" );
delay_time = ReadTime() + 1250;
wait_for_response();
port->Write( "ATH0\r" );
if ( wait_for_response() == MODEM_SUCCESS ) {
port->Set( modem_data->initial_baud_rate );
return MODEM_SUCCESS;
}
return MODEM_DI
四散
- 粉丝: 65
- 资源: 1万+
最新资源
- ExifTool-12.84.dmg
- 【小程序毕业设计】基于小程序的蒙服汇作业源码(完整前后端+mysql+说明文档).zip
- MATLAB《用于低光图像增强的生物启发式多曝光融合框架》+项目源码+文档说明+代码注释+数据
- 【小程序毕业设计】报修小程序源码(完整前后端+mysql+说明文档).zip
- 一款低代码生成器,可根据自定义模板内容,快速生成代码,实现项目的快速开发、上线,减少重复的代码编写,开发人员只需专注业务逻辑即可
- 纯电动乘用车用减速器总成技术条件
- winform GDI+ 绘制的(双人)五子棋.zip
- 我们常常在Python中需要使用一些数据包对数据进行数据分析,但是在Python中的包却又不能满足我们的需求,又需要
- java项目,课程设计-ssm大学生企业推荐系统.zip
- 【Unity 动画插件】DOTween Pro 可以在短时间内实现复杂的动画逻辑,极大提升了游戏开发的效率
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈