www.pudn.com > C_modem16.zip > MODEM.CPP


#include "stdafx.h" 
#include "modem.h" 
 
 
 
void MTIMER::set(DWORD t) 
{ 
  settime=GetTickCount()+t; 
} 
 
BOOL MTIMER::ifzero() 
{ 
  if(GetTickCount()>=settime) return TRUE; 
  return FALSE; 
} 
 
 
void MTIMER::delay(DWORD t) 
{ 
  set(t); 
  while(!ifzero()); 
} 
 
 
//------------------------------------------------------------------------- 
 
 
 
MODEM::ANSINFO info[MESSAGE_NUM]= 
{ 
  {"OK",           TRUE,   M_OK}, 
  {"ERROR",        TRUE,   M_ERROR}, 
  {"NO DIAL",      TRUE,   M_NOTONE}, 
  {"BUSY",         TRUE,   M_BUSY}, 
  {"NO ANSWER",    TRUE,   M_NOANSWER}, 
  {"RING",         TRUE,   M_RING}, 
  {"CONNECT",      FALSE,  M_CONNECT}, 
  {"PROTOCOL:",    FALSE,  M_PROTOCOL}, 
  {"COMPRESSION:", FALSE,  M_COMPRESS}, 
  {"CARRIER",      FALSE,  M_CARRIER}, 
  {"NO CARRIER",   TRUE,   M_NODCD}, 
  {"RELIABLE",     FALSE,  M_RELIABLE} 
}; 
 
 
MODEM::CONFIGBUFF config[3]= 
{ 
  {"&D2","&E4&Q0"}, 
  {"&D2","&Q5&K1W1S37=0S95=44S46=138S36=5"}, 
  {"",""} 
}; 
 
 
MODEM::MODEM() 
{ 
  nCid=-1; 
  IfRx=FALSE; 
  IfTx=FALSE; 
  err=0; 
  IfCom=FALSE; 
  IfModem=FALSE; 
  IfCommand=FALSE; 
  IfTransFile=FALSE; 
  ansinfo=info; 
  configbuff=config; 
} 
 
 
int MODEM::IniCom(HINSTANCE hInst,HWND hwnd,char *string) 
{ 
  static char com[10]; 
  int i; 
//  FARPROC lpfnTimerProc; 
  IfCom=FALSE; 
  if(nCid>=0){ 
  	CloseComm(nCid); 
//  	KillTimer(hwindow,MODEM_TIMER); 
  } 
  if(toupper(string[0])!='C') return -1; 
  for(i=0;i<4;i++)com[i]=string[i]; 
  com[4]=0; 
  nCid=OpenComm(com,IN_QUEUE_SIZE,OUT_QUEUE_SIZE); 
  if(nCid<0){ 
	 err=-1; 
	 return err; 
  } 
//  sprintf(p,"%s:  %s,N,8,1",com,rate); 
  err=BuildCommDCB(string,&dcb); 
  if(err<0) return err; 
  dcb.fOutxCtsFlow=1; 
  dcb.fOutxDsrFlow=0; 
  dcb.fRtsflow=1; 
  dcb.fDtrflow=0; 
  dcb.fInX=0; 
  dcb.fOutX=0; 
  err=SetCommState(&dcb); 
  if(err<0) return err; 
  SetCommEventMask(nCid,EV_CTSS); 
//  EnableCommNotification(nCid,hwnd,-1,-1); 
  hwindow=hwnd; 
//  hInstance=hInst; 
//  lpfnTimerProc=MakeProcInstance((FARPROC)ModemTimerProc,hInstance); 
//  SetTimer(hwindow,MODEM_TIMER,50,(TIMERPROC)lpfnTimerProc); 
  IfCom=TRUE; 
  return 0; 
//  ConfigModem(0); 
} 
 
void MODEM::ChangeBaud(char *p) 
{ 
	UINT baud; 
	if(nCid<0) return; 
	baud=(UINT)atol(p); 
	dcb.BaudRate=baud; 
	SetCommState(&dcb); 
} 
 
