📄 fax.cpp
字号:
// ******************************************************************** //
// //
// FAX.CPP //
// Copyright (c) 1993, Michael Holmes and Bob Flanders //
// C++ Communication Utilities //
// //
// Chapter 7: Facsimile Reception and Transmission //
// Last changed in chapter 7 //
// //
// This file contains the functions to implement the Fax class. //
// This class contains all of the support for receiving and //
// transmitting facsimilies. //
// //
// ******************************************************************** //
#define FAX_CLASS1 "AT +FCLASS=1\r" // enter FAX class 1 mode
#define FAX_TX_HDLC "AT +FTH=3\r" // enter HDLC transmit mode
#define FAX_RX_HDLC "AT +FRH=3\r" // enter HDLC recieve mode
#define FAX_TX_DATA "AT +FTM=%d\r" // enter FAX transmit mode
#define FAX_RX_DATA "AT +FRM=%d\r" // enter FAX receive mode
#define FAX_TX_SPD "AT +FTM=?\r" // get FAX transmit speeds
#define FAX_RX_SPD "AT +FRM=?\r" // get FAX receive speeds
#define FAX_SILENT "AT +FRS=8\r" // 80 ms of silence
#define FAX_SILENT1 "AT +FRS=20\r" // 200 ms of silence
#define FAX_CLASS1 "AT +FCLASS=1\r" // enter FAX class 1 mode
#define FAX_MODEM "AT +FCLASS=0\r" // return to non-FAX mode
#define FAX_ANSWER "AT A\r" // answer an incoming call
#define FAX_HANGUP "AT H\r" // disconnect from line
#define FAX_DIAL "AT DT" // dial command
#define FAX_OK "\r\nOK\r\n" // OK response
#define FAX_ERR "\r\nERROR\r\n" // ERROR response
#define FAX_NO_CARR "\r\nNO CARRIER\r\n" // NO CARRIER response
#define FAX_CONN "\r\nCONNECT\r\n" // CONNECT response
#define FAX_RING "\r\nRING\r\n" // RING message
#define FAX_SETMDM "AT Q0 V1 E0\r" // set modem parameters
#define FAX_RSTMDM "AT Z\r" // reset modem
#define FAX_ADDR 0xff // value for address byte
#define FAX_CTL 0xC0 // value for control field
#define FAX_CTL_FF 0xC8 // control field + final frame
#define FAX_FCF_DIS 0x01 // digital ID signal
#define FAX_FCF_CSI 0x02 // called subscriber ID
#define FAX_FCF_NSF 0x04 // non-standard facilities
#define FAX_FCF_DCS 0xC1 // digital command signal
#define FAX_FCF_TSI 0xC2 // transmitting subscriber ID
#define FAX_FCF_CFR 0x21 // confirmation to receive
#define FAX_FCF_FTT 0x22 // failure to train
#define FAX_FCF_EOM 0xF1 // end of message
#define FAX_FCF_MPS 0xF2 // multipage signal
#define FAX_FCF_EOP 0xF4 // end of procedure
#define FAX_FCF_MCF 0x31 // message confirmation
#define FAX_FCF_DCN 0xDF // disconnect
#define FINAL 8 // final frame
#define NON_FINAL 0 // non-final frame
#define TRANSMIT 0 // connect in send mode
#define RECEIVE 1 // connect in receive mode
#define FAX_T9600 0x80 // 9600 transmit
#define FAX_T7200 0x40 // 7200 transmit
#define FAX_T4800 0x20 // 4800 transmit
#define FAX_T2400 0x10 // 2400 transmit
#define FAX_R9600 0x08 // 9600 receive
#define FAX_R7200 0x04 // 7200 receive
#define FAX_R4800 0x02 // 4800 receive
#define FAX_R2400 0x01 // 2400 receive
/* ******************************************************************** *
*
* Fax specific variables, structs, etc.
*
* ******************************************************************** */
char dis_msg[] = // DIS frame data
{ 0, // first byte:
// not G1, G2
0x70, // second byte:
// T.4 operation
// 9600/7200/4800/2400 bps
// 3.85 lines/mm
// one-dimensional coding
0x02 // third byte:
}; // 1728 pels/215mm
// A4 paper only
// 40ms receive time
char dcs_msg[] = // DCS frame data
{ 0, // first byte:
// not G1, G2
0x40, // second byte:
// T.4 operation
// speed to be set
// 3.85 lines/mm
// one-dimensional coding
0x02 // third byte:
}; // 1728 pels/215mm
// A4 paper only
// 40ms per line
struct HDLC_msg // format of HDLC message
{
UCHAR addr; // address byte (always 0xff)
UCHAR ctl_fld; // control field
UCHAR fax_ctl_fld; // FAX control field (FCF)
UCHAR data[253]; // optional data
int len; // received frame length
};
struct FxStat // Fax status structure
{
void *f_parm; // Fax init parameter
char f_msg[50]; // message string
char *f_ptr; // pointer to message
};
struct FxHdr // Fax file header structure
{
char ff_type[3]; // file type (G3)
char ff_dcs[16]; // DCS for transfer
char ff_id[21]; // original station ID
char ff_reserved[88]; // reserved space
};
/* ******************************************************************** *
*
* Fax class definition
*
* ******************************************************************** */
class Fax : Protocol
{
public:
Fax (Comm *, // Fax instance contstructor
char *, // Comm instance, station ID
int (*)(int, // status routine
struct FxStat *),
void *); // FxStat parameter
~Fax(void); // destructor
void Send(char *, char *), // send a fax
Receive(char *); // receive a fax
private:
Comm *cp; // Comm instance
int Send_CSI(void), // send optional CSI
HDLC_Mode(int), // set HDLC tx|rx mode
Data_Mode(int, int), // set data tx|rx mode
Get_Speeds(void), // get tx and rx speeds
Get_Line(char *, int), // get a CR-terminate line
Get_Char(char *, int), // get a character
Rcv_Hmsg(void), // receive an HDLC frame
Send_Our_ID(UCHAR), // send our ID to remote
Send_Hmsg(UCHAR,UCHAR,int), // send an HDLC frame
Send_TSI(void), // send TSI frame to remote
Send_DIS(void), // send DIS frame to remote
Send_DCS(void), // send DCS frame to remote
Init_Modem(void), // initialize modem
(*stat)(int, // status routine pointer
struct FxStat *),
connected; // HDLC link active
UINT oldparms, // old communications parameters
pbi; // page buffer index
long oldspeed; // old commuincations speed
void Reverse_Bytes(UCHAR *, int),// reverse bits in char array
Display_ID(char *, UCHAR *),// display remote station ID
Display_Msg(int), // display a fax_msgs message
Reset_Modem(void); // reset modem and comm parms
UCHAR speeds, // speeds supported
// 1... .... 9600 transmit
// .1.. .... 7200
// ..1. .... 4800
// ...1 .... 2400
// .... 1... 9600 receive
// .... .1.. 7200
// .... ..1. 4800
// .... ...1 2400
*pagebuf, // page buffer area
Reverse_Byte(UCHAR value); // reverse bits in a byte
char *station; // our station id
struct FxStat fs; // fax status structure
struct FxHdr fh; // fax file header structure
union { // accesss HDLC msg as chars
struct HDLC_msg hmsg; // HDLC message area
UCHAR cmsg[256]; // .. same as char array
};
};
/* ********************************************************************
*
* Fax -- Fax instance constuctor
*
* ********************************************************************/
Fax::Fax(Comm *ci, // comm instance
char *sid, // .. our station ID (telno)
int (*sr)(int, struct FxStat *), // .. status routine
void *w) // .. fax status parameter
{
cp = ci; // save comm instance pointer
stat = sr; // .. and status routine
station = sid; // .. and station ID
connected = 0; // no HDLC connection active
fs.f_parm = w; // save fax status parameter
strcpy(fh.ff_type, "G3"); // preset the file type
memset(fh.ff_reserved, ' ', // .. and clear reserved area
sizeof(fh.ff_reserved));
pagebuf = new UCHAR[1024]; // allocate page buffer
}
/* ********************************************************************
*
* ~Fax -- destructor
*
* ********************************************************************/
Fax::~Fax(void) // Fax destructor
{
delete pagebuf; // free pagebuf memory
}
/* ******************************************************************** *
*
* Init_Modem -- initialize the fax modem
*
* returns: -2 = User pressed ESC
* -1 - Timeout
* 0 = successful; OK response from modem
* 1 = ERROR response from modem
*
* ******************************************************************** */
int Fax::Init_Modem(void)
{
int rc, // return code
i; // work counter for loops
char buf[80], // work buffer for speeds
*c, // work pointer
*t; // token work pointer
cp->Write("\r"); // send a <CR> to modem
Purge(cp, 2); // .. kill any receive messages
oldspeed = cp->GetSpeed(); // get the old link speed
oldparms = cp->Set8n(); // .. and old comm parameters
// .. while setting 8,n,1
cp->SetBPS(19200L); // set new comm speed
cp->SetBPS(9600L); // set new comm speed
for (rc = i = 0; (rc == 0) && i++ < 3;) // try three times
{
cp->Write(FAX_SETMDM); // set the modem parameters
rc = wait_for(FAX_OK, FAX_ERR, 2); // wait for OK response
}
if (rc < 0) // q. user cancellation?
return(rc - 1); // a. yes .. return error
speeds = 0; // reset speeds supported
cp->Write(FAX_CLASS1); // place modem in CLASS 1 mode
rc = wait_for(FAX_OK, FAX_ERR, 5) - 1; // wait for modem response
if (rc) // q. modem respond ok?
return(rc); // a. no .. tell the caller
cp->Write(FAX_TX_SPD); // retrieve transmit speeds
rc = Get_Line(buf, 5); // kill the first CR
rc = Get_Line(buf, 5); // get the line from the mode
if (rc) // q. any error?
return(rc); // a. yes.. return w/error
Purge(cp, 1); // kill additional characters
c = (*buf == '\n') ? buf+1 : buf; // select start point
while ((t = strtok(c, ",")) != 0) // while there are tokens
{
c = NULL; // continue searching buf
i = atoi(t); // get the token's value
switch(i) // for various values..
{
case 24: // 2400 found
speeds |= FAX_T2400; // .. set set the speed flag
break;
case 48: // 4800 found
speeds |= FAX_T4800; // .. set set the speed flag
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -