diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/avctp/avctppacket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/avctp/avctppacket.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,279 @@ +// Copyright (c) 2005-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 +#include +#include "avctppacket.h" +#include "avctpcommon.h" +#include "avctpmuxer.h" +#include "avctputils.h" +#include "avctpconstants.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_AVCTP); +#endif + +#ifdef _DEBUG +PANICCATEGORY("avctppkt"); +#endif + +using namespace SymbianAvctp; + +/*static*/ TPtrC8 CAvctpPacket::GetHeader(const RMBufChain& aChain) + { + const RMBuf* mbuf = aChain.First(); + // set the descriptor to read out the whole of the first mbuf (into which the header fits) + return TPtrC8(mbuf->Ptr(), mbuf->Length()); + } + + +/** +Fills in the TAvctpHeaderInfo + +This function takes a TAvctpStartHeaderInfo rather than a TAvctpHeaderInfo to +avoid problems with casting from TAvctpHeaderInfo to TAvctpStartHeaderInfo & +mangling data. + + @internalComponent + @param aData The data buffer that contains the AVCTP packet to be parsed + @param aHeaderInfo will contain the result of the parsing. + @return KErrNone if there was no problem parsing the header, otherwise returns an + Avctp specific error. +*/ +/*static*/ TInt CAvctpPacket::ParseHeader(const RMBufChain& aData, TAvctpStartHeaderInfo& aHeaderInfo) + { + LOG_STATIC_FUNC + + TInt err = KErrNone; + + // We require the packet to be long enough to at least contain the packet type + const TPtrC8 dataP(GetHeader(aData)); + + if (dataP.Length() < EMinimumHeaderLength) + { + err = KErrPacketTooShort; + } + + if (err == KErrNone) + { + aHeaderInfo.iMsgType = SymbianAvctp::MessageType(dataP); + aHeaderInfo.iTransactionLabel = SymbianAvctp::TransactionLabel(dataP); + } + + // No checking needs to be done on the TAvctpHeaderInfo variables since + // all values are allowed. + + // get the packet type + if (err == KErrNone) + { + aHeaderInfo.iPktType = SymbianAvctp::PacketType(dataP); + switch (aHeaderInfo.iPktType) + { + case ENormalPkt: + if (dataP.Length() < ENormalHeaderLength) + { + err = KErrPacketTooShort; + } + else + { + err = ParseNormalHeader(dataP, aHeaderInfo); + } + break; + case EStartFrag: + if (dataP.Length() < EStartFragHeaderLength) + { + err = KErrPacketTooShort; + } + else + { + err = ParseStartHeader(dataP, aHeaderInfo); + } + break; + case EContinueFrag: + case EEndFrag: + // the Size check before this switch statement ensures that + // the given data is long enough since EOtherFragHeaderLength = 1 + break; + default: + err = KErrUnknownPacketType; + break; + } + } + return err; + } + +/** +Fills in the TAvctpNormalHeaderInfo +Assumes aData is at least ENormalHeaderLength long + + @internalComponent + @param aData The data buffer that contains the AVCTP packet to be parsed + @param aHeaderInfo will contain the result of the parsing. + @return KErrNone if there was no problem parsing the header, otherwise returns an + Avctp specific error. +*/ +/*static*/ TInt CAvctpPacket::ParseNormalHeader(const TDesC8& aData, TAvctpNormalHeaderInfo& aHeaderInfo) + { + LOG_STATIC_FUNC + + aHeaderInfo.iHasValidPid = IsValidPid(aData); + aHeaderInfo.iPid = Pid(aData); + return CheckNormalHeaderInfo(aHeaderInfo); + } + +/** +Fills in the TAvctpStartHeaderInfo +Assumes aData is at least EStartFragHeaderLength long + + @internalComponent + @param aData The data buffer that contains the AVCTP packet to be parsed + @param aHeaderInfo will contain the result of the parsing. + @return KErrNone if there was no problem parsing the header, otherwise returns an + Avctp specific error. +*/ +/*static*/ TInt CAvctpPacket::ParseStartHeader(const TDesC8& aData, TAvctpStartHeaderInfo& aHeaderInfo) + { + LOG_STATIC_FUNC + + TInt err = ParseNormalHeader(aData, aHeaderInfo); + if (err == KErrNone) + { + aHeaderInfo.iFragmentsInSdu = FragmentsInSdu(aData); + err = CheckStartHeaderInfo(aHeaderInfo); + } + + return err; + } + +/* +Checks the validity of a TAvctpNormalHeaderInfo object. Note that the variables +derived from TAvctpHeaderInfo cannot be incorrect since all values that might appear +in a air packet are allowed. + +(NB the RFA field in Continue and End packets [the IPID field in other types of packet] +must be set to 0 in the AVCTP v1.0 spec. However, we don't enforce this on incoming +in case it is used in future.) +*/ +/*static*/ TInt CAvctpPacket::CheckNormalHeaderInfo(const TAvctpNormalHeaderInfo& aHeaderInfo) + { + LOG_STATIC_FUNC + + ASSERT_DEBUG(aHeaderInfo.iPktType == ENormalPkt || + aHeaderInfo.iPktType == EStartFrag); + + TInt ret = KErrNone; + if (!aHeaderInfo.iHasValidPid && aHeaderInfo.iMsgType == ECommand) + { + ret = KErrMalformedPacketFromRemote; + } + return ret; + } + +/* +Checks the validity of a TAvctpStartHeaderInfo object. +*/ +/*static*/ TInt CAvctpPacket::CheckStartHeaderInfo(const TAvctpStartHeaderInfo& aHeaderInfo) + { + LOG_STATIC_FUNC + + ASSERT_DEBUG(aHeaderInfo.iPktType == EStartFrag); + + TInt ret = KErrNone; + if (aHeaderInfo.iFragmentsInSdu > 1) + { + ret = CheckNormalHeaderInfo(aHeaderInfo); + } + else + { + ret = KErrMalformedPacketFromRemote; + } + + return ret; + } + + +// +// // +// HAvctpOutgoingSdu Implementation // +// // +// + +HAvctpOutgoingSdu* HAvctpOutgoingSdu::NewL(const TAvctpNormalHeaderInfo& aHeaderInfo, + const TBTDevAddr& aAddr, + RMBufChain& aData) + { + LOG_STATIC_FUNC + + HAvctpOutgoingSdu* sdu = new(ELeave) HAvctpOutgoingSdu(aHeaderInfo, aAddr); + CleanupStack::PushL(sdu); + sdu->ConstructL(aData); + CleanupStack::Pop(sdu); + return sdu; + } + +/** +Create the buffer by copying over the other descriptor allowing space for a header +at the beginning +*/ +void HAvctpOutgoingSdu::ConstructL(RMBufChain& aData) + { + LOG_FUNC + iSduData.Assign(aData); + } + +HAvctpOutgoingSdu* HAvctpOutgoingSdu::NewIpidResponseL(const HAvctpIncomingSdu& aIncomingSdu, TInt aChannel) + { + LOG_STATIC_FUNC + + TPtrC8 hdr(CAvctpPacket::GetHeader(aIncomingSdu.Data())); + + LOG1(_L("to Pid 0x%x"), Pid(hdr)); + + TAvctpNormalHeaderInfo headerInfo = + TAvctpNormalHeaderInfo(TransactionLabel(hdr), + ENormalPkt, + EResponse, + EFalse, + Pid(hdr) + ); + + HAvctpOutgoingSdu* sdu = new(ELeave) HAvctpOutgoingSdu(headerInfo, aIncomingSdu.BTAddr()); + sdu->iChannel = aChannel; + + return sdu; + } + +HAvctpOutgoingSdu::~HAvctpOutgoingSdu() + { + LOG_FUNC + + iSduData.Free(); + + if (iOutboundQ) + { + iOutboundQ->Deque(*this); + } + else + { + iQueLink.Deque(); + } + } + +