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.

897 lines
38 KiB

  1. /***************************************************************************
  2. Name : WHATNEXT.C
  3. Comment : T30 Decision-point Callback function
  4. Copyright (c) 1993 Microsoft Corp.
  5. Revision Log
  6. Num Date Name Description
  7. --- -------- ---------- -----------------------------------------------
  8. ***************************************************************************/
  9. #include "prep.h"
  10. #include "efaxcb.h"
  11. #include "protocol.h"
  12. ///RSL
  13. #include "glbproto.h"
  14. #define faxTlog(m) DEBUGMSG(ZONE_WHATNEXT, m)
  15. #define FILEID FILEID_WHATNEXT
  16. // used in eventPOSTPAGERESPONSE
  17. // first index got from ifrSend (MPS=0, EOM=1, EOP=2, EOMwithFastTurn=3)
  18. // second index got from ifrRecv (MCF=0, RTP=1, RTNnoRetrans=2, RTNretrans=3)
  19. ET30ACTION PostPageAction[4][4] =
  20. {
  21. { actionGONODE_I, actionGONODE_D, actionGONODE_D, actionGONODE_D },
  22. { actionGONODE_T, actionGONODE_T, actionGONODE_T, actionGONODE_T /* or D? */ },
  23. { actionDCN, actionDCN, actionDCN, actionGONODE_D },
  24. { actionGONODE_A, actionGONODE_A, actionGONODE_A, actionGONODE_D /* or A? */ }
  25. };
  26. void CopyFrToRFS(PThrdGlbl pTG, NPRFS npRecvd, LPFR lpfr)
  27. {
  28. USHORT uLen;
  29. BG_CHK(MAXFRAMES == (sizeof(npRecvd->rglpfr) / sizeof(LPFR)));
  30. if(npRecvd->uNumFrames >= (sizeof(npRecvd->rglpfr) / sizeof(LPFR)))
  31. {
  32. BG_CHK(FALSE);
  33. return;
  34. }
  35. uLen = sizeof(FRBASE) + lpfr->cb;
  36. if(npRecvd->uFreeSpaceOff + uLen >= sizeof(npRecvd->b))
  37. {
  38. BG_CHK(FALSE);
  39. return;
  40. }
  41. _fmemcpy(npRecvd->b + npRecvd->uFreeSpaceOff, lpfr, uLen);
  42. npRecvd->rglpfr[npRecvd->uNumFrames++] = (LPFR)(npRecvd->b + npRecvd->uFreeSpaceOff);
  43. npRecvd->uFreeSpaceOff += uLen;
  44. BG_CHK(npRecvd->uNumFrames <= MAXFRAMES);
  45. BG_CHK(npRecvd->uFreeSpaceOff <= MAXSPACE);
  46. }
  47. /***-------------- Warning. This is called as a Vararg function --------***/
  48. ET30ACTION __cdecl FAR
  49. WhatNext (
  50. PThrdGlbl pTG,
  51. ET30EVENT event,
  52. WORD wArg1,
  53. DWORD lArg2,
  54. DWORD lArg3
  55. )
  56. {
  57. ET30ACTION action = actionERROR;
  58. NPPROT npProt = &pTG->ProtInst;
  59. // program bug. failure will cause a GP fault
  60. BG_CHK(pTG->ProtInst.fInUse);
  61. if (pTG->fAbortRequested) {
  62. if (pTG->fOkToResetAbortReqEvent && (!pTG->fAbortReqEventWasReset)) {
  63. MyDebugPrint(pTG, LOG_ALL, "WhatNext RESETTING AbortReqEvent at %lx\n",GetTickCount() );
  64. pTG->fAbortReqEventWasReset = 1;
  65. ResetEvent(pTG->AbortReqEvent);
  66. }
  67. MyDebugPrint(pTG, LOG_ALL, "WhatNext ABORTing at %lx\n",GetTickCount() );
  68. return actionERROR;
  69. }
  70. if(npProt->fAbort)
  71. {
  72. ERRMSG((SZMOD "<<ERROR>> Aborting in WhatNext\r\n"));
  73. // ICommFailureCode already set
  74. return actionERROR;
  75. }
  76. switch(event)
  77. {
  78. case eventGOTFRAMES:
  79. {
  80. /* uCount=wArg1. This is the number of frames received.
  81. *
  82. * lplpfr=(LPLPET30FR)lArg2. Pointer to an array of pointers to
  83. * the received frames, each in an ET30FR structure whose
  84. * format is defined in ET30defs.H
  85. *
  86. * return must be actionNULL
  87. */
  88. USHORT uCount = wArg1;
  89. LPLPFR lplpfr = (LPLPFR)lArg2;
  90. LPIFR lpifr = (LPIFR)lArg3; // pointer to IFR that the "Response Recvd"
  91. // routine will return to the main body
  92. // can be modified, for example, if a bad
  93. // franes is deciphered.
  94. LPFR lpfr;
  95. USHORT i;
  96. BOOL fGotRecvCaps=0, fGotRecvParams=0, fGotPollReq=0;
  97. /***
  98. Each time we enter here we have an entire block of frames
  99. that were sent as one "command" or "response". For frames
  100. that can be multiple (NSF/NSS/NSC), we want to be sure that
  101. _iff_ we have new ones, we throw away the old ones. Therefore
  102. on the _first_ occurence of NSF, NSC and NSS resp. in the
  103. loop below, zap npProt->uNumRecvdNS?s to 0. This may hold
  104. good for SEP/PWD/SUB also.
  105. ***/
  106. BOOL fZappedNSxCount=0;
  107. // fZappedSEPPWDCount=0;
  108. // BOOL fWaitingForPWD=0;
  109. if(*lpifr == ifrBAD)
  110. {
  111. ERRMSG((SZMOD "<<WARNING>> Callback on Bad Frame. Ignoring ALL\r\n"));
  112. action = actionNULL; // only allowed response to eventGOTFRAMES
  113. break;
  114. }
  115. for(i=0; i<uCount; i++)
  116. {
  117. ///////////////////////////////////////////////////////////////
  118. // Prepare to get trash (upto 2 bytes) at end of every frame //
  119. ///////////////////////////////////////////////////////////////
  120. lpfr = lplpfr[i];
  121. switch(lpfr->ifr)
  122. {
  123. case ifrBAD: ERRMSG((SZMOD "<<ERROR>> Bad Frame not caught\r\n"));
  124. BG_CHK(FALSE);
  125. // ignore it
  126. break;
  127. case ifrCSI:
  128. case ifrTSI:
  129. case ifrCIG: CopyRevIDFrame(pTG, npProt->bRemoteID, lpfr);
  130. // trailing-trash removed by length limit IDFIFSIZE
  131. npProt->fRecvdID = TRUE;
  132. // prepare CSID for logging by FaxSvc
  133. pTG->RemoteID = AnsiStringToUnicodeString(pTG->ProtInst.bRemoteID);
  134. if (pTG->RemoteID) {
  135. pTG->fRemoteIdAvail = 1;
  136. }
  137. break;
  138. case ifrDIS: npProt->uRemoteDISlen = CopyFrame(pTG, (LPBYTE)(&npProt->RemoteDIS), lpfr, sizeof(DIS));
  139. // trailing-trash removed in ParseDISDTCDCS
  140. npProt->fRecvdDIS = TRUE;
  141. fGotRecvCaps = TRUE;
  142. break;
  143. case ifrDCS: npProt->uRemoteDCSlen = CopyFrame(pTG, (LPBYTE)(&npProt->RemoteDCS), lpfr, sizeof(DIS));
  144. // trailing-trash removed in ParseDISDTCDCS
  145. npProt->fRecvdDCS = TRUE;
  146. fGotRecvParams = TRUE;
  147. break;
  148. case ifrDTC: npProt->uRemoteDTClen = CopyFrame(pTG, (LPBYTE)(&npProt->RemoteDTC), lpfr, sizeof(DIS));
  149. // trailing-trash removed in ParseDISDTCDCS
  150. npProt->fRecvdDTC = TRUE;
  151. fGotPollReq = TRUE;
  152. break;
  153. case ifrNSS: fGotRecvParams = TRUE; //some OEMs send NSS w/o DCS
  154. goto DoRecvNSx;
  155. case ifrNSC: fGotPollReq = TRUE; //some OEMs send NSC w/o DTC
  156. goto DoRecvNSx;
  157. case ifrNSF: goto DoRecvNSx;
  158. DoRecvNSx:
  159. if(!fZappedNSxCount)
  160. {
  161. ZeroRFS(pTG, &npProt->RecvdNS);
  162. fZappedNSxCount = TRUE;
  163. }
  164. CopyFrToRFS(pTG, &npProt->RecvdNS, lpfr);
  165. break;
  166. case ifrCFR: case ifrFTT:
  167. case ifrEOM: case ifrMPS: case ifrEOP:
  168. case ifrPRI_EOM: case ifrPRI_MPS: case ifrPRI_EOP:
  169. case ifrMCF: case ifrRTP: case ifrRTN:
  170. case ifrPIP: case ifrPIN:
  171. case ifrDCN:
  172. case ifrCRP:
  173. /*** ECM frames below ***/
  174. case ifrCTR: case ifrERR:
  175. case ifrRR: case ifrRNR:
  176. case ifrEOR_NULL:
  177. case ifrEOR_MPS: case ifrEOR_PRI_MPS:
  178. case ifrEOR_EOM: case ifrEOR_PRI_EOM:
  179. case ifrEOR_EOP: case ifrEOR_PRI_EOP:
  180. // These have no FIF
  181. ERRMSG((SZMOD "<<WARNING>> These are not supposed to be signalled\r\n"));
  182. // bad frame. ignore it
  183. // BG_CHK(FALSE);
  184. break;
  185. /********* New T.30 frames ******************************/
  186. case ifrSUB: CopyRevIDFrame(pTG, npProt->bRecipSubAddr, lpfr);
  187. npProt->fRecvdSUB = TRUE;
  188. break;
  189. /**
  190. case ifrSEP:
  191. case ifrPWD:
  192. if(!fZappedSEPPWDCount)
  193. {
  194. ZeroRFS(pTG, &npProt->RecvdSEPPWD);
  195. fZappedSEPPWDCount = TRUE;
  196. }
  197. CopyFrToRFS(pTG, &npProt->RecvdSEPPWD, lpfr);
  198. break;
  199. **/
  200. /********* ECM stuff starts here. T.30 section A.4 ******/
  201. // These have FIFs
  202. case ifrPPR: if(lpfr->cb < 32)
  203. {
  204. // bad frame. FORCE A RETRANSMIT!!
  205. ERRMSG((SZMOD "<<ERROR>> Bad PPR length!!\r\n"));
  206. *lpifr = ifrNULL;
  207. break;
  208. }
  209. _fmemcpy(npProt->bRemotePPR, lpfr->fif, 32);
  210. // trailing-trash removed by length limit 32
  211. npProt->fRecvdPPR = TRUE;
  212. break;
  213. case ifrPPS_NULL:
  214. case ifrPPS_EOM:
  215. case ifrPPS_MPS:
  216. case ifrPPS_EOP:
  217. case ifrPPS_PRI_EOM:
  218. case ifrPPS_PRI_MPS:
  219. case ifrPPS_PRI_EOP:
  220. if(lpfr->cb < 3)
  221. {
  222. // bad frame. FORCE A RETRANSMIT!!
  223. ERRMSG((SZMOD "<<ERROR>> Bad PPS length!!\r\n"));
  224. *lpifr = ifrNULL;
  225. break;
  226. }
  227. _fmemset(npProt->bRemotePPS, 0, 4);
  228. _fmemcpy(npProt->bRemotePPS, lpfr->fif, 3);
  229. // trailing-trash removed by length limit 3
  230. npProt->fRecvdPPS = TRUE;
  231. // only set this on first PPS in a block
  232. if(!npProt->uFramesInThisBlock)
  233. npProt->uFramesInThisBlock = (USHORT)(npProt->bRemotePPS[2]) + 1; //3rd byte of fif
  234. break;
  235. case ifrCTC:
  236. BG_CHK(npProt->fllRecvParamsGot);
  237. if(lpfr->cb < 2)
  238. {
  239. // bad frame. FORCE A RETRANSMIT!!
  240. ERRMSG((SZMOD "<<ERROR>> Bad CTC length!!\r\n"));
  241. *lpifr = ifrNULL;
  242. break;
  243. }
  244. npProt->llRecvParams.Baud = ((LPDIS)(&(lpfr->fif)))->Baud;
  245. // trailing-trash removed by length limit 2
  246. break;
  247. }
  248. }
  249. if(fGotRecvCaps)
  250. {
  251. // program bug. Failure may cause some random (non fatal) results
  252. BG_CHK(!fGotRecvParams && !fGotPollReq);
  253. GotRecvCaps(pTG);
  254. }
  255. if(fGotRecvParams)
  256. {
  257. // program bug. Failure may cause some random (non fatal) results
  258. BG_CHK(!fGotRecvCaps && !fGotPollReq);
  259. GotRecvParams(pTG);
  260. }
  261. if(fGotPollReq)
  262. {
  263. // program bug. Failure may cause some random (non fatal) results
  264. BG_CHK(!fGotRecvCaps && !fGotRecvParams);
  265. GotPollReq(pTG);
  266. }
  267. action = actionNULL; // only allowed response to eventGOTFRAMES
  268. break;
  269. }
  270. /****** Transmitter Phase B. Fig A-7/T.30 (sheet 1) ******/
  271. case eventNODE_T: // do nothing. Hook for abort in T1 loop
  272. action=actionNULL; break;
  273. case eventNODE_R: // do nothing. Hook for abort in T1 loop
  274. action=actionNULL; break;
  275. case eventNODE_A:
  276. {
  277. IFR ifrRecv = (IFR)wArg1; // last received frame
  278. // lArg2 & lArg3 missing
  279. if(ifrRecv != ifrDIS && ifrRecv != ifrDTC)
  280. {
  281. ERRMSG((SZMOD "<<ERROR>> Unknown frames at NodeA\r\n"));
  282. ICommFailureCode(pTG, T30FAIL_NODEA_UNKNOWN);
  283. action = actionHANGUP; // G3 only
  284. }
  285. else if(npProt->fSendParamsInited)
  286. {
  287. BG_CHK(npProt->SendParams.bctype == SEND_PARAMS);
  288. action = actionGONODE_D; // sends DCS/NSS (in response to DIS or DTC)
  289. }
  290. else if(npProt->fSendPollReqInited)
  291. {
  292. BG_CHK(npProt->SendPollReq.bctype == SEND_POLLREQ);
  293. // BG_CHK(ifrRecv == ifrDIS); // no need. DTC can follow DTC for Stalling
  294. action = actionGONODE_R2; // sends DTC/NSC (in response to DIS only)
  295. }
  296. else
  297. {
  298. ERRMSG((SZMOD "<<ERROR>> NodeA: No more work...!!\r\n"));
  299. ICommFailureCode(pTG, T30FAILS_NODEA_NOWORK);
  300. action = actionDCN; // hangs up (sends DCN)
  301. }
  302. break;
  303. }
  304. case eventSENDDCS:
  305. {
  306. // 0==1st DCS 1==after NoReply 2==afterFTT
  307. USHORT uWhichDCS = (UWORD)wArg1;
  308. // where to return the number of frames returned
  309. LPUWORD lpuwN = (LPUWORD)lArg2;
  310. // where to return a pointer to an array of pointers to
  311. // return frames
  312. LPLPLPFR lplplpfr = (LPLPLPFR)lArg3;
  313. USHORT uSize = 0;
  314. if(uWhichDCS == 2) // got FTT
  315. {
  316. if(!DropSendSpeed(pTG))
  317. {
  318. ERRMSG((SZMOD "<<ERROR>> FTT: Can't Drop speed any lower\r\n"));
  319. ICommFailureCode(pTG, T30FAILS_FTT_FALLBACK);
  320. action = actionDCN;
  321. break;
  322. }
  323. }
  324. CreateNSSTSIDCS(pTG, npProt, &pTG->rfsSend, uWhichDCS);
  325. BG_CHK(npProt->fllNegotiated);
  326. if(npProt->llNegot.fECM)
  327. {
  328. uSize = (1 << (ProtGetECMFrameSize(pTG)));
  329. BG_CHK(uSize==64 || uSize==256);
  330. ICommSetSendMode(pTG, TRUE, MY_ECMBUF_SIZE, uSize, TRUE);
  331. }
  332. else
  333. {
  334. ICommSetSendMode(pTG, FALSE, MY_BIGBUF_SIZE, MY_BIGBUF_ACTUALSIZE-4, FALSE);
  335. }
  336. *lpuwN = pTG->rfsSend.uNumFrames;
  337. *lplplpfr = pTG->rfsSend.rglpfr;
  338. action = actionSENDDCSTCF;
  339. #ifdef OEMNSF
  340. if(wOEMFlags && lpfnOEMNextAction)
  341. {
  342. switch(lpfnOEMNextAction())
  343. {
  344. case OEMNSF_SENDDCN: action = actionDCN; break;
  345. case OEMNSF_SKIPTCF: action = actionSKIPTCF; break;
  346. }
  347. }
  348. #endif
  349. break;
  350. // Could also return DCN if not compatible
  351. // or SKIPTCF for Ricoh hook
  352. }
  353. case eventGOTCFR:
  354. {
  355. // wArg1, lArg2 & lArg3 are all missing
  356. // Can return GONODE_D (Ricoh hook)
  357. // or GONODE_I (Non ECM) or GONODE_IV (ECM)
  358. BG_CHK(npProt->fllNegotiated);
  359. if(npProt->llNegot.fECM)
  360. action = actionGONODE_IV;
  361. else
  362. action = actionGONODE_I;
  363. break;
  364. }
  365. /****** Transmitter Phase C. Fig A-7/T.30 (sheet 1) ******/
  366. /***
  367. case eventSTARTSEND:
  368. {
  369. if(!StartNextSendPage(pTG))
  370. {
  371. ERRMSG((SZMOD "<<ERROR>> PhaseC: No more pages\r\n"));
  372. ICommFailureCode(T30FAILS_BUG3);
  373. action = actionDCN;
  374. }
  375. else
  376. action = actionCONTINUE;
  377. break;
  378. }
  379. ***/
  380. /****** Transmitter ECM and non-ECM Phase D1. Fig A-7/T.30 (sheet 2) ******/
  381. case eventECM_POSTPAGE:
  382. case eventPOSTPAGE:
  383. {
  384. USHORT uNextSend;
  385. // wArg1, lArg2 & lArg3 are all missing
  386. // Can turn Zero stuffing off here, or wait for next page....
  387. // ET30ExtFunction(npProt->het30, ET30_SET_ZEROPAD, 0);
  388. // Don't turn it off!! It is used only for Page Send
  389. // and is set only on sending a DCS, so it is set once
  390. // before a multi-page send.
  391. uNextSend = ICommNextSend(pTG);
  392. switch(uNextSend)
  393. {
  394. case NEXTSEND_MPS: action = actionSENDMPS; break;
  395. case NEXTSEND_EOM: action = actionSENDEOM; break;
  396. case NEXTSEND_EOP: action = actionSENDEOP; break;
  397. case NEXTSEND_ERROR:
  398. default: action = actionSENDEOP; break;
  399. }
  400. break;
  401. // also possible -- GOPRIEOP, PRIMPS or PRIEOM
  402. }
  403. /****** Transmitter Phase D2. Fig A-7/T.30 (sheet 2) ******/
  404. case eventGOTPOSTPAGERESP:
  405. {
  406. IFR ifrRecv = (IFR)wArg1; // last received frame
  407. IFR ifrSent = (IFR)lArg2;
  408. // the IFR was simply cast to DWORD and then to LPVOID
  409. // lArg3 is missing
  410. USHORT i, j;
  411. // change PRI commands to ordinary ones
  412. if(ifrSent >= ifrPRI_FIRST && ifrSent <= ifrPRI_LAST)
  413. ifrSent = (ifrSent + ifrMPS - ifrPRI_MPS);
  414. BG_CHK(ifrSent==ifrMPS || ifrSent==ifrEOM || ifrSent==ifrEOP);
  415. if(ifrRecv!=ifrMCF && ifrRecv!=ifrRTP && ifrRecv!=ifrRTN)
  416. {
  417. // can't BG_CHK cause we can get any garbage response anytime
  418. ERRMSG((SZMOD "<<ERROR>> Unexpected Response %d\r\n", ifrRecv));
  419. ICommFailureCode(pTG, T30FAILS_POSTPAGE_UNKNOWN);
  420. action = actionDCN;
  421. break;
  422. }
  423. i = ifrSent - ifrMPS; //i: 0=MPS, 1=EOM, 2=EOP
  424. j = ifrRecv - ifrMCF; //j: 0=MCF, 1=RTP, 2=RTN
  425. # ifdef FASTTURN
  426. if(ifrSent == ifrEOM)
  427. {
  428. BG_CHK(i==1);
  429. i = 3; //i: 3==EOM with fast turn
  430. }
  431. # endif
  432. if(ICommSendPageAck(pTG, ((ifrRecv==ifrRTN) ? FALSE : TRUE)))
  433. {
  434. BG_CHK(j==2);
  435. j = 3; //j: 3==RTN with retransmit
  436. }
  437. // no need at all to drop speed on RTP
  438. if(ifrRecv==ifrRTN) // || ifrRecv==ifrRTP) // drop on RTP also??
  439. {
  440. if(pTG->ProtParams.RTNAction == 2)
  441. {
  442. ERRMSG((SZMOD "<<ERROR>> RTN: INI settings says HANGUP\r\n"));
  443. ICommFailureCode(pTG, T30FAILS_RTN_FALLBACK);
  444. action = actionDCN;
  445. break; // set action to DCN and return
  446. }
  447. else if (pTG->ProtParams.RTNAction == 1)
  448. {
  449. ERRMSG((SZMOD "<<WARNING>> RTN: INI setting says don't drop speed\r\n"));
  450. }
  451. else
  452. {
  453. BG_CHK(pTG->ProtParams.RTNAction == 0);
  454. // put >2 case here as well, so that we do the reasonable
  455. // thing if this setting gets messed up
  456. if(!DropSendSpeed(pTG))
  457. {
  458. ERRMSG((SZMOD "<<ERROR>> RTN: Can't Drop speed any lower\r\n"));
  459. ICommFailureCode(pTG, T30FAILS_RTN_FALLBACK);
  460. action = actionDCN;
  461. break; // set action to DCN and return
  462. }
  463. }
  464. }
  465. action = PostPageAction[i][j];
  466. if(action == actionDCN)
  467. {
  468. (MyDebugPrint(pTG, LOG_ALL, "PostPage --> Game over\r\n"));
  469. ICommFailureCode(pTG, T30FAILS_POSTPAGE_OVER);
  470. }
  471. break;
  472. // Can also return GO_D, GO_R1, GO_R2. Only restriction is
  473. // that GO_I is the only valid response to MPS sent followed
  474. // by MCF
  475. }
  476. /****** Transmitter ECM Phase D2. Fig A-7/T.30 (sheet 2) ******/
  477. case eventGOT_ECM_PPS_RESP:
  478. {
  479. IFR ifrRecv = (IFR)wArg1; // last received frame
  480. IFR ifrSent = (IFR)lArg2;
  481. // the IFR was simply cast to DWORD
  482. // lArg3 is missing
  483. // program bug. Failure may cause some random (non fatal) results
  484. BG_CHK(ifrRecv == ifrMCF); // only valid response in ECM mode
  485. if(ifrSent != ifrPPS_NULL) // not end-of-block(i.e. midpage)
  486. ICommSendPageAck(pTG, TRUE);
  487. switch(ifrSent)
  488. {
  489. case ifrPPS_NULL: action = actionGONODE_IV; // Same page. New block
  490. break;
  491. case ifrPPS_MPS:
  492. case ifrPPS_PRI_MPS: action = actionGONODE_IV; // New page
  493. break;
  494. case ifrPPS_EOM:
  495. case ifrPPS_PRI_EOM: // After sending EOM, Receiver always goes
  496. // back to sending NSF etc so we have to go
  497. // back to NodeT to receive all that junk.
  498. action = actionGONODE_T;
  499. break;
  500. case ifrPPS_EOP:
  501. case ifrPPS_PRI_EOP:
  502. // action = actionSUCCESS;
  503. (MyDebugPrint(pTG, LOG_ALL, "ECM -- Send Done\r\n"));
  504. ICommFailureCode(pTG, T30FAILSE_ECM_NOPAGES);
  505. action = actionDCN;
  506. break;
  507. default:
  508. ERRMSG((SZMOD "<<ERROR>> Dunno what we sent %d\r\n", ifrSent));
  509. // program bug. hangup
  510. BG_CHK(FALSE);
  511. ICommFailureCode(pTG, T30FAILSE_BUG4);
  512. action = actionDCN;
  513. break;
  514. }
  515. // Can also return GO_D, GO_R1, GO_R2. Only restriction is
  516. // that GO_I is the only valid response to MPS sent followed
  517. // by MCF
  518. break;
  519. }
  520. /****** Transmitter Phase D (PIN/PIN stuff). Fig A-7/T.30 (sheet 2) ******/
  521. #ifdef PRI
  522. case eventGOTPINPIP:
  523. {
  524. IFR ifrRecv = (IFR)wArg1; // last received frame
  525. IFR ifrSent = (IFR)lArg2; // the IFR was simply cast to DWORD
  526. // lArg3 is missing
  527. ERRMSG((SZMOD "<<ERROR>> Can't deal with PIN PIP\r\n"));
  528. ICommFailureCode(pTG, T30FAIL_BUG5);
  529. action = actionDCN;
  530. break;
  531. // must alert operator, check that handset has been lifted
  532. // and then return actionGOVOICE. If handest is not lifted
  533. // within T3 must return GO_A (???) or maybe GO_DCN (???) or
  534. // GO_D. Not sure what.
  535. }
  536. case eventVOICELINE:
  537. {
  538. // All Args are missing
  539. ERRMSG((SZMOD "<<ERROR>> Can't deal with VOICELINE\r\n"));
  540. ICommFailureCode(pTG, T30FAIL_BUG6);
  541. action = actionDCN;
  542. break;
  543. // must connect handset to phone line, wait until operator
  544. // finishes talking. Then return HANGUP, GO_T, GO_R1 (??)
  545. // or GO_R2 (??)
  546. }
  547. #endif
  548. /****** Receiver Phase B. Fig A-7/T.30 (sheet 1) ******/
  549. case eventSENDDIS:
  550. {
  551. // wArg1 is 0
  552. // where to return the number of frames returned
  553. LPUWORD lpuwN = (LPUWORD)lArg2;
  554. // where to return a pointer to an array of pointers to
  555. // return frames
  556. LPLPLPFR lplplpfr = (LPLPLPFR)lArg3;
  557. // CreateNSFCSIDIS(npProt, lpuwN, lplplpfr);
  558. BG_CHK(npProt->fSendCapsInited);
  559. BG_CHK(npProt->fllSendCapsInited);
  560. BG_CHK(npProt->fHWCapsInited);
  561. BCtoNSFCSIDIS(pTG, &pTG->rfsSend, (NPBC)&npProt->SendCaps, &npProt->llSendCaps);
  562. *lpuwN = pTG->rfsSend.uNumFrames;
  563. *lplplpfr = pTG->rfsSend.rglpfr;
  564. action = actionSEND_DIS;
  565. break;
  566. }
  567. case eventSENDDTC:
  568. {
  569. // wArg1 is 0
  570. // where to return the number of frames returned
  571. LPUWORD lpuwN = (LPUWORD)lArg2;
  572. // where to return a pointer to an array of pointers to
  573. // return frames
  574. LPLPLPFR lplplpfr = (LPLPLPFR)lArg3;
  575. // CreateNSCCIGDTC(npProt, lpuwN, lplplpfr);
  576. BG_CHK(npProt->fSendPollReqInited);
  577. BG_CHK(npProt->fllSendCapsInited);
  578. BG_CHK(npProt->fHWCapsInited);
  579. BCtoNSCCIGDTC(pTG, &pTG->rfsSend, (NPBC)&npProt->SendPollReq, &npProt->llSendCaps);
  580. *lpuwN = pTG->rfsSend.uNumFrames;
  581. *lplplpfr = pTG->rfsSend.rglpfr;
  582. action = actionSEND_DTC;
  583. break;
  584. }
  585. #ifdef PRI
  586. case eventQUERYLOCALINT:
  587. {
  588. // all Args are missing
  589. // return actionTRUE if a local interrupt is pending, else actionFALSE
  590. action = actionFALSE;
  591. break;
  592. }
  593. #endif // PRI
  594. /*** Receiver Phase B. Main Command Loop. Fig A-7/T.30 (sheet 1&2) ***/
  595. case eventRECVCMD:
  596. {
  597. IFR ifrRecv = (IFR)wArg1; // last received frame
  598. // lArg2 & lArg3 missing
  599. switch(ifrRecv)
  600. {
  601. case ifrDTC:
  602. // flow chart says Goto D, but actually we need to decide if we
  603. // have anything to send. So goto NodeA first
  604. // return GONODE_D;
  605. action = actionGONODE_A;
  606. break;
  607. case ifrDIS:
  608. action = actionGONODE_A;
  609. break;
  610. case ifrDCS:
  611. {
  612. // Check the received DCS for compatibility with us
  613. // set Recv Baud rate--no need. TCF already recvd by this time
  614. // ET30ExtFunction(npProt->het30, ET30_SET_RECVDATASPEED, npProt->RemoteDCS.Baud);
  615. action = actionGETTCF;
  616. // only other valid action is HANGUP
  617. break;
  618. }
  619. case ifrNSS:
  620. {
  621. // Check the received NSS for compatibility with us
  622. // set Recv Baud rate--no need. TCF already recvd by this time
  623. // ET30ExtFunction(npProt->het30, ET30_SET_RECVDATASPEED, npProt->RemoteDCS.Baud);
  624. action = actionGETTCF;
  625. // only other valid action is HANGUP
  626. break;
  627. }
  628. default:
  629. // program bug. hangup
  630. BG_CHK(FALSE);
  631. ICommFailureCode(pTG, T30FAIL_BUG7);
  632. action = actionHANGUP;
  633. break;
  634. }
  635. break;
  636. }
  637. case eventGOTTCF:
  638. {
  639. SWORD swErr = (SWORD)wArg1; // errors per 1000
  640. // lArg2 & lArg3 missing
  641. (MyDebugPrint(pTG, LOG_ALL, "GOTTCF num of errors = %d\r\n", swErr));
  642. if(swErr >= 0)
  643. {
  644. // very important!! Re-init the fPageOK flag in case we miss
  645. // the page entirely, and jump into PhaseD this must be FALSE
  646. // npProt->fPageOK = FALSE;
  647. // done at start of PhaseC by calling ProtResetRecvPageAck()
  648. action = actionSENDCFR; // just going along
  649. }
  650. else
  651. action = actionSENDFTT;
  652. break;
  653. }
  654. /****** Receiver Phase C. Fig A-7/T.30 (sheet 1) ******/
  655. /***
  656. case eventSTARTRECV:
  657. {
  658. if(!StartNextRecvPage())
  659. {
  660. ICommFailureCode(T30FAILR_BUG8);
  661. action = actionDCN;
  662. }
  663. else
  664. action = actionCONTINUE;
  665. break;
  666. }
  667. ***/
  668. /****** Receiver Phase D. Fig A-7/T.30 (sheet 1) ******/
  669. #ifdef PRI
  670. case eventPRIQ:
  671. {
  672. IFR ifrRecv = (IFR)wArg1; // last received frame
  673. // lArg2 & lArg3 missing
  674. /**
  675. ifrRecv can be PRI-Q, PPS-PRI-Q, EOR-PRI-Q
  676. alert operator etc.
  677. can return SENDPIP, SENDPIN, GONODE_F, GO_RECVPOSTPAGE
  678. If PPS-PRIQ can send only PIP not PIN
  679. If EOR-PRIQ can send only PIN not PIP
  680. or HANGUP. Have to combine the stuff on Fig A-18/T.30
  681. (RHS) and on LHS of FigA-7/T.30 (sheet 2) (below node III)
  682. **/
  683. // not implemented
  684. BG_CHK(FALSE);
  685. break;
  686. }
  687. #endif
  688. case eventRECVPOSTPAGECMD:
  689. {
  690. // IFR ifrRecv = (IFR)wArg1; // last received frame
  691. // lArg2 & lArg3 missing
  692. GetRecvPageAck(pTG);
  693. if( ! pTG->fPageIsBad)
  694. action = actionSENDMCF; // quality fine
  695. else
  696. action = actionSENDRTN; // quality unacceptable
  697. // can also return actionSENDPIP or actionSENDPIN in a local
  698. // interrupt is pending
  699. break;
  700. }
  701. /**----------------------- Exclusively ECM ----------------------------**/
  702. case event4THPPR:
  703. {
  704. USHORT uFramesInBlock = (USHORT)wArg1;
  705. USHORT uFramesSent = (USHORT)lArg2;
  706. USHORT uNumBad, i, j;
  707. // program bug. Failure may cause some random (non fatal) results
  708. BG_CHK(npProt->fRecvdPPR);
  709. for(uNumBad=0, i=0; i<=uFramesInBlock; i++)
  710. {
  711. j = (1 << (i % 8));
  712. if(npProt->bRemotePPR[i/8] & j)
  713. uNumBad++;
  714. }
  715. (MyDebugPrint(pTG, LOG_ALL, "4thPPR: FrameCount=%d FramesSent=%d NumBad=%d\r\n",
  716. uFramesInBlock, uFramesSent, uNumBad));
  717. if(pTG->ProtParams.CTCAction == 1)
  718. {
  719. ERRMSG((SZMOD "<<ERROR>> PPR: Too many bad frames\r\n"));
  720. ICommFailureCode(pTG, T30FAILS_4PPR_ERRORS);
  721. action = actionSENDEOR_EOP; // give up
  722. // No need for EOR stuff. If we give up on a file, we can't
  723. // transmit the next page. Doesn't make sense.
  724. }
  725. else
  726. {
  727. // drop speed
  728. if(DropSendSpeed(pTG) != TRUE)
  729. {
  730. ERRMSG((SZMOD "<<ERROR>> PPR: Can't Drop speed any lower\r\n"));
  731. ICommFailureCode(pTG, T30FAILS_4PPR_FALLBACK);
  732. action = actionSENDEOR_EOP;
  733. }
  734. else
  735. action = actionGONODE_ECMRETRANSMIT;
  736. }
  737. break;
  738. }
  739. default:
  740. {
  741. ERRMSG((SZMOD "<<ERROR>> Unknown Event = %d\r\n", event));
  742. ICommFailureCode(pTG, T30FAIL_BUG9);
  743. break;
  744. }
  745. }
  746. //done:
  747. (MyDebugPrint(pTG, LOG_ALL, "WhatNext event %d returned %d\r\n", event, action));
  748. return action;
  749. }