bluetooth/btstack/avctp/avctp.cpp
changeset 0 29b1cd4cb562
child 13 20fda83a6398
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2005-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 AVCTP protocol object
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include <e32def.h>
       
    24 #include <bluetooth/logger.h>
       
    25 #include <bluetoothav.h>
       
    26 
       
    27 #include "Avctp.h"
       
    28 #include "avctpsap.h"
       
    29 #include "avctpmuxerstates.h"
       
    30 #include "avctpconstants.h" 
       
    31 #include "IncomingConnListener.h"
       
    32 #include "avctpPacketMgr.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_AVCTP);
       
    36 #endif
       
    37 
       
    38 #ifdef _DEBUG
       
    39 PANICCATEGORY("avctp");
       
    40 #endif
       
    41 
       
    42 using namespace SymbianAvctp;
       
    43 
       
    44 #include "avctpmuxer.h"
       
    45 
       
    46 
       
    47 
       
    48 #ifdef __FLOG_ACTIVE
       
    49 #define LOG_SAPS LogSaps();
       
    50 #define LOG_MUXERS LogMuxers();
       
    51 #define LOG_SAPLINKSMGRS LogSapLinkMgrs();
       
    52 #else
       
    53 #define LOG_SAPS
       
    54 #define LOG_MUXERS
       
    55 #define LOG_SAPLINKSMGRS
       
    56 #endif
       
    57 
       
    58 /** 
       
    59 Protocol object constructor.
       
    60 
       
    61 @see CBTSecMan
       
    62 @param aSecMan The Bluetooth security manager
       
    63 @param aControlPlane the object which the protocol can use to pass control plane messages
       
    64 @param aCodMan the CoD manager for the protocol
       
    65 @return A pointer to the AVCTP protocol object
       
    66 @internalComponent
       
    67 */
       
    68 CAvctpProtocol::CAvctpProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    69 :	CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan),
       
    70 	iSaps(_FOFF(CAvctpSap, iQueLink)),
       
    71 	iTransports(_FOFF(CAvctpTransport, iQueLink)),
       
    72 	iIpidResponses(_FOFF(HAvctpOutgoingSdu, iQueLink))
       
    73 	{
       
    74 	LOG_FUNC
       
    75 	
       
    76 	TCallBack callBack(TryToClose, this);
       
    77 	iIdleTimerEntry.Set(callBack);
       
    78 	}
       
    79 
       
    80 /** Static protocol object factory function.
       
    81 
       
    82 Leaves the protocol object on the cleanup stack.
       
    83 
       
    84 @see CBTSecMan
       
    85 @param aSecMan The Bluetooth security manager
       
    86 @param aControlPlane the object which the protocol can use to pass control plane messages
       
    87 @param aCodMan the CoD manager for the protocol
       
    88 @return A pointer to the AVCTP protocol object
       
    89 @leave KErrNoMemory if the protocol object could not be created
       
    90 @internalComponent
       
    91 */
       
    92 CAvctpProtocol* CAvctpProtocol::NewLC(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    93 	{
       
    94 	CONNECT_LOGGER
       
    95 	LOG_STATIC_FUNC
       
    96 	CAvctpProtocol* self = new(ELeave) CAvctpProtocol(aSecMan, aControlPlane, aCodMan);
       
    97 	CleanupStack::PushL(self);
       
    98 	self->ConstructL();
       
    99 	return self;
       
   100 	}
       
   101 
       
   102 /** Static protocol object factory function.
       
   103 
       
   104 @see CBTSecMan
       
   105 @param aSecMan The Bluetooth security manager
       
   106 @param aControlPlane the object which the protocol can use to pass control plane messages
       
   107 @param aCodMan the CoD manager for the protocol
       
   108 @return A pointer to the AVCTP protocol object
       
   109 @leave KErrNoMemory if the protocol object could not be created
       
   110 @internalComponent
       
   111 */
       
   112 CAvctpProtocol* CAvctpProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
   113 	{
       
   114 	LOG_STATIC_FUNC
       
   115 	CAvctpProtocol* self = CAvctpProtocol::NewLC(aSecMan, aControlPlane, aCodMan);
       
   116 	CleanupStack::Pop(self);
       
   117 	return self;
       
   118 	}
       
   119 
       
   120 /** Protocol object second-phase construction.
       
   121 
       
   122 @internalComponent
       
   123 */
       
   124 void CAvctpProtocol::ConstructL()
       
   125 	{
       
   126 	LOG_FUNC
       
   127 	iMuxerStateFactory = CAvctpMuxerStateFactory::NewL();
       
   128 
       
   129 	TCallBack cb(IpidAsyncCallBack, this);
       
   130 	iIpidResponseAsyncCallBack = new (ELeave)CAsyncCallBack(cb, EActiveHighPriority);
       
   131 	
       
   132 	}
       
   133 
       
   134 /** Protocol object destructor.
       
   135 
       
   136 We don't clear up the SAPs, or the Muxer Collections as they are owned by ESock
       
   137 and it is up to it to destroy them.
       
   138 
       
   139  muxers are owned by the protocol and so should be destroyed by it.
       
   140 
       
   141 @internalComponent
       
   142 */
       
   143 CAvctpProtocol::~CAvctpProtocol()
       
   144 	{
       
   145 	LOG_FUNC
       
   146 	
       
   147 	DequeIdleTimer();
       
   148 
       
   149 	if (LowerProtocol())
       
   150 		{
       
   151 		LowerProtocol()->Close();  // Matches the bind
       
   152 		}
       
   153 
       
   154 	CancelIpidAsyncCallBack();
       
   155 	delete iIpidResponseAsyncCallBack;
       
   156 
       
   157 	TDblQueIter<HAvctpOutgoingSdu> sduIter(iIpidResponses);
       
   158 	while(sduIter)
       
   159 		{
       
   160 		delete sduIter++; // deques sdu
       
   161 		}				
       
   162 	TDblQueIter<CAvctpTransport> muxerIter(iTransports);
       
   163 	while(muxerIter)
       
   164 		{
       
   165 		delete muxerIter++; // deques muxer
       
   166 		}	
       
   167 
       
   168 	delete iMuxerStateFactory;
       
   169 	// iListener is deleted through CBluetoothProtocolBase
       
   170 	delete iSecondChannelListener;
       
   171 	iClientItems.Close();
       
   172 	
       
   173 	
       
   174 	}
       
   175 
       
   176 /** Pre-binding initialise.
       
   177 
       
   178 Alloc any stuff we need. This will only ever be called once during the lifetime of this protocol.
       
   179 
       
   180 @internalAll
       
   181 @leave KErrNoMemory if the state factory cannot be created
       
   182 @param aTag The strin   g identifier for the protocol from the ESock ini file
       
   183 */
       
   184 void CAvctpProtocol::InitL(TDesC& /*aTag*/)
       
   185 	{
       
   186 	LOG_FUNC
       
   187 	}
       
   188 
       
   189 /** Binding complete.
       
   190 
       
   191 @internalAll
       
   192 */
       
   193 void CAvctpProtocol::StartL()
       
   194 	{
       
   195 	LOG_FUNC
       
   196 
       
   197 	// Should check that we're bound now.
       
   198 	if (!iLowerProtocol)
       
   199 		{
       
   200 		User::Leave(ENotBound);
       
   201 		}
       
   202 	User::LeaveIfError(IncrementListeners());
       
   203 	}
       
   204 
       
   205 /** Request by Protocol Mgr to bind to the specified protocol. 
       
   206 
       
   207 We can only be bound to one lower layer protocol, so the function leaves if we are already bound.
       
   208 
       
   209 @internalAll
       
   210 @leave KErrProtocolAlreadyBound if we are already bound, and any other leave from the lower protocol's BindL()
       
   211 @param aProtocol The protocol we need to bind to.
       
   212 */
       
   213 void CAvctpProtocol::BindToL(CProtocolBase* aProtocol)
       
   214 	{
       
   215 	LOG_FUNC
       
   216 
       
   217 	if(!iLowerProtocol)
       
   218 		{
       
   219 #ifdef _DEBUG
       
   220 		TServerProtocolDesc prtDesc;
       
   221 		aProtocol->Identify(&prtDesc);
       
   222 
       
   223 		if(prtDesc.iAddrFamily != KBTAddrFamily ||
       
   224 		   prtDesc.iProtocol != KL2CAP)
       
   225 			{
       
   226 			User::Leave(KErrBtEskError);
       
   227 			}
       
   228 #endif
       
   229 
       
   230 		iLowerProtocol=static_cast<CBluetoothProtocolBase*>(aProtocol);
       
   231 		iLowerProtocol->BindL(this, 0); // id not used
       
   232 		iLowerProtocol->Open();
       
   233 		}
       
   234 	else
       
   235 		{
       
   236 	    User::Leave(KErrProtocolAlreadyBound);
       
   237 		}
       
   238 	}
       
   239 
       
   240 /** Create a new SAP.
       
   241 
       
   242 The SAP returned is owned by the caller -- this protocol will not clean it up.
       
   243 ESock uses this function to create a new SAP, and ESock will delete when it is
       
   244 finished with it.
       
   245 
       
   246 @internalAll
       
   247 @leave KErrNotSupported if aSockType is not KSockDatagram, KErrNoMemory if a
       
   248      new SAP could not be created
       
   249 @param aSockType The socket type for the SAP: AVCTP only supports KSockDatagram
       
   250 @return A pointer to a new SAP
       
   251 */
       
   252 CServProviderBase* CAvctpProtocol::NewSAPL(TUint aSockType)
       
   253 	{
       
   254 	LOG_FUNC
       
   255 
       
   256 	CBluetoothSAP* sap = NULL;
       
   257 	
       
   258 	switch(aSockType)
       
   259 		{
       
   260 	case KSockDatagram:    // AVCTP uses datagrams for data SAPs
       
   261 		sap = CAvctpSap::NewL(*this);
       
   262 		break;
       
   263 	case KSockRaw:    // AVCTP uses Raw for control SAPs
       
   264 		sap = CAvctpControlSAP::NewL(*this);
       
   265 		break;
       
   266 	default:
       
   267 		User::Leave(KErrNotSupported);
       
   268 		break;
       
   269 		}
       
   270 
       
   271 	return sap;
       
   272 	}
       
   273 	
       
   274 
       
   275 /** Identify the protocol.
       
   276 
       
   277 The descriptor is filled in to identify the protocol to ESock.
       
   278 
       
   279 @internalAll
       
   280 @param aDesc A pointer to the descriptor to be filled in
       
   281 */
       
   282 void CAvctpProtocol::Identify(TServerProtocolDesc* aDesc) const
       
   283 	{
       
   284 	LOG_FUNC
       
   285 
       
   286 	ProtocolIdentity(aDesc);
       
   287 	}
       
   288 
       
   289 /** Fill in the protocol descriptor.
       
   290 
       
   291 This is a static utility function to fill in the protocol details.
       
   292 
       
   293 @internalComponent
       
   294 @param aDesc A pointer to the descriptor to be filled in
       
   295 */
       
   296 void CAvctpProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc)
       
   297 	{
       
   298 	LOG_STATIC_FUNC
       
   299 
       
   300 	_LIT(KAvctpProtocolName,"AVCTP"); 
       
   301 	aDesc->iName			= KAvctpProtocolName;
       
   302 	aDesc->iAddrFamily		= KBTAddrFamily;
       
   303 	aDesc->iSockType		= KUndefinedSockType; // can support datagram AND raw
       
   304 	aDesc->iProtocol		= KAVCTP;
       
   305 	aDesc->iVersion			= TVersion(KBTMajor,KBTMinor,KBTBuild);
       
   306 	aDesc->iByteOrder		= ELittleEndian;
       
   307 	aDesc->iServiceInfo		= KServiceInfo;
       
   308 	aDesc->iNamingServices	= NULL;
       
   309 	aDesc->iSecurity		= KSocketNoSecurity; // cause we do our own
       
   310 	aDesc->iMessageSize		= KSocketMessageSizeNoLimit; // we can fragment to our heart's content
       
   311 	aDesc->iServiceTypeInfo	= KServiceTypeInfo;
       
   312 	aDesc->iNumSockets		= KMaxNumSocketsInProtocol;
       
   313 	}
       
   314 
       
   315 /** Our protocol reference in esock is now zero, so start to close.
       
   316 
       
   317 We don't actually close, merely Q a timer for a later close down.
       
   318 This close can be pre-empted by another open.
       
   319 
       
   320 @internalAll
       
   321 */
       
   322 void CAvctpProtocol::CloseNow()
       
   323 	{
       
   324 	LOG_FUNC
       
   325 
       
   326 	iClosePending = ETrue;
       
   327 	
       
   328 	// We can only assert there are no saps cause the sap links mgrs are asynchronously deleted
       
   329 	// and so may still be around at this point. However they should've been deleted by the
       
   330 	// time TryToClose is called so we assert IsIdle() there.
       
   331 	ASSERT_DEBUG(iSaps.IsEmpty());
       
   332 	
       
   333 	QueIdleTimer();
       
   334 	}
       
   335 
       
   336 /** Request to open the protocol.
       
   337 
       
   338 The protocol may be repeatedly opened and closed.  The order of calls is
       
   339 InitL, [Open *n , Close * n,  CloseNow] * m etc.
       
   340 
       
   341 @internalAll
       
   342 */
       
   343 void CAvctpProtocol::Open()
       
   344 	{
       
   345 	LOG_FUNC
       
   346 
       
   347 	iClosePending = EFalse;
       
   348 	DequeIdleTimer();
       
   349 	CProtocolBase::Open();
       
   350 	}
       
   351 
       
   352 /**
       
   353    This is one session closing.
       
   354 */
       
   355 void CAvctpProtocol::Close()
       
   356 
       
   357 	{
       
   358 	LOG_FUNC
       
   359 	CProtocolBase::Close();
       
   360 	}
       
   361 
       
   362 
       
   363 /**
       
   364 Helper to actually start listening. This protocol doesn't use the base class
       
   365 implementation as it needs to do a bit more.
       
   366 @internalComponent
       
   367 */
       
   368 void CAvctpProtocol::DoStartAvctpListeningL()
       
   369 	{	
       
   370 	LOG_FUNC
       
   371 
       
   372 	const TUint KDefaultMtu = 335;
       
   373 	
       
   374 	CServProviderBase* sap =iLowerProtocol->NewSAPL(KSockSeqPacket);
       
   375 	CleanupStack::PushL(sap);
       
   376 	
       
   377 	TBTSockAddr localAddr;
       
   378 	localAddr.SetPort(KAVCTP);
       
   379 
       
   380 	// the security settings are:	
       
   381 	// (though see :Preauthorise() for the authentication exceptions due to avdtp authentication)
       
   382 	TBTServiceSecurity sec;
       
   383 	sec.SetAuthentication(KInboundAuthenticationDefault);
       
   384 	sec.SetAuthorisation(KInboundAuthoristationDefault);
       
   385 	sec.SetEncryption(KInboundEncryptionDefault);
       
   386 	sec.SetDenied(EFalse);
       
   387 	sec.SetUid(KAvctpServiceUid);
       
   388 	localAddr.SetSecurity(sec);
       
   389 	
       
   390 	CleanupStack::Pop(sap);
       
   391 	iListener = CIncomingConnectionListener::NewL(*this, sap, localAddr, KProtocolListeningQueueSize);										
       
   392 	
       
   393 	CServProviderBase* sap2 =iLowerProtocol->NewSAPL(KSockSeqPacket);
       
   394 	CleanupStack::PushL(sap2);
       
   395 	
       
   396 	TPckgBuf<TL2CapConfig> config;
       
   397 	config().SetMaxTransmitUnitSize(KAvctpSecondaryChannelInboundMTU);
       
   398 	config().SetMinMTU(KDefaultMtu);
       
   399 	config().SetMaxReceiveUnitSize(KAvctpSecondaryChannelInboundMTU);
       
   400 	config().SetMinMRU(KDefaultMtu);
       
   401 	
       
   402 	__DEBUG_ONLY(TInt err =) sap2->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, config); 
       
   403 	__ASSERT_DEBUG(err == KErrNone, Panic(ESetOptionError));
       
   404 	
       
   405 	// security for the secondary channel is not required
       
   406 	sec.SetAuthentication(KSecondaryChannelAuthenticationDefault);
       
   407 	sec.SetAuthorisation(KSecondaryChannelAuthoristationDefault);
       
   408 	sec.SetEncryption(KInboundEncryptionDefault);
       
   409 	sec.SetDenied(EFalse);
       
   410 	sec.SetUid(KAvctpServiceUid);	
       
   411 	localAddr.SetSecurity(sec);
       
   412 	localAddr.SetPort(KAvctpSecondChannelPSM);
       
   413 	
       
   414 	CleanupStack::Pop(sap2);
       
   415 	iSecondChannelListener  = CIncomingConnectionListener::NewL(*this, sap2, localAddr, KProtocolListeningQueueSize);										
       
   416 	}
       
   417 
       
   418 /**
       
   419 AVCTP connection listener connect complete function (cloned SAP overload).
       
   420 
       
   421 Part of the MSocketNotify interface.
       
   422 
       
   423 Called by the listening L2CAP SAP when an incoming connection occurs.
       
   424 
       
   425 This checks with the protocol to check for an existing muxer - if there
       
   426 is one, an error is returned and the new L2CAP SAP is shut down (the 
       
   427 remote device should be using the existing muxer). If not, the SAP is
       
   428 given to the muxer.
       
   429 
       
   430 @internalAll
       
   431 @param aSap The SAP for the new lower layer connection
       
   432 */
       
   433 TInt CAvctpProtocol::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSSP)
       
   434 	{
       
   435 	LOG_FUNC
       
   436 	
       
   437 	IF_FLOGGING
       
   438 		(
       
   439 		TBuf<KBTAddressLength> address; 
       
   440 		aAddr.GetReadable(address);
       
   441 		)
       
   442 		
       
   443 	LOG1(_L("from BT Device 0x%S"), &address);
       
   444 	
       
   445 	// NB: If no error occurs, ownership of aSSP passes to the muxer.
       
   446 	// If an error does occur then the CIncomingConnectionListener will take care of aSSP for us
       
   447 	TInt err = AttachInboundConnectionToTransport(aAddr, aSSP);
       
   448 	
       
   449 	return err;
       
   450 	}
       
   451 
       
   452 
       
   453 
       
   454 /**
       
   455 Control plane message delivery system between protocols
       
   456 @return error as a result of processing or not consuming the control message
       
   457 @param aMessage the message
       
   458 @param aParam arbitrary data for message - knowledge of aMessage allows casting
       
   459 @see CBTProtocolFamily
       
   460 @internalComponent
       
   461 */
       
   462 TInt CAvctpProtocol::ControlPlaneMessage(TBTControlPlaneMessage aMessage, TAny* aParam)
       
   463 	{
       
   464 	LOG_FUNC
       
   465 
       
   466 	// only ones applicable to this protocol at present are 
       
   467 	// for preauthorising a device - must have come from AVCTP, with PID=RCP
       
   468 	TInt ret = KErrNotSupported;
       
   469 	
       
   470 	switch (aMessage)
       
   471 		{
       
   472 		case EPreauthoriseDevice:
       
   473 			{
       
   474 			__ASSERT_DEBUG(aParam, Panic(EProtocolReceivingBadlyFormedControlMessage));
       
   475 			const TOverrideAuthorise& override = *reinterpret_cast<const TOverrideAuthorise*>(aParam);
       
   476 			__ASSERT_DEBUG(override.iAuthorisingProtocol == KAVDTP, Panic(EProtocolReceivingControlFromUnexpectedProtocol));
       
   477 			
       
   478 			SetPreauthorisation(override.iPreauthorisedRemoteAddress,
       
   479 								override.iPreauthorise);
       
   480 			ret = KErrNone;							
       
   481 			break;
       
   482 			}
       
   483 		default:
       
   484 			__ASSERT_DEBUG(aParam, Panic(EProtocolReceivingBadlyFormedControlMessage));
       
   485 		}
       
   486 	return ret;
       
   487 	}
       
   488 
       
   489 /**
       
   490 Helper to hide the need to supply the socket level to which preauthorisation pertains
       
   491 @param aPreauthoriseAddress the address of the device to preauthorise
       
   492 @param aSetPreauthorisation ETrue if the device is allowed to be authorised for other AVDTP/AVCTP connection, EFalse to cancel
       
   493 @internalComponent
       
   494 */
       
   495 TInt CAvctpProtocol::SetPreauthorisation(const TBTDevAddr& aPreauthoriseAddress, TBool aSetPreauthorisation)
       
   496 	{
       
   497 	LOG_FUNC
       
   498 
       
   499 	TInt ret = KErrNone;
       
   500 	if (IsListening())
       
   501 		{
       
   502 		if (aSetPreauthorisation && !Listener().IsPreauthorised(KSolBtL2CAP, aPreauthoriseAddress))
       
   503 			{
       
   504 			Listener().SetPreauthorisation(KSolBtL2CAP, aPreauthoriseAddress, ETrue);
       
   505 
       
   506 			// tell AVDTP
       
   507 			TOverrideAuthorise override;
       
   508 			override.iAuthorisingProtocol = KAVCTP;
       
   509 			override.iAuthorisingPort = KAvrcpPid;			
       
   510 			override.iPreauthorise = aSetPreauthorisation;
       
   511 			override.iPreauthorisedRemoteAddress = aPreauthoriseAddress;
       
   512 			
       
   513 			ControlPlane().Preauthorise(KAVDTP, override);
       
   514 
       
   515 			}
       
   516 		else if (!aSetPreauthorisation)
       
   517 			{
       
   518 			Listener().SetPreauthorisation(KSolBtL2CAP, aPreauthoriseAddress, EFalse);			
       
   519 			}
       
   520 		// else do nothing
       
   521 		}
       
   522 	else
       
   523 		{
       
   524 		ret = KErrNotReady;
       
   525 		}
       
   526 	return ret;
       
   527 	}
       
   528 
       
   529 
       
   530 
       
   531 //
       
   532 // Interface to all Saps provided for the muxers
       
   533 
       
   534 /**
       
   535   Used by a muxer to tell the saps that it is now in a position to 
       
   536   send data
       
   537 	
       
   538   @param aRemoteAddr the remote address which they an now send to.
       
   539   @internalComponent
       
   540 */
       
   541 void CAvctpProtocol::SignalCanSendToSaps(CAvctpPacketMgr& IF_FLOGGING(aPacketMgr))
       
   542 	{
       
   543 	LOG_FUNC
       
   544 	LOG1(_L("from Packetgr 0x%08x"), &aPacketMgr);
       
   545 	
       
   546 	// kick off the ipid sending process.
       
   547 	StartSendIpidAsyncCallBack();
       
   548 	
       
   549 	TDblQueIter<CAvctpSap> sapIter(iSaps);
       
   550 	CAvctpSap* sap;
       
   551 	while(sapIter)
       
   552 		{
       
   553 		sap = sapIter++;
       
   554 		sap->CanSend(); 
       
   555 		}	
       
   556 	}
       
   557 	 
       
   558 /**
       
   559   Find out whether there are any saps with data for the given remote address
       
   560   @param aRemoteAddr the remote device which might have data for it
       
   561   @return ETrue if there is such a sap, EFalse otherwise
       
   562   @internalComponent
       
   563 **/	
       
   564 TBool CAvctpProtocol::SapsHaveDataFor(const TBTDevAddr& aRemoteAddr)
       
   565 	{
       
   566 	LOG_FUNC
       
   567 	IF_FLOGGING
       
   568 		(
       
   569 		TBuf<KBTAddressLength> address;
       
   570 		aRemoteAddr.GetReadable(address);
       
   571 		)
       
   572 
       
   573 	LOG1(_L("from BT Device 0x%S"), &address);
       
   574 
       
   575 	TDblQueIter<CAvctpSap> iter(iSaps);
       
   576 	CAvctpSap* sap;
       
   577 	TBool ans = EFalse;
       
   578 	
       
   579 	while(iter)
       
   580 		{
       
   581 		sap = iter++;
       
   582 		if(sap->HasDataFor(aRemoteAddr))
       
   583 			{
       
   584 			ans = ETrue;
       
   585 			break;
       
   586 			}
       
   587 		}
       
   588 
       
   589 	LOG1(_L("result %d"), ans);
       
   590 	return ans;
       
   591 	}
       
   592 	
       
   593 /**
       
   594 Note the a TAvctpHeaderInfo could be provided as a parameter to this function
       
   595 but since the HAvctpIncomingSdu data contains this info too, there's a danger
       
   596 that the TAvctpHeaderInfo would not match the actual sdu. Hence the header
       
   597 info class isn't provided. This isn't a big cost cause it's quick to pull 
       
   598 the transaction label, PID etc out of the sdu itself.
       
   599 */
       
   600 void CAvctpProtocol::SignalNewDataToSaps(HAvctpIncomingSdu* aSdu, TInt aChannel)
       
   601 	{
       
   602 	LOG_FUNC
       
   603 
       
   604 	// Give data to each sap in turn to see if they want the PDU
       
   605 	TDblQueIter<CAvctpSap> iter(iSaps);
       
   606 	CAvctpSap* sap;
       
   607 	TBool sapAcceptedData = EFalse;
       
   608 	while(iter)
       
   609 		{
       
   610 		sap = iter++;
       
   611 		sapAcceptedData = sap->NewData(aSdu, aChannel);
       
   612 		if (sapAcceptedData)
       
   613 			{
       
   614 			break; // Once one accepts it, there's no point giving the data to the others
       
   615 			}
       
   616 		}					  	 
       
   617 
       
   618 	if (!sapAcceptedData)
       
   619 		{
       
   620 		// This is not for a registered PID.  If this is a command we should
       
   621 		// return an IPID response, if not we just dump it.  Crazy remote!
       
   622 		TAvctpStartHeaderInfo headerInfo;
       
   623 		TInt err = CAvctpPacket::ParseHeader(aSdu->Data(), headerInfo);
       
   624 		
       
   625 		if(!err && headerInfo.iMsgType == SymbianAvctp::ECommand)
       
   626 			{
       
   627 			HAvctpOutgoingSdu* ipidSdu = NULL;
       
   628 			TRAPD(ret, ipidSdu = HAvctpOutgoingSdu::NewIpidResponseL(*aSdu, aChannel));
       
   629 			if (ret == KErrNone)
       
   630 				{
       
   631 				iIpidResponses.AddLast(*ipidSdu);
       
   632 				StartSendIpidAsyncCallBack();
       
   633 				}
       
   634 			}
       
   635 		// else - we've OOM & we'll have to break the AVCTP spec & not send an IPID response :(
       
   636 		// or it's a response that we can't re-respond to.
       
   637 
       
   638 		// No one took the data so we need to clean it up
       
   639 		delete aSdu;
       
   640 		}
       
   641 	}
       
   642 
       
   643 /**
       
   644 This function is called when a muxer goes down and is used to inform Saps
       
   645 of this fact so they can get rid of any packets that are now stale.
       
   646 */
       
   647 void CAvctpProtocol::SignalMuxerDownToSaps(const TBTDevAddr& aRemoteAddr)
       
   648 	{
       
   649 	LOG_FUNC
       
   650 
       
   651 	IF_FLOGGING
       
   652 		(
       
   653 		TBuf<KBTAddressLength> address;
       
   654 		aRemoteAddr.GetReadable(address);
       
   655 		)
       
   656 
       
   657 	LOG1(_L("from BT Device 0x%S"), &address);
       
   658 	
       
   659 	TDblQueIter<CAvctpSap> iter(iSaps);
       
   660 	CAvctpSap* sap;
       
   661 	
       
   662 	while(iter)
       
   663 		{
       
   664 		sap = iter++;
       
   665 		sap->MuxerDown(aRemoteAddr);
       
   666 		}					  	 
       
   667 	}
       
   668 
       
   669 //
       
   670 // Que Management Functions	 
       
   671 
       
   672 /** 
       
   673 Adds a SAP to their queue.
       
   674 Ensures that there will only ever be one sap on the Q for each PID
       
   675 
       
   676 @internalComponent
       
   677 @param aSap The SAP to be added
       
   678 @return KErrInUse if there is already a Sap on aSap's PID, otherwise KErrNone
       
   679 */   
       
   680 TInt CAvctpProtocol::AddSap(CAvctpSap& aSap)
       
   681 	{
       
   682 	LOG_FUNC
       
   683 	LOG2(_L("Adding 0x%08x on Pid 0x%x"), &aSap, aSap.Pid());
       
   684 	LOG_SAPS
       
   685 	
       
   686 	// The given sap must have a valid Pid to be on the protocol's Q
       
   687 	__ASSERT_DEBUG(aSap.Pid() != 0, Panic(ENullPid));
       
   688 	
       
   689 	TInt ret = KErrNone;
       
   690 	
       
   691 	CAvctpSap* sap = FindSap(aSap.Pid());
       
   692 	
       
   693 	if (!sap && aSap.iChannel == KAvctpSecondaryChannel)
       
   694 		{
       
   695 		ret = KErrNotReady;
       
   696 		}
       
   697 	else if (sap && aSap.iChannel == KAvctpPrimaryChannel)
       
   698 		{
       
   699 		// Bit of a hack to support two SAPs doing one PID
       
   700 		ret = KErrAlreadyExists;
       
   701 		}
       
   702 	else
       
   703 		{
       
   704 		// tell the sap that has been inserted in the list. Infact a sap that is not inserted in the
       
   705 		// list is shutdown from esock. In that process CAvctpProtocol::RemoveSap() is called and 
       
   706 		// would remove the "PID's client" from the iClientItems list. But it has to remove it only if that
       
   707 		// sap has been inserted in the list.
       
   708 		aSap.iIsInList = ETrue;
       
   709 		iSaps.AddFirst(aSap);
       
   710 		DequeIdleTimer();
       
   711 		}
       
   712 	
       
   713 	return ret;
       
   714 	}
       
   715 	
       
   716 /** 
       
   717 Removes a SAP from their queue.
       
   718 
       
   719 @internalComponent
       
   720 @param aSap The SAP to be removed
       
   721 */   	
       
   722 void CAvctpProtocol::RemoveSap(CAvctpSap& aSap)
       
   723 	{
       
   724 	LOG_FUNC
       
   725 	LOG2(_L("Removing 0x%08x from Pid 0x%x"), &aSap, aSap.Pid());
       
   726 	LOG_SAPS
       
   727 
       
   728 	if (aSap.IsInList())
       
   729 		{
       
   730 		aSap.iQueLink.Deque(); // safe to Deque even if it's already been done
       
   731 		
       
   732 		TDblQueIter<CAvctpTransport> muxerIter(iTransports);
       
   733 		CAvctpTransport* transport = NULL;
       
   734 		
       
   735 		
       
   736 		while(muxerIter)
       
   737 			{
       
   738 			transport = muxerIter++;
       
   739 			//Sap pid is used as clientId key to uniquely identify the client RAvctp
       
   740 			if (transport->HasClient(aSap.Pid()))
       
   741 				{
       
   742 				if (aSap.Channel() == KAvctpPrimaryChannel)
       
   743 					{
       
   744 					transport->RemovePrimaryChannelRef(aSap.Pid());
       
   745 					}
       
   746 				else
       
   747 					{
       
   748 					transport->RemoveSecondaryChannelRef(aSap.Pid());
       
   749 					}
       
   750 				}
       
   751 			}
       
   752 	
       
   753 		// as we are removing the sap it means the RAvctp for this Pid is being closing
       
   754 		// so we must remove the TClientItem from the protocol. To avoid removing it twice
       
   755 		// (it should be safe though) we only remove it for the primary channel sap
       
   756 				
       
   757 		if (aSap.Channel() == KAvctpPrimaryChannel)
       
   758 			{
       
   759 			__DEBUG_ONLY(TInt err = ) iClientItems.Remove(aSap.Pid());
       
   760 			__ASSERT_DEBUG(err == KErrNone, Panic(EAvctpClientNotFound));
       
   761 			}
       
   762 		
       
   763 		CheckForIdle();
       
   764 		}
       
   765 	}
       
   766 
       
   767 /** Find the SAP that is on this PID.
       
   768 
       
   769 If no such SAP exists, return NULL. Note this function doesn't transfer ownership.
       
   770 
       
   771 There should be no Sap with a zero PID on the Q
       
   772 
       
   773 @internalComponent
       
   774 @param aClientId The client Id to look for
       
   775 @return The SAP connected on the specified PID, if any, otherwise NULL. 
       
   776 */
       
   777 CAvctpSap* CAvctpProtocol::FindSap(TUint16 aClientId)
       
   778 	{
       
   779 	LOG_FUNC
       
   780 
       
   781 	TDblQueIter<CAvctpSap> iter(iSaps);
       
   782 	CAvctpSap* sap = NULL;
       
   783 	CAvctpSap* foundSap = NULL;
       
   784 
       
   785 	while (iter)
       
   786 		{
       
   787 		sap = iter++;
       
   788 		__ASSERT_DEBUG(sap->Pid() != 0, Panic(ENullPid));
       
   789 		if(sap->Pid() == aClientId)
       
   790 			{
       
   791 			foundSap = sap;
       
   792 			break;
       
   793 			}
       
   794 		}
       
   795 
       
   796 	return foundSap;
       
   797 	}
       
   798 	
       
   799 /** 
       
   800 Adds a Muxer to their queue which has been assigned a remote address. 
       
   801 Does the transfer from the blank muxer Q for the muxer.
       
   802 
       
   803 @internalComponent
       
   804 @param aMuxer The Muxer to be added
       
   805 @return KErrInUse if there is already a Muxer on aMuxer's BTDevAddr, otherwise KErrNone
       
   806 */   
       
   807 TInt CAvctpProtocol::AddTransport(CAvctpTransport& aTransport)
       
   808 	{
       
   809 	LOG_FUNC
       
   810 
       
   811 	LOG_MUXERS
       
   812 	
       
   813 	// The given muxer must have a valid remote addr to be on the protocol's Q
       
   814 	__ASSERT_DEBUG(aTransport.DevAddr() != TBTDevAddr(0), Panic(ENullTBTDevAddr));
       
   815 	
       
   816 	TInt ret = KErrNone;
       
   817 	CAvctpTransport* transport = FindTransport(aTransport.DevAddr());
       
   818 	if (transport)
       
   819 		{
       
   820 		ret = KErrInUse;
       
   821 		}
       
   822 	else
       
   823 		{
       
   824 		iTransports.AddFirst(aTransport);
       
   825 		}
       
   826 	
       
   827 	return ret;
       
   828 	}
       
   829 
       
   830 /** 
       
   831 Removes a Muxer from their queue.
       
   832 
       
   833 @internalComponent
       
   834 @param aMuxer The Muxer to be removed
       
   835 */   	 
       
   836 void CAvctpProtocol::RemoveTransport(CAvctpTransport& aTransport)
       
   837 	{
       
   838 	LOG_FUNC
       
   839 	LOG_MUXERS
       
   840 	  
       
   841 	aTransport.iQueLink.Deque(); // safe to Deque even if it's already been done
       
   842 	}
       
   843 
       
   844 /** Find the Muxer that is on this remote address.
       
   845 If no such Muxer exists, return NULL. Note this function doesn't transfer ownership.
       
   846 
       
   847 There should be no Muxer with a zero BTDevAddr on the Q
       
   848 @internalComponent
       
   849 @param aDevAddr The remote address to look for
       
   850 @return The Muxer connected on the specified remote address, if any, otherwise NULL.
       
   851 */
       
   852 CAvctpTransport* CAvctpProtocol::FindTransport(const TBTDevAddr& aDevAddr)
       
   853 	{
       
   854 	LOG_FUNC
       
   855 
       
   856 	TDblQueIter<CAvctpTransport> iter(iTransports); 
       
   857 	CAvctpTransport* transport = NULL;
       
   858 	CAvctpTransport* foundTransport = NULL;
       
   859 
       
   860 	while (iter)
       
   861 		{
       
   862 		transport = iter++;
       
   863 
       
   864 		if(transport->DevAddr() == aDevAddr)
       
   865 			{
       
   866 			foundTransport = transport;
       
   867 			break;
       
   868 			}
       
   869 		}
       
   870 
       
   871 	return foundTransport;
       
   872 	}
       
   873 
       
   874 CAvctpTransport* CAvctpProtocol::FindOrCreateTransport(const TBTDevAddr& aDevAddr, TInt aChannel, CServProviderBase* aL2CAPConSAP)
       
   875 	{
       
   876 	LOG_FUNC
       
   877 	TInt err = KErrNone;
       
   878 	CAvctpTransport* transport = FindTransport(aDevAddr);
       
   879 	
       
   880 	if (!transport)
       
   881 		{
       
   882 		// we create the transport but, in this case, we don't have PIDs attached and 
       
   883 		// we cannot notify them
       
   884 		TRAP(err, transport = CAvctpTransport::NewL(*this));
       
   885 		if (err == KErrNone)
       
   886 			{
       
   887 			iTransports.AddLast(*transport);
       
   888 			}
       
   889 		
       
   890 		if (err == KErrNone)
       
   891 			{
       
   892 			if (aL2CAPConSAP)
       
   893 				{
       
   894 				err = transport->StartIncoming(aDevAddr, aL2CAPConSAP);
       
   895 				}
       
   896 			else
       
   897 				{
       
   898 				err = transport->Start(aDevAddr, KUndefinedPid);
       
   899 				}
       
   900 			
       
   901 			if (err == KErrNone)
       
   902 				{
       
   903 				// It's possible that the muxer had to synchronously delete itself
       
   904 				// and wasn't able to return a synchronous error.
       
   905 				// In this case the muxer will have removed itself from the protocol's Q
       
   906 				if (!FindTransport(aDevAddr))
       
   907 					{
       
   908 					transport = NULL; // since it's already dead
       
   909 					}
       
   910 				}
       
   911 			}
       
   912 		}
       
   913 	else if (aChannel == KAvctpSecondaryChannel)	// secondary channel
       
   914 		{
       
   915 		if (!transport->HasSecondChannel())
       
   916 			{
       
   917 			CServProviderBase* sap = NULL;
       
   918 			TRAP(err, sap = iLowerProtocol->NewSAPL(KSockSeqPacket));
       
   919 			if (err == KErrNone)
       
   920 				{
       
   921 				err = transport->AddSecondChannel(*sap);
       
   922 				if (err!=KErrNone)
       
   923 					{
       
   924 					delete sap;
       
   925 					sap = NULL;
       
   926 					}
       
   927 				}
       
   928 			}
       
   929 		}
       
   930 	return transport;
       
   931 	}
       
   932 
       
   933 void CAvctpProtocol::AwaitTransport(TUint16 aClientId, MSocketNotify& aControlSocket)
       
   934 	{
       
   935 	LOG_FUNC
       
   936 	AddClientItem(aClientId, aControlSocket);
       
   937 	}
       
   938 
       
   939 /**
       
   940  It is submitted by the client saying it is happy to accept an incoming indication (for the primary channel).
       
   941  When the client receive an attach indication it can decide to accept or refuse it. 
       
   942  If accepts it sends back an agree attachment ioctl that results in this call.
       
   943  @param aClientId is the RAvctp pid value
       
   944  @param aRemoteAddr is the remote device's address which has been connected
       
   945  */
       
   946 TInt CAvctpProtocol::PrimaryChannelAgreeAttachment(TUint16 aClientId, const TBTDevAddr& aRemoteAddr)
       
   947 	{
       
   948 	LOG_FUNC
       
   949 	TInt err = KErrMuxerNotFound;
       
   950 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
   951 	if (transport)
       
   952 		{
       
   953 		TClientItem* item = iClientItems.Find(aClientId);
       
   954 		__ASSERT_DEBUG(item, Panic(EAvctpClientNotFound));
       
   955 		err = transport->AddPrimaryChannelRef(item); // it returns KErrNone or KErrNoMemory
       
   956 		}
       
   957 	return err;
       
   958 	}
       
   959 
       
   960 /**
       
   961  It is submitted by the client saying it is happy to accept an incoming indication (for the secondary channel).
       
   962  When the client receive an attach indication it can decide to accept or refuse it. 
       
   963  If accepts it sends back an agree attachment ioctl that results in this call.
       
   964  @param aClientId is the RAvctp pid value
       
   965  @param aRemoteAddr is the remote device's address which has been connected
       
   966  */
       
   967 TInt CAvctpProtocol::SecondaryChannelAgreeAttachment(TUint16 aClientId, const TBTDevAddr& aRemoteAddr)
       
   968 	{
       
   969 	LOG_FUNC
       
   970 	TInt err = KErrMuxerNotFound;
       
   971 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
   972 	if (transport)
       
   973 		{
       
   974 		TClientItem* item = iClientItems.Find(aClientId);
       
   975 		__ASSERT_DEBUG(item, Panic(EAvctpClientNotFound));
       
   976 		transport->AddSecondaryChannelRef();
       
   977 		err = KErrNone;
       
   978 		}
       
   979 	return err;
       
   980 	}
       
   981 
       
   982 /**
       
   983  If not already present it adds a TClientItem to the hashtable. Despite it was already present or not
       
   984  it always calls AttachPrimaryChannel to update the MSocketNotify.
       
   985  That is because once the TClientItem is added to the hastable it remains alive until the protocol 
       
   986  is alive. So we need to update the socket observer because it can be changed. i.e an RAvctp is created
       
   987  and used, then it is destroyed, and created again. The "clientId" remains the same, but the 
       
   988  MSocketNofity passed through it is probably changed. The item will be found (already added to the
       
   989  protocol hashtable) but the MSocketNotify& must be updated.
       
   990  @param aClientId is the unique identifier of the RAvctp client
       
   991  @param aNotify the socket observer for the ioctl messages (the primary channel CAvctpControlSAp)
       
   992  */
       
   993 const TClientItem* CAvctpProtocol::AddClientItem(TUint16 aClientId, MSocketNotify& aNotify) // it doesn't pass the ownership
       
   994 	{
       
   995 	LOG_FUNC
       
   996 	TClientItem* pitem = iClientItems.Find(aClientId);
       
   997 	if (!pitem)
       
   998 		{
       
   999 		// pitem is null so, proceed creating it and inserting in the hashtable
       
  1000 		TClientItem newItem(aClientId);
       
  1001 		newItem.AttachPrimaryChannel(aNotify);
       
  1002 		if (iClientItems.Insert(aClientId, newItem) == KErrNone)
       
  1003 			{
       
  1004 			// insertion succesfully, so we assign the inserted item to pitem
       
  1005 			pitem = iClientItems.Find(aClientId);
       
  1006 			}
       
  1007 		// if an error occurred (out of memory) pitem is still null
       
  1008 		}
       
  1009 	
       
  1010 	if (pitem)	// pitem can be null if the insertion failed 
       
  1011 		{
       
  1012 		// we update aNotify anyway, so it is always updated to the correct reference
       
  1013 		pitem->AttachPrimaryChannel(aNotify);
       
  1014 		}
       
  1015 	
       
  1016 	return const_cast<const TClientItem*>(pitem);	// it doesn't pass the ownership
       
  1017 	}
       
  1018 
       
  1019 const TClientItem* CAvctpProtocol::ClientItem(TUint16 aClientId) const // it doesn't pass ownership
       
  1020 	{
       
  1021 	LOG_FUNC
       
  1022 	const TClientItem* pitem = iClientItems.Find(aClientId);
       
  1023 	return pitem;
       
  1024 	}
       
  1025 
       
  1026 void CAvctpProtocol::NotifyLinkUp(const TBTDevAddr& aAddr, TBool aIsSecondChannel)
       
  1027 	{
       
  1028 	LOG_FUNC
       
  1029 	TControlIoctlMessage msg(ELinkUp, aAddr);
       
  1030 	TPckgC<TControlIoctlMessage> pck(msg);
       
  1031 	
       
  1032 	THashMapIter<TInt, TClientItem> iter(iClientItems);
       
  1033 	while(iter.NextKey())
       
  1034 		{
       
  1035 		TClientItem* pitem = iter.CurrentValue();
       
  1036 		MSocketNotify* socket = aIsSecondChannel ? pitem->SecondaryChannel() : pitem->PrimaryChannel();
       
  1037 
       
  1038 		__DEBUG_ONLY
       
  1039 			(
       
  1040 			if (!aIsSecondChannel)
       
  1041 				{
       
  1042 				__ASSERT_DEBUG(socket, Panic(EAvctpInvalidChannelNotify));
       
  1043 				}
       
  1044 			)
       
  1045 
       
  1046 		if (socket)
       
  1047 			{
       
  1048 			socket->IoctlComplete(&pck);
       
  1049 			}
       
  1050 		}
       
  1051 	}
       
  1052 
       
  1053 /** Gets a muxer for the given BT device address, using the L2CAP connection provided.
       
  1054 @internalComponent
       
  1055 */	
       
  1056 TInt CAvctpProtocol::StartProtocolListening()
       
  1057 	{
       
  1058 	LOG_FUNC
       
  1059 
       
  1060 	// because we do non-default security we override the base class
       
  1061 	// and new the incoming listener ourselves
       
  1062 	TRAPD(err, DoStartAvctpListeningL());
       
  1063 	return err;
       
  1064 	}
       
  1065 	
       
  1066 /** Gets a muxer for the given BT device address.
       
  1067 	
       
  1068 If it finds the muxer or successfully creates a new muxer, it returns 
       
  1069 with KErrNone and a valid pointer to the correct muxer. On a failure, 
       
  1070 it will return with a standard error, without a pointer to  a muxer.
       
  1071 This flavour of GetMuxer is used when a muxer is being created in response 
       
  1072 to a local request to connect to a remote device (i.e. no existing 
       
  1073 L2CAP connection exists) or when someone just wants a muxer on the given 
       
  1074 address whether or not one exists.
       
  1075 
       
  1076 Note that because a synchronous error could occur during the Start call, 
       
  1077 aMuxer might be NULL at the end of this function. Note thought this
       
  1078 depends on whether aMuxer was able to asynchronously delete itself or not.
       
  1079 Note that there could then be two error paths, one via the muxer sending
       
  1080 a ConnectComplete (with error) & the return from this function. If this is
       
  1081 the case, KErrSynchronousMuxerError will be returned which should be voided
       
  1082 so that the client doesn't get two errors.
       
  1083 
       
  1084 @internalComponent
       
  1085 @param aRemoteAddr The remote address for which we want a muxer
       
  1086 @param aMuxer A muxer will be created by this function if one doesn't exist and a connection attempt start. 
       
  1087 			  If there is an existing muxer it is returned aMuxer will be not be owned by the caller
       
  1088 @param aLinksMgr a possible control client for the newly created muxer
       
  1089 @return KErrNone if the muxer is successfully returned, 
       
  1090 		KErrSynchronousMuxerError if the muxer failed immediately on the address given, or
       
  1091 		KErrNoMemory or
       
  1092 		any other error code from CAvctpTransport::NewL
       
  1093 */ 
       
  1094 TInt CAvctpProtocol::ProvideTransport(const TBTDevAddr& aRemoteAddr, TUint16 aClientId,
       
  1095 									  MSocketNotify& aControlSocket)
       
  1096 	{
       
  1097 	LOG_FUNC
       
  1098 	IF_FLOGGING
       
  1099 		(
       
  1100 		TBuf<KBTAddressLength> address;
       
  1101 		aRemoteAddr.GetReadable(address);
       
  1102 		)
       
  1103 
       
  1104 	LOG1(_L("from BT Device 0x%S"), &address);
       
  1105 	
       
  1106 	TInt err = KErrNone;
       
  1107 	
       
  1108 	// first of all I add the Client Id to my list and get a pointer to it.
       
  1109 	const TClientItem* item = AddClientItem(aClientId, aControlSocket);
       
  1110 	
       
  1111 	if (item)	// we were able to allocate the memory for it
       
  1112 		{
       
  1113 		CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1114 	
       
  1115 		if (!transport)
       
  1116 			{
       
  1117 			TRAP(err,transport = CAvctpTransport::NewL(*this));
       
  1118 			if (err == KErrNone)
       
  1119 				{
       
  1120 				err = transport->AddPrimaryChannelRef(item);
       
  1121 				if (err == KErrNone)
       
  1122 					{
       
  1123 					iTransports.AddLast(*transport);
       
  1124 					}
       
  1125 				else
       
  1126 					{
       
  1127 					// it is safe to call it on a non-attached clientId and it is the only
       
  1128 					// way we have to ask the transport to destroying itself
       
  1129 					// as we just created the transport we know calling this method will destroy it
       
  1130 					transport->RemovePrimaryChannelRef(aClientId);
       
  1131 					}
       
  1132 				}
       
  1133 			}
       
  1134 		else
       
  1135 			{
       
  1136 			err = transport->AddPrimaryChannelRef(item);
       
  1137 			// in this case we already had the transport, probably with some clients attached.
       
  1138 			// we can't destroy it, and it is working for the attached clients. So, we simply
       
  1139 			// return an error to the client is asking to be attached.
       
  1140 			}
       
  1141 		
       
  1142 		if (err == KErrNone)
       
  1143 			{
       
  1144 			err = transport->Start(aRemoteAddr, aClientId);
       
  1145 	
       
  1146 			if (err == KErrNone)
       
  1147 				{
       
  1148 				// It's possible that the muxer had to synchronously delete itself
       
  1149 				// and wasn't able to return a synchronous error (e.g. if the client
       
  1150 				// tries to connect to itself and the async deletion attempt OOMs)
       
  1151 				// In this case the muxer will have removed itself from the protocol's Q
       
  1152 				if (!FindTransport(aRemoteAddr))
       
  1153 					{
       
  1154 					transport = NULL; // since it's already dead
       
  1155 					err = KErrSynchronousMuxerError;
       
  1156 					}
       
  1157 				}
       
  1158 			}
       
  1159 		}
       
  1160 	else
       
  1161 		{
       
  1162 		err = KErrNoMemory;
       
  1163 		}
       
  1164 	
       
  1165 	return err;
       
  1166 	}
       
  1167 
       
  1168 TInt CAvctpProtocol::ActiveExtendTransport(const TBTDevAddr& aRemoteAddr, TUint16 aClientId, MSocketNotify& aSecondChannelControlSocket)
       
  1169 	{
       
  1170 	LOG_FUNC
       
  1171 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1172 	TInt err = KErrMuxerNotFound;
       
  1173 	if (transport)
       
  1174 		{
       
  1175 		if (!transport->HasSecondChannel())
       
  1176 			{
       
  1177 			// get a new SAP and ask transport to connect it up
       
  1178 			CServProviderBase* sap = NULL;
       
  1179 			TRAP(err, sap = iLowerProtocol->NewSAPL(KSockSeqPacket));
       
  1180 			err = transport->AddSecondChannel(*sap);
       
  1181 			if (err!=KErrNone)
       
  1182 				{
       
  1183 				delete sap;
       
  1184 				sap = NULL;
       
  1185 				}
       
  1186 			else
       
  1187 				{
       
  1188 				transport->SetSecondChannelCtrlNotify(aClientId, aSecondChannelControlSocket);
       
  1189 				transport->AddSecondaryChannelRef();
       
  1190 				}
       
  1191 			}
       
  1192 		else
       
  1193 			{
       
  1194 			transport->SetSecondChannelCtrlNotify(aClientId, aSecondChannelControlSocket);
       
  1195 			transport->AddSecondaryChannelRef();
       
  1196 			transport->NotifyAttachConfirm(aClientId, KErrNone, ETrue);
       
  1197 			}
       
  1198 		}
       
  1199 	return err;
       
  1200 	}
       
  1201 
       
  1202 void CAvctpProtocol::SetSecondChannelCtrlNotify(TUint16 aClientId, MSocketNotify& aSecondChannelControlSocket)
       
  1203 	{
       
  1204 	LOG_FUNC
       
  1205 	TClientItem* item = iClientItems.Find(aClientId);
       
  1206 	__ASSERT_DEBUG(item, Panic(EAvctpClientNotFound));
       
  1207 	item->AttachSecondaryChannel(aSecondChannelControlSocket);
       
  1208 	}
       
  1209 
       
  1210 void CAvctpProtocol::AwaitForExtendedTransport(TUint16 aClientId, MSocketNotify& aSecondChannelControlSocket)
       
  1211 	{
       
  1212 	LOG_FUNC
       
  1213 	SetSecondChannelCtrlNotify(aClientId, aSecondChannelControlSocket);
       
  1214 	}
       
  1215 
       
  1216 void CAvctpProtocol::PrimaryChannelRefuseAttach(const TBTDevAddr& aRemoteAddr, TUint16 aClientId)
       
  1217 	{
       
  1218 	LOG_FUNC
       
  1219 	
       
  1220 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1221 	
       
  1222 	// when this method is called it means the client refused to be attached to the transport
       
  1223 	// and didn't call the AgreeAttachment. It means that we don't have the TClientItem attached to
       
  1224 	// the transport.
       
  1225 	// However we call transport->RemovePrimaryChannelRef anyway. It is safe to call it even if the
       
  1226 	// aClientId item is not attached, and it does the reference count control so that if there
       
  1227 	// are no more clients attached it destroys the transport.
       
  1228 	// this method can also be called on the PrimaryChannelCancelAttach invocation client side.
       
  1229 	// In this case the client will be found and removed
       
  1230 	if(transport)
       
  1231 		{
       
  1232 		// NOTE: if transport has no more clients attached it deletes itself.
       
  1233 		// so, don't rely on transport after this call because it could have been deleted
       
  1234 		transport->RemovePrimaryChannelRef(aClientId);
       
  1235 		}
       
  1236 	}
       
  1237 
       
  1238 void CAvctpProtocol::SecondaryChannelRefuseAttach(const TBTDevAddr& aRemoteAddr, TUint16 aClientId)
       
  1239 	{
       
  1240 	LOG_FUNC
       
  1241 
       
  1242 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1243 	
       
  1244 	// when this method is called it means the client refused to be attached to the transport
       
  1245 	// and didn't call the AgreeAttachment. It means that we don't have the TClientItem attached to
       
  1246 	// the transport.
       
  1247 	// However we call transport->RemovePrimaryChannelRef anyway. It is safe to call it even if the
       
  1248 	// aClientId item is not attached, and it does the reference count control so that if there
       
  1249 	// are no more clients attached it destroys the transport.
       
  1250 	
       
  1251 	if(transport)
       
  1252 		{
       
  1253 		// we must call AddSecondaryChannelRef() first, that increments the reference count
       
  1254 		// because then we call RemoveSecondaryChannelRef() that decrements it.
       
  1255 		// we want to call RemoveSecondaryChannelRef() because it manages the zero reference which
       
  1256 		// drives the secondary l2cap channel destruction 
       
  1257 		transport->AddSecondaryChannelRef();
       
  1258 		transport->RemoveSecondaryChannelRef(aClientId);
       
  1259 		}
       
  1260 	}
       
  1261 
       
  1262 TInt CAvctpProtocol::GetChannelMtu(TInt aChannel, const TBTDevAddr& aAddr, TInt& aMtu)
       
  1263 	{
       
  1264 	LOG_FUNC
       
  1265 	TInt err = KErrNotReady;
       
  1266 	CAvctpTransport* t = FindTransport(aAddr);
       
  1267 	if(t)
       
  1268 		{
       
  1269 		err = t->GetChannelMtu(aChannel, aMtu);
       
  1270 		}
       
  1271 	return err;
       
  1272 	}
       
  1273 
       
  1274 TInt CAvctpProtocol::ReleaseTransport(const TBTDevAddr& aRemoteAddr, TUint16 aClientId)
       
  1275 	{
       
  1276 	LOG_FUNC
       
  1277 	TInt err = KErrMuxerNotFound;
       
  1278 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1279 	if(transport)
       
  1280 		{
       
  1281 		err = KErrNone;
       
  1282 		transport->NotifyDetachConfirm(aClientId, err);
       
  1283 		// NOTE: if there are no more pid attached to the transport it will delete itself.
       
  1284 		// so, don't rely on the transport after this call because it could have been deleted
       
  1285 		transport->RemovePrimaryChannelRef(aClientId);
       
  1286 		}
       
  1287 	return err;
       
  1288 	}
       
  1289 
       
  1290 TInt CAvctpProtocol::ReleaseExtendedTransport(const TBTDevAddr& aRemoteAddr, TUint16 aClientId)
       
  1291 	{
       
  1292 	LOG_FUNC
       
  1293 	TInt err = KErrMuxerNotFound;
       
  1294 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1295 	if(transport)
       
  1296 		{
       
  1297 		err = KErrNone;
       
  1298 		transport->NotifyDetachConfirm(aClientId, err, ETrue);
       
  1299 		transport->RemoveSecondaryChannelRef(aClientId);
       
  1300 		}
       
  1301 	return err;
       
  1302 	}
       
  1303 
       
  1304 void CAvctpProtocol::PrimaryChannelIncomingRemoteDisconnection(const TBTDevAddr& aRemoteAddr)
       
  1305 	{
       
  1306 	LOG_FUNC
       
  1307 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1308 	if(transport)
       
  1309 		{
       
  1310 		// the secondary channel, if present, has been already destroyed.
       
  1311 		transport->NotifyLinkDown(aRemoteAddr, KAvctpPrimaryChannel);	// we are destroying the transport 
       
  1312 		}
       
  1313 	}
       
  1314 
       
  1315 /**
       
  1316 Gets a muxer for the given BT device address, using the L2CAP connection provided.
       
  1317 
       
  1318 If it is found that a muxer for the specified BT device already exists, 
       
  1319 KErrAlreadyExists will be returned. If a new muxer is successfully created, 
       
  1320 KErrNone will be returned along with a valid pointer to the correct muxer in aMuxer 
       
  1321 
       
  1322 This flavour of GetMuxer is used when a muxer is being created in response to a 
       
  1323 remote request to connect to the local device (i.e. an L2CAP SAP has been created 
       
  1324 due to an incoming connection).
       
  1325 
       
  1326 Note that because a synchronous error could occur during the Start call, 
       
  1327 aMuxer might be NULL at the end of this function. Note thought this
       
  1328 depends on whether aMuxer was able to asynchronously delete itself or not.
       
  1329 Note that there could then be two error paths, one via the muxer sending
       
  1330 a ConnectComplete (with error) & the return from this function. If this is
       
  1331 the case, KErrSynchronousMuxerError will be returned which should be voided
       
  1332 so that the client doesn't get two errors.
       
  1333 
       
  1334 @internalComponent
       
  1335 @param aRemoteAddr The remote address for which we want a muxer
       
  1336 @param aL2CAPConSAP This is a non null, L2CAP sap for the incoming connection from aRemoteAddr
       
  1337 @param aMuxer A muxer created by this function to hold aL2CAPConSAP (assuming there wasn't one already for aRemoteAddr). aMuxer will be not be owned by the caller
       
  1338 @return KErrNone if the muxer is successfully returned, 
       
  1339 		KErrSynchronousMuxerError if the muxer failed immediately on the address give, or
       
  1340 		any other error code from CAvctpTransport::NewL
       
  1341 */
       
  1342 TInt CAvctpProtocol::AttachInboundConnectionToTransport(const TBTDevAddr& aRemoteAddr,
       
  1343 														CServProviderBase* aL2CAPConSAP)
       
  1344 	{
       
  1345 	LOG_FUNC
       
  1346 	__DEBUG_ONLY
       
  1347 		(
       
  1348 		TBuf<KBTAddressLength> address;
       
  1349 		aRemoteAddr.GetReadable(address);
       
  1350 		LOG1(_L("from BT Device 0x%S"), &address);
       
  1351 		
       
  1352 		//	Check that the device address and the device of the L2CAP remote address match!!
       
  1353 		TBTSockAddr addr;
       
  1354 		aL2CAPConSAP->RemName(addr);
       
  1355 		__ASSERT_DEBUG(addr.BTAddr()==aRemoteAddr,Panic(EMismatchedAddressAndSap));
       
  1356 		)
       
  1357 
       
  1358 	TL2CAPPort localPSM;
       
  1359 	TPckg<TL2CAPPort> localPSMBuf(localPSM);
       
  1360 	TInt err = aL2CAPConSAP->GetOption(KSolBtL2CAP, KL2CAPLocalPSM, localPSMBuf);
       
  1361 
       
  1362 	__ASSERT_DEBUG(err == KErrNone, Panic(EGetOptionError));
       
  1363 	
       
  1364 	//first try to find the transport with a given address: if it exists then this inbound link could be the second channel
       
  1365 	CAvctpTransport* transport = FindTransport(aRemoteAddr);
       
  1366 
       
  1367 	if (transport)
       
  1368 		{
       
  1369 		// ok so try finding a listener transport for this link (which should be control)
       
  1370 		if (localPSM == KAvctpSecondChannelPSM)
       
  1371 			{
       
  1372 			transport->AddSecondChannel(*aL2CAPConSAP);
       
  1373 			}
       
  1374 		else
       
  1375 			{
       
  1376 			// remote was being daft
       
  1377 			return KErrGeneral;
       
  1378 			}
       
  1379 		}
       
  1380 	else
       
  1381 		{
       
  1382 		
       
  1383 		if (localPSM != KAVCTP)
       
  1384 			{
       
  1385 			return KErrGeneral; // the other type of daft remote
       
  1386 			}
       
  1387 				
       
  1388 		// else remote sensibly connected first channel to the right PSM, for which we should have a listening transport on bdaddr==0
       
  1389 		transport = FindOrCreateTransport(aRemoteAddr, KAvctpPrimaryChannel, aL2CAPConSAP); 
       
  1390 		if (transport)
       
  1391 			{
       
  1392 			// It's possible that the muxer had to synchronously delete itself
       
  1393 			// and wasn't able to return a synchronous error (e.g. if the client
       
  1394 			// tries to connect to itself and the async deletion attempt OOMs)
       
  1395 			// In this case the muxer will have removed itself from the protocol's Q
       
  1396 			if (!FindTransport(aRemoteAddr))
       
  1397 				{
       
  1398 				transport = NULL; // since it's already dead
       
  1399 				err = KErrSynchronousMuxerError;
       
  1400 				}
       
  1401 			else
       
  1402 				{	// notify link up
       
  1403 				NotifyLinkUp(aRemoteAddr, EFalse);
       
  1404 				}
       
  1405 			}
       
  1406 		else
       
  1407 			{
       
  1408 			err = KErrNotReady;
       
  1409 			}
       
  1410 		}
       
  1411 
       
  1412 	return err;
       
  1413 	}
       
  1414 
       
  1415 /** 
       
  1416 Provide interface to class to send AVCTP SDUs (if one for the needed address exists
       
  1417 */
       
  1418 MAvctpSDUSender* CAvctpProtocol::GetSDUSender(const TBTDevAddr& aRemoteAddr, TInt aChannel)
       
  1419 	{
       
  1420 	LOG_FUNC
       
  1421 
       
  1422 	CAvctpTransport* transport = FindOrCreateTransport(aRemoteAddr, aChannel);
       
  1423 	return transport ? &static_cast<MAvctpSDUSender&>(transport->PacketMgr()) : NULL;
       
  1424 	}
       
  1425 
       
  1426 /**
       
  1427 Check to see if we're still needed.  If not, Q a delayed delete.
       
  1428 
       
  1429   @internalComponent
       
  1430 */
       
  1431 void CAvctpProtocol::CheckForIdle()
       
  1432 	{
       
  1433 	LOG_FUNC
       
  1434 
       
  1435 	if (IsIdle())
       
  1436 		{
       
  1437 		QueIdleTimer();
       
  1438 		}
       
  1439 	}
       
  1440 
       
  1441 /** 
       
  1442 Called to check whether we can close down. I.e. are there any clients remaining on the
       
  1443 other side of Esock.
       
  1444 
       
  1445 We could be idle even if there are Avctp muxers alive since Esock won't know about these
       
  1446 
       
  1447 @internalComponent
       
  1448 @return ETrue if the protocol can close, EFalse if not
       
  1449 */
       
  1450 TBool CAvctpProtocol::IsIdle()
       
  1451 	{
       
  1452 	LOG_FUNC
       
  1453 	LOG_SAPS
       
  1454 	
       
  1455 	return (iClosePending && 
       
  1456 			iSaps.IsEmpty());
       
  1457 	}
       
  1458 	
       
  1459 /**
       
  1460 Queues the idle timer if necessary
       
  1461 
       
  1462   @internalComponent
       
  1463 */
       
  1464 void CAvctpProtocol::QueIdleTimer()
       
  1465 	{
       
  1466 	LOG_FUNC
       
  1467 
       
  1468 	if (!iIdleTimerQueued)
       
  1469 		{
       
  1470 		LOG(_L("Queued idle timer"));
       
  1471 
       
  1472 		iIdleTimerQueued = ETrue;
       
  1473 		BTSocketTimer::Queue(KProtocolIdleTimeout, iIdleTimerEntry);
       
  1474 		}
       
  1475 	}
       
  1476 
       
  1477 /**
       
  1478 Deques idle timer if necessary
       
  1479 
       
  1480   @internalComponent
       
  1481 */
       
  1482 void CAvctpProtocol::DequeIdleTimer()
       
  1483 	{
       
  1484 	LOG_FUNC
       
  1485 
       
  1486 	if (iIdleTimerQueued)
       
  1487 		{
       
  1488 		LOG(_L("Dequeued idle timer"));
       
  1489 
       
  1490 		iIdleTimerQueued = EFalse;
       
  1491 		BTSocketTimer::Remove(iIdleTimerEntry);
       
  1492 		}
       
  1493 	}
       
  1494 
       
  1495 	
       
  1496 /** Asynchronous callback function.
       
  1497 
       
  1498 We check if should close then close.
       
  1499 
       
  1500 @internalComponent
       
  1501 @param aProtocol The protocol object
       
  1502 @return EFalse to indicate the callback does not need to be reissued
       
  1503 */
       
  1504 TInt CAvctpProtocol::TryToClose(TAny* aProtocol)
       
  1505 	{
       
  1506 	LOG_STATIC_FUNC
       
  1507 
       
  1508 	CAvctpProtocol* protocol	= static_cast<CAvctpProtocol*>(aProtocol);
       
  1509 	protocol->iIdleTimerQueued	= EFalse;
       
  1510 	__ASSERT_DEBUG(protocol->IsIdle(), Panic(EIdleTimeoutWhenNotIdle));
       
  1511 	protocol->CanClose();
       
  1512 
       
  1513 	return EFalse; // don't try to callback again
       
  1514 	}
       
  1515 
       
  1516 TInt CAvctpProtocol::IpidAsyncCallBack(TAny* aProtocol)
       
  1517 	{
       
  1518 	LOG_STATIC_FUNC
       
  1519 
       
  1520 	__ASSERT_DEBUG(aProtocol, Panic(ENullAvctpProtocol));
       
  1521 	
       
  1522 	CAvctpProtocol& protocol = *static_cast<CAvctpProtocol*>(aProtocol);
       
  1523 
       
  1524 	TDblQueIter<HAvctpOutgoingSdu> iter(protocol.iIpidResponses);
       
  1525 	HAvctpOutgoingSdu* sdu = NULL;
       
  1526 	MAvctpSDUSender* sender = NULL;
       
  1527 	
       
  1528 	TInt err;
       
  1529 	
       
  1530 	while(iter)
       
  1531 		{
       
  1532 		sdu = iter++;
       
  1533 		sender = protocol.GetSDUSender(sdu->BTAddr(), sdu->Channel());
       
  1534 
       
  1535 		if (sender)
       
  1536 			{
       
  1537 			LOG1(_L("Attempt to write IPID response 0x%08x in IpidAsyncCallBack"), &sdu);
       
  1538 			if ((err = sender->WriteIpid(sdu)) != KErrNone)
       
  1539 				{
       
  1540 				if (err == KErrRemoteSentTooManyIpidSdus)
       
  1541 					{
       
  1542 					CAvctpTransport* transport = protocol.FindTransport(sdu->BTAddr());
       
  1543 					if (transport)
       
  1544 						{
       
  1545 						transport->Shutdown(KErrRemoteSentTooManyIpidSdus);
       
  1546 						}
       
  1547 					}
       
  1548 				else if (err == KErrMuxerBlocked)
       
  1549 					{
       
  1550 					//got blocked
       
  1551 					//it will be called again asyncronously
       
  1552 					}
       
  1553 				}
       
  1554 			// else send completed and sdu ownership transferred to the sender
       
  1555 			}
       
  1556 		else
       
  1557 			{
       
  1558 			// can't send the IPID since we don't have a data path to send it over
       
  1559 			delete sdu; // will deque the sdu
       
  1560 			}
       
  1561 		}	
       
  1562 	return EFalse;	
       
  1563 	}
       
  1564 	
       
  1565 #ifdef __FLOG_ACTIVE	
       
  1566 void CAvctpProtocol::LogSaps()
       
  1567 	{
       
  1568 	LOG_FUNC
       
  1569 	TDblQueIter<CAvctpSap> iter(iSaps);
       
  1570 	CAvctpSap* sap = NULL;
       
  1571 	while (iter)
       
  1572 		{
       
  1573 		sap = iter++;
       
  1574 		LOG2(_L("0x%08x is a sap on PID %d"), sap, sap->Pid());
       
  1575 		}	
       
  1576 	}
       
  1577 	
       
  1578 void CAvctpProtocol::LogMuxers()
       
  1579 	{
       
  1580 	LOG_FUNC
       
  1581 	TDblQueIter<CAvctpTransport> iter(iTransports);
       
  1582 	CAvctpTransport* transport = NULL;
       
  1583 	TBuf<KBTAddressLength> address;
       
  1584 	while (iter)
       
  1585 		{
       
  1586 		transport= iter++;
       
  1587 		transport->DevAddr().GetReadable(address);
       
  1588 		LOG2(_L("0x%08x is a transport on BT Device %S"), transport, &address);
       
  1589 		}	
       
  1590 	}
       
  1591 
       
  1592 #endif
       
  1593 
       
  1594 // TClientItem
       
  1595 
       
  1596 TClientItem::TClientItem(TUint16 aClientId) : 
       
  1597 	iClientId(aClientId),
       
  1598 	iPrimaryChannel(NULL),
       
  1599 	iSecondaryChannel(NULL),
       
  1600 	iIsSecondaryChannelAttached(EFalse),
       
  1601 	iRefCount(0)
       
  1602 	{
       
  1603 	LOG_FUNC
       
  1604 	}
       
  1605 
       
  1606 void TClientItem::AttachPrimaryChannel(MSocketNotify& aNotify)
       
  1607 	{
       
  1608 	LOG_FUNC
       
  1609 	iPrimaryChannel = &aNotify;
       
  1610 	iIsSecondaryChannelAttached = EFalse;
       
  1611 	}
       
  1612 
       
  1613 void TClientItem::AttachSecondaryChannel(MSocketNotify& aNotify)
       
  1614 	{
       
  1615 	LOG_FUNC
       
  1616 	iSecondaryChannel = &aNotify;
       
  1617 	iIsSecondaryChannelAttached = ETrue;
       
  1618 	}
       
  1619 
       
  1620 TUint16 TClientItem::ClientId() const
       
  1621 	{
       
  1622 	LOG_FUNC
       
  1623 	return iClientId;
       
  1624 	}
       
  1625 
       
  1626 MSocketNotify* TClientItem::PrimaryChannel() const
       
  1627 	{
       
  1628 	LOG_FUNC
       
  1629 	return iPrimaryChannel;
       
  1630 	}
       
  1631 
       
  1632 MSocketNotify* TClientItem::SecondaryChannel() const
       
  1633 	{
       
  1634 	LOG_FUNC
       
  1635 	return iSecondaryChannel;
       
  1636 	}
       
  1637 
       
  1638 TBool TClientItem::IsSecondaryChannelAttached() const
       
  1639 	{
       
  1640 	LOG_FUNC
       
  1641 	return iIsSecondaryChannelAttached;
       
  1642 	}
       
  1643 
       
  1644 void TClientItem::DetachSecondaryChannel()
       
  1645 	{
       
  1646 	LOG_FUNC
       
  1647 	iSecondaryChannel = NULL;
       
  1648 	iIsSecondaryChannelAttached = EFalse;
       
  1649 	}