www.pudn.com > AtModem.rar > YsATModem.cpp


// ATModem.cpp: implementation of the CYsATModem class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "YsATModem.h" 
 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
UINT CYsATModem::WaitThread(LPVOID lpvoid) 
{ 
	CYsATModem* pThis=(CYsATModem*)lpvoid; 
	pThis->DetectConnect(); 
	return 1; 
} 
 
//检测modem是否就续 
UINT CYsATModem::DetectModemThread(LPVOID pParam) 
{ 
	TRACE(_T("in Detect Thread")); 
	CYsATModem* pThis=(CYsATModem*)pParam; 
	DWORD dwEvent; 
	DWORD dwTime; 
	int iRing=0; 
 
	pThis->m_bCD=0; 
 
	while(1==pThis->WaitEvent(&dwEvent,INFINITE)) 
	{ 
		if(dwEvent&EV_DSR) 
		{ 
			pThis->SetEvent(0); 
			//糟啦,modem坏啦!!! 
			TRACE(_T("My God!!! the modem broken!!!\n")); 
			pThis->Purge(PURGE_ALL); 
			pThis->ChangeMode(MODE_UNMODEM); 
			TRACE(_T("Quit Detect Thread")); 
			return 1; 
		} 
		else if(dwEvent&EV_RING)//win95不支持这种通知 
		{ 
			//这里有个问题,如果对方拨号一声后,挂断,计数器没清零,第二次就会出问题 
			if(iRing>0) 
			{ 
				if(GetTickCount()-dwTime>10000)  
					iRing=0;//如果两次响铃大于10秒钟,重设为0 
			} 
			dwTime=GetTickCount(); 
			iRing++; 
			CString s; 
			s.Format("ring count=%d %d Mode=%d\n",iRing,pThis->m_nRingCount,pThis->m_nMode); 
			TRACE(s); 
			if(pThis->m_nMode==MODE_COMMAND) 
			{ 
				if(iRing>=pThis->m_nRingCount) 
				{ 
					iRing=0; 
#ifdef USER_ANSWER 
					Sleep(500); 
					pThis->SendAT(CMD_ATA); 
#endif				 
					AfxBeginThread(WaitThread,pThis); 
				} 
			} 
		} 
		else if(dwEvent&EV_RLSD) 
		{ 
			CString s; 
			s.Format("\nCD灯改变 @@@  %d -%d\n",pThis->m_nMode,pThis->m_bCD); 
			TRACE(s); 
			if(pThis->m_nMode==MODE_DATA) 
			{ 
				pThis->m_bCD=FALSE; 
				TRACE("Modem Disconnect!!!!\n"); 
 
				ResetEvent(pThis->m_hConnected); 
				pThis->ChangeMode(MODE_COMMAND); 
 
				pThis->HangUp(); 
				if(pThis->m_Thread) 
				{ 
					if(WAIT_OBJECT_0!=WaitForSingleObject(pThis->m_Thread->m_hThread,10000)) 
					{ 
						TerminateThread(pThis->m_Thread->m_hThread,-11); 
					} 
					delete pThis->m_Thread; 
					pThis->m_Thread=NULL; 
				} 
			} 
			else if(pThis->m_nMode==MODE_CONNECTING) 
			{ 
				pThis->m_bCD=TRUE; 
 
				pThis->StopRead(); 
 
				pThis->Purge(PURGE_ALL); 
				pThis->m_Thread = AfxBeginThread(CYsATModem::ReadCommThread,(LPVOID)pThis); 
				if(!pThis->m_Thread) 
				{ 
					pThis->ChangeMode(MODE_COMMAND); 
					pThis->SetLastError(_TEXT("Start read comm thread error")); 
					return FALSE; 
				} 
				pThis->m_Thread->m_bAutoDelete=FALSE; 
				::SetEvent(pThis->m_hConnected); 
				pThis->ChangeMode(MODE_DATA); 
				TRACE("Modem connect!!!!\n"); 
				//无处理 
			} 
			else pThis->m_bCD=FALSE;//如果正在拨号的时候断线,可能会出现CD变化? 
		} 
	} 
	TRACE(_T("Quit Detect Thread")); 
	return 1; 
} 
 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: UINT CYsATModem::ReadCommThread(LPVOID pParam) 
 
