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.

948 lines
30 KiB

  1. /***************************************************************************
  2. Name : DIS.C
  3. Comment : Collection if DIS/DCS/DTC and CSI/TSI/CIG mangling routines.
  4. They manipulate the DIS struct whose members correspond to the bits
  5. of the T30 DIS/DCS/DTC frames.
  6. Copyright (c) 1993 Microsoft Corp.
  7. Revision Log
  8. Date Name Description
  9. -------- ----- ---------------------------------------------------------
  10. ***************************************************************************/
  11. #include "prep.h"
  12. #include "protocol.h"
  13. ///RSL
  14. #include "glbproto.h"
  15. #define faxTlog(m) DEBUGMSG(ZONE_DIS, m)
  16. #define FILEID FILEID_DIS
  17. #ifdef DEBUG
  18. # define ST_DIS(x) if(ZONE_DIS) { x; }
  19. #else
  20. # define ST_DIS(x) { }
  21. #endif
  22. ///////// switched from RES-->AWRES values. Table no longer valid /////////
  23. //
  24. // #define fsim_ILLEGAL 255
  25. // // converts from RES_ #defines to
  26. // // DIS bits. Some values have no conversions
  27. // BYTE F24S_fsim[16] =
  28. // {
  29. // /* Converts RES_FINE, RES_200, RES_400, RES_SUPER_SUPER to
  30. // * ResFine_200, Res16x15_400, ResInchBased, ResMetricBased
  31. // */
  32. // /* F24S fsim */
  33. // /* 0000 --> 0000 */ 0,
  34. // /* 0001 --> 0101 */ 5,
  35. // /* 0010 --> 0110 */ 6,
  36. // /* 0011 --> 0111 */ 7,
  37. // /* 0100 --> 1010 */ 10,
  38. // /* 0101 --> XXXX */ fsim_ILLEGAL,
  39. // /* 0110 --> 1110 */ 14,
  40. // /* 0111 --> XXXX */ fsim_ILLEGAL,
  41. // /* 1000 --> 1001 */ 8, /*9,*/ // vanilla Fine mode. No need for metric bit
  42. // /* 1001 --> 1101 */ 13,
  43. // /* 1010 --> XXXX */ fsim_ILLEGAL,
  44. // /* 1011 --> XXXX */ fsim_ILLEGAL,
  45. // /* 1100 --> 1011 */ 11,
  46. // /* 1101 --> XXXX */ fsim_ILLEGAL,
  47. // /* 1110 --> XXXX */ fsim_ILLEGAL,
  48. // /* 1111 --> 1111 */ 15
  49. // };
  50. //
  51. ///////////////////////////////////////////////////////////////////////
  52. USHORT SetupDISorDCSorDTC(PThrdGlbl pTG, NPDIS npdis, NPBCFAX npbcFax, NPLLPARAMS npll, BOOL fECM, BOOL f64)
  53. {
  54. // return length of DIS
  55. USHORT uLen;
  56. (MyDebugPrint(pTG, LOG_ALL, "In SetOurDIS: baud=0x%02x min=0x%02x res=0x%02x code=0x%02x wide=0x%02x len=0x%02x\r\n",
  57. npll->Baud, npll->MinScan, (WORD)npbcFax->AwRes, npbcFax->Encoding, npbcFax->PageWidth, npbcFax->PageLength));
  58. BG_CHK(npdis);
  59. BG_CHK((npll->MinScan & ~MINSCAN_MASK) == 0);
  60. BG_CHK((npbcFax->AwRes & ~AWRES_ALLT30) == 0);
  61. BG_CHK((npbcFax->Encoding & ~(MH_DATA|MR_DATA|MMR_DATA)) == 0);
  62. BG_CHK((npbcFax->PageWidth & ~WIDTH_MASK) == 0);
  63. BG_CHK((npbcFax->PageLength & ~LENGTH_MASK) == 0);
  64. BG_CHK(npbcFax->fPublicPoll==0 || npbcFax->fPublicPoll==1);
  65. BG_CHK(fECM==0 || fECM==1);
  66. BG_CHK(f64==0 || f64==1);
  67. BG_CHK(!(fECM==0 && f64!=0));
  68. _fmemset(npdis, 0, sizeof(DIS));
  69. // npdis->G1stuff = 0;
  70. // npdis->G2stuff = 0;
  71. npdis->G3Rx = 1; // always ON for DIS & DCS. Indicates T.4 recv Cap/Mode
  72. npdis->G3Tx = (BYTE) (npbcFax->fPublicPoll);
  73. // This must be 0 for a DCS frame. The Omnifax G77 and GT choke on it!
  74. npdis->Baud = npll->Baud;
  75. npdis->MR_2D = ((npbcFax->Encoding & MR_DATA) != 0);
  76. npdis->MMR = ((npbcFax->Encoding & MMR_DATA) != 0);
  77. // npdis->MR_2D = 0;
  78. // npdis->MMR = 0;
  79. npdis->PageWidth = (BYTE) (npbcFax->PageWidth);
  80. npdis->PageLength = (BYTE) (npbcFax->PageLength);
  81. npdis->MinScanCode = npll->MinScan;
  82. // npdis->Uncompressed = npdis->ELM = 0;
  83. npdis->ECM = fECM != FALSE;
  84. npdis->SmallFrame = f64 != FALSE;
  85. if(npbcFax->PageWidth > WIDTH_MAX)
  86. {
  87. npdis->WidthInvalid = TRUE;
  88. npdis->Width2 = (npbcFax->PageWidth>>WIDTH_SHIFT);
  89. }
  90. // doesn't hold for SendParams (why??)
  91. // BG_CHK(npbcFax->AwRes & AWRES_mm080_038);
  92. npdis->Res_300 = 0; // RSL ((npbcFax->AwRes & AWRES_300_300) != 0);
  93. npdis->Res8x15 = ((npbcFax->AwRes & AWRES_mm080_154) != 0);
  94. if (! pTG->SrcHiRes) {
  95. npdis->ResFine_200 = 0;
  96. }
  97. else {
  98. npdis->ResFine_200 = ((npbcFax->AwRes & (AWRES_mm080_077|AWRES_200_200)) != 0);
  99. }
  100. npdis->Res16x15_400 = ((npbcFax->AwRes & (AWRES_mm160_154|AWRES_400_400)) != 0);
  101. npdis->ResInchBased = ((npbcFax->AwRes & (AWRES_200_200|AWRES_400_400)) != 0);
  102. npdis->ResMetricBased = ((npbcFax->AwRes & AWRES_mm160_154) ||
  103. ((npbcFax->AwRes & AWRES_mm080_077) && npdis->ResInchBased));
  104. /**** switched RES-->AWRES. Table no longer valid *******
  105. fsim = F24S_fsim[npbcFax->AwRes & 0x0F];
  106. BG_CHK(fsim != fsim_ILLEGAL);
  107. npdis->ResFine_200 = ((fsim & 0x08) != 0); // f
  108. npdis->Res16x15_400 = ((fsim & 0x04) != 0); // s
  109. npdis->ResInchBased = ((fsim & 0x02) != 0); // i
  110. npdis->ResMetricBased = ((fsim & 0x01) != 0); // m
  111. **** switched RES-->AWRES. Table no longer valid *******/
  112. npdis->MinScanSuperHalf = ((npll->MinScan & MINSCAN_SUPER_HALF) != 0);
  113. if(!fECM) goto done; // can't have file transfer stuff w/o ECM
  114. /***
  115. BG_CHK(npll->fNonEfaxBFT==0 || npll->fNonEfaxBFT==1);
  116. BG_CHK(npll->fNonEfaxSUB==0 || npll->fNonEfaxSUB==1);
  117. BG_CHK(npll->fNonEfaxSEP==0 || npll->fNonEfaxSEP==1);
  118. BG_CHK(npll->fNonEfaxPWD==0 || npll->fNonEfaxPWD==1);
  119. npdis->SEPcap = npll->fNonEfaxSEP;
  120. npdis->SUBcap = npll->fNonEfaxSUB;
  121. npdis->PWDcap = npll->fNonEfaxPWD;
  122. npdis->BFTcap = npdis->CanEmitDataFile = npll->fNonEfaxBFT;
  123. npdis->DTMcap = npll->fNonEfaxDTM;
  124. npdis->EDIcap = npll->fNonEfaxEDI;
  125. npdis->CanEmitCharFile = npdis->CharMode = npll->fNonEfaxCharMode;
  126. ***/
  127. done:
  128. // npdis->Extend24 = npdis->Extend32 = npdis->Extend40 = 0;
  129. // npdis->Extend48 = npdis->Extend56 = npdis->Extend64 = 0;
  130. // npdis->Reserved1 = npdis->Reserved2 = npdis->Reserved3 = 0;
  131. // npdis->Reserved4 = npdis->Reserved5 = 0;
  132. npdis->Extend24 = npdis->Extend32 = npdis->Extend40 = 0;
  133. uLen = 3;
  134. #if 0
  135. for(p = ((NPSTR)npdis)+sizeof(DIS)-1; p>(NPSTR)npdis+2 && *p==0; p--)
  136. // (MyDebugPrint(pTG, LOG_ALL, "t SetOurDIS: Loop p=0x%08lx\r\n", (LPSTR)p))
  137. ;
  138. // p points to last non-zero or to npdis+2 (i.e. 3rd byte)
  139. for(q = ((NPSTR)npdis)+2; q<p; (*q) |= 0x80, q++)
  140. // (MyDebugPrint(pTG, LOG_ALL, "t SetOurDIS: Loop p=0x%08lx q=0x%08lx\r\n", (LPSTR)p, (LPSTR)q));
  141. ;
  142. // turn high (extend) bit on for all bytes from 3rd (i.e. p+2
  143. // until the last but one non-zero byte
  144. // ST_DIS(D_HexPrint((LPSTR)npdis, 8));
  145. // CHANGE: NEC reports that NTTFAX T31 cannot accept the extra trailing 0
  146. // so we should stop sending it!!!
  147. // // return one more byte in DIS len so that we'll always one extra 0 byte
  148. // // at the end of each DIS/DCS/DTC. Most fax machines do this, so there must
  149. // // be some compatibility reason for this
  150. // // uLen = ((p+1-(NPSTR)npdis) + 1); // size of DIS to send
  151. uLen = (p+1-(NPSTR)npdis); // size of DIS to send
  152. if(uLen > sizeof(DIS))
  153. uLen = sizeof(DIS); // no extra byte if we have reached end of DIS!
  154. #endif
  155. (MyDebugPrint(pTG, LOG_ALL, "DIS len = %d\r\n", uLen));
  156. return uLen;
  157. }
  158. ///////// switched from RES-->AWRES values. Table no longer valid /////////
  159. //
  160. // #define F24S_ILLEGAL 255
  161. // // converts from DIS bits to RES_ #defines
  162. // Some values have no conversions
  163. // BYTE fsim_F24S[16] =
  164. // {
  165. // /* Converts ResFine_200, Res16x15_400, ResInchBased, ResMetricBased to
  166. // * AWRES_mm080_077, AWRES_200_200, AWRES_400_400, AWRES_mm160_154
  167. // */
  168. // /* fsim F24S */
  169. // /* 0000 --> 0000 */ 0,
  170. // /* 0001 --> XXXX */ F24S_ILLEGAL,
  171. // /* 0010 --> XXXX */ F24S_ILLEGAL,
  172. // /* 0011 --> XXXX */ F24S_ILLEGAL,
  173. // /* 0100 --> XXXX */ 1, /*F24S_ILLEGAL,*/ // try and make sense of it anyway
  174. // /* 0101 --> 0001 */ 1,
  175. // /* 0110 --> 0010 */ 2,
  176. // /* 0111 --> 0011 */ 3,
  177. // /* 1000 --> 1000 */ 8,
  178. // /* 1001 --> 1000 */ 8,
  179. // /* 1010 --> 0100 */ 4,
  180. // /* 1011 --> 1100 */ 12,
  181. // /* 1100 --> XXXX */ 9, /*F24S_ILLEGAL,*/ // assume metric preferred
  182. // /* 1101 --> 1001 */ 9,
  183. // /* 1110 --> 0110 */ 6,
  184. // /* 1111 --> 1111 */ 15
  185. // };
  186. //
  187. ///////// switched from RES-->AWRES values. Table no longer valid /////////
  188. void ParseDISorDCSorDTC(PThrdGlbl pTG, NPDIS npDIS, NPBCFAX npbcFax, NPLLPARAMS npll, BOOL fParams)
  189. {
  190. ///////////////////////////////////////////////////////////////
  191. // Prepare to get trash (upto 2 bytes) at end of every frame //
  192. ///////////////////////////////////////////////////////////////
  193. // BYTE fsim, F24S;
  194. NPBYTE npb, npbLim;
  195. // first make sure DIS is clean. We may have picked up some trailing CRCs
  196. // trailing-trash removed by reading the Extend bits
  197. npb = npbLim = (NPBYTE)npDIS;
  198. npbLim += sizeof(DIS);
  199. for(npb+=2; npb<npbLim && (*npb & 0x80); npb++)
  200. ;
  201. // exits when npb points past end of structure or
  202. // points to the first byte with the high bit NOT set
  203. // i.e. the last VALID byte
  204. for(npb++; npb<npbLim; npb++)
  205. *npb = 0;
  206. // starting with the byte AFTER the last valid byte, until end
  207. // of the structure, zap all bytes to zero
  208. // parse high level params into NPI
  209. memset(npbcFax, 0, sizeof(BCFAX));
  210. npbcFax->AwRes = 0;
  211. npbcFax->Encoding = 0;
  212. // Resolution
  213. if(npDIS->Res8x15) npbcFax->AwRes |= AWRES_mm080_154;
  214. if(npDIS->Res_300) npbcFax->AwRes |= AWRES_300_300;
  215. if(npDIS->ResInchBased)
  216. {
  217. if(npDIS->ResFine_200) npbcFax->AwRes |= AWRES_200_200;
  218. if(npDIS->Res16x15_400) npbcFax->AwRes |= AWRES_400_400;
  219. }
  220. if(npDIS->ResMetricBased || !npDIS->ResInchBased)
  221. {
  222. if(npDIS->ResFine_200) npbcFax->AwRes |= AWRES_mm080_077;
  223. if(npDIS->Res16x15_400) npbcFax->AwRes |= AWRES_mm160_154;
  224. }
  225. /***** switched from RES-->AWRES values. Table no longer valid *****
  226. fsim = 0;
  227. if(npDIS->ResFine_200) fsim |= 0x08; // f
  228. if(npDIS->Res16x15_400) fsim |= 0x04; // s
  229. if(npDIS->ResInchBased) fsim |= 0x02; // i
  230. if(npDIS->ResMetricBased) fsim |= 0x01; // m
  231. F24S = fsim_F24S[fsim];
  232. if(F24S != F24S_ILLEGAL)
  233. {
  234. npbcFax->AwRes |= F24S;
  235. }
  236. else
  237. {
  238. // BG_CHK(FALSE);
  239. // must be prepared to receive any garbage
  240. }
  241. ***** switched from RES-->AWRES values. Table no longer valid *****/
  242. // Encoding (MMR only if ECM also supported)
  243. if(npDIS->MR_2D) npbcFax->Encoding |= MR_DATA;
  244. if(npDIS->MMR && npDIS->ECM) npbcFax->Encoding |= MMR_DATA;
  245. if(!fParams)
  246. {
  247. // setting up capabilities -- add the "always present" caps
  248. npbcFax->AwRes |= AWRES_mm080_038;
  249. npbcFax->Encoding |= MH_DATA;
  250. }
  251. else
  252. {
  253. // setting up params -- set the defaults if none otehr specified
  254. if(!npbcFax->AwRes) npbcFax->AwRes = AWRES_mm080_038;
  255. if(!npbcFax->Encoding) npbcFax->Encoding = MH_DATA;
  256. // if both MR & MMR are set (this happens with Ricoh's fax simulator!)
  257. // then set just MMR. MH doesnt have an explicit bit, so we set MH
  258. // here only if nothing else is set. So the only multiple-setting case
  259. // (for encodings) that we can encounter is (MR|MMR). BUG#6950
  260. if(npbcFax->Encoding == (MR_DATA|MMR_DATA))
  261. npbcFax->Encoding = MMR_DATA;
  262. }
  263. // PageWidth and Length
  264. npbcFax->PageWidth = npDIS->PageWidth;
  265. // IFAX Bug#8152: Hack for interpreting invalid value (1,1) as
  266. // A3, because some fax machines do that. This is
  267. // as per Note 7 of Table 2/T.30 of ITU-T.30 (1992, page 40).
  268. #define WIDTH_ILLEGAL_A3 0x3
  269. if (!fParams && npbcFax->PageWidth==WIDTH_ILLEGAL_A3)
  270. {
  271. npbcFax->PageWidth=WIDTH_A3;
  272. }
  273. npbcFax->PageLength = npDIS->PageLength;
  274. // has G3 file available for polling
  275. npbcFax->fPublicPoll = npDIS->G3Tx;
  276. // This must be 0 for DCS frames! However if it's not let it pass anyway
  277. BG_CHK(fParams ? (npDIS->G3Tx==0) : TRUE);
  278. /**** Can't deal with narrow widths yet. Just pretend they're 1728 ****
  279. if(npDIS->PageWidthInvalid)
  280. npbcFax->PageWidth = (npdis->PageWidth2 << WIDTH_SHIFT);
  281. ***********************************************************************/
  282. // Now low level params LLPARAMS
  283. // Baudrate, ECM, ECM frame size, and MinScan. That's it!
  284. npll->Baud = npDIS->Baud;
  285. npll->fECM = npDIS->ECM;
  286. npll->fECM64 = npDIS->SmallFrame;
  287. npll->MinScan = npDIS->MinScanCode;
  288. if(npDIS->MinScanSuperHalf)
  289. npll->MinScan |= MINSCAN_SUPER_HALF;
  290. if(!npll->fECM) goto done; // can't have file transfer stuff w/o ECM
  291. /***
  292. npll->fNonEfaxSUB = npdis->SUBcap;
  293. npll->fNonEfaxSEP = npdis->SEPcap;
  294. npll->fNonEfaxPWD = npdis->PWDcap;
  295. npll->fNonEfaxBFT = npdis->BFTcap;
  296. npll->fNonEfaxDTM = npdis->DTMcap;
  297. npll->fNonEfaxEDI = npdis->EDIcap;
  298. npll->fNonEfaxCharMode = npdis->CharMode;
  299. ***/
  300. done:
  301. (MyDebugPrint(pTG, LOG_ALL, "Ex ParseDIS_DCS: baud=0x%02x min=0x%02x res=0x%02x code=0x%02x wide=0x%02x len=0x%02x\r\n",
  302. npll->Baud, npll->MinScan, (WORD)npbcFax->AwRes, npbcFax->Encoding, npbcFax->PageWidth, npbcFax->PageLength));
  303. ;
  304. }
  305. /* Converts the code for a speed to the speed in BPS */
  306. UWORD CodeToBPS[16] =
  307. {
  308. /* V27_2400 0 */ 2400,
  309. /* V29_9600 1 */ 9600,
  310. /* V27_4800 2 */ 4800,
  311. /* V29_7200 3 */ 7200,
  312. /* V33_14400 4 */ 14400,
  313. 0,
  314. /* V33_12000 6 */ 12000,
  315. 0,
  316. /* V17_14400 8 */ 14400,
  317. /* V17_9600 9 */ 9600,
  318. /* V17_12000 10 */ 12000,
  319. /* V17_7200 11 */ 7200,
  320. 0,
  321. 0,
  322. 0,
  323. 0
  324. };
  325. #define msBAD 255
  326. /* Converts a DCS min-scan field code into millisecs */
  327. BYTE msPerLine[8] = { 20, 5, 10, msBAD, 40, msBAD, msBAD, 0 };
  328. USHORT MinScanToBytesPerLine(PThrdGlbl pTG, BYTE MinScan, BYTE Baud)
  329. {
  330. USHORT uStuff;
  331. BYTE ms;
  332. uStuff = CodeToBPS[Baud];
  333. BG_CHK(uStuff);
  334. ms = msPerLine[MinScan];
  335. BG_CHK(ms != msBAD);
  336. uStuff /= 100; // StuffBytes = (BPS * ms)/8000
  337. uStuff *= ms; // take care not to use longs
  338. uStuff /= 80; // or overflow WORD or lose precision
  339. uStuff += 1; // Rough fix for truncation problems
  340. return uStuff;
  341. }
  342. #define ms40 4
  343. #define ms20 0
  344. #define ms10 2
  345. #define ms5 1
  346. #define ms0 7
  347. /* first index is a DIS min-scan capability. 2nd is 0 for normal
  348. * 1 for fine (1/2) and 2 for super-fine (if 1/2 yet again).
  349. * Output is the Code to stick in the DCS.
  350. */
  351. BYTE MinScanTab[8][3] =
  352. {
  353. ms20, ms20, ms10,
  354. ms5, ms5, ms5,
  355. ms10, ms10, ms5,
  356. ms20, ms10, ms5,
  357. ms40, ms40, ms20,
  358. ms40, ms20, ms10,
  359. ms10, ms5, ms5,
  360. ms0, ms0, ms0
  361. };
  362. #define V_ILLEGAL 255
  363. #define V27_2400 0
  364. #define V27_4800 2
  365. #define V29_9600 1
  366. #define V29_7200 3
  367. #define V33_14400 4
  368. #define V33_12000 6
  369. #define V17_14400 8
  370. #define V17_12000 10
  371. #define V17_9600 9
  372. #define V17_7200 11
  373. #define V27_SLOW 0
  374. #define V27_ONLY 2
  375. #define V29_ONLY 1
  376. #define V33_ONLY 4
  377. #define V17_ONLY 8
  378. #define V27_V29 3
  379. #define V27_V29_V33 7
  380. #define V27_V29_V33_V17 11
  381. #define V_ALL 15
  382. /* Converts a capability into the best speed it offers.
  383. * index will usually be the & of both DIS's Baud rate fields
  384. * (both having first been "adjusted", i.e. 11 changed to 15)
  385. * Output is the Code to stick in the DCS.
  386. */
  387. BYTE BaudNegTab[16] =
  388. {
  389. /* V27_SLOW 0 --> 0 */ V27_2400,
  390. /* V29_ONLY 1 --> 1 */ V29_9600,
  391. /* V27_ONLY 2 --> 2 */ V27_4800,
  392. /* V27_V29 3 --> 1 */ V29_9600,
  393. V_ILLEGAL,
  394. V_ILLEGAL,
  395. V_ILLEGAL,
  396. /* V27_V29_V33 7 --> 4 */ V33_14400,
  397. V_ILLEGAL,
  398. V_ILLEGAL,
  399. V_ILLEGAL,
  400. /* V27_V29_V33_V17 11 --> 8 */ V17_14400,
  401. V_ILLEGAL,
  402. V_ILLEGAL,
  403. V_ILLEGAL,
  404. /* V_ALL 15 --> 8 */ V17_14400
  405. };
  406. /***************************************************************************
  407. Name : NegotiateLowLevelParams
  408. Purpose : Takes a received DIS and optionally MS NSF,
  409. our HW caps and
  410. picks highest common baud rate, ECM is picked if both have it
  411. ECM frame size is 256 unless remote DIS has that bit set to 1
  412. or we want small frames (compiled-in option).
  413. The MinScan time is set to the max.
  414. (i.e. highest/slowest) of both.
  415. Fill results in Negot section of npProt
  416. CalledFrom: NegotiateLowLevelParams is called by the sender when a DIS
  417. and/or NSF is received.
  418. ***************************************************************************/
  419. void NegotiateLowLevelParams(PThrdGlbl pTG, NPLLPARAMS npllRecv, NPLLPARAMS npllSend,
  420. DWORD AwRes, USHORT uEnc, NPLLPARAMS npllNegot)
  421. {
  422. USHORT Baud, Baud1, Baud2;
  423. USHORT MinScanCode, col;
  424. ////// negotiate Baudrate, ECM, ECM frame size, and MinScan. That's it!
  425. Baud1 = npllRecv->Baud;
  426. Baud2 = npllSend->Baud;
  427. if(Baud1 == 11) Baud1=15;
  428. if(Baud2 == 11) Baud2=15;
  429. Baud = Baud1 & Baud2;
  430. npllNegot->Baud = BaudNegTab[Baud];
  431. BG_CHK(npllNegot->Baud != V_ILLEGAL);
  432. // there is always some common baud rate (i.e. at least 2400 mandatory)
  433. // ECM. On if both have it. Frame size is small if either
  434. // party want it so. (though using this bit in the DIS is
  435. // contrary to the T.30 spec). But we will come to no harm
  436. // treating it so
  437. if((uEnc==MH_DATA || uEnc==MR_DATA) && (pTG->ProtParams.EnableG3SendECM==0))
  438. {
  439. npllNegot->fECM = 0;
  440. npllNegot->fECM64 = 0;
  441. }
  442. else
  443. {
  444. // gotta be TRUE otherwise we've negotiated
  445. // ourselves into a hole here....
  446. BG_CHK(npllRecv->fECM && npllSend->fECM);
  447. npllNegot->fECM = 0; // RSL BUGBUG (npllRecv->fECM && npllSend->fECM);
  448. // 64 bytes if receiver request it & we support it
  449. // npllNegot->fECM64 = (npllRecv->fECM64 && npllSend->fECM64);
  450. // Exercise sender's prerogative--64 bytes if we have that selected
  451. // npllNegot->fECM64 = npllSend->fECM64;
  452. // Use if either want it (i.e. sender selected it or receiver prefers it)
  453. npllNegot->fECM64 = 0; // RSL BUGBUG (npllRecv->fECM64 || npllSend->fECM64);
  454. }
  455. /* Minimum Scan line times. Only Receiver's pref matters.
  456. * Use teh table above to convert from Receiver's DIS to the
  457. * required DCS. Col 1 is used if vertical res. is normal (100dpi)
  458. * Col2 if VR is 200 or 300dpi, (OR if VR is 400dpi, but Bit 46
  459. * is not set), and Col3 is used if VR is 400dpi *and* Bit 46
  460. * (MinScanSuperHalf) is set
  461. */
  462. if(npllNegot->fECM)
  463. {
  464. npllNegot->MinScan = ms0;
  465. }
  466. else
  467. {
  468. MinScanCode = (npllRecv->MinScan & 0x07); // low 3 bits
  469. if(AwRes & (AWRES_mm080_154|AWRES_mm160_154|AWRES_400_400))
  470. {
  471. if(npllRecv->MinScan & MINSCAN_SUPER_HALF)
  472. col = 2;
  473. else
  474. col = 1;
  475. }
  476. // T30 says scan time for 300dpi & 200dpi is the same
  477. else if(AwRes & (AWRES_300_300|AWRES_mm080_077|AWRES_200_200))
  478. col = 1;
  479. else
  480. col = 0;
  481. npllNegot->MinScan = MinScanTab[MinScanCode][col];
  482. }
  483. (MyDebugPrint(pTG, LOG_ALL, "In NegotiateLL: baud=0x%02x min=0x%02x ECM=%d small=%d\r\n",
  484. npllNegot->Baud, npllNegot->MinScan, npllNegot->fECM, npllNegot->fECM64));
  485. }
  486. USHORT GetStupidReversedFIFs(PThrdGlbl pTG, LPSTR lpstr1, LPSTR lpstr2)
  487. {
  488. /** Both args always 20 bytes long. Throws away leading & trailing
  489. blanks, then copies what's left *reversed* into lpstr[].
  490. Terminates with 0.
  491. **/
  492. int i, j, k;
  493. BG_CHK(lpstr2 && lpstr1);
  494. // (MyDebugPrint(pTG, LOG_ALL, "In GetReverseFIF: lpstr1=0x%08lx lpstr2=0x%08lx lpstr2=%20s\r\n",
  495. // (LPSTR)lpstr1, lpstr2, lpstr2));
  496. for(k=0; k<IDFIFSIZE && lpstr2[k]==' '; k++) // k==first nonblank or 20
  497. ;
  498. for(j=IDFIFSIZE-1; j>=k && lpstr2[j]==' '; j--) // j==last nonblank or -1
  499. ;
  500. // RSL 10/30/96 Leave FIF alone: just remove leading/trailing blanks and reverse bytes.
  501. #if 0
  502. // added to convert single leading space to +. See bug#771 & comments
  503. // under CreateIdFrame routine. Since lpstr2 is reversed, leading==
  504. // trailing
  505. if(j == IDFIFSIZE-2) // single leading blank only
  506. {
  507. lpstr1[0] = '+';
  508. i = 1;
  509. }
  510. else
  511. i = 0;
  512. #else
  513. i = 0;
  514. #endif
  515. for( ; i<IDFIFSIZE && j>=k; i++, j--)
  516. lpstr1[i] = lpstr2[j];
  517. lpstr1[i] = 0;
  518. (MyDebugPrint(pTG, LOG_ALL, "GetFIF: Got<%s> produced<%s>\r\n", (LPSTR)lpstr2, (LPSTR)lpstr1));
  519. // (MyDebugPrint(pTG, LOG_ALL, "Ex GetReverseFIF: lpstr1=0x%08lx lpstr2=0x%08lx lpstr1=%20s lpstr2=%20s\r\n",
  520. // (LPSTR)lpstr1, lpstr2, (LPSTR)lpstr1, lpstr2));
  521. return (USHORT)i;
  522. }
  523. void CreateStupidReversedFIFs(PThrdGlbl pTG, LPSTR lpstr1, LPSTR lpstr2)
  524. {
  525. /** Both args always 20 bytes long. Copies LPSTR *reversed* into
  526. the end of lpstr1[], then pads rest with blank.
  527. Terminates with a 0
  528. **/
  529. int i, j;
  530. BG_CHK(lpstr2 && lpstr1);
  531. // (MyDebugPrint(pTG, LOG_ALL, "In CreateReverseFIF: lpstr1=0x%08lx lpstr2=0x%08lx lpstr2=%20s\r\n",
  532. // lpstr1, lpstr2, lpstr2));
  533. for(i=0, j=IDFIFSIZE-1; lpstr2[i] && j>=0; i++, j--)
  534. lpstr1[j] = lpstr2[i];
  535. if(j>=0)
  536. _fmemset(lpstr1, ' ', j+1);
  537. lpstr1[IDFIFSIZE] = 0;
  538. // (MyDebugPrint(pTG, LOG_ALL, "Ex CreateReverseFIF: lpstr1=0x%08lx lpstr2=0x%08lx lpstr1=%20s lpstr2=%20s\r\n",
  539. // lpstr1, lpstr2, lpstr1, lpstr2));
  540. }
  541. /* Converts a the code for a speed to the code fro the next
  542. * best (lower) speed. order is
  543. (V17: 144-120-96-72-V27_2400) (V33: 144 120 V29: 96 72 V27: 48 24)
  544. */
  545. // NOTE: FRANCE defines the fallback sequence to go from V17_7200 to V27_4800
  546. BYTE DropBaudTab[16] =
  547. {
  548. /* V27_2400 --> X 0 --> X */ V_ILLEGAL,
  549. /* V29_9600 --> V29_7200 1 --> 3 */ V29_7200,
  550. /* V27_4800 --> V27_2400 2 --> 0 */ V27_2400,
  551. /* V29_7200 --> V27_4800 3 --> 2 */ V27_4800,
  552. /* V33_14400 -> V33_12000 4 --> 6 */ V33_12000,
  553. V_ILLEGAL,
  554. /* V33_12000 -> V29_9600 6 --> 1 */ V29_9600,
  555. V_ILLEGAL,
  556. /* V17_14400 -> V17_12000 8 -> 10 */ V17_12000,
  557. /* V17_9600 --> V17_7200 9 -> 11 */ V17_7200,
  558. /* V17_12000 -> V17_9600 10 -> 9 */ V17_9600,
  559. /* V17_7200 --> V29_9600 11 -> 1
  560. or V29_7200 11 -> 3
  561. USE THIS---> or V27_4800 11 -> 2
  562. or V27_2400 11 -> 0 */ V27_4800,
  563. V_ILLEGAL,
  564. V_ILLEGAL,
  565. V_ILLEGAL,
  566. V_ILLEGAL
  567. };
  568. BOOL DropSendSpeed(PThrdGlbl pTG)
  569. {
  570. USHORT uSpeed;
  571. BG_CHK(pTG->ProtInst.fllNegotiated);
  572. // enforce LowestSendSpeed
  573. if( ((uSpeed=DropBaudTab[pTG->ProtInst.llNegot.Baud]) == V_ILLEGAL) ||
  574. ((pTG->ProtInst.LowestSendSpeed <= 14400) &&
  575. (CodeToBPS[uSpeed] < pTG->ProtInst.LowestSendSpeed)) )
  576. {
  577. BG_CHK(pTG->ProtInst.llNegot.Baud==V27_2400 ||
  578. CodeToBPS[pTG->ProtInst.llNegot.Baud]==pTG->ProtInst.LowestSendSpeed);
  579. (MyDebugPrint(pTG, LOG_ALL, "DropSpeed--Can't drop (0x%02x)\r\n", pTG->ProtInst.llNegot.Baud));
  580. return FALSE;
  581. // speed remains same as before if lowest speed
  582. // return FALSE to hangup
  583. }
  584. else
  585. {
  586. (MyDebugPrint(pTG, LOG_ALL, "DropSpeed--Now at 0x%02x\r\n", uSpeed));
  587. pTG->ProtInst.llNegot.Baud = (BYTE) uSpeed;
  588. return TRUE;
  589. }
  590. }
  591. void EnforceMaxSpeed(PThrdGlbl pTG)
  592. {
  593. // enforce HighestSendSpeed setting
  594. BG_CHK(!pTG->ProtInst.HighestSendSpeed || (pTG->ProtInst.HighestSendSpeed>=2400 &&
  595. pTG->ProtInst.HighestSendSpeed >= pTG->ProtInst.LowestSendSpeed));
  596. if( pTG->ProtInst.HighestSendSpeed && pTG->ProtInst.HighestSendSpeed >= 2400 &&
  597. pTG->ProtInst.HighestSendSpeed >= pTG->ProtInst.LowestSendSpeed)
  598. {
  599. (MyDebugPrint(pTG, LOG_ALL, "MaxSend=%d. Baud=%x BPS=%d, dropping\r\n",
  600. pTG->ProtInst.HighestSendSpeed, pTG->ProtInst.llNegot.Baud, CodeToBPS[pTG->ProtInst.llNegot.Baud]));
  601. while(CodeToBPS[pTG->ProtInst.llNegot.Baud] > pTG->ProtInst.HighestSendSpeed)
  602. {
  603. if(!DropSendSpeed(pTG))
  604. {
  605. BG_CHK(FALSE);
  606. break;
  607. }
  608. }
  609. (MyDebugPrint(pTG, LOG_ALL, "Done---MaxSend=%d. Baud=%x BPS=%d\r\n",
  610. pTG->ProtInst.HighestSendSpeed, pTG->ProtInst.llNegot.Baud, CodeToBPS[pTG->ProtInst.llNegot.Baud]));
  611. }
  612. }
  613. USHORT CopyFrame(PThrdGlbl pTG, LPBYTE lpbDst, LPFR lpfr, USHORT uSize)
  614. {
  615. ///////////////////////////////////////////////////////////////
  616. // Prepare to get trash (upto 2 bytes) at end of every frame //
  617. ///////////////////////////////////////////////////////////////
  618. USHORT uDstLen;
  619. uDstLen = min(uSize, lpfr->cb);
  620. _fmemset(lpbDst, 0, uSize);
  621. _fmemcpy(lpbDst, lpfr->fif, uDstLen);
  622. return uDstLen;
  623. }
  624. void CopyRevIDFrame(PThrdGlbl pTG, LPBYTE lpbDst, LPFR lpfr)
  625. {
  626. ///////////////////////////////////////////////////////////////
  627. // Prepare to get trash (upto 2 bytes) at end of every frame //
  628. ///////////////////////////////////////////////////////////////
  629. USHORT uDstLen;
  630. char szTemp[IDFIFSIZE+2];
  631. uDstLen = min(IDFIFSIZE, lpfr->cb);
  632. _fmemset(szTemp, ' ', IDFIFSIZE); // fill spaces (reqd by GetReverse)
  633. _fmemcpy(szTemp, lpfr->fif, uDstLen);
  634. szTemp[IDFIFSIZE] = 0; // zero-terminate
  635. GetStupidReversedFIFs(pTG, lpbDst, szTemp);
  636. if(uDstLen!=IDFIFSIZE)
  637. MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Bad ID frame\r\n" );
  638. }