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.

1039 lines
41 KiB

  1. /////// Global #defines that would've gone on the Cmd line //////
  2. /////////////////////////////////////////////////////////////////
  3. /***************************************************************************
  4. Name : HDLC.C
  5. Comment : Contains miscellenous HDLC framing T30 frame recognition and
  6. generation routines. Mostly called from the main T30 skeleton
  7. in T30.C
  8. Revision Log
  9. Num Date Name Description
  10. --- -------- ---------- -----------------------------------------------
  11. ***************************************************************************/
  12. #include "prep.h"
  13. #include "t30.h"
  14. #include "hdlc.h"
  15. #include "debug.h"
  16. ///RSL
  17. #include "glbproto.h"
  18. # define faxTlog(m) DEBUGMSG(ZONE_HD, m)
  19. # define faxT2log(m) DEBUGMSG(ZONE_BUFS, m)
  20. # define FILEID FILEID_HDLC
  21. // CBPFR is a code-based pointer to an FR structure, with the base as
  22. // the current Code segment. It will only be used to access
  23. // the table below which is a CODESEG based constant table.
  24. #define ifrMAX 48
  25. // This table better match the #defines in et30API.H !!!!
  26. // This is everything you never wanted to know about T30 frames....
  27. FRAME TEXTBASED rgFrameInfo[ifrMAX] = {
  28. #define ifrNULL 0
  29. { 0x00, 0, 0, 0, "ifrNULL!!!" },
  30. #define ifrDIS 1
  31. { 0x80, 0, 0, 0xFF, "DIS" },
  32. #define ifrCSI 2
  33. { 0x40, 0, 0, 0xFF, "CSI" },
  34. #define ifrNSF 3
  35. { 0x20, 0, 0, 0xFF, "NSF" },
  36. #define ifrDTC 4
  37. { 0x81, 0, 0, 0xFF, "DTC" },
  38. #define ifrCIG 5
  39. { 0x41, 0, 0, 0xFF, "CIG" },
  40. #define ifrNSC 6
  41. { 0x21, 0, 0, 0xFF, "NSC" },
  42. #define ifrDCS 7
  43. { 0x82, 0, 1, 0xFF, "DCS" },
  44. #define ifrTSI 8
  45. { 0x42, 0, 1, 0xFF, "TSI" },
  46. #define ifrNSS 9
  47. { 0x22, 0, 1, 0xFF, "NSS" },
  48. #define ifrCFR 10
  49. { 0x84, 0, 1, 0, "CFR" },
  50. #define ifrFTT 11
  51. { 0x44, 0, 1, 0, "FTT" },
  52. #define ifrMPS 12
  53. { 0x4E, 0, 1, 0, "MPS" },
  54. #define ifrEOM 13
  55. { 0x8E, 0, 1, 0, "EOM" },
  56. #define ifrEOP 14
  57. { 0x2E, 0, 1, 0, "EOP" },
  58. #define ifrPWD 15
  59. { 0xC1, 0, 0, 0xFF, "PWD" },
  60. #define ifrSEP 16
  61. { 0xA1, 0, 0, 0xFF, "SEP" },
  62. #define ifrSUB 17
  63. { 0xC2, 0, 1, 0xFF, "SUB" },
  64. #define ifrMCF 18
  65. { 0x8C, 0, 1, 0, "MCF" },
  66. #define ifrRTP 19
  67. { 0xCC, 0, 1, 0, "RTP" },
  68. #define ifrRTN 20
  69. { 0x4C, 0, 1, 0, "RTN" },
  70. #define ifrPIP 21
  71. { 0xAC, 0, 1, 0, "PIP" },
  72. #define ifrPIN 22
  73. { 0x2C, 0, 1, 0, "PIN" },
  74. #define ifrDCN 23
  75. { 0xFA, 0, 1, 0, "DCN" },
  76. #define ifrCRP 24
  77. { 0x1A, 0, 1, 0, "CRP" },
  78. #define ifrPRI_MPS 25
  79. { 0x5E, 0, 1, 0, "PRI_MPS" },
  80. #define ifrPRI_EOM 26
  81. { 0x9E, 0, 1, 0, "PRI_EOM" },
  82. #define ifrPRI_EOP 27
  83. { 0x3E, 0, 1, 0, "PRI_EOP" },
  84. /********* ECM stuff starts here. T.30 section A.4 ******/
  85. #define ifrCTC 28
  86. { 0x12, 0, 1, 2, "CTC" },
  87. #define ifrCTR 29
  88. { 0xC4, 0, 1, 0, "CTR" },
  89. #define ifrRR 30
  90. { 0x6E, 0, 1, 0, "RR" },
  91. #define ifrPPR 31
  92. { 0xBC, 0, 1, 32, "PPR" },
  93. #define ifrRNR 32
  94. { 0xEC, 0, 1, 0, "RNR" },
  95. #define ifrERR 33
  96. { 0x1C, 0, 1, 0, "ERR" },
  97. #define ifrPPS_NULL 34
  98. { 0xBE, 0x00+1, 1, 3, "PPS-NULL" },
  99. #define ifrPPS_MPS 35
  100. { 0xBE, 0x4F+1, 1, 3, "PPS-MPS" },
  101. #define ifrPPS_EOM 36
  102. { 0xBE, 0x8F+1, 1, 3, "PPS-EOM" },
  103. #define ifrPPS_EOP 37
  104. { 0xBE, 0x2F+1, 1, 3, "PPS-EOP" },
  105. #define ifrPPS_PRI_MPS 38
  106. { 0xBE, 0x5F+1, 1, 3, "PPS-PRI-MPS" },
  107. #define ifrPPS_PRI_EOM 39
  108. { 0xBE, 0x9F+1, 1, 3, "PPS-PRI-EOM" },
  109. #define ifrPPS_PRI_EOP 40
  110. { 0xBE, 0x3F+1, 1, 3, "PPS-PRI-EOP" },
  111. #define ifrEOR_NULL 41
  112. { 0xCE, 0x00+1, 1, 0, "EOR-NULL" },
  113. #define ifrEOR_MPS 42
  114. { 0xCE, 0x4F+1, 1, 0, "EOR-MPS" },
  115. #define ifrEOR_EOM 43
  116. { 0xCE, 0x8F+1, 1, 0, "EOR-EOM" },
  117. #define ifrEOR_EOP 44
  118. { 0xCE, 0x2F+1, 1, 0, "EOR-EOP" },
  119. #define ifrEOR_PRI_MPS 45
  120. { 0xCE, 0x5F+1, 1, 0, "EOR-PRI-MPS" },
  121. #define ifrEOR_PRI_EOM 46
  122. { 0xCE, 0x9F+1, 1, 0, "EOR-PRI-EOM" },
  123. #define ifrEOR_PRI_EOP 47
  124. { 0xCE, 0x3F+1, 1, 0, "EOR-PRI-EOP" }
  125. #define ifrMAX 48
  126. };
  127. #define EOX_FIRST ifrMPS
  128. #define EOX_LAST ifrEOP
  129. #define PRI_EOX_FIRST ifrPRI_MPS
  130. #define PRI_EOX_LAST ifrPRI_EOP
  131. #define PPS_X_FIRST ifrPPS_NULL
  132. #define PPS_X_LAST ifrPPS_PRI_EOP
  133. #ifdef DLEHERE
  134. # define DLE 0x10
  135. # define ETX 0x03
  136. #endif //DLEHERE
  137. /* Converts a the T30 code for a speed to the Class1 code
  138. * Generates V.17 with Long Training.
  139. * Add 1 to V.17 codes to get teh Short-train version
  140. */
  141. /***************************************************************************
  142. Name : CreateFrame()
  143. Purpose : Create an HDLC frame
  144. Parameters: IFR ifr == ifr number (index into rgfrFrameInfo),
  145. of frame to be generated.
  146. LPB lpbFIF == pointer to FIF BYTEs
  147. UWORD uwFIFLen== length of the pbFIF array
  148. BOOL fFinal == whether Final frame (to set bit 5 of BYTE 2)
  149. NPB npbOut == pointer to space for frame
  150. Returns : TRUE on success, FALSE if bogus params.
  151. CalledFrom: By the protocol module (external to the DLL) in addition
  152. to internal use.
  153. Returns : Composes frame in lpframe->rgb[]
  154. sets lpframe->cb to total length of frame.
  155. Revision Log
  156. Num Date Name Description
  157. --- -------- ---------- -----------------------------------------------
  158. ***************************************************************************/
  159. UWORD CreateFrame(PThrdGlbl pTG, IFR ifr, LPB lpbFIF, USHORT uFIFLen, BOOL fFinal, LPB lpbOut)
  160. {
  161. CBPFRAME cbpframe; // need to worry about NEAR/FAR here...
  162. // bpfr is a CODESEG based pointer
  163. LPB lpbCurr;
  164. // UWORD uw;
  165. BG_CHK(lpbOut && (uFIFLen>0 || !lpbFIF) && ifr>ifrNULL && ifr<ifrMAX);
  166. cbpframe = &rgFrameInfo[ifr];
  167. lpbCurr = lpbOut;
  168. *lpbCurr++ = 0xFF; // HDLC address field Sec 5.3.4
  169. *lpbCurr++ = (BYTE)(fFinal ? 0x13 : 0x03); // HDLC control field Sec 5.3.5
  170. if(pTG->T30.fReceivedDIS && cbpframe->fInsertDISBit)
  171. *lpbCurr++ = (BYTE)(cbpframe->bFCF1 | 0x01);
  172. else
  173. *lpbCurr++ = cbpframe->bFCF1;
  174. // we're not stuffing here, because we're sure FCF is never 0x10, but
  175. // use an assert() to make sure
  176. #ifdef DLEHERE
  177. BG_CHK(*(lpbCurr-1) != DLE);
  178. #endif //DLEHERE
  179. if(cbpframe->bFCF2) // for ECM frames
  180. *lpbCurr++ = cbpframe->bFCF2-1;
  181. #ifdef DLEHERE
  182. BG_CHK(*(lpbCurr-1) != DLE);
  183. #endif //DLEHERE
  184. if(cbpframe->wFIFLength) // check if FIF is reqd
  185. {
  186. BG_CHK(uFIFLen);
  187. // Cant stuff with DLEs here, because DLE stuffing has
  188. // to come *after* SW HDLC framing if any.
  189. // we _never_ do SW HDLC for negotiation frames (the only
  190. // ones that come thru here & we need the cycles, so do
  191. // teh stuffing here again).
  192. _fmemcpy(lpbCurr, lpbFIF, uFIFLen);
  193. lpbCurr += uFIFLen;
  194. #ifdef DLEHERE
  195. for(uw=0; uw<uFIFLen; uw++)
  196. {
  197. if((*lpbCurr++ = lpbFIF[uw]) == DLE)
  198. *lpbCurr++ = DLE; // stuff DLE
  199. }
  200. #endif //DLEHERE
  201. }
  202. else
  203. {
  204. BG_CHK(uFIFLen == 0);
  205. }
  206. #ifdef DLEHERE
  207. *lpbCurr++ = DLE;
  208. *lpbCurr++ = ETX;
  209. // *lpbCurr++ = '\r'; // RC224ATF sends this along with the frame!
  210. // now if anyone *needs* it, we're hosed
  211. #endif //DLEHERE
  212. *lpbCurr = 0; // for debugging printouts
  213. return (UWORD)(lpbCurr-lpbOut);
  214. }
  215. /***************************************************************************
  216. Name : SendFrame
  217. Purpose : Creates & sends HDLC frame & does some logging
  218. Parameters: IFR ifr == Frame index
  219. LPB lpbFIF == pointer to FIF data
  220. UWORD uwLen == length of FIF data
  221. BOOL fFinal == Set Final bit ON or not. Also
  222. whether to wait for OK or CONNECT
  223. after sending frame
  224. Returns : TRUE on success, FALSE on failure
  225. Calls : CreateFrame & WriteFrame
  226. CalledFrom:
  227. Comment : This routine is called from one quadrillion macros
  228. defined in HDLC.H, one for each frame.
  229. e g. SendCFR() macros to SendHDLC(ifrCFR, NULL, 0, TRUE)
  230. Revision Log
  231. Num Date Name Description
  232. --- -------- ---------- -----------------------------------------------
  233. ***************************************************************************/
  234. #define SF_LASTFR (SEND_ENDFRAME|SEND_FINAL)
  235. #define SF_NOTLASTFR (SEND_ENDFRAME)
  236. BOOL SendSingleFrame(PThrdGlbl pTG, IFR ifr, LPB lpbFIF, USHORT uFIFLen, BOOL fSleep)
  237. {
  238. UWORD cb;
  239. BYTE bSend[MAXFRAMESIZE];
  240. // has to hold addr+control+FCF+possibly FCF2+FIF+(maybe DLE+ETX+CR+NULL)
  241. // == FIFlen + 8. Therefore bSend[] better be big enough.
  242. BG_CHK(uFIFLen+8<sizeof(bSend));
  243. // on IFAX, we really do want to wait for silence, otherwise we could
  244. // end up colliding with the other guy & wasting our time. SO give it a
  245. // very long (3sec?) timeout.
  246. // Here we always call RecvSilence. The IFAX driver looks for silence
  247. // to avoid collisions. The Class1 modem driver just uses TwiddleThumbs()
  248. // not FRS or FTS because they are dangerous and slow.
  249. // On PCs we should pause before ALL frames _except_ CFR & FTT (because
  250. // those are too time critical). On IFAX we pause always.
  251. #ifndef MDDI // no pause before CFR/FTT
  252. if(ifr!=ifrCFR && ifr!=ifrFTT)
  253. #endif
  254. {
  255. #ifdef MDDI
  256. // when we are doing send-after-send, and we should use SendSilence
  257. // instead of RecvSilence. If we dont do this, we take too long &
  258. // Ricoh's protocol tester complains. This is Bugs 7071, 7100
  259. if( pTG->T30.fSendAfterSend &&
  260. ((ifr>=EOX_FIRST && ifr<=EOX_LAST) ||
  261. (ifr>=PRI_EOX_FIRST && ifr<=PRI_EOX_LAST) ||
  262. (ifr>=PPS_X_FIRST && ifr<=PPS_X_LAST)) )
  263. {
  264. (MyDebugPrint(pTG, LOG_ALL, "Send V21--Using SendSilence\r\n"));
  265. ModemSendSilence(pTG, pTG->Params.hModem, SEND_LOWSPEED_PAUSE, LONG_RECVSILENCE_TIMEOUT);
  266. }
  267. else
  268. #endif
  269. if (fSleep) {
  270. if(!ModemRecvSilence(pTG, pTG->Params.hModem, RECV_LOWSPEED_PAUSE, LONG_RECVSILENCE_TIMEOUT))
  271. {
  272. ERRMSG((SZMOD "<<ERROR>> V21-Single RecvSilence(%d, %d) FAILED!!!\r\n", RECV_LOWSPEED_PAUSE, LONG_RECVSILENCE_TIMEOUT));
  273. }
  274. }
  275. }
  276. pTG->T30.fSendAfterSend=FALSE;
  277. if(!ModemSendMode(pTG, pTG->Params.hModem, V21_300, TRUE, ifr))
  278. {
  279. ERRMSG((SZMOD "<<ERROR>> ModemSendMode failed in SendSingleFrame\r\n"));
  280. return FALSE;
  281. }
  282. cb = CreateFrame(pTG, ifr, lpbFIF, uFIFLen, TRUE, bSend);
  283. BG_CHK(cb >= uFIFLen+3);
  284. // BG_CHK(cb >= uFIFLen+5);
  285. D_PrintFrame(bSend, cb);
  286. //Protocol Dump
  287. DumpFrame(pTG, TRUE, ifr, uFIFLen, lpbFIF);
  288. if(!ModemSendMem(pTG, pTG->Params.hModem, bSend, cb, SF_LASTFR))
  289. return FALSE;
  290. return TRUE;
  291. }
  292. BOOL SendManyFrames(PThrdGlbl pTG, LPLPFR lplpfr, USHORT uNumFrames)
  293. {
  294. USHORT i;
  295. UWORD cb;
  296. BYTE bSend[MAXFRAMESIZE];
  297. ULONG ulTimeout;
  298. IFR ifrHint;
  299. // ifrHint == last one
  300. ifrHint = lplpfr[uNumFrames-1]->ifr;
  301. // when sending DIS, DCS or DTC we may collide with DCS, DIS or DIS
  302. // coming from the other side. This can be really long
  303. // (preamble+2NSFs+CSI+DIS > 5secs) so wait for upto 10 secs!
  304. if(ifrHint==ifrDIS || ifrHint==ifrDCS || ifrHint==ifrDTC ||
  305. ifrHint==ifrNSS || ifrHint==ifrNSF || ifrHint==ifrNSC)
  306. ulTimeout = REALLY_LONG_RECVSILENCE_TIMEOUT; // 10secs
  307. else
  308. ulTimeout = LONG_RECVSILENCE_TIMEOUT; // 3secs
  309. // on IFAX, we really do want to wait for silence, otherwise we could
  310. // end up colliding with the other guy & wasting our time. SO give it a
  311. // very long (3sec?) timeout.
  312. // Here we always call RecvSilence. The IFAX driver looks for silence
  313. // to avoid collisions. The Class1 modem driver just uses TwiddleThumbs()
  314. // not FRS or FTS because they are dangerous and slow.
  315. // We always pause before multi-frame sets
  316. #ifdef MDDI
  317. // when we are doing send-after-send, and we should use SendSilence
  318. // instead of RecvSilence. If we dont do this, we take too long &
  319. // Ricoh's protocol tester complains. This is Bugs 7071, 7100
  320. if(pTG->T30.fSendAfterSend && (ifrHint==ifrDIS || ifrHint==ifrNSF))
  321. {
  322. (MyDebugPrint(pTG, LOG_ALL, "Send V21--Using SendSilence\r\n"));
  323. ModemSendSilence(pTG, pTG->Params.hModem, SEND_LOWSPEED_PAUSE, LONG_RECVSILENCE_TIMEOUT);
  324. }
  325. else
  326. #endif
  327. if(!ModemRecvSilence(pTG, pTG->Params.hModem, RECV_LOWSPEED_PAUSE, ulTimeout))
  328. {
  329. ERRMSG((SZMOD "<<ERROR>> V21-Multi RecvSilence(%d, %d) FAILED!!!\r\n", RECV_LOWSPEED_PAUSE, ulTimeout));
  330. }
  331. pTG->T30.fSendAfterSend=FALSE;
  332. if(!ModemSendMode(pTG, pTG->Params.hModem, V21_300, TRUE, ifrHint))
  333. {
  334. ERRMSG((SZMOD "<<ERROR>> ModemSendMode failed in SendManyFrames\r\n"));
  335. return FALSE;
  336. }
  337. for(i=0; i<uNumFrames; i++)
  338. {
  339. // has to hold addr+control+FCF+possibly FCF2+FIF+(maybe DLE+ETX+CR+NULL)
  340. // == FIFlen + 8. Therefore bSend[] better be big enough.
  341. BG_CHK(lplpfr[i]->cb+8<sizeof(bSend));
  342. cb = CreateFrame(pTG, lplpfr[i]->ifr, lplpfr[i]->fif, lplpfr[i]->cb, (USHORT)(i==(uNumFrames-1)), bSend);
  343. D_PrintFrame(bSend, cb);
  344. //Protocol Dump
  345. DumpFrame(pTG, TRUE, lplpfr[i]->ifr, lplpfr[i]->cb, lplpfr[i]->fif);
  346. if(!ModemSendMem(pTG, pTG->Params.hModem, bSend, (USHORT)cb,
  347. (USHORT)((i==(USHORT)(uNumFrames-1)) ? SF_LASTFR : SF_NOTLASTFR)))
  348. return FALSE;
  349. }
  350. return TRUE;
  351. }
  352. /***************************************************************************
  353. Name : SendTCF
  354. Purpose : Send a TCF signal. Waits until OK response from modem at end.
  355. Parameters:
  356. Returns : TRUE/FALSE
  357. Revision Log
  358. Num Date Name Description
  359. --- -------- ---------- -----------------------------------------------
  360. ***************************************************************************/
  361. #define min(x,y) (((x) < (y)) ? (x) : (y))
  362. BOOL SendZeros(PThrdGlbl pTG, USHORT uCount, BOOL fFinal)
  363. {
  364. #define TCF_BUFSIZE 256
  365. BYTE bZero[TCF_BUFSIZE];
  366. int i; // must be signed
  367. _fmemset(bZero, 0, TCF_BUFSIZE);
  368. for(i=uCount; i>0; i -= TCF_BUFSIZE)
  369. {
  370. if(i <= TCF_BUFSIZE)
  371. {
  372. // no need to stuff. They're all zeros!
  373. if(!ModemSendMem(pTG, pTG->Params.hModem, bZero, (USHORT)i, (USHORT)(fFinal?SEND_FINAL:0)))
  374. return FALSE;
  375. }
  376. else
  377. {
  378. // no need to stuff. They're all zeros!
  379. if(!ModemSendMem(pTG, pTG->Params.hModem, bZero, (USHORT)TCF_BUFSIZE, (USHORT) 0))
  380. return FALSE;
  381. }
  382. }
  383. return TRUE;
  384. }
  385. // length of TCF = 1.5 * bpscode * 100 / 8 == 75 * bpscode / 4
  386. BOOL SendTCF(PThrdGlbl pTG)
  387. {
  388. USHORT uCount;
  389. USHORT uCurMod;
  390. (MyDebugPrint(pTG, LOG_ALL, "SENDING Training.....at %lx \r\n", GetTickCount() ));
  391. uCurMod = ProtGetSendMod(pTG);
  392. // *Don't* add ST_FLAG. Need long train for TCF
  393. BG_CHK((uCurMod & (~0x0F)) == 0);
  394. #ifndef MDDI2
  395. // length of TCF = 1.5 * bps / 8
  396. uCount = TCFLen[uCurMod & 0x0F]; // kill the ST_FLAG first
  397. // FTT testing!!
  398. // uCount = 450;
  399. #endif
  400. #if (PAGE_PREAMBLE_DIV != 0)
  401. BG_CHK(PAGE_PREAMBLE_DIV);
  402. // (uCount / PAGE_PREAMBLE_DIV) zeros will be sent in ModemSendMode
  403. uCount -= (uCount / (PAGE_PREAMBLE_DIV));
  404. #endif // (PAGE_PREAMBLE_DIV != 0)
  405. #if 0 // RSL
  406. // **DON'T** call RecvSilence here since it is a send-followed-by-send
  407. // case. _Only_ call RecvSilence in recv-followed-by-send cases
  408. if(!ModemSendSilence(pTG, pTG->Params.hModem, SEND_PHASEC_PAUSE, SHORT_SENDSILENCE_TIMEOUT))
  409. {
  410. ERRMSG((SZMOD "<<ERROR>> TCF SendSilence(%d, %d) FAILED!!!\r\n", SEND_PHASEC_PAUSE, SHORT_SENDSILENCE_TIMEOUT));
  411. }
  412. #endif
  413. #ifdef MDDI2
  414. return ModemSendTCF(pTG, pTG->Params.hModem, uCurMod, 1500);
  415. #else //MDDI2
  416. if(!ModemSendMode(pTG, pTG->Params.hModem, uCurMod, FALSE, ifrTCF))
  417. {
  418. ERRMSG((SZMOD "<<ERROR>> ModemSendMode failed in SendTCF\r\n"));
  419. return FALSE;
  420. }
  421. if(!SendZeros(pTG, uCount, TRUE)) // Send TCF zeros
  422. return FALSE;
  423. (MyDebugPrint(pTG, LOG_ALL, "TCF Send Done.....\r\n"));
  424. return TRUE;
  425. #endif //MDDI2
  426. }
  427. /***************************************************************************
  428. Name : SendRTC
  429. Purpose : SendRTC sends 6 eols, DLE-ETX, CR-LF asynchronously,
  430. Parameters: none
  431. Returns : nothing
  432. Comment : Currently SendRTC sends packed EOLs, but some Fax cards may
  433. require BYTE-aligned EOLs, so watch out. All receivers
  434. should theoretically accept BYTE-aligned EOLs, but not
  435. all machines are 100% to the spec.
  436. Revision Log
  437. Num Date Name Description
  438. --- -------- ---------- -----------------------------------------------
  439. ***************************************************************************/
  440. BOOL SendRTC(PThrdGlbl pTG, BOOL fFinal)
  441. {
  442. BYTE bBuf[13];
  443. USHORT uEnc, uLen;
  444. uEnc = ProtGetSendEncoding(pTG);
  445. BG_CHK(uEnc==MR_DATA || uEnc==MH_DATA);
  446. if(uEnc == MR_DATA)
  447. {
  448. (MyDebugPrint(pTG, LOG_ALL, "Send MR RTC\n"));
  449. // MR RTC is EOL+1 6 times. Data produced by Faxcodec end in a
  450. // byte-aligned EOL i.e. 0x80. So I need to put out (1 + EOL)
  451. // 6 times. Simplest is to send out (0x01 0x80) 6 times
  452. // bBuf[0] = 0x01; bBuf[1] = 0x80; bBuf[2] = 0x01; bBuf[3] = 0x80;
  453. // bBuf[4] = 0x01; bBuf[5] = 0x80; bBuf[6] = 0x01; bBuf[7] = 0x80;
  454. // bBuf[8] = 0x01; bBuf[9] = 0x80; bBuf[10]= 0x01; bBuf[11]= 0x80;
  455. // bBuf[12] = 0; // for debugging printouts
  456. // uLen = 12;
  457. // But Ricoh claims this is incorrect, so we need to send a compact
  458. // RTC, i.e. exactly 11 0s for each EOL. 1 + (eol+1)x5 is
  459. // 01 30 00 06 C0 00 18 00 03
  460. bBuf[0] = 0x01; bBuf[1] = 0x30; bBuf[2] = 0x00; bBuf[3] = 0x06;
  461. bBuf[4] = 0xC0; bBuf[5] = 0x00; bBuf[6] = 0x18; bBuf[7] = 0x00;
  462. bBuf[8] = 0x03; bBuf[9] = 0x00;
  463. uLen = 9;
  464. }
  465. else
  466. {
  467. (MyDebugPrint(pTG, LOG_ALL, "Send MH RTC\n"));
  468. // bBuf[0] = 0x00; bBuf[1] = 0x20; bBuf[2] = 0x00;
  469. // bBuf[3] = 0x02; bBuf[4] = 0x20; bBuf[5] = 0x00;
  470. // bBuf[6] = 0x02; bBuf[7] = 0x20; bBuf[8] = 0x00;
  471. // bBuf[9] = 0x02; bBuf[10] = 0; // for debugging printouts
  472. // uLen = 10;
  473. // But Ricoh claims this is incorrect, so we need to send a compact
  474. // RTC, i.e. exactly 11 0s for each EOL. (eol)x5 is
  475. // 00 08 80 00 08 80 00 08
  476. bBuf[0] = 0x00; bBuf[1] = 0x08; bBuf[2] = 0x80; bBuf[3] = 0x00;
  477. bBuf[4] = 0x08; bBuf[5] = 0x80; bBuf[6] = 0x00; bBuf[7] = 0x08;
  478. bBuf[8] = 0x00;
  479. uLen = 8;
  480. }
  481. // no need to stuff
  482. return ModemSendMem(pTG, pTG->Params.hModem, bBuf, uLen, (USHORT)(fFinal ? SEND_FINAL : 0));
  483. }
  484. /***************************************************************************
  485. Name : GetTCF()
  486. Purpose : Receive a TCF signal, analyse it, recognize "good" or "bad"
  487. Parameters: none
  488. Returns : 1 if a "good" signal is received.
  489. 0 on error
  490. -1 if too short TCF signal
  491. -2 if too many errors
  492. Comment : The CCITT does not tell us what consitutes a good training,
  493. so I'm playing blind here. If we are too stringent we'll fail
  494. to ever sync. If we are too liberal, we'll end up with a high
  495. error rate when we could have dropped baud rate & got a
  496. perfectly good signal.
  497. Emperically I observe bits of contigous trash at the
  498. beginning and end of the training even on a perfectly good
  499. line. (OK, I now know this is known as the turn-on and
  500. turn-off sequence. So what we have now is
  501. <turnon trash><1111s><0000s (training)><1111s><turnoff trash>
  502. The turnon/turnoff trash & the marks (1111s) should not
  503. interfere with recognizing a perfectly good training signal.
  504. The trash is isolated from the 00s by FFs
  505. Algo: Wait for the first good burst of zeros, then count
  506. zeros, and randomly interspersed non-zero (these represent
  507. real noise errors). Stop counting when we get a burst of FFs.
  508. Now make sure teh zero burst is long enough & the "real"
  509. error rate is not too high.
  510. Lots of parameters here:-
  511. flP_ERROR == keep Prob(error) below this. Between 0 and 1
  512. uwZEROmin == how many zeros before we start counting
  513. uwTURNOFFmin == how much consecutive trash before we
  514. ignore rest
  515. Tune these parameters after real testing with real lines!!!
  516. (maybe a phone line simulator with a lil white noise -- Yeah!!)
  517. At the end of this function, (nZeros/nTotal) is an estimate
  518. of the probability that a byte gets thru OK. Call this PB.
  519. Then prob. that a line of average 30-40 bytes gets through
  520. is PB^30. If we drop the expected number of OK lines as low
  521. as 80% this still means that PB must be no lower than
  522. the 30th root of 0.8, which is 0.9925. Therefore
  523. flP_ERROR must be less than 0.75%
  524. At PL=90%, PB rises to 0.9965 and flP_ERROR to 0.0035
  525. Revision Log
  526. Num Date Name Description
  527. --- -------- ---------- -----------------------------------------------
  528. ***************************************************************************/
  529. // We read the TCF in units of One-Tenth of nominal TCF length
  530. // We discard the first 2 chunks (20%), examine the next 4 chunks (40%)
  531. // discard the rest. If the length is between 6 & 13 chunks (60% to 130%)
  532. // and the error rates in chunk 2 & 3 is below the threshold we declare
  533. // it OK. This (a) accepts too-short TCFs (some Class2 modems), and
  534. // too long ones. (b) ignores leading and trailing trash (c) Can afford
  535. // to be pretty strict with the core of the TCF
  536. USHORT OneTenthTCFLen[16] =
  537. {
  538. /* V27_2400 0 */ 45,
  539. /* V29_9600 1 */ 180,
  540. /* V27_4800 2 */ 90,
  541. /* V29_7200 3 */ 135,
  542. /* V33_14400 4 */ 270,
  543. 0,
  544. /* V33_12000 6 */ 225,
  545. 0,
  546. /* V17_14400 8 */ 270,
  547. /* V17_9600 9 */ 180,
  548. /* V17_12000 10 */ 225,
  549. /* V17_7200 11 */ 135,
  550. 0,
  551. 0,
  552. 0,
  553. 0
  554. };
  555. #define RECV_TCFBUFSIZE 270 // must be >= max chunk in above table
  556. #define MIN_TCFLEN 4 // measured in 10ths of the nominal length
  557. #define MAX_TCFLEN 13 // measured in 10ths of the nominal length
  558. #define CHECKTCF_START 2 // lowest 10th to measure (20% and up)
  559. #define CHECKTCF_STOP 5 // highest 10th to measure (upto 59%)
  560. #define MAX_ERRS_PER_1000 20 // Increased from 1% to 2%. Be more lax
  561. #ifdef MDDI
  562. # define RECVBUF_SLACK 0 // OEM drivers fill buffer of any size
  563. // NOT! -- Xerox's Cactus driver is based
  564. // on our Class1 driver -- but we don't care
  565. // now, do we?
  566. #else
  567. # define RECVBUF_SLACK 3 // Class1 driver fills only > 3, and leaves 3 empty spaces
  568. #endif
  569. SWORD GetTCF(PThrdGlbl pTG)
  570. {
  571. USHORT uCurMod, uChunkSize, uLength, uMeasuredLength, uErrCount;
  572. USHORT uPhase, uNumRead, uEOF, i;
  573. BYTE bRecvTCF[RECV_TCFBUFSIZE + RECVBUF_SLACK];
  574. SWORD swRet;
  575. // uCurMod = ProtGetRecvMod();
  576. uCurMod = pTG->T30.uRecvTCFMod;
  577. BG_CHK((uCurMod & (~0x0F)) == 0);
  578. // *Don't* add ST_FLAG since we need long training for TCF
  579. pTG->T30.sRecvBufSize = 0;
  580. // Need a CritSection for receiving TCF. Must call Exit on every path out of here
  581. EnterPageCrit(); // start the GetTCF critsection
  582. if(ModemRecvMode(pTG, pTG->Params.hModem, uCurMod, FALSE, TCF_TIMEOUT, ifrTCF) != RECV_OK)
  583. {
  584. ExitPageCrit(); // end the GetTCF critsection
  585. swRet= -1112;
  586. goto missedit;
  587. }
  588. pTG->CommCache.fReuse = 1;
  589. ExitPageCrit(); // end the GetTCF critsection
  590. (MyDebugPrint(pTG, LOG_ALL, "Receiving TCF: Mod=%d\r\n", uCurMod));
  591. // make it large, in case of large buffers & slow modems
  592. #define READ_TIMEOUT 10000
  593. uChunkSize = OneTenthTCFLen[uCurMod];
  594. BG_CHK(uChunkSize+RECVBUF_SLACK <= sizeof(bRecvTCF));
  595. uErrCount = 0;
  596. uLength = 0;
  597. uMeasuredLength = 0;
  598. for(uPhase=0; ;uPhase++)
  599. {
  600. // read a whole chunk
  601. for(uNumRead=0; uNumRead<uChunkSize; )
  602. {
  603. USHORT uTemp = 0;
  604. uEOF = ModemRecvMem(pTG, pTG->Params.hModem, bRecvTCF+uNumRead, (USHORT) (uChunkSize-uNumRead+RECVBUF_SLACK), READ_TIMEOUT, &uTemp);
  605. BG_CHK(uTemp <= (uChunkSize-uNumRead));
  606. uNumRead+=uTemp;
  607. if(uEOF==RECV_EOF)
  608. break;
  609. else if(uEOF != RECV_OK)
  610. {
  611. swRet = -1113;
  612. goto missedit;
  613. }
  614. }
  615. BG_CHK(uEOF==RECV_EOF || (uEOF==RECV_OK && uNumRead==uChunkSize));
  616. // ignore phases 0, 1, and 6 and above
  617. if(uPhase>=CHECKTCF_START && uPhase<=CHECKTCF_STOP)
  618. {
  619. for(i=0; i< uNumRead; i++)
  620. {
  621. if(bRecvTCF[i])
  622. uErrCount++;
  623. uMeasuredLength++;
  624. }
  625. }
  626. uLength += uNumRead;
  627. if(uEOF==RECV_EOF)
  628. break;
  629. }
  630. // comes here on EOF only
  631. BG_CHK(uEOF==RECV_EOF);
  632. // Official length must be at least 1.5s -10% = 1.35secs
  633. // We allow much more latitude because length variation
  634. // cannot be caused by line noise, only be bugs at the sender
  635. //
  636. // E.g. Fury DNE 1086 (German modem) sends a TCF that's too short
  637. // (sends 600 bytes at 4800 and 200 at 2400). This is less than
  638. // half of what we expect.
  639. // TCF with few errs (i.e. uErrCount==0) and is greater
  640. // that half of the min length we expect (i.e. longer
  641. // than 375 for 4800 and 172 for 2400) then accept it
  642. // (allow if uErr<=2 (arbitary small number))
  643. if(uPhase<MIN_TCFLEN || uPhase>MAX_TCFLEN) // length<40% or >139%
  644. {
  645. ERRMSG(("BAD TCF length (%d), expected %d, Min %d uPhase=%d\r\n", uLength,
  646. uChunkSize*10, uChunkSize*MIN_TCFLEN, uChunkSize*MAX_TCFLEN, uPhase));
  647. swRet = -1000; // too short or long
  648. }
  649. else
  650. {
  651. // Calc errors per 1000 = (uErrCount * 1000)/uMeasuredLength
  652. BG_CHK(uMeasuredLength);
  653. swRet = (SWORD)((((DWORD)uErrCount) * 1000L) / ((DWORD)uMeasuredLength));
  654. if(swRet > MAX_ERRS_PER_1000)
  655. {
  656. swRet = (-swRet);
  657. ERRMSG((SZMOD "TOO MANY TCF ERRORS: swRet=%d uErrCount=%d uMeasured=%d uLength=%d uPhase=%d\r\n",
  658. swRet, uErrCount, uMeasuredLength, uLength, uPhase));
  659. }
  660. }
  661. BG_CHK(swRet >= -1000);
  662. (MyDebugPrint(pTG, LOG_ALL, "GetTCF -- returning %d\r\n", swRet));
  663. return swRet;
  664. missedit:
  665. (MyDebugPrint(pTG, LOG_ALL, "GetTCF -- MISSED IT!! returning %d\r\n", swRet));
  666. return swRet;
  667. }
  668. /***************************************************************************
  669. Name : DEBUG.C
  670. Comment : Factored out debug code
  671. Functions : (see Prototypes just below)
  672. Revision Log
  673. Num Date Name Description
  674. --- -------- ---------- -----------------------------------------------
  675. ***************************************************************************/
  676. #ifdef DEBUG
  677. void D_PrintFrame(LPB lpb, UWORD cb)
  678. {
  679. UWORD uw, j;
  680. IFR ifr;
  681. #define PRINTFRAMEBUFSIZE 256
  682. BYTE b2[PRINTFRAMEBUFSIZE];
  683. for(ifr=1; ifr<ifrMAX; ifr++)
  684. if(rgFrameInfo[ifr].bFCF1 ==
  685. (BYTE)(rgFrameInfo[ifr].fInsertDISBit ?
  686. (lpb[2] & 0xFE) : lpb[2]))
  687. break;
  688. if(ifr == ifrMAX) ifr = 0;
  689. j = (UWORD)wsprintf((LPSTR)b2, " (%s) 0x%02x [", (LPSTR)(rgFrameInfo[ifr].szName), lpb[2]);
  690. for(uw=3; uw<cb;)
  691. j += (UWORD)wsprintf((LPSTR)b2+j, "%02x ", (UWORD)lpb[uw++]);
  692. j += (UWORD)wsprintf((LPSTR)b2+j, "]\r\n");
  693. DEBUGMSG(1, (SZMOD "%s\r\n", (LPSTR)b2));
  694. }
  695. #endif
  696. USHORT ModemRecvBuf(PThrdGlbl pTG, HMODEM hModem, BOOL fECM, LPBUFFER far* lplpbf, ULONG ulTimeout)
  697. {
  698. USHORT uRet;
  699. // (MyDebugPrint(pTG, LOG_ALL, "In ModemRecvBuf lplpbf=%08lx ulTimeout=%ld\r\n", lplpbf, ulTimeout));
  700. BG_CHK(lplpbf);
  701. BG_CHK(pTG->T30.sRecvBufSize);
  702. #ifdef IFK
  703. TstartTimeOut(pTG, &pTG->T30.toBuf, WAITFORBUF_TIMEOUT);
  704. while(!(*lplpbf = MyAllocBuf(pTG, pTG->T30.sRecvBufSize)))
  705. {
  706. if(!TcheckTimeOut(pTG, &pTG->T30.toBuf))
  707. {
  708. ERRMSG((SZMOD "<<ERROR>> Giving up on BufAlloc in T30 after %ld millisecs\r\n", ((ULONG)WAITFORBUF_TIMEOUT)));
  709. BG_CHK(FALSE);
  710. return RECV_ERROR;
  711. }
  712. RETAILMSG((SZMOD "<<ERROR>> BufAlloc failed in T30. Trying again\r\n"));
  713. IFProcSleep(100);
  714. }
  715. #else
  716. if(!(*lplpbf = MyAllocBuf(pTG, pTG->T30.sRecvBufSize)))
  717. return RECV_ERROR;
  718. #endif
  719. MyDebugPrint(pTG, LOG_ALL, "In ModemRecvBuf allocated %d bytes \n", pTG->T30.sRecvBufSize);
  720. #ifdef SWECM
  721. if(fECM)
  722. uRet = SWECMRecvFrame(pTG, hModem, (*lplpbf)->lpbBegBuf,
  723. (*lplpbf)->wLengthBuf, ulTimeout, &((*lplpbf)->wLengthData));
  724. else
  725. #endif
  726. uRet = ModemRecvMem(pTG, hModem, (*lplpbf)->lpbBegBuf,
  727. (*lplpbf)->wLengthBuf, ulTimeout, &((*lplpbf)->wLengthData));
  728. if(!((*lplpbf)->wLengthData))
  729. {
  730. (MyDebugPrint(pTG, LOG_ALL, "Got 0 bytes from ModemRecvMem--freeing Buf 0x%08lx\r\n", *lplpbf));
  731. MyFreeBuf(pTG, *lplpbf);
  732. *lplpbf = NULL;
  733. BG_CHK(uRet != RECV_OK);
  734. // moved this error case handling out, since it's different for
  735. // ECM and non-ECM cases. In both cases want to ignore rather than
  736. // abort, so RECV_ERROR is not an appropriate return value
  737. // if(uRet==RECV_OK) uRet=RECV_ERROR; // just in case. see bug#1492
  738. }
  739. if(*lplpbf)
  740. faxT2log((SZMOD "Ex ModemRecvBuf lpbf=%08lx uSize=%d uCount=%d uRet=%d\r\n", *lplpbf, (*lplpbf)->wLengthBuf, (*lplpbf)->wLengthData, uRet));
  741. else
  742. faxT2log((SZMOD "Ex ModemRecvBuf lpbf=null uRet=%d\r\n", uRet));
  743. return uRet;
  744. }
  745. #ifdef PDUMP // Protocol Dump
  746. #include <protdump.h>
  747. void RestartDump(PThrdGlbl pTG)
  748. {
  749. (MyDebugPrint(pTG, LOG_ALL, "Restart Dump old=%d off=%d\r\n", pTG->fsDump.uNumFrames, pTG->fsDump.uFreeSpaceOff));
  750. pTG->fsDump.uNumFrames = 0;
  751. pTG->fsDump.uFreeSpaceOff = 0;
  752. }
  753. void DumpFrame(PThrdGlbl pTG, BOOL fSend, IFR ifr, USHORT cbFIF, LPBYTE lpbFIF)
  754. {
  755. LPFR lpfr;
  756. if( pTG->fsDump.uNumFrames >= MAXDUMPFRAMES ||
  757. pTG->fsDump.uFreeSpaceOff+cbFIF+sizeof(FRBASE) >= MAXDUMPSPACE)
  758. {
  759. DEBUGMSG(1, (SZMOD " Out of dump space num=%d size=%d\r\n",
  760. pTG->fsDump.uNumFrames, pTG->fsDump.uFreeSpaceOff));
  761. return;
  762. }
  763. lpfr = (LPFR) (((LPBYTE)(pTG->fsDump.b)) + pTG->fsDump.uFreeSpaceOff);
  764. lpfr->ifr = ifr;
  765. if(fSend) lpfr->ifr |= 0x80;
  766. lpfr->cb = (BYTE) cbFIF;
  767. if(cbFIF)
  768. {
  769. _fmemcpy(lpfr->fif, lpbFIF, cbFIF);
  770. }
  771. pTG->fsDump.uFrameOff[pTG->fsDump.uNumFrames++] =
  772. (USHORT)((((LPBYTE)(lpfr)) - ((LPBYTE)(pTG->fsDump.b))));
  773. pTG->fsDump.uFreeSpaceOff += (cbFIF + sizeof(FRBASE));
  774. BG_CHK(pTG->fsDump.uNumFrames <= MAXDUMPFRAMES);
  775. BG_CHK(pTG->fsDump.uFreeSpaceOff <= MAXDUMPSPACE);
  776. }
  777. void PrintDump(PThrdGlbl pTG)
  778. {
  779. int i, j;
  780. (MyDebugPrint(pTG, LOG_ALL, "-*-*-*-*-*-*-*-* Print Protocol Dump -*-*-*-*-*-*-*-*-\r\n"));
  781. for(i=0; i<(int)pTG->fsDump.uNumFrames; i++)
  782. {
  783. LPFR lpfr = (LPFR) (((LPBYTE)(pTG->fsDump.b)) + pTG->fsDump.uFrameOff[i]);
  784. IFR ifr = (lpfr->ifr & 0x7F);
  785. BOOL fSend = (lpfr->ifr & 0x80);
  786. BG_CHK(ifr <= ifrMAX);
  787. (MyDebugPrint(pTG, LOG_ALL, "%s: %s [ ",
  788. (LPSTR)(fSend ? "Sent" : "Recvd"),
  789. (LPSTR)(ifr ? rgFrameInfo[ifr].szName : "???") ));
  790. for(j=0; j<lpfr->cb; j++)
  791. (MyDebugPrint(pTG, LOG_ALL, "%02x ", (WORD)lpfr->fif[j]));
  792. (MyDebugPrint(pTG, LOG_ALL, "]\r\n"));
  793. }
  794. (MyDebugPrint(pTG, LOG_ALL, "-*-*-*-*-*-*-*-* End Protocol Dump -*-*-*-*-*-*-*-*-\r\n"));
  795. }
  796. #endif //PDUMP