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.

285 lines
6.9 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module convert.c | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Scott Holden (sholden)
  12. *
  13. * Date: 10/4/1996 (created)
  14. *
  15. * Contents: Conversion routine from an ndis packet to an ir packet.
  16. *
  17. *
  18. *****************************************************************************/
  19. #include "irsir.h"
  20. extern const USHORT fcsTable[];
  21. ULONG __inline EscapeSlowIrData(PUCHAR Dest, UCHAR SourceByte)
  22. {
  23. switch (SourceByte){
  24. case SLOW_IR_BOF:
  25. case SLOW_IR_EOF:
  26. case SLOW_IR_ESC:
  27. Dest[0] = SLOW_IR_ESC;
  28. Dest[1] = SourceByte ^ SLOW_IR_ESC_COMP;
  29. return 2;
  30. default:
  31. Dest[0] = SourceByte;
  32. return 1;
  33. }
  34. }
  35. /*****************************************************************************
  36. *
  37. * Function: NdisToIrPacket
  38. *
  39. * Synopsis: convert an NDIS packet to an IR packet
  40. *
  41. * Write the IR packet into the provided buffer and report
  42. * its actual size.
  43. *
  44. * Arguments: pThisDev
  45. * pPacket
  46. * irPacketBuf
  47. * irPacketBufLen
  48. * irPacketLen
  49. *
  50. * Returns: TRUE - on success
  51. * FALSE - on failure
  52. *
  53. * Algorithm:
  54. *
  55. * History: dd-mm-yyyy Author Comment
  56. * 10/4/1996 sholden author
  57. *
  58. * Notes:
  59. *
  60. * If failing, *irPacketLen will contain the buffer size that
  61. * the caller should retry with (or 0 if a corruption was detected).
  62. *
  63. *****************************************************************************/
  64. BOOLEAN
  65. NdisToIrPacket(
  66. PIR_DEVICE pThisDev,
  67. PNDIS_PACKET pPacket,
  68. UCHAR *irPacketBuf,
  69. UINT irPacketBufLen,
  70. UINT *irPacketLen
  71. )
  72. {
  73. UINT i;
  74. UINT ndisPacketBytes;
  75. UINT I_fieldBytes;
  76. UINT totalBytes;
  77. UINT ndisPacketLen;
  78. UINT numExtraBOFs;
  79. UINT bufLen;
  80. SLOW_IR_FCS_TYPE fcs;
  81. SLOW_IR_FCS_TYPE tmpfcs;
  82. UCHAR *bufData;
  83. UCHAR nextChar;
  84. PNDIS_BUFFER ndisBuf;
  85. PNDIS_IRDA_PACKET_INFO packetInfo;
  86. DEBUGMSG(DBG_FUNC, ("+NdisToIrPacket\n"));
  87. //
  88. // Initialize locals.
  89. //
  90. ndisPacketBytes = 0;
  91. I_fieldBytes = 0;
  92. totalBytes = 0;
  93. packetInfo = GetPacketInfo(pPacket);
  94. //
  95. // Get the packet's entire length and its first NDIS buffer.
  96. //
  97. NdisQueryPacket(pPacket, NULL, NULL, &ndisBuf, &ndisPacketLen);
  98. //
  99. // Make sure that the packet is big enough to be legal.
  100. // It consists of an A, C, and variable-length I field.
  101. //
  102. if (ndisPacketLen < SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE)
  103. {
  104. DEBUGMSG(DBG_ERR, (" Packet too short in NdisToIrPacket (%d bytes)\n",
  105. ndisPacketLen));
  106. return FALSE;
  107. }
  108. else
  109. {
  110. I_fieldBytes = ndisPacketLen - SLOW_IR_ADDR_SIZE - SLOW_IR_CONTROL_SIZE;
  111. }
  112. //
  113. // Make sure that we won't overwrite our contiguous buffer.
  114. // Make sure that the passed-in buffer can accomodate this packet's
  115. // data no matter how much it grows through adding ESC-sequences, etc.
  116. //
  117. if ((ndisPacketLen > MAX_IRDA_DATA_SIZE) ||
  118. (MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > irPacketBufLen))
  119. {
  120. //
  121. // The packet is too large
  122. // Tell the caller to retry with a packet size large
  123. // enough to get past this stage next time.
  124. //
  125. DEBUGMSG(DBG_ERR, ("Packet too large in NdisToIrPacket (%d=%xh bytes), \n"
  126. "MAX_IRDA_DATA_SIZE=%d, irPacketBufLen=%d.",
  127. ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, irPacketBufLen));
  128. *irPacketLen = ndisPacketLen;
  129. return FALSE;
  130. }
  131. if (!ndisBuf)
  132. {
  133. DEBUGMSG(DBG_ERR, ("No NDIS_BUFFER in NdisToIrPacket"));
  134. *irPacketLen = 0;
  135. return FALSE;
  136. }
  137. NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
  138. if (!bufData)
  139. {
  140. DEBUGMSG(DBG_ERR, ("No data in NDIS_BUFFER in NdisToIrPacket"));
  141. *irPacketLen = 0;
  142. return FALSE;
  143. }
  144. fcs = 0xffff;
  145. // Calculate FCS and write the new buffer in ONE PASS.
  146. //
  147. // Now begin building the IR frame.
  148. //
  149. // This is the final format:
  150. //
  151. // BOF (1)
  152. // extra BOFs ...
  153. // NdisMediumIrda packet (what we get from NDIS):
  154. // Address (1)
  155. // Control (1)
  156. // FCS (2)
  157. // EOF (1)
  158. //
  159. // Prepend BOFs (extra BOFs + 1 actual BOF)
  160. //
  161. numExtraBOFs = packetInfo->ExtraBOFs;
  162. if (numExtraBOFs > MAX_NUM_EXTRA_BOFS)
  163. {
  164. numExtraBOFs = MAX_NUM_EXTRA_BOFS;
  165. }
  166. if (pThisDev->fRequireMinTurnAround &&
  167. packetInfo->MinTurnAroundTime>0)
  168. {
  169. //
  170. // A MinTurnAroundTime delay is required, to be implemented
  171. // by inserting extra BOF characters.
  172. //
  173. // TurnaroundBOFS = (BitsPerSec/BitsPerChar) * (uSecDelay/uSecPerSecond)
  174. // 10 1000000
  175. //
  176. ASSERT(pThisDev->currentSpeed<=MAX_SPEED_SUPPORTED);
  177. ASSERT(packetInfo->MinTurnAroundTime<=MAX_TURNAROUND_usec);
  178. //
  179. // The following operation won't overflow 32 bit operators so long
  180. // as currentSpeed<=115200 and MinTurnAroundTime<=10000
  181. //
  182. numExtraBOFs += (pThisDev->currentSpeed * packetInfo->MinTurnAroundTime)
  183. / (BITS_PER_CHAR*usec_PER_SEC);
  184. //
  185. // Don't need minimum turn around time until our next receive.
  186. //
  187. pThisDev->fRequireMinTurnAround = FALSE;
  188. }
  189. RtlFillMemory(irPacketBuf, numExtraBOFs+1, SLOW_IR_BOF);
  190. totalBytes = numExtraBOFs + 1;
  191. for (i=0; i<ndisPacketLen; i++)
  192. {
  193. ASSERT(bufData);
  194. nextChar = *bufData++;
  195. fcs = (fcs >> 8) ^ fcsTable[(fcs ^ nextChar) & 0xff];
  196. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], nextChar);
  197. if (--bufLen==0)
  198. {
  199. NdisGetNextBuffer(ndisBuf, &ndisBuf);
  200. if (ndisBuf)
  201. {
  202. NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
  203. }
  204. else
  205. {
  206. bufData = NULL;
  207. }
  208. }
  209. }
  210. if (bufData!=NULL)
  211. {
  212. /*
  213. * Packet was corrupt -- it misreported its size.
  214. */
  215. DEBUGMSG(DBG_ERR, ("Packet corrupt in NdisToIrPacket (buffer lengths don't add up to packet length)."));
  216. *irPacketLen = 0;
  217. return FALSE;
  218. }
  219. fcs = ~fcs;
  220. // Now we escape the fcs onto the end.
  221. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs&0xff));
  222. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs>>8));
  223. // EOF
  224. irPacketBuf[totalBytes++] = SLOW_IR_EOF;
  225. *irPacketLen = totalBytes;
  226. DEBUGMSG(DBG_FUNC, ("-NdisToIrPacket converted %d-byte ndis pkt to %d-byte irda pkt:\n", ndisPacketLen, *irPacketLen));
  227. return TRUE;
  228. }