Leaked source code of windows server 2003
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.

804 lines
29 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. #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_MAIN
  13. #include "prep.h"
  14. #include "t30.h"
  15. #include "hdlc.h"
  16. #include "debug.h"
  17. #include "glbproto.h"
  18. #include "psslog.h"
  19. #define FILE_ID FILE_ID_HDLC
  20. // This is everything you never wanted to know about T30 frames....
  21. FRAME rgFrameInfo[ifrMAX] = {
  22. { 0x00, 0, 0, 0, "ifrNULL!!!"},
  23. { 0x80, 0, 0, 0xFF, "DIS" },
  24. { 0x40, 0, 0, 0xFF, "CSI" },
  25. { 0x20, 0, 0, 0xFF, "NSF" },
  26. { 0x81, 0, 0, 0xFF, "DTC" },
  27. { 0x41, 0, 0, 0xFF, "CIG" },
  28. { 0x21, 0, 0, 0xFF, "NSC" },
  29. { 0x82, 0, 1, 0xFF, "DCS" },
  30. { 0x42, 0, 1, 0xFF, "TSI" },
  31. { 0x22, 0, 1, 0xFF, "NSS" },
  32. { 0x84, 0, 1, 0, "CFR" },
  33. { 0x44, 0, 1, 0, "FTT" },
  34. { 0x4E, 0, 1, 0, "MPS" },
  35. { 0x8E, 0, 1, 0, "EOM" },
  36. { 0x2E, 0, 1, 0, "EOP" },
  37. { 0xC1, 0, 0, 0xFF, "PWD" },
  38. { 0xA1, 0, 0, 0xFF, "SEP" },
  39. { 0xC2, 0, 1, 0xFF, "SUB" },
  40. { 0x8C, 0, 1, 0, "MCF" },
  41. { 0xCC, 0, 1, 0, "RTP" },
  42. { 0x4C, 0, 1, 0, "RTN" },
  43. { 0xAC, 0, 1, 0, "PIP" },
  44. { 0x2C, 0, 1, 0, "PIN" },
  45. { 0xFA, 0, 1, 0, "DCN" },
  46. { 0x1A, 0, 1, 0, "CRP" },
  47. { 0x5E, 0, 1, 0, "PRI_MPS" },
  48. { 0x9E, 0, 1, 0, "PRI_EOM" },
  49. { 0x3E, 0, 1, 0, "PRI_EOP" },
  50. /********* ECM stuff starts here. T.30 section A.4 ******/
  51. { 0x12, 0, 1, 2, "CTC" },
  52. { 0xC4, 0, 1, 0, "CTR" },
  53. { 0x6E, 0, 1, 0, "RR" },
  54. { 0xBC, 0, 1, 32,"PPR" },
  55. { 0xEC, 0, 1, 0, "RNR" },
  56. { 0x1C, 0, 1, 0, "ERR" },
  57. { 0xBE, 0x00+1, 1, 3, "PPS-NULL" },
  58. { 0xBE, 0x4F+1, 1, 3, "PPS-MPS" },
  59. { 0xBE, 0x8F+1, 1, 3, "PPS-EOM" },
  60. { 0xBE, 0x2F+1, 1, 3, "PPS-EOP" },
  61. { 0xBE, 0x5F+1, 1, 3, "PPS-PRI-MPS" },
  62. { 0xBE, 0x9F+1, 1, 3, "PPS-PRI-EOM" },
  63. { 0xBE, 0x3F+1, 1, 3, "PPS-PRI-EOP" },
  64. { 0xCE, 0x00+1, 1, 0, "EOR-NULL" },
  65. { 0xCE, 0x4F+1, 1, 0, "EOR-MPS" },
  66. { 0xCE, 0x8F+1, 1, 0, "EOR-EOM" },
  67. { 0xCE, 0x2F+1, 1, 0, "EOR-EOP" },
  68. { 0xCE, 0x5F+1, 1, 0, "EOR-PRI-MPS" },
  69. { 0xCE, 0x9F+1, 1, 0, "EOR-PRI-EOM" },
  70. { 0xCE, 0x3F+1, 1, 0, "EOR-PRI-EOP" }
  71. };
  72. /* Converts a the T30 code for a speed to the Class1 code
  73. * Generates V.17 with Long Training.
  74. * Add 1 to V.17 codes to get teh Short-train version
  75. */
  76. /***************************************************************************
  77. Name : CreateFrame()
  78. Purpose : Create an HDLC frame
  79. Parameters: IFR ifr == ifr number (index into rgfrFrameInfo),
  80. of frame to be generated.
  81. LPB lpbFIF == pointer to FIF BYTEs
  82. UWORD uwFIFLen== length of the pbFIF array
  83. BOOL fFinal == whether Final frame (to set bit 5 of BYTE 2)
  84. NPB npbOut == pointer to space for frame
  85. Returns : TRUE on success, FALSE if bogus params.
  86. CalledFrom: By the protocol module (external to the DLL) in addition
  87. to internal use.
  88. Returns : Composes frame in lpframe->rgb[]
  89. sets lpframe->cb to total length of frame.
  90. Revision Log
  91. Num Date Name Description
  92. --- -------- ---------- -----------------------------------------------
  93. ***************************************************************************/
  94. UWORD CreateFrame(PThrdGlbl pTG, IFR ifr, LPB lpbFIF, USHORT uFIFLen, BOOL fFinal, LPB lpbOut)
  95. {
  96. CBPFRAME cbpframe; // need to worry about NEAR/FAR here...
  97. // bpfr is a CODESEG based pointer
  98. LPB lpbCurr;
  99. cbpframe = &rgFrameInfo[ifr];
  100. lpbCurr = lpbOut;
  101. *lpbCurr++ = 0xFF; // HDLC address field Sec 5.3.4
  102. *lpbCurr++ = (BYTE)(fFinal ? 0x13 : 0x03); // HDLC control field Sec 5.3.5
  103. if(pTG->T30.fReceivedDIS && cbpframe->fInsertDISBit)
  104. {
  105. *lpbCurr++ = (BYTE)(cbpframe->bFCF1 | 0x01);
  106. }
  107. else
  108. {
  109. *lpbCurr++ = cbpframe->bFCF1;
  110. }
  111. if(cbpframe->bFCF2) // for ECM frames
  112. *lpbCurr++ = cbpframe->bFCF2-1;
  113. if(cbpframe->wFIFLength) // check if FIF is reqd
  114. {
  115. // Cant stuff with DLEs here, because DLE stuffing has
  116. // to come *after* SW HDLC framing if any.
  117. // we _never_ do SW HDLC for negotiation frames (the only
  118. // ones that come thru here & we need the cycles, so do
  119. // teh stuffing here again).
  120. _fmemcpy(lpbCurr, lpbFIF, uFIFLen);
  121. lpbCurr += uFIFLen;
  122. }
  123. *lpbCurr = 0; // for debugging printouts
  124. return (UWORD)(lpbCurr-lpbOut);
  125. }
  126. /***************************************************************************
  127. Name : SendFrame
  128. Purpose : Creates & sends HDLC frame & does some logging
  129. Parameters: IFR ifr == Frame index
  130. LPB lpbFIF == pointer to FIF data
  131. UWORD uwLen == length of FIF data
  132. BOOL fFinal == Set Final bit ON or not. Also
  133. whether to wait for OK or CONNECT
  134. after sending frame
  135. Returns : TRUE on success, FALSE on failure
  136. Calls : CreateFrame & WriteFrame
  137. CalledFrom:
  138. Comment : This routine is called from one quadrillion macros
  139. defined in HDLC.H, one for each frame.
  140. e g. SendCFR() macros to SendHDLC(ifrCFR, NULL, 0, TRUE)
  141. Revision Log
  142. Num Date Name Description
  143. --- -------- ---------- -----------------------------------------------
  144. ***************************************************************************/
  145. #define SF_LASTFR (SEND_ENDFRAME|SEND_FINAL)
  146. #define SF_NOTLASTFR (SEND_ENDFRAME)
  147. BOOL SendSingleFrame(PThrdGlbl pTG, IFR ifr, LPB lpbFIF, USHORT uFIFLen, BOOL fSleep)
  148. {
  149. UWORD cb;
  150. BYTE bSend[MAXFRAMESIZE];
  151. DEBUG_FUNCTION_NAME(_T("SendSingleFrame"));
  152. // has to hold addr+control+FCF+possibly FCF2+FIF+(maybe DLE+ETX+CR+NULL)
  153. // == FIFlen + 8. Therefore bSend[] better be big enough.
  154. // On PCs we should pause before ALL frames _except_ CFR & FTT (because
  155. // those are too time critical). On IFAX we pause always.
  156. if(ifr!=ifrCFR && ifr!=ifrFTT)
  157. {
  158. if (fSleep)
  159. {
  160. Sleep(RECV_LOWSPEED_PAUSE);
  161. }
  162. }
  163. if(!ModemSendMode(pTG, V21_300))
  164. {
  165. DebugPrintEx(DEBUG_ERR,"ModemSendMode failed in SendSingleFrame");
  166. return FALSE;
  167. }
  168. cb = CreateFrame(pTG, ifr, lpbFIF, uFIFLen, TRUE, bSend);
  169. D_PrintFrame(bSend, cb);
  170. //Protocol Dump
  171. DumpFrame(pTG, TRUE, ifr, uFIFLen, lpbFIF);
  172. PSSLogEntryHex(PSS_MSG, 2, bSend, cb, "send: %s, %d bytes,", rgFrameInfo[ifr].szName, cb);
  173. if(!ModemSendMem(pTG, bSend, cb, SF_LASTFR))
  174. {
  175. DebugPrintEx(DEBUG_ERR,"ModemSendMem failed in SendSingleFrame");
  176. return FALSE;
  177. }
  178. return TRUE;
  179. }
  180. BOOL SendManyFrames(PThrdGlbl pTG, LPLPFR lplpfr, USHORT uNumFrames)
  181. {
  182. USHORT i;
  183. UWORD cb;
  184. BYTE bSend[MAXFRAMESIZE];
  185. ULONG ulTimeout;
  186. IFR ifrHint;
  187. DEBUG_FUNCTION_NAME(_T("SendManyFrames"));
  188. // ifrHint == last one
  189. ifrHint = lplpfr[uNumFrames-1]->ifr;
  190. // when sending DIS, DCS or DTC we may collide with DCS, DIS or DIS
  191. // coming from the other side. This can be really long
  192. // (preamble+2NSFs+CSI+DIS > 5secs) so wait for upto 10 secs!
  193. if(ifrHint==ifrDIS || ifrHint==ifrDCS || ifrHint==ifrDTC ||
  194. ifrHint==ifrNSS || ifrHint==ifrNSF || ifrHint==ifrNSC)
  195. {
  196. ulTimeout = REALLY_LONG_RECVSILENCE_TIMEOUT; // 6 secs
  197. }
  198. else
  199. {
  200. ulTimeout = LONG_RECVSILENCE_TIMEOUT; // 3secs
  201. }
  202. // We always pause before multi-frame sets
  203. Sleep(RECV_LOWSPEED_PAUSE);
  204. if(!ModemSendMode(pTG, V21_300))
  205. {
  206. DebugPrintEx(DEBUG_ERR,"ModemSendMode failed in SendManyFrames");
  207. return FALSE;
  208. }
  209. for(i=0; i<uNumFrames; i++)
  210. {
  211. // has to hold addr+control+FCF+possibly FCF2+FIF+(maybe DLE+ETX+CR+NULL)
  212. // == FIFlen + 8. Therefore bSend[] better be big enough.
  213. cb = CreateFrame(pTG, lplpfr[i]->ifr, lplpfr[i]->fif, lplpfr[i]->cb, (USHORT)(i==(uNumFrames-1)), bSend);
  214. D_PrintFrame(bSend, cb);
  215. //Protocol Dump
  216. DumpFrame(pTG, TRUE, lplpfr[i]->ifr, lplpfr[i]->cb, lplpfr[i]->fif);
  217. PSSLogEntryHex(PSS_MSG, 2, bSend, cb, "send: %s, %d bytes,", rgFrameInfo[lplpfr[i]->ifr].szName, cb);
  218. if(!ModemSendMem(pTG, bSend, (USHORT)cb,
  219. (USHORT)((i==(USHORT)(uNumFrames-1)) ? SF_LASTFR : SF_NOTLASTFR)))
  220. {
  221. return FALSE;
  222. }
  223. }
  224. return TRUE;
  225. }
  226. /***************************************************************************
  227. Name : SendTCF
  228. Purpose : Send a TCF signal. Waits until OK response from modem at end.
  229. Parameters:
  230. Returns : TRUE/FALSE
  231. Revision Log
  232. Num Date Name Description
  233. --- -------- ---------- -----------------------------------------------
  234. ***************************************************************************/
  235. #define min(x,y) (((x) < (y)) ? (x) : (y))
  236. #define TCF_BUFSIZE 256
  237. BOOL SendZeros(PThrdGlbl pTG, USHORT uCount, BOOL fFinal)
  238. {
  239. BYTE bZero[TCF_BUFSIZE];
  240. int i; // must be signed
  241. _fmemset(bZero, 0, TCF_BUFSIZE);
  242. PSSLogEntry(PSS_MSG, 2, "send: %d zeroes", uCount);
  243. for(i=uCount; i>0; i -= TCF_BUFSIZE)
  244. {
  245. if(i <= TCF_BUFSIZE)
  246. {
  247. // no need to stuff. They're all zeros!
  248. if(!ModemSendMem(pTG, bZero, (USHORT)i, (USHORT)(fFinal?SEND_FINAL:0)))
  249. return FALSE;
  250. }
  251. else
  252. {
  253. // no need to stuff. They're all zeros!
  254. if(!ModemSendMem(pTG, bZero, (USHORT)TCF_BUFSIZE, (USHORT) 0))
  255. return FALSE;
  256. }
  257. }
  258. return TRUE;
  259. }
  260. // length of TCF = 1.5 * bpscode * 100 / 8 == 75 * bpscode / 4
  261. BOOL SendTCF(PThrdGlbl pTG)
  262. {
  263. USHORT uCount;
  264. USHORT uCurMod;
  265. DEBUG_FUNCTION_NAME(_T("SendTCF"));
  266. uCurMod = pTG->ProtInst.llNegot.Baud;
  267. // length of TCF = 1.5 * bps / 8
  268. uCount = TCFLen[uCurMod & 0x0F]; // kill the ST_FLAG first
  269. // (uCount / PAGE_PREAMBLE_DIV) zeros will be sent in ModemSendMode
  270. uCount -= (uCount / (PAGE_PREAMBLE_DIV));
  271. if(!ModemSendMode(pTG, uCurMod))
  272. {
  273. DebugPrintEx(DEBUG_ERR,"ModemSendMode failed in SendTCF");
  274. return FALSE;
  275. }
  276. if(!SendZeros(pTG, uCount, TRUE)) // Send TCF zeros
  277. {
  278. DebugPrintEx(DEBUG_ERR,"TCF SendZeroes(uCount=%d) FAILED!!!", uCount);
  279. return FALSE;
  280. }
  281. DebugPrintEx(DEBUG_MSG,"TCF Send Done.....");
  282. return TRUE;
  283. }
  284. /***************************************************************************
  285. Name : SendRTC
  286. Purpose : SendRTC sends 6 eols, DLE-ETX, CR-LF asynchronously,
  287. Parameters: none
  288. Returns : nothing
  289. Comment : Currently SendRTC sends packed EOLs, but some Fax cards may
  290. require BYTE-aligned EOLs, so watch out. All receivers
  291. should theoretically accept BYTE-aligned EOLs, but not
  292. all machines are 100% to the spec.
  293. Revision Log
  294. Num Date Name Description
  295. --- -------- ---------- -----------------------------------------------
  296. ***************************************************************************/
  297. BOOL SendRTC(PThrdGlbl pTG, BOOL fFinal)
  298. {
  299. BYTE bBuf[13];
  300. USHORT uEnc, uLen;
  301. DEBUG_FUNCTION_NAME(_T("SendRTC"));
  302. uEnc = pTG->ProtInst.SendParams.Fax.Encoding;
  303. if(uEnc == MR_DATA)
  304. {
  305. DebugPrintEx(DEBUG_MSG,"Send MR RTC");
  306. // MR RTC is EOL+1 6 times. Data produced by Faxcodec end in a
  307. // byte-aligned EOL i.e. 0x80. So I need to put out (1 + EOL)
  308. // 6 times. Simplest is to send out (0x01 0x80) 6 times
  309. // bBuf[0] = 0x01; bBuf[1] = 0x80; bBuf[2] = 0x01; bBuf[3] = 0x80;
  310. // bBuf[4] = 0x01; bBuf[5] = 0x80; bBuf[6] = 0x01; bBuf[7] = 0x80;
  311. // bBuf[8] = 0x01; bBuf[9] = 0x80; bBuf[10]= 0x01; bBuf[11]= 0x80;
  312. // bBuf[12] = 0; // for debugging printouts
  313. // uLen = 12;
  314. // But Ricoh claims this is incorrect, so we need to send a compact
  315. // RTC, i.e. exactly 11 0s for each EOL. 1 + (eol+1)x5 is
  316. // 01 30 00 06 C0 00 18 00 03
  317. bBuf[0] = 0x01; bBuf[1] = 0x30; bBuf[2] = 0x00; bBuf[3] = 0x06;
  318. bBuf[4] = 0xC0; bBuf[5] = 0x00; bBuf[6] = 0x18; bBuf[7] = 0x00;
  319. bBuf[8] = 0x03; bBuf[9] = 0x00;
  320. uLen = 9;
  321. }
  322. else
  323. {
  324. DebugPrintEx(DEBUG_MSG,"Send MH RTC");
  325. // bBuf[0] = 0x00; bBuf[1] = 0x20; bBuf[2] = 0x00;
  326. // bBuf[3] = 0x02; bBuf[4] = 0x20; bBuf[5] = 0x00;
  327. // bBuf[6] = 0x02; bBuf[7] = 0x20; bBuf[8] = 0x00;
  328. // bBuf[9] = 0x02; bBuf[10] = 0; // for debugging printouts
  329. // uLen = 10;
  330. // But Ricoh claims this is incorrect, so we need to send a compact
  331. // RTC, i.e. exactly 11 0s for each EOL. (eol)x5 is
  332. // 00 08 80 00 08 80 00 08
  333. bBuf[0] = 0x00; bBuf[1] = 0x08; bBuf[2] = 0x80; bBuf[3] = 0x00;
  334. bBuf[4] = 0x08; bBuf[5] = 0x80; bBuf[6] = 0x00; bBuf[7] = 0x08;
  335. bBuf[8] = 0x00;
  336. uLen = 8;
  337. }
  338. PSSLogEntryHex(PSS_MSG, 2, bBuf, uLen, "send: RTC, %d bytes,", uLen);
  339. // no need to stuff
  340. return ModemSendMem(pTG, bBuf, uLen, (USHORT)(fFinal ? SEND_FINAL : 0));
  341. }
  342. /***************************************************************************
  343. Name : GetTCF()
  344. Purpose : Receive a TCF signal, analyse it, recognize "good" or "bad"
  345. Parameters: none
  346. Returns :
  347. 0..MAX_ERRS_PER_1000 - Good TCF (retval is number of non-zero bytes)
  348. -MAX_ERRS_PER_1000 .. -1000 - Bad TCF (retval is negative of number of non-zero bytes)
  349. -1000 - TCF too long or too short
  350. -1112 - Missed the TCF (AT+FRM failed)
  351. Comment : The CCITT does not tell us what consitutes a good training,
  352. so I'm playing blind here. If we are too stringent we'll fail
  353. to ever sync. If we are too liberal, we'll end up with a high
  354. error rate when we could have dropped baud rate & got a
  355. perfectly good signal.
  356. Emperically I observe bits of contigous trash at the
  357. beginning and end of the training even on a perfectly good
  358. line. (OK, I now know this is known as the turn-on and
  359. turn-off sequence. So what we have now is
  360. <turnon trash><1111s><0000s (training)><1111s><turnoff trash>
  361. The turnon/turnoff trash & the marks (1111s) should not
  362. interfere with recognizing a perfectly good training signal.
  363. The trash is isolated from the 00s by FFs
  364. Algo: Wait for the first good burst of zeros, then count
  365. zeros, and randomly interspersed non-zero (these represent
  366. real noise errors). Stop counting when we get a burst of FFs.
  367. Now make sure teh zero burst is long enough & the "real"
  368. error rate is not too high.
  369. Lots of parameters here:-
  370. flP_ERROR == keep Prob(error) below this. Between 0 and 1
  371. uwZEROmin == how many zeros before we start counting
  372. uwTURNOFFmin == how much consecutive trash before we
  373. ignore rest
  374. Tune these parameters after real testing with real lines!!!
  375. (maybe a phone line simulator with a lil white noise -- Yeah!!)
  376. At the end of this function, (nZeros/nTotal) is an estimate
  377. of the probability that a byte gets thru OK. Call this PB.
  378. Then prob. that a line of average 30-40 bytes gets through
  379. is PB^30. If we drop the expected number of OK lines as low
  380. as 80% this still means that PB must be no lower than
  381. the 30th root of 0.8, which is 0.9925. Therefore
  382. flP_ERROR must be less than 0.75%
  383. At PL=90%, PB rises to 0.9965 and flP_ERROR to 0.0035
  384. Revision Log
  385. Num Date Name Description
  386. --- -------- ---------- -----------------------------------------------
  387. ***************************************************************************/
  388. // We read the TCF in units of One-Tenth of nominal TCF length
  389. // We discard the first 2 chunks (20%), examine the next 4 chunks (40%)
  390. // discard the rest. If the length is between 6 & 13 chunks (60% to 130%)
  391. // and the error rates in chunk 2 & 3 is below the threshold we declare
  392. // it OK. This (a) accepts too-short TCFs (some Class2 modems), and
  393. // too long ones. (b) ignores leading and trailing trash (c) Can afford
  394. // to be pretty strict with the core of the TCF
  395. USHORT OneTenthTCFLen[16] =
  396. {
  397. /* V27_2400 0 */ 45,
  398. /* V29_9600 1 */ 180,
  399. /* V27_4800 2 */ 90,
  400. /* V29_7200 3 */ 135,
  401. /* V33_14400 4 */ 270,
  402. 0,
  403. /* V33_12000 6 */ 225,
  404. 0,
  405. /* V17_14400 8 */ 270,
  406. /* V17_9600 9 */ 180,
  407. /* V17_12000 10 */ 225,
  408. /* V17_7200 11 */ 135,
  409. 0,
  410. 0,
  411. 0,
  412. 0
  413. };
  414. #define RECV_TCFBUFSIZE 270 // must be >= max chunk in above table
  415. #define MIN_TCFLEN 4 // measured in 10ths of the nominal length
  416. #define MAX_TCFLEN 13 // measured in 10ths of the nominal length
  417. #define CHECKTCF_START 2 // lowest 10th to measure (20% and up)
  418. #define CHECKTCF_STOP 5 // highest 10th to measure (upto 59%)
  419. #define MAX_ERRS_PER_1000 20 // Increased from 1% to 2%. Be more lax
  420. #define RECVBUF_SLACK 3 // Class1 driver fills only > 3, and leaves 3 empty spaces
  421. SWORD GetTCF(PThrdGlbl pTG)
  422. {
  423. USHORT uCurMod, uChunkSize, uLength, uMeasuredLength, uErrCount;
  424. USHORT uPhase, uNumRead, uEOF=0, i;
  425. BYTE bRecvTCF[RECV_TCFBUFSIZE + RECVBUF_SLACK];
  426. SWORD swRet;
  427. DEBUG_FUNCTION_NAME(_T("GetTCF"));
  428. uCurMod = pTG->T30.uRecvTCFMod;
  429. // *Don't* add ST_FLAG since we need long training for TCF
  430. pTG->T30.sRecvBufSize = 0;
  431. if(ModemRecvMode(pTG, uCurMod, TCF_TIMEOUT, TRUE) != RECV_OK)
  432. {
  433. swRet= -1112;
  434. goto missedit;
  435. }
  436. pTG->CommCache.fReuse = 1;
  437. DebugPrintEx(DEBUG_MSG,"Receiving TCF: Mod=%d", uCurMod);
  438. // make it large, in case of large buffers & slow modems
  439. #define READ_TIMEOUT 10000
  440. uChunkSize = OneTenthTCFLen[uCurMod];
  441. uErrCount = 0;
  442. uLength = 0;
  443. uMeasuredLength = 0;
  444. for(uPhase=0; uPhase<=MAX_TCFLEN; uPhase++)
  445. {
  446. // read a whole chunk
  447. for(uNumRead=0; uNumRead<uChunkSize; )
  448. {
  449. USHORT uTemp = 0;
  450. uEOF = ModemRecvMem(pTG, bRecvTCF+uNumRead, (USHORT) (uChunkSize-uNumRead+RECVBUF_SLACK), READ_TIMEOUT, &uTemp);
  451. uNumRead+=uTemp;
  452. if(uEOF==RECV_EOF)
  453. {
  454. break;
  455. }
  456. else if(uEOF != RECV_OK)
  457. {
  458. swRet = -1113;
  459. goto missedit;
  460. }
  461. }
  462. // ignore phases 0, 1, and 6 and above
  463. if(uPhase>=CHECKTCF_START && uPhase<=CHECKTCF_STOP)
  464. {
  465. for(i=0; i< uNumRead; i++)
  466. {
  467. if(bRecvTCF[i])
  468. {
  469. uErrCount++;
  470. }
  471. uMeasuredLength++;
  472. }
  473. }
  474. uLength += uNumRead;
  475. if(uEOF==RECV_EOF)
  476. break;
  477. }
  478. PSSLogEntry(PSS_MSG, 2, "recv: TCF: %d errors in %d signifact bytes of %d total bytes",
  479. uErrCount, uMeasuredLength, uLength);
  480. // Official length must be at least 1.5s -10% = 1.35secs
  481. // We allow much more latitude because length variation
  482. // cannot be caused by line noise, only be bugs at the sender
  483. //
  484. // E.g. Fury DNE 1086 (German modem) sends a TCF that's too short
  485. // (sends 600 bytes at 4800 and 200 at 2400). This is less than
  486. // half of what we expect.
  487. // TCF with few errs (i.e. uErrCount==0) and is greater
  488. // that half of the min length we expect (i.e. longer
  489. // than 375 for 4800 and 172 for 2400) then accept it
  490. // (allow if uErr<=2 (arbitary small number))
  491. if(uPhase<MIN_TCFLEN || uPhase>MAX_TCFLEN) // length<40% or >139%
  492. {
  493. DebugPrintEx( DEBUG_ERR,
  494. "BAD TCF length (%d), expected=%d, Min=%d Max=%d uPhase=%d",
  495. uLength,
  496. uChunkSize*10,
  497. uChunkSize*MIN_TCFLEN,
  498. uChunkSize*MAX_TCFLEN,
  499. uPhase);
  500. swRet = -1000; // too short or long
  501. }
  502. else
  503. {
  504. // Calc errors per 1000 = (uErrCount * 1000)/uMeasuredLength
  505. swRet = (SWORD)((((DWORD)uErrCount) * 1000L) / ((DWORD)uMeasuredLength));
  506. if(swRet > MAX_ERRS_PER_1000)
  507. {
  508. swRet = (-swRet);
  509. DebugPrintEx( DEBUG_ERR,
  510. "TOO MANY TCF ERRORS: swRet=%d uErrCount=%d uMeasured=%d"
  511. " uLength=%d uPhase=%d",
  512. swRet,
  513. uErrCount,
  514. uMeasuredLength,
  515. uLength,
  516. uPhase);
  517. }
  518. }
  519. DebugPrintEx(DEBUG_MSG,"returning %d", swRet);
  520. return swRet;
  521. missedit:
  522. DebugPrintEx(DEBUG_MSG,"MISSED IT!! returning %d", swRet);
  523. return swRet;
  524. }
  525. /***************************************************************************
  526. Name : DEBUG.C
  527. Comment : Factored out debug code
  528. Functions : (see Prototypes just below)
  529. Revision Log
  530. Num Date Name Description
  531. --- -------- ---------- -----------------------------------------------
  532. ***************************************************************************/
  533. #ifdef DEBUG
  534. #define PRINTFRAMEBUFSIZE 256
  535. void D_PrintFrame(LPB lpb, UWORD cb)
  536. {
  537. UWORD uw, j;
  538. IFR ifr;
  539. BYTE b2[PRINTFRAMEBUFSIZE];
  540. DEBUG_FUNCTION_NAME(_T("D_PrintFrame"));
  541. for(ifr=1; ifr<ifrMAX; ifr++)
  542. {
  543. if(rgFrameInfo[ifr].bFCF1 ==(BYTE)(rgFrameInfo[ifr].fInsertDISBit ?
  544. (lpb[2] & 0xFE) : lpb[2]))
  545. break;
  546. }
  547. if(ifr == ifrMAX) ifr = 0;
  548. j = (UWORD)wsprintf((LPSTR)b2, "(%s) 0x%02x (", (LPSTR)(rgFrameInfo[ifr].szName), lpb[2]);
  549. for(uw=0; uw<cb;)
  550. {
  551. j += (UWORD)wsprintf((LPSTR)b2+j, "%02x ", (UWORD)lpb[uw++]);
  552. }
  553. j += (UWORD)wsprintf((LPSTR)b2+j, ")");
  554. DebugPrintEx(DEBUG_MSG,"%s", (LPSTR)b2);
  555. }
  556. #endif
  557. USHORT ModemRecvBuf(PThrdGlbl pTG, LPBUFFER far* lplpbf, ULONG ulTimeout)
  558. {
  559. USHORT uRet;
  560. DEBUG_FUNCTION_NAME(_T("ModemRecvBuf"));
  561. if(!(*lplpbf = MyAllocBuf(pTG, pTG->T30.sRecvBufSize)))
  562. return RECV_ERROR;
  563. DebugPrintEx( DEBUG_MSG,
  564. "In ModemRecvBuf allocated %d bytes",
  565. pTG->T30.sRecvBufSize);
  566. uRet = ModemRecvMem(pTG, (*lplpbf)->lpbBegBuf,
  567. (*lplpbf)->wLengthBuf, ulTimeout, &((*lplpbf)->wLengthData));
  568. if(!((*lplpbf)->wLengthData))
  569. {
  570. DebugPrintEx( DEBUG_MSG,
  571. "Got 0 bytes from ModemRecvMem--freeing Buf 0x%08lx",
  572. *lplpbf);
  573. MyFreeBuf(pTG, *lplpbf);
  574. *lplpbf = NULL;
  575. // moved this error case handling out, since it's different for
  576. // ECM and non-ECM cases. In both cases want to ignore rather than
  577. // abort, so RECV_ERROR is not an appropriate return value
  578. // if(uRet==RECV_OK) uRet=RECV_ERROR; // just in case. see bug#1492
  579. }
  580. if(*lplpbf)
  581. {
  582. DebugPrintEx( DEBUG_MSG,
  583. "Ex lpbf=%08lx uSize=%d uCount=%d uRet=%d",
  584. *lplpbf,
  585. (*lplpbf)->wLengthBuf,
  586. (*lplpbf)->wLengthData,
  587. uRet);
  588. }
  589. else
  590. {
  591. DebugPrintEx(DEBUG_MSG,"Ex lpbf=null uRet=%d", uRet);
  592. }
  593. return uRet;
  594. }
  595. void RestartDump(PThrdGlbl pTG)
  596. {
  597. DEBUG_FUNCTION_NAME(_T("RestartDump"));
  598. DebugPrintEx( DEBUG_MSG,
  599. "Restart Dump old=%d off=%d",
  600. pTG->fsDump.uNumFrames,
  601. pTG->fsDump.uFreeSpaceOff);
  602. pTG->fsDump.uNumFrames = 0;
  603. pTG->fsDump.uFreeSpaceOff = 0;
  604. }
  605. void DumpFrame(PThrdGlbl pTG, BOOL fSend, IFR ifr, USHORT cbFIF, LPBYTE lpbFIF)
  606. {
  607. LPFR lpfr;
  608. DEBUG_FUNCTION_NAME(_T("DumpFrame"));
  609. if( pTG->fsDump.uNumFrames >= MAXDUMPFRAMES ||
  610. pTG->fsDump.uFreeSpaceOff+cbFIF+sizeof(FRBASE) >= MAXDUMPSPACE)
  611. {
  612. DebugPrintEx( DEBUG_WRN,
  613. "Out of dump space num=%d size=%d",
  614. pTG->fsDump.uNumFrames,
  615. pTG->fsDump.uFreeSpaceOff);
  616. return;
  617. }
  618. lpfr = (LPFR) (((LPBYTE)(pTG->fsDump.b)) + pTG->fsDump.uFreeSpaceOff);
  619. lpfr->ifr = ifr;
  620. if(fSend) lpfr->ifr |= 0x80;
  621. lpfr->cb = (BYTE) cbFIF;
  622. if(cbFIF)
  623. {
  624. _fmemcpy(lpfr->fif, lpbFIF, cbFIF);
  625. }
  626. pTG->fsDump.uFrameOff[pTG->fsDump.uNumFrames++] =
  627. (USHORT)((((LPBYTE)(lpfr)) - ((LPBYTE)(pTG->fsDump.b))));
  628. pTG->fsDump.uFreeSpaceOff += (cbFIF + sizeof(FRBASE));
  629. }
  630. void PrintDump(PThrdGlbl pTG)
  631. {
  632. int i, j;
  633. char szBuf[1000] = {0};
  634. DEBUG_FUNCTION_NAME(_T("PrintDump"));
  635. DebugPrintEx(DEBUG_MSG,"-*-*-*-*-*-*-*-* Print Protocol Dump -*-*-*-*-*-*-*-*-");
  636. for(i=0; i<(int)pTG->fsDump.uNumFrames; i++)
  637. {
  638. LPFR lpfr = (LPFR) (((LPBYTE)(pTG->fsDump.b)) + pTG->fsDump.uFrameOff[i]);
  639. IFR ifr = (lpfr->ifr & 0x7F);
  640. BOOL fSend = (lpfr->ifr & 0x80);
  641. DebugPrintEx( DEBUG_MSG,
  642. "%s: %s",
  643. (LPSTR)(fSend ? "Sent" : "Recvd"),
  644. (LPSTR)(ifr ? rgFrameInfo[ifr].szName : "???") );
  645. for(j=0; j<min(lpfr->cb,1000); j++)
  646. _stprintf(szBuf,"%02x ", (WORD)lpfr->fif[j]);
  647. DebugPrintEx(DEBUG_MSG, "(%s)",szBuf);
  648. }
  649. DebugPrintEx(DEBUG_MSG,"-*-*-*-*-*-*-*-* End Protocol Dump -*-*-*-*-*-*-*-*-");
  650. }