void MODEM::OnTimer() 
{ 
	static int r,i,j; 
	static BYTE buf[100]; 
	static char buf1[100]; 
	static char *p; 
	static int state=LEADING_CR; 
	if(!IfCom) return; 
	r=ReadComm(nCid,buf,100); 
	r=abs(r); 
	id=M_UNKNOW; 
	if(r){ 
		IfRx=TRUE; 
		SendMessage(hwindow,WM_CHARSARRIVE,r,(DWORD)buf); 
		for(i=0;ipointr+packet->paklong>=packet->bottom){ 
	 f.read(packet->data,PAKBUFSIZE); 
	 packet->bottom=f.gcount(); 
//	 if(f) return -1;       //-1 mean file error 
	 if(!packet->bottom) return 0;     //0 mean no more data to read 
	 packet->pointr=0; 
  } 
  else packet->pointr+=packet->paklong;    //ÐÞÕýÖ¸Õë 
  packet->paklong=(soh==YSOH)?1024:128;    //ÐÞÕýpaklong 
  if(packet->pointr+packet->paklong>packet->bottom){ 
	 soh=XSOH;                              //·ÀÖ¹Ô½½ç 
	 packet->paklong=128; 
	 if(packet->pointr+packet->paklong>packet->bottom) 
		for(i=packet->bottom;ipointr+packet->paklong;i++) 
		  packet->data[i]=0;                 //ÎļþβÇåÁã 
  } 
  packet->soh=soh; 
  packet->pnum1=(BYTE)(packet->paknum&0x00ff); 
  packet->pnum2=(BYTE)(~packet->pnum1); 
  packet->total+=packet->paklong; 
  packet->paknum++; 
  return packet->paklong; 
} 
 
void MODEM::SendCkSum() 
{ 
  static int i; 
  static BYTE s; 
  for(s=i=0;ipaklong;i++) 
	 s+=packet->data[i+packet->pointr]; 
  packet->ckval=s; 
} 
 
 
int MODEM::Except(int exceptnum, int &count,int maxcount) 
{ 
  int code=CONTINUE; 
  switch(exceptnum){ 
	 case E_USRCAN: 
			FlushComm(nCid,0);                      //Clear send buffer 
			timer.delay(2000);	//need delaying to care for the receiver 
			code=BREAK; 
			WriteAChar(CAN); 
//			timer.delay(200); 
			break; 
//Send Error 
	 case E_NODCD: 
			FlushComm(nCid,0);                      //Clear send buffer 
			code=BREAK; 
			SEND("No DCD!"); 
			break; 
	 case E_FILEMTY: 
			SEND("File is empty!"); 
			break; 
	 case E_NOACK: 
			++count; 
			sprintf(dispbuf,"ACK is not detected. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			ClearReceBuf(); 
			break; 
	 case E_RCVCAN: 
			SEND("Receiver cancel!"); 
			FlushComm(nCid,0);                      //Clear send buffer 
			code=BREAK; 
			break; 
	 case E_BADPAK: 
			++count; 
			sprintf(dispbuf,"Bad packet(receive NAK). Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			ClearReceBuf(); 
			break; 
	 case E_EOF: 
			code=E_EOF; 
			count=0; 
			break; 
	 case E_SNDOK: 
			code=E_EOF; 
			count=0; 
			SEND("Send is successful"); 
			break; 
	 case E_DSKREAD: 
			SEND("Read disk error!"); 
			code=BREAK; 
			break; 
	 case E_LASTACK: 
         SEND("Last ACK is not received"); 
			FlushComm(nCid,0);                      //Clear send buffer 
			WriteAChar(CAN); 
//			timer.delay(500); 
			break; 
//Receive Error 
	 case E_NOSOH: 
			++count; 
			sprintf(dispbuf,"SOH is not received. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			WriteAChar(NAK); 
			break; 
	 case E_DSKWRITE: 
			FlushComm(nCid,0);                      //Clear send buffer 
			WriteAChar(CAN); 
			SEND("Write disk error!"); 
//			timer.delay(300); 
			code=BREAK; 
			break; 
	 case E_SNDCAN: 
			SEND("Sender cancel!"); 
			code=BREAK; 
			break; 
	 case E_RCVOK: 
			FlushComm(nCid,0);                      //Clear send buffer 
			code=E_RCVOK; 
			WriteAChar(ACK); 
			SEND("Receive is successful"); 
//			timer.delay(300); 
			break; 
	 case E_BADSOH: 
			++count; 
			sprintf(dispbuf,"Bad soh. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			ClearReceBuf(); 
			WriteAChar(NAK); 
			break; 
	 case E_NODATA: 
			++count; 
			sprintf(dispbuf,"No data is received. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			WriteAChar(NAK); 
			break; 
	 case E_PAKSEQ: 
			SEND("Packet sequence number is error!"); 
			ClearReceBuf(); 
			code=BREAK; 
			break; 
	 case E_PAKNUM: 
			++count; 
			sprintf(dispbuf,"Paknum2 is error. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			ClearReceBuf(); 
			WriteAChar(NAK); 
			break; 
	 case E_SNDACK: 
			++count; 
			sprintf(dispbuf,"Sender missed last ack. Try %d",count); 
         SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			ClearReceBuf(); 
			WriteAChar(ACK); 
			break; 
	 case E_BADCKV: 
			++count; 
			sprintf(dispbuf,"Invalid checkvalue received. Try %d",count); 
			SEND(dispbuf); 
			FlushComm(nCid,0);                      //Clear send buffer 
			WriteAChar(NAK); 
			break; 
 
  } 
  if(count>=maxcount) code=BREAK; 
  if(code!=CONTINUE) timer.delay(300); 
  return code; 
} 
 
//return TRUE if success 
int MODEM::SendAFile(fstream &f) 
{ 
  int errcode=CONTINUE; 
  int errcnt=0; 
  int paknum; 
  int ckvmode=-1; 
  int i; 
  BYTE c; 
  IfTransFile=TRUE; 
  FlushComm(nCid,0);                      //Clear send buffer 
  EscapeCommFunction(nCid,SETDTR);        //Open DTR 
  FlushComm(nCid,1);                      //Clear receive buffer 
  packet=new PACKET; 
  paknum=ReadPacket(XSOH,f); 
  SEND("Sending file ..."); 
  if(paknum<=0) errcode=Except(E_DSKREAD,errcnt,MAXCOUNT); 
  while(errcode==CONTINUE && ckvmode==-1){ 
	 c=0; 
	 Readn(&c,1,4000,2000,TRUE); 
	 if(err==USER_BREAK){ 
		errcode=Except(E_USRCAN,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==NO_DCD){ 
		errcode=Except(E_NODCD,errcnt,MAXCOUNT); 
		break; 
	 } 
	 switch (c){ 
		case NAK: 
			  ckvmode=SUM; 
			  SendCkSum(); 
			  break; 
		case CAN: 
			  errcode=Except(E_RCVCAN,errcnt,MAXCOUNT); 
			  break; 
	 } 
  } 
  errcnt=0; 
  while(errcode==CONTINUE){ 
	 switch(paknum){ 
		case 0: 
			  errcode=Except(E_EOF,errcnt,MAXCOUNT); 
			  continue; 
		case -1: 
			  errcode=Except(E_DSKREAD,errcnt,MAXCOUNT); 
			  continue; 
	 } 
	 FlushComm(nCid,0);                      //Clear send buffer 
	 FlushComm(nCid,1);                      //Clear receive buffer 
	 Writen((BYTE *)packet,3); 
	 Writen(packet->data+packet->pointr,packet->paklong); 
	 WriteAChar((BYTE)packet->ckval); 
	 c=0; 
	 ReadAChar(c,60000L,TRUE); 
	 if(err==USER_BREAK){ 
		errcode=Except(E_USRCAN,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==NO_DCD){ 
		errcode=Except(E_NODCD,errcnt,MAXCOUNT); 
		break; 
	 } 
	 switch(c){ 
		case ACK: 
			  sprintf(dispbuf,"Send %lu bytes",packet->total); 
			  SEND(dispbuf); 
			  paknum=ReadPacket(XSOH,f); 
			  if(paknum>0) SendCkSum(); 
			  break; 
		case NAK: 
			  errcode=Except(E_BADPAK,errcnt,MAXCOUNT); 
			  break; 
		case CAN: 
			  errcode=Except(E_RCVCAN,errcnt,MAXCOUNT); 
			  break; 
		default: 
			  errcode=Except(E_NOACK,errcnt,MAXCOUNT); 
	 } 
  } 
  if(errcode==E_EOF){ 
	 errcnt=0; 
	 c=0; 
	 for(i=0;ipaklong=(packet->soh==YSOH)?1024:128; 
  for(cksum=i=0;ipaklong;i++) 
	 cksum+=packet->data[packet->pointw+i]; 
  return cksum==packet->data[packet->pointw+packet->paklong]; 
} 
 
 
int MODEM::WritePacket(int flag,fstream &f) 
{ 
  packet->paklong=(packet->soh==YSOH)?1024:128; 
  packet->total+=packet->paklong; 
  if(flag>=0) packet->pointw+=packet->paklong; 
  if(packet->pointw+packet->paklong+10>PAKBUFSIZE||flag<0){ 
	 f.write(packet->data,packet->pointw); 
//	 if(!f) return 0; 
	 packet->pointw=0; 
  } 
  packet->paknum++; 
  packet->pnum1=(BYTE)(packet->paknum&0x00ff); 
  packet->pnum2=(BYTE)(~packet->pnum1); 
  return packet->paklong; 
} 
 
 
 
int MODEM::ReceAFile(fstream &f) 
{ 
  BYTE c; 
  int errcnt=0; 
  int errcode=CONTINUE; 
  static BYTE pnum[2]; 
  IfTransFile=TRUE; 
  SEND("Receive file ..."); 
  FlushComm(nCid,0);                      //Clear send buffer 
  EscapeCommFunction(nCid,SETDTR);        //Open DTR 
  FlushComm(nCid,1);                      //Clear receive buffer 
  packet=new PACKET; 
  WriteAChar(NAK); 
  while(errcode==CONTINUE){ 
	 c=0; 
	 Readn(&c,1,5000,5000,TRUE); 
	 if(err==USER_BREAK){ 
		errcode=Except(E_USRCAN,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==NO_DCD){ 
		errcode=Except(E_NODCD,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==TIME_OUT){ 
		errcode=Except(E_NOSOH,errcnt,MAXNOSOH); 
		continue; 
	 } 
	 if(((packet->soh=c)!=XSOH)&&((packet->soh=c)!=YSOH)){ 
		switch(c){ 
		  case EOT: 
				 if(!WritePacket(-1,f)) errcode=Except(E_DSKWRITE,errcnt,MAXCOUNT); 
				 else errcode=Except(E_RCVOK,errcnt,MAXCOUNT); 
				 break; 
		  case CAN: 
				 errcode=Except(E_SNDCAN,errcnt,MAXCOUNT); 
				 break; 
		  default: 
				 errcode=Except(E_BADSOH,errcnt,MAXCOUNT); 
		} 
		continue; 
	 } 
	 packet->soh=c; 
	 Readn(pnum,2,1000,1000,TRUE); 
	 if(err==USER_BREAK){ 
		errcode=Except(E_USRCAN,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==NO_DCD){ 
		errcode=Except(E_NODCD,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==TIME_OUT){ 
		errcode=Except(E_NODATA,errcnt,MAXCOUNT); 
		continue; 
	 } 
	 if(pnum[0]!=packet->pnum1) 
		if(pnum[0]==packet->pnum1-1){ 
		  errcode=Except(E_SNDACK,errcnt,MAXCOUNT); 
		  continue; 
		} 
		else{ 
		  errcode=Except(E_PAKSEQ,errcnt,MAXCOUNT); 
		  break; 
		} 
	 if(pnum[1]!=packet->pnum2){ 
		errcode=Except(E_PAKNUM,errcnt,MAXCOUNT); 
		break; 
	 } 
	 Readn(packet->data+packet->pointw,129,1000,1000,TRUE); 
	 if(err==USER_BREAK){ 
		errcode=Except(E_USRCAN,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==NO_DCD){ 
		errcode=Except(E_NODCD,errcnt,MAXCOUNT); 
		break; 
	 } 
	 if(err==TIME_OUT){ 
		errcode=Except(E_NODATA,errcnt,MAXCOUNT); 
		continue; 
	 } 
	 if(!ReceCkSum()){ 
		errcode=Except(E_BADCKV,errcnt,MAXCOUNT); 
		continue; 
	 } 
	 if(!WritePacket(1,f)){ 
		errcode=Except(E_DSKWRITE,errcnt,MAXCOUNT); 
		break; 
	 } 
	 sprintf(dispbuf,"Receive %lu bytes",packet->total); 
	 SEND(dispbuf); 
	 FlushComm(nCid,0);                      //Clear send buffer 
	 WriteAChar(ACK); 
  } 
  FlushComm(nCid,0);                      //Clear send buffer 
  FlushComm(nCid,1);                      //Clear receive buffer 
  delete packet; 
  IfTransFile=FALSE; 
  if(errcode==E_RCVOK)SEND("Transmission succeed"); 
 // else SEND("Transmission fail"); 
  return (errcode==E_RCVOK); 
}