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);
}