bthci/hci2implementations/initialisors/ti/src/ControllerInitialisationPluginImpl.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bthci/hci2implementations/initialisors/ti/src/ControllerInitialisationPluginImpl.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,526 @@
+// 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 "ControllerInitialisationPluginImpl.h"
+#include "ControllerInitialisationCmndParser.h"
+#include "tiinitialisorutils.h"
+
+#include <bluetooth/hci/vendordebugcommand.h>
+#include <bluetooth/hci/controllerinitialisationobserver.h>
+#include <bluetooth/hcicommandqueue.h>
+
+#include <bluetooth/hci/readlocalversioninfocommand.h>
+
+#include <bluetooth/hci/commandcompleteevent.h>
+#include <bluetooth/hci/readlocalversioninfocompleteevent.h>
+#include <bluetooth/hci/vendordebugcompleteevent.h>
+
+#include <bluetooth/hci/hctlconfiginterface.h>
+#include <bluetooth/hci/corehci.h>
+
+#include <bluetooth/logger.h>
+
+#include <es_sock.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_INITIALISOR_TI);
+#endif
+
+_LIT(KScriptPath, "z:\\private\\101f7989\\Bluetooth\\");
+_LIT(KScriptPathFileFormat, "%Stiinit_%d.%d.%d.bts");
+
+const TUint16 KHciVSUpdateUartHCIBaudRate = 0xFF36;
+const TUint16 KHciVSEnableSleepMode = 0xFF0C;
+const TUint16 KHciVSSleepModeConfig = 0xFD0C; // BRF6300 version
+const TUint16 KHciVSSetBDAddr = 0xFC06;
+
+const TUint16 KProjectTypeMask = 0x7C00;	// mask needed to extract the project type
+const TUint16 KProjectTypeShift = 10;		// shift needed to extract the project type
+const TUint16 KMinorVersionMask = 0x007F;
+const TUint16 KMajorVersionMask = 0x0380;	// mask needed to extract the major version
+const TUint16 KMajorVersionShift = 7;		// shift needed to extract the major version
+const TUint16 KBit15Mask = 0x8000;
+const TUint16 KBit15Shift = 12;				// shift needed to move bit15 to bit3
+											// (it will be pre-pended as an extra hi-bit for
+											// the 3-bit major version number)
+
+
+/*static*/ CControllerInitialisationPluginImpl* CControllerInitialisationPluginImpl::NewL()
+	{
+	LOG_STATIC_FUNC
+
+	CControllerInitialisationPluginImpl* self = new (ELeave) CControllerInitialisationPluginImpl();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+void CControllerInitialisationPluginImpl::ConstructL()
+	{
+	LOG_FUNC
+
+	// Add Async Callbacks
+	TCallBack preResetCallBack(AsyncCallBackForPreReset, this);
+	iAsyncCallBackForPreReset = new (ELeave)CAsyncCallBack(preResetCallBack, CActive::EPriorityStandard);
+	TCallBack postResetCallBack(AsyncCallBackForPostReset, this);
+	iAsyncCallBackForPostReset = new (ELeave)CAsyncCallBack(postResetCallBack, CActive::EPriorityStandard);
+
+	iSleepDisableTimer = CSleepDisableTimer::NewL(*this);
+	}
+	
+CControllerInitialisationPluginImpl::CControllerInitialisationPluginImpl()
+  : iInitState(EIdle)
+	{
+	LOG_FUNC
+	}
+
+CControllerInitialisationPluginImpl::~CControllerInitialisationPluginImpl()
+	{
+	LOG_FUNC
+
+	delete iCommandParser;
+	// Delete async CallBacks.	If running, these should be cancelled by the
+	// d'tor of CAsyncOneShot.
+	delete iAsyncCallBackForPreReset;
+	delete iAsyncCallBackForPostReset;		
+	delete iSleepDisableTimer;
+	}
+
+	
+/*virtual*/ TAny* CControllerInitialisationPluginImpl::Interface(TUid aUid)
+	{	
+	LOG_FUNC
+
+	TAny* ret = NULL;
+	switch(aUid.iUid)
+		{
+		case KControllerInitialisationInterfaceUid:
+			ret = reinterpret_cast<TAny*>(static_cast<MControllerInitialisationInterface*>(this));
+			break;
+
+		default:
+			break;
+		};
+	return ret;
+	}
+
+// Static async CallBack methods.
+/*static*/ TInt CControllerInitialisationPluginImpl::AsyncCallBackForPreReset(TAny* aInitPlugin)
+	{
+	LOG_STATIC_FUNC
+
+	CControllerInitialisationPluginImpl* initPlugin = static_cast<CControllerInitialisationPluginImpl*>(aInitPlugin);
+	initPlugin->DoPreReset();
+	return EFalse;	// Don't call back any more.
+	}
+	
+/*static*/ TInt CControllerInitialisationPluginImpl::AsyncCallBackForPostReset(TAny* aInitPlugin)
+	{
+	LOG_STATIC_FUNC
+
+	CControllerInitialisationPluginImpl* initPlugin = static_cast<CControllerInitialisationPluginImpl*>(aInitPlugin);
+	initPlugin->DoPostReset();
+	return EFalse;	// Don't call back any more.
+	}
+
+void CControllerInitialisationPluginImpl::DoPreReset()
+	{
+	LOG_FUNC
+
+	iInitState = EIdle;
+	
+	// Inform stack that we have finished	
+	iControllerInitialisationObserver->McioPreResetCommandComplete(KErrNone);
+	}
+
+void CControllerInitialisationPluginImpl::DoPostReset()
+	{
+	LOG_FUNC
+
+	// Request local version information.
+	CReadLocalVersionInfoCommand* cmd = NULL;
+	TRAPD(err, cmd = CReadLocalVersionInfoCommand::NewL());
+	if(err == KErrNone)
+		{
+		TRAP(err, iHCICommandQueue->MhcqAddInitCommandL(cmd, *this));
+		}
+		
+	if(err != KErrNone)
+		{
+		// Inform the stack of the initialisation status.
+		iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+		}
+	iInitState = EWaitLocalDeviceInfo;
+	}
+
+/*virtual*/ void CControllerInitialisationPluginImpl::MciiPreResetCommand()
+	{
+	LOG_FUNC
+
+	__ASSERT_DEBUG(iControllerInitialisationObserver, PANIC(KTiControllerInitialisorPanic, ENullInitialisationObserver));
+
+	// Use async callback
+	iAsyncCallBackForPreReset->CallBack();	
+	}
+
+/*virtual*/ void CControllerInitialisationPluginImpl::MciiPostResetCommand()
+	{	
+	LOG_FUNC
+
+	__ASSERT_DEBUG(iControllerInitialisationObserver, PANIC(KTiControllerInitialisorPanic, ENullInitialisationObserver));
+	
+	// Use async callback
+	iAsyncCallBackForPostReset->CallBack();
+	}
+
+/*virtual*/ void CControllerInitialisationPluginImpl::MciiSetHCICommandQueue(MHCICommandQueue& aHCICommandQueue)
+	{
+	LOG_FUNC
+
+	__ASSERT_DEBUG(iHCICommandQueue == 0, PANIC(KTiControllerInitialisorPanic, EHciCommandQueueOverwritten));
+	iHCICommandQueue = &aHCICommandQueue;
+	}
+
+/*virtual*/ void CControllerInitialisationPluginImpl::MciiSetControllerInitialisationObserver(MControllerInitialisationObserver& aObserver)
+	{
+	LOG_FUNC
+
+	__ASSERT_DEBUG(iControllerInitialisationObserver == 0, PANIC(KTiControllerInitialisorPanic, EInitialisationObserverOverwritten));
+	iControllerInitialisationObserver = &aObserver;
+	}
+
+/*virtual*/ void CControllerInitialisationPluginImpl::MciiSetCoreHci(MCoreHci& aCoreHci)
+	{
+	LOG_FUNC
+
+	__ASSERT_DEBUG(iCoreHci == 0, PANIC(KTiControllerInitialisorPanic, ECoreHciOverwritten));
+	iCoreHci = &aCoreHci;
+	}
+
+void CControllerInitialisationPluginImpl::SendNextScriptFileCommandL()
+	{
+	LOG_FUNC
+
+	// Create default Vendor command.
+	CVendorDebugCommand* cmd = CVendorDebugCommand::NewL(KVendorDebugOGF);
+	CleanupStack::PushL(cmd);
+	LEAVEIFERRORL(iCommandParser->GetNextVendorCommand(*cmd));
+
+	// Make any command specific changes.
+	switch(cmd->Opcode())
+		{
+		case KHciVSUpdateUartHCIBaudRate:
+			{
+			iDesiredBaudRate = LittleEndian::Get32(cmd->Command().Ptr());
+			}
+			break;
+
+		case KHciVSSetBDAddr:
+			{
+			SetLocalBDAddr(cmd->Command());
+			}
+			break;
+
+		default:
+			// Nothing to do.
+			break;			
+		};
+		
+		
+	// Send the command.
+	CleanupStack::Pop();
+	iHCICommandQueue->MhcqAddInitCommandL(cmd, *this);
+	}
+
+void CControllerInitialisationPluginImpl::MhcqcCommandEventReceived(const THCIEventBase& aEvent,
+																	const CHCICommandBase* /*aRelatedCommand*/)
+	{
+	LOG_FUNC
+
+	if (aEvent.EventCode() == ECommandCompleteEvent)
+		{
+		// Switch on the opcode.
+		THCICommandCompleteEvent& event = THCICommandCompleteEvent::Cast(aEvent);
+		switch(event.CommandOpcode())
+			{
+			case KReadLocalVersionInfoOpcode:
+				{
+				TReadLocalVersionInfoCompleteEvent& lvEvent = TReadLocalVersionInfoCompleteEvent::Cast(event);
+				HandleReadLocalVersionInfoCompleteEvent(lvEvent);
+				}
+				break;
+
+			default:
+				// Check for VS commands.
+				if((event.CommandOpcode() & KVendorDebugOGF) == KVendorDebugOGF)
+					{
+					TVendorDebugCompleteEvent& vEvent = TVendorDebugCompleteEvent::Cast(event);
+					HandleVendorSpecificCompleteEvent(vEvent);
+					}						
+				break;	
+			}
+		}
+	}
+
+void CControllerInitialisationPluginImpl::HandleReadLocalVersionInfoCompleteEvent(const TReadLocalVersionInfoCompleteEvent& aEvent)
+	{
+	LOG_FUNC
+	
+	TInt err = KErrNone;				// innocent until proved guilty
+	
+	if (iInitState == EWaitLocalDeviceInfo)
+		{
+		if (aEvent.ErrorCode() != EOK)
+			{
+			err = KHCIErrorBase - aEvent.ErrorCode();
+			}
+		else
+			{
+			iSubVersion = aEvent.LMPSubversion();
+			
+			// Attempt to open the script file.
+			TFileName fileName;
+			fileName.Format(KScriptPathFileFormat,
+							&KScriptPath,
+			                ((iSubVersion & KProjectTypeMask) >> KProjectTypeShift),
+			                ((iSubVersion & KMajorVersionMask) >> KMajorVersionShift) | ((iSubVersion & KBit15Mask) >> KBit15Shift),
+			                (iSubVersion & KMinorVersionMask));
+
+			TRAP(err, iCommandParser = CCommandParser::NewL(fileName));
+			}
+		if(err == KErrNone)
+			{
+			iSleepDisableTimer->Start();
+			iInitState = EWaitForSleepTimerExpiry;
+			}
+		else
+			{
+			iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+			iInitState = EIdle;
+			}
+		}
+	}
+
+void CControllerInitialisationPluginImpl::HandleVendorSpecificCompleteEvent(const TVendorDebugCompleteEvent& aEvent)
+	{
+	LOG_FUNC
+
+	switch(iInitState)
+		{
+		case ESendScriptCommands:
+			{
+			switch(aEvent.CommandOpcode())
+				{
+				case KHciVSUpdateUartHCIBaudRate:
+					{
+					MHctlConfigInterface* configIf = static_cast<MHctlConfigInterface*>(iCoreHci->MchHctlPluginInterface(TUid::Uid(KHctlConfigInterfaceUid)));
+					__ASSERT_DEBUG(configIf, PANIC(KTiControllerInitialisorPanic, EConfigInterfaceNull));
+
+					TInt err = configIf->MhciUpdateBaudRate(iDesiredBaudRate);
+					if(err != KErrNone)
+						{
+						iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+						}
+					}
+					break;
+
+				case KHciVSEnableSleepMode:
+				case KHciVSSleepModeConfig:
+					{
+					SetSleepProtocol(EFalse);
+					}
+					break;
+					
+				default:
+					break;
+				};
+
+			// Send the next command.
+			TRAPD(err, SendNextScriptFileCommandL());
+			// End of File is not an error that needs to be reported.
+			if(err == KErrEof)
+				{
+				// All commands have been sent.
+				iControllerInitialisationObserver->McioPostResetCommandComplete(KErrNone);
+				}
+			else if(err != KErrNone)
+				{
+				// Inform the stack of the initialisation status.
+				iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+				}
+			}
+			break;
+			
+		case EWaitSleepDisableCompleteEvent:
+			{
+			TUint16 opcode = aEvent.CommandOpcode();
+			if(opcode == KHciVSEnableSleepMode ||
+			   opcode == KHciVSSleepModeConfig)
+				{
+				SetSleepProtocol(EFalse);
+
+				// Response received.  Start sending commands from the script file.
+				iInitState = ESendScriptCommands;
+				
+				TRAPD(err, SendNextScriptFileCommandL());
+				// End of File is not an error that needs to be reported.
+				if(err == KErrEof)
+					{
+					// All commands have been sent.
+					iControllerInitialisationObserver->McioPostResetCommandComplete(KErrNone);
+					}
+				else if(err != KErrNone)
+					{
+					// Inform the stack of the initialisation status.
+					iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+					}
+				}
+			}
+			break;
+		};
+	}
+	
+void CControllerInitialisationPluginImpl::MhcqcCommandErrored(TInt aErrorCode,
+					  										  const CHCICommandBase* /*aCommand*/)
+	{
+	LOG_FUNC
+
+	switch(iInitState)
+		{
+		case EWaitLocalDeviceInfo:
+		case ESendScriptCommands:
+			{
+			// Inform the stack of the initialisation failure.
+			iControllerInitialisationObserver->McioPostResetCommandComplete(aErrorCode);
+			}
+			break;
+
+		default:
+			PANIC(KTiControllerInitialisorPanic, EInvalidInitialisorState);
+			break;
+		};
+	}
+
+
+void CControllerInitialisationPluginImpl::SleepDisableTimerExpired()
+	{
+	LOG_FUNC
+
+	TInt err = KErrNone;
+	CVendorDebugCommand* cmd = NULL;
+	SetSleepProtocol(EFalse);
+	
+	// Send the sleep disable command.
+	if(((iSubVersion & KProjectTypeMask) >> KProjectTypeShift) >= 4)
+		{
+		TRAP(err, cmd = CVendorDebugCommand::NewL(KHciVSSleepModeConfig));
+		if(err == KErrNone)
+			{
+			// Populate the command.
+			TDes8& cmdData = cmd->Command();
+			cmdData.FillZ(9);
+			cmdData[3] = 0xff;
+			cmdData[4] = 0xff;
+			cmdData[5] = 0xff;
+			}
+		}
+	else
+		{
+		TRAP(err, cmd = CVendorDebugCommand::NewL(KHciVSEnableSleepMode));
+		if(err == KErrNone)
+			{
+			// Populate the command.
+			TDes8& cmdData = cmd->Command();
+			cmdData.FillZ(9);
+			}
+		}
+
+	if(err == KErrNone)
+		{
+		TRAP(err, iHCICommandQueue->MhcqAddInitCommandL(cmd, *this));
+		}
+		
+	if(err != KErrNone)
+		{
+		// Inform the stack of the initialisation status.
+		iControllerInitialisationObserver->McioPostResetCommandComplete(err);
+		}
+	iInitState = EWaitSleepDisableCompleteEvent;
+	}
+
+void CControllerInitialisationPluginImpl::SetLocalBDAddr(TDes8& /*aVSCommandData*/) const
+	{
+	LOG_FUNC
+
+	// Update the address from the script file if required.
+	}
+
+void CControllerInitialisationPluginImpl::SetSleepProtocol(TBool /*aEnabled*/)
+	{
+	LOG_FUNC
+
+	// Adjust the controller sleep protocol.
+	}
+	
+//
+//
+CSleepDisableTimer* CSleepDisableTimer::NewL(MSleepDisableTimerEventObserver& aTimerObserver)
+	{
+	LOG_STATIC_FUNC
+
+   	CSleepDisableTimer* self = new (ELeave) CSleepDisableTimer(aTimerObserver);
+   	CleanupStack::PushL(self);
+   	self->ConstructL();
+   	CleanupStack::Pop(self);
+   	return self;
+	}
+
+void CSleepDisableTimer::ConstructL()
+	{
+	LOG_FUNC
+
+   	CTimer::ConstructL();
+   	CActiveScheduler::Add(this);
+	}
+
+CSleepDisableTimer::CSleepDisableTimer(MSleepDisableTimerEventObserver& aTimerObserver)
+  : CTimer(EPriorityStandard),
+    iTimerObserver(aTimerObserver)
+	{
+	LOG_FUNC
+	}
+
+void CSleepDisableTimer::Start()
+	{
+	LOG_FUNC
+
+	if(!IsActive())
+		{
+		After(KSleepDisableTimerDuration);
+		}
+	}
+	
+void CSleepDisableTimer::RunL()
+	{
+ 	LOG_FUNC
+
+  	iTimerObserver.SleepDisableTimerExpired();
+   	}