Class1.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:55k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: Class1.c++,v 1.51 2008/07/16 16:17:39 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. /*
  27.  * EIA/TIA-578 (Class 1) Modem Driver.
  28.  */
  29. #include "Sys.h"
  30. #include "Class1.h"
  31. #include "ModemConfig.h"
  32. #include "HDLCFrame.h"
  33. #include "t.30.h"
  34. #include "tiffio.h"
  35. #include <stdlib.h>
  36. #include <ctype.h>
  37. const char* Class1Modem::modulationNames[6] = {
  38.     "v.21, chan 2",
  39.     "v.27ter fallback mode",
  40.     "v.27ter",
  41.     "v.29",
  42.     "v.17",
  43.     "v.33",
  44. };
  45. /*
  46.  * Modem capabilities are queried at startup and a
  47.  * table based on this is created for each modem.
  48.  * This information is used to negotiate T.30 session
  49.  * parameters (e.g. signalling rate).
  50.  *
  51.  * NB: v.17 w/ long training is the same as v.33, at
  52.  *     least at 12000 and 14400.
  53.  */
  54. const Class1Cap Class1Modem::basicCaps[15] = {
  55.     {  3,  0,   0,      V21,   false, 0 },  // v.21
  56.     {  24, BR_2400, DCSSIGRATE_2400V27,  V27FB, false, 1 },  // v.27 ter
  57.     {  48, BR_4800, DCSSIGRATE_4800V27,  V27,   false, 2 },  // v.27 ter
  58.     {  72, BR_7200, DCSSIGRATE_7200V29,  V29,   false, 3 },  // v.29
  59.     {  73, BR_7200, DCSSIGRATE_7200V17,  V17,   false, 4 },  // v.17
  60.     {  74, BR_7200, DCSSIGRATE_7200V17,  V17,   false, 5 },  // v.17 w/st
  61.     {  96, BR_9600, DCSSIGRATE_9600V29,  V29,   false, 6 },  // v.29
  62.     {  97, BR_9600, DCSSIGRATE_9600V17,  V17,   false, 7 },  // v.17
  63.     {  98, BR_9600, DCSSIGRATE_9600V17,  V17,   false, 8 },  // v.17 w/st
  64.     { 121, BR_12000, DCSSIGRATE_12000V33, V33,   false, 9 },  // v.33
  65.     { 121, BR_12000, DCSSIGRATE_12000V17, V17,   false, 10 }, // v.17
  66.     { 122, BR_12000, DCSSIGRATE_12000V17, V17,   false, 11 }, // v.17 w/st
  67.     { 145, BR_14400, DCSSIGRATE_14400V33, V33,   false, 12 }, // v.33
  68.     { 145, BR_14400, DCSSIGRATE_14400V17, V17,   false, 13 }, // v.17
  69.     { 146, BR_14400, DCSSIGRATE_14400V17, V17,   false, 14 }, // v.17 w/st
  70. };
  71. #define NCAPS (sizeof (basicCaps) / sizeof (basicCaps[0]))
  72. const char* Class1Modem::tmCmdFmt = "AT+FTM=%u";
  73. const char* Class1Modem::rmCmdFmt = "AT+FRM=%u";
  74. Class1Modem::Class1Modem(FaxServer& s, const ModemConfig& c)
  75.     : FaxModem(s,c)
  76.     , thCmd("AT+FTH=3")
  77.     , rhCmd("AT+FRH=3")
  78. {
  79.     messageReceived = false;
  80.     memcpy(xmitCaps, basicCaps, sizeof (basicCaps));
  81.     memcpy(recvCaps, basicCaps, sizeof (basicCaps));
  82.     /*
  83.      * Because the sending routines deliver data to the transmit functions
  84.      * in segments, these must be globally available to spool outgoing data
  85.      * until a complete ECM block can be assembled.
  86.      *
  87.      * Besides the contents of ecmBlock, ecmStuffedBlock must be able to
  88.      * hold all sync flag bytes, stuffed bits, and RCP frames.
  89.      */
  90.     u_int fs = 256;
  91.     if (conf.class1ECMFrameSize == 64) fs = 64;
  92.     ecmFrame = (u_char*) malloc(fs + 4);
  93.     fxAssert(ecmFrame != NULL, "ECM procedure error (frame).");
  94.     ecmBlock = (u_char*) malloc((fs + 4) * 256);
  95.     fxAssert(ecmBlock != NULL, "ECM procedure error (block).");
  96.     ecmStuffedBlock = (u_char*) malloc(fs == 256 ? 83000 : 33000);
  97.     fxAssert(ecmStuffedBlock != NULL, "ECM procedure error (stuffed block).");
  98.     gotCTRL = false;
  99.     repeatPhaseB = false;
  100.     silenceHeard = false;
  101.     imagefd = 0;
  102. }
  103. Class1Modem::~Class1Modem()
  104. {
  105.     free(ecmFrame);
  106.     free(ecmBlock);
  107.     free(ecmStuffedBlock);
  108. }
  109. bool
  110. Class1Modem::atCmd(const fxStr& cmd, ATResponse r, long ms)
  111. {
  112.     silenceHeard = false;
  113.     return (ClassModem::atCmd(cmd, r, ms));
  114. }
  115. /*
  116.  * Check if the modem is a Class 1 modem and,
  117.  * if so, configure it for use.
  118.  */
  119. bool
  120. Class1Modem::setupModem(bool isSend)
  121. {
  122.     if (!selectBaudRate(conf.maxRate, conf.flowControl, conf.flowControl))
  123. return (false);
  124.     // Query service support information
  125.     fxStr s;
  126.     if (doQuery(conf.classQueryCmd, s, 5000) && FaxModem::parseRange(s, modemServices))
  127. traceBits(modemServices & SERVICE_ALL, serviceNames);
  128.     if ((modemServices & serviceType) == 0)
  129. return (false);
  130.     atCmd(classCmd);
  131.     /*
  132.      * Query manufacturer, model, and firmware revision.
  133.      * We use the manufacturer especially as a key to
  134.      * working around firmware bugs (yech!).
  135.      */
  136.     if (setupManufacturer(modemMfr)) {
  137. modemCapability("Mfr " | modemMfr);
  138. modemMfr.raisecase();
  139.     }
  140.     (void) setupModel(modemModel);
  141.     (void) setupRevision(modemRevision);
  142.     if (modemModel != "")
  143. modemCapability("Model " | modemModel);
  144.     if (modemRevision != "")
  145. modemCapability("Revision " | modemRevision);
  146.     /*
  147.      * Get modem capabilities and calculate best signalling
  148.      * rate, data formatting capabilities, etc. for use in
  149.      * T.30 negotiations.
  150.      */
  151.     if (!class1Query(conf.class1TMQueryCmd, xmitCaps)) {
  152. serverTrace("Error parsing "+FTM" query response: "%s"", rbuf);
  153. return (false);
  154.     }
  155.     modemParams.br = 0;
  156.     u_int i;
  157.     for (i = 1; i < NCAPS; i++)
  158. if (xmitCaps[i].ok)
  159.     modemParams.br |= BIT(xmitCaps[i].br);
  160.     nonV34br = modemParams.br;
  161.     if (conf.class1EnableV34Cmd != "" && conf.class1ECMSupport) {
  162. // This is cosmetic, mostly, to state the modem supports V.34.
  163. // We could query the modem but that would require another
  164. // config option, so we just trust the enable command.
  165. primaryV34Rate = 0;
  166. u_short pos = conf.class1EnableV34Cmd.findR(conf.class1EnableV34Cmd.length(), "+F34=", 5) + 4;
  167. if (pos == 4) // Unknown class1EnableV34Cmd
  168.     modemCapability("Unable to determinate V.34 speed from class1EnableV34Cmd, V.34 faxing will be disabled!");
  169. else
  170.     primaryV34Rate = atoi(conf.class1EnableV34Cmd.extract(pos, conf.class1EnableV34Cmd.next(pos, ',') - pos));
  171. modemParams.br |= BIT(primaryV34Rate) - 1;
  172.     }
  173.     modemParams.wd = conf.class1PageWidthSupport;
  174.     modemParams.ln = conf.class1PageLengthSupport;
  175.     modemParams.df = BIT(DF_1DMH) | (conf.class1MRSupport ? BIT(DF_2DMR) : 0);
  176.     modemParams.bf = BF_DISABLE;
  177.     modemParams.st = ST_ALL;
  178.     modemParams.jp = 0;
  179.     pokeConfig(isSend);
  180.     traceModemParams();
  181.     /*
  182.      * Receive capabilities are maintained separately from
  183.      * transmit capabilities because we need to know more
  184.      * than the signalling rate to formulate the DIS.
  185.      */ 
  186.     if (!class1Query(conf.class1RMQueryCmd, recvCaps)) {
  187. serverTrace("Error parsing "+FRM" query response: "%s"", rbuf);
  188. return (false);
  189.     }
  190.     u_int mods = 0;
  191.     for (i = 1; i < NCAPS; i++)
  192. if (recvCaps[i].ok)
  193.     mods |= BIT(recvCaps[i].mod);
  194.     switch (mods) {
  195.     case BIT(V27FB):
  196. discap = DISSIGRATE_V27FB;
  197. break;
  198.     case BIT(V27FB)|BIT(V27):
  199. discap = DISSIGRATE_V27;
  200. break;
  201.     case BIT(V29):
  202. discap = DISSIGRATE_V29;
  203. break;
  204.     case BIT(V27FB)|BIT(V27)|BIT(V29):
  205. discap = DISSIGRATE_V2729;
  206. break;
  207.     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V33):
  208. discap = DISSIGRATE_V33;
  209. break;
  210.     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V17):
  211.     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V33)|BIT(V17):
  212. discap = DISSIGRATE_V17;
  213. break;
  214.     }
  215.     /*
  216.      * T.30 specifies that HDLC frame data are in MSB bit
  217.      * order except for CIG/TSI data which have LSB bit order.
  218.      * We compose and interpret frame data in MSB bit order
  219.      * and pass the frames through frameRev immediately before
  220.      * transmitting and upon receiving to handle modem characteristics.
  221.      *
  222.      * Class1Modem::encodeTSI and Class1Modem::decodeTSI (below)
  223.      * assume this work and process CIG/TSI data accordingly.
  224.      */
  225.     frameRev = TIFFGetBitRevTable(conf.frameFillOrder == FILLORDER_LSB2MSB);
  226.     setupClass1Parameters();
  227.     return (true);
  228. }
  229. /*
  230.  * These are potentially dynamic modem settings that can be altered on-the-fly.
  231.  */
  232. void
  233. Class1Modem::pokeConfig(bool isSend)
  234. {
  235.     modemParams.vr = conf.class1Resolutions; // bitmapped by configuration
  236.     if (conf.class1ECMSupport) {
  237. modemParams.ec = BIT(EC_DISABLE) | BIT(EC_ENABLE64) | BIT(EC_ENABLE256);
  238.   modemParams.df |= (conf.class1MMRSupport ? BIT(DF_2DMMR) : 0);
  239. switch (conf.class1JBIGSupport) {
  240.     case FaxModem::JBIG_FULL:
  241. jbigSupported = true; 
  242. break;
  243.     case FaxModem::JBIG_SEND:
  244. jbigSupported = isSend;
  245. break;
  246.     case FaxModem::JBIG_RECV:
  247. jbigSupported = !isSend;
  248. break;
  249.     default:
  250. jbigSupported = false;
  251. break;
  252. }
  253. if (jbigSupported) modemParams.df |= BIT(DF_JBIG);
  254. if (conf.class1GreyJPEGSupport || conf.class1ColorJPEGSupport)
  255.     modemParams.jp |= BIT(JP_GREY);
  256. if (conf.class1ColorJPEGSupport)
  257.     modemParams.jp |= BIT(JP_COLOR);
  258.     } else
  259. modemParams.ec = BIT(EC_DISABLE);
  260. }
  261. /*
  262.  * Send the modem the Class 1 configuration commands.
  263.  */
  264. bool
  265. Class1Modem::setupClass1Parameters()
  266. {
  267.     if (modemServices & serviceType) {
  268. setupFlowControl(flowControl);
  269. atCmd(conf.setupAACmd);
  270.     }
  271.     return (true);
  272. }
  273. void
  274. Class1Modem::hangup()
  275. {
  276.     if (useV34) {
  277. // terminate V.34 channel
  278. u_char buf[2];
  279. buf[0] = DLE; buf[1] = EOT; // <DLE><EOT>
  280. putModemData(buf, 2);
  281. // T.31-A1 samples indicate an OK response, but anything is acceptable
  282. (void) atResponse(rbuf, 60000);
  283.     }
  284.     atCmd(conf.onHookCmd, AT_OK, 5000);
  285. }
  286. /*
  287.  * Setup receive-specific parameters.
  288.  */
  289. bool
  290. Class1Modem::setupReceive()
  291. {
  292.     return (true); // nothing to do
  293. }
  294. /*
  295.  * Send the modem any commands needed to force use of
  296.  * the specified flow control scheme.
  297.  */
  298. bool
  299. Class1Modem::setupFlowControl(FlowControl fc)
  300. {
  301.     switch (fc) {
  302.     case FLOW_NONE: return atCmd(conf.class1NFLOCmd);
  303.     case FLOW_XONXOFF: return atCmd(conf.class1SFLOCmd);
  304.     case FLOW_RTSCTS: return atCmd(conf.class1HFLOCmd);
  305.     }
  306.     return (true);
  307. }
  308. /*
  309.  * Place the modem into the appropriate state
  310.  * for sending facsimile.
  311.  */
  312. bool
  313. Class1Modem::faxService(bool enableV34, bool enableV17)
  314. {
  315.     if (!atCmd(classCmd)) return (false);
  316.     if (conf.class1EnableV34Cmd != "" && enableV34)
  317. atCmd(conf.class1EnableV34Cmd);
  318.     useV34 = false; // only when V.8 handshaking is used
  319.     gotEOT = false;
  320.     return (setupFlowControl(flowControl));
  321. }
  322. /*
  323.  * The modem is initialized. Now set it to ready for answer.
  324.  */
  325. bool
  326. Class1Modem::ready(long ms)
  327. {
  328.     gotEOT = false;
  329.     useV34 = false;     // only when V.8 handshaking is used
  330.     if (conf.class1EnableV34Cmd != "" && conf.class1ECMSupport)   
  331.         if (!atCmd(conf.class1EnableV34Cmd))
  332.     return (false);
  333.     if (conf.class1AdaptRecvCmd != "")
  334. if (!atCmd(conf.class1AdaptRecvCmd))
  335.     return (false);
  336.     return (FaxModem::ready(ms));
  337. }
  338. /*
  339.  * Set the local subscriber identification.
  340.  */
  341. void
  342. Class1Modem::setLID(const fxStr& number)
  343. {
  344.     encodeTSI(lid, number);
  345. }
  346. bool
  347. Class1Modem::supportsPolling() const
  348. {
  349.     return (true);
  350. }
  351. /*
  352.  * Construct a binary TSI/CIG string for transmission.  Note
  353.  * that we do not enforce the specification that restricts
  354.  * the alphabet to that of Table 3/T.30 (numeric digits,
  355.  * hyphen, period, and space), but instead permit any
  356.  * printable ASCII string of at most 20 characters to be
  357.  * used.  Note also that the bit reversal is done with the
  358.  * understanding that the encoded string is processed again
  359.  * using frameRev (see above) when forming the transmitted
  360.  * HDLC frame.
  361.  */
  362. void
  363. Class1Modem::encodeTSI(fxStr& binary, const fxStr& ascii)
  364. {
  365.     u_int i, j;
  366.     u_char buf[20];
  367.     u_int n = fxmin(ascii.length(),(u_int) 20);
  368.     for (i = 0, j = 0; i < n; i++) {
  369. int c = ascii[i];
  370. if (isprint(c) || c == ' ')
  371.     buf[j++] = frameRev[c];
  372.     }
  373.     /*
  374.      * Now ``reverse copy'' the string.
  375.      */
  376.     binary.resize(20);
  377.     for (i = 0; j > 0; i++, j--)
  378. binary[i] = buf[j-1];
  379.     for (; i < 20; i++)
  380. binary[i] = frameRev[' ']; // blank pad remainder
  381. }
  382. /*
  383.  * Encode an NSF string for transmission.
  384.  */
  385. void
  386. Class1Modem::encodeNSF(fxStr& binary, const fxStr& ascii)
  387. {
  388.     u_int i, j;
  389.     u_int n = ascii.length();
  390.     binary.resize(n);
  391.     for (i = 0, j = 0; i < n; i++) {
  392. int c = ascii[i];
  393. if (isprint(c) || c == ' ')
  394.     binary[j++] = frameRev[c];
  395.     }
  396. }
  397. /*
  398.  * Do the inverse of encodeTSI; i.e. convert a binary
  399.  * string of encoded digits into the equivalent ascii.
  400.  * Note that as above (and per the spec) bytes are
  401.  * presumed to be transmitted in LSB2MSB bit order and
  402.  * then reversed on receipt according to the host bit
  403.  * order.
  404.  */
  405. const fxStr&
  406. Class1Modem::decodeTSI(fxStr& ascii, const HDLCFrame& binary)
  407. {
  408.     int n = binary.getFrameDataLength();
  409.     if (n > 20) // spec says no more than 20 digits
  410. n = 20;
  411.     else n--; // trim FCF
  412.     ascii.resize(n);
  413.     u_int d = 0;
  414.     bool seenDigit = false;
  415.     for (const u_char* cp = binary.getFrameData() + n-1; n > 0; cp--, n--) {
  416. /*
  417.  * Accept any printable ascii.
  418.  */
  419. u_char c = frameRev[*cp];
  420.         if (isprint(c) || c == ' ') {
  421.     if (c != ' ')
  422. seenDigit = true;
  423.     if (seenDigit)
  424. ascii[d++] = c;
  425. }
  426.     }
  427.     ascii.resize(d);
  428.     return ascii;
  429. }
  430. /*
  431.  * Construct a binary PWD/SUB/SEP string for transmission.
  432.  */
  433. void
  434. Class1Modem::encodePWD(fxStr& binary, const fxStr& ascii)
  435. {
  436.     encodeTSI(binary, ascii);
  437. }
  438. /*
  439.  * Do the inverse of encodePWD; i.e. convert a binary
  440.  * string of encoded digits into the equivalent ascii.
  441.  */
  442. const fxStr&
  443. Class1Modem::decodePWD(fxStr& ascii, const HDLCFrame& binary)
  444. {
  445.     return decodeTSI(ascii, binary);
  446. }
  447. bool
  448. Class1Modem::switchingPause(fxStr& emsg, u_int times)
  449. {
  450.     /*
  451.      * If class1SwitchingCmd is of the AT+FRS=n form we honor
  452.      * the caller's indicattion for a multiplication of the 
  453.      * configured silence detection.  This is primarily used
  454.      * to avoid sending CRP as a receiver during a sender's TCF,
  455.      * but it could also be used in places where we find a 
  456.      * longer wait often necessary.
  457.      */
  458.     fxStr scmd = fxStr(conf.class1SwitchingCmd);
  459.     if (times != 1) {
  460. fxStr ncmd = fxStr(scmd);
  461. ncmd.raiseatcmd();
  462. if (ncmd.length() > 7 && ncmd.head(7) == "AT+FRS=") {
  463.     int dur = atoi(ncmd.tail(ncmd.length()-7)) * times;
  464.     scmd = scmd.head(7) | fxStr(dur, "%d");
  465. }
  466.     }
  467.     if (!silenceHeard && !atCmd(scmd, AT_OK)) {
  468. emsg = "Failure to receive silence (synchronization failure). {E100}";
  469. protoTrace(emsg);
  470. if (wasTimeout()) abortReceive();
  471. return (false);
  472.     }
  473.     /*
  474.      * We necessarily use class1SwitchingCmd rather frequently... 
  475.      * sometimes this is programmed to be immediately before our signalling,
  476.      * and sometimes this is programmed to be immediately after the remote
  477.      * signalling.  That doesn't therefore give us very good control on 
  478.      * ensuring that class1SwitchingCmd is not issued in duplicate in some
  479.      * kinds of program flow.
  480.      *
  481.      * Ideally we'd be able to standardize on issuing class1SwitchingCmd
  482.      * only in one case or another (but not both), but that's not particularly
  483.      * an easy ideal to realize given the number of exceptions to that rule
  484.      * that would neccesarily be required.
  485.      *
  486.      * So for now we just set this flag here, and we unset it in atCmd, and 
  487.      * if the flag is set when we come back here, then we can avoid duplication.
  488.      */
  489.     silenceHeard = true;
  490.     return (true);
  491. }
  492. /*
  493.  * Pass data to modem, filtering DLE's and
  494.  * optionally including the end-of-data
  495.  * marker <DLE><ETX>.
  496.  *
  497.  * If the data transfer is aborted by the user
  498.  * then we must take care to send <DLE><ETX>
  499.  * in order to exit gracefully.
  500.  */
  501. bool
  502. Class1Modem::sendClass1Data(const u_char* data, u_int cc,
  503.     const u_char* bitrev, bool eod, long ms)
  504. {
  505.     bool ok = putModemDLEData(data, cc, bitrev, ms, conf.doPhaseCDebug);
  506.     if (eod || abortRequested()) {
  507. u_char buf[2];
  508. buf[0] = DLE;
  509. buf[1] = ETX;
  510. ok = putModemData(buf, 2, ms);
  511. return (ok && !abortRequested());
  512.     } else
  513. return (ok);
  514. }
  515. /*
  516.  * Receive timed out, abort the operation
  517.  * and resynchronize before returning.
  518.  */
  519. void
  520. Class1Modem::abortReceive()
  521. {
  522.     if (useV34) return; // nothing to do in V.34
  523.     bool b = wasTimeout();
  524.     char c = CAN; // anything other than DC1/DC3
  525.     putModem(&c, 1, 1);
  526.     /*
  527.      * If the modem handles abort properly, then just
  528.      * wait for an OK result.  Otherwise, wait a short
  529.      * period of time, flush any input, and then send
  530.      * "AT" and wait for the return "OK".
  531.      */
  532.     if (conf.class1RecvAbortOK == 0) { // modem doesn't send OK response
  533. pause(200);
  534. flushModemInput();
  535. (void) atCmd("AT", AT_OK, 100);
  536.     } else
  537. while (!waitFor(AT_OK, conf.class1RecvAbortOK) && lastResponse == AT_OTHER && !wasTimeout());
  538.     setTimeout(b); // XXX putModem clobbers timeout state
  539. }
  540. /*
  541.  * Request a primary rate renegotiation.
  542.  */
  543. bool
  544. Class1Modem::renegotiatePrimary(bool constrain)
  545. {
  546.     u_char buf[4];
  547.     u_short size = 0;
  548.     buf[size++] = DLE;
  549.     if (constrain) {
  550. // don't neotiate a faster rate
  551. if (primaryV34Rate == 1) buf[size++] = 0x70; // 2400 bit/s
  552. else if (primaryV34Rate == 2 || primaryV34Rate == 3) {
  553.     /*
  554.      * V.34 bitspeed 2400 is only possible with symbolrate 2400, and
  555.      * as we have no way of determining the symbolrate, we cannot
  556.      * wisely instruct the modem to use 2400 bps unless the modem
  557.      * negotiates it independently.
  558.      */
  559.     buf[size++] = 0x71; // 4800 bit/s
  560. } else buf[size++] = primaryV34Rate + 0x6D; // drop 4800 bit/s
  561. buf[size++] = DLE;
  562.     }
  563.     buf[size++] = 0x6C; // <DLE><pph>
  564.     if (!putModemData(buf, size)) return (false);
  565.     if (constrain)
  566. protoTrace("Request primary rate renegotiation (limit %u bit/s).", 
  567.     primaryV34Rate == 1 ? 2400 : primaryV34Rate > 3 ? (primaryV34Rate-2)*2400 : 4800);
  568.     else
  569. protoTrace("Request primary rate renegotiation.");
  570.     return (true);
  571. }
  572. /*
  573.  * Wait for a <DLE><ctrl> response per T.31-A1 B.8.4.
  574.  */
  575. bool
  576. Class1Modem::waitForDCEChannel(bool awaitctrl)
  577. {
  578.     time_t start = Sys::now();
  579.     int c;
  580.     fxStr garbage;
  581.     bool gotresponse = false;
  582.     gotRTNC = false;
  583.     ctrlFrameRcvd = fxStr::null;
  584.     do {
  585. c = getModemChar(60000);
  586. if (c == DLE) {
  587.     /*
  588.      * With V.34-faxing we expect <DLE><command>
  589.      * Refer to T.31-A1 Table B.1.  Except for EOT
  590.      * these are merely indicators and do not require
  591.      * action.
  592.      */
  593.     c = getModemChar(60000);
  594.     switch (c) {
  595. case EOT:
  596.     protoTrace("EOT received (end of transmission)");
  597.     gotEOT = true;
  598.     recvdDCN = true;
  599.     return (false);
  600. case 0x69:
  601.     protoTrace("Control channel retrain");
  602.     // wait for the control channel to reappear
  603.     // should we reset the timeout setting?
  604.     gotresponse = waitForDCEChannel(true);
  605.     gotRTNC = true;
  606.     return ((awaitctrl ? gotresponse : false));
  607. case 0x6B:
  608.     protoTrace("Primary channel selected");
  609.     gotCTRL = false;
  610.     continue;
  611. case 0x6D:
  612.     protoTrace("Control channel selected");
  613.     gotCTRL = true;
  614.     continue;
  615. case 0x6E: // 1200 bit/s
  616. case 0x6F: // 2400 bit/s
  617.     // control rate indication
  618.     if (controlV34Rate != (c - 0x6D)) {
  619. controlV34Rate = (c - 0x6D);
  620. protoTrace("Control channel rate now %u bit/s", controlV34Rate*1200);
  621.     }
  622.     if (awaitctrl) gotresponse = true;
  623.     continue;
  624. case 0x70: //  2400 bit/s
  625. case 0x71: //  4800 bit/s
  626. case 0x72: //  7200 bit/s
  627. case 0x73: //  9600 bit/s
  628. case 0x74: // 12000 bit/s
  629. case 0x75: // 14400 bit/s
  630. case 0x76: // 16800 bit/s
  631. case 0x77: // 19200 bit/s
  632. case 0x78: // 21600 bit/s
  633. case 0x79: // 24000 bit/s
  634. case 0x7A: // 26400 bit/s
  635. case 0x7B: // 28800 bit/s
  636. case 0x7C: // 31200 bit/s
  637. case 0x7D: // 33600 bit/s
  638.     // primary rate indication
  639.     if (primaryV34Rate != (c - 0x6F)) {
  640. primaryV34Rate = (c - 0x6F);
  641. protoTrace("Primary channel rate now %u bit/s", primaryV34Rate*2400);
  642.     }
  643.     if (!awaitctrl) gotresponse = true;
  644.     continue;
  645. default:
  646.     // unexpected <DLE><command>, deem as garbage
  647.     garbage.append(DLE);
  648.     garbage.append(c);
  649.     break;
  650.     }
  651. } else garbage.append(c);
  652. if (gotCTRL && garbage.length() > 2 && (garbage[0] & 0xFF) == 0xFF && 
  653.     (garbage[garbage.length()-2] & 0xFF) == 0x10 &&
  654.     (garbage[garbage.length()-1] & 0xFF) == 0x03) {
  655.     // We got a control frame and won't get the channel change...
  656.     for (u_int i = 0; i < garbage.length()-2; i++) {
  657. if ((garbage[i] & 0xFF) == DLE && ++i < garbage.length()) {
  658.     /*
  659.      * We've got a frame and must apply T.31-A1 Table B.1.
  660.      */
  661.     if ((garbage[i] & 0xFF) == 0x07) { // end of HDLC frame w/FCS error
  662. // what to do? send CRP? discard frame?
  663. continue;
  664.     }
  665.     switch (garbage[i] & 0xFF) {
  666. case DLE: // <DLE><DLE> => <DLE>
  667.     ctrlFrameRcvd.append(DLE);
  668.     break;
  669. case SUB: // <DLE><SUB> => <DLE><DLE>
  670.     ctrlFrameRcvd.append(DLE);
  671.     ctrlFrameRcvd.append(DLE);
  672.     break;
  673. case 0x51: // <DLE><0x51> => <DC1>
  674.     ctrlFrameRcvd.append(DC1);
  675.     break;
  676. case 0x53: // <DLE><0x53> => <DC3>
  677.     ctrlFrameRcvd.append(0x13);
  678.     break;
  679.     }
  680. } else
  681.     ctrlFrameRcvd.append(garbage[i] & 0xFF);
  682.     }
  683.     return (false);
  684. }
  685. fxStr rcpsignal;
  686. rcpsignal.append(0xFF); rcpsignal.append(0x03); rcpsignal.append(0x86); rcpsignal.append(0x69);
  687. rcpsignal.append(0xCB); rcpsignal.append(0x10); rcpsignal.append(0x03);
  688. if (!gotCTRL && garbage == rcpsignal) {
  689.     // We anticipate getting "extra" RCP frames since we
  690.     // only look for one but usually we will see three.
  691.     garbage.cut(0, 7);
  692. }
  693.     } while (!gotresponse && Sys::now()-start < 60);
  694.     if (getHDLCTracing() && garbage.length()) {
  695. fxStr buf;
  696. u_int j = 0;
  697. for (u_int i = 0; i < garbage.length(); i++) {
  698.     if (j > 0)
  699. buf.append(' ');
  700.     buf.append(fxStr(garbage[i] & 0xFF, "%2.2X"));
  701.     j++;
  702.     if (j > 19) {
  703. protoTrace("--> [%u:%.*s]",
  704.     j, buf.length(), (const char*) buf);
  705. buf = "";
  706. j = 0;
  707.     }
  708. }
  709. if (j)
  710.     protoTrace("--> [%u:%.*s]",
  711. j, buf.length(), (const char*) buf);
  712.     }
  713.     return (gotresponse);
  714. }
  715. /*
  716.  * Receive an HDLC frame. The frame itself must
  717.  * be received within 3 seconds (per the spec).
  718.  * If a carrier is received, but the complete frame
  719.  * is not received before the timeout, the receive
  720.  * is aborted.
  721.  */
  722. bool
  723. Class1Modem::recvRawFrame(HDLCFrame& frame)
  724. {
  725.     /*
  726.      * We need to be generous here ... given that
  727.      * some frames can be long and some devices
  728.      * can add lots of flags to the signalling.
  729.      * Adhering to the spec too closely, 5 sec,
  730.      * appears to be too conservative; if the modem
  731.      * has said CONNECT, then it should be
  732.      * responsible enough to carry-through with
  733.      * things.  A timeout here is only needed to
  734.      * reign-in modems that don't carry-through.
  735.      */
  736.     startTimeout(10000);
  737.     /*
  738.      * Strip HDLC frame flags. This is not needed,
  739.      * (according to the standard DCE does the job),
  740.      * be we leave this legacy code unchanged
  741.      * for sure - D.B.
  742.      */
  743.     int c;
  744.     fxStr garbage;
  745.     for (;;) {
  746. c = getModemChar(0);
  747. if (c == 0xff || c == EOF)
  748.     break;
  749. if (useV34 && c == DLE) {
  750.     c = getModemChar(0);
  751.     switch (c) {
  752. case EOT:
  753.     protoTrace("EOT received (end of transmission)");
  754.     gotEOT = true;
  755.     recvdDCN = true;
  756.     return (false);
  757. case 0x69:
  758.     protoTrace("Control channel retrain");
  759.     // wait for the control channel to reappear
  760.     // should we reset the timeout setting?
  761.     waitForDCEChannel(true);
  762.     gotRTNC = true;
  763.     return (false);
  764. default:
  765.     // unexpected <DLE><command>, deem as garbage
  766.     garbage.append(DLE);
  767.     break;
  768.     }
  769. }
  770. garbage.append(c);
  771. if ( garbage.length() >= 2 && garbage.tail(2) == "rn") {
  772.     /*
  773.      * CR+LF received before address field.
  774.      * We expect result code (though it's possible
  775.      * that CR+LF is a part of garbage frame)
  776.      */
  777.     garbage = garbage.head(garbage.length() - 2);
  778.     break;
  779. }
  780.     }
  781.     if (getHDLCTracing() && garbage.length()) {
  782. fxStr buf;
  783. u_int j = 0;
  784. for (u_int i = 0; i < garbage.length(); i++) {
  785.     if (j > 0)
  786. buf.append(' ');
  787.     buf.append(fxStr(garbage[i] & 0xFF, "%2.2X"));
  788.     j++;
  789.     if (j > 19) {
  790. protoTrace("--> [%u:%.*s]",
  791.     j, buf.length(), (const char*) buf);
  792. buf = "";
  793. j = 0;
  794.     }
  795. }
  796. if (j)
  797.     protoTrace("--> [%u:%.*s]",
  798. j, buf.length(), (const char*) buf);
  799.     }
  800.     if (c == 0xff) { // address field received
  801. do {
  802.     if (c == DLE) {
  803. c = getModemChar(0);
  804. if (c == ETX || c == EOF)
  805.     break;
  806. if (useV34) {
  807.     /*
  808.      * T.31-A1 Table B.1
  809.      * These indicate transparancy, shielding, or delimiting.
  810.      */
  811.     if (c == 0x07) { // end of HDLC frame w/FCS error
  812. break;
  813.     }
  814.     switch (c) {
  815. case EOT:
  816.     protoTrace("EOT received (end of transmission)");
  817.     gotEOT = true;
  818.     recvdDCN = true;
  819.     return (false);
  820. case DLE: // <DLE><DLE> => <DLE>
  821.     break;
  822. case SUB: // <DLE><SUB> => <DLE><DLE>
  823.     frame.put(frameRev[DLE]);
  824.     break;
  825. case 0x51: // <DLE><0x51> => <DC1>
  826.     c = DC1;
  827.     break;
  828. case 0x53: // <DLE><0x53> => <DC3>
  829.     c = 0x13;
  830.     break;
  831.     }
  832. } else {
  833.     /*
  834.      * Some modems may not double-up the in-data DLEs like they should.
  835.      */
  836.     if (conf.class1ModemHasDLEBug) frame.put(frameRev[DLE]);
  837.     else if (c != DLE) {
  838. protoTrace("Odd.  Modem reported meaningless <DLE><0x%X>.  Possible DLE bug indication.", c);
  839.     }
  840. }
  841.     }
  842.     frame.put(frameRev[c]);
  843. } while ((c = getModemChar(0)) != EOF);
  844.     }
  845.     stopTimeout("receiving HDLC frame data");
  846.     if (frame.getLength() > 0)
  847. traceHDLCFrame("-->", frame);
  848.     if (wasTimeout()) {
  849. abortReceive();
  850. return (false);
  851.     }
  852.     /*
  853.      * Now collect the "OK", "ERROR", or "FCERROR"
  854.      * response telling whether or not the FCS was
  855.      * legitimate.
  856.      */
  857.     if (!useV34 && !waitFor(AT_OK)) {
  858. if (lastResponse == AT_ERROR)
  859.     protoTrace("FCS error");
  860. return (false);
  861.     }
  862.     if (useV34 && c == 0x07) {
  863. protoTrace("FCS error");
  864. return (false);
  865.     }
  866.     if (frame.getFrameDataLength() < 1) {
  867. protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  868. return (false);
  869.     }
  870.     if ((frame[1]&0xf7) != 0xc0) {
  871. protoTrace("HDLC frame with bad control field %#x", frame[1]);
  872. return (false);
  873.     }
  874.     if (conf.class1ValidateV21Frames && !frame.checkCRC()) {
  875. protoTrace("FCS error (calculated)");
  876. return (false);
  877.     }
  878.     frameRcvd = "";
  879.     for (u_int i = 0; i < frame.getLength(); i++) frameRcvd.append(frame[i]);
  880.     frame.setOK(true);
  881.     return (true);
  882. }
  883. bool
  884. Class1Modem::syncECMFrame()
  885. {
  886.     /*
  887.      * We explicitly look for the first sync flag so as to
  888.      * not get confused by any initial garbage or training.
  889.      */
  890.     int bit = 0;
  891.     u_short ones = 0;
  892.     // look for the first sync flag
  893.     time_t start = Sys::now();
  894.     startTimeout(60000); // despite indications by T.4 A.3.1
  895.     do {
  896. if ((unsigned) Sys::now()-start >= 60) {
  897.     protoTrace("Timeout awaiting synchronization sequence");
  898.     setTimeout(true);
  899.     return (false);
  900. }
  901. bit = getModemBit(0);
  902.     } while (bit != 0 && !didBlockEnd());
  903.     do {
  904. if ((unsigned) Sys::now()-start >= 60) {
  905.     protoTrace("Timeout awaiting synchronization sequence");
  906.     setTimeout(true);
  907.     return (false);
  908. }
  909. if (bit == 0 || ones > 0xFF) ones = 0;
  910. bit = getModemBit(0);
  911. if (bit == 1) ones++;
  912.     } while (!(ones == 6 && bit == 0 && bit != EOF) && !didBlockEnd());
  913.     stopTimeout("awaiting synchronization sequence");
  914.     if (wasTimeout()) {
  915. return (false);
  916.     }
  917.     return (true);
  918. }
  919. /*
  920.  * Receive an HDLC frame with ECM.  We must always be cautious
  921.  * of "stuffed" zero-bits after five sequential one-bits between
  922.  * flag sequences.  We assume this is called only after a
  923.  * successfuly received complete flag sequence.
  924.  *
  925.  * Things are significantly more simple with V.34-fax ECM since
  926.  * there is no synchronization or RCP frames.  In this case we
  927.  * simply have to handle byte transparancy and shielding, looking
  928.  * for byte-aligned frame delimiters.
  929.  */
  930. bool
  931. Class1Modem::recvECMFrame(HDLCFrame& frame)
  932. {
  933.     if (useV34) {
  934. int c;
  935. for (;;) {
  936.     c = getModemChar(60000);
  937.     if (wasTimeout()) {
  938. return (false);
  939.     }
  940.     if (c == DLE) {
  941. c = getModemChar(60000);
  942. if (wasTimeout()) {
  943.     return (false);
  944. }
  945. switch (c) {
  946.     case DLE:
  947. break;
  948.     case SUB:
  949. frame.put(frameRev[DLE]);
  950. break;
  951.     case 0x51:
  952. c = 0x11;
  953. break;
  954.     case 0x53:
  955. c = 0x13;
  956. break;
  957.     case ETX:
  958. if (frame.getLength() > 0)
  959.     traceHDLCFrame("-->", frame, true);
  960. if (frame.getLength() < 5) { // RCP frame size
  961.     protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  962.     return (false);
  963. }
  964. if (frame[0] != 0xff) {
  965.     protoTrace("HDLC frame with bad address field %#x", frame[0]);
  966.     return (false);
  967. }
  968. if ((frame[1]&0xf7) != 0xc0) {
  969.     protoTrace("HDLC frame with bad control field %#x", frame[1]);
  970.     return (false);
  971. }
  972. return (true);
  973.     case 0x07:
  974. protoTrace("FCS error");
  975. return (false);
  976.     case 0x04:
  977. protoTrace("EOT received (end of transmission)");
  978. gotEOT = true;
  979. recvdDCN = true;
  980. return (false);
  981.     case 0x6D:
  982. protoTrace("Control channel selected");
  983. gotCTRL = true;
  984. return (false);
  985.     default:
  986. protoTrace("got <DLE><%X>", c);
  987. break;
  988. }
  989.     }
  990.     frame.put(frameRev[c]);
  991. }
  992.     }
  993.     int bit = getModemBit(60000);
  994.     u_short ones = 0;
  995.     // look for the last sync flag (possibly the previous one)
  996.     // some senders use this as the time to do framing so we must wait longer than T.4 A.3.1 implies
  997.     time_t start = Sys::now();
  998.     while (bit != 1 && bit != EOF && !didBlockEnd()) { // flag begins with zero, address begins with one
  999. do {
  1000.     if ((unsigned) Sys::now()-start >= 300) { // 5 minutes of synchronization is too much
  1001. protoTrace("Timeout waiting for the last synchronization flag");
  1002. return false;
  1003.     }
  1004.     if (bit == 0 || ones > 6) ones = 0;
  1005.     bit = getModemBit(60000);
  1006.     if (bit == 1) ones++;
  1007. } while (!(ones == 6 && bit == 0 && bit != EOF) && !didBlockEnd());
  1008. ones = 0;
  1009. bit = getModemBit(60000);
  1010.     }
  1011.     // receive the frame, strip stuffed zero-bits, and look for end flag
  1012.     ones = 1;
  1013.     u_short bitpos = 7;
  1014.     u_int byte = (bit << bitpos);
  1015.     bool rcpframe = false;
  1016.     start = Sys::now();
  1017.     do {
  1018. if ((unsigned) Sys::now()-start >= 3) {
  1019.     protoTrace("Timeout receiving HDLC frame");
  1020.     return (false);
  1021. }
  1022. bit = getModemBit(60000);
  1023. if (bit == 1) {
  1024.     ones++;
  1025. }
  1026. if (!(ones == 5 && bit == 0 && bit != EOF)) { // not transparent stuffed zero-bits
  1027.     bitpos--;
  1028.     byte |= (bit << bitpos);
  1029.     if (bitpos == 0) { // fully populated byte
  1030. frame.put(byte);
  1031. bitpos = 8;
  1032. byte = 0;
  1033.     }
  1034. }
  1035. if (bit == 0) ones = 0;
  1036. // don't wait for the terminating flag on an RCP frame
  1037. if (frame[0] == 0xff && frame[1] == 0xc0 && frame[2] == 0x61 && frame.getLength() == 5 && frame.checkCRC()) {
  1038.     protoTrace("RECV received RCP frame");
  1039.     rcpframe = true;
  1040. } else if (didBlockEnd()) {
  1041.     // sometimes RCP frames are truncated by or are missing due to premature DLE+ETX characters, sadly
  1042.     protoTrace("RECV assumed RCP frame with block end");
  1043.     // force-feed a valid RCP frame with FCS
  1044.     frame.reset();
  1045.     frame.put(0xff); frame.put(0xc0); frame.put(0x61); frame.put(0x96); frame.put(0xd3);
  1046.     rcpframe = true;
  1047. }
  1048.     } while (ones != 6 && bit != EOF && !rcpframe && frame.getLength() < frameSize+6);
  1049.     if (ones == 6) bit = getModemBit(60000); // trailing bit on flag
  1050.     if (!rcpframe && frame.getLength() < frameSize+6) {
  1051. /*
  1052.  * The HDLC frame was terminated early by a flag.  T.30 A.3.5 states that
  1053.  * frame size cannot change during one page, and T.4 A.3.6.2 seems to provide
  1054.  * for padding in order to get that last frame on a block to always line up
  1055.  * on a byte and frame boundary.  However, the NOTE 2 there seemse to give
  1056.  * leniency to that requirement, and in fact many senders will send short
  1057.  * frames on the last frame of a block.  So we run a couple of additional
  1058.  * checks here (in addition to FCS checking) to limit the remote chance
  1059.  * of FCS actually checking out on corrupt data (although that may be very
  1060.  * remote indeed).  We don't do these "trailing flag" tests on normal-sized
  1061.  * frames because we deliberately don't look for a trailing flag when we
  1062.  * get enough data.
  1063.  */
  1064. if (bit) { // should have been zero
  1065.     protoTrace("Bad HDLC terminating flag received.");
  1066.     return (false);
  1067. }
  1068. if (byte != 0x7e) { // trailing byte should be flag
  1069.     protoTrace("HDLC frame not byte-oriented.  Trailing byte: %#x", byte);
  1070.     return (false);
  1071. }
  1072.     }
  1073.     traceHDLCFrame("-->", frame, true);
  1074.     if (bit == EOF) {
  1075. protoTrace("EOF received.");
  1076. return (false);
  1077.     }
  1078.     if (frame.getLength() < 5) { // RCP frame size
  1079. protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  1080. return (false);
  1081.     }
  1082.     if (frame[0] != 0xff) {
  1083. protoTrace("HDLC frame with bad address field %#x", frame[0]);
  1084. return (false);
  1085.     }
  1086.     if ((frame[1]&0xf7) != 0xc0) {
  1087. protoTrace("HDLC frame with bad control field %#x", frame[1]);
  1088. return (false);
  1089.     }
  1090.     return (true);
  1091. }
  1092. bool
  1093. Class1Modem::endECMBlock()
  1094. {
  1095.     if (didBlockEnd()) return (true); // some erroniously re-use bytes
  1096.     int c = getLastByte(); // some erroniously re-use bits
  1097.     time_t start = Sys::now();
  1098.     setTimeout(false);
  1099.     do {
  1100. if ((unsigned) Sys::now()-start >= 60) { // 60 seconds of garbage after RCP is too much
  1101.     protoTrace("Timeout waiting for DLE+ETX");
  1102.     setTimeout(true);
  1103.     return false;
  1104. }
  1105. if (c == DLE) {
  1106.     c = getModemChar(30*1000);
  1107.     if (c == ETX || c == EOF)
  1108. break;
  1109. }
  1110.     } while ((c = getModemChar(30*1000)) != EOF);
  1111.     if (c == EOF) return (false);
  1112.     else return (true);
  1113. }
  1114. #include "StackBuffer.h"
  1115. /*
  1116.  * Log an HLDC frame along with a time stamp (secs.10ms).
  1117.  */
  1118. void
  1119. Class1Modem::traceHDLCFrame(const char* direction, const HDLCFrame& frame, bool isecm)
  1120. {
  1121.     if (!isecm) {
  1122. if (!getHDLCTracing()) return;
  1123.     } else {
  1124. if (!getECMTracing()) return;
  1125.     }
  1126.     const char* hexdigits = "0123456789ABCDEF";
  1127.     fxStackBuffer buf;
  1128.     for (u_int i = 0; i < frame.getLength(); i++) {
  1129. u_char b = frame[i];
  1130. if (i > 0)
  1131.     buf.put(' ');
  1132. buf.put(hexdigits[b>>4]);
  1133. buf.put(hexdigits[b&0xf]);
  1134.     }
  1135.     protoTrace("%s HDLC<%u:%.*s>", direction,
  1136. frame.getLength(), buf.getLength(), (const char*) buf);
  1137. }
  1138. /*
  1139.  * Send a raw HDLC frame and wait for the modem response.
  1140.  * The modem is expected to be an HDLC frame sending mode
  1141.  * (i.e. +FTH=3 or similar has already be sent to the modem).
  1142.  * The T.30 max frame length is enforced with a 3 second
  1143.  * timeout on the send.
  1144.  */
  1145. bool
  1146. Class1Modem::sendRawFrame(HDLCFrame& frame)
  1147. {
  1148.     traceHDLCFrame("<--", frame);
  1149.     if (frame.getLength() < 3) {
  1150. protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  1151. return (false);
  1152.     }
  1153.     if (frame[0] != 0xff) {
  1154. protoTrace("HDLC frame with bad address field %#x", frame[0]);
  1155. return (false);
  1156.     }
  1157.     if ((frame[1]&0xf7) != 0xc0) {
  1158. protoTrace("HDLC frame with bad control field %#x", frame[1]);
  1159. return (false);
  1160.     }
  1161.     signalSent = "";
  1162.     for (u_int i = 0; i < frame.getLength(); i++) signalSent.append(frame[i]);
  1163.     /*
  1164.      * sendFrame() is always called with a timeout set.
  1165.      * Let's keep it that way
  1166.      */
  1167.     return (sendClass1Data(frame, frame.getLength(), frameRev, true, 0) &&
  1168. (useV34 ? true : waitFor(frame.moreFrames() ? AT_CONNECT : AT_OK, 0)));
  1169. }
  1170. /*
  1171.  * Send a single byte frame.
  1172.  */
  1173. bool
  1174. Class1Modem::sendFrame(u_char fcf, bool lastFrame)
  1175. {
  1176.     HDLCFrame frame(conf.class1FrameOverhead);
  1177.     frame.put(0xff);
  1178.     frame.put(lastFrame ? 0xc8 : 0xc0);
  1179.     frame.put(fcf);
  1180.     return (sendRawFrame(frame));
  1181. }
  1182. /*
  1183.  * Send a frame with DCS/DIS.
  1184.  */
  1185. bool
  1186. Class1Modem::sendFrame(u_char fcf, FaxParams& dcs_caps, bool lastFrame)
  1187. {
  1188.     HDLCFrame frame(conf.class1FrameOverhead);
  1189.     frame.put(0xff);
  1190.     frame.put(lastFrame ? 0xc8 : 0xc0);
  1191.     frame.put(fcf);
  1192.     int curByte = 0;
  1193.     //add dcs bytes an any optional bytes
  1194.     frame.put(dcs_caps.getByte(curByte));
  1195.     while (dcs_caps.hasNextByte(curByte)) {
  1196.         curByte += 1;
  1197.         frame.put(dcs_caps.getByte(curByte));
  1198.     }
  1199.     return (sendRawFrame(frame));
  1200. }
  1201. /*
  1202.  * Send a frame with TSI/CSI/PWD/SUB/SEP/PPR.
  1203.  */
  1204. bool
  1205. Class1Modem::sendFrame(u_char fcf, const fxStr& tsi, bool lastFrame)
  1206. {
  1207.     HDLCFrame frame(conf.class1FrameOverhead);
  1208.     frame.put(0xff);
  1209.     frame.put(lastFrame ? 0xc8 : 0xc0);
  1210.     frame.put(fcf);
  1211.     frame.put((const u_char*)(const char*)tsi, tsi.length());
  1212.     return (sendRawFrame(frame));
  1213. }
  1214. /*
  1215.  * Send a frame with NSF.
  1216.  */
  1217. bool
  1218. Class1Modem::sendFrame(u_char fcf, const u_char* code, const fxStr& nsf, bool lastFrame)
  1219. {
  1220.     HDLCFrame frame(conf.class1FrameOverhead);
  1221.     frame.put(0xff);
  1222.     frame.put(lastFrame ? 0xc8 : 0xc0);
  1223.     frame.put(fcf);
  1224.     frame.put(code, 3); // should be in LSBMSB already
  1225.     frame.put((const u_char*)(const char*)nsf, nsf.length());
  1226.     return (sendRawFrame(frame));
  1227. }
  1228. bool
  1229. Class1Modem::transmitFrame(fxStr& signal)
  1230. {
  1231.     HDLCFrame frame(conf.class1FrameOverhead);
  1232.     for (u_int i = 0; i < signal.length(); i++) frame.put(signal[i]);
  1233.     startTimeout(7550);
  1234.     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
  1235.     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
  1236.     if (frameSent) frameSent = sendRawFrame(frame);
  1237.     else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1238.     stopTimeout("sending HDLC frame");
  1239.     return (frameSent);
  1240. }
  1241. bool
  1242. Class1Modem::transmitFrame(u_char fcf, bool lastFrame)
  1243. {
  1244.     startTimeout(7550);
  1245.     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
  1246.     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
  1247.     if (frameSent) frameSent = sendFrame(fcf, lastFrame);
  1248.     else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1249.     stopTimeout("sending HDLC frame");
  1250.     return (frameSent);
  1251. }
  1252. bool
  1253. Class1Modem::transmitFrame(u_char fcf, FaxParams& dcs_caps, bool lastFrame)
  1254. {
  1255.     /*
  1256.      * The T.30 spec says no frame can take more than 3 seconds
  1257.      * (+/- 15%) to transmit.  But the DCE can take as much as 5
  1258.      * seconds to respond CONNECT or result OK, per T.31.
  1259.      */
  1260.     startTimeout(7550);
  1261.     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
  1262.     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
  1263.     if (frameSent) frameSent = sendFrame(fcf, dcs_caps, lastFrame);
  1264.     else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1265.     stopTimeout("sending HDLC frame");
  1266.     return (frameSent);
  1267. }
  1268. bool
  1269. Class1Modem::transmitFrame(u_char fcf, const fxStr& tsi, bool lastFrame)
  1270. {
  1271.     startTimeout(7550);
  1272.     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
  1273.     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
  1274.     if (frameSent) frameSent = sendFrame(fcf, tsi, lastFrame);
  1275.     else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1276.     stopTimeout("sending HDLC frame");
  1277.     return (frameSent);
  1278. }
  1279. bool
  1280. Class1Modem::transmitFrame(u_char fcf, const u_char* code, const fxStr& nsf, bool lastFrame)
  1281. {
  1282.     startTimeout(7550);
  1283.     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
  1284.     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
  1285.     if (frameSent) frameSent = sendFrame(fcf, code, nsf, lastFrame);
  1286.     else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1287.     stopTimeout("sending HDLC frame");
  1288.     return (frameSent);
  1289. }
  1290. /*
  1291.  * Send data using the specified signalling rate.
  1292.  */
  1293. bool
  1294. Class1Modem::transmitData(int br, u_char* data, u_int cc,
  1295.     const u_char* bitrev, bool eod)
  1296. {
  1297.     if (flowControl == FLOW_XONXOFF)
  1298. setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
  1299.     fxStr tmCmd(br, tmCmdFmt);
  1300.     bool ok = atCmd(tmCmd, AT_CONNECT);
  1301.     if (ok) {
  1302. // T.31 8.3.3 requires the DCE to report CONNECT at the beginning
  1303. // of transmission of the training pattern rather than at the end.
  1304. // We pause here to allow the remote's +FRM to result in CONNECT.
  1305. // This delay will vary depending on the modem's adherence to T.31.
  1306. pause(conf.class1TMConnectDelay);
  1307. ok = sendClass1Data(data, cc, bitrev, eod, getDataTimeout());
  1308. if (ok && eod) {
  1309.     ok = false;
  1310.     u_short attempts = 0;
  1311.     lastResponse = AT_NOTHING;
  1312.     while (!ok && lastResponse != AT_NOCARRIER && attempts++ < 3) {
  1313. ok = waitFor(AT_OK, 60*1000); // wait up to 60 seconds for "OK"
  1314.     }
  1315. }
  1316.     } else if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1317.     if (flowControl == FLOW_XONXOFF)
  1318. setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
  1319.     return (ok);
  1320. }
  1321. /*
  1322.  * Receive an HDLC frame.  The timeout is against
  1323.  * the receipt of the HDLC flags; the frame itself must
  1324.  * be received within 3 seconds (per the spec).
  1325.  * If a carrier is received, but the complete frame
  1326.  * is not received before the timeout, the receive
  1327.  * is aborted.
  1328.  *
  1329.  * If the frame is received in error, then in instances
  1330.  * where the other end is likely to be able to receive
  1331.  * it, we can transmit CRP to get the other end to
  1332.  * retransmit the frame. 
  1333.  */
  1334. bool
  1335. Class1Modem::recvFrame(HDLCFrame& frame, u_char dir, long ms, bool readPending, bool docrp, bool usehooksensitivity)
  1336. {
  1337.     bool gotframe;
  1338.     u_short crpcnt = 0, rhcnt = 0;
  1339.     u_int onhooks = 0;
  1340.     gotCONNECT = true;
  1341.     time_t start = Sys::now();
  1342.     if (useV34) {
  1343. do {
  1344.     if (crpcnt) traceFCF(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
  1345.     frame.reset();
  1346.     gotframe = recvRawFrame(frame);
  1347. } while (!gotframe && !gotRTNC && !gotEOT && docrp && crpcnt++ < 3 && !wasTimeout() && transmitFrame(dir|FCF_CRP));
  1348. return (gotframe);
  1349.     }
  1350.     startTimeout(ms);
  1351.     if (!readPending) {
  1352. /*
  1353.  * Hopefully the modem is smart enough to *not* do +FCERROR after +FRH=3,
  1354.  * as it is only a stumbling-block for us and cannot be beneficial.  But,
  1355.  * in case it adheres blindly to the spec, we'll repeat ourselves here
  1356.  * until we timeout or we do get the V.21 carrier.  We do slow the looping
  1357.  * with a pause to prevent unwanted massive amounts of tracing.  The pause 
  1358.  * needs to be short enough, though, that the modem will still pick up
  1359.  * any V.21 signalling if it misses that much of the startup.
  1360.  *
  1361.  * T.31 8.3.6 states that the NO CARRIER result to AT+FRH=3 indicates 
  1362.  * carrier loss.  Getting this result without first getting a CONNECT 
  1363.  * response (indicating carrier detection) seems a bit undefined.  However,
  1364.  * sample sessions T.31 I.1 and I.2 seem to give its use as a means to
  1365.  * deliberately detect carrier loss since the OK result to AT+FRH=3 does
  1366.  * not necessarily indicate carrier loss (even on final frames - although
  1367.  * smart modem developers would make it thus).  Thus could serve a purpose
  1368.  * similar to AT+FRS=1 as we haved used in Class1TCFRecvHackCmd (which is
  1369.  * generally a bad idea).  In any case, if we're trying to detect a V.21
  1370.  * HDLC frame and we get a NO CARRIER result immediately following AT+FRH=3
  1371.  * it probably means that the previous carrier was still up, that we just
  1372.  * saw its loss, and so we just need to re-issue AT+FRH=3.  See more below...
  1373.  */
  1374. do {
  1375.     readPending = atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT, 0);
  1376.     if (lastResponse == AT_FCERROR) pause(200);
  1377.     if (lastResponse == AT_ERROR && !wasTimeout() && ++onhooks <= conf.class1HookSensitivity) {
  1378. if (!usehooksensitivity) {
  1379.     /*
  1380.      * Class1HookSensitivity is used by the calling function, not us.
  1381.      */
  1382.     break;
  1383. } else {
  1384.     stopTimeout("");
  1385.     startTimeout(ms);
  1386. }
  1387.     }
  1388. } while (((u_int) Sys::now()-start < conf.t1Timer) && !wasTimeout() &&
  1389.     (lastResponse == AT_FCERROR || lastResponse == AT_NOCARRIER || (lastResponse == AT_ERROR && onhooks <= conf.class1HookSensitivity)));
  1390.     }
  1391.     if (readPending) {
  1392.         stopTimeout("waiting for HDLC flags");
  1393.         if (wasTimeout()){
  1394.             abortReceive();
  1395.             return (false);
  1396.         }
  1397. fxStr emsg;
  1398. do {
  1399.     if (crpcnt || rhcnt) {
  1400. if (rhcnt) crpcnt = 0;
  1401. if (crpcnt) {
  1402.     rhcnt = 0;
  1403.     traceFCF(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
  1404. }
  1405. do {
  1406.     lastResponse = AT_NOTHING;
  1407.     startTimeout(ms);
  1408.     if (!(atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT,0))) {
  1409. stopTimeout("waiting for v.21 carrier");
  1410. if (wasTimeout()) {
  1411.     abortReceive();
  1412.     setTimeout(false);
  1413. }
  1414. if (lastResponse != AT_NOCARRIER || rhcnt++ > 30) return (false);
  1415.     }
  1416.     stopTimeout("waiting for v.21 carrier");
  1417.     /*
  1418.      * The meaning of a direct NO CARRIER response/result to the AT+FRH=3 
  1419.      * command can be interpreted two ways due to wording in ITU T.31.
  1420.      * The more traditional interpretation is that it is out-of-spec: that
  1421.      * a NO CARRIER response should only come after a CONNECT message.
  1422.      * However, T.31 gives sample sessions that illustrate precisely this 
  1423.      * kind of out-of-spec sequence:
  1424.      *
  1425.      * <-- AT+FRH=3
  1426.      * --> NO CARRIER
  1427.      *
  1428.      * And the interpretation is clear to indicate that in this case the
  1429.      * modem detected a carrier, but it apparently was not V.21 HDLC, and
  1430.      * the NO CARRIER response indicates that the indeterminate carrier
  1431.      * has dropped.  This functionality is more cumbersome than it is
  1432.      * helpful (its value is not much different than that of an AT+FRS=1 
  1433.      * command), and what it really means is that we just need to re-issue 
  1434.      * the AT+FRH=3 command until we get something useful as this scenario
  1435.      * will most likely occur on incidence of Phase C premature carrier loss.
  1436.      */
  1437. } while (lastResponse == AT_NOCARRIER);
  1438.     }
  1439.     frame.reset();
  1440.             gotframe = recvRawFrame(frame);
  1441.     /*
  1442.      * Some modems aren't very particular about reporting CONNECT after AT+FRH=3.
  1443.      * So, for such modems CONNECT may come with V.17 modulated audio or any noise
  1444.      * whatsoever.  Those modems tend to report NO CARRIER after CONNECT, perhaps
  1445.      * after <DLE><ETX> or some other garbage possibly.  NO CARRIER is an invalid
  1446.      * modem response at that point, anyway.  So it is a good indicator for us.
  1447.      * So we simply repeat AT+FRH=3 in that case.
  1448.      */
  1449. } while (((u_int) Sys::now()-start < howmany(conf.t1Timer, 1000)) && !gotframe && !wasTimeout() && 
  1450.     ((conf.class1HasRHConnectBug && !frame.getLength() && lastResponse == AT_NOCARRIER && rhcnt++ < 30) ||
  1451.     (docrp && crpcnt++ < 3 && switchingPause(emsg, 3) && transmitFrame(dir|FCF_CRP)))); /* triple switchingPause to avoid sending CRP during TCF */
  1452. return (gotframe);
  1453.     } else {
  1454. gotCONNECT = false;
  1455. if (lastResponse == AT_ERROR) gotEOT = true; // on hook
  1456.     }
  1457.     stopTimeout("waiting for v.21 carrier");
  1458.     if (wasTimeout()) {
  1459. abortReceive();
  1460. setTimeout(false);
  1461.     }
  1462.     return (false);
  1463. }
  1464. /*
  1465.  * Receive TCF data using the specified signalling rate.
  1466.  */
  1467. bool
  1468. Class1Modem::recvTCF(int br, HDLCFrame& buf, const u_char* bitrev, long ms)
  1469. {
  1470.     buf.reset();
  1471.     if (flowControl == FLOW_XONXOFF)
  1472. setXONXOFF(FLOW_NONE, FLOW_XONXOFF, ACT_DRAIN);
  1473.     /*
  1474.      * Loop waiting for carrier or timeout.
  1475.      */
  1476.     bool readPending, gotCarrier;
  1477.     fxStr rmCmd(br, rmCmdFmt);
  1478.     startTimeout(ms);
  1479.     u_short attempts = 0;
  1480.     do {
  1481. readPending = atCmd(rmCmd, AT_NOTHING, 0);
  1482. gotCarrier = readPending && waitFor(AT_CONNECT, 0);
  1483.     } while (readPending && !gotCarrier && lastResponse == AT_FCERROR && ++attempts < conf.class1RMPersistence);
  1484.     /*
  1485.      * If carrier was recognized, collect the data.
  1486.      */
  1487.     bool gotData = false;
  1488.     if (gotCarrier) {
  1489. int c = getModemChar(0); // NB: timeout is to first byte
  1490. stopTimeout("receiving TCF");
  1491. if (c != EOF) {
  1492.     buf.reset();
  1493.     /*
  1494.      * Use a  timer to receive the 1.5
  1495.      * second TCF--perhaps if it is too long it
  1496.      * won't permit us to send the nak in time?
  1497.      *
  1498.      * The initial timer needs to be longer than 1.5 seconds
  1499.      * to support senders that may not start the zeros
  1500.      * until a second or two after CONNECT.  This is
  1501.      * also why we restart our timeout after the zeros
  1502.      * start.
  1503.      */
  1504.     bool zerosstarted = false;
  1505.     startTimeout(ms);
  1506.     do {
  1507. if (c == 0x00 && !zerosstarted) {
  1508.     zerosstarted = true;
  1509.     startTimeout(ms);
  1510. }
  1511. if (c == DLE) {
  1512.     c = getModemChar(0);
  1513.     if (c == ETX) {
  1514. gotData = true;
  1515. break;
  1516.     }
  1517.     if (c == EOF) {
  1518. break;
  1519.     }
  1520. }
  1521. buf.put(bitrev[c]);
  1522. if (buf.getLength() > 10000) {
  1523.     setTimeout(true);
  1524.     break;
  1525. }
  1526.     } while ((c = getModemChar(0)) != EOF);
  1527. }
  1528.     }
  1529.     stopTimeout("receiving TCF");
  1530.     /*
  1531.      * If the +FRM is still pending, abort it.
  1532.      */
  1533.     if (readPending && wasTimeout())
  1534. abortReceive();
  1535.     if (flowControl == FLOW_XONXOFF)
  1536. setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
  1537.     return (gotData);
  1538. }
  1539. /* 
  1540.  * Modem manipulation support.
  1541.  */
  1542. /*
  1543.  * Reset a Class 1 modem.
  1544.  */
  1545. bool
  1546. Class1Modem::reset(long ms)
  1547. {
  1548.     return (FaxModem::reset(ms) && setupClass1Parameters());
  1549. }
  1550. ATResponse
  1551. Class1Modem::atResponse(char* buf, long ms)
  1552. {
  1553.     if (FaxModem::atResponse(buf, ms) == AT_OTHER && strneq(buf, "+FCERROR", 8))
  1554. lastResponse = AT_FCERROR;
  1555.     if (lastResponse == AT_OTHER && strneq(buf, "+FRH:3", 6))
  1556. lastResponse = AT_FRH3;
  1557.     if (lastResponse == AT_OTHER && strneq(buf, "+F34:", 5)) {
  1558. /*
  1559.  * V.8 handshaking was successful.  The rest of the
  1560.  * session is governed by T.31 Amendment 1 Annex B.
  1561.  * (This should only happen after ATA or ATD.)
  1562.  *
  1563.  * The +F34: response is interpreted according to T.31-A1 B.6.2.
  1564.  */
  1565. buf += 5; // skip "+F34:" prefix
  1566. primaryV34Rate = 0;
  1567. while (!isdigit(buf[0])) buf++; // move to digits
  1568. do {
  1569.     primaryV34Rate = primaryV34Rate*10 + (buf[0] - '0');
  1570.         } while (isdigit((++buf)[0]));
  1571. controlV34Rate = 0;
  1572. while (!isdigit(buf[0])) buf++; // move to digits
  1573. do {
  1574.     controlV34Rate = controlV34Rate*10 + (buf[0] - '0');
  1575.         } while (isdigit((++buf)[0]));
  1576. useV34 = true;
  1577. protoTrace("V.8 handshaking succeeded, V.34-Fax (SuperG3) capability enabled.");
  1578. protoTrace("Primary channel rate: %u bit/s, Control channel rate: %u bit/s.", primaryV34Rate*2400, controlV34Rate*1200);
  1579. modemParams.br |= BIT(primaryV34Rate) - 1;
  1580.     }
  1581.     return (lastResponse);
  1582. }
  1583. /*
  1584.  * Wait (carefully) for some response from the modem.
  1585.  */
  1586. bool
  1587. Class1Modem::waitFor(ATResponse wanted, long ms)
  1588. {
  1589.     for (;;) {
  1590. ATResponse response = atResponse(rbuf, ms);
  1591. if (response == wanted)
  1592.     return (true);
  1593. switch (response) {
  1594. case AT_TIMEOUT:
  1595. case AT_EMPTYLINE:
  1596. case AT_ERROR:
  1597. case AT_NOCARRIER:
  1598. case AT_NODIALTONE:
  1599. case AT_NOANSWER:
  1600. case AT_OFFHOOK:
  1601. case AT_RING:
  1602.     modemTrace("MODEM %s", ATresponses[response]);
  1603.     /* fall thru... */
  1604. case AT_OTHER:
  1605. case AT_FCERROR:
  1606. case AT_FRH3:
  1607. case AT_OK:
  1608.     return (false);
  1609. }
  1610.     }
  1611. }
  1612. /*
  1613.  * Send queryCmd and get a range response.
  1614.  */
  1615. bool
  1616. Class1Modem::class1Query(const fxStr& queryCmd, Class1Cap caps[])
  1617. {
  1618.     char response[1024];
  1619.     if (queryCmd[0] == '!') {
  1620. return (parseQuery(queryCmd.tail(queryCmd.length()-1), caps));
  1621.     }
  1622.     if (atCmd(queryCmd, AT_NOTHING) && atResponse(response) == AT_OTHER) {
  1623. sync(5000);
  1624. return (parseQuery(response, caps));
  1625.     }
  1626.     return (false);
  1627. }
  1628. /*
  1629.  * Map the DCS signalling rate to the appropriate
  1630.  * Class 1 capability entry.
  1631.  */
  1632. const Class1Cap*
  1633. Class1Modem::findSRCapability(u_short sr, const Class1Cap caps[])
  1634. {
  1635.     for (u_int i = NCAPS-1; i > 0; i--) {
  1636. const Class1Cap* cap = &caps[i];
  1637. if (cap->sr == sr) {
  1638.     if (cap->mod == V17 && HasShortTraining(cap-1))
  1639. cap--;
  1640.     return (cap);
  1641. }
  1642.     }
  1643.     // XXX should not happen...
  1644.     protoTrace("MODEM: unknown signalling rate %#x, using 9600 v.29", sr);
  1645.     return findSRCapability(DCSSIGRATE_9600V29, caps);
  1646. }
  1647. /*
  1648.  * Map the Class 2 bit rate to the best
  1649.  * signalling rate capability of the modem.
  1650.  */
  1651. const Class1Cap*
  1652. Class1Modem::findBRCapability(u_short br, const Class1Cap caps[])
  1653. {
  1654.     for (u_int i = NCAPS-1; i > 0; i--) {
  1655. const Class1Cap* cap = &caps[i];
  1656. if (cap->br == br && cap->ok) {
  1657.     if (cap->mod == V17 && HasShortTraining(cap-1))
  1658. cap--;
  1659.     return (cap);
  1660. }
  1661.     }
  1662.     protoTrace("MODEM: unsupported baud rate %#x", br);
  1663.     return NULL;
  1664. }
  1665. /*
  1666.  * Build upon the result from Class2Params.
  1667.  */
  1668. FaxParams
  1669. Class1Modem::modemDIS() const
  1670. {
  1671.     FaxParams dis_caps = FaxModem::modemDIS();
  1672.     // signalling rates
  1673.     for (u_short i = 0; i < 4; i++) dis_caps.setBit(11+i, (discap & (0x08>>i)));
  1674.     if (useV34) dis_caps.setBit(FaxParams::BITNUM_V8_CAPABLE, true);
  1675.     // preferred ECM frame size
  1676.     if (conf.class1ECMFrameSize == 64) dis_caps.setBit(FaxParams::BITNUM_FRAMESIZE_DIS, true);
  1677.     // we set both units preferences to allow the sender to choose
  1678.     dis_caps.setBit(FaxParams::BITNUM_METRIC_RES, true);
  1679.     dis_caps.setBit(FaxParams::BITNUM_INCH_RES, true);
  1680.     // we indicate both letter and legal page size support
  1681.     dis_caps.setBit(FaxParams::BITNUM_LETTER_SIZE, true);
  1682.     dis_caps.setBit(FaxParams::BITNUM_LEGAL_SIZE, true);
  1683.     // selective polling, subaddressing, password
  1684.     dis_caps.setBit(FaxParams::BITNUM_SEP, true);
  1685.     dis_caps.setBit(FaxParams::BITNUM_SUB, true);
  1686.     dis_caps.setBit(FaxParams::BITNUM_PWD, true);
  1687.     if (conf.class1ECMSupport) {
  1688. // JBIG
  1689. if (jbigSupported) {
  1690.     dis_caps.setBit(FaxParams::BITNUM_JBIG_BASIC, true);
  1691.     dis_caps.setBit(FaxParams::BITNUM_JBIG_L0, true); // JBIG library can handle L0 = 1-Yd
  1692. }
  1693. /* - disabled for now
  1694. // JBIG grey/color requires JPEG grey/color
  1695. if (conf.class1GreyJBIGSupport || conf.class1ColorJBIGSupport) {
  1696.     dis_caps.setBit(FaxParams::BITNUM_JPEG, true);
  1697.     dis_caps.setBit(FaxParams::BITNUM_JBIG, true);
  1698. }
  1699. if (conf.class1ColorJBIGSupport)
  1700.     dis_caps.setBit(FaxParams::BITNUM_FULLCOLOR, true);
  1701. */
  1702. // JPEG
  1703. if (conf.class1GreyJPEGSupport || conf.class1ColorJPEGSupport)
  1704.     dis_caps.setBit(FaxParams::BITNUM_JPEG, true);
  1705. if (conf.class1ColorJPEGSupport)
  1706.     dis_caps.setBit(FaxParams::BITNUM_FULLCOLOR, true);
  1707.     }
  1708.     return dis_caps;
  1709. }
  1710. const char COMMA = ',';
  1711. const char SPACE = ' ';
  1712. /*
  1713.  * Parse a Class 1 parameter string.
  1714.  */
  1715. bool
  1716. Class1Modem::parseQuery(const char* cp, Class1Cap caps[])
  1717. {
  1718.     bool bracket = false, first = true;
  1719.     
  1720.     while (cp[0]) {
  1721. if (cp[0] == SPACE) { // ignore white space
  1722.     cp++;
  1723.     continue;
  1724. }
  1725.         /* by a.pogoda@web.de, jan 21st 2002
  1726.          * workaround for modems sending (<item>,<item>,...), i.e. 
  1727.          * enclosed in brackets rather than just <item>,<item>,...
  1728.          * e.g. elsa microlink 56k internet II and maybo others
  1729.          */
  1730.         if (cp[0]=='(' && first && !bracket) {
  1731.           /* check whether the first non-space char is an 
  1732.            * opening bracket and skip it if true
  1733.            */ 
  1734.           bracket = true;
  1735.           cp++;
  1736.           continue;
  1737.         }
  1738.         else if (cp[0]==')' && !first && bracket) {
  1739.           /* if an opening bracket was scanned before and 
  1740.            * the current char is a closing one, skip it
  1741.            */
  1742.           bracket = false;
  1743.           cp++;
  1744.           continue;
  1745.         }
  1746.         else if (!isdigit(cp[0]))
  1747.   return (false);
  1748.         /* state that we already scanned past the first char */
  1749.         first = false;
  1750. int v = 0;
  1751. do {
  1752.     v = v*10 + (cp[0] - '0');
  1753. } while (isdigit((++cp)[0]));
  1754. int r = v;
  1755. if (cp[0] == '-') { // <low>-<high>
  1756.     cp++;
  1757.     if (!isdigit(cp[0])) {
  1758. return (false);
  1759.     }
  1760.     r = 0;
  1761.     do {
  1762. r = r*10 + (cp[0] - '0');
  1763.     } while (isdigit((++cp)[0]));
  1764. }
  1765. for (u_int i = 0; i < NCAPS; i++)
  1766.     if (caps[i].value >= v && caps[i].value <= r) {
  1767. caps[i].ok = true;
  1768. break;
  1769.     }
  1770. if (cp[0] == COMMA) // <item>,<item>...
  1771.     cp++;
  1772.     }
  1773.     return (true);
  1774. }