bluetooth/btstack/l2cap/l2capMuxController.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/l2cap/l2capMuxController.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,292 @@
+// Copyright (c) 1999-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:
+// Holds a list of all Muxers and listening SAP signal handlers.
+// 
+//
+
+#include <bluetooth/logger.h>
+#include "l2capSAPSignalHandler.h"
+#include "l2capMuxController.h"
+#include "l2capCommand.h"
+#include "l2signalmgr.h"
+#include "l2util.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_L2CAP);
+#endif
+
+CL2CAPMuxController::~CL2CAPMuxController()
+	{
+	LOG_FUNC
+	// Delete all L2Cap Muxers 
+	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
+	CL2CAPMux* muxerPtr;
+	while((muxerPtr = muxIter++) != NULL)
+		{
+		delete muxerPtr;
+		}
+
+	// Delete all the listening SAP Signal Handlers 
+	TDblQueIter<CL2CapSAPSignalHandler> listeningSapIter(iListeningSapSignalHandlers);
+	CL2CapSAPSignalHandler* sapSignalPtr;
+	while((sapSignalPtr = listeningSapIter++) != NULL)
+		{
+		delete sapSignalPtr;
+		}
+		
+	// Delete all the bound SAP Signal Handlers 
+	TDblQueIter<CL2CapSAPSignalHandler> boundSapIter(iBoundSapSignalHandlers);
+	while((sapSignalPtr = boundSapIter++) != NULL)
+		{
+		delete sapSignalPtr;
+		}		
+	}
+
+	
+CL2CAPMuxController::CL2CAPMuxController(CL2CAPProtocol& aProtocol)
+	: 
+	iMuxers(_FOFF(CL2CAPMux, iMuxControllerLink)),
+	iBoundSapSignalHandlers(_FOFF(CL2CapSAPSignalHandler, iLink)),
+	iListeningSapSignalHandlers(_FOFF(CL2CapSAPSignalHandler, iLink)),
+	iProtocol(aProtocol)
+	{
+	LOG_FUNC
+	}
+
+// This method is called to register the signal handler owned by a cloned SAP to the
+// appropriate Mux.  A Mux should always be available as this event has been triggered
+// by receipt of an incoming connection.
+TInt CL2CAPMuxController::AttachPassiveSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler,const TBTDevAddr& aAddr)
+	{
+	LOG_FUNC
+	// Find the muxer and register the SAP SH.
+	TInt rerr = KErrNone;
+
+	CL2CAPMux* mux = FindMuxer(aAddr);
+	if(mux)
+		{
+		mux->RegisterSAPSignalHandler(aSAPSignalHandler);
+		}
+	else
+		{
+		rerr = KErrSessionClosed;
+		}
+	return rerr;
+	}
+	
+// This method is called to register an active SAP signal handler to the appropriate Mux.
+// If the Mux does not exist a new one will be allocated and tasked with establishing
+// an ACL connection.	
+TInt CL2CAPMuxController::AttachActiveSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler,const TBTDevAddr& aAddr)
+	{
+	LOG_FUNC
+	TInt rerr = KErrNone;
+	
+	CL2CAPMux* mux = FindMuxer(aAddr);
+	if(mux)
+		{
+		mux->RegisterSAPSignalHandler(aSAPSignalHandler);
+		}
+	else
+		{
+		TRAP(rerr, mux = CreateMuxerL(aAddr));
+		if(rerr == KErrNone)
+			{
+			mux->RegisterSAPSignalHandler(aSAPSignalHandler);
+			aSAPSignalHandler.ActiveConnectionRequest();
+			}
+		}
+	return rerr;	
+	}
+	
+	
+// This method adds a listening SAP signal handler to the list of current listeners.	
+void CL2CAPMuxController::AttachListeningSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler)
+	{
+	LOG_FUNC
+	iListeningSapSignalHandlers.AddLast(aSAPSignalHandler);
+	}
+
+// This method adds a bound SAP signal handler to the bound list.
+void CL2CAPMuxController::AttachBoundSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler)
+	{
+	LOG_FUNC
+	iBoundSapSignalHandlers.AddLast(aSAPSignalHandler);	
+	}
+
+TInt CL2CAPMuxController::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP)
+	{
+	LOG_FUNC
+	TInt retVal;
+	CL2CAPMux* muxer = FindMuxer(aAddr);
+	if(!muxer)
+		{
+		// If no error occurs, ownership of aSSP passes to the Mux;
+		TRAP(retVal, muxer = CreateMuxerL(aAddr));	
+		if(retVal == KErrNone)
+			{
+			TRAP(retVal, muxer->CompleteACLConnect(aSAP));
+			}
+		}
+	else
+		{
+		retVal = KErrAlreadyExists;
+		}
+
+	return retVal;
+	}
+	
+CL2CAPMux* CL2CAPMuxController::FindMuxer(const TBTDevAddr& aAddr)
+/**
+	Find muxer by BT address.
+	Lookup this address to find if there's a L2CAP Mux associated
+    with it
+**/
+	{
+	LOG_FUNC
+	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
+	muxIter.SetToFirst();
+	CL2CAPMux* muxerPtr = NULL;
+
+	while((muxerPtr = muxIter++) != NULL)
+		{
+		if(muxerPtr->RemoteBTAddr() == aAddr)
+			{
+			break;
+			}
+		}
+	return muxerPtr;
+	}	
+	
+CL2CAPMux* CL2CAPMuxController::CreateMuxerL(const TBTDevAddr& aAddr)
+/**
+   Create a new L2CAP Mux.
+   
+   The muxer returned is owned by this CL2CAPMuxController -- it
+   does not hand over ownership of the mux to the caller.
+
+   Note that this function does not check (except in debug) that there
+   is no existing muxer.
+
+**/
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(!FindMuxer(aAddr), Panic(EL2CAPMuxAlreadyExists));
+	
+	CL2CAPMux* muxer = CL2CAPMux::NewL(*this, aAddr);
+
+	iMuxers.AddFirst(*muxer);
+	return muxer;
+	}
+	
+CL2CapSAPSignalHandler* CL2CAPMuxController::FindListeningSignalHandler(TL2CAPPort aPort)
+	{
+	LOG_FUNC
+	/** Searches the listening Q for a SAP listening at PSM: aPort
+	@return the listening SAP found, or zero (NULL) if not found.
+	**/
+
+	TDblQueIter<CL2CapSAPSignalHandler> sapIter(iListeningSapSignalHandlers);
+	CL2CapSAPSignalHandler* sapSignalPtr;
+
+	while((sapSignalPtr = sapIter++) != NULL)
+		{
+		if(sapSignalPtr->LocalPort() == aPort)
+			return sapSignalPtr;
+		}
+
+	return NULL;
+	}
+
+CL2CapSAPSignalHandler* CL2CAPMuxController::FindIdleSignalHandler(TL2CAPPort aPort)
+	{
+	LOG_FUNC
+	/** Searches the bound Q for a SAP bound to PSM: aPort and if it doesn't find one it
+	    then searches the listening Q.
+	@return the idle SAP found, or zero (NULL) if not found.
+	**/
+
+	TDblQueIter<CL2CapSAPSignalHandler> sapIter(iBoundSapSignalHandlers);
+	CL2CapSAPSignalHandler* sapSignalPtr;
+	
+	while((sapSignalPtr = sapIter++) != NULL)
+		{
+		if(sapSignalPtr->LocalPort() == aPort)
+			return sapSignalPtr;
+		}
+
+	return FindListeningSignalHandler(aPort);
+	}
+
+void CL2CAPMuxController::UpdateMuxerPriorities()
+	{
+	LOG_FUNC
+	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
+	CL2CAPMux* muxerPtr;
+
+	// Lowest muxer priority.
+	TInt muxerPriority = EBaseMuxerPriority;
+	
+	// This starting value is equivalent to one or all of the channels
+	// open on a Mux being of priority low.
+	TInt currentSumMuxerPriorities = 0;
+	TInt nextSumMuxerPriorities;
+	TInt sum;
+	
+	while(currentSumMuxerPriorities != KMaxTInt)
+		{
+		nextSumMuxerPriorities = KMaxTInt;
+
+		muxIter.SetToFirst();
+		while((muxerPtr = muxIter++) != NULL)		
+			{
+			sum = muxerPtr->GetSumMuxerChannelPriorities();
+			if(sum == currentSumMuxerPriorities)
+				{
+				muxerPtr->MuxerPriorityUpdate(muxerPriority);
+				}
+			
+			if(sum > currentSumMuxerPriorities && sum < nextSumMuxerPriorities)
+				{
+				nextSumMuxerPriorities = sum;
+				}
+			}
+		currentSumMuxerPriorities = nextSumMuxerPriorities;
+		muxerPriority++;
+		}
+	}
+
+TInt CL2CAPMuxController::FindFreeUserPSM(TL2CAPPort& aPSM)
+	{
+	LOG_FUNC
+	TInt rerr = KErrL2CAPNoMorePSMs;
+	aPSM = KL2CapDynamicPSMStart;
+
+	// The PSM value will eventually wrap round if a free PSM
+	// can't be found.
+	while(aPSM >= KL2CapDynamicPSMStart)
+		{
+		if(FindIdleSignalHandler(aPSM) == NULL)
+			{
+			// There is not currently a SAP listening on this
+			// PSM, so this will be chosen.
+			rerr = KErrNone;
+			break;
+			}
+		aPSM+=2;
+		}
+
+	return rerr;
+	}
+