--- /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;
+ }
+
+
+