--- /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);
+ }