bthci/hci2implementations/corehcis/symbian/src/hciserverrequestmgr.cpp
changeset 27 83036355c0f3
parent 0 29b1cd4cb562
--- a/bthci/hci2implementations/corehcis/symbian/src/hciserverrequestmgr.cpp	Tue Feb 02 01:12:20 2010 +0200
+++ b/bthci/hci2implementations/corehcis/symbian/src/hciserverrequestmgr.cpp	Thu Oct 14 11:30:12 2010 +0100
@@ -1,658 +1,658 @@
-// Copyright (c) 2006-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
-*/
-
-#include "hciserverrequestmgr.h"
-#include "HciCorePluginImpl.h"
-#include "corehciutil.h"
-
-#include <bluetooth/hci/hciipc.h>
-#include <bluetooth/hci/vendordebugcommand.h>
-#include <bluetooth/hci/vendordebugcompleteevent.h>
-#include <bluetooth/hci/vendordebugevent.h>
-
-#include <bluetooth/hcicommandqueueclient.h>
-#include <bluetooth/hcicommandqueue.h>
-#include <bluetooth/btpowercontrol.h>
-#include <bluetooth/dutmode.h>
-#include <bluetooth/a2dpoptimisation.h>
-#include <bluetooth/a2dpoptimisationparams.h>
-
-#include <bluetooth/logger.h>
-#include <bluetooth/btpowercontrolmessages.h>
-
-#include <es_sock.h>
-#include <bt_sock.h>
-
-#ifdef __FLOG_ACTIVE
-_LIT8(KLogComponent, LOG_COMPONENT_HCISERVER);
-#endif
-
-const TInt KHCIServerIpcDesOutParam = 2;
-
-void CHCIServerRequestManager::BlockAsync(CHCISession& aSession, const RMessage2& aMessage)
-	{
-	LOG_FUNC
-
-	iAsyncTaskMessage = aMessage;
-	iAsyncTaskSession = &aSession;
-	iBlockMask |= MaskBit();
-	}
-	
-void CHCIServerRequestManager::CompleteAsyncTask(TInt aError)
-	{
-	LOG_FUNC
-	
-	//check message is not already complete
-	if(iAsyncTaskMessage.Handle())
-		{
-		iAsyncTaskMessage.Complete(aError);
-		}
-	else
-		{
-		__ASSERT_DEBUG(EFalse, PANIC(KHciServerPanicCat, EMessageAlreadyCompleted));
-		}
-
-	// Remove Async block		
-	iAsyncTaskSession = 0;
-	iBlockMask &= ~MaskBit();
-	}
-	
-TBool CHCIServerRequestManager::IsAsyncBlocked()
-	{
-	LOG_FUNC
-	
-	return (iBlockMask & MaskBit());
-	}
-	
-CHCIServerRequestManager::CHCIServerRequestManager(CCoreHCIPluginImpl& aHCI)
- :	iHCI(aHCI)
-	{
-	LOG_FUNC
-	}
-	
-void CHCIServerRequestManager::ConstructL()
-	{
-	LOG_FUNC
-	}
-
-void CHCIServerRequestManager::ServiceL(CHCISession& aSession, const RMessage2& aMessage)
-	{
-	if(aMessage.Function() == EServiceSpecificRequest)
-		{
-		if(HasCapabilities(aMessage))
-			{
-			DoServiceL(aSession, aMessage);
-			}
-		// else HasCapabilities failed (and has dealt with aMessage).
-		}
-	else
-		{
-		// The client has issued a bad HCI Server request, we only expect a server specific
-		// request to be made (the specific request being encoded in the TIpcArgs).
-		PanicClient(aMessage, EUnknownHciServerFunction);
-		}
-	}
-
-//
-// HCI Direct Access Service
-//
-CHCIDirectAccessManager* CHCIDirectAccessManager::NewL(CCoreHCIPluginImpl& aHCI)
-	{
-	LOG_STATIC_FUNC
-	
-	CHCIDirectAccessManager* self = new (ELeave) CHCIDirectAccessManager(aHCI);
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	CleanupStack::Pop(self);
-	return self;
-	}
-	
-void CHCIDirectAccessManager::SetHCICommandQueue(MHCICommandQueue& aHCICommandQueue)
-	{
-	LOG_FUNC
-	
-	__ASSERT_ALWAYS(!iHCICommandQueue, PANIC(KCoreHciPanicCat, EInterfaceAlreadyInitialised));
-	iHCICommandQueue = &aHCICommandQueue;
-	}
-
-/*virtual*/ TBool CHCIDirectAccessManager::HasCapabilities(const RMessage2& aMessage)
-	{
-	LOG_FUNC
-	
-	TBool allowed = EFalse;
-	
-	switch (aMessage.Int0())
-		{
-	case KHCIDirectAccessVendorCommand:
-		// Drop through
-	case KHCIDirectAccessCancel: // requires Network Control + Local Services
-		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
-		break;
-
-	default:
-		PanicClient(aMessage, EUnknownDirectAccessFunction);
-		return EFalse;
-		}
-	
-	if(!allowed)
-		{
-		aMessage.Complete(KErrPermissionDenied);
-		}
-		
-	return allowed;
-	}
-
-/*virtual*/ void CHCIDirectAccessManager::DoServiceL(CHCISession& aSession, const RMessage2& aMessage)
-	{
-	LOG_FUNC
-	
-	TInt request = aMessage.Int0();
-
-	switch (request)
-		{
-	case KHCIDirectAccessCancel:
-		if (iAsyncTaskSession != &aSession)
-			{
-			return; //drop - not for current async task
-			}
-
-		// clear cache
-		iMessage = NULL;
-		
-		// perform cancellation procedure
-		CompleteAsyncTask(KErrCancel);
-		break;
-
-	case KHCIDirectAccessVendorCommand:
-		{
-		if (IsAsyncBlocked())
-			{
-			aMessage.Complete(KErrInUse);
-			return;
-			}
-
-		const TInt len = User::LeaveIfError(aMessage.GetDesLength(1));
-		
-		// Check the Vendor Command is at least 3 bytes long for the opcode
-		// and the length
-		if (len < 3)
-			{
-			PanicClient(aMessage, EInvalidVendorCommand);
-			break;
-			}
-		
-		HBufC8* buf = HBufC8::NewLC(len);
-		TPtr8 params(buf->Des());
-		aMessage.ReadL(1, params);
-		
-		// Extract the opcode and create the new command
-		TUint16 opcode = LittleEndian::Get16(params.Ptr());
-		
-		if (iHCICommandQueue)
-			{
-			CVendorDebugCommand* cmd = CVendorDebugCommand::NewL(opcode);
-
-			// Remove the opcode and length from the Vendor Command parameters,
-			// these will be added again to the command frame once it has been
-			// formatted
-			cmd->Command() = params.RightTPtr(params.Length() - 3);
-			
-			// cmd will be deleted in MhcqAddCommandL if Leaves.
-			TUint qid = iHCICommandQueue->MhcqAddCommandL(cmd, *this);
-
-			// Block only after we succeed in adding a command.
-			BlockAsync(aSession, aMessage);
-
-			// Cache to return completion data to client
-			iMessage = &aMessage;
-			}
-		else
-			{
-			// Slight possible race that a request is made before we have been
-			// given the command queue to work with - so don't panic just error.
-			aMessage.Complete(KErrNotReady);
-			}
-		CleanupStack::PopAndDestroy(buf);
-		}
-		break;
-
-	default:
-		// Unknown message, panic client
-		PanicClient(aMessage, EUnknownDirectAccessFunction);
-		break;
-		}
-	}
-
-/*virtual*/ void CHCIDirectAccessManager::MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* /*aCommand*/)
-	{
-	LOG_FUNC
-
-	// clear cache
-	iMessage = NULL;
-
-	CompleteAsyncTask(aErrorCode);
-	}
-
-/*virtual*/ void CHCIDirectAccessManager::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aCommand)
-	{
-	LOG_FUNC
-
-	// We are not the unmatched event observer therefore we must always get a
-	// command
-	__ASSERT_DEBUG(aCommand, PANIC(KCoreHciPanicCat, EReceivedUnmatchedEvent));
-	
-	// It is possible to receive an event but not have a message to complete. This
-	// could happen if a request was cancelled after a Vendor Specific command was
-	// sent, in this case we do nothing.
-	if (iMessage)
-		{
-		TInt err = KErrNone;
-		
-		const THCIEventCode eventcode(aEvent.EventCode());
-		switch(eventcode)
-			{
-		case ECommandCompleteEvent:
-			{
-			if ((aCommand->Opcode() & KVendorDebugOGF) == KVendorDebugOGF)
-				{
-				const TVendorDebugCompleteEvent& event = TVendorDebugCompleteEvent::Cast(aEvent);
-				
-				// Return the event
-				err = iMessage->Write(KHCIServerIpcDesOutParam, event.VendorDebugData());
-				}
-			else
-				{
-				__ASSERT_DEBUG(EFalse, PANIC(KHciServerPanicCat, ENonVendorOpcodeCompleted));
-				}
-			}
-			break;
-
-		case EVendorDebugEvent:
-			{
-			const TVendorDebugEvent& event = TVendorDebugEvent::Cast(aEvent);
-
-			// Return the event
-			err = iMessage->Write(KHCIServerIpcDesOutParam, event.VendorDebugData());
-			}
-			break;
-			
-		default:
-			__ASSERT_DEBUG(EFalse, PANIC(KCoreHciPanicCat, EReceivedUnknownEvent));
-			break;
-			}
-
-		CompleteAsyncTask(err);
-		}
-	}
-
-/*virtual*/ void CHCIDirectAccessManager::CompleteAsyncTask(TInt aError)
-	{
-	LOG_FUNC
-
-	if (!IsAsyncBlocked())
-		{
-		return; //drop
-		}
-
-	CHCIServerRequestManager::CompleteAsyncTask(aError);
-	}
-
-CHCIDirectAccessManager::CHCIDirectAccessManager(CCoreHCIPluginImpl& aHCI)
-:	CHCIServerRequestManager(aHCI)
-	{
-	LOG_FUNC
-	}
-	
-
-TUint CHCIDirectAccessManager::MaskBit() const
-	{
-	LOG_FUNC
-	
-	return EHCIDirectAccessMaskBit;
-	}
-			
-//
-// Power Control Service
-//
-CBTPowerControlManager* CBTPowerControlManager::NewL(CCoreHCIPluginImpl& aHCI)
-	{
-	LOG_STATIC_FUNC
-	
-	CBTPowerControlManager* self = new (ELeave) CBTPowerControlManager(aHCI);
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-TBool CBTPowerControlManager::HasCapabilities(const RMessage2& aMessage)
-	{
-	LOG_FUNC
-	
-	TBool allowed(EFalse);
-	
-	switch (aMessage.Int0())
-		{
-	case KHCICancelPower:
-		// fall through
-	case EHCISetPower: // requires Network Control + Local Services
-		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
-		break;
-	
-	case EHCIGetPower: // requires Local Services
-		allowed = aMessage.HasCapability(ECapabilityLocalServices);
-		break;
-
-	default:
-		PanicClient(aMessage, EUnknownPowerControlFunction);
-		return EFalse;
-		}
-		
-	if(!allowed)
-		{
-		aMessage.Complete(KErrPermissionDenied);
-		}
-		
-	return allowed;
-	}
-
-/*virtual*/ void CBTPowerControlManager::DoServiceL(CHCISession& aSession, const RMessage2& aMessage)
-	{
-	LOG_FUNC
-
-	TInt request = aMessage.Int0();
-	TInt err;
-	TBTPowerState state;
-	
-	switch (request)
-		{
-	case KHCICancelPower:
-		if(iAsyncTaskSession!=&aSession)
-			{
-			return; //drop - not for current async task
-			}
-
-		//perform cancellation procedure
-		CompleteAsyncTask(KErrCancel);
-		break;
-
-	case EHCISetPower:
-		if(IsAsyncBlocked())
-			{
-			aMessage.Complete(KErrInUse);
-			return;
-			}
-		
-		//Should be called before set power because it could complete synchronously
-		BlockAsync(aSession, aMessage);		
-		state = static_cast<TBTPowerState>(aMessage.Int3());
-		err = iHCI.SetPower(state, NULL);
-		if(err != KErrNone)
-			{
-			aMessage.Complete(err);
-			return;
-			}
-		break;
-
-	case EHCIGetPower:
-		{
-		err = iHCI.GetPower(state, NULL);
-		if(err != KErrNone)
-			{
-			aMessage.Complete(err);
-			return;
-			}
-		
-		TPckg<TBTPowerState> pckg(state);
-		TRAP(err, aMessage.WriteL(EPSStateReturnSlot, pckg));
-		aMessage.Complete(err);
-		}
-		break; //synchronous so do not block
-	
-	default:
-		// Unknown message
-		PanicClient(aMessage, EUnknownPowerControlFunction);
-		break;
-		}
-	}
-
-/*virtual*/ void CBTPowerControlManager::CompleteAsyncTask(TInt aError)
-	{
-	LOG_FUNC
-	
-	if(!IsAsyncBlocked())
-		{
-		return; //drop
-		}
-
-	CHCIServerRequestManager::CompleteAsyncTask(aError);
-	}
-
-void CBTPowerControlManager::CompleteRequest(TInt aError)
-	{
-	CompleteAsyncTask(aError);
-	}
-
-CBTPowerControlManager::CBTPowerControlManager(CCoreHCIPluginImpl& aHCI)
-:	CHCIServerRequestManager(aHCI)
-	{
-	LOG_FUNC
-	}
-	
-
-TUint CBTPowerControlManager::MaskBit() const
-	{
-	LOG_FUNC
-	
-	return EBTPowerControlMaskBit;
-	}
-
-//
-// Bluetooth HCI Utils Service
-//
-CBluetoothDutModeManager* CBluetoothDutModeManager::NewL(CCoreHCIPluginImpl& aHCI)
-	{
-	LOG_STATIC_FUNC
-	
-	CBluetoothDutModeManager* self = new (ELeave) CBluetoothDutModeManager(aHCI);
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-TBool CBluetoothDutModeManager::HasCapabilities(const RMessage2& aMessage)
-	{
-	LOG_FUNC
-	
-	TBool allowed(EFalse);
-	
-	switch (aMessage.Int0())
-		{
-	case RBluetoothDutMode::EHCIActivateDutMode:
-		// fall through
-	case RBluetoothDutMode::EHCIDeactivateDutMode: // requires Network Control + Local Services
-		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
-		break;
-
-	default:
-		PanicClient(aMessage, EUnknownBluetoothDutModeFunction);
-		return EFalse;
-		}
-		
-	if(!allowed)
-		{
-		aMessage.Complete(KErrPermissionDenied);
-		}
-		
-	return allowed;
-	}
-
-/*virtual*/ void CBluetoothDutModeManager::DoServiceL(CHCISession& /*aSession*/, const RMessage2& aMessage)
-	{
-	LOG_FUNC
-
-	TInt request = aMessage.Int0();
-	TInt err = KErrNotSupported;
-
-	switch (request)
-		{
-	case RBluetoothDutMode::EHCIActivateDutMode:
-		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
-		LOG(_L("EHCIActivateDutMode"));
-		aMessage.Complete(err);
-		break;
-
-	case RBluetoothDutMode::EHCIDeactivateDutMode:
-		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
-		LOG(_L("EHCIDeactivateDutMode"));
-		aMessage.Complete(err);
-		break;
-
-	default:
-		// Unknown message
-		PanicClient(aMessage, EUnknownBluetoothDutModeFunction);
-		break;
-		}
-	}
-
-CBluetoothDutModeManager::CBluetoothDutModeManager(CCoreHCIPluginImpl& aHCI)
-:	CHCIServerRequestManager(aHCI)
-	{
-	LOG_FUNC
-	}
-	
-
-TUint CBluetoothDutModeManager::MaskBit() const
-	{
-	LOG_FUNC
-	
-	return EBluetoothDutModeMaskBit;
-	}
-
-//
-// A2DP Optimiser Service
-//
-CA2dpOptimiserManager* CA2dpOptimiserManager::NewL(CCoreHCIPluginImpl& aHCI)
-	{
-	LOG_STATIC_FUNC
-	
-	CA2dpOptimiserManager* self = new (ELeave) CA2dpOptimiserManager(aHCI);
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-TBool CA2dpOptimiserManager::HasCapabilities(const RMessage2& aMessage)
-	{
-	LOG_FUNC
-	
-	TBool allowed(EFalse);
-	
-	switch (aMessage.Int0())
-		{
-	case RA2dpOptimiser::EHCIA2dpOptimiseAcl:
-		// fall through
-	case RA2dpOptimiser::EHCIA2dpRemoveAclOptimisation: // requires Network Control + Local Services
-		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
-		break;
-
-	default:
-		PanicClient(aMessage, EUnknownA2dpOptimiserFunction);
-		return EFalse;
-		}
-		
-	if(!allowed)
-		{
-		aMessage.Complete(KErrPermissionDenied);
-		}
-		
-	return allowed;
-	}
-
-/*virtual*/ void CA2dpOptimiserManager::DoServiceL(CHCISession& /*aSession*/, const RMessage2& aMessage)
-	{
-	LOG_FUNC
-
-	TInt request = aMessage.Int0();
-	TInt err = KErrNotSupported;
-	TBuf<20> targetAddrBuf;
-	
-	switch (request)
-		{
-	case RA2dpOptimiser::EHCIA2dpOptimiseAcl:
-		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
-		if (aMessage.GetDesLength(1) == sizeof(TA2dpOptimisationParams))
-			{
-			TPckgBuf<TA2dpOptimisationParams> args;
-	
-			aMessage.ReadL(1, args);
-			args().RemoteDeviceAddress().GetReadable(targetAddrBuf);
-			LOG3(_L("EHCIA2dpOptimiseAcl BT Addr: %S, Peak Bandwidth: %d, Access Latency: %d\n"), 
-						&targetAddrBuf, args().PeakBandwidth(), args().AccessLatency());
-	
-			aMessage.Complete(err);
-			}
-		else
-			{
-			PanicClient(aMessage, EInvalidArgument);
-			}
-		break;
-
-	case RA2dpOptimiser::EHCIA2dpRemoveAclOptimisation:
-		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
-		if (aMessage.GetDesLength(1) == sizeof(TBTDevAddr))
-			{
-			TPckgBuf<TBTDevAddr> addrBuf;
-	
-			aMessage.ReadL(1, addrBuf);
-			addrBuf().GetReadable(targetAddrBuf);
-			LOG1(_L("EHCIA2dpRemoveAclOptimisation BT Addr: %S\n"), &targetAddrBuf);
-	
-			aMessage.Complete(err);
-			}
-		else
-			{
-			PanicClient(aMessage, EInvalidArgument);
-			}
-		break;
-
-	default:
-		// Unknown message
-		PanicClient(aMessage, EUnknownA2dpOptimiserFunction);
-		break;
-		}
-	}
-
-CA2dpOptimiserManager::CA2dpOptimiserManager(CCoreHCIPluginImpl& aHCI)
-:	CHCIServerRequestManager(aHCI)
-	{
-	LOG_FUNC
-	}
-	
-
-TUint CA2dpOptimiserManager::MaskBit() const
-	{
-	LOG_FUNC
-	
-	return EA2dpOptimiserMaskBit;
-	}
-
+// Copyright (c) 2006-2010 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
+*/
+
+#include "hciserverrequestmgr.h"
+#include "HciCorePluginImpl.h"
+#include "corehciutil.h"
+
+#include <bluetooth/hci/hciipc.h>
+#include <bluetooth/hci/vendordebugcommand.h>
+#include <bluetooth/hci/vendordebugcompleteevent.h>
+#include <bluetooth/hci/vendordebugevent.h>
+
+#include <bluetooth/hcicommandqueueclient.h>
+#include <bluetooth/hcicommandqueue.h>
+#include <bluetooth/btpowercontrol.h>
+#include <bluetooth/dutmode.h>
+#include <bluetooth/a2dpoptimisation.h>
+#include <bluetooth/a2dpoptimisationparams.h>
+
+#include <bluetooth/logger.h>
+#include <bluetooth/btpowercontrolmessages.h>
+
+#include <es_sock.h>
+#include <bt_sock.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_HCISERVER);
+#endif
+
+const TInt KHCIServerIpcDesOutParam = 2;
+
+void CHCIServerRequestManager::BlockAsync(CHCISession& aSession, const RMessage2& aMessage)
+	{
+	LOG_FUNC
+
+	iAsyncTaskMessage = aMessage;
+	iAsyncTaskSession = &aSession;
+	iBlockMask |= MaskBit();
+	}
+	
+void CHCIServerRequestManager::CompleteAsyncTask(TInt aError)
+	{
+	LOG_FUNC
+	
+	//check message is not already complete
+	if(iAsyncTaskMessage.Handle())
+		{
+		iAsyncTaskMessage.Complete(aError);
+		}
+	else
+		{
+		__ASSERT_DEBUG(EFalse, PANIC(KHciServerPanicCat, EMessageAlreadyCompleted));
+		}
+
+	// Remove Async block		
+	iAsyncTaskSession = 0;
+	iBlockMask &= ~MaskBit();
+	}
+	
+TBool CHCIServerRequestManager::IsAsyncBlocked()
+	{
+	LOG_FUNC
+	
+	return (iBlockMask & MaskBit());
+	}
+	
+CHCIServerRequestManager::CHCIServerRequestManager(CCoreHCIPluginImpl& aHCI)
+ :	iHCI(aHCI)
+	{
+	LOG_FUNC
+	}
+	
+void CHCIServerRequestManager::ConstructL()
+	{
+	LOG_FUNC
+	}
+
+void CHCIServerRequestManager::ServiceL(CHCISession& aSession, const RMessage2& aMessage)
+	{
+	if(aMessage.Function() == EServiceSpecificRequest)
+		{
+		if(HasCapabilities(aMessage))
+			{
+			DoServiceL(aSession, aMessage);
+			}
+		// else HasCapabilities failed (and has dealt with aMessage).
+		}
+	else
+		{
+		// The client has issued a bad HCI Server request, we only expect a server specific
+		// request to be made (the specific request being encoded in the TIpcArgs).
+		PanicClient(aMessage, EUnknownHciServerFunction);
+		}
+	}
+
+//
+// HCI Direct Access Service
+//
+CHCIDirectAccessManager* CHCIDirectAccessManager::NewL(CCoreHCIPluginImpl& aHCI)
+	{
+	LOG_STATIC_FUNC
+	
+	CHCIDirectAccessManager* self = new (ELeave) CHCIDirectAccessManager(aHCI);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+void CHCIDirectAccessManager::SetHCICommandQueue(MHCICommandQueue& aHCICommandQueue)
+	{
+	LOG_FUNC
+	
+	__ASSERT_ALWAYS(!iHCICommandQueue, PANIC(KCoreHciPanicCat, EInterfaceAlreadyInitialised));
+	iHCICommandQueue = &aHCICommandQueue;
+	}
+
+/*virtual*/ TBool CHCIDirectAccessManager::HasCapabilities(const RMessage2& aMessage)
+	{
+	LOG_FUNC
+	
+	TBool allowed = EFalse;
+	
+	switch (aMessage.Int0())
+		{
+	case KHCIDirectAccessVendorCommand:
+		// Drop through
+	case KHCIDirectAccessCancel: // requires Network Control + Local Services
+		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
+		break;
+
+	default:
+		PanicClient(aMessage, EUnknownDirectAccessFunction);
+		return EFalse;
+		}
+	
+	if(!allowed)
+		{
+		aMessage.Complete(KErrPermissionDenied);
+		}
+		
+	return allowed;
+	}
+
+/*virtual*/ void CHCIDirectAccessManager::DoServiceL(CHCISession& aSession, const RMessage2& aMessage)
+	{
+	LOG_FUNC
+	
+	TInt request = aMessage.Int0();
+
+	switch (request)
+		{
+	case KHCIDirectAccessCancel:
+		if (iAsyncTaskSession != &aSession)
+			{
+			return; //drop - not for current async task
+			}
+
+		// clear cache
+		iMessage = NULL;
+		
+		// perform cancellation procedure
+		CompleteAsyncTask(KErrCancel);
+		break;
+
+	case KHCIDirectAccessVendorCommand:
+		{
+		if (IsAsyncBlocked())
+			{
+			aMessage.Complete(KErrInUse);
+			return;
+			}
+
+		const TInt len = User::LeaveIfError(aMessage.GetDesLength(1));
+		
+		// Check the Vendor Command is at least 3 bytes long for the opcode
+		// and the length
+		if (len < 3)
+			{
+			PanicClient(aMessage, EInvalidVendorCommand);
+			break;
+			}
+		
+		HBufC8* buf = HBufC8::NewLC(len);
+		TPtr8 params(buf->Des());
+		aMessage.ReadL(1, params);
+		
+		// Extract the opcode and create the new command
+		TUint16 opcode = LittleEndian::Get16(params.Ptr());
+		
+		if (iHCICommandQueue)
+			{
+			CVendorDebugCommand* cmd = CVendorDebugCommand::NewL(opcode);
+
+			// Remove the opcode and length from the Vendor Command parameters,
+			// these will be added again to the command frame once it has been
+			// formatted
+			cmd->Command() = params.RightTPtr(params.Length() - 3);
+			
+			// cmd will be deleted in MhcqAddCommandL if Leaves.
+			TUint qid = iHCICommandQueue->MhcqAddCommandL(cmd, *this);
+
+			// Block only after we succeed in adding a command.
+			BlockAsync(aSession, aMessage);
+
+			// Cache to return completion data to client
+			iMessage = &aMessage;
+			}
+		else
+			{
+			// Slight possible race that a request is made before we have been
+			// given the command queue to work with - so don't panic just error.
+			aMessage.Complete(KErrNotReady);
+			}
+		CleanupStack::PopAndDestroy(buf);
+		}
+		break;
+
+	default:
+		// Unknown message, panic client
+		PanicClient(aMessage, EUnknownDirectAccessFunction);
+		break;
+		}
+	}
+
+/*virtual*/ void CHCIDirectAccessManager::MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* /*aCommand*/)
+	{
+	LOG_FUNC
+
+	// clear cache
+	iMessage = NULL;
+
+	CompleteAsyncTask(aErrorCode);
+	}
+
+/*virtual*/ void CHCIDirectAccessManager::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aCommand)
+	{
+	LOG_FUNC
+
+	// We are not the unmatched event observer therefore we must always get a
+	// command
+	__ASSERT_DEBUG(aCommand, PANIC(KCoreHciPanicCat, EReceivedUnmatchedEvent));
+	
+	// It is possible to receive an event but not have a message to complete. This
+	// could happen if a request was cancelled after a Vendor Specific command was
+	// sent, in this case we do nothing.
+	if (iMessage)
+		{
+		TInt err = KErrNone;
+		
+		const THCIEventCode eventcode(aEvent.EventCode());
+		switch(eventcode)
+			{
+		case ECommandCompleteEvent:
+			{
+			if ((aCommand->Opcode() & KVendorDebugOGF) == KVendorDebugOGF)
+				{
+				const TVendorDebugCompleteEvent& event = TVendorDebugCompleteEvent::Cast(aEvent);
+				
+				// Return the event
+				err = iMessage->Write(KHCIServerIpcDesOutParam, event.VendorDebugData());
+				}
+			else
+				{
+				__ASSERT_DEBUG(EFalse, PANIC(KHciServerPanicCat, ENonVendorOpcodeCompleted));
+				}
+			}
+			break;
+
+		case EVendorDebugEvent:
+			{
+			const TVendorDebugEvent& event = TVendorDebugEvent::Cast(aEvent);
+
+			// Return the event
+			err = iMessage->Write(KHCIServerIpcDesOutParam, event.VendorDebugData());
+			}
+			break;
+			
+		default:
+			__ASSERT_DEBUG(EFalse, PANIC(KCoreHciPanicCat, EReceivedUnknownEvent));
+			break;
+			}
+
+		CompleteAsyncTask(err);
+		}
+	}
+
+/*virtual*/ void CHCIDirectAccessManager::CompleteAsyncTask(TInt aError)
+	{
+	LOG_FUNC
+
+	if (!IsAsyncBlocked())
+		{
+		return; //drop
+		}
+
+	CHCIServerRequestManager::CompleteAsyncTask(aError);
+	}
+
+CHCIDirectAccessManager::CHCIDirectAccessManager(CCoreHCIPluginImpl& aHCI)
+:	CHCIServerRequestManager(aHCI)
+	{
+	LOG_FUNC
+	}
+	
+
+TUint CHCIDirectAccessManager::MaskBit() const
+	{
+	LOG_FUNC
+	
+	return EHCIDirectAccessMaskBit;
+	}
+			
+//
+// Power Control Service
+//
+CBTPowerControlManager* CBTPowerControlManager::NewL(CCoreHCIPluginImpl& aHCI)
+	{
+	LOG_STATIC_FUNC
+	
+	CBTPowerControlManager* self = new (ELeave) CBTPowerControlManager(aHCI);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+TBool CBTPowerControlManager::HasCapabilities(const RMessage2& aMessage)
+	{
+	LOG_FUNC
+	
+	TBool allowed(EFalse);
+	
+	switch (aMessage.Int0())
+		{
+	case KHCICancelPower:
+		// fall through
+	case EHCISetPower: // requires Network Control + Local Services
+		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
+		break;
+	
+	case EHCIGetPower: // requires Local Services
+		allowed = aMessage.HasCapability(ECapabilityLocalServices);
+		break;
+
+	default:
+		PanicClient(aMessage, EUnknownPowerControlFunction);
+		return EFalse;
+		}
+		
+	if(!allowed)
+		{
+		aMessage.Complete(KErrPermissionDenied);
+		}
+		
+	return allowed;
+	}
+
+/*virtual*/ void CBTPowerControlManager::DoServiceL(CHCISession& aSession, const RMessage2& aMessage)
+	{
+	LOG_FUNC
+
+	TInt request = aMessage.Int0();
+	TInt err;
+	TBTPowerState state;
+	
+	switch (request)
+		{
+	case KHCICancelPower:
+		if(iAsyncTaskSession!=&aSession)
+			{
+			return; //drop - not for current async task
+			}
+
+		//perform cancellation procedure
+		CompleteAsyncTask(KErrCancel);
+		break;
+
+	case EHCISetPower:
+		if(IsAsyncBlocked())
+			{
+			aMessage.Complete(KErrInUse);
+			return;
+			}
+		
+		//Should be called before set power because it could complete synchronously
+		BlockAsync(aSession, aMessage);		
+		state = static_cast<TBTPowerState>(aMessage.Int3());
+		err = iHCI.SetPower(state, NULL);
+		if(err != KErrNone)
+			{
+			CompleteAsyncTask(err);
+			return;
+			}
+		break;
+
+	case EHCIGetPower:
+		{
+		err = iHCI.GetPower(state, NULL);
+		if(err != KErrNone)
+			{
+			aMessage.Complete(err);
+			return;
+			}
+		
+		TPckg<TBTPowerState> pckg(state);
+		TRAP(err, aMessage.WriteL(EPSStateReturnSlot, pckg));
+		aMessage.Complete(err);
+		}
+		break; //synchronous so do not block
+	
+	default:
+		// Unknown message
+		PanicClient(aMessage, EUnknownPowerControlFunction);
+		break;
+		}
+	}
+
+/*virtual*/ void CBTPowerControlManager::CompleteAsyncTask(TInt aError)
+	{
+	LOG_FUNC
+	
+	if(!IsAsyncBlocked())
+		{
+		return; //drop
+		}
+
+	CHCIServerRequestManager::CompleteAsyncTask(aError);
+	}
+
+void CBTPowerControlManager::CompleteRequest(TInt aError)
+	{
+	CompleteAsyncTask(aError);
+	}
+
+CBTPowerControlManager::CBTPowerControlManager(CCoreHCIPluginImpl& aHCI)
+:	CHCIServerRequestManager(aHCI)
+	{
+	LOG_FUNC
+	}
+	
+
+TUint CBTPowerControlManager::MaskBit() const
+	{
+	LOG_FUNC
+	
+	return EBTPowerControlMaskBit;
+	}
+
+//
+// Bluetooth HCI Utils Service
+//
+CBluetoothDutModeManager* CBluetoothDutModeManager::NewL(CCoreHCIPluginImpl& aHCI)
+	{
+	LOG_STATIC_FUNC
+	
+	CBluetoothDutModeManager* self = new (ELeave) CBluetoothDutModeManager(aHCI);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+TBool CBluetoothDutModeManager::HasCapabilities(const RMessage2& aMessage)
+	{
+	LOG_FUNC
+	
+	TBool allowed(EFalse);
+	
+	switch (aMessage.Int0())
+		{
+	case RBluetoothDutMode::EHCIActivateDutMode:
+		// fall through
+	case RBluetoothDutMode::EHCIDeactivateDutMode: // requires Network Control + Local Services
+		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
+		break;
+
+	default:
+		PanicClient(aMessage, EUnknownBluetoothDutModeFunction);
+		return EFalse;
+		}
+		
+	if(!allowed)
+		{
+		aMessage.Complete(KErrPermissionDenied);
+		}
+		
+	return allowed;
+	}
+
+/*virtual*/ void CBluetoothDutModeManager::DoServiceL(CHCISession& /*aSession*/, const RMessage2& aMessage)
+	{
+	LOG_FUNC
+
+	TInt request = aMessage.Int0();
+	TInt err = KErrNotSupported;
+
+	switch (request)
+		{
+	case RBluetoothDutMode::EHCIActivateDutMode:
+		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
+		LOG(_L("EHCIActivateDutMode"));
+		aMessage.Complete(err);
+		break;
+
+	case RBluetoothDutMode::EHCIDeactivateDutMode:
+		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
+		LOG(_L("EHCIDeactivateDutMode"));
+		aMessage.Complete(err);
+		break;
+
+	default:
+		// Unknown message
+		PanicClient(aMessage, EUnknownBluetoothDutModeFunction);
+		break;
+		}
+	}
+
+CBluetoothDutModeManager::CBluetoothDutModeManager(CCoreHCIPluginImpl& aHCI)
+:	CHCIServerRequestManager(aHCI)
+	{
+	LOG_FUNC
+	}
+	
+
+TUint CBluetoothDutModeManager::MaskBit() const
+	{
+	LOG_FUNC
+	
+	return EBluetoothDutModeMaskBit;
+	}
+
+//
+// A2DP Optimiser Service
+//
+CA2dpOptimiserManager* CA2dpOptimiserManager::NewL(CCoreHCIPluginImpl& aHCI)
+	{
+	LOG_STATIC_FUNC
+	
+	CA2dpOptimiserManager* self = new (ELeave) CA2dpOptimiserManager(aHCI);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+TBool CA2dpOptimiserManager::HasCapabilities(const RMessage2& aMessage)
+	{
+	LOG_FUNC
+	
+	TBool allowed(EFalse);
+	
+	switch (aMessage.Int0())
+		{
+	case RA2dpOptimiser::EHCIA2dpOptimiseAcl:
+		// fall through
+	case RA2dpOptimiser::EHCIA2dpRemoveAclOptimisation: // requires Network Control + Local Services
+		allowed = aMessage.HasCapability(ECapabilityNetworkControl) && aMessage.HasCapability(ECapabilityLocalServices);
+		break;
+
+	default:
+		PanicClient(aMessage, EUnknownA2dpOptimiserFunction);
+		return EFalse;
+		}
+		
+	if(!allowed)
+		{
+		aMessage.Complete(KErrPermissionDenied);
+		}
+		
+	return allowed;
+	}
+
+/*virtual*/ void CA2dpOptimiserManager::DoServiceL(CHCISession& /*aSession*/, const RMessage2& aMessage)
+	{
+	LOG_FUNC
+
+	TInt request = aMessage.Int0();
+	TInt err = KErrNotSupported;
+	TBuf<20> targetAddrBuf;
+	
+	switch (request)
+		{
+	case RA2dpOptimiser::EHCIA2dpOptimiseAcl:
+		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
+		if (aMessage.GetDesLength(1) == sizeof(TA2dpOptimisationParams))
+			{
+			TPckgBuf<TA2dpOptimisationParams> args;
+	
+			aMessage.ReadL(1, args);
+			args().RemoteDeviceAddress().GetReadable(targetAddrBuf);
+			LOG3(_L("EHCIA2dpOptimiseAcl BT Addr: %S, Peak Bandwidth: %d, Access Latency: %d\n"), 
+						&targetAddrBuf, args().PeakBandwidth(), args().AccessLatency());
+	
+			aMessage.Complete(err);
+			}
+		else
+			{
+			PanicClient(aMessage, EInvalidArgument);
+			}
+		break;
+
+	case RA2dpOptimiser::EHCIA2dpRemoveAclOptimisation:
+		// Implementation is adaptation specific and therefore not supported in our reference HCI Server
+		if (aMessage.GetDesLength(1) == sizeof(TBTDevAddr))
+			{
+			TPckgBuf<TBTDevAddr> addrBuf;
+	
+			aMessage.ReadL(1, addrBuf);
+			addrBuf().GetReadable(targetAddrBuf);
+			LOG1(_L("EHCIA2dpRemoveAclOptimisation BT Addr: %S\n"), &targetAddrBuf);
+	
+			aMessage.Complete(err);
+			}
+		else
+			{
+			PanicClient(aMessage, EInvalidArgument);
+			}
+		break;
+
+	default:
+		// Unknown message
+		PanicClient(aMessage, EUnknownA2dpOptimiserFunction);
+		break;
+		}
+	}
+
+CA2dpOptimiserManager::CA2dpOptimiserManager(CCoreHCIPluginImpl& aHCI)
+:	CHCIServerRequestManager(aHCI)
+	{
+	LOG_FUNC
+	}
+	
+
+TUint CA2dpOptimiserManager::MaskBit() const
+	{
+	LOG_FUNC
+	
+	return EA2dpOptimiserMaskBit;
+	}
+