windows-nt/Source/XPSP1/NT/net/irda/samples/nscirda/convert.c
2020-09-26 16:20:57 +08:00

196 lines
4.9 KiB
C

/*
************************************************************************
*
* 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<ndisPacketLen; i++)
{
ASSERT(bufData);
nextChar = *bufData++;
fcs = (fcs >> 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;
}