bluetooth/btstack/avdtp/avdtpSEPCache.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/avdtp/avdtpSEPCache.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,284 @@
+// Copyright (c) 2003-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:
+// Implements the avdtp SEP cache
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <bluetooth/logger.h>
+#include <bluetoothav.h>
+#include "avdtpSEPCache.h"
+#include "gavdpinterface.h"
+#include "avdtpSignallingMessages.h"
+#include "avdtputil.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
+#endif
+
+CRemoteSEP* CRemoteSEP::NewL(const TBTDevAddr& aAddr, const TAvdtpSEPInfo& aInfo)
+	{
+	LOG_STATIC_FUNC
+	CRemoteSEP* s = new (ELeave) CRemoteSEP(aAddr, aInfo);
+	CleanupStack::PushL(s);
+	s->ConstructL();
+	CleanupStack::Pop(s);
+	return s;
+	}
+	
+CRemoteSEP::CRemoteSEP(const TBTDevAddr& aAddr, const TAvdtpSEPInfo& aInfo)
+: iRemoteDev(aAddr), iInfo(aInfo)
+	{
+	LOG_FUNC
+	// age already set to zero
+	 // only store remote sep details in the cache
+	__ASSERT_DEBUG(!aInfo.SEID().IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
+	}
+	
+CRemoteSEP::~CRemoteSEP()
+	{
+	LOG_FUNC
+	delete iCapabilitiesBuf;
+	}
+
+	
+void CRemoteSEP::ConstructL()
+	{
+	LOG_FUNC
+	}
+
+void CRemoteSEP::UpdateInfo(const TAvdtpSEPInfo& aInfo)
+	{
+	iInfo = aInfo;
+	}
+	
+TBool CRemoteSEP::HasCapability(TAvdtpServiceCategory aCat)
+	{
+	LOG_FUNC
+	TBool ret = EFalse;
+	
+	if (iCapabilitiesBuf)
+		{
+		CCapabilityPresentVisitor* presVisitor = new CCapabilityPresentVisitor(aCat);
+		
+		if (presVisitor)
+			{
+			TPtr8 ptr = iCapabilitiesBuf->Des();
+			presVisitor->Process(ptr);
+			ret = presVisitor->IsPresent();
+			delete presVisitor;
+			}
+		}
+	return ret;
+	}
+	
+
+/*
+Returns a pointer descriptor to SEP capability *in the protocol domain*
+It is upto a client to get this parsed as needed
+Motivation - to push more easilythrough ESOCK AND save unneccasry parsing
+*/
+TPtrC8 CRemoteSEP::GetCapabilityL(TAvdtpServiceCategory aCat)
+	{
+	LOG_FUNC
+	// use visitor to extract relevant bit
+	CCapabilityExtractorVisitor* extractor = new (ELeave) CCapabilityExtractorVisitor(aCat);
+	TPtr8 ptr = iCapabilitiesBuf->Des();
+	extractor->Process(ptr);
+	
+	TPtrC8 cap = extractor->GetCapability();
+	delete extractor;
+	return cap;
+	}
+
+
+void CRemoteSEP::SetCapabilities(HBufC8* aCapsAsProtocol)
+	{
+	LOG_FUNC
+	delete iCapabilitiesBuf;
+	iCapabilitiesBuf = aCapsAsProtocol; // takes ownership
+	
+	// set a visitor on it now to summarise caps
+	CCapabilitySummaryVisitor* summariser = new CCapabilitySummaryVisitor;
+	if (summariser)
+		{
+		TPtr8 des = iCapabilitiesBuf->Des();
+		summariser->Process(des);
+		iKnownCaps = summariser->CapabilitiesPresent();
+		delete summariser;
+		}
+	}
+
+CRemoteSEPCache* CRemoteSEPCache::NewL()
+	{
+	LOG_STATIC_FUNC
+	CRemoteSEPCache* s = new (ELeave) CRemoteSEPCache();
+	return s;	
+	}
+	
+/**
+Modifies SEP if already exists
+*/
+TInt CRemoteSEPCache::AddSEP(const TBTDevAddr& aAddr, const TAvdtpSEPInfo& aInfo)
+	{
+	LOG_FUNC
+	TInt err = KErrNone;
+	
+	CRemoteSEP* sep = FindSEP(aAddr, aInfo.SEID());
+	if (!sep)
+		{
+		TRAP(err, sep = CRemoteSEP::NewL(aAddr, aInfo));
+		if (!err)
+			{
+			err = iRemoteSEPs.Append(sep);
+			if (err)
+	        	{
+	       	    delete sep;
+	        	}
+			}
+		}
+	else
+		{
+		// modify the one there
+		sep->UpdateInfo(aInfo);
+		}
+	return err;
+	}
+	
+TPtrC8 CRemoteSEPCache::GetCapabilityL(const TBTDevAddr& aAddr, TSEID aSEID, TAvdtpServiceCategory aCat)
+	{
+	LOG_FUNC
+	CRemoteSEP* sep = FindSEP(aAddr, aSEID);
+	
+	if (sep)
+		{
+		return sep->GetCapabilityL(aCat);
+		}
+		
+	User::Leave(KErrNotFound);
+	return KNullDesC8();// never reached
+	}
+
+
+TAvdtpServiceCategories CRemoteSEPCache::GetCapabilitiesL(const TBTDevAddr& aAddr, TSEID aSEID) const
+	{
+	LOG_FUNC
+	CRemoteSEP* sep = FindSEP(aAddr, aSEID);
+	
+	if (sep)
+		{
+		return sep->GetCapabilities();
+		}
+		
+	User::Leave(KErrNotFound);
+	return TAvdtpServiceCategories();
+	}
+
+
+TBool CRemoteSEPCache::HasCapability(const TBTDevAddr& aAddr, TSEID aSEID, TAvdtpServiceCategory aCat)
+	{
+	LOG_FUNC
+	CRemoteSEP* sep = FindSEP(aAddr, aSEID);
+	
+	if (sep)
+		{
+		return sep->HasCapability(aCat);
+		}
+		
+	return EFalse; // unknown => false
+	}
+
+
+
+void CRemoteSEPCache::SetCapabilities(const TBTDevAddr& aAddr, TSEID aSEID, HBufC8* aCapabilitiesAsProtocol)
+/**
+Sets capabilites from the RMBufChain passed in on the relevant CRemoteSEP in our
+cache.
+
+@return a bitmask of the service categories we saw.
+*/
+	{
+	LOG_FUNC
+	CRemoteSEP* sep = FindSEP(aAddr, aSEID);
+	
+	if (sep)
+		{
+		sep->SetCapabilities(aCapabilitiesAsProtocol);
+		}
+	else
+		{
+		// would be nice to cache this, but if we don't know the SEP at this point
+		// the user hadn't done a Discover - which is ok for them, but for us we don't know if the
+		// SEP is in use or Audio/Video etc....We keep the capabilities as the stack finds
+		// them useful later
+		TAvdtpSEPInfo info;
+		info.SetSEID(aSEID);
+		if (AddSEP(aAddr, info)==KErrNone)
+			{
+			SetCapabilities(aAddr, aSEID, aCapabilitiesAsProtocol);
+			}
+		}
+	}
+
+CRemoteSEPCache::~CRemoteSEPCache()
+	{
+	LOG_FUNC
+	iRemoteSEPs.ResetAndDestroy();
+	}
+
+TBool CRemoteSEPCache::Exists(const TBTDevAddr& aAddr, TSEID aSEID) const
+	{
+	LOG_FUNC
+	return (FindSEP(aAddr, aSEID)!=NULL);
+	}
+	
+CRemoteSEP* CRemoteSEPCache::FindSEP(const TBTDevAddr& aAddr, TSEID aSEID) const
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(!aSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
+	
+	for (TInt i=0; i<iRemoteSEPs.Count(); i++)
+		{
+		CRemoteSEP& sep = *iRemoteSEPs[i];
+		if (sep.iInfo.SEID() == aSEID && sep.iRemoteDev == aAddr)
+			{
+			return iRemoteSEPs[i]; // does not transfer ownership
+			}
+		}
+	return NULL;
+	}
+
+void CRemoteSEPCache::InvalidateSEPs(const TBTDevAddr& aAddr)
+	{
+	LOG_FUNC
+	// typically called when signalling channel has gone down
+	// in future we could age the seps and save doing a GetCaps, but this does
+	// risk the use of invalid capabilities (but would still be compliant with GAVDP)	
+	CRemoteSEP* sep = NULL;
+	for (TInt i=0; i<iRemoteSEPs.Count(); i++)
+		{
+		sep = iRemoteSEPs[i];
+		if (sep->iRemoteDev == aAddr)
+			{
+			iRemoteSEPs.Remove(i);
+			delete sep;
+			sep = NULL;
+			}
+		}
+	}
+