--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/avdtp/avdtpStreamStates.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,1422 @@
+// 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 stream statemachine
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <bluetooth/logger.h>
+#include "avdtpStream.h"
+#include "avdtp.h"
+#include "avdtpSignallingChannel.h"
+#include "avdtpSignallingSession.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVDTP);
+#endif
+
+#ifdef _DEBUG
+#define DEBUGPANICINSTATE(aPanic) PanicInState(aPanic)
+#else
+#define DEBUGPANICINSTATE(aPanic)
+#endif
+
+// state ctors
+
+TAVStreamState::TAVStreamState(CAVStreamStateFactory& aFactory)
+: iFactory(aFactory)
+ {
+ STATENAME("BASE");
+ }
+
+TAVStreamStateIdle::TAVStreamStateIdle(CAVStreamStateFactory& aFactory)
+: TAVStreamState(aFactory)
+ {
+ STATENAME("Idle");
+ }
+
+TAVStreamStateOpen::TAVStreamStateOpen(CAVStreamStateFactory& aFactory)
+: TAVStreamStateIdle(aFactory)
+ {
+ STATENAME("Open");
+ }
+
+TAVStreamStateReady::TAVStreamStateReady(CAVStreamStateFactory& aFactory)
+: TAVStreamStateOpen(aFactory)
+ {
+ STATENAME("Ready");
+ }
+
+TAVStreamStateWaitForSessions::TAVStreamStateWaitForSessions(CAVStreamStateFactory& aFactory)
+: TAVStreamStateIdle(aFactory)
+ {
+ STATENAME("WaitForSessions");
+ }
+
+TAVStreamStateWaitForSessionsStartReceived::TAVStreamStateWaitForSessionsStartReceived(CAVStreamStateFactory& aFactory)
+: TAVStreamStateWaitForSessions(aFactory)
+ {
+ STATENAME("WaitForSessionsStartReceived");
+ }
+
+TAVStreamStateConfiguring::TAVStreamStateConfiguring(CAVStreamStateFactory& aFactory)
+: TAVStreamStateIdle(aFactory)
+ {
+ STATENAME("Configuring");
+ }
+
+TAVStreamStateConfigured::TAVStreamStateConfigured(CAVStreamStateFactory& aFactory)
+: TAVStreamStateIdle(aFactory)
+ {
+ STATENAME("**Abstract** Configure");
+ }
+
+TAVStreamStateINTConfigured::TAVStreamStateINTConfigured(CAVStreamStateFactory& aFactory)
+: TAVStreamStateConfigured(aFactory)
+ {
+ STATENAME("INTConfigured");
+ }
+
+TAVStreamStateACPConfigured::TAVStreamStateACPConfigured(CAVStreamStateFactory& aFactory)
+: TAVStreamStateConfigured(aFactory)
+ {
+ STATENAME("ACPConfigured");
+ }
+
+TAVStreamStateOpening::TAVStreamStateOpening(CAVStreamStateFactory& aFactory)
+: TAVStreamStateIdle(aFactory)
+ {
+ STATENAME("Opening");
+ }
+
+TAVStreamStateCreatingLogicalChannels::TAVStreamStateCreatingLogicalChannels(CAVStreamStateFactory& aFactory)
+: TAVStreamStateOpen(aFactory)
+ {
+ STATENAME("CreatingLogicalChannels");
+ }
+
+TAVStreamStateReleasing::TAVStreamStateReleasing(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Releasing");
+ }
+
+TAVStreamStateAborting::TAVStreamStateAborting(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Aborting");
+ }
+
+TAVStreamStateStreaming::TAVStreamStateStreaming(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Streaming");
+ }
+
+TAVStreamStateStarting::TAVStreamStateStarting(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Starting");
+ }
+
+TAVStreamStateSuspending::TAVStreamStateSuspending(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Suspending");
+ }
+
+TAVStreamStateWaitingForLogicalChannels::TAVStreamStateWaitingForLogicalChannels(CAVStreamStateFactory& aFactory)
+: TAVStreamStateOpen(aFactory)
+ {
+ STATENAME("WaitingForLogicalChannels");
+ }
+
+TAVStreamStateReconfiguring::TAVStreamStateReconfiguring(CAVStreamStateFactory& aFactory)
+: TAVStreamStateReady(aFactory)
+ {
+ STATENAME("Reconfiguring");
+ }
+
+
+// default state actions
+
+void TAVStreamState::Enter(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // do nothing by default
+ }
+
+void TAVStreamState::Exit(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // do nothing by default
+ }
+
+void TAVStreamState::Release(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // it already has been Released
+ aStream.Released();
+ }
+
+void TAVStreamState::AwaitLogicalChannelsL(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedAwaitLogicalChannelsEvent);
+ }
+
+void TAVStreamState::LogicalChannelsAvailable(CAVStream& /*aStream*/, TLogicalChannelFactoryTicket /*aTicket*/, TInt /*aError*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedLogicalChannelsAvailableEvent);
+ }
+
+void TAVStreamState::WatchdogFired(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedWatchdogFiredEvent);
+ }
+
+void TAVStreamState::Configured(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedConfiguredEvent);
+ }
+
+void TAVStreamState::SetConfigurationL(CAVStream& /*aStream*/,
+ RBuf8& /*aPacketBuffer*/, CSignallingChannel& /*aSignallingChannel*/,
+ TBool /*aReportingConfigured*/,
+ TBool /*aRecoveryConfigured*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedSetConfigurationEvent);
+ User::Leave(KErrNotReady);
+ }
+
+void TAVStreamState::SetConfigConfirm(CAVStream& /*aStream*/, TInt /*aResult*/,
+ TSEID /*aRemoteSEID*/, TAvdtpServiceCategory /*aFailedCategory*/) const
+ {
+ // throw away
+ }
+
+void TAVStreamState::ReconfigConfirm(CAVStream& /*aStream*/, TInt /*aResult*/,
+ TSEID /*aRemoteSEID*/, TAvdtpServiceCategory /*aFailedCategory*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+void TAVStreamState::StartConfirm(CAVStream& /*aStream*/, TInt /*aResult*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+void TAVStreamState::AbortConfirm(CAVStream& /*aStream*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+void TAVStreamState::OpenConfirm(CAVStream& /*aStream*/, TInt /*aResult*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // default, throw away weirdo response from remote
+ }
+
+void TAVStreamState::ReleaseConfirm(CAVStream& /*aStream*/, TInt /*aResult*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+void TAVStreamState::SuspendConfirm(CAVStream& /*aStream*/, TInt /*aResult*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+TInt TAVStreamState::AddSession(CAVStream& /*aStream*/,
+ TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/,
+ CTransportChannel*& /*aTransportChannel*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedAddSessionEvent);
+ return KErrNotReady;
+ }
+
+void TAVStreamState::DropSession(CAVStream& /*aStream*/, TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ DEBUGPANICINSTATE(EAvdtpUnexpectedDropSession);
+ }
+
+TInt TAVStreamState::StartReceived(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+
+TBool TAVStreamState::IsStreaming(const CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return EFalse;
+ }
+
+TInt TAVStreamState::Start(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+
+TInt TAVStreamState::Suspend(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+
+void TAVStreamState::Started(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // signalling session should have sanity checked with previous StartReceived()
+ DEBUGPANICINSTATE(EAvdtpUnexpectedStartedEvent);
+ }
+
+void TAVStreamState::Suspended(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // signalling session should have sanity checked with previous IsStreaming
+ DEBUGPANICINSTATE(EAvdtpUnexpectedSuspendedEvent);
+ }
+
+void TAVStreamState::ChangeState(CAVStream& aContext, CAVStreamStateFactory::TAVStreamStates aState) const
+ {
+ LOG_FUNC
+ aContext.iState->Exit(aContext);
+
+#ifdef __FLOG_ACTIVE
+ const TAVStreamState* const newState=&iFactory.GetState(aState);
+ LOG2(_L("Stream: State %S -> %S"), &aContext.iState->iName, &newState->iName);
+#endif //__FLOG_ACTIVE
+
+ aContext.iState=&iFactory.GetState(aState);
+ aContext.iState->Enter(aContext);
+ }
+
+void TAVStreamState::PanicInState(TAvdtpPanic aPanic) const
+ {
+ Panic(aPanic, iFactory.StateIndex(this));
+ }
+
+
+// derived states and state changes
+
+void TAVStreamStateIdle::Configured(CAVStream& aStream) const
+ {
+ // ah - going ACP
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateACPConfigured);
+ }
+
+void TAVStreamStateIdle::SetConfigurationL(CAVStream& aStream,
+ RBuf8& aPacketBuffer,
+ CSignallingChannel& aSignallingChannel,
+ TBool aReportingConfigured,
+ TBool aRecoveryConfigured) const
+ {
+ LOG_FUNC
+// An INT procedure to add in extra options the stack wishes to do, regardless of client
+// At present this is limited to mux&frag - which we do if local and remote have
+// the *capability* to do so, even if the proposed *configuration* doesnt mention it
+
+// AVDTP is daft, so have to arrange for IDs before objects exist if muxing used
+
+// we also need to base this on the number of sessions we know we're going to run
+// see 8.19.8
+// 5.4.6 allow fors no reporting session so it's not *obvious* when the 2nd element is
+// bit like not obvious what the 2nd L2cap channel will bear
+
+// further, if we're muxing, we need to see what optional sessions are proposed
+// in the configuration to see what to configure in the mux capability
+
+ TBool canMux;
+ TBool canFrag;
+ aStream.CanMuxFrag(canMux, canFrag);
+
+ TInt err = KErrNone;
+
+ if (canMux)
+ {
+ // muxing is awkward - must identify the TCs and TSs that are going to be used NOW
+ TAvdtpMultiplexingCapability* mux = aStream.CreateMuxCapabilityL(aReportingConfigured, aRecoveryConfigured, aSignallingChannel);
+
+ // ok to create packetstructure - only exchange IDs if do mux
+ err = mux->AsProtocol(aPacketBuffer);
+ }
+
+ if (!err)
+ {
+ // First check that we are in a state to send a set configuration command as
+ // we don't want to send one unless we can commit the pending configuration
+ err = aStream.iLocalSEP->CheckConfigurationState(EFalse);
+
+ if (!err)
+ {
+ err = aSignallingChannel.SendSetConfiguration(aStream,
+ aStream.LocalSEID(), aStream.RemoteSEID(), aPacketBuffer);
+ if (!err)
+ {
+ // tell SEP
+ err = aStream.iLocalSEP->SetPendingConfiguration(aPacketBuffer, EFalse); //takes ownership of RBuf
+
+ // we should not get an error here as we called CheckConfigurationState above
+ __ASSERT_DEBUG(!err, PanicInState(EAvdtpInconsistentPendingConfigurationState));
+
+ if (!err)
+ {
+ aPacketBuffer.Assign(NULL); // since ownership transfer succeeded
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateConfiguring);
+ }
+ }
+ }
+ }
+
+ if (err)
+ {
+ // clean up and don't bother proceeding
+ aStream.DeallocateUnclaimedTransportSessionIDs();
+ User::Leave(err);
+ }
+ }
+
+void TAVStreamStateIdle::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+
+void TAVStreamStateConfiguring::SetConfigConfirm(CAVStream& aStream, TInt aResult,
+ TSEID /*aRemoteSEID*/, TAvdtpServiceCategory aFailedCategory) const
+ {
+ LOG_FUNC
+ //update our state before telling others
+ TRAPD(res, aStream.iLocalSEP->CommitPendingConfigurationL(aResult==KErrNone, EFalse));
+
+ if (res!=KErrNone)
+ {
+ aResult = res;
+ }
+
+ if (aResult==KErrNone)
+ {
+ TBool rp = aStream.CheckConfigured(EServiceCategoryReporting);
+ TBool rc = aStream.CheckConfigured(EServiceCategoryRecovery);
+ aStream.iNumSessionsRequired = AvdtpInternalUtils::NumberOfTransportObjects(rp, rc);
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateINTConfigured);
+ }
+
+ aStream.iStreamNotify.StreamConfigured(aStream.LocalSEID(), aResult, aFailedCategory);
+
+ if (aResult!=KErrNone)
+ {
+ // remove the stream as the configure failed the stream is invalid
+ aStream.Released(); // deletes stream
+ }
+ }
+
+void TAVStreamStateConfiguring::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateConfigured::Release(CAVStream& aStream) const
+ {
+ // in this state to Release a stream object (cos it errored say)
+ // needs us to send an Abort rather than a Close to remote
+ // this is because the remote will need to mark its SEP as not in use,
+ // but we haven't yet sent an Open.
+ LOG_FUNC
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.iRemoteAddress.BTAddr());
+
+ if (sigch)
+ {
+ TInt err = sigch->SendAbort(aStream, aStream.RemoteSEID());
+ if (err==KErrNone)
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateAborting);
+ }
+ else
+ {
+ // just have to die
+ aStream.Released();
+ }
+ }
+ }
+
+void TAVStreamStateConfigured::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+/**
+An INT primitive
+A session is adding itself to the stream.
+Record its details and find a channel for it to use.
+Record the binding between session and channel.
+Once all the required sessions are added the stream tries to open the remote
+*/
+TInt TAVStreamStateINTConfigured::AddSession(CAVStream& aStream,
+ TAvdtpTransportSessionType aType,
+ CUserPlaneTransportSession& aSession,
+ CTransportChannel*& aChannel) const
+ {
+ LOG_FUNC
+ TInt ret = KErrNone;
+ // check GAVDP isn't being naughty and asking for an unconfigured session
+ if ((aType==EReporting && !aStream.CheckConfigured(EServiceCategoryReporting))
+ || (aType==ERecovery && !aStream.CheckConfigured(EServiceCategoryRecovery)))
+ {
+ // gavdp is trying to use a session it has never configured
+ ret = KErrNotSupported;
+ }
+
+ if (ret == KErrNone)
+ {
+ TBool useMux;
+ TBool useFrag; //ignored
+ aStream.CanMuxFrag(useMux, useFrag);
+
+ aChannel = aStream.iProtocol.GetTransportChannel(aStream.iRemoteAddress, useMux);
+
+ if (aChannel)
+ {
+ // bind session to channel
+ ret = aChannel->AttachTransportSession(aSession, aType);
+ if (ret==KErrNone)
+ {
+ // keep a copy of this binding
+ TTransportBinding binding;
+ binding.iSession = &aSession;
+ binding.iChannel = aChannel;
+
+ // keep object bindings
+ TTransportBinding* b = NULL;
+
+ switch (aType)
+ {
+ case EMedia:
+ b = &aStream.iMediaBinding;
+ break;
+ case EReporting:
+ b = &aStream.iReportingBinding;
+ break;
+ case ERecovery:
+ b = &aStream.iRecoveryBinding;
+ break;
+ }
+
+ __ASSERT_DEBUG(b, PanicInState(EAvdtpBadSessionAttachingToStream));
+ // remember binding
+ *b = binding;
+ }
+ TryToOpen(aStream);
+ }
+ else
+ {
+ ret = KErrNotReady; // TC went down...
+ }
+ }
+ return ret;
+ }
+
+/**
+One of the sessions in the stream is dropping from the stream.
+At this point the stream hadn't been opened, so don't Release stream
+Just cancel oustanding logical channel factory request
+*/
+void TAVStreamStateINTConfigured::DropSession(CAVStream& aStream, TAvdtpTransportSessionType /*aType*/, CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ aStream.iProtocol.LogicalChannelFactory().Cancel(aStream.iFactoryJob);
+ }
+
+void TAVStreamStateINTConfigured::TryToOpen(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // check how many sessions we think we need
+ // if all have added to us then we find signalling ch and issue an open
+
+ TInt numSessionsBound = (aStream.iMediaBinding.iSession ?1:0) +
+ (aStream.iReportingBinding.iSession ?1:0) +
+ (aStream.iRecoveryBinding.iSession ?1:0);
+
+
+ __ASSERT_DEBUG(numSessionsBound>=1 && numSessionsBound<=3, PanicInState(EAVDTPBadSessionCount));
+ if (numSessionsBound == aStream.iNumSessionsRequired)
+ {
+ // GO!
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.DeviceAddress());
+ TInt err = sigch ? sigch->SendOpenStream(aStream, aStream.RemoteSEID()) : KErrNotReady;
+ if (err==KErrNone)
+ {
+ // all sessions joined - so Open
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateOpening);
+ }
+ else
+ {
+ aStream.NotifyUserPlaneTransportSessionsError(NULL, err);
+ // no need to release stream - leave gavdp client to decide
+ }
+ }
+ }
+
+void TAVStreamStateINTConfigured::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateINTConfigured::SetConfigurationL(CAVStream& /*aStream*/,
+ RBuf8& /*aPacketBuffer*/,
+ CSignallingChannel& /*aSignallingChannel*/,
+ TBool /*aReportingConfigured*/,
+ TBool /*aRecoveryConfigured*/) const
+ {
+ // GAVDP spec v1.1 sect4.1.5 forbids this - must be at OPEN state before reconfiguring
+ // in our implementation this means we need to be in Ready state (thus have transport channels)
+ // yes it is weird...
+ User::Leave(KErrAvdtpInvalidStateForReconfigure);
+ }
+
+/**
+ACP configured, now need to await the Open
+*/
+
+void TAVStreamStateACPConfigured::AwaitLogicalChannelsL(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ const TBool requireReporting = aStream.CheckConfigured(EServiceCategoryReporting);
+ const TBool requireRecovery = aStream.CheckConfigured(EServiceCategoryRecovery);
+
+ TAvdtpMultiplexingCapability* const muxCap = static_cast<TAvdtpMultiplexingCapability*>
+ (aStream.iLocalSEP->Configuration()[EServiceCategoryMultiplexing]);
+
+ if (muxCap)
+ {
+ TAvdtpMultiplexingCapabilityHelper helper(*muxCap, requireReporting, requireRecovery);
+ DoAwaitMuxedChannelsL(aStream, helper, requireReporting, requireRecovery);
+ }
+ else
+ {
+ DoAwaitDirectChannelsL(aStream, requireReporting, requireRecovery);
+ }
+ }
+
+
+void TAVStreamStateACPConfigured::DoAwaitMuxedChannelsL(CAVStream& aStream,
+ TAvdtpMultiplexingCapabilityHelper& aHelper,
+ TBool aRequireReporting,
+ TBool aRequireRecovery) const
+ {
+ LOG_FUNC
+ TInt numExtraLogicalChannelsNeeded=0;
+ TAvdtpSockAddr address = aStream.iRemoteAddress;
+ // get TCIDs for the sessions in the mux record
+ // this will indicate the TCIDs that the INT has proposed
+
+ // we look for mux channels with any TCIDs proposed
+ // and reduce thus reduce the number of TCs we expect
+ CTransportChannel** tcPtr = &aStream.iMediaBinding.iChannel;
+
+ *tcPtr = aStream.iProtocol.FindMuxChannel(aHelper.MediaCID());
+ if (!*tcPtr)
+ {
+ address.SetSession(EMedia);
+ *tcPtr = aStream.iProtocol.GetTransportChannel(address, ETrue, aHelper.MediaCID());
+ User::LeaveIfNull(*tcPtr);
+ numExtraLogicalChannelsNeeded++;
+ }
+
+ tcPtr = &aStream.iReportingBinding.iChannel;
+ if (aRequireReporting)
+ {
+ __ASSERT_DEBUG(aHelper.ReportingCID() != KInvalidTCID, PanicInState(EAVDTPBadMuxConfiguration));
+ *tcPtr = aStream.iProtocol.FindMuxChannel(aHelper.ReportingCID());
+ if (!*tcPtr)
+ {
+ // might need a new channel
+ if (aHelper.ReportingCID()!=aHelper.MediaCID())
+ {
+ address.SetSession(EReporting);
+ *tcPtr = aStream.iProtocol.GetTransportChannel(address, ETrue, aHelper.ReportingCID());
+ User::LeaveIfNull(*tcPtr);
+ numExtraLogicalChannelsNeeded++;
+ }
+ // else remote has proposed putting reporting in same channel as media
+ }
+ }
+
+ tcPtr = &aStream.iRecoveryBinding.iChannel;
+ if (aRequireRecovery)
+ {
+ __ASSERT_DEBUG(aHelper.RecoveryCID() != KInvalidTCID, PanicInState(EAVDTPBadMuxConfiguration));
+ *tcPtr = aStream.iProtocol.FindMuxChannel(aHelper.RecoveryCID());
+ if (!*tcPtr)
+ {
+ // might need a new channel
+ if (aHelper.RecoveryCID()!=aHelper.MediaCID() && aHelper.RecoveryCID()!=aHelper.ReportingCID())
+ {
+ address.SetSession(ERecovery);
+ *tcPtr = aStream.iProtocol.GetTransportChannel(address, ETrue, aHelper.RecoveryCID());
+ User::LeaveIfNull(*tcPtr);
+ numExtraLogicalChannelsNeeded++;
+ }
+ else if (aHelper.RecoveryCID()==aHelper.MediaCID())
+ {
+ __DEBUGGER();
+ User::Leave(KErrCorrupt); // remote has contravened spec
+ }
+ }
+ }
+
+ if (!numExtraLogicalChannelsNeeded)
+ {
+ // everything we need is already here, kick state machine and wait for sessions to attach
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateWaitForSessions);
+ // tell signalling session
+ aStream.iStreamNotify.StreamAccepted(aStream.LocalSEID(),
+ aStream.RemoteSEID(), aRequireReporting, aRequireRecovery);
+ }
+ else
+ {
+ // TCs were created above, now wait for appropriate logical channels
+ aStream.iFactoryJob = aStream.iProtocol.LogicalChannelFactory().
+ ExpectSessionLogicalChannelsL(aStream,
+ numExtraLogicalChannelsNeeded);
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateWaitingForLogicalChannels);
+ }
+ }
+
+
+void TAVStreamStateACPConfigured::DoAwaitDirectChannelsL(CAVStream& aStream,
+ TBool aRequireReporting,
+ TBool aRequireRecovery) const
+ {
+ LOG_FUNC
+ // create the necessary Transport Channels ready for the logical channels
+ // assume all inbound TCs are mux -our seps always do muxing, and allows for "upgrades"
+ // if others SEPs want to add sessions to them later
+
+ TInt numExtraLogicalChannelsNeeded = 0;
+ TAvdtpSockAddr address = aStream.iRemoteAddress;
+ address.SetSession(EMedia);
+
+#ifdef __SYMBIAN_AVDTP_HIDE_MUX
+ #define CAN_BECOME_MUX EFalse
+#else
+#pragma message("Not sure if this true - remember morgan, cannot upgrade as dont know which "direct" channel has which TCID")
+ #define CAN_BECOME_MUX ETrue
+#endif
+
+ aStream.iMediaBinding.iChannel = aStream.iProtocol.GetTransportChannel(address, CAN_BECOME_MUX);
+ User::LeaveIfNull(aStream.iMediaBinding.iChannel);
+ numExtraLogicalChannelsNeeded++;
+
+ if (aRequireReporting)
+ {
+ address.SetSession(EReporting);
+ aStream.iReportingBinding.iChannel = aStream.iProtocol.GetTransportChannel(address, CAN_BECOME_MUX);
+ User::LeaveIfNull(aStream.iReportingBinding.iChannel);
+ numExtraLogicalChannelsNeeded++;
+ }
+
+ if (aRequireRecovery)
+ {
+ address.SetSession(ERecovery);
+ aStream.iRecoveryBinding.iChannel = aStream.iProtocol.GetTransportChannel(address, CAN_BECOME_MUX);
+ User::LeaveIfNull(aStream.iRecoveryBinding.iChannel);
+ numExtraLogicalChannelsNeeded++;
+ }
+
+ LOG1(_L8("Awaiting %d logical channels"), numExtraLogicalChannelsNeeded);
+
+ // wait for appropriate logical channels
+ aStream.iFactoryJob = aStream.iProtocol.LogicalChannelFactory().
+ ExpectSessionLogicalChannelsL(aStream,
+ numExtraLogicalChannelsNeeded);
+
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateWaitingForLogicalChannels);
+ }
+
+TInt TAVStreamStateACPConfigured::AddSession(CAVStream& /*aStream*/,
+ TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/,
+ CTransportChannel*& /*aTransportChannel*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+
+void TAVStreamStateACPConfigured::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+
+void TAVStreamStateOpen::DropSession(CAVStream& aStream, TAvdtpTransportSessionType /*aType*/, CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ // if any session in the stream is shutdown
+ // we invalidate the stream, and thus send a Release
+
+ // we leave the GC to actually shutdown the session saps
+ DoRelease(aStream);
+ // leave unbinding transport objects until ReleaseConfirm
+ }
+
+void TAVStreamStateOpen::Release(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // we need to Release this as the object is going
+ DoRelease(aStream);
+ }
+
+void TAVStreamStateOpen::DoRelease(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.iRemoteAddress.BTAddr());
+
+ if (sigch)
+ {
+ sigch->SendRelease(aStream, aStream.RemoteSEID());
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReleasing);
+ }
+ }
+
+void TAVStreamStateOpen::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+TInt TAVStreamStateReady::AddSession(CAVStream& /*aStream*/,
+ TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/,
+ CTransportChannel*& /*aTransportChannel*/) const
+{
+LOG_FUNC
+#ifdef _DEBUG
+return KErrPanicAvdtpOpenInBadState;
+#else
+return KErrNotReady;
+#endif
+}
+
+void TAVStreamStateReady::SetConfigurationL(CAVStream& aStream,
+ RBuf8& aPacketBuffer,
+ CSignallingChannel& aSignallingChannel,
+ TBool __DEBUG_ONLY(aReportingConfigured),
+ TBool __DEBUG_ONLY(aRecoveryConfigured)) const
+ {
+ // this is a Reconfigure - see GAVDP spec
+ LOG_FUNC
+ __ASSERT_DEBUG(!aReportingConfigured && !aRecoveryConfigured, PanicInState(EAvdtpReconfigurationCapabilitiesNotChecked));
+
+ // First check that we are in a state to send a reconfigure command as
+ // we don't want to send one unless we can commit the pending configuration
+ TInt err = aStream.iLocalSEP->CheckConfigurationState(ETrue);
+
+ if (!err)
+ {
+ err = aSignallingChannel.SendReconfigure(aStream, aStream.RemoteSEID(), aPacketBuffer);
+
+ if (!err)
+ {
+ // tell SEP
+ err = aStream.iLocalSEP->SetPendingConfiguration(aPacketBuffer, ETrue); //takes ownership of RBuf
+
+ // we should not get an error here as we called CheckConfigurationState above
+ __ASSERT_DEBUG(!err, PanicInState(EAvdtpInconsistentPendingReconfigurationState));
+
+ if (!err)
+ {
+ aPacketBuffer.Assign(NULL); // since ownership transfer succeeded
+ // release configuration buffer as we own it in this state
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReconfiguring);
+ }
+ }
+ }
+
+ User::LeaveIfError(err);
+ }
+
+/**
+ * Before the OpenStream returns, gavdp might get Cancel()ed. At this point we have an outstanding
+ * request on the signalling channel. We can't issue a cancel on the individual request, and we
+ * can't close sigch down as it's shared, but there should only be one outstanding for this stream,
+ * so we can cancel all transactions for it.
+ */
+void TAVStreamStateOpening::DropSession(CAVStream& aStream, TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.DeviceAddress());
+ __ASSERT_DEBUG(sigch, PanicInState(EAvdtpSignallingChannelShouldExist));
+ sigch->CancelTransactions(aStream);
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateIdle);
+ }
+
+void TAVStreamStateOpening::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateOpening::OpenConfirm(CAVStream& aStream, TInt aResult, TSEID __DEBUG_ONLY(aRemoteSEID)) const
+ {
+ LOG_FUNC
+ // good!
+ __ASSERT_DEBUG(aRemoteSEID == aStream.RemoteSEID(), PanicInState(EAvdtpConfirmAddressedToWrongRequester));
+ TInt ret = KErrNone;
+
+// now we kick TCs into life
+ if (aResult)
+ {
+ // can return to Idle, user could try this operation again
+ // the way Open works means we have transport sessions interested in result of this
+ // they need to tell their sockets that their connects failed
+
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateIdle);
+
+ // no need to tell signalling session as Opening is not available to RGavdp
+ // Opening is performed when the necessary sockets are created and connected in a stream
+ aStream.NotifyUserPlaneTransportSessionsError(NULL, aResult);
+ }
+ else
+ {
+ // create a job - see what logical channels need creating
+ TInt numLogicalChannelsRequired =
+ aStream.iMediaBinding.iChannel->IsConnected() ? 0 : 1;
+
+ if (aStream.iReportingBinding.iChannel)
+ {
+ // a reporting transport channel is required - but is it available?
+ if (!aStream.iReportingBinding.iChannel->IsConnected())
+ {
+ // this is required, so add into job
+ numLogicalChannelsRequired++;
+ }
+ }
+
+ if (aStream.iRecoveryBinding.iChannel)
+ {
+ // a recovery transport channel is required - but is it available?
+ if (!aStream.iRecoveryBinding.iChannel->IsConnected())
+ {
+ // this is required, so add into job
+ numLogicalChannelsRequired++;
+ }
+ }
+
+ if (numLogicalChannelsRequired)
+ {
+ // if either required, kick off request...
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateCreatingLogicalChannels);
+ TLogicalChannelFactoryTicket ticket;
+ TRAP(ret, ticket=aStream.iProtocol.LogicalChannelFactory().CreateSessionLogicalChannelsL(
+ aStream.iRemoteAddress.BTAddr(),
+ aStream, numLogicalChannelsRequired));
+ if (ret==KErrNone)
+ {
+ aStream.iFactoryJob = ticket; // record this, so we can cancel if needed
+ }
+ else
+ {
+ // stay in same state
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateOpening);
+ }
+ }
+ else
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateOpen);
+ // all TCs appear to be available without creating new ones
+ aStream.TransportChannelsReady();
+ }
+ }
+ }
+
+
+TInt TAVStreamStateReady::StartReceived(CAVStream& aStream) const
+ {
+ LOG_FUNC
+
+ aStream.ReadyForStartIndication();
+
+ return KErrNone;
+ }
+
+TInt TAVStreamStateReady::Start(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ TInt retVal = KErrNone;
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.iRemoteAddress.BTAddr());
+
+ // should always have sigch here - hence function signature
+ __ASSERT_DEBUG(sigch, PanicInState(EAvdtpSignallingChannelShouldExist));
+ if (sigch)
+ {
+ retVal = sigch->SendStartStream(aStream, aStream.RemoteSEID());
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateStarting);
+ }
+ return retVal;
+ }
+
+void TAVStreamStateReady::Started(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateStreaming);
+ }
+
+void TAVStreamStateReady::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateStarting::Enter(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // Tell the physical link that encryption keys could be refreshed now, to prevent an auto refresh later
+ aStream.TryToAndThenPreventHostEncryptionKeyRefresh();
+ }
+
+
+void TAVStreamStateStarting::StartConfirm(CAVStream& aStream, TInt aResult, TSEID /*aRemoteSEID*/) const
+ {
+ LOG_FUNC
+ // just change state
+ if (aResult==KErrNone)
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateStreaming);
+ aStream.iStreamNotify.StreamStarted(aStream.LocalSEID());
+ }
+ else
+ {
+ // whether suspended or idle, we return to ready
+ // but first release the prevent encryption key refresh token
+ aStream.AllowHostEncryptionKeyRefresh();
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, aResult);
+ }
+ }
+
+TInt TAVStreamStateStarting::StartReceived(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+
+ // we need to tell the other end 'nope we're busy' because the starts 'crossed in the post'
+ // returning KErrInUse will tell the other end to go away (politely of course)
+ return KErrInUse;
+ }
+
+
+void TAVStreamStateReleasing::Release(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // we are already releasing so do nothing.
+ }
+
+void TAVStreamStateReleasing::ReleaseConfirm(CAVStream& aStream, TInt /*aResult*/, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ // ignore error - proceed anyway
+ aStream.Released();
+ }
+
+void TAVStreamStateReleasing::DropSession(CAVStream& /*aStream*/, TAvdtpTransportSessionType /*aType*/, CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ // to guard against sending multiple Releases per dropped session
+ // since we're releasing, we don't need to send a Release, but we just consume
+ }
+
+void TAVStreamStateReleasing::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+
+void TAVStreamStateAborting::AbortConfirm(CAVStream& aStream, TSEID /*aSEID*/) const
+ {
+ LOG_FUNC
+ aStream.Released();
+ }
+
+void TAVStreamStateAborting::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+
+void TAVStreamStateAborting::Release(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // we are already releasing so do nothing.
+ }
+
+
+void TAVStreamStateCreatingLogicalChannels::LogicalChannelsAvailable(CAVStream& aStream, TLogicalChannelFactoryTicket aTicket, TInt aError) const
+ {
+ LOG_FUNC
+ aStream.iFactoryJob = aTicket;
+ aStream.BindLogicalAndTransportChannels(aTicket, aError);
+
+ if (aError==KErrNone)
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ // tell sessions...
+ aStream.TransportChannelsReady();
+ }
+ else
+ {
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, aError);
+ }
+ }
+
+
+void TAVStreamStateCreatingLogicalChannels::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateWaitingForLogicalChannels::Enter(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+
+ // start guard timer in case logical channels never arrive for TCs
+ aStream.StartWatchdog();
+ }
+
+void TAVStreamStateWaitingForLogicalChannels::LogicalChannelsAvailable(CAVStream& aStream, TLogicalChannelFactoryTicket aResponse, TInt aError) const
+ {
+ LOG_FUNC
+ // we created the transport channels in :Await, so now we can bind
+ // then the sessions can call :AddSession and scoop up the TCs
+ aStream.iFactoryJob = aResponse;
+ aStream.BindLogicalAndTransportChannels(aResponse, aError);
+
+ if (aError==KErrNone)
+ {
+ const TBool reportingPresent = aStream.iReportingBinding.iChannel ? ETrue : EFalse;
+ const TBool recoveryPresent = aStream.iRecoveryBinding.iChannel ? ETrue : EFalse;
+
+ aStream.iNumSessionsRequired = AvdtpInternalUtils::NumberOfTransportObjects(reportingPresent, recoveryPresent);
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateWaitForSessions);
+ // tell signalling session
+ aStream.iStreamNotify.StreamAccepted(aStream.LocalSEID(),
+ aStream.RemoteSEID(), reportingPresent, recoveryPresent);
+ }
+ else
+ {
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, aError);
+ }
+ }
+
+void TAVStreamStateWaitingForLogicalChannels::DropSession(CAVStream& aStream, TAvdtpTransportSessionType /*aType*/,
+ CUserPlaneTransportSession& /*aSession*/) const
+ {
+ LOG_FUNC
+ aStream.iProtocol.LogicalChannelFactory().Cancel(aStream.iFactoryJob);
+ }
+
+void TAVStreamStateWaitingForLogicalChannels::Exit(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // start guard timer in case logical channels never arrive for TCs
+ aStream.StopWatchdog();
+ }
+
+void TAVStreamStateWaitingForLogicalChannels::WatchdogFired(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // need to tidy TCs, and Abort stream and cancel job
+ TLogicalChannelFactoryTicket nullTicket;
+
+ aStream.BindLogicalAndTransportChannels(nullTicket, KErrTimedOut);
+
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, KErrTimedOut);
+ }
+
+
+/**
+An ACP primitive: the TCs & LCs are ready, now we are awaiting the sessions
+to come in and connect to the TCs. The sessions do so at the behest of GAVDP
+*/
+TInt TAVStreamStateWaitForSessions::AddSession(CAVStream& aStream,
+ TAvdtpTransportSessionType aType,
+ CUserPlaneTransportSession& aSession,
+ CTransportChannel*& aChannel) const
+ {
+ LOG_FUNC
+ TInt ret = KErrNone;
+
+ // bind session to channel - the channel is there, we'd have been told if it had gone
+ TTransportBinding* b = NULL;
+
+ switch (aType)
+ {
+ case EMedia:
+ b = &aStream.iMediaBinding;
+ break;
+ case EReporting:
+ // check GAVDP isn't being naughty and asking for an unconfigured session
+ if (aStream.CheckConfigured(EServiceCategoryReporting))
+ {
+ b = &aStream.iReportingBinding;
+ }
+ else
+ {
+ // GAVDP asking for a bearer that is not configured
+ ret = KErrNotSupported;
+ }
+ break;
+ case ERecovery:
+ // check GAVDP isn't being naughty and asking for an unconfigured session
+ if (aStream.CheckConfigured(EServiceCategoryRecovery))
+ {
+ b = &aStream.iRecoveryBinding;
+ }
+ else
+ {
+ // GAVDP asking for a bearer that is not configured
+ ret = KErrNotSupported;
+ }
+ break;
+ default:
+ PanicInState(EAvdtpBadSessionAttachingToStream);
+ }
+
+ if (ret == KErrNone)
+ {
+ ret = b->iChannel->AttachTransportSession(aSession, aType);
+ if (ret==KErrNone)
+ {
+ // stream needs to remember binding
+ b->iSession = &aSession;
+ // and session need to know channel
+ aChannel = b->iChannel;
+ // check if all sessions have bound
+ if (!--aStream.iNumSessionsRequired)
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ aStream.TransportChannelsReady();
+ }
+ }
+ }
+ return ret;
+ }
+
+TInt TAVStreamStateWaitForSessions::StartReceived(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateWaitForSessionsStartReceived);
+ return KErrNone;
+ }
+
+void TAVStreamStateWaitForSessions::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+/**
+Overrides the method in TAVStreamStateWaitForSessions. The start has already been received by
+CSignallingSession::StartIndication, so after changing the state to EStreamStateReady data
+stored in the CAVStream object will be used to pass a start indication to GAVDP.
+*/
+TInt TAVStreamStateWaitForSessionsStartReceived::AddSession(CAVStream& aStream,
+ TAvdtpTransportSessionType aType,
+ CUserPlaneTransportSession& aSession,
+ CTransportChannel*& aChannel) const
+ {
+ LOG_FUNC
+ // Call the function from the parent class to bind the session
+ TInt ret = TAVStreamStateWaitForSessions::AddSession(aStream,aType,aSession,aChannel);
+
+ // if that worked, and all the channels are bound, we can now issue the delayed start
+ if((ret == KErrNone) && (!aStream.iNumSessionsRequired))
+ {
+ aStream.ReadyForStartIndication();
+ }
+
+ return ret;
+ }
+
+TInt TAVStreamStateWaitForSessionsStartReceived::StartReceived(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+
+void TAVStreamStateWaitForSessionsStartReceived::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateSuspending::SuspendConfirm(CAVStream& aStream, TInt aResult, TSEID /*aRemoteSEID*/) const
+ {
+ LOG_FUNC
+ // just change state
+ if (aResult==KErrNone)
+ {
+ // no difference between a "suspended" state, and ready
+ // making them the same helps support reconfig in more states
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ aStream.iStreamNotify.StreamSuspended(aStream.LocalSEID());
+ }
+ else
+ {
+ // stay in streaming state and notify the user of the error
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateStreaming);
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, aResult);
+ }
+ }
+
+void TAVStreamStateSuspending::Suspended(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ // throw away
+ }
+
+
+void TAVStreamStateSuspending::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+void TAVStreamStateReconfiguring::ReconfigConfirm(CAVStream& aStream, TInt aResult,
+ TSEID /*aRemoteSEID*/, TAvdtpServiceCategory aFailedCategory) const
+ {
+ LOG_FUNC
+ // ok to return to ready on success or failure
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ TRAPD(err, aStream.iLocalSEP->CommitPendingConfigurationL(aResult==KErrNone, ETrue));
+ if (err!=KErrNone)
+ {
+ aStream.iStreamNotify.StreamInitiatedServiceFailed(aStream, aResult);
+ }
+ aStream.iStreamNotify.StreamConfigured(aStream.LocalSEID(), aResult, aFailedCategory);
+ }
+
+void TAVStreamStateReconfiguring::Enter(CAVStream& __DEBUG_ONLY(aStream)) const
+ {
+ LOG_FUNC
+ //We should not be preventing the encryption key refresh in this state. Asserting this condition.
+ __ASSERT_DEBUG(!aStream.IsHostEncryptionKeyRefreshPrevented(),Panic(EUnexpectedEncryptionKeyRefreshPrevent));
+ }
+
+
+void TAVStreamStateStreaming::Enter(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ // experiments with window dragging show not much change if thread priority bumped
+ // maybe due to trying to get into esock in the first place
+ // Changing the role of the Esock_BT thread in the cmi file, from player to
+ // DealerPlayer allows messages to be passed directly to the Esock_BT thread
+
+ aStream.iOriginalESockBTPriority = RThread().Priority(); //save the original priority of the Esock_BT thread.
+ RThread().SetPriority(EPriorityRealTime);
+
+ }
+
+void TAVStreamStateStreaming::Exit(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ RThread().SetPriority(aStream.iOriginalESockBTPriority);//set the priority of the thread back to the original value.
+
+ // Tell the physical link that encryption keys could be refreshed now, to prevent an auto refresh later
+ aStream.AllowHostEncryptionKeyRefresh();
+ }
+
+TInt TAVStreamStateStreaming::Suspend(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ TInt retVal = KErrNone;
+ CSignallingChannel* sigch = aStream.iProtocol.FindSignallingChannel(aStream.iRemoteAddress.BTAddr());
+
+ __ASSERT_DEBUG(sigch, PanicInState(EAvdtpSignallingChannelShouldExist));
+ if (sigch)
+ {
+ retVal = sigch->SendSuspendStream(aStream, aStream.RemoteSEID());
+ if (retVal==KErrNone)
+ {
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateSuspending);
+ }
+ }
+ return retVal;
+ }
+
+void TAVStreamStateStreaming::Suspended(CAVStream& aStream) const
+ {
+ LOG_FUNC
+ ChangeState(aStream, CAVStreamStateFactory::EStreamStateReady);
+ }
+
+TBool TAVStreamStateStreaming::IsStreaming(const CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return ETrue;
+ }
+
+TInt TAVStreamStateStreaming::Start(CAVStream& /*aStream*/) const
+ {
+ // don't want to tell remote to Start when already Streaming, cos it's BadState
+ return KErrNotReady;
+ }
+
+TInt TAVStreamStateStreaming::StartReceived(CAVStream& /*aStream*/) const
+ {
+ LOG_FUNC
+ return KErrNotReady;
+ }
+