PURPOSE: 线程函数,把串口读入缓冲区的字符,写到自己维护的缓冲区中,并判断断线 
 
PARAMETERS: 
		pParam:指向CYsATModem类 
 
RETURN VALUE: 
 
COMMENTS: 断线的处理,也许还要改进 
**********************************************************************/ 
UINT CYsATModem::ReadCommThread(LPVOID pParam) 
{ 
	//judge if no carrier 
	char strJudge[]=ECHO_NOCARRIER; 
	//current judge string position 
	int iJudge=0; 
	int iJudgeSize=strlen(strJudge); 
 
	TRACE("Start Thread\n"); 
	CYsATModem* pThis=(CYsATModem*)pParam; 
 
	DWORD dwInterTimeOut=INFINITE;//读每个字符之间的等待时间 
 
	int i; 
	BYTE chRead; 
	DWORD dwHaveRead; 
	while(1) 
	{ 
		do  
		{ 
			//read one char 
			i=pThis->ReadComm(&chRead,1,&dwHaveRead,dwInterTimeOut); 
			if (1==i) 
			{ 
				TRACE(_TEXT("##:%02x\n"),chRead,chRead); 
				pThis->m_pQueue->Put(&chRead); 
			} 
			else if(i==-3) 
			{ 
				TRACE(_TEXT("stop event set!~\n")); 
				//user hangup 
				i=TRUE; 
				goto Exit; 
			} 
			else if(i==-1) //非超时 
			{ 
				TRACE(_TEXT("in Function Read Error code%d\n"),i); 
				i=FALSE; 
				goto Exit; 
			} 
		} 
		while(dwHaveRead); 
	}//while 
Exit: 
	TRACE(_TEXT("End Read comm Thread\n")); 
 
	if(!i) TRACE(_TEXT("there are some error occur in thread\n")); 
	return i; 
} 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CYsATModem::CYsATModem() 
{ 
	m_nRingCount=2; 
	m_bInit=FALSE; 
	m_bTestMode=FALSE; 
	ChangeMode(MODE_UNINITIALIZE); 
 
	m_pQueue=new CYsQueue(QUEUE_SIZE); 
 
	m_Thread=NULL; 
	//顺序不能变 
	pstrCmdString[0]=ECHO_OK; 
	pstrCmdString[1]=ECHO_CONNECT; 
	pstrCmdString[2]=ECHO_RING; 
	pstrCmdString[3]=ECHO_NOCARRIER; 
	pstrCmdString[4]=ECHO_ERROR; 
	pstrCmdString[5]=ECHO_CONNECT1200; 
	pstrCmdString[6]=ECHO_NODIALTONE; 
	pstrCmdString[7]=ECHO_BUSY; 
	pstrCmdString[8]=ECHO_NOANSWER; 
	m_hConnected=CreateEvent(NULL,TRUE,FALSE,NULL); 
	ResetError(); 
} 
 
 
CYsATModem::~CYsATModem() 
{ 
#ifndef USER_ANSWER 
	if(m_nMode==MODE_COMMAND) 
		SendAT(CMD_ATS0); 
#endif 
	//because m_Thread->m_bAutoDelete set FALSE 
	if(m_pQueue)delete m_pQueue; 
} 
 
/*************************2001.10.30 ycat ********************************************* 
/*************************2002.04.15 ycat ********************************************* 
 
FUNCTION: BOOL CYsATModem::DialUp(LPTSTR strDial,int iTime) 
 
PURPOSE: 用AT命令建立连接 
 
PARAMETERS: 
		strDial:要拨号的号码 
		iTime:如果不为0,如果当前状态为连接状态,或线路忙(转成等待方式),等待的时间 
RETURN VALUE: 
    如果操作成功,返回TRUE,如果失败返回FALSE 
 
COMMENTS:  
	1)发送ATDXXX后,会段时间等待,连接字符串的返回, 
		如果另一边一拨号成功就发送数据,很可能会导致数据丢失 
	2)对电话号码的支持有待测试,特别字符 
**********************************************************************/ 
BOOL CYsATModem::DialUp(LPCTSTR strDial) 
{ 
	if(m_bTestMode)return TRUE; 
	if(m_nMode==MODE_UNINITIALIZE||m_nMode==MODE_UNMODEM) 
		if(m_bInit) 
		{ 
			if(!InitModem(m_nPort,m_iBaud,2,m_hWnd)) 
				return FALSE; 
		} 
	if(m_nMode==MODE_DATA) 
	{ 
		return TRUE;//have connected 
	} 
	if(m_nMode==MODE_CONNECTING)//connecting 
	{ 
		//wait connect success 
		if(WAIT_OBJECT_0==WaitForSingleObject(m_hConnected,DIALTIME_START)) 
			return TRUE;//have connected 
		return FALSE; 
	} 
	if(m_nMode!=MODE_COMMAND)//MODE_DIALING MODE_WAITRING 
		return FALSE; 
 
	CHAR strTemp[200]; 
	lstrcpy(strTemp,CMD_ATD); 
	lstrcat(strTemp,(LPCTSTR)strDial); 
	SendAT(strTemp); 
 
	return DetectConnect(); 
} 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: int CYsATModem::DetectConnect() 
 
