diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/linkmgr/hcifacade_commands.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/hcifacade_commands.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,602 @@ +// 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: +// These functions are called by parts of the stack that would like to issue +// HCI commands. +// The general pattern is for these functions create a new command and then +// add it to the command Q, which takes ownership of the command. +// +// + +#include +#include "hcifacade.h" +#include "linkutil.h" +#include "linkconsts.h" +#include "hostresolver.h" + +#include +#include +#include "debug.h" +#include +#include +#include + +#include +#include + +// Command Headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void CHCIFacade::SCOConnectL(THCIConnHandle aACLHandle, TUint16 aPacketTypeMask, const TBTDevAddr& aBdaddr) +/** + @pre Callers should check that the ACL Handle exists + + Attempts to attach an SCO link to the baseband +**/ + { + TBTDevHCIVersion hciVersion = iLinkMgrProtocol.GetHWHCIVersion(); // Read Hardware HCI Version + if (hciVersion.iHCIVersion > EHWHCIv1_1) // May not support Add_SCO_Connection + { + #pragma message("KBTVoiceSetting - hardware specific value. KBTVoiceSetting should be replaced by HCI implementation, and should NOT be modified in a BT stack.") + SetupSynchronousConnectionCommandL(aACLHandle,KBTSync64KBit,KBTSync64KBit,KeSCOMaxLatencyDontCare,KBTVoiceSetting,EeSCORetransmitDontCare,(aPacketTypeMask >> KSCOvsSyncHVOffset) | KNoEDReSCOPacketMask, aBdaddr); // Need to specify not to use EDR eSCO packets, as they are enabled by default + } + else // Supports Add_SCO_Connection + { + CAddSCOConnectionCommand* cmd = CAddSCOConnectionCommand::NewL(aACLHandle, aPacketTypeMask, aBdaddr); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + } + +void CHCIFacade::SetupSynchronousConnectionCommandL(THCIConnHandle aACLHandle, + TUint aTransmitBandwidth, TUint aReceiveBandwidth, TUint16 aMaxLatency, + TUint16 aVoiceSettings, TUint8 aRetransmissionEffort, + TBTSyncPacketTypes aPacketTypeMask, const TBTDevAddr& aBdaddr) +/** + @pre Callers should check that the ACL Handle exists + + Attempts to attach a synchronous link to the baseband +**/ + { + CSetupSynchronousConnectionCommand* cmd = CSetupSynchronousConnectionCommand::NewL(aACLHandle, aTransmitBandwidth, aReceiveBandwidth, aMaxLatency, aVoiceSettings, aRetransmissionEffort, aPacketTypeMask, aBdaddr); + #pragma message("NB. This message relates to the CommandsEvents of the HCI(v2). It appears here because CE source code is generated.") + #pragma message("Value of iVoiceSetting (see HCI Command) member is closely related to hardware used. ") + #pragma message("Bits: Input Coding, Input Data, Input Sample Size and Linear_PCM_Bit_pos, should be set...") + #pragma message("...according to hardware capabilities, and OR-ed to create appropriate iVoiceSetting value.") + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::AcceptSynchronousConnectionL(const TBTDevAddr& aBdaddr, + TUint aTransmitBandwidth, TUint aReceiveBandwidth, TUint16 aMaxLatency, + TUint16 aContentFormat, TUint8 aRetransmissionEffort, TBTSyncPacketTypes aPacketTypeMask) + { + CAcceptSynchronousConnectionRequestCommand* cmd = CAcceptSynchronousConnectionRequestCommand::NewL(aBdaddr, aTransmitBandwidth, aReceiveBandwidth, aMaxLatency, aContentFormat, aRetransmissionEffort, aPacketTypeMask); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + + +void CHCIFacade::RejectSynchronousConnectionL(const TBTDevAddr& aBdaddr, THCIErrorCode aReason) + { + CRejectSynchronousConnectionRequestCommand* cmd = CRejectSynchronousConnectionRequestCommand::NewL(aBdaddr, aReason); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + + +void CHCIFacade::ConnectL(const TBTDevAddr& aAddr, + TUint16 aPacketType, + TUint8 aPageScanRepetitionMode, + TUint8 aPageScanMode, + TUint16 aClockOffset, + TUint8 aAllowRoleSwitch) + { + CCreateACLConnectionCommand* cmd = CCreateACLConnectionCommand::NewL(aAddr, aPacketType, aPageScanRepetitionMode, aPageScanMode, aClockOffset, aAllowRoleSwitch); + + // Before the CreateConnection command can be added to the queue we try + // to ensure any inquiry is cancelled as some hardware will disallow the + // connect otherwise. + iLinkMgrProtocol.InquiryMgr().Suspend(); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::DisconnectL(THCIConnHandle aConnH, THCIErrorCode aErr) + { + CDisconnectCommand* cmd = CDisconnectCommand::NewL(aConnH, aErr); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteLinkPolicySettingsL(THCIConnHandle aConnH, TUint16 aSettings) + { + CWriteLinkPolicySettingsCommand* cmd = CWriteLinkPolicySettingsCommand::NewL(aConnH, aSettings); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteScanEnableL(THCIScanEnable aEnable) + { + CWriteScanEnableCommand* cmd = CWriteScanEnableCommand::NewL(aEnable); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::HostNumberOfCompletedPacketsL(THCIConnHandle aConnH, TUint16 aFrags) + { + RArray connHandles; + connHandles.Append(aConnH); + + RArray numPackets; + numPackets.Append(aFrags); + + CHostNumberOfCompletedPacketsCommand* cmd = CHostNumberOfCompletedPacketsCommand::NewL(1, connHandles, numPackets); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::AcceptConnectionRequestL(const TBTDevAddr& aAddr, TUint8 aRole) + { + CAcceptConnectionRequestCommand* cmd = CAcceptConnectionRequestCommand::NewL(aAddr, aRole); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::RejectConnectionRequestL(const TBTConnect& aConnect, THCIErrorCode aReason) + { + CRejectConnectionRequestCommand* cmd = CRejectConnectionRequestCommand::NewL(aConnect.iBdaddr, aReason); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + + +void CHCIFacade::ReadRemoteVersionL(THCIConnHandle aHandle) + { + CReadRemoteVersionInfoCommand* cmd = CReadRemoteVersionInfoCommand::NewL(aHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ReadRemoteSupportedFeaturesL(THCIConnHandle aHandle) + { + CReadRemoteSupportedFeaturesCommand* cmd = CReadRemoteSupportedFeaturesCommand::NewL(aHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ReadRemoteExtendedFeaturesL(THCIConnHandle aHandle, TUint8 aPageNumber) + { + TInt err = KErrNotSupported; + TBTDevHCIVersion hciVersion = iLinkMgrProtocol.GetHWHCIVersion(); // Read Hardware HCI Version + if (hciVersion.iHCIVersion > EHWHCIv1_1) // May not support Read_Remote_Extended_Features command + { + // Maybe migrate this to use HCIv2 so command is owned by physical link + CReadRemoteExtendedFeaturesCommand* cmd = NULL; + TRAP(err, cmd = CReadRemoteExtendedFeaturesCommand::NewL(aHandle, aPageNumber)); + // Ownership of cmd transfered even if MhcqAddCommandL leaves + if(err == KErrNone) + { + TRAP(err, iCmdController->MhcqAddCommandL(cmd, *this)); + } + } + if(err != KErrNone) + { + // Some error occured but we have to signal the SSP state + iLinksMgr->ReadRemoteExtendedFeaturesComplete(EUnknownOpcode, aHandle, TUint64(0), KRemoteExtendedFeaturesPage1, 0); + User::Leave(err); + } + } + + +void CHCIFacade::ReadClockOffsetL(THCIConnHandle aHandle) +/** + Create a command to find remote clock offset +**/ + { + CReadClockOffsetCommand* cmd = CReadClockOffsetCommand::NewL(aHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::RefreshEncryptionKeyL(THCIConnHandle aHandle) + { + CRefreshEncryptionKeyCommand* cmd = CRefreshEncryptionKeyCommand::NewL(aHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteLinkSupervisionTimeoutL(THCIConnHandle aHandle, TInt aTimeout) + { + CWriteLinkSupervisionTimeoutCommand* cmd = CWriteLinkSupervisionTimeoutCommand::NewL(aHandle, aTimeout); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::FlushL(THCIConnHandle aConnH) + { + CFlushCommand* cmd = CFlushCommand::NewL(aConnH); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::SetEventMaskL(const THCIEventMask& aEventMask) + { + static const TUint8 KSizeOf64BitsInBytes = 8; + TBuf8 eventMask; + eventMask.SetLength(KSizeOf64BitsInBytes); + TUint8* ptr = const_cast(eventMask.Ptr()); + LittleEndian::Put32(ptr, aEventMask.iLoBytes); + LittleEndian::Put32(ptr+sizeof(TUint32), aEventMask.iHiBytes); + + CSetEventMaskCommand* cmd = CSetEventMaskCommand::NewL(eventMask); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteLocalNameL(const TDesC8& aName) + { + CWriteLocalNameCommand* cmd = CWriteLocalNameCommand::NewL(aName); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +TInt CHCIFacade::LinkKeyRequestReply(const TBTDevAddr& aBdaddr, const TDesC8& aLinkKey) const +/** + We have obtained a linkkey, tell HC +**/ + { + CLinkKeyRequestReplyCommand* cmd = NULL; + TBTLinkKey linkkey; + linkkey.Copy(aLinkKey); + + TRAPD(err, cmd = CLinkKeyRequestReplyCommand::NewL(aBdaddr, linkkey)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, const_cast(*this))); + } + return err; + } + +TInt CHCIFacade::LinkKeyRequestNegativeReply(const TBTDevAddr& aBdaddr) const +/** + We have not obtained a linkkey, tell HC +**/ + { + CLinkKeyRequestReplyNegativeCommand* cmd = NULL; + + TRAPD(err, cmd = CLinkKeyRequestReplyNegativeCommand::NewL(aBdaddr)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, const_cast(*this))); + } + return err; + } + +TInt CHCIFacade::ChangeConnectionLinkKey(THCIConnHandle aConnHandle) +/** +Change the link key for the specified connection handle +**/ + { + CChangeLinkKeyCommand* cmd = NULL; + + TRAPD(err, cmd = CChangeLinkKeyCommand::NewL(aConnHandle)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, *this)); + } + return err; + } + + +TInt CHCIFacade::PINCodeRequestReply(const TBTDevAddr& aBdaddr,const TDesC8& aPIN) const +/** + We have obtained a PIN, tell HC +**/ + { + CPINCodeRequestReplyCommand* cmd = NULL; + TBTPinCode pin; + pin.Copy(aPIN); + TPtrC8 pinContents(pin().iPIN, pin().iLength); + + TRAPD(err, cmd = CPINCodeRequestReplyCommand::NewL(aBdaddr, pin().iLength, pinContents)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, const_cast(*this))); + } + return err; + } + +TInt CHCIFacade::PINCodeRequestNegativeReply(const TBTDevAddr& aBdaddr) const +/** + We have not obtained a PIN, tell HC +**/ + { + CPINCodeRequestReplyNegativeCommand* cmd = NULL; + + TRAPD(err, cmd = CPINCodeRequestReplyNegativeCommand::NewL(aBdaddr)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, const_cast(*this))); + } + return err; + } + +TInt CHCIFacade::ChangeConnectionPacketType(THCIConnHandle aConnHandle, TUint16 aType) + { + CChangeConnectionPacketTypeCommand* cmd = NULL; + + TRAPD(err, cmd = CChangeConnectionPacketTypeCommand::NewL(aConnHandle, aType)); + if (err == KErrNone) + { + // Ownership of cmd transfered even if MhcqAddCommandL leaves + TRAP(err, iCmdController->MhcqAddCommandL(cmd, *this)); + } + return err; + } + +void CHCIFacade::AuthenticateL(THCIConnHandle aConnHandle) +/** + Do an authentication +**/ + { + CAuthenticationRequestedCommand* cmd = CAuthenticationRequestedCommand::NewL(aConnHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::SetEncryptL(THCIConnHandle aConnHandle,TBool aEnable) +/** + Creates command to enable/disable encryption on a given link +**/ + { + CSetConnectionEncryptionCommand* cmd = CSetConnectionEncryptionCommand::NewL(aConnHandle, aEnable); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::SniffL(THCIConnHandle aHandleToRemote) + { + CSniffModeCommand* cmd = CSniffModeCommand::NewL(aHandleToRemote, KBTSniffModeMaxInterval, KBTSniffModeMinInterval, KBTSniffModeAttempt, KBTSniffModeTimeout); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ExitSniffL(THCIConnHandle aHandleToRemote) + { + CExitSniffModeCommand* cmd = CExitSniffModeCommand::NewL(aHandleToRemote); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::HoldL(THCIConnHandle aHandle) + { + CHoldModeCommand* cmd = CHoldModeCommand::NewL(aHandle, KBTHoldModeMaxInterval, KBTHoldModeMinInterval); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ParkL(THCIConnHandle aHandle) + { + CParkModeCommand* cmd = CParkModeCommand::NewL(aHandle, KBTParkModeBeaconMaxInterval, KBTParkModeBeaconMinInterval); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ExitParkL(THCIConnHandle aHandle) + { + CExitParkModeCommand* cmd = CExitParkModeCommand::NewL(aHandle); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ChangeRoleL(TBTBasebandRole aRole, const TBTDevAddr& aAddr) + { + CSwitchRoleCommand* cmd = CSwitchRoleCommand::NewL(aAddr, aRole); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteDeviceClassL(TUint aCoD) + { + CWriteClassOfDeviceCommand* cmd = CWriteClassOfDeviceCommand::NewL(aCoD); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::SetAFHHostChannelClassificationL(const TBTAFHHostChannelClassification& aChannelClassification) + { + __ASSERT_DEBUG(aChannelClassification.Validate()==KErrNone, + __BTDEBUGGER()); + if(aChannelClassification.Validate()!=KErrNone) + { + //NB If this is called by one of Bluetooth's "Publish + //and Subscribe" subscribers, then the KErrNotSupported + //will be dropped - no error will be reported to the user... + //which is good - we do not want the user reacting to errors. + User::Leave(KErrNotSupported); + } + if(iAFHTimer->IsActive()) + { + //Timer is active => a host channel classification has just been sent. + //Setup timer so that this command is postponed to occur more than one second after + //that last host channel classification command - as per spec. + //NB You only need the latest Host Channel Classification command + //when the timer fires. + iAFHTimer->SetPending(aChannelClassification); + } + else + { + //Start AFHHost Channel Classification Command blocking timer with a + //long timeout (in case command never completes). + //This will be updated when/if the command does complete. + iAFHTimer->After(KAFHHostChannelClassificationCommandCompleteTimer); + + CSetAFHHostChannelClassificationCommand* cmd = CSetAFHHostChannelClassificationCommand::NewL(aChannelClassification); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + } + +void CHCIFacade::WriteAFHChannelAssessmentModeL(TBool aEnable) + { + CWriteAFHChannelAssessmentModeCommand* cmd = CWriteAFHChannelAssessmentModeCommand::NewL(aEnable?1:0); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::SetControllerToHostFlowControlL() + { + CSetControllerToHostFlowControlCommand* cmd = CSetControllerToHostFlowControlCommand::NewL(ETrue); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::ReadDeviceClassL() + { + CReadClassOfDeviceCommand* cmd = CReadClassOfDeviceCommand::NewL(); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + + +void CHCIFacade::ObtainHostControllerBufferSizeL() + { + CReadBufferSizeCommand* cmd = CReadBufferSizeCommand::NewL(); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::AdvertiseHostBufferSizeL(TUint16 aNumBuffers) + { + CHostBufferSizeCommand* cmd = CHostBufferSizeCommand::NewL(KLinkMgrIncomingBufferSize, KStackSCOBuffersSize, aNumBuffers, KStackSCOBuffersNum); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::WriteIACLAPL(TUint8 aNumCurrentIAC, TUint aIAC_LAP[]) + { + RArray iacLap; + + for (TInt count = 0; count < aNumCurrentIAC; count++) + { + iacLap.Append(aIAC_LAP[count]); + } + + CWriteCurrentIACLAPCommand* cmd = CWriteCurrentIACLAPCommand::NewL(aNumCurrentIAC, iacLap); + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + } + +void CHCIFacade::VendorSpecificCommandL(const THCIOpcode aOpcode, + const TDesC8& aParameters) + { + CVendorDebugCommand* cmd = CVendorDebugCommand::NewL(aOpcode); + + CleanupStack::PushL(cmd); + if(aParameters.Length() > cmd->Command().MaxLength()) + { + User::Leave(KErrOverflow); + } + CleanupStack::Pop(); // We don't leave from this point on. + + cmd->Command() = aParameters; + + // Ownership of cmd transfered even if MhcqAddCommandL leaves + iCmdController->MhcqAddCommandL(cmd, *this); + }