bluetooth/btstack/avdtp/avdtpSignallingSession.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the avdtp signalling session
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include "avdtpSignallingSession.h"
       
    25 #include "avdtpSignallingChannel.h"
       
    26 #include "avdtp.h"
       
    27 #include "avdtpsap.h"
       
    28 #include "avdtpStream.h"
       
    29 #include "avdtpLogicalChannelFactory.h"
       
    30 #include "avdtpConfigurators.h"
       
    31 #include "avdtputil.h"
       
    32 #include "avdtpDirectChannel.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
       
    36 #endif
       
    37 
       
    38 #ifdef _DEBUG
       
    39 PANICCATEGORY("avdtpsigse");
       
    40 #endif
       
    41 
       
    42 CSignallingSession* CSignallingSession::NewLC(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
       
    43 	{
       
    44 	LOG_STATIC_FUNC
       
    45 	CSignallingSession* s = new (ELeave) CSignallingSession(aProtocol, aSAP);
       
    46 	CleanupStack::PushL(s);
       
    47 	s->ConstructL();
       
    48 	return s;
       
    49 	}
       
    50 	
       
    51 CSignallingSession* CSignallingSession::NewL(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
       
    52 	{
       
    53 	LOG_STATIC_FUNC
       
    54 	CSignallingSession* s = CSignallingSession::NewLC(aProtocol, aSAP);
       
    55 	CleanupStack::Pop();
       
    56 	return s;		
       
    57 	}
       
    58 	
       
    59 CSignallingSession::CSignallingSession(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
       
    60 : CTransportSession(aProtocol, aSAP, ESignalling),
       
    61   iLocalSEPs(_FOFF(CLocalSEP, iSignallingSessionLink))
       
    62 	{
       
    63 	LOG_FUNC	
       
    64 	}
       
    65 
       
    66 CSignallingSession::~CSignallingSession()
       
    67 	{
       
    68 	LOG_FUNC
       
    69 	DestroyLocalSEPs();
       
    70 	ClearSignallingChannel();
       
    71 	delete iSEPConfigurator;
       
    72 	}
       
    73 
       
    74 	
       
    75 void CSignallingSession::ConstructL()
       
    76 	{
       
    77 	LOG_FUNC
       
    78 	CTransportSession::ConstructL();
       
    79 	}
       
    80 
       
    81 TInt CSignallingSession::ActiveOpen()
       
    82 	{
       
    83 	LOG_FUNC
       
    84 	// esock will protect us from an accidental double connect
       
    85 	TInt ret = KErrNone;
       
    86 	if (iSignallingChannel)
       
    87 		{
       
    88 		if (!iSignallingChannel->IsListening())
       
    89 			{
       
    90 			// already got a suitable SC - probably due to a passive connection
       
    91 			// just say it's done (we're already attached)
       
    92 			iSAP.Ready();
       
    93 			}
       
    94 		else
       
    95 			{
       
    96 			// signalling channel is listening - detach from it, user has decided to connect
       
    97 			// drop through afterwards
       
    98 			ClearSignallingChannel();
       
    99 			}
       
   100 		}
       
   101 	// not else as ClearSignallingChannel will NULL iSignallingChannel
       
   102 	if (!iSignallingChannel)
       
   103 		{
       
   104 		iSignallingChannel = iProtocol.GetSignallingChannel(RemoteAddress());
       
   105 		if (iSignallingChannel)
       
   106 			{
       
   107 			ret = iSignallingChannel->AttachSignallingUser(*this);
       
   108 			}
       
   109 		else
       
   110 			{
       
   111 			ret = KErrNoMemory;
       
   112 			}
       
   113 		}
       
   114 
       
   115 	return ret;
       
   116 	}
       
   117 	
       
   118 void CSignallingSession::ClearSignallingChannel()
       
   119 	{
       
   120 	LOG_FUNC
       
   121 	if (iSignallingChannel)
       
   122 		{
       
   123 		iSignallingChannel->DetachSignallingUser(*this);	
       
   124 		}
       
   125 	iSignallingChannel = NULL;
       
   126 	}
       
   127 	
       
   128 void CSignallingSession::DestroyLocalSEPs()
       
   129 	{
       
   130 	LOG_FUNC
       
   131 	while (!iLocalSEPs.IsEmpty())
       
   132 		{
       
   133 		CLocalSEP* sep = iLocalSEPs.First();
       
   134 		sep->iSignallingSessionLink.Deque();
       
   135 		// inform codman - it'll clear bits as necessary since it reference coutns
       
   136 		iProtocol.CodMan().RemoveCodService(sep->Info().IsSink() ? EMajorServiceRendering :
       
   137 																	EMajorServiceCapturing);
       
   138 		delete sep;		
       
   139 		}
       
   140 	}
       
   141 	
       
   142 void CSignallingSession::DoShutdown()
       
   143 	{
       
   144 	LOG_FUNC
       
   145 
       
   146 	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
   147 	while(iter)
       
   148 		{
       
   149 		iter++->SetInUse(EFalse);
       
   150 		}
       
   151 		
       
   152 	ClearSignallingChannel();
       
   153 	
       
   154 	if (iSAPShutdown == ENormal)
       
   155 		{
       
   156 		iSAP.CanClose();
       
   157 		}
       
   158 	else
       
   159 		{
       
   160 		// base class has detached us so that we own ourselves
       
   161 		// nothing more to do, apart from die.
       
   162 		delete this;
       
   163 		}
       
   164 	}
       
   165 
       
   166 TInt CSignallingSession::Send(RMBufChain& /*aData*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
   167 	{
       
   168 	LOG_FUNC
       
   169 	// not supported in signalling - only ioctls and opts allowed
       
   170 	return 0;
       
   171 	}
       
   172 
       
   173 TInt CSignallingSession::GetData(RMBufChain& /*aData*/)
       
   174 	{
       
   175 	LOG_FUNC
       
   176 	return KErrNotSupported;
       
   177 	}
       
   178 	
       
   179 // stuff forwarded from SAP
       
   180 TInt CSignallingSession::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption)
       
   181 	{
       
   182 	LOG_FUNC
       
   183 	TInt ret = KErrNotSupported;
       
   184 
       
   185 	if (aLevel == KSolBtAVDTPSignalling)
       
   186 		{
       
   187 		switch (aName)
       
   188 			{
       
   189 			case EAwaitPassiveSignallingChannel:
       
   190 				{
       
   191 				if (iIsListening && iSignallingChannel && iSignallingChannel->IsListening())
       
   192 					{
       
   193 					ret = KErrAlreadyExists;
       
   194 					}
       
   195 				else if (iSignallingChannel && !iSignallingChannel->IsListening())
       
   196 					{
       
   197 					ret = KErrInUse;
       
   198 					}
       
   199 				else
       
   200 					{					
       
   201 	                iSignallingChannel=iProtocol.FindListeningSignallingChannel();
       
   202 					// For ACP - triggered when client is ready for listening
       
   203 					// (would be nice to be "automatic", but needs client to be happy they've registered all their seps
       
   204 					if (!iSignallingChannel)
       
   205 						{
       
   206 	    				iSignallingChannel = iProtocol.CreateSignallingChannelForListening();
       
   207 						}
       
   208 					
       
   209 					if (iSignallingChannel)
       
   210 						{
       
   211 						ASSERT_DEBUG(iSignallingChannel->IsListening());
       
   212 						ret = iSignallingChannel->AttachSignallingUser(*this);
       
   213 						if (ret == KErrNone)
       
   214 							{
       
   215 							iIsListening = ETrue;
       
   216 							}
       
   217 						else
       
   218 							{
       
   219 							// if we didn't manage to tell anyone else
       
   220 							// then no one else knows so actually we're best
       
   221 							// off cleaning up after ourselves.
       
   222 							iSignallingChannel->DetachSignallingUser(*this);
       
   223 							iSignallingChannel = NULL;
       
   224 							}							
       
   225 						}
       
   226 					else
       
   227 						{
       
   228 						ret = KErrNoMemory;
       
   229 						}
       
   230 					}
       
   231 				break;
       
   232 				}
       
   233 
       
   234 			case EStopAwaitPassiveSignallingChannel:
       
   235 				{
       
   236 				if (!iSignallingChannel)
       
   237 					{
       
   238     				ret = KErrNotReady;
       
   239 					}
       
   240 
       
   241 				else
       
   242 					{
       
   243 					iIsListening = EFalse;
       
   244 					ClearSignallingChannel();
       
   245 					}
       
   246 				break;
       
   247 				}
       
   248 			
       
   249 			// also for reconfigure - the configurator decides
       
   250 			case EStartConfiguringRemote:
       
   251 				{
       
   252 				if (iSEPConfigurator)
       
   253 					{
       
   254 					ret = KErrInUse;
       
   255 					}
       
   256 				else
       
   257 					{
       
   258 					// Check the integrity of the descriptor					
       
   259 					if (!aOption.Ptr() || aOption.Length() != sizeof(TInternalSelectRemoteSEP))
       
   260 						{
       
   261 						ret = KErrBadDescriptor;
       
   262 						}
       
   263 					else
       
   264 						{
       
   265 						// get Remote SEID we're configuring, and the binding local SEP SEID
       
   266 						// avdtp spec makes us have to do the binding now
       
   267 						TInternalSelectRemoteSEP select = *reinterpret_cast<const TInternalSelectRemoteSEP*>(aOption.Ptr());
       
   268 
       
   269 						if (!select.iLocalSEID.IsLocal())
       
   270 							{
       
   271 							ret = KErrArgument;
       
   272 							}
       
   273 						else
       
   274 							{							
       
   275 							CLocalSEP* localSEP = FindLocalSEP(select.iLocalSEID);
       
   276 							if (!localSEP)
       
   277 								{
       
   278 								// client supplied bad SEID
       
   279 								ret = KErrArgument;
       
   280 								}
       
   281 							else
       
   282 								{
       
   283 								// don't support reconfiguring of an active stream - client must suspend
       
   284 								CAVStream* stream = localSEP->Stream();
       
   285 								if (stream && stream->IsStreaming())
       
   286 									{
       
   287 									ret = KErrInUse;
       
   288 									}
       
   289 								else
       
   290 									{
       
   291 									TRAP(ret, iSEPConfigurator = CRemoteSEPConfigurator::NewL(*this,
       
   292 																  iProtocol,
       
   293 																  select.iLocalSEID,
       
   294 																  select.iRemoteSEID,
       
   295 																  stream ? ETrue : EFalse));
       
   296 									}
       
   297 								}
       
   298 							}
       
   299 						}
       
   300 					}
       
   301 				break;
       
   302 				}
       
   303 			case EStartConfiguringLocal:
       
   304 				{
       
   305 				if (iSEPConfigurator)
       
   306 					{
       
   307 					ret = KErrInUse;
       
   308 					}
       
   309 				else
       
   310 					{
       
   311 					// Check the integrity of the descriptor					
       
   312 					if (!aOption.Ptr() || aOption.Length() != sizeof(TSEID))
       
   313 						{
       
   314 						ret = KErrBadDescriptor;
       
   315 						}
       
   316 					else
       
   317 						{
       
   318 						// get Local SEID we're configuring
       
   319 						TSEID localseid = *reinterpret_cast<const TSEID*>(aOption.Ptr());
       
   320 						TRAP(ret, iSEPConfigurator = CLocalSEPConfigurator::NewL(*this, iProtocol, localseid));
       
   321 						}
       
   322 					}
       
   323 				break;
       
   324 				}
       
   325 			
       
   326 			case EAddCapabilitySelection:
       
   327 				{
       
   328 				if (iSEPConfigurator)
       
   329 					{
       
   330 					ret = iSEPConfigurator->AddCapability(aOption);
       
   331 					}
       
   332 				else
       
   333 					{
       
   334 					ret = KErrNotReady;
       
   335 					}
       
   336 				break;
       
   337 				}
       
   338 				
       
   339 			case ESendConfigurationResponse:
       
   340 				{
       
   341 				if (iSignallingChannel)
       
   342 					{
       
   343 					// Check the integrity of the descriptor					
       
   344 					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalConfigurationResponse))
       
   345 						{
       
   346 						ret = KErrBadDescriptor;
       
   347 						}
       
   348 					else
       
   349 						{
       
   350 						const TAvdtpInternalConfigurationResponse rsp = *reinterpret_cast<const TAvdtpInternalConfigurationResponse*>(aOption.Ptr());
       
   351 						// check SEID is ok
       
   352 						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
       
   353 						if (sep)
       
   354 							{						
       
   355 	 						// need to tell sep of the outcome so it can clear its state
       
   356 	 						// this needs to occur for config and reconfig
       
   357 	 						// first param is true if result is kerrnone- i.e. all ok, false otherwise
       
   358 	 						TRAP(ret, sep->CommitPendingConfigurationL(rsp.iResult == KErrNone,rsp.iIsReconfigure));
       
   359 							if (!rsp.iIsReconfigure)
       
   360 								{
       
   361 								if (rsp.iResult == KErrNone)
       
   362 									{
       
   363 									if (ret==KErrNone)
       
   364 										{
       
   365 										ret = iSignallingChannel->SendSetConfigurationAccept(rsp.iTransactionLabel);
       
   366 										if (ret==KErrNone)
       
   367 											{
       
   368 											// time to spawn that (ACP) stream
       
   369 											TRAP(ret, sep->ExpectStreamL(RemoteAddress(), *this, iProtocol));
       
   370 											}
       
   371 										}
       
   372 									}
       
   373 								else
       
   374 									{
       
   375 									ret = iSignallingChannel->SendSetConfigurationReject(rsp.iTransactionLabel,
       
   376 																			   AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult),
       
   377 																			   rsp.iCategory);
       
   378 									}
       
   379 								}
       
   380 							else
       
   381 								{
       
   382 								if (!sep->InUse())
       
   383 									{
       
   384 									// almost assertable since we shouldnt have forwarded the indication if not
       
   385 									// but we don't want a DoS if bad client
       
   386 									ret = KErrNotReady;
       
   387 									}
       
   388 								else
       
   389 									{
       
   390 									if (rsp.iResult == KErrNone)
       
   391 										{
       
   392 										ret = iSignallingChannel->SendReconfigureAccept(rsp.iTransactionLabel);
       
   393 										}
       
   394 									else
       
   395 										{
       
   396 										ret = iSignallingChannel->SendReconfigureReject(rsp.iTransactionLabel,
       
   397 																			   AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult),
       
   398 																			   rsp.iCategory);
       
   399 										}
       
   400 									}
       
   401 								}
       
   402 							if (ret==KErrNone && rsp.iResult == KErrNone && !rsp.iIsReconfigure)
       
   403 								{
       
   404 								// now in use, and from AVDTP spec sect6.3 we now do not expect other transactions until stream started
       
   405 								// not point resetting for reconfigure
       
   406 								sep->SetInUse(ETrue);
       
   407 								}
       
   408 							}
       
   409 						else
       
   410 							{
       
   411 							ret = KErrArgument;
       
   412 							}
       
   413 						}
       
   414 					}
       
   415 				else
       
   416 					{
       
   417 					ret = KErrDisconnected;
       
   418 					}
       
   419 				break;
       
   420 				}
       
   421 				
       
   422 			case ESendStartResponse:
       
   423 				{
       
   424 				if (iSignallingChannel)
       
   425 					{
       
   426 					// Check the integrity of the descriptor					
       
   427 					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalStartResponse))
       
   428 						{
       
   429 						ret = KErrBadDescriptor;
       
   430 						}
       
   431 					else
       
   432 						{
       
   433 						const TAvdtpInternalStartResponse rsp = *reinterpret_cast<const TAvdtpInternalStartResponse*>(aOption.Ptr());
       
   434 						// check SEID is ok
       
   435 						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
       
   436 						
       
   437 						if (sep && sep->Stream() && rsp.iResult == KErrNone)
       
   438 							{
       
   439 							ret = iSignallingChannel->SendStartAccept(rsp.iTransactionLabel);
       
   440 							if (ret==KErrNone)
       
   441 								{
       
   442 								sep->Stream()->Started();
       
   443 								}
       
   444 							}
       
   445 						else if (sep && !(sep->Stream()))
       
   446 							{
       
   447 							ret = KErrUnknown;
       
   448 							}
       
   449 						else if (sep)
       
   450 							{
       
   451 							// The AVDTP error code (spec... ACP to INT error code table) is offset by -18045
       
   452 							ret = iSignallingChannel->SendStartReject(rsp.iTransactionLabel, AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult), rsp.iSEID);
       
   453 							}
       
   454 						else
       
   455 							{
       
   456 							ret = KErrArgument;
       
   457 							}
       
   458 						}
       
   459 					}
       
   460 				else
       
   461 					{
       
   462 					ret = KErrDisconnected;
       
   463 					}
       
   464 				break;
       
   465 				}
       
   466 			case ESendSuspendResponse:
       
   467 				{
       
   468 				if (iSignallingChannel)
       
   469 					{
       
   470 					// Check the integrity of the descriptor					
       
   471 					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalSuspendResponse))
       
   472 						{
       
   473 						ret = KErrBadDescriptor;
       
   474 						}
       
   475 					else
       
   476 						{
       
   477 						const TAvdtpInternalSuspendResponse rsp = *reinterpret_cast<const TAvdtpInternalSuspendResponse*>(aOption.Ptr());
       
   478 						// check SEID is ok
       
   479 						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
       
   480 						if (sep && sep->Stream() && rsp.iResult == KErrNone)
       
   481 							{
       
   482 							ret = iSignallingChannel->SendSuspendAccept(rsp.iTransactionLabel);
       
   483 							if (ret==KErrNone)
       
   484 								{
       
   485 								sep->Stream()->Suspended();
       
   486 								}
       
   487 							}
       
   488 						else if (sep && !(sep->Stream()))
       
   489 							{
       
   490 							ret = KErrUnknown;
       
   491 							}
       
   492 						else if (sep)
       
   493 							{
       
   494 							// The AVDTP error code (spec... ACP to INT error code table) is offset by -18045
       
   495 							ret = iSignallingChannel->SendSuspendReject(rsp.iTransactionLabel, AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult), rsp.iSEID);
       
   496 							}
       
   497 						else
       
   498 							{
       
   499 							ret = KErrArgument;
       
   500 							}
       
   501 						}
       
   502 					}
       
   503 				else
       
   504 					{
       
   505 					ret = KErrDisconnected;
       
   506 					}
       
   507 				break;
       
   508 				}
       
   509 			case ESendSecurityControlResponse:
       
   510 				{
       
   511 				if (iSignallingChannel)
       
   512 					{
       
   513 					// Check the integrity of the descriptor					
       
   514 					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalSecurityControlResponse))
       
   515 						{
       
   516 						ret = KErrBadDescriptor;
       
   517 						}
       
   518 					else
       
   519 						{
       
   520 						const TAvdtpInternalSecurityControlResponse secRsp = *reinterpret_cast<const TAvdtpInternalSecurityControlResponse*>(aOption.Ptr());
       
   521 						// check SEID is ok
       
   522 						CLocalSEP* sep = FindLocalSEP(secRsp.iSEID);
       
   523 						if (!sep)
       
   524 							{
       
   525 							ret = KErrArgument;
       
   526 							}
       
   527 						else
       
   528 							{
       
   529 							if(secRsp.iResult == KErrNone)
       
   530 								{
       
   531 								const TDesC8* rspInfo = secRsp.iSecurityControlInfo.Length() ? &secRsp.iSecurityControlInfo : NULL;
       
   532 								ret = iSignallingChannel->SendSecurityControlAccept(secRsp.iTransactionLabel, rspInfo);
       
   533 								}
       
   534 							else
       
   535 								{
       
   536 								ret = iSignallingChannel->SendSecurityControlReject(secRsp.iTransactionLabel,
       
   537 																		AvdtpInternalUtils::SymbianErrorToAvdtpError(secRsp.iResult));
       
   538 								}
       
   539 							}
       
   540 						}
       
   541 					}
       
   542 				else
       
   543 					{
       
   544 					ret = KErrDisconnected;
       
   545 					}
       
   546 				break;
       
   547 				}
       
   548 			case EShutdown:
       
   549 				{
       
   550 				ret=KErrNone;
       
   551 				TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
   552 				while(iter)
       
   553 					{
       
   554 					if (iter++->Stream()) 
       
   555 						{
       
   556 						ret=KErrNotReady;
       
   557 						}
       
   558 					}
       
   559 				if (ret==KErrNone)
       
   560 					{
       
   561 					iter.SetToFirst();
       
   562 					while(iter)
       
   563 						{
       
   564 						iter++->SetInUse(EFalse);
       
   565 						}
       
   566 
       
   567 					ClearSignallingChannel();
       
   568 					iSAP.SessionDisconnect();
       
   569 					}
       
   570 				break;
       
   571 				}
       
   572 			}
       
   573 		}
       
   574 	return ret;
       
   575 	}
       
   576 	
       
   577 	
       
   578 	
       
   579 void CSignallingSession::Ioctl(TUint aLevel, TUint aName, const TDesC8* aOption)
       
   580 	{
       
   581 	LOG_FUNC
       
   582 	TInt res = KErrNotSupported;
       
   583 	
       
   584 	if (aLevel == KSolBtAVDTPSignalling)	
       
   585 		{
       
   586 		const TUint8* optionPtr=NULL;
       
   587 		if (aOption)
       
   588 			{
       
   589 			optionPtr = aOption->Ptr();
       
   590 			}
       
   591 			
       
   592 		switch (aName)
       
   593 			{
       
   594 			case EDiscoverSEPs:
       
   595 				{
       
   596 				res=iSignallingChannel ? iSignallingChannel->SendDiscoverSEPs(*this) : KErrNotReady;
       
   597 				break;
       
   598 				}
       
   599 			case EGetCapabilities:
       
   600 				{
       
   601 				// Check the integrity of the descriptor					
       
   602 				if (!optionPtr || aOption->Length() != sizeof(TSEID))
       
   603 					{
       
   604 					res = KErrBadDescriptor;
       
   605 					}
       
   606 				else
       
   607 					{
       
   608 					TSEID seid = *reinterpret_cast<const TSEID*>(optionPtr);
       
   609 					
       
   610 					if (seid.IsLocal())
       
   611 						{
       
   612 						// meaningless to try to associate with a remote sep at this stage
       
   613 						// getting local capabilities not supported
       
   614 						res = KErrArgument;
       
   615 						}
       
   616 					else
       
   617 						{						
       
   618 						// client doesn't need to have populated remote sep cache at this point, so just try to send
       
   619 						res=iSignallingChannel ?  iSignallingChannel->SendGetCapabilities(*this, seid) : KErrNotReady;
       
   620 						}
       
   621 					}
       
   622 				break;
       
   623 				}
       
   624 			case EAbortStream:
       
   625 				{
       
   626 				// Check the integrity of the descriptor					
       
   627 				if (!optionPtr || aOption->Length() != sizeof(TSEID))
       
   628 					{
       
   629 					res = KErrBadDescriptor;
       
   630 					}
       
   631 				else
       
   632 					{
       
   633 					res = KErrNone;
       
   634 					// check seid exists
       
   635 					const TSEID& seid = *reinterpret_cast<const TSEID*>(optionPtr);
       
   636 					TSEID packetSeid;
       
   637 					
       
   638 					if (seid.IsLocal())
       
   639 						{
       
   640 						CLocalSEP* sep = FindLocalSEP(seid);
       
   641 						// check local sep exists
       
   642 						if (!sep || !(sep->Stream()))
       
   643 							{
       
   644 							res = KErrArgument;
       
   645 							}
       
   646 						else
       
   647 							{
       
   648 							packetSeid = sep->Stream()->RemoteSEID();
       
   649 							}
       
   650 						}
       
   651 					else
       
   652 						{
       
   653 						// remote was specified - again, check it'ok
       
   654 						if (!FindStreamFromRemoteSEID(seid))
       
   655 							{
       
   656 							res = KErrArgument;
       
   657 							}
       
   658 						else
       
   659 							{
       
   660 							packetSeid = seid;
       
   661 							}
       
   662 						}
       
   663 					if (res==KErrNone)
       
   664 						{
       
   665 						res = SendAbort(packetSeid);
       
   666 						}
       
   667 					}
       
   668 				break;
       
   669 				}
       
   670 			case ESelectSEP:
       
   671 				{
       
   672 				if (iSEPConfigurator)
       
   673 					{				
       
   674 					TInt cfgRes = iSEPConfigurator->Finalise();
       
   675 					// user doesn't need to know whether we sync or async
       
   676 					res = cfgRes == KRequestPending ? KErrNone : cfgRes;
       
   677 					if (cfgRes==KErrNone)
       
   678 						{
       
   679 						// can complete the service now
       
   680 						iSAP.ServiceComplete(NULL);
       
   681 						}
       
   682 					delete iSEPConfigurator;
       
   683 					iSEPConfigurator = NULL;
       
   684 					}
       
   685 				else
       
   686 					{
       
   687 					res = KErrNotReady;
       
   688 					}
       
   689 				break;
       
   690 				}
       
   691 			case EStartStreaming:
       
   692 				{
       
   693 				if (iSignallingChannel==NULL)
       
   694 					{
       
   695 					res = KErrNotReady;
       
   696 					}
       
   697 				else
       
   698 					{
       
   699 					// Check the integrity of the descriptor					
       
   700 				if (!optionPtr || aOption->Length() != sizeof(TSEID))
       
   701 					{
       
   702 					res = KErrBadDescriptor;
       
   703 					}
       
   704 					else
       
   705 						{
       
   706 						const TSEID& clientSeid = *reinterpret_cast<const TSEID*>(optionPtr);
       
   707 						
       
   708 						// see whether it was a local or remote seid - either is ok
       
   709 						CAVStream* stream = NULL;
       
   710 						
       
   711 						if (clientSeid.IsLocal())
       
   712 							{
       
   713 							CLocalSEP* sep = FindLocalSEP(clientSeid);
       
   714 							if (sep)
       
   715 								{
       
   716 								stream = sep->Stream();
       
   717 								}
       
   718 							}
       
   719 						else
       
   720 							{
       
   721 							// client supplied remote seid so just check
       
   722 							stream = FindStreamFromRemoteSEID(clientSeid);
       
   723 							}
       
   724 						res = stream ? stream->Start() : KErrUnknown;
       
   725 						}
       
   726 					}					
       
   727 				break;
       
   728 				}
       
   729 			case ESuspendStreaming:
       
   730 				{
       
   731 				if (iSignallingChannel==NULL)
       
   732 					{
       
   733 					res = KErrNotReady;
       
   734 					}
       
   735 				else
       
   736 					{
       
   737 					// Check the integrity of the descriptor					
       
   738 				if (!optionPtr || aOption->Length() != sizeof(TSEID))
       
   739 					{
       
   740 					res = KErrBadDescriptor;
       
   741 					}
       
   742 					else
       
   743 						{
       
   744 						const TSEID& clientSeid = *reinterpret_cast<const TSEID*>(optionPtr);
       
   745 						// see whether it was a local or remote seid - either is ok
       
   746 						CAVStream* stream = NULL;
       
   747 						
       
   748 						if (clientSeid.IsLocal())
       
   749 							{
       
   750 							CLocalSEP* sep = FindLocalSEP(clientSeid);
       
   751 							if (sep)
       
   752 								{
       
   753 								stream = sep->Stream();
       
   754 								}
       
   755 							}
       
   756 						else
       
   757 							{
       
   758 							// client supplied remote seid so just check
       
   759 							stream = FindStreamFromRemoteSEID(clientSeid);
       
   760 							}
       
   761 						res = stream ? stream->Suspend() : KErrUnknown;
       
   762 						}
       
   763 					}
       
   764 				break;
       
   765 				}
       
   766 			case ESendSecurityControl:
       
   767 				{
       
   768 				//GAVDP is wishing to send security control command (allowed any time if capable)
       
   769 				// needs to be remote
       
   770 				// Check the integrity of the descriptor					
       
   771 				if (!optionPtr || aOption->Length() != sizeof(TAvdtpInternalSendSecurityControl))
       
   772 					{
       
   773 					res = KErrBadDescriptor;
       
   774 					}
       
   775 				else
       
   776 					{
       
   777 					const TAvdtpInternalSendSecurityControl& security = *reinterpret_cast<const TAvdtpInternalSendSecurityControl*>(optionPtr);
       
   778 					if (!security.iRemoteSEID.IsLocal())
       
   779 						{
       
   780 						// check capability
       
   781 						if (iSignallingChannel)
       
   782 							{
       
   783 							if (iProtocol.RemoteSEPCache().HasCapability(RemoteAddress(),
       
   784 																		security.iRemoteSEID,
       
   785 																		EServiceCategoryContentProtection))
       
   786 								{
       
   787 								res = iSignallingChannel->SendSecurityControl(*this,
       
   788 																		security.iRemoteSEID,
       
   789 																		security.iSecurityControlInfo);
       
   790 								}
       
   791 							else
       
   792 								{
       
   793 								// remote doesnt support CP
       
   794 								res = KErrNotSupported;
       
   795 								}
       
   796 							}
       
   797 						else
       
   798 							{
       
   799 							res = KErrNotReady;
       
   800 							}
       
   801 						}
       
   802 					else
       
   803 						{
       
   804 						res = KErrArgument;
       
   805 						}
       
   806 					}
       
   807 				break;
       
   808 				}	
       
   809 			default:
       
   810 				{
       
   811 				res = KErrNotSupported;
       
   812 				}
       
   813 			}
       
   814 		if (res!=KErrNone)
       
   815 			{
       
   816 			iSAP.Error(res);
       
   817 			}
       
   818 		}
       
   819 	}
       
   820 	
       
   821 #ifdef _DEBUG	
       
   822 void CSignallingSession::CancelIoctl(TUint aLevel, TUint /*aName*/)
       
   823 #else
       
   824 void CSignallingSession::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/)
       
   825 #endif
       
   826 	{
       
   827 	LOG_FUNC
       
   828 	__ASSERT_DEBUG(aLevel==KSolBtAVDTPSignalling, Panic(EAvdtpBadIoctl));
       
   829 	// none at present	
       
   830 	}
       
   831 	
       
   832 	
       
   833 TInt CSignallingSession::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
       
   834 	{
       
   835 	LOG_FUNC
       
   836 	TInt ret = KErrNotSupported;
       
   837 	
       
   838 	if (aLevel == KSolBtAVDTPSignalling)
       
   839 		{
       
   840 		switch (aName)
       
   841 			{
       
   842 			case EGetProposedConfiguration:
       
   843 				{
       
   844 				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
       
   845 				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetProposedConfiguration))
       
   846 					{
       
   847 					ret = KErrBadDescriptor;
       
   848 					}
       
   849 				else
       
   850 					{
       
   851 					TInternalGetProposedConfiguration& conf = *const_cast<TInternalGetProposedConfiguration*>(reinterpret_cast<const TInternalGetProposedConfiguration*>(aOption.Ptr()));
       
   852 					CLocalSEP* s = FindLocalSEP(conf.iSEID);
       
   853 					if (s)
       
   854 						{
       
   855 						// Check that the option buffer size is sufficient
       
   856 						TPtrC8 pendingConf(s->PendingConfiguration());
       
   857 						if (aOption.MaxLength() < pendingConf.Length())
       
   858 							{
       
   859 							ret = KErrUnderflow;
       
   860 							}
       
   861 						else
       
   862 							{
       
   863 							// would be nice to use a return struct
       
   864 							// but gets tricky - we don't know how big the option is
       
   865 							// so can't use TBuf. TPtr falls foul of IPC.
       
   866 							aOption.Copy(pendingConf);
       
   867 							ret = KErrNone;
       
   868 							}
       
   869 						}
       
   870 					else
       
   871 						{
       
   872 						ret = KErrArgument;
       
   873 						}
       
   874 					}
       
   875 				break;
       
   876 				}
       
   877 			
       
   878 			case EGetSecurityControl:
       
   879 				{
       
   880 				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
       
   881 				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetSecurityControl))
       
   882 					{
       
   883 					ret = KErrBadDescriptor;
       
   884 					}
       
   885 				else
       
   886 					{
       
   887 					TInternalGetSecurityControl& sec = *const_cast<TInternalGetSecurityControl*>(reinterpret_cast<const TInternalGetSecurityControl*>(aOption.Ptr()));
       
   888 					CLocalSEP* s = FindLocalSEP(sec.iSEID);
       
   889 					if (s)
       
   890 						{
       
   891 						// Check that the option buffer size is sufficient
       
   892 						TPtrC8 securityData(s->SecurityControl());
       
   893 						if (aOption.MaxLength() < securityData.Length())
       
   894 							{
       
   895 							ret = KErrUnderflow;
       
   896 							}
       
   897 						else
       
   898 							{
       
   899 							aOption.Copy(securityData);
       
   900 							ret = KErrNone;
       
   901 							}
       
   902 						}
       
   903 					else
       
   904 						{
       
   905 						ret = KErrArgument;
       
   906 						}				
       
   907 					}
       
   908 				break;
       
   909 				}
       
   910 			case EGetAVDTPCapabilityResponse:
       
   911 				{
       
   912 				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
       
   913 				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetSEPCapability))
       
   914 					{
       
   915 					ret = KErrBadDescriptor;
       
   916 					}
       
   917 				else
       
   918 					{
       
   919 					TInternalGetSEPCapability cap = *reinterpret_cast<const TInternalGetSEPCapability*>(aOption.Ptr());
       
   920 					TPtrC8 ptr;
       
   921 					// get the required capability from the SEP cache (in 'air' form)
       
   922 					TRAP(ret, ptr.Set(iProtocol.RemoteSEPCache().GetCapabilityL(
       
   923 															RemoteAddress(),
       
   924 															cap.iSEID,
       
   925 															cap.iServiceCategory));)
       
   926 															
       
   927 					if (ret==KErrNone)
       
   928 						{
       
   929 						// Check that the option buffer size is sufficient
       
   930 						if (aOption.MaxLength() < ptr.Length())
       
   931 							{
       
   932 							ret = KErrUnderflow;
       
   933 							}
       
   934 						else
       
   935 							{
       
   936 							aOption.Copy(ptr);
       
   937 							}
       
   938 						}
       
   939 					}
       
   940 				break;
       
   941 				}
       
   942 				
       
   943 			case ERegisterSEP:
       
   944 				{
       
   945 				// Check the integrity of the descriptor
       
   946 				if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpSEPInfo))
       
   947 					{
       
   948 					ret = KErrBadDescriptor;
       
   949 					}
       
   950 				else
       
   951 					{
       
   952 					TAvdtpSEPInfo info = *reinterpret_cast<const TAvdtpSEPInfo*>(aOption.Ptr());
       
   953 					// client doesn't manage inUse field - we do
       
   954 					info.SetInUse(EFalse);
       
   955 					
       
   956 					TRAP(ret, const_cast<CSignallingSession*>(this)->CreateLocalSEPL(info));
       
   957 					
       
   958 					TPckg<TAvdtpSEPInfo> pckg(info);
       
   959 					aOption.Copy(pckg);
       
   960 					}
       
   961 				break;
       
   962 				}
       
   963 				
       
   964 			case EGetReportingAndRecoveryConfig:
       
   965 				{
       
   966 				// Check the integrity of the descriptor
       
   967 				if (!aOption.Ptr() || aOption.Length() != sizeof(TReportingAndRecovery))
       
   968 					{
       
   969 					ret = KErrBadDescriptor;
       
   970 					}
       
   971 				else
       
   972 					{
       
   973 					TReportingAndRecovery rar;
       
   974 					TPckg<TReportingAndRecovery> rarBuf(rar);
       
   975 					rarBuf.Copy(aOption);
       
   976 					CAVStream* stream = FindStreamFromRemoteSEID(rar.iSEID);
       
   977 					if(stream == NULL)
       
   978 						{
       
   979 						ret = KErrNotFound;
       
   980 						}
       
   981 					else
       
   982 						{
       
   983 						rar.iReporting = stream->CheckConfigured(EServiceCategoryReporting);
       
   984 						rar.iRecovery  = stream->CheckConfigured(EServiceCategoryRecovery);
       
   985 						aOption.Copy(rarBuf);
       
   986 						ret = KErrNone;
       
   987 						}
       
   988 					}
       
   989 				break;
       
   990 				}
       
   991 			}
       
   992 		}
       
   993 		
       
   994 	return ret;
       
   995 	}
       
   996 	
       
   997 
       
   998 
       
   999 TInt CSignallingSession::OpenIndication(TSEID aSEID)
       
  1000 	{
       
  1001 	LOG_FUNC
       
  1002 	// now create the full Stream Object
       
  1003 	CLocalSEP* sep = FindLocalSEP(aSEID);
       
  1004 	if (sep && sep->Stream())
       
  1005 		{
       
  1006 		// this will tell channel factory to expect n channels on sending resp
       
  1007 		TRAPD(err, sep->Stream()->AwaitLogicalChannelsL());
       
  1008 		return err;
       
  1009 		}
       
  1010 	else if (sep && !sep->Stream())
       
  1011 		{
       
  1012 		// the remote must have decided that a GetConfig yielded just what they wanted
       
  1013 		// and have proceeded directly with Open
       
  1014 		// this *violates* GAVDP - see p 16
       
  1015 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1016 		}
       
  1017 	else
       
  1018 		{
       
  1019 		return KErrNotFound;
       
  1020 		}
       
  1021 	}
       
  1022 	
       
  1023 	
       
  1024 TInt CSignallingSession::DiscoverIndication(TAvdtpTransactionLabel /*aLabel*/, CAvdtpOutboundSignallingMessage& aDiscoverResponseMessage)
       
  1025 	{
       
  1026 	LOG_FUNC
       
  1027 	// iterate over all idle SEPs returning their capabilities
       
  1028 	// need to return the label back to the Signalling Channel to tie up response
       
  1029 
       
  1030 	// this is *far* easier if we process this synchronously
       
  1031 	// otherwise the design is tricky - we'd need to call a primitive bacxk on SigCh
       
  1032 	// and it would need to know our last SEP info etc
       
  1033 	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
  1034 	CLocalSEP* sep;
       
  1035 	while(iter)
       
  1036 		{
       
  1037 		sep = iter++;
       
  1038 		
       
  1039 		TRAPD(overFlow, aDiscoverResponseMessage.AddSEPInfoL(sep->Info()));
       
  1040 
       
  1041 		if (overFlow)
       
  1042 			{
       
  1043 			// no more will go, try continuing with usecase though
       
  1044 			// so NOT releaving - cos the message is ok
       
  1045 			break;
       
  1046 			}			
       
  1047 		}
       
  1048 	return KErrNone;
       
  1049 	}
       
  1050 	
       
  1051 
       
  1052 TInt CSignallingSession::GetCapsIndication(TAvdtpTransactionLabel /*aLabel*/,
       
  1053 										   TSEID aSEID,
       
  1054 										   CAvdtpOutboundSignallingMessage& aGetCapsResponseMessage)
       
  1055 	{
       
  1056 	LOG_FUNC
       
  1057 	// client has set caps now - if they haven't then we will prob just send empty stuff back
       
  1058 	// i.e. we send whatever we've got (but possibly "knowing" this fact
       
  1059 	
       
  1060 	// find the idle SEP with aSEID
       
  1061 	CLocalSEP* sep = FindLocalSEP(aSEID);
       
  1062 	// this uses the same pattern as :DiscoverIndication
       
  1063 	if (!sep)
       
  1064 		{
       
  1065 		return KErrNotFound;
       
  1066 		}
       
  1067 	
       
  1068 	TInt ret = KErrNone;
       
  1069 	
       
  1070 	for (TInt i=0; i<sep->Capabilities().Count(); i++)
       
  1071 		{
       
  1072 		// one at a time - easier for us to cope if we OOM
       
  1073 		if (sep->Capabilities()[i])
       
  1074 			{
       
  1075 			// local sep has capability
       
  1076 			TRAPD(overFlow, aGetCapsResponseMessage.AddSEPCapabilityL(*sep->Capabilities()[i]));
       
  1077 			if (overFlow)
       
  1078 				{
       
  1079 				// no more will go
       
  1080 				// if even the first capability didn't go then we have to forget replying
       
  1081 				if (i==0)
       
  1082 					{
       
  1083 					// there are no caps in the response, so it's meaningless
       
  1084 					ret = KErrUnderflow;		
       
  1085 					}
       
  1086 				// otherwise we can try continuing with usecase though
       
  1087 				// so NOT erroring - cos the message is ok
       
  1088 				break;
       
  1089 				}			
       
  1090 			}
       
  1091 		
       
  1092 		}
       
  1093 	return ret;
       
  1094 	}
       
  1095 
       
  1096 TInt CSignallingSession::SetConfigIndication(TAvdtpTransactionLabel aLabel,
       
  1097 											  TSEID aACPSEID,
       
  1098 											  TSEID aINTSEID,
       
  1099 											  RBuf8& aConfig)
       
  1100 	{
       
  1101 	LOG_FUNC
       
  1102 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1103 	
       
  1104 	if (!sep)
       
  1105 		{
       
  1106 		// for a SEP not on this session
       
  1107 		return KErrNotFound;
       
  1108 		}
       
  1109 
       
  1110 /*
       
  1111 we check to see if the remote has (wrongly) set capabilities that the idle sep has not
       
  1112 if the remote has then we reject the request
       
  1113 else pass onto gavdp
       
  1114 */
       
  1115 	
       
  1116 	CCapabilityNotAllowedVisitor* checker =
       
  1117 				new CCapabilityNotAllowedVisitor(sep->Categories());
       
  1118 	
       
  1119 	if (!checker)
       
  1120 		{
       
  1121 		return KErrNoMemory;
       
  1122 		}
       
  1123 
       
  1124 	checker->Process(aConfig);
       
  1125 	
       
  1126 	if (!checker->IsValid())
       
  1127 		{
       
  1128 		// signalling channel expects us to put the duff category in the aConfig
       
  1129 		// take the first one (as suggested by spec)
       
  1130 		TPckgBuf<TAvdtpServiceCategory> catBuf(checker->WrongCategory());
       
  1131 		aConfig.Copy(catBuf);
       
  1132 		delete checker;
       
  1133 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadServCategory);
       
  1134 		}
       
  1135 
       
  1136 	delete checker;
       
  1137 	checker = NULL;
       
  1138 	
       
  1139 	// update the SEP to contain the pending configuration
       
  1140 	// commited when gavdp says ok
       
  1141 	TInt res = sep->SetPendingConfiguration(aConfig, EFalse); // transfers aConfig ownership
       
  1142 	if (res==KErrNone)
       
  1143 		{
       
  1144 		sep->SetRemoteSEID(aINTSEID);
       
  1145 
       
  1146 		// all ok, so pass on an indication to GAVDP as they need to configure too
       
  1147 		TInternalAvdtpConfigurationIndication ind;
       
  1148 		ind.iIndication = EAvdtpSetConfiguration;
       
  1149 		ind.iPayloadLength = aConfig.Length();
       
  1150 		ind.iSEID = aACPSEID;
       
  1151 		ind.iINTSEID = aINTSEID;
       
  1152 		ind.iTransactionLabel = aLabel;
       
  1153 
       
  1154 		TPckg<TInternalAvdtpConfigurationIndication> indPckg(ind);
       
  1155 		iSAP.Indication(indPckg);
       
  1156 		}
       
  1157 
       
  1158 	return res;
       
  1159 	}
       
  1160 	
       
  1161 TInt CSignallingSession::GetConfigIndication(TAvdtpTransactionLabel /*aLabel*/, TSEID aLocalSEID,
       
  1162 									CAvdtpOutboundSignallingMessage& aGetConfigResponseMessage)
       
  1163 	{
       
  1164 	LOG_FUNC
       
  1165 	CLocalSEP* sep = FindLocalSEP(aLocalSEID);
       
  1166 	
       
  1167 	if (!sep)
       
  1168 		{
       
  1169 		return KErrNotFound;
       
  1170 		}
       
  1171 
       
  1172 	// remote may not have sent SetConfiguration
       
  1173 	if (sep->PreConfigured())
       
  1174 		{
       
  1175 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1176 		}
       
  1177 		
       
  1178 	TInt ret = KErrNone;
       
  1179 	
       
  1180 	for (TInt i=0; i<sep->Configuration().Count(); i++)
       
  1181 		{
       
  1182 		// one at a time - easier for us to cope if we OOM
       
  1183 		if (sep->Configuration()[i])
       
  1184 			{
       
  1185 			// local sep has capability
       
  1186 			TRAPD(overFlow, aGetConfigResponseMessage.AddSEPCapabilityL(*sep->Configuration()[i]));
       
  1187 			if (overFlow)
       
  1188 				{
       
  1189 				// no more will go
       
  1190 				// if even the first capability didn't go then we have to forget replying
       
  1191 				if (i==0)
       
  1192 					{
       
  1193 					// there are no caps in the response, so it's meaningless
       
  1194 					ret = KErrUnderflow;		
       
  1195 					}
       
  1196 				// otherwise we can try continuing with usecase though
       
  1197 				// so NOT erroring - cos the message is ok
       
  1198 				break;
       
  1199 				}	
       
  1200 			}
       
  1201 		}
       
  1202 
       
  1203 	return ret;			
       
  1204 	}
       
  1205 	
       
  1206 TInt CSignallingSession::ReconfigIndication(TAvdtpTransactionLabel aLabel,
       
  1207 															TSEID aACPSEID,
       
  1208 															RBuf8& aNewConfig)
       
  1209 	{
       
  1210 	LOG_FUNC
       
  1211 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1212 	
       
  1213 	if (!sep)
       
  1214 		{
       
  1215 		// for a SEP not on this session
       
  1216 		return KErrNotFound;
       
  1217 		}
       
  1218 		
       
  1219 	if (!sep->Stream())
       
  1220 		{
       
  1221 		// remote has been bad
       
  1222 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1223 		}
       
  1224 
       
  1225 /*
       
  1226 we check to see if the remote has (wrongly) set capabilities that the spec forbids
       
  1227 see 8.10.1 avdtp sepc
       
  1228 if the remote has then we reject the request
       
  1229 else pass onto gavdp
       
  1230 */
       
  1231 	TAvdtpServiceCategories allowed;
       
  1232 	allowed.SetCapability(EServiceCategoryMediaCodec);
       
  1233 	allowed.SetCapability(EServiceCategoryContentProtection);
       
  1234 
       
  1235 	CCapabilityNotAllowedVisitor* checker = new CCapabilityNotAllowedVisitor(allowed);
       
  1236 	
       
  1237 	if (!checker)
       
  1238 		{
       
  1239 		return KErrNoMemory;
       
  1240 		}
       
  1241 
       
  1242 	checker->Process(aNewConfig);
       
  1243 		
       
  1244 	if (!checker->IsValid())
       
  1245 		{
       
  1246 		// signalling channel expects us to put the duff category in the aConfig
       
  1247 		// take the first one (as suggested by spec)
       
  1248 		TPckg<TUint8> catBuf(checker->WrongCategory());
       
  1249 		aNewConfig.Copy(catBuf);
       
  1250 		delete checker;
       
  1251 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpInvalidCapabilities);
       
  1252 		}
       
  1253 
       
  1254 	delete checker;
       
  1255 	checker = NULL;
       
  1256 
       
  1257 //take ownership of config buffer
       
  1258 	TInt res = sep->SetPendingConfiguration(aNewConfig, ETrue);	
       
  1259 	
       
  1260 	if (res==KErrNone)
       
  1261 		{
       
  1262 		// all ok, so pass on an indication to GAVDP as they need to reconfigure too
       
  1263 		TInternalAvdtpConfigurationIndication ind;
       
  1264 		ind.iIndication = EAvdtpReconfigure;
       
  1265 		ind.iPayloadLength = aNewConfig.Length();
       
  1266 		ind.iSEID = aACPSEID;
       
  1267 		// to give consistent API for Set and Re-configure , give the INT SEID again
       
  1268 		ind.iINTSEID = sep->Stream()->RemoteSEID();
       
  1269 
       
  1270 		ind.iTransactionLabel = aLabel;
       
  1271 
       
  1272 		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1273 		iSAP.Indication(indPckg);
       
  1274 		}
       
  1275 	
       
  1276 	return res;
       
  1277 	}
       
  1278 
       
  1279 /** Handle a Start Indication from remote.
       
  1280 
       
  1281 The decision about when to issue the start indication to the client is taken by
       
  1282 the stream.
       
  1283 
       
  1284 @param aLabel The transaction label of the start command.
       
  1285 @param aACPSEID The (local) seid referring to the stream to be started.
       
  1286 */
       
  1287 TInt CSignallingSession::StartIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
       
  1288 	{
       
  1289 	LOG_FUNC
       
  1290 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1291 	
       
  1292 	if (!sep)
       
  1293 		{
       
  1294 		// for a SEP not on this session
       
  1295 		return KErrNotFound;
       
  1296 		}
       
  1297 
       
  1298 	TInt err = KErrUnknown;
       
  1299 	if (sep->Stream())
       
  1300 		{
       
  1301 		// If the stream is in a valid state it will call back to the sig session
       
  1302 		// to cause the indication to be passed to the client.
       
  1303 		err = sep->Stream()->StartIndication(aLabel, aACPSEID);
       
  1304 		}
       
  1305 
       
  1306 	if(err == KErrNone)	
       
  1307 		{
       
  1308 		return KErrNone;
       
  1309 		}
       
  1310 	else
       
  1311 		{
       
  1312 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1313 		}
       
  1314 	}
       
  1315 		
       
  1316 TInt CSignallingSession::ReleaseIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
       
  1317 	{
       
  1318 	LOG_FUNC
       
  1319 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1320 	
       
  1321 	if (!sep)
       
  1322 		{
       
  1323 		// for a SEP not on this session
       
  1324 		return KErrNotFound;
       
  1325 		}
       
  1326 		
       
  1327 	if (sep->Stream())
       
  1328 		{
       
  1329 		// dont ask GAVDP to confirm
       
  1330 		// we also know that if we have a stream it must be releaseable
       
  1331 		(void)iSignallingChannel->SendReleaseAccept(aLabel);
       
  1332 
       
  1333 		sep->SetInUse(EFalse);
       
  1334 
       
  1335 		// We try and hand off the channels to be closed.  This is because it is
       
  1336 		// the responsibility of the INT to release these so we can't just 
       
  1337 		// shut them down straight away.  We don't want to have to deal with the 
       
  1338 		// complication of funny stream states and clearup by leaving them with the
       
  1339 		// stream once it's effectively dead.  If it fails however, we just let the 
       
  1340 		// channels go away.
       
  1341 		// This is only done for non-muxed streams, otherwise we just revert to 
       
  1342 		// closing the channels ourselves.  
       
  1343 #ifndef __SYMBIAN_AVDTP_HIDE_MUX
       
  1344 #warning ("Release ACP channel release must be fixed for muxed case")
       
  1345 #endif
       
  1346 		if(!sep->MultiplexingConfigured())
       
  1347 			{
       
  1348 			// Take the channels from the stream to disconnect
       
  1349 			// Note that although some of these may be the same CloseLogicalChannels will
       
  1350 			// deal with correctly closing each channel once.
       
  1351 			TFixedArray<CDirectChannel*, KAvdtpChannelArraySize> channels;
       
  1352 			channels[0] = static_cast<CDirectChannel*>(sep->Stream()->iMediaBinding.iChannel);
       
  1353 			channels[1] = static_cast<CDirectChannel*>(sep->Stream()->iReportingBinding.iChannel);
       
  1354 			channels[2] = static_cast<CDirectChannel*>(sep->Stream()->iRecoveryBinding.iChannel);
       
  1355 			TArray<CDirectChannel*> array = channels.Array();
       
  1356 
       
  1357 			TRAP_IGNORE(iProtocol.LogicalChannelFactory().CloseSessionLogicalChannelsL(array, KAvdtpACPReleaseChannelCloseTimeout));	
       
  1358 			}
       
  1359 
       
  1360 		// just error the stream - it will tell the user-plane sessions
       
  1361 		// they'll then tell the user
       
  1362 		// so , like open, we don't let user directly see this as an indication
       
  1363 		DestroyStream(sep->Stream(), KErrDisconnected);
       
  1364 		
       
  1365 		// all ok, so pass on an indication to GAVDP
       
  1366 		TInternalAvdtpAirIndication ind;
       
  1367 		ind.iIndication = EAvdtpRelease;
       
  1368 		ind.iPayloadLength = 0;
       
  1369 		ind.iSEID = aACPSEID;
       
  1370 		ind.iTransactionLabel = aLabel; // not used 
       
  1371 
       
  1372 		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1373 		iSAP.Indication(indPckg);
       
  1374 		
       
  1375 		return KErrNone;
       
  1376 		}
       
  1377 	else
       
  1378 		{
       
  1379 		// remote is in bad state
       
  1380 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1381 		}
       
  1382 	}
       
  1383 	
       
  1384 TInt CSignallingSession::SuspendIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
       
  1385 	{
       
  1386 	LOG_FUNC
       
  1387 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1388 	
       
  1389 	if (!sep)
       
  1390 		{
       
  1391 		// for a SEP not on this session
       
  1392 		return KErrNotFound;
       
  1393 		}
       
  1394 		
       
  1395 	// check that we think stream suspendable
       
  1396 	if (sep->Stream() && sep->Stream()->IsStreaming())
       
  1397 		{
       
  1398 		// all ok, so pass on an indication to GAVDP
       
  1399 		TInternalAvdtpAirIndication ind;
       
  1400 		ind.iIndication = EAvdtpSuspend;
       
  1401 		ind.iPayloadLength = 0;
       
  1402 		ind.iSEID = aACPSEID;
       
  1403 		ind.iTransactionLabel = aLabel;
       
  1404 
       
  1405 		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1406 		iSAP.Indication(indPckg);
       
  1407 		return KErrNone;
       
  1408 		}
       
  1409 	else
       
  1410 		{
       
  1411 		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
       
  1412 		}
       
  1413 	}
       
  1414 
       
  1415 TInt CSignallingSession::AbortIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
       
  1416 	{
       
  1417 	LOG_FUNC
       
  1418 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1419 	
       
  1420 	if (!sep)
       
  1421 		{
       
  1422 		// for a SEP not on this session
       
  1423 		return KErrNotFound;
       
  1424 		}
       
  1425 	else
       
  1426 		{
       
  1427 		// tell the sep, stream, then the user (only if we have a stream though)
       
  1428 		sep->SetInUse(EFalse);
       
  1429 		
       
  1430 		if (sep->Stream())
       
  1431 			{			
       
  1432 			DestroyStream(sep->Stream(),KErrAbort);		
       
  1433 			}
       
  1434 		// Pass on an indication to GAVDP as they need to know too
       
  1435 		TInternalAvdtpAirIndication ind;
       
  1436 		ind.iIndication = EAvdtpAbort;
       
  1437 		ind.iSEID = aACPSEID;
       
  1438 		ind.iTransactionLabel = aLabel; // not that useful, client cant respond
       
  1439 
       
  1440 		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1441 		iSAP.Indication(indPckg);			
       
  1442 		}
       
  1443 	return KErrNone;			
       
  1444 	}
       
  1445 	
       
  1446 void CSignallingSession::AbortConfirm(TSEID aRemoteSEID)
       
  1447 	{
       
  1448 	LOG_FUNC
       
  1449 	// tell client
       
  1450 	CompleteBasicService(KErrNone);
       
  1451 
       
  1452 	// error stream associated with remote
       
  1453 	CAVStream* stream = FindStreamFromRemoteSEID(aRemoteSEID);
       
  1454 	if (stream)
       
  1455 		{
       
  1456 		DestroyStream(stream, KErrAbort);
       
  1457 		}
       
  1458 	}
       
  1459 	
       
  1460 TInt CSignallingSession::SecurityControlIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID, const HBufC8* aSecurityData)
       
  1461 	{
       
  1462 	LOG_FUNC
       
  1463 	CLocalSEP* sep = FindLocalSEP(aACPSEID);
       
  1464 	
       
  1465 	if (!sep)
       
  1466 		{
       
  1467 		// for a SEP not on this session
       
  1468 		return KErrNotFound;
       
  1469 		}
       
  1470 	else
       
  1471 		{
       
  1472 		// pass ownership of HBuf to SEP
       
  1473 		sep->SetSecurityControl(aSecurityData);
       
  1474 				
       
  1475 		// all ok, so pass on an indication to GAVDP as they need to do the actual security control response
       
  1476 		TInternalAvdtpAirIndication ind;
       
  1477 		ind.iIndication = EAvdtpSecurityControl;
       
  1478 		ind.iSEID = aACPSEID;
       
  1479 		ind.iPayloadLength = aSecurityData->Length();
       
  1480 		ind.iTransactionLabel = aLabel;
       
  1481 
       
  1482 		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1483 		iSAP.Indication(indPckg);
       
  1484 		
       
  1485 		return KErrNone;			
       
  1486 		}
       
  1487 	}
       
  1488 
       
  1489 void CSignallingSession::SecurityControlConfirm(TInt aResult, TSEID aRemoteSEID, const TDesC8& aResponseData)
       
  1490  	{
       
  1491 	LOG_FUNC
       
  1492  	if (aResult==KErrNone)
       
  1493  		{
       
  1494  		TPckgBuf<TAvdtpInternalSendSecurityControl> securityControlPckgBuf;
       
  1495  		securityControlPckgBuf().iRemoteSEID = aRemoteSEID;
       
  1496  		securityControlPckgBuf().iSecurityControlInfo = aResponseData;
       
  1497 		iSAP.ServiceComplete(&securityControlPckgBuf);
       
  1498  		}
       
  1499  	else
       
  1500  		{
       
  1501  		iSAP.Error(aResult);
       
  1502  		}
       
  1503  	}
       
  1504 
       
  1505 
       
  1506 void CSignallingSession::DiscoverConfirm(TInt aResult, const TAvdtpInternalDiscoverConfirm* const aConfirm)
       
  1507 	{
       
  1508 	LOG_FUNC
       
  1509 	if (aResult==KErrNone)
       
  1510 		{
       
  1511 		__ASSERT_DEBUG(aConfirm, Panic(EAvdtpSignallingSessionReceivedBadIndication));
       
  1512 		//complete the client request with the number of SEPs
       
  1513 		TPckgBuf<TAvdtpInternalDiscoverConfirm> buf(*aConfirm);
       
  1514 		iSAP.ServiceComplete(&buf);
       
  1515 		}
       
  1516 	else
       
  1517 		{
       
  1518 		//either we were rejected by the peer or there was an internal
       
  1519 		//error in the signalling channel
       
  1520 		iSAP.Error(aResult);
       
  1521 		}
       
  1522 	}
       
  1523 
       
  1524 
       
  1525 void CSignallingSession::GetCapsConfirm(TInt aResult, TSEID /*aRemoteSEID*/, TAvdtpServiceCatBitMask aSeen)
       
  1526 	{
       
  1527 	LOG_FUNC
       
  1528 	if (aResult==KErrNone)
       
  1529 		{
       
  1530 		TPckgC<TAvdtpServiceCatBitMask> buf(aSeen);
       
  1531 		iSAP.ServiceComplete(&buf);
       
  1532 		}
       
  1533 	else
       
  1534 		{
       
  1535 		iSAP.Error(aResult);
       
  1536 		}
       
  1537 	}
       
  1538 
       
  1539 void CSignallingSession::StreamStarted(TSEID aLocalSEID)
       
  1540 	{
       
  1541 	LOG_FUNC
       
  1542 	if (FindLocalSEP(aLocalSEID))
       
  1543 		{
       
  1544 		// now tell client
       
  1545 		CompleteBasicService(KErrNone);
       
  1546 		}
       
  1547 	}
       
  1548 
       
  1549 void CSignallingSession::StreamSuspended(TSEID aLocalSEID)
       
  1550 	{
       
  1551 	LOG_FUNC
       
  1552 	if (FindLocalSEP(aLocalSEID))
       
  1553 		{
       
  1554 		// now tell client
       
  1555 		CompleteBasicService(KErrNone);
       
  1556 		}
       
  1557 	}
       
  1558 	
       
  1559 void CSignallingSession::StreamAccepted(TSEID aLocalSEID, TSEID aRemoteSEID, TBool aWithReporting, TBool aWithRecovery)
       
  1560  	{
       
  1561 	LOG_FUNC
       
  1562  	__ASSERT_DEBUG(aLocalSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
       
  1563 	TInternalAvdtpStreamReadyIndication ind;
       
  1564 	ind.iSEID = aLocalSEID;
       
  1565 	ind.iRemoteSEID = aRemoteSEID;
       
  1566 	ind.iReportingPresent = aWithReporting;
       
  1567 	ind.iRecoveryPresent = aWithRecovery;
       
  1568  	TPckg<TInternalAvdtpStreamReadyIndication> indPckg(ind);
       
  1569  	iSAP.Indication(indPckg);
       
  1570  	}
       
  1571  	
       
  1572 void CSignallingSession::StreamConfigured(TSEID /*aLocalSEID*/, TInt aResult, TAvdtpServiceCategory aFailedCategory)
       
  1573 	{
       
  1574 	LOG_FUNC
       
  1575 	// tell the user in all cases
       
  1576 	TPckgBuf<TAvdtpConfigReject> rejDataBuf;
       
  1577 	rejDataBuf().iError = aResult;
       
  1578 	rejDataBuf().iFailedCategory = aFailedCategory;
       
  1579 	
       
  1580 	// GAVDP will call back to client with Error upcall, so no need to error SAP
       
  1581 	iSAP.ServiceComplete(&rejDataBuf);
       
  1582 	}
       
  1583 
       
  1584 /*
       
  1585 This callback is for the stream to inform gavdp of a failure in its state machine
       
  1586 The signalling session SHALL NOT mutate the stream based on this; the stream should
       
  1587 proceed, or die, or error in line with its present state and potential GAVDP recovery of that stream
       
  1588 */
       
  1589 void CSignallingSession::StreamInitiatedServiceFailed(const CAVStream& /*aStream*/, TInt aError)
       
  1590 	{
       
  1591 	LOG_FUNC
       
  1592 	ServiceError(aError);
       
  1593 	}
       
  1594 
       
  1595 /** 
       
  1596 This should be called from the stream when it is ready for a start indication
       
  1597 to be passed up to the client. 
       
  1598 */	
       
  1599 void CSignallingSession::StreamReadyForStartIndication(const TAvdtpTransactionLabel aLabel, const TSEID aSeid)
       
  1600 	{
       
  1601 	LOG_FUNC
       
  1602 			
       
  1603 	// pass on an indication to GAVDP
       
  1604 	TInternalAvdtpAirIndication ind;
       
  1605 	ind.iIndication = EAvdtpStart;
       
  1606 	ind.iPayloadLength = 0;
       
  1607 	ind.iSEID = aSeid;
       
  1608 	ind.iTransactionLabel = aLabel;
       
  1609 
       
  1610 	TPckg<TInternalAvdtpAirIndication> indPckg(ind);
       
  1611 
       
  1612 	iSAP.Indication(indPckg);
       
  1613 	}
       
  1614 	
       
  1615 TInt CSignallingSession::SendAbort(TSEID aRemoteSEID)
       
  1616 	{
       
  1617 	LOG_FUNC
       
  1618 	return iSignallingChannel ? iSignallingChannel->SendAbort(*this, aRemoteSEID) : KErrNotReady;
       
  1619 	}
       
  1620 	
       
  1621 /*inline*/void CSignallingSession::CompleteBasicService(TInt aErr)
       
  1622 	{
       
  1623 	LOG_FUNC
       
  1624 	// basic services have no data to return
       
  1625 	aErr ? iSAP.Error(aErr) : iSAP.ServiceComplete(NULL);
       
  1626 	}
       
  1627 	
       
  1628 	
       
  1629 /**
       
  1630 Called as an INT - create the Stream object when we're setting configuration
       
  1631 */
       
  1632 void CSignallingSession::DoConfigureStreamL(RBuf8& aConfigBuffer,
       
  1633 												CLocalSEP& aLocalSEP,
       
  1634 												TSEID aRemoteSEID,
       
  1635 												TBool aReportingConfigured,
       
  1636 												TBool aRecoveryConfigured)
       
  1637 	{
       
  1638 	LOG_FUNC
       
  1639 	
       
  1640 	// check to see if SignallingChannel went down during configuration
       
  1641 	if (iSignallingChannel)
       
  1642 		{
       
  1643 		TBool streamCreated = EFalse;
       
  1644 		
       
  1645 		// if there is no stream then we create one now
       
  1646 		// a stream would exist if this is a reconfigure
       
  1647 		CAVStream* stream = FindStreamFromRemoteSEID(aRemoteSEID);
       
  1648 		if (!stream)
       
  1649 			{
       
  1650 			TAvdtpSockAddr addr;
       
  1651 			addr.SetBTAddr(RemoteAddress());
       
  1652 			addr.SetSEID(aRemoteSEID);
       
  1653 			stream = &aLocalSEP.CreateStreamL(addr, *this, iProtocol);
       
  1654 		
       
  1655 			streamCreated = ETrue;
       
  1656 			CleanupStack::PushL(stream);
       
  1657 			}
       
  1658 		else
       
  1659 			{
       
  1660 			__ASSERT_DEBUG(stream->RemoteSEID()==aRemoteSEID, Panic(EAvdtpSignallingSessionFoundWrongStream));
       
  1661 			}
       
  1662 
       
  1663 		stream->SetConfigurationL(aConfigBuffer, *iSignallingChannel,
       
  1664 									aReportingConfigured, aRecoveryConfigured);
       
  1665 									
       
  1666 		if (streamCreated)
       
  1667 			{
       
  1668 			// SetConfigurationL ok, pop stream if we created one
       
  1669 			CleanupStack::Pop();
       
  1670 			}
       
  1671 		}
       
  1672 	else
       
  1673 		{
       
  1674 		User::Leave(KErrDisconnected);
       
  1675 		}
       
  1676 	}
       
  1677 
       
  1678 
       
  1679 void CSignallingSession::CreateLocalSEPL(TAvdtpSEPInfo& aSEPInfo)
       
  1680 	{
       
  1681 	LOG_FUNC
       
  1682 	// create an idle sep into queue for later discovery and selection
       
  1683 	CLocalSEP* idleSEP = CLocalSEP::NewL(aSEPInfo, iProtocol.SEIDManager());
       
  1684 	iLocalSEPs.AddFirst(*idleSEP);
       
  1685 	// return the SEID to GAVDP via the reference paramter
       
  1686 	
       
  1687 	// adjust the service class of CoD, using reference counting of codman
       
  1688 	iProtocol.CodMan().RegisterCodService(aSEPInfo.IsSink() ? EMajorServiceRendering :
       
  1689 															   EMajorServiceCapturing);
       
  1690 	}
       
  1691 
       
  1692 CLocalSEP* CSignallingSession::FindLocalSEP(TSEID aSEID) const
       
  1693 	{
       
  1694 	LOG_FUNC
       
  1695 	__ASSERT_DEBUG(aSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
       
  1696 	CLocalSEP* s = NULL;
       
  1697 	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
  1698 	
       
  1699 	while (iter)
       
  1700 		{
       
  1701 		s = iter++;
       
  1702 		if (s->SEID()==aSEID)
       
  1703 			{			
       
  1704 			return s;
       
  1705 			}
       
  1706 		}
       
  1707 	return NULL;
       
  1708 	}
       
  1709 	
       
  1710 	
       
  1711 CLocalSEP& CSignallingSession::FindLocalSEPL(TSEID aSEID) const
       
  1712 	{
       
  1713 	LOG_FUNC
       
  1714 	CLocalSEP* sep = FindLocalSEP(aSEID);
       
  1715 	if (!sep)
       
  1716 		{
       
  1717 		User::Leave(KErrNotFound);
       
  1718 		}
       
  1719 	return *sep;
       
  1720 	}
       
  1721 
       
  1722 CAVStream* CSignallingSession::FindStreamFromRemoteSEID(const TSEID& aRemoteSEID) const
       
  1723 	{
       
  1724 	LOG_FUNC
       
  1725 	__ASSERT_DEBUG(!aRemoteSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
       
  1726 	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
  1727 	
       
  1728 	while (iter)
       
  1729 		{
       
  1730 		CAVStream* s = iter++->Stream();
       
  1731 		if (s && s->RemoteSEID()==aRemoteSEID)
       
  1732 			{			
       
  1733 			return s;
       
  1734 			}
       
  1735 		}
       
  1736 	return NULL;
       
  1737 	}
       
  1738 
       
  1739 void CSignallingSession::SignallingChannelError(TInt aError)
       
  1740 	{
       
  1741 	LOG_FUNC
       
  1742 	// set all SEPs to be not in use
       
  1743 	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
       
  1744 	while(iter)
       
  1745 		{
       
  1746 		CLocalSEP* sep = iter++;
       
  1747 			
       
  1748 		sep->SetInUse(EFalse);
       
  1749 		// need to inform sessions - so tell stream
       
  1750 		if (sep->Stream())
       
  1751 			{
       
  1752 			DestroyStream(sep->Stream(),aError);
       
  1753 			}
       
  1754 		}
       
  1755 	// leave the channel
       
  1756 	ClearSignallingChannel();
       
  1757 	// tell the user, on all channels
       
  1758 	iSAP.Error(aError);
       
  1759 	iSAP.SessionDisconnect();
       
  1760 	TPckgBuf<TInternalAvdtpErrorIndication> error;
       
  1761 	error().iError = aError;
       
  1762 	iSAP.Indication(error);
       
  1763 	}
       
  1764 
       
  1765 // sigsession has two error paths - one by being a channel user, and the other for protocol errors
       
  1766 void CSignallingSession::ServiceError(TInt aError)
       
  1767 	{
       
  1768 	LOG_FUNC
       
  1769 	iSAP.Error(aError);
       
  1770 	}
       
  1771 	
       
  1772 void CSignallingSession::SignallingChannelReady(CSignallingChannel& aNewChannel)
       
  1773 	{
       
  1774 	LOG_FUNC
       
  1775 	// we may have migrated from old signalling channel to the new instance 
       
  1776 	// so cannot use old signalling channel pointer
       
  1777 	iSignallingChannel = &aNewChannel;
       
  1778 	
       
  1779 	SetRemoteAddress(aNewChannel.RemoteAddress());
       
  1780 
       
  1781 	if (iIsListening)
       
  1782 		{
       
  1783 		TInternalAvdtpSignallingReadyIndication ind;
       
  1784 		ind.iBuf = aNewChannel.RemoteAddress().Des();
       
  1785 		
       
  1786 		TPckg<TInternalAvdtpSignallingReadyIndication> indPckg(ind);
       
  1787 		iSAP.Indication(indPckg);
       
  1788 		iIsListening = EFalse;
       
  1789 		}
       
  1790 	else
       
  1791 		{
       
  1792 		iSAP.Ready();
       
  1793 		}
       
  1794 	}
       
  1795 
       
  1796 void CSignallingSession::DestroyStream(CAVStream* aStream, TInt aError)
       
  1797 	{
       
  1798 	// tell all sessions of the error
       
  1799 	aStream->NotifyUserPlaneTransportSessionsError(NULL, aError);
       
  1800 	// and remove the stream
       
  1801 	delete aStream;
       
  1802 	}
       
  1803 
       
  1804 CCapabilityNotAllowedVisitor::CCapabilityNotAllowedVisitor(TAvdtpServiceCategories aLocallySupported)
       
  1805 : iLocallySupported(aLocallySupported), iIsValid(ETrue)
       
  1806 	{
       
  1807 	LOG_FUNC
       
  1808 	}
       
  1809 
       
  1810 TBool CCapabilityNotAllowedVisitor::Capability(TAvdtpServiceCategory aCat)
       
  1811 	{
       
  1812 	LOG_FUNC
       
  1813 	// need to put aCat into correct bit position
       
  1814 	TAvdtpServiceCategories cat;
       
  1815 	cat.SetCapability(aCat);
       
  1816 	
       
  1817 	if ((cat() ^ iLocallySupported()) & cat())
       
  1818 		{
       
  1819 		// remote has wrongly used a cap we don't support, mark it as dud
       
  1820 		iWrongCategory = aCat;
       
  1821 		iIsValid = EFalse;
       
  1822 		}
       
  1823 	return iIsValid; // will therefore stop at first broken capability
       
  1824 	}
       
  1825 	
       
  1826 TBool CCapabilityNotAllowedVisitor::IsValid() const
       
  1827 	{
       
  1828 	LOG_FUNC
       
  1829 	return iIsValid;
       
  1830 	}
       
  1831 
       
  1832 TAvdtpServiceCategory CCapabilityNotAllowedVisitor::WrongCategory() const
       
  1833 	{
       
  1834 	LOG_FUNC
       
  1835 	return iWrongCategory;
       
  1836 	}
       
  1837