bluetoothengine/btsac/src/btsacStateListening.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btsac/src/btsacStateListening.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,442 @@
+/*
+* 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, BTSAC is listening for remote connection
+*								 from a stereo audio accessory
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "btsacStateListening.h"
+#include "btsacStateConnected.h"
+#include "btsacStateConnecting.h"
+#include "btsacStateConfiguring.h"
+#include "btsacactive.h"
+#include "btsacGavdp.h"
+#include "debug.h"
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::NewL
+// -----------------------------------------------------------------------------
+//
+CBtsacListening* CBtsacListening::NewL(CBTSAController& aParent,
+	TBTSACGavdpResetReason aGavdpResetReason, TInt aDisconnectReason)
+    {
+    CBtsacListening* self = new( ELeave ) CBtsacListening(aParent, aGavdpResetReason, aDisconnectReason);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::CBtsacListening
+// -----------------------------------------------------------------------------
+//
+CBtsacListening::CBtsacListening(CBTSAController& aParent,
+	TBTSACGavdpResetReason aGavdpResetReason, TInt aDisconnectReason)
+: 	CBtsacState(aParent, EStateListening), iGavdpResetReason(aGavdpResetReason),
+	iDisconnectReason(aDisconnectReason), iPendingRequests(KRequestNone),
+	iInitializationProcedure(EInitProcedureOngoing), iUnfinishedGavdpError(EFalse)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::ConstructL()
+	{
+	iSelfCompleteActive = CBtsacActive::NewL(*this, CActive::EPriorityStandard, KRequestIdSelfComplete);
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::~CBtsacListening
+// -----------------------------------------------------------------------------
+//    
+CBtsacListening::~CBtsacListening()
+    {
+    TRACE_FUNC
+    delete iSelfCompleteActive;
+    iSelfCompleteActive = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::EnterL
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::EnterL()
+    {
+	TRACE_STATE(_L("[BTSAC State] Listening"))
+	_LIT(KName, "CBtsacStateListening");
+	const TDesC& Name = KName;	
+	Parent().iGavdp->RegisterObserver(this, Name);
+	
+	Parent().ResetRemoteCache();
+	Parent().CleanSockets();
+	
+	// RGavdp.Close (which is called from ResetGavdp method) should not be called from 
+	// within a client's implementation of any MGavdpUser (upcall) method. Do self
+	// complete first then call ResetGavdp.
+	
+	// Need for self completion is gavdp user up calls but we will do self complete every time
+	// when we enter into listening state.
+	DoSelfComplete(KErrNone);
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::ConnectL
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::ConnectL(const TBTDevAddr& aAddr)
+    {
+    TRACE_FUNC
+    iPendingRequests = KConnectReq;
+    if(iInitializationProcedure == EInitProcedureDone)
+		{
+		// we have a connection already with this accessory
+		if ( Parent().GetRemoteAddr() == aAddr )
+			{
+			Parent().ChangeStateL(CBtsacConnected::NewL(Parent(), EOutgoingConnNoDiscovery));
+			}
+		else
+			{
+		    Parent().SetRemoteAddr(aAddr);	// first update address cause InitializeSEPManager uses it
+		    Parent().InitializeSEPManager(); // initializes iRemoteSEPs
+		    Parent().ChangeStateL(CBtsacConnecting::NewL(Parent(), EOutgoingConn));
+			}
+		}
+	else
+		{
+		// Save the address, reset procedure is not completed yet.
+		Parent().SetRemoteAddr(aAddr);
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::OpenAudioLinkL
+// -----------------------------------------------------------------------------
+//    
+void CBtsacListening::OpenAudioLinkL(const TBTDevAddr& aAddr)
+	{  
+	TRACE_FUNC
+	iPendingRequests = KOpenAudioReq;
+	if(iInitializationProcedure == EInitProcedureDone)
+		{
+	    // we have a connection already with this accessory
+	    if ( Parent().GetRemoteAddr() == aAddr )
+	    	{
+			Parent().ChangeStateL(CBtsacConnected::NewL(Parent(), EOutgoingConnWithAudioNoDiscovery));
+	    	}
+	    else
+	    	{
+	        Parent().SetRemoteAddr(aAddr);	// first update address cause InitializeSEPManager uses it
+		    Parent().InitializeSEPManager(); // initializes iRemoteSEPs
+		    Parent().ChangeStateL(CBtsacConnecting::NewL(Parent(), EOutgoingConnWithAudio));
+	    	}
+		}
+	else
+		{
+		// Save the address, reset procedure is not completed yet.
+		Parent().SetRemoteAddr(aAddr);
+		}	
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::CancelOpenAudioLinkL
+// -----------------------------------------------------------------------------
+//    
+void CBtsacListening::CancelOpenAudioLinkL()
+    {
+    TRACE_FUNC
+    // We can have only one request active at the time, so we can reset pending requests
+    iPendingRequests = KRequestNone;
+	GoListen();
+	Parent().CompletePendingRequests(KOpenAudioReq, KErrCancel);
+    }	
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::DeleyedOpenAudioAndConnectL
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::DeleyedOpenAudioAndConnectL()
+	{
+	TRACE_FUNC
+	if(iPendingRequests & (KConnectReq | KOpenAudioReq))
+		{				
+		Parent().InitializeSEPManager();
+		if(iPendingRequests & KOpenAudioReq)
+			{			
+			Parent().ChangeStateL(CBtsacConnecting::NewL(Parent(), EOutgoingConnWithAudio));
+			}
+		else
+			{			
+			Parent().ChangeStateL(CBtsacConnecting::NewL(Parent(), EOutgoingConn));
+			}				
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::GAVDP_ConfigurationConfirm
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::GAVDP_ConfigurationConfirm()
+	{
+	TRACE_INFO((_L("CBtsacListening::GAVDP_ConfigurationConfirm() Local SEPs registered successfully.")))
+	// Local SEPs got registered, so start listening
+	TInt err = Parent().iGavdp->Listen();
+	if (err)
+		{
+		TRACE_INFO((_L("CBtsacListening::GAVDP_ConfigurationConfirm() Listen returned error:%d."), err))
+		ResetGavdp(EGavdpResetReasonGeneral);
+		return;
+		}
+	if(iInitializationProcedure == EInitProcedureWaitingConfConfirmed)
+		{
+		iInitializationProcedure = EInitProcedureDone;
+		TRAP_IGNORE(DeleyedOpenAudioAndConnectL());
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::GAVDP_ConnectConfirm
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::GAVDP_ConnectConfirm(const TBTDevAddr& aAddr)
+	{
+	TRACE_INFO((_L("CBtsacListening::GAVDP_ConnectConfirm() Accessory made connection.")))
+	Parent().SetRemoteAddr(aAddr);  // first update address cause InitializeSEPManager uses it
+	Parent().InitializeSEPManager(); // initializes iRemoteSEPs
+	TRAPD(err, Parent().ChangeStateL(CBtsacConnected::NewL(Parent(), EIncomingConn)));
+	if(err)
+		{
+		TRACE_INFO((_L("CBtsacListening::GAVDP_ConnectConfirm(), NewL failed.")))
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::GAVDP_AbortStreamConfirm
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::GAVDP_AbortStreamConfirm()
+	{
+	TRACE_FUNC
+	GoListen();
+	}
+	
+// -----------------------------------------------------------------------------
+// CBtsacListening::GAVDP_ConfigurationStartIndication
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::GAVDP_ConfigurationStartIndication(TSEID aLocalSEID, TSEID aRemoteSEID)
+	{
+    TRACE_FUNC
+    Parent().InitializeSEPManager();
+	TRAP_IGNORE(Parent().ChangeStateL(CBtsacConfiguring::NewL(Parent(), aLocalSEID, aRemoteSEID)));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::RequestCompletedL
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::RequestCompletedL(CBtsacActive& aActive)
+    {
+	TRACE_FUNC
+	switch(aActive.RequestId())
+		{
+		case KRequestIdSelfComplete:
+			{
+			TBTDevAddr remoteAddr = Parent().GetRemoteAddr();
+			if(iUnfinishedGavdpError)
+				{
+				// We have unfinished gavdp error, force gavdp reset
+				iGavdpResetReason = EGavdpResetReasonGeneral;
+				}
+			if(iGavdpResetReason != EGavdpResetReasonNone)
+				{
+				ResetGavdp(iGavdpResetReason);
+				}
+			else
+				{
+				GoListen();
+				}				
+			if(iDisconnectReason == KErrDisconnected || iDisconnectReason == KErrHCILinkDisconnection)
+				{
+				if(remoteAddr != TBTDevAddr())
+					{						
+					Parent().DisconnectedFromRemote(remoteAddr, iDisconnectReason);
+					}
+				Parent().SetResetAudioInput(ETrue);
+				}
+			if(Parent().GetResetAudioInput())
+				{
+				Parent().SetResetAudioInput(EFalse);
+				Parent().iStreamer->ResetAudioInput();
+				}
+			if(iInitializationProcedure != EInitProcedureWaitingConfConfirmed)
+				{
+				iInitializationProcedure = EInitProcedureDone;
+				DeleyedOpenAudioAndConnectL();
+				}
+			break;
+			}
+		default:
+			{
+			TRACE_INFO((_L("CBtsacListening::RequestCompletedL() Unknown request")))
+			break;
+			}	
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::GoListen
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::GoListen()
+	{
+	TRACE_INFO((_L("CBtsacListening::GoListen(), Disconnect signalling channel")))
+	if(iPendingRequests == KRequestNone)
+		{					
+		Parent().SetRemoteAddr(TBTDevAddr());
+		}
+	TInt err = Parent().iGavdp->Shutdown();
+	if(!err)
+		{
+		TRACE_INFO((_L("CBtsacListening::GoListen(), Signalling disconnected, Re-listen...")))
+		// Starts to listen for inbound signalling channel connections.
+		err = Parent().iGavdp->Listen();
+		}
+	if(err)
+		{
+		// Shutdown failed, reset gavdp
+		TRACE_INFO((_L("CBtsacListening::GoListen(), error = %d."), err))
+		ResetGavdp(EGavdpResetReasonGeneral);
+		}		
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::ResetGavdp
+// -----------------------------------------------------------------------------
+//
+TInt CBtsacListening::ResetGavdp(TBTSACGavdpResetReason aReason)
+	{
+	TRACE_FUNC
+	Parent().iGavdp->Close();
+	if( Parent().iGavdp->Open() == KErrNone )
+		{
+		iInitializationProcedure = EInitProcedureWaitingConfConfirmed;
+		if(aReason != EGavdpResetReasonCancelOpenAudio)
+			{
+			if(iPendingRequests == KRequestNone)
+				{
+				TRACE_INFO((_L("CBtsacListening::ResetGavdp() Remote Addr reseted.")))
+				Parent().SetRemoteAddr(TBTDevAddr());
+				}
+			}
+		return Parent().iGavdp->RegisterSEPs(*Parent().iLocalSEPs, Parent().iStreamer->GetCaps());
+		}
+	else
+		{
+		TRACE_INFO((_L("CBtsacListening::ResetGavdp() Couldn't open gavdp.")))
+		return KErrGeneral;
+		}		
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::CancelRequest
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::CancelRequest(CBtsacActive& /*aActive*/)
+	{
+	TRACE_FUNC
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacListening::DoSelfComplete
+// -----------------------------------------------------------------------------
+//
+void CBtsacListening::DoSelfComplete(TInt aError) 
+	{
+	TRACE_FUNC
+	if(iSelfCompleteActive)
+		{		
+		if (!iSelfCompleteActive->IsActive())
+		    {		    
+		    TRequestStatus* sta = &(iSelfCompleteActive->iStatus);
+		    iSelfCompleteActive->iStatus = KRequestPending;
+		    User::RequestComplete(sta, aError);
+		    iSelfCompleteActive->GoActive();
+		    }
+		}
+	else
+		{
+		TRACE_INFO((_L("CBtsacListening::DoSelfComplete() AO doesn't exist.")))
+		}
+	}
+    
+// -----------------------------------------------------------------------------
+// CBtsacListening::HandleGavdpErrorL
+// -----------------------------------------------------------------------------
+//	
+void CBtsacListening::HandleGavdpErrorL(TInt aError)
+	{
+	TRACE_FUNC
+    if(iInitializationProcedure != EInitProcedureDone)
+	    {
+	    TRACE_INFO((_L("CBtsacListening::HandleGavdpErrorL() error ignored, initialization procedure ongoing.")))
+	    iUnfinishedGavdpError = ETrue;	    
+	    return;
+	    }
+	switch(aError)
+		{
+		case KErrHCILinkDisconnection: // -6305
+		case KErrDisconnected: // -36
+			{
+			// If address is zero, initialization procedure is already executed, so there is no need
+			// to tell gavdp to go listen and no need to inform btaudioman about the disconnection
+			if(Parent().GetRemoteAddr() != TBTDevAddr())
+				{
+				GoListen();
+				// for both outgoing or incoming connection, if we have an error, 
+				// this means there is disconnection		 	
+			 	Parent().DisconnectedFromRemote(Parent().GetRemoteAddr(), aError);	  	  	    	
+				Parent().SetRemoteAddr(TBTDevAddr());
+				Parent().iStreamer->ResetAudioInput();
+			 	}
+			break;
+			}
+		
+		case KErrCouldNotConnect: // -34
+			{
+			GoListen();
+			break;
+			}
+		
+		default:
+		// KErrAbort -39
+		// KErrDied -13
+		// KErrInUse -14
+			{
+			ResetGavdp(EGavdpResetReasonGeneral);			
+			break;
+			}
+		}
+	Parent().CompletePendingRequests(KCompleteAllReqs, aError);
+	}
+
+//  End of File