📄 fax.cpp
字号:
case Confirm: // confirm training check frame
Display_Msg(10); // update the status
rc = Send_Hmsg(FINAL, // send the confirmation
FAX_FCF_CFR, 0);
if (rc != 0) // q. confirmation go ok?
{
state = RcvError; // a. no .. show the error
continue; // .. continue processing
}
state = PhaseC; // start receiving FAX
break;
case PhaseC: // receive the FAX data
rc = Data_Mode(RECEIVE, speed); // start receiving the FAX
if (rc != 0) // q. receive start ok?
{
state = RcvError; // a. no .. show the error
continue; // .. continue processing
}
Display_Msg(11); // update the status
state = RcvPage; // receive a page of data
dleflag = FALSE; // set no DLE seen yet
pbi = 0; // reset the page buffer index
pagelen = 0; // .. and no page data yet
fseek(faxfile, 0L, SEEK_END); // go to end of file
reclen = ftell(faxfile); // .. save the position
fwrite(&pagelen, 4, 1, faxfile); // .. write the page's length
break;
case RcvPage: // receive 1 page of data
rc = Get_Char(&c, 1); // get a character
if (rc != 0) // q. receive ok?
{ // a. no ..
state = RcvError; // .. declare an error
continue; // .. and continue processing
}
pagebuf[pbi++] = c; // save the character
pagelen++; // increment bytes in page
if (pbi == 1024) // q. buffer full?
{ // a. yes ..
fwrite(pagebuf, 1024, 1, // .. write out a page
faxfile);
pbi = 0; // reset page buffer index
}
if (dleflag) // q. previous char DLE?
{ // a. yes ..
dleflag = FALSE; // .. reset the flag
if (c == ETX) // q. DLE ETX sequence?
{ // a. yes ..
state = EndPage; // .. process end of page
Display_Msg(12); // update the status
}
}
else if (c == DLE) // q. char a DLE?
dleflag = TRUE; // a. yes .. show true
break; // continue processing
case EndPage: // Page complete
rc = wait_for(FAX_NO_CARR, // we should now have no carrier
FAX_ERR, 5) - 1;
if (pbi) // buffer contain data?
fwrite(pagebuf, pbi, 1, // a. yes.. write out a page
faxfile);
fseek(faxfile, reclen, SEEK_SET); // set postion to length record
fwrite(&pagelen, 4, 1, faxfile); // update the page's length
fseek(faxfile, 0L, SEEK_END); // .. return to end of file
if (rc != 0) // q. correct response?
{ // a. no ..
state = RcvError; // .. declare an error
continue;
}
state = PhaseD; // start post message procedure
break;
case PhaseD: // post message procedure
rc = Rcv_Hmsg(); // get the next message
if (rc != 0) // q. correct response?
{ // a. no ..
state = RcvError; // .. declare an error
continue;
}
i = hmsg.fax_ctl_fld; // save the response
rc = Send_Hmsg(FINAL, // send the final frame
FAX_FCF_MCF, 0); // .. message confirmation
if (rc != 0) // q. correct response?
{ // a. no ..
state = RcvError; // .. declare an error
continue;
}
switch(i) // based on the response..
{
case FAX_FCF_MPS: // multi-page signal
Display_Msg(13); // update the status
state = PhaseC; // .. receive next page
break;
case FAX_FCF_EOM: // end of message
Display_Msg(14); // update the status
state = PhaseB; // .. renegotiate & continue
break;
case FAX_FCF_EOP: // end of procedure
Display_Msg(15); // update the status
state = PhaseE; // .. disconnect now
break;
case FAX_FCF_DCN: // disconnect
Display_Msg(16); // update the status
state = PhaseE; // .. and hang up
continue;
default:
state = RcvError; // unknown response
break;
}
break; // continue processing
case PhaseE: // call is done .. disconnect
cp->Write(FAX_HANGUP); // hangup the modem
state = ExitFax; // .. and exit the fax receive
break;
case RcvError: // error during receive
Display_Msg(17); // update the status
if (rc == -2) // q. user cancellation?
{ // a. yes ..
state = UserCan; // .. show the reason
continue; // .. continue processing
}
else if (error) // q. error set?
{ // a. yes ..
fs.f_ptr = fax_errors[error]; // .. set the message pointer
(stat)(2, &fs); // .. and display it
}
else if (rc == -1) // q. timeout?
Display_Msg(20); // a. yes .. show the message
else if (rc == 1) // q. unexpected response?
Display_Msg(21); // a. yes .. tell the user
state = ExitFax; // .. set new state
break;
case UserCan: // user cancelled transmission
Display_Msg(18); // update the status
state = ExitFax; // .. set new state
break;
case ExitFax: // exit FAX receive
if (fileopen) // q. fax file open?
fclose(faxfile); // a. yes .. close the file
Reset_Modem(); // reset the modem
loop = FALSE; // .. end the loop
break; // .. and return to caller
}
}
/* ********************************************************************
*
* Send -- Send a Facsimile
*
* ******************************************************************** */
void Fax::Send(char *faxname, // fax file name
char *telno) // telephone number
{
int rc = 0, // return code
speed, // link speed
nextspeed, // next link speed
fileopen = FALSE, // receive file not open
dis_received = FALSE, // DIS not yet received
i, // work variable
error = 0, // error number
loop = TRUE; // loop until complete
FILE *faxfile; // fax file
char dis[16], // DIS received
csi[21], // CSI received
c, // work character
w; // work register
ULONG pagelen, // length of received page
st; // work for elapsed time
enum SndStates // FAX send states
{
PhaseA, // phase A - make connection
PhaseB, // get HDLC frames
SetSpeed, // set the link speed
SendTSI, // select speed, send ID & DCS
SendTCF, // send the TCF
GetConfTCF, // get TCF confirmation
PhaseC, // send the document
SendPage, // send a page of data
PhaseD, // post message process
AnotherPage, // another page to send
AllSent, // send complete
PhaseE, // disconnect
SndError, // error during send
UserCan, // user cancelled transmission
ExitFax // exit FAX receive
} state;
strcpy(fh.ff_id, " "); // blank out the ID string
state = PhaseA; // start in Phase A
if ((faxfile = fopen(faxname, "rb")) // q. send file open ok?
== NULL)
{ // a. no ..
error = 9; // .. set the error code
state = SndError; // .. and declare an error
}
fread(&fh, 128, 1, faxfile); // read the header
if (strcmp(fh.ff_type, "G3")) // q. G3 file?
{ // a. no ..
error = 13; // .. show invalid format
state = SndError; // .. and declare an error
}
fileopen = TRUE; // show the file is open
fread(&pagelen, 4, 1, faxfile); // read in the first page length
while(loop) // top of state machine
switch(state) // perform next state
{
case PhaseA: // phase A - make connection
Display_Msg(1); // update the status
if ((rc = Init_Modem()) != 0) // q. modem init ok?
{
error = 1; // a. no .. exit now
state = SndError; // .. declare the error
continue;
}
Display_Msg(22); // update the status
cp->Write(FAX_DIAL); // send the dial command
cp->Write(telno); // .. and the phone number
cp->Write('\r'); // .. and finish the command
rc = wait_for(FAX_CONN, // wait for a connection
FAX_NO_CARR, 120);
if (--rc) // q. any error
{ // a. yes ..
if (rc == 1) // q. connection fail?
error = 10; // a. yes .. show connect failed
state = SndError; // declare an error
continue; // .. go to next state
}
state = PhaseB; // get frames
connected = TRUE; // ... show we are connected
break;
case PhaseB: // get HDLC frames
if ((rc = Rcv_Hmsg()) != 0) // q. any error getting a frame?
if (rc < 0) // a. yes .. timeout or ESC?
{ // a. yes ..
error = 3; // .. error receiving HDLC frame
state = SndError; // .. leave with error.
continue; // .. continue process
}
else // else .. NO CARRIER
{
cp->Write(FAX_SILENT1); // wait for 200ms silence
rc = wait_for(FAX_OK, // wait for the OK response
FAX_ERR,
10) - 1;
state = SetSpeed; // .. and set the speed
}
if (rc) // q. any error yet?
{ // a. yes ..
state = SndError; // .. declare an error
continue;
}
switch(hmsg.fax_ctl_fld) // process based on message type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -