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.

535 lines
18 KiB

  1. /***************************************************************************
  2. Name : FRAMING.C
  3. Comment :
  4. Functions: (see Prototypes just below)
  5. Copyright (c) Microsoft Corp. 1991 1992 1993
  6. Revision Log
  7. Date Name Description
  8. -------- ----- ---------------------------------------------------------
  9. ***************************************************************************/
  10. #include "prep.h"
  11. #include "encoder.h"
  12. #include "decoder.h"
  13. #include "class1.h"
  14. #include "debug.h"
  15. #include "glbproto.h"
  16. #define faxTlog(m) DEBUGMSG(ZONE_SWFRAME, m)
  17. #define faxT2log(m) DEBUGMSG(ZONE_SWFRAME2, m)
  18. #define FILEID FILEID_FRAMING
  19. #ifdef DEBUG
  20. # define ST_SWFRAME2(x) if(ZONE_SWFRAME2) { x; }
  21. #else
  22. # define ST_SWFRAME2(x) { }
  23. #endif
  24. BOOL FramingBufSetup(PThrdGlbl pTG, BOOL fOn);
  25. BOOL SWFramingSendSetup(PThrdGlbl pTG, BOOL fOn)
  26. {
  27. // If fOn=TRUE, Check that Recv framing is not ON.
  28. // Can't use Recv and Send framing simultaneously
  29. BG_CHK(!(fOn && pTG->Class1Modem.fRecvSWFraming));
  30. if(fOn)
  31. {
  32. BG_CHK(!pTG->Class1Modem.fSendSWFraming);
  33. }
  34. else if(!pTG->Class1Modem.fSendSWFraming)
  35. {
  36. TRACE((SZMOD "<<WARNING>> SWFramingSendSetup(FALSE) called when not inited. Ignoring\r\n"));
  37. return TRUE;
  38. }
  39. if(!FramingBufSetup(pTG, fOn))
  40. return FALSE;
  41. pTG->Class1Modem.fSendSWFraming = fOn;
  42. InitEncoder(pTG, pTG->Framing.EncodeState);
  43. return TRUE;
  44. }
  45. BOOL SWFramingRecvSetup(PThrdGlbl pTG, BOOL fOn)
  46. {
  47. // if fOn=TRUE Check that Send framing is not ON.
  48. // Can't use Recv and Send framing simultaneously
  49. BG_CHK(!(fOn && pTG->Class1Modem.fSendSWFraming));
  50. if(fOn)
  51. {
  52. BG_CHK(!pTG->Class1Modem.fRecvSWFraming);
  53. }
  54. else if(!pTG->Class1Modem.fRecvSWFraming)
  55. {
  56. TRACE((SZMOD "<<WARNING>> SWFramingRecvSetup(FALSE) called when not inited. Ignoring\r\n"));
  57. return TRUE;
  58. }
  59. if(!FramingBufSetup(pTG, fOn))
  60. return FALSE;
  61. pTG->Class1Modem.fRecvSWFraming = fOn;
  62. InitDecoder(pTG, pTG->Framing.DecodeState);
  63. return TRUE;
  64. }
  65. BOOL FramingBufSetup(PThrdGlbl pTG, BOOL fOn)
  66. {
  67. // UWORD uwJunk;
  68. if(fOn)
  69. {
  70. #ifdef SMM
  71. pTG->Framing.lpbBuf = pTG->bStaticFramingBuf;
  72. pTG->Framing.cbBufSize = FRAMEBUFINITIALSIZE;
  73. #else
  74. #error NYI ERROR: Code Not Complete--Have to pick GMEM_ flags (FIXED? SHARE?)
  75. ...also have to call IFProcSetResFlags(hinstMe).....
  76. BG_CHK(pTG->Framing.lpbBuf==0);
  77. if(!(pTG->Framing.lpbBuf = IFMemAlloc(0, FRAMEBUFINITIALSIZE, &uwJunk)))
  78. {
  79. ERRMSG((SZMOD "<<ERROR>> Out of global memory!!));
  80. // iModemSetError(MODEMERR_RESOURCES, ERR_OUT_OF_MEMORY, 0);
  81. return FALSE;
  82. }
  83. pTG->Framing.cbBufSize = uwJunk;
  84. #endif
  85. }
  86. else
  87. {
  88. BG_CHK(fOn == FALSE);
  89. #ifndef SMM
  90. BG_CHK(pTG->Framing.lpbBuf);
  91. IFMemFree(pTG->Framing.lpbBuf);
  92. #endif
  93. pTG->Framing.lpbBuf = 0;
  94. pTG->Framing.cbBufSize = 0;
  95. }
  96. pTG->Framing.cbBufCount = 0;
  97. pTG->Framing.lpbBufSrc = pTG->Framing.lpbBuf;
  98. pTG->Framing.swEOF = 0;
  99. return TRUE;
  100. }
  101. BOOL SWFramingSendFrame(PThrdGlbl pTG, LPBYTE lpb, USHORT uCount, USHORT uFlags)
  102. {
  103. WORD wCRC;
  104. USHORT cbDst;
  105. (MyDebugPrint(pTG, LOG_ALL, "iSW: lpb=%08lx c=%d f=%02x ", lpb, uCount, uFlags, lpb[0]));
  106. // always DLE-stuff here. Never zero-stuff
  107. BG_CHK(uFlags & SEND_ENDFRAME);
  108. BG_CHK(lpb && uCount);
  109. BG_CHK(uCount <= 260); // can add stuff to realloc the Dst buffer
  110. // to a bigger one as needed here
  111. wCRC = CalcCRC(pTG, lpb, uCount);
  112. faxT2log((SZMOD "CRC=%04x ", wCRC));
  113. cbDst = HDLC_Encode(pTG, lpb, uCount, pTG->Framing.lpbBuf, &pTG->Framing.EncodeState);
  114. faxT2log((SZMOD "D1=%d ", cbDst));
  115. cbDst += HDLC_Encode(pTG, (LPB)(&wCRC), 2, pTG->Framing.lpbBuf+cbDst, &pTG->Framing.EncodeState);
  116. faxT2log((SZMOD "D2=%d\r\n", cbDst));
  117. BG_CHK(cbDst + pTG->ModemParams.InterframeFlags <= pTG->Framing.cbBufSize);
  118. cbDst += HDLC_AddFlags(pTG, pTG->Framing.lpbBuf+cbDst, pTG->ModemParams.InterframeFlags, &pTG->Framing.EncodeState);
  119. faxT2log((SZMOD "D3=%d f=%02x l=%02x\r\n", cbDst, pTG->Framing.lpbBuf[0], pTG->Framing.lpbBuf[cbDst-1]));
  120. // always DLE-stuff here. Never zero-stuff
  121. if(!FComFilterAsyncWrite(pTG, pTG->Framing.lpbBuf, cbDst, FILTER_DLEONLY))
  122. {
  123. ERRMSG((SZMOD "<<ERROR>> DataWrite Timeout\r\n"));
  124. goto error;
  125. }
  126. if(uFlags & SEND_FINAL)
  127. {
  128. if(!SWFramingSendPostamble(pTG, pTG->Class1Modem.CurMod))
  129. goto error;
  130. #ifdef CL0
  131. if(pTG->ModemParams.Class == FAXCLASS0)
  132. {
  133. if(!FComDirectAsyncWrite(pTG, bDLEETXOK, 8))
  134. goto error;
  135. }
  136. else
  137. #endif //CL0
  138. {
  139. // if(!FComDirectAsyncWrite(bDLEETXCR, 3))
  140. if(!FComDirectAsyncWrite(pTG, bDLEETX, 2))
  141. goto error;
  142. }
  143. if(!iModemDrain(pTG))
  144. goto error;
  145. SWFramingSendSetup(pTG, FALSE);
  146. FComOutFilterClose(pTG);
  147. FComOverlappedIO(pTG, FALSE);
  148. FComXon(pTG, FALSE); // critical. End of PhaseC
  149. EndMode(pTG);
  150. }
  151. return TRUE;
  152. error:
  153. SWFramingSendSetup(pTG, FALSE);
  154. FComOutFilterClose(pTG);
  155. FComOverlappedIO(pTG, FALSE);
  156. FComXon(pTG, FALSE); // critical. End of PhaseC (err)
  157. EndMode(pTG);
  158. return FALSE;
  159. }
  160. BOOL SWFramingSendFlags(PThrdGlbl pTG, USHORT uHowMany)
  161. {
  162. int cb, i; // must be signed
  163. (MyDebugPrint(pTG, LOG_ALL, "SENDING ECM Flags (%d).....\r\n", uHowMany));
  164. for(i=0, cb = uHowMany; cb>0; i++, cb -= pTG->Framing.cbBufSize)
  165. {
  166. if(i<=1)
  167. HDLC_AddFlags(pTG, pTG->Framing.lpbBuf, pTG->Framing.cbBufSize, &pTG->Framing.EncodeState);
  168. // always DLE-stuff here. Never zero-stuff
  169. if(!FComFilterAsyncWrite(pTG, pTG->Framing.lpbBuf,(USHORT) min((USHORT)pTG->Framing.cbBufSize, (USHORT)cb), FILTER_DLEONLY))
  170. {
  171. ERRMSG((SZMOD "<<ERROR>> PreFlagDataWrite Timeout\r\n"));
  172. return FALSE;
  173. }
  174. }
  175. return TRUE;
  176. }
  177. USHORT SWFramingRecvFrame(PThrdGlbl pTG, LPBYTE lpb, USHORT cbMax, ULONG ulTimeout, USHORT far* lpcbRecv)
  178. {
  179. USHORT cbDst, cbProduce, cbConsume, uRet;
  180. LPB lpbDst;
  181. (MyDebugPrint(pTG, LOG_ALL, "iSW: Buf=%08lx Src=%08lx cbSrc=%d cbMax=%d\r\n", pTG->Framing.lpbBuf, pTG->Framing.lpbBufSrc, pTG->Framing.cbBufCount, cbMax));
  182. /**/
  183. BG_CHK(pTG->Class1Modem.ModemMode == FRM);
  184. BG_CHK(pTG->Class1Modem.fRecvSWFraming);
  185. startTimeOut(pTG, &(pTG->Class1Modem.toRecv), ulTimeout);
  186. /**/
  187. BG_CHK(lpb && cbMax && lpcbRecv);
  188. *lpcbRecv = 0;
  189. for(lpbDst=lpb, cbDst=cbMax ;; )
  190. {
  191. if(pTG->Framing.cbBufCount == 0)
  192. {
  193. if(pTG->Framing.swEOF == 0)
  194. {
  195. pTG->Framing.lpbBufSrc = pTG->Framing.lpbBuf;
  196. // 4th arg must be FALSE for Class1
  197. pTG->Framing.cbBufCount = FComFilterReadBuf(pTG, pTG->Framing.lpbBufSrc, pTG->Framing.cbBufSize, &(pTG->Class1Modem.toRecv), FALSE, &pTG->Framing.swEOF);
  198. faxT2log((SZMOD "f=%02x l=%02x\r\n", pTG->Framing.lpbBufSrc[0], pTG->Framing.lpbBufSrc[pTG->Framing.cbBufCount-1]));
  199. if(pTG->Framing.swEOF == -1)
  200. {
  201. #ifdef CL0
  202. if(pTG->ModemParams.Class == FAXCLASS0)
  203. {
  204. TRACE((SZMOD "Got Class0 DLE-ETX\r\n"));
  205. pTG->Framing.swEOF = 1;
  206. }
  207. else
  208. #endif //CL0
  209. {
  210. // See LONG comment under DDI.C ModemRecvData()
  211. // option (a)
  212. // ERRMSG((SZMOD "<<WARNING>> Got arbitrary DLE-ETX. Assuming END OF PAGE!!!\r\n"));
  213. // pTG->Framing.swEOF = 1;
  214. // option (b)
  215. ERRMSG((SZMOD "<<WARNING>> Got arbitrary DLE-ETX. Ignoring\r\n"));
  216. pTG->Framing.swEOF = 0;
  217. }
  218. }
  219. BG_CHK(pTG->Framing.swEOF == 0 || pTG->Framing.swEOF == 1 ||
  220. pTG->Framing.swEOF == -2 || pTG->Framing.swEOF == -3);
  221. // check for progress
  222. BG_CHK(pTG->Framing.cbBufCount!=0 || pTG->Framing.swEOF!=0);
  223. }
  224. else
  225. {
  226. // pTG->Framing.swEOF != 0
  227. BG_CHK(pTG->Framing.swEOF == 1 || pTG->Framing.swEOF == -2 || pTG->Framing.swEOF == -3);
  228. if(cbDst != cbMax)
  229. {
  230. ERRMSG((SZMOD "<<WARNING>> SWFramingRecv: Got EOF with partial frame %d bytes\r\n", cbMax-cbDst));
  231. ST_SWFRAME2(D_HexPrint(lpb, (USHORT)(cbMax-cbDst)));
  232. uRet = RECV_BADFRAME;
  233. goto done;
  234. }
  235. if(pTG->Framing.swEOF == 1) // class1 eof
  236. {
  237. SWFramingRecvSetup(pTG, FALSE);
  238. EndMode(pTG);
  239. uRet = RECV_EOF;
  240. goto done;
  241. }
  242. else if(pTG->Framing.swEOF < 0) // error or timeout
  243. {
  244. SWFramingRecvSetup(pTG, FALSE);
  245. EndMode(pTG);
  246. uRet = ((pTG->Framing.swEOF == -2) ? RECV_ERROR : RECV_TIMEOUT);
  247. goto done;
  248. }
  249. }
  250. }
  251. // cbDst=space left in destination lpbDst=start of space
  252. // pTG->Framing.cbBufCount=bytes left in source pTG->Framing.lpbBufSrc=start of bytes
  253. cbConsume = HDLC_Decode(pTG, pTG->Framing.lpbBufSrc,(USHORT) min(pTG->Framing.cbBufCount, cbDst), lpbDst, &cbProduce, &pTG->Framing.DecodeState);
  254. BG_CHK(cbConsume <= pTG->Framing.cbBufCount && pTG->Framing.lpbBufSrc+cbConsume<=pTG->Framing.lpbBuf+pTG->Framing.cbBufSize);
  255. BG_CHK(cbProduce <= cbDst && lpbDst+cbProduce <= lpb+cbMax);
  256. faxT2log((SZMOD "iSW: C=%d P=%d fa=%d\r\n", cbConsume, cbProduce, pTG->Framing.DecodeState.flagabort));
  257. pTG->Framing.cbBufCount -= cbConsume;
  258. pTG->Framing.lpbBufSrc += cbConsume;
  259. cbDst -= cbProduce;
  260. lpbDst += cbProduce;
  261. // check for progress.
  262. BG_CHK(pTG->Framing.DecodeState.flagabort==FLAG || // exits below
  263. cbProduce || cbConsume || // exits eventually
  264. pTG->Framing.cbBufCount==0); // exits or continues above
  265. if(pTG->Framing.DecodeState.flagabort == FLAG)
  266. {
  267. if((cbMax-cbDst)>=2 && (CalcCRC(pTG, lpb, (USHORT)(cbMax-cbDst)) == ((WORD)(~0xF0B8))) )
  268. {
  269. cbDst += 2;
  270. if(cbMax <= cbDst)
  271. {
  272. ERRMSG(("GOOD Frame BAD Length!! cbMax=%d cbDst=%d, lpb[0]=%02x lpb[1]=%02x, CRC=%04x\r\n",
  273. cbMax, cbDst, lpb[0], lpb[1], CalcCRC(pTG, lpb, (USHORT)(cbMax+2-cbDst))));
  274. BG_CHK(FALSE); // can't get good frame of 0 length!
  275. // must return RECV_BADFRAME here otherwise we break.
  276. // In HDLC.C the (RECV_OK swRead==0) pair gets converted
  277. // to RECV_ERROR and we quit receiving. On some modems
  278. // this can happen often. See BUG#1684
  279. uRet = RECV_BADFRAME;
  280. }
  281. else
  282. uRet = RECV_OK;
  283. }
  284. else
  285. {
  286. BG_CHK(cbMax >= cbDst);
  287. #ifdef DEBUG
  288. if (cbMax-cbDst)
  289. {
  290. ERRMSG((SZMOD "<<WARNING>> BADFR: SWFrRecvFr: CbMax-cbDst = %d bytes\r\n", cbMax-cbDst));
  291. }
  292. #endif
  293. ST_SWFRAME2(D_HexPrint(lpb, (USHORT)(cbMax-cbDst)));
  294. uRet = RECV_BADFRAME;
  295. }
  296. goto done;
  297. }
  298. else if(pTG->Framing.DecodeState.flagabort == ABORT)
  299. {
  300. lpbDst=lpb; cbDst=cbMax;
  301. }
  302. else if(cbDst == 0)
  303. {
  304. // bad frames can be very long
  305. ERRMSG((SZMOD "<<WARNING>> SWFramingRecv: Overflow. Got %d chars -- no flag\r\n", cbMax));
  306. uRet = RECV_BADFRAME;
  307. goto done;
  308. }
  309. }
  310. done:
  311. *lpcbRecv = cbMax-cbDst;
  312. (MyDebugPrint(pTG, LOG_ALL, "xSW: uR=%d *lpcbR=%d\r\n", uRet, *lpcbRecv));
  313. return uRet;
  314. }
  315. /*********************
  316. ECM Preamble and PostAmble: In T.4 appendix A it says
  317. that the Preamble must be 200ms +/1 100ms of flags,
  318. and the postamble must be 50ms max.
  319. However we also have recving modems that don't know they
  320. are getting ECM and need the 6eols to tell them when to
  321. stop recving. Also some of them lose large chunks of data
  322. at the end of PhaseC due to "carrier squelch", i.e. whne
  323. they lose carrier, they throw away the contents of their
  324. recv buffer.
  325. To get 240ms of flags, just multiply CurMod by 3
  326. // #define SWFramingSendPreamble(b) \
  327. // (FComDirectAsyncWrite(b00EOL, 2), SWFramingSendFlags(b + b + b))
  328. Postamble must have *max* 50ms of flags, so let's say 30ms, which is
  329. 9 flags at 2400 and 54 at 14400. Just multiply CurMod by (3/8)
  330. to get correct number of flags
  331. // #define SWFramingSendPostamble(b) SWFramingSendFlags((b+b+b) >> 3)
  332. but with carrier squelch and all that, so few may not be safe.
  333. Murata sends out 44 flags at 2400 baud on closing. So lets
  334. just send out 80ms (just CurMod flags)
  335. This is the 80ms postamble
  336. // #define SWFramingSendPostamble(b) SWFramingSendFlags(b)
  337. // Fix for DSI bug -- drops last 500 bytes or so ////
  338. // #define SWFramingSendPostamble(b) SWFramingSendFlags(600)
  339. *********************/
  340. BYTE b00EOL[3] = { 0x00, 0x80, 0 };
  341. BYTE b6EOLs[10] = { 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00 };
  342. BOOL SWFramingSendPreamble(PThrdGlbl pTG, USHORT uCurMod)
  343. {
  344. BOOL fRet = TRUE;
  345. #ifdef CL0
  346. if(pTG->ModemParams.Class != FAXCLASS0)
  347. #endif //CL0
  348. {
  349. // fix bug#1762. DataRace modem misses leading EOL unless
  350. // preceded by some zeros, and it then chews up all data
  351. // until an EOL, thereby eating up part of the first frame
  352. SendZeros1(pTG, 100);
  353. fRet = fRet && FComDirectAsyncWrite(pTG, b00EOL, 2);
  354. }
  355. fRet = fRet && SWFramingSendFlags(pTG, (USHORT)(uCurMod + uCurMod + uCurMod));
  356. return fRet;
  357. }
  358. BOOL SWFramingSendPostamble(PThrdGlbl pTG, USHORT uCurMod)
  359. {
  360. BYTE bZero[50];
  361. USHORT i;
  362. BOOL fRet = TRUE;
  363. // send 80ms of flags
  364. fRet &= SWFramingSendFlags(pTG, uCurMod);
  365. #ifdef CL0
  366. if(pTG->ModemParams.Class != FAXCLASS0)
  367. #endif //CL0
  368. {
  369. // then send 6EOLs
  370. fRet &= FComDirectAsyncWrite(pTG, b6EOLs, 9);
  371. // then send 250 or so 00s
  372. _fmemset(bZero, 0, 50);
  373. for (i=0; i<5; i++)
  374. fRet &= FComDirectAsyncWrite(pTG, bZero, 50);
  375. }
  376. return fRet;
  377. }