Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1338 lines
50 KiB

  1. /***************************************************************************
  2. Name : ECM.C
  3. Comment : Contains the ECM T30 routines
  4. Revision Log
  5. Date Name Description
  6. -------- ----- ---------------------------------------------------------
  7. ***************************************************************************/
  8. #include "prep.h"
  9. #include "efaxcb.h"
  10. #include "t30.h"
  11. #include "hdlc.h"
  12. #include "debug.h"
  13. ///RSL
  14. #include "glbproto.h"
  15. #define faxTlog(m) DEBUGMSG(ZONE_ECM, m)
  16. #define FILEID FILEID_ECM
  17. typedef enum
  18. {
  19. ECMRECVOK_OK,
  20. ECMRECVOK_BADFR,
  21. ECMRECVOK_ABORT
  22. }
  23. ECMRECVOK;
  24. /****************** begin prototypes from ecm.c *****************/
  25. IFR RNR_RRLoop(PThrdGlbl pTG);
  26. IFR CTC_RespRecvd(PThrdGlbl pTG, USHORT uBaud);
  27. BOOL Recv_NotReadyLoop(PThrdGlbl pTG, IFR ifrFirst, IFR ifrLast);
  28. BOOL FillInFrames(PThrdGlbl pTG, USHORT N, LONG sBufSize, USHORT uDataSize);
  29. ECMRECVOK ECMRecvOK(PThrdGlbl pTG);
  30. /***************** end of prototypes from ecm.c *****************/
  31. BYTE RCP[3] = { 0xFF, 0x03, 0x86 };
  32. ET30ACTION ECMPhaseC(PThrdGlbl pTG, BOOL fReTx)
  33. {
  34. USHORT uFrameNum, uFramesSent, uLim;
  35. SWORD swRet;
  36. ULONG lTotalLen=0;
  37. LPBYTE lpPPRMask;
  38. LPBUFFER lpbf=0;
  39. USHORT uMod;
  40. /******** Transmitter ECM Phase C. Fig A-7/T.30 (sheet 1) ********/
  41. /***
  42. switch(action = Params.lpfnWhatNext(pTG, eventSTARTSEND))
  43. {
  44. case actionCONTINUE: break;
  45. case actionDCN:
  46. case actionHANGUP: return action;
  47. case actionERROR: return action; // goto PhaseLoop & exit
  48. default: return BadAction(action);
  49. }
  50. ***/
  51. pTG->ECM.uFrameSize = ProtGetECMFrameSize(pTG);
  52. BG_CHK(pTG->ECM.uFrameSize==6 || pTG->ECM.uFrameSize==8);
  53. // already done in WhatNext
  54. // uSize = (1 << pTG->ECM.uFrameSize);
  55. // ICommSetSendMode(TRUE, uSize+ECM_EXTRA, uSize, TRUE);
  56. if(fReTx)
  57. {
  58. lpPPRMask = ProtGetRetransmitMask(pTG);
  59. }
  60. else
  61. {
  62. pTG->ECM.uPPRCount = 0;
  63. if(pTG->ECM.fEndOfPage)
  64. {
  65. pTG->ECM.SendPageCount++;
  66. pTG->ECM.SendBlockCount = 1;
  67. pTG->ECM.dwPageSize=0;
  68. faxTlog((SZMOD "Waiting for Startpage in ECM at 0x%08lx\r\n", GetTickCount()));
  69. DEBUGSTMT(IFProcProfile((HTASK)(-1), TRUE));
  70. // Callback to open file to send. Doesn't return any data
  71. if((swRet=GetSendBuf(pTG, 0, SEND_STARTPAGE)) != SEND_OK)
  72. {
  73. ERRMSG((SZMOD "<<ERROR>> Nonzero return %d from SendProc at Start Page\r\n", swRet));
  74. // return actionDCN;
  75. return actionERROR;
  76. }
  77. DEBUGSTMT(IFProcProfile((HTASK)(-1), FALSE));
  78. faxTlog((SZMOD "Got Startpage in ECM at 0x%08lx\r\n", GetTickCount()));
  79. }
  80. else
  81. {
  82. pTG->ECM.SendBlockCount++;
  83. faxTlog((SZMOD "Waiting for Startblock in ECM at 0x%08lx\r\n", GetTickCount()));
  84. DEBUGSTMT(IFProcProfile((HTASK)(-1), TRUE));
  85. // Callback to open file to send. Doesn't return any data
  86. if((swRet=GetSendBuf(pTG, 0, SEND_STARTBLOCK)) != SEND_OK)
  87. {
  88. ERRMSG((SZMOD "<<ERROR>> Nonzero return %d from SendProc at Start Page\r\n", swRet));
  89. // return actionDCN;
  90. return actionERROR;
  91. }
  92. DEBUGSTMT(IFProcProfile((HTASK)(-1), FALSE));
  93. faxTlog((SZMOD "Got Startblock in ECM at 0x%08lx\r\n", GetTickCount()));
  94. }
  95. }
  96. faxTlog((SZMOD "Starting ECM Partial Page SEND.......P=%d B=%d ReTx=%d\r\n",
  97. pTG->ECM.SendPageCount, pTG->ECM.SendBlockCount, fReTx));
  98. if(fReTx)
  99. ICommStatus(pTG, T30STATS_RESEND_ECM, pTG->ECM.SendPageCount, 0, pTG->ECM.SendBlockCount);
  100. uMod = ProtGetSendMod(pTG);
  101. if(uMod >= V17_START && !pTG->ECM.fSentCTC) uMod |= ST_FLAG;
  102. pTG->ECM.fSentCTC = FALSE;
  103. // here we should use a small timeout (100ms?) and if it fails,
  104. // should go back to sending the previous V21 frame (which could be DCS
  105. // or MPS or whatever, which is why it gets complicated & we havn't
  106. // done it!). Meanwhile use a long timeout, ignore return value
  107. // and send anyway.
  108. if(!ModemRecvSilence(pTG, pTG->Params.hModem, RECV_PHASEC_PAUSE, LONG_RECVSILENCE_TIMEOUT))
  109. {
  110. ERRMSG((SZMOD "<<ERROR>> ECM Pix RecvSilence(%d, %d) FAILED!!!\r\n", RECV_PHASEC_PAUSE, LONG_RECVSILENCE_TIMEOUT));
  111. }
  112. if(!ModemSendMode(pTG, pTG->Params.hModem, uMod, TRUE, ifrECMPIX))
  113. {
  114. ERRMSG((SZMOD "<<ERROR>> ModemSendMode failed in Tx ECM PhaseC\r\n"));
  115. ICommFailureCode(pTG, T30FAILSE_SENDMODE_PHASEC);
  116. BG_CHK(FALSE);
  117. return actionERROR;
  118. }
  119. #ifdef IFAX
  120. BroadcastMessage(pTG, IF_PSIFAX_DATAMODE, (PSIFAX_SEND|PSIFAX_ECM|(fReTx ? PSIFAX_RESEND : 0)), (uMod & (~ST_FLAG)));
  121. #endif
  122. faxTlog((SZMOD "SENDING ECM Page Data.....\r\n"));
  123. FComCriticalNeg(pTG, FALSE);
  124. uLim = (fReTx ? pTG->ECM.SendFrameCount : 256);
  125. BG_CHK(uLim);
  126. BG_CHK(lpbf == 0);
  127. for(uFrameNum=0, uFramesSent=0, lTotalLen=0, swRet=0; uFrameNum<uLim; uFrameNum++)
  128. {
  129. if(!fReTx || (lpPPRMask[uFrameNum/8] & (1 << (uFrameNum%8))))
  130. {
  131. BG_CHK(uFrameNum < 256 && pTG->ECM.uFrameSize <=8); // shift below won't ovf 16 bits
  132. BG_CHK(lpbf == 0);
  133. swRet = GetSendBuf(pTG, &lpbf, (fReTx ? ((SLONG)(uFrameNum << pTG->ECM.uFrameSize)) : SEND_SEQ));
  134. if(swRet == SEND_ERROR)
  135. {
  136. ERRMSG((SZMOD "<<ERROR>> Error return from SendProc in ECM retransmit\r\n"));
  137. BG_CHK(lpbf == 0);
  138. // return actionDCN; // goto NodeC;
  139. return actionERROR;
  140. }
  141. else if(swRet == SEND_EOF)
  142. {
  143. BG_CHK(lpbf == 0);
  144. if(!fReTx)
  145. break;
  146. else
  147. {
  148. BG_CHK(FALSE);
  149. ICommFailureCode(pTG, T30FAILSE_PHASEC_RETX_EOF);
  150. return actionDCN;
  151. }
  152. }
  153. BG_CHK(swRet == SEND_OK);
  154. BG_CHK(lpbf);
  155. BG_CHK(lpbf->lpbBegBuf+4 == lpbf->lpbBegData);
  156. lpbf->lpbBegBuf[0] = 0xFF;
  157. lpbf->lpbBegBuf[1] = 0x03;
  158. lpbf->lpbBegBuf[2] = 0x06;
  159. lpbf->lpbBegBuf[3] = (BYTE) uFrameNum;
  160. lpbf->lpbBegData -= 4;
  161. lpbf->wLengthData += 4;
  162. lTotalLen += lpbf->wLengthData;
  163. if(!ModemSendMem(pTG, pTG->Params.hModem, lpbf->lpbBegData, lpbf->wLengthData, SEND_ENDFRAME))
  164. {
  165. ERRMSG((SZMOD "<<ERROR>> DataWrite Timeout in ECM Phase C\r\n"));
  166. ICommFailureCode(pTG, T30FAILSE_MODEMSEND_PHASEC);
  167. BG_CHK(FALSE);
  168. return actionERROR; // goto error;
  169. }
  170. // faxTlog((SZMOD "Freeing 0x%08lx in ECM\r\n", lpbf));
  171. if(!MyFreeBuf(pTG, lpbf))
  172. {
  173. ERRMSG((SZMOD "<<ERROR>> FReeBuf failed in ECM Phase C\r\n"));
  174. ICommFailureCode(pTG, T30FAILSE_FREEBUF_PHASEC);
  175. BG_CHK(FALSE);
  176. return actionERROR; // goto error;
  177. }
  178. lpbf = 0;
  179. uFramesSent++;
  180. }
  181. }
  182. if( !ModemSendMem(pTG, pTG->Params.hModem, RCP, 3, SEND_ENDFRAME) ||
  183. !ModemSendMem(pTG, pTG->Params.hModem, RCP, 3, SEND_ENDFRAME) ||
  184. !ModemSendMem(pTG, pTG->Params.hModem, RCP, 3, SEND_ENDFRAME|SEND_FINAL))
  185. {
  186. ERRMSG((SZMOD "<<ERROR>> DataWrite Timeout on RCPs\r\n"));
  187. ICommFailureCode(pTG, T30FAILSE_MODEMSEND_ENDPHASEC);
  188. BG_CHK(FALSE);
  189. return actionERROR; // goto error;
  190. }
  191. /***
  192. if(!ModemDrain())
  193. return FALSE;
  194. ***/
  195. FComCriticalNeg(pTG, TRUE);
  196. faxTlog((SZMOD "Page Send Done.....len=(%ld, 0x%08x)\r\n", lTotalLen, lTotalLen));
  197. pTG->ECM.FramesSent = uFramesSent;
  198. if(!fReTx)
  199. {
  200. BG_CHK(lTotalLen>=(ULONG)uFramesSent*4);
  201. pTG->ECM.dwPageSize+= (lTotalLen-uFramesSent*4); // 4-bytes of framing data
  202. pTG->ECM.SendFrameCount = uFrameNum;
  203. switch(GetSendBuf(pTG, 0, SEND_QUERYENDPAGE))
  204. {
  205. case SEND_OK: pTG->ECM.fEndOfPage = FALSE; break;
  206. case SEND_EOF: pTG->ECM.fEndOfPage = TRUE; break;
  207. default: ERRMSG((SZMOD "<<ERROR>> Got SEND_ERROR from GetSendBuf at end of page\r\n"));
  208. return actionERROR;
  209. }
  210. }
  211. if(!pTG->ECM.FramesSent)
  212. {
  213. ERRMSG((SZMOD "<<ERROR>> Sent 0 frames--Bad PPR recvd or bad send file\r\n"));
  214. ICommFailureCode(pTG, T30FAILSE_BADPPR);
  215. return actionERROR;
  216. }
  217. pTG->T30.fSendAfterSend = TRUE; // ECM PhaseC/PIX--PPS-X
  218. return actionGONODE_V;
  219. }
  220. ET30ACTION ECMPhaseD(PThrdGlbl pTG)
  221. {
  222. USHORT uTryCount, i;
  223. ET30ACTION action;
  224. BYTE bPPSfif[3];
  225. LPBYTE lpPPR;
  226. /******** Transmitter ECM Phase D. Fig A-8 to A-17/T.30 ********/
  227. if(!pTG->ECM.fEndOfPage)
  228. {
  229. pTG->T30.ifrSend = ifrPPS_NULL;
  230. }
  231. else
  232. {
  233. switch(action = pTG->Params.lpfnWhatNext(pTG, eventPOSTPAGE))
  234. {
  235. case actionSENDMPS: pTG->T30.ifrSend = ifrPPS_MPS; break;
  236. case actionSENDEOM: pTG->T30.ifrSend = ifrPPS_EOM; break;
  237. case actionSENDEOP: pTG->T30.ifrSend = ifrPPS_EOP; break;
  238. #ifdef PRI
  239. case actionSENDPRIMPS: pTG->T30.ifrSend = ifrPPS_PRI_MPS; break;
  240. case actionSENDPRIEOM: pTG->T30.ifrSend = ifrPPS_PRI_EOM; break;
  241. case actionSENDPRIEOP: pTG->T30.ifrSend = ifrPPS_PRI_EOP; break;
  242. #endif
  243. case actionERROR: return action; // goto PhaseLoop & exit
  244. default: return BadAction(pTG, action);
  245. }
  246. }
  247. bPPSfif[0] = pTG->ECM.SendPageCount-1;
  248. bPPSfif[1] = pTG->ECM.SendBlockCount-1;
  249. BG_CHK(pTG->ECM.FramesSent && pTG->ECM.FramesSent<=256);
  250. // bPPSfif[2] = pTG->ECM.SendFrameCount-1; // don't know which one..!!
  251. bPPSfif[2] = pTG->ECM.FramesSent-1; // this one! For sure
  252. for(uTryCount=0 ;;)
  253. {
  254. SendSingleFrame(pTG, pTG->T30.ifrSend, bPPSfif, 3, 1);
  255. echoretry:
  256. pTG->T30.ifrResp = GetResponse(pTG, ifrPPSresponse);
  257. // if we hear our own frame, try to recv again. DONT retransmit!
  258. if(pTG->T30.ifrResp==pTG->T30.ifrSend) { ECHOMSG(pTG->T30.ifrResp); goto echoretry; }
  259. if(pTG->T30.ifrResp != ifrNULL && pTG->T30.ifrResp != ifrBAD)
  260. break;
  261. if(++uTryCount >= 3)
  262. {
  263. ERRMSG((SZMOD "<<ERROR>> ECM 3 PostPages, No reply\r\n"));
  264. ICommFailureCode(pTG, T30FAILSE_3POSTPAGE_NOREPLY);
  265. return actionDCN;
  266. }
  267. }
  268. switch(pTG->T30.ifrResp)
  269. {
  270. case ifrBAD:
  271. case ifrNULL: BG_CHK(FALSE); // should never get here
  272. ICommFailureCode(pTG, T30FAILSE_BUG2);
  273. return actionERROR; // in case they do :-)
  274. case ifrDCN: ERRMSG((SZMOD "<<ERROR>> Got ifrDCN from GetResponse after sending post-page command\r\n"));
  275. ICommFailureCode(pTG, T30FAILSE_POSTPAGE_DCN);
  276. return actionHANGUP;
  277. case ifrPPR: faxTlog((SZMOD "PPR (P=%d B=%d F=%d) Received: ", pTG->ECM.SendPageCount-1, pTG->ECM.SendBlockCount-1, pTG->ECM.FramesSent-1));
  278. lpPPR = ProtGetRetransmitMask(pTG);
  279. #ifdef DEBUG
  280. for(i=0; i<32; i++)
  281. faxTlog((" %02x", lpPPR[i]));
  282. faxTlog(("]\r\n"));
  283. #endif //DEBUG
  284. if(++pTG->ECM.uPPRCount >= 4)
  285. goto FourthPPR;
  286. return actionGONODE_ECMRETRANSMIT;
  287. case ifrRNR: if((pTG->T30.ifrResp=RNR_RRLoop(pTG)) == ifrDCN)
  288. {
  289. ERRMSG((SZMOD "<<ERROR>> RR_RNR loop failed\r\n"));
  290. // ICommFailureCode already called in RR_RNRLoop()
  291. return actionDCN;
  292. }
  293. faxTlog((SZMOD "Got %d from RNR\r\n", pTG->T30.ifrResp));
  294. break;
  295. }
  296. switch(pTG->T30.ifrResp)
  297. {
  298. case ifrPIP:
  299. case ifrPIN:
  300. # ifdef PRI
  301. return GONODE_E;
  302. # else
  303. ERRMSG((SZMOD "<<WARNING>> Procedure interrupts not supported\r\n"));
  304. // return actionERROR;
  305. // fallthru and treat like MCF
  306. pTG->T30.ifrResp = ifrMCF;
  307. # endif
  308. case ifrMCF:
  309. {
  310. WORD wSize = (WORD) (pTG->ECM.dwPageSize>>10); //Units are KB
  311. ICommStatus(pTG, T30STATS_CONFIRM_ECM,
  312. (USHORT) LOBYTE(wSize),
  313. (USHORT) HIBYTE(wSize),
  314. (USHORT)(pTG->ECM.SendPageCount&0xff));
  315. ERRMSG((SZMOD "Sending T30STATS_CONFIRM_pTG->ECM. wSize=%u\r\n",
  316. (unsigned) wSize));
  317. }
  318. action=pTG->Params.lpfnWhatNext(pTG, eventGOT_ECM_PPS_RESP,
  319. (UWORD)pTG->T30.ifrResp, (LPVOID)((DWORD)pTG->T30.ifrSend));
  320. if(pTG->T30.ifrSend==ifrPPS_EOP && pTG->T30.ifrResp==ifrMCF && action==actionDCN)
  321. {
  322. ICommFailureCode(pTG, T30FAILSE_SUCCESS);
  323. return actionDCN_SUCCESS;
  324. }
  325. else
  326. return action;
  327. default: ERRMSG((SZMOD "<<ERROR>> Got UNKNOWN from GetResponse after sending post-page command\r\n"));
  328. ICommFailureCode(pTG, T30FAILSE_POSTPAGE_UNKNOWN);
  329. return actionDCN;
  330. }
  331. FourthPPR:
  332. action = pTG->Params.lpfnWhatNext(pTG, event4THPPR, (WORD)pTG->ECM.SendFrameCount, (DWORD)pTG->ECM.FramesSent);
  333. switch(action)
  334. {
  335. case actionGONODE_ECMRETRANSMIT:
  336. if(CTC_RespRecvd(pTG, ProtGetSendMod(pTG)) == ifrCTR)
  337. {
  338. pTG->ECM.uPPRCount = 0;
  339. pTG->ECM.fSentCTC = TRUE;
  340. return actionGONODE_ECMRETRANSMIT;
  341. }
  342. else
  343. {
  344. ERRMSG((SZMOD "<<ERROR>> CTC-CTR failed\r\n"));
  345. // ICommFailureCode already called in CTC_RespRecvd(pTG)
  346. return actionDCN;
  347. }
  348. case actionSENDEOR_EOP:
  349. case actionDCN:
  350. case actionERROR:
  351. return action;
  352. default:
  353. return BadAction(pTG, action);
  354. // none of the EOR stuff
  355. // return actionDCN;
  356. }
  357. }
  358. ET30ACTION ECMSendEOR_EOP(PThrdGlbl pTG)
  359. {
  360. // dont set new ICommFailure codes in this function. We have already
  361. // set the 'too many retries' code
  362. USHORT uTryCount;
  363. for(uTryCount=0 ;;)
  364. {
  365. RETAILMSG((SZMOD "<<WARNING>> Sending EOR-EOP\r\n"));
  366. pTG->T30.ifrSend = ifrEOR_EOP;
  367. SendEOR_EOP(pTG);
  368. echoretry:
  369. pTG->T30.ifrResp = GetResponse(pTG, ifrEORresponse);
  370. // if we hear our own frame, try to recv again. DONT retransmit!
  371. if(pTG->T30.ifrResp==pTG->T30.ifrSend) { ECHOMSG(pTG->T30.ifrResp); goto echoretry; }
  372. if(pTG->T30.ifrResp != ifrNULL && pTG->T30.ifrResp != ifrBAD)
  373. break;
  374. if(++uTryCount >= 3)
  375. {
  376. ERRMSG((SZMOD "<<ERROR>> ECM 3 EORs, No reply\r\n"));
  377. return actionDCN;
  378. }
  379. }
  380. switch(pTG->T30.ifrResp)
  381. {
  382. case ifrBAD:
  383. case ifrNULL: BG_CHK(FALSE); // should never get here
  384. return actionERROR; // in case they do :-)
  385. case ifrDCN: ERRMSG((SZMOD "<<ERROR>> Got ifrDCN from GetResponse after sending EOR\r\n"));
  386. return actionHANGUP;
  387. case ifrRNR: RETAILMSG((SZMOD "<<WARNING>> Sent EOR-EOP, got RNR\r\n"));
  388. if((pTG->T30.ifrResp=RNR_RRLoop(pTG)) == ifrDCN)
  389. {
  390. ERRMSG((SZMOD "<<ERROR>> RR_RNR loop failed\r\n"));
  391. // ICommFailureCode already called in RR_RNRLoop(pTG)
  392. return actionDCN;
  393. }
  394. faxTlog((SZMOD "Got %d from RNR\r\n", pTG->T30.ifrResp));
  395. break;
  396. }
  397. switch(pTG->T30.ifrResp)
  398. {
  399. case ifrERR: RETAILMSG((SZMOD "<<WARNING>> Sent EOR-EOP. Got ERR. Sending DCN\r\n"));
  400. return actionDCN;
  401. default: ERRMSG((SZMOD "<<ERROR>> Got UNKNOWN from GetResponse after sending EOR\r\n"));
  402. return actionDCN;
  403. }
  404. }
  405. // reduce this so that when externally measured it always ends up less
  406. // then the specified max of 65s, so we pass protocol conformance tests
  407. #define T5_TIMEOUT 62000L // 60s + 5s
  408. IFR RNR_RRLoop(PThrdGlbl pTG)
  409. {
  410. /** Flowchart is:- Enter this on getting an RNR. Then start T5,
  411. send RR, get response (standard ResponseRecvd routine). If
  412. no response, send RR again. Repeat 3 times. If RNR response
  413. recvd, send RR again & repeat, until T5 expires, upon which
  414. send DCN & hangup.
  415. This routine returns ifrDCN, implying teh caller should
  416. go to NodeC, or ifrXXX, which is used as the response to be
  417. analysed further down the chart. Never returns ifrNULL
  418. **/
  419. UWORD i;
  420. IFR ifr;
  421. TstartTimeOut(pTG, &(pTG->ECM.toT5), T5_TIMEOUT);
  422. do
  423. {
  424. for(i=0; i<3; i++)
  425. {
  426. if(!TcheckTimeOut(pTG, &(pTG->ECM.toT5)))
  427. {
  428. ERRMSG((SZMOD "<<ERROR>> T5 timeout on Sender\r\n"));
  429. ICommFailureCode(pTG, T30FAILSE_RR_T5);
  430. return ifrDCN; // T5 timed out
  431. }
  432. SendRR(pTG);
  433. echoretry:
  434. ifr = GetResponse(pTG, ifrRRresponse);
  435. // if we hear our own frame, try to recv again. DONT retransmit!
  436. if(ifr==ifrRR) { ECHOMSG(ifr); goto echoretry; }
  437. if(ifr!=ifrNULL && ifr!=ifrBAD)
  438. break;
  439. // on ifrNULL (T4 timeout) we resend RR & try again -- 3 times
  440. }
  441. }
  442. while(ifr == ifrRNR);
  443. // BG_CHK(ifr!=ifrRNR && ifr!=ifrNULL && ifr!=ifrBAD && ifr!=ifrTIMEOUT);
  444. // can get BAD or NULL here when i=3
  445. BG_CHK(ifr!=ifrRNR && ifr!=ifrTIMEOUT);
  446. if(ifr == ifrDCN)
  447. {
  448. ERRMSG((SZMOD "<<ERROR>> Got DCN in response to RR\r\n"));
  449. ICommFailureCode(pTG, T30FAILSE_RR_DCN);
  450. }
  451. if(ifr==ifrBAD || ifr==ifrNULL)
  452. {
  453. BG_CHK(i==3);
  454. ERRMSG((SZMOD "<<ERROR>> No response to RR 3 times\r\n"));
  455. ICommFailureCode(pTG, T30FAILSE_RR_3xT4);
  456. ifr=ifrDCN; // same as T5 timeout
  457. }
  458. return ifr; // finally got a non-RNR response
  459. // return ifrDCN or ifrXXXX (not RNR)
  460. }
  461. IFR CTC_RespRecvd(PThrdGlbl pTG, USHORT uBaud)
  462. {
  463. UWORD i;
  464. IFR ifr = ifrDCN;
  465. BYTE bCTCfif[2];
  466. BG_CHK((uBaud & (~0x0F)) == 0);
  467. bCTCfif[0] = 0;
  468. bCTCfif[1] = (uBaud << 2);
  469. for(i=0; i<3; i++)
  470. {
  471. SendCTC (pTG, bCTCfif);
  472. echoretry:
  473. ifr = GetResponse(pTG, ifrCTCresponse);
  474. // if we hear our own frame, try to recv again. DONT retransmit!
  475. if(ifr==ifrCTC) { ECHOMSG(ifr); goto echoretry; }
  476. if(ifr!=ifrNULL && ifr!=ifrBAD)
  477. break;
  478. // on ifrNULL (T4 timeout) we resend RR & try again -- 3 times
  479. }
  480. if(ifr==ifrNULL || ifr==ifrBAD)
  481. {
  482. BG_CHK(i == 3);
  483. ERRMSG((SZMOD "<<ERROR>> No response to CTC 3 times\r\n"));
  484. ICommFailureCode(pTG, T30FAILSE_CTC_3xT4);
  485. ifr = ifrDCN;
  486. }
  487. else if(ifr != ifrCTR)
  488. {
  489. ERRMSG((SZMOD "<<ERROR>> Bad response CTC\r\n"));
  490. ICommFailureCode(pTG, T30FAILSE_CTC_UNKNOWN);
  491. }
  492. return ifr; // return ifrDCN or ifrXXXX
  493. }
  494. ET30ACTION ECMRecvPhaseD ( PThrdGlbl pTG)
  495. {
  496. DWORD CurrPPS;
  497. ET30ACTION action;
  498. switch(pTG->T30.ifrCommand)
  499. {
  500. case ifrPRI_MPS:
  501. case ifrPRI_EOM:
  502. case ifrPRI_EOP:
  503. # ifdef PRI
  504. return actionGONODE_RECVPRIQ;
  505. # else
  506. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPRI_MPS+ifrMPS;
  507. break;
  508. # endif
  509. case ifrPPS_PRI_MPS:
  510. case ifrPPS_PRI_EOM:
  511. case ifrPPS_PRI_EOP:
  512. # ifdef PRI
  513. goto RecvPPSPRIQ;
  514. # else
  515. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPPS_PRI_MPS+ifrPPS_MPS;
  516. break;
  517. # endif
  518. case ifrEOR_PRI_MPS:
  519. case ifrEOR_PRI_EOM:
  520. case ifrEOR_PRI_EOP:
  521. # ifdef PRI
  522. goto RecvEORPRIQ;
  523. # else
  524. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrEOR_PRI_MPS+ifrEOR_MPS;
  525. break;
  526. # endif
  527. }
  528. UsePrevCommand:
  529. switch(pTG->T30.ifrCommand)
  530. {
  531. case ifrCTC:
  532. EnterPageCrit(); //start CTR--PAGE critsection
  533. pTG->ECM.fRecvdCTC = TRUE;
  534. SendCTR(pTG);
  535. ECHOPROTECT(ifrCTR, modeECMRETX);
  536. return actionGONODE_RECVECMRETRANSMIT;
  537. case ifrPPS_NULL:
  538. case ifrPPS_MPS:
  539. case ifrPPS_EOM:
  540. case ifrPPS_EOP:
  541. // saved for PPS--RNR--RR--MCF(missed)--RR--MCF sequences
  542. pTG->ECM.ifrPrevCommand = pTG->T30.ifrCommand;
  543. //////BugFix 396//////
  544. CurrPPS = ProtGetPPS(pTG);
  545. if(pTG->ECM.ifrPrevResponse==ifrMCF && _fmemcmp(pTG->ECM.bPrevPPS, (LPBYTE)(&CurrPPS), 4)==0)
  546. goto GoSendMCF;
  547. _fmemcpy(pTG->ECM.bPrevPPS, (LPBYTE)(&CurrPPS), 4);
  548. pTG->ECM.ifrPrevResponse = 0;
  549. //////BugFix 396//////
  550. switch(ECMRecvOK(pTG))
  551. {
  552. default:
  553. case ECMRECVOK_ABORT: return actionERROR;
  554. case ECMRECVOK_OK: break;
  555. case ECMRECVOK_BADFR:
  556. EnterPageCrit(); //start PPR--PAGE critsection
  557. SendPPR(pTG, pTG->ECM.bRecvBadFrameMask);
  558. ECHOPROTECT(ifrPPR, modeECMRETX);
  559. return actionGONODE_RECVECMRETRANSMIT;
  560. }
  561. // now we can mark eop here
  562. // #ifdef PRI is on, this won't work (e.g. if the guy sends
  563. // PRI_MPS at end of page, then this needs to be called but it won't.
  564. if(pTG->T30.ifrCommand != ifrPPS_NULL
  565. && !pTG->ECM.fRecvEndOfPage) // so we won't call this twice
  566. {
  567. // RECV_ENDDOC if PPS_EOP or PPS_EOM
  568. PutRecvBuf(pTG, NULL, ((pTG->T30.ifrCommand==ifrPPS_MPS) ? RECV_ENDPAGE : RECV_ENDDOC));
  569. // ignore error/abort. We'll catch it soon enough
  570. pTG->ECM.fRecvEndOfPage = TRUE;
  571. }
  572. if(!Recv_NotReadyLoop(pTG, ifrPPS_FIRST, ifrPPS_LAST))
  573. {
  574. ICommFailureCode(pTG, T30FAILRE_PPS_RNR_LOOP);
  575. return actionHANGUP;
  576. }
  577. if(pTG->T30.ifrCommand == ifrPPS_NULL)
  578. {
  579. action = actionSENDMCF;
  580. }
  581. else switch(action = pTG->Params.lpfnWhatNext(pTG, eventRECVPOSTPAGECMD,(WORD)pTG->T30.ifrCommand))
  582. {
  583. case actionSENDMCF: break;
  584. case actionSENDRTN:
  585. case actionHANGUP:
  586. case actionERROR:
  587. default: return BadAction(pTG, action);
  588. }
  589. #ifdef PRI
  590. if(pTG->T30.ifrCommand != ifrPPS_NULL)
  591. {
  592. if((action = pTG->Params.lpfnWhatNext(pTG, eventQUERYLOCALINT))==actionTRUE)
  593. {
  594. ECHOPROTECT(ifrPIP, 0);
  595. SendPIP(pTG);
  596. break;
  597. }
  598. else if(action == actionERROR)
  599. return action;
  600. }
  601. #endif //PRI
  602. GoSendMCF:
  603. pTG->ECM.ifrPrevResponse = ifrMCF;
  604. if(pTG->T30.ifrCommand == ifrPPS_NULL || pTG->T30.ifrCommand == ifrPPS_MPS)
  605. {
  606. EnterPageCrit(); //start ECM MCF--PAGE critsection
  607. ECHOPROTECT(ifrMCF, modeECM);
  608. SendMCF(pTG);
  609. return actionGONODE_RECVPHASEC;
  610. }
  611. ECHOPROTECT(ifrMCF, 0);
  612. SendMCF(pTG);
  613. if(pTG->T30.ifrCommand==ifrPPS_EOP)
  614. return actionNODEF_SUCCESS;
  615. else
  616. break;
  617. case ifrEOR_NULL:
  618. case ifrEOR_MPS:
  619. case ifrEOR_EOM:
  620. case ifrEOR_EOP:
  621. // saved for EOR--RNR--RR--ERR(missed)--RR--ERR sequences
  622. pTG->ECM.ifrPrevCommand = pTG->T30.ifrCommand;
  623. if(pTG->T30.ifrCommand!=ifrEOR_NULL
  624. && !pTG->ECM.fRecvEndOfPage) // so we won't call this twice
  625. {
  626. // RECV_ENDDOC if EOR_EOP or EOR_EOM
  627. PutRecvBuf(pTG, NULL, ((pTG->T30.ifrCommand==ifrEOR_MPS) ? RECV_ENDPAGE : RECV_ENDDOC));
  628. // ignore error/abort. We'll catch it soon enough
  629. pTG->ECM.fRecvEndOfPage = TRUE;
  630. }
  631. if(!Recv_NotReadyLoop(pTG, ifrEOR_FIRST, ifrEOR_LAST))
  632. {
  633. ICommFailureCode(pTG, T30FAILRE_EOR_RNR_LOOP);
  634. return actionHANGUP;
  635. }
  636. #ifdef PRI
  637. if(pTG->T30.ifrCommand != ifrPPS_NULL)
  638. {
  639. if((action = pTG->Params.lpfnWhatNext(pTG, eventQUERYLOCALINT))==actionTRUE)
  640. {
  641. ECHOPROTECT(ifrPIN, 0);
  642. SendPIN(pTG);
  643. break;
  644. }
  645. else if(action == actionERROR)
  646. return action;
  647. }
  648. #endif //PRI
  649. if(pTG->T30.ifrCommand == ifrEOR_NULL || pTG->T30.ifrCommand == ifrEOR_MPS)
  650. {
  651. EnterPageCrit(); //start ERR--PAGE critsection
  652. ECHOPROTECT(ifrERR, modeECM);
  653. SendERR(pTG);
  654. return actionGONODE_RECVPHASEC;
  655. }
  656. ECHOPROTECT(ifrERR, 0);
  657. SendERR(pTG);
  658. break;
  659. case ifrRR:
  660. if(pTG->ECM.ifrPrevCommand)
  661. {
  662. pTG->T30.ifrCommand = pTG->ECM.ifrPrevCommand;
  663. goto UsePrevCommand;
  664. }
  665. else
  666. {
  667. ERRMSG((SZMOD "<<WARNING>> ignoring ERR at weird time\r\n"));
  668. break;
  669. }
  670. default:
  671. ERRMSG((SZMOD "<<WARNING>> Random Command frame received=%d\r\n", pTG->T30.ifrCommand));
  672. break; // ignore it
  673. }
  674. return actionGONODE_F;
  675. #ifdef PRI
  676. RecvPRIPPS:
  677. switch(ECMRecvOK(pTG))
  678. {
  679. default:
  680. ECMRECVOK_ABORT: return actionERROR;
  681. ECMRECVOK_OK: break;
  682. ECMRECVOK_BADFR:
  683. EnterPageCrit(); //start PRI PPR--PAGE critsection
  684. ECHOPROTECT(ifrPPR, modeECMRETX);
  685. SendPPR(pTG, pTG->ECM.bRecvBadFrameMask);
  686. return actionGONODE_RECVECMRETRANSMIT;
  687. }
  688. RecvPRIEOR:
  689. switch(action = pTG->Params.lpfnWhatNext(pTG, eventGOTPRIQ, (WORD)pTG->T30.ifrCommand))
  690. {
  691. case actionERROR: break; // return to PhaseLoop
  692. case actionHANGUP: break;
  693. case actionGONODE_F: break;
  694. case actionSENDPIP: pTG->T30.ifrSend=ifrPIP; return actionGOVOICE;
  695. case actionSENDPIN: pTG->T30.ifrSend=ifrPIN; return actionGOVOICE;
  696. case actionGO_RECVPOSTPAGE:
  697. if(pTG->T30.ifrCommand >= ifrPPS_PRI_FIRST && pTG->T30.ifrCommand <= ifrPPS_PRI_LAST)
  698. {
  699. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPPS_PRI_MPS+ifrPPS_MPS;
  700. goto NodeVIIIa;
  701. }
  702. else if(pTG->T30.ifrCommand >= ifrEOR_PRI_FIRST && pTG->T30.ifrCommand <= ifrEOR_PRI_LAST)
  703. {
  704. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrEOR_PRI_MPS+ifrEOR_MPS;
  705. goto NodeIXa;
  706. }
  707. else
  708. {
  709. BG_CHK(FALSE);
  710. }
  711. }
  712. return action;
  713. #endif //PRI
  714. }
  715. BOOL Recv_NotReadyLoop(PThrdGlbl pTG, IFR ifrFirst, IFR ifrLast)
  716. {
  717. IFR ifrCommand;
  718. // OBSOLETE:- (??)
  719. // this is wrong. We should exit only on DCN I think.
  720. // We should definitely loop again on BAD
  721. // dunno about TIMEOUT and NULL
  722. do
  723. {
  724. if(ICommRecvBufIsEmpty(pTG))
  725. return TRUE;
  726. // sleep for a while, to give FMTRES etc some CPU cycles to catch
  727. // up with us. Can sleep just before sending response, since sender
  728. // waits upto 3 (6?) secs for it.
  729. #ifndef FILET30
  730. IFProcSleep(1000);
  731. #endif
  732. SendRNR(pTG);
  733. echoretry:
  734. ifrCommand = GetCommand(pTG, ifrRNRcommand);
  735. // if we hear our own frame, try to recv again. DONT retransmit!
  736. if(ifrCommand==ifrRNR) { ECHOMSG(ifrCommand); goto echoretry; }
  737. }
  738. while( ifrCommand==ifrNULL || ifrCommand==ifrBAD ||
  739. ifrCommand == ifrRR ||
  740. (ifrCommand >= ifrFirst && ifrCommand <= ifrLast) );
  741. // This means we exit on any valid frame _except_ RR and the PPS-X
  742. // or EOR-X we were expecting. We also exit on ifrTIMEOUT which is
  743. // when the GetCommand() times out without getting any CONNECT.
  744. // Otherwise we'd end up sending an MCF after timing out which
  745. // Ricoh's protocol tester doesnt like. (Ricoh's bug numbbers B3-0106)
  746. return FALSE; // just hangs up after this
  747. }
  748. ECMRECVOK ECMRecvOK(PThrdGlbl pTG)
  749. {
  750. USHORT N, i;
  751. N = ProtGetRecvECMFrameCount(pTG);
  752. // N==actual number of frames, i.e. PPR value+1
  753. faxTlog((SZMOD "ECMRecvChk %d frames\r\n", N));
  754. if(!N || N>256)
  755. {
  756. BG_CHK(FALSE);
  757. return ECMRECVOK_ABORT;
  758. }
  759. for(i=0; i<N; i++)
  760. {
  761. if(pTG->ECM.bRecvBadFrameMask[i/8] & (1 << (i%8)))
  762. {
  763. faxTlog((SZMOD "ECMRecvChk--bad fr=%d\r\n", i));
  764. return ECMRECVOK_BADFR;
  765. }
  766. }
  767. return ECMRECVOK_OK;
  768. }
  769. ET30ACTION ECMRecvPhaseC(PThrdGlbl pTG, BOOL fRetrans)
  770. {
  771. /******** Receiver ECM Phase C. Fig A-7/T.30 (sheet 1) ********/
  772. ULONG lTotalLen=0;
  773. USHORT uRet, uFrameNum, uRCPCount, uSize;
  774. USHORT uRecvFrame, uMod;
  775. LPBUFFER lpbf;
  776. LPBUFFER lpbfShort;
  777. // There is a race between sending the CFR and sending out an
  778. // +FRM=xx command, so we want to do it ASAP.
  779. pTG->ECM.uFrameSize = ProtGetRecvECMFrameSize(pTG);
  780. BG_CHK(pTG->ECM.uFrameSize==6 || pTG->ECM.uFrameSize==8);
  781. uSize = (1 << pTG->ECM.uFrameSize);
  782. uMod = ProtGetRecvMod(pTG);
  783. if(uMod >= V17_START && !pTG->ECM.fRecvdCTC) uMod |= ST_FLAG;
  784. pTG->T30.sRecvBufSize = MY_ECMBUF_SIZE;
  785. if((uRet = ModemECMRecvMode(pTG, pTG->Params.hModem, uMod, PHASEC_TIMEOUT)) != RECV_OK)
  786. {
  787. ExitPageCrit();
  788. ERRMSG((SZMOD "<<WARNING>> ECMPhC: RecvMode ret=%d\r\n", uRet));
  789. if(!fRetrans)
  790. {
  791. // in case we miss the page entirely
  792. // and jump into PhaseD directly
  793. // init bad frame bitmask to all-bad
  794. memset(pTG->ECM.bRecvBadFrameMask, 0xFF, 32); // all bad
  795. // init the status vars for the PPS/EOR--(RR-RNR)*--PPR/MCF loop
  796. pTG->ECM.ifrPrevCommand = 0;
  797. // reset the FrameInThisBlock count. Reset only on
  798. // non-retransmit. Set when first PPS is recvd
  799. ProtResetRecvECMFrameCount(pTG);
  800. if(pTG->ECM.fRecvEndOfPage) // as opposed to end-of-block
  801. uRet = (USHORT)PutRecvBuf(pTG, NULL, RECV_STARTPAGE);
  802. else
  803. uRet = (USHORT)PutRecvBuf(pTG, NULL, RECV_STARTBLOCK);
  804. pTG->ECM.fRecvEndOfPage = FALSE;
  805. if(!uRet)
  806. {
  807. ERRMSG((SZMOD "<<ERROR>> Got Error from PutRecvBuf at StartPage/Block\r\n"));
  808. return actionERROR;
  809. }
  810. pTG->EchoProtect.modePrevRecv = modeECM;
  811. }
  812. else
  813. pTG->EchoProtect.modePrevRecv = modeECMRETX;
  814. // set global flag if we got WRONGMODE
  815. pTG->EchoProtect.fGotWrongMode = (uRet==RECV_WRONGMODE);
  816. // elim flush--does no good & wastes 10ms
  817. // ModemFlush(pTG->Params.hModem);
  818. return actionGONODE_F;
  819. // try to get 300bps command instead
  820. }
  821. ExitPageCrit();
  822. // as soon as we get good carrier ZERO the pTG->EchoProtect state
  823. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  824. // reset this flag AFTER we successfully recv LONG_TRAIN. We may get an
  825. // echo of our last command, go to NodeF, reject the echo and loop back
  826. // here. In that case we want to retry LONG train, otherwise we always
  827. // croak after a CTC
  828. pTG->ECM.fRecvdCTC = FALSE;
  829. #ifdef IFAX
  830. BroadcastMessage(pTG, IF_PSIFAX_DATAMODE, (PSIFAX_RECV|PSIFAX_ECM|(fRetrans ? PSIFAX_RERECV : 0)), (uMod & (~ST_FLAG)));
  831. #endif
  832. faxTlog((SZMOD "RECEIVING ECM Page.......\r\n"));
  833. if(fRetrans)
  834. ICommStatus(pTG, T30STATR_RERECV_ECM, 0, 0, 0);
  835. // Turn yielding on *after* entering receive mode safely!
  836. FComCriticalNeg(pTG, FALSE);
  837. /***
  838. switch(action = pTG->Params.lpfnWhatNext(eventSTARTRECV))
  839. {
  840. case actionCONTINUE: break;
  841. case actionDCN: ERRMSG((SZMOD "<<ERROR>> Got actionDCN from eventSTARTRECV\r\n"));
  842. return actionDCN; // goto NodeC;
  843. case actionHANGUP: ERRMSG((SZMOD "<<ERROR>> Got actionHANGUP from eventSTARTRECV\r\n"));
  844. return action; // goto NodeB;
  845. case actionERROR: return action;
  846. default: return BadAction(action);
  847. }
  848. ***/
  849. if(!fRetrans)
  850. {
  851. memset(pTG->ECM.bRecvBadFrameMask, 0xFF, 32);
  852. ProtResetRecvECMFrameCount(pTG);
  853. if(pTG->ECM.fRecvEndOfPage) // as opposed to end-of-block
  854. uRet = (USHORT)PutRecvBuf(pTG, NULL, RECV_STARTPAGE);
  855. else
  856. uRet = (USHORT)PutRecvBuf(pTG, NULL, RECV_STARTBLOCK);
  857. if(!uRet)
  858. {
  859. ERRMSG((SZMOD "<<ERROR>> Got Error from PutRecvBuf at StartPage/Block\r\n"));
  860. return actionERROR;
  861. }
  862. }
  863. pTG->ECM.ifrPrevCommand = 0;
  864. pTG->ECM.fRecvEndOfPage = FALSE;
  865. pTG->ECM.ifrPrevResponse = 0;
  866. DEBUGSTMT(if(fRetrans) D_PSIFAXCheckMask(pTG, pTG->ECM.bRecvBadFrameMask));
  867. // make it large, in case of large buffers & slow modems
  868. #define READ_TIMEOUT 25000
  869. lpbfShort=0;
  870. for(uFrameNum=0, lpbf=0, lTotalLen=0, uRCPCount=0, uRet=RECV_OK; uRet!=RECV_EOF;)
  871. {
  872. if(lpbf)
  873. {
  874. faxTlog((SZMOD "<<WARNING>> ECM RecvPhC: Freeing leftover Buf 0x%08lx inside loop\r\n", lpbf));
  875. MyFreeBuf(pTG, lpbf); // need to free after bad frames etc
  876. }
  877. lpbf = 0;
  878. uRet=ModemRecvBuf(pTG, pTG->Params.hModem, TRUE, &lpbf, READ_TIMEOUT);
  879. if(uRet == RECV_BADFRAME)
  880. {
  881. ERRMSG((SZMOD "<<WARNING>> ModemRecvBuf returns BADFRAME\r\n"));
  882. continue;
  883. }
  884. else if(uRet == RECV_EOF)
  885. {
  886. BG_CHK(lpbf == 0);
  887. if(lpbfShort)
  888. {
  889. lpbf = lpbfShort;
  890. lpbfShort = 0;
  891. if(fRetrans && ((USHORT)(lpbf->lpbBegData[3])+1 < ProtGetRecvECMFrameCount(pTG)))
  892. {
  893. RETAILMSG((SZMOD "<<WARNING>> DISCARDING Short but not-really-terminal FCD frame(N=%d). len=%d. PADDING to %d!!\r\n", lpbf->lpbBegData[3], lpbf->wLengthData, uSize+4));
  894. IFBufFree(lpbf);
  895. break;
  896. }
  897. else
  898. {
  899. RETAILMSG((SZMOD "<<WARNING>> Short Terminal FCD frame(N=%d). len=%d. PADDING to %d!!\r\n", lpbf->lpbBegData[3], lpbf->wLengthData, uSize+4));
  900. BG_CHK(lpbf->wLengthBuf >= uSize+4);
  901. _fmemset(lpbf->lpbBegData+lpbf->wLengthData, 0, (uSize+4-lpbf->wLengthData));
  902. lpbf->wLengthData = uSize+4;
  903. goto skipchks;
  904. }
  905. }
  906. else
  907. break;
  908. }
  909. else if(uRet != RECV_OK)
  910. {
  911. ERRMSG((SZMOD "<<WARNING>> Got %d from RecvBuf in ECMREcvPhaseC\r\n", uRet));
  912. break;
  913. }
  914. else if(lpbf==0)
  915. {
  916. // sometimes we get RECV_OK with no data. Treat same as bad frame
  917. continue;
  918. }
  919. BG_CHK(uRet==RECV_OK && lpbf && lpbf->lpbBegData);
  920. if(uRCPCount >= 3)
  921. {
  922. ERRMSG((SZMOD "<<WARNING>> Got a good frame after %d RCP\r\n", uRCPCount));
  923. continue;
  924. }
  925. if( lpbf->lpbBegData[0] != 0xFF ||
  926. lpbf->lpbBegData[1] != 0x03 ||
  927. (lpbf->lpbBegData[2] & 0x7F) != 0x06)
  928. {
  929. ERRMSG((SZMOD "<<ERROR>> Bad frame (N=%d) not caught FCF=%02x!!\r\n", uFrameNum, lpbf->lpbBegData[2]));
  930. BG_CHK(FALSE);
  931. continue;
  932. }
  933. if(lpbf->lpbBegData[2] == 0x86)
  934. {
  935. // got RCP
  936. if(lpbf->wLengthData != 3)
  937. {
  938. ERRMSG((SZMOD "<<ERROR>> Bad RCP frame len=%d\r\n", lpbf->wLengthData));
  939. BG_CHK(FALSE);
  940. continue;
  941. }
  942. uRCPCount++;
  943. faxTlog((SZMOD "Got %d RCP\r\n", uRCPCount));
  944. #ifdef CL0
  945. if(uRCPCount >= 3)
  946. {
  947. // tell modem that recv is done
  948. // but keep calling RecvMem until we get RECV_EOF
  949. ModemEndRecv(pTG, pTG->Params.hModem);
  950. }
  951. #endif //CL0
  952. continue;
  953. }
  954. if(lpbfShort)
  955. {
  956. ERRMSG((SZMOD "<<ERROR>> Short FCD frame(N=%d). len=%d DISCARDING\r\n", lpbfShort->lpbBegData[3], lpbfShort->wLengthData));
  957. MyFreeBuf(pTG, lpbfShort);
  958. lpbfShort = NULL;
  959. }
  960. if(lpbf->wLengthData > (uSize+4))
  961. {
  962. ERRMSG((SZMOD "<<ERROR>> FCD frame too long(N=%d %d). len=%d. DISCARDING\r\n", uFrameNum, lpbf->lpbBegData[3], lpbf->wLengthData));
  963. continue;
  964. }
  965. else if(lpbf->wLengthData < (uSize+4))
  966. {
  967. RETAILMSG((SZMOD "<<WARNING>> Short FCD frame(N=%d %d). len=%d. Storing\r\n", uFrameNum, lpbf->lpbBegData[3], lpbf->wLengthData));
  968. BG_CHK(lpbfShort==0);
  969. lpbfShort = lpbf;
  970. lpbf = NULL;
  971. continue;
  972. }
  973. skipchks:
  974. BG_CHK(lpbf->lpbBegData[2] == 0x06);
  975. BG_CHK(lpbf->wLengthData == (uSize+4));
  976. uRecvFrame = lpbf->lpbBegData[3];
  977. lpbf->lpbBegData += 4;
  978. lpbf->wLengthData -= 4;
  979. if(!fRetrans)
  980. {
  981. if(uFrameNum > uRecvFrame)
  982. {
  983. ERRMSG((SZMOD "<<ERROR>> Out of order frame. Got %d Looking for %d\r\n", uRecvFrame, uFrameNum));
  984. BG_CHK(FALSE);
  985. // ignore this frame in non-debug mode
  986. continue;
  987. }
  988. else if(uFrameNum < uRecvFrame)
  989. {
  990. if(!FillInFrames(pTG, (USHORT)(uRecvFrame-uFrameNum), pTG->T30.sRecvBufSize, uSize))
  991. {
  992. ERRMSG((SZMOD "<<ERROR>> Zero return from PutRecvBuf in FillInFrames\r\n"));
  993. return actionERROR;
  994. }
  995. }
  996. lTotalLen += lpbf->wLengthData;
  997. }
  998. uFrameNum = uRecvFrame;
  999. if(!fRetrans || (pTG->ECM.bRecvBadFrameMask[uFrameNum/8] & (1 << (uFrameNum%8))))
  1000. {
  1001. BG_CHK(uFrameNum < 256 && pTG->ECM.uFrameSize <=8); // shift below wont ovf 16 bits
  1002. if(!PutRecvBuf(pTG, lpbf, (fRetrans ? ((SLONG)(uFrameNum << pTG->ECM.uFrameSize)) : RECV_SEQ)))
  1003. {
  1004. ERRMSG((SZMOD "<<ERROR>> Zero return from PutRecvBuf in page\r\n"));
  1005. return actionERROR;
  1006. }
  1007. pTG->ECM.bRecvBadFrameMask[uFrameNum/8] &= ~(1 << (uFrameNum%8));
  1008. uFrameNum++;
  1009. lpbf = 0;
  1010. }
  1011. }
  1012. if(lpbf)
  1013. {
  1014. ERRMSG((SZMOD "<<ERROR>> ECMRecvPhC: Freeing leftover Buf 0x%08lx outside loop\r\n", lpbf));
  1015. MyFreeBuf(pTG, lpbf); // need to free after bad frames etc
  1016. }
  1017. if(uRet == RECV_EOF)
  1018. {
  1019. FComCriticalNeg(pTG, TRUE);
  1020. // cant mark end of page until we know if end of page or block etc.
  1021. // PutRecvBuf(NULL, RECV_ENDPAGE); // to mark end of Page
  1022. }
  1023. else
  1024. {
  1025. ERRMSG((SZMOD "<<ERROR>> DataRead Timeout or Error=%d\r\n", uRet));
  1026. BG_CHK(FALSE);
  1027. ICommFailureCode(pTG, T30FAILRE_MODEMRECV_PHASEC);
  1028. return actionERROR; // goto error;
  1029. }
  1030. faxTlog((SZMOD "ECM Page Recv Done.....len=(%ld, 0x%08x)\r\n", lTotalLen, lTotalLen));
  1031. ECHOPROTECT(0, 0);
  1032. return actionGONODE_F; // goto NodeF; // get post-message command
  1033. }
  1034. BOOL FillInFrames(PThrdGlbl pTG, USHORT N, LONG sBufSize, USHORT uDataSize)
  1035. {
  1036. USHORT i;
  1037. LPBUFFER lpbf;
  1038. for(i=0; i<N; i++)
  1039. {
  1040. #ifdef IFK
  1041. TstartTimeOut(pTG, &pTG->T30.toBuf, WAITFORBUF_TIMEOUT);
  1042. while(!(lpbf = MyAllocBuf(pTG, sBufSize)))
  1043. {
  1044. if(!TcheckTimeOut(pTG, &pTG->T30.toBuf))
  1045. {
  1046. ERRMSG((SZMOD "<<ERROR>> Giving up on BufAlloc in T30-ECM after %ld millisecs\r\n", ((ULONG)WAITFORBUF_TIMEOUT)));
  1047. BG_CHK(FALSE);
  1048. return FALSE;
  1049. }
  1050. RETAILMSG((SZMOD "<<ERROR>> BufAlloc failed in T30-pTG->ECM. Trying again\r\n"));
  1051. IFProcSleep(100);
  1052. }
  1053. #else
  1054. if(!(lpbf = MyAllocBuf( pTG, sBufSize)))
  1055. return FALSE;
  1056. #endif
  1057. lpbf->wLengthData = uDataSize;
  1058. if(!PutRecvBuf(pTG, lpbf, RECV_SEQBAD))
  1059. {
  1060. ERRMSG((SZMOD "<<ERROR>> Zero return from PutRecvBuf in page\r\n"));
  1061. return FALSE;
  1062. }
  1063. }
  1064. return TRUE;
  1065. }
  1066. #ifdef SWECM
  1067. USHORT ModemECMRecvMode(PThrdGlbl pTG, HMODEM h, USHORT uMod, ULONG ulTimeout)
  1068. {
  1069. if(!SWECMRecvSetup(pTG, TRUE))
  1070. {
  1071. BG_CHK(FALSE);
  1072. return RECV_ERROR;
  1073. }
  1074. return ModemRecvMode(pTG, h, uMod, FALSE, ulTimeout, ifrPIX_SWECM);
  1075. }
  1076. #endif //SWECM