Hylafax Developers Mailing List Archives

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

[hylafax-devel] a bundle of my patches, try #3 :-)



Here is the updated set of my changes against current CVS; I have separated
them into the different independent parts to make Robert happy :-) (well,
it's third attempt to commit this code; I hope it will be finally
successful :-)) But it may cause some problems: first, I had to split the
monolitic diff by hands, so could miss/break something, and second, they
cannot be automatically applied in sequence (although any single part
can). So be extremely careful!

OK, after the caution let's return to our business :-) Here is the list of
changes and appropriate diffs:

General Class1 changes
----------------------

        Decoding of T.30 DIS frame

Due to the bug DIS decording routine failed on the short frames (with
"remote is not T.4 compatible" error).

        HDLC timeout

Orginal code supposed that HDLC flags is present in DCE-supplied data (in
responce to AT+FRH=3) and set timeouts wrong way. This caused connection
sometimes to be incorrectly terminated.

        Number of training attempts

If the training attempt was unsuccessful, original code tried every speed
twice, i.e.
14400->14400->12000->12000->9600->...
I believe it was only wasting the time. Not each speed is tried once:
14400->12000->9600->...



General Class 2.0 changes
-------------------------

        Class 2.0 PPM query

Explicit status query to distinguish between RTN and PIN.



RTN related changes
-------------------
        Reencoding first EOL and removing extra RTC/EOL in the end of TIFF data

Reencode TIFF data so that first EOL does not contain zero fill bits
(prohibited by T.4) and remove trailing RTC/EOL if present (will be appended
later if necessary).

        Class2SendRTC now affects Class 2.0

According to Class 2.0 specs DCE sends RTC itself, so I have made
Class2SendRTC config parameter (with default value "no") affect Class2.0
operation as well as Class2 one.

        RTNHandlingMethod parameter

Specifies how to react to RTN signal, received from the remote;
one of ``Retransmit'', ``Giveup'' and ``Ignore''. ``Retransmit''
assumes that the page is not sent succesfully if RTN signal has been received.
Hylafax will made up to 2 additional attempts to send the page,
decreasing signalling rate and retraining. If RTN is still there,
it will place up to 2 additional calls. So if the remote always respond with
RTN, the page will be send 9 times. Although this algorithm comply with
T.30 specs and was originally implemented by Sam Leffler as the only
possible choice, real fax machines behave completely different. There is a
non-written rule among fax developers, that RTN means ``over and out'' -- hang
up immediately and never try to send the same page to the same destination
again. That is because RTN usually indicates problems with flow control,
incorrectly encoded T.4 data, incompatibility between local and remote
equipment etc., but very rarely is caused by the real noise on the line.
This ``over and out'' behaviour can be activated by ``Giveup'' value.
There is also third option, not so radical as ``Giveup''. Yes, we will never
retransmit the page, but we can try to send the next page, and let the
remote to decide what to do (accept our decision or hang up). Thus one page will
(or will not) be missed but we have a chance to successfully send all other pages.
This behaviour can be activated by ``Ignore'' value.

        Class1 RTN alrogithm

Adapted to use RTNHandlingMethod parameter, and work the same (right) way
as in Class2/2.0 mode.

        Class2 RTN alrogithm

Adapted to use RTNHandlingMethod parameter


Default config values
---------------------

These changes affect only parameters' default value, i.e value used if the
parameter is not present in config.<modem> file. If the parameter's value
is explicitly specified, it will be used anyway.

Now all (I hope) Class* and Modem* parameters have reasonable defaults so
that most (if not all) modems should work "out of the box" with no Class*
and Modem* entries in their config.<modem> files. Of course, if you need
extra features (adaptive answer, custom dial commands etc.), you still have
to append necessary parameters yourself.

        ModemType

If not present, sequence Class 2.0->Class2->Class1 is tried until supported 
fax class is found. Buggy USR modems are immediately switched to
Class1. (Again, if you don't like it, just add "ModemType: Class2.0" entry
to your config.<modem>)

        ModemFlowControl

Default value is changed to "XONXOFF" which is supported by any modem and
is activated after AT+FCLASS=2 and AT+FCLASS=2.0. BTW, software flow control
is quite enough due to the half-duplex nature of fax protocol.

        ModemSendFillOrder
        ModemRecvFillOrder

Now are correctly set for Class1, Class2, Class2.0. Special "Multitech"
case (the only modem known to me, which uses RecvFillOrder=LSB2MSB in Class2) is
(should be) handled properly. People who own Multitech, can you check if it
works with the patch applied? (just comment out ModemSendFillOrder &
ModemRecvFillOrder in your config and see if it still works).



Updated config templates
------------------------

For the modems I've tested. (Zyxel & USR)

Well, I should also say, that default config/Class* templates (those that
faxaddmodem script uses if it cannot identify the modem) are completely
broken -- no neccessary Modem* entries and absolutely useless Class*
ones. *No* unidentified Class2 modem will work with faxaddmodem-generated
config and Hylafax without my patches!

I have not changed these "template" because after my patches there is no
need in them -- above config defaults do the job. If the changes are
commited, you can simply wipe "templates" out :-)



Hope to hear from you soon,
Dmitry



Index: hylafax/faxd/Class1.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class1.c++,v
retrieving revision 1.3
diff -u -r1.3 Class1.c++
--- Class1.c++	1999/08/23 11:19:31	1.3
+++ Class1.c++	2000/06/05 10:09:59
@@ -396,8 +406,7 @@
 }
 
 /*
- * Receive an HDLC frame.  The timeout is against
- * the receipt of the HDLC flags; the frame itself must
+ * Receive an HDLC frame. The frame itself must
  * be received within 3 seconds (per the spec).
  * If a carrier is received, but the complete frame
  * is not received before the timeout, the receive
@@ -408,20 +417,22 @@
 {
     int c;
     /*
-     * Search for HDLC frame flags.  The
-     * timeout is to reception of the flags.
+     * The spec says that a frame that takes between
+     * 2.55 and 3.45 seconds to be received may be
+     * discarded; we also add some time for DCE
+     * to detect and strip flags. 
      */
+    startTimeout(5000);
+    /*
+     * Strip HDLC frame flags. This is not needed,
+     * (according to the standard DCE does the job),
+     * be we leave this legacy code unchanged
+     * for sure - D.B.
+     */
     do {
 	c = getModemChar(0);
     } while (c != EOF && c != 0xff);
