diff -r 000000000000 -r f63038272f30 bluetoothengine/btsac/src/btsacStateConfigured.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/btsac/src/btsacStateConfigured.cpp Mon Jan 18 20:28:57 2010 +0200 @@ -0,0 +1,388 @@ +/* +* Copyright (c) 2002-2005 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: In this state, avdtp link is ready to be used and btsac opens +* audio automatically if there is request pending otherwise +* it will wait open audio request. +* +*/ + + + + +// INCLUDE FILES +#include "btsacStateConfigured.h" +#include "btsacStateListening.h" +#include "btsacStateStreaming.h" +#include "btsacStateAborting.h" +#include "btsacactive.h" +#include "btsacGavdp.h" +#include "btsacSEPManager.h" +#include "btsacStreamerController.h" +#include "debug.h" + +// A2DP codec-specific element definitions +// in bluetoothAV.h +using namespace SymbianBluetoothAV; + +// Subband codec-specific values +// in bluetoothAV.h +using namespace SymbianSBC; + +const TInt KStartIndicationDelay = 1000000; // 1 sec + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::NewL +// ----------------------------------------------------------------------------- +// +CBtsacConfigured* CBtsacConfigured::NewL(CBTSAController& aParent, RSocket aNewSocket, + TAudioOpenedBy aAudioOpenedBy, TStreamConfiguredBy aStreamConfiguredBy) + { + CBtsacConfigured* self = new( ELeave ) CBtsacConfigured(aParent, aNewSocket, aAudioOpenedBy, aStreamConfiguredBy); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::CBtsacConfigured +// ----------------------------------------------------------------------------- +// +CBtsacConfigured::CBtsacConfigured(CBTSAController& aParent, RSocket aNewSocket, + TAudioOpenedBy aAudioOpenedBy, TStreamConfiguredBy aStreamConfiguredBy) +: CBtsacState(aParent, EStateConfigured), iAudioOpenedBy(aAudioOpenedBy), + iStreamConfiguredBy(aStreamConfiguredBy), iStartStreamStatus(EStartNone) + { + TRACE_ASSERT(Parent().iStreamingSockets.Count() == 0, EBTPanicSocketExists) + TRACE_INFO((_L("[SOCKET] created."))) + Parent().iStreamingSockets.Append(aNewSocket); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::ConstructL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::ConstructL() + { + iTimerActive = CBtsacActive::NewL(*this, CActive::EPriorityStandard, KRequestIdTimer); + iTimer.CreateLocal(); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::~CBtsacConfigured +// ----------------------------------------------------------------------------- +// +CBtsacConfigured::~CBtsacConfigured() + { + TRACE_FUNC + delete iTimerActive; + iTimerActive = NULL; + iTimer.Close(); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::EnterL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::EnterL() + { + TRACE_STATE(_L("[BTSAC State] Configured")) + _LIT(KName, "CBtsacStateConfigured"); + const TDesC& Name = KName; + Parent().iGavdp->RegisterObserver(this, Name); + + // ** OPEN AUDIO automatically ** + if(iStreamConfiguredBy == EStreamConfiguredBySrc) + { + if(Parent().IsOpenAudioReqFromAccFWPending()) + { + TInt err; + TRAP(err, OpenAudioLinkL(Parent().GetRemoteAddr())); + if( err ) + { + Parent().CompletePendingRequests(KOpenAudioReq, err); + } + } + } + else // Stream configured by sink + { + if(iAudioOpenedBy == EAudioOpenedByAcc) + { + GAVDP_StartIndication(TSEID(1, ETrue)); + } + else if(Parent().IsOpenAudioReqFromAccFWPending()) + { + // Start timer to protect such a situation that we will not receive StartIndication from remote end. + StartTimer(KStartIndicationDelay); + } + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::StartTimer +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::StartTimer(TTimeIntervalMicroSeconds32 aTimeout) + { + TRACE_FUNC + if (iTimerActive) + { + if(!iTimerActive->IsActive()) + { + iTimer.After(iTimerActive->iStatus, aTimeout); + iTimerActive->GoActive(); + } + } + else + { + TRACE_INFO((_L("CBtsacConfigured::StartTimer, Timer Active doesn't exist."))) + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::StopTimer +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::StopTimer() + { + TRACE_FUNC + if (iTimerActive) + { + iTimerActive->Cancel(); + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::CancelActionL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::CancelActionL(TInt aError, TBTSACGavdpResetReason aGavdpReset) + { + TRACE_FUNC + Parent().CompletePendingRequests(KOpenAudioReq, aError); + Parent().ChangeStateL(CBtsacListening::NewL(Parent(), aGavdpReset, aError)); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::CancelConnectL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::CancelConnectL() + { + TRACE_FUNC + CancelActionL(KErrCancel, EGavdpResetReasonGeneral); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::OpenAudioLinkL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::OpenAudioLinkL(const TBTDevAddr& aAddr) + { + TRACE_FUNC + if((iStreamConfiguredBy == EStreamConfiguredBySrc) || (iAudioOpenedBy == EAudioOpenedByAFW)) + { + TAvdtpSEPInfo SEPInfo; + iStartStreamStatus = EStartSendBySrc; + if (Parent().iRemoteSEPs->GetInfo(Parent().GetSEPIndex(), SEPInfo) || (aAddr != Parent().GetRemoteAddr() )) + { + TRACE_INFO((_L("TStateConfigured::OpenAudio Couldn't retrieve SEP Info !"))) + Parent().CompletePendingRequests(KOpenAudioReq, KErrGeneral); + return; + } + Parent().SetRemoteAddr(aAddr); + TSEID remoteSEPid = SEPInfo.SEID(); + Parent().iGavdp->StartStreams(remoteSEPid); + } + else + { + // Remote end (sink) has configured us. We can't call StartStreams. Complete audio req later, + // after we have received start indication from the remote (sink). + + // Start timer to protect such a situation that we will not receive StartIndication from remote end. + StartTimer(KStartIndicationDelay); + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::CancelOpenAudioLinkL() +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::CancelOpenAudioLinkL() + { + TRACE_FUNC + CancelActionL(KErrCancel, EGavdpResetReasonGeneral); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::DisconnectL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::DisconnectL() + { + TRACE_FUNC + Parent().CompletePendingRequests(KDisconnectReq, KErrNone); + // Cancel all other requests + Parent().CompletePendingRequests(KCompleteAllReqs, KErrCancel); + Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonGeneral, KErrNone)); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::GAVDP_StartStreamsConfirm() +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::GAVDP_StartStreamsConfirm() + { + TRACE_FUNC + if ( Parent().iStreamer->StartStream(Parent().iStreamingSockets[0], Parent().iStreamer->FrameLength()) != KErrNone ) + { + TRACE_INFO((_L("CBtsacConfigured::GAVDP_StartStreamsConfirm() [ERR] Could not start streaming!"))) + TInt err = Parent().AbortStream(); + if(err) + { + TRACE_INFO((_L("CBtsacConfigured::GAVDP_StartStreamsConfirm() [ERR] Couldn't abort stream."))) + } + TRAP_IGNORE(CancelActionL(KErrNotReady, EGavdpResetReasonGeneral)); + } + else + { + TBool Collision = iStartStreamStatus == EStartCollision ? ETrue : EFalse; + Parent().CompletePendingRequests(KOpenAudioReq, KErrNone); + TRAP_IGNORE(Parent().ChangeStateL(CBtsacStreaming::NewL(Parent(), EAudioOpenedByAFW, Collision))); + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::GAVDP_StartIndication +// ----------------------------------------------------------------------------- +// +TInt CBtsacConfigured::GAVDP_StartIndication(TSEID aLocalSEID) + { + TRACE_INFO((_L("CBtsacConfigured::GAVDP_StartIndication() aLocalSEID:%d"), aLocalSEID.SEID())) + (void) aLocalSEID; + StopTimer(); + // Check if acc fw has already requested to open audio + if(Parent().IsOpenAudioReqFromAccFWPending()) + { + if(iStartStreamStatus == EStartSendBySrc) + { + // Src has also sent start stream cmd. + iStartStreamStatus = EStartCollision; + } + + GAVDP_StartStreamsConfirm(); + } + else + { + // Accessory has send this indication. + // CBtsacStreaming state can use this indication to start audio automatically then later. + TRAPD(err, Parent().ChangeStateL(CBtsacStreaming::NewL(Parent(), EAudioOpenedByAcc, EFalse))); + if (err) + { + TRACE_INFO((_L("CBtsacConfigured::GAVDP_StartIndication() Couldn't change state."))) + return KErrNoMemory; + } + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::RequestCompletedL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::RequestCompletedL(CBtsacActive& aActive) + { + TRACE_FUNC + switch(aActive.RequestId()) + { + case KRequestIdTimer: + { + if(Parent().IsOpenAudioReqFromAccFWPending()) + { + // Well, seems that accessory didn't send us GAVDP_StartIndication. Let's try to open audio. + // Over write iAudioOpenedBy previous value and call open audio + iAudioOpenedBy = EAudioOpenedByAFW; + OpenAudioLinkL(Parent().GetRemoteAddr()); + } + break; + } + default: + { + TRACE_INFO((_L("CBtsacConfigured::RequestCompletedL() Unknown request"))) + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::CancelRequest +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::CancelRequest(CBtsacActive& aActive) + { + TRACE_FUNC + if(aActive.RequestId() == KRequestIdTimer ) + { + iTimer.Cancel(); + } + else + { + TRACE_INFO((_L("CBtsacConfigured::CancelRequest() Unknown request"))) + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfigured::HandleGavdpErrorL +// ----------------------------------------------------------------------------- +// +void CBtsacConfigured::HandleGavdpErrorL(TInt aError) + { + TRACE_FUNC + StopTimer(); + switch (aError) + { + case KErrAvdtpRequestTimeout: // -18005 + case (KErrAvdtpSignallingErrorBase - EAvdtpBadState): // 18094 + { + TRACE_INFO((_L("CBtsacConfigured::HandleGavdpErrorL() Request TIMEOUT/Bad state"))) + TInt err = Parent().AbortStream(); + if(!err) + { + // Complete Connect/Audio requests in Aborting state + Parent().ChangeStateL(CBtsacAborting::NewL(Parent())); + } + else + { + CancelActionL(KErrDisconnected, EGavdpResetReasonGeneral); + } + break; + } + case KErrHCILinkDisconnection: // -6305 + case KErrDisconnected: // -36 + { + TRACE_INFO((_L("CBtsacConfigured::HandleGavdpErrorL() Signalling disconnected."))) + CancelActionL(aError, EGavdpResetReasonNone); + break; + } + default: + { + CancelActionL(KErrDisconnected, EGavdpResetReasonGeneral); + break; + } + } + } + +// End of File