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