PURPOSE: 检测连接 
 
PARAMETERS: 
RETURN VALUE: 
    如果操作成功,返回TRUE,如果失败返回FALSE 
COMMENTS:  
**********************************************************************/ 
int CYsATModem::DetectConnect() 
{ 
	if(m_nMode!=MODE_COMMAND) return FALSE; 
	ChangeMode(MODE_CONNECTING); 
	CHAR strTemp[200]; 
	Sleep(3000); 
	 
	//读字符 
	DWORD dwRead; 
	int nErr; 
	int nRet=FALSE; 
 
	Purge(PURGE_ALL); 
	TRACE("\n  Clear  \n"); 
	memset(strTemp,0,200); 
	nErr=this->ReadComm((PBYTE)strTemp,200,&dwRead,DIALTIME_START,DIALTIME_INTER); 
	TRACE(strTemp); 
/*	if(nErr!=-2) 
	{ 
		goto Exit; 
	} 
	strTemp[dwRead]='\0'; 
 
	i=CheckString(strTemp); 
	 
	//find AT command string  
	if(i==CODE_CONNECT)		nRet=TRUE; 
	else if(i==CODE_CANNTFIND)//can't fine AT command string 
	{ 
		TRACE(_TEXT("Unknow string %s\n"),strTemp); 
		goto Exit; 
	} 
	else// if(i==CODE_BUSY||i==CODE_NODIALTONE) 
	{ 
		goto Exit; 
	} 
	if(m_nMode!=MODE_CONNECTING) return m_bCD;//可能中间运行了hangup()*/ 
//Exit: 
	if(!m_bCD) 
	{ 
		SendAT(CMD_AT);//打断连接 
		Sleep(500); 
		Purge(PURGE_ALL); 
		ChangeMode(MODE_COMMAND); 
	} 
	else ChangeMode(MODE_DATA); 
	return m_bCD; 
} 
 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: BOOL InitModem(UINT nPort,HWND hWnd) 
 
PURPOSE: 生成串口文件句柄, 
		 发送AT命令查看Modem是否正常, 
		 生成一个挂起的收数线程 
 
PARAMETERS: 
		nPort:串口号,com1为1,com2为2 
		hWnd:用来接收消息的窗口 
RETURN VALUE: 
    如果操作成功,返回TRUE,如果失败返回FALSE 
 
