bluetooth/gavdp/source/gavdpHelpers.cpp
changeset 0 29b1cd4cb562
child 22 786b94c6f0a4
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-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 // Implementation of the helper active objects that talk to AVDTP
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @publishedPartner
       
    20 */
       
    21 
       
    22 #include "gavdpInternal.h"
       
    23 #include "gavdpinterface.h"
       
    24 
       
    25 /**
       
    26 The default helper has EPriorityStandard.  Some of the derived helpers
       
    27 will set their priority to something different when running.  This enables
       
    28 enforcement of orderings, as because both a helper and an indication may
       
    29 have an outstanding completion we need to ensure that these are scheduled
       
    30 in the order that will cause the notifications to the client in the correct
       
    31 order.
       
    32 
       
    33 An example of this:
       
    34 AVDTP recieves an Open, which it indicates to GAVDP.  
       
    35 On receipt of the Open GAVDP will issue socket connects.
       
    36 AVDTP completes the socket connects.
       
    37 AVDTP receives an incoming Start and issues a Start indication to GAVDP by Ioctl completion.
       
    38 GAVDP now has two outstanding completed requests: 
       
    39 	- the Start indication (leading to GAVDP_StartIndication).
       
    40 	- the UPlaneConnect completion (leading to GAVDP_BearerReady).
       
    41 Unless we ensure that the connect is processed before the start, the client
       
    42 may receive the start indication before it has sockets available.
       
    43 */
       
    44 CGavdpHelper::CGavdpHelper(CGavdp& aGavdp, MGavdpUser& aUser)
       
    45 : CActive(EPriorityStandard),
       
    46   iGavdp(&aGavdp),
       
    47   iUser(aUser)
       
    48 	{
       
    49 	CActiveScheduler::Add(this);
       
    50 	}
       
    51 
       
    52 TInt CGavdpHelper::RunError(TInt aError)
       
    53 	{
       
    54 	RDebug::Print(_L("GAVDP::RunError %d"), aError);
       
    55 	
       
    56 	if (iGavdp)
       
    57 		{	
       
    58 		Gavdp().ServiceComplete(aError);
       
    59 		}
       
    60 	
       
    61 	User().GAVDP_Error(aError, KNullDesC8); // helpers with extended error can't use this path
       
    62 	//delete this whether or not we know about our CGavdp owner:
       
    63 	//if we do - it will no longer know about us (see CGavdp::ServiceComplete)
       
    64 	//if we don't - it will have detached from us earlier and expect us to
       
    65 	//clean ourselves up
       
    66 	delete this;
       
    67 	
       
    68 	return KErrNone;
       
    69 	}	
       
    70 
       
    71 void CGavdpHelper::CheckFailedL()
       
    72 	{
       
    73 	// if failed, leave and tell Gavdp service is complete
       
    74 	User::LeaveIfError(iStatus.Int());
       
    75 	}
       
    76 	
       
    77 /**
       
    78 Called by helpers to inform GAVDP they no-longer need its services, but still have
       
    79 calls to make to the User
       
    80 The helper will be detached from GAVDP, and upon completion of their duties they should
       
    81 delete themselves
       
    82 This enables GAVDP to do more for the client while the helper carries on
       
    83 **/
       
    84 void CGavdpHelper::DetachFromGavdp(TInt aError)
       
    85 	{
       
    86 	Gavdp().ServiceComplete(aError);
       
    87 	iGavdp = NULL;
       
    88 	}
       
    89 	
       
    90 inline MGavdpUser& CGavdpHelper::User()
       
    91 	{
       
    92 	return iUser;
       
    93 	}
       
    94 	
       
    95 CGavdpDiscover* CGavdpDiscover::NewL(CGavdp& aGavdp, MGavdpUser& aUser)
       
    96 	{
       
    97 	return new (ELeave) CGavdpDiscover(aGavdp, aUser);
       
    98 	}
       
    99 	
       
   100 CGavdpDiscover::CGavdpDiscover(CGavdp& aGavdp, MGavdpUser& aUser)
       
   101 								   
       
   102 : CGavdpHelper(aGavdp, aUser)
       
   103 	{
       
   104 	}
       
   105 
       
   106 CGavdpDiscover::~CGavdpDiscover()
       
   107 	{
       
   108 	Cancel();
       
   109 	}
       
   110 	
       
   111 void CGavdpDiscover::DoCancel()
       
   112 	{
       
   113 	AvdtpRequester().CancelAll();
       
   114 	}
       
   115 	
       
   116 void CGavdpDiscover::RunL()
       
   117 	{
       
   118 	CheckFailedL();
       
   119 	// found n SEPs - create a buffer into which to place the details
       
   120 	// short circuit this if zero SEPs found
       
   121 	User::LeaveIfError(iConfirm().iResult);
       
   122 	DetachFromGavdp(KErrNone);
       
   123 
       
   124 	TFixedArray<TAvdtpSEPInfo, KMaxAvdtpNumSEPs>& sepInfos = iConfirm().iDiscoveredSEPs();
       
   125 	for (TInt i=0;i<=iConfirm().iNumSEPs-1;i++)
       
   126 		{
       
   127 		const TAvdtpSEPInfo info = sepInfos[i];
       
   128 		User().GAVDP_SEPDiscovered(info);
       
   129 		}
       
   130 
       
   131 	User().GAVDP_SEPDiscoveryComplete();
       
   132 	
       
   133 	delete this;
       
   134 	}
       
   135 	
       
   136 	
       
   137 void CGavdpDiscover::Begin()
       
   138 	{
       
   139 	AvdtpRequester().Ioctl(EDiscoverSEPs, iStatus, &iConfirm, KSolBtAVDTPSignalling);
       
   140 	SetActive();	
       
   141 	}
       
   142 
       
   143 
       
   144 CGavdpGetCaps* CGavdpGetCaps::NewL(CGavdp& aGavdp,
       
   145 					  			  MGavdpUser& aUser,
       
   146 					  			  TSEID aSEID,
       
   147 					  			  TAvdtpServiceCategories aInterestingCategories)
       
   148 	{
       
   149 	CGavdpGetCaps* g = new (ELeave) CGavdpGetCaps(aGavdp, aUser, aSEID, aInterestingCategories);
       
   150 	CleanupStack::PushL(g);
       
   151 	g->ConstructL();
       
   152 	CleanupStack::Pop(g);
       
   153 	return g;
       
   154 	}
       
   155 	
       
   156 void CGavdpGetCaps::ConstructL()
       
   157 	{
       
   158 	TPckg<TSEID> seidPckg(iSEID);
       
   159 	iSEPCapBuf = seidPckg.AllocL();
       
   160 	iSEPCapPtr.Set(iSEPCapBuf->Des());
       
   161 	}
       
   162 	
       
   163 
       
   164 CGavdpGetCaps::CGavdpGetCaps(CGavdp& aGavdp, MGavdpUser& aUser,
       
   165 							 TSEID aSEID, TAvdtpServiceCategories aInterestingCategories)
       
   166 : CGavdpHelper(aGavdp, aUser), iSEPCapPtr(0,0), iSEID(aSEID), iInteresting(aInterestingCategories)
       
   167 	{
       
   168 	}
       
   169 	
       
   170 CGavdpGetCaps::~CGavdpGetCaps()
       
   171 	{
       
   172 	Cancel();
       
   173 	delete iSEPCapBuf;
       
   174 	}
       
   175 
       
   176 void CGavdpGetCaps::DoCancel()
       
   177 	{
       
   178 	AvdtpRequester().CancelAll();
       
   179 	}
       
   180 
       
   181 void CGavdpGetCaps::Begin()
       
   182 	{
       
   183 	AvdtpRequester().Ioctl(EGetCapabilities, iStatus ,&iSEPCapPtr, KSolBtAVDTPSignalling);
       
   184 	SetActive();
       
   185 	}
       
   186 
       
   187 void CGavdpGetCaps::RunL()
       
   188 	{
       
   189 	CheckFailedL();
       
   190 	
       
   191 	// iSEPCapPtr now has mask of capabilities at this point
       
   192 	TAvdtpServiceCatBitMask sepCapMask = *reinterpret_cast<const TAvdtpServiceCatBitMask*>(iSEPCapPtr.Ptr());
       
   193 	// don't trouble user with ones they'd ignore anyway
       
   194 	sepCapMask &= iInteresting();
       
   195 		
       
   196 	if (!sepCapMask)
       
   197 		{
       
   198 		// the remote sep has no capabilities the user is interested in
       
   199 		// tell them NotSupported
       
   200 		User::Leave(KErrNotSupported);
       
   201 		}
       
   202 
       
   203 	for (TInt index=0; index<ENumberOfServiceCategories; index++)
       
   204 		{
       
   205 		// go through each bit
       
   206 		if (sepCapMask & (1<<index)) // test for bit set
       
   207 			{		
       
   208 			// it's set - create a buffer big enough to receive the value
       
   209 			const TAvdtpServiceCategory servcat = static_cast<TAvdtpServiceCategory>(index+1);
       
   210 			
       
   211 			TInt bufsize =0;
       
   212 			
       
   213 			switch (servcat)
       
   214 				{
       
   215 				case EServiceCategoryMediaTransport:
       
   216 					{
       
   217 					bufsize = sizeof(TAvdtpMediaTransportCapabilities);
       
   218 					}
       
   219 					break;
       
   220 				case EServiceCategoryReporting:
       
   221 					{
       
   222 					bufsize = sizeof(TAvdtpReportingCapabilities);
       
   223 					}
       
   224 					break;
       
   225 				case EServiceCategoryRecovery:
       
   226 					{
       
   227 					bufsize = sizeof(TAvdtpRecoveryCapabilities);
       
   228 					}
       
   229 					break;
       
   230 				case EServiceCategoryContentProtection:
       
   231 					{
       
   232 					bufsize = sizeof(TAvdtpContentProtectionCapabilities);
       
   233 					}
       
   234 					break;
       
   235 				case EServiceCategoryHeaderCompression:
       
   236 					{
       
   237 					bufsize = sizeof(TAvdtpHeaderCompressionCapabilities);	
       
   238 					}
       
   239 					break;
       
   240 				case EServiceCategoryMultiplexing:
       
   241 					{
       
   242 					bufsize = sizeof(TAvdtpMultiplexingCapability);
       
   243 					}
       
   244 					break;
       
   245 				case EServiceCategoryMediaCodec:
       
   246 					{
       
   247 					// to handle an arbitrary codec (different LOSCs)
       
   248 					// we need to assume largest LOSC.  It's not around
       
   249 					// for long, so should be ok to make it big.
       
   250 					bufsize = KUnknownLOSC;
       
   251 					}
       
   252 					break;
       
   253 				}
       
   254 			
       
   255 			if (iSEPCapBuf->Length() < bufsize)
       
   256 				{
       
   257 				iSEPCapBuf = iSEPCapBuf->ReAllocL(Max(bufsize, sizeof(TInternalGetSEPCapability)));
       
   258 				}
       
   259 			
       
   260 			TPckgBuf<TInternalGetSEPCapability> capbuf;
       
   261 			capbuf().iSEID = iSEID;
       
   262 			capbuf().iServiceCategory = servcat;
       
   263 			
       
   264 			// send into socket, output will be capability
       
   265 			iSEPCapPtr.Set(iSEPCapBuf->Des());
       
   266 			iSEPCapPtr.Copy(capbuf);
       
   267 			
       
   268 			User::LeaveIfError(AvdtpRequester().GetOpt(EGetAVDTPCapabilityResponse, KSolBtAVDTPSignalling, iSEPCapPtr));
       
   269 
       
   270 			TAvdtpServiceCapability* cap = NULL;
       
   271 			
       
   272 			TRAPD(err, cap = TAvdtpServiceCapability::AllocFromPDUL(servcat, *iSEPCapBuf));
       
   273 			
       
   274 			if (err == KErrNone)
       
   275 				{
       
   276 				User().GAVDP_SEPCapability(cap); //ownership transferred!!
       
   277 				}
       
   278 			else if (err == KErrNoMemory)
       
   279 				{
       
   280 				// Special case OOM conditions to allow the client code to see them.
       
   281 				// Otherwise the 'assume capability unsupported' block below hides the
       
   282 				// error.
       
   283 				User::Leave(err);
       
   284 				}
       
   285 			else
       
   286 				{
       
   287 				// probably a capability not supported by us, so no point telling user
       
   288 				// we don't want to leave though - try to process next capability
       
   289 				}
       
   290 			}
       
   291 		}
       
   292 
       
   293 	DetachFromGavdp(KErrNone);		
       
   294 	User().GAVDP_SEPCapabilityComplete();
       
   295 	// in future - should prob go back to scheduler and do one at a time		
       
   296 	// we've got them all
       
   297 	delete this;
       
   298 	}
       
   299 
       
   300 CGavdpAbort* CGavdpAbort::NewL(CGavdp& aGavdp, MGavdpUser& aUser, TSEID aSEID)
       
   301 	{
       
   302 	return new (ELeave) CGavdpAbort(aGavdp, aUser, aSEID);
       
   303 	}
       
   304 	
       
   305 CGavdpAbort::CGavdpAbort(CGavdp& aGavdp, MGavdpUser& aUser, TSEID aSEID)
       
   306 : CGavdpHelper(aGavdp, aUser)
       
   307 	{
       
   308 	iSEID() = aSEID;
       
   309 	}
       
   310 
       
   311 CGavdpAbort::~CGavdpAbort()
       
   312 	{
       
   313 	Cancel();
       
   314 	}
       
   315 
       
   316 void CGavdpAbort::DoCancel()
       
   317 	{
       
   318 	AvdtpRequester().CancelAll();
       
   319 	}
       
   320 
       
   321 void CGavdpAbort::Begin()
       
   322 	{
       
   323 	SetPriority(EPriorityHigh);
       
   324 	AvdtpRequester().Ioctl(EAbortStream, iStatus ,&iSEID, KSolBtAVDTPSignalling);
       
   325 	SetActive();
       
   326 	}
       
   327 
       
   328 void CGavdpAbort::RunL()
       
   329 	{
       
   330 	CheckFailedL();
       
   331 	DetachFromGavdp(KErrNone);	
       
   332 
       
   333 	User().GAVDP_AbortStreamConfirm();
       
   334 	
       
   335 	delete this;
       
   336 	}
       
   337 
       
   338 
       
   339 
       
   340 CGavdpStart* CGavdpStart::NewL(CGavdp& aGavdp,
       
   341 					  		   MGavdpUser& aUser,
       
   342 					  		   TSEID aSeid)
       
   343 	{
       
   344 	return new (ELeave) CGavdpStart(aGavdp, aUser, aSeid);
       
   345 	}
       
   346 	
       
   347 CGavdpStart::CGavdpStart(CGavdp& aGavdp, MGavdpUser& aUser, TSEID aSeid)
       
   348 : CGavdpHelper(aGavdp, aUser), iSeidPckg(aSeid)
       
   349 	{
       
   350 	}
       
   351 
       
   352 CGavdpStart::~CGavdpStart()
       
   353 	{
       
   354 	Cancel();
       
   355 	}
       
   356 	
       
   357 void CGavdpStart::DoCancel()
       
   358 	{
       
   359 	AvdtpRequester().CancelAll();
       
   360 	}
       
   361 
       
   362 	
       
   363 void CGavdpStart::Begin()
       
   364 	{
       
   365 	AvdtpRequester().Ioctl(EStartStreaming, iStatus, &iSeidPckg, KSolBtAVDTPSignalling);
       
   366 	SetActive();
       
   367 	}
       
   368 	
       
   369 void CGavdpStart::RunL()
       
   370 	{
       
   371 	// at present since GAVDP only allows one seid to start at a time then there is
       
   372 	// no need for extended info, AVDTP also makes this assumption
       
   373 	CheckFailedL();
       
   374 	DetachFromGavdp(KErrNone);
       
   375 	
       
   376 	User().GAVDP_StartStreamsConfirm();
       
   377 
       
   378 	delete this;
       
   379 	}
       
   380 
       
   381 
       
   382 
       
   383 
       
   384 CGavdpSuspend* CGavdpSuspend::NewL(CGavdp& aGavdp,
       
   385 					  		   MGavdpUser& aUser,
       
   386 					  		   TSEID aSeid)
       
   387 	{
       
   388 	return new (ELeave) CGavdpSuspend(aGavdp, aUser, aSeid);
       
   389 	}
       
   390 	
       
   391 CGavdpSuspend::CGavdpSuspend(CGavdp& aGavdp, MGavdpUser& aUser, TSEID aSeid)
       
   392 : CGavdpHelper(aGavdp, aUser), iSeidPckg(aSeid)
       
   393 	{
       
   394 	}
       
   395 
       
   396 CGavdpSuspend::~CGavdpSuspend()
       
   397 	{
       
   398 	Cancel();
       
   399 	}
       
   400 
       
   401 void CGavdpSuspend::DoCancel()
       
   402 	{
       
   403 	AvdtpRequester().CancelAll();
       
   404 	}
       
   405 
       
   406 void CGavdpSuspend::Begin()
       
   407 	{
       
   408 	AvdtpRequester().Ioctl(ESuspendStreaming, iStatus, &iSeidPckg, KSolBtAVDTPSignalling);
       
   409 	SetActive();
       
   410 	}
       
   411 	
       
   412 void CGavdpSuspend::RunL()
       
   413 	{
       
   414 	// at present since GAVDP only allows one seid to suspend at a time then there is
       
   415 	// no need for extended info, AVDTP also makes this assumption
       
   416 	CheckFailedL();
       
   417 	DetachFromGavdp(KErrNone);
       
   418 	
       
   419 	User().GAVDP_SuspendStreamsConfirm();
       
   420 
       
   421 	delete this;
       
   422 	}
       
   423 
       
   424 
       
   425 
       
   426 CGavdpSelectSEP* CGavdpSelectSEP::NewL(CGavdp& aGavdp, MGavdpUser& aUser)
       
   427 	{
       
   428 	return new (ELeave) CGavdpSelectSEP(aGavdp, aUser);
       
   429 	}
       
   430 	
       
   431 CGavdpSelectSEP::CGavdpSelectSEP(CGavdp& aGavdp, MGavdpUser& aUser)
       
   432 : CGavdpHelper(aGavdp, aUser)
       
   433 	{
       
   434 	}
       
   435 
       
   436 
       
   437 CGavdpSelectSEP::~CGavdpSelectSEP()
       
   438 	{
       
   439 	Cancel();
       
   440 	}
       
   441 	
       
   442 void CGavdpSelectSEP::DoCancel()
       
   443 	{
       
   444 	AvdtpRequester().CancelAll();
       
   445 	}
       
   446 
       
   447 void CGavdpSelectSEP::Begin()
       
   448 	{
       
   449 	AvdtpRequester().Ioctl(ESelectSEP, iStatus, &iRejDataBuf, KSolBtAVDTPSignalling);
       
   450 	SetActive();
       
   451 	}
       
   452 	
       
   453 void CGavdpSelectSEP::RunL()
       
   454 	{
       
   455 	// if the Ioctl itself failed then we might have an error in the iStatus...
       
   456 	TInt result = iStatus.Int();
       
   457 	CheckFailedL();
       
   458 	DetachFromGavdp(KErrNone);	
       
   459 
       
   460 	// the ioctl mechanism may have worked but the signalling failed - with extended data...
       
   461 	result = iRejDataBuf().iError;
       
   462 	if (result!=KErrNone)
       
   463 		{
       
   464 		// the error buffer contains extended failure data
       
   465 		User().GAVDP_Error(result, iRejDataBuf);
       
   466 		}
       
   467 	else
       
   468 		{
       
   469 		User().GAVDP_ConfigurationConfirm();
       
   470 		}
       
   471 	delete this;
       
   472 	}
       
   473 
       
   474 	
       
   475 
       
   476 CGavdpConnector* CGavdpConnector::NewL(CGavdp& aGavdp, MGavdpUser& aUser, const TBTDevAddr& aAddr)
       
   477 	{
       
   478 	return new (ELeave) CGavdpConnector(aGavdp, aUser, aAddr);
       
   479 	}
       
   480 	
       
   481 CGavdpConnector::CGavdpConnector(CGavdp& aGavdp, MGavdpUser& aUser, const TBTDevAddr& aAddr)
       
   482 : CGavdpHelper(aGavdp, aUser)
       
   483 	{
       
   484 	iSocketAddress.SetBTAddr(aAddr);
       
   485 	iSocketAddress.SetSession(ESignalling);
       
   486 	}
       
   487 
       
   488 CGavdpConnector::~CGavdpConnector()
       
   489 	{
       
   490 	Cancel();
       
   491 	}
       
   492 
       
   493 void CGavdpConnector::DoCancel()
       
   494 	{
       
   495 	AvdtpRequester().CancelAll(); // ESOCK has better semantics to SAP than CancelConnect.
       
   496 	}
       
   497 
       
   498 
       
   499 void CGavdpConnector::Begin()
       
   500 	{
       
   501 	// Ensure that once this is completed the RunL is scheduled
       
   502 	// before handling completion of the indication ioctl.
       
   503 	SetPriority(EPriorityStandard+1);
       
   504 	AvdtpRequester().Connect(iSocketAddress, iStatus);
       
   505 	SetActive();
       
   506 	}
       
   507 
       
   508 void CGavdpConnector::RunL()
       
   509 	{
       
   510 		
       
   511 	// Do not call CGavdpHelper::CheckFailedL() here - avdtp will indicate a failure to connect, 
       
   512 	// and GAVDP is informed via CGavdpIndicator::RunL().
       
   513 	
       
   514 	TInt error = iStatus.Int();
       
   515 	DetachFromGavdp(error);	
       
   516 	
       
   517 	if (error == KErrNone)
       
   518 		{
       
   519 		User().GAVDP_ConnectConfirm(iSocketAddress.BTAddr());	// reuse the same callback to make life easier for app
       
   520 		}
       
   521 	else
       
   522 		{
       
   523 		User().GAVDP_Error(error, KNullDesC8);
       
   524 		}
       
   525 		
       
   526 	delete this;
       
   527 	}
       
   528 
       
   529 CGavdpIndicator::~CGavdpIndicator()
       
   530 	{
       
   531 	Cancel();
       
   532 	}
       
   533 	
       
   534 void CGavdpIndicator::DoCancel()
       
   535 	{
       
   536 	AvdtpIndicator().CancelAll();
       
   537 	}
       
   538 
       
   539 CGavdpIndicator* CGavdpIndicator::NewL(CGavdp& aGavdp, MGavdpUser& aUser)
       
   540 	{
       
   541 	return new (ELeave) CGavdpIndicator(aGavdp, aUser);
       
   542 	}
       
   543 	
       
   544 CGavdpIndicator::CGavdpIndicator(CGavdp& aGavdp, MGavdpUser& aUser)
       
   545 : CGavdpHelper(aGavdp, aUser)
       
   546 	{
       
   547 	}
       
   548 
       
   549 
       
   550 void CGavdpIndicator::RunL()
       
   551 	{
       
   552 	// this service is not-one shot, so don't call DetachFromGavdp
       
   553 	User::LeaveIfError(iStatus.Int());
       
   554 		
       
   555 	// reinterpret our now complete descriptor as a TAvdtpIndicationPckg
       
   556 	// then raise appropriate indication
       
   557 	
       
   558 	const TUint8* ptr = iIndication.Ptr();
       
   559 	const TInternalAvdtpIndication& indtype = *reinterpret_cast<const TInternalAvdtpIndication*>(ptr);
       
   560 
       
   561 	if (indtype.iType == TInternalAvdtpIndication::EError)
       
   562 		{
       
   563 		const TInternalAvdtpErrorIndication& error = reinterpret_cast<const TInternalAvdtpErrorIndication&>(indtype);
       
   564 		// if avdtp errors, so does Gavdp
       
   565 		Gavdp().Error(error.iError); // GAVDP tells the user if needed: ESOCK DEF - that may delete GAVDP
       
   566 		}
       
   567 		
       
   568 	else if (indtype.iType == TInternalAvdtpIndication::EObject)
       
   569 		{
       
   570 		const TInternalAvdtpObjectIndication& ind = *reinterpret_cast<const TInternalAvdtpObjectIndication*>(ptr);
       
   571 		switch (ind.iObjectIndication)
       
   572 			{
       
   573 			case TInternalAvdtpObjectIndication::ESignallingReady:
       
   574 			TBTDevAddr addr(ind.iBuf);
       
   575 			Gavdp().BindSignallingL(addr);			
       
   576 			break;
       
   577 			
       
   578 			}
       
   579 		}
       
   580 	
       
   581 	else if (indtype.iType == TInternalAvdtpIndication::EAir)
       
   582 		{		
       
   583 		TInt res = SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
   584 		const TInternalAvdtpAirIndication& ind = *reinterpret_cast<const TInternalAvdtpAirIndication*>(ptr);
       
   585 
       
   586 		switch (ind.iIndication)
       
   587 			{
       
   588 			// only ones the stack doesn't deal with completely
       
   589 			case EAvdtpSetConfiguration:
       
   590 			case EAvdtpReconfigure:
       
   591 				{
       
   592 				// app must have a say in determining if the configuration is OK
       
   593 				// the remote has selected the sep it is interested in
       
   594 				// and checked the caps the apps has already set
       
   595 				// but stack would find it "hard" to semantically compare optional caps etc
       
   596 				// need to get the payload from the stack
       
   597 				const TInternalAvdtpConfigurationIndication& cfgInd=static_cast<const TInternalAvdtpConfigurationIndication&>(ind);
       
   598 				HBufC8* resp = HBufC8::NewMaxLC(Max(cfgInd.iPayloadLength, sizeof(TInternalGetProposedConfiguration)));
       
   599 				TPtr8 des = resp->Des();
       
   600 				
       
   601 				TInternalGetProposedConfiguration& getConfBuf = *const_cast<TInternalGetProposedConfiguration*>(reinterpret_cast<const TInternalGetProposedConfiguration*>(resp->Des().Ptr()));
       
   602 				getConfBuf.iSEID = ind.iSEID;
       
   603 								
       
   604 				// get remainder of configuration from AVDTP
       
   605 				TInt err = AvdtpRequester().GetOpt(EGetProposedConfiguration,
       
   606 													KSolBtAVDTPSignalling,
       
   607 													des);
       
   608 
       
   609 				__ASSERT_DEBUG(err==KErrNone, Fault(EGavdpUnexpectedAvdtpError));
       
   610 				
       
   611 				TAvdtpServiceCategories cats;
       
   612 				cats.SetCapability(EAllServiceCategories);
       
   613 				
       
   614 				CCapabilityParseVisitor* parser = new (ELeave) CCapabilityParseVisitor(cats);
       
   615 				parser->Process(des);
       
   616 				TCapabilitiesArray caps = parser->GetCapabilities();
       
   617 				delete parser;
       
   618 				
       
   619 				// tell app they're abuot to be offered configuration details
       
   620 				
       
   621 				User().GAVDP_ConfigurationStartIndication(cfgInd.iSEID, cfgInd.iINTSEID);
       
   622 				
       
   623 				for (TInt i=0; i<ENumberOfServiceCategories; i++)
       
   624 					{
       
   625 					// go through each capability...
       
   626 					if (EServiceCategoryMultiplexing==i)
       
   627 						{
       
   628 						// don't offer this one to user, it's not for them
       
   629 						// as it's part of AVDTP adaptation services...
       
   630 						continue;
       
   631 						}
       
   632 					TAvdtpServiceCapability*& cap = caps[i];
       
   633 					if (cap)
       
   634 						{
       
   635 						// and tell client
       
   636 						res = User().GAVDP_ConfigurationIndication(cap);
       
   637 						CheckClientResult(res);
       
   638 						if (res!=KErrNone)
       
   639 							{
       
   640 							TAvdtpServiceCategory cat = cap->Category();
       
   641 							
       
   642 							Gavdp().SendResponse(cfgInd, res, &cat);
       
   643 							// protocol says we finish config when anything is rejected
       
   644 							break;
       
   645 							}
       
   646 						else
       
   647 							{
       
   648 							// passed ownership for the error-free case
       
   649 							cap = NULL;
       
   650 							}
       
   651 						}
       
   652 					}
       
   653 				if (res==KErrNone)
       
   654 					{				
       
   655 					// tell app there's no more
       
   656 					res = User().GAVDP_ConfigurationEndIndication();
       
   657 					CheckClientResult(res);
       
   658 					// As we don't have a particular category to refer to we pass in
       
   659 					// the null category (0x0) in case GAVDP_ConfigurationEndIndication 
       
   660 					// returned an error. (Bluetooth Errata ID 332)
       
   661 					TAvdtpServiceCategory nullcat(EServiceCategoryNull);
       
   662 					// whatever user has said is now their final answer
       
   663 					Gavdp().SendResponse(cfgInd, res, &nullcat);
       
   664 					}
       
   665 
       
   666 				CleanupStack::PopAndDestroy(resp);
       
   667 				caps.DeleteAll();
       
   668 				break;
       
   669 				}
       
   670 			
       
   671 			case EAvdtpOpen:
       
   672 				{
       
   673 				 // need to process to stop deadlock if the other end doesnt do Start as INT
       
   674 				 // which it might do annoyingly if it wrongly relies on AVRCP
       
   675 				// we can just connect up sockets
       
   676 				const TInternalAvdtpStreamReadyIndication& r = reinterpret_cast<const TInternalAvdtpStreamReadyIndication&>(ind);
       
   677 			
       
   678 				Gavdp().BindBearersL(r.iRemoteSEID, r.iReportingPresent, r.iRecoveryPresent);
       
   679 				// no response to send
       
   680 				break;
       
   681 				}
       
   682 				
       
   683 			case EAvdtpRelease:
       
   684 				{
       
   685 				// just tell the user the stream has gone, AVDTP has already replied
       
   686 				User().GAVDP_ReleaseIndication(ind.iSEID);
       
   687 				break;
       
   688 				}
       
   689 		
       
   690 			case EAvdtpStart:
       
   691 				{
       
   692 				// although the packet may contain muliple SEIDs by this point
       
   693 				// each indication will have one as the ordering of the SEIDs
       
   694 				// in the packet relative to GAVDP user / session ordering is
       
   695 				// not specified.
       
   696 				res = User().GAVDP_StartIndication(ind.iSEID);
       
   697 				CheckClientResult(res);
       
   698 				Gavdp().SendResponse(ind, res);
       
   699 				break;
       
   700 				}
       
   701 			case EAvdtpSuspend:
       
   702 				{
       
   703 				// although the packet may contain muliple SEIDs by this point
       
   704 				// each indication will have one as the ordering of the SEIDs
       
   705 				// in the packet relative to GAVDP user / session ordering is
       
   706 				// not specified.
       
   707 				
       
   708 				res = User().GAVDP_SuspendIndication(ind.iSEID);
       
   709 				CheckClientResult(res);
       
   710 				Gavdp().SendResponse(ind, res);
       
   711 				break;
       
   712 				}
       
   713 			case EAvdtpSecurityControl:
       
   714 				{
       
   715 				TInt length = ind.iPayloadLength;
       
   716 				if (length < sizeof(TInternalGetSecurityControl))
       
   717 					{
       
   718 					length = sizeof(TInternalGetSecurityControl);
       
   719 					}
       
   720 				
       
   721 				HBufC8* resp = HBufC8::NewMaxLC(length);
       
   722 				TPtr8 securityData = resp->Des();
       
   723 				
       
   724 				TInternalGetSecurityControl& getSecBuf = *const_cast<TInternalGetSecurityControl*>(reinterpret_cast<const TInternalGetSecurityControl*>(resp->Des().Ptr()));
       
   725 				getSecBuf.iSEID = ind.iSEID;
       
   726 								
       
   727 				// get remainder of securitycontrol from AVDTP
       
   728 				TInt err = AvdtpRequester().GetOpt(EGetSecurityControl,
       
   729 													KSolBtAVDTPSignalling,
       
   730 													securityData);
       
   731 
       
   732 				__ASSERT_DEBUG(err==KErrNone, Fault(EGavdpUnexpectedAvdtpError));
       
   733 
       
   734 
       
   735 				res = User().GAVDP_SecurityControlIndication(ind.iSEID, securityData);
       
   736 				CheckClientResult(res);
       
   737 				// the client is allowed to change the buffer contents to supply data in response
       
   738 				Gavdp().SendResponse(ind, res, securityData.Ptr(), securityData.Length());
       
   739 				CleanupStack::PopAndDestroy(resp);
       
   740 				break;
       
   741 				}
       
   742 			case EAvdtpAbort:
       
   743 				{
       
   744 				// no return from client - there's nothing they can do
       
   745 				User().GAVDP_AbortIndication(ind.iSEID);
       
   746 				// stack already responded
       
   747 				break;
       
   748 				}
       
   749 			default:
       
   750 				{
       
   751 				}
       
   752 			};
       
   753 		}
       
   754 
       
   755 		// This service is never complete, reissue ioctl.  We do this once we have finished using
       
   756 		// the iIndication data as once the ioctl has been issued the data may be overwritten.
       
   757 		// If AVDTP has an indication to pass to us and an ioctl has not been issued the
       
   758 		// indication will be queued within AVDTP until we have issued the ioctl again.
       
   759 		Begin();
       
   760 	}
       
   761 	
       
   762 /**
       
   763 RunError overriden for CGavdpIndicator only. This GAVDP helper is used in its own right by GAVDP.
       
   764 It is not treated as a 'general' GAVDP helper, and, unlike a 'general' GAVDP helper,
       
   765 should live for the duration of GAVDP.
       
   766 Note, however that hitting this RunError is deemed fatal, and so we kill GAVDP completely. The 
       
   767 user will have to re-open it to recover.
       
   768 */
       
   769 TInt CGavdpIndicator::RunError(TInt aError)
       
   770 	{
       
   771 	RDebug::Print(_L("GAVDP::Fatal Error %d"), aError);
       
   772 	Gavdp().FatalError();
       
   773 	
       
   774 	//*****No code below here please - call to CGAVDP::FatalError will delete us****
       
   775 	return KErrNone;
       
   776 	}	
       
   777 
       
   778 void CGavdpIndicator::CheckClientResult(TInt aResult)
       
   779 	{
       
   780 	__ASSERT_ALWAYS(aResult<=KErrNone, Panic(EGavdpClientHasRepliedInCorrectly));
       
   781 	}
       
   782 	
       
   783 /**
       
   784 @internalComponent
       
   785 Start the Indicator helper
       
   786 */
       
   787 void CGavdpIndicator::Begin()
       
   788 	{
       
   789 	AvdtpIndicator().Ioctl(EAwaitIndication, iStatus, &iIndication, KSolBtAVDTPSignalling);
       
   790 	SetActive();	
       
   791 	}
       
   792 
       
   793 
       
   794 /**
       
   795 @internalComponent
       
   796 Create a User-plane bearer connector helper
       
   797 */
       
   798 CGavdpUPlaneConnector* CGavdpUPlaneConnector::NewL(CGavdp& aGavdp,
       
   799 												   MGavdpUser& aUser,
       
   800 												   const TAvdtpSockAddr& aAddr,
       
   801 											 	   TBool aRequireReporting,
       
   802 											 	   TBool aRequireRecovery,
       
   803 											 	   RSocketServ& aClientSession)
       
   804 	{
       
   805 	CGavdpUPlaneConnector* s = new (ELeave) CGavdpUPlaneConnector(aGavdp, aUser, aAddr,
       
   806 																	aRequireReporting,
       
   807 																	aRequireRecovery,
       
   808 																	aClientSession);
       
   809 	CleanupStack::PushL(s);
       
   810 	s->ConstructL(aRequireReporting, aRequireRecovery);
       
   811 	CleanupStack::Pop(s);																	
       
   812 	return s;
       
   813 	}
       
   814 	
       
   815 CGavdpUPlaneConnector::CGavdpUPlaneConnector(CGavdp& aGavdp, MGavdpUser& aUser,
       
   816 											 const TAvdtpSockAddr& aSockAddr,
       
   817 											 TBool aRequireReporting,
       
   818 											 TBool aRequireRecovery,
       
   819 						  					 RSocketServ& aClientSession)
       
   820 : CGavdpHelper(aGavdp, aUser),
       
   821   iClientSession(aClientSession)
       
   822 	{
       
   823 	iAddress = aSockAddr;
       
   824 	iNumBearersRequired = AvdtpInternalUtils::NumberOfTransportObjects(aRequireReporting, aRequireRecovery);
       
   825 	}
       
   826 
       
   827 void CGavdpUPlaneConnector::ConstructL(TBool aRequireReporting, TBool aRequireRecovery)
       
   828 	{
       
   829 	TAvdtpSockAddr addr = iAddress;
       
   830 	addr.SetSession(EMedia);
       
   831 	iSocketConnectors[0]=CSocketConnector::NewL(*this, AvdtpSession(), addr);
       
   832 
       
   833 	if (aRequireReporting)
       
   834 		{
       
   835 		addr.SetSession(EReporting);
       
   836 		iSocketConnectors[1]=CSocketConnector::NewL(*this, AvdtpSession(), addr);
       
   837 		}
       
   838 
       
   839 	if (aRequireRecovery)
       
   840 		{
       
   841 		addr.SetSession(ERecovery);
       
   842 		iSocketConnectors[2]=CSocketConnector::NewL(*this, AvdtpSession(), addr);
       
   843 		}
       
   844 	}
       
   845 	
       
   846 CGavdpUPlaneConnector::~CGavdpUPlaneConnector()
       
   847 	{
       
   848 	Cancel();
       
   849 	iSocketConnectors.DeleteAll();
       
   850 	}
       
   851 
       
   852 void CGavdpUPlaneConnector::DoCancel()
       
   853 	{
       
   854 	for (TInt i=0; i<iSocketConnectors.Count()-1; i++)
       
   855 		{
       
   856 		if (iSocketConnectors[i])
       
   857 			{
       
   858 			iSocketConnectors[i]->Cancel();
       
   859 			}
       
   860 		}
       
   861 	}
       
   862 
       
   863 void CGavdpUPlaneConnector::Begin()
       
   864 	{
       
   865 	// Ensure that once this is completed the RunL is scheduled
       
   866 	// before handling completion of the indication ioctl.
       
   867 	SetPriority(EPriorityStandard+1);
       
   868 	for (TInt i=0; i<iSocketConnectors.Count()-1; i++)
       
   869 		{
       
   870 		if (iSocketConnectors[i])
       
   871 			{
       
   872 			iSocketConnectors[i]->Begin();
       
   873 			}
       
   874 		}
       
   875 	}
       
   876 
       
   877 void CGavdpUPlaneConnector::ConnectComplete(TInt aErr)
       
   878 	{
       
   879 	DoConnectComplete(aErr);
       
   880 
       
   881 	if (aErr)
       
   882 		{
       
   883 		DoCancel();	// now not active, but we need to cancel the remaining socketconnectors
       
   884 		}
       
   885 	}
       
   886 	
       
   887 void CGavdpUPlaneConnector::DoConnectComplete(TInt aErr)
       
   888 	{
       
   889 	--iNumBearersRequired;
       
   890 	
       
   891 	if(aErr >= EGavdpMinPanicErr && aErr <= EGavdpMaxPanicErr)
       
   892 		{
       
   893 		Panic (static_cast<TGavdpPanic>(aErr));
       
   894 		}
       
   895 	
       
   896 	if (!iNumBearersRequired || aErr!=KErrNone)
       
   897 		{
       
   898 		// service is complete
       
   899 		TRequestStatus* ours = &iStatus;
       
   900 		*ours = KRequestPending;
       
   901 		SetActive();
       
   902 		User::RequestComplete(ours, aErr);
       
   903 		}
       
   904 	}
       
   905 	
       
   906 void CGavdpUPlaneConnector::RunL()
       
   907 	{
       
   908 	CheckFailedL();
       
   909 
       
   910 	// all required bearers connected, helper can detach from gavdp
       
   911 	DetachFromGavdp(KErrNone);
       
   912 	
       
   913 	AllBearersReadyL();
       
   914 
       
   915 	delete this;
       
   916 	}
       
   917 	
       
   918 void CGavdpUPlaneConnector::AllBearersReadyL()
       
   919 	{
       
   920 	// transfer our sockets onto the client session
       
   921 	for (TInt i=0; i<=iSocketConnectors.Count()-1; i++)
       
   922 		{
       
   923 		CSocketConnector* const connector = iSocketConnectors[i];
       
   924 		if (connector)
       
   925 			{
       
   926 			RSocket& socket = connector->Socket();
       
   927 			// take socket and transfer to client session
       
   928 			TName socketName;
       
   929 			User::LeaveIfError(socket.Name(socketName));
       
   930 
       
   931 			RSocket clientSocket;
       
   932 
       
   933 			//plat sect stuff to transfer sockets - to this same process
       
   934 			TSecurityPolicy secPol(RProcess().SecureId());
       
   935 			TPckgBuf<TSecurityPolicy> secPolBuf(secPol);
       
   936 			User::LeaveIfError(socket.SetOpt(KSOEnableTransfer, KSOLSocket, secPolBuf));
       
   937 			User::LeaveIfError(clientSocket.Transfer(iClientSession, socketName));
       
   938 			
       
   939 			User().GAVDP_BearerReady(clientSocket, connector->Address());
       
   940 			}
       
   941 		}
       
   942 	}
       
   943 	
       
   944 
       
   945 CSocketConnector* CSocketConnector::NewL(CGavdpUPlaneConnector& aParent,
       
   946 									RSocketServ& aSocketServer,
       
   947 									const TAvdtpSockAddr& aSockAddr)
       
   948 
       
   949 	{
       
   950 	CSocketConnector* self = new(ELeave) CSocketConnector(aParent, aSocketServer, aSockAddr);
       
   951 	CleanupStack::PushL(self);
       
   952 	self->ConstructL();
       
   953 	CleanupStack::Pop(self);
       
   954 	return self;
       
   955 	}
       
   956 
       
   957 void CSocketConnector::ConstructL()
       
   958 	{
       
   959 	User::LeaveIfError(iSocket.Open(iSocketServer, KAVDTPProtocolName));
       
   960 	}
       
   961 	
       
   962 void CSocketConnector::Begin()
       
   963 	{
       
   964 	iSocket.Connect(iSockAddr, iStatus);
       
   965 	SetActive();
       
   966 	}
       
   967 	
       
   968 CSocketConnector::CSocketConnector(CGavdpUPlaneConnector& aParent,
       
   969 									RSocketServ& aSocketServer,
       
   970 									const TAvdtpSockAddr& aSockAddr)
       
   971 : CActive(EPriorityStandard+1), iParent(aParent),
       
   972 iSocketServer(aSocketServer), iSockAddr(aSockAddr)
       
   973 	{
       
   974 	CActiveScheduler::Add(this);
       
   975 	}
       
   976 
       
   977 CSocketConnector::~CSocketConnector()
       
   978 	{
       
   979 	Cancel();
       
   980 
       
   981 	if (iSocket.SubSessionHandle())
       
   982 		{
       
   983 		iSocket.Close();
       
   984 		}
       
   985 	}
       
   986 	
       
   987 void CSocketConnector::RunL()
       
   988 	{
       
   989 	iParent.ConnectComplete(iStatus.Int());
       
   990 	}
       
   991 	
       
   992 void CSocketConnector::DoCancel()
       
   993 	{
       
   994 	if (iSocket.SubSessionHandle())
       
   995 		{
       
   996 		iSocket.CancelAll();
       
   997 		}
       
   998 	}
       
   999 	
       
  1000 
       
  1001 CGavdpSecurityControl* CGavdpSecurityControl::NewL(CGavdp& aGavdp,
       
  1002 					  		  MGavdpUser& aUser,
       
  1003 					  		  TSEID aSeid,
       
  1004 					  		  const TDesC8& aSecurityControl)
       
  1005 	{
       
  1006 	return new (ELeave) CGavdpSecurityControl(aGavdp, aUser, aSeid, aSecurityControl);
       
  1007 	}
       
  1008 	
       
  1009 void CGavdpSecurityControl::Begin()
       
  1010 	{
       
  1011 	AvdtpRequester().Ioctl(ESendSecurityControl, iStatus, &iSecurityControlPckgBuf, KSolBtAVDTPSignalling);
       
  1012 	SetActive();		
       
  1013 	}
       
  1014 	
       
  1015 CGavdpSecurityControl::~CGavdpSecurityControl()
       
  1016 	{
       
  1017 	Cancel();
       
  1018 	}
       
  1019 	
       
  1020 CGavdpSecurityControl::CGavdpSecurityControl(CGavdp& aGavdp, MGavdpUser& aUser, TSEID aSeid, const TDesC8& aSecurityData)
       
  1021 : CGavdpHelper(aGavdp, aUser)
       
  1022 	{
       
  1023 	iSecurityControlPckgBuf().iRemoteSEID = aSeid;
       
  1024 	iSecurityControlPckgBuf().iSecurityControlInfo = aSecurityData;
       
  1025 	}
       
  1026 	
       
  1027 void CGavdpSecurityControl::RunL()
       
  1028 	{
       
  1029 	CheckFailedL();
       
  1030 	DetachFromGavdp(KErrNone);	
       
  1031 
       
  1032 	User().GAVDP_SecurityControlConfirm(iSecurityControlPckgBuf().iSecurityControlInfo);
       
  1033 
       
  1034 	delete this;
       
  1035 	}
       
  1036 	
       
  1037 void CGavdpSecurityControl::DoCancel()
       
  1038 	{
       
  1039 	AvdtpRequester().CancelAll();
       
  1040 	}