bluetooth/btstack/l2cap/l2capMuxController.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Holds a list of all Muxers and listening SAP signal handlers.
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 #include "l2capSAPSignalHandler.h"
       
    20 #include "l2capMuxController.h"
       
    21 #include "l2capCommand.h"
       
    22 #include "l2signalmgr.h"
       
    23 #include "l2util.h"
       
    24 
       
    25 #ifdef __FLOG_ACTIVE
       
    26 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP);
       
    27 #endif
       
    28 
       
    29 CL2CAPMuxController::~CL2CAPMuxController()
       
    30 	{
       
    31 	LOG_FUNC
       
    32 	// Delete all L2Cap Muxers 
       
    33 	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
       
    34 	CL2CAPMux* muxerPtr;
       
    35 	while((muxerPtr = muxIter++) != NULL)
       
    36 		{
       
    37 		delete muxerPtr;
       
    38 		}
       
    39 
       
    40 	// Delete all the listening SAP Signal Handlers 
       
    41 	TDblQueIter<CL2CapSAPSignalHandler> listeningSapIter(iListeningSapSignalHandlers);
       
    42 	CL2CapSAPSignalHandler* sapSignalPtr;
       
    43 	while((sapSignalPtr = listeningSapIter++) != NULL)
       
    44 		{
       
    45 		delete sapSignalPtr;
       
    46 		}
       
    47 		
       
    48 	// Delete all the bound SAP Signal Handlers 
       
    49 	TDblQueIter<CL2CapSAPSignalHandler> boundSapIter(iBoundSapSignalHandlers);
       
    50 	while((sapSignalPtr = boundSapIter++) != NULL)
       
    51 		{
       
    52 		delete sapSignalPtr;
       
    53 		}		
       
    54 	}
       
    55 
       
    56 	
       
    57 CL2CAPMuxController::CL2CAPMuxController(CL2CAPProtocol& aProtocol)
       
    58 	: 
       
    59 	iMuxers(_FOFF(CL2CAPMux, iMuxControllerLink)),
       
    60 	iBoundSapSignalHandlers(_FOFF(CL2CapSAPSignalHandler, iLink)),
       
    61 	iListeningSapSignalHandlers(_FOFF(CL2CapSAPSignalHandler, iLink)),
       
    62 	iProtocol(aProtocol)
       
    63 	{
       
    64 	LOG_FUNC
       
    65 	}
       
    66 
       
    67 // This method is called to register the signal handler owned by a cloned SAP to the
       
    68 // appropriate Mux.  A Mux should always be available as this event has been triggered
       
    69 // by receipt of an incoming connection.
       
    70 TInt CL2CAPMuxController::AttachPassiveSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler,const TBTDevAddr& aAddr)
       
    71 	{
       
    72 	LOG_FUNC
       
    73 	// Find the muxer and register the SAP SH.
       
    74 	TInt rerr = KErrNone;
       
    75 
       
    76 	CL2CAPMux* mux = FindMuxer(aAddr);
       
    77 	if(mux)
       
    78 		{
       
    79 		mux->RegisterSAPSignalHandler(aSAPSignalHandler);
       
    80 		}
       
    81 	else
       
    82 		{
       
    83 		rerr = KErrSessionClosed;
       
    84 		}
       
    85 	return rerr;
       
    86 	}
       
    87 	
       
    88 // This method is called to register an active SAP signal handler to the appropriate Mux.
       
    89 // If the Mux does not exist a new one will be allocated and tasked with establishing
       
    90 // an ACL connection.	
       
    91 TInt CL2CAPMuxController::AttachActiveSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler,const TBTDevAddr& aAddr)
       
    92 	{
       
    93 	LOG_FUNC
       
    94 	TInt rerr = KErrNone;
       
    95 	
       
    96 	CL2CAPMux* mux = FindMuxer(aAddr);
       
    97 	if(mux)
       
    98 		{
       
    99 		mux->RegisterSAPSignalHandler(aSAPSignalHandler);
       
   100 		}
       
   101 	else
       
   102 		{
       
   103 		TRAP(rerr, mux = CreateMuxerL(aAddr));
       
   104 		if(rerr == KErrNone)
       
   105 			{
       
   106 			mux->RegisterSAPSignalHandler(aSAPSignalHandler);
       
   107 			aSAPSignalHandler.ActiveConnectionRequest();
       
   108 			}
       
   109 		}
       
   110 	return rerr;	
       
   111 	}
       
   112 	
       
   113 	
       
   114 // This method adds a listening SAP signal handler to the list of current listeners.	
       
   115 void CL2CAPMuxController::AttachListeningSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler)
       
   116 	{
       
   117 	LOG_FUNC
       
   118 	iListeningSapSignalHandlers.AddLast(aSAPSignalHandler);
       
   119 	}
       
   120 
       
   121 // This method adds a bound SAP signal handler to the bound list.
       
   122 void CL2CAPMuxController::AttachBoundSignalHandler(CL2CapSAPSignalHandler& aSAPSignalHandler)
       
   123 	{
       
   124 	LOG_FUNC
       
   125 	iBoundSapSignalHandlers.AddLast(aSAPSignalHandler);	
       
   126 	}
       
   127 
       
   128 TInt CL2CAPMuxController::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP)
       
   129 	{
       
   130 	LOG_FUNC
       
   131 	TInt retVal;
       
   132 	CL2CAPMux* muxer = FindMuxer(aAddr);
       
   133 	if(!muxer)
       
   134 		{
       
   135 		// If no error occurs, ownership of aSSP passes to the Mux;
       
   136 		TRAP(retVal, muxer = CreateMuxerL(aAddr));	
       
   137 		if(retVal == KErrNone)
       
   138 			{
       
   139 			TRAP(retVal, muxer->CompleteACLConnect(aSAP));
       
   140 			}
       
   141 		}
       
   142 	else
       
   143 		{
       
   144 		retVal = KErrAlreadyExists;
       
   145 		}
       
   146 
       
   147 	return retVal;
       
   148 	}
       
   149 	
       
   150 CL2CAPMux* CL2CAPMuxController::FindMuxer(const TBTDevAddr& aAddr)
       
   151 /**
       
   152 	Find muxer by BT address.
       
   153 	Lookup this address to find if there's a L2CAP Mux associated
       
   154     with it
       
   155 **/
       
   156 	{
       
   157 	LOG_FUNC
       
   158 	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
       
   159 	muxIter.SetToFirst();
       
   160 	CL2CAPMux* muxerPtr = NULL;
       
   161 
       
   162 	while((muxerPtr = muxIter++) != NULL)
       
   163 		{
       
   164 		if(muxerPtr->RemoteBTAddr() == aAddr)
       
   165 			{
       
   166 			break;
       
   167 			}
       
   168 		}
       
   169 	return muxerPtr;
       
   170 	}	
       
   171 	
       
   172 CL2CAPMux* CL2CAPMuxController::CreateMuxerL(const TBTDevAddr& aAddr)
       
   173 /**
       
   174    Create a new L2CAP Mux.
       
   175    
       
   176    The muxer returned is owned by this CL2CAPMuxController -- it
       
   177    does not hand over ownership of the mux to the caller.
       
   178 
       
   179    Note that this function does not check (except in debug) that there
       
   180    is no existing muxer.
       
   181 
       
   182 **/
       
   183 	{
       
   184 	LOG_FUNC
       
   185 	__ASSERT_DEBUG(!FindMuxer(aAddr), Panic(EL2CAPMuxAlreadyExists));
       
   186 	
       
   187 	CL2CAPMux* muxer = CL2CAPMux::NewL(*this, aAddr);
       
   188 
       
   189 	iMuxers.AddFirst(*muxer);
       
   190 	return muxer;
       
   191 	}
       
   192 	
       
   193 CL2CapSAPSignalHandler* CL2CAPMuxController::FindListeningSignalHandler(TL2CAPPort aPort)
       
   194 	{
       
   195 	LOG_FUNC
       
   196 	/** Searches the listening Q for a SAP listening at PSM: aPort
       
   197 	@return the listening SAP found, or zero (NULL) if not found.
       
   198 	**/
       
   199 
       
   200 	TDblQueIter<CL2CapSAPSignalHandler> sapIter(iListeningSapSignalHandlers);
       
   201 	CL2CapSAPSignalHandler* sapSignalPtr;
       
   202 
       
   203 	while((sapSignalPtr = sapIter++) != NULL)
       
   204 		{
       
   205 		if(sapSignalPtr->LocalPort() == aPort)
       
   206 			return sapSignalPtr;
       
   207 		}
       
   208 
       
   209 	return NULL;
       
   210 	}
       
   211 
       
   212 CL2CapSAPSignalHandler* CL2CAPMuxController::FindIdleSignalHandler(TL2CAPPort aPort)
       
   213 	{
       
   214 	LOG_FUNC
       
   215 	/** Searches the bound Q for a SAP bound to PSM: aPort and if it doesn't find one it
       
   216 	    then searches the listening Q.
       
   217 	@return the idle SAP found, or zero (NULL) if not found.
       
   218 	**/
       
   219 
       
   220 	TDblQueIter<CL2CapSAPSignalHandler> sapIter(iBoundSapSignalHandlers);
       
   221 	CL2CapSAPSignalHandler* sapSignalPtr;
       
   222 	
       
   223 	while((sapSignalPtr = sapIter++) != NULL)
       
   224 		{
       
   225 		if(sapSignalPtr->LocalPort() == aPort)
       
   226 			return sapSignalPtr;
       
   227 		}
       
   228 
       
   229 	return FindListeningSignalHandler(aPort);
       
   230 	}
       
   231 
       
   232 void CL2CAPMuxController::UpdateMuxerPriorities()
       
   233 	{
       
   234 	LOG_FUNC
       
   235 	TDblQueIter<CL2CAPMux> muxIter(iMuxers);
       
   236 	CL2CAPMux* muxerPtr;
       
   237 
       
   238 	// Lowest muxer priority.
       
   239 	TInt muxerPriority = EBaseMuxerPriority;
       
   240 	
       
   241 	// This starting value is equivalent to one or all of the channels
       
   242 	// open on a Mux being of priority low.
       
   243 	TInt currentSumMuxerPriorities = 0;
       
   244 	TInt nextSumMuxerPriorities;
       
   245 	TInt sum;
       
   246 	
       
   247 	while(currentSumMuxerPriorities != KMaxTInt)
       
   248 		{
       
   249 		nextSumMuxerPriorities = KMaxTInt;
       
   250 
       
   251 		muxIter.SetToFirst();
       
   252 		while((muxerPtr = muxIter++) != NULL)		
       
   253 			{
       
   254 			sum = muxerPtr->GetSumMuxerChannelPriorities();
       
   255 			if(sum == currentSumMuxerPriorities)
       
   256 				{
       
   257 				muxerPtr->MuxerPriorityUpdate(muxerPriority);
       
   258 				}
       
   259 			
       
   260 			if(sum > currentSumMuxerPriorities && sum < nextSumMuxerPriorities)
       
   261 				{
       
   262 				nextSumMuxerPriorities = sum;
       
   263 				}
       
   264 			}
       
   265 		currentSumMuxerPriorities = nextSumMuxerPriorities;
       
   266 		muxerPriority++;
       
   267 		}
       
   268 	}
       
   269 
       
   270 TInt CL2CAPMuxController::FindFreeUserPSM(TL2CAPPort& aPSM)
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	TInt rerr = KErrL2CAPNoMorePSMs;
       
   274 	aPSM = KL2CapDynamicPSMStart;
       
   275 
       
   276 	// The PSM value will eventually wrap round if a free PSM
       
   277 	// can't be found.
       
   278 	while(aPSM >= KL2CapDynamicPSMStart)
       
   279 		{
       
   280 		if(FindIdleSignalHandler(aPSM) == NULL)
       
   281 			{
       
   282 			// There is not currently a SAP listening on this
       
   283 			// PSM, so this will be chosen.
       
   284 			rerr = KErrNone;
       
   285 			break;
       
   286 			}
       
   287 		aPSM+=2;
       
   288 		}
       
   289 
       
   290 	return rerr;
       
   291 	}
       
   292