bluetooth/btstack/rfcomm/rfcomm.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 // Implements the Protocol object
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 #include <e32def.h>
       
    20 #include "rfcomm.h"
       
    21 #include "rfcommstates.h"
       
    22 #include "rfcommmuxer.h"
       
    23 #include "rfcommmuxchannel.h"
       
    24 #include "rfcommconsts.h" 
       
    25 #include "bt.h"
       
    26 #include "l2cap.h"
       
    27 #include "IncomingConnListener.h"
       
    28 
       
    29 #ifdef __FLOG_ACTIVE
       
    30 _LIT8(KLogComponent, LOG_COMPONENT_RFCOMM);
       
    31 #endif
       
    32 
       
    33 CRfcommProtocol::CRfcommProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    34 :	CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan),
       
    35 	iMuxes(_FOFF(CRfcommMuxer, iLink)),
       
    36 	iListeningSAPs(_FOFF(CRfcommSAP, iListeningLink)),
       
    37 	iBoundSAPs(_FOFF(CRfcommSAP,iBoundLink)),
       
    38 	iCBFCDisallowed(EFalse)
       
    39 	{
       
    40 	LOG_FUNC
       
    41 	TCallBack cb(TryToClose, this);
       
    42 	iIdleTimerEntry.Set(cb);
       
    43 	}
       
    44 
       
    45 CRfcommProtocol::~CRfcommProtocol()
       
    46 	/**
       
    47 	   Destructor.
       
    48 	   We don't clear up the SAPs as they are owned by
       
    49 	   ESOCK and it is up to it to destroy them.
       
    50 	**/
       
    51 	{
       
    52 	LOG_FUNC
       
    53 	RemoveIdleTimerEntry();
       
    54 	if(LowerProtocol())
       
    55 		LowerProtocol()->Close();  // Matches the bind
       
    56 	delete iStateFactory;
       
    57 	delete iFlowStrategyFactory;
       
    58 	delete iMuxChannelStateFactory;
       
    59 #ifdef __FLOG_ACTIVE
       
    60 	CLOSE_LOGGER
       
    61 #endif
       
    62 	}
       
    63 
       
    64 CRfcommProtocol* CRfcommProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    65 	{
       
    66 #ifdef __FLOG_ACTIVE
       
    67 	CONNECT_LOGGER
       
    68 #endif
       
    69 	LOG_STATIC_FUNC
       
    70 	CRfcommProtocol* i=new (ELeave) CRfcommProtocol(aSecMan, aControlPlane, aCodMan);
       
    71 	CleanupStack::PushL(i);
       
    72 	i->ConstructL();
       
    73 	CleanupStack::Pop(i);
       
    74 	return i;
       
    75 	}
       
    76 
       
    77 void CRfcommProtocol::ConstructL()
       
    78 	{
       
    79 	LOG_FUNC
       
    80 	}
       
    81 
       
    82 void CRfcommProtocol::InitL(TDesC& /*aTag*/)
       
    83 /**
       
    84 	Pre-binding initialise.
       
    85 
       
    86 	Alloc any stuff we need.
       
    87 	This will only ever be called once during the lifetime of this
       
    88 	protocol.
       
    89 **/
       
    90 	{
       
    91 	LOG_FUNC
       
    92 	// Create all the things we need now
       
    93 	iStateFactory=CRfcommStateFactory::NewL();
       
    94 	iFlowStrategyFactory=CRfcommFlowStrategyFactory::NewL();
       
    95 	iMuxChannelStateFactory=CMuxChannelStateFactory::NewL();
       
    96 	}
       
    97 
       
    98 void CRfcommProtocol::StartL()
       
    99 /**
       
   100 	Binding complete.
       
   101 **/
       
   102 	{
       
   103 	LOG_FUNC
       
   104 	  // Should check that we're bound now.
       
   105 	  if(!LowerProtocol())
       
   106 	    {
       
   107 		User::Leave(KErrRfcommNotBound);
       
   108 	    }
       
   109 	}
       
   110 
       
   111 
       
   112 void CRfcommProtocol::BindToL(CProtocolBase* aProtocol)
       
   113   /***
       
   114       Request by Protocol Mgr to bind to the specified protocol.
       
   115       We can only be bound to one lower layer protocol, so the function leaves
       
   116       if we are already bound.
       
   117       @param aProtocol The protocol we need to bind to.
       
   118   **/
       
   119 	{
       
   120 	LOG_FUNC
       
   121 	if(!LowerProtocol())
       
   122 		{
       
   123 #ifdef _DEBUG
       
   124 		TServerProtocolDesc prtDesc;
       
   125 		aProtocol->Identify(&prtDesc);
       
   126 
       
   127 		if(prtDesc.iAddrFamily!=KBTAddrFamily ||
       
   128 		   prtDesc.iProtocol!=KL2CAP)
       
   129 			{
       
   130 			User::Leave(KErrBtEskError);
       
   131 			}
       
   132 #endif
       
   133 
       
   134 		iLowerProtocol=static_cast<CBluetoothProtocolBase*>(aProtocol);
       
   135 		LowerProtocol()->BindL(this, 0); // id not used
       
   136 		LowerProtocol()->Open();
       
   137 		}
       
   138 	else
       
   139 		{
       
   140 	    User::Leave(KErrRfcommAlreadyBound);
       
   141 		}
       
   142 	}
       
   143 
       
   144 // Factory functions
       
   145 
       
   146 CServProviderBase* CRfcommProtocol::NewSAPL(TUint aSockType)
       
   147   /** 
       
   148       Create a new SAP.
       
   149       The SAP returned is owned by the caller -- this protocol will
       
   150       not clean it up.  esock uses this function to create a new SAP,
       
   151       and esock will delete when it is finished with it.
       
   152   **/
       
   153 	{
       
   154 	LOG_FUNC
       
   155 
       
   156 	CRfcommSAP* sap=0;
       
   157 	
       
   158 	switch(aSockType)
       
   159 		{
       
   160 	case KSockStream:    // the connected type
       
   161 		sap=CRfcommSAP::NewL(*this);
       
   162 		break;
       
   163 	default:
       
   164 		User::Leave(KErrNotSupported);
       
   165 		break;
       
   166 		}
       
   167 	LOG1(_L("RFCOMM: NewSAPL created SAP %08x"), sap);
       
   168 	return sap;
       
   169 	}
       
   170 
       
   171 
       
   172 TInt CRfcommProtocol::StartProtocolListening()
       
   173 /**
       
   174 	A SAP has wanted to start us listening...we look after the values to do this
       
   175 **/
       
   176 	{
       
   177 	LOG_FUNC
       
   178 	TInt rerr = CBluetoothProtocolBase::StartListening(KRFCOMMPSM, KSockSeqPacket, KRFCOMMIncomingConnQueueSize, KUidServiceRfcomm);
       
   179 	if(rerr == KErrNone)
       
   180 		//	We should now have an L2Cap listener. 
       
   181 		//  Use it to setup L2Cap config for RFComm.
       
   182 		{
       
   183 		TL2CapConfigPkg configPkg;
       
   184 		SetL2CapConfig(configPkg);
       
   185 		rerr = Listener().SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configPkg);
       
   186 		if(rerr!=KErrNone)
       
   187 			{
       
   188 			StopProtocolListening(); //clean up
       
   189 			}
       
   190 		}
       
   191 	return rerr;
       
   192 	}
       
   193 
       
   194 // Query functions
       
   195 
       
   196 void CRfcommProtocol::SetL2CapConfig(TL2CapConfigPkg& aConfigPkg)
       
   197 /*
       
   198 	L2Cap configuration required by RFComm
       
   199 */
       
   200 	{
       
   201 	LOG_FUNC
       
   202 	aConfigPkg().ConfigureReliableChannel(TL2CapConfig::EDefaultRetransmission);
       
   203 	aConfigPkg().SetMaxReceiveUnitSize(KMaxL2CAPMTUAllowed);
       
   204 	}
       
   205 
       
   206 void CRfcommProtocol::Identify(TServerProtocolDesc *aDesc)const
       
   207 //
       
   208 // Identify request from SOCKET server
       
   209 //
       
   210 	{
       
   211 	LOG_FUNC
       
   212 	CRfcommProtocol::ProtocolIdentity(aDesc);
       
   213 	}
       
   214 
       
   215 void CRfcommProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc)
       
   216 	{
       
   217 	LOG_STATIC_FUNC
       
   218 	_LIT(name,"RFCOMM");
       
   219 	aDesc->iProtocol=KRFCOMM;
       
   220 
       
   221 	aDesc->iName=name;
       
   222 	aDesc->iAddrFamily=KBTAddrFamily;
       
   223 	aDesc->iSockType=KSockStream;
       
   224 	
       
   225 	aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild);
       
   226 	aDesc->iByteOrder=ELittleEndian;
       
   227 	aDesc->iServiceInfo=KRFCOMMStreamServiceInfo;
       
   228 	aDesc->iNamingServices=0;
       
   229 	aDesc->iSecurity=KSocketNoSecurity;
       
   230 	aDesc->iMessageSize=KSocketMessageSizeIsStream;
       
   231 	aDesc->iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains|EPreferDescriptors|EUseCanSend;
       
   232 	aDesc->iNumSockets=100;
       
   233 	}
       
   234 
       
   235 void CRfcommProtocol::CloseNow()
       
   236 	/**
       
   237 	   Our reference is now zero, so start to close.
       
   238 
       
   239 	   We don't actually close, merely Q a timer for a later close
       
   240 	   down.  This close can be prempted by another open.
       
   241 	**/
       
   242 	{
       
   243 	LOG_FUNC
       
   244 	iClosePending = ETrue;
       
   245 	QueIdleTimerEntry();
       
   246 	}
       
   247 
       
   248 void CRfcommProtocol::Open()
       
   249   /**
       
   250      Request to open the protocol.
       
   251      The protocol may be repeatedly opened and closed.  The order of calls is
       
   252      InitL, [Open *n , Close * n,  CloseNow] * m etc.
       
   253   **/
       
   254      {
       
   255 	LOG_FUNC
       
   256 	 iClosePending = EFalse;
       
   257 	 RemoveIdleTimerEntry();
       
   258 	 CProtocolBase::Open();
       
   259      }
       
   260      
       
   261 void CRfcommProtocol::Close()
       
   262 	/**
       
   263 	   This is one session closing.
       
   264 	**/
       
   265 	{
       
   266 	LOG_FUNC
       
   267 	CProtocolBase::Close();
       
   268 	}
       
   269 
       
   270 CRfcommFlowStrategyFactory* CRfcommProtocol::FlowStrategyFactory() const
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	return iFlowStrategyFactory;
       
   274 	}
       
   275 
       
   276 CRfcommStateFactory* CRfcommProtocol::StateFactory() const
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	return iStateFactory;
       
   280 	}
       
   281 
       
   282 TInt CRfcommProtocol::GetMux(TBTSockAddr& aRemoteAddr, CRfcommMuxer*& aMuxer)
       
   283 	/**
       
   284 	Gets a muxer for the given BT device address.
       
   285 	
       
   286 	If it finds the muxer or successfully creates a new muxer, it returns 
       
   287 	with KErrNone and a valid pointer to the correct muxer. On a failure, 
       
   288 	it will return with a standard error, without a pointer to  a muxer.
       
   289 	This flavour of GetMux is used when a muxer is being created in response 
       
   290 	to a local request to connect to a remote device (i.e. no existing 
       
   291 	L2CAP connection exists).
       
   292 	**/
       
   293 	{
       
   294 	LOG_FUNC
       
   295 	TBTDevAddr devAddr=aRemoteAddr.BTAddr();
       
   296 	aMuxer=FindMux(devAddr);
       
   297 
       
   298 	if(!aMuxer)
       
   299 		{
       
   300 		// Need to create one
       
   301 		TRAPD(err, aMuxer=CRfcommMuxer::NewL(*this, *LowerProtocol(), *iMuxChannelStateFactory));
       
   302 		if(err != KErrNone)
       
   303 			{
       
   304 			return err;
       
   305 			}
       
   306 
       
   307 		LOG1(_L("RFCOMM: (Outgoing) Creating new mux %08x"), aMuxer);
       
   308 		LOG6(_L(" for BT Device %02x %02x %02x %02x %02x %02x"), TUint8(devAddr[0]), TUint8(devAddr[1]), TUint8(devAddr[2]), TUint8(devAddr[3]), TUint8(devAddr[4]), TUint8(devAddr[5]));
       
   309 		// Add mux to the Q
       
   310 		iMuxes.AddFirst(*aMuxer);
       
   311 		aMuxer->Bind(devAddr);  // Sets the remote addr
       
   312 		}
       
   313 	
       
   314 	return KErrNone;
       
   315 	}
       
   316 
       
   317 TInt CRfcommProtocol::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP)
       
   318 	{
       
   319 	LOG_FUNC
       
   320 	CRfcommMuxer* muxer = NULL; // don't care about getting pointer to muxer
       
   321 	return GetMux(aAddr, aSAP, muxer);	//	NB If no error occurs, ownership of aSSP passes to the muxer.
       
   322 	}
       
   323 
       
   324 const TBTDevAddr& CRfcommProtocol::LocalBTAddr() const
       
   325 	{
       
   326 	LOG_FUNC
       
   327 	return static_cast<const CL2CAPProtocol*>(iLowerProtocol)->LocalBTAddr();
       
   328 	}
       
   329 
       
   330 TInt CRfcommProtocol::GetMux(const TBTDevAddr& aRemoteAddr, CServProviderBase* aL2CAPConSAP, CRfcommMuxer*& aMuxer)
       
   331 	/**
       
   332 	Gets a muxer for the given BT device address, using the L2CAP connection provided.
       
   333 	
       
   334 	If it is found that a muxer for the specified BT device already exists, 
       
   335 	KErrAlreadyExists will be returned. If a new muxer is successfully created, 
       
   336 	KErrNone will be returned along with a valid pointer to the correct muxer in aMuxer 
       
   337 
       
   338 	This flavour of GetMux is used when a muxer is being created in response to a 
       
   339 	remote request to connect to the local device (i.e. an L2CAP SAP has been created 
       
   340 	due to an incoming connection).
       
   341 	**/
       
   342 	{
       
   343 	LOG_FUNC
       
   344 #ifdef _DEBUG
       
   345 	//	Check that the device address and the device of the L2CAP remote address match!!
       
   346 	TBTSockAddr addr;
       
   347 	aL2CAPConSAP->RemName(addr);
       
   348 	__ASSERT_DEBUG(addr.BTAddr()==aRemoteAddr,Panic(ERfcommMismatchedAddressAndSAP));
       
   349 #endif//_DEBUG
       
   350 
       
   351 	aMuxer=FindMux(aRemoteAddr);
       
   352 	TInt err=KErrNone;
       
   353 	if(aMuxer!=NULL)	// i.e. a muxer already exists
       
   354 		err=KErrAlreadyExists;
       
   355 	else
       
   356 		{
       
   357 		TRAP(err, aMuxer=CRfcommMuxer::NewL(*this, aL2CAPConSAP, *iMuxChannelStateFactory));
       
   358 		LOG1(_L("RFCOMM: (Incoming) Creating new mux %08x"), aMuxer);
       
   359 		LOG6(_L(" for BT Device %02x %02x %02x %02x %02x %02x"),
       
   360 					  TUint8(aRemoteAddr[0]), TUint8(aRemoteAddr[1]), TUint8(aRemoteAddr[2]), TUint8(aRemoteAddr[3]),
       
   361 					  TUint8(aRemoteAddr[4]), TUint8(aRemoteAddr[5]));
       
   362 		
       
   363 		if(!err) 		// Add mux to the Q
       
   364 			iMuxes.AddFirst(*aMuxer);
       
   365 		}
       
   366 	return err;
       
   367 	}
       
   368 
       
   369 CRfcommMuxer* CRfcommProtocol::FindMux(const TBTDevAddr& aAddr)
       
   370 	/**
       
   371 	   Find the existing muxer for this address.
       
   372 	   @return  Pointer to a muxer for this address, or NULL if it doesn't exist.
       
   373 	**/	
       
   374 	{
       
   375 	LOG_STATIC_FUNC
       
   376 	TDblQueIter<CRfcommMuxer> iter(iMuxes);
       
   377 	CRfcommMuxer* mux;
       
   378 
       
   379 	while(iter)
       
   380 		{
       
   381 		mux=iter++;
       
   382 		// Find a mux aimed at the same addr, then check it's not on its way down
       
   383 		if((mux->iRemoteAddr == aAddr) && mux->iMuxChannel->CanAttachSAP())
       
   384 			{
       
   385 			// We have a mux, so return it
       
   386 			return mux;
       
   387 			}
       
   388 		}
       
   389 	// No mux
       
   390 	return NULL;
       
   391 	}
       
   392 
       
   393 void CRfcommProtocol::MuxDown(CRfcommMuxer& aMux)
       
   394 	/**
       
   395 	   Called by the mux when it's dying.
       
   396 
       
   397 	   We clean up and delete it.
       
   398 	**/
       
   399 	{
       
   400 	LOG_FUNC
       
   401 	LOG1(_L("RFCOMM: Mux %08x down"), &aMux);
       
   402 	aMux.iLink.Deque();
       
   403 	delete &aMux;
       
   404 
       
   405 	if(CheckForClose())
       
   406 		QueIdleTimerEntry();
       
   407 	}
       
   408 
       
   409 void CRfcommProtocol::AddIdleSAP(CRfcommSAP& aSAP)
       
   410 	/**
       
   411 	Used to inform the protocol of a SAP which has been told to listen
       
   412 	**/
       
   413 	{
       
   414 	LOG_FUNC
       
   415 #if defined(_DEBUG) || defined(__FLOG_ACTIVE)
       
   416 	TDblQueIter<CRfcommSAP> iter(iListeningSAPs);
       
   417 #endif
       
   418 
       
   419 #ifdef _DEBUG
       
   420 	//	Check that the SAP about to be added is not already on the listening list
       
   421 	CRfcommSAP* mySAP=NULL;
       
   422 	TBool found(EFalse);
       
   423 	while(iter && !found)
       
   424 		{
       
   425 		mySAP=iter++;
       
   426 		if(mySAP==&aSAP)	
       
   427 			found=ETrue;
       
   428 		}
       
   429 	if(found)
       
   430 		Panic(ERfcommRequeuingListeningSAP);
       
   431 #endif
       
   432 
       
   433 	iListeningSAPs.AddLast(aSAP);
       
   434 
       
   435 #ifdef __FLOG_ACTIVE
       
   436 	iter.SetToFirst();
       
   437 	while(iter)
       
   438 		{
       
   439 		LOG1(_L("RFCOMM: Listening on channel %d"),(iter++)->ServerChannel());
       
   440 		};
       
   441 #endif //__FLOG_ACTIVE
       
   442 	}
       
   443 
       
   444 void CRfcommProtocol::AddBoundSAP(CRfcommSAP& aSAP)
       
   445 	/**
       
   446 	Used to inform the protocol of a SAP which has been told to bind
       
   447 	**/
       
   448 	{
       
   449 	LOG_FUNC
       
   450 	#ifdef _DEBUG
       
   451 	TDblQueIter<CRfcommSAP> iter(iBoundSAPs);
       
   452 	//	Check that the SAP about to be added is not already on the Bound list
       
   453 	CRfcommSAP* mySAP=NULL;
       
   454 	TBool found(EFalse);
       
   455 	while(iter && !found)
       
   456 		{
       
   457 		mySAP=iter++;
       
   458 		if(mySAP==&aSAP)	
       
   459 			found=ETrue;
       
   460 		}
       
   461 	if(found)
       
   462 		Panic(ERfcommRequeuingBoundSAP);
       
   463 	#endif
       
   464 	
       
   465 	iBoundSAPs.AddLast(aSAP);
       
   466 	}
       
   467 	
       
   468 void CRfcommProtocol::RemoveIdleSAP(CRfcommSAP& aSAP)
       
   469 	/**
       
   470 	Used to inform the protocol of a listening SAP which is about to be destroyed
       
   471 	**/
       
   472 	{
       
   473 	LOG_FUNC
       
   474 #ifdef _DEBUG
       
   475 	//	Should check that the SAP about to be dequed is actually on the listening list
       
   476 	CRfcommSAP* SAP=NULL;
       
   477 	TBool found(EFalse);
       
   478 	TDblQueIter<CRfcommSAP> iter(iListeningSAPs);
       
   479 	while(iter && !found)
       
   480 		{
       
   481 		SAP=iter++;
       
   482 		if(SAP==&aSAP)	
       
   483 			found=ETrue;
       
   484 		}
       
   485 	if(!found)
       
   486 		Panic(ERfcommDequeingBadListeningSAP);
       
   487 #endif//_DEBUG
       
   488 
       
   489 	aSAP.iListeningLink.Deque();
       
   490 	}
       
   491 	
       
   492 void CRfcommProtocol::RemoveBoundSAP(CRfcommSAP& aSAP)
       
   493 	/**
       
   494 	Used to inform the protocol of a bound SAP which is about to be destroyed
       
   495 	**/
       
   496 	{
       
   497 	LOG_FUNC
       
   498 	//	check that the SAP about to be dequeued is actually on the bound list	
       
   499 	__ASSERT_DEBUG(SAPIsBound(aSAP),Panic(ERfcommDequeuingBadBoundSAP));
       
   500 
       
   501 	aSAP.iBoundLink.Deque();
       
   502 	}
       
   503 	
       
   504 TBool CRfcommProtocol::SAPIsBound(const CRfcommSAP& aSAP)
       
   505 	/**
       
   506 	Used to inform the protocol if a SAP is bound  
       
   507 	**/
       
   508 	{
       
   509 	LOG_FUNC
       
   510 	CRfcommSAP* SAP=NULL;
       
   511 	TBool found(EFalse);
       
   512 	TDblQueIter<CRfcommSAP> iter(iBoundSAPs);
       
   513 	
       
   514 	while(iter && !found)
       
   515 		{
       
   516 		SAP=iter++;
       
   517 		if(SAP==&aSAP)	
       
   518 			found=ETrue;
       
   519 		}
       
   520 
       
   521 	return found;
       
   522 	}
       
   523 
       
   524 CRfcommSAP* CRfcommProtocol::FindInboundConnectedSAP(const TBTSockAddr& aSockAddr)
       
   525 	/**
       
   526 	Used to enquire of the protocol whether there is a cloned SAP created from a SAP told to
       
   527 	listen on the specified address. This can be used to determine if a local Server Channel
       
   528 	is in use even though the original listening SAP no longer exists.
       
   529 
       
   530 	Returns NULL if no such SAP exists.
       
   531 	**/
       
   532 	{
       
   533 	LOG_FUNC
       
   534 	CRfcommSAP* SAP=NULL;
       
   535 	CRfcommMuxer* mux=NULL;
       
   536 	TUint8 dlci=0;
       
   537 
       
   538 	// Search for matching SAP across all Muxes	
       
   539 	TDblQueIter<CRfcommMuxer> iter(iMuxes);
       
   540 	while(iter && !SAP)
       
   541 		{
       
   542 		mux=iter++;
       
   543 		dlci=mux->MakeInboundDLCI(aSockAddr.Port());
       
   544 
       
   545 		SAP=mux->FindSAP(dlci);
       
   546 		}
       
   547 	return SAP;	
       
   548 	}
       
   549 	
       
   550 CRfcommSAP* CRfcommProtocol::FindIdleSAP(const TBTSockAddr& aSockAddr)
       
   551 	/**
       
   552 	Used to enquire of the protocol whether there is a SAP which has been told to listen on the specified address.
       
   553 
       
   554 	Returns NULL if no such SAP exists.
       
   555 	**/
       
   556 	{
       
   557 	LOG_FUNC
       
   558 	CRfcommSAP* SAP=NULL;
       
   559 	TDblQueIter<CRfcommSAP> iter(iListeningSAPs);
       
   560 	while(iter)
       
   561 		{
       
   562 		SAP=iter++;
       
   563 		if(SAP->ListeningTo(aSockAddr))
       
   564 			//	Found a SAP which is interested...
       
   565 			return SAP;
       
   566 		}
       
   567 	return NULL;
       
   568 	}
       
   569 	
       
   570 CRfcommSAP* CRfcommProtocol::FindBoundSAP(const TBTSockAddr& aSockAddr)
       
   571 	{
       
   572 	LOG_FUNC
       
   573 	CRfcommSAP* SAP=NULL;
       
   574 	TDblQueIter<CRfcommSAP> iter(iBoundSAPs);
       
   575 	while(iter)
       
   576 		{
       
   577 		SAP=iter++;
       
   578 		if(SAP->BoundTo(aSockAddr))
       
   579 			//	Found a SAP which is interested...
       
   580 			return SAP;
       
   581 		}
       
   582 	return NULL;
       
   583 	}
       
   584 
       
   585 TInt CRfcommProtocol::FindFreeServerChannel()
       
   586 	/**
       
   587 	Returns a server channel on which this device is not currently bound or listening
       
   588 	**/
       
   589 	{
       
   590 	LOG_FUNC
       
   591 	// Array indexed from 0 to 29 but valid server channels are 1 to 30 so
       
   592 	// valid server channel = index + 1
       
   593 	TFixedArray<TBool, KMaxRfcommServerChannel> channelInUse;
       
   594 
       
   595 	TDblQueIter<CRfcommSAP> iterListening(iListeningSAPs);
       
   596 	TDblQueIter<CRfcommSAP> iterBound(iBoundSAPs);
       
   597 	TDblQueIter<CRfcommMuxer> iterMuxes(iMuxes);
       
   598 	
       
   599 	for(TInt i = 0; i < KMaxRfcommServerChannel; i++)
       
   600 		{
       
   601 		channelInUse[i] = EFalse;
       
   602 		}
       
   603 
       
   604 	while(iterListening)
       
   605 		{
       
   606 		channelInUse[(*iterListening++).ServerChannel() - 1] = ETrue;
       
   607 		}
       
   608 		
       
   609 	while(iterBound)
       
   610 		{
       
   611 		channelInUse[(*iterBound++).ServerChannel() - 1] = ETrue;
       
   612 		}
       
   613 
       
   614 	// Need to check Muxes for cloned SAPs that are not taken account of already 
       
   615 	// because the associated listening SAP has been removed
       
   616 	while(iterMuxes)
       
   617 		{
       
   618 		(*iterMuxes++).GetInboundServerChannelsInUse(channelInUse);
       
   619 		}
       
   620 
       
   621 	TInt index = 0;
       
   622 	while(index < KMaxRfcommServerChannel && channelInUse[index++])
       
   623 		{
       
   624 		// Do nothing, index will be set appropriately when loop exits
       
   625 		}
       
   626 
       
   627 	return index < KMaxRfcommServerChannel ? index : KErrInUse;
       
   628 	}
       
   629 
       
   630 void CRfcommProtocol::DisallowCBFC()
       
   631 	{
       
   632 	LOG_FUNC
       
   633 	iCBFCDisallowed = ETrue;
       
   634 	}
       
   635 
       
   636 void CRfcommProtocol::AllowCBFC()
       
   637 	{
       
   638 	LOG_FUNC
       
   639 	iCBFCDisallowed = EFalse;
       
   640 	}
       
   641 
       
   642 TBool CRfcommProtocol::CBFCDisallowed()
       
   643 	{
       
   644 	LOG_FUNC
       
   645 	return iCBFCDisallowed;
       
   646 	}
       
   647 
       
   648 
       
   649 TBool CRfcommProtocol::CheckForClose()
       
   650 	/**
       
   651 	   Called to check whether we can close down
       
   652 	**/
       
   653 	{
       
   654 	LOG_FUNC
       
   655 	return (iClosePending && iMuxes.IsEmpty());
       
   656 	}
       
   657 
       
   658 TInt CRfcommProtocol::TryToClose(TAny* aProtocol)
       
   659 	{
       
   660 	LOG_STATIC_FUNC
       
   661 	CRfcommProtocol* p=static_cast<CRfcommProtocol*>(aProtocol);
       
   662 	p->iIdleEntryQueued = EFalse;
       
   663 	if (p->iClosePending && p->iMuxes.IsEmpty())
       
   664 		{
       
   665 
       
   666 		LOG(_L("RFCOMM: protocol can close now"));
       
   667 		p->CanClose();
       
   668 		}
       
   669 	return EFalse;
       
   670 	}
       
   671    
       
   672 void CRfcommProtocol::RemoveIdleTimerEntry()
       
   673 	/**
       
   674 	   Takes us off the idle timer Q, if we're on it.
       
   675 	**/
       
   676 	{
       
   677 	LOG_FUNC
       
   678 	if(iIdleEntryQueued)
       
   679 		{
       
   680 		LOG(_L("RFCOMM: Protocol removing timer entry"));
       
   681 		BTSocketTimer::Remove(iIdleTimerEntry);
       
   682 		iIdleEntryQueued=EFalse;
       
   683 		}
       
   684 	}
       
   685 
       
   686 void CRfcommProtocol::QueIdleTimerEntry()
       
   687 	/**
       
   688 	   Q a timer to delete us.
       
   689 	**/
       
   690 	{
       
   691 	LOG_FUNC
       
   692 	if(!iIdleEntryQueued)
       
   693 		{
       
   694 		LOG(_L("RFCOMM: Protocol adding timer entry"));
       
   695 		BTSocketTimer::Queue(KRfcommIdleTimeout, iIdleTimerEntry);
       
   696 		iIdleEntryQueued =  ETrue;
       
   697 		}
       
   698 	}
       
   699