bluetoothappprofiles/avrcp/remconbeareravrcp/src/bulkbearer.cpp
changeset 0 f63038272f30
child 6 6a29d5ad0713
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothappprofiles/avrcp/remconbeareravrcp/src/bulkbearer.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,363 @@
+// Copyright (c) 2008-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:
+//
+
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#include <remconaddress.h>
+#include <remconbeareravrcp.h>
+#include <remcon/remconbearerbulkobserver.h>
+
+#include "avrcpbrowsingcommandhandler.h"
+#include "avrcprouter.h"
+#include "avrcputils.h"
+#include "browsecommand.h"
+#include "bulkbearer.h"
+#include "playerstatewatcher.h"
+
+#include "avrcplog.h"
+
+#ifdef _DEBUG
+PANICCATEGORY("avrcpbulk");
+#endif // _DEBUG
+
+CAvrcpBulkBearer* CAvrcpBulkBearer::NewL(RAvctp& aAvctp, CAvrcpPlayerInfoManager& aPlayerInfoManager)
+	{
+	LOG_STATIC_FUNC
+	CAvrcpBulkBearer* bulkBearer = new(ELeave) CAvrcpBulkBearer(aPlayerInfoManager, aAvctp);
+	return bulkBearer;
+	}
+
+CAvrcpBulkBearer::~CAvrcpBulkBearer()
+	{
+	LOG_FUNC
+	ASSERT_DEBUG(!iRouter); // Should already be stopped...
+	}
+
+CAvrcpBulkBearer::CAvrcpBulkBearer(CAvrcpPlayerInfoManager& aPlayerInfoManager, RAvctp& aAvctp)
+	: iPlayerInfoManager(aPlayerInfoManager)
+	, iAvctp(aAvctp)
+	, iReadyBrowseCommands(_FOFF(CAvrcpCommand, iReadyLink))
+	{
+	LOG_FUNC
+	}
+
+MIncomingCommandHandler* CAvrcpBulkBearer::IncomingHandler(const TBTDevAddr& aAddr)
+	{
+	LOG_FUNC
+	
+	MIncomingCommandHandler* handler = NULL;
+	TInt ix = iBrowseHandlers.Find(aAddr, CAvrcpBulkBearer::CompareBrowsingCommandHandlerByBDAddr);
+	if(ix >= 0)
+		{
+		handler = iBrowseHandlers[ix];
+		}
+
+	return handler;
+	}
+
+MOutgoingCommandHandler* CAvrcpBulkBearer::OutgoingHandler(const TBTDevAddr& /*aAddr*/)
+	{
+	LOG_FUNC
+	// We've received a response, but we haven't sent a command.  Naughty remote,
+	// just ignore it.
+	return NULL;
+	}
+
+void CAvrcpBulkBearer::DoConnectIndicateL(const TBTDevAddr& aBTDevice)
+	{
+	LOG_FUNC
+	ASSERT_BULK_THREAD;
+	
+	ASSERT_DEBUG(Operational());
+	
+	CRcpBrowsingCommandHandler* handler = CRcpBrowsingCommandHandler::NewL(*this, *iRouter, iPlayerInfoManager, aBTDevice);
+	CleanupStack::PushL(handler);
+	
+	iBrowseHandlers.AppendL(handler);
+	
+	CleanupStack::Pop(handler);
+	}
+	
+void CAvrcpBulkBearer::ConnectIndicate(const TBTDevAddr& aBTDevice)
+	{
+	LOG_FUNC
+	// If we failed to allocate a handler for this connection the router will
+	// not be able to find it when it checks, and will tell AVCTP that we're 
+	// not interested in this connection.
+	TRAP_IGNORE(DoConnectIndicateL(aBTDevice));
+	}
+
+void CAvrcpBulkBearer::ConnectConfirm(const TBTDevAddr& IF_FLOGGING(aBTDevice), TInt IF_FLOGGING(aError))
+	{
+	LOG_FUNC
+	LOGBTDEVADDR(aBTDevice);
+	LOG1(_L("\taError = %d"), aError);
+	
+	// Outlandish!  We did not ask for this!
+	__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpConnectConfirmOnBrowseChannel));
+	}
+
+void CAvrcpBulkBearer::DisconnectIndicate(const TBTDevAddr& aBTDevice)
+	{
+	LOG_FUNC
+	ASSERT_BULK_THREAD;
+	
+	CRcpBrowsingCommandHandler* handler = NULL;
+	TInt ix = iBrowseHandlers.Find(aBTDevice, CAvrcpBulkBearer::CompareBrowsingCommandHandlerByBDAddr);
+	if(ix >= 0)
+		{
+		handler = iBrowseHandlers[ix];
+		delete handler;
+		iBrowseHandlers.Remove(ix);
+		}
+	else
+		{
+		ASSERT_DEBUG(EFalse);
+		}
+	}
+
+void CAvrcpBulkBearer::DisconnectConfirm(const TBTDevAddr& IF_FLOGGING(aBTDevice), TInt IF_FLOGGING(aError))
+	{
+	LOG_FUNC
+	LOGBTDEVADDR(aBTDevice);
+	LOG1(_L("\taError = %d"), aError);
+	
+	// Also outlandish!  Connections on browse channel are all passive.
+	__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpDisconnectConfirmOnBrowseChannel));
+	}
+
+void CAvrcpBulkBearer::MrcciNewCommand(CAvrcpCommand& aCommand)
+	{
+	LOG_FUNC
+
+	DoNewCommand(aCommand, KNullClientId);
+	}
+
+// This overload is used when we want to address a stateless command that may
+// be interleaved with commands from other controllers.  The only command
+// this is currently used for is the internal UidCounterUpdate command.
+void CAvrcpBulkBearer::MrcciNewCommand(CAvrcpCommand& aCommand, const TRemConClientId& aClientId)
+	{
+	LOG_FUNC
+	// Verify that it's an internal command
+	__ASSERT_DEBUG(aCommand.RemoteAddress() == TBTDevAddr(0), AvrcpUtils::Panic(ESpecificAddressUsedForBrowsingCommand));
+		
+	DoNewCommand(aCommand, aClientId);
+	}
+
+void CAvrcpBulkBearer::DoNewCommand(CAvrcpCommand& aCommand, const TRemConClientId& aClientId)
+	{
+	LOG_FUNC
+
+	// Need to put the command on the queue straight
+	// away in case RemCon collects it synchronously
+	iReadyBrowseCommands.AddLast(aCommand);
+	aCommand.IncrementUsers();
+	
+	TRemConAddress remAddr;
+	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
+	
+	TInt err = (aClientId == KNullClientId) ? iObserver->NewCommand(remAddr) : iObserver->NewCommand(remAddr, aClientId);
+		
+	if(err != KErrNone)
+		{
+		TUid interfaceUid;
+		TUint remconId, operationId;
+		RBuf8 commandData;
+		TBTDevAddr btAddr;
+		
+		// Calling GetCommandInfo transfers ownership of the command data.  
+		aCommand.GetCommandInfo(interfaceUid, remconId, operationId, commandData, btAddr);
+		MrcbbiSendReject(interfaceUid, operationId, remconId, remAddr);
+		commandData.Close();
+
+		// RemCon is not going to pick this command up
+		aCommand.iReadyLink.Deque();
+		aCommand.DecrementUsers();
+		}
+	}
+
+TUint CAvrcpBulkBearer::MrcciNewTransactionId()
+	{
+	LOG_FUNC
+	return iObserver->NewTransactionId();
+	}
+
+TInt CAvrcpBulkBearer::MrcbciSetAddressedClient(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC
+	return iObserver->SetAddressedClient(aAddr, aClient);
+	}
+
+void CAvrcpBulkBearer::MrcbciRemoveAddressing(const TRemConAddress& aAddr)
+	{
+	LOG_FUNC
+	iObserver->RemoveAddressing(aAddr);
+	}
+
+TInt CAvrcpBulkBearer::MrcbbiGetCommand(TUid& aInterfaceUid, 
+	TUint& aTransactionId, 
+	TUint& aOperationId, 
+	RBuf8& aData, 
+	TRemConAddress& aAddr)
+	{
+	LOG_FUNC
+	TInt result = KErrNotFound;
+	
+	if(!iReadyBrowseCommands.IsEmpty())
+		{
+		CAvrcpCommand* command = iReadyBrowseCommands.First();
+
+		// Calling GetCommandInfo transfers the command data to RemCon.  This means
+		// once we have called it we are committed to returning KErrNone.
+		TBTDevAddr btAddr;
+		command->GetCommandInfo(aInterfaceUid, aTransactionId, aOperationId, aData, btAddr);
+		AvrcpUtils::BTToRemConAddr(btAddr, aAddr);
+		
+		// Remove command from queue first because calling
+		// DecrementUsers() may delete command
+		command->iReadyLink.Deque();
+		command->DecrementUsers();
+		result = KErrNone;
+		}
+	else
+		{
+		__DEBUGGER();
+		}
+	
+	return result;
+	}
+
+TInt CAvrcpBulkBearer::MrcbbiSendResponse(TUid aInterfaceUid, 
+	TUint /*aOperationId*/, 
+	TUint aTransactionId, 
+	RBuf8& aData, 
+	const TRemConAddress& aAddr)
+	{
+	LOG_FUNC
+	TBTDevAddr btAddr;
+	TInt err = KErrNone;
+	
+	err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
+	__ASSERT_DEBUG(err == KErrNone, AvrcpUtils::Panic(EInvalidBtAddrInResponse));
+	
+	if(btAddr != TBTDevAddr(0))
+		{
+		MIncomingCommandHandler* handler = IncomingHandler(btAddr);
+		__ASSERT_ALWAYS(handler, AVRCP_PANIC(EAvrcpNotConnected));
+
+		err = handler->SendRemConResponse(aInterfaceUid, aTransactionId, aData);
+		}
+	else
+		{
+		err = iInternalHandler->SendRemConResponse(aInterfaceUid, aTransactionId, aData);
+		}
+		
+	return err;
+	}
+
+void CAvrcpBulkBearer::MrcbbiSendReject(TUid aInterfaceUid, 
+	TUint /*aOperationId*/, 
+	TUint aTransactionId, 
+	const TRemConAddress& aAddr)
+	{
+	LOG_FUNC
+	
+	TBTDevAddr btAddr;
+	TInt err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
+	__ASSERT_DEBUG(err == KErrNone, AvrcpUtils::Panic(EInvalidBtAddrInResponse));
+
+	if(btAddr != TBTDevAddr(0))
+		{
+		IncomingHandler(btAddr)->SendReject(aInterfaceUid, aTransactionId);
+		}
+	else
+		{
+		iInternalHandler->SendReject(aInterfaceUid, aTransactionId);
+		}
+	}
+
+TInt CAvrcpBulkBearer::MrcbbiStartBulk(MRemConBearerBulkObserver& aObserver)
+	{
+	LOG_FUNC
+	iObserver = &aObserver;
+	TRAPD(err, DoStartBulkL());
+	if(err != KErrNone)
+		{
+		MrcbbiStopBulk();
+		}
+	return err;
+	}
+
+void CAvrcpBulkBearer::DoStartBulkL()
+	{
+	LOG_FUNC
+	LEAVEIFERRORL(Dll::SetTls(reinterpret_cast<TAny*>(EBulkThread)));
+	iInternalHandler = iPlayerInfoManager.BulkStartedL(*this);
+	iRouter = CBulkRouter::NewL(iAvctp, *this);
+	}
+
+void CAvrcpBulkBearer::MrcbbiStopBulk()
+	{
+	LOG_FUNC
+	WEAK_ASSERT_BULK_THREAD;
+	
+	iPlayerInfoManager.BulkStopped();
+	iInternalHandler = NULL;
+	
+	delete iRouter;
+	iRouter = NULL;
+	
+	iBrowseHandlers.ResetAndDestroy();
+	
+	iObserver = NULL; // the observer is no longer valid.
+	
+	Dll::FreeTls();
+	}
+
+TBool CAvrcpBulkBearer::Operational() const
+	{
+	LOG_FUNC
+	ASSERT_DEBUG(!iRouter == !iObserver); // internal consistency check
+	return !!iRouter;
+	}
+
+void CAvrcpBulkBearer::MrcbbiBulkClientAvailable(const TRemConClientId& aId)
+	{
+	LOG_FUNC
+	iPlayerInfoManager.BulkClientAvailable(aId);
+	}
+
+void CAvrcpBulkBearer::MrcbbiBulkClientNotAvailable(const TRemConClientId& aId)
+	{
+	LOG_FUNC
+	iPlayerInfoManager.BulkClientNotAvailable(aId);
+	}
+
+
+TBool CAvrcpBulkBearer::CompareBrowsingCommandHandlerByBDAddr(const TBTDevAddr* aKey, const CRcpBrowsingCommandHandler& aHandler)
+	{
+	LOG_STATIC_FUNC
+	return aKey && aHandler.BtAddr() == *aKey;
+	}
+
+
+