bluetooth/btstack/linkmgr/hcifacade_events.cpp
changeset 0 29b1cd4cb562
child 16 9f17f914e828
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/linkmgr/hcifacade_events.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,1386 @@
+// 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:
+// This file is made up of 4 different sections:
+// - Command Complete processing functions
+// These are private functions that implement a specific command 
+// complete event, one per handled opcode.
+// - Event processing functions
+// These are private functions that implement a specific
+// command event, one per handled event. These events may or may not
+// be matched to a particular command. 
+// - Data event processing functions
+// These are private functions that implement a specific data event,
+// one per handled event.
+// - HCI APIs
+// These are the functions that are called directly by the 
+// different parts of the HCI and make up the MHCICommandQueueClient 
+// and MHCIDataEventObserver interfaces.
+// 
+//
+
+#include <bluetooth/logger.h>
+#include "hcifacade.h"
+#include "physicallinksmanager.h"
+#include "linkmgr.h"
+#include "hostresolver.h"
+#include "linkutil.h"
+#include "linkmuxer.h"
+#include "linkflowcontrol.h"
+#include "linkconsts.h"
+#include "VendorSAP.h"
+#include "vendorspecific.h"
+#include "AclDataQController.h"
+#include "pairingserver.h"
+#include "oobdata.h"
+
+#include <e32std.h>
+#include <bt_sock.h>
+#include <utf.h>
+#include <es_ini.h>
+#include <btextnotifiers.h>
+#include <bluetooth/hcicommandqueue.h>
+#include <bluetooth/hci/hciopcodes.h>
+
+#include <bluetooth/hci/command.h>
+
+// Command Events
+#include <bluetooth/hci/connectioncompleteevent.h>
+#include <bluetooth/hci/connectionrequestevent.h>
+#include <bluetooth/hci/disconnectioncompleteevent.h>
+#include <bluetooth/hci/authenticationcompleteevent.h>
+#include <bluetooth/hci/encryptionchangeevent.h>
+#include <bluetooth/hci/readremsuppfeatcompleteevent.h>
+#include <bluetooth/hci/readremoteextendedfeaturescompleteevent.h>
+#include <bluetooth/hci/readremverinfocompleteevent.h>
+#include <bluetooth/hci/commandstatusevent.h>
+#include <bluetooth/hci/hardwareerrorevent.h>
+#include <bluetooth/hci/rolechangeevent.h>
+#include <bluetooth/hci/numberofcompletedpacketsevent.h>
+#include <bluetooth/hci/modechangeevent.h>
+#include <bluetooth/hci/pincoderequestevent.h>
+#include <bluetooth/hci/linkkeyrequestevent.h>
+#include <bluetooth/hci/linkkeynotificationevent.h>
+#include <bluetooth/hci/maxslotschangeevent.h>
+#include <bluetooth/hci/readclockoffsetevent.h>
+#include <bluetooth/hci/connectionpackettypechangedevent.h>
+#include <bluetooth/hci/linksupervisiontimeoutchangedevent.h>
+#include <bluetooth/hci/synchronousconnectioncompleteevent.h>
+#include <bluetooth/hci/vendordebugevent.h>
+#include <bluetooth/hci/vendordebugcompleteevent.h>
+#include <bluetooth/hci/writesimplepairingmodecommand.h>
+#include <bluetooth/hci/readlocalsupportedcommandscommand.h>
+
+
+// Command Complete Events
+#include <bluetooth/hci/writelinkpolicysettingscompleteevent.h>
+#include <bluetooth/hci/readbdaddrcompleteevent.h>
+#include <bluetooth/hci/readbuffersizecompleteevent.h>
+#include <bluetooth/hci/readclassofdevicecompleteevent.h>
+#include <bluetooth/hci/readlocalversioninfocompleteevent.h>
+#include <bluetooth/hci/flushcompleteevent.h>
+#include <bluetooth/hci/readlocalsupportedfeaturescompleteevent.h>
+#include <bluetooth/hci/readlocalsupportedcommandscompleteevent.h>
+#include <bluetooth/hci/readlocaloobdatacompleteevent.h>
+#include <bluetooth/hci/remoteoobdatarequestreplycompleteevent.h>
+#include <bluetooth/hci/remoteoobdatarequestnegativereplycompleteevent.h>
+#include <bluetooth/hci/readinquiryresponsetransmitpowerlevelcompleteevent.h>
+
+// Related commands
+
+#include <bluetooth/hci/readremoteextendedfeaturescommand.h>
+#include <bluetooth/hci/readinquiryresponsetransmitpowerlevelcommand.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_HCI_FACADE);
+#endif
+
+// ----------------------------------------------------------------------------
+// Command Complete processing functions
+// ----------------------------------------------------------------------------
+
+void CHCIFacade::WriteLinkPolicySettingsOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	THCIConnHandle connH(KInvalidConnectionHandle);
+	
+	if (aEvent != NULL)
+		{
+		const TWriteLinkPolicySettingsCompleteEvent& writeLinkPolicyCompleteEvent = TWriteLinkPolicySettingsCompleteEvent::Cast(*aEvent);
+		connH = writeLinkPolicyCompleteEvent.ConnectionHandle();
+		}
+		
+	iLinksMgr->WriteLinkPolicySettingsCompleteEvent(aHciErr, connH);
+	}
+
+void CHCIFacade::ResetOpcode(THCIErrorCode /*aHciErr*/, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	// We only expect a reset command event when we are initialising
+	__ASSERT_ALWAYS(iInitState == EResetting, Panic(EHCICmdQNotInitialising));
+	iInitState = EReset;
+	if (iControllerInitialisor != NULL)
+		{
+		iControllerInitialisor->MciiPostResetCommand();
+		}
+	else
+		{
+		// There is no initialisation plugin so behave as if there
+		// were and it had completed its post reset phase
+		McioPostResetCommandComplete(KErrNone);
+		}
+	}
+
+void CHCIFacade::ReadBdaddrOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+/**
+	Got the local address
+	Tell LinkMgr protocol
+**/
+	{
+	LOG_FUNC
+	if ((aHciErr == EOK) && (aEvent != NULL))
+		{
+		const TReadBdaddrCompleteEvent& readBdaddrCompleteEvent = TReadBdaddrCompleteEvent::Cast(*aEvent);
+		iLinkMgrProtocol.SetLocalBTAddress(readBdaddrCompleteEvent.BDADDR());
+		}
+	// do nothing if error
+	}
+
+void CHCIFacade::ReadBufferSizeOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	if ((aHciErr == EOK) && (aEvent != NULL))
+		{
+		const TReadBufferSizeCompleteEvent& readBufSizeCompleteEvent = TReadBufferSizeCompleteEvent::Cast(*aEvent);
+
+		TUint aclPacketLen = readBufSizeCompleteEvent.HCACLDataPacketLength();
+		TUint scoPacketLen = readBufSizeCompleteEvent.HCSynchronousDataPacketLength();
+		TUint noAclPackets = readBufSizeCompleteEvent.HCTotalNumACLDataPackets();
+		TUint noScoPackets = readBufSizeCompleteEvent.HCTotalNumSynchronousDataPackets();
+
+		iLinkMuxer->HandleLocalReadBufferSizeResult(aclPacketLen, scoPacketLen, noAclPackets, noScoPackets);
+		LOG3(_L("Link [HCIFacade_Events.cpp]: ReadBufferSizeResult - aErr %d, aAclMaxLen %d, aNoACL %d"), aHciErr, aclPacketLen, noAclPackets);
+		}
+	}
+
+void CHCIFacade::ReadClassOfDeviceOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	TUint cod(0);
+	
+	if ((aHciErr == EOK) && (aEvent != NULL))
+		{
+		const TReadClassOfDeviceCompleteEvent& readCoDCompleteEvent = TReadClassOfDeviceCompleteEvent::Cast(*aEvent);
+		cod = readCoDCompleteEvent.ClassOfDevice();
+		}
+
+	LOG2(_L("HCIFacade: ReadClassOfDevice Result Event (%d, 0x%x)"), aHciErr, cod);
+	iLinkMgrProtocol.UpdateDeviceClass(aHciErr == EOK, cod);
+	}
+
+void CHCIFacade::WriteLocalNameOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: SetLocalName Command Complete Event"));
+	iLinkMgrProtocol.InquiryMgr().SetLocalNameComplete(CHciUtil::SymbianErrorCode(aHciErr));
+	iLinkMgrProtocol.UpdateLocalDeviceName(aHciErr == EOK);
+	}
+
+void CHCIFacade::WriteCurrentIACLAPOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: WriteCurrentIACLAP Command Complete Event"));
+	
+	iLinkMgrProtocol.UpdateLimitedDiscoverable(aHciErr == EOK);
+	}
+
+void CHCIFacade::WriteClassOfDeviceOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: WriteClassOfDevice Command Complete Event"));
+
+	iLinkMgrProtocol.UpdateDeviceClass(aHciErr == EOK);
+	}
+
+void CHCIFacade::SetControllerToHostFlowControlOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: SetControllerToHostFlowControl Command Complete Event"));
+	iLinkMuxer->RecordHostControllerToHostFlowControl(aHciErr == EOK ? ETrue:EFalse);
+	}
+
+void CHCIFacade::WriteScanEnableOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: WriteScanEnable Command Complete Event"));
+
+	iLinkMgrProtocol.UpdateLocalDeviceScanEnable(aHciErr == EOK);
+	}
+
+void CHCIFacade::SetAFHHostChannelClassificationOpcode(THCIErrorCode /*aHciErr*/, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: WriteAFHHostChannelClassification Command Complete Event"));
+
+	//Update timer to fire after required interval
+	//between AFH Host Channel Classification Commands 
+	iAFHTimer->Cancel();
+	iAFHTimer->After(KAFHHostChannelClassificationIntervalTimer);
+	}
+
+void CHCIFacade::WriteAFHChannelAssessmentModeOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("HCIFacade: WriteAFHChannelAssessmentMode Command Complete Event"));
+	//If 'status' is not EOK, the registry will not be updated. In particular, if
+	//channel assessment is not supported the AFHChannelAssessmentMode
+	//will remain set to ETrue. As this value is only used to update the 
+	//controller, it does not matter.
+	iLinkMgrProtocol.UpdateAFHChannelAssessmentMode(aHciErr == EOK);
+	}
+
+
+void CHCIFacade::ReadLocalVersionInfoOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	TBTDevHCIVersion hciVersion;
+	TBTDevLMPVersion lmpVersion;
+
+	if (aEvent != NULL)
+		{
+		const TReadLocalVersionInfoCompleteEvent& readLocalVersionCompleteEvent = TReadLocalVersionInfoCompleteEvent::Cast(*aEvent);
+		
+		hciVersion.iHCIVersion = readLocalVersionCompleteEvent.Version();
+		hciVersion.iHCIRevision = readLocalVersionCompleteEvent.Revision();
+		lmpVersion.iLMPVersion = readLocalVersionCompleteEvent.LMPVersion();
+		lmpVersion.iManufacturerID = readLocalVersionCompleteEvent.ManufacturerName();
+		lmpVersion.iLMPSubVersion = readLocalVersionCompleteEvent.LMPSubversion();
+		}
+	iLinkMgrProtocol.SetLocalVersion(aHciErr, hciVersion, lmpVersion);
+	
+	if(aHciErr == EOK && aEvent)
+		{
+		if(hciVersion.iHCIVersion > EHWHCIv1_1) // Only send a supported commands command
+			{
+			CReadLocalSupportedCommandsCommand* cmd = NULL;
+			TRAPD(err, cmd = CReadLocalSupportedCommandsCommand::NewL());
+			if(err == KErrNone)
+				{
+				static_cast<void>(SendInitialisationCommand(cmd));
+				}
+			}
+		}
+
+	iReadLocalVersionComplete = ETrue;
+	if (iReadLocalSupportedFeaturesComplete)
+		{
+		SetSupportedEventMasks();		
+		}
+	}
+
+void CHCIFacade::SetSupportedEventMasks()
+	{
+	TBTDevHCIVersion hciVersion;
+	TUint32 supportedEventMaskLoBytes;
+	TUint32 supportedEventMaskHiBytes;
+	
+	// We Dont mask the LoBytes events yet
+	supportedEventMaskLoBytes = THCIEventMask::KDefaultLoBytes;
+	supportedEventMaskHiBytes = THCIEventMask::KDefaultHiBytes;
+	
+	hciVersion = iLinkMgrProtocol.GetHWHCIVersion();
+	
+	if (hciVersion.iHCIVersion < EHWHCIv1_2)
+		{
+		// By default we support the core spec v1.2 however the HiBytes for the supported
+		// events are not used pre v1.2 and by clearing them it allows us to work with old 
+		// controllers if required
+		supportedEventMaskHiBytes = 0;
+		}		
+
+	if (iLinkMgrProtocol.IsExtendedInquiryResponseSupportedLocally())
+		{ 
+		supportedEventMaskHiBytes |=	THCIEventMask::EExtendedInquiryResultEvent;
+		}
+	
+	if (iLinkMgrProtocol.IsSecureSimplePairingSupportedLocally())
+		{  
+		supportedEventMaskHiBytes |=	THCIEventMask::EIOCapabilityRequestEvent|
+										THCIEventMask::EIOCapabilityRequestReplyEvent|
+										THCIEventMask::EUserConfirmationRequestEvent|
+										THCIEventMask::EUserPasskeyRequestEvent|
+										THCIEventMask::ERemoteOOBDataRequestEvent|
+										THCIEventMask::ESimplePairingCompleteEvent|
+										THCIEventMask::EUserPasskeyNotificationEvent|
+										THCIEventMask::EKeypressNotificationEvent;
+		}
+	
+	if (hciVersion.iHCIVersion == EHWHCIv2_1)
+		{  
+		supportedEventMaskHiBytes |=	THCIEventMask::ERemoteHostSupportedFeaturesNotificationEvent;
+		supportedEventMaskHiBytes |=	THCIEventMask::ELinkSupervisionTimeoutChangedEvent;
+		supportedEventMaskHiBytes |=	THCIEventMask::EEncryptionKeyRefreshCompleteEvent;
+		supportedEventMaskHiBytes |=	THCIEventMask::ERemoteHostSupportedFeaturesNotificationEvent;
+		}		
+	
+	THCIEventMask eventMask = {supportedEventMaskLoBytes, supportedEventMaskHiBytes};
+	TRAPD(err, SetEventMaskL(eventMask));
+	__ASSERT_DEBUG(err == KErrNone, Panic(EHCIControllerInitialisation));
+	(void) (err != err);
+	}
+
+void CHCIFacade::ReadLocalSupportedFeaturesOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	if ((aHciErr == EOK) && (aEvent != NULL))
+		{
+		const TReadLocalSupportedFeaturesCompleteEvent& readLocalFeaturesCompleteEvent = TReadLocalSupportedFeaturesCompleteEvent::Cast(*aEvent);
+		TBTFeatures features(readLocalFeaturesCompleteEvent.LMPFeatures());
+		iLinkMgrProtocol.SetLocalFeatures(aHciErr, features);
+
+		if(iLinkMgrProtocol.IsSecureSimplePairingSupportedLocally())
+			{
+			CWriteSimplePairingModeCommand* cmd = NULL;
+			TRAP_IGNORE(cmd = CWriteSimplePairingModeCommand::NewL(ESimplePairingEnabled));
+			static_cast<void>(SendInitialisationCommand(cmd));
+			iLinksMgr->SecMan().SetLocalSimplePairingMode(ETrue); //probably unnecessary
+			}
+		else
+			{
+			iLinksMgr->SecMan().SetLocalSimplePairingMode(EFalse);
+			}
+		}
+	else
+		{
+		iLinkMgrProtocol.SetLocalFeatures(aHciErr, TBTFeatures(0));
+		}
+
+	iReadLocalSupportedFeaturesComplete = ETrue;
+	if (iReadLocalVersionComplete)
+		{
+		SetSupportedEventMasks();		
+		}
+
+	}
+
+void CHCIFacade::ReadLocalSupportedCommandsOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	if ((aHciErr == EOK) && (aEvent != NULL))
+		{
+		const TReadLocalSupportedCommandsCompleteEvent& readLocalCommandsCompleteEvent = TReadLocalSupportedCommandsCompleteEvent::Cast(*aEvent);
+		TBluetoothHciCommands commands(readLocalCommandsCompleteEvent.SupportedCommands());
+		iLinkMgrProtocol.SetLocalCommands(aHciErr, commands);
+
+		if (iLinkMgrProtocol.IsCommandSupportedLocally(ESupportedReadInquiryResponseTransmitPowerCommand))
+			{
+			CReadInquiryResponseTransmitPowerLevelCommand* cmd = NULL;
+			TRAP_IGNORE(cmd = CReadInquiryResponseTransmitPowerLevelCommand::NewL());
+			if(cmd)
+				{
+				static_cast<void>(SendInitialisationCommand(cmd));
+				}
+			}
+
+		}
+	else
+		{
+		TBluetoothHciCommands commands;
+		iLinkMgrProtocol.SetLocalCommands(aHciErr, commands);
+		}
+	}
+
+void CHCIFacade::FlushOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	THCIConnHandle connH(KInvalidConnectionHandle);
+
+	if (aEvent != NULL)
+		{
+		const TFlushCompleteEvent& flushCompleteEvent = TFlushCompleteEvent::Cast(*aEvent);
+		connH = flushCompleteEvent.ConnectionHandle();
+		}
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: FlushCompleteEvent"));
+	iLinkMgrProtocol.ACLController().FlushComplete(CHciUtil::SymbianErrorCode(aHciErr), connH);
+	}
+
+void CHCIFacade::SwitchRoleOpcode(THCIErrorCode aHciErr, const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	if (aHciErr != EOK)
+		{
+		// Role change failed, probably "Role change not allowed", notify clients
+		iLinksMgr->RoleChangeRejectedByHW(aHciErr);
+		return;						
+		}		
+	}
+
+void CHCIFacade::SetEventMaskOpcode(THCIErrorCode __DEBUG_ONLY(aHciErr), const THCIEventBase* /*aEvent*/, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	#ifdef _DEBUG
+	LOG1(_L("HCIFacade: SetEventMask Result Event (%d)"), aHciErr); // leave in at all?
+	#endif
+	__ASSERT_DEBUG(aHciErr ==  EOK, Panic(EHCIControllerInitialisation));
+	iLinkMgrProtocol.LocalSupportedFeaturesAvailable();
+	}
+
+void CHCIFacade::ReadInquiryResponseTransmitPowerLevelOpcode(THCIErrorCode aHciErr, const THCIEventBase* aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	if (aHciErr == EOK && aEvent)
+		{
+		const TReadInquiryResponseTransmitPowerLevelCompleteEvent& readInquiryResponseTransmitPowerLevelCompleteEvent = TReadInquiryResponseTransmitPowerLevelCompleteEvent::Cast(*aEvent);
+		TInt8 txPowerLevel = readInquiryResponseTransmitPowerLevelCompleteEvent.TxPowerLevel();
+		iLinkMgrProtocol.UpdateInquiryResponseTxPowerLevel(txPowerLevel);
+		FTRACE(FPrint(_L("HCIFacade: TxPowerLevel (%d)"), txPowerLevel));
+		}
+	}
+
+
+// ----------------------------------------------------------------------------
+// Event processing functions
+// ----------------------------------------------------------------------------
+
+void CHCIFacade::ConnectionCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand)
+	/**
+	   Some connection request has completed.
+
+	   This may be a successful connection complete, or a failure.
+	**/
+	{
+	LOG_FUNC
+	TBTConnect conn;
+	const TConnectionCompleteEvent& connCompleteEvent = TConnectionCompleteEvent::Cast(aEvent);
+	THCIErrorCode err = aEvent.ErrorCode();
+	
+	conn.iConnH = connCompleteEvent.ConnectionHandle();
+	conn.iBdaddr = connCompleteEvent.BDADDR();
+	conn.iLinkType = TLinkType(connCompleteEvent.LinkType());
+	conn.iEncryptMode = TEncryptMode(connCompleteEvent.EncryptionMode());
+	
+	LOG2(_L("Link [HCIFacade_Events.cpp]: Connection complete event. Code %d, link type=%d [from]"), err,conn.iLinkType);
+	LOGHEXDESC(conn.iBdaddr.Des());
+	iLinksMgr->ConnectionComplete(err, conn);
+
+	if(!aRelatedCommand  ||
+		(aRelatedCommand && (aRelatedCommand->Opcode() == KCreateACLConnectionOpcode)))
+		// this has only to do with paging, that is actively creating connections 
+		// to maintain symmetry with updating UI we do it here, and not trouble PHYmgr
+		{
+		iLinkMgrProtocol.SetUIConnecting(EFalse);
+		}
+	}
+
+void CHCIFacade::AuthenticationCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TAuthenticationCompleteEvent& authCompleteEvent = TAuthenticationCompleteEvent::Cast(aEvent);
+	iLinksMgr->AuthenticationComplete(aEvent.ErrorCode(), authCompleteEvent.ConnectionHandle());
+	}
+
+void CHCIFacade::ReadRemSuppFeatCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TReadRemSuppFeatCompleteEvent& readRemSuppFeatCompleteEvent = TReadRemSuppFeatCompleteEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: ReadRemoteSupportedFeaturesCompleteEvent"));
+	
+	TBTFeatures features(readRemSuppFeatCompleteEvent.LMPFeatures());
+	iLinksMgr->ReadRemoteSupportedFeaturesComplete(aEvent.ErrorCode(), readRemSuppFeatCompleteEvent.ConnectionHandle(), features);
+	}
+
+void CHCIFacade::ReadRemoteExtendedFeaturesCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TReadRemoteExtendedFeaturesCompleteEvent& readRemoteExtendedFeaturesCompleteEvent = TReadRemoteExtendedFeaturesCompleteEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: ReadRemoteExtendedFeaturesCompleteEvent"));
+	
+	TUint64 features = readRemoteExtendedFeaturesCompleteEvent.ExtendedLMPFeatures();
+	TUint8 pageNumber = readRemoteExtendedFeaturesCompleteEvent.PageNumber();
+	TUint8 maxPageNumber = readRemoteExtendedFeaturesCompleteEvent.MaximumPageNumber();
+	iLinksMgr->ReadRemoteExtendedFeaturesComplete(aEvent.ErrorCode(), readRemoteExtendedFeaturesCompleteEvent.ConnectionHandle(), features, pageNumber, maxPageNumber);
+	}
+
+
+void CHCIFacade::ReadRemVerInfoCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TReadRemVerInfoCompleteEvent& readRemVerInfoCompleteEvent = TReadRemVerInfoCompleteEvent::Cast(aEvent);
+	TBTDevRemoteHwVersion ver;
+	
+	ver.iLMPVersion = readRemVerInfoCompleteEvent.LMPVersion();
+	ver.iManufacturerID = readRemVerInfoCompleteEvent.ManufacturerName();
+	ver.iLMPSubVersion = readRemVerInfoCompleteEvent.LMPSubversion();
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: ReadRemoteVersionInformationCompleteEvent"));
+
+	iLinksMgr->ReadRemoteVersionInfoComplete(aEvent.ErrorCode(), readRemVerInfoCompleteEvent.ConnectionHandle(), ver);
+	}
+
+void CHCIFacade::CommandCompleteEvent(THCIOpcode aOpcode, THCIErrorCode aHciErr, 
+										const THCIEventBase* aEvent, const CHCICommandBase* aRelatedCommand)
+	{
+	LOG_FUNC
+	LOG3(_L("aOpcode=%d, aHciErr=%d, iOutstandingCommands.Count()=%d"), aOpcode, aHciErr, iOutstandingCommands.Count());
+
+	switch(aOpcode)
+		{
+	case KWriteLinkPolicySettingsOpcode:
+		WriteLinkPolicySettingsOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KResetOpcode:
+		__ASSERT_ALWAYS(iOutstandingCommands.Count()==1, Panic(EHCICtrlrInitOnlyOneResetCmdAllowed));
+		ResetOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KWriteLocalNameOpcode:
+		WriteLocalNameOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KReadClassOfDeviceOpcode:
+		ReadClassOfDeviceOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KWriteCurrentIACLAPOpcode:
+		WriteCurrentIACLAPOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KWriteClassOfDeviceOpcode:
+		WriteClassOfDeviceOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KSetControllerToHostFlowControlOpcode:
+		SetControllerToHostFlowControlOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KWriteScanEnableOpcode:
+		WriteScanEnableOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KSetAFHHostChannelClassificationOpcode:
+		SetAFHHostChannelClassificationOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KWriteAFHChannelAssessmentModeOpcode:
+		WriteAFHChannelAssessmentModeOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KReadLocalVersionInfoOpcode:
+		ReadLocalVersionInfoOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KReadLocalSupportedFeaturesOpcode:
+		ReadLocalSupportedFeaturesOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+	
+	case KReadLocalSupportedCommandsOpcode:
+		ReadLocalSupportedCommandsOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KReadBufferSizeOpcode:
+		ReadBufferSizeOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KReadBdaddrOpcode:
+		ReadBdaddrOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KFlushOpcode:
+		FlushOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+		
+	case KSwitchRoleOpcode:
+		SwitchRoleOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+
+	case KSetEventMaskOpcode:
+		SetEventMaskOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+
+	case KReadInquiryResponseTransmitPowerLevelOpcode:
+		ReadInquiryResponseTransmitPowerLevelOpcode(aHciErr, aEvent, aRelatedCommand);
+		break;
+
+	// Inquiry related events
+	case KInquiryCancelOpcode:
+	case KRemoteNameRequestCancelOpcode:
+		// Only the inquiry manager issues remote name requests.
+		FTRACE(FPrint(_L("Error!! Unsolicited inquiry-type command complete event (opcode: 0x%04x)"), aOpcode));
+		__ASSERT_DEBUG(EFalse, Panic(EHCIUnmatchedInquiryEvent));
+		break;
+
+	// Security related events that are sent from the facade.
+	case KWriteSimplePairingModeOpcode:
+	case KReadLocalOOBDataOpcode:
+	case KRemoteOOBDataRequestReplyOpcode:
+	case KRemoteOOBDataRequestNegativeReplyOpcode:
+	case KIOCapabilityRequestReplyOpcode:
+	case KUserConfirmationRequestReplyOpcode:
+	case KUserConfirmationRequestNegativeReplyOpcode:
+	case KUserPasskeyRequestReplyOpcode:
+	case KUserPasskeyRequestNegativeReplyOpcode:
+	case KIOCapabilityRequestNegativeReplyOpcode:
+		iLinksMgr->SecMan().HCIEventHandler().MhcqcCommandEventReceived(*aEvent, aRelatedCommand);
+		break;
+		
+	// List of valid command complete event opcodes that we ignore
+	case KRejectConnectionRequestOpcode:
+	case KReadStoredLinkKeyOpcode:
+	case KWriteStoredLinkKeyOpcode:
+	case KDeleteStoredLinkKeyOpcode:
+	case KReadScanEnableOpcode:
+	case KReadEncryptionModeOpcode:
+	case KReadNumberOfSupportedIACOpcode:
+	case KReadVoiceSettingOpcode:
+	case KReadAuthenticationEnableOpcode:
+	case KReadCountryCodeOpcode:
+	case KReadCurrentIACLAPOpcode:
+	case KWriteLinkSupervisionTimeoutOpcode:
+	case KLinkKeyRequestReplyOpcode:
+	case KLinkKeyRequestReplyNegativeOpcode:
+	case KPINCodeRequestReplyOpcode:
+	case KPINCodeRequestReplyNegativeOpcode:
+	case KRoleDiscoveryOpcode:
+	case KPeriodicInquiryModeOpcode:
+	case KExitPeriodicInquiryModeOpcode:
+	case KSetEventFilterOpcode:
+	case KCreateNewUnitKeyOpcode:
+	case KWriteAuthenticationEnableOpcode:
+	case KHostNumberOfCompletedPacketsOpcode:
+	case KWriteEncryptionModeOpcode:
+	case KWritePageTimeoutOpcode:
+	case KReadConnectionAcceptTimeoutOpcode:
+	case KWriteConnectionAcceptTimeoutOpcode:
+	case KWriteVoiceSettingOpcode:
+	case KHostBufferSizeOpcode:
+	case KReadAFHChannelMapOpcode:
+	case KReadAFHChannelAssessmentModeOpcode:
+	case KReadPageTimeoutOpcode:
+	case KCreateConnectionCancelOpcode:
+	case KReadLMPHandleOpcode:
+	case KReadLinkPolicySettingsOpcode:
+	case KReadDefaultLinkPolicySettingsOpcode:
+	case KWriteDefaultLinkPolicySettingsOpcode:	
+	case KReadPINTypeOpcode:
+	case KWritePINTypeOpcode:		
+	case KReadPageScanActivityOpcode:
+	case KWritePageScanActivityOpcode:
+	case KReadInquiryScanActivityOpcode:
+	case KWriteInquiryScanActivityOpcode:
+	case KReadAutomaticFlushTimeoutOpcode:
+	case KWriteAutomaticFlushTimeoutOpcode:
+	case KReadNumBroadcastRetransmissionsOpcode:
+	case KWriteNumBroadcastRetransmissionsOpcode:
+	case KReadHoldModeActivityOpcode:
+	case KWriteHoldModeActivityOpcode:
+	case KReadTransmitPowerLevelOpcode:
+	case KReadSynchronousFlowControlEnableOpcode:
+	case KWriteSynchronousFlowControlEnableOpcode:		
+	case KReadLinkSupervisionTimeoutOpcode:
+	case KReadPageScanPeriodOpcode:
+	case KWritePageScanPeriodOpcode:
+	case KReadPageScanOpcode:
+	case KWritePageScanOpcode:
+	case KReadInquiryScanTypeOpcode:
+	case KWriteInquiryScanTypeOpcode:
+	case KReadInquiryModeOpcode:
+	case KReadPageScanTypeOpcode:
+	case KWritePageScanTypeOpcode:
+	case KReadLocalExtendedFeaturesOpcode:
+	case KReadFailedContactCounterOpcode:
+	case KResetFailedContactCounterOpcode:
+	case KReadLinkQualityOpcode:
+	case KReadRSSIOpcode:
+	case KReadClockOpcode:
+	case KReadLoopbackModeOpcode:
+	case KWriteLoopbackModeOpcode:
+	case KEnableDeviceUnderTestModeOpcode:
+	case KReadExtendedInquiryResponseOpcode:
+
+	case KReadSimplePairingModeOpcode:
+	case KSendKeypressNotificationOpcode:
+
+	case KWriteSimplePairingDebugModeOpcode:
+		
+		// Catch all the events we do not handle
+		LOG1(_L("Warning!! Unhandled Command Complete Event (opcode:%d)"), aOpcode);
+		break;
+		
+	default:
+		THCIOpcode OGF=static_cast<THCIOpcode>(aOpcode&KOGFMask);
+
+		if(OGF==KVendorDebugOGF)
+			{
+			LOG(_L("Link: [HCIFacade_Events.cpp]: Vendor Specfic Command Complete Event"));
+			if(iLinkMgrProtocol.VendorSpecificSAP())
+				{
+				if (aEvent)
+					{
+					TPtrC8 eventPacket(TVendorDebugCompleteEvent::Cast(*aEvent).VendorDebugData());
+					iLinkMgrProtocol.VendorSpecificSAP()->VendorCommandCompleteEvent(aHciErr, &eventPacket);
+					}
+				else
+					{
+					FLOG(_L("Link: [HCIFacade_Events.cpp]: Vendor Specific Command Complete Event is NULL"));
+					iLinkMgrProtocol.VendorSpecificSAP()->VendorCommandCompleteEvent(aHciErr, NULL);
+					}
+				}
+			break;
+			}
+
+		LOG2(_L("Link [HCIFacade_Events.cpp]: Warning: Unknown Command complete event! Opcode %d error code %d"), aOpcode, aHciErr);
+
+		__ASSERT_DEBUG(EFalse, Panic(EHCIUnknownCommandCompleteOpcode));			
+		break;				
+		}
+		
+	if(iInitState == EPostReset)
+		{
+		__ASSERT_ALWAYS(iOutstandingCommands.Count() > 0, Panic(EHCICtrlrInitNoOutstandingCmds));
+		TInt position(FindOutstandingCommandOpCode(aOpcode));
+		
+		if (position < 0)
+			{
+			// HCI matches the incoming event to a command which stack has not sent and hence we must panic.
+			// More explicitly HCI cmdQ has got a command (aRelatedCommand != NULL) which was not sent by stack. 
+			// (position <0 i.e. not found)
+			
+			__ASSERT_ALWAYS(!aRelatedCommand, Panic(EHCICtrlrInitCmdNotFound));
+			}
+		else
+			{
+			iOutstandingCommands.Remove(position);
+			if (!iInitialisationError && iOutstandingCommands.Count() == 0)
+				{
+				// start the CmdQ
+				iCmdController->Start();
+				iInitState = EInitialised;
+				// if we haven't error'd, power is ON
+				iLinkMgrProtocol.UpdateLocalDevicePower(EBTOn);	
+				}
+			}
+		}
+	else if(iInitState == EReset)
+		{
+		// If an initialisor is present, ResetOpcode() calls its MciiPostResetCommand()
+		// function. If this sends an async command, it does not call McioPostResetCommandComplete(),
+		// and iInitState will not get updated and still be set to EReset.
+		// We should remove the command from the queue, without updating iInitState.
+		__ASSERT_ALWAYS(iOutstandingCommands.Count() == 1, Panic(EHCICtrlrInitNoOutstandingCmds));
+		__ASSERT_DEBUG(aOpcode == KResetOpcode, Panic(EHCICtrlrInitCmdNotFound));
+		TInt position(FindOutstandingCommandOpCode(aOpcode));
+		__ASSERT_ALWAYS(position >= 0, Panic(EHCICtrlrInitCmdNotFound));
+		iOutstandingCommands.Remove(position);		
+		}
+	else if(iInitState == EResetting)
+		{
+		__ASSERT_ALWAYS(iOutstandingCommands.Count()==1, Panic(EHCICtrlrInitOnlyOneResetCmdAllowed));
+		}
+	else
+		{
+		__ASSERT_ALWAYS(iOutstandingCommands.Count()==0, Panic(EHCICtrlrInitFailedToRemoveCmd));
+		}
+	}
+
+void CHCIFacade::CommandStatusEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand)
+	{
+	LOG_FUNC
+	const TCommandStatusEvent& commandStatusEvent = TCommandStatusEvent::Cast(aEvent);
+	THCIOpcode opcode = commandStatusEvent.CommandOpcode();
+	THCIErrorCode hciErr = commandStatusEvent.ErrorCode();
+	
+	if (hciErr != EOK)
+		{
+		// got an error
+		// map onto the event that would have occurred: some things we will have to let the client work out
+		// e.g. they should check error and connection handle etc.
+		switch (opcode)
+			{
+		case KCreateACLConnectionOpcode:
+		case KAcceptConnectionRequestOpcode:
+			{
+			TBTConnect nulldevice;
+			nulldevice.iBdaddr = MAKE_TINT64(0,0);
+			nulldevice.iLinkType = EACLLink;
+			iLinksMgr->ConnectionComplete(hciErr, nulldevice);
+
+			if(opcode == KCreateACLConnectionOpcode)
+				// this has only to do with paging, that is actively creating connections 
+				// to maintain symmetry with updating UI we do it here, and not trouble PHYmgr
+				{
+				iLinkMgrProtocol.SetUIConnecting(EFalse);
+				}
+			break;
+			}
+			
+		case KAuthenticationRequestedOpcode:
+			iLinksMgr->AuthenticationComplete(hciErr, KInvalidConnectionHandle);
+			break;
+			
+		case KDisconnectOpcode:
+			iLinksMgr->Disconnection(hciErr, KInvalidConnectionHandle, hciErr); // reason=aStatus
+			break;
+			
+		case KAddSCOConnectionOpcode:
+			{
+			TBTConnect nulldevice;
+			nulldevice.iBdaddr = MAKE_TINT64(0,0);
+			nulldevice.iLinkType = ESCOLink;
+			iLinksMgr->ConnectionComplete(hciErr, nulldevice);
+			break;
+			}
+			
+		case KSetConnectionEncryptionOpcode:
+			iLinksMgr->EncryptionChange(hciErr, KInvalidConnectionHandle, EFalse); // no encryption
+			break;
+			
+		case KReadRemoteSupportedFeaturesOpcode:
+			iLinksMgr->ReadRemoteSupportedFeaturesComplete(hciErr, KInvalidConnectionHandle, TBTFeatures(0)); // no bitmask
+			break;
+			
+		case KReadClockOffsetOpcode:
+			iLinksMgr->ClockOffset(hciErr, KInvalidConnectionHandle, 0);
+			break;
+			
+		case KReadRemoteVersionInfoOpcode:
+			{
+			TBTDevRemoteHwVersion nullversion;
+			nullversion.iLMPVersion=0;
+			nullversion.iManufacturerID=0;
+			nullversion.iLMPSubVersion=0;
+		
+			iLinksMgr->ReadRemoteVersionInfoComplete(hciErr, KInvalidConnectionHandle, nullversion);
+			break;
+			}
+			
+		case KSetupSynchronousConnectionOpcode:
+		case KAcceptSynchronousConnectionRequestOpcode:
+			{
+		    TBTConnect conn;
+		    conn.iConnH = 0;
+		    conn.iLinkType = EeSCOLink;
+
+			TBTSyncConnectOpts syncOpts(0, 0, 0, 0, EuLawLog);
+
+			iLinksMgr->SynchronousConnectionComplete(hciErr, conn, syncOpts);
+			break;
+			}				
+
+		case KHostNumberOfCompletedPacketsOpcode:
+			{
+			iLinksMgr->CompletedPackets(KInvalidConnectionHandle, 0); //no packets
+			break;
+			}
+		
+		case KReadRemoteExtendedFeaturesOpcode:
+			{
+			// Maybe migrate this to use HCIv2 so command is owned by physical link
+			__ASSERT_ALWAYS(aRelatedCommand, Panic(EHCIUnexpectedEvent));
+			__ASSERT_ALWAYS(aRelatedCommand->Opcode() == KReadRemoteExtendedFeaturesOpcode, Panic(EHCICommandBadArgument));
+			const CReadRemoteExtendedFeaturesCommand* cmd = reinterpret_cast<const CReadRemoteExtendedFeaturesCommand*>(aRelatedCommand);
+			iLinksMgr->ReadRemoteExtendedFeaturesComplete(hciErr, cmd->ConnectionHandle(), TUint64(0), cmd->PageNumber(), 0);
+			break;
+			}
+		// Deal with low power mode request failures. 
+		// We only change state when we receive successful responses to low power 
+		// mode requests. Errors can be safely ignored as we haven't changed state
+		// at this time. 
+		// Whilst it would be preferable to handle these responses doing so would 
+		// require substantial changes to the functions that handle low power mode 
+		// requests in order for them to take full advantage of HCIv2. At present 
+		// this problem only occurs in debug mode and so this is solution is preferable. 
+		case KHoldModeOpcode:
+		case KParkModeOpcode:
+		case KExitParkModeOpcode:
+		case KSniffModeOpcode:
+		case KExitSniffModeOpcode:
+			{
+			break;
+			}
+		case KChangeConnectionPacketTypeOpcode:	
+			{
+			iLinksMgr->PacketTypeChange(hciErr, KInvalidConnectionHandle,0);
+			break;
+			}
+		
+		default:
+			// Complete any other commands with an error
+			CommandCompleteEvent(opcode, hciErr, NULL, NULL);
+			break;	
+			}
+		}
+	else // Error free status event
+		{
+		switch (opcode)
+			{
+		case KCreateACLConnectionOpcode:
+			// protocol looks after the ui gubbins
+			iLinkMgrProtocol.SetUIConnecting(ETrue);		
+			break;
+			
+		case KAuthenticationRequestedOpcode:
+			// tell secman that it really going through authentication
+			iLinksMgr->SecMan().AuthenticationInProgress();
+			break;
+		
+		default:
+			break;
+			}
+		}
+	}
+
+void CHCIFacade::ReadClockOffsetEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TReadClockOffsetEvent& readClockOffsetEvent = TReadClockOffsetEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: ReadClockOffsetResultEvent"));
+	iLinksMgr->ClockOffset(aEvent.ErrorCode(), readClockOffsetEvent.ConnectionHandle(), readClockOffsetEvent.ClockOffset());
+	}
+
+void CHCIFacade::ConnectionPacketTypeChangedEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TConnectionPacketTypeChangedEvent& connPacketTypeChangedEvent = TConnectionPacketTypeChangedEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]:ConnectionPacketTypeChangedEvent"));
+	// we need to pass onto the connections manager - this will let the connections know
+	// and subsequently the baseband model
+	iLinksMgr->PacketTypeChange(aEvent.ErrorCode(), connPacketTypeChangedEvent.ConnectionHandle(), connPacketTypeChangedEvent.PacketType());
+	}
+
+void CHCIFacade::LinkSupervisionTimeoutChangedEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TLinkSupervisionTimeoutChangedEvent& linkSupervisionTimeoutChangedEvent = TLinkSupervisionTimeoutChangedEvent::Cast(aEvent);
+
+	iLinksMgr->LinkSupervisionTimeoutChange(aEvent.ErrorCode(),
+											linkSupervisionTimeoutChangedEvent.ConnectionHandle(),
+											linkSupervisionTimeoutChangedEvent.LinkSupervisionTimeout());
+	}
+
+void CHCIFacade::SynchronousConnectionCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TSynchronousConnectionCompleteEvent& syncConnCompleteEvent = TSynchronousConnectionCompleteEvent::Cast(aEvent);
+	
+    TBTConnect conn;
+    conn.iConnH = syncConnCompleteEvent.ConnectionHandle();
+    conn.iBdaddr = syncConnCompleteEvent.BDADDR();
+    conn.iLinkType = TLinkType(syncConnCompleteEvent.LinkType());
+	
+	LOG(_L("Link [HCIFacade_Events.cpp]: Synchronous connection complete [from]"));
+	LOGHEXDESC(conn.iBdaddr.Des());
+
+	TBTSyncConnectOpts syncOpts(syncConnCompleteEvent.TransmissionInterval(), 
+								syncConnCompleteEvent.RetransmissionWindow(),
+								syncConnCompleteEvent.RxPacket_Length(),
+								syncConnCompleteEvent.TxPacket_Length(),
+								TAirMode(syncConnCompleteEvent.AirMode()));
+
+	iLinksMgr->SynchronousConnectionComplete(aEvent.ErrorCode(), conn, syncOpts);
+	}
+
+void CHCIFacade::VendorDebugEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	LOG(_L("Link [HCIFacade_Events.cpp]: **WARNING** - Just received a Vendor Specific Debug Event !"));
+
+	if(iLinkMgrProtocol.VendorSpecificSAP())
+		{
+		const TVendorDebugEvent& vendorEvent = TVendorDebugEvent::Cast(aEvent);
+
+		const TDesC8& des = vendorEvent.VendorDebugData();
+		iLinkMgrProtocol.VendorSpecificSAP()->VendorDebugEvent(aEvent.ErrorCode(), &des);
+		}	
+	}
+
+void CHCIFacade::ConnectionRequestEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+/**
+   A connection request has come in.
+   
+   Tell connections mgr = it will decide whether to accept or not
+**/
+	{
+	LOG_FUNC
+	TBTConnect conn;
+	const TConnectionRequestEvent& connRequestEvent = TConnectionRequestEvent::Cast(aEvent);
+	THCIErrorCode err = aEvent.ErrorCode();
+	
+	conn.iBdaddr = connRequestEvent.BDADDR();
+	conn.iCoD = connRequestEvent.ClassOfDevice();
+	conn.iLinkType = TLinkType(connRequestEvent.LinkType());
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: Connection request [from]"));
+	LOGHEXDESC(conn.iBdaddr.Des());
+	
+	iLinksMgr->ConnectionRequest(conn);	// passes Address and CoD
+	}
+
+void CHCIFacade::DisconnectionCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+/**
+   Disconnect indication up from hardware.
+   
+   Called for local or remote initiated baseband disconnect, or on
+   hardware failure.
+   Any flushed ACL data will be indicated up to us seperately.
+   
+   @param aErr    HCI Error code -- if not EOK we didn't actually connect.
+   @param aConnH  Handle the disconnect happended on.
+   @param aReason If aErr == EOK, this tells us why we disconnect. Else not valid.
+**/
+	{
+	LOG_FUNC
+	const TDisconnectionCompleteEvent& disconnCompleteEvent = TDisconnectionCompleteEvent::Cast(aEvent);
+	THCIErrorCode err = aEvent.ErrorCode();
+	THCIConnHandle connH = disconnCompleteEvent.ConnectionHandle();
+	THCIErrorCode reason = THCIErrorCode(disconnCompleteEvent.Reason());
+	
+	LOG2(_L("HCI: disconnection complete event, handle %d, error %d"), connH, err);
+	iLinksMgr->Disconnection(err, connH, reason);
+	}
+
+void CHCIFacade::EncryptionChangeEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TEncryptionChangeEvent& encryptChangeEvent = TEncryptionChangeEvent::Cast(aEvent);
+	iLinksMgr->EncryptionChange(aEvent.ErrorCode(), encryptChangeEvent.ConnectionHandle(), encryptChangeEvent.EncryptionEnable());
+	}
+
+void CHCIFacade::HardwareErrorEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const THardwareErrorEvent& hardwareErrorEvent = THardwareErrorEvent::Cast(aEvent);
+	TUint8 hwErr = hardwareErrorEvent.HardwareCode();
+	
+	// Just log event, QDP is responsible for 'rebooting' the stack if required
+	LOG1(_L("Link [HCIFacade_Events.cpp]: Error! HardwareErrorEvent Received: %d"), hwErr);
+	}
+
+void CHCIFacade::RoleChangeEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TRoleChangeEvent& roleChangeEvent = TRoleChangeEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: RoleChangeEvent"));
+	iLinksMgr->RoleChange(aEvent.ErrorCode(), roleChangeEvent.BDADDR(), TBTBasebandRole(roleChangeEvent.Newrole()));
+	}
+
+void CHCIFacade::ModeChangeEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TModeChangeEvent& modeChangeEvent = TModeChangeEvent::Cast(aEvent);
+	TBTLinkMode mode = EActiveMode;
+	switch(modeChangeEvent.CurrentMode())
+		{
+	// Mode 0, as defined for the Mode Change Event, is Active Mode
+	case 0: 
+		break;
+		
+	case 1: 
+		mode = EHoldMode; 
+		break;
+		
+	case 2:	
+		mode = ESniffMode;
+		break;
+		
+	case 3:
+		mode = EParkMode;
+		break;
+		
+	default:
+		__ASSERT_ALWAYS(EFalse, Panic(EHCICommandBadArgument));
+		break;
+		}
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: ModeChangeEvent"));
+	iLinksMgr->ModeChange(aEvent.ErrorCode(), modeChangeEvent.ConnectionHandle(), mode, modeChangeEvent.Interval());
+	}
+
+void CHCIFacade::PINCodeRequestEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TPINCodeRequestEvent& pinCodeRequestEvent = TPINCodeRequestEvent::Cast(aEvent);
+
+	iLinksMgr->PinRequest(pinCodeRequestEvent.BDADDR(), *this);
+	}
+
+void CHCIFacade::LinkKeyRequestEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TLinkKeyRequestEvent& linkKeyRequestEvent = TLinkKeyRequestEvent::Cast(aEvent);
+
+	// Tell the Connections Manager
+	// this is something the Connections look after - they can tell the Registry when they want of the new key
+	iLinksMgr->LinkKeyRequest(linkKeyRequestEvent.BDADDR(), *this);
+	}
+
+void CHCIFacade::LinkKeyNotificationEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TLinkKeyNotificationEvent& linkKeyNotEvent = TLinkKeyNotificationEvent::Cast(aEvent);
+
+	// Tell the Connections Manager
+	// this is something the Connections look after - they can tell the Registry when they want of the new key
+	iLinksMgr->NewLinkKey(linkKeyNotEvent.BDADDR(), linkKeyNotEvent.LinkKey(), static_cast<THCILinkKeyType>(linkKeyNotEvent.KeyType()));
+	}
+
+void CHCIFacade::MaxSlotsChangeEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+	const TMaxSlotsChangeEvent& maxSlotsChangeEvent = TMaxSlotsChangeEvent::Cast(aEvent);
+
+	LOG(_L("Link [HCIFacade_Events.cpp]: MaxSlotsChangeEvent"));
+	iLinksMgr->MaxSlotsChange(maxSlotsChangeEvent.ConnectionHandle(), maxSlotsChangeEvent.LMPMaxSlots());
+	}
+
+// ----------------------------------------------------------------------------
+// Data event processing functions
+// ----------------------------------------------------------------------------
+
+void CHCIFacade::NumberOfCompletedPacketsEvent(THCIEventBase& aEvent)
+/**
+	Packets sent by HC to remote device.
+	For informational scheduling purposes, this connection handle just
+	cleared its oldest aNum packets.
+**/
+	{
+	LOG_FUNC
+	const TNumberOfCompletedPacketsEvent& numCompletedPacketsEvent = TNumberOfCompletedPacketsEvent::Cast(aEvent);
+	TUint numPackets;
+
+	TUint numHandles = numCompletedPacketsEvent.NumberofHandles();
+	for (TUint index = 0; index < numHandles; index++)
+		{
+		numPackets = numCompletedPacketsEvent.HCNumOfCompletedPackets(index);
+		
+		LOG1(_L("HCIFacade: Notifying DataQ Controller of %d Completed packets"), numPackets);
+
+		iLinksMgr->CompletedPackets(numCompletedPacketsEvent.ConnectionHandle(index), numPackets);
+		}
+	}
+
+// ----------------------------------------------------------------------------
+// HCI APIs
+// ----------------------------------------------------------------------------
+
+// MHCICommandQueueClient
+void CHCIFacade::MhcqcCommandEventReceived(const THCIEventBase& aEvent,
+										   const CHCICommandBase* aRelatedCommand)
+	{
+	LOG_FUNC
+	switch(aEvent.EventCode())
+		{
+	case EConnectionCompleteEvent:
+		ConnectionCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EAuthenticationCompleteEvent:
+		AuthenticationCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EReadRemSuppFeatCompleteEvent:
+		ReadRemSuppFeatCompleteEvent(aEvent, aRelatedCommand);
+		break;
+	
+	case EReadRemoteExtendedFeaturesCompleteEvent:
+		ReadRemoteExtendedFeaturesCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EReadRemVerInfoCompleteEvent:
+		ReadRemVerInfoCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ECommandCompleteEvent:
+		{
+		const THCICommandCompleteEvent* completeEvent = reinterpret_cast<const THCICommandCompleteEvent*>(&aEvent);
+		CommandCompleteEvent(completeEvent->CommandOpcode(), aEvent.ErrorCode(), &aEvent, aRelatedCommand);
+		break;
+		}
+		
+	case ECommandStatusEvent:
+		CommandStatusEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EReadClockOffsetEvent:
+		ReadClockOffsetEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EConnectionPacketTypeChangedEvent:
+		ConnectionPacketTypeChangedEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ELinkSupervisionTimeoutChangedEvent:
+		LinkSupervisionTimeoutChangedEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ESynchronousConnectionCompleteEvent:
+		SynchronousConnectionCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EConnectionRequestEvent:
+		ConnectionRequestEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EDisconnectionCompleteEvent:
+		DisconnectionCompleteEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EEncryptionChangeEvent:
+		EncryptionChangeEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EHardwareErrorEvent:
+		HardwareErrorEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ERoleChangeEvent:
+		RoleChangeEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EModeChangeEvent:
+		ModeChangeEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EPINCodeRequestEvent:
+		PINCodeRequestEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ELinkKeyRequestEvent:
+		LinkKeyRequestEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case ELinkKeyNotificationEvent:
+		LinkKeyNotificationEvent(aEvent, aRelatedCommand);
+		break;
+		
+	case EMaxSlotsChangeEvent:
+		MaxSlotsChangeEvent(aEvent, aRelatedCommand);
+		break;
+
+	case EVendorDebugEvent:
+		VendorDebugEvent(aEvent, aRelatedCommand);
+		break;
+
+	// Inquiry based events.
+	// By default these should be caused by the inquiry manager and so be returned to it.
+	case EInquiryCompleteEvent:
+	case EInquiryResultEvent:
+	case EInquiryResultwithRSSIEvent:
+	case EExtendedInquiryResultEvent:
+	case ERemoteNameReqCompleteEvent:
+	case ERemoteHostSupportedFeaturesNotificationEvent:
+		FTRACE(FPrint(_L("Error!! Unsolicited inquiry-type event (event code:%d)"), aEvent.EventCode()));
+		__ASSERT_DEBUG(EFalse, Panic(EHCIUnmatchedInquiryEvent));
+		break;
+
+	// Security based events.
+	case EIOCapabilityRequestEvent:
+	case EIOCapabilityResponseEvent:
+	case EUserConfirmationRequestEvent:
+	case ERemoteOOBDataRequestEvent:
+	case ESimplePairingCompleteEvent:
+	case EUserPasskeyNotificationEvent:
+	case EKeypressNotificationEvent:
+		iLinksMgr->SecMan().HCIEventHandler().MhcqcCommandEventReceived(aEvent, aRelatedCommand);
+		break;
+
+	// Catch all the events we do not handle
+	case EChangeLinkKeyEvent:
+	case EMasterLinkKeyEvent:
+	case EQOSSetupCompleteEvent:
+	case EReturnLinkKeysEvent:
+	case EFlowSpecificationCompleteEvent:
+	case ESynchronousConnectionChangedEvent:
+	case ELoopbackCommandEvent:
+	case EPageScanModeChangeEvent:
+	case EPageScanRepetitionModeChangeEvent:
+	case EUserPasskeyRequestEvent:
+	case EEncryptionKeyRefreshCompleteEvent:		
+		LOG1(_L("Warning!! Unhandled Command Event (event code:%d)"), aEvent.EventCode());
+		break;
+		
+	default:
+		LOG1(_L("Warning!! Unknown Command Event Received (event code:%d)"), aEvent.EventCode());
+		__ASSERT_DEBUG(EFalse, Panic(EHCIUnknownCommandEvent));
+		break;
+		}
+	}
+
+void CHCIFacade::MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* aCommand)
+	{
+	LOG_FUNC
+	LOG1(_L("MhcqcCommandErrored: error code:%d"), aErrorCode);
+
+	// The stack maybe in a state that requires a response from the errored command so
+	// fake up a command status event. This will be correctly processed by the stack even if the 
+	// errored command was not expecting a command status event.
+	if (aCommand != NULL)
+		{
+		LOG1(_L("... associated Command (opcode=%d)"), aCommand->Opcode());
+
+		THCIErrorCode err(ECommandDisallowed);		
+		if ((aErrorCode < KHCIErrorBase) && (aErrorCode > (KHCIErrorBase - static_cast<TInt>(KMaxTUint8)))) // error code is 8bits
+			{
+			// aErrorCode is an HCI Error, use it to inform stack
+			err = (THCIErrorCode) (KHCIErrorBase - aErrorCode);
+			}
+			
+		if (iInitState != EInitialised)
+			{
+			__ASSERT_ALWAYS(iOutstandingCommands.Count(), Panic(EHCICtrlrInitNoOutstandingCmds));
+			iInitialisationError = ETrue;
+			}
+		
+		TBuf8<256> fakeCommandStatusBuffer;
+		TCommandStatusEvent fakeCommandStatusEvent(err, 1, aCommand->Opcode(), fakeCommandStatusBuffer);
+		MhcqcCommandEventReceived(fakeCommandStatusEvent, aCommand);
+		
+		}
+	}
+
+// MHCIDataEventObserver
+void CHCIFacade::MhdeoEventNotification(THCIEventBase& aEvent)
+	{
+	LOG_FUNC
+	switch(aEvent.EventCode())
+		{
+	case ENumberOfCompletedPacketsEvent:
+		NumberOfCompletedPacketsEvent(aEvent);
+		break;
+		
+	case EFlushOccurredEvent:
+		LOG(_L("Link [HCIFacade_Events.cpp]: FlushOccuredEvent - NOT HANDLED"));
+		break;
+		
+	case EDataBufferOverflowEvent:
+		Panic(ELinkMgrOverflowedHostController);  // this is really bad - out HC modelling has gone wrong...
+		break;
+		
+	case EQOSViolationEvent:
+		LOG(_L("Link [HCIFacade_Events.cpp]: Warning!! Unhandled QOSViolationEvent"));
+		// we don't do QOS at the moment -drop
+		break;
+		
+	default:
+		LOG(_L("HCIFacade: Warning!! Unknown Data Event Received"));
+		__ASSERT_DEBUG(EFalse, Panic(EHCIUnknownDataEvent));
+		break;
+		}
+	}
+
+