COMMENTS:  
**********************************************************************/ 
BOOL CYsATModem::InitModem(UINT nPort,UINT uBaud,int iRingCount,HWND hWnd) 
{ 
	m_bCD=FALSE; 
	m_nRingCount=iRingCount; 
	if(!m_bTestMode) 
	{ 
		if(m_nMode!=MODE_UNINITIALIZE&&m_nMode!=MODE_UNMODEM) return TRUE; 
 
 
	} 
 
	//create comm 
	if(!Create(nPort)) 
	{ 
		SetLastError(_TEXT("Create Comm error")); 
		return FALSE; 
	} 
	if(!SetComm(uBaud)) 
	{ 
		SetLastError(_TEXT("Set comm error")); 
		return FALSE; 
	} 
 
	m_hWnd=hWnd; 
 
	//clear comm buffer 
	if(!Purge(PURGE_ALL)) 
	{ 
		return FALSE; 
	} 
	m_pQueue->Clear(); 
	if(m_bTestMode) return TRUE; 
 
	ChangeMode(MODE_UNMODEM); 
 
	int i; 
	TCHAR buffer[50]; 
	DWORD length=0; 
 
	//send ATZ0,复位命令 
	if(!SendAT(CMD_ATZ0)) 
	{ 
		return FALSE; 
	} 
	//if echo don't open then must timeout 
	i=ReadComm((PBYTE)buffer,11,&length,WAITTIME); 
 
	if(i!=1&&i!=-2) 
	{ 
		SetLastError(_TEXT("Read comm error")); 
		return FALSE; 
	} 
	buffer[length]='\0'; 
	i=CheckString(buffer); 
	if(i!=CODE_OK) 
	{ 
		SetLastError(_TEXT("Cann't find OK string")); 
		return FALSE; 
 
	} 
 
	//取消回显 
	if(!SendAT(CMD_ATE)) 
	{ 
		return FALSE; 
	} 
	i=ReadComm((PBYTE)buffer,10,&length,WAITTIME); 
	if(1!=i) 
	{ 
		SetLastError(_TEXT("Read comm error")); 
		return FALSE; 
	} 
	buffer[length]='\0'; 
	i=CheckString(buffer); 
	if(i!=CODE_OK) 
	{ 
		SetLastError(_TEXT("Cann't find OK string")); 
		return FALSE; 
	} 
 
#ifndef USER_ANSWER 
	TCHAR temp[10]; 
	lstrcpy(buffer,"ATS0="); 
	sprintf(temp,"%d",iRingCount); 
	lstrcat(buffer,temp); 
 
	//send 设置自动应答 
	SendAT(buffer); 
	ReadComm((PBYTE)buffer,6,&length,WAITTIME); 
	buffer[length]='\0'; 
	i=CheckString(buffer); 
	if(i!=CODE_OK) 
	{ 
		SetLastError(_TEXT("Set autoreply mode fail")); 
		return FALSE; 
	} 
#endif 
 
	//clear comm buffer 
	if(!Purge(PURGE_ALL)) 
	{ 
		return FALSE; 
	} 
 
	TRACE("Com%d InitModem Success \n",m_nPort); 
	ChangeMode(MODE_COMMAND); 
	 
	if(!SetEvent(EV_DSR|EV_RING|EV_RLSD))//设备就续状态改变性号,现在已经就续,如果收到这个信号表示modem出问题了 
	{ 
		SetLastError(_TEXT("Set comm event error")); 
		return FALSE; 
	} 
	AfxBeginThread(DetectModemThread,this); 
	ResetError(); 
	m_bInit=TRUE; 
	return TRUE; 
} 
 
