bthci/hci2implementations/hctls/bcsp/src/hctlbcspframe.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bthci/hci2implementations/hctls/bcsp/src/hctlbcspframe.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,757 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "hctlbcspframe.h"
+
+#include "bcsputils.h"
+#include "hctlbcspconsts.h"
+#include "debug.h"
+
+const TUint16 KCrcTable[] = 
+/**
+	Global CRC table
+*/
+	{
+	0x0000, 0x1081, 0x2102, 0x3183,
+	0x4204, 0x5285, 0x6306, 0x7387,
+	0x8408, 0x9489, 0xa50a, 0xb58b,
+	0xc60c, 0xd68d,	0xe70e, 0xf78f
+	};
+
+/**
+Implementation of Class THctlBcspPacketType
+*/
+
+
+/**
+	Method to set BCSP ProtocolId
+*/
+TInt THCTLBcspPacketType::SetProtocolId(TUint8 aProtocolId)
+	{
+	LOG_FUNC
+
+#ifdef __ARMCC__
+// Suppressing the warning "Pointless comparison of unsigned integer with zero"
+// as although a constant may be zero it is present so as to make the code more
+// understandable.
+# pragma diag_suppress 186
+#endif // __ARMCC__
+
+	// if (>2 && <5 || >7) then fail
+if ((aProtocolId > KBcspBcCmdChnl && aProtocolId < KBcspCommEvntChnl) || (aProtocolId > KBcspSynchronousDataChnl))
+	{
+	LOG1(_L8("THCTLBcspPacketType: Header unsupported, this used to be a BCSP 6 panic, now error handled. aProtocolId = %d"), aProtocolId);
+	return KErrNotSupported;
+	}	               
+	               
+#ifdef __ARMCC__
+# pragma diag_default 186
+#endif // __ARMCC__
+
+	iProtocolId = aProtocolId;
+	return KErrNone;
+	}
+
+TUint8 THCTLBcspPacketType::ProtocolId() const
+	{
+	return iProtocolId;
+	}
+
+/**
+Implementation of Class THctlBcspFlags
+*/
+
+TBool THCTLBcspFlags::CrcEnabled() const
+	{
+	return (iFlagsField & KBcspCrcPresentMask);
+	}
+
+TUint8 THCTLBcspFlags::Ack() const
+	{
+	return ((iFlagsField & KBcspAckMask) >> KBcspAckFieldOffset);
+	}
+
+TUint8 THCTLBcspFlags::Sequence() const
+	{
+	return (iFlagsField & KBcspSeqMask);
+	}
+
+TBool THCTLBcspFlags::IsReliableProtcolType() const
+	{
+	return (iFlagsField & KBcspProtocolTypeMask);
+	}
+
+TUint8 THCTLBcspFlags::FlagsField() const
+	{
+	return iFlagsField;
+	}
+
+/**
+	Trivial setter will panic if we attempt to set an invalid value
+*/
+void THCTLBcspFlags::SetAck(TUint8 aValue) 
+	{
+	__ASSERT_DEBUG((aValue < KMaxWindowSize), PANIC(KBcspPanicCat, EBcspInvalidAckValue));
+	// Clear the existing value and set the new value.
+	iFlagsField &= ~KBcspAckMask;
+	iFlagsField |= (aValue << KBcspAckFieldOffset);
+	}
+
+/**
+	Trivial setter will panic if we attempt to set an invalid value
+*/
+void THCTLBcspFlags::SetSequence(TUint8 aSeq)
+	{
+	__ASSERT_DEBUG((aSeq < KMaxWindowSize), PANIC(KBcspPanicCat, EBcspInvalidSequenceValue));
+	iFlagsField &= ~KBcspSeqMask;
+	iFlagsField |= aSeq;
+	}
+
+/**
+	Trivial setter
+*/
+void THCTLBcspFlags::SetCrcEnabled(TBool aCrcEnabled)
+	{
+	if(aCrcEnabled)
+		{
+		iFlagsField |= KBcspCrcPresentMask;
+		}
+	else
+		{
+		iFlagsField &= ~KBcspCrcPresentMask;
+		}
+	}
+
+void THCTLBcspFlags::SetIsReliableProtcolType(TBool aIsReliableProtcolType)
+	{
+	if(aIsReliableProtcolType)
+		{
+		iFlagsField |= KBcspProtocolTypeMask;
+		}
+	else
+		{
+		iFlagsField &= ~KBcspProtocolTypeMask;
+		}
+	}
+
+void THCTLBcspFlags::SetFlagsField(TUint8 aFlagsField)
+	{
+	iFlagsField = aFlagsField;
+	}
+	
+/**
+Implementation of Class CHCTLBcspFrame
+*/
+CHCTLBcspFrame::CHCTLBcspFrame()
+	{
+	}
+
+/**
+	Method to set the flags in the Header byte of a BCSP frame
+*/
+void CHCTLBcspFrame::SetFlags(TUint8 aAck, TBool aIsCrcEnabled, TBool aIsReliableProtcolType)
+	{
+	LOG_FUNC
+	iFlagHeaderByte.SetAck(aAck);
+	iFlagHeaderByte.SetCrcEnabled(aIsCrcEnabled);
+	iFlagHeaderByte.SetIsReliableProtcolType(aIsReliableProtcolType);
+	}
+
+void CHCTLBcspFrame::SetSequence(TUint8 aSeq)
+	{
+	iFlagHeaderByte.SetSequence(aSeq);
+	}
+
+TInt CHCTLBcspFrame::SetProtocolId(TUint8 aProtocolId)
+	{
+	return iProtocolId.SetProtocolId(aProtocolId);
+	}
+
+TBool CHCTLBcspFrame::CrcEnabled() const
+	{
+	return iFlagHeaderByte.CrcEnabled();
+	}
+
+TUint8 CHCTLBcspFrame::CheckSum() const
+	{
+	return iCheckSum;
+	}
+
+TUint8 CHCTLBcspFrame::ProtocolId() const
+	{
+	return iProtocolId.ProtocolId();
+	}
+
+TUint8 CHCTLBcspFrame::FlagsField() const
+	{
+	return iFlagHeaderByte.FlagsField();
+	}
+
+TUint16 CHCTLBcspFrame::PayloadLength() const
+	{
+	return static_cast<TUint16>(iPayloadPtr.Size());
+	}
+
+TInt CHCTLBcspFrame::ValidateChecksum(const TDesC8& aHeader)
+/**
+	Method to validate the checksum of a received frame header
+*/
+	{
+	LOG_FUNC
+	TInt rerr = KErrNone;
+
+	if (aHeader.Length() < KBcspHeaderBytes)
+		{
+		rerr = KErrBcspHeaderCorrupt;
+		}
+	else if(aHeader[KBcspHeaderChecksumByteIndex] != CalcCheckSum(aHeader))
+		{
+		rerr = KErrBcspHeaderCorrupt;
+		}
+
+	return rerr;
+	}
+
+TDesC8& CHCTLBcspFrame::Payload()
+/**
+	Trivial getter method
+*/
+	{
+	return iPayloadPtr;
+	}
+
+TUint8 CHCTLBcspFrame::Sequence() const
+/**
+	Trivial getter method
+*/
+	{
+	return iFlagHeaderByte.Sequence();
+	}
+
+TUint8 CHCTLBcspFrame::Ack() const
+/**
+	Trivial getter method
+*/
+	{
+	return iFlagHeaderByte.Ack();
+	}
+
+TBool CHCTLBcspFrame::IsReliableProtcolType() const
+/**
+	Trivial getter method
+*/
+	{
+	return iFlagHeaderByte.IsReliableProtcolType();
+	}
+
+TUint16 CHCTLBcspFrame::CalcCRC(const TDesC8& aData)
+/**
+ 	@param aData - Parameters Buffer upon which to calculate crc
+ 	@return CRC Value TUint16
+*/
+ 	{
+ 	LOG_FUNC
+  	TUint16 crcValue = 0xffff;	// Fill the shift register with 1s
+  	TUint8 dataByte;
+  	
+  	for (TInt i=0;i<aData.Length();i++)
+  		{
+  		dataByte = aData[i];
+  		crcValue = static_cast<TUint16>((crcValue >> 4) ^ KCrcTable[(crcValue^dataByte) & 0xf]);
+  		crcValue = static_cast<TUint16>((crcValue >> 4) ^ KCrcTable[(crcValue^(dataByte >> 4)) & 0xf]);
+  		}
+  	return ReverseCrcBits(crcValue); // Reverse all the bits in the CRC
+  	}
+
+TUint16 CHCTLBcspFrame::ReverseCrcBits(TUint16 aCRCValue)
+/**
+	Method to reverse the CRC Value
+	@param aCRCValue
+*/
+	{
+	TUint16 result = 0; 
+	for(TInt b=0;b<16;b++)
+		{
+		result = static_cast<TUint16>(result << 1) ;
+		result |= (aCRCValue & 1);
+		aCRCValue = static_cast<TUint16>(aCRCValue >> 1);
+		}
+	return result;
+	}
+
+
+
+TUint8 CHCTLBcspFrame::CalcCheckSum(const TDesC8& aHeader)
+/**
+	Method to calculate the checksum
+	The Checksum error is used to check the integrity of the header:
+*/
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(aHeader.Length() >= KBcspHeaderBytes, PANIC(KBcspPanicCat, EBadBcspFrame));
+	TUint8 tempsum = static_cast <TUint8>(aHeader[KBcspHeaderFlagsByteIndex] + 
+	                                      aHeader[KBcspHeaderByte2Index] + 
+	                                      aHeader[KBcspHeaderByte3Index]);
+	return ~tempsum;
+	}
+
+void CHCTLBcspFrame::Reset()
+/**
+	Method to reset the frame
+*/
+	{
+	LOG_FUNC
+	iIsValid = EFalse;
+	}
+
+TBool CHCTLBcspFrame::IsValid() const
+/**
+	Trvial getter method
+*/
+ 	{
+ 	return iIsValid;
+ 	}
+
+
+/**
+Implementation of Class CTxHctlBcspFrame
+*/
+
+CTxHctlBcspFrame* CTxHctlBcspFrame::NewLC(const TDesC8& aHCIPayload)
+	{
+	LOG_STATIC_FUNC
+	CTxHctlBcspFrame* self= new(ELeave) CTxHctlBcspFrame();
+	CleanupStack::PushL(self);
+	self->ConstructL(aHCIPayload);
+	return self;
+	}
+
+CTxHctlBcspFrame* CTxHctlBcspFrame::NewLC(TInt aFrameSize)
+	{
+	LOG_STATIC_FUNC
+	CTxHctlBcspFrame* self= new(ELeave) CTxHctlBcspFrame();
+	CleanupStack::PushL(self);
+	self->ConstructL(aFrameSize);
+	return self;
+	}
+
+CTxHctlBcspFrame* CTxHctlBcspFrame::NewL(const TDesC8& aHCIPayload)
+	{
+	LOG_STATIC_FUNC
+	CTxHctlBcspFrame *self=NewLC(aHCIPayload);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CTxHctlBcspFrame* CTxHctlBcspFrame::NewL(TInt aFrameSize)
+	{
+	LOG_STATIC_FUNC
+	CTxHctlBcspFrame *self=NewLC(aFrameSize);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CTxHctlBcspFrame::ConstructL(const TDesC8& aHCIPayload)
+	{
+	LOG_FUNC
+
+	// Instantiates iFrame and the TPtr8 iFramePtr to it
+	// Then calls the SetPayload() method with the param aHCIPayload
+	iFrame = HBufC8::NewL(aHCIPayload.Length() + KBcspHeaderBytes + KBcspCrcBytes);
+	iFramePtr.Set(iFrame->Des());
+
+	SetPayload(aHCIPayload);
+	}
+
+void CTxHctlBcspFrame::ConstructL(TInt aFrameSize)
+	{
+	LOG_FUNC
+
+	// Instantiates iFrame and the TPtr8 iFramePtr to it
+	// then calls the SetPayload() method.
+	iFrame = HBufC8::NewL(KBcspHeaderBytes + KBcspCrcBytes + aFrameSize);
+	iFramePtr.Set(iFrame->Des());
+
+	SetPayload();
+	}
+
+void CTxHctlBcspFrame::SetPayload(const TDesC8 &aPayload)
+	{
+	iFramePtr.SetMax();
+	TPtr8 payload(iFramePtr.MidTPtr(KBcspHeaderBytes));
+
+	payload = aPayload.Right(payload.MaxSize());
+	iPayloadPtr.Set(payload);
+
+	iFramePtr.SetLength(KBcspHeaderBytes + aPayload.Size());
+
+	iIsValid = ETrue;
+	}
+
+void CTxHctlBcspFrame::SetPayload()
+	{
+	LOG_FUNC
+	iPayloadPtr.Set(KNullDesC8);
+
+	iFramePtr.SetLength(KBcspHeaderBytes);
+
+	iIsValid = ETrue;
+	}
+
+CTxHctlBcspFrame::CTxHctlBcspFrame()
+  : iFramePtr(NULL, 0, 0)
+	{
+	LOG_FUNC
+	}
+
+CTxHctlBcspFrame::~CTxHctlBcspFrame()
+	{
+	LOG_FUNC
+	delete iFrame;
+	}
+
+void CTxHctlBcspFrame::BuildFrame()
+/**
+	Build  BCSP frame method
+
+	Zero the frame Ptr
+	Set the frame length to KMaxHeaderBytes - to address the BCSP header bytes
+
+	Populate all 4 header bytes with the Flag byte,PayloadLength, ProtocolId and checksum
+
+	Set the frame length to Payloadlength + KMaxBcspHeaderBytes
+
+	Populate the BCSP frame payload
+
+	Check if the CRC flag is set if it is then Calculate the CRC of the Whole Frame and append the crc
+
+*/
+	{
+	LOG_FUNC
+	iFramePtr.SetLength(KBcspHeaderBytes);
+	iFramePtr[KBcspHeaderFlagsByteIndex] = iFlagHeaderByte.FlagsField();
+	iFramePtr[KBcspHeaderByte2Index] = static_cast<TUint8>(ProtocolId() | ((PayloadLength() & 0xf) << 4));
+	iFramePtr[KBcspHeaderByte3Index] = static_cast<TUint8>((PayloadLength() & 0xff0) >> 4);
+	iFramePtr[KBcspHeaderChecksumByteIndex] = CalcCheckSum(iFramePtr);
+
+	iFramePtr.SetLength(PayloadLength() + KBcspHeaderBytes);
+
+	if (PayloadLength() > 0)
+		{
+		iPayloadPtr.Set(iFramePtr.Ptr() + KBcspHeaderBytes, PayloadLength());
+		}
+
+	if (CrcEnabled())
+		{
+		TUint16 crcValue = CalcCRC(iFramePtr.Left(PayloadLength() + KBcspHeaderBytes));
+		iFramePtr.Append((crcValue & 0xff00) >> 8); //Append first byte of CRC
+		iFramePtr.Append(crcValue & 0x00ff);        //Append second Byte of CRC
+		}
+	}
+
+void CTxHctlBcspFrame::Reset()
+/**
+	Reset the BCSP frame and set retries to 0
+*/
+	{
+	LOG_FUNC
+	CHCTLBcspFrame::Reset();
+	iRetries = 0;
+	}
+
+void CTxHctlBcspFrame::SlipEncodeFrame(TPtr8 aSlipFrame)
+/**
+	SlipEncoding method
+	SLIP is outlined in RFC 1055. The principle is to surround each packet
+	with a start and an end special byte. This allows the beginning and the end of a packet to be
+	found and consequently the length of the packet to be known.
+	The packet encoding and decoding scheme has two basic rules:
+	Because the special byte can only appear in the stream as a delimiter, it has to be replaced inside
+	the payload by an escape sequence, composed of two bytes: 0xc0 is mapped to 0xDB 0xDC.
+	Consequently 0xDB is also a special byte, and each occurrence of this escape byte is replaced
+	by an another sequence of two bytes: 0xDB 0xDD
+	This method is very quick and simple for encoding a packet. The corresponding Decoding
+	procedure is used for received packets.
+	Moreover, as explained in the section regarding detecting errors, the SLIP layer provides a
+	method of error detection.
+*/
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iFrame != NULL, PANIC(KBcspPanicCat, EBadFramePointer));
+
+	aSlipFrame.Zero();
+	aSlipFrame.SetMax();
+
+	TInt i=0;
+	TInt j=0;
+
+	aSlipFrame[j++] = KSlipWrapperByte;
+
+	for (i=0;i<iFrame->Length();i++)
+		{
+		switch((*iFrame)[i])
+			{
+			case KSlipWrapperByte:
+				{
+				aSlipFrame[j++] = KSlipByteDB;
+				aSlipFrame[j++] = KSlipByteDC;
+				break;
+				}
+			case 0xdb:
+				{
+				aSlipFrame[j++] = KSlipByteDB;
+				aSlipFrame[j++] = KSlipByteDD;
+				break;
+				}
+
+			default:
+				{
+				aSlipFrame[j++] = (*iFrame)[i];
+				break;
+				}
+			}
+		}
+
+	aSlipFrame[j++] = KSlipWrapperByte;
+	aSlipFrame.SetLength(j);
+	}
+
+
+
+/**
+Implementation of Class CRxHctlBcspFrame
+*/
+
+
+CRxHctlBcspFrame* CRxHctlBcspFrame::NewL()
+/**
+	CRxHctlBcspFrame::NewL() method
+	
+	@return self
+*/
+	{
+	LOG_STATIC_FUNC
+	return new(ELeave) CRxHctlBcspFrame;
+	}
+
+TInt CRxHctlBcspFrame::SlipDecodeFrame(const TDesC8& aReceivedFrame)
+/**
+	Slip decoding methopd for received frames
+*/
+	{
+	LOG_FUNC
+	TInt rerr = KErrNone;
+
+ 	// TPtrC8 packet = aReceivedFrame;
+	TPtr8 packet(const_cast<TUint8*>(aReceivedFrame.Ptr()),
+			     aReceivedFrame.Size(),
+				 aReceivedFrame.Size());
+
+	if ((packet.Length() < KBcspHeaderBytes) || (packet[packet.Length()-1] != KSlipWrapperByte) || (packet[0] == KSlipWrapperByte))
+		{
+		/** 
+		Fail slip decoding for one of or none of these reasons:
+			1. first byte is another slip wrapper byte (One has been received already and discarded in terminating reads)
+			   should not receive 2 consecutive slip wrapper byte in any one slip packet
+			2. The final packet byte is not a slip wrapper byte
+		
+		NB. A good slip Packet at this stage should have x-bytes appended with one slip wrapper byte.
+		This is because the first slip wrapper byte was already picked up on the first terminated read.
+		*/
+		rerr = KErrSlipCorrupted;
+		}
+	else
+		{
+		packet.SetLength(packet.Length() - 1); // Remove the last 0xc0 byte.
+
+		TInt  i = 0;
+		TInt  offset = 0;
+		TInt  length = packet.Length();
+
+		while ( (i<length) && (rerr == KErrNone) )
+			{
+			switch (packet[i])
+				{
+				case 0xc0:	// If this appears do nothing as it should be either the header or trailer byte checked above
+					rerr = KErrSlipCorrupted;
+					break;
+
+				case 0xdb:
+					i++; // Check the next byte immediately
+					offset--;
+					if ( i<length )
+						{
+						switch (packet[i])
+							{
+							case 0xdc:
+								packet[i+offset] = 0xc0;
+								break;
+
+							case 0xdd:
+								packet[i+offset] = 0xdb;
+								break;
+
+							default:
+								rerr = KErrSlipCorrupted;
+							};
+						}
+					else
+						{
+						rerr = KErrSlipCorrupted;
+						}
+					break;
+
+				default:
+					if ( offset )
+						{
+						packet[i+offset] = packet[i];
+						}
+					break;
+				}
+			i++;
+			}
+
+		if(rerr == KErrNone)
+			{
+			packet.SetLength(length + offset);
+			rerr = Set(packet);
+			}
+		}
+
+	return rerr;
+	}
+
+TInt CRxHctlBcspFrame::Set(const TDesC8& aFrame)
+/**
+	Populate a BCSP frame object and vaildate its contents via the various BCSP error 
+	checking methods
+*/
+	{
+	LOG_FUNC
+	TInt err = ValidateChecksum(aFrame);	// Do Checksum check
+	TInt errId = KErrNone;
+	TUint16 payloadLen = 0;
+
+	if (err == KErrNone)
+		{
+		ParseFlagByte(aFrame);	// populate THctlBcspFlags members
+		
+		errId = ParsePayloadLenProtId(aFrame, payloadLen);	
+		if (errId)
+			{
+			return errId;	// corrupted Id, no point in continuing 	
+			}
+
+		// Check header payload length field is the same as the actual HCIPayloadLength
+		if (CrcEnabled())
+			{
+			TInt actualPayloadLen = aFrame.Length() - KBcspCrcBytes - KBcspHeaderBytes;
+			if(actualPayloadLen >= 0) // Check payload is sufficient length
+				{
+				iPayloadPtr.Set(aFrame.Ptr() + KBcspHeaderBytes, actualPayloadLen);
+
+				if (PayloadLength() != payloadLen) // Check payload length
+					{
+					LOG(_L8("CRxHctlBcspFrame: KErrBcspCorruptedHCIPayload..."));
+					err = KErrBcspCorruptedHCIPayload;
+					}
+				else if (CheckCRC(aFrame) != KErrNone) // Do CRC Check
+					{
+					LOG(_L8("CRxHctlBcspFrame: KErrBCSPCRCCheckFailed..."));
+					err = KErrBcspCRCCheckFailed;
+					}
+				}
+			else
+				{
+				LOG(_L8("CRxHctlBcspFrame: KErrBcspCorruptedHCIPayload..."));
+				err = KErrBcspCorruptedHCIPayload;
+				}
+			}
+		else 
+			{
+			TInt actualPayloadLen = aFrame.Length() - KBcspHeaderBytes;
+			// There is no need to check that the payload is of sufficient length since
+			// the ValidateChecksum call would have failed and stopped us getting here.
+			__ASSERT_DEBUG(actualPayloadLen >= 0, PANIC(KBcspPanicCat, EBadBcspFrame));
+			iPayloadPtr.Set(aFrame.Ptr() + KBcspHeaderBytes, actualPayloadLen);
+			if (PayloadLength() != payloadLen) 
+				{
+				LOG(_L8("HCTLBcsp: KErrBcspCorruptedHCIPayload..."));
+				LOGHEXDESC(aFrame);
+				err = KErrBcspCorruptedHCIPayload;
+				}
+			}
+		}
+
+	iIsValid = (err == KErrNone) ? ETrue : EFalse;
+
+	return err;
+	}
+
+
+CRxHctlBcspFrame::CRxHctlBcspFrame()
+  : CHCTLBcspFrame()
+	{
+	}
+
+void CRxHctlBcspFrame::ParseFlagByte(const TDesC8& aHeader)
+	{
+	LOG_FUNC
+	LOG1(_L8("Parse HeaderByte %02x"), aHeader[KBcspHeaderFlagsByteIndex]);
+
+	iFlagHeaderByte.SetFlagsField(aHeader[KBcspHeaderFlagsByteIndex]);
+	}
+
+TInt CRxHctlBcspFrame::ParsePayloadLenProtId(const TDesC8& aHeader, TUint16& aRetPayloadLen)
+/**
+	Method to extract the Payload Length and Protocol Id from the 2nd and 3rd header bytes
+*/
+	{
+	LOG_FUNC
+	TInt err = KErrNone;
+
+	err = SetProtocolId((aHeader[KBcspHeaderByte2Index] & KBcspProtocolIdMask));
+	if (!err)
+		{
+		aRetPayloadLen = static_cast<TUint16>(((aHeader[KBcspHeaderByte2Index] & KBcspPayloadLen1stBitsMask) >> 4) | (aHeader[KBcspHeaderByte3Index] << 4));
+		}
+	
+	return err;
+	}
+
+TInt CRxHctlBcspFrame::CheckCRC(const TDesC8 &aFrame)
+/**
+	Method to check and validate the CRC
+*/
+	{
+	LOG_FUNC
+	TPtrC8 frame(aFrame.Ptr(), aFrame.Size() - KBcspCrcBytes);
+
+	TUint16 tempCRCvalue;
+	TUint16 crcValue = CalcCRC(frame);	// Calculates and sets iCRCValue
+
+	//compare with hctl trailer CRC value
+	TBuf8<2> crcval;
+	crcval = aFrame.Right(KBcspCrcBytes);
+	
+	tempCRCvalue = static_cast<TUint16>((crcval[0] << 8) + crcval[1]);
+
+	return ((crcValue == tempCRCvalue) ? KErrNone : KErrBcspCRCCheckFailed);
+	}