}
/*
* It is possible (and with some modems likely) that the sending
- * system has not yet dropped its V.21 carrier. So we follow the
- * reasoning behind Class 1.0's adaptive reception control in T.32
- * 8.5.1 and the strategy documented in T.31 Appendix II.1: we issue
- * another +FRH and wait for NO CARRIER before looking for the high
- * speed carrier. Even if the remote dropped its V.21 carrier at the
- * same moment that we received the signal, the remote still has to
- * wait 75 +/- 20 ms before sending us TCF as dictated by T.30
- * Chapter 5, Note 3. T.31 alerts us to the possibility of an ERROR
- * result instead of NO CARRIER due to line noise at carrier shut-off
- * and that we should ignore the ERROR.
+ * system has not yet dropped its V.21 carrier because the modem may
+ * simply signal OK when the HDLC frame is received completely and not
+ * not wait for the carrier drop to occur. We don't follow the strategy
+ * documented in T.31 Appendix II.1 about issuing another +FRH and
+ * waiting for NO CARRIER because it's possible that the sender does not
+ * send enough V.21 HDLC after the last frame to make that work.
+ *
+ * The remote has to wait 75 +/- 20 ms after DCS before sending us TCF
+ * as dictated by T.30 Chapter 5, Note 3. If we have a modem that gives
+ * us an OK after DCS before the sender actually drops the carrier, then
+ * the best approach will be to simply look for silence with AT+FRS=1.
+ * Unfortunately, +FRS is not supported on all modems, and so when they
+ * need it, they will have to simply use a <delay:n> or possibly use
+ * a different command sequence.
*
- * This approach poses less risk of failure than previous methods
- * which simply ran through +FRM -> +FCERROR -> +FRM loops because
- * with each iteration of said loop we ran the risk of losing our
- * timing due to the DCE being deaf for a short period of time.
- * Unfortunately, this routine will cause some modems (i.e. Zyxel
- * U336 and USR Courier 3367) to fail TCF reception.
*/
- if (conf.class1TCFRecvHack)
- atCmd(rhCmd, AT_NOCARRIER);
+ if (!atCmd(conf.class1TCFRecvHackCmd, AT_OK)) {
+ return (false);
+ }
protoTrace("RECV training at %s %s",
modulationNames[curcap->mod],
* Look for message carrier and receive Phase C data.
*/
/*
- * Same reasoning here as before receiving TCF. In practice,
- * however, we can't follow Class1TCFRecvHack because it
- * apparently takes too much time to drop the V.21 carrier.
- * So, our approach is much like Class1SwitchingCmd.
+ * Same reasoning here as before receiving TCF.
*/
if (!atCmd(conf.class1MsgRecvHackCmd, AT_OK)) {
emsg = "Failure to receive silence.";
{ "class1tmquerycmd", &ModemConfig::class1TMQueryCmd, "AT+FTM=?" },
{ "class1eopwaitcmd", &ModemConfig::class1EOPWaitCmd, "AT+FTS=9" },
{ "class1msgrecvhackcmd", &ModemConfig::class1MsgRecvHackCmd, "" },
+{ "class1tcfrecvhackcmd", &ModemConfig::class1TCFRecvHackCmd, "" },
{ "class1switchingcmd", &ModemConfig::class1SwitchingCmd, "AT+FRS=7" },
{ "class2cmd", &ModemConfig::class2Cmd },
{ "class2borcmd", &ModemConfig::class2BORCmd },
#endif
class1Resolutions = VR_ALL; // resolutions support
class1PersistentECM = true; // continue to correct
- class1TCFRecvHack = false; // historical behavior
class1ValidateV21Frames = false; // assume the modem does this
setVolumeCmds("ATM0 ATL0M1 ATL1M1 ATL2M1 ATL3M1");
recvDataFormat = DF_ALL; // default to no transcoding
class1Resolutions = getBoolean(value) ? VR_ALL : (VR_NORMAL | VR_FINE);
else if (streq(tag, "class1resolutions"))
class1Resolutions = getNumber(value);
- else if (streq(tag, "class1tcfrecvhack"))
- class1TCFRecvHack = getBoolean(value);
+ else if (streq(tag, "class1tcfrecvhack") && getBoolean(value))
+ class1TCFRecvHackCmd = "AT+FRS=1"; // backwards compatibility
else if (streq(tag, "class1validatev21frames"))
class1ValidateV21Frames = getBoolean(value);
else if (streq(tag, "modemminspeed"))
fxStr class1EOPWaitCmd; // cmd to stop and wait prior to EOP
fxStr class1SwitchingCmd; // after recv HDLC and before sending
fxStr class1MsgRecvHackCmd; // cmd to avoid +FCERROR before image
+ fxStr class1TCFRecvHackCmd; // cmd to avoid +FCERROR before TCF
u_int class1TCFRecvTimeout; // timeout receiving TCF
u_int class1RecvAbortOK; // if non-zero, OK sent after recv abort
u_int class1RMPersistence; // how many times to persist through +FCERROR
bool class1MRSupport; // support 2-D MR
bool class1MMRSupport; // support 2-D MMR
bool class1PersistentECM; // continue to correct
- bool class1TCFRecvHack; // deliberately look for V.21 disconnect
bool class1ValidateV21Frames;// check received FCS values in V.21
// for class 2 and 2.0:
fxStr class2Cmd; // cmd for setting Class 2/2.0
Class1TMQueryCmd string \s-1AT+FTM=?\s+1 Class 1/1.0: command to query modem data transmission rates
Class1EOPWaitCmd string \s-1AT+FTS=9\s+1 Class 1/1.0: command to stop and wait before EOP
Class1MsgRecvHackCmd string \s-1""\s+1 Class 1/1.0: command to avoid +FCERROR before image data
+Class1TCFRecvHackCmd string \s-1""\s+1 Class 1/1.0: command to avoid +FCERROR before TCF
Class1TCFMaxNonZero integer \s-110\s+1 Class 1/1.0: max% of non-zero data in good \s-1TCF\s+1
Class1TCFMinRun integer \s-11000\s+1 Class 1/1.0: minimum zero run in good \s-1TCF\s+1
-Class1TCFRecvHack boolean \s-1No\s+1 Class 1/1.0: deliberately look for carrier loss before TCF
Class1TCFRecvTimeout integer \s-14500\s+1 Class 1/1.0: max wait (ms) for \s-1TCF\s+1
Class1TMConnectDelay integer \s-10\s+1 Class 1/1.0: delay between +FTM CONNECT and data transmission
Class1SwitchingCmd string \s-1AT+FRS=7\s+1 Class 1/1.0: command to ensure silence after HDLC reception
See also
.BR Class1TCFMaxNonZero .
.TP
-.B Class1TCFRecvHack
-Deliberately look for the low-speed carrier loss before
-switching to the high-speed TCF carrier. Use this if session logs
-consistently show +FCERROR prior to TCF reception.
+.B Class1TCFRecvHackCmd
+If receive failures occur due to +FCERROR just prior to TCF data
+reception, setting
+.B Class1TCFRecvHackCmd
+to AT+FRS=1 may help.
.TP
.B Class1TCFRecvTimeout
The maximum time to wait, in milliseconds, for the first byte and