/* ************************************************************************ * * CONVERT.c * * * Portions Copyright (C) 1996-2001 National Semiconductor Corp. * All rights reserved. * Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved. * * * ************************************************************************* */ #include "nsc.h" extern const USHORT fcsTable[]; ULONG __inline EscapeSlowIrData(PUCHAR Dest, UCHAR SourceByte) { switch (SourceByte){ case SLOW_IR_BOF: case SLOW_IR_EOF: case SLOW_IR_ESC: Dest[0] = SLOW_IR_ESC; Dest[1] = SourceByte ^ SLOW_IR_ESC_COMP; return 2; default: Dest[0] = SourceByte; return 1; } } /* ************************************************************************* * NdisToIrPacket ************************************************************************* * * * Convert an NDIS Packet into an IR packet. * Write the IR packet into the provided buffer and report its actual size. * * If failing, *irPacketLen will contain the buffer size that * the caller should retry with (or 0 if a corruption was detected). * */ BOOLEAN NdisToIrPacket( IrDevice *thisDev, PNDIS_PACKET Packet, UCHAR *irPacketBuf, UINT irPacketBufLen, UINT *irPacketLen ) { PNDIS_BUFFER ndisBuf; UINT i, ndisPacketBytes = 0, I_fieldBytes, totalBytes = 0; UINT ndisPacketLen, numExtraBOFs; SLOW_IR_FCS_TYPE fcs; PNDIS_IRDA_PACKET_INFO packetInfo = GetPacketInfo(Packet); UCHAR nextChar; UCHAR *bufData; UINT bufLen; DBGOUT(("NdisToIrPacket() ...")); /* * Get the packet's entire length and its first NDIS buffer */ NdisQueryPacket(Packet, NULL, NULL, &ndisBuf, &ndisPacketLen); /* * Make sure that the packet is big enough to be legal. * It consists of an A, C, and variable-length I field. */ if (ndisPacketLen < IR_ADDR_SIZE + IR_CONTROL_SIZE){ DBGERR(("packet too short in NdisToIrPacket (%d bytes)", ndisPacketLen)); return FALSE; } else { I_fieldBytes = ndisPacketLen - IR_ADDR_SIZE - IR_CONTROL_SIZE; } /* * Make sure that we won't overwrite our contiguous buffer. * Make sure that the passed-in buffer can accomodate this packet's * data no matter how much it grows through adding ESC-sequences, etc. */ if ((ndisPacketLen > MAX_IRDA_DATA_SIZE) || (MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > irPacketBufLen)){ /* * The packet is too large * Tell the caller to retry with a packet size large * enough to get past this stage next time. */ DBGERR(("Packet too large in NdisToIrPacket (%d=%xh bytes), MAX_IRDA_DATA_SIZE=%d, irPacketBufLen=%d.", ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, irPacketBufLen)); *irPacketLen = ndisPacketLen; return FALSE; } if (!ndisBuf) { DBGERR(("No NDIS_BUFFER in NdisToIrPacket")); return FALSE; } NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen); fcs = 0xffff; // Calculate FCS and write the new buffer in ONE PASS. /* * Now begin building the IR frame. * * This is the final format: * * BOF (1) * extra BOFs ... * NdisMediumIrda packet (what we get from NDIS): * Address (1) * Control (1) * FCS (2) * EOF (1) */ // Prepend BOFs (extra BOFs + 1 actual BOF) numExtraBOFs = packetInfo->ExtraBOFs; if (numExtraBOFs > MAX_NUM_EXTRA_BOFS){ numExtraBOFs = MAX_NUM_EXTRA_BOFS; } for (i = totalBytes = 0; i < numExtraBOFs; i++){ *(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_EXTRA_BOF; totalBytes += SLOW_IR_EXTRA_BOF_SIZE; } *(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_BOF; totalBytes += SLOW_IR_BOF_SIZE; for (i=0; i> 8) ^ fcsTable[(fcs ^ nextChar) & 0xff]; totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], nextChar); if (--bufLen==0) { NdisGetNextBuffer(ndisBuf, &ndisBuf); if (ndisBuf) { NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen); } else { bufData = NULL; } } } if (bufData!=NULL) { /* * Packet was corrupt -- it misreported its size. */ DBGERR(("Packet corrupt in NdisToIrPacket (buffer lengths don't add up to packet length).")); *irPacketLen = 0; return FALSE; } fcs = ~fcs; // Now we escape the fcs onto the end. totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs&0xff)); totalBytes += EscapeSlowIrData(&irPacketBuf[totalBytes], (UCHAR)(fcs>>8)); // EOF *(SLOW_IR_EOF_TYPE *)&irPacketBuf[totalBytes] = SLOW_IR_EOF; totalBytes += SLOW_IR_EOF_SIZE; *irPacketLen = totalBytes; DBGOUT(("... NdisToIrPacket converted %d-byte ndis pkt to %d-byte irda pkt:", ndisPacketLen, *irPacketLen)); return TRUE; }