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.

195 lines
4.9 KiB

  1. /*
  2. ************************************************************************
  3. *
  4. * CONVERT.c
  5. *
  6. *
  7. * Portions Copyright (C) 1996-2001 National Semiconductor Corp.
  8. * All rights reserved.
  9. * Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved.
  10. *
  11. *
  12. *
  13. *************************************************************************
  14. */
  15. #include "nsc.h"
  16. extern const USHORT fcsTable[];
  17. ULONG __inline EscapeSlowIrData(PUCHAR Dest, UCHAR SourceByte)
  18. {
  19. switch (SourceByte){
  20. case SLOW_IR_BOF:
  21. case SLOW_IR_EOF:
  22. case SLOW_IR_ESC:
  23. Dest[0] = SLOW_IR_ESC;
  24. Dest[1] = SourceByte ^ SLOW_IR_ESC_COMP;
  25. return 2;
  26. default:
  27. Dest[0] = SourceByte;
  28. return 1;
  29. }
  30. }
  31. /*
  32. *************************************************************************
  33. * NdisToIrPacket
  34. *************************************************************************
  35. *
  36. *
  37. * Convert an NDIS Packet into an IR packet.
  38. * Write the IR packet into the provided buffer and report its actual size.
  39. *
  40. * If failing, *irPacketLen will contain the buffer size that
  41. * the caller should retry with (or 0 if a corruption was detected).
  42. *
  43. */
  44. BOOLEAN NdisToIrPacket( IrDevice *thisDev,
  45. PNDIS_PACKET Packet,
  46. UCHAR *irPacketBuf,
  47. UINT irPacketBufLen,
  48. UINT *irPacketLen
  49. )
  50. {
  51. PNDIS_BUFFER ndisBuf;
  52. UINT i, ndisPacketBytes = 0, I_fieldBytes, totalBytes = 0;
  53. UINT ndisPacketLen, numExtraBOFs;
  54. SLOW_IR_FCS_TYPE fcs;
  55. PNDIS_IRDA_PACKET_INFO packetInfo = GetPacketInfo(Packet);
  56. UCHAR nextChar;
  57. UCHAR *bufData;
  58. UINT bufLen;
  59. DBGOUT(("NdisToIrPacket() ..."));
  60. /*
  61. * Get the packet's entire length and its first NDIS buffer
  62. */
  63. NdisQueryPacket(Packet, NULL, NULL, &ndisBuf, &ndisPacketLen);
  64. /*
  65. * Make sure that the packet is big enough to be legal.
  66. * It consists of an A, C, and variable-length I field.
  67. */
  68. if (ndisPacketLen < IR_ADDR_SIZE + IR_CONTROL_SIZE){
  69. DBGERR(("packet too short in NdisToIrPacket (%d bytes)", ndisPacketLen));
  70. return FALSE;
  71. }
  72. else {
  73. I_fieldBytes = ndisPacketLen - IR_ADDR_SIZE - IR_CONTROL_SIZE;
  74. }
  75. /*
  76. * Make sure that we won't overwrite our contiguous buffer.
  77. * Make sure that the passed-in buffer can accomodate this packet's
  78. * data no matter how much it grows through adding ESC-sequences, etc.
  79. */
  80. if ((ndisPacketLen > MAX_IRDA_DATA_SIZE) ||
  81. (MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > irPacketBufLen)){
  82. /*
  83. * The packet is too large
  84. * Tell the caller to retry with a packet size large
  85. * enough to get past this stage next time.
  86. */
  87. DBGERR(("Packet too large in NdisToIrPacket (%d=%xh bytes), MAX_IRDA_DATA_SIZE=%d, irPacketBufLen=%d.",
  88. ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, irPacketBufLen));
  89. *irPacketLen = ndisPacketLen;
  90. return FALSE;
  91. }
  92. if (!ndisBuf)
  93. {
  94. DBGERR(("No NDIS_BUFFER in NdisToIrPacket"));
  95. return FALSE;
  96. }
  97. NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
  98. fcs = 0xffff;
  99. // Calculate FCS and write the new buffer in ONE PASS.
  100. /*
  101. * Now begin building the IR frame.
  102. *
  103. * This is the final format:
  104. *
  105. * BOF (1)
  106. * extra BOFs ...
  107. * NdisMediumIrda packet (what we get from NDIS):
  108. * Address (1)
  109. * Control (1)
  110. * FCS (2)
  111. * EOF (1)
  112. */
  113. // Prepend BOFs (extra BOFs + 1 actual BOF)
  114. numExtraBOFs = packetInfo->ExtraBOFs;
  115. if (numExtraBOFs > MAX_NUM_EXTRA_BOFS){
  116. numExtraBOFs = MAX_NUM_EXTRA_BOFS;
  117. }
  118. for (i = totalBytes = 0; i < numExtraBOFs; i++){
  119. *(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_EXTRA_BOF;
  120. totalBytes += SLOW_IR_EXTRA_BOF_SIZE;
  121. }
  122. *(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_BOF;
  123. totalBytes += SLOW_IR_BOF_SIZE;
  124. for (i=0; i<ndisPacketLen; i++)
  125. {
  126. ASSERT(bufData);
  127. nextChar = *bufData++;
  128. fcs = (fcs >> 8) ^ fcsTable[(fcs ^ nextChar) & 0xff];
  129. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], nextChar);
  130. if (--bufLen==0)
  131. {
  132. NdisGetNextBuffer(ndisBuf, &ndisBuf);
  133. if (ndisBuf)
  134. {
  135. NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
  136. }
  137. else
  138. {
  139. bufData = NULL;
  140. }
  141. }
  142. }
  143. if (bufData!=NULL)
  144. {
  145. /*
  146. * Packet was corrupt -- it misreported its size.
  147. */
  148. DBGERR(("Packet corrupt in NdisToIrPacket (buffer lengths don't add up to packet length)."));
  149. *irPacketLen = 0;
  150. return FALSE;
  151. }
  152. fcs = ~fcs;
  153. // Now we escape the fcs onto the end.
  154. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs&0xff));
  155. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs>>8));
  156. // EOF
  157. *(SLOW_IR_EOF_TYPE *)&irPacketBuf[totalBytes] = SLOW_IR_EOF;
  158. totalBytes += SLOW_IR_EOF_SIZE;
  159. *irPacketLen = totalBytes;
  160. DBGOUT(("... NdisToIrPacket converted %d-byte ndis pkt to %d-byte irda pkt:", ndisPacketLen, *irPacketLen));
  161. return TRUE;
  162. }