/*************************2001.10.30 ycat ********************************************* 
BOOL CYsATModem::SendAT(LPCSTR strCmd,BOOL AddReturn) 
 
PURPOSE: 发送AT命令 
 
PARAMETERS: 
	strCmd:要发送的AT命令 
	AddReturn:指明是否要在AT命令后面加上回车 
 
RETURN VALUE: 
    如果操作成功,返回TRUE,如果失败返回FALSE 
 
COMMENTS:  
	1)大多数AT命令要加上回车符,才能运行,但+++却不同,不要加回车 
	所以不支持+++命令 
**********************************************************************/ 
BOOL CYsATModem::SendAT(LPCSTR strCmd,BOOL AddReturn) 
{ 
	//在传送data模式 
	if(m_nMode==MODE_DATA) 
	{ 
		SetLastError(_TEXT("Send AT Command error")); 
		return FALSE; 
	} 
 
	TCHAR buffer[50]; 
	lstrcpy(buffer,strCmd); 
 
	lstrcat(buffer,"\r\n");//只有+++,可以省\n 
 
	TRACE("send AT command %s\n",buffer); 
//	DWORD dw; 
 
//	WaitEvent(&dw,0); 
 
	//如果strCmd中间含有值为0的字符,将会产生不良后果 
	if(WriteComm((PBYTE)buffer,strlen(buffer))==1) 
		return TRUE; 
 
	SetLastError(_TEXT("Send AT Command error")); 
	return FALSE; 
} 
/* 
挂断连接,进入MODE_COMMAND状态 
 
后面被取消的程序挂断连接,有时不能很好运行 
*/ 
BOOL CYsATModem::HangUp() 
{ 
	if(m_bTestMode)return TRUE; 
 
	if(m_nMode==MODE_UNINITIALIZE) return TRUE; 
 
	//如果正在连接,发送任意字符,则会中断 
	if(m_nMode==MODE_CONNECTING) 
	{ 
		SendAT(CMD_AT); 
		Sleep(500); 
	} 
 
	if(!Purge(PURGE_ALL)) return FALSE; 
	if(!Clear(PURGE_ALL)) return FALSE; 
 
	if(m_nMode==MODE_COMMAND) return TRUE; 
	if(m_nMode==MODE_UNMODEM) return TRUE; 
 
 
	TCHAR buffer[50]; 
	DWORD length=0; 
	 
	if(m_Thread) 
	{ 
		if(WAIT_OBJECT_0!=WaitForSingleObject(m_Thread->m_hThread,10000)) 
		{ 
			TerminateThread(m_Thread->m_hThread,-11); 
		} 
		delete m_Thread; 
		m_Thread=NULL; 
	} 
 
	if(m_nMode!=MODE_DATA) return TRUE; 
	ResetEvent(m_hConnected); 
 
	ChangeMode(MODE_COMMAND);	 
 
	if(!Purge(PURGE_ALL)) 
		return FALSE;//comm error 
 
	Sleep(1000); 
 
	//change mode to MODE_COMMAND 
	//+++ 不用换行 
	 
	TCHAR strSend[]=_TEXT("+++"); 
	if(1!=WriteComm((PBYTE)strSend,3)) return FALSE;//comm error 
	TRACE(_TEXT("Send +++ \n")); 
	int i; 
	DWORD dwReaded; 
 
	if(-1==ReadComm((PBYTE)buffer,6,&dwReaded,WAITADDADDADDTIME)) 
		return FALSE;//comm error 
 
	buffer[dwReaded]='\0'; 
 
	i=CheckString(buffer); 
	if(i!=CODE_OK) 
	{ 
		SetLastError(_TEXT("send +++ but cann't recept OK")); 
		TRACE("1  %s\n",buffer); 
		return HangUp2(); 
	} 
 
	//hangup command 
	SendAT(CMD_ATH0);	 
 
	if(-1==ReadComm((PBYTE)buffer,6,&dwReaded,WAITATHTIME)) return FALSE; 
	buffer[dwReaded]='\0'; 
 
	i=CheckString(buffer); 
	//wait for OK 
	if(i!=CODE_OK) 
	{ 
		SetLastError(_TEXT("send ATH0 but cann't recept OK")); 
		TRACE("2  %s\n",buffer); 
		return HangUp2(); 
	} 
 
	TRACE("hang up OK!!!\n"); 
	ChangeMode(MODE_COMMAND); 
	return TRUE; 
} 
 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: BOOL CYsATModem::Clear(DWORD dwType) 
 
PURPOSE: 清除串口 
 
PARAMETERS: 
		nType的值及说明,可组合起来用 
		nType=PURGE_TXABORT Terminates all outstanding 
				overlapped write operations and returns  
				immediately, even if the write operations  
				have not been completed.  
		nType=PURGE_RXABORT Terminates all outstanding  
				overlapped read operations and returns  
				immediately, even if the read operations 
				have not been completed.  
		nType=PURGE_TXCLEAR Clears the output buffer  
				(if the device driver has one).  
		nType=PURGE_RXCLEAR Clears the input buffer  
				(if the device driver has one).  
 
RETURN VALUE: 
    如果操作成功,返回TRUE,如果失败返回FALSE 
 
COMMENTS:  
	1)读缓冲区实际上是m_pQueue里的缓冲区 
	2)PURGE_RXABORT不起作用 
**********************************************************************/ 
BOOL CYsATModem::Clear(DWORD dwType) 
{ 
	if(m_bTestMode)return Purge(dwType); 
 
	if(dwType&PURGE_RXCLEAR) 
	{ 
		if(!m_pQueue->Clear())  
		{ 
			SetLastError(_T("In clear() clear queue error")); 
			return FALSE; 
		} 
	} 
 
	if(dwType&PURGE_TXCLEAR) 
		if(!Purge(PURGE_TXCLEAR)) 
		{ 
			SetLastError(_T("In clear() clear tx buffer error")); 
			return FALSE; 
		} 
	if(dwType&PURGE_TXABORT) 
		if(!Purge(PURGE_TXABORT)) 
		{ 
			SetLastError(_T("In clear() clear tx abort error")); 
			return FALSE; 
		} 
	return TRUE; 
} 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: int CYsATModem::Write(LPCSTR lpstrWrite,DWORD dwCount) 
 
