--- /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 <bluetooth/logger.h>
+#include <es_sock.h>
+#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();
+ }
+ }
+
+