bluetooth/btstack/avdtp/avdtpLogicalChannelFactory.cpp
changeset 0 29b1cd4cb562
child 22 786b94c6f0a4
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 logical channel factory
       
    15 // which creates the logical (L2CAP) channels for transport and signalling channels
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22 */
       
    23 
       
    24 #include <bluetooth/logger.h>
       
    25 #include <bluetoothav.h>
       
    26 
       
    27 #include "bt.h"
       
    28 #include "avdtpLogicalChannelFactory.h"
       
    29 #include "gavdpinterface.h"
       
    30 #include "avdtputil.h"
       
    31 #include "avdtp.h"
       
    32 #include "avdtpDirectChannel.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
       
    36 #endif
       
    37 
       
    38 CLogicalChannelFactory* CLogicalChannelFactory::NewL(CBluetoothProtocolBase& aProtocol, CProtocolBase& aSAPFactory)
       
    39 	{
       
    40 	LOG_STATIC_FUNC
       
    41 	CLogicalChannelFactory* f = new (ELeave) CLogicalChannelFactory(aProtocol, aSAPFactory);
       
    42 	CleanupStack::PushL(f);
       
    43 	f->ConstructL();
       
    44 	CleanupStack::Pop(f);
       
    45 	return f;
       
    46 	}
       
    47 	
       
    48 
       
    49 CLogicalChannelFactory::CLogicalChannelFactory(CBluetoothProtocolBase& aProtocol,
       
    50 												CProtocolBase& aSAPFactory)
       
    51 : iProtocol(aProtocol), iBearerSAPFactory(aSAPFactory),
       
    52   iUnclaimedLogicalChannels(_FOFF(CManagedLogicalChannel, iFactoryQLink)),
       
    53   iPendingActiveJobs(_FOFF(CLogicalChannelFactoryRequest, iFactoryQLink)),
       
    54   iPendingPassiveSignallingJobs(_FOFF(CLogicalChannelFactoryRequest, iFactoryQLink)),
       
    55   iPendingPassiveSessionJobs(_FOFF(CLogicalChannelFactoryRequest, iFactoryQLink)),
       
    56   iCloseChannelJobs(_FOFF(CLogicalChannelFactoryRequest, iFactoryQLink))
       
    57 	{
       
    58 	LOG_FUNC
       
    59 	}
       
    60 
       
    61 CLogicalChannelFactory::~CLogicalChannelFactory()
       
    62 	{
       
    63 	LOG_FUNC
       
    64 	iProtocol.StopProtocolListening();
       
    65 	// iterator through jobs and destroy - they'll take down unclaimed channels
       
    66 	TSglQueIter<CLogicalChannelFactoryActiveRequest> iter(iPendingActiveJobs);
       
    67 	
       
    68 	while (iter)
       
    69 		{
       
    70 		delete iter++;
       
    71 		}
       
    72 
       
    73 	TSglQueIter<CCloseSessionLogicalChannels> closeIter(iCloseChannelJobs);
       
    74 	while(closeIter)
       
    75 		{
       
    76 		delete closeIter++;
       
    77 		}
       
    78 		
       
    79 	TDblQueIter<CManagedLogicalChannel> unclaimedChannelsIter(iUnclaimedLogicalChannels);
       
    80 	
       
    81 	while (unclaimedChannelsIter)
       
    82 		{
       
    83 		delete unclaimedChannelsIter++;
       
    84 		}
       
    85 	
       
    86 	// We shouldn't be deleted when we have a job outstanding
       
    87 	__ASSERT_DEBUG(!iAsyncTryNextJob->IsActive(), Panic(EAvdtpLogicalChannelFactoryDeletionWhileJobPending));
       
    88 	delete iAsyncTryNextJob;
       
    89 	delete iCurrentActiveJob;
       
    90 	}
       
    91 	
       
    92 void CLogicalChannelFactory::ConstructL()
       
    93 	{
       
    94 	LOG_FUNC
       
    95 	TCallBack callback(TryNextJob, this);
       
    96 	iAsyncTryNextJob = new(ELeave) CAsyncCallBack(callback, CActive::EPriorityStandard);
       
    97 	}
       
    98 
       
    99 
       
   100 CCreateSignallingLogicalChannel* CCreateSignallingLogicalChannel::NewLC(const TBTDevAddr& aAddr,
       
   101 																		XLogicalChannelFactoryClient& aClient,
       
   102 																		TLogicalChannelFactoryRequestId aId,
       
   103 																		CLogicalChannelFactory& aLogicalChannelFactory)
       
   104 	{
       
   105 	LOG_STATIC_FUNC
       
   106 	CCreateSignallingLogicalChannel* r = new (ELeave) CCreateSignallingLogicalChannel(aAddr, aClient, aId);
       
   107 	CleanupStack::PushL(r);
       
   108 	r->ConstructL(aLogicalChannelFactory); // create the channel holders
       
   109 	return r;
       
   110 	}
       
   111 
       
   112 CCreateSignallingLogicalChannel* CCreateSignallingLogicalChannel::NewL(const TBTDevAddr& aAddr,
       
   113 																	   XLogicalChannelFactoryClient& aClient,
       
   114 																	   TLogicalChannelFactoryRequestId aId,
       
   115 																	   CLogicalChannelFactory& aLogicalChannelFactory)
       
   116 	{
       
   117 	LOG_STATIC_FUNC
       
   118 	CCreateSignallingLogicalChannel* r =
       
   119 							CCreateSignallingLogicalChannel::NewLC(aAddr,
       
   120 																   aClient,
       
   121 																   aId,
       
   122 																   aLogicalChannelFactory);
       
   123 	CleanupStack::Pop();
       
   124 	return r;
       
   125 	}
       
   126 	
       
   127 	
       
   128 void CCreateSignallingLogicalChannel::ConstructL(CLogicalChannelFactory& aLogicalChannelFactory)
       
   129 	{
       
   130 	LOG_FUNC
       
   131 	iLogicalChannels[0] = CManagedLogicalChannel::NewL(aLogicalChannelFactory,
       
   132 														iRemoteDev,
       
   133 														KInitialSequenceNumber,
       
   134 														iId);
       
   135 	}
       
   136 
       
   137 	
       
   138 CCreateSignallingLogicalChannel::CCreateSignallingLogicalChannel(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId)
       
   139 : CLogicalChannelFactoryActiveRequest(aAddr, aClient, aId)
       
   140 	{
       
   141 	LOG_FUNC
       
   142 	// this job has one channel
       
   143 	iNumChannelsRequired = 1;
       
   144 	// so SAP[0] is a signalling SAP
       
   145 	}
       
   146 		
       
   147 CCreateSessionLogicalChannels* CCreateSessionLogicalChannels::NewLC(const TBTDevAddr& aAddr,
       
   148 													XLogicalChannelFactoryClient& aClient,
       
   149 													TLogicalChannelFactoryRequestId aId,
       
   150 													TInt aNumRequired)
       
   151 	{
       
   152 	LOG_STATIC_FUNC
       
   153 	CCreateSessionLogicalChannels* r =
       
   154 		new (ELeave) CCreateSessionLogicalChannels(aAddr, aClient, aId, aNumRequired);
       
   155 	CleanupStack::PushL(r);
       
   156 	return r;
       
   157 	}
       
   158 
       
   159 CCreateSessionLogicalChannels* CCreateSessionLogicalChannels::NewL(const TBTDevAddr& aAddr,
       
   160 												   XLogicalChannelFactoryClient& aClient,
       
   161 												   TLogicalChannelFactoryRequestId aId,
       
   162 												   TInt aNumRequired)
       
   163 	{
       
   164 	LOG_STATIC_FUNC
       
   165 	CCreateSessionLogicalChannels* r = new (ELeave) CCreateSessionLogicalChannels(aAddr,
       
   166 														aClient,
       
   167 														aId,
       
   168 														aNumRequired);
       
   169 	return r;
       
   170 	}
       
   171 	
       
   172 CCreateSessionLogicalChannels::CCreateSessionLogicalChannels(const TBTDevAddr& aAddr,
       
   173 											 XLogicalChannelFactoryClient& aClient,
       
   174 											 TLogicalChannelFactoryRequestId aId,
       
   175 											 TInt aNumRequired)
       
   176 : CLogicalChannelFactoryActiveRequest(aAddr, aClient, aId)
       
   177 	{
       
   178 	LOG_FUNC
       
   179 	// this job has one, two or three channels - but all need to come up for success
       
   180 	iNumChannelsRequired = aNumRequired;
       
   181 	}
       
   182 
       
   183 //************************************************************************
       
   184 // Close Logical Channels
       
   185 //************************************************************************
       
   186 
       
   187 CCloseSessionLogicalChannels* CCloseSessionLogicalChannels::NewL(XLogicalChannelFactoryClient& aClient,
       
   188 												   TLogicalChannelFactoryRequestId aId)
       
   189 	{
       
   190 	LOG_STATIC_FUNC
       
   191 	CCloseSessionLogicalChannels* r =  CCloseSessionLogicalChannels::NewLC(aClient, aId);
       
   192 	CleanupStack::Pop(r);
       
   193 	return r;
       
   194 	}
       
   195 
       
   196 CCloseSessionLogicalChannels* CCloseSessionLogicalChannels::NewLC(XLogicalChannelFactoryClient& aClient,
       
   197 												   TLogicalChannelFactoryRequestId aId)
       
   198 	{
       
   199 	LOG_STATIC_FUNC
       
   200 	CCloseSessionLogicalChannels* r = new (ELeave) CCloseSessionLogicalChannels(aClient,
       
   201 														aId);
       
   202 	CleanupStack::PushL(r);
       
   203 	return r;
       
   204 	}
       
   205 
       
   206 CCloseSessionLogicalChannels::~CCloseSessionLogicalChannels()
       
   207 	{
       
   208 	LOG_STATIC_FUNC
       
   209 	BTSocketTimer::Remove(iTimerEntry);
       
   210 	CloseChannels(EFalse);
       
   211 	}
       
   212 
       
   213 /**
       
   214 One of this job's logical channels has been closed by the remote.  If this
       
   215 is the final remaining channel the job is completed.
       
   216 
       
   217 @param aChannel The channel that has been closed.
       
   218 */
       
   219 void CCloseSessionLogicalChannels::ChannelClosed(CManagedLogicalChannel* aChannel)
       
   220 	{
       
   221 	LOG_FUNC
       
   222 
       
   223 	TBool channelsRemaining = EFalse;
       
   224 
       
   225 	for(TInt i = 0; i < KAvdtpChannelArraySize; i++)
       
   226 		{
       
   227 		if(iLogicalChannels[i] == aChannel)
       
   228 			{
       
   229 			iLogicalChannels[i] = NULL;
       
   230 			}
       
   231 		else if(iLogicalChannels[i])
       
   232 			{
       
   233 			channelsRemaining = ETrue;
       
   234 			}
       
   235 		}
       
   236 
       
   237 	aChannel->Shutdown();
       
   238 	delete aChannel;
       
   239 
       
   240 	if(!channelsRemaining)
       
   241 		{
       
   242 		BTSocketTimer::Remove(iTimerEntry);
       
   243 		
       
   244 		// Notify factory of request completion
       
   245 		TLogicalChannelFactoryTicket ticket(NULL, iId);
       
   246 		iClient.LogicalChannelFactoryRequestComplete(ticket, KErrNone);
       
   247 		}
       
   248 	}
       
   249 
       
   250 /**
       
   251 Begin the job.  
       
   252 
       
   253 @param aTimeout Number of milliseconds to wait for the remote to close
       
   254 				the channels before locally initiating the shutdown.
       
   255 */
       
   256 void CCloseSessionLogicalChannels::StartJob(TInt aTimeout)	
       
   257 	{
       
   258 	LOG_FUNC
       
   259 
       
   260 	if(aTimeout)
       
   261 		{
       
   262 		TCallBack callBack(WatchdogBarked, this);
       
   263 		iTimerEntry.Set(callBack);
       
   264 
       
   265 		BTSocketTimer::Queue(aTimeout, iTimerEntry);
       
   266 		}
       
   267 	else
       
   268 		{
       
   269 		CloseChannels(ETrue);
       
   270 		}
       
   271 	}
       
   272 
       
   273 /**
       
   274 Static function called on expiry of channel close watchdog.
       
   275 */
       
   276 TInt CCloseSessionLogicalChannels::WatchdogBarked(TAny* aCloseLogicalChannels)
       
   277 	{
       
   278 	LOG_STATIC_FUNC
       
   279 	static_cast<CCloseSessionLogicalChannels*>(aCloseLogicalChannels)->CloseChannels(ETrue);
       
   280 
       
   281 	return KErrNone;
       
   282 	}
       
   283 	
       
   284 /**
       
   285 Close all remaining channels.  
       
   286 
       
   287 @param aNotifyCompletion if ETrue then inform client that job is complete
       
   288 						 if EFalse then silently close remaining channels
       
   289 */
       
   290 void CCloseSessionLogicalChannels::CloseChannels(TBool aNotifyCompletion)
       
   291 	{
       
   292 	LOG_FUNC
       
   293 
       
   294 	for(TInt i = 0; i < KAvdtpChannelArraySize; i++)
       
   295 		{
       
   296 		if(iLogicalChannels[i])
       
   297 			{
       
   298 			iLogicalChannels[i]->Shutdown();
       
   299 			delete iLogicalChannels[i];
       
   300 			iLogicalChannels[i] = NULL;
       
   301 			}
       
   302 		}
       
   303 
       
   304 	if(aNotifyCompletion)
       
   305 		{
       
   306 		// Notify factory of request completion
       
   307 		TLogicalChannelFactoryTicket ticket(NULL, iId);
       
   308 		iClient.LogicalChannelFactoryRequestComplete(ticket, KErrNone);
       
   309 		}
       
   310 	}
       
   311 
       
   312 /** 
       
   313 Constructor.
       
   314 
       
   315 @param aClient Client to be notified on completion of this job. 
       
   316 @param aId The job id of this job.
       
   317 */
       
   318 CCloseSessionLogicalChannels::CCloseSessionLogicalChannels(XLogicalChannelFactoryClient& aClient,
       
   319 											 TLogicalChannelFactoryRequestId aId)
       
   320 : CLogicalChannelFactoryRequest(aClient, aId)
       
   321 	{
       
   322 	LOG_FUNC
       
   323 	}
       
   324 
       
   325 CLogicalChannelFactoryRequest::CLogicalChannelFactoryRequest(XLogicalChannelFactoryClient& aClient,
       
   326 															 TLogicalChannelFactoryRequestId aId)
       
   327 : iClient(aClient), iId(aId)
       
   328 	{
       
   329 	LOG_FUNC
       
   330 	}
       
   331 	
       
   332 CLogicalChannelFactoryPassiveRequest::CLogicalChannelFactoryPassiveRequest(XLogicalChannelFactoryClient& aClient,
       
   333     																		  TLogicalChannelFactoryRequestId aId,
       
   334     																		  CBluetoothProtocolBase& aAvdtp)
       
   335  : CLogicalChannelFactoryRequest(aClient, aId), iAvdtp(aAvdtp)
       
   336    	{
       
   337    	LOG_FUNC
       
   338    	}
       
   339 
       
   340 CLogicalChannelFactoryPassiveRequest::~CLogicalChannelFactoryPassiveRequest()
       
   341  	{
       
   342 	LOG_FUNC
       
   343  	iAvdtp.DecrementListeners();
       
   344  	} 
       
   345    	
       
   346 void CLogicalChannelFactoryPassiveRequest::BaseConstructL()
       
   347  	{
       
   348  	LOG_FUNC
       
   349  	User::LeaveIfError(iAvdtp.IncrementListeners());
       
   350  	}
       
   351 	
       
   352 CLogicalChannelFactoryActiveRequest::CLogicalChannelFactoryActiveRequest(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId)
       
   353 : CLogicalChannelFactoryRequest(aClient, aId), iRemoteDev(aAddr)
       
   354 	{
       
   355 	LOG_FUNC
       
   356 	}
       
   357 
       
   358 CExpectSignallingLogicalChannel* CExpectSignallingLogicalChannel::NewL(XLogicalChannelFactoryClient& aClient,
       
   359  																	   TLogicalChannelFactoryRequestId aId,
       
   360  																	   CBluetoothProtocolBase& aAvdtp)											 
       
   361    	{
       
   362    	LOG_STATIC_FUNC
       
   363  	CExpectSignallingLogicalChannel* req = new (ELeave)CExpectSignallingLogicalChannel(aClient, aId, aAvdtp);
       
   364  	CleanupStack::PushL(req);
       
   365  	req->ConstructL();
       
   366  	CleanupStack::Pop(req);
       
   367  	return req;
       
   368  	}
       
   369  	
       
   370 void CExpectSignallingLogicalChannel::ConstructL()
       
   371  	{
       
   372  	LOG_FUNC
       
   373 	BaseConstructL();
       
   374    	}
       
   375    
       
   376 CExpectSignallingLogicalChannel::CExpectSignallingLogicalChannel(XLogicalChannelFactoryClient& aClient,
       
   377  																 TLogicalChannelFactoryRequestId aId,
       
   378  																 CBluetoothProtocolBase& aAvdtp)
       
   379 : CLogicalChannelFactoryPassiveRequest(aClient, aId, aAvdtp)
       
   380    	{
       
   381    	LOG_FUNC
       
   382    	iNumChannelsRequired = 1;
       
   383    	}
       
   384    
       
   385 CExpectSessionLogicalChannels* CExpectSessionLogicalChannels::NewL(XLogicalChannelFactoryClient& aClient,
       
   386 																   TLogicalChannelFactoryRequestId aId,
       
   387 										   						   TInt aNumRequired,
       
   388 										   						   CBluetoothProtocolBase& aAvdtp)
       
   389 	{
       
   390 	LOG_STATIC_FUNC
       
   391 	CExpectSessionLogicalChannels* req = new (ELeave)CExpectSessionLogicalChannels(aClient, aId, aNumRequired, aAvdtp);
       
   392 	CleanupStack::PushL(req);
       
   393 	req->ConstructL();
       
   394 	CleanupStack::Pop(req);
       
   395 	return req;
       
   396 	}
       
   397  
       
   398 void CExpectSessionLogicalChannels::ConstructL()
       
   399  	{
       
   400  	LOG_FUNC
       
   401  	BaseConstructL();
       
   402    	}
       
   403    
       
   404 CExpectSessionLogicalChannels::CExpectSessionLogicalChannels(XLogicalChannelFactoryClient& aClient,
       
   405 															 TLogicalChannelFactoryRequestId aId,
       
   406 															 TInt aNumRequired,
       
   407 															 CBluetoothProtocolBase& aAvdtp)
       
   408 : CLogicalChannelFactoryPassiveRequest(aClient, aId, aAvdtp)
       
   409 	{
       
   410 	LOG_FUNC
       
   411 	iNumChannelsRequired = aNumRequired;
       
   412 	}
       
   413 
       
   414 CLogicalChannelFactoryActiveRequest::~CLogicalChannelFactoryActiveRequest()
       
   415 	{
       
   416 	LOG_FUNC
       
   417 	// clear up any unclaimed stuff - array will be empty if saps claimed
       
   418 	for (TInt i=0; i<iLogicalChannels.Count(); i++)
       
   419 		{
       
   420 		delete iLogicalChannels[i];
       
   421 		}
       
   422 	}
       
   423 		
       
   424 void CLogicalChannelFactory::DeleteRequest(CLogicalChannelFactoryRequest *aRequest)
       
   425 	{
       
   426 	LOG_FUNC
       
   427 	
       
   428 	iIdManager.FreeId(aRequest->iId);	// free the ID associated with this request
       
   429 
       
   430 	delete aRequest;
       
   431 	}
       
   432 
       
   433 void CLogicalChannelFactory::Cancel(TLogicalChannelFactoryTicket& aJobSpec)
       
   434 /*
       
   435 The caller has decided they don't want to have the SAPs
       
   436 we need to find the job and update it as Cancelled
       
   437 we MUST then disconnect these channels as the remote entity will
       
   438 misunderstand what sessions could be running over them
       
   439 i.e. we cannot keep these SAPs just in case someone else wants them!
       
   440 */
       
   441 	{
       
   442 	LOG_FUNC
       
   443 	// only cancel if the job is outstanding
       
   444 	if (aJobSpec.State()==TLogicalChannelFactoryTicket::ERequestOutstanding)
       
   445 		{
       
   446 		TSglQueIter<CLogicalChannelFactoryRequest> iter(iPendingActiveJobs);
       
   447 		CLogicalChannelFactoryRequest* request = NULL;
       
   448 		TBool found = EFalse;
       
   449 		
       
   450 		while (iter)
       
   451 			{
       
   452 			// try active jobs first
       
   453 			request = iter++;
       
   454 			if (request->iId==aJobSpec.iId)
       
   455 				{
       
   456 				iPendingActiveJobs.Remove(*static_cast<CLogicalChannelFactoryActiveRequest*>(request));
       
   457 				DeleteRequest(request);
       
   458 				found = ETrue;
       
   459 				}
       
   460 			}
       
   461 			
       
   462 		if (!found)
       
   463 			{
       
   464 			// go through pending *passive signalling* jobs now
       
   465 			iter = iPendingPassiveSignallingJobs;
       
   466 			
       
   467 			while (iter)
       
   468 				{
       
   469 				request = iter++;
       
   470 				if (request->iId==aJobSpec.iId)
       
   471 					{
       
   472 					iPendingPassiveSignallingJobs.Remove(*static_cast<CLogicalChannelFactoryPassiveRequest*>(request));
       
   473 					DeleteRequest(request);
       
   474 					found = ETrue;
       
   475 					}
       
   476 				}
       
   477 			}
       
   478 			
       
   479 		if (!found)
       
   480 			{
       
   481 			// go through pending *passive session* jobs now
       
   482 			iter = iPendingPassiveSessionJobs;
       
   483 			
       
   484 			while (iter)
       
   485 				{
       
   486 				request = iter++;
       
   487 				if (request->iId==aJobSpec.iId)
       
   488 					{
       
   489 					iPendingPassiveSessionJobs.Remove(*static_cast<CLogicalChannelFactoryPassiveRequest*>(request));
       
   490 					DeleteRequest(request);
       
   491 					found = ETrue;
       
   492 					}
       
   493 				}
       
   494 			}
       
   495 				
       
   496 		if (!found)
       
   497 			{
       
   498 			// perhaps it's the current one
       
   499 			if (iCurrentActiveJob && iCurrentActiveJob->iId == aJobSpec.iId)
       
   500 				{
       
   501 				iCurrentJobCancelled = ETrue;
       
   502 				}
       
   503 			}
       
   504 		
       
   505 		if (found)
       
   506 			{
       
   507 			aJobSpec.SetState(TLogicalChannelFactoryTicket::ERequestIdle);
       
   508 			}
       
   509 		}
       
   510 	}
       
   511 
       
   512 void CLogicalChannelFactory::FreeId(TAny* aFactory)
       
   513 	{
       
   514 	LOG_STATIC_FUNC
       
   515 	CLogicalChannelFactory *fact = static_cast<CLogicalChannelFactory*>(aFactory);
       
   516 	fact->iIdManager.FreeId(fact->iId);
       
   517 	}
       
   518 	
       
   519 TLogicalChannelFactoryTicket CLogicalChannelFactory::CreateSignallingLogicalChannelL(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient)
       
   520 	{
       
   521 	LOG_FUNC
       
   522 	// check that we don't have an inbound one from remote
       
   523 	// if we have then we just use that unclaimed one
       
   524 	// if we don't then go and create an outbound one
       
   525 	TLogicalChannelFactoryRequestId id;
       
   526 	TLogicalChannelFactoryTicket::TLogicalChannelFactoryRequestState state;
       
   527 	
       
   528 	CManagedLogicalChannel* ch = FindUnclaimedLogicalChannel(aAddr, ESignalling, id);
       
   529 	if (ch)
       
   530 		{
       
   531 		state = TLogicalChannelFactoryTicket::ERequestComplete;
       
   532 		// they'll come back and get SAP off their request
       
   533 		}
       
   534 	else
       
   535 		{
       
   536 		// need to create a new one
       
   537 		User::LeaveIfError(iIdManager.GetId(id));
       
   538 		iId = id; // just in case we need to clean it up this needs to be stored
       
   539 		CleanupStack::PushL(TCleanupItem(FreeId, (TAny*)this));
       
   540 		CCreateSignallingLogicalChannel* req =
       
   541 				CCreateSignallingLogicalChannel::NewL(aAddr,
       
   542 													  aClient,
       
   543 													  id,
       
   544 													  *this);
       
   545 		CleanupStack::Pop();
       
   546 		// got a complete job to do - put into job list
       
   547 		iPendingActiveJobs.AddLast(*req);
       
   548 
       
   549 		state = TLogicalChannelFactoryTicket::ERequestOutstanding;
       
   550 		TryNextActiveJob();
       
   551 		}
       
   552 
       
   553 	TLogicalChannelFactoryTicket ticket(this, id);
       
   554 	ticket.SetState(state);
       
   555 	return ticket;
       
   556 	}
       
   557 
       
   558 TLogicalChannelFactoryTicket CLogicalChannelFactory::CreateSessionLogicalChannelsL(
       
   559 								const TBTDevAddr& aAddr,
       
   560 								XLogicalChannelFactoryClient& aClient,
       
   561 								TInt aNumRequired)
       
   562 	{
       
   563 	LOG_FUNC
       
   564 //#pragma message("Check not already got or getting signalling channel for remote")
       
   565 	
       
   566 	TLogicalChannelFactoryRequestId id;
       
   567 	User::LeaveIfError(iIdManager.GetId(id));
       
   568 	
       
   569 	iId = id; // just in case we need to clean it up this needs to be stored
       
   570 	CleanupStack::PushL(TCleanupItem(FreeId, (TAny*)this));
       
   571 	CCreateSessionLogicalChannels* req = CCreateSessionLogicalChannels::NewLC(aAddr, aClient, id, aNumRequired);
       
   572 		
       
   573 	CManagedLogicalChannel* ch;
       
   574 	// we connect up the SAPs backwards to save a member variable (a counter)
       
   575 	// so the sequence number needs to go backwards
       
   576 	// then the claimer (who specifies sequence number) is really getting the
       
   577 	// right sequence number (e.g. the 3rd channel connected really was the 3rd)
       
   578 	for (TInt chIndex=aNumRequired-1; chIndex>=0; chIndex--)
       
   579 		{
       
   580 		// sequene number is 1 indexed, so chIndex+1...
       
   581 		ch = CManagedLogicalChannel::NewL(*this, aAddr, chIndex+1, id);
       
   582 		// transfer ownership to request
       
   583 		req->iLogicalChannels[chIndex] = ch;														  
       
   584 		}	
       
   585 											  
       
   586 	CleanupStack::Pop(req);
       
   587 	CleanupStack::Pop();
       
   588 	// got a complete job to do - put into job list
       
   589 	iPendingActiveJobs.AddLast(*req);			
       
   590 	TryNextActiveJob();
       
   591 	
       
   592 	TLogicalChannelFactoryTicket ticket(this, id);
       
   593 	ticket.SetState(TLogicalChannelFactoryTicket::ERequestOutstanding);
       
   594 	return ticket;
       
   595 	}
       
   596 
       
   597 /**
       
   598 Request some logical channels be closed.  This takes ownership of the lower protocol
       
   599 SAPs from the transport channels.  Unlike other logical channel factory jobs this does
       
   600 not require a client to callback on completion, as it is anticipated that clients do
       
   601 not have actions that are required on channel closure.
       
   602 
       
   603 This does not support multiplexed channels.
       
   604 
       
   605 @param aChannels CTransportChannels that are the current owners of the lower SAPs.  All transport 
       
   606 				 channels should be passed so they can be appropriately informed that they no longer 
       
   607 				 have a valid lower SAP.  Note that although ownership of the lower SAP is passed
       
   608 				 ownership of the CTransportChannel itself is not.
       
   609 @param aTimeout  If this is non-zero then this job will wait for the remote to initiate
       
   610 				 a close of the channels, with a guard timer of aTimeout milliseconds, after
       
   611 				 which it will initiate the shutdown locally.
       
   612 */
       
   613 void CLogicalChannelFactory::CloseSessionLogicalChannelsL(
       
   614 								TArray<CDirectChannel*>& aChannels,
       
   615 								TInt aTimeout)
       
   616 	{
       
   617 	LOG_FUNC
       
   618 
       
   619 	TLogicalChannelFactoryRequestId id;
       
   620 	User::LeaveIfError(iIdManager.GetId(id));
       
   621 
       
   622 	iId = id; // just in case we need to clean it up this needs to be stored
       
   623 	CleanupStack::PushL(TCleanupItem(FreeId, (TAny*)this));
       
   624 
       
   625 	// We want to take all or none of the SAP's, so we will wait until after the failable
       
   626 	// allocations before transferring SAP ownership
       
   627 	CCloseSessionLogicalChannels* req = CCloseSessionLogicalChannels::NewLC(*this, id);
       
   628 
       
   629 	CManagedLogicalChannel* ch;
       
   630 
       
   631 	for (TInt i = 0; i < KAvdtpChannelArraySize; i++)
       
   632 		{
       
   633 		// default the channel to NULL
       
   634 		// so it doesn't appear in the job we are creating
       
   635 		req->iLogicalChannels[i] = NULL;
       
   636 		if (aChannels[i])
       
   637 			{
       
   638 			ch = CManagedLogicalChannel::NewL(*this, id);
       
   639 			// transfer ownership to request
       
   640 			req->iLogicalChannels[i] = ch;	
       
   641 			}													  
       
   642 		}
       
   643 
       
   644 	// failing stuff all done now - no leaving after this point
       
   645 
       
   646 	for (TInt i = 0; i < KAvdtpChannelArraySize; i++)
       
   647 		{
       
   648 		if (aChannels[i])
       
   649 			{
       
   650 			CServProviderBase* sap = aChannels[i]->ObtainSAP();
       
   651 			/*
       
   652 			NOTE it IS possible that the channel is NOT totally setup
       
   653 			if the remote is behaving badly.
       
   654 			So in case check the channel has a SAP BEFORE 
       
   655 			calling shutdown. */
       
   656 			if (sap)
       
   657 				{
       
   658 				req->iLogicalChannels[i]->ProvideSAP(sap);
       
   659 				}
       
   660 			}													  
       
   661 		}
       
   662 
       
   663 	req->StartJob(aTimeout);
       
   664 									  
       
   665 	CleanupStack::Pop(req);
       
   666 	CleanupStack::Pop();
       
   667 
       
   668 	iCloseChannelJobs.AddLast(*req);	
       
   669 	}
       
   670 
       
   671 void CLogicalChannelFactory::DoObtainChannelL()
       
   672 	{
       
   673 	LOG_FUNC
       
   674 	__ASSERT_DEBUG(iCurrentActiveJob && iCurrentActiveJob->iNumChannelsRequired, Panic(EAvdtpLogicalChannelFactoryJobHasNoLogicalChannels));
       
   675 	
       
   676 	static const TInt KAVDTPPSM = 0x19;	
       
   677 	
       
   678 	TInt iter = 0;
       
   679 	TInt currentLogicalChannel;
       
   680 	
       
   681 	//Get the actual channel counts, (iter-1)
       
   682 	while(++iter <= iCurrentActiveJob->iLogicalChannels.Count() && iCurrentActiveJob->iLogicalChannels[iter-1] != NULL)
       
   683 		{		
       
   684 		}
       
   685 	//currentLogicalChannel's value will increase for each call, 
       
   686 	//as iCurrentActiveJob->iNumChannelsRequired decreases each time
       
   687 	currentLogicalChannel = iter - iCurrentActiveJob->iNumChannelsRequired - 1;
       
   688 	
       
   689 	//Make sure that channel's index in the array matches its sequence number('iSequenceNumber')
       
   690 	//Correct match is: index = 0 ----> iSequenceNumber = 1 (Media Channel)
       
   691 	//					index = 1 ----> iSequenceNumber = 2 (Reporting/Recovery Channel)
       
   692 	//					index = 2 ----> iSequenceNumber = 3 (Reporting/Recovery Channel)
       
   693 	//Please refer to function: CLogicalChannelFactory::CreateSessionLogicalChannelsL()
       
   694 	__ASSERT_DEBUG(iCurrentActiveJob->iLogicalChannels[currentLogicalChannel]->iSequenceNumber == currentLogicalChannel + 1, 
       
   695 						Panic(EAvdtpLogicalChannelArrayMismatchesIndexAndSequence));
       
   696 	
       
   697 	// working forwards through array of SAPs requiring connections
       
   698 	CServProviderBase& sap = 
       
   699 		*iCurrentActiveJob->iLogicalChannels[currentLogicalChannel]->iLogicalChannelSAP;
       
   700 
       
   701 	// for the 'active' SAP we become the socket for now
       
   702 	sap.SetNotify(this);
       
   703 	
       
   704 	TBTServiceSecurity sec;
       
   705 	sec.SetAuthentication(EMitmDesired);
       
   706 	sec.SetAuthorisation(EFalse);
       
   707 	sec.SetEncryption(ETrue);
       
   708 	sec.SetDenied(EFalse);
       
   709 
       
   710 	TL2CAPSockAddr addr;
       
   711 	addr.SetBTAddr(iCurrentActiveJob->iRemoteDev);
       
   712 	addr.SetPort(KAVDTPPSM);
       
   713 	addr.SetSecurity(sec);
       
   714 	
       
   715 	TInt err = sap.SetRemName(addr);
       
   716 	__ASSERT_DEBUG(err==KErrNone, Panic(EAvdtpUnexpectedErrorFromL2CAP));
       
   717 	
       
   718 	sap.ActiveOpen();
       
   719 	
       
   720 	// The call to ActiveOpen could affect iCurrentActiveJob if 
       
   721 	// L2CAP synchrononously errors -- in which case iCurrentActiveJob could now
       
   722 	// have become NULL. Make sure it is still valid.
       
   723 	if (iCurrentActiveJob)
       
   724 		{		
       
   725 		// decrement how many more channels required for this job
       
   726 		--iCurrentActiveJob->iNumChannelsRequired;
       
   727 		iCurrentJobCancelled = EFalse;
       
   728 		}
       
   729 	// a next job may be attempted from a synchronous error from l2cap
       
   730 	}
       
   731 
       
   732 /**
       
   733 This examines the job queue and tries to pass off the new channel to an outstanding
       
   734 job.
       
   735 
       
   736 @param aRemote The device from which the connection orginates
       
   737 @param aSAP An L2CAP SAP.  The job initiator takes this from the factory on
       
   738 			successful job completion.
       
   739 @return KErrNone if the connection was successfully taken by the job.
       
   740 		KErrNotReady if there are no jobs on this queue.
       
   741 		System wide error if the new PendingLogicalChannel could not be created.
       
   742 */	
       
   743 TInt CLogicalChannelFactory::TryToTakeConnection(const TBTDevAddr& aRemote,
       
   744 	CServProviderBase* aSAP, TSglQue<CLogicalChannelFactoryPassiveRequest>& aJobQueue)
       
   745 	{
       
   746 	LOG_FUNC
       
   747 	
       
   748 	if(aJobQueue.IsEmpty())
       
   749 		{
       
   750 		// No jobs on this queue mate!
       
   751 		return KErrNotReady;
       
   752 		}
       
   753 
       
   754 	CLogicalChannelFactoryPassiveRequest* job = aJobQueue.First();
       
   755 
       
   756 	// need to place this newSAP into a logical channel - then put that into job
       
   757 	TInt seqNumber = KInitialSequenceNumber;
       
   758 	TDblQueIter<CManagedLogicalChannel> iter(iUnclaimedLogicalChannels);
       
   759 	
       
   760 	while (iter)
       
   761 		{
       
   762 		CManagedLogicalChannel* r = iter++;
       
   763 		if (r->iRemoteAddress == aRemote)
       
   764 			{
       
   765 			seqNumber++;
       
   766 			}
       
   767 		}
       
   768 
       
   769 	// job doesnt take ownership yet
       
   770 	CManagedLogicalChannel* pch = NULL;
       
   771 	TRAPD(err, pch = CManagedLogicalChannel::NewL(*this, aRemote, seqNumber, job->iId, aSAP));
       
   772 	if (err==KErrNone)
       
   773 		{
       
   774 		iUnclaimedLogicalChannels.AddFirst(*pch);
       
   775 		if (--job->iNumChannelsRequired == 0)
       
   776 			{
       
   777 			// all channels obtained
       
   778 			aJobQueue.Remove(*job);
       
   779 			NotifyComplete(KErrNone, *job);
       
   780 			delete job;
       
   781 			}
       
   782 		}
       
   783 		
       
   784 	return err;
       
   785 	}	
       
   786 
       
   787 TInt CLogicalChannelFactory::BearerConnectComplete(const TBTDevAddr& aRemote,
       
   788 													CServProviderBase* aSAP)
       
   789 	{
       
   790 	LOG_FUNC
       
   791 	// inbound connection!!
       
   792 	// then bung on queue and notify 
       
   793 	
       
   794 	if (iPendingPassiveSignallingJobs.IsEmpty() && iPendingPassiveSessionJobs.IsEmpty())
       
   795 		{
       
   796 		return KErrNotReady; // connection will be auto-disposed by listener
       
   797 		}
       
   798 	
       
   799 	if (iCurrentActiveJob)
       
   800 		{
       
   801 		// we're doing outbound stuff - need to make sure it's not to same remote
       
   802 		// as it would then be being naughty...
       
   803 		if (iCurrentActiveJob->iRemoteDev == aRemote)
       
   804 			{
       
   805 			//tsk tsk
       
   806 			return KErrAlreadyExists; // connection will be auto-disposed
       
   807 			}
       
   808 		}
       
   809 
       
   810 	TInt res;
       
   811 	// We need to work out what type of session this is.  Because the first, and only
       
   812 	// the first, channel to each remote must be a signalling channel we can use this 
       
   813 	// information to decide whether to use this new channel to complete a signalling
       
   814 	// job or a session job.
       
   815 	if((static_cast<CAvdtpProtocol&>(iProtocol)).FindSignallingChannel(aRemote))
       
   816 		{
       
   817 		// Already got a signalling channel, complete a session job if we have one
       
   818 		LOG(_L("Looking for a session job to complete"));
       
   819 		res = TryToTakeConnection(aRemote, aSAP, iPendingPassiveSessionJobs);
       
   820 		}
       
   821 	else
       
   822 		{
       
   823 		// No signalling channel yet, complete a signalling job if we have one
       
   824 		LOG(_L("Looking for a signalling job to complete"));
       
   825 		res = TryToTakeConnection(aRemote, aSAP, iPendingPassiveSignallingJobs);
       
   826 		}
       
   827 
       
   828 	return res;
       
   829 	}
       
   830 
       
   831 
       
   832 // from MSocketNotify
       
   833 void CLogicalChannelFactory::NewData(TUint /*aCount*/)
       
   834 	{
       
   835 	LOG_FUNC
       
   836 	// we should have transferred ownership before newdata is called
       
   837 	__DEBUGGER();
       
   838 	}
       
   839 
       
   840 void CLogicalChannelFactory::CanSend()
       
   841 	{
       
   842 	LOG_FUNC
       
   843 	// we don't send data
       
   844 	__DEBUGGER();
       
   845 	}
       
   846 
       
   847 void CLogicalChannelFactory::ConnectComplete()
       
   848 	{
       
   849 	LOG_FUNC
       
   850 	// that's what we want!
       
   851 	TBool done = CheckActiveJobComplete(*iCurrentActiveJob);
       
   852 	
       
   853 	if (done)
       
   854 		{
       
   855 //		LOG1(_L("ConnectComplete for request: id=%d"), iCurrentActiveJob->iId)
       
   856 		CompleteActiveJob(KErrNone);
       
   857 		}
       
   858 	else
       
   859 		{
       
   860 		// more channels required for job
       
   861 //		LOG1(_L("ConnectComplete for request: id=%d (but more channels needed)"), iCurrentActiveJob->iId)
       
   862 		TRAPD(err, DoObtainChannelL());
       
   863 		if (err)
       
   864 			{
       
   865 			CompleteActiveJob(KErrNoMemory);
       
   866 			}
       
   867 		}
       
   868 	}
       
   869 
       
   870 void CLogicalChannelFactory::ConnectComplete(const TDesC8& /*aConnectData*/)
       
   871 	{
       
   872 	LOG_FUNC
       
   873 	// no connect data supported
       
   874 	ConnectComplete();
       
   875 	}
       
   876 	
       
   877 void CLogicalChannelFactory::ConnectComplete(CServProviderBase& /*aSAP*/)
       
   878 	{
       
   879 	LOG_FUNC
       
   880 	__DEBUGGER(); // should have come via protocol's listener
       
   881 	}
       
   882 	
       
   883 void CLogicalChannelFactory::ConnectComplete(CServProviderBase& /*aSAP*/,const TDesC8& /*aConnectData*/)
       
   884 	{
       
   885 	LOG_FUNC
       
   886 	// not used	
       
   887 	__DEBUGGER();
       
   888 	}
       
   889 
       
   890 void CLogicalChannelFactory::CanClose(TDelete /*aDelete*/)
       
   891 	{
       
   892 	LOG_FUNC
       
   893 	// not used
       
   894 	__DEBUGGER();
       
   895 	}
       
   896 
       
   897 void CLogicalChannelFactory::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
   898 	{
       
   899 	LOG_FUNC
       
   900 	// not used
       
   901 	__DEBUGGER();
       
   902 	}
       
   903 
       
   904 void CLogicalChannelFactory::Error(TInt aError,TUint /*aOperationMask*/)
       
   905 	{
       
   906 	LOG_FUNC
       
   907 	// whoops - need to find the job on which the sap is
       
   908 	// eventually we may process jobs out of order see!
       
   909 
       
   910 	// at present we error the whole job if any channel fails
       
   911 	CompleteActiveJob(aError);
       
   912 	}
       
   913 
       
   914 void CLogicalChannelFactory::Disconnect()
       
   915 	{
       
   916 	LOG_FUNC
       
   917 	// not used
       
   918 	__DEBUGGER();
       
   919 	}
       
   920 
       
   921 void CLogicalChannelFactory::Disconnect(TDesC8& /*aDisconnectData*/)
       
   922 	{
       
   923 	LOG_FUNC
       
   924 	//not used
       
   925 	__DEBUGGER();
       
   926 	}
       
   927 
       
   928 void CLogicalChannelFactory::IoctlComplete(TDesC8* /*aBuf*/)
       
   929 	{
       
   930 	LOG_FUNC
       
   931 	// not used	
       
   932 	__DEBUGGER();
       
   933 	}
       
   934 
       
   935 void CLogicalChannelFactory::NoBearer(const TDesC8& /*aConnectionInfo*/)
       
   936 	{
       
   937 	LOG_FUNC
       
   938 	// not used	
       
   939 	__DEBUGGER();
       
   940 	}
       
   941 
       
   942 void CLogicalChannelFactory::Bearer(const TDesC8& /*aConnectionInfo*/)
       
   943 	{
       
   944 	LOG_FUNC
       
   945 	// not used
       
   946 	__DEBUGGER();
       
   947 	}
       
   948 
       
   949 /*static*/ TInt CLogicalChannelFactory::TryNextJob(TAny* aAny)
       
   950 	{
       
   951 	LOG_STATIC_FUNC
       
   952 	CLogicalChannelFactory* self = static_cast<CLogicalChannelFactory*>(aAny);
       
   953 	self->TryNextActiveJob();
       
   954 	return KErrNone;
       
   955 	}
       
   956 
       
   957 
       
   958 void CLogicalChannelFactory::TryNextActiveJob()
       
   959 	{
       
   960 	LOG_FUNC
       
   961 	// since each channel *might* take a different amount of time to come up we
       
   962 	// must serialise these so that we *and* the remote agree on the transport session
       
   963 	// that will flow over the l2cap logical channel.
       
   964 
       
   965 	// so we don't call DoObtainChannel until the previous job is completed, or there are none waiting
       
   966 	if (!iCurrentActiveJob)
       
   967 		{
       
   968 		if (!iPendingActiveJobs.IsEmpty())
       
   969 			{
       
   970 			iCurrentActiveJob = iPendingActiveJobs.First();
       
   971 			// iCurrent Job takes ownership from queue...
       
   972 			iPendingActiveJobs.Remove(*iCurrentActiveJob);
       
   973 			LOG1(_L("Obtaining channel for current active request: id=%d"), iCurrentActiveJob->iId);
       
   974 			TRAPD(error, DoObtainChannelL());
       
   975 			if (error != KErrNone)
       
   976 				{
       
   977 				CompleteActiveJob(error);
       
   978 				iCurrentActiveJob = NULL;
       
   979 				TryNextActiveJob();
       
   980 				}			
       
   981 			}
       
   982 		}
       
   983 	}
       
   984 	
       
   985 CManagedLogicalChannel* CLogicalChannelFactory::FindUnclaimedLogicalChannel(
       
   986 														const TBTDevAddr& aAddr,
       
   987 														TInt aSequenceNumber,
       
   988 														TLogicalChannelFactoryRequestId& aId)
       
   989 	{
       
   990 	LOG_FUNC
       
   991 	TDblQueIter<CManagedLogicalChannel> iter(iUnclaimedLogicalChannels);
       
   992 	
       
   993 	while (iter)
       
   994 		{
       
   995 		CManagedLogicalChannel* ch = iter++;
       
   996 		if (ch->iRemoteAddress == aAddr && ch->iSequenceNumber == aSequenceNumber)
       
   997 			{
       
   998 			aId = ch->iId;
       
   999 			return ch;
       
  1000 			}
       
  1001 		}
       
  1002 	return NULL;
       
  1003 	}
       
  1004 
       
  1005 	
       
  1006 TBool CLogicalChannelFactory::CheckActiveJobComplete(CLogicalChannelFactoryActiveRequest& aJob)
       
  1007 	{
       
  1008 	LOG_FUNC
       
  1009 	//if we get to zero - or error occurs - job is done
       
  1010 	if (iCurrentJobCancelled)
       
  1011 		{
       
  1012 		// we left the cancelled job running, to sequence the channels
       
  1013 		// but proceed no more with other channels, destroy via completion of job
       
  1014 		CompleteActiveJob(KErrCancel);
       
  1015 		return ETrue;
       
  1016 		}
       
  1017 	return (!aJob.iNumChannelsRequired);
       
  1018 	}
       
  1019 	
       
  1020 
       
  1021 void CLogicalChannelFactory::CompleteActiveJob(TInt aError)
       
  1022 	{
       
  1023 	LOG_FUNC
       
  1024 	if ((!iCurrentJobCancelled) && (iCurrentActiveJob))
       
  1025 		{
       
  1026 		if (aError == KErrNone)
       
  1027 			{
       
  1028 			for (TInt index = 0; index<iCurrentActiveJob->iLogicalChannels.Count(); index++)
       
  1029 				{
       
  1030 				CManagedLogicalChannel* ch = iCurrentActiveJob->iLogicalChannels[index];
       
  1031 				if (ch)
       
  1032 					{
       
  1033 					// put on unclaimed queue now - caller may come back synchronously
       
  1034 					iUnclaimedLogicalChannels.AddFirst(*ch);
       
  1035 					
       
  1036 					// transferred ownership, so take them off job array
       
  1037 					iCurrentActiveJob->iLogicalChannels[index] = NULL;
       
  1038 					}
       
  1039 				}
       
  1040 			}
       
  1041 		else
       
  1042 			{
       
  1043 			// leave to be destroyed below
       
  1044 			}
       
  1045 		NotifyComplete(aError, *iCurrentActiveJob);
       
  1046 		}
       
  1047 	else
       
  1048 		{
       
  1049 		// cleanup 
       
  1050 		if (iCurrentActiveJob)
       
  1051 			{
       
  1052 			iIdManager.FreeId(iCurrentActiveJob->iId);		
       
  1053 			}
       
  1054 		// rest of cleanup will be done on destruction of job
       
  1055 		}
       
  1056 	
       
  1057 	// the job is done, and the logical channels transferred onto pending queue, so delete job
       
  1058 	delete iCurrentActiveJob;
       
  1059 	iCurrentActiveJob = NULL;
       
  1060 	iAsyncTryNextJob->CallBack();
       
  1061 	}
       
  1062 
       
  1063 void CLogicalChannelFactory::NotifyComplete(TInt aError, CLogicalChannelFactoryRequest& aRequest)
       
  1064 	{
       
  1065 	LOG_FUNC
       
  1066 
       
  1067 	// if client cancelled this request, ID was already freed and NotifyComplete() should not be called
       
  1068 	__ASSERT_DEBUG(aError!=KErrCancel, Panic(EAvdtpNotifyCompleteCancelledRequest));
       
  1069 
       
  1070 	TLogicalChannelFactoryTicket ticket(this, aRequest.iId);
       
  1071 	ticket.SetState((aError==KErrNone) ? TLogicalChannelFactoryTicket::ERequestComplete : TLogicalChannelFactoryTicket::ERequestErrored);
       
  1072 
       
  1073 	aRequest.iClient.LogicalChannelFactoryRequestComplete(ticket, aError);
       
  1074 	
       
  1075 	// LogicalChannelFactoryRequestComplete() does not free the ID of errorred jobs
       
  1076 	if (aError != KErrNone)
       
  1077 		{
       
  1078 		iIdManager.FreeId(aRequest.iId);
       
  1079 		}
       
  1080 	
       
  1081 	}
       
  1082 
       
  1083 TLogicalChannelRecord CLogicalChannelFactory::ClaimLogicalChannel(TInt aSequenceNumber, TLogicalChannelFactoryRequestId aId, TBool& aFinished)
       
  1084 	{
       
  1085 	LOG_FUNC
       
  1086 	__ASSERT_DEBUG(aSequenceNumber>=KInitialSequenceNumber, Panic(EAvdtpLogicalChannelFactoryBadClaimLogicalChannel));
       
  1087 	CManagedLogicalChannel* ch = NULL;
       
  1088 	CManagedLogicalChannel* chFound = NULL;
       
  1089 	TDblQueIter<CManagedLogicalChannel> iter(iUnclaimedLogicalChannels);
       
  1090 	TInt channelsWithId=0;
       
  1091 
       
  1092 	aFinished = EFalse; // set to true below if last channel of job retrieved
       
  1093 	
       
  1094 	while (iter)
       
  1095 		{		
       
  1096 		ch = iter++;
       
  1097 		if (ch->iId == aId)
       
  1098 			{
       
  1099 			// channel is part of the request - count it
       
  1100 			++channelsWithId;
       
  1101 			
       
  1102 			if (ch->iSequenceNumber == aSequenceNumber)
       
  1103 				{
       
  1104 				// this is the channel explicitly sought
       
  1105 				ch->iFactoryQLink.Deque(); // this one link is claimed - may be more on job
       
  1106 				chFound = ch;
       
  1107 				}
       
  1108 			// don't break loop - we want to continue to see if this is the last channel for the job
       
  1109 			}
       
  1110 		}
       
  1111 		
       
  1112 	__ASSERT_DEBUG(chFound, Panic(EAvdtpLogicalChannelFactoryBadClaimLogicalChannel));
       
  1113 
       
  1114 	TLogicalChannelRecord rec;
       
  1115 	rec.iLogicalChannelSAP = chFound->ObtainSAP();
       
  1116 	rec.iDataCount = chFound->iDataCount;
       
  1117 	rec.iEndOfData = chFound->iEndOfData;	
       
  1118 	
       
  1119 	// logicalchannel is no longer pending, so remove
       
  1120 	delete chFound;
       
  1121 	
       
  1122 	// but don't release the id until all the logical channels on the job claimed
       
  1123 	if (channelsWithId==1)	
       
  1124 		{
       
  1125 		// that was the last channel on the job, so the job id can be freed
       
  1126 		iIdManager.FreeId(aId);
       
  1127 		aFinished = ETrue;
       
  1128 		}
       
  1129 	
       
  1130 	return rec;
       
  1131 	}
       
  1132 	
       
  1133 TLogicalChannelFactoryTicket CLogicalChannelFactory::ExpectSignallingLogicalChannelL(XLogicalChannelFactoryClient& aClient)
       
  1134 	{
       
  1135 	LOG_FUNC
       
  1136 	TLogicalChannelFactoryRequestId id;
       
  1137 	User::LeaveIfError(iIdManager.GetId(id));
       
  1138 
       
  1139 	iId = id; // just in case we need to clean it up this needs to be stored
       
  1140 	CleanupStack::PushL(TCleanupItem(FreeId, (TAny*)this));
       
  1141  	CExpectSignallingLogicalChannel* req = CExpectSignallingLogicalChannel::NewL(aClient, id, iProtocol);
       
  1142 	CleanupStack::Pop();
       
  1143 	
       
  1144 	// got a complete job to do - put into job list
       
  1145 	iPendingPassiveSignallingJobs.AddLast(*req);
       
  1146 
       
  1147 	TLogicalChannelFactoryTicket ticket(this, id);
       
  1148 	ticket.SetState(TLogicalChannelFactoryTicket::ERequestOutstanding);
       
  1149 	return ticket;
       
  1150 	}
       
  1151 	
       
  1152 	
       
  1153 TLogicalChannelFactoryTicket CLogicalChannelFactory::
       
  1154 								ExpectSessionLogicalChannelsL(XLogicalChannelFactoryClient& aClient,
       
  1155 																TInt aNumRequired)
       
  1156 	{
       
  1157 	LOG_FUNC
       
  1158 
       
  1159 	TLogicalChannelFactoryRequestId id;
       
  1160 	User::LeaveIfError(iIdManager.GetId(id)); //Qualified
       
  1161 		
       
  1162 	iId = id; // just in case we need to clean it up this needs to be stored
       
  1163 	CleanupStack::PushL(TCleanupItem(FreeId, (TAny*)this));
       
  1164 	CExpectSessionLogicalChannels* req = CExpectSessionLogicalChannels::NewL(aClient,id, aNumRequired, iProtocol); //Qualified
       
  1165 	CleanupStack::Pop();
       
  1166 		
       
  1167 	// got a complete job to do - put into job list
       
  1168 	iPendingPassiveSessionJobs.AddLast(*req);
       
  1169 
       
  1170 	TLogicalChannelFactoryTicket ticket(this, id);
       
  1171 	ticket.SetState(TLogicalChannelFactoryTicket::ERequestOutstanding);
       
  1172 	return ticket;
       
  1173 	}
       
  1174 	
       
  1175 /**
       
  1176 For some jobs that clients are not interested in the results of we act as the client, dealing
       
  1177 with completion of the job.
       
  1178 */
       
  1179 void CLogicalChannelFactory::LogicalChannelFactoryRequestComplete(TLogicalChannelFactoryTicket aTicket, TInt aResult)
       
  1180 	{
       
  1181 	LOG_FUNC
       
  1182 #ifdef _DEBUG
       
  1183 	TBool found = EFalse;
       
  1184 #endif
       
  1185 
       
  1186 	CCloseSessionLogicalChannels* clc = NULL;
       
  1187 	TSglQueIter<CCloseSessionLogicalChannels> iter(iCloseChannelJobs);
       
  1188 	while(iter)
       
  1189 		{
       
  1190 		clc = iter++;
       
  1191 		if(clc->iId == aTicket.iId)
       
  1192 			{
       
  1193 #ifdef _DEBUG 
       
  1194 			found = ETrue;
       
  1195 #endif 
       
  1196 			iCloseChannelJobs.Remove(*clc);
       
  1197 			delete clc;
       
  1198 			// Only free the ID of successful jobs - NotifyComplete() frees the ID of unsuccessful jobs
       
  1199 			if (aResult == KErrNone)
       
  1200 			{
       
  1201 				iIdManager.FreeId(aTicket.iId);				
       
  1202 			}
       
  1203 			break;
       
  1204 			}
       
  1205 		}
       
  1206 		
       
  1207 	__ASSERT_DEBUG(found, Panic(EAvdtpJobCompleteForUnknownCloseChannelJob));
       
  1208 	}
       
  1209 
       
  1210 CServProviderBase* CManagedLogicalChannel::ObtainSAP()
       
  1211 	{
       
  1212 	LOG_FUNC
       
  1213 	CServProviderBase* sap = iLogicalChannelSAP;
       
  1214 	iLogicalChannelSAP = NULL;
       
  1215 	return sap;
       
  1216 	}
       
  1217 
       
  1218 void CManagedLogicalChannel::ProvideSAP(CServProviderBase* aSAP)
       
  1219 	{
       
  1220 	__ASSERT_DEBUG(aSAP, Panic(EAvdtpPassingNullSapOwnershipToChannel));
       
  1221 	__ASSERT_DEBUG(!iLogicalChannelSAP, Panic(EAvdtpPassingSapOwnershipToChannelThatAlreadyHasASap));
       
  1222 	iLogicalChannelSAP = aSAP;
       
  1223 	iLogicalChannelSAP->SetNotify(this);
       
  1224 	}
       
  1225 
       
  1226 void CLogicalChannelFactory::LogicalChannelLost(CManagedLogicalChannel* aChannel)
       
  1227 	{
       
  1228 	LOG_FUNC
       
  1229 
       
  1230 	// This could be a channel we've been asked to disconnect, or a channel
       
  1231 	// we've brought up with has been lost before being claimed.
       
  1232 
       
  1233 	TSglQueIter<CCloseSessionLogicalChannels> closeChannelIter(iCloseChannelJobs);
       
  1234 	while(closeChannelIter)
       
  1235 		{
       
  1236 		CCloseSessionLogicalChannels* clc = closeChannelIter++;
       
  1237 		if(clc->iId == aChannel->iId)
       
  1238 			{
       
  1239 			clc->ChannelClosed(aChannel);
       
  1240 			return;
       
  1241 			}
       
  1242 		}
       
  1243 
       
  1244 	// We weren't waiting for this channel to go down, check the unclaimed channels
       
  1245 	// find, remove and delete
       
  1246 	TDblQueIter<CManagedLogicalChannel> unclaimedIter(iUnclaimedLogicalChannels);
       
  1247 	
       
  1248 	while (unclaimedIter)
       
  1249 		{
       
  1250 		CManagedLogicalChannel* ch = unclaimedIter++;
       
  1251 		if (ch == aChannel)
       
  1252 			{
       
  1253 			ch->iFactoryQLink.Deque();
       
  1254 			delete ch;
       
  1255 			break; // cos we're adding at head
       
  1256 			}
       
  1257 		}
       
  1258 	}
       
  1259 
       
  1260 
       
  1261 CManagedLogicalChannel* CManagedLogicalChannel::NewL(CLogicalChannelFactory& aFactory,
       
  1262 								 		const TBTDevAddr& aAddr,
       
  1263 								 		TInt aSequenceNumber,
       
  1264 								 		TLogicalChannelFactoryRequestId aId,
       
  1265 								 		CServProviderBase* aPrecreatedSAP/*=NULL*/)
       
  1266 	{
       
  1267 	LOG_STATIC_FUNC
       
  1268 	CManagedLogicalChannel* self = new (ELeave) CManagedLogicalChannel(aFactory, aAddr, aSequenceNumber, aId);
       
  1269 	CleanupStack::PushL(self);
       
  1270 	self->ConstructL(aPrecreatedSAP);
       
  1271 	CleanupStack::Pop(self);
       
  1272 	return self;
       
  1273 	}
       
  1274 
       
  1275 CManagedLogicalChannel* CManagedLogicalChannel::NewL(CLogicalChannelFactory& aFactory,
       
  1276 								 		TLogicalChannelFactoryRequestId aId)
       
  1277 	{
       
  1278 	LOG_STATIC_FUNC
       
  1279 	// We don't call the ConstructL here as this overload of NewL is used when the SAP
       
  1280 	// will be provided later.
       
  1281 	CManagedLogicalChannel* self = new (ELeave) CManagedLogicalChannel(aFactory, aId);
       
  1282 	return self;
       
  1283 	}
       
  1284 
       
  1285 void CManagedLogicalChannel::ConstructL(CServProviderBase* aPrecreatedSAP)
       
  1286 	{
       
  1287 	LOG_FUNC
       
  1288 	iLogicalChannelSAP = aPrecreatedSAP ? aPrecreatedSAP :
       
  1289 										  iFactory.SAPFactory().NewSAPL(KSockSeqPacket);
       
  1290 	
       
  1291 	// There are two things we may need to change here, depending on what
       
  1292 	// sort of channel we're creating:
       
  1293 	// - On outgoing request for a signalling channel we need to 
       
  1294 	//   request a reliable channel
       
  1295 	// - On any request for a transport channel we need to bump up the channel priority
       
  1296 	
       
  1297 	TPckgBuf<TL2CapConfig> configBuf;
       
  1298 	iLogicalChannelSAP->GetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configBuf);
       
  1299 
       
  1300 	if(iSequenceNumber != KInitialSequenceNumber)
       
  1301 		{
       
  1302 		configBuf().ConfigureChannelPriority(TL2CapConfig::EHigh);
       
  1303 		iLogicalChannelSAP->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configBuf);
       
  1304 		}
       
  1305 	else if(!aPrecreatedSAP)
       
  1306 		{
       
  1307 		// FIXME consider value of rtx timer, should consider Tgavdp
       
  1308 		// Note: The 'rtx timer' actually sets max retransmit count instead [Piotr].
       
  1309 		configBuf().ConfigureReliableChannel(500);
       
  1310 		iLogicalChannelSAP->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configBuf);
       
  1311 		}
       
  1312 
       
  1313 	// tell sap who its socket is
       
  1314 	iLogicalChannelSAP->SetNotify(this);
       
  1315 	iLogicalChannelSAP->Start();
       
  1316 	}
       
  1317 
       
  1318 CManagedLogicalChannel::CManagedLogicalChannel(CLogicalChannelFactory& aFactory,
       
  1319 										   	   const TBTDevAddr& aAddr,
       
  1320 						   					   TInt aSequenceNumber ,
       
  1321 						   					   TLogicalChannelFactoryRequestId aId)
       
  1322 : iFactory(aFactory), iRemoteAddress(aAddr), iSequenceNumber(aSequenceNumber), iId(aId)
       
  1323 	{
       
  1324 	LOG_FUNC
       
  1325 	__ASSERT_DEBUG(iSequenceNumber>=KInitialSequenceNumber, Panic(EAvdtpLogicalChannelFactoryBadSequenceNumber));
       
  1326 	}
       
  1327 
       
  1328 CManagedLogicalChannel::CManagedLogicalChannel(CLogicalChannelFactory& aFactory,
       
  1329 										   	   TLogicalChannelFactoryRequestId aId)
       
  1330 : iFactory(aFactory), iId(aId)
       
  1331 	{
       
  1332 	LOG_FUNC
       
  1333 	}
       
  1334 	
       
  1335 CManagedLogicalChannel::~CManagedLogicalChannel()
       
  1336 	{
       
  1337 	LOG_FUNC
       
  1338 	// need to clear up SAP (we're unclaimed at this point)
       
  1339 	delete iLogicalChannelSAP;
       
  1340 	}
       
  1341 	
       
  1342 void CManagedLogicalChannel::Shutdown()
       
  1343 	{
       
  1344 	/*
       
  1345 	NOTE it IS possible that the channel is NOT totally setup
       
  1346 	if the remote is behaving badly.
       
  1347 	So in case check the channel has a SAP BEFORE 
       
  1348 	calling shutdown. */
       
  1349 	if (iLogicalChannelSAP)
       
  1350 		{
       
  1351 		iLogicalChannelSAP->Shutdown(CServProviderBase::EImmediate);
       
  1352 		}
       
  1353 	}
       
  1354 
       
  1355 void CManagedLogicalChannel::NewData(TUint aCount)
       
  1356 	{
       
  1357 	LOG_FUNC
       
  1358 	// this class doesn't "know" the protocol. it just leaves the data in l2cap
       
  1359 	// for the eventual user of this sap to extract
       
  1360 	if (aCount==KNewDataEndofData)
       
  1361 		{
       
  1362 		iEndOfData = ETrue;
       
  1363 		}
       
  1364 	else
       
  1365 		{
       
  1366 		iDataCount+=aCount;
       
  1367 		}
       
  1368 	}
       
  1369 	
       
  1370 void CManagedLogicalChannel::CanSend()
       
  1371 	{
       
  1372 	LOG_FUNC
       
  1373 	// we never send
       
  1374 	__DEBUGGER();
       
  1375 	}
       
  1376 	
       
  1377 void CManagedLogicalChannel::ConnectComplete()
       
  1378 	{
       
  1379 	LOG_FUNC
       
  1380 	// we never connect
       
  1381 	__DEBUGGER();
       
  1382 	}
       
  1383 	
       
  1384 void CManagedLogicalChannel::ConnectComplete(const TDesC8& /*aConnectData*/)
       
  1385 	{
       
  1386 	LOG_FUNC
       
  1387 	// we never connect
       
  1388 	__DEBUGGER();
       
  1389 	}
       
  1390 
       
  1391 void CManagedLogicalChannel::ConnectComplete(CServProviderBase& /*aSSP*/)
       
  1392 	{
       
  1393 	LOG_FUNC
       
  1394 	// we never connect
       
  1395 	__DEBUGGER();
       
  1396 	}
       
  1397 	
       
  1398 void CManagedLogicalChannel::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
  1399 	{
       
  1400 	LOG_FUNC
       
  1401 	// we never connect
       
  1402 	__DEBUGGER();
       
  1403 	}
       
  1404 
       
  1405 void CManagedLogicalChannel::CanClose(TDelete /*aDelete*/)
       
  1406 	{
       
  1407 	LOG_FUNC
       
  1408 	// we only shutdown immediately
       
  1409 	__DEBUGGER();
       
  1410 	}
       
  1411 	
       
  1412 void CManagedLogicalChannel::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
  1413 	{
       
  1414 	LOG_FUNC
       
  1415 	// we only shutdown immediately
       
  1416 	__DEBUGGER();
       
  1417 	}
       
  1418 	
       
  1419 void CManagedLogicalChannel::Error(TInt /*aError*/,TUint /*aOperationMask*/)
       
  1420 	{
       
  1421 	LOG_FUNC
       
  1422 	iFactory.LogicalChannelLost(this); // will delete us
       
  1423 	}
       
  1424 	
       
  1425 void CManagedLogicalChannel::Disconnect()
       
  1426 	{
       
  1427 	LOG_FUNC
       
  1428 	iFactory.LogicalChannelLost(this); // will delete us
       
  1429 	}
       
  1430 
       
  1431 void CManagedLogicalChannel::Disconnect(TDesC8& /*aDisconnectData*/)
       
  1432 	{
       
  1433 	LOG_FUNC
       
  1434 	// bearer doesnt support disconnect data
       
  1435 	__DEBUGGER();
       
  1436 	Disconnect();
       
  1437 	}
       
  1438 	
       
  1439 void CManagedLogicalChannel::IoctlComplete(TDesC8* /*aBuf*/)
       
  1440 	{
       
  1441 	LOG_FUNC
       
  1442 	// we don't issue ioctls
       
  1443 	__DEBUGGER();
       
  1444 	}
       
  1445 	
       
  1446 void CManagedLogicalChannel::NoBearer(const TDesC8& /*aConnectionInfo*/)
       
  1447 	{
       
  1448 	LOG_FUNC
       
  1449 	// a redundant artefact of IP nonsense
       
  1450 	__DEBUGGER();
       
  1451 	}
       
  1452 	
       
  1453 void CManagedLogicalChannel::Bearer(const TDesC8& /*aConnectionInfo*/)
       
  1454 	{
       
  1455 	LOG_FUNC
       
  1456 	// a redundant artefact of IP nonsense
       
  1457 	__DEBUGGER();
       
  1458 	}
       
  1459 
       
  1460 
       
  1461 TLogicalChannelFactoryTicket::TLogicalChannelFactoryTicket(CLogicalChannelFactory* aFactory, TLogicalChannelFactoryRequestId aId)
       
  1462 	: iFactory(aFactory)
       
  1463 	, iId(aId)
       
  1464 	, iState(TLogicalChannelFactoryTicket::ERequestIdle)
       
  1465 	{
       
  1466 	LOG_FUNC
       
  1467 	}
       
  1468 
       
  1469 TLogicalChannelFactoryTicket::TLogicalChannelFactoryTicket()
       
  1470 	: iState(TLogicalChannelFactoryTicket::ERequestIdle)
       
  1471 	{
       
  1472 	LOG_FUNC
       
  1473 	}
       
  1474 
       
  1475 TLogicalChannelRecord TLogicalChannelFactoryTicket::GetLogicalChannel(TInt aSequenceNumber/*=1*/)
       
  1476 	{
       
  1477 	LOG_FUNC
       
  1478 	__ASSERT_DEBUG(iState != ERequestErrored, Panic(EAvdtpInvalidResponseInUse));
       
  1479 	TBool finished = EFalse;
       
  1480 	TLogicalChannelRecord rec = iFactory->ClaimLogicalChannel(aSequenceNumber, iId, finished);
       
  1481 	if (finished)
       
  1482 		{
       
  1483 		// to stop people forgetting
       
  1484 		iState = ERequestComplete;
       
  1485 		}
       
  1486 	return rec;
       
  1487 	}
       
  1488 
       
  1489 void TLogicalChannelFactoryTicket::SetState(TLogicalChannelFactoryRequestState aNewState)
       
  1490 	{
       
  1491 	LOG_FUNC
       
  1492 	LOG2(_L("State Transition %d -> %d"), iState, aNewState);
       
  1493 	iState = aNewState;
       
  1494 	}
       
  1495 
       
  1496 	
       
  1497 TLogicalChannelFactoryTicketInspector::TLogicalChannelFactoryTicketInspector(
       
  1498 							TLogicalChannelFactoryTicket& aTicket,
       
  1499 							TBool aRequireReporting,
       
  1500 							TBool aRequireRecovery, TBool aMuxed)
       
  1501 	: iTicket(aTicket)
       
  1502 	, iSignallingSequenceNumber(KInitialSequenceNumber)
       
  1503 	, iMediaSequenceNumber(KInitialSequenceNumber)
       
  1504 	, iCached(EFalse)
       
  1505 	{
       
  1506 	LOG_FUNC
       
  1507 #ifdef _DEBUG
       
  1508 	// to assert against later
       
  1509 	iRequireReporting = aRequireReporting;
       
  1510 	iRequireRecovery = aRequireRecovery;
       
  1511 #endif
       
  1512 	if (aMuxed)
       
  1513 		{
       
  1514 		// the reporting and media go in one channel, the first created
       
  1515 		// this class knows a bit about the strategy of mux allocation
       
  1516 		iReportingSequenceNumber = 1; // with media
       
  1517 		iRecoverySequenceNumber = 2;
       
  1518 		}
       
  1519 	else
       
  1520 		{
       
  1521 		iReportingSequenceNumber = 2;
       
  1522 		iRecoverySequenceNumber = aRequireReporting & aRequireRecovery ? 3 : 2;
       
  1523 		}
       
  1524 	}
       
  1525 							
       
  1526 TLogicalChannelRecord TLogicalChannelFactoryTicketInspector::GetLogicalChannel(TAvdtpTransportSessionType aType)
       
  1527 	{
       
  1528 	LOG_FUNC
       
  1529 	TLogicalChannelRecord rec;
       
  1530 	
       
  1531 	if (!iCached)
       
  1532 		{
       
  1533 		const TInt* index;
       
  1534 		switch (aType)
       
  1535 			{
       
  1536 			case ESignalling:
       
  1537 				index = &iSignallingSequenceNumber;
       
  1538 				break;
       
  1539 			case EMedia:
       
  1540 				index = &iMediaSequenceNumber;
       
  1541 				break;
       
  1542 			case EReporting:
       
  1543 				__ASSERT_DEBUG(iRequireReporting, Panic(EAvdtpLogicalChannelFactoryBadClaimLogicalChannel));
       
  1544 				index = &iReportingSequenceNumber;
       
  1545 				break;
       
  1546 			case ERecovery:
       
  1547 				__ASSERT_DEBUG(iRequireRecovery, Panic(EAvdtpLogicalChannelFactoryBadClaimLogicalChannel));
       
  1548 				index = &iRecoverySequenceNumber;
       
  1549 				break;
       
  1550 			default:
       
  1551 				index = NULL;
       
  1552 			}
       
  1553 		__ASSERT_DEBUG(index, Panic(EAvdtpLogicalChannelFactoryBadClaimLogicalChannel));
       
  1554 		rec = iTicket.GetLogicalChannel(*index);
       
  1555 		
       
  1556 		if (iReportingSequenceNumber==iMediaSequenceNumber)
       
  1557 			{
       
  1558 			// we're in muxed case...
       
  1559 			// this helper helps further by caching the record
       
  1560 			// so that the client can claim again for reporting, even if same record
       
  1561 			// that the factory will have (rightly) purged
       
  1562 			// therefore cache this
       
  1563 			iCachedRecord = rec;
       
  1564 			iCached = ETrue;
       
  1565 			}
       
  1566 		}
       
  1567 	else
       
  1568 		{
       
  1569 		// cached - use same record, and allow arbitrary order of
       
  1570 		// collection of cache-able session types
       
  1571 		if (aType == EMedia || aType == EReporting)
       
  1572 			{
       
  1573 			rec = iCachedRecord;
       
  1574 			iCached = EFalse;
       
  1575 			}
       
  1576 		}
       
  1577 	return rec;
       
  1578 	}