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.

2443 lines
97 KiB

  1. /***************************************************************************
  2. Name : T30.C
  3. Comment : Contains the main T30 routine, which drives this whole baby.
  4. It calls the user-supplied protocol function to make all the
  5. protocol decision functions. Thus in a sense this merely
  6. a hollow shell.
  7. This file should be read together with the appropriate
  8. protocol function that is in use, and the T30 flowchart
  9. (the enhanced one which includes ECM that is supplied in
  10. T.30 Appendix-A). Ideally the (paper) copy of the chart
  11. which I've annotated to chow which nodes are implemented
  12. in the protocol callback function.
  13. The other routines contained here implement the T.30
  14. flowchart "subroutines" labelled "Response Received"
  15. "Command Received", "RR Response Received" and "CTC
  16. Response Received". All of which are called (only)
  17. from ET30MainBody().
  18. Most of teh real work is farmed out to HDLC.C (and macros
  19. in HDLC.H), so the T30 routine is reasonably lucid.
  20. It's organized as a block of statements with gotos between
  21. them to closely mirror the T30 flowchart. (It's actually
  22. uncannily close!)
  23. Functions: (see Prototypes just below)
  24. Revision Log
  25. Date Name Description
  26. -------- ----- ---------------------------------------------------------
  27. 06/14/92 arulm Created it in the new incarnation for the first time. The
  28. T30Main() function is re-written to call WhatNext() at *all*
  29. decision points. Some parts are simplified. It bears some
  30. resemblance to the original. Command/ResponseReceived is
  31. completely re-written.
  32. 06/15/92 arulm Added ECM. Still havn't tried compiling it.
  33. 06/16/92 arulm First successful compile.
  34. ***************************************************************************/
  35. #include "prep.h"
  36. #include "efaxcb.h"
  37. #include "t30.h"
  38. #include "hdlc.h"
  39. #include "..\comm\modemint.h"
  40. #include "..\comm\fcomint.h"
  41. #include "..\comm\mdmcmds.h"
  42. #include "debug.h"
  43. #include "tiff.h"
  44. #include "glbproto.h"
  45. #include "t30gl.h"
  46. #define faxTlog(m) DEBUGMSG(ZONE_T30, m)
  47. #define faxT2log(m) DEBUGMSG(ZONE_FRAMES, m)
  48. #define FILEID FILEID_T30
  49. #ifdef MDDI // zero-stuffing
  50. # define SetStuffZERO(x) T30SetStuffZERO(x)
  51. extern void T30SetStuffZERO(PThrdGlbl pTG, USHORT cbLineMin);
  52. extern BOOL FilterSendMem(PThrdGlbl pTG, HMODEM h, LPBYTE lpb, USHORT uCount);
  53. #else
  54. # define SetStuffZERO(pTG, x) FComSetStuffZERO(pTG, x)
  55. # define FilterSendMem(pTG, h, lpb, uCnt) ModemSendMem(pTG, h, lpb, uCnt, 0)
  56. #endif
  57. #ifdef DEBUG
  58. # define TIMESTAMP(str) \
  59. faxTlog((SZMOD "TIMESTAMP %lu %s--\r\n", (unsigned long) GetTickCount(), (LPSTR) (str)));
  60. #else // !DEBUG
  61. # define TIMESTAMP(str)
  62. #endif // !DEBUG
  63. /***************************************************************************
  64. Name : ET30MainBody
  65. Purpose : This is the main T30. It's main purpose is to faithfully
  66. reproduce the flowchart on pages 100-103 of Fascicle VII.3
  67. of the CCITT blue book, Recomendation T30.
  68. It is to be called from the protocol module after a call has
  69. been successfully placed or answered & the modem is in HDLC
  70. receive or send mode respectively. It conducts the entire call,
  71. making callbacks at all decision points to a protocol-supplied
  72. callback function. It also calls protocol-supplied callback
  73. functions to get data to send and to unload received data.
  74. Returns : When it returns, the phone is on hook & the modem reset.
  75. It returns TRUE on successful call completion, and FALSE on
  76. error. In all cases, GetLastError() will return the completion
  77. status.
  78. Arguments:
  79. Comment : This function is supposed to mirror the flowchart
  80. so it is structured as a series of statement blocks and a rats
  81. nest of Gotos. Yes I hate GOTOs too. Havn't used one in years,
  82. but try to do this yourself sometime in a "structured" way.
  83. The Labels used are the same as those used in the Flowchart, and
  84. the blocks are arranged in approximately teh same order as in
  85. the chart, so reading both together will be a pleasant surprise.
  86. Make sure you use the chart in the __APPENDIX-A__ of the
  87. **1988** (or Blue Book) CCITT specs. The chart in teh main body
  88. of teh spec is (a) deceptively similar (b) out-of-date
  89. Calls : All of HDLC.C, some of MODEM.C, and a little of FCOM.C.
  90. all the rest of the functions in this file.
  91. Called By:
  92. Revision Log
  93. Date Name Description
  94. -------- ----- ---------------------------------------------------------
  95. 06/15/92 arulm Adding ECM. Making it compilable
  96. ***************************************************************************/
  97. #ifdef MDDI
  98. # // Ricohs protocol tester complains if this exceeds 40secs
  99. # define T1_TIMEOUT 35000L // use exact 35s nominal value
  100. #else
  101. # define T1_TIMEOUT 40000L // 35s + 5s. On PCs be more lax
  102. #endif
  103. // #define T2_TIMEOUT 7000 // 6s + 1s
  104. #define T2_TIMEOUT 6000 // 6s
  105. #define T3_TIMEOUT 15000L // 10s + 5s
  106. // #define T4_TIMEOUT 3450 // 3s + 15%
  107. #define T4_TIMEOUT 3000 // 3s
  108. // #define T4_TIMEOUT 2550 // 3s - 15%
  109. // if our DCS-TCF collides with the recvrs 2nd NSF-DIS or NSC-DTC
  110. // then if the lengths are just right, we can end up in lock step
  111. // after the first try, increase the TCF-response timeout so we
  112. // get out of lock step! This is bug#6847
  113. #define TCFRESPONSE_TIMEOUT_SLACK 500 // 0.5 secs
  114. /****************** begin prototypes from t30.c *****************/
  115. ET30ACTION PhaseNodeA(PThrdGlbl pTG);
  116. ET30ACTION PhaseNodeT(PThrdGlbl pTG);
  117. ET30ACTION PhaseNodeD(PThrdGlbl pTG, BOOL);
  118. ET30ACTION NonECMPhaseC(PThrdGlbl pTG );
  119. ET30ACTION NonECMPhaseD(PThrdGlbl pTG );
  120. ET30ACTION RecvPhaseB(PThrdGlbl pTG, ET30ACTION action);
  121. ET30ACTION PhaseNodeF(PThrdGlbl pTG, BOOL, BOOL);
  122. ET30ACTION PhaseRecvCmd(PThrdGlbl pTG );
  123. ET30ACTION PhaseGetTCF(PThrdGlbl pTG, IFR, BOOL);
  124. ET30ACTION NonECMRecvPhaseC(PThrdGlbl pTG);
  125. ET30ACTION NonECMRecvPhaseD(PThrdGlbl pTG);
  126. /***************** end of prototypes from t30.c *****************/
  127. USHORT T30MainBody(PThrdGlbl pTG, BOOL fCaller, ET30ACTION actionInitial, HLINE hLine, HMODEM hModem )
  128. {
  129. ET30ACTION action;
  130. USHORT uRet;
  131. BOOL fEnteredHalfway;
  132. uRet = T30_CALLFAIL;
  133. FComCriticalNeg(pTG, TRUE);
  134. (MyDebugPrint(pTG, LOG_ALL, "\r\n\r\n\r\n\r\n\r\n======================= Entering MainBody ==============================\r\n\r\n\r\n\r\n"));
  135. // zero-init the 3 global structs T30, ECM and Params. After this some
  136. // fields are inited to non-zero below. Rest are set approp elsewhere
  137. // in the code (hopefully before use :-)
  138. _fmemset(&pTG->Params, 0, sizeof(pTG->Params));
  139. _fmemset(&pTG->T30, 0, sizeof(pTG->T30));
  140. _fmemset(&pTG->ECM, 0, sizeof(pTG->ECM));
  141. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  142. pTG->Params.hModem = hModem;
  143. pTG->Params.hLine = hLine;
  144. pTG->Params.lpfnWhatNext = ProtGetWhatNext(pTG);
  145. // INI file settings related stuff
  146. pTG->T30.uSkippedDIS = 0;
  147. // Initialize this global. Very Important!! See HDLC.C for usage.
  148. pTG->T30.fReceivedDIS = FALSE;
  149. pTG->T30.fReceivedDTC = FALSE;
  150. pTG->T30.fReceivedEOM = FALSE;
  151. pTG->T30.uTrainCount = 0;
  152. pTG->T30.uRecvTCFMod = 0xFFFF;
  153. pTG->T30.ifrCommand = pTG->T30.ifrResp = pTG->T30.ifrSend = 0;
  154. pTG->ECM.ifrPrevResponse = 0;
  155. pTG->ECM.SendPageCount = 0;
  156. pTG->ECM.fEndOfPage = pTG->ECM.fRecvEndOfPage = TRUE;
  157. pTG->T30.fAtEndOfRecvPage = FALSE;
  158. pTG->ECM.fSentCTC = FALSE;
  159. pTG->ECM.fRecvdCTC = FALSE;
  160. #ifdef SMM
  161. pTG->T30.lpfs = (LPFRAMESPACE)pTG->bStaticRecvdFrameSpace;
  162. #else
  163. #error NYI ERROR: Code Not Complete--Have to pick GMEM_ flags (FIXED? SHARE?)
  164. ...also have to call IFProcSetResFlags(hinstMe).....
  165. pTG->T30.lpfs = (LPFRAMESPACE)IFMemAlloc(0,TOTALRECVDFRAMESPACE, &uwJunk);
  166. #endif
  167. pTG->T30.Nframes = 0;
  168. fEnteredHalfway = FALSE;
  169. if(actionInitial != actionNULL)
  170. {
  171. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Got Initial Action = %d\r\n", actionInitial));
  172. action = actionInitial;
  173. fEnteredHalfway = TRUE;
  174. BG_CHK(action==actionGONODE_F || action==actionGONODE_D);
  175. }
  176. else if(fCaller) // choose the right entry point
  177. action = actionGONODE_T;
  178. else
  179. {
  180. action = actionGONODE_R1;
  181. pTG->T30.fSendAfterSend = TRUE; // CED--NSF/DIS
  182. }
  183. // fall through into PhaseLoop
  184. /******** Phase loop ********/
  185. //PhaseLoop:
  186. for(;;)
  187. {
  188. /******************************************************************************
  189. T = Start of Phase be for transmitter
  190. R1 = Start of Phase B for callee
  191. R2 = start of Phase B for poller
  192. A = Poll/Send decision point
  193. D = Start of DCS/TCF
  194. F = Recv Command loop
  195. RecvCmd = Interpretation of pre-page cmds
  196. RecvPhaseC = Start of Rx PhaseC (ECM and Non-pTG->ECM. New Page in ECM mode)
  197. I = Start of Tx PhaseC (ECM & Non-pTG->ECM. New page in ECM mode)
  198. II = Start of Tx Non-ECM PhaseD
  199. III = Start of Rx Non-ECM PhaseD
  200. IV = Start of Tx ECM PhaseC (Same page, new block)
  201. V = Start of Tx ECM PhaseD (end of partial page)
  202. VII = Start of Rx ECM PhaseD
  203. RecvPRIQ = Handling of recvd PRI-Q commands
  204. E = Handling of received PIP/PIN responses
  205. *******************************************************************************/
  206. switch(action)
  207. {
  208. case actionGONODE_T: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_T\r\n"));
  209. action = PhaseNodeT(pTG);
  210. break;
  211. case actionGONODE_D: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_D\r\n"));
  212. action = PhaseNodeD(pTG, fEnteredHalfway);
  213. fEnteredHalfway = FALSE;
  214. break;
  215. case actionGONODE_A: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_A\r\n"));
  216. action = PhaseNodeA(pTG);
  217. break;
  218. case actionGONODE_R1: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_R1\r\n"));
  219. action = RecvPhaseB(pTG, action);
  220. break;
  221. case actionGONODE_R2: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_R2\r\n"));
  222. action = RecvPhaseB(pTG, action);
  223. break;
  224. case actionNODEF_SUCCESS:
  225. (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionNODEF_SUCCESS\r\n"));
  226. action = PhaseNodeF(pTG, TRUE, FALSE);
  227. break;
  228. case actionGONODE_F: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_F\r\n"));
  229. action = PhaseNodeF(pTG, FALSE, fEnteredHalfway);
  230. fEnteredHalfway = FALSE;
  231. break;
  232. case actionGONODE_RECVCMD:
  233. (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_RECVCMD\r\n"));
  234. action = PhaseRecvCmd(pTG);
  235. break;
  236. case actionGONODE_I: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_I\r\n"));
  237. action = NonECMPhaseC(pTG);
  238. break;
  239. case actionGONODE_II: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_II\r\n"));
  240. action = NonECMPhaseD(pTG);
  241. break;
  242. case actionGONODE_III: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_III\r\n"));
  243. action = NonECMRecvPhaseD(pTG);
  244. break;
  245. case actionGONODE_IV: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_IV_New\r\n"));
  246. action = ECMPhaseC(pTG, FALSE); // ReTx
  247. break;
  248. case actionGONODE_ECMRETRANSMIT:
  249. (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_ECMRETRANSMIT\r\n"));
  250. action = ECMPhaseC(pTG, TRUE); // ReTx
  251. break;
  252. case actionGONODE_V: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_V\r\n"));
  253. action = ECMPhaseD(pTG);
  254. break;
  255. case actionSENDEOR_EOP: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionSENDEOR_EOP\r\n"));
  256. action = ECMSendEOR_EOP(pTG);
  257. break;
  258. case actionGONODE_VII: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_VII\r\n"));
  259. action = ECMRecvPhaseD(pTG);
  260. break;
  261. case actionGONODE_RECVPHASEC:
  262. // (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_RECVPHASEC\r\n"));
  263. /**/
  264. if(ProtReceivingECM(pTG))
  265. action = ECMRecvPhaseC(pTG, FALSE);
  266. else
  267. /**/
  268. action = NonECMRecvPhaseC(pTG);
  269. break;
  270. case actionGONODE_RECVECMRETRANSMIT:
  271. // (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_RECVECMRETRANSMIT\r\n"));
  272. BG_CHK(ProtReceivingECM(pTG));
  273. action = ECMRecvPhaseC(pTG, TRUE);
  274. break;
  275. case actionNULL: BG_CHK(FALSE);
  276. goto error;
  277. case actionDCN_SUCCESS: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionDCN_SUCCESS\r\n"));
  278. uRet = T30_CALLDONE;
  279. goto NodeC; // successful end of send call
  280. case actionHANGUP_SUCCESS:
  281. (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionHANGUP_SUCCESS\r\n"));
  282. ICommGotDisconnect(pTG);
  283. uRet = T30_CALLDONE;
  284. goto NodeB; // successful end of recv call
  285. case actionDCN: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionDCN\r\n"));
  286. goto NodeC;
  287. case actionHANGUP: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionHANGUP\r\n"));
  288. // This should only be called on a _successful_ completion,
  289. // otherwise we get either (a) a DCN that MSGHNDLR does not
  290. // want OR (b) A fake EOJ posted to MSGHNDLR. See bug#4019
  291. ////// ICommGotDisconnect(); /////
  292. goto NodeB;
  293. case actionERROR: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionERROR\r\n"));
  294. // ICommStatus(T30STAT_ERROR, 0, 0, 0);
  295. goto error;
  296. default: BG_CHK(FALSE);
  297. goto error;
  298. # ifdef PRI
  299. case actionGONODE_RECVPRIQ:
  300. (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_RECVPRIQ\r\n"));
  301. goto RecvPriQ;
  302. case actionGONODE_E:(MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGONODE_E\r\n"));
  303. goto NodeE;
  304. case actionGOVOICE: (MyDebugPrint(pTG, LOG_ALL, "EndPhase: Got actionGOVOICE\r\n"));
  305. goto VoiceLine;
  306. # endif
  307. }
  308. }
  309. /******** PRI-Q stuff (Rx side) ********/
  310. #ifdef PRI
  311. // no fall through here
  312. BG_CHK(FALSE);
  313. RecvPRIQ:
  314. switch(action = pTG->Params.lpfnWhatNext(pTG, eventGOTPRIQ, (WORD)pTG->T30.ifrCommand))
  315. {
  316. case actionSENDPIP: pTG->T30.ifrSend=ifrPIP; goto VoiceLine;
  317. case actionSENDPIN: pTG->T30.ifrSend=ifrPIN; goto VoiceLine;
  318. case actionGONODE_F: CLEAR_MISSED_TCFS(); break;
  319. case actionGO_RECVPOSTPAGE:
  320. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPRI_MPS+ifrMPS;
  321. action = GONODE_III;
  322. break;
  323. case actionHANGUP: break;
  324. case actionERROR: break; // goto PhaseLoop & exit
  325. //// default: return BadAction(action);
  326. }
  327. goto PhaseLoop;
  328. /******** PIP/PIN stuff (Tx side) ********/
  329. // no fall through here
  330. BG_CHK(FALSE);
  331. NodeE:
  332. switch(action = pTG->Params.lpfnWhatNext(pTG, eventGOTPIPPIN,
  333. (WORD)pTG->T30.ifrResp, (DWORD)pTG->T30.ifrSend))
  334. {
  335. case actionGOVOICE: goto VoiceLine;
  336. case actionGONODE_A: BG_CHK(FALSE); // dunno what to do here
  337. case actionDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionDCN from eventGOTPIPPIN\r\n"));
  338. action = actionDCN;
  339. break;
  340. case actionERROR: break; // goto PhaseLoop & exit
  341. //// default: return BadAction(action);
  342. }
  343. goto PhaseLoop;
  344. // no fall through here
  345. VoiceLine:
  346. SendSingleFrame(pTG, pTG->T30.ifrSend, 0, 0, 1); // re-send PRI-Q or send PIP/PIN
  347. switch(action = pTG->Params.lpfnWhatNext(pTG, eventVOICELINE))
  348. {
  349. case actionHANGUP: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionHANGUP from eventVOICELINE\r\n"));
  350. action = actionHANGUP;
  351. break;
  352. case actionGONODE_T:
  353. case actionGONODE_R1:
  354. case actionGONODE_R2: break;
  355. case actionERROR: break; // goto PhaseLoop & exit
  356. //// default: return BadAction(action);
  357. }
  358. goto PhaseLoop;
  359. #endif
  360. error:
  361. (MyDebugPrint(pTG, LOG_ERR, "=======******* USER ABORT or TRANSPORT FATAL ERROR *******========\r\n"));
  362. // must call this always, because it's resets the Modem Driver's
  363. // global state (e.g. shuts down SW framing & filters if open,
  364. // resets the state variables etc (EndMode()))
  365. // Must call it before the SendDCN() because SendDCN causes
  366. // BG_CHKs if in strange state.
  367. ModemSync(pTG, pTG->Params.hModem, RESYNC_TIMEOUT1);
  368. if(pTG->T30.fReceivedDIS || pTG->T30.fReceivedDTC)
  369. SendDCN(pTG);
  370. // hangup in T30Main
  371. // NCULink(pTG->Params.hLine, 0, 0, NCULINK_HANGUP);
  372. // already hungup?
  373. #ifndef SMM
  374. IFMemFree(pTG, pTG->T30.lpfs);
  375. #endif
  376. FComCriticalNeg(pTG, FALSE);
  377. uRet = T30_CALLFAIL;
  378. goto done;
  379. NodeC:
  380. #ifdef MDDI
  381. ModemSync(pTG, pTG->Params.hModem, RESYNC_TIMEOUT1);
  382. #else // !MDDI
  383. // +++ 4/12/95 Win95 hack -- to prevent ModemSync from sending
  384. // an AT here.
  385. ModemSyncEx(pTG, pTG->Params.hModem, RESYNC_TIMEOUT1, fMDMSYNC_DCN);
  386. #endif // !MDDI
  387. SendDCN(pTG);
  388. // falls through here
  389. NodeB:
  390. // call this here also??
  391. // ModemSync(pTG->Params.hModem, RESYNC_TIMEOUT1);
  392. // hangup in T30Main
  393. // NCULink(pTG->Params.hLine, 0, 0, NCULINK_HANGUP);
  394. #ifndef SMM
  395. IFMemFree(pTG, pTG->T30.lpfs);
  396. #endif
  397. FComCriticalNeg(pTG, FALSE);
  398. // fall through to done:
  399. done:
  400. return uRet;
  401. }
  402. // End of T30 routine!!!!!!!!!
  403. ET30ACTION PhaseNodeA(PThrdGlbl pTG)
  404. {
  405. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseNodeA \n" );
  406. if(pTG->T30.ifrCommand == ifrDIS)
  407. pTG->T30.fReceivedDIS = TRUE;
  408. else if(pTG->T30.ifrCommand == ifrDTC)
  409. pTG->T30.fReceivedDTC = TRUE;
  410. return (pTG->Params.lpfnWhatNext) (pTG, eventNODE_A, (WORD)pTG->T30.ifrCommand);
  411. }
  412. ET30ACTION PhaseNodeT(PThrdGlbl pTG)
  413. {
  414. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseNodeT \n" );
  415. /******** Transmitter Phase B. Fig A-7/T.30 (sheet 1) ********/
  416. // NodeT:
  417. // Have to redo this "DIS bit" everytime through PhaseB
  418. pTG->T30.fReceivedDIS = FALSE;
  419. // also the Received EOM stuff
  420. pTG->T30.fReceivedEOM = FALSE;
  421. // and teh received-DTC stuff
  422. pTG->T30.fReceivedDTC = FALSE;
  423. // INI file settings related stuff
  424. if(pTG->ProtParams.SendT1Timer)
  425. TstartTimeOut(pTG, &pTG->T30.toT1, pTG->ProtParams.SendT1Timer);
  426. else
  427. TstartTimeOut(pTG, &pTG->T30.toT1, T1_TIMEOUT);
  428. do
  429. {
  430. if(pTG->Params.lpfnWhatNext(pTG, eventNODE_T) == actionERROR)
  431. break;
  432. // no need for echo protection. We havnt transmitted anything!
  433. switch(pTG->T30.ifrCommand=GetCommand(pTG, ifrPHASEBcommand))
  434. {
  435. // ifrTIMEOUT means no flags before T2
  436. // ifrNULL means timeout, or loss of carrier, or no flags
  437. // or no frame. ifrBAD means *only* bad frames recvd.
  438. case ifrBAD: SendCRP(pTG); // and fall thru to NULL/TIMEOUT
  439. case ifrTIMEOUT:
  440. case ifrNULL: break;
  441. case ifrDIS: // INI file settings related stuff
  442. if(pTG->ProtParams.IgnoreDIS && ((int)pTG->T30.uSkippedDIS < pTG->ProtParams.IgnoreDIS))
  443. {
  444. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Ignoring First DIS\r\n"));
  445. pTG->T30.uSkippedDIS++;
  446. break; // continue with T1 loop
  447. }
  448. case ifrDTC:
  449. // case ifrNSF:
  450. // case ifrNSC:
  451. return actionGONODE_A; // got a valid frame
  452. default: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Caller T1: Got random ifr=%d\r\n", pTG->T30.ifrCommand));
  453. break; // continue with T1 loop
  454. }
  455. }
  456. while(TcheckTimeOut(pTG, &pTG->T30.toT1));
  457. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> T1 timeout at Caller\r\n"));
  458. ICommFailureCode(pTG, T30FAILS_T1);
  459. return actionHANGUP;
  460. }
  461. ET30ACTION PhaseNodeD(PThrdGlbl pTG, BOOL fEnteredHere)
  462. {
  463. LPLPFR lplpfr;
  464. USHORT N;
  465. ET30ACTION action;
  466. USHORT uWhichDCS; // 0=first, 1=after NoReply 2=afterFTT
  467. DWORD TiffConvertThreadId;
  468. /******** Transmitter Phase B2. Fig A-7/T.30 (sheet 1) ********/
  469. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseNodeD \n" );
  470. if (pTG->Inst.SendParams.Fax.Encoding == MR_DATA) {
  471. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MR;
  472. }
  473. else {
  474. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MH;
  475. }
  476. if (pTG->Inst.SendParams.Fax.AwRes & ( AWRES_mm080_077 | AWRES_200_200 ) ) {
  477. pTG->TiffConvertThreadParams.HiRes = 1;
  478. }
  479. else {
  480. pTG->TiffConvertThreadParams.HiRes = 0;
  481. // use LoRes TIFF file prepared by FaxSvc
  482. // pTG->lpwFileName[ wcslen(pTG->lpwFileName) - 1] = (unsigned short) ('$');
  483. }
  484. _fmemcpy (pTG->TiffConvertThreadParams.lpszLineID, pTG->lpszPermanentLineID, 8);
  485. pTG->TiffConvertThreadParams.lpszLineID[8] = 0;
  486. uWhichDCS = 0;
  487. NodeD:
  488. N = 0;
  489. lplpfr = 0;
  490. action = pTG->Params.lpfnWhatNext(pTG, eventSENDDCS,(WORD)uWhichDCS,
  491. (ULONG_PTR)((LPUWORD)&N),(ULONG_PTR)((LPLPLPFR)&lplpfr));
  492. switch(action)
  493. {
  494. case actionDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionDCN from eventSENDDCS(uWhichDCS=%d)\r\n", uWhichDCS));
  495. return actionDCN;
  496. case actionSENDDCSTCF: break;
  497. case actionSKIPTCF: break; // Ricoh hook
  498. case actionERROR: return action; // goto PhaseLoop & exit
  499. default: return BadAction(pTG, action);
  500. }
  501. NodeDprime: // used only by TCF--no reply
  502. ICommStatus(pTG, T30STATS_TRAIN, ProtGetSendMod(pTG), (USHORT)(pTG->T30.uTrainCount+1), 0);
  503. SendManyFrames(pTG, lplpfr, N);
  504. if(action != actionSKIPTCF) // Ricoh hook
  505. {
  506. if (!pTG->fTiffThreadCreated) {
  507. (MyDebugPrint(pTG, LOG_ALL, "Creating TIFF helper thread \r\n"));
  508. pTG->hThread = CreateThread(
  509. NULL,
  510. 0,
  511. (LPTHREAD_START_ROUTINE) TiffConvertThreadSafe,
  512. (LPVOID) pTG,
  513. 0,
  514. &TiffConvertThreadId
  515. );
  516. if (!pTG->hThread) {
  517. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> TiffConvertThread create FAILED\r\n"));
  518. return actionDCN;
  519. }
  520. pTG->fTiffThreadCreated = 1;
  521. pTG->AckTerminate = 0;
  522. pTG->fOkToResetAbortReqEvent = 0;
  523. if ( (pTG->RecoveryIndex >=0 ) && (pTG->RecoveryIndex < MAX_T30_CONNECT) ) {
  524. T30Recovery[pTG->RecoveryIndex].TiffThreadId = TiffConvertThreadId;
  525. T30Recovery[pTG->RecoveryIndex].CkSum = ComputeCheckSum(
  526. (LPDWORD) &T30Recovery[pTG->RecoveryIndex].fAvail,
  527. sizeof ( T30_RECOVERY_GLOB ) / sizeof (DWORD) - 1 );
  528. }
  529. }
  530. (MyDebugPrint(pTG, LOG_ALL, "SENDING TCF\r\n"));
  531. SendTCF(pTG);
  532. pTG->T30.uTrainCount++;
  533. (MyDebugPrint(pTG, LOG_ALL, "TCF Send Done\r\n"));
  534. }
  535. // no need for echo protection? Wouldnt know what to do anyway!
  536. pTG->T30.ifrResp = GetResponse(pTG, ifrTCFresponse);
  537. #ifdef RICOHAI
  538. if(fEnteredHere)
  539. {
  540. if(pTG->T30.ifrResp != ifrCFR && pTG->T30.ifrResp != ifrFTT)
  541. {
  542. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Send-side AI protocol failed\r\n"));
  543. fUsingOEMProt = 0;
  544. return actionGONODE_T;
  545. }
  546. }
  547. #else
  548. BG_CHK(!fEnteredHere);
  549. #endif
  550. switch(pTG->T30.ifrResp)
  551. {
  552. case ifrDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got ifrDCN in GetResponse after sending TCF\r\n"));
  553. ICommFailureCode(pTG, T30FAILS_TCF_DCN);
  554. return actionHANGUP; // got DCN. Must hangup
  555. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  556. case ifrNULL: // timeout. May try again
  557. if(pTG->T30.uTrainCount >= 3)
  558. {
  559. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got no reply after 3 TCFs\r\n"));
  560. ICommFailureCode(pTG, T30FAILS_3TCFS_NOREPLY);
  561. return actionDCN;
  562. }
  563. else
  564. {
  565. uWhichDCS = 1;
  566. // goto NodeD; // send new DCS??
  567. goto NodeDprime; // resend *same* DCS, same baudrate
  568. }
  569. case ifrDIS:
  570. case ifrDTC:
  571. if(pTG->T30.uTrainCount >= 3)
  572. {
  573. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got DIS/DTC after 3 TCFs\r\n"));
  574. ICommFailureCode(pTG, T30FAILS_3TCFS_DISDTC);
  575. return actionDCN;
  576. }
  577. else
  578. {
  579. pTG->T30.ifrCommand = pTG->T30.ifrResp;
  580. return actionGONODE_A;
  581. }
  582. case ifrFTT:
  583. // reset training count on FTT since we drop speed. Want to try
  584. // 3 times _without_ a response (DIS DTC doesn't count) before
  585. // giving up
  586. pTG->T30.uTrainCount = 0;
  587. uWhichDCS = 2;
  588. goto NodeD;
  589. case ifrCFR:
  590. pTG->T30.uTrainCount = 0;
  591. switch(action = pTG->Params.lpfnWhatNext(pTG, eventGOTCFR))
  592. {
  593. case actionGONODE_I: // Non-ECM PhaseC
  594. case actionGONODE_IV: // ECM PhaseC, new page
  595. return action;
  596. case actionGONODE_D: goto NodeD; // Ricoh hook
  597. case actionERROR: return action; // goto PhaseLoop & exit
  598. default: return BadAction(pTG, action);
  599. }
  600. default:
  601. {
  602. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Unknown Reply to TCF\r\n"));
  603. ICommFailureCode(pTG, T30FAILS_TCF_UNKNOWN);
  604. return actionDCN;
  605. }
  606. }
  607. BG_CHK(FALSE);
  608. }
  609. ET30ACTION NonECMPhaseC(PThrdGlbl pTG)
  610. {
  611. /******** Transmitter Phase C. Fig A-7/T.30 (sheet 1) ********/
  612. LPBUFFER lpbf=0;
  613. ULONG lTotalLen=0;
  614. SWORD swRet;
  615. USHORT uMod, uEnc;
  616. (MyDebugPrint(pTG, LOG_ALL, "T30: NonECMPhaseC Starting Page SEND.......\r\n"));
  617. /***
  618. switch(action = pTG->Params.lpfnWhatNext(eventSTARTSEND))
  619. {
  620. case actionCONTINUE: break;
  621. case actionDCN:
  622. case actionHANGUP: return action;
  623. case actionERROR: return action; // goto PhaseLoop & exit
  624. default: return BadAction(action);
  625. }
  626. ***/
  627. // already done in WhatNext
  628. // ICommSetSendMode(FALSE, MY_BIGBUF_SIZE, MY_BIGBUF_ACTUALSIZE-4, FALSE);
  629. // Callback to open file to send. Returns no data
  630. (MyDebugPrint(pTG, LOG_ALL, "Waiting for Startpage in T30 at 0x%08lx\r\n", GetTickCount()));
  631. DEBUGSTMT(IFProcProfile((HTASK)(-1), TRUE));
  632. if((swRet=GetSendBuf(pTG, 0, SEND_STARTPAGE)) != SEND_OK)
  633. {
  634. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Nonzero return %d from SendProc at Start Page\r\n", swRet));
  635. // return actionDCN;
  636. return actionERROR;
  637. }
  638. DEBUGSTMT(IFProcProfile((HTASK)(-1), FALSE));
  639. (MyDebugPrint(pTG, LOG_ALL, "Got Startpage in T30 at 0x%08lx\r\n", GetTickCount()));
  640. uEnc = ProtGetSendEncoding(pTG);
  641. BG_CHK(uEnc==MR_DATA || uEnc==MH_DATA);
  642. uMod = ProtGetSendMod(pTG);
  643. // in non-ECM mode, PhaseC is ALWAYS with short-train.
  644. // Only TCF uses long-train
  645. if(uMod >= V17_START) uMod |= ST_FLAG;
  646. //(MyDebugPrint(pTG, "Calling SendMode in T30 at 0x%08lx\r\n", GetTickCount()));
  647. // **MUST** call RecvSilence here since it is recv-followed-by-send case
  648. // here we should use a small timeout (100ms?) and if it fails,
  649. // should go back to sending the previous V21 frame (which could be DCS
  650. // or MPS or whatever, which is why it gets complicated & we havn't
  651. // done it!). Meanwhile use a long timeout, ignore return value
  652. // and send anyway.
  653. if(!ModemRecvSilence(pTG, pTG->Params.hModem, RECV_PHASEC_PAUSE, LONG_RECVSILENCE_TIMEOUT))
  654. {
  655. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Non-ECM PIX RecvSilence(%d, %d) FAILED!!!\r\n", RECV_PHASEC_PAUSE, LONG_RECVSILENCE_TIMEOUT));
  656. }
  657. if(!ModemSendMode(pTG, pTG->Params.hModem, uMod, FALSE, (IFR)((uEnc==MR_DATA) ? ifrPIX_MR : ifrPIX_MH)))
  658. {
  659. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> ModemSendMode failed in Tx PhaseC\r\n"));
  660. ICommFailureCode(pTG, T30FAILS_SENDMODE_PHASEC);
  661. BG_CHK(FALSE);
  662. return actionERROR;
  663. }
  664. //(MyDebugPrint(pTG, "Done SendMode in T30 at 0x%08lx\r\n", GetTickCount()));
  665. // need to send these quickly to avoid underrun (see bug842).
  666. // Also move the preamble/postamble into the ModemSendMode
  667. // and ModemSendMem(FINAL)
  668. // Already sent (in ModemSendMode)
  669. // SendZeros(PAGE_PREAMBLE, FALSE); // Send some zeros to warm up....
  670. // (MyDebugPrint(pTG, "SENT Preamble Training.....\r\n"));
  671. // need to set line min zeros here. get from prot and call Modem
  672. SetStuffZERO(pTG, (ProtGetMinBytesPerLine(pTG)) ); // Enable ZERO stuffing
  673. // Start yielding *after* entering PhaseC and getting some stuff into the buffer
  674. FComCriticalNeg(pTG, FALSE);
  675. // DONT SEND an EOL here. See BUG#6441. We now make sure the EOL is
  676. // added by FAXCODEC. At this level we only append the RTC
  677. #ifdef IFAX
  678. BroadcastMessage(pTG, IF_PSIFAX_DATAMODE, PSIFAX_SEND, (uMod & (~ST_FLAG)));
  679. #endif
  680. (MyDebugPrint(pTG, LOG_ALL, "SENDING Page Data.....at %ld \n", GetTickCount()));
  681. lTotalLen = 0;
  682. BG_CHK(lpbf == 0);
  683. while((swRet=GetSendBuf(pTG, &lpbf, SEND_SEQ)) == SEND_OK)
  684. {
  685. BG_CHK(lpbf);
  686. if(!lpbf->wLengthData)
  687. {
  688. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got 0 bytes from GetSendBuf--freeing buf\r\n"));
  689. MyFreeBuf(pTG, lpbf);
  690. continue;
  691. }
  692. lTotalLen += lpbf->wLengthData;
  693. if(!FilterSendMem(pTG, pTG->Params.hModem, lpbf->lpbBegData, lpbf->wLengthData))
  694. {
  695. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> DataWrite Timeout in NON-ECM Phase C\r\n"));
  696. ICommFailureCode(pTG, T30FAILS_MODEMSEND_PHASEC);
  697. BG_CHK(FALSE);
  698. return actionERROR; // goto error;
  699. }
  700. // (MyDebugPrint(pTG, "Freeing 0x%08lx in NON-ECM\r\n", lpbf));
  701. if(!MyFreeBuf(pTG, lpbf))
  702. {
  703. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> FReeBuf failed in NON-ECM Phase C\r\n"));
  704. ICommFailureCode(pTG, T30FAILS_FREEBUF_PHASEC);
  705. BG_CHK(FALSE);
  706. return actionERROR; // goto error;
  707. }
  708. lpbf = 0;
  709. }
  710. BG_CHK(!lpbf);
  711. if(swRet == SEND_ERROR)
  712. {
  713. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Error in SendBuf\r\n"));
  714. // return actionDCN;
  715. return actionERROR;
  716. }
  717. BG_CHK(swRet == SEND_EOF);
  718. (MyDebugPrint(pTG, LOG_ALL, "SENDING RTC.....at %ld \n", GetTickCount()));
  719. SetStuffZERO(pTG, 0); // Disable ZERO stuffing BEFORE sending RTC!
  720. if(!SendRTC(pTG, FALSE)) // RTC and final flag NOT set
  721. {
  722. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Error in SendMem at end-PhaseC\r\n"));
  723. BG_CHK(FALSE);
  724. ICommFailureCode(pTG, T30FAILS_MODEMSEND_ENDPHASEC);
  725. return actionERROR; // error return from ModemSendMem
  726. }
  727. // Turn off yielding *before* the buffer completely drains
  728. FComCriticalNeg(pTG, TRUE);
  729. #if (PAGE_POSTAMBLE_DIV != 0)
  730. BG_CHK(PAGE_POSTAMBLE_DIV);
  731. // Send zeros to cool off FINAL flag SET
  732. SendZeros(pTG, (USHORT)(TCFLen[uMod & 0x0F] / (PAGE_POSTAMBLE_DIV)), TRUE);
  733. #else
  734. // Need this!! Need to send the SEND_EOF flag to modem driver
  735. SendZeros(pTG, 1, TRUE); // sending 0 bytes is a bit unsafe....
  736. #endif // (PAGE_POSTAMBLE_DIV != 0)
  737. // I think this can precede the SEND_FINAL code,
  738. // to be _very_ safe put it after the whole buffer has drained
  739. // need to set line min back to 0 here.
  740. //+++SetStuffZERO(0); // Disable ZERO stuffing
  741. (MyDebugPrint(pTG, LOG_ALL, "Page Send Done.....len=(%ld, 0x%08x)\r\n", lTotalLen, lTotalLen));
  742. pTG->T30.fSendAfterSend = TRUE; // PhaseC/PIX--MPS/EOM/EOP
  743. return actionGONODE_II;
  744. }
  745. ET30ACTION NonECMPhaseD(PThrdGlbl pTG)
  746. {
  747. USHORT uTryCount;
  748. ET30ACTION action;
  749. /******** Transmitter Phase D. Fig A-7/T.30 (sheet 2) ********/
  750. // NodeII:
  751. MyDebugPrint (pTG, LOG_ALL, "T30: NonECMPhaseD \n" );
  752. switch(action = pTG->Params.lpfnWhatNext(pTG, eventPOSTPAGE))
  753. {
  754. case actionSENDMPS: pTG->T30.ifrSend = ifrMPS; break;
  755. case actionSENDEOM: pTG->T30.ifrSend = ifrEOM; break;
  756. case actionSENDEOP: pTG->T30.ifrSend = ifrEOP; break;
  757. #ifdef PRI
  758. case actionSENDPRIMPS: pTG->T30.ifrSend = ifrPRIMPS; break;
  759. case actionSENDPRIEOM: pTG->T30.ifrSend = ifrPRIEOM; break;
  760. case actionSENDPRIEOP: pTG->T30.ifrSend = ifrPRIEOP; break;
  761. #endif
  762. case actionERROR: return action; // goto PhaseLoop & exit
  763. default: return BadAction(pTG, action);
  764. }
  765. for(uTryCount=0;;)
  766. {
  767. (MyDebugPrint(pTG, LOG_ALL, "Sending postpage in T30 at %ld\r\n", GetTickCount()));
  768. // RSL dont sleep here
  769. SendSingleFrame(pTG, pTG->T30.ifrSend, 0, 0, 0);
  770. echoretry:
  771. pTG->T30.ifrResp = GetResponse(pTG, ifrPOSTPAGEresponse);
  772. // if we hear our own frame, try to recv again. DONT retransmit!
  773. if(pTG->T30.ifrResp==pTG->T30.ifrSend) { ECHOMSG(pTG->T30.ifrResp); goto echoretry; }
  774. (MyDebugPrint(pTG, LOG_ALL, "Got postpage resp in T30 at %08ld\r\n", GetTickCount()));
  775. if(pTG->T30.ifrResp != ifrNULL && pTG->T30.ifrResp != ifrBAD)
  776. break;
  777. if(++uTryCount >= 3)
  778. {
  779. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got no reply after 3 post-page commands\r\n"));
  780. ICommFailureCode(pTG, T30FAILS_3POSTPAGE_NOREPLY);
  781. return actionDCN;
  782. }
  783. }
  784. switch(pTG->T30.ifrResp)
  785. {
  786. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  787. case ifrNULL: BG_CHK(FALSE); // these should never get here
  788. ICommFailureCode(pTG, T30FAILS_BUG1);
  789. return actionERROR; // in case they do
  790. case ifrDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got ifrDCN from GetResponse after sending post-page command\r\n"));
  791. ICommFailureCode(pTG, T30FAILS_POSTPAGE_DCN);
  792. return actionHANGUP;
  793. case ifrPIN:
  794. case ifrPIP:
  795. # ifdef PRI
  796. goto NodeE;
  797. # else
  798. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Procedure interrupts not supported\r\n"));
  799. pTG->T30.ifrResp = pTG->T30.ifrResp - ifrPIP + ifrRTP;
  800. // ICommFailureCode(T30FAILS_POSTPAGE_PIPPIN);
  801. // return actionERROR;
  802. // return actionDCN;
  803. # endif
  804. // default: // fallthrough --- MCF, RTN, RTP
  805. }
  806. action = pTG->Params.lpfnWhatNext(pTG, eventGOTPOSTPAGERESP,
  807. (WORD)pTG->T30.ifrResp, (DWORD)pTG->T30.ifrSend);
  808. if(pTG->T30.ifrSend==ifrEOP &&
  809. (pTG->T30.ifrResp==ifrMCF || pTG->T30.ifrResp==ifrRTP)
  810. && action==actionDCN)
  811. {
  812. ICommFailureCode(pTG, T30FAILS_SUCCESS);
  813. return actionDCN_SUCCESS;
  814. }
  815. else
  816. return action;
  817. }
  818. ET30ACTION RecvPhaseB(PThrdGlbl pTG, ET30ACTION action)
  819. {
  820. LPLPFR lplpfr;
  821. USHORT N, i;
  822. /******** Receiver Phase B. Fig A-7/T.30 (sheet 1) ********/
  823. MyDebugPrint (pTG, LOG_ALL, "T30: RecvPhaseB \n" );
  824. if(action == actionGONODE_R1)
  825. {
  826. // NodeR1:
  827. // Have to redo this "DIS bit" everytime through PhaseB
  828. pTG->T30.fReceivedDIS = FALSE; // set to FALSE when sending DIS
  829. // also the Received EOM stuff
  830. pTG->T30.fReceivedEOM = FALSE;
  831. // and teh received-DTC stuff
  832. pTG->T30.fReceivedDTC = FALSE;
  833. N = 0;
  834. lplpfr = 0;
  835. action = pTG->Params.lpfnWhatNext(pTG, eventSENDDIS,(WORD)0,
  836. (ULONG_PTR)((LPUWORD)&N),(ULONG_PTR)((LPLPLPFR)&lplpfr));
  837. }
  838. else
  839. {
  840. // NodeR2:
  841. BG_CHK(action == actionGONODE_R2);
  842. // fix the Received EOM stuff
  843. pTG->T30.fReceivedEOM = FALSE;
  844. N = 0;
  845. lplpfr = 0;
  846. action = pTG->Params.lpfnWhatNext(pTG, eventSENDDTC,(WORD)0,
  847. (ULONG_PTR)((LPUWORD)&N),(ULONG_PTR)((LPLPLPFR)&lplpfr));
  848. }
  849. switch(action)
  850. {
  851. case actionDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionDCN from eventSENDDIS or SENDDTC\r\n"));
  852. return actionDCN;
  853. case actionSEND_DIS:
  854. case actionSEND_DTC: break;
  855. case actionERROR: return action; // goto PhaseLoop & exit
  856. default: return BadAction(pTG, action);
  857. }
  858. // INI file settings related stuff
  859. if(pTG->ProtParams.RecvT1Timer)
  860. TstartTimeOut(pTG, &pTG->T30.toT1, pTG->ProtParams.RecvT1Timer);
  861. else
  862. TstartTimeOut(pTG, &pTG->T30.toT1, T1_TIMEOUT);
  863. do
  864. {
  865. ICommStatus(pTG, T30STATR_TRAIN, 0, 0, 0);
  866. if(pTG->Params.lpfnWhatNext(pTG, eventNODE_R) == actionERROR)
  867. break;
  868. TIMESTAMP("Sending NSF-DIS")
  869. SendManyFrames(pTG, lplpfr, N);
  870. /**
  871. for(i=0; i<N; i++)
  872. SendFrame( lplpfr[i]->ifr, lplpfr[i]->fif, lplpfr[i]->cb, i==(N-1));
  873. **/
  874. pTG->T30.uRecvTCFMod = 0xFFFF;
  875. echoretry:
  876. TIMESTAMP("Getting Response")
  877. pTG->T30.ifrCommand=GetResponse(pTG, ifrPHASEBresponse);
  878. // if we hear our own frame, try to recv again. DONT retransmit!
  879. for(i=0; i<N; i++)
  880. {
  881. if(pTG->T30.ifrCommand == lplpfr[i]->ifr)
  882. {
  883. ECHOMSG(pTG->T30.ifrCommand);
  884. goto echoretry;
  885. }
  886. }
  887. switch(pTG->T30.ifrCommand)
  888. {
  889. case ifrNSS: // do same as for DCS
  890. case ifrDCS: return PhaseGetTCF(pTG, pTG->T30.ifrCommand, FALSE);
  891. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  892. case ifrNULL: break; // out of the switch() and continue with loop
  893. case ifrDCN:
  894. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got DCN after DIS or DTC\r\n"));
  895. ICommFailureCode(pTG, T30FAILR_PHASEB_DCN);
  896. return actionHANGUP; //bugfix #478
  897. default: return actionGONODE_RECVCMD;
  898. }
  899. }
  900. while(TcheckTimeOut(pTG, &(pTG->T30.toT1)));
  901. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> T1 timeout on Receiver\r\n"));
  902. ICommFailureCode(pTG, T30FAILR_T1);
  903. return actionDCN;
  904. }
  905. ET30ACTION PhaseNodeF(PThrdGlbl pTG, BOOL fEopMcf, BOOL fEnteredHere)
  906. {
  907. USHORT uFLoopCount;
  908. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseNodeF \n" );
  909. // NodeF:
  910. uFLoopCount = 0;
  911. NodeFprime:
  912. for(;;)
  913. {
  914. pTG->T30.uRecvTCFMod = 0xFFFF;
  915. echoretry:
  916. pTG->T30.ifrCommand = GetCommand(pTG, (USHORT)(pTG->EchoProtect.fGotWrongMode ? ifrNODEFafterWRONGMODE : ifrNODEFcommand));
  917. // reset the fGotWrongMode flag
  918. pTG->EchoProtect.fGotWrongMode = 0;
  919. // if we hear the last frame we sent, try to recv again. DONT retx!
  920. // bug--might have matched ifrNULL...
  921. // added: if ModemRecvMode() returns EOF then also retry. RecvMode
  922. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  923. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  924. // this case we want to retry the high speed PIX recv
  925. if(pTG->EchoProtect.ifrLastSent && (pTG->T30.ifrCommand==pTG->EchoProtect.ifrLastSent || pTG->T30.ifrCommand==ifrEOFfromRECVMODE))
  926. {
  927. ECHOMSG(pTG->T30.ifrCommand);
  928. switch(pTG->EchoProtect.modePrevRecv)
  929. {
  930. default:
  931. case modeNONE: goto echoretry;
  932. case modeNONECM: return actionGONODE_RECVPHASEC;
  933. case modeECM: return actionGONODE_RECVPHASEC;
  934. case modeECMRETX:return actionGONODE_RECVECMRETRANSMIT;
  935. }
  936. }
  937. // as soon as we get anything else ZERO the pTG->EchoProtect state
  938. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  939. // reset this flag if we fail completely to train after a CTC. We may
  940. // get an echo of our last command, go to NodeF, reject the echo and
  941. // loop back to ECMRecvPhaseC. AT that point we need this flag STILL
  942. // set so we try to recv LONG train. HOWEVER should the ECMRecvPhaseC
  943. // fail for some OTHER reason than echo, this flag need to be reset
  944. // here or it may stay alive confusing something much later.
  945. pTG->ECM.fRecvdCTC = FALSE;
  946. #ifdef RICOHAI
  947. if(fEnteredHere)
  948. {
  949. if(pTG->T30.ifrCommand!=ifrNSS)
  950. {
  951. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Recv-side AI protocol failed\r\n"));
  952. fUsingOEMProt = 0;
  953. return actionGONODE_R1;
  954. }
  955. }
  956. #else
  957. BG_CHK(!fEnteredHere);
  958. #endif
  959. switch(pTG->T30.ifrCommand)
  960. {
  961. // ifrNULL means T2 timeout, or loss of carrier, or no flags
  962. // or no frame. ifrBAD means *only* bad frame(s) recvd.
  963. case ifrNSS: // do same as for DCS
  964. case ifrDCS: return PhaseGetTCF(pTG, pTG->T30.ifrCommand, fEnteredHere);
  965. // ifrDCS is highly time-critical!!
  966. case ifrBAD: SendCRP(pTG); // and fall thru to ifrNULL
  967. case ifrNULL: break; // Loop again, until timeout
  968. case ifrTIMEOUT: goto T2Timeout;
  969. // ifrTIMEOUT means T2 timed out without flags...
  970. case ifrDCN: if(fEopMcf)
  971. {
  972. ICommFailureCode(pTG, T30FAILR_SUCCESS);
  973. return actionHANGUP_SUCCESS;
  974. }
  975. else
  976. {
  977. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> DCN following UNKNOWN on Receiver\r\n"));
  978. ICommFailureCode(pTG, T30FAILR_UNKNOWN_DCN1);
  979. return actionHANGUP;
  980. }
  981. default: return actionGONODE_RECVCMD;
  982. }
  983. }
  984. T2Timeout:
  985. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> T2 timed out\r\n"));
  986. // restart PhaseB after T2 timeout IFF (a) EOM or PPS-EOM was recvd
  987. // AND (b) If we are in ECM mode, the last response sent was n MCF
  988. // This avoids us doing this after sending a CTR, RNR or PPR
  989. // Ricoh's protocol conformance tester doesnt like this. This is
  990. // Ricoh's bug numbbers B3-0142, 0143, 0144
  991. if(pTG->T30.fReceivedEOM && (ProtReceivingECM(pTG) ? (pTG->ECM.ifrPrevResponse==ifrMCF) : TRUE) )
  992. return actionGONODE_R1;
  993. else if(ProtReceivingECM(pTG) && ++uFLoopCount<3)
  994. goto NodeFprime;
  995. #ifdef PRI
  996. else // no EOM && (no ECM || 3 times)
  997. {
  998. if((pTG->Params.lpfnWhatNext(pTG, eventQUERYLOCALINT))==actionTRUE)
  999. goto NodeF;
  1000. }
  1001. #endif
  1002. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got T2 timeout in GetCommand\r\n"));
  1003. ICommFailureCode(pTG, T30FAILR_T2);
  1004. return actionHANGUP;
  1005. }
  1006. ET30ACTION PhaseRecvCmd(PThrdGlbl pTG)
  1007. {
  1008. ET30ACTION action;
  1009. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseRecvCmd \n" );
  1010. if(pTG->T30.ifrCommand == ifrDCN)
  1011. {
  1012. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got DCN in GetCommand\r\n"));
  1013. ICommFailureCode(pTG, T30FAILR_UNKNOWN_DCN2);
  1014. return actionHANGUP;
  1015. }
  1016. if( pTG->T30.ifrCommand==ifrDTC || pTG->T30.ifrCommand==ifrDCS ||
  1017. pTG->T30.ifrCommand==ifrDIS || pTG->T30.ifrCommand==ifrNSS)
  1018. {
  1019. switch(action = pTG->Params.lpfnWhatNext(pTG, eventRECVCMD, (WORD)pTG->T30.ifrCommand))
  1020. {
  1021. case actionGETTCF: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> MainBody: Wrong Way to GETTCF\r\n"));
  1022. ICommFailureCode(pTG, T30FAILR_BUG2);
  1023. BG_CHK(FALSE);
  1024. return actionERROR;
  1025. case actionGONODE_A: return actionGONODE_A;
  1026. case actionGONODE_D: return action;
  1027. case actionHANGUP: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionHANGUP from eventRECVCMD\r\n"));
  1028. return action;
  1029. case actionERROR: return action; // goto PhaseLoop & exit
  1030. default: return BadAction(pTG, action);
  1031. }
  1032. }
  1033. if( pTG->T30.ifrCommand == ifrEOM || pTG->T30.ifrCommand == ifrPRI_EOM ||
  1034. pTG->T30.ifrCommand == ifrPPS_EOM || pTG->T30.ifrCommand == ifrPPS_PRI_EOM ||
  1035. pTG->T30.ifrCommand == ifrEOR_EOM || pTG->T30.ifrCommand == ifrEOR_PRI_EOM)
  1036. pTG->T30.fReceivedEOM = TRUE;
  1037. if(ProtReceivingECM(pTG))
  1038. return actionGONODE_VII;
  1039. else if(pTG->T30.ifrCommand >= ifrPRI_FIRST && pTG->T30.ifrCommand <= ifrPRI_LAST)
  1040. {
  1041. #ifdef PRI
  1042. return actionGONODE_RECVPRIQ;
  1043. #else
  1044. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPRI_MPS+ifrMPS;
  1045. // fall thru to GONODEIII
  1046. #endif
  1047. }
  1048. if(pTG->T30.ifrCommand >= ifrMPS && pTG->T30.ifrCommand <= ifrEOP)
  1049. return actionGONODE_III;
  1050. else
  1051. {
  1052. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got UNKNOWN in GetCommand\r\n"));
  1053. ICommFailureCode(pTG, T30FAILR_UNKNOWN_UNKNOWN2);
  1054. return actionHANGUP;
  1055. }
  1056. /***
  1057. else if(pTG->T30.ifrCommand >= ifrMPS && pTG->T30.ifrCommand <= ifrEOP)
  1058. return actionGONODE_III;
  1059. else if(pTG->T30.ifrCommand >= ifrECM_FIRST && ProtReceivingECM())
  1060. return actionGONODE_VII;
  1061. #ifdef PRI
  1062. else if(pTG->T30.ifrCommand >= ifrPRI_FIRST && pTG->T30.ifrCommand <= ifrPRI_LAST)
  1063. return actionGONODE_RECVPRIQ;
  1064. #endif
  1065. ***/
  1066. }
  1067. ET30ACTION PhaseGetTCF(PThrdGlbl pTG, IFR ifr, BOOL fEnteredHere)
  1068. {
  1069. SWORD swRet;
  1070. IFR ifrDummy;
  1071. ET30ACTION action;
  1072. MyDebugPrint (pTG, LOG_ALL, "T30: PhaseGetTCF \n" );
  1073. if(pTG->T30.uRecvTCFMod == 0xFFFF) // uninitialised
  1074. {
  1075. ECHOPROTECT(0, 0);
  1076. CLEAR_MISSED_TCFS();
  1077. action = actionGONODE_F;
  1078. goto error;
  1079. }
  1080. #ifdef OEMNSF
  1081. else if(pTG->T30.uRecvTCFMod == 0xFF)
  1082. {
  1083. swRet = 0;
  1084. goto sendcfr;
  1085. }
  1086. #endif
  1087. swRet = GetTCF(pTG); // swRet = errs per 1000, +ve or 0 if we think its good
  1088. // -ve if we think its bad. -1111 if other error
  1089. // -1000 if too short
  1090. if(swRet < -1000)
  1091. {
  1092. BG_CHK(swRet == -1112 || swRet == -1113);
  1093. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Timed out/missed getting TCF\r\n"));
  1094. ECHOPROTECT(0, 0);
  1095. #ifndef MDDI
  1096. pTG->T30.uMissedTCFs++;
  1097. if (pTG->T30.uMissedTCFs >= MAX_MISSED_TCFS_BEFORE_FTT)
  1098. {
  1099. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Sending FTT after %u missed TCFs\r\n",
  1100. (unsigned) pTG->T30.uMissedTCFs));
  1101. CLEAR_MISSED_TCFS();
  1102. swRet = -1000; // We pretend we got a too-short TCF.
  1103. }
  1104. else
  1105. #endif // !MDDI
  1106. {
  1107. action = actionGONODE_F;
  1108. goto error;
  1109. }
  1110. }
  1111. #ifdef OEMNSF
  1112. sendcfr:
  1113. #endif
  1114. // Here we can also signal the frames received before DCS!
  1115. // Were no longer in time-critical mode, so call all the
  1116. // callbacks we skipped. One for recording the received frames
  1117. // and one for handling teh received command, i.e. DCS.
  1118. // (the only options the protocol has is actionGETTCF or HANGUP)
  1119. ifrDummy = ifr;
  1120. action = pTG->Params.lpfnWhatNext(pTG, eventGOTFRAMES, pTG->T30.Nframes,
  1121. (ULONG_PTR)((LPLPFR)(pTG->T30.lpfs->rglpfr)), (ULONG_PTR)((LPIFR)(&ifrDummy)));
  1122. if(action == actionERROR)
  1123. goto error;
  1124. if(ifr != ifrDummy)
  1125. {
  1126. switch(ifrDummy)
  1127. {
  1128. case ifrNULL:
  1129. case ifrBAD:
  1130. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got ifrBAD from whatnext after recv TCF\r\n"));
  1131. ECHOPROTECT(0, 0);
  1132. CLEAR_MISSED_TCFS();
  1133. action = actionGONODE_F;
  1134. goto error;
  1135. default:
  1136. BG_CHK(FALSE);
  1137. break;
  1138. }
  1139. }
  1140. // BG_CHK(action == actionNULL);
  1141. // BG_CHK(ifrDummy == ifr);
  1142. // Now call teh callback to check the received TCF and
  1143. // return either FTT or CFR
  1144. switch(action = pTG->Params.lpfnWhatNext(pTG, eventGOTTCF,(WORD)swRet))
  1145. {
  1146. case actionSENDCFR:
  1147. (MyDebugPrint(pTG, LOG_ALL, "Good TCF\r\n"));
  1148. EnterPageCrit(); // start the CFR--PAGE critsection
  1149. SendCFR(pTG); // after sending CFR we are again in a race
  1150. ECHOPROTECT(ifrCFR, 0); // dunno recv mode yet
  1151. return actionGONODE_RECVPHASEC;
  1152. case actionSENDFTT:
  1153. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Bad TCF.....!!!\r\n"));
  1154. SendFTT(pTG);
  1155. ECHOPROTECT(ifrFTT, 0);
  1156. CLEAR_MISSED_TCFS();
  1157. return actionGONODE_F;
  1158. case actionERROR:
  1159. goto error;
  1160. default:
  1161. action = BadAction(pTG, action);
  1162. goto error;
  1163. }
  1164. error:
  1165. // missed TCF or no NSS. Did _not_ reply to TCF
  1166. // if we sent a reply, must _not_ come here
  1167. #ifdef RICOHAI
  1168. if(fEnteredHere)
  1169. return actionGONODE_R1;
  1170. #else
  1171. BG_CHK(!fEnteredHere);
  1172. #endif
  1173. return action;
  1174. }
  1175. ET30ACTION NonECMRecvPhaseC(PThrdGlbl pTG)
  1176. {
  1177. /******** Receiver Phase C. Fig A-7/T.30 (sheet 1) ********/
  1178. LPBUFFER lpbf;
  1179. ULONG lTotalLen=0;
  1180. USHORT uRet, uMod, uEnc;
  1181. DWORD tiffCompression;
  1182. LPSTR lpsTemp;
  1183. DWORD HiRes;
  1184. // There is a race between sending the CFR and sending out an
  1185. // +FRM=xx command, so we want to do it ASAP.
  1186. MyDebugPrint (pTG, LOG_ALL, "T30: NonECMRecvPhaseC \n" );
  1187. uEnc = ProtGetRecvEncoding(pTG);
  1188. BG_CHK(uEnc==MR_DATA || uEnc==MH_DATA);
  1189. if (uEnc == MR_DATA) {
  1190. tiffCompression = TIFF_COMPRESSION_MR;
  1191. }
  1192. else {
  1193. tiffCompression = TIFF_COMPRESSION_MH;
  1194. }
  1195. if (pTG->ProtInst.RecvParams.Fax.AwRes & (AWRES_mm080_077 | AWRES_200_200) ) {
  1196. HiRes = 1;
  1197. }
  1198. else {
  1199. HiRes = 0;
  1200. }
  1201. //
  1202. // do it once per RX
  1203. //
  1204. if ( !pTG->fTiffOpenOrCreated) {
  1205. //
  1206. // top 32bits of 64bit handle are guaranteed to be zero
  1207. //
  1208. pTG->Inst.hfile = PtrToUlong(TiffCreateW ( pTG->lpwFileName,
  1209. tiffCompression,
  1210. 1728,
  1211. FILLORDER_LSB2MSB,
  1212. HiRes
  1213. ) );
  1214. if (! (pTG->Inst.hfile)) {
  1215. lpsTemp = UnicodeStringToAnsiString(pTG->lpwFileName);
  1216. MyDebugPrint(pTG, LOG_ERR, "ERROR:Can't create tiff file %s compr=%d \n",
  1217. lpsTemp,
  1218. tiffCompression);
  1219. MemFree(lpsTemp);
  1220. return actionERROR;
  1221. }
  1222. pTG->fTiffOpenOrCreated = 1;
  1223. lpsTemp = UnicodeStringToAnsiString(pTG->lpwFileName);
  1224. MyDebugPrint(pTG, LOG_ALL, "Created tiff file %s compr=%d HiRes=%d \n",
  1225. lpsTemp, tiffCompression, HiRes);
  1226. MemFree(lpsTemp);
  1227. }
  1228. uMod = ProtGetRecvMod(pTG);
  1229. // in non-ECM mode, PhaseC is ALWAYS with short-train.
  1230. // Only TCF uses long-train
  1231. if(uMod >= V17_START) uMod |= ST_FLAG;
  1232. pTG->T30.sRecvBufSize = MY_BIGBUF_SIZE;
  1233. if((uRet = ModemRecvMode(pTG, pTG->Params.hModem, uMod, FALSE, PHASEC_TIMEOUT,
  1234. (IFR)((uEnc==MR_DATA) ? ifrPIX_MR : ifrPIX_MH))) != RECV_OK)
  1235. {
  1236. ExitPageCrit();
  1237. // reset Page ack. In case we miss page completely
  1238. ProtResetRecvPageAck(pTG);
  1239. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> NonECMPhC: RecvMode returned %d\r\n", uRet));
  1240. pTG->EchoProtect.modePrevRecv = modeNONECM;
  1241. // set global flag if we got WRONGMODE
  1242. pTG->EchoProtect.fGotWrongMode = (uRet==RECV_WRONGMODE);
  1243. // elim flush--does no good & wastes 10ms
  1244. // ModemFlush(pTG->Params.hModem);
  1245. CLEAR_MISSED_TCFS();
  1246. return actionGONODE_F;
  1247. // try to get 300bps command
  1248. // return actionHANGUP;
  1249. // goto error instead. No way to recover from here!
  1250. }
  1251. ExitPageCrit();
  1252. // as soon as we get good carrier ZERO the EchoProtect state
  1253. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  1254. #ifdef IFAX
  1255. BroadcastMessage(pTG, IF_PSIFAX_DATAMODE, PSIFAX_RECV, (uMod & (~ST_FLAG)));
  1256. #endif
  1257. (MyDebugPrint(pTG, LOG_ALL, "RECEIVING Page.......\r\n"));
  1258. // reset Page ack
  1259. ProtResetRecvPageAck(pTG);
  1260. // Turn yielding on *after* entering receive mode safely!
  1261. FComCriticalNeg(pTG, FALSE);
  1262. /***
  1263. switch(action = pTG->Params.lpfnWhatNext(eventSTARTRECV))
  1264. {
  1265. case actionCONTINUE: break;
  1266. case actionDCN: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionDCN from eventSTARTRECV\r\n"));
  1267. return actionDCN; // goto NodeC;
  1268. case actionHANGUP: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionHANGUP from eventSTARTRECV\r\n"));
  1269. return actionHANGUP; // goto NodeB;
  1270. case actionERROR: return action; // goto PhaseLoop & exit
  1271. default: return BadAction(action);
  1272. }
  1273. ***/
  1274. /***
  1275. BG_CHK((BOOL)Comm.dcb.fOutX == FALSE);
  1276. // Paranoia! Dont want to take ^Q/^S from modem to
  1277. // be XON/XOFF in the receive data phase!!
  1278. FComInFilterInit();
  1279. ***/
  1280. // to mark start of Page
  1281. if(!PutRecvBuf(pTG, NULL, RECV_STARTPAGE))
  1282. {
  1283. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Zero return from PutRecvBuf(start page)\r\n"));
  1284. return actionERROR;
  1285. }
  1286. // make it large, in case of large buffers & slow modems
  1287. #define READ_TIMEOUT 25000
  1288. lTotalLen = 0;
  1289. do
  1290. {
  1291. uRet=ModemRecvBuf(pTG, pTG->Params.hModem, FALSE, &lpbf, READ_TIMEOUT);
  1292. // lpbf==0 && uRet==RECV_OK just does nothing & loops back
  1293. if (uRet == RECV_EOF) {
  1294. // indicate that this is actually last recv_seq (we've got dle/etx already).
  1295. (MyDebugPrint(pTG, LOG_ALL, "RECV: NonECMRecvPhaseC fLastReadBlock = 1 \n"));
  1296. pTG->fLastReadBlock = 1;
  1297. }
  1298. if(lpbf)
  1299. {
  1300. lTotalLen += lpbf->wLengthData;
  1301. if(!PutRecvBuf(pTG, lpbf, RECV_SEQ))
  1302. {
  1303. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Zero return from PutRecvBuf in page\r\n"));
  1304. return actionERROR;
  1305. }
  1306. lpbf = 0;
  1307. }
  1308. else {
  1309. if ( pTG->fLastReadBlock == 1) {
  1310. PutRecvBuf(pTG, lpbf, RECV_FLUSH);
  1311. }
  1312. }
  1313. }
  1314. while(uRet == RECV_OK);
  1315. if(uRet == RECV_EOF)
  1316. {
  1317. FComCriticalNeg(pTG, TRUE);
  1318. pTG->T30.fAtEndOfRecvPage = TRUE;
  1319. // call this *after* getting MPS/EOM/EOP
  1320. // PutRecvBuf(NULL, RECV_ENDPAGE); // to mark end of Page
  1321. }
  1322. else
  1323. {
  1324. // Timeout from ModemRecvBuf
  1325. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> DataRead Timeout or Error=%d\r\n", uRet));
  1326. // BG_CHK(FALSE);
  1327. ICommFailureCode(pTG, T30FAILR_MODEMRECV_PHASEC);
  1328. return actionERROR; // goto error;
  1329. }
  1330. (MyDebugPrint(pTG, LOG_ALL, "Page Recv Done.....len=(%ld, 0x%08x)\r\n", lTotalLen, lTotalLen));
  1331. ECHOPROTECT(0, 0);
  1332. CLEAR_MISSED_TCFS();
  1333. return actionGONODE_F; // goto NodeF; // get post-message command
  1334. }
  1335. ET30ACTION NonECMRecvPhaseD(PThrdGlbl pTG)
  1336. {
  1337. ET30ACTION action;
  1338. ET30ACTION ret;
  1339. MyDebugPrint (pTG, LOG_ALL, "T30: NonECMRecvPhaseD \n" );
  1340. /******** Receiver Phase D. Fig A-7/T.30 (sheet 2) ********/
  1341. // NodeIII:
  1342. /** Here the T30 flowchart is all BS. Fundamentally relying on
  1343. a +FCERROR response is not possible, so what we do here really
  1344. depends on what we've got. (According to the T30 flowchart we
  1345. return to NodeF after sending MCF/RTP/RTN, in all cases. What we
  1346. now know is that,
  1347. after MPS/MCF goto RecvPhaseC to get the next page
  1348. after EOM/MCF goto NodeR1 and send NSF etc all over again
  1349. ***changed*** go back to NodeF, wait for T2 timeout
  1350. before sending DIS all over again.
  1351. after EOP/MCF goto NodeF, where GetResponse() will get
  1352. a DCN and we end up in NodeB (disconnect)
  1353. after xxx/RTN or xxx/RTP, I don't know what to do, but my guess
  1354. (looking at the Sender side of T30 flowchart) is:-
  1355. after MPS/RTx goto NodeF (sender goes to NodeD)
  1356. after EOP/RTx goto NodeF (sender goes to D or C)
  1357. after EOM/RTx goto NodeR1 (sender goes to NodeT)
  1358. ***changed*** go back to NodeF, wait for T2 timeout
  1359. before sending DIS all over again.
  1360. ****/
  1361. // only MPS/EOM/EOP commands come here
  1362. if(pTG->T30.fAtEndOfRecvPage) // so we won't call this twice
  1363. {
  1364. // This calls ET30ProtRecvPageAck so that WhatNext can choose
  1365. // MCF or RTN respectively. So it *must* be done before the
  1366. // call to WhatNext below
  1367. // RECV_ENDDOC if EOP or EOM
  1368. PutRecvBuf(pTG, NULL, ((pTG->T30.ifrCommand==ifrMPS) ? RECV_ENDPAGE : RECV_ENDDOC));
  1369. // ignore error/abort. We'll catch it soon enough
  1370. pTG->T30.fAtEndOfRecvPage = FALSE;
  1371. }
  1372. // returns MCF if page was OK, or RTN if it was bad
  1373. ret=actionGONODE_F;
  1374. ECHOPROTECT(0, 0);
  1375. CLEAR_MISSED_TCFS();
  1376. switch(action = pTG->Params.lpfnWhatNext(pTG, eventRECVPOSTPAGECMD,(WORD)pTG->T30.ifrCommand))
  1377. {
  1378. case actionSENDMCF: if(pTG->T30.ifrCommand==ifrMPS)
  1379. {
  1380. EnterPageCrit(); //start MPS--PAGE critsection
  1381. ECHOPROTECT(ifrMCF, modeNONECM);
  1382. ret=actionGONODE_RECVPHASEC;
  1383. }
  1384. else if(pTG->T30.ifrCommand==ifrEOP)
  1385. {
  1386. ECHOPROTECT(ifrMCF, 0);
  1387. CLEAR_MISSED_TCFS();
  1388. ret=actionNODEF_SUCCESS;
  1389. }
  1390. SendMCF(pTG);
  1391. break;
  1392. case actionSENDRTN: ECHOPROTECT(ifrRTN, 0);
  1393. SendRTN(pTG);
  1394. break;
  1395. case actionHANGUP: (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got actionHANGUP from eventRECVPOSTPAGECMD\r\n"));
  1396. ret=actionHANGUP;
  1397. break;
  1398. // case actionSENDRTP: SendRTP(pTG); break; // never send RTP
  1399. case actionERROR: ret=action; break; // goto PhaseLoop & exit
  1400. default: return BadAction(pTG, action);
  1401. }
  1402. return ret;
  1403. }
  1404. /***************************************************************************
  1405. Name : IFR GetCmdResp(BOOL fCommand)
  1406. Purpose : Implement the "Command Received" and "Response Received"
  1407. subroutines in the T.30 flowchart. The following macros are
  1408. defined:-
  1409. #define GetResponse() GetCmdResp(FALSE)
  1410. #define GetCommand() GetCmdResp(TRUE)
  1411. where the first form results in a faithful implem.
  1412. of the "Response Received" subroutine, the 2nd one
  1413. changes two things (i) the timeout for getting falgs goes from
  1414. T4 to T2, and (ii) if the routine times out on the very
  1415. first frame without getting flags (i.e. T2 times out)
  1416. it returns ifrTIMEOUT. This results in the "Command Recvd"
  1417. and the enclosing T2 loop being implemented in this
  1418. routine.
  1419. Upon receiving a set of frames, this routine assembles them
  1420. into the ET30FR structs pointed to by rglpfr, and if any
  1421. of them have a non-null FIF, or if >1 frame are received, it
  1422. calls (*Callbacks.Callbacks.lpWhatNext)().
  1423. Finally it returns the ifr of the last frame received, if
  1424. all frames were good, or ifrBAD if *all* frames were bad.
  1425. The algorithm it implements is very close to the "Response
  1426. Received" flowchart, minus the "Transmit DCN" box & below.
  1427. It returns ifrNULL or ifrBAD corresponding to return via
  1428. Node 2, (i.e. ifrNULL for timeout and other errors), ifrBAD
  1429. for bad frames, *iff* it can resync and get 200ms of silence
  1430. following these. ifrERROR for Node 1 (i.e. any error or timeout
  1431. after which we cannot resync or get silence for 200ms),
  1432. and ifrDCN for Node 3 (i.e. DCN was received).
  1433. <<<Node1 (ifrERROR is bad, so we dont use it. On error
  1434. we immediately return BAD or NULL or TIMEOUT and allow retry>>>
  1435. The "Optional Response" box is replaced by a "Not final frame".
  1436. A "start T4" box is assumed at "Enter" and a "Reset T4" box
  1437. is assumed after "process optional response"
  1438. It also modifies the flowchart in that *all* the frames are got
  1439. until a final frame, even if an FCS error frame is recvd. This
  1440. is partly because after an erroneous frame we have absolutely
  1441. no idea how long to wait until we either get silence or timeout
  1442. and hangup. ALso it may be more robust. The main routine
  1443. throws away the entire set of frames if one is bad.
  1444. The callback function is called before any return and it gets
  1445. a pointer to the desired return vakue, so it can modify this.
  1446. Arguments: whether it is called as "Command Received" or as
  1447. "Response Received"
  1448. Returns : ifrNULL -- timeout
  1449. ifrTIMEOUT -- T2 timed out before first flag
  1450. (returns this if and only if fCommand==TRUE)
  1451. ifrBAD -- all frames received were bad
  1452. ifrDCN -- DCN was received. The only valid action is "goto NodeB"
  1453. ifrXXXX -- last received frame
  1454. Calls :
  1455. Called By: GetResponse() GetCommand1() and GetCommand2() macros (ONLY!)
  1456. These are called only from ET30MainBody.
  1457. Comment : Watch out for timeouts > 65535 (max UWORD)
  1458. Revision Log
  1459. Date Name Description
  1460. -------- ----- ---------------------------------------------------------
  1461. 06/15/92 arulm Created for first time (completely from scratch)
  1462. ***************************************************************************/
  1463. IFR GetCmdResp(PThrdGlbl pTG, BOOL fCommand, USHORT ifrHint)
  1464. {
  1465. /*** we need to try for T4 to get a frame here. The way Class1 modems
  1466. works, as long as no flags are received, the AT+FRH=3 command will
  1467. time out and return ERROR. CONNECT is returned as soon as flags
  1468. are received. Some modems return <CR><LF>OK<CR><LF><CR><LF>CONNECT
  1469. which is still taken care of by out new ModemDialog which throws
  1470. away blank lines and looks for the expected answer i.e. "CONNECT"
  1471. in this case, in multi-line responses.
  1472. ***/
  1473. BYTE bRecv[MAXFRAMESIZE];
  1474. BOOL fFinal, fNoFlags, fGotFIF, fGotBad;
  1475. IFR ifr, ifrLastGood;
  1476. USHORT uRet, uRecv, j;
  1477. ET30ACTION action;
  1478. LPLPFR lplpfr;
  1479. LPFR lpfrNext;
  1480. BOOL fResync=0;
  1481. ULONG ulTimeout;
  1482. BOOL fGotEofFromRecvMode=0;
  1483. // need to init these first
  1484. pTG->T30.Nframes=0, fFinal=FALSE, fNoFlags=TRUE, fGotFIF=FALSE, fGotBad=FALSE;
  1485. ifrLastGood=ifrNULL;
  1486. // figure out the timeout
  1487. if(fCommand)
  1488. ulTimeout = T2_TIMEOUT;
  1489. else
  1490. ulTimeout = T4_TIMEOUT;
  1491. // if we're sending DCS-TCF and waiting for CFR, we increase the timeout each time
  1492. // we fail, to avoid getting an infinite collision. This fixes bug#6847
  1493. if(ifrHint==ifrTCFresponse && pTG->T30.uTrainCount>1)
  1494. {
  1495. ulTimeout += TCFRESPONSE_TIMEOUT_SLACK;
  1496. (MyDebugPrint(pTG, LOG_ALL, "Get TCF response: traincount=%d timeout=%ld\r\n", pTG->T30.uTrainCount, ulTimeout));
  1497. }
  1498. lplpfr = pTG->T30.lpfs->rglpfr;
  1499. lpfrNext = (LPFR)(pTG->T30.lpfs->b);
  1500. pTG->T30.sRecvBufSize = 0;
  1501. uRet = ModemRecvMode(pTG, pTG->Params.hModem, V21_300, TRUE, ulTimeout, ifrHint);
  1502. if(uRet == RECV_TIMEOUT || uRet == RECV_ERROR)
  1503. {
  1504. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> RecvMode failed=%d\r\n", uRet));
  1505. fResync = TRUE;
  1506. goto error;
  1507. }
  1508. else if(uRet == RECV_WRONGMODE)
  1509. {
  1510. // BG_CHK(FALSE); // just so we know who gives it!!
  1511. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got FCERROR from FRH=3\r\n"));
  1512. // treat like timeout
  1513. // fReSync = FALSE; // no need to resync
  1514. goto error;
  1515. }
  1516. else if(uRet == RECV_EOF)
  1517. {
  1518. // ModemRecvMode() returns EOF then return ifrEOF immediately. RecvMode
  1519. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  1520. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  1521. // this case we want to retry the high speed PIX recv again immediately
  1522. (MyDebugPrint(pTG, LOG_ERR, "WARNING: ECHO--Got EOF from V21 RecvMode\r\n"));
  1523. fGotEofFromRecvMode=TRUE;
  1524. goto error;
  1525. }
  1526. BG_CHK(uRet == RECV_OK);
  1527. for( ;!fFinal; )
  1528. {
  1529. if((((LPB)lpfrNext+sizeof(FR)+30-(LPB)pTG->T30.lpfs) > TOTALRECVDFRAMESPACE)
  1530. || (pTG->T30.Nframes >= MAXRECVFRAMES))
  1531. {
  1532. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Out of space for received frames. Haaalp!!\r\n"));
  1533. pTG->T30.Nframes = 0;
  1534. // fGotBad = TRUE; // fGotBad = FALSE;
  1535. lplpfr = pTG->T30.lpfs->rglpfr;
  1536. lpfrNext = (LPFR)(pTG->T30.lpfs->b);
  1537. // BG_CHK(FALSE);
  1538. // fall through
  1539. }
  1540. uRet = ModemRecvMem(pTG, pTG->Params.hModem, bRecv, MAXFRAMESIZE, ulTimeout, &uRecv);
  1541. if(uRet == RECV_TIMEOUT)
  1542. {
  1543. fResync = TRUE;
  1544. goto error; // timeout in FRH=3
  1545. }
  1546. fNoFlags = FALSE;
  1547. if(uRet == RECV_EOF)
  1548. {
  1549. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Got NO CARRIER, but no final bit\r\n"));
  1550. BG_CHK(uRecv == 0);
  1551. goto error; // ignore good frames if we got any, because we
  1552. // must've missed the last (most important) one
  1553. // fFinal = TRUE; // pretend we got fFinal
  1554. // continue;
  1555. }
  1556. else if(uRet == RECV_ERROR)
  1557. {
  1558. fResync = TRUE;
  1559. goto error; // error in FRH=3
  1560. }
  1561. /** Sometimes modems give use ERROR even when teh frame is good.
  1562. Happens a lot from Though to PP144MT on CFR. So we ignore the
  1563. BADFRAME response, and check the recvd data for ourselves.
  1564. First stage--check the FF-03/13-FCF. If this is OK (i.e. got
  1565. a known FCF) and no FIF reqd and data length is correct
  1566. then accept it. But if the frame requires an FIF and we
  1567. got a BADFRAME response then don't accept it even if it
  1568. looks good--too dangerous.
  1569. 2nd-stage(NYI)--keep a table of CRCs for each fixed frame & check
  1570. them ourselves.
  1571. **/
  1572. #ifdef MDDI // badframe handling
  1573. else if(uRet == RECV_BADFRAME)
  1574. goto badframe;
  1575. BG_CHK(uRet==RECV_OK);
  1576. #else
  1577. BG_CHK(uRet == RECV_OK || uRet==RECV_BADFRAME);
  1578. #endif
  1579. // faxT2log(("FRAME>>> \r\n"));
  1580. // ST_FRAMES(D_HexPrint(bRecv, uRecv));
  1581. /*** Got Valid OK Frame. Now analyse it. In general here we
  1582. want to be pretty lax in recognizing frames. Oftentimes
  1583. we have mucho garbage thrown in.
  1584. <CHANGE> Actually we're checking strictly now....
  1585. If we get a bad frame, we mark this in the lpfrfr[] array
  1586. and go on to try and get another frame.
  1587. <CHANGE> We've stopped saving bad frames
  1588. ***/
  1589. // AT&T modem gives us frames w/o CRC, so we get just 1 byte here!!
  1590. // <CHNAGE> fixed that at driver level, so we always get 3 bytes here
  1591. // IFF it is a valid frame
  1592. if(uRecv < 3)
  1593. goto badframe;
  1594. if(bRecv[0] != 0xFF)
  1595. goto badframe;
  1596. if(bRecv[1] == 0x03)
  1597. fFinal = FALSE;
  1598. else if(bRecv[1] == 0x13)
  1599. {
  1600. fFinal = TRUE;
  1601. #ifdef CL0
  1602. // tell modem that recv is done
  1603. // but keep calling RecvMem until we get RECV_EOF
  1604. ModemEndRecv(pTG, pTG->Params.hModem);
  1605. #endif //CL0
  1606. }
  1607. else
  1608. goto badframe;
  1609. for(ifr=1; ifr<ifrMAX; ifr++)
  1610. {
  1611. if(rgFrameInfo[ifr].fInsertDISBit)
  1612. {
  1613. // Mask off the DIS bit
  1614. if(rgFrameInfo[ifr].bFCF1 != (BYTE)(bRecv[2] & 0xFE))
  1615. continue;
  1616. }
  1617. else
  1618. {
  1619. if(rgFrameInfo[ifr].bFCF1 != bRecv[2])
  1620. continue;
  1621. }
  1622. j=3;
  1623. if(rgFrameInfo[ifr].bFCF2)
  1624. {
  1625. // AT&T modem gives us frames w/o CRC, so we get just 1 byte frames!!
  1626. if(uRecv < 4)
  1627. goto badframe;
  1628. if((BYTE)(rgFrameInfo[ifr].bFCF2-1) != bRecv[3])
  1629. continue;
  1630. j++;
  1631. }
  1632. BG_CHK(j <= uRecv);
  1633. if(rgFrameInfo[ifr].wFIFLength == 0xFF) // var length FIF
  1634. {
  1635. // Var length frames
  1636. // Cant accept it if the modem thought they it was bad
  1637. // accept it IFF RECV_OK & FIFlen>0
  1638. if(uRet==RECV_OK && (j < uRecv))
  1639. fGotFIF = TRUE;
  1640. else
  1641. {
  1642. (MyDebugPrint(pTG, LOG_ERR, "Discarding Bad Frame: uRet=%d FIFlen=%d Reqd=Var\r\n", uRet, (uRecv-j)));
  1643. goto badframe;
  1644. }
  1645. }
  1646. else if(rgFrameInfo[ifr].wFIFLength) // fixed length FIF
  1647. {
  1648. // if frame length is exactly right then accept it
  1649. // else if modem said frame was ok and length is
  1650. // longer than expected then accept it too
  1651. if((j+rgFrameInfo[ifr].wFIFLength) == uRecv)
  1652. fGotFIF = TRUE;
  1653. else if(uRet==RECV_OK && (j+rgFrameInfo[ifr].wFIFLength < uRecv))
  1654. fGotFIF = TRUE;
  1655. else
  1656. {
  1657. (MyDebugPrint(pTG, LOG_ERR, "Discarding Bad Frame: uRet=%d FIFlen=%d Reqd=%d\r\n", uRet, (uRecv-j), rgFrameInfo[ifr].wFIFLength));
  1658. goto badframe;
  1659. }
  1660. }
  1661. else // no FIF reqd
  1662. {
  1663. if(j != uRecv)
  1664. {
  1665. (MyDebugPrint(pTG, LOG_ALL, "Weird frame(2)\r\n"));
  1666. BG_CHK(j < uRecv);
  1667. // see the BADFRAME comment block above on why we do this
  1668. if(uRet != RECV_OK)
  1669. goto badframe;
  1670. // accept it even if wrong length *iff* uRet==RECV_OK
  1671. // goto badframe;
  1672. // **additional** reason to do this that 2 bytes of extra
  1673. // CRC may be present. This happens because of the AT&T and
  1674. // NEC modems that doen't give CRC, so we do no CRC lopping-off
  1675. // in the modem driver. So accept it anyway here.
  1676. }
  1677. }
  1678. goto goodframe;
  1679. }
  1680. // fall through here when ifr == ifrMAX
  1681. BG_CHK(ifr==ifrMAX);
  1682. badframe:
  1683. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> IGNORING Bad Frame (Size=%d) -->\r\n", uRecv));
  1684. // D_HexPrint(bRecv, uRecv);
  1685. //Protocol Dump
  1686. DumpFrame(pTG, FALSE, 0, uRecv, bRecv);
  1687. fGotBad = TRUE; // remember we got a bad frame
  1688. // Don't want to save bad frames
  1689. /***
  1690. // mark frame as bad
  1691. ifr = ifrBAD;
  1692. lpfrNext->ifr = ifrBAD;
  1693. lpfrNext->cb = (BYTE)uRecv;
  1694. _fmemcpy(lpfrNext->fif, bRecv, uRecv);
  1695. lplpfr[pTG->T30.Nframes] = lpfrNext;
  1696. pTG->T30.Nframes++;
  1697. lpfrNext++; // skips over only the base part of frame
  1698. lpfrNext = ((LPBYTE)lpfrNext + uRecv); // skips over FIF too
  1699. ***/
  1700. continue;
  1701. // loop back here for the next frame
  1702. goodframe:
  1703. // (MyDebugPrint(pTG, "FRAME RECEIVED: (%s) 0x%02x -->\r\n", (LPSTR)(rgFrameInfo[ifr].szName), bRecv[2]));
  1704. // ST_T30_2(D_HexPrint(bRecv, uRecv));
  1705. ifrLastGood = ifr; // save last good ifr
  1706. lpfrNext->ifr = ifr;
  1707. if(uRecv > j)
  1708. {
  1709. lpfrNext->cb = uRecv-j;
  1710. _fmemcpy(lpfrNext->fif, bRecv+j, uRecv-j);
  1711. //Protocol Dump
  1712. DumpFrame(pTG, FALSE, ifr, (USHORT)(uRecv-j), bRecv+j);
  1713. }
  1714. else
  1715. {
  1716. lpfrNext->cb = 0;
  1717. BG_CHK(uRecv == j);
  1718. //Protocol Dump
  1719. DumpFrame(pTG, FALSE, ifr, 0, 0);
  1720. }
  1721. lplpfr[pTG->T30.Nframes] = lpfrNext;
  1722. pTG->T30.Nframes++;
  1723. ///////////// back to NSS-DCS form ////////////
  1724. if(ifr==ifrDCS && fFinal)
  1725. {
  1726. // Need to set receive speed, since bypass all callbacks
  1727. // now and go straight to AT+FRM=xx
  1728. pTG->T30.uRecvTCFMod = (((lpfrNext->fif[1])>>2) & 0x0F);
  1729. (MyDebugPrint(pTG, LOG_ALL, "cmdresp-DCS fx sp=%d\r\n", pTG->T30.uRecvTCFMod));
  1730. // fastexit:
  1731. BG_CHK(ifr==ifrDCS);
  1732. return ifr; // ifr of final frame
  1733. }
  1734. #ifdef OEMNSF
  1735. else if(ifr==ifrNSS && lpfnOEMGetBaudRate && fUsingOEMProt)
  1736. {
  1737. WORD wRet = lpfnOEMGetBaudRate(pTG, lpfrNext->fif, lpfrNext->cb, fFinal);
  1738. if(wRet)
  1739. {
  1740. BG_CHK(fFinal);
  1741. if(LOBYTE(wRet) == OEMNSF_GET_TCF)
  1742. {
  1743. (MyDebugPrint(pTG, LOG_ALL, "cmdresp-NSS fx sp=%d\r\n", pTG->T30.uRecvTCFMod));
  1744. pTG->T30.uRecvTCFMod = HIBYTE(wRet);
  1745. BG_CHK(ifr==ifrNSS);
  1746. return ifr;
  1747. }
  1748. else if(LOBYTE(wRet) == OEMNSF_NO_TCF)
  1749. {
  1750. (MyDebugPrint(pTG, LOG_ALL, "cmdresp-NSS fx sp=%d\r\n", pTG->T30.uRecvTCFMod));
  1751. pTG->T30.uRecvTCFMod = 0xFF;
  1752. BG_CHK(ifr==ifrNSS);
  1753. return ifr;
  1754. }
  1755. }
  1756. else if(fFinal)
  1757. {
  1758. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> OEMGetBaudRate returned %d for FINAL frame. Using standard T30\r\n"));
  1759. fUsingOEMProt = 0;
  1760. return ifrNULL;
  1761. }
  1762. }
  1763. #endif
  1764. lpfrNext++; // skips over only the base part of frame
  1765. lpfrNext = (LPFR)((LPBYTE)lpfrNext + (uRecv-j)); // skips over FIF too
  1766. if(ifr == ifrCRP)
  1767. {
  1768. fGotBad = TRUE; // pretend we got a bad response (so the T30 chart says!)
  1769. // fResync = FALSE;
  1770. goto error; // exit, but get 200ms of silence
  1771. // caller will resend command
  1772. }
  1773. if(ifr == ifrDCN)
  1774. goto exit2; // exit. Don't call callback function!
  1775. // loop back here for the next frame
  1776. }
  1777. BG_CHK(fFinal); // only reason we ever drop through here
  1778. // let ifrDCN also come through here. No hurry, so we can report
  1779. // it to the protocol module. If we got *only* bad frames, here we'll
  1780. // return ifrBAD
  1781. //exit:
  1782. if(!pTG->T30.Nframes || // we got no good frames
  1783. (ifr != ifrLastGood)) // final frame was bad
  1784. {
  1785. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Got %d good frames. LastGood=%d Last=%d. Ignoring ALL\r\n",
  1786. pTG->T30.Nframes, ifrLastGood, ifr ));
  1787. // fResync = FALSE;
  1788. goto error;
  1789. }
  1790. // ifr of final frame
  1791. BG_CHK(ifr == ifrLastGood);
  1792. if(pTG->T30.Nframes>1 || fGotFIF)
  1793. {
  1794. action=pTG->Params.lpfnWhatNext(pTG, eventGOTFRAMES, pTG->T30.Nframes,
  1795. (ULONG_PTR)lplpfr, (ULONG_PTR)((LPIFR)&ifr));
  1796. BG_CHK(action==actionNULL || action==actionERROR);
  1797. }
  1798. exit2:
  1799. // ifr can be changed by callback function (e.g. if bad FIFs)
  1800. if(ifr==ifrDTC)
  1801. pTG->T30.fReceivedDTC = TRUE;
  1802. return ifr; // ifr of final frame
  1803. error:
  1804. // comes here on getting RECV_TIMEOUT, RECV_WRONGMODE, RECV_ERROR
  1805. // and ifrCRP, or on getting no Frames
  1806. // fReSync is set on RECV_TIMEOUT or RECV_ERROR
  1807. #ifdef DEBUG
  1808. if(pTG->T30.Nframes>0 && ifr!=ifrCRP && ifrLastGood!=ifrCRP)
  1809. {
  1810. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Got some good frames--Throwing away!! IFR=%d Last=%d\r\n", ifr, ifrLastGood));
  1811. // BG_CHK(FALSE);
  1812. }
  1813. #endif
  1814. if(fGotBad)
  1815. ifr = ifrBAD; // caller can send CRP if desired
  1816. else
  1817. ifr = ifrNULL; // caller can repeat command & try again
  1818. if(fCommand && fNoFlags) ifr = ifrTIMEOUT; // hook for "Command Recvd?"
  1819. // may not need this on TIMEOUT since AT-OK has already been
  1820. // called in ModemDialog. Probably need it on ERROR
  1821. if(uRet==RECV_ERROR)
  1822. {
  1823. BG_CHK(fResync);
  1824. ModemSync(pTG, pTG->Params.hModem, RESYNC_TIMEOUT2);
  1825. }
  1826. // eliminate Flush--serves no purpose
  1827. // else if(uRet==RECV_WRONGMODE)
  1828. // {
  1829. // ModemFlush(pTG->Params.hModem);
  1830. // }
  1831. // ModemRecvMode() returns EOF then return ifrEOF immediately. RecvMode
  1832. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  1833. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  1834. // this case we want to retry the high speed PIX recv again immediately
  1835. if(fGotEofFromRecvMode) ifr=ifrEOFfromRECVMODE;
  1836. BG_CHK(ifr==ifrBAD || ifr==ifrNULL || ifr==ifrTIMEOUT || ifr==ifrEOFfromRECVMODE);
  1837. return ifr;
  1838. /*-----------------------------------------------------------------
  1839. * Don't want to return ifrERROR ever. Nobody wants to deal with it.
  1840. * Don't try to get the 200ms of silence, because it causes us to
  1841. * get badly out of sync, i.e. after a few bad frames we don't
  1842. * resync and we lose the call. Just do a local-resync (AT-OK)
  1843. * and try to recv again.
  1844. * -----------------------------------------------------------------
  1845. *
  1846. * if( !ModemSync(pTG->Params.hModem, RESYNC_TIMEOUT) ||
  1847. * !ModemRecvSilence(pTG->Params.hModem, 20, RESYNC_TIMEOUT))
  1848. * {
  1849. * (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Can't get silence after Response timeout--hanging up\r\n"));
  1850. * // ifr = ifrERROR;
  1851. * // caller must send DCN and hangup
  1852. * }
  1853. * action=pTG->Params.lpfnWhatNext(eventGOTFRAMES, pTG->T30.Nframes,
  1854. * (DWORD)lplpfr, (DWORD)((LPIFR)&ifr));
  1855. * BG_CHK(action == actionNULL);
  1856. *
  1857. * -----------------------------------------------------------------
  1858. * and don't want to regsiter garbage frame sets. Nobody does anything
  1859. * but retry on BAD/NULL/TIMEOUT returns anyway
  1860. *-----------------------------------------------------------------*/
  1861. }