PURPOSE: 写数据 
 
PARAMETERS: 
		lpstrWrite:要写的字符串 
		dwCount: 字符串的长度 
RETURN VALUE: 
    返回1为正常 
    返回-1为失败 
    返回-4为断线 
COMMENTS:  
**********************************************************************/ 
int CYsATModem::Write(LPCSTR lpstrWrite,DWORD dwCount) 
{ 
	if(!m_bTestMode) 
	{ 
		if(m_nMode==MODE_COMMAND) return -4; 
		if(m_nMode!=MODE_DATA) return -1; 
	} 
	int nRet=CYsComm::WriteComm((PBYTE)lpstrWrite,dwCount); 
	if(nRet==1) return 1; 
	return -1; 
} 
/*************************2001.10.30 ycat ********************************************* 
FUNCTION: int CYsATModem::Read(LPTSTR lpstrRead,DWORD dwCount, 
			DWORD* dwHaveReaded,DWORD nTimeOut) 
 
PURPOSE: 读数据 
 
PARAMETERS: 
		lpstrRead:		放读出字符串的缓冲区 
		dwCount:		缓冲区的长度 
		dwHaveReaded:	实际读到的字符数 
		nTimeOut:		超时 
RETURN VALUE: 
    返回1为正常 
    返回-1为失败 
	返回-2为超时 
    返回-4为断线 
COMMENTS:  
**********************************************************************/ 
int CYsATModem::Read(LPTSTR lpstrRead,DWORD dwCount, 
			DWORD* dwHaveReaded,DWORD nTimeOut) 
{ 
	if(m_bTestMode) 
	{ 
		return CYsComm::ReadComm((PBYTE)lpstrRead,dwCount,dwHaveReaded,nTimeOut); 
	} 
	 
	if(m_nMode==MODE_COMMAND) return -4; 
	if(m_nMode!=MODE_DATA) return -1; 
 
	int nRet; 
	DWORD dwTimeAfter; 
	DWORD dwTimeUsed; 
	DWORD dwTimeBefore; 
 
	for(DWORD i=0;iGet((PBYTE)(lpstrRead+i),nTimeOut)) 
		{ 
			//TRACE("Read2 Timeout %ld \n",nTimeOut); 
			nRet=-2;//超时 
			goto Exit; 
		} 
		dwTimeAfter=GetTickCount(); 
		dwTimeUsed=dwTimeAfter-dwTimeBefore; 
 
		//断线 
		if(m_nMode==MODE_COMMAND) 
		{ 
			nRet=-3; 
			goto Exit; 
		} 
 
		if(dwTimeUsed>nTimeOut) 
		{ 
			if(iGetCount(); 
} 
 
 
//return state describe string  
CString CYsATModem::GetStateDesc() 
{ 
	if(m_bTestMode) return "测试状态"; 
	switch(m_nMode) 
	{ 
	case MODE_UNINITIALIZE: 
		return _TEXT("串口有问题"); 
	case MODE_UNMODEM: 
		return _TEXT("Modem有问题"); 
	case MODE_COMMAND: 
		return _TEXT("可以拨号"); 
	case MODE_CONNECTING: 
		return _TEXT("正在建立连接"); 
	case MODE_DATA: 
		return _TEXT("远程Modem连接");//(如不成功,返回2状态) 
	default: 
		return _TEXT("Unknow state!"); 
	} 
} 
//如果HangUp()不成功,只好调用HangUp2()了 
BOOL CYsATModem::HangUp2() 
{ 
	if(m_bTestMode)return TRUE; 
	TRACE("\n\n In Hangup 2\n\n"); 
	ChangeMode(MODE_UNINITIALIZE); 
	Sleep(1000); 
	return InitModem(m_nPort,m_iBaud,m_nRingCount,m_hWnd); 
} 
 
void CYsATModem::ChangeMode(int newMode) 
{ 
	if(m_nMode!=newMode) 
	{ 
		if(m_hWnd) 
			PostMessage(m_hWnd,WM_MODEM_CHANGE,newMode,m_nPort); 
		m_nMode=newMode; 
		TRACE("Mode Change =%d \n",m_nMode); 
 
	} 
}