-    stopTimeout("waiting for HDLC flags");
-    if (c == 0xff) {			// flags received
-	/*
-	 * The spec says that a frame that takes between
-	 * 2.55 and 3.45 seconds to be received may be
-	 * discarded; we use 3.1 seconds as a compromise.
-	 */
-	startTimeout(3100);
+    if (c == 0xff) {			// address field received
 	do {
 	    if (c == DLE) {
 		c = getModemChar(0);
@@ -430,8 +441,8 @@
 	    }
 	    frame.put(frameRev[c]);
 	} while ((c = getModemChar(0)) != EOF);
-	stopTimeout("receiving HDLC frame data");
     }
+    stopTimeout("receiving HDLC frame data");
     if (wasTimeout()) {
 	abortReceive();
 	return (false);
@@ -638,8 +649,14 @@
     frame.reset();
     startTimeout(ms);
     bool readPending = atCmd(rhCmd, AT_NOTHING);
-    if (readPending && waitFor(AT_CONNECT,0))
-	return recvRawFrame(frame);		// NB: stops inherited timeout
+    if (readPending && waitFor(AT_CONNECT,0)){
+        stopTimeout("waiting for HDLC flags");
+        if (wasTimeout()){
+            abortReceive();
+            return (false);
+        }
+        return recvRawFrame(frame);
+    }
     stopTimeout("waiting for v.21 carrier");
     if (readPending && wasTimeout())
 	abortReceive();
Index: hylafax/faxd/Class1Send.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class1Send.c++,v
retrieving revision 1.3
diff -u -r1.3 Class1Send.c++
--- Class1Send.c++	2000/05/15 13:23:43	1.3
+++ Class1Send.c++	2000/06/05 10:10:20
@@ -103,9 +103,7 @@
     time_t start = Sys::now();
     HDLCFrame frame(conf.class1FrameOverhead);
 
-    startTimeout(conf.t2Timer);
     bool framerecvd = recvRawFrame(frame);
-    stopTimeout("receiving id frame");
     for (;;) {
 	if (framerecvd) {
 	    /*
@@ -465,7 +471,16 @@
 	 */
 	params.br = curcap->br;
 	dcs = (dcs &~ DCS_SIGRATE) | curcap->sr;
-	int t = 2;
+        /*
+	 * Set the number of train attemps on the same
+	 * modulation; having set it to 1 we immediately drop
+	 * the speed if the training has been failed.
+	 * This parameter is not specified by T.30
+	 * (the algorith left implementation defined),
+	 * so we choose the exact value according to our
+	 * common sense.
+	 */
+	int t = 1;
 	do {
 	    protoTrace("SEND training at %s %s",
 		modulationNames[curcap->mod],
@@ -540,7 +555,7 @@
 	    pause(conf.class1TrainingRecovery);
 	} while (--t > 0);
 	/*
-	 * Two attempts at the current speed failed, drop
+	 * (t) attempts at the current speed failed, drop
 	 * the signalling rate to the next lower rate supported
 	 * by the local & remote sides and try again.
 	 */
@@ -846,6 +867,7 @@
 	    return (false);
     }
     emsg = "No response to MPS or EOP repeated 3 tries";
+    protoTrace(emsg);
     return (false);
 }
 
Index: hylafax/faxd/HDLCFrame.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/HDLCFrame.c++,v
retrieving revision 1.2
diff -u -r1.2 HDLCFrame.c++
--- HDLCFrame.c++	1999/06/13 07:41:04	1.2
+++ HDLCFrame.c++	2000/06/05 10:10:45
@@ -105,10 +105,10 @@
 HDLCFrame::getDataWord() const
 {
     u_int n = getFrameDataLength();
-    u_int w = (n > 1) ? (*this)[3] : 0;
-    if (n > 2) w = (w<<8)|(*this)[4];
-    if (n > 3) w = (w<<8)|(*this)[5];
-    if (n > 4) w = (w<<8)|(*this)[6];
+    u_int w = (n >= 1) ? (*this)[3] : 0;
+    if (n >= 2) w = (w<<8)|(*this)[4];
+    if (n >= 3) w = (w<<8)|(*this)[5];
+    if (n >= 4) w = (w<<8)|(*this)[6];
     return w;
 }
 
@@ -116,9 +116,9 @@
 HDLCFrame::getDIS() const
 {
     u_int n = getFrameDataLength();
-    u_int dis = (n > 1) ? (*this)[3] : 0;
-    dis <<= 8; if (n > 2) dis |= (*this)[4];
-    dis <<= 8; if (n > 3) dis |= (*this)[5];
+    u_int dis = (n >= 1) ? (*this)[3] : 0;
+    dis <<= 8; if (n >= 2) dis |= (*this)[4];
+    dis <<= 8; if (n >= 3) dis |= (*this)[5];
     return dis;
 }
 
@@ -126,9 +126,9 @@
 HDLCFrame::getXINFO() const
 {
     u_int n = getFrameDataLength();
-    u_int xinfo = (n > 4 && ((*this)[5] & 0x1)) ? (*this)[6] : 0;
-    xinfo <<= 8; if (n > 5 && (xinfo & 0x100)) xinfo |= (*this)[7];
-    xinfo <<= 8; if (n > 6 && (xinfo & 0x100)) xinfo |= (*this)[8];
-    xinfo <<= 8; if (n > 7 && (xinfo & 0x100)) xinfo |= (*this)[9];
+    u_int xinfo = (n >= 4 && ((*this)[5] & 0x1)) ? (*this)[6] : 0;
+    xinfo <<= 8; if (n >= 5 && (xinfo & 0x100)) xinfo |= (*this)[7];
+    xinfo <<= 8; if (n >= 6 && (xinfo & 0x100)) xinfo |= (*this)[8];
+    xinfo <<= 8; if (n >= 7 && (xinfo & 0x100)) xinfo |= (*this)[9];
     return xinfo;
 }

Index: hylafax/faxd/Class20.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class20.c++,v
retrieving revision 1.2
diff -u -r1.2 Class20.c++
--- Class20.c++	1999/06/13 07:41:01	1.2
+++ Class20.c++	2000/06/05 10:10:23
@@ -162,12 +162,24 @@
 	    case AT_FHNG:
 		if (!isNormalHangup())
 		    return (false);
-		/* fall thru... */
-	    case AT_OK:				// page data good
-		ppr = PPR_MCF;			// could be PPR_RTP/PPR_PIP
+		ppr = PPR_MCF;
 		return (true);
-	    case AT_ERROR:			// page data bad
-		ppr = PPR_RTN;			// could be PPR_PIN
+	    case AT_OK:
+	    case AT_ERROR:
+		/*
+		 * Despite of the (wrong) comment above,
+		 * we do explicit status query e.g. to
+		 * distinguish between RTN and PIN 
+		 */
+		{
+		    fxStr s;
+		    if(!atQuery("AT+FPS?", s) ||
+		       sscanf(s, "%u", &ppr) != 1){
+		        protoTrace("MODEM protocol botch (\"%s\"), %s",
+		    		   (const char*)s, "can not parse PPR");
+		        return (false);		// force termination
+		    }
+		}
 		return (true);
 	    case AT_EMPTYLINE:
 	    case AT_TIMEOUT:

Index: hylafax/faxd/Class1Send.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class1Send.c++,v
retrieving revision 1.3
diff -u -r1.3 Class1Send.c++
--- Class1Send.c++	2000/05/15 13:23:43	1.3
+++ Class1Send.c++	2000/06/05 10:10:20
@@ -276,6 +274,7 @@
 	    tracePPR("SEND recv", ppr);
 	    switch (ppr) {
 	    case FCF_RTP:		// ack, continue after retraining
+            ignore:
 		params.br = (u_int) -1;	// force retraining above
 		/* fall thru... */
 	    case FCF_MCF:		// ack confirmation
@@ -306,22 +305,29 @@
 		emsg = "Remote fax disconnected prematurely";
 		return (send_retry);
 	    case FCF_RTN:		// nak, retry after retraining
-		if ((++ntrys % 2) == 0) {
-		    /*
-		     * Drop to a lower signalling rate and retry.
-		     */
-		    if (params.br == BR_2400) {
-			emsg = "Unable to transmit page"
-			       " (NAK at all possible signalling rates)";
-			return (send_retry);
-		    }
-		    --params.br;
-		    curcap = NULL;	// force sendTraining to reselect
-		}
-		if (!sendTraining(params, 3, emsg))
-		    return (send_retry);
-		morePages = true;	// force continuation
-		next = params;		// avoid retraining above
+                switch( conf.rtnHandling ){
+                case RTN_IGNORE:
+                    goto ignore; // ignore error and try to send next page
+                                 // after retraining
+                case RTN_GIVEUP:
+                    emsg = "Unable to transmit page"
+                        " (giving up after RTN)";
+                    return (send_failed); // "over and out"
+                }
+                // case RTN_RETRANSMIT
+                if (++ntrys >= 3) {
+                    emsg = "Unable to transmit page"
+                        " (giving up after 3 attempts)";
+                    return (send_retry);
+                }
+                if (params.br == BR_2400) {
+                    emsg = "Unable to transmit page"
+                        "(NAK at all possible signalling rates)";
+                    return (send_retry);
+                }
+                next.br--;
+                curcap = NULL;	        // force sendTraining to reselect
+                morePages = true;	// retransmit page
 		break;
 	    case FCF_PIN:		// nak, retry w/ operator intervention
 		emsg = "Unable to transmit page"
@@ -734,6 +749,12 @@
 	    totdata = totdata+ts - (dp-data);
 	} else
 	    dp = data;
+
+        /*
+         * correct broken Phase C (T.4) data if neccessary 
+         */
+        correctPhaseCData(dp, &totdata, fillorder, params);
+
 	/*
 	 * Send the page of data.  This is slightly complicated
 	 * by the fact that we may have to add zero-fill before the
Index: hylafax/faxd/Class20.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class20.c++,v
retrieving revision 1.2
diff -u -r1.2 Class20.c++
--- Class20.c++	1999/06/13 07:41:01	1.2
+++ Class20.c++	2000/06/05 10:10:23
@@ -131,7 +131,7 @@
     bool rc = sendPageData(tif, pageChop);
     if (!rc)
 	abortDataTransfer();
-    else
+    else if( conf.class2SendRTC )
 	rc = sendRTC(params.is2D());
     if (flowControl == FLOW_XONXOFF)
 	setXONXOFF(getInputFlow(), FLOW_XONXOFF, ACT_DRAIN);
Index: hylafax/faxd/Class2Recv.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class2Recv.c++,v
retrieving revision 1.2
diff -u -r1.2 Class2Recv.c++
--- Class2Recv.c++	1999/06/13 07:41:01	1.2
+++ Class2Recv.c++	2000/06/05 10:10:26
@@ -212,6 +212,12 @@
 	 */
 	if (hostDidCQ)
 	    ppr = isQualityOK(params) ? PPR_MCF : PPR_RTN;
+#if 0
+        /*
+	 * RTN debug code: always respond with RTN to sending facsimile
+	 */
+        ppr = PPR_RTN;
+#endif
 	if (ppr & 1)
 	    TIFFWriteDirectory(tif);	// complete page write
 	else
Index: hylafax/faxd/Class2Send.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class2Send.c++,v
retrieving revision 1.4
diff -u -r1.4 Class2Send.c++
--- Class2Send.c++	2000/05/15 13:23:43	1.4
+++ Class2Send.c++	2000/06/05 10:10:28
@@ -250,6 +250,7 @@
 		case PPR_MCF:		// page good
 		case PPR_PIP:		// page good, interrupt requested
 		case PPR_RTP:		// page good, retrain requested
+                ignore:
 		    countPage();	// bump page count
 		    notifyPageSent(tif);// update server
 		    if (pph[2] == 'Z')
@@ -276,6 +277,15 @@
 		    transferOK = true;
 		    break;
 		case PPR_RTN:		// page bad, retrain requested
+                    switch( conf.rtnHandling ){
+                    case RTN_IGNORE:
+                        goto ignore; // ignore error and trying to send next page
+                    case RTN_GIVEUP:
+                        emsg = "Unable to transmit page"
+                            " (giving up after RTN)";
+                        goto failed; // "over and out"
+                    }
+                    // case RTN_RETRANSMIT
 		    if (++ntrys >= 3) {
 			emsg = "Unable to transmit page"
 			       " (giving up after 3 attempts)";
@@ -387,6 +397,12 @@
 	    totdata = totdata+ts - (dp-data);
 	} else
 	    dp = data;
+
+        /*
+         * correct broken Phase C (T.4) data if necessary
+         */
+        correctPhaseCData(dp, &totdata, fillorder, params);
+
 	beginTimedTransfer();
 	rc = putModemDLEData(dp, (u_int) totdata, bitrev, getDataTimeout());
 	endTimedTransfer();
Index: hylafax/faxd/FaxModem.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/FaxModem.c++,v
retrieving revision 1.3
diff -u -r1.3 FaxModem.c++
--- FaxModem.c++	2000/05/15 13:23:44	1.3
+++ FaxModem.c++	2000/06/05 10:10:39
@@ -634,4 +633,188 @@
 {
     if (curreq)
 	server.notifyPageSent(*curreq, TIFFFileName(tif));
+}
+
+/*
+ * Phase C data correction
+ */
+
+#include "G3Decoder.h"
+#include "G3Encoder.h"
+#include "StackBuffer.h"
+#include "Class2Params.h"
+
+class MemoryDecoder : public G3Decoder {
+private:
+    u_char*     bp;
+    u_int       width;
+    u_int       byteWidth;
+    u_long      cc;
+    
+    u_int fillorder;
+    bool is2D;
+    
+    u_char*     endOfData;      // used by cutExtraRTC
+
+    tiff_runlen_t*
+                runs;
+    u_char*     rowBuf;
+
+    int		decodeNextByte();
+public:
+    MemoryDecoder(u_char* data, u_int wid, u_long n,
+                  u_int fillorder, bool twoDim);
+    ~MemoryDecoder();
+    u_char* current() { return bp; }
+    void fixFirstEOL();
+    u_char* cutExtraRTC();
+};
+
+MemoryDecoder::MemoryDecoder(u_char* data, u_int wid, u_long n,
+                             u_int order, bool twoDim)
+{
+    bp         = data;
+    width      = wid;
+    byteWidth  = howmany(width, 8);
+    cc         = n;
+    
+    fillorder  = order;
+    is2D       = twoDim;
+
+    runs      = new tiff_runlen_t[2*width];      // run arrays for cur+ref rows
+    rowBuf    = new u_char[byteWidth];
+    setupDecoder(fillorder, is2D);
+    setRuns(runs, runs+width, width);
+}
+MemoryDecoder::~MemoryDecoder()
+{
+    delete rowBuf;
+    delete runs;
+}
+
+int
+MemoryDecoder::decodeNextByte()
+{
+    if (cc == 0)
+	raiseRTC();			// XXX don't need to recognize EOF
+    cc--;
+    return (*bp++);
+}
+
+#ifdef roundup
+#undef roundup
+#endif
+#define	roundup(a,b)	((((a)+((b)-1))/(b))*(b))
+
+/*
+ * TIFF Class F specs say:
+ *
+ * "As illustrated in FIGURE 1/T.4 in Recommendation T.4 (the Red
+ * Book, page 20), facsimile documents begin with an EOL (which in
+ * Class F is byte-aligned)..."
+ *
+ * This is wrong! "Byte-aligned" first EOL means extra zero bits
+ * which are not allowed by T.4. Reencode first row to fix this
+ * "byte-alignment".
+ */
+void MemoryDecoder::fixFirstEOL()
+{
+    fxStackBuffer result;
+    G3Encoder enc(result);
+    enc.setupEncoder(fillorder, is2D);
+    
+    memset(rowBuf, 0, byteWidth*sizeof(u_char)); // clear row to white
+    if(!RTCraised()) {
+        u_char* start = current();
+        (void)decodeRow(rowBuf, width);
+        /*
+         * syncronize to the next EOL and calculate pointer to it
+         * (see detailed explanation of look_ahead in TagLine.c++)
+         */
+        (void)isNextRow1D();
+        u_int look_ahead = roundup(getPendingBits(),8) / 8;
+        u_int decoded = current() - look_ahead - start;
+
+        enc.encode(rowBuf, width, 1);
+        u_int encoded = result.getLength();
+            
+        while( encoded < decoded ){
+            result.put((char) 0);
+            encoded++;
+        }
+        if( encoded == decoded ){
+            memcpy(start, (const char*)result, encoded);
+        }
+    }
+}
+
+
+/*
+ * TIFF Class F specs say:
+ *
+ * "Aside from EOL's, TIFF Class F files contain only image data. This
+ * means that the Return To Control sequence (RTC) is specifically
+ * prohibited..."
+ *
+ * Nethertheless Ghostscript and possibly other TIFF Class F writers
+ * append RTC or single EOL to the last encoded line. Remove them.
+ */
+u_char* MemoryDecoder::cutExtraRTC()
+{
+    u_char* start = current();
+    
+    /*
+     * We expect RTC near the end of data and thus
+     * do not check all image to save processing time.
+     * It's safe because we will resync on the first 
+     * encountered EOL.
+     *
+     * NB: We expect G3Decoder::data==0 and
+     * G3Decoder::bit==0 (no data in the accumulator).
+     * As we cannot explicitly clear the accumulator
+     * (bit and data are private), cutExtraRTC()
+     * should be called immediately after
+     * MemoryDecoder() constructing.
+     */
+    const u_long CheckArea = 20;
+    if( cc > CheckArea ){
+        bp += (cc-CheckArea);
+        cc = CheckArea;
+    }
+        
+    endOfData = NULL;
+    if(!RTCraised()) {
+        /*
+         * syncronize to the next EOL and calculate pointer to it
+         * (see detailed explanation of look_ahead in TagLine.c++)
+         */
+        (void)isNextRow1D();
+        u_int look_ahead = roundup(getPendingBits(),8) / 8;
+        endOfData = current() - look_ahead;
+        for (;;) {
+            if( decodeRow(NULL, width) ){
+                /*
+                 * endOfData is now after last good row. Thus we correctly handle
+                 * RTC, single EOL in the end, or no RTC/EOL at all
+                 */
+                endOfData = current();
+            }
+        }
+    }
+    return endOfData;
+}
+
+void
+FaxModem::correctPhaseCData(u_char* buf, u_long* pBufSize,
+                            u_int fillorder, const Class2Params& params)
+{
+    MemoryDecoder dec1(buf, params.pageWidth(), *pBufSize, fillorder, params.is2D());
+    dec1.fixFirstEOL();
+    /*
+     * We have to construct new decoder. See comments to cutExtraRTC().
+     */
+    MemoryDecoder dec2(buf, params.pageWidth(), *pBufSize, fillorder, params.is2D());
+    u_char* endOfData = dec2.cutExtraRTC();
+    if( endOfData )
+        *pBufSize = endOfData - buf;
 }
Index: hylafax/faxd/FaxModem.h
===================================================================
RCS file: /cvsroot/hylafax/faxd/FaxModem.h,v
retrieving revision 1.3
diff -u -r1.3 FaxModem.h
--- FaxModem.h	2000/05/15 13:23:44	1.3
+++ FaxModem.h	2000/06/05 10:10:42
@@ -40,6 +40,10 @@
 class FaxFont;
 class FaxServer;
 
+// NB: these would be enums in the FaxModem class
+//     if there were a portable way to refer to them!
+typedef unsigned int RTNHandling;       // RTN signal handling method 
+
 /*
  * This is an abstract class that defines the interface to
  * the set of modem drivers.  Real drivers are derived from
@@ -133,7 +139,18 @@
     bool	setupTagLineSlop(const Class2Params&);
     u_int	getTagLineSlop() const;
     u_char*	imageTagLine(u_char* buf, u_int fillorder, const Class2Params&);
+/*
+ * Correct if neccessary Phase C (T.4) data (remove extra RTC etc.)
+ */
+    void        correctPhaseCData(u_char* buf, u_long* pBufSize,
+                                  u_int fillorder, const Class2Params& params);
 public:
+    enum {
+        RTN_RETRANSMIT = 0,         // retransmit page after RTN until MCF/MPS
+        RTN_GIVEUP     = 1,         // immediately abort
+        RTN_IGNORE     = 2,         // ignore error and send next page
+    };
+
     virtual ~FaxModem();
 
     bool isFaxModem() const;
Index: hylafax/faxd/G3Encoder.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/G3Encoder.c++,v
retrieving revision 1.2
diff -u -r1.2 G3Encoder.c++
--- G3Encoder.c++	1999/06/13 07:41:03	1.2
+++ G3Encoder.c++	2000/06/05 10:10:44
@@ -71,10 +71,13 @@
 G3Encoder::encode(const void* vp, u_int w, u_int h)
 {
     u_int rowbytes = howmany(w, 8);
+    bool firstEOL = true;
 
     while (h-- > 0) {
-	if (bit != 4)					// byte-align EOL
-	    putBits(0, (bit < 4) ? bit+4 : bit-4);
+        if( firstEOL )                                  // according to T.4 first EOL 
+            firstEOL = false;                           // should not be aligned
+        else if (bit != 4)
+	    putBits(0, (bit < 4) ? bit+4 : bit-4);      // byte-align other EOLs
 	if (is2D)
 	    putBits((EOL<<1)|1, 12+1);
 	else
Index: hylafax/faxd/ModemConfig.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/ModemConfig.c++,v
retrieving revision 1.4
diff -u -r1.4 ModemConfig.c++
--- ModemConfig.c++	2000/05/11 15:32:41	1.4
+++ ModemConfig.c++	2000/06/05 10:10:48
@@ -213,6 +213,7 @@
     class2SendRTC	= false;		// default per Class 2 spec
     setVolumeCmds("ATM0 ATL0M1 ATL1M1 ATL2M1 ATL3M1");
     recvDataFormat	= DF_ALL;		// default to no transcoding
+    rtnHandling         = FaxModem::RTN_RETRANSMIT; // retransmit until MCF/MPS
 }
 
 void
@@ -462,6 +463,37 @@
     return (df);
 }
 
+bool
+ModemConfig::findRTNHandling(const char* cp, RTNHandling& rh)
+{
+    static const struct {
+	const char* name;
+	RTNHandling rh;
+    } rhnames[] = {
+	{ "RETRANSMIT", FaxModem::RTN_RETRANSMIT },
+	{     "GIVEUP", FaxModem::RTN_GIVEUP },
+	{     "IGNORE", FaxModem::RTN_IGNORE },
+	{  "H_POLLACK", FaxModem::RTN_IGNORE }, // inventor's name as an alias :-)
+    };
+    for (u_int i = 0; i < N(rhnames); i++)
+	if (valeq(cp, rhnames[i].name)) {
+	    rh = rhnames[i].rh;
+	    return (true);
+	}
+    return (false);
+}
+
+u_int
+ModemConfig::getRTNHandling(const char* cp)
+{
+    RTNHandling rh;
+    if (!findRTNHandling(cp, rh)) {
+	configError("Unknown RTN handling method \"%s\", using RETRANSMIT", cp);
+	rh = FaxModem::RTN_RETRANSMIT;   // default
+    }
+    return (rh);
+}
+
 void
 ModemConfig::parseCID(const char* rbuf, CallerID& cid) const
 {
@@ -500,6 +532,8 @@
 	minSpeed = getSpeed(value);
     else if (streq(tag, "recvdataformat"))
 	recvDataFormat = getDataFormat(value);
+    else if (streq(tag, "rtnhandlingmethod"))
+	rtnHandling = getRTNHandling(value);
     else
 	return (false);
     return (true);
Index: hylafax/faxd/ModemConfig.h
===================================================================
RCS file: /cvsroot/hylafax/faxd/ModemConfig.h,v
retrieving revision 1.2
diff -u -r1.2 ModemConfig.h
--- ModemConfig.h	1999/06/13 07:41:04	1.2
+++ ModemConfig.h	2000/06/05 10:10:50
@@ -39,11 +39,13 @@
     void	setVolumeCmds(const fxStr& value);
     u_int	getSpeed(const char* value);
     u_int	getDataFormat(const char* value);
+    u_int       getRTNHandling(const char* cp);
 
     static bool findRate(const char*, BaudRate&);
     static bool findATResponse(const char*, ATResponse&);
     static bool findFlow(const char*, FlowControl&);
     static bool findDataFormat(const char*, u_int&);
+    static bool findRTNHandling(const char*, RTNHandling&);
 protected:
     ModemConfig();
 
@@ -170,6 +172,8 @@
     fxStr	tagLineFontFile;	// font file for imaging tag lines
     u_int	recvDataFormat;		// received facsimile data format
 
+    RTNHandling rtnHandling;            // RTN signal handling method
+    
     virtual ~ModemConfig();
 
     void parseCID(const char*, CallerID&) const;
Index: hylafax/man/config.4f
===================================================================
RCS file: /cvsroot/hylafax/man/config.4f,v
retrieving revision 1.3
diff -u -r1.3 config.4f
--- config.4f	1999/08/18 09:35:11	1.3
+++ config.4f	2000/06/05 10:11:20
@@ -174,6 +174,7 @@
 RingFax	string	\-	distinctive ring fax call identifier
 RingsBeforeAnswer	integer	\s-10\s+1	rings to wait before answering phone
 RingVoice	string	\-	distinctive ring voice call identifier
+RTNHandlingMethod	string	\s-1Retransmit\s+1	RTN signal handling method	
 SendFaxCmd\(dg	string	\s-1bin/faxsend\s+1	fax transmit command script
 SendPageCmd\(dg	string	\s-1bin/pagesend\s+1	pager transmit command script
 SendUUCPCmd\(dg	string	\s-1bin/uucpsend\s+1	\s-1UUCP\s+1 transmit command script
@@ -304,6 +305,7 @@
 Class2PTSCmd	string	\s-1AT+FPS\s+1	Class 2.0: command to set received page status
 Class2RecvDataTrigger	string	\s-1``\e22''\s+1	Class 2.0: character to send to trigger recv
 Class2RELCmd	string	\-	Class 2.0: command to enable byte-aligned \s-1EOL\s+1 codes
+Class2SendRTC	boolean	\s-1No\s+1	Class 2.0: append \s-1RTC\s+1 to page data on transmit
 Class2SFLOCmd	string	\s-1AT+FLO=1\s+1	Class 2.0: command to set software flow control
 Class2SPLCmd	string	\s-1AT+FSP\s+1	Class 2.0: command to set polling request
 Class2TBCCmd	string	\s-1AT+FPP=0\s+1	Class 2.0: command to enable stream mode
@@ -975,6 +977,29 @@
 and
 .BR RingFax .
 .TP
+.B RTNHandlingMethod
+Specifies how to react to RTN signal, received from the remote;
+one of ``\s-1Retransmit\s+1'', ``\s-1Giveup\s+1'' and
+``\s-1Ignore\s+1''. ``\s-1Retransmit\s+1'' assumes that the
+page is not sent succesfully if RTN signal has been received.
+Hylafax will made up to 2 additional attempts to send the page,
+decreasing signalling rate and retraining. If RTN is still there,
+it will place up to 2 additional calls. So if the remote always respond with
+RTN, the page will be send 9 times. Although this algorithm comply with
+T.30 specs and was originally implemented by Sam Leffler as the only
+possible choice, real fax machines behave completely different. There is a
+non-written rule among fax developers, that RTN means ``over and out'' -- hang
+up immediately and never try to send the same page to the same destination
+again. That is because RTN usually indicates problems with flow control,
+incorrectly encoded T.4 data, incompatibility between local and remote
+equipment etc., but very rarely is caused by the real noise on the line.
+This ``over and out'' behaviour can be activated by ``Giveup'' value.
+There is also third option, not so radical as ``Giveup''. Yes, we will never
+retransmit the page, but we can try to send the next page, and let the
+remote to decide what to do (accept our decision or hang up). Thus one page will
+(or will not) be missed but we have a chance to successfully send all other pages.
+This behaviour can be activated by ``Ignore'' value.
+.TP
 .B SendFaxCmd\(dg
 The command to use to process outbound facsimile jobs; see
 .IR faxsend (1M).
@@ -2091,7 +2121,8 @@
 .B Class2SendRTC
 Whether or not to append an explicit ``Return To Control'' (\s-1RTC\s+1)
 signal to the page data when transmitting.
-The Class 2 spec (i.e. SP-2388-A) states the modem will append
+The Class 2 and Class 2.0 specs (i.e. SP-2388-A and TIA/EIA-592) state
+that the modem will append
 .SM RTC
 when it receives the post-page message command from the host; this
 parameter is provided in case the modem does not correctly implement

Index: hylafax/faxd/Class0.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class0.c++,v
retrieving revision 1.2
diff -u -r1.2 Class0.c++
--- Class0.c++	1999/06/13 07:40:59	1.2
+++ Class0.c++	2000/06/05 10:09:55
@@ -34,6 +34,9 @@
 Class0Modem::Class0Modem(ModemServer& s, const ModemConfig& c)
     : ClassModem(s, c)
 {
+    mfrQueryCmd    = "ATI3";
+    modelQueryCmd  = "ATI0";
+    revQueryCmd    = "";        // I know no standard way - D.B.
 }
 
 Class0Modem::~Class0Modem()
Index: hylafax/faxd/Class1.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class1.c++,v
retrieving revision 1.3
diff -u -r1.3 Class1.c++
--- Class1.c++	1999/08/23 11:19:31	1.3
+++ Class1.c++	2000/06/05 10:09:59
@@ -177,6 +177,16 @@
 	break;
     }
     /*
+     * Class1 defaults for send & receive bit order
+     */
+    sendFillOrder = (conf.sendFillOrder != 0)?
+        conf.sendFillOrder :
+        FILLORDER_LSB2MSB;
+    recvFillOrder = (conf.recvFillOrder != 0)?
+        conf.recvFillOrder :
+        FILLORDER_LSB2MSB;
+
+    /*
      * T.30 specifies that HDCL frame data are in MSB bit
      * order except for CIG/TSI data which have LSB bit order.
      * We compose and interpret frame data in MSB bit order
Index: hylafax/faxd/Class1Send.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class1Send.c++,v
retrieving revision 1.3
diff -u -r1.3 Class1Send.c++
--- Class1Send.c++	2000/05/15 13:23:43	1.3
+++ Class1Send.c++	2000/06/05 10:10:20
@@ -698,7 +713,7 @@
 	uint16 fillorder;
 	TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
 	const u_char* bitrev =
-	    TIFFGetBitRevTable(conf.sendFillOrder != FILLORDER_LSB2MSB);
+	    TIFFGetBitRevTable(sendFillOrder != FILLORDER_LSB2MSB);
 	/*
 	 * Setup tag line processing.
 	 */
Index: hylafax/faxd/Class2.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class2.c++,v
retrieving revision 1.2
diff -u -r1.2 Class2.c++
--- Class2.c++	1999/06/13 07:41:01	1.2
+++ Class2.c++	2000/06/05 10:10:21
@@ -32,7 +32,6 @@
 {
     hangupCode[0] = '\0';
     serviceType = 0;			// must be set in derived class
-    rtcRev = TIFFGetBitRevTable(conf.sendFillOrder == FILLORDER_LSB2MSB);
 }
 
 Class2Modem::~Class2Modem()
@@ -183,6 +182,28 @@
 	xmitWaitForXON = false;
     else
 	xmitWaitForXON = conf.class2XmitWaitForXON;
+
+    /*
+     * Class2/2.0 defaults for send & receive bit order
+     */
+    sendFillOrder = (conf.sendFillOrder != 0)?
+        conf.sendFillOrder :
+        FILLORDER_LSB2MSB;
+    recvFillOrder = (conf.recvFillOrder != 0)?
+        conf.recvFillOrder : 
+        (serviceType == SERVICE_CLASS20 || modemMfr.find(0, "MULTI-TECH") == 0)?
+            /*
+	     * Multitech report the manufacturer as
+	     * "Multi-Tech Sys" or "Multi-Tech Systems"
+	     *
+	     * it seems to be the only Class2 modem which
+	     * does not clone the infamous Rockwell bug
+	     * (which has become "standard" now)
+	     */
+            FILLORDER_LSB2MSB :
+            FILLORDER_MSB2LSB;
+
+    rtcRev = TIFFGetBitRevTable(sendFillOrder == FILLORDER_LSB2MSB);
 
     setupClass2Parameters();			// send parameters to the modem
     return (true);
Index: hylafax/faxd/Class2Send.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/Class2Send.c++,v
retrieving revision 1.4
diff -u -r1.4 Class2Send.c++
--- Class2Send.c++	2000/05/15 13:23:43	1.4
+++ Class2Send.c++	2000/06/05 10:10:28
@@ -349,7 +359,7 @@
 	uint16 fillorder;
 	TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
 	const u_char* bitrev =
-	    TIFFGetBitRevTable(fillorder != conf.sendFillOrder);
+	    TIFFGetBitRevTable(fillorder != sendFillOrder);
 	/*
 	 * Setup tag line processing.
 	 */
Index: hylafax/faxd/ClassModem.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/ClassModem.c++,v
retrieving revision 1.3
diff -u -r1.3 ClassModem.c++
--- ClassModem.c++	2000/05/29 07:47:18	1.3
+++ ClassModem.c++	2000/06/05 10:10:34
@@ -130,8 +130,6 @@
     // XXX: workaround yet another GCC bug (sigh)
     const fxStr& flow = conf.getFlowCmd(conf.flowControl);
     resetCmds = "AT"
-	      | stripAT(conf.softResetCmd)
-	      | "\nAT"
 	      | stripAT(conf.resetCmds)		// prepend to insure our needs
 	      | stripAT(conf.echoOffCmd)
 	      | stripAT(conf.verboseResultsCmd)
@@ -652,6 +650,7 @@
     if (!setBaudRate(rate, iFlow, oFlow))
 	return (false);
     flushModemInput();
+    (void) atCmd(conf.softResetCmd, AT_OK, conf.resetDelay);
     return atCmd(resetCmds, AT_OK, ms);
 }
 
Index: hylafax/faxd/CopyQuality.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/CopyQuality.c++,v
retrieving revision 1.5
diff -u -r1.5 CopyQuality.c++
--- CopyQuality.c++	2000/05/11 14:19:38	1.5
+++ CopyQuality.c++	2000/06/05 10:10:36
@@ -47,7 +47,7 @@
 FaxModem::recvPageDLEData(TIFF* tif, bool checkQuality,
     const Class2Params& params, fxStr& emsg)
 {
-    setupDecoder(conf.recvFillOrder, params.is2D());
+    setupDecoder(recvFillOrder, params.is2D());
 
     u_int rowpixels = params.pageWidth();	// NB: assume rowpixels <= 2432
     tiff_runlen_t runs[2*2432];			// run arrays for cur+ref rows
Index: hylafax/faxd/FaxModem.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/FaxModem.c++,v
retrieving revision 1.3
diff -u -r1.3 FaxModem.c++
--- FaxModem.c++	2000/05/15 13:23:44	1.3
+++ FaxModem.c++	2000/06/05 10:10:39
@@ -37,6 +37,8 @@
     : ClassModem(s,c)
     , server(s)
 {
+    recvFillOrder = 0; // set later in the inherited class
+    sendFillOrder = 0; // set later in the inherited class
     tagLineFont = NULL;
     minsp = BR_2400;
     curreq = NULL;
Index: hylafax/faxd/FaxModem.h
===================================================================
RCS file: /cvsroot/hylafax/faxd/FaxModem.h,v
retrieving revision 1.3
diff -u -r1.3 FaxModem.h
--- FaxModem.h	2000/05/15 13:23:44	1.3
+++ FaxModem.h	2000/06/05 10:10:42
@@ -84,6 +88,8 @@
     NSF     nsf;		// received nonstandard facilities
     // NB: remaining session state is below (params) or maintained by subclass
 protected:
+    u_int	recvFillOrder;	// bit order of recvd data (ModemConfig & autodetected)
+    u_int	sendFillOrder;	// bit order of sent data (ModemConfig & autodetected)
 // NB: these are defined protected for convenience (XXX)
     Class2Params modemParams;	// NOTE: these are masks of Class 2 codes
     u_int	minsp;		// minimum required signalling rate
Index: hylafax/faxd/FaxServer.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/FaxServer.c++,v
retrieving revision 1.3
diff -u -r1.3 FaxServer.c++
--- FaxServer.c++	1999/08/23 11:19:32	1.3
+++ FaxServer.c++	2000/06/05 10:10:43
@@ -28,6 +28,7 @@
 
 #include "Sys.h"
 #include "FaxServer.h"
+#include "Class0.h"
 #include "Class1.h"
 #include "Class2Ersatz.h"
 #include "Class20.h"
@@ -116,16 +117,38 @@
 {
     fxStr h(type);
     h.raisecase();
+    ClassModem* modem;
+    /*
+     * Don't use Class2.0 with USR modems if not explicitly
+     * specified in the config file (it doesn't work reliably) - D.B.
+     */
+    if( h == "UNKNOWN" ){
+        modem = new Class0Modem(*this, *this);
+        if( modem ){
+            bool buggyUSR = false;
+	    if( modem->setupModem() ){
+                fxStr mnf    = modem->getManufacturer();
+                mnf.raisecase();
+                u_int mnfLen = mnf.length();
+                if( mnf.find(0,"USROBOTICS") != mnfLen ){
+                    modem->serverTrace("USR modem: disable Class 2.0 by default");
+                    buggyUSR = true;
+                }
+            }
+            delete modem;
+            if( buggyUSR )
+                goto forceClass1;
+        }
+    }
     /*
      * Probe for modem using type, if specified; otherwise
      * try Class 2.0, Class 2, Class 1, and then Class 0 types.
      */
-    ClassModem* modem;
     if (h == "CLASS2.0" || h == "UNKNOWN") {
 	modem = new Class20Modem(*this, *this);
 	if (modem) {
 	    if (modem->setupModem())
-		return modem;
+                return modem;
 	    delete modem;
 	}
     }
@@ -137,6 +160,7 @@
 	    delete modem;
 	}
     }
+ forceClass1:
     if (h == "CLASS1" || h == "UNKNOWN") {
 	modem = new Class1Modem(*this, *this);
 	if (modem) {
Index: hylafax/faxd/ModemConfig.c++
===================================================================
RCS file: /cvsroot/hylafax/faxd/ModemConfig.c++,v
retrieving revision 1.4
diff -u -r1.4 ModemConfig.c++
--- ModemConfig.c++	2000/05/11 15:32:41	1.4
+++ ModemConfig.c++	2000/06/05 10:10:48
@@ -157,8 +157,8 @@
     u_int ModemConfig::* p;
     u_int		 def;
 } fillorders[] = {
-{ "modemrecvfillorder",	 &ModemConfig::recvFillOrder,  FILLORDER_LSB2MSB },
-{ "modemsendfillorder",	 &ModemConfig::sendFillOrder,  FILLORDER_LSB2MSB },
+{ "modemrecvfillorder",	 &ModemConfig::recvFillOrder,  0 }, // undefined
+{ "modemsendfillorder",	 &ModemConfig::sendFillOrder,  0 }, // undefined
 { "modemframefillorder", &ModemConfig::frameFillOrder, FILLORDER_LSB2MSB },
 };
 static const struct {
@@ -205,7 +205,7 @@
     for (i = N(numbers)-1; i >= 0; i--)
 	(*this).*numbers[i].p = numbers[i].def;
 
-    flowControl		= ClassModem::FLOW_NONE;// no flow control
+    flowControl		= ClassModem::FLOW_XONXOFF;// software flow control
     maxRate		= ClassModem::BR19200;	// reasonable for most modems
     minSpeed		= BR_2400;		// minimum transmit speed
     waitForConnect	= false;		// unique modem answer response
Index: hylafax/man/config.4f
===================================================================
RCS file: /cvsroot/hylafax/man/config.4f,v
retrieving revision 1.3
diff -u -r1.3 config.4f
--- config.4f	1999/08/18 09:35:11	1.3
+++ config.4f	2000/06/05 10:11:20
@@ -207,7 +208,7 @@
 ModemDialCmd	string	\s-1ATDT%s\s+1	command for dialing (%s for number to dial)
 ModemDialResponseTimeout	integer	\s-1180000\s+1	dialing command timeout (ms)
 ModemEchoOffCmd	string	\s-1ATE0\s+1	command for disabling command echo
-ModemFlowControl	string	\s-1None\s+1	\s-1DTE-DCE\s+1 flow control scheme
+ModemFlowControl	string	\s-1XONXOFF\s+1	\s-1DTE-DCE\s+1 flow control scheme
 ModemFrameFillOrder	string	\s-1LSB2MSB\s+1	bit order for \s-1HDLC\s+1 frames
 ModemHardFlowCmd	string	\-	command for setting hardware flow control between \s-1DTE\s+1 and \s-1DCE\s+1
 ModemMinSpeed	string	\s-12400\s+1	minimum acceptable transmit speed
@@ -1511,6 +1536,11 @@
 communication.
 However, beware that many modems only support software
 flow control when sending or receiving facsimile.
+.IP
+Note that modems usually support software flow control even
+if they have no explicit AT-command to activate it; in this case
+it is switched on when the modem enters fax mode, having
+AT+FCLASS=... from \s-1DTE\s+1.
 .TP
 .B ModemFrameFillOrder
 The bit order to expect for received

Index: hylafax/config/usr-2.0
===================================================================
RCS file: /cvsroot/hylafax/config/usr-2.0,v
retrieving revision 1.2
diff -u -r1.2 usr-2.0
--- usr-2.0	1999/01/04 10:19:07	1.2
+++ usr-2.0	2000/06/04 07:37:30
@@ -78,3 +78,7 @@
 # It is not necessary for the Courier modem.
 #
 Class2NRCmd:    AT+FNR=1,1,1,0
+#
+# Modem violates the Class 2.0 specs and do not send RTC itself
+#
+Class2SendRTC:	yes
Index: hylafax/config/zyxel-1496e
===================================================================
RCS file: /cvsroot/hylafax/config/zyxel-1496e,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 zyxel-1496e
--- zyxel-1496e	1998/10/12 20:47:48	1.1.1.1
+++ zyxel-1496e	2000/06/04 07:37:31
@@ -66,16 +66,9 @@
 #
 # Additional reset commands:
 #
-# &B1	  DTE-DCE rate is fixed at DTE setting
-# &N0	  Auto-negotiate highest possible DCE-DCE link rate
-# &S0	  DSR always on
-# *F0	  Deny remote configuration
-# S18=2	  Receive at 38400
-# S38.3=1 DCD on/off sequence follows UNIX standard; also
-#	  fix receiving baud rate at S18 value
-# S39=0	  (avoid Class 2 compatibility hacks)
+# S38.3=1 DCD on/off sequence follows UNIX standard
 # 
-ModemResetCmds:		AT&B1&N0&S0*F0S18=2S38.3=1S39=0
+ModemResetCmds:		S38.3=1
 #
 # We normally append the "@" symbol to the dial string so that
 # the modem will wait 5 seconds before attempting to connect
@@ -106,8 +99,17 @@
 #
 PagerSetupCmds:		AT&K0&N15	# use V.22 at 1200 bps (PageNet)
 #
-# Rev 6.1x firmware have a bug in the ECM support so
-# explicitly disable it's use.  To re-enable its use just
-# comment out the following line.
+# ECM is not implemented in U1496 despite AT+FCC=? says
 #
 Class2DCCQueryCmd:	"!(0,1),(0-5),(0-4),(0-2),(0,1),(0),(0),(0-7)"
+#                                                          
+# Quality Checking is not implemented in U1496 despite AT+FCQ=? says
+#                                                          
+Class2CQQueryCmd:       "!(0),(0)"
+#
+# Disable unnecessary, not implemented and possibly dangerous commands
+#
+Class2BORCmd:           "AT"
+Class2PIECmd:           "AT"                               
+Class2PHCTOCmd:         "AT"                               
+Class2TBCCmd:           "AT"                               
Index: hylafax/config/zyxel-1496e-1
===================================================================
RCS file: /cvsroot/hylafax/config/zyxel-1496e-1,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 zyxel-1496e-1
--- zyxel-1496e-1	1998/10/12 20:47:48	1.1.1.1
+++ zyxel-1496e-1	2000/06/04 07:37:31
@@ -55,13 +55,9 @@
 #
 # Additional reset commands:
 #
-# &B1	  DTE-DCE rate is fixed at DTE setting
-# &N0	  Auto-negotiate highest possible DCE-DCE link rate
-# &S0	  DSR always on
-# *F0	  Deny remote configuration
 # S38.3=1 DCD on/off sequence follows UNIX standard
 # 
-ModemResetCmds:		AT&B1&N0&S0*F0S38.3=1
+ModemResetCmds:		S38.3=1
 #
 # We normally append the "@" symbol to the dial string so that
 # the modem will wait 5 seconds before attempting to connect
Index: hylafax/config/zyxel-1496e-2.0
===================================================================
RCS file: /cvsroot/hylafax/config/zyxel-1496e-2.0,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 zyxel-1496e-2.0
--- zyxel-1496e-2.0	1998/10/12 20:47:48	1.1.1.1
+++ zyxel-1496e-2.0	2000/06/04 07:37:32
@@ -61,16 +61,9 @@
 #
 # Additional reset commands:
 #
-# &B1	  DTE-DCE rate is fixed at DTE setting
-# &N0	  Auto-negotiate highest possible DCE-DCE link rate
-# &S0	  DSR always on
-# *F0	  Deny remote configuration
-# S18=2	  Receive at 38400
-# S38.3=1 DCD on/off sequence follows UNIX standard; also
-#	  fix receiving baud rate at S18 value
-# S39=0	  (avoid Class 2 compatibility hacks)
+# S38.3=1 DCD on/off sequence follows UNIX standard
 # 
-ModemResetCmds:		AT&B1&N0&S0*F0S18=2S38.3=1S39=0
+ModemResetCmds:		S38.3=1
 #
 ModemDialCmd:		ATDT%s		# no '@' 'cuz then busy not recognized
 NoCarrierRetrys:	3		# retry 3 times on no carrier
@@ -85,8 +78,17 @@
 #
 PagerSetupCmds:		AT&K0&N15	# use V.22 at 1200 bps (PageNet)
 #
-# Rev 6.1x firmware have a bug in the ECM support so
-# explicitly disable it's use.  To re-enable its use just
-# comment out the following line.
+# ECM is not implemented in U1496 despite AT+FCC=? says
 #
 Class2DCCQueryCmd:	"!(0,1),(0-5),(0-4),(0-2),(0,1),(0),(0),(0-7)"
+#                                                          
+# Quality Checking is not implemented in U1496 despite AT+FCQ=? says
+#                                                          
+Class2CQQueryCmd:       "!(0),(0)"
+#
+# Disable unnecessary, not implemented and possibly dangerous commands
+#
+Class2BORCmd:           "AT"
+Class2PIECmd:           "AT"                               
+Class2PHCTOCmd:         "AT"                               
+Class2TBCCmd:           "AT"                               





Home
Report any problems to webmaster@hylafax.org

HylaFAX is a trademark of Silicon Graphics Corporation.
Internet connectivity for hylafax.org is provided by:
VirtuALL Private Host Services