diff -r 28479eeba3fb -r 83036355c0f3 bthci/hci2implementations/corehcis/symbian/src/hciserverrequestmgr.cpp --- 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#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(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 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 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 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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(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 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 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 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; + } +