📄 fax.cpp
字号:
speed, // link speed
fileopen = FALSE, // receive file not open
dcs_received = FALSE, // DCS not yet received
i, // work variable
error = 0, // error number
dleflag = FALSE, // DLE sequence found flag
loop = TRUE; // loop until complete
FILE *faxfile; // fax file
char c; // work character
ULONG pagelen, // length of received page
reclen, // offset of page record length
et, // elapsed time
st; // work for timer
enum RcvStates // FAX receive states
{
PhaseA, // phase A - make connection
AwaitCall, // wait for a call
AnswerCall, // answer incoming call
SendCSI, // send our CSI frame, if needed
PhaseB, // negotiate session parameters
GetFrames, // get HDLC frames
SetSpeed, // set the link speed
PrepTCF, // prepare to receive TCF
FailConnTCF, // fail the TCF connect
RcvTCF, // receive/test TCF
RcvTCF1, // get rest of TCF
FailTCF, // fail the TCF
Confirm, // confirm training check frame
PhaseC, // receive the FAX data
RcvPage, // receive 1 page of data
EndPage, // page complete
PhaseD, // post message procedure
PhaseE, // call is done .. disconnect
RcvError, // error during receive
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, "wb+")) // q. receive file open ok?
== NULL)
{ // a. no ..
error = 9; // .. set the error code
state = RcvError; // .. and declare an error
}
fileopen = TRUE; // show the file is open
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 = RcvError; // .. declare the error
continue;
}
state = AwaitCall; // else .. wait for a ring
Display_Msg(2); // update the status
break; // end this state
case AwaitCall: // wait for a call
rc = wait_for(FAX_RING, // wait for a RING from modem
FAX_RING, 10);
if (rc > 0) // q. RING arrive?
{ // a. yes ..
state = AnswerCall; // .. go answer the call
continue;
}
if (rc == -1) // q. user press ESC?
state = UserCan; // a. yes .. exit now
break; // else .. continue waiting
case AnswerCall: // answer incoming call
Display_Msg(3); // update the status
cp->Write(FAX_ANSWER); // send the answer command
rc = wait_for(FAX_CONN, // wait for a carrier
FAX_NO_CARR, 60);
if (--rc == 0) // q. connect?
{
state = SendCSI; // a. yes .. send our CSI
connected = TRUE; // .. show we're connected
}
else // else ..
{
state = RcvError; // .. process general error
error = 2; // .. show the error type
}
break; // .. next state
case SendCSI: // send our CSI frame
Display_Msg(4); // update the status
rc = Send_CSI(); // .. send our ID
if (rc) // q. error?
state = RcvError; // a. yes .. declare the error
else
state = PhaseB; // select next state
break;
case PhaseB: // negotiate session parameters
Display_Msg(5); //
state = ((rc = Send_DIS()) != 0) ? // q. DIS send go ok?
RcvError : // a. no .. declare error
GetFrames; // else .. get frames
break;
case GetFrames: // 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 = RcvError; // .. 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 = RcvError; // .. declare an error
continue;
}
switch(hmsg.fax_ctl_fld) // process based on message type
{
case FAX_FCF_TSI: // transmitting subscriber ID
Display_Msg(6); // update the status
Reverse_Bytes(hmsg.data, // .. reset the bytes to normal
20);
hmsg.data[20] = 0; // .. end string in zero
strcpy((char *) fh.ff_id, // .. copy it to file header
(char *) hmsg.data);
Display_ID("Called by:", // .. and display the remote ID
hmsg.data);
break;
case FAX_FCF_DCN: // disconnect
Display_Msg(16); // update the status
state = PhaseE; // .. and hang up
continue;
case FAX_FCF_DCS: // digital command signal
Display_Msg(7); // update the status
memcpy(fh.ff_dcs, hmsg.data,// .. move the DCS to the header
hmsg.len - 7);
dcs_received = 1; // show we got DCS
break;
}
if (hmsg.ctl_fld == FAX_CTL_FF) // q. final frame?
{ // a. yes ..
state = SetSpeed; // .. set link speed
fseek(faxfile, 0L, SEEK_SET); // go to start of file
fwrite(&fh, 128, 1, faxfile); // .. and write the header
}
break;
case SetSpeed: // set the link speed
if (dcs_received == 0) // q. dcs received?
{ // a. no ..
error = 4; // .. show the error
state = RcvError; // .. and go to error state
continue; // .. continue with next state
}
switch (fh.ff_dcs[1] & 0x30) // get modulation value
{
case 0x00: // q. speed 2400?
speed = 24; // a. yes . set speed
i = 44; // .. and message
break;
case 0x10: // q. speed 4800?
speed = 48; // a. yes .. set speed
i = 43; // .. and message
break;
case 0x30: // q. speed 7200?
speed = 72; // a. yes .. set speed
i = 42; // .. and message
break;
case 0x20: // q. speed 9600?
speed = 96; // a. yes .. set speed
i = 41; // .. and message
break;
}
Display_Msg(i); // display speed message
state = PrepTCF; // next, prepare to test link
break;
case PrepTCF: // prepare to receive TCF
rc = Data_Mode(RECEIVE, speed); // start the receive
if (rc == 1) // q. did connection fail?
state = FailConnTCF; // a. yes.. fail TCF connect
else if (rc != 0) // q. other failure?
state = RcvError; // a. yes .. declare an error
else
{
state = RcvTCF; // receive training check frame
Display_Msg(9); // update the status
}
break;
case FailConnTCF: // fail the TCF connect
rc = Send_Hmsg(FINAL, // send failure to train
FAX_FCF_FTT, 0);
if (rc) // q. retrain send fail?
state = RcvError; // a. yes .. declare an error
else
state = GetFrames; // get a new set of frames
break;
case RcvTCF: // receive/test TCF
rc = Get_Char(&c, 5); // wait a max of 5 secs for data
if (rc != 0) // q. any error
{ // a. yes ..
state = RcvError; // .. declare an error
continue; // .. and continue processing
}
if ((UCHAR) c == 0) // q. zero byte?
state = RcvTCF1; // a. yes .. receive the rest
break;
case RcvTCF1: // get rest of TCF
st = get_time(); // get time of day in ticks
for(;;) // get characters
{
rc = Get_Char(&c, 1); // get a character
if (rc != 0) // q. any error?
{ // a. yes ..
Purge(cp, 1); // .. purge the comm line
error = 7; // .. TCF too short
state = RcvError; // .. declare an error
break; // .. and exit loop
}
if (c != 0) // q. end of sequence?
break; // a. yes .. exit loop
}
if (rc != 0) // q. was there an error?
continue; // a. yes .. continue process
et = elapsed_time(st); // calculate elapsed time
if ((et < 24) || (et > 31)) // q. 1.5 seconds +/- 10%?
{ // a. yes ..
Purge(cp, 1); // .. purge the comm line
state = FailTCF; // .. declare train failure
continue; // .. and continue loop
}
rc = wait_for(FAX_NO_CARR, // wait for no carrier
FAX_ERR, 5) - 1; // .. or other information
if (rc != 0) // q. NO CARRIER received?
{ // a. no ..
state = RcvError; // .. declare receieve error
continue; // .. and continue loop
}
state = Confirm; // else .. confirm TCF
break; // .. and continue processing
case FailTCF: // fail the TCF
Display_Msg(19); // update the status
rc = Send_Hmsg(FINAL, // send failure to train
FAX_FCF_FTT, 0);
if (rc) // q. retrain send fail?
state = RcvError; // .. declare an error
else
state = GetFrames; // get a new set of frames
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -