#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_T123PSTN);

/*	crc.cpp
 *
 *	Copyright (c) 1994-1995 by DataBeam Corporation, Lexington, KY
 *
 *	Abstract:
 *		This is the implementation file for the CRC class.
 *
 *	Private Instance Variables:
 *		CRC_Table[] 	-	Look-up table for pre-calc CRC values.
 *		CRC_Poly 		-	The algorithm's polynomial.
 *		CRC_Init 		-	Initial register value.
 *		CRC_Check_Value -	The value to compare the resulting received CRC.
 *		Invert 			-	Determines wether to invert the CRC value before 
 *							sending.
 *		CRC_Register 	-	CRC register during execution.
 *
 *	Caveats:
 *		None.
 *
 *	Authors:
 *		Marvin Nicholson
 */
#include "crc.h"



/*  CRC::CRC()
 *
 *  Public 
 *
 *	Functional Description:
 *  	The constructor fo CRC class initializes some member variables.
 */
CRC::CRC()
{

	CRC_Width = 16;    /* Width of the CRC register. */
	CRC_Poly = 0x8408; /* Polynomial used in generating the CRC. */
	CRC_Init = 0xFFFF; /* Initial value of the CRC register. */
	Invert = TRUE;     /* Enables 1's complement of CRC */

	if (Invert)
	{
       /*
        *  If using 1's complement use this value to check incoming
        *  CRC.
        */
       CRC_Check_Value = 0xF0B8;
    }
	else
	{
        /*
         *  If not inverting CRC on transmittion, use this value to
         *  check received CRC.
         */
       CRC_Check_Value = 0x0000;
    }

	CRCTableGenerator (CRC_Poly);
}


/*  CRC::~CRC()
 *
 *  Public
 *
 *	Functional Description:
 *  This is the destructor for the CRC class.
 */
CRC::~CRC()
{
}


/* ULONG CRC::OldCRCGenerator(HPUChar block_adr, ULONG block_len)
 *
 * Public
 *
 *	Functional Description:
 * 		This routine computes the CRC value using standard bit-shifting.
 */
ULONG CRC::OldCRCGenerator (
			LPBYTE block_adr,
            ULONG block_len)
{
	Int 	i;
	UChar	input_byte;
	USHORT	byte_count;

	CRC_Register = (USHORT) CRC_Init;
	byte_count = 0;
	while(byte_count < block_len)
	{
		input_byte = *(block_adr + byte_count);
		CRC_Register ^= input_byte;
		for(i=0; i<8; i++)
		{
			if(CRC_Register & 1)
			{
				CRC_Register >>= 1;
				CRC_Register ^= (USHORT) CRC_Poly;
			}
			else
				CRC_Register >>= 1;
		}
		byte_count++;
	}
	if (Invert)
		return (CRC_Register ^ 0xFFFF);
	else
		return (CRC_Register);
}


/* ULONG CRC::CRCGenerator(HPUChar block_adr, ULONG block_len)
 *
 * Public
 *
 *	Functional Descriprion:
 * 		This routine computes the CRC value using a look-up table.
 */
ULONG CRC::CRCGenerator(
			LPBYTE block_adr,
            ULONG block_len)
{

	CRC_Register = (USHORT) CRC_Init;

	while(block_len--)
	{
		CRC_Register = 
			CRC_Table[(UChar) (((UChar) CRC_Register) ^ *block_adr++)] ^ 
			(CRC_Register >> 8);
	}
	if (Invert)
		return (CRC_Register ^ 0xFFFF);
	else
		return (CRC_Register);
}


/*	
 *	USHORT CRC::CRCTableValue(
 *					Int index,
 *   	            ULONG poly)
 *
 *	Functional Description
 *		This function generates a value that goes in the CRC_Table
 *
 *	Formal Parameters
 *		index	(i)	-	Index into the table
 *		poly	(i)	-	Polynomial used to generate the value
 *
 *	Return Value
 *		Value generated.
 *
 *	Side Effects
 *		None
 *
 *	Caveats
 *		None
 */
USHORT CRC::CRCTableValue(
				Int index,
                ULONG poly)
{
	Int i;
	ULONG r;
	ULONG inbyte = (ULONG) index;

	r = inbyte;
	for(i=0; i<8; i++)
	{
		if (r & 1)
			r = (r >> 1) ^ poly;
		else
			r >>= 1;
	}
	return ((USHORT) r);
}


/*	
 *	void CRC::CRCTableGenerator (ULONG poly)
 *
 *	Functional Description
 *		This function generates the CRC table 
 *
 *	Formal Parameters
 *		poly	(i)	-	Polynomial used to generate the table
 *
 *	Return Value
 *		None
 *
 *	Side Effects
 *		None
 *
 *	Caveats
 *		None
 */
void CRC::CRCTableGenerator (ULONG poly)
{
	Int i;

	for(i=0; i<CRC_TABLE_SIZE; i++)
		CRC_Table[i] = CRCTableValue(i,poly);
}

/* BOOL CRC::CheckCRC(HPUChar block_adr, ULONG block_len)
 *
 * Public 
 *
 *	Functional Description:
 * 		This routine computes the CRC of a datablock and its associated CRC and
 * 		returns a TRUE value if the resulting CRC value is 0x0000
 * 		or 0xF0B8.
 */
BOOL CRC::CheckCRC(
				LPBYTE	block_adr,
                ULONG 	block_len)
{
	CRC_Register = (USHORT) CRC_Init;

	while(block_len--)
	{
		CRC_Register = 
			CRC_Table[(UChar) (((UChar) CRC_Register) ^ *block_adr++)] ^ 
			(CRC_Register >> 8);
	}
	if (CRC_Register == CRC_Check_Value)
		return TRUE;
	else
		return FALSE;
}


/*
 *	void	CRC::GetOverhead (
 *				USHORT	maximum_packet,
 *				USHORT *	new_maximum_packet)
 *
 * Public 
 *
 *	Functional Description:
 * 		This routine adds the number of overhead bytes generated by a CRC to
 *		the packet size passed in.
 */
void	CRC::GetOverhead (
			USHORT	maximum_packet,
			USHORT *	new_maximum_packet)
{
	*new_maximum_packet = maximum_packet + 2;
}
