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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: Class2Ersatz.c++,v 1.2 2007/10/18 06:05:09 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. #include "Class2Ersatz.h"
  27. #include "ModemConfig.h"
  28. #include <stdlib.h>
  29. #include <ctype.h>
  30. Class2ErsatzModem::Class2ErsatzModem(FaxServer& s, const ModemConfig& c)
  31.     : Class2Modem(s,c)
  32. {
  33.     serviceType = SERVICE_CLASS2;
  34.     setupDefault(classCmd, conf.class2Cmd, "AT+FCLASS=2");
  35.     setupDefault(mfrQueryCmd, conf.mfrQueryCmd, "AT+FMFR?");
  36.     setupDefault(modelQueryCmd, conf.modelQueryCmd, "AT+FMDL?");
  37.     setupDefault(revQueryCmd, conf.revQueryCmd, "AT+FREV?");
  38.     setupDefault(dccQueryCmd, conf.class2DCCQueryCmd, "AT+FDCC=?");
  39.     setupDefault(abortCmd, conf.class2AbortCmd, "AT+FK");
  40.     setupDefault(borCmd, conf.class2BORCmd, "AT+FBOR=0");
  41.     setupDefault(tbcCmd, conf.class2TBCCmd, "AT+FTBC=0");
  42.     setupDefault(crCmd, conf.class2CRCmd, "AT+FCR=1");
  43.     setupDefault(phctoCmd, conf.class2PHCTOCmd, "AT+FPHCTO=30");
  44.     setupDefault(bugCmd, conf.class2BUGCmd, "AT+FBUG=1");
  45.     setupDefault(lidCmd, conf.class2LIDCmd, "AT+FLID");
  46.     setupDefault(dccCmd, conf.class2DCCCmd, "AT+FDCC");
  47.     setupDefault(disCmd, conf.class2DISCmd, "AT+FDIS");
  48.     setupDefault(cigCmd, conf.class2CIGCmd, "AT+FCIG");
  49.     setupDefault(splCmd, conf.class2SPLCmd, "AT+FSPL");
  50.     setupDefault(ptsCmd, conf.class2PTSCmd, "AT+FPTS");
  51.     setupDefault(minspCmd, conf.class2MINSPCmd, "AT+FMINSP");
  52.     setupDefault(noFlowCmd, conf.class2NFLOCmd, "");
  53.     setupDefault(softFlowCmd, conf.class2SFLOCmd, "");
  54.     setupDefault(hardFlowCmd, conf.class2HFLOCmd, "");
  55. }
  56. Class2ErsatzModem::~Class2ErsatzModem()
  57. {
  58. }
  59. ATResponse
  60. Class2ErsatzModem::atResponse(char* buf, long ms)
  61. {
  62.     if (FaxModem::atResponse(buf, ms) == AT_OTHER &&
  63.       (buf[0] == '+' && buf[1] == 'F')) {
  64. if (strneq(buf, "+FHNG:", 6)) {
  65.     processHangup(buf+6);
  66.     lastResponse = AT_FHNG;
  67.     hadHangup = true;
  68. } else if (strneq(buf, "+FCON", 5))
  69.     lastResponse = AT_FCON;
  70. else if (strneq(buf, "+FPOLL", 6))
  71.     lastResponse = AT_FPOLL;
  72. else if (strneq(buf, "+FDIS:", 6))
  73.     lastResponse = AT_FDIS;
  74. else if (strneq(buf, "+FNSF:", 6))
  75.     lastResponse = AT_FNSF;
  76. else if (strneq(buf, "+FCSI:", 6))
  77.     lastResponse = AT_FCSI;
  78. else if (strneq(buf, "+FPTS:", 6))
  79.     lastResponse = AT_FPTS;
  80. else if (strneq(buf, "+FDCS:", 6))
  81.     lastResponse = AT_FDCS;
  82. else if (strneq(buf, "+FNSS:", 6))
  83.     lastResponse = AT_FNSS;
  84. else if (strneq(buf, "+FTSI:", 6))
  85.     lastResponse = AT_FTSI;
  86. else if (strneq(buf, "+FET:", 5))
  87.     lastResponse = AT_FET;
  88. else if (strneq(buf, "+FPA:", 5))
  89.     lastResponse = AT_FPA;
  90. else if (strneq(buf, "+FSA:", 5))
  91.     lastResponse = AT_FSA;
  92. else if (strneq(buf, "+FPW:", 5))
  93.     lastResponse = AT_FPW;
  94.     }
  95.     return (lastResponse);
  96. }
  97. /*
  98.  * Handle the page-end protocol.
  99.  */
  100. bool
  101. Class2ErsatzModem::pageDone(u_int ppm, u_int& ppr)
  102. {
  103.     ppr = 0; // something invalid
  104.     if (class2Cmd("AT+FET", ppm, AT_NOTHING)) {
  105. for (;;) {
  106.     switch (atResponse(rbuf, conf.pageDoneTimeout)) {
  107.     case AT_FPTS:
  108. if (sscanf(rbuf+6, "%u", &ppr) != 1) {
  109.     protoTrace("MODEM protocol botch ("%s"), %s",
  110. rbuf, "can not parse PPR");
  111.     return (false); // force termination
  112. }
  113. /*
  114.  * This hack produces more problems than solves (latest ZyXELs
  115.  * seem not to have the bug described below). But if there is
  116.  * some delay between +FPTS and OK, and the next command is
  117.  * feeded before OK is returned, some modems (e.g. Xircom)
  118.  * will then return an error (+FHNG:2). Nonetheless I daren't
  119.  * remove this code completely :-) -- dbely
  120.  */
  121. #if 0
  122. /*
  123.  * (In some firmware revisions...) The ZyXEL modem
  124.  * appears to drop DCD when the remote side drops
  125.  * carrier, no matter whether DCD is configured to
  126.  * follow carrier or not.  This results in a stream
  127.  * of empty lines, sometimes* followed by the requisite
  128.  * trailing OK.  As a hack workaround to deal with
  129.  * the situation we accept the post page response if
  130.  * this is the last page that we're sending and the
  131.  * page is good (i.e. we would hang up immediately anyway).
  132.  */
  133. if (ppm == PPM_EOP && ppr == PPR_MCF)
  134.     return (true);
  135. #endif     
  136. break;
  137.     case AT_OK: // normal result code
  138.     case AT_ERROR: // possible if page retransmit
  139. return (true);
  140.     case AT_FHNG:
  141. waitFor(AT_OK);
  142. /*
  143.  * Certain modems respond +FHNG:0 on the final page
  144.  * w/o providing post-page status when sending to
  145.  * broken fax machines.  We interpret this to be an
  146.  * acknowledgement, even though it's really a violation
  147.  * of the spec.
  148.  */
  149. if (ppm == PPM_EOP && ppr == 0 && isNormalHangup()) {
  150.     ppr = PPR_MCF;
  151.     return (true);
  152. }
  153. return (isNormalHangup());
  154.     case AT_EMPTYLINE:
  155.     case AT_TIMEOUT:
  156.     case AT_NOCARRIER:
  157.     case AT_NODIALTONE:
  158.     case AT_NOANSWER:
  159. goto bad;
  160.     }
  161. }
  162.     }
  163. bad:
  164.     processHangup("50"); // Unspecified Phase D error
  165.     return (false);
  166. }
  167. /*
  168.  * Abort a data transfer in progress.
  169.  */
  170. void
  171. Class2ErsatzModem::abortDataTransfer()
  172. {
  173.     protoTrace("SEND abort data transfer");
  174.     char c = CAN;
  175.     putModemData(&c, 1);
  176. }
  177. /*
  178.  * Send an end-of-transmission signal to the modem.
  179.  */
  180. bool
  181. Class2ErsatzModem::sendEOT()
  182. {
  183.     static char EOT[] = { DLE, ETX };
  184.     return (putModemData(EOT, sizeof (EOT)));
  185. }
  186. /*
  187.  * Send a page of data using the ``stream interface''.
  188.  */
  189. bool
  190. Class2ErsatzModem::sendPage(TIFF* tif, u_int pageChop)
  191. {
  192.     protoTrace("SEND begin page");
  193.     if (flowControl == FLOW_XONXOFF)
  194. setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
  195.     bool rc = sendPageData(tif, pageChop);
  196.     if (rc && conf.class2SendRTC)
  197. rc = sendRTC(params);
  198.     if (rc)
  199. rc = sendEOT();
  200.     else
  201. abortDataTransfer();
  202.     if (flowControl == FLOW_XONXOFF)
  203. setXONXOFF(getInputFlow(), FLOW_XONXOFF, ACT_DRAIN);
  204.     protoTrace("SEND end page");
  205.     return (rc ?
  206. (waitFor(AT_OK, conf.pageDoneTimeout) && hangupCode[0] == '') : rc);
  207. }