bluetooth/btstack/avdtp/avdtp.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2003-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 avdtp protocol object
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include <e32def.h>
       
    25 #include <bluetoothav.h>
       
    26 #include <bluetooth/avctptypes.h> // for PID used for pre-authorisation
       
    27 #include "IncomingConnListener.h"
       
    28 #include "avdtp.h"
       
    29 #include "avdtpsap.h"
       
    30 #include "avdtpTransportChannel.h"
       
    31 #include "avdtpTransportSession.h"
       
    32 #include "avdtpSignallingChannel.h"
       
    33 #include "avdtpStream.h"
       
    34 #include "avdtputil.h"
       
    35 
       
    36 #ifdef __FLOG_ACTIVE
       
    37 _LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
       
    38 #endif
       
    39 
       
    40 /**
       
    41 Protocol object constructor.
       
    42 
       
    43 @internalComponent
       
    44 @param aSecMan The bluetooth security manager
       
    45 @see CBTSecMan
       
    46 @return A pointer to the AVDTP protocol object
       
    47 */
       
    48 CAvdtpProtocol::CAvdtpProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    49 :	CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan),
       
    50 	iTransportChannels(_FOFF(CTransportChannel, iProtocolQLink)),
       
    51 	iClosingTransportChannels(_FOFF(CTransportChannel, iProtocolQLink)),
       
    52 	iSignallingChannels(_FOFF(CSignallingChannel, iProtocolQLink)),
       
    53 	iStreams(_FOFF(CAVStream, iProtocolQLink)),
       
    54 	iSecondarySAPs(_FOFF(CAvdtpSAP, iLink))
       
    55 	{
       
    56 	CONNECT_LOGGER
       
    57 	LOG_FUNC
       
    58 	TCallBack cb(TryToClose, this);
       
    59 	iIdleTimerEntry.Set(cb);
       
    60 	}
       
    61 
       
    62 /**
       
    63 Protocol object destructor.
       
    64 We don't clear up the SAPs as they are owned by ESock and it is up to it to destroy them.
       
    65 
       
    66 @internalComponent
       
    67 */
       
    68 CAvdtpProtocol::~CAvdtpProtocol()
       
    69 	{
       
    70 	LOG_FUNC
       
    71 	__ASSERT_DEBUG(!iIdleEntryQueued, Panic(EAvdtpProtocolDeletionWhilstIdling));
       
    72 	RemoveIdleTimerEntry();
       
    73 
       
    74 	if (iLowerProtocol)
       
    75 		iLowerProtocol->Close();  // Matches the bind
       
    76 
       
    77 	delete iLogicalChannelFactory;
       
    78 	delete iStreamStateFactory;
       
    79 	delete iRemoteSEPCache;
       
    80 	
       
    81 	__ASSERT_ALWAYS(iStreams.IsEmpty(), Panic(EAvdtpProtocolDyingWithStreamsOnQueue));
       
    82 	__ASSERT_ALWAYS(iSignallingChannels.IsEmpty(), Panic(EAvdtpProtocolDyingWithSignallingChannelsOnQueue));
       
    83 	__ASSERT_ALWAYS(iTransportChannels.IsEmpty(), Panic(EAvdtpProtocolDyingWithTransportChannelsOnQueue));
       
    84 	__ASSERT_ALWAYS(iClosingTransportChannels.IsEmpty(), Panic(EAvdtpProtocolDyingWithTransportChannelsOnQueue));
       
    85 
       
    86 	CLOSE_LOGGER
       
    87 }
       
    88 
       
    89 /**
       
    90 Static protocol object factory function.
       
    91 Leaves the protocol object on the cleanup stack.
       
    92 
       
    93 @internalComponent
       
    94 @see CBTSecMan
       
    95 @leave KErrNoMemory if the protocol object could not be created
       
    96 @param aSecMan The bluetooth security manager
       
    97 
       
    98 @return A pointer to the AVDTP protocol object
       
    99 */
       
   100 CAvdtpProtocol* CAvdtpProtocol::NewLC(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
   101 	{
       
   102 	LOG_STATIC_FUNC	
       
   103 	CAvdtpProtocol* self = new(ELeave) CAvdtpProtocol(aSecMan, aControlPlane, aCodMan);
       
   104 	CleanupStack::PushL(self);
       
   105 	self->ConstructL();
       
   106 	return self;
       
   107 	}
       
   108 
       
   109 /**
       
   110 Static protocol object factory function.
       
   111 
       
   112 @internalComponent
       
   113 @see CBTSecMan
       
   114 @leave KErrNoMemory if the protocol object could not be created
       
   115 @param aSecMan The bluetooth security manager
       
   116 @return A pointer to the AVDTP protocol object
       
   117 */
       
   118 CAvdtpProtocol* CAvdtpProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
   119 	{
       
   120 	LOG_STATIC_FUNC
       
   121 	CAvdtpProtocol* self = CAvdtpProtocol::NewLC(aSecMan, aControlPlane, aCodMan);
       
   122 	CleanupStack::Pop(self);
       
   123 	return self;
       
   124 	}
       
   125 
       
   126 /**
       
   127 Protocol object second-phase construction
       
   128 
       
   129 @internalComponent
       
   130 */
       
   131 void CAvdtpProtocol::ConstructL()
       
   132 	{
       
   133 	LOG_FUNC
       
   134 	iStreamStateFactory = CAVStreamStateFactory::NewL();
       
   135 	iRemoteSEPCache = CRemoteSEPCache::NewL();
       
   136 	}
       
   137 
       
   138 /**
       
   139 Pre-binding initialise.
       
   140 
       
   141 Alloc any stuff we need. This will only ever be called once during the lifetime of this protocol.
       
   142 
       
   143 @internalComponent
       
   144 @leave KErrNoMemory if the state factory cannot be created
       
   145 @param aTag The string identifier for the protocol from the ESock ini file
       
   146 */
       
   147 void CAvdtpProtocol::InitL(TDesC& /*aTag*/)
       
   148 	{
       
   149 	LOG_FUNC
       
   150 	}
       
   151 
       
   152 /**
       
   153 Binding complete.
       
   154 
       
   155 @internalComponent
       
   156 */
       
   157 void CAvdtpProtocol::StartL()
       
   158 	{
       
   159 	LOG_FUNC
       
   160 	// Should check that we're bound now.
       
   161 	if (!iLowerProtocol)
       
   162 		{
       
   163 		User::Leave(KErrAvdtpNotBound);
       
   164 		}
       
   165 	
       
   166 	iLogicalChannelFactory = CLogicalChannelFactory::NewL(*this, *iLowerProtocol);
       
   167 	}
       
   168 
       
   169 // From higher protocol
       
   170 void CAvdtpProtocol::BindL(CProtocolBase* /*protocol*/, TUint /* id*/)
       
   171 	{
       
   172 	LOG_FUNC
       
   173 	// Could register the protocol that's bound to us
       
   174 	// (e.g. "see" whether we support RTCP/RTP-FEC (if that
       
   175 	// protocol suite becomes ESOCK-side!)
       
   176 	}
       
   177 
       
   178 /**
       
   179 Request by Protocol Mgr to bind to the specified protocol. We can only be bound
       
   180 to one lower layer protocol, so the function leaves if we are already bound.
       
   181 
       
   182 @internalComponent
       
   183 @leave KErrAvdtpAlreadyBound if we are already bound, and any other leave from
       
   184      the lower protocol's BindL()
       
   185 @param aProtocol The protocol we need to bind to.
       
   186 */
       
   187 void CAvdtpProtocol::BindToL(CProtocolBase* aProtocol)
       
   188 	{
       
   189 	LOG_FUNC
       
   190 	if(!iLowerProtocol)
       
   191 		{
       
   192 #ifdef _DEBUG
       
   193 		TServerProtocolDesc prtDesc;
       
   194 		aProtocol->Identify(&prtDesc);
       
   195 
       
   196 		if(prtDesc.iAddrFamily!=KBTAddrFamily ||
       
   197 		   prtDesc.iProtocol!=KL2CAP)
       
   198 			{
       
   199 			User::Leave(KErrBtEskError);
       
   200 			}
       
   201 #endif
       
   202 
       
   203 		iLowerProtocol=static_cast<CBluetoothProtocolBase*>(aProtocol);
       
   204 		iLowerProtocol->BindL(this, 0); // id not used
       
   205 		iLowerProtocol->Open();
       
   206 		}
       
   207 	else
       
   208 		{
       
   209 	    User::Leave(KErrAvdtpAlreadyBound);
       
   210 		}
       
   211 	}
       
   212 
       
   213 void CAvdtpProtocol::Close()
       
   214 	{
       
   215 	LOG_FUNC
       
   216 	CProtocolBase::Close();
       
   217 	}
       
   218 
       
   219 
       
   220 /** 
       
   221 Create a new SAP: all SAPs are datagram.
       
   222 
       
   223 The SAP will eventually construct a session, to which the SAP delegates
       
   224 most of its work.  This is reminiscent of the Adaptor pattern.
       
   225 
       
   226 The delegate represents a session as per the AVDTP specification.
       
   227 
       
   228 Note that this implmentation adds to the available session types with
       
   229 the signalling session.  This allows for multiplexed use of the signalling
       
   230 channel.
       
   231 
       
   232 The SAP returned is owned by the caller -- this protocol will not clean it up.
       
   233 ESock uses this function to create a new SAP, and ESock will delete when it is
       
   234 finished with it.
       
   235 
       
   236 In future this could take care of secondary saps - make them !datagram
       
   237 
       
   238 @internalComponent
       
   239 @leave KErrNotSupported if aSockType is not datagram
       
   240 
       
   241 @param aSockType The socket type for the SAP:
       
   242 @return A pointer to a new SAP
       
   243 */
       
   244 CServProviderBase* CAvdtpProtocol::NewSAPL(TUint aSockType)
       
   245 	{
       
   246 	LOG_FUNC
       
   247 	CAvdtpSAP* sap = NULL;
       
   248 	
       
   249 	switch(aSockType)
       
   250 		{		
       
   251 		case KSockDatagram:
       
   252 			sap = CAvdtpSAP::NewL(*this);
       
   253 			break;
       
   254 		default:
       
   255 			User::Leave(KErrNotSupported);
       
   256 			break;
       
   257 		}
       
   258 
       
   259 	return sap;
       
   260 	}
       
   261 
       
   262 /**
       
   263 Identify the protocol.
       
   264 
       
   265 The descriptor is filled in to identify the protocol to ESock.
       
   266 
       
   267 @internalComponent
       
   268 @param aDesc A pointer to the descriptor to be filled in
       
   269 */
       
   270 void CAvdtpProtocol::Identify(TServerProtocolDesc* aDesc) const
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	ProtocolIdentity(aDesc);
       
   274 	}
       
   275 
       
   276 /**
       
   277 Fill in the protocol descriptor.
       
   278 
       
   279 This is a static utility function to fill in the protocol details.
       
   280 Called from family too.
       
   281 
       
   282 @internalComponent
       
   283 @param aDesc A pointer to the descriptor to be filled in
       
   284 */
       
   285 void CAvdtpProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc)
       
   286 	{
       
   287 	LOG_STATIC_FUNC
       
   288 	aDesc->iName			= KAVDTPProtocolName;
       
   289 	aDesc->iAddrFamily		= KBTAddrFamily;
       
   290 	aDesc->iSockType		= KSockDatagram; // because of bearing rtp
       
   291 	aDesc->iProtocol		= KAVDTP;
       
   292 	aDesc->iVersion			= TVersion(KBTMajor,KBTMinor,KBTBuild);
       
   293 	aDesc->iByteOrder		= ELittleEndian;
       
   294 	aDesc->iServiceInfo		= KAvdtpServiceInfo;
       
   295 	aDesc->iNamingServices	= NULL;
       
   296 	aDesc->iSecurity		= KSocketNoSecurity;
       
   297 	aDesc->iMessageSize		= KSocketMessageSizeUndefined; // whatever l2cap dynamically. not static knowledge of max
       
   298 	aDesc->iServiceTypeInfo	= ESocketSupport | ECantProcessMBufChains |
       
   299 							  EPreferDescriptors | EUseCanSend;
       
   300 	aDesc->iNumSockets		= 100;
       
   301 	}
       
   302 
       
   303 
       
   304 /**
       
   305 Our reference is now zero, so start to close.
       
   306 
       
   307 We don't actually close, merely Q a timer for a later close down.
       
   308 This close can be prempted by another open.
       
   309 
       
   310 @internalComponent
       
   311 */
       
   312 void CAvdtpProtocol::CloseNow()
       
   313 	{
       
   314 	LOG_FUNC
       
   315 	iClosePending = ETrue;
       
   316 	QueIdleTimerEntry();
       
   317 	}
       
   318 
       
   319 void CAvdtpProtocol::Open()
       
   320 /**
       
   321 Request to open the protocol.
       
   322 
       
   323 The protocol may be repeatedly opened and closed.  The order of calls is
       
   324 InitL, [Open *n , Close * n,  CloseNow] * m etc.
       
   325 
       
   326 @internalComponent
       
   327 */
       
   328 	{
       
   329 	LOG_FUNC
       
   330 	iClosePending = EFalse;
       
   331 	RemoveIdleTimerEntry();
       
   332 	CProtocolBase::Open();
       
   333 	}
       
   334 
       
   335 
       
   336 /**
       
   337 Create a signalling channel for listening - this has the special address of 0
       
   338 */
       
   339 CSignallingChannel* CAvdtpProtocol::CreateSignallingChannelForListening()
       
   340 	{
       
   341 // the signalling channel with addr=0 *is* the listener
       
   342 	LOG_FUNC
       
   343 	return GetSignallingChannel(TBTDevAddr(0));
       
   344 	}
       
   345 
       
   346 /**
       
   347 For an open platform we need to support shared use of the Signalling Channel
       
   348 Signalling sessions ask for this then and attach themselves to it
       
   349 */
       
   350 CSignallingChannel* CAvdtpProtocol::FindSignallingChannel(const TBTDevAddr& aRemoteAddr)
       
   351 	{
       
   352 	LOG_FUNC
       
   353 	CSignallingChannel* c = NULL;
       
   354 	TDblQueIter<CSignallingChannel> iter(iSignallingChannels);
       
   355 	
       
   356 	while (iter)
       
   357 		{
       
   358 		c = iter++;
       
   359 		if (c->iRemoteAddress==aRemoteAddr)
       
   360 			{			
       
   361 			return c;
       
   362 			}
       
   363 		}
       
   364 	return NULL;	
       
   365 	}
       
   366 	
       
   367 CSignallingChannel* CAvdtpProtocol::FindListeningSignallingChannel()
       
   368 	{
       
   369 	LOG_FUNC
       
   370 	CSignallingChannel* c = NULL;
       
   371 	TDblQueIter<CSignallingChannel> iter(iSignallingChannels);
       
   372 	
       
   373 	while (iter)
       
   374 		{
       
   375 		c = iter++;
       
   376 		if (c->IsListening())
       
   377 			{			
       
   378 			return c;
       
   379 			}
       
   380 		}
       
   381 	return NULL;	
       
   382 	}
       
   383 	
       
   384 CSignallingChannel* CAvdtpProtocol::GetSignallingChannel(const TBTDevAddr& aRemoteAddr) 
       
   385 	{
       
   386 	LOG_FUNC
       
   387 	// if not found, create one else return it
       
   388 	CSignallingChannel* ch = FindSignallingChannel(aRemoteAddr);
       
   389 	if (!ch)
       
   390 		{
       
   391 		TRAP_IGNORE(ch = CSignallingChannel::NewL(*this, *iLogicalChannelFactory, aRemoteAddr));
       
   392 		if (ch)
       
   393 			{
       
   394 			iSignallingChannels.AddFirst(*ch);
       
   395 			}
       
   396 		}
       
   397 	return ch;
       
   398 	}
       
   399 
       
   400 /**
       
   401 This function transfers sessions attached to a listening channel to the connected signalling
       
   402 channel. It is only effective if the connected channel is the result of an active open rather
       
   403 than an incoming connection. This function does nothing in the latter case.
       
   404 */
       
   405 void CAvdtpProtocol::ConnectSignallingListeners(CSignallingChannel& aConnectedSignallingChannel)
       
   406 	{
       
   407 	LOG_FUNC
       
   408 	CSignallingChannel* listeningChannel = FindListeningSignallingChannel();
       
   409 	
       
   410 	if (listeningChannel)
       
   411 		{
       
   412 		// take off all the sessions, and re-attach to the connected signalling channel
       
   413 		TDblQueIter<XAvdtpSignalReceiver> listeningIter(const_cast<TDblQue<XAvdtpSignalReceiver>&>
       
   414 											(listeningChannel->Users()));
       
   415 		XAvdtpSignalReceiver* user;
       
   416 		
       
   417 		while ((user = listeningIter++) != NULL)
       
   418 			{
       
   419 			listeningChannel->DetachSignallingUser(*user);
       
   420 			aConnectedSignallingChannel.AttachSignallingUser(*user);
       
   421 			}	
       
   422 		}
       
   423 	// else do nothing
       
   424 	}
       
   425 	
       
   426 /**
       
   427 Find a transport channel for a transport session to bind to, allocate if needed
       
   428 Ownership is NOT returned - channels own themselves
       
   429 The protocol keeps a reference to the channel in a queue
       
   430 so that it can hand out further references (in the form of pointers) as needed
       
   431 
       
   432 Algorithm is thus:
       
   433 
       
   434 1) Deduce session type this channel would be for: s
       
   435 2) Deduce device address this channel would be for: d
       
   436 3) Deduce Stream this channel would be for: S
       
   437 4) Find the stream container object for S - this say if we can mux
       
   438 5) If mux then find a TC with different S if s = Recovery
       
   439 6) elseif !mux then create new TC
       
   440 */
       
   441 CTransportChannel* CAvdtpProtocol::GetTransportChannel(const TAvdtpSockAddr& aRemoteAddr,
       
   442 													 	TBool aUseMux,
       
   443 													 	TTCID aRemotelyAssignedTTCID/*=KInvalidTCID*/)
       
   444 	{
       
   445 	LOG_FUNC
       
   446 	
       
   447 	CTransportChannel* tc = NULL;
       
   448 
       
   449 	if (aUseMux)
       
   450 		{
       
   451 		// try to find a TC we already have on which this session can go
       
   452 		TDblQueIter<CTransportChannel> iter(iTransportChannels);
       
   453 		
       
   454 		while (iter)
       
   455 			{
       
   456 			CTransportChannel* possibleChannel = iter++;
       
   457 			if (possibleChannel->CouldAttachSession(aRemoteAddr))
       
   458 				{
       
   459 				// found one
       
   460 				tc = possibleChannel;
       
   461 				break;
       
   462 				}
       
   463 			}
       
   464 		}
       
   465 		
       
   466 	if (!tc)
       
   467 		{
       
   468 		// we now know we do actually need a new TC
       
   469 		// ***but don't connect it yet***
       
   470 		__ASSERT_DEBUG(FindSignallingChannel(aRemoteAddr.BTAddr()), Panic(EAvdtpSignallingChannelShouldExist));
       
   471 		// spec is unclear but it is the case that only mux channels get assigned TCIDs
       
   472 		TInt err = KErrNone;
       
   473 		if (aUseMux)
       
   474 			{
       
   475 			TRAP(err, tc = CTransportChannel::NewMuxChannelL(*this, 
       
   476 											aRemoteAddr.BTAddr(),
       
   477 								 			aRemotelyAssignedTTCID));
       
   478 			}
       
   479 		else
       
   480 			{
       
   481 			TRAP(err, tc = CTransportChannel::NewDirectChannelL(*this, 
       
   482 											aRemoteAddr.BTAddr()));
       
   483 			}
       
   484 		if (err==KErrNone)
       
   485 			{
       
   486 			iTransportChannels.AddFirst(*tc);
       
   487 			}
       
   488 		}
       
   489 	
       
   490 	return tc;
       
   491 	}
       
   492 	
       
   493 	
       
   494 /**
       
   495 Find transport channel with TCID==aTCID
       
   496 If not found return NULL - do not create (like the Get method)
       
   497 There is no need to search for Direct Channels so this is asserted against
       
   498 */
       
   499 CTransportChannel* CAvdtpProtocol::FindMuxChannel(TTCID aTCID)
       
   500 	{
       
   501 	LOG_FUNC
       
   502 	__ASSERT_DEBUG(aTCID!=KDirectChannelTCID, Panic(EAvdtpSearchingForDirectChannel));
       
   503 
       
   504 	TDblQueIter<CTransportChannel> iter(iTransportChannels);
       
   505 	CTransportChannel* tc = NULL;
       
   506 	
       
   507 	while (iter)
       
   508 		{
       
   509 		tc = iter++;
       
   510 		if (tc->TCID() == aTCID)
       
   511 			{
       
   512 			// found it
       
   513 			__ASSERT_DEBUG(tc->TCID()!=KDirectChannelTCID, Panic(EAvdtpIncorrectlyFoundDirectChannel));
       
   514 			break;
       
   515 			}
       
   516 		}
       
   517 	
       
   518 	return tc;
       
   519 	}
       
   520 
       
   521 /**
       
   522 Called by the transport channel when it's dead
       
   523 eg when link lost, or graceful close completed
       
   524 
       
   525 @internalComponent
       
   526 @param aTransportChannel The channel that's down
       
   527 */
       
   528 void CAvdtpProtocol::TransportChannelDown(CTransportChannel& aTransportChannel)
       
   529 	{
       
   530 	LOG_FUNC
       
   531 #ifdef _DEBUG
       
   532 	TDblQueIter<CTransportChannel> openiter(iTransportChannels);
       
   533 	TBool found = EFalse;
       
   534 	while (openiter)
       
   535 		{
       
   536 		// look on open queue
       
   537 		if (openiter++ == &aTransportChannel)
       
   538 			{
       
   539 			found = ETrue;
       
   540 			break;
       
   541 			}
       
   542 		}
       
   543 	if (!found)
       
   544 		{
       
   545 		// look on closing queue
       
   546 		TDblQueIter<CTransportChannel> closingiter(iClosingTransportChannels);
       
   547 		while (closingiter)
       
   548 			{
       
   549 			// look on open queue
       
   550 			if (closingiter++ == &aTransportChannel)
       
   551 				{
       
   552 				found = ETrue;
       
   553 				break;
       
   554 				}
       
   555 			}
       
   556 		}
       
   557 	if (!found) Panic(EAvdtpProtocolToldToRemoveUnknownTransportChannel);
       
   558 #endif
       
   559 	// take off our queue, and leave the channel to delete itself
       
   560 	
       
   561 	aTransportChannel.iProtocolQLink.Deque();
       
   562 
       
   563 	if (ShouldClose())
       
   564 		{
       
   565 		QueIdleTimerEntry();
       
   566 		}
       
   567 	}
       
   568 
       
   569 /**
       
   570 Called by transport channel when it is no longer able to be used, but is closing
       
   571 */
       
   572 void CAvdtpProtocol::TransportChannelClosing(CTransportChannel& aTransportChannel)
       
   573 	{
       
   574 	LOG_FUNC
       
   575 #ifdef _DEBUG
       
   576 	TDblQueIter<CTransportChannel> iter(iTransportChannels);
       
   577 	TBool found = EFalse;
       
   578 	while (iter)
       
   579 		{
       
   580 		if (iter++ == &aTransportChannel)
       
   581 			{
       
   582 			found = ETrue;
       
   583 			break;
       
   584 			}
       
   585 		}
       
   586 	if (!found) Panic(EAvdtpProtocolToldToRemoveUnknownTransportChannel);
       
   587 #endif
       
   588 	// take off our queue, and leave the channel to delete itself
       
   589 	
       
   590 	aTransportChannel.iProtocolQLink.Deque();
       
   591 	iClosingTransportChannels.AddFirst(aTransportChannel);
       
   592 
       
   593 	// don't start looking to see if idle yet
       
   594 	}
       
   595 	
       
   596 /**
       
   597 Called by the signalling channel when it's dead.
       
   598 
       
   599 @internalComponent
       
   600 @param aSignallingChannel The channel that's down
       
   601 */
       
   602 void CAvdtpProtocol::SignallingChannelDown(CSignallingChannel& aSignallingChannel)
       
   603 	{
       
   604 	LOG_FUNC
       
   605 #ifdef _DEBUG
       
   606 	TDblQueIter<CSignallingChannel> iter(iSignallingChannels);
       
   607 	CSignallingChannel* sigch = NULL;
       
   608 	while (iter)
       
   609 		{
       
   610 		sigch = iter++;
       
   611 		if (sigch==&aSignallingChannel)
       
   612 			{
       
   613 			break;
       
   614 			}
       
   615 		}
       
   616 #ifndef _OOM_TEST
       
   617 	__ASSERT_DEBUG(sigch, Panic(EAvdtpSignallingChannelShouldExist));
       
   618 #endif
       
   619 #endif
       
   620 	
       
   621 	aSignallingChannel.iProtocolQLink.Deque();
       
   622 
       
   623 	if (ShouldClose())
       
   624 		{
       
   625 		QueIdleTimerEntry();
       
   626 		}
       
   627 	}
       
   628 	
       
   629 /**
       
   630 Asynchronous callback function.toe check if should close
       
   631 
       
   632 @internalComponent
       
   633 @param aProtocol The protocol object
       
   634 @return EFalse to indicate the callback does not need to be reissued
       
   635 */
       
   636 TInt CAvdtpProtocol::TryToClose(TAny* aProtocol)
       
   637 	{
       
   638 	LOG_STATIC_FUNC
       
   639 	CAvdtpProtocol* protocol	= static_cast<CAvdtpProtocol*>(aProtocol);
       
   640 	protocol->iIdleEntryQueued	= EFalse;
       
   641 
       
   642 	if (protocol->ShouldClose())
       
   643 		{
       
   644 		protocol->CanClose();
       
   645 		}
       
   646 
       
   647 	return EFalse; // don't try to callback again
       
   648 	}
       
   649    
       
   650 void CAvdtpProtocol::RemoveIdleTimerEntry()
       
   651 /**
       
   652 Takes us off the idle timer Q if we're on it.
       
   653 
       
   654 @internalComponent
       
   655 */
       
   656 	{
       
   657 	LOG_FUNC
       
   658 	if (iIdleEntryQueued)
       
   659 		{
       
   660 		BTSocketTimer::Remove(iIdleTimerEntry);
       
   661 		iIdleEntryQueued = EFalse;
       
   662 		}
       
   663 	}
       
   664 
       
   665 /**
       
   666 Q a timer to delete us. If already running, not reset.
       
   667 
       
   668 @internalComponent
       
   669 */
       
   670 void CAvdtpProtocol::QueIdleTimerEntry()
       
   671 	{
       
   672 	if (!iIdleEntryQueued)
       
   673 		{
       
   674 		BTSocketTimer::Queue(KAvdtpIdleTimeout, iIdleTimerEntry);
       
   675 		iIdleEntryQueued = ETrue;
       
   676 		}
       
   677 	}
       
   678 
       
   679 /**
       
   680 Called to check whether we can close down.
       
   681 
       
   682 @internalComponent
       
   683 @return ETrue if the protocol can close, EFalse if not
       
   684 */
       
   685 TBool CAvdtpProtocol::ShouldClose()
       
   686 	{
       
   687 	LOG_FUNC
       
   688 	return (iClosePending &&
       
   689 			iTransportChannels.IsEmpty() &&
       
   690 			iClosingTransportChannels.IsEmpty() &&
       
   691 			iSignallingChannels.IsEmpty());
       
   692 	}
       
   693 	
       
   694 /**
       
   695 Called from logical channel factory when bearer listening is required
       
   696 @internalComponent
       
   697 */
       
   698 TInt CAvdtpProtocol::StartProtocolListening()
       
   699 	{
       
   700 	LOG_FUNC
       
   701 	// because we do non-default security we override the base class
       
   702 	// and new the incoming listener ourselves
       
   703 	TRAPD(err, DoStartAvdtpListeningL());
       
   704 	return err;
       
   705 	}
       
   706 	
       
   707 /**
       
   708 Helper to actually start listening. This protocol doesn't use the base class
       
   709 implementation as it needs to do a bit more.
       
   710 @internalComponent
       
   711 */
       
   712 void CAvdtpProtocol::DoStartAvdtpListeningL()
       
   713 	{
       
   714 	LOG_FUNC
       
   715 	// Check that we haven't already got an iListener.
       
   716 	// NOTE: in production code we will leak an iListener
       
   717 	// these are fairly small so not too severe.
       
   718 	__ASSERT_DEBUG(iListener == NULL, Panic(EAvdtpStartedListeningAgain));
       
   719 	CServProviderBase* sap = iLowerProtocol->NewSAPL(KSockSeqPacket);
       
   720 	
       
   721 	// We listen with streaming mode by default.  This allows fallback to eRTM
       
   722 	// or basic mode if the remote requests it.  We have to do it this way round
       
   723 	// and assume the remote will correctly request a reliable channel for signalling
       
   724 	// as if we listen expecting a reliable channel we can't fall back to unreliable.
       
   725 	
       
   726 	TPckgBuf<TL2CapConfig> configBuf;
       
   727 	sap->GetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configBuf);
       
   728 	
       
   729 	configBuf().ConfigureUnreliableChannel(500);
       
   730 	configBuf().ConfigureUnreliableDesiredChannel(500, TL2CapConfig::EDefaultRetransmission);
       
   731 	sap->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configBuf);
       
   732 
       
   733 	TBTSockAddr localAddr;
       
   734 	localAddr.SetPort(0x19);
       
   735 
       
   736 	// the security settings are:	
       
   737 	// for signalling channel, authenticate, authorise
       
   738 	// (though see CIncomingConnectionListner:Preauthorise())
       
   739 	TBTServiceSecurity sec;
       
   740 	sec.SetAuthentication(EMitmDesired);
       
   741 	sec.SetAuthorisation(ETrue);
       
   742 	sec.SetEncryption(ETrue);
       
   743 	sec.SetDenied(EFalse);
       
   744 
       
   745 	sec.SetUid(KAvdtpUID);
       
   746 	
       
   747 	// as logical channels come in these settings are changed to stop
       
   748 	// multiple authorises for the stream bearers
       
   749 
       
   750 	localAddr.SetSecurity(sec);
       
   751 
       
   752 // set the MTU into SAP here - for now we put the same on all logical channels - chosen with 5 slot packets in mind
       
   753 //	TPckgBuf<TUint16> mtu;
       
   754 //	mtu() = 339;
       
   755 
       
   756 	iListener=CIncomingConnectionListener::NewL(*this, sap, localAddr, 3);										
       
   757 	}
       
   758 	
       
   759 /**
       
   760 AVDTP being a weird protocol has to to use the Logical Channel Factory for bearer listening
       
   761 So just forward to it...
       
   762 
       
   763 @param aSAP The SAP for the new lower layer connection
       
   764 @internalComponent
       
   765 */
       
   766 TInt CAvdtpProtocol::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP)
       
   767 	{
       
   768 	LOG_FUNC
       
   769 	return LogicalChannelFactory().BearerConnectComplete(aAddr, aSAP);
       
   770 	}
       
   771 
       
   772 /**
       
   773 A stream has been created and is being made known to the protocol
       
   774 @param aStream the stream being created
       
   775 @panic if protocol already knows about stream
       
   776 @internalComponent
       
   777 */
       
   778 void CAvdtpProtocol::StreamCreated(CAVStream& aStream)
       
   779 	{
       
   780 	LOG_FUNC
       
   781 #ifdef _DEBUG
       
   782 	// check not already added
       
   783 	TDblQueIter<CAVStream> iter(iStreams);
       
   784 	while (iter)
       
   785 		{
       
   786 		__ASSERT_DEBUG(iter!=&aStream, Panic(EAvdtpStreamAlreadyExists));
       
   787 		iter++;
       
   788 		}
       
   789 #endif	
       
   790 	iStreams.AddFirst(aStream);
       
   791 	}
       
   792 
       
   793 /**
       
   794 Find a stream based on it's remote address
       
   795 @panic if the SEID in the address is Local
       
   796 @param aRemoteAddr the remote address of the stream to find. The BTAddr and SEID are used
       
   797 @internalComponent
       
   798 */	
       
   799 CAVStream* CAvdtpProtocol::FindStream(const TAvdtpSockAddr& aRemoteAddr)
       
   800 	{
       
   801 	LOG_FUNC
       
   802 	CAVStream* s = NULL;
       
   803 	TDblQueIter<CAVStream> iter(iStreams);
       
   804 	__ASSERT_DEBUG(!aRemoteAddr.SEID().IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
       
   805 
       
   806 	CAVStream* i;
       
   807 	while (iter)
       
   808 		{
       
   809 		i = iter++;
       
   810 		if (i->RemoteSEID()==aRemoteAddr.SEID() &&
       
   811 				 i->DeviceAddress()==aRemoteAddr.BTAddr())
       
   812 			{
       
   813 			s = i;
       
   814 			break;
       
   815 			}
       
   816 		}
       
   817 
       
   818 	return s;
       
   819 	}
       
   820 
       
   821 
       
   822 /**
       
   823 A stream going is going down, and wishes for the protocol to remove knowledge of it
       
   824 @param aStream the stream going down
       
   825 @panic debug panic if the stream wasn't known originally
       
   826 @internalComponent
       
   827 */
       
   828 void CAvdtpProtocol::RemoveStream(CAVStream& aStream)
       
   829 	{
       
   830 	LOG_FUNC
       
   831 	CAVStream* s = NULL;
       
   832 	TDblQueIter<CAVStream> iter(iStreams);
       
   833 	
       
   834 	while (iter)
       
   835 		{
       
   836 		s = iter++;
       
   837 		if (s == &aStream)
       
   838 			{
       
   839 			s->iProtocolQLink.Deque();
       
   840 			break;
       
   841 			}
       
   842 		}
       
   843 	__ASSERT_DEBUG(s!=NULL, Panic(EAVDTPBadRemoveStream));
       
   844 	}
       
   845 	
       
   846 
       
   847 /*
       
   848 A secondary SAP has been created - we own it until a Primary SAP claims one
       
   849 @internalComponent
       
   850 */	
       
   851 void CAvdtpProtocol::AddSecondarySAP(CAvdtpSAP& aSecondarySAP)
       
   852 	{
       
   853 	LOG_FUNC
       
   854 	iSecondarySAPs.AddFirst(aSecondarySAP);
       
   855 	}
       
   856 
       
   857 /*
       
   858 Tidy up unclaimed secondary SAPs
       
   859 @internalComponent
       
   860 */	
       
   861 void CAvdtpProtocol::DestroySecondarySAPs()
       
   862 	{
       
   863 	LOG_FUNC
       
   864 	while (!iSecondarySAPs.IsEmpty())
       
   865 		{
       
   866 		CAvdtpSAP* secondarySAP = iSecondarySAPs.First();
       
   867 		iSecondarySAPs.Remove(*secondarySAP);
       
   868 		delete secondarySAP;
       
   869 		}
       
   870 	}
       
   871 	
       
   872 
       
   873 /*
       
   874 Primary SAP seeking (good-looking) Secondary SAP for protocol enjoyment
       
   875 just give it the first one	
       
   876 ownership will remain with the socket
       
   877 @internalComponent
       
   878 */
       
   879 CAvdtpSAP* CAvdtpProtocol::GetSecondarySAP()
       
   880 	{
       
   881 	LOG_FUNC
       
   882 	CAvdtpSAP* secondarySAP = NULL;
       
   883 	if (!iSecondarySAPs.IsEmpty())
       
   884 		{
       
   885 		secondarySAP = iSecondarySAPs.First();
       
   886 		iSecondarySAPs.Remove(*secondarySAP);
       
   887 		}
       
   888 	__ASSERT_DEBUG(secondarySAP, Panic(EAvdtpProtocolAskedForSecondarySAPWhenNonExist));
       
   889 	return secondarySAP;
       
   890 	}
       
   891 	
       
   892 
       
   893 /**
       
   894 Control plane message delivery system between protocols
       
   895 @return error as a result of processing or not consuming the control message
       
   896 @param aMessage the message
       
   897 @param aParam arbitrary data for message - knowledge of aMessage allows casting
       
   898 @see CBTProtocolFamily
       
   899 @internalComponent
       
   900 */
       
   901 TInt CAvdtpProtocol::ControlPlaneMessage(TBTControlPlaneMessage aMessage, TAny* aParam)
       
   902 	{
       
   903 	LOG_FUNC
       
   904 	// only ones applicable to this protocol at present are 
       
   905 	// for preauthorising a device - must have come from AVCTP, with PID=RCP
       
   906 	TInt ret = KErrNotSupported;
       
   907 	
       
   908 	switch (aMessage)
       
   909 		{
       
   910 		case EPreauthoriseDevice:
       
   911 			{
       
   912 			__ASSERT_DEBUG(aParam, Panic(EAvdtpProtocolReceivingBadlyFormedControlMessage));
       
   913 			const TOverrideAuthorise& override = *reinterpret_cast<const TOverrideAuthorise*>(aParam);
       
   914 			__ASSERT_DEBUG(override.iAuthorisingProtocol == KAVCTP, Panic(EAvdtpProtocolReceivingControlFromUnexpectedProtocol));
       
   915 			__ASSERT_DEBUG(override.iAuthorisingPort == SymbianAvctp::KAvrcpPid, Panic(EAvdtpProtocolReceivingControlFromUnexpectedPort)); //magic
       
   916 			
       
   917 			SetPreauthorisation(override.iPreauthorisedRemoteAddress,
       
   918 								override.iPreauthorise);
       
   919 			ret = KErrNone;							
       
   920 			break;
       
   921 			}
       
   922 		default:
       
   923 			__ASSERT_DEBUG(aParam, Panic(EAvdtpProtocolReceivingBadlyFormedControlMessage));
       
   924 		}
       
   925 	return ret;
       
   926 	}
       
   927 
       
   928 
       
   929 /**
       
   930 Helper to hide the need to supply the socket level to which preauthorisation pertains
       
   931 @param aPreauthorisedAddress the address of the device to preauthorise
       
   932 @param aPreauthorise ETrue if the device is allowed to be authorised for other AVDTP/AVCTP connection, EFalse to cancel
       
   933 @internalComponent
       
   934 */
       
   935 TInt CAvdtpProtocol::SetPreauthorisation(const TBTDevAddr& aPreauthoriseAddress, TBool aSetPreauthorisation)
       
   936 	{
       
   937 	LOG_FUNC
       
   938 	TInt ret = KErrNone;
       
   939 	if (IsListening())
       
   940 		{
       
   941 		if (aSetPreauthorisation && !Listener().IsPreauthorised(KSolBtL2CAP, aPreauthoriseAddress))
       
   942 			{
       
   943 			Listener().SetPreauthorisation(KSolBtL2CAP, aPreauthoriseAddress, ETrue);
       
   944 			
       
   945 			TOverrideAuthorise override;
       
   946 			override.iAuthorisingProtocol = KAVDTP;
       
   947 			override.iPreauthorise = aSetPreauthorisation;
       
   948 			override.iPreauthorisedRemoteAddress = aPreauthoriseAddress;
       
   949 			
       
   950 			ControlPlane().Preauthorise(KAVCTP, override);
       
   951 			}
       
   952 		else if (!aSetPreauthorisation)
       
   953 			{
       
   954 			Listener().SetPreauthorisation(KSolBtL2CAP, aPreauthoriseAddress, EFalse);			
       
   955 			}
       
   956 		// else do nothing
       
   957 		}
       
   958 	else
       
   959 		{
       
   960 		ret = KErrNotReady;
       
   961 		}
       
   962 		
       
   963 	return ret;
       
   964 	}