bluetooth/btstack/avdtp/avdtpSignallingSession.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/avdtp/avdtpSignallingSession.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,1837 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements the avdtp signalling session
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <bluetooth/logger.h>
+#include "avdtpSignallingSession.h"
+#include "avdtpSignallingChannel.h"
+#include "avdtp.h"
+#include "avdtpsap.h"
+#include "avdtpStream.h"
+#include "avdtpLogicalChannelFactory.h"
+#include "avdtpConfigurators.h"
+#include "avdtputil.h"
+#include "avdtpDirectChannel.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("avdtpsigse");
+#endif
+
+CSignallingSession* CSignallingSession::NewLC(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
+	{
+	LOG_STATIC_FUNC
+	CSignallingSession* s = new (ELeave) CSignallingSession(aProtocol, aSAP);
+	CleanupStack::PushL(s);
+	s->ConstructL();
+	return s;
+	}
+	
+CSignallingSession* CSignallingSession::NewL(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
+	{
+	LOG_STATIC_FUNC
+	CSignallingSession* s = CSignallingSession::NewLC(aProtocol, aSAP);
+	CleanupStack::Pop();
+	return s;		
+	}
+	
+CSignallingSession::CSignallingSession(CAvdtpProtocol& aProtocol, CAvdtpSAP& aSAP)
+: CTransportSession(aProtocol, aSAP, ESignalling),
+  iLocalSEPs(_FOFF(CLocalSEP, iSignallingSessionLink))
+	{
+	LOG_FUNC	
+	}
+
+CSignallingSession::~CSignallingSession()
+	{
+	LOG_FUNC
+	DestroyLocalSEPs();
+	ClearSignallingChannel();
+	delete iSEPConfigurator;
+	}
+
+	
+void CSignallingSession::ConstructL()
+	{
+	LOG_FUNC
+	CTransportSession::ConstructL();
+	}
+
+TInt CSignallingSession::ActiveOpen()
+	{
+	LOG_FUNC
+	// esock will protect us from an accidental double connect
+	TInt ret = KErrNone;
+	if (iSignallingChannel)
+		{
+		if (!iSignallingChannel->IsListening())
+			{
+			// already got a suitable SC - probably due to a passive connection
+			// just say it's done (we're already attached)
+			iSAP.Ready();
+			}
+		else
+			{
+			// signalling channel is listening - detach from it, user has decided to connect
+			// drop through afterwards
+			ClearSignallingChannel();
+			}
+		}
+	// not else as ClearSignallingChannel will NULL iSignallingChannel
+	if (!iSignallingChannel)
+		{
+		iSignallingChannel = iProtocol.GetSignallingChannel(RemoteAddress());
+		if (iSignallingChannel)
+			{
+			ret = iSignallingChannel->AttachSignallingUser(*this);
+			}
+		else
+			{
+			ret = KErrNoMemory;
+			}
+		}
+
+	return ret;
+	}
+	
+void CSignallingSession::ClearSignallingChannel()
+	{
+	LOG_FUNC
+	if (iSignallingChannel)
+		{
+		iSignallingChannel->DetachSignallingUser(*this);	
+		}
+	iSignallingChannel = NULL;
+	}
+	
+void CSignallingSession::DestroyLocalSEPs()
+	{
+	LOG_FUNC
+	while (!iLocalSEPs.IsEmpty())
+		{
+		CLocalSEP* sep = iLocalSEPs.First();
+		sep->iSignallingSessionLink.Deque();
+		// inform codman - it'll clear bits as necessary since it reference coutns
+		iProtocol.CodMan().RemoveCodService(sep->Info().IsSink() ? EMajorServiceRendering :
+																	EMajorServiceCapturing);
+		delete sep;		
+		}
+	}
+	
+void CSignallingSession::DoShutdown()
+	{
+	LOG_FUNC
+
+	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+	while(iter)
+		{
+		iter++->SetInUse(EFalse);
+		}
+		
+	ClearSignallingChannel();
+	
+	if (iSAPShutdown == ENormal)
+		{
+		iSAP.CanClose();
+		}
+	else
+		{
+		// base class has detached us so that we own ourselves
+		// nothing more to do, apart from die.
+		delete this;
+		}
+	}
+
+TInt CSignallingSession::Send(RMBufChain& /*aData*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
+	{
+	LOG_FUNC
+	// not supported in signalling - only ioctls and opts allowed
+	return 0;
+	}
+
+TInt CSignallingSession::GetData(RMBufChain& /*aData*/)
+	{
+	LOG_FUNC
+	return KErrNotSupported;
+	}
+	
+// stuff forwarded from SAP
+TInt CSignallingSession::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption)
+	{
+	LOG_FUNC
+	TInt ret = KErrNotSupported;
+
+	if (aLevel == KSolBtAVDTPSignalling)
+		{
+		switch (aName)
+			{
+			case EAwaitPassiveSignallingChannel:
+				{
+				if (iIsListening && iSignallingChannel && iSignallingChannel->IsListening())
+					{
+					ret = KErrAlreadyExists;
+					}
+				else if (iSignallingChannel && !iSignallingChannel->IsListening())
+					{
+					ret = KErrInUse;
+					}
+				else
+					{					
+	                iSignallingChannel=iProtocol.FindListeningSignallingChannel();
+					// For ACP - triggered when client is ready for listening
+					// (would be nice to be "automatic", but needs client to be happy they've registered all their seps
+					if (!iSignallingChannel)
+						{
+	    				iSignallingChannel = iProtocol.CreateSignallingChannelForListening();
+						}
+					
+					if (iSignallingChannel)
+						{
+						ASSERT_DEBUG(iSignallingChannel->IsListening());
+						ret = iSignallingChannel->AttachSignallingUser(*this);
+						if (ret == KErrNone)
+							{
+							iIsListening = ETrue;
+							}
+						else
+							{
+							// if we didn't manage to tell anyone else
+							// then no one else knows so actually we're best
+							// off cleaning up after ourselves.
+							iSignallingChannel->DetachSignallingUser(*this);
+							iSignallingChannel = NULL;
+							}							
+						}
+					else
+						{
+						ret = KErrNoMemory;
+						}
+					}
+				break;
+				}
+
+			case EStopAwaitPassiveSignallingChannel:
+				{
+				if (!iSignallingChannel)
+					{
+    				ret = KErrNotReady;
+					}
+
+				else
+					{
+					iIsListening = EFalse;
+					ClearSignallingChannel();
+					}
+				break;
+				}
+			
+			// also for reconfigure - the configurator decides
+			case EStartConfiguringRemote:
+				{
+				if (iSEPConfigurator)
+					{
+					ret = KErrInUse;
+					}
+				else
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TInternalSelectRemoteSEP))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						// get Remote SEID we're configuring, and the binding local SEP SEID
+						// avdtp spec makes us have to do the binding now
+						TInternalSelectRemoteSEP select = *reinterpret_cast<const TInternalSelectRemoteSEP*>(aOption.Ptr());
+
+						if (!select.iLocalSEID.IsLocal())
+							{
+							ret = KErrArgument;
+							}
+						else
+							{							
+							CLocalSEP* localSEP = FindLocalSEP(select.iLocalSEID);
+							if (!localSEP)
+								{
+								// client supplied bad SEID
+								ret = KErrArgument;
+								}
+							else
+								{
+								// don't support reconfiguring of an active stream - client must suspend
+								CAVStream* stream = localSEP->Stream();
+								if (stream && stream->IsStreaming())
+									{
+									ret = KErrInUse;
+									}
+								else
+									{
+									TRAP(ret, iSEPConfigurator = CRemoteSEPConfigurator::NewL(*this,
+																  iProtocol,
+																  select.iLocalSEID,
+																  select.iRemoteSEID,
+																  stream ? ETrue : EFalse));
+									}
+								}
+							}
+						}
+					}
+				break;
+				}
+			case EStartConfiguringLocal:
+				{
+				if (iSEPConfigurator)
+					{
+					ret = KErrInUse;
+					}
+				else
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TSEID))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						// get Local SEID we're configuring
+						TSEID localseid = *reinterpret_cast<const TSEID*>(aOption.Ptr());
+						TRAP(ret, iSEPConfigurator = CLocalSEPConfigurator::NewL(*this, iProtocol, localseid));
+						}
+					}
+				break;
+				}
+			
+			case EAddCapabilitySelection:
+				{
+				if (iSEPConfigurator)
+					{
+					ret = iSEPConfigurator->AddCapability(aOption);
+					}
+				else
+					{
+					ret = KErrNotReady;
+					}
+				break;
+				}
+				
+			case ESendConfigurationResponse:
+				{
+				if (iSignallingChannel)
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalConfigurationResponse))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						const TAvdtpInternalConfigurationResponse rsp = *reinterpret_cast<const TAvdtpInternalConfigurationResponse*>(aOption.Ptr());
+						// check SEID is ok
+						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
+						if (sep)
+							{						
+	 						// need to tell sep of the outcome so it can clear its state
+	 						// this needs to occur for config and reconfig
+	 						// first param is true if result is kerrnone- i.e. all ok, false otherwise
+	 						TRAP(ret, sep->CommitPendingConfigurationL(rsp.iResult == KErrNone,rsp.iIsReconfigure));
+							if (!rsp.iIsReconfigure)
+								{
+								if (rsp.iResult == KErrNone)
+									{
+									if (ret==KErrNone)
+										{
+										ret = iSignallingChannel->SendSetConfigurationAccept(rsp.iTransactionLabel);
+										if (ret==KErrNone)
+											{
+											// time to spawn that (ACP) stream
+											TRAP(ret, sep->ExpectStreamL(RemoteAddress(), *this, iProtocol));
+											}
+										}
+									}
+								else
+									{
+									ret = iSignallingChannel->SendSetConfigurationReject(rsp.iTransactionLabel,
+																			   AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult),
+																			   rsp.iCategory);
+									}
+								}
+							else
+								{
+								if (!sep->InUse())
+									{
+									// almost assertable since we shouldnt have forwarded the indication if not
+									// but we don't want a DoS if bad client
+									ret = KErrNotReady;
+									}
+								else
+									{
+									if (rsp.iResult == KErrNone)
+										{
+										ret = iSignallingChannel->SendReconfigureAccept(rsp.iTransactionLabel);
+										}
+									else
+										{
+										ret = iSignallingChannel->SendReconfigureReject(rsp.iTransactionLabel,
+																			   AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult),
+																			   rsp.iCategory);
+										}
+									}
+								}
+							if (ret==KErrNone && rsp.iResult == KErrNone && !rsp.iIsReconfigure)
+								{
+								// now in use, and from AVDTP spec sect6.3 we now do not expect other transactions until stream started
+								// not point resetting for reconfigure
+								sep->SetInUse(ETrue);
+								}
+							}
+						else
+							{
+							ret = KErrArgument;
+							}
+						}
+					}
+				else
+					{
+					ret = KErrDisconnected;
+					}
+				break;
+				}
+				
+			case ESendStartResponse:
+				{
+				if (iSignallingChannel)
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalStartResponse))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						const TAvdtpInternalStartResponse rsp = *reinterpret_cast<const TAvdtpInternalStartResponse*>(aOption.Ptr());
+						// check SEID is ok
+						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
+						
+						if (sep && sep->Stream() && rsp.iResult == KErrNone)
+							{
+							ret = iSignallingChannel->SendStartAccept(rsp.iTransactionLabel);
+							if (ret==KErrNone)
+								{
+								sep->Stream()->Started();
+								}
+							}
+						else if (sep && !(sep->Stream()))
+							{
+							ret = KErrUnknown;
+							}
+						else if (sep)
+							{
+							// The AVDTP error code (spec... ACP to INT error code table) is offset by -18045
+							ret = iSignallingChannel->SendStartReject(rsp.iTransactionLabel, AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult), rsp.iSEID);
+							}
+						else
+							{
+							ret = KErrArgument;
+							}
+						}
+					}
+				else
+					{
+					ret = KErrDisconnected;
+					}
+				break;
+				}
+			case ESendSuspendResponse:
+				{
+				if (iSignallingChannel)
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalSuspendResponse))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						const TAvdtpInternalSuspendResponse rsp = *reinterpret_cast<const TAvdtpInternalSuspendResponse*>(aOption.Ptr());
+						// check SEID is ok
+						CLocalSEP* sep = FindLocalSEP(rsp.iSEID);
+						if (sep && sep->Stream() && rsp.iResult == KErrNone)
+							{
+							ret = iSignallingChannel->SendSuspendAccept(rsp.iTransactionLabel);
+							if (ret==KErrNone)
+								{
+								sep->Stream()->Suspended();
+								}
+							}
+						else if (sep && !(sep->Stream()))
+							{
+							ret = KErrUnknown;
+							}
+						else if (sep)
+							{
+							// The AVDTP error code (spec... ACP to INT error code table) is offset by -18045
+							ret = iSignallingChannel->SendSuspendReject(rsp.iTransactionLabel, AvdtpInternalUtils::SymbianErrorToAvdtpError(rsp.iResult), rsp.iSEID);
+							}
+						else
+							{
+							ret = KErrArgument;
+							}
+						}
+					}
+				else
+					{
+					ret = KErrDisconnected;
+					}
+				break;
+				}
+			case ESendSecurityControlResponse:
+				{
+				if (iSignallingChannel)
+					{
+					// Check the integrity of the descriptor					
+					if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpInternalSecurityControlResponse))
+						{
+						ret = KErrBadDescriptor;
+						}
+					else
+						{
+						const TAvdtpInternalSecurityControlResponse secRsp = *reinterpret_cast<const TAvdtpInternalSecurityControlResponse*>(aOption.Ptr());
+						// check SEID is ok
+						CLocalSEP* sep = FindLocalSEP(secRsp.iSEID);
+						if (!sep)
+							{
+							ret = KErrArgument;
+							}
+						else
+							{
+							if(secRsp.iResult == KErrNone)
+								{
+								const TDesC8* rspInfo = secRsp.iSecurityControlInfo.Length() ? &secRsp.iSecurityControlInfo : NULL;
+								ret = iSignallingChannel->SendSecurityControlAccept(secRsp.iTransactionLabel, rspInfo);
+								}
+							else
+								{
+								ret = iSignallingChannel->SendSecurityControlReject(secRsp.iTransactionLabel,
+																		AvdtpInternalUtils::SymbianErrorToAvdtpError(secRsp.iResult));
+								}
+							}
+						}
+					}
+				else
+					{
+					ret = KErrDisconnected;
+					}
+				break;
+				}
+			case EShutdown:
+				{
+				ret=KErrNone;
+				TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+				while(iter)
+					{
+					if (iter++->Stream()) 
+						{
+						ret=KErrNotReady;
+						}
+					}
+				if (ret==KErrNone)
+					{
+					iter.SetToFirst();
+					while(iter)
+						{
+						iter++->SetInUse(EFalse);
+						}
+
+					ClearSignallingChannel();
+					iSAP.SessionDisconnect();
+					}
+				break;
+				}
+			}
+		}
+	return ret;
+	}
+	
+	
+	
+void CSignallingSession::Ioctl(TUint aLevel, TUint aName, const TDesC8* aOption)
+	{
+	LOG_FUNC
+	TInt res = KErrNotSupported;
+	
+	if (aLevel == KSolBtAVDTPSignalling)	
+		{
+		const TUint8* optionPtr=NULL;
+		if (aOption)
+			{
+			optionPtr = aOption->Ptr();
+			}
+			
+		switch (aName)
+			{
+			case EDiscoverSEPs:
+				{
+				res=iSignallingChannel ? iSignallingChannel->SendDiscoverSEPs(*this) : KErrNotReady;
+				break;
+				}
+			case EGetCapabilities:
+				{
+				// Check the integrity of the descriptor					
+				if (!optionPtr || aOption->Length() != sizeof(TSEID))
+					{
+					res = KErrBadDescriptor;
+					}
+				else
+					{
+					TSEID seid = *reinterpret_cast<const TSEID*>(optionPtr);
+					
+					if (seid.IsLocal())
+						{
+						// meaningless to try to associate with a remote sep at this stage
+						// getting local capabilities not supported
+						res = KErrArgument;
+						}
+					else
+						{						
+						// client doesn't need to have populated remote sep cache at this point, so just try to send
+						res=iSignallingChannel ?  iSignallingChannel->SendGetCapabilities(*this, seid) : KErrNotReady;
+						}
+					}
+				break;
+				}
+			case EAbortStream:
+				{
+				// Check the integrity of the descriptor					
+				if (!optionPtr || aOption->Length() != sizeof(TSEID))
+					{
+					res = KErrBadDescriptor;
+					}
+				else
+					{
+					res = KErrNone;
+					// check seid exists
+					const TSEID& seid = *reinterpret_cast<const TSEID*>(optionPtr);
+					TSEID packetSeid;
+					
+					if (seid.IsLocal())
+						{
+						CLocalSEP* sep = FindLocalSEP(seid);
+						// check local sep exists
+						if (!sep || !(sep->Stream()))
+							{
+							res = KErrArgument;
+							}
+						else
+							{
+							packetSeid = sep->Stream()->RemoteSEID();
+							}
+						}
+					else
+						{
+						// remote was specified - again, check it'ok
+						if (!FindStreamFromRemoteSEID(seid))
+							{
+							res = KErrArgument;
+							}
+						else
+							{
+							packetSeid = seid;
+							}
+						}
+					if (res==KErrNone)
+						{
+						res = SendAbort(packetSeid);
+						}
+					}
+				break;
+				}
+			case ESelectSEP:
+				{
+				if (iSEPConfigurator)
+					{				
+					TInt cfgRes = iSEPConfigurator->Finalise();
+					// user doesn't need to know whether we sync or async
+					res = cfgRes == KRequestPending ? KErrNone : cfgRes;
+					if (cfgRes==KErrNone)
+						{
+						// can complete the service now
+						iSAP.ServiceComplete(NULL);
+						}
+					delete iSEPConfigurator;
+					iSEPConfigurator = NULL;
+					}
+				else
+					{
+					res = KErrNotReady;
+					}
+				break;
+				}
+			case EStartStreaming:
+				{
+				if (iSignallingChannel==NULL)
+					{
+					res = KErrNotReady;
+					}
+				else
+					{
+					// Check the integrity of the descriptor					
+				if (!optionPtr || aOption->Length() != sizeof(TSEID))
+					{
+					res = KErrBadDescriptor;
+					}
+					else
+						{
+						const TSEID& clientSeid = *reinterpret_cast<const TSEID*>(optionPtr);
+						
+						// see whether it was a local or remote seid - either is ok
+						CAVStream* stream = NULL;
+						
+						if (clientSeid.IsLocal())
+							{
+							CLocalSEP* sep = FindLocalSEP(clientSeid);
+							if (sep)
+								{
+								stream = sep->Stream();
+								}
+							}
+						else
+							{
+							// client supplied remote seid so just check
+							stream = FindStreamFromRemoteSEID(clientSeid);
+							}
+						res = stream ? stream->Start() : KErrUnknown;
+						}
+					}					
+				break;
+				}
+			case ESuspendStreaming:
+				{
+				if (iSignallingChannel==NULL)
+					{
+					res = KErrNotReady;
+					}
+				else
+					{
+					// Check the integrity of the descriptor					
+				if (!optionPtr || aOption->Length() != sizeof(TSEID))
+					{
+					res = KErrBadDescriptor;
+					}
+					else
+						{
+						const TSEID& clientSeid = *reinterpret_cast<const TSEID*>(optionPtr);
+						// see whether it was a local or remote seid - either is ok
+						CAVStream* stream = NULL;
+						
+						if (clientSeid.IsLocal())
+							{
+							CLocalSEP* sep = FindLocalSEP(clientSeid);
+							if (sep)
+								{
+								stream = sep->Stream();
+								}
+							}
+						else
+							{
+							// client supplied remote seid so just check
+							stream = FindStreamFromRemoteSEID(clientSeid);
+							}
+						res = stream ? stream->Suspend() : KErrUnknown;
+						}
+					}
+				break;
+				}
+			case ESendSecurityControl:
+				{
+				//GAVDP is wishing to send security control command (allowed any time if capable)
+				// needs to be remote
+				// Check the integrity of the descriptor					
+				if (!optionPtr || aOption->Length() != sizeof(TAvdtpInternalSendSecurityControl))
+					{
+					res = KErrBadDescriptor;
+					}
+				else
+					{
+					const TAvdtpInternalSendSecurityControl& security = *reinterpret_cast<const TAvdtpInternalSendSecurityControl*>(optionPtr);
+					if (!security.iRemoteSEID.IsLocal())
+						{
+						// check capability
+						if (iSignallingChannel)
+							{
+							if (iProtocol.RemoteSEPCache().HasCapability(RemoteAddress(),
+																		security.iRemoteSEID,
+																		EServiceCategoryContentProtection))
+								{
+								res = iSignallingChannel->SendSecurityControl(*this,
+																		security.iRemoteSEID,
+																		security.iSecurityControlInfo);
+								}
+							else
+								{
+								// remote doesnt support CP
+								res = KErrNotSupported;
+								}
+							}
+						else
+							{
+							res = KErrNotReady;
+							}
+						}
+					else
+						{
+						res = KErrArgument;
+						}
+					}
+				break;
+				}	
+			default:
+				{
+				res = KErrNotSupported;
+				}
+			}
+		if (res!=KErrNone)
+			{
+			iSAP.Error(res);
+			}
+		}
+	}
+	
+#ifdef _DEBUG	
+void CSignallingSession::CancelIoctl(TUint aLevel, TUint /*aName*/)
+#else
+void CSignallingSession::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/)
+#endif
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(aLevel==KSolBtAVDTPSignalling, Panic(EAvdtpBadIoctl));
+	// none at present	
+	}
+	
+	
+TInt CSignallingSession::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
+	{
+	LOG_FUNC
+	TInt ret = KErrNotSupported;
+	
+	if (aLevel == KSolBtAVDTPSignalling)
+		{
+		switch (aName)
+			{
+			case EGetProposedConfiguration:
+				{
+				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
+				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetProposedConfiguration))
+					{
+					ret = KErrBadDescriptor;
+					}
+				else
+					{
+					TInternalGetProposedConfiguration& conf = *const_cast<TInternalGetProposedConfiguration*>(reinterpret_cast<const TInternalGetProposedConfiguration*>(aOption.Ptr()));
+					CLocalSEP* s = FindLocalSEP(conf.iSEID);
+					if (s)
+						{
+						// Check that the option buffer size is sufficient
+						TPtrC8 pendingConf(s->PendingConfiguration());
+						if (aOption.MaxLength() < pendingConf.Length())
+							{
+							ret = KErrUnderflow;
+							}
+						else
+							{
+							// would be nice to use a return struct
+							// but gets tricky - we don't know how big the option is
+							// so can't use TBuf. TPtr falls foul of IPC.
+							aOption.Copy(pendingConf);
+							ret = KErrNone;
+							}
+						}
+					else
+						{
+						ret = KErrArgument;
+						}
+					}
+				break;
+				}
+			
+			case EGetSecurityControl:
+				{
+				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
+				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetSecurityControl))
+					{
+					ret = KErrBadDescriptor;
+					}
+				else
+					{
+					TInternalGetSecurityControl& sec = *const_cast<TInternalGetSecurityControl*>(reinterpret_cast<const TInternalGetSecurityControl*>(aOption.Ptr()));
+					CLocalSEP* s = FindLocalSEP(sec.iSEID);
+					if (s)
+						{
+						// Check that the option buffer size is sufficient
+						TPtrC8 securityData(s->SecurityControl());
+						if (aOption.MaxLength() < securityData.Length())
+							{
+							ret = KErrUnderflow;
+							}
+						else
+							{
+							aOption.Copy(securityData);
+							ret = KErrNone;
+							}
+						}
+					else
+						{
+						ret = KErrArgument;
+						}				
+					}
+				break;
+				}
+			case EGetAVDTPCapabilityResponse:
+				{
+				// Check the integrity of the descriptor. The option length is variable, subject to the payload length.
+				if (!aOption.Ptr() || aOption.Length() < sizeof(TInternalGetSEPCapability))
+					{
+					ret = KErrBadDescriptor;
+					}
+				else
+					{
+					TInternalGetSEPCapability cap = *reinterpret_cast<const TInternalGetSEPCapability*>(aOption.Ptr());
+					TPtrC8 ptr;
+					// get the required capability from the SEP cache (in 'air' form)
+					TRAP(ret, ptr.Set(iProtocol.RemoteSEPCache().GetCapabilityL(
+															RemoteAddress(),
+															cap.iSEID,
+															cap.iServiceCategory));)
+															
+					if (ret==KErrNone)
+						{
+						// Check that the option buffer size is sufficient
+						if (aOption.MaxLength() < ptr.Length())
+							{
+							ret = KErrUnderflow;
+							}
+						else
+							{
+							aOption.Copy(ptr);
+							}
+						}
+					}
+				break;
+				}
+				
+			case ERegisterSEP:
+				{
+				// Check the integrity of the descriptor
+				if (!aOption.Ptr() || aOption.Length() != sizeof(TAvdtpSEPInfo))
+					{
+					ret = KErrBadDescriptor;
+					}
+				else
+					{
+					TAvdtpSEPInfo info = *reinterpret_cast<const TAvdtpSEPInfo*>(aOption.Ptr());
+					// client doesn't manage inUse field - we do
+					info.SetInUse(EFalse);
+					
+					TRAP(ret, const_cast<CSignallingSession*>(this)->CreateLocalSEPL(info));
+					
+					TPckg<TAvdtpSEPInfo> pckg(info);
+					aOption.Copy(pckg);
+					}
+				break;
+				}
+				
+			case EGetReportingAndRecoveryConfig:
+				{
+				// Check the integrity of the descriptor
+				if (!aOption.Ptr() || aOption.Length() != sizeof(TReportingAndRecovery))
+					{
+					ret = KErrBadDescriptor;
+					}
+				else
+					{
+					TReportingAndRecovery rar;
+					TPckg<TReportingAndRecovery> rarBuf(rar);
+					rarBuf.Copy(aOption);
+					CAVStream* stream = FindStreamFromRemoteSEID(rar.iSEID);
+					if(stream == NULL)
+						{
+						ret = KErrNotFound;
+						}
+					else
+						{
+						rar.iReporting = stream->CheckConfigured(EServiceCategoryReporting);
+						rar.iRecovery  = stream->CheckConfigured(EServiceCategoryRecovery);
+						aOption.Copy(rarBuf);
+						ret = KErrNone;
+						}
+					}
+				break;
+				}
+			}
+		}
+		
+	return ret;
+	}
+	
+
+
+TInt CSignallingSession::OpenIndication(TSEID aSEID)
+	{
+	LOG_FUNC
+	// now create the full Stream Object
+	CLocalSEP* sep = FindLocalSEP(aSEID);
+	if (sep && sep->Stream())
+		{
+		// this will tell channel factory to expect n channels on sending resp
+		TRAPD(err, sep->Stream()->AwaitLogicalChannelsL());
+		return err;
+		}
+	else if (sep && !sep->Stream())
+		{
+		// the remote must have decided that a GetConfig yielded just what they wanted
+		// and have proceeded directly with Open
+		// this *violates* GAVDP - see p 16
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+	
+	
+TInt CSignallingSession::DiscoverIndication(TAvdtpTransactionLabel /*aLabel*/, CAvdtpOutboundSignallingMessage& aDiscoverResponseMessage)
+	{
+	LOG_FUNC
+	// iterate over all idle SEPs returning their capabilities
+	// need to return the label back to the Signalling Channel to tie up response
+
+	// this is *far* easier if we process this synchronously
+	// otherwise the design is tricky - we'd need to call a primitive bacxk on SigCh
+	// and it would need to know our last SEP info etc
+	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+	CLocalSEP* sep;
+	while(iter)
+		{
+		sep = iter++;
+		
+		TRAPD(overFlow, aDiscoverResponseMessage.AddSEPInfoL(sep->Info()));
+
+		if (overFlow)
+			{
+			// no more will go, try continuing with usecase though
+			// so NOT releaving - cos the message is ok
+			break;
+			}			
+		}
+	return KErrNone;
+	}
+	
+
+TInt CSignallingSession::GetCapsIndication(TAvdtpTransactionLabel /*aLabel*/,
+										   TSEID aSEID,
+										   CAvdtpOutboundSignallingMessage& aGetCapsResponseMessage)
+	{
+	LOG_FUNC
+	// client has set caps now - if they haven't then we will prob just send empty stuff back
+	// i.e. we send whatever we've got (but possibly "knowing" this fact
+	
+	// find the idle SEP with aSEID
+	CLocalSEP* sep = FindLocalSEP(aSEID);
+	// this uses the same pattern as :DiscoverIndication
+	if (!sep)
+		{
+		return KErrNotFound;
+		}
+	
+	TInt ret = KErrNone;
+	
+	for (TInt i=0; i<sep->Capabilities().Count(); i++)
+		{
+		// one at a time - easier for us to cope if we OOM
+		if (sep->Capabilities()[i])
+			{
+			// local sep has capability
+			TRAPD(overFlow, aGetCapsResponseMessage.AddSEPCapabilityL(*sep->Capabilities()[i]));
+			if (overFlow)
+				{
+				// no more will go
+				// if even the first capability didn't go then we have to forget replying
+				if (i==0)
+					{
+					// there are no caps in the response, so it's meaningless
+					ret = KErrUnderflow;		
+					}
+				// otherwise we can try continuing with usecase though
+				// so NOT erroring - cos the message is ok
+				break;
+				}			
+			}
+		
+		}
+	return ret;
+	}
+
+TInt CSignallingSession::SetConfigIndication(TAvdtpTransactionLabel aLabel,
+											  TSEID aACPSEID,
+											  TSEID aINTSEID,
+											  RBuf8& aConfig)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+
+/*
+we check to see if the remote has (wrongly) set capabilities that the idle sep has not
+if the remote has then we reject the request
+else pass onto gavdp
+*/
+	
+	CCapabilityNotAllowedVisitor* checker =
+				new CCapabilityNotAllowedVisitor(sep->Categories());
+	
+	if (!checker)
+		{
+		return KErrNoMemory;
+		}
+
+	checker->Process(aConfig);
+	
+	if (!checker->IsValid())
+		{
+		// signalling channel expects us to put the duff category in the aConfig
+		// take the first one (as suggested by spec)
+		TPckgBuf<TAvdtpServiceCategory> catBuf(checker->WrongCategory());
+		aConfig.Copy(catBuf);
+		delete checker;
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadServCategory);
+		}
+
+	delete checker;
+	checker = NULL;
+	
+	// update the SEP to contain the pending configuration
+	// commited when gavdp says ok
+	TInt res = sep->SetPendingConfiguration(aConfig, EFalse); // transfers aConfig ownership
+	if (res==KErrNone)
+		{
+		sep->SetRemoteSEID(aINTSEID);
+
+		// all ok, so pass on an indication to GAVDP as they need to configure too
+		TInternalAvdtpConfigurationIndication ind;
+		ind.iIndication = EAvdtpSetConfiguration;
+		ind.iPayloadLength = aConfig.Length();
+		ind.iSEID = aACPSEID;
+		ind.iINTSEID = aINTSEID;
+		ind.iTransactionLabel = aLabel;
+
+		TPckg<TInternalAvdtpConfigurationIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		}
+
+	return res;
+	}
+	
+TInt CSignallingSession::GetConfigIndication(TAvdtpTransactionLabel /*aLabel*/, TSEID aLocalSEID,
+									CAvdtpOutboundSignallingMessage& aGetConfigResponseMessage)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aLocalSEID);
+	
+	if (!sep)
+		{
+		return KErrNotFound;
+		}
+
+	// remote may not have sent SetConfiguration
+	if (sep->PreConfigured())
+		{
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+		
+	TInt ret = KErrNone;
+	
+	for (TInt i=0; i<sep->Configuration().Count(); i++)
+		{
+		// one at a time - easier for us to cope if we OOM
+		if (sep->Configuration()[i])
+			{
+			// local sep has capability
+			TRAPD(overFlow, aGetConfigResponseMessage.AddSEPCapabilityL(*sep->Configuration()[i]));
+			if (overFlow)
+				{
+				// no more will go
+				// if even the first capability didn't go then we have to forget replying
+				if (i==0)
+					{
+					// there are no caps in the response, so it's meaningless
+					ret = KErrUnderflow;		
+					}
+				// otherwise we can try continuing with usecase though
+				// so NOT erroring - cos the message is ok
+				break;
+				}	
+			}
+		}
+
+	return ret;			
+	}
+	
+TInt CSignallingSession::ReconfigIndication(TAvdtpTransactionLabel aLabel,
+															TSEID aACPSEID,
+															RBuf8& aNewConfig)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+		
+	if (!sep->Stream())
+		{
+		// remote has been bad
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+
+/*
+we check to see if the remote has (wrongly) set capabilities that the spec forbids
+see 8.10.1 avdtp sepc
+if the remote has then we reject the request
+else pass onto gavdp
+*/
+	TAvdtpServiceCategories allowed;
+	allowed.SetCapability(EServiceCategoryMediaCodec);
+	allowed.SetCapability(EServiceCategoryContentProtection);
+
+	CCapabilityNotAllowedVisitor* checker = new CCapabilityNotAllowedVisitor(allowed);
+	
+	if (!checker)
+		{
+		return KErrNoMemory;
+		}
+
+	checker->Process(aNewConfig);
+		
+	if (!checker->IsValid())
+		{
+		// signalling channel expects us to put the duff category in the aConfig
+		// take the first one (as suggested by spec)
+		TPckg<TUint8> catBuf(checker->WrongCategory());
+		aNewConfig.Copy(catBuf);
+		delete checker;
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpInvalidCapabilities);
+		}
+
+	delete checker;
+	checker = NULL;
+
+//take ownership of config buffer
+	TInt res = sep->SetPendingConfiguration(aNewConfig, ETrue);	
+	
+	if (res==KErrNone)
+		{
+		// all ok, so pass on an indication to GAVDP as they need to reconfigure too
+		TInternalAvdtpConfigurationIndication ind;
+		ind.iIndication = EAvdtpReconfigure;
+		ind.iPayloadLength = aNewConfig.Length();
+		ind.iSEID = aACPSEID;
+		// to give consistent API for Set and Re-configure , give the INT SEID again
+		ind.iINTSEID = sep->Stream()->RemoteSEID();
+
+		ind.iTransactionLabel = aLabel;
+
+		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		}
+	
+	return res;
+	}
+
+/** Handle a Start Indication from remote.
+
+The decision about when to issue the start indication to the client is taken by
+the stream.
+
+@param aLabel The transaction label of the start command.
+@param aACPSEID The (local) seid referring to the stream to be started.
+*/
+TInt CSignallingSession::StartIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+
+	TInt err = KErrUnknown;
+	if (sep->Stream())
+		{
+		// If the stream is in a valid state it will call back to the sig session
+		// to cause the indication to be passed to the client.
+		err = sep->Stream()->StartIndication(aLabel, aACPSEID);
+		}
+
+	if(err == KErrNone)	
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+	}
+		
+TInt CSignallingSession::ReleaseIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+		
+	if (sep->Stream())
+		{
+		// dont ask GAVDP to confirm
+		// we also know that if we have a stream it must be releaseable
+		(void)iSignallingChannel->SendReleaseAccept(aLabel);
+
+		sep->SetInUse(EFalse);
+
+		// We try and hand off the channels to be closed.  This is because it is
+		// the responsibility of the INT to release these so we can't just 
+		// shut them down straight away.  We don't want to have to deal with the 
+		// complication of funny stream states and clearup by leaving them with the
+		// stream once it's effectively dead.  If it fails however, we just let the 
+		// channels go away.
+		// This is only done for non-muxed streams, otherwise we just revert to 
+		// closing the channels ourselves.  
+#ifndef __SYMBIAN_AVDTP_HIDE_MUX
+#warning ("Release ACP channel release must be fixed for muxed case")
+#endif
+		if(!sep->MultiplexingConfigured())
+			{
+			// Take the channels from the stream to disconnect
+			// Note that although some of these may be the same CloseLogicalChannels will
+			// deal with correctly closing each channel once.
+			TFixedArray<CDirectChannel*, KAvdtpChannelArraySize> channels;
+			channels[0] = static_cast<CDirectChannel*>(sep->Stream()->iMediaBinding.iChannel);
+			channels[1] = static_cast<CDirectChannel*>(sep->Stream()->iReportingBinding.iChannel);
+			channels[2] = static_cast<CDirectChannel*>(sep->Stream()->iRecoveryBinding.iChannel);
+			TArray<CDirectChannel*> array = channels.Array();
+
+			TRAP_IGNORE(iProtocol.LogicalChannelFactory().CloseSessionLogicalChannelsL(array, KAvdtpACPReleaseChannelCloseTimeout));	
+			}
+
+		// just error the stream - it will tell the user-plane sessions
+		// they'll then tell the user
+		// so , like open, we don't let user directly see this as an indication
+		DestroyStream(sep->Stream(), KErrDisconnected);
+		
+		// all ok, so pass on an indication to GAVDP
+		TInternalAvdtpAirIndication ind;
+		ind.iIndication = EAvdtpRelease;
+		ind.iPayloadLength = 0;
+		ind.iSEID = aACPSEID;
+		ind.iTransactionLabel = aLabel; // not used 
+
+		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		
+		return KErrNone;
+		}
+	else
+		{
+		// remote is in bad state
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+	}
+	
+TInt CSignallingSession::SuspendIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+		
+	// check that we think stream suspendable
+	if (sep->Stream() && sep->Stream()->IsStreaming())
+		{
+		// all ok, so pass on an indication to GAVDP
+		TInternalAvdtpAirIndication ind;
+		ind.iIndication = EAvdtpSuspend;
+		ind.iPayloadLength = 0;
+		ind.iSEID = aACPSEID;
+		ind.iTransactionLabel = aLabel;
+
+		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		return KErrNone;
+		}
+	else
+		{
+		return SymbianBluetoothAV::ConvertToSymbianError::AvdtpError(EAvdtpBadState);
+		}
+	}
+
+TInt CSignallingSession::AbortIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+	else
+		{
+		// tell the sep, stream, then the user (only if we have a stream though)
+		sep->SetInUse(EFalse);
+		
+		if (sep->Stream())
+			{			
+			DestroyStream(sep->Stream(),KErrAbort);		
+			}
+		// Pass on an indication to GAVDP as they need to know too
+		TInternalAvdtpAirIndication ind;
+		ind.iIndication = EAvdtpAbort;
+		ind.iSEID = aACPSEID;
+		ind.iTransactionLabel = aLabel; // not that useful, client cant respond
+
+		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+		iSAP.Indication(indPckg);			
+		}
+	return KErrNone;			
+	}
+	
+void CSignallingSession::AbortConfirm(TSEID aRemoteSEID)
+	{
+	LOG_FUNC
+	// tell client
+	CompleteBasicService(KErrNone);
+
+	// error stream associated with remote
+	CAVStream* stream = FindStreamFromRemoteSEID(aRemoteSEID);
+	if (stream)
+		{
+		DestroyStream(stream, KErrAbort);
+		}
+	}
+	
+TInt CSignallingSession::SecurityControlIndication(TAvdtpTransactionLabel aLabel, TSEID aACPSEID, const HBufC8* aSecurityData)
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aACPSEID);
+	
+	if (!sep)
+		{
+		// for a SEP not on this session
+		return KErrNotFound;
+		}
+	else
+		{
+		// pass ownership of HBuf to SEP
+		sep->SetSecurityControl(aSecurityData);
+				
+		// all ok, so pass on an indication to GAVDP as they need to do the actual security control response
+		TInternalAvdtpAirIndication ind;
+		ind.iIndication = EAvdtpSecurityControl;
+		ind.iSEID = aACPSEID;
+		ind.iPayloadLength = aSecurityData->Length();
+		ind.iTransactionLabel = aLabel;
+
+		TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		
+		return KErrNone;			
+		}
+	}
+
+void CSignallingSession::SecurityControlConfirm(TInt aResult, TSEID aRemoteSEID, const TDesC8& aResponseData)
+ 	{
+	LOG_FUNC
+ 	if (aResult==KErrNone)
+ 		{
+ 		TPckgBuf<TAvdtpInternalSendSecurityControl> securityControlPckgBuf;
+ 		securityControlPckgBuf().iRemoteSEID = aRemoteSEID;
+ 		securityControlPckgBuf().iSecurityControlInfo = aResponseData;
+		iSAP.ServiceComplete(&securityControlPckgBuf);
+ 		}
+ 	else
+ 		{
+ 		iSAP.Error(aResult);
+ 		}
+ 	}
+
+
+void CSignallingSession::DiscoverConfirm(TInt aResult, const TAvdtpInternalDiscoverConfirm* const aConfirm)
+	{
+	LOG_FUNC
+	if (aResult==KErrNone)
+		{
+		__ASSERT_DEBUG(aConfirm, Panic(EAvdtpSignallingSessionReceivedBadIndication));
+		//complete the client request with the number of SEPs
+		TPckgBuf<TAvdtpInternalDiscoverConfirm> buf(*aConfirm);
+		iSAP.ServiceComplete(&buf);
+		}
+	else
+		{
+		//either we were rejected by the peer or there was an internal
+		//error in the signalling channel
+		iSAP.Error(aResult);
+		}
+	}
+
+
+void CSignallingSession::GetCapsConfirm(TInt aResult, TSEID /*aRemoteSEID*/, TAvdtpServiceCatBitMask aSeen)
+	{
+	LOG_FUNC
+	if (aResult==KErrNone)
+		{
+		TPckgC<TAvdtpServiceCatBitMask> buf(aSeen);
+		iSAP.ServiceComplete(&buf);
+		}
+	else
+		{
+		iSAP.Error(aResult);
+		}
+	}
+
+void CSignallingSession::StreamStarted(TSEID aLocalSEID)
+	{
+	LOG_FUNC
+	if (FindLocalSEP(aLocalSEID))
+		{
+		// now tell client
+		CompleteBasicService(KErrNone);
+		}
+	}
+
+void CSignallingSession::StreamSuspended(TSEID aLocalSEID)
+	{
+	LOG_FUNC
+	if (FindLocalSEP(aLocalSEID))
+		{
+		// now tell client
+		CompleteBasicService(KErrNone);
+		}
+	}
+	
+void CSignallingSession::StreamAccepted(TSEID aLocalSEID, TSEID aRemoteSEID, TBool aWithReporting, TBool aWithRecovery)
+ 	{
+	LOG_FUNC
+ 	__ASSERT_DEBUG(aLocalSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
+	TInternalAvdtpStreamReadyIndication ind;
+	ind.iSEID = aLocalSEID;
+	ind.iRemoteSEID = aRemoteSEID;
+	ind.iReportingPresent = aWithReporting;
+	ind.iRecoveryPresent = aWithRecovery;
+ 	TPckg<TInternalAvdtpStreamReadyIndication> indPckg(ind);
+ 	iSAP.Indication(indPckg);
+ 	}
+ 	
+void CSignallingSession::StreamConfigured(TSEID /*aLocalSEID*/, TInt aResult, TAvdtpServiceCategory aFailedCategory)
+	{
+	LOG_FUNC
+	// tell the user in all cases
+	TPckgBuf<TAvdtpConfigReject> rejDataBuf;
+	rejDataBuf().iError = aResult;
+	rejDataBuf().iFailedCategory = aFailedCategory;
+	
+	// GAVDP will call back to client with Error upcall, so no need to error SAP
+	iSAP.ServiceComplete(&rejDataBuf);
+	}
+
+/*
+This callback is for the stream to inform gavdp of a failure in its state machine
+The signalling session SHALL NOT mutate the stream based on this; the stream should
+proceed, or die, or error in line with its present state and potential GAVDP recovery of that stream
+*/
+void CSignallingSession::StreamInitiatedServiceFailed(const CAVStream& /*aStream*/, TInt aError)
+	{
+	LOG_FUNC
+	ServiceError(aError);
+	}
+
+/** 
+This should be called from the stream when it is ready for a start indication
+to be passed up to the client. 
+*/	
+void CSignallingSession::StreamReadyForStartIndication(const TAvdtpTransactionLabel aLabel, const TSEID aSeid)
+	{
+	LOG_FUNC
+			
+	// pass on an indication to GAVDP
+	TInternalAvdtpAirIndication ind;
+	ind.iIndication = EAvdtpStart;
+	ind.iPayloadLength = 0;
+	ind.iSEID = aSeid;
+	ind.iTransactionLabel = aLabel;
+
+	TPckg<TInternalAvdtpAirIndication> indPckg(ind);
+
+	iSAP.Indication(indPckg);
+	}
+	
+TInt CSignallingSession::SendAbort(TSEID aRemoteSEID)
+	{
+	LOG_FUNC
+	return iSignallingChannel ? iSignallingChannel->SendAbort(*this, aRemoteSEID) : KErrNotReady;
+	}
+	
+/*inline*/void CSignallingSession::CompleteBasicService(TInt aErr)
+	{
+	LOG_FUNC
+	// basic services have no data to return
+	aErr ? iSAP.Error(aErr) : iSAP.ServiceComplete(NULL);
+	}
+	
+	
+/**
+Called as an INT - create the Stream object when we're setting configuration
+*/
+void CSignallingSession::DoConfigureStreamL(RBuf8& aConfigBuffer,
+												CLocalSEP& aLocalSEP,
+												TSEID aRemoteSEID,
+												TBool aReportingConfigured,
+												TBool aRecoveryConfigured)
+	{
+	LOG_FUNC
+	
+	// check to see if SignallingChannel went down during configuration
+	if (iSignallingChannel)
+		{
+		TBool streamCreated = EFalse;
+		
+		// if there is no stream then we create one now
+		// a stream would exist if this is a reconfigure
+		CAVStream* stream = FindStreamFromRemoteSEID(aRemoteSEID);
+		if (!stream)
+			{
+			TAvdtpSockAddr addr;
+			addr.SetBTAddr(RemoteAddress());
+			addr.SetSEID(aRemoteSEID);
+			stream = &aLocalSEP.CreateStreamL(addr, *this, iProtocol);
+		
+			streamCreated = ETrue;
+			CleanupStack::PushL(stream);
+			}
+		else
+			{
+			__ASSERT_DEBUG(stream->RemoteSEID()==aRemoteSEID, Panic(EAvdtpSignallingSessionFoundWrongStream));
+			}
+
+		stream->SetConfigurationL(aConfigBuffer, *iSignallingChannel,
+									aReportingConfigured, aRecoveryConfigured);
+									
+		if (streamCreated)
+			{
+			// SetConfigurationL ok, pop stream if we created one
+			CleanupStack::Pop();
+			}
+		}
+	else
+		{
+		User::Leave(KErrDisconnected);
+		}
+	}
+
+
+void CSignallingSession::CreateLocalSEPL(TAvdtpSEPInfo& aSEPInfo)
+	{
+	LOG_FUNC
+	// create an idle sep into queue for later discovery and selection
+	CLocalSEP* idleSEP = CLocalSEP::NewL(aSEPInfo, iProtocol.SEIDManager());
+	iLocalSEPs.AddFirst(*idleSEP);
+	// return the SEID to GAVDP via the reference paramter
+	
+	// adjust the service class of CoD, using reference counting of codman
+	iProtocol.CodMan().RegisterCodService(aSEPInfo.IsSink() ? EMajorServiceRendering :
+															   EMajorServiceCapturing);
+	}
+
+CLocalSEP* CSignallingSession::FindLocalSEP(TSEID aSEID) const
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(aSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
+	CLocalSEP* s = NULL;
+	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+	
+	while (iter)
+		{
+		s = iter++;
+		if (s->SEID()==aSEID)
+			{			
+			return s;
+			}
+		}
+	return NULL;
+	}
+	
+	
+CLocalSEP& CSignallingSession::FindLocalSEPL(TSEID aSEID) const
+	{
+	LOG_FUNC
+	CLocalSEP* sep = FindLocalSEP(aSEID);
+	if (!sep)
+		{
+		User::Leave(KErrNotFound);
+		}
+	return *sep;
+	}
+
+CAVStream* CSignallingSession::FindStreamFromRemoteSEID(const TSEID& aRemoteSEID) const
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(!aRemoteSEID.IsLocal(), Panic(EAvdtpSEIDHasWrongDomain));
+	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+	
+	while (iter)
+		{
+		CAVStream* s = iter++->Stream();
+		if (s && s->RemoteSEID()==aRemoteSEID)
+			{			
+			return s;
+			}
+		}
+	return NULL;
+	}
+
+void CSignallingSession::SignallingChannelError(TInt aError)
+	{
+	LOG_FUNC
+	// set all SEPs to be not in use
+	TDblQueIter<CLocalSEP> iter(iLocalSEPs);
+	while(iter)
+		{
+		CLocalSEP* sep = iter++;
+			
+		sep->SetInUse(EFalse);
+		// need to inform sessions - so tell stream
+		if (sep->Stream())
+			{
+			DestroyStream(sep->Stream(),aError);
+			}
+		}
+	// leave the channel
+	ClearSignallingChannel();
+	// tell the user, on all channels
+	iSAP.Error(aError);
+	iSAP.SessionDisconnect();
+	TPckgBuf<TInternalAvdtpErrorIndication> error;
+	error().iError = aError;
+	iSAP.Indication(error);
+	}
+
+// sigsession has two error paths - one by being a channel user, and the other for protocol errors
+void CSignallingSession::ServiceError(TInt aError)
+	{
+	LOG_FUNC
+	iSAP.Error(aError);
+	}
+	
+void CSignallingSession::SignallingChannelReady(CSignallingChannel& aNewChannel)
+	{
+	LOG_FUNC
+	// we may have migrated from old signalling channel to the new instance 
+	// so cannot use old signalling channel pointer
+	iSignallingChannel = &aNewChannel;
+	
+	SetRemoteAddress(aNewChannel.RemoteAddress());
+
+	if (iIsListening)
+		{
+		TInternalAvdtpSignallingReadyIndication ind;
+		ind.iBuf = aNewChannel.RemoteAddress().Des();
+		
+		TPckg<TInternalAvdtpSignallingReadyIndication> indPckg(ind);
+		iSAP.Indication(indPckg);
+		iIsListening = EFalse;
+		}
+	else
+		{
+		iSAP.Ready();
+		}
+	}
+
+void CSignallingSession::DestroyStream(CAVStream* aStream, TInt aError)
+	{
+	// tell all sessions of the error
+	aStream->NotifyUserPlaneTransportSessionsError(NULL, aError);
+	// and remove the stream
+	delete aStream;
+	}
+
+CCapabilityNotAllowedVisitor::CCapabilityNotAllowedVisitor(TAvdtpServiceCategories aLocallySupported)
+: iLocallySupported(aLocallySupported), iIsValid(ETrue)
+	{
+	LOG_FUNC
+	}
+
+TBool CCapabilityNotAllowedVisitor::Capability(TAvdtpServiceCategory aCat)
+	{
+	LOG_FUNC
+	// need to put aCat into correct bit position
+	TAvdtpServiceCategories cat;
+	cat.SetCapability(aCat);
+	
+	if ((cat() ^ iLocallySupported()) & cat())
+		{
+		// remote has wrongly used a cap we don't support, mark it as dud
+		iWrongCategory = aCat;
+		iIsValid = EFalse;
+		}
+	return iIsValid; // will therefore stop at first broken capability
+	}
+	
+TBool CCapabilityNotAllowedVisitor::IsValid() const
+	{
+	LOG_FUNC
+	return iIsValid;
+	}
+
+TAvdtpServiceCategory CCapabilityNotAllowedVisitor::WrongCategory() const
+	{
+	LOG_FUNC
+	return iWrongCategory;
+	}
+