bluetooth/btstack/linkmgr/hcifacade.cpp
changeset 0 29b1cd4cb562
child 11 20fda83a6398
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // The conduit to the HCI and HW - formulates and Qs commands, and implements HCI events
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 #include "hcifacade.h"
       
    20 #include "linkmgr.h"
       
    21 #include "hostresolver.h"
       
    22 #include "linkutil.h"
       
    23 
       
    24 #include "AclDataQController.h"
       
    25 #include "linkmuxer.h"
       
    26 #include "linkconsts.h"
       
    27 
       
    28 #include <e32std.h>
       
    29 #include <e32cmn.h>
       
    30 #include <bt_sock.h>
       
    31 #include <es_ini.h>
       
    32 #include <e32base.h>
       
    33 
       
    34 #include <bluetooth/hcicommandqueue.h>
       
    35 #include <bluetooth/hcicommandqitem.h>
       
    36 #include <bluetooth/hcicmdqcontroller.h>
       
    37 
       
    38 #include <bluetooth/hci/controllerinitialisationinterface.h>
       
    39 #include <bluetooth/hci/hcidataframer.h>
       
    40 #include <bluetooth/hci/readlocalsupportedfeaturescommand.h>
       
    41 #include <bluetooth/hci/hostbuffersizecommand.h>
       
    42 #include <bluetooth/hci/resetcommand.h>
       
    43 #include <bluetooth/hci/readbdaddrcommand.h>
       
    44 #include <bluetooth/hci/readlocalversioninfocommand.h>
       
    45 #include <bluetooth/hci/writeconnectionaccepttimeoutcommand.h>
       
    46 #include <bluetooth/hci/writevoicesettingcommand.h>
       
    47 #include <bluetooth/hci/readclassofdevicecommand.h>
       
    48 #include <bluetooth/hci/readbuffersizecommand.h>
       
    49 #include <bluetooth/hci/setcontrollertohostflowcontrolcommand.h>
       
    50 
       
    51 #ifdef __FLOG_ACTIVE
       
    52 _LIT8(KLogComponent, LOG_COMPONENT_HCI_FACADE);
       
    53 #endif
       
    54 
       
    55 // definitions
       
    56 const TBasebandTime TBasebandPolicy::KPageTimeoutR0 = static_cast<TBasebandTime>(2.56 /*seconds*/ / KBasebandSlotTime); // in baseband slots
       
    57 const TBasebandTime TBasebandPolicy::KPageTimeoutR1 = static_cast<TBasebandTime>(5.12 /*seconds*/ / KBasebandSlotTime); // in baseband slots
       
    58 const TBasebandTime TBasebandPolicy::KPageTimeoutR2 = static_cast<TBasebandTime>(10.24 /*seconds*/ / KBasebandSlotTime); // in baseband slots
       
    59 const TReal TBasebandPolicy::KBestEffortTimeMultiplier = 2;
       
    60 const TReal TBasebandPolicy::KQuickTimeMultiplier = 0.5;
       
    61 
       
    62 _LIT(KHciUtilComponentName, "bluetooth_stack");
       
    63 
       
    64 CHCIFacade* CHCIFacade::NewL(CLinkMgrProtocol& aProtocol)
       
    65 	{
       
    66 	LOG_STATIC_FUNC
       
    67 	CHCIFacade* p= new (ELeave) CHCIFacade(aProtocol);
       
    68 	CleanupStack::PushL(p);
       
    69 	p->ConstructL();
       
    70 	CleanupStack::Pop();
       
    71 	return p;
       
    72 	}
       
    73 
       
    74 void CHCIFacade::ConstructL()
       
    75 /**
       
    76    2nd phase construct the HCI Facade.
       
    77    
       
    78    This is where the stack loads both the HCI CommandQ and the CoreHCI and
       
    79    then distributes the required APIs between the different components.
       
    80 **/
       
    81 	{
       
    82 	LOG_FUNC
       
    83 	// Create HCI CommandQ
       
    84 	iCmdController = CHCICmdQController::NewL();
       
    85 
       
    86 	// Create HCI Utility library
       
    87 	iHciUtil = CHciUtil::NewL(KHciUtilComponentName);
       
    88 
       
    89 	// If we can't open the ini file then this will be treated in the same way
       
    90 	// as not reading a valid UID from the ini file.
       
    91 	TRAP_IGNORE(iHciUtil->OpenIniFileL());
       
    92 	
       
    93 	// Create Core HCI plugin
       
    94 	_LIT(KSection, "CoreHci");
       
    95 	_LIT(KCoreHciUidTag, "EcomUid");
       
    96 
       
    97 	TUid coreHciImplUid = TUid::Null();
       
    98 	TRAPD(err, coreHciImplUid = iHciUtil->GetUidFromFileL(KSection, KCoreHciUidTag));
       
    99 	
       
   100 	if (err == KErrNone)
       
   101 		{
       
   102 		// Valid UID found, load it
       
   103 		iCoreHciPlugin = CCoreHCIPlugin::NewL(coreHciImplUid);
       
   104 		}
       
   105 	else
       
   106 		{
       
   107 		// No UID found in ini file, attempt to load single instance of 
       
   108 		// implementation
       
   109 		iCoreHciPlugin = CCoreHCIPlugin::NewL();
       
   110 		}
       
   111 	
       
   112 	// Get Core HCI APIs
       
   113 	iCoreHci = static_cast<MCoreHci*>(iCoreHciPlugin->Interface(TUid::Uid(KCoreHciInterfaceUid)));
       
   114 	iHctl = static_cast<MHCTLInterface*>(iCoreHciPlugin->Interface(TUid::Uid(KHCTLInterfaceUid)));
       
   115 	
       
   116 	iControllerInitialisor = static_cast<MControllerInitialisationInterface*>
       
   117 								(iCoreHciPlugin->Interface(TUid::Uid(KControllerInitialisationInterfaceUid)));
       
   118 	if (iControllerInitialisor != NULL)
       
   119 		{
       
   120 		// attempt to get the Controller Initialisation Abort Extension API
       
   121 		iControllerInitAbortExtension = static_cast<MControllerInitialisationAbortExtensionInterface*>
       
   122 								(iCoreHciPlugin->Interface(TUid::Uid(KControllerInitialisationAbortExtenstionInterfaceUid)));
       
   123 		}
       
   124 	
       
   125 	iDataFramer = static_cast<MHCIDataFramer*>(iCoreHciPlugin->Interface(TUid::Uid(KHCIDataFramerInterfaceUid)));
       
   126 	iHardResetInitiator = static_cast<MHardResetInitiator*>(iCoreHciPlugin->Interface(TUid::Uid(KHCHardResetUid)));
       
   127 
       
   128 	// Panic if we don't get the required interfaces, note that the initialisor
       
   129 	// interface is optional
       
   130 	__ASSERT_ALWAYS(iCoreHci && iHctl && iDataFramer && iHardResetInitiator,
       
   131 					Panic(EHCIIncompleteInterfaces));
       
   132 	
       
   133 	// Provide direct APIs
       
   134 	iCmdController->SetLinkMuxNotifier(*this);
       
   135 	iCmdController->SetHCIUnmatchedEventObserver(*this);
       
   136 	iCmdController->SetHardResetInitiator(*this);
       
   137 	iCmdController->SetPhysicalLinksState(*this);
       
   138 
       
   139 	iCoreHci->MchSetHardResetInitiator(*this);
       
   140 	iCoreHci->MchSetPhysicalLinksState(*this);	
       
   141 	iCoreHci->MchSetDataEventObserver(*this);
       
   142 	iCoreHci->MchSetDataObserver(*this);
       
   143 	iCoreHci->MchSetChannelObserver(*this);
       
   144 	iCoreHci->MchSetControllerStateObserver(*this);
       
   145 	
       
   146 	// Provide Core HCI with CommandQ components
       
   147 	iCoreHci->MchSetCommandEventObserver(*(static_cast<MHCICommandEventObserver*>(iCmdController)));
       
   148 	iCoreHci->MchSetHCICommandQueue(*(static_cast<MHCICommandQueue*>(iCmdController)));
       
   149 	
       
   150 	// Provide CommandQ with HCI components
       
   151 	iCmdController->SetHCTLInterface(*iHctl);
       
   152 	iCmdController->SetHCICommandAllocator(*(static_cast<MHCICommandAllocator*>(iCoreHciPlugin->Interface(TUid::Uid(KHCICommandAllocatorInterfaceUid)))));
       
   153 
       
   154 	// Initialise initialisor plugin if present
       
   155 	if (iControllerInitialisor != NULL)
       
   156 		{
       
   157 		// Provide Initialisor with Stack
       
   158 		iControllerInitialisor->MciiSetControllerInitialisationObserver(*this);
       
   159 
       
   160 		// Provide Initialisor with CommandQ
       
   161 		iControllerInitialisor->MciiSetHCICommandQueue(*(static_cast<MHCICommandQueue*>(iCmdController)));
       
   162 		}
       
   163 
       
   164 	// Attempt to supply the HCI with the Client Usage API
       
   165 	MHCIClientUsageCallback* hciClientUsageCallback = static_cast<MHCIClientUsageCallback*>
       
   166 								(iCoreHciPlugin->Interface(TUid::Uid(KHCIClientUsageCallbackUid)));
       
   167 	
       
   168 	if (hciClientUsageCallback)
       
   169 		{
       
   170 		// Support for the Client Usage Callback API is optional for CoreHCI plugins, pass the HCI
       
   171 		// the Client Usage API if supported.
       
   172 		hciClientUsageCallback->MhcucSetClientUsage(*this);
       
   173 		}
       
   174 
       
   175 	iAFHTimer=CAFHTimer::NewL(*this);
       
   176 	
       
   177 	// Read low power mode override timeout from the configuration file
       
   178 	_LIT(KLPMSection, "lowpowermodeconfiguration");
       
   179 	_LIT(KLPMTag, "overridelpmtimeout_microseconds");
       
   180 
       
   181 	TUint overrideLPMTimeout = 0;
       
   182 	TRAP(err, overrideLPMTimeout = iHciUtil->GetValueFromFileL(KLPMSection, KLPMTag));
       
   183 	
       
   184 	if (err == KErrNone)
       
   185 		{
       
   186 		// LPM override timeout found, pass the value into link manager
       
   187 		iLinkMgrProtocol.SetOverrideLPMTimeout(overrideLPMTimeout);
       
   188 		}
       
   189 	
       
   190 	iLastPowerState = EBTOn;
       
   191 	
       
   192 	// used later to ensure that we have enough data to call SetEventMask
       
   193 	iReadLocalSupportedFeaturesComplete = EFalse;
       
   194 	iReadLocalVersionComplete           = EFalse;
       
   195 			
       
   196 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   197 	iMBufPool = CHostMBufPool::NewL(*this);
       
   198 #endif
       
   199 	}
       
   200 	
       
   201 void CHCIFacade::SetLinkMuxer(CLinkMuxer& aLinkMuxer)
       
   202 	{
       
   203 	LOG_FUNC
       
   204 	iLinkMuxer=&aLinkMuxer;
       
   205 	}
       
   206 
       
   207 
       
   208 void CHCIFacade::SetPhysicalLinksMgr(CPhysicalLinksManager& aLinksMgr)
       
   209 	{
       
   210 	LOG_FUNC
       
   211 	iLinksMgr = &aLinksMgr;
       
   212 	}
       
   213 
       
   214 TInt CHCIFacade::SendInitialisationCommand(CHCICommandBase* aCommand)
       
   215 	/*
       
   216 	  This method takes ownership of the command.
       
   217 	*/
       
   218 	{
       
   219 	LOG_FUNC
       
   220 	__ASSERT_ALWAYS(aCommand != NULL, Panic(EHCICommandNullItem));
       
   221 	__ASSERT_ALWAYS(iInitState==EResetting || iInitState==EPostReset, Panic(EHCICtrlrInitAddingInitialisationCommandInBadState));
       
   222 	if(iInitState==EResetting)
       
   223 		{
       
   224 		__ASSERT_ALWAYS(iOutstandingCommands.Count()==0, Panic(EHCICtrlrInitOnlyOneResetCmdAllowed));
       
   225 		}
       
   226 
       
   227 	TInt err = KErrNone;
       
   228 	TUint qid = 0;
       
   229 
       
   230 	// Ownership of the command is passed to the queue.
       
   231 	// MhcqAddInitCommandL guarantees to take ownership even if it
       
   232 	// leaves.
       
   233 
       
   234 	// see CHCIFacade::MhcqcCommandEventReceived for completion
       
   235 	TRAP(err, qid = iCmdController->MhcqAddInitCommandL(aCommand, *this));
       
   236 	if (err != KErrNone)
       
   237 		{
       
   238 		iInitialisationError = ETrue;
       
   239 
       
   240 		LOG1(_L("Error! CHCIFacade::SendInitialisationCommand %d"), err);
       
   241 		return err;
       
   242 		}
       
   243 
       
   244 	// We need to know when we have completed initialisation of the stack so that
       
   245 	// we can Start() the HCI Command Queue. To do this we keep a list of all the
       
   246 	// initialisation command opcodes and then remove them from the list when we
       
   247 	// get the corresponding completion event. The stack initialisation is complete
       
   248 	// when the list of opcodes is empty.
       
   249 	if ((err = AddOutstandingCommandOpCode(aCommand->Opcode()))	!= KErrNone)
       
   250 		{
       
   251 		if (iCmdController->MhcqRemoveCommand(qid, *this) != KErrNone)
       
   252 			{
       
   253 			Panic(EHCICtrlrInitFailedToRemoveCmd);
       
   254 			}
       
   255 		iInitialisationError = ETrue;
       
   256 
       
   257 		LOG1(_L("Error! CHCIFacade::SendInitialisationCommand %d"), err);
       
   258 		return err;
       
   259 		}
       
   260 
       
   261 	return KErrNone;
       
   262 	}
       
   263 
       
   264 void CHCIFacade::InitL(const TBTLocalDevice& aDeviceConfig)
       
   265 /**
       
   266 	The start-up strategy
       
   267 
       
   268 	If there is an Initialisor the pre-reset initialisation method will
       
   269 	be called on it at this point. When the Initialisor pre-reset method
       
   270 	completes the stack will be called back to enable it to send the HCI
       
   271 	reset command, see McioPreResetCommandComplete().
       
   272 	
       
   273 	If there is no Initialisor then this method will call the pre-reset
       
   274 	complete method directly allowing the stack to send the HCI reset
       
   275 	command.
       
   276 **/
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	// Only re-initialise the stack is the current state is not pre-reset.
       
   280 	if(iInitState != EPreReset)
       
   281 		{
       
   282 		// Initialise the Command Queue
       
   283 		iCmdController->Initialise();
       
   284 		iInitState = EPreReset;
       
   285 		
       
   286 		// DeviceClass is cached and retrieved from HCI if not currently
       
   287 		// set in aDeviceConfig
       
   288 		iDeviceClass = aDeviceConfig.DeviceClass();
       
   289 
       
   290 		// Get the Local Name from the Persist storage
       
   291 		TInt err(iLinkMgrProtocol.SetLocalDeviceName(aDeviceConfig.DeviceName()));
       
   292 		if (KErrNone != err && KErrNotSupported != err)
       
   293 			{
       
   294 			User::Leave(err);
       
   295 			}
       
   296 		if (iControllerInitialisor != NULL)
       
   297 			{
       
   298 			// see CHCIFacade::McioPreResetCommandComplete
       
   299 			iControllerInitialisor->MciiPreResetCommand();
       
   300 			}
       
   301 		else
       
   302 			{
       
   303 			// There is no initialisation plugin so behave as if there
       
   304 			// were and it had completed its pre reset phase
       
   305 			McioPreResetCommandComplete(KErrNone);
       
   306 			}
       
   307 		}
       
   308 	}
       
   309 
       
   310 CHCIFacade::CHCIFacade(CLinkMgrProtocol& aProtocol)
       
   311   : iLinkMgrProtocol(aProtocol),
       
   312     iInitState(EIdle),
       
   313     iInitialisationError(EFalse)
       
   314 	{
       
   315 	LOG_FUNC
       
   316 	}
       
   317 
       
   318 CHCIFacade::~CHCIFacade()
       
   319 	{
       
   320 	LOG_FUNC
       
   321 	delete iAFHTimer;
       
   322 	#ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   323 	delete iMBufPool;
       
   324 	#endif
       
   325 
       
   326 	delete iCoreHciPlugin;
       
   327 	
       
   328 	if(iCmdController)
       
   329 		{
       
   330 		iCmdController->MhcqRemoveAllCommands(*this);
       
   331 		delete iCmdController;
       
   332 		}
       
   333 		
       
   334 	iOutstandingCommands.Close();
       
   335 	delete iHciUtil;
       
   336 	}
       
   337 
       
   338 CHctlAclDataFrame* CHCIFacade::NewACLDataFrameL(TUint16 aSize) const
       
   339 	{
       
   340 	LOG_FUNC
       
   341 	return (iDataFramer->MhdfNewAclDataFrameL(aSize));
       
   342 	}
       
   343 
       
   344 #ifdef STACK_SCO_DATA
       
   345 CHctlSynchronousDataFrame* CHCIFacade::NewSynchronousDataFrameL(TUint8 aSCODataLen) const
       
   346 	{
       
   347 	LOG_FUNC
       
   348 	return (iDataFramer->MhdfNewSynchronousDataFrameL(aSCODataLen));
       
   349 	}
       
   350 #endif
       
   351 
       
   352 THCITransportChannel CHCIFacade::HCTLState() const
       
   353 	{
       
   354 	LOG_FUNC
       
   355 	return iHCTLState; // give to muxer
       
   356 	}
       
   357 
       
   358 
       
   359 
       
   360 void CHCIFacade::HandlePowerStatusChange(TBTPowerState aStatus)
       
   361 /**
       
   362 	This method assumes that the power is actually changing, i.e. from off to on or
       
   363 	from on to off, and it is the responsibility of the caller, the hctl in non-error
       
   364 	conditions, to ensure this.
       
   365 	
       
   366 	The only real dangerous transition is from on to on as this would intialise the
       
   367 	stack even if it is currently in an on state with or without existing state and 
       
   368 	connections.
       
   369 **/
       
   370 	{
       
   371 	LOG_FUNC
       
   372 	switch(aStatus)
       
   373 		{
       
   374 	case EBTOn:
       
   375 		// Start-up Bluetooth
       
   376 		// Avoid from ON to ON
       
   377 		__ASSERT_DEBUG (iLastPowerState == EBTOff, Panic(EHCIPowerStateError));
       
   378 		
       
   379 		iLastPowerState = aStatus;
       
   380 		//recovery the channels
       
   381 		iLinkMgrProtocol.LinkMuxer().ChannelsFree(iHCTLState);
       
   382 		
       
   383 		TRAPD(err, InitL(iLinkMgrProtocol.LocalDevice()));
       
   384 		// Hopefully this should just work it won't rename the device though 
       
   385 		// since that is persisted
       
   386 		if (err)
       
   387 			{
       
   388 			HandlePowerStatusChange(EBTOff);
       
   389 			return;
       
   390 			}
       
   391 		else
       
   392 			{
       
   393 			// Reset the inquiry manager
       
   394 			iLinkMgrProtocol.InquiryMgr().SetHWState(CBTInquiryMgr::EIdle);
       
   395 			// Clear debug mode
       
   396 			iLinkMgrProtocol.SecMan().ClearDebugMode();
       
   397 			}
       
   398 		break;
       
   399 		
       
   400 	case EBTOff:
       
   401 		// Reset the Command Queue
       
   402 		// Avoid from OFF to OFF
       
   403 		__ASSERT_DEBUG (iLastPowerState == EBTOn, Panic(EHCIPowerStateError));
       
   404 			
       
   405 		iLastPowerState = aStatus;
       
   406 		
       
   407 		// Determine if we are waiting for a callback from the initialisation plugin
       
   408 		if ((iInitState == EPreReset) || (iInitState == EReset))
       
   409 			{
       
   410 			// cancel initialisation callback if possible
       
   411 			if (iControllerInitAbortExtension != NULL)
       
   412 				{
       
   413 				iControllerInitAbortExtension->MciaeiAbortInitialisation();
       
   414 				}
       
   415 			}
       
   416 		iInitState = EIdle;
       
   417 			
       
   418 		iCmdController->Reset();
       
   419 		iOutstandingCommands.Reset();
       
   420 		
       
   421 		// Ensure that no command or data messages are output by blocking all channels
       
   422 		//
       
   423 		iLinkMgrProtocol.LinkMuxer().ChannelsClosed(KHCITransportAllChannels);
       
   424 		iLinkMgrProtocol.Error(KErrHardwareNotAvailable);
       
   425 		// Reset UI
       
   426 		iLinkMgrProtocol.SetUIConnecting(EFalse);
       
   427 		iLinkMgrProtocol.SetUINumPhysicalLinks(0);
       
   428 		// The h/w CoD has been reset, so we need to clear our persistent value, to reflect this
       
   429 		iLinkMgrProtocol.ClearPendingLocalDeviceSettingsCod();
       
   430 		
       
   431 		// Removes any pending AFH Channel Classification command 
       
   432 		// and cancels timer.
       
   433 		// NB This ensures AFH host channel classification command blocking is 
       
   434 		// not in place if power comes back on.
       
   435 		iAFHTimer->Reset();
       
   436 		break;
       
   437 		
       
   438 	default:
       
   439 		Panic(EHCIUnknownPowerState);
       
   440 		break;
       
   441 		}
       
   442 	
       
   443 	// Successfully changed power state
       
   444 	iLinkMgrProtocol.UpdateLocalDevicePower(aStatus);
       
   445 	}
       
   446 
       
   447 TInt CHCIFacade::ChangeMode(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
   448 	{
       
   449 	LOG_FUNC
       
   450 	TRAPD(err, DoChangeModeL(aMode, aConnHandle));
       
   451 	return err;
       
   452 	}
       
   453 
       
   454 void CHCIFacade::DoChangeModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
   455 	{
       
   456 	LOG_FUNC
       
   457 	switch (aMode)
       
   458 		{
       
   459 		case ESniffMode:
       
   460 			{
       
   461 			SniffL(aConnHandle);
       
   462 			break;
       
   463 			}
       
   464 		case EParkMode:
       
   465 			{
       
   466 			ParkL(aConnHandle);
       
   467 			break;
       
   468 			}
       
   469 		case EHoldMode:
       
   470 			{
       
   471 			HoldL(aConnHandle);
       
   472 			break;
       
   473 			}
       
   474 		case EScatterMode:
       
   475 		case EActiveMode:
       
   476 			__ASSERT_DEBUG(0, Panic(EHCICommandBadArgument));
       
   477 			break;
       
   478 		}
       
   479 	}
       
   480 	
       
   481 TInt CHCIFacade::ExitMode(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
   482 	{
       
   483 	LOG_FUNC
       
   484 	TRAPD(err, DoExitModeL(aMode, aConnHandle));
       
   485 	return err;
       
   486 	}
       
   487 	
       
   488 void CHCIFacade::DoExitModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
   489 	{
       
   490 	LOG_FUNC
       
   491 	switch (aMode)
       
   492 		{
       
   493 		case ESniffMode:
       
   494 			{
       
   495 			ExitSniffL(aConnHandle);
       
   496 			break;
       
   497 			}
       
   498 		case EParkMode:
       
   499 			{
       
   500 			ExitParkL(aConnHandle);
       
   501 			break;
       
   502 			}
       
   503 		// Not possile to prematurely exit hold mode
       
   504 		default:
       
   505 			{
       
   506 			break;
       
   507 			}
       
   508 		}
       
   509 	}
       
   510 
       
   511 void CHCIFacade::SetupFlowControlL(TFlowControlMode aMode)
       
   512 /** 
       
   513 	Set up flow control scheme to be used.
       
   514 	SetupFlowControlL should only be called once on init because it may leave.
       
   515 
       
   516 	If TFlowControlMode is chosen to be EFlowControlFromHostControllerOnly or 
       
   517 	ETwoWayFlowControlEnabled, then it is the responsibility of the HCI client
       
   518 	to issue the appropriate HostBufferSize(..) command.
       
   519 */
       
   520 	{
       
   521 	LOG_FUNC
       
   522 	switch (aMode)
       
   523 		{
       
   524 		case ENoFlowControl:
       
   525 			{
       
   526 #ifndef _DEBUG
       
   527 			Panic(ELinkMgrBadFlowControlSetInReleaseBuild);
       
   528 #endif
       
   529 			break;
       
   530 			}
       
   531 		case EFlowControlToHostControllerOnly:
       
   532 			{
       
   533 			// the host will not tell the Controller about its buffers
       
   534 
       
   535 			User::LeaveIfError(
       
   536 				SendInitialisationCommand(CReadBufferSizeCommand::NewL()));
       
   537 			break;
       
   538 			}
       
   539 		case EFlowControlFromHostControllerOnly:
       
   540 			{
       
   541 #ifdef _DEBUG
       
   542 			CHCICommandBase *command = CHostBufferSizeCommand::NewL(KLinkMgrIncomingBufferSize,
       
   543 											 KStackSCOBuffersSize, KStackACLBuffersNum,
       
   544 											 KStackSCOBuffersNum);
       
   545 
       
   546 			User::LeaveIfError(SendInitialisationCommand(command));
       
   547 
       
   548 			command = CSetControllerToHostFlowControlCommand::NewL(ETrue);
       
   549 
       
   550 			User::LeaveIfError(SendInitialisationCommand(command));
       
   551 
       
   552 #else
       
   553 			Panic(ELinkMgrBadFlowControlSetInReleaseBuild);
       
   554 #endif
       
   555 			break;
       
   556 			}
       
   557 		case ETwoWayFlowControlEnabled:
       
   558 			{
       
   559 			CHCICommandBase *command = CHostBufferSizeCommand::NewL(KLinkMgrIncomingBufferSize,
       
   560 											 KStackSCOBuffersSize, KStackACLBuffersNum,
       
   561 											 KStackSCOBuffersNum);
       
   562 
       
   563 			User::LeaveIfError(SendInitialisationCommand(command));
       
   564 
       
   565 			command = CSetControllerToHostFlowControlCommand::NewL(ETrue);
       
   566 
       
   567 			User::LeaveIfError(SendInitialisationCommand(command));
       
   568 
       
   569 			break;
       
   570 			}
       
   571 		default:
       
   572 			Panic(ELinkMgrNoSuchFlowControlMode);
       
   573 			break;
       
   574 		}
       
   575 	}
       
   576 
       
   577 
       
   578 // simple forwarding functions so that all stack usage to HCI is via Facade.
       
   579 
       
   580 TInt CHCIFacade::WriteACLData(const CHctlAclDataFrame& aFrame) const
       
   581 	{
       
   582 	LOG_FUNC
       
   583 	return iHctl->MhiWriteAclData(aFrame.HCTLPayload());
       
   584 	}
       
   585 
       
   586 TInt CHCIFacade::WriteSCOData(const CHctlSynchronousDataFrame& aFrame) const
       
   587 	{
       
   588 	LOG_FUNC
       
   589 	return iHctl->MhiWriteSynchronousData(aFrame.HCTLPayload());
       
   590 	}
       
   591 
       
   592 void CHCIFacade::FormatACLData(CHctlAclDataFrame& aFrame, THCIConnHandle aHandle,
       
   593 							   TUint8 aOptions, const TDesC8& aData) const
       
   594 	{
       
   595 	LOG_FUNC
       
   596 	TUint8 flags = aOptions;
       
   597 	TAclPacketBoundaryFlag pbFlag = static_cast<TAclPacketBoundaryFlag>(flags & KPacketPBFlagMask);
       
   598 	TAclPacketBroadcastFlag bcFlag = static_cast<TAclPacketBroadcastFlag>((flags & KPacketBCFlagMask) >> KPacketPBtoBCFlagShift);
       
   599 	iDataFramer->MhdfFormatAclData(aFrame, aHandle, pbFlag, bcFlag, aData);
       
   600 	}
       
   601 
       
   602 void CHCIFacade::FormatSCOData(CHctlSynchronousDataFrame& aFrame, THCIConnHandle aHandle,
       
   603 							   const TDesC8& aData) const
       
   604 	{
       
   605 	LOG_FUNC
       
   606 	iDataFramer->MhdfFormatSynchronousData(aFrame, aHandle, aData);
       
   607 	}
       
   608 
       
   609 void CHCIFacade::MhriStartHardReset()
       
   610 	{
       
   611 	LOG_FUNC
       
   612 	/*
       
   613 	Could have forced a...
       
   614 	HandlePowerStatusChange(EBTOff); 
       
   615 	here - but instead let HCTL call this.
       
   616 	*/
       
   617 	iHardResetInitiator->MhriStartHardReset();
       
   618 	}
       
   619 
       
   620 TUint16 CHCIFacade::ReadACLReportingInterval() const
       
   621 	{
       
   622 	LOG_FUNC
       
   623 	return 0;
       
   624 	}
       
   625 
       
   626 TUint16 CHCIFacade::ReadACLFramingOverhead() const
       
   627 	{
       
   628 	LOG_FUNC
       
   629 	return 0;
       
   630 	}
       
   631 
       
   632 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   633 RMBufChain CHCIFacade::TakeInboundACLDataBufferFromPool(const THCIConnHandle& aForConnHandle)
       
   634 	{
       
   635 	LOG_FUNC
       
   636 	return iMBufPool->TakeBuffer(aForConnHandle);
       
   637 	}
       
   638 #endif
       
   639 
       
   640 // MControllerInitialisationObserver
       
   641 void CHCIFacade::McioPreResetCommandComplete(TInt aError)
       
   642 	{
       
   643 	LOG_FUNC
       
   644 	CHCICommandBase* command(NULL);
       
   645 	TInt err;
       
   646 
       
   647 	// check that we are in the correct state
       
   648 	__ASSERT_ALWAYS(iInitState == EPreReset, Panic(EIncorrectStateOnPreResetCallback));
       
   649 	iInitState = EResetting;
       
   650 	
       
   651 	if (aError != KErrNone)
       
   652 		{
       
   653 		// The initialisor plugin has failed pre reset initialisation
       
   654 		err = aError;
       
   655 		}
       
   656 	else
       
   657 		{
       
   658 		// Send Reset command
       
   659 		TRAP(err, command = CResetCommand::NewL());
       
   660 		
       
   661 		if (err == KErrNone)
       
   662 			{
       
   663 			err = SendInitialisationCommand(command);
       
   664 			}
       
   665 		}
       
   666 		
       
   667 	if (err != KErrNone)
       
   668 		{
       
   669 		// Initialisation has failed. At this point all we can do is power down
       
   670 		// Bluetooth. This means that initialisation can be attempted again by
       
   671 		// turning on the power but this again could fail.
       
   672 		HandlePowerStatusChange(EBTOff);
       
   673 		}
       
   674 	}
       
   675 
       
   676 void CHCIFacade::DoSendPostResetCommandsL()
       
   677 	{
       
   678 	LOG_FUNC
       
   679 	User::LeaveIfError(SendInitialisationCommand(CReadLocalSupportedFeaturesCommand::NewL()));
       
   680 	User::LeaveIfError(SendInitialisationCommand(CReadBdaddrCommand::NewL()));
       
   681 	User::LeaveIfError(SendInitialisationCommand(CReadLocalVersionInfoCommand::NewL()));
       
   682 	
       
   683 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   684 #pragma message("Transport FlowControl = Two Way")
       
   685 
       
   686 	SetupFlowControlL(ETwoWayFlowControlEnabled);
       
   687 		
       
   688 #else
       
   689 #pragma message("Transport FlowControl = None from HostController")
       
   690 
       
   691 	SetupFlowControlL(EFlowControlToHostControllerOnly);
       
   692 		
       
   693 #endif
       
   694 
       
   695 	User::LeaveIfError(SendInitialisationCommand(CWriteConnectionAcceptTimeoutCommand::NewL(KHCIDefaultAcceptTimeout)));
       
   696 	User::LeaveIfError(SendInitialisationCommand(CWriteVoiceSettingCommand::NewL(KBTVoiceSetting)));
       
   697 
       
   698 	if (iDeviceClass)
       
   699 		{
       
   700 		// Some phones never set their CoD in s/w, we don't want to
       
   701 		// overwrite their h/w settings
       
   702 		LOG1(_L("DoSendPostResetCommandsL - SetDeviceClassL (0x%x)"), iDeviceClass);
       
   703 		iLinkMgrProtocol.SetDeviceClassL(iDeviceClass);
       
   704 		}
       
   705 	else
       
   706 		{
       
   707 		// We want to update the P&S value with the h/w value
       
   708 		User::LeaveIfError(SendInitialisationCommand(CReadClassOfDeviceCommand::NewL()));
       
   709 		}
       
   710 
       
   711 	TRAPD(err, iLinkMgrProtocol.SetInquiryAndPageScanningL());
       
   712 	if(err != KErrNone && err != KErrNotSupported)
       
   713 		{
       
   714 		User::Leave(err);
       
   715 		}
       
   716 	}
       
   717 	
       
   718 void CHCIFacade::McioPostResetCommandComplete(TInt aError)
       
   719 	{
       
   720 	LOG_FUNC
       
   721 	TInt err;
       
   722 	
       
   723 	// check that we are in the correct state
       
   724 	__ASSERT_ALWAYS(iInitState == EReset, Panic(EIncorrectStateOnPostResetCallback));
       
   725 	iInitState = EPostReset;
       
   726 
       
   727 	if (aError == KErrNone)
       
   728 		{
       
   729 		// Send post reset commands required by stack
       
   730 		TRAP(err, DoSendPostResetCommandsL());
       
   731 		}
       
   732 	else
       
   733 		{
       
   734 		// The initialisor plugin has failed post reset initialisation
       
   735 		err = aError;
       
   736 		}
       
   737 		
       
   738 	if (err != KErrNone)
       
   739 		{
       
   740 		// Initialisation has failed. At this point all we can do is power down
       
   741 		// Bluetooth. This means that initialisation can be attempted again by
       
   742 		// turning on the power but this again could fail.
       
   743 		HandlePowerStatusChange(EBTOff);
       
   744 		}
       
   745 	}
       
   746 
       
   747 // MHCIDataObserver
       
   748 void CHCIFacade::MhdoProcessAclData(THCIConnHandle aConnH, TAclPacketBoundaryFlag aBoundaryFlag, TAclPacketBroadcastFlag aBroadcastFlag, const TDesC8& aData)
       
   749 	{
       
   750 	LOG_FUNC
       
   751 	// Stack currently works with the old flag passing mechanism.  So recombine into the old
       
   752 	// flag type before continuing.
       
   753 	TUint8 flag = (aBoundaryFlag | (aBroadcastFlag << KPacketPBtoBCFlagShift)) << KPacketPBBCFlagShift;
       
   754 
       
   755 	LOG3(_L("Link [HCIFacade_Events.cpp]: CHCIFacade data received on handle %d, flags %d, length %d"), aConnH, flag, aData.Length());
       
   756 
       
   757 	iLinksMgr->ACLDataReceived(aConnH, flag, aData);
       
   758 	}
       
   759 
       
   760 void CHCIFacade::MhdoProcessSynchronousData(THCIConnHandle aConnH, TUint8 /*aReserved*/, const TDesC8& aData)
       
   761 	{
       
   762 	LOG_FUNC
       
   763 	iLinksMgr->SCODataReceived(aConnH, aData);
       
   764 	}
       
   765 
       
   766 // MHCTLChannelObserver
       
   767 void CHCIFacade::MhcoChannelOpen(THCITransportChannel aChannels)
       
   768 /**
       
   769 	The HCI has notified us that transport channels have become free
       
   770 **/
       
   771 	{
       
   772 	LOG_FUNC
       
   773 	LOG1(_L("Transport channels 0x%04x now free"), aChannels);
       
   774 
       
   775 	// record the channel status
       
   776 	iHCTLState |= aChannels;
       
   777 	
       
   778 	if (iLinkMuxer)
       
   779 		{
       
   780 		iLinkMuxer->ChannelsFree(aChannels); //try to send on this channel
       
   781 		}
       
   782 	}
       
   783 	
       
   784 void CHCIFacade::MhcoChannelClosed(THCITransportChannel aChannels)
       
   785 	{
       
   786 	LOG_FUNC
       
   787 	// record the channel status
       
   788 	iHCTLState &= (~aChannels) & KHCITransportAllChannels;
       
   789 	
       
   790 	// Tell the Muxer these channels are closed, if Muxer is ready
       
   791 	if (iLinkMuxer)
       
   792 		{
       
   793 		iLinkMuxer->ChannelsClosed(aChannels);
       
   794 		}
       
   795 	}
       
   796 
       
   797 // MControllerStateObserver
       
   798 void CHCIFacade::McsoProcessPowerChange(TInt aError, TControllerChangeType aChangeType, TBTPowerState aState)
       
   799 	{
       
   800 	LOG_FUNC
       
   801 	if(aError!=KErrNone)
       
   802 		//Don't do anything - assume error implies no change took place
       
   803 		{
       
   804 		return;
       
   805 		}
       
   806 		
       
   807 	if(aChangeType==MControllerStateObserver::EBTNonFatalChange)
       
   808 		//Don't do anything - controller change will not affect us
       
   809 		{
       
   810 		return;
       
   811 		}
       
   812 		
       
   813 	// For now continue to use HandlePowerStatusChange as common code for power states and hard reset states
       
   814 	HandlePowerStatusChange(aState);
       
   815 	}
       
   816 
       
   817 void CHCIFacade::McsoProcessHardResetPhaseChange(TInt aError, TControllerChangeType aChangeType, TBTHardResetState aState)
       
   818 	{
       
   819 	LOG_FUNC
       
   820 	if(aError!=KErrNone)
       
   821 		{
       
   822 		//We may need to inform user somehow that reset has failed - depends on
       
   823 		//nature of error. What if error is KErrInUse? Should we set a timer
       
   824 		//and try again?
       
   825 		return;
       
   826 		}
       
   827 		
       
   828 	if(aChangeType==MControllerStateObserver::EBTNonFatalChange)
       
   829 		//Don't do anything - controller change will not affect us
       
   830 		{
       
   831 		return;
       
   832 		}
       
   833 		
       
   834 	switch(aState)
       
   835 		{
       
   836 		case EBTResetStarted:
       
   837 			HandlePowerStatusChange(EBTOff);
       
   838 			break;
       
   839 		case EBTResetComplete:
       
   840 			HandlePowerStatusChange(EBTOn);
       
   841 			break;
       
   842 		default:
       
   843 			Panic(EHCIUnknownHardResetState);
       
   844 			break;
       
   845 		}
       
   846 	}
       
   847 
       
   848 // MPhysicalLinksState - Simply forward the request to iLinksMgr
       
   849 TInt CHCIFacade::MplsGetConnectionHandles(RHCIConnHandleArray& aConnectionHandles, TLinkType aLinkType) const
       
   850 	{
       
   851 	LOG_FUNC
       
   852 	if (iLinksMgr)
       
   853 		{
       
   854 		return iLinksMgr->GetConnectionHandles(aConnectionHandles, aLinkType);
       
   855 		}
       
   856 	return KErrNotReady;
       
   857 	}
       
   858 
       
   859 TInt CHCIFacade::MplsGetNumPendingHandles(TInt& aConnectionHandles, TLinkType aLinkType) const
       
   860 	{
       
   861 	LOG_FUNC
       
   862 	if (iLinksMgr)
       
   863 		{
       
   864 		return iLinksMgr->GetNumPendingHandles(aConnectionHandles, aLinkType);
       
   865 		}
       
   866 	return KErrNotReady;
       
   867 	}
       
   868 
       
   869 TInt CHCIFacade::MplsGetConnectionHandles(RHCIConnHandleArray& aConnectionHandles, TLinkType aLinkType, const TBTDevAddr& aBDAddr) const
       
   870 	{
       
   871 	LOG_FUNC
       
   872 	if (iLinksMgr)
       
   873 		{
       
   874 		return iLinksMgr->GetConnectionHandles(aConnectionHandles, aLinkType, aBDAddr);
       
   875 		}
       
   876 	return KErrNotReady;
       
   877 	}
       
   878 
       
   879 TInt CHCIFacade::MplsGetNumPendingHandles(TInt& aConnectionHandles, TLinkType aLinkType, const TBTDevAddr& aBDAddr) const
       
   880 	{
       
   881 	LOG_FUNC
       
   882 	if (iLinksMgr)
       
   883 		{
       
   884 		return iLinksMgr->GetNumPendingHandles(aConnectionHandles, aLinkType, aBDAddr);
       
   885 		}
       
   886 	return KErrNotReady;
       
   887 	}
       
   888 
       
   889 TInt CHCIFacade::MplsGetRemoteAddress(TBTDevAddr& aBDAddr, THCIConnHandle aConnectionHandle) const
       
   890 	{
       
   891 	LOG_FUNC
       
   892 	if (iLinksMgr)
       
   893 		{
       
   894 		return iLinksMgr->GetRemoteAddress(aBDAddr, aConnectionHandle);
       
   895 		}
       
   896 	return KErrNotReady;
       
   897 	}
       
   898 
       
   899 TInt CHCIFacade::MplsGetRemoteDeviceClass(TBTDeviceClass& aDeviceClass, const TBTDevAddr& aBDAddr) const
       
   900 	{
       
   901 	LOG_FUNC
       
   902 	if (iLinksMgr)
       
   903 		{
       
   904 		return iLinksMgr->GetRemoteDeviceClass(aDeviceClass, aBDAddr);
       
   905 		}
       
   906 	return KErrNotReady;
       
   907 	}
       
   908 
       
   909 TInt CHCIFacade::MplsGetRemoteSupportedFeatures(TBTFeatures& aRemoteSupportedFeatures, const TBTDevAddr& aBDAddr) const
       
   910 	{
       
   911 	LOG_FUNC
       
   912 	if (iLinksMgr)
       
   913 		{
       
   914 		return iLinksMgr->GetRemoteSupportedFeatures(aRemoteSupportedFeatures, aBDAddr);
       
   915 		}
       
   916 	return KErrNotReady;
       
   917 	}
       
   918 
       
   919 TInt CHCIFacade::MplsGetLinkPolicySettings(TLinkPolicy& aLinkPolicySettings, const TBTDevAddr& aBDAddr) const
       
   920 	{
       
   921 	LOG_FUNC
       
   922 	if (iLinksMgr)
       
   923 		{
       
   924 		return iLinksMgr->GetLinkPolicySettings(aLinkPolicySettings, aBDAddr);
       
   925 		}
       
   926 	return KErrNotReady;
       
   927 	}
       
   928 
       
   929 TInt CHCIFacade::MplsGetBasebandLinkState(TBTBasebandLinkState& aBasebandLinkState, const TBTDevAddr& aBDAddr) const
       
   930 	{
       
   931 	LOG_FUNC
       
   932 	if (iLinksMgr)
       
   933 		{
       
   934 		return iLinksMgr->GetBasebandLinkState(aBasebandLinkState, aBDAddr);
       
   935 		}
       
   936 	return KErrNotReady;
       
   937 	}
       
   938 
       
   939 // MLinkMuxNotifier
       
   940 void CHCIFacade::TryToSend()
       
   941 	{
       
   942 	LOG_FUNC
       
   943 	if (iLinkMuxer)
       
   944 		{
       
   945 		iLinkMuxer->TryToSend();
       
   946 		}
       
   947 	}
       
   948 
       
   949 // from MHCIClientUsage
       
   950 void CHCIFacade::MhcuOpenClientReference()
       
   951 	{
       
   952 	iLinkMgrProtocol.LocalOpen();
       
   953 	}
       
   954 
       
   955 void CHCIFacade::MhcuCloseClientReference()
       
   956 	{
       
   957 	iLinkMgrProtocol.LocalClose();
       
   958 	}
       
   959 
       
   960 // Should only be tracking outstanding commands during cmdQ initialisation
       
   961 TInt CHCIFacade::AddOutstandingCommandOpCode(THCIOpcode aOpCode)
       
   962 	{
       
   963 	LOG_FUNC
       
   964 	__ASSERT_ALWAYS(iInitState != EInitialised, Panic(EHCICmdQNotInitialising));
       
   965 	TUint32 opcode = static_cast<TUint32>(aOpCode);
       
   966 	return iOutstandingCommands.Append(opcode);	
       
   967 	}
       
   968 
       
   969 // Should only be tracking outstanding commands during cmdQ initialisation	
       
   970 TInt CHCIFacade::FindOutstandingCommandOpCode(THCIOpcode aOpCode) const
       
   971 	{
       
   972 	LOG_FUNC
       
   973 	__ASSERT_ALWAYS(iInitState != EInitialised, Panic(EHCICmdQNotInitialising));
       
   974 	TUint32 opcode = static_cast<TUint32>(aOpCode);
       
   975 	return iOutstandingCommands.Find(opcode);	
       
   976 	}
       
   977 	
       
   978 // TBasebandPolicy
       
   979 
       
   980 void TBasebandPolicy::InitialPolicy(const TBasebandPolicyParams& aParams)
       
   981 	{
       
   982 	LOG_FUNC
       
   983 	iPageTimePolicy = aParams.iPageTimePolicy;
       
   984 	}
       
   985 
       
   986 TInt TBasebandPolicy::TryToChangePolicy(const TBasebandPolicyParams& aNewParams)
       
   987 	{
       
   988 	LOG_FUNC
       
   989 	// just deal with pagetime for now
       
   990 	TBasebandPageTimePolicy& current = iPageTimePolicy;
       
   991 
       
   992 	switch (current)
       
   993 		{
       
   994 		case EPagingDontCare:
       
   995 			break;
       
   996 
       
   997 		case EPagingNormal:
       
   998 			current = aNewParams.iPageTimePolicy;
       
   999 			break;
       
  1000 
       
  1001 		case EPagingBestEffort:
       
  1002 			//only change if user wants Quick paging
       
  1003 			current = (aNewParams.iPageTimePolicy == EPagingQuick) ? aNewParams.iPageTimePolicy : current;
       
  1004 			break;
       
  1005 
       
  1006 		case EPagingQuick:
       
  1007 			//only change if user wants Best effort paging
       
  1008 			current = (aNewParams.iPageTimePolicy == EPagingBestEffort) ? aNewParams.iPageTimePolicy : current;
       
  1009 			break;
       
  1010 
       
  1011 		default:
       
  1012 			LOG(_L("TBasebandPolicy: bogus policy requested for pagetimeout"));
       
  1013 			return KErrArgument;
       
  1014 		}
       
  1015 
       
  1016 	LOG1(_L("TBasebandPolicy: now using page time policy %d"), aNewParams.iPageTimePolicy);
       
  1017 	return (current == aNewParams.iPageTimePolicy) ? KErrNone : KErrInUse;
       
  1018 	}
       
  1019 
       
  1020 
       
  1021 TBasebandPageTimePolicy TBasebandPolicy::PageTimePolicy() const
       
  1022 	{
       
  1023 	LOG_FUNC
       
  1024 	return iPageTimePolicy;
       
  1025 	}
       
  1026 
       
  1027 //class CAFHTimer
       
  1028 CAFHTimer* CAFHTimer::NewL(CHCIFacade& aParent)
       
  1029 	{
       
  1030 	LOG_STATIC_FUNC
       
  1031 	CAFHTimer* self = new (ELeave) CAFHTimer(aParent);
       
  1032 	CleanupStack::PushL(self);
       
  1033 	self->ConstructL();
       
  1034 	CleanupStack::Pop();
       
  1035 	return self;
       
  1036 	}
       
  1037 
       
  1038 void CAFHTimer::ConstructL()
       
  1039 	{
       
  1040 	LOG_FUNC
       
  1041 	CTimer::ConstructL();
       
  1042 	CActiveScheduler::Add(this);
       
  1043 	}
       
  1044 
       
  1045 CAFHTimer::CAFHTimer(CHCIFacade& aParent)
       
  1046 : CTimer(CActive::EPriorityStandard), iParent(aParent), iPending(EFalse)
       
  1047 	{
       
  1048 	LOG_FUNC
       
  1049 	}
       
  1050 		
       
  1051 void CAFHTimer::SetPending(const TBTAFHHostChannelClassification& aHCC)
       
  1052 	{
       
  1053 	LOG_FUNC
       
  1054 	iHCC.Copy(aHCC);
       
  1055 	iPending=ETrue;
       
  1056 	}
       
  1057 	
       
  1058 void CAFHTimer::RemovePendingHostChannelClassifications()
       
  1059 	{
       
  1060 	LOG_FUNC
       
  1061 	iHCC.Reset();
       
  1062 	iPending=EFalse;
       
  1063 	}
       
  1064 	
       
  1065 void CAFHTimer::Reset()
       
  1066 	{
       
  1067 	LOG_FUNC
       
  1068 	RemovePendingHostChannelClassifications();
       
  1069 	Cancel();
       
  1070 	}
       
  1071 	
       
  1072 void CAFHTimer::RunL()
       
  1073 	{
       
  1074 	LOG_FUNC
       
  1075 	if(iPending)
       
  1076 		{
       
  1077 		if(iStatus==KErrNone)
       
  1078 			{
       
  1079 			iParent.SetAFHHostChannelClassificationL(iHCC);
       
  1080 			}
       
  1081 		RemovePendingHostChannelClassifications();
       
  1082 		}
       
  1083 	}
       
  1084 
       
  1085 TInt CAFHTimer::RunError(TInt /*aError*/)
       
  1086 	{
       
  1087 	LOG_FUNC
       
  1088 	return KErrNone;
       
  1089 	}
       
  1090 
       
  1091 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
  1092 
       
  1093 CHostMBufPool* CHostMBufPool::NewL(CHCIFacade& aHCIFacade)
       
  1094 	{
       
  1095 	LOG_FUNC
       
  1096 	CHostMBufPool* self = new (ELeave) CHostMBufPool(aHCIFacade);
       
  1097 	CleanupStack::PushL(self);
       
  1098 	self->ConstructL();
       
  1099 	CleanupStack::Pop(self);
       
  1100 	return self;
       
  1101 	}
       
  1102 	
       
  1103 void CHostMBufPool::DeletePool(TSglQue<TPoolBuffer>& aQueue)
       
  1104 	{
       
  1105 	LOG_FUNC
       
  1106 	TPoolBuffer* tmpItem = NULL;
       
  1107 	TSglQueIter<TPoolBuffer> iter(aQueue);
       
  1108 	while(iter)
       
  1109 		{
       
  1110 		tmpItem=iter++;
       
  1111 		aQueue.Remove(*tmpItem);
       
  1112 		delete tmpItem;
       
  1113 		}
       
  1114 	}
       
  1115 	
       
  1116 CHostMBufPool::~CHostMBufPool()
       
  1117 	{
       
  1118 	LOG_FUNC
       
  1119 	Cancel();
       
  1120 	DeletePool(iBufferPool);
       
  1121 	DeletePool(iWaitingAllocPool);
       
  1122 	}
       
  1123 	
       
  1124 CHostMBufPool::CHostMBufPool(CHCIFacade& aHCIFacade) :
       
  1125 	CActive(0),iHCIFacade(aHCIFacade),iBufferPool(_FOFF(TPoolBuffer,iLink)),
       
  1126 	iWaitingAllocPool(_FOFF(TPoolBuffer,iLink)),iCurrAckHandle(KErrNotFound),iCurrCompletedPackets(0)
       
  1127 	{
       
  1128 	LOG_FUNC
       
  1129 	}
       
  1130 	
       
  1131 void CHostMBufPool::ConstructL()
       
  1132 /**
       
  1133 2nd phase constructor for the Host MBuf Pool.
       
  1134 
       
  1135 This method will attempt to reserve enough MBufs from the global pool
       
  1136 for bluetooth use.
       
  1137 @leave KErrNoMemory If the required number of MBufs couldn't be reserved
       
  1138 */
       
  1139 	{
       
  1140 	LOG_FUNC
       
  1141 	LOG2(_L("CHostMBufPool: now reserving %d size %d MBufChains"),KStackACLBuffersNum,KLinkMgrIncomingBufferSize);
       
  1142 			
       
  1143 	for (TInt i=0;i<=KStackACLBuffersNum-1;i++)
       
  1144 		{
       
  1145 		TPoolBuffer* thisBuffer = new (ELeave) TPoolBuffer();
       
  1146 		CleanupStack::PushL(thisBuffer);
       
  1147 		thisBuffer->iCurrentHandle=KErrNotFound; //we assert on this later
       
  1148 		thisBuffer->iMBufChain.AllocL(KLinkMgrIncomingBufferSize);
       
  1149 		iBufferPool.AddFirst(*thisBuffer);
       
  1150 		CleanupStack::Pop(thisBuffer);
       
  1151 		}
       
  1152 		
       
  1153 	CActiveScheduler::Add(this);
       
  1154 	}
       
  1155 	
       
  1156 void CHostMBufPool::DoCancel()
       
  1157 	{
       
  1158 	LOG_FUNC
       
  1159 	iMBufRequester.Cancel();
       
  1160 	}
       
  1161 	
       
  1162 RMBufChain CHostMBufPool::TakeBuffer(const THCIConnHandle& aConnHandle)
       
  1163 /**
       
  1164 Takes a buffer from the pool and schedules an asynchronous allocation
       
  1165 of the next buffer.	 Only when that allocation has succeeded will the host
       
  1166 controller be signalled with a host_number_of_completed_packets.  Hence,
       
  1167 if we cannot allocate a buffer from the global MBuf pool, the host controller
       
  1168 will be flowed off and no data will be lost.
       
  1169 */
       
  1170 	{
       
  1171 	LOG_FUNC
       
  1172 	TPoolBuffer* ready = iBufferPool.First();
       
  1173 	iBufferPool.Remove(*ready);
       
  1174 	__ASSERT_DEBUG(!ready->iMBufChain.IsEmpty(),Panic(ELinkMgrHostControllerHasOverflowedHost));
       
  1175 	__ASSERT_DEBUG(ready->iCurrentHandle==KErrNotFound,Panic(ELinkMgrHostControllerHasOverflowedHost));
       
  1176 	ready->iCurrentHandle = aConnHandle;
       
  1177 	
       
  1178 	RMBufChain retChain;
       
  1179 	retChain.Assign(ready->iMBufChain);
       
  1180 	
       
  1181 	if (IsActive())
       
  1182 		{
       
  1183 		//This buffer will be reclaimed from the global pool
       
  1184 		//after the one(s) we're currently trying to reclaim
       
  1185 		LOG(_L("CHostMBufPool: TakeBuffer, buffer taken while alloc outstanding: queued alloc"));
       
  1186 		iWaitingAllocPool.AddLast(*ready);
       
  1187 		}
       
  1188 	else
       
  1189 		{
       
  1190 		LOG(_L("CHostMBufPool: TakeBuffer, buffer taken"));
       
  1191 		iBufferPool.AddLast(*ready); //NB the Controller cannot use this
       
  1192 									//buffer until it is alloced as it will
       
  1193 									//be flowed off.
       
  1194 		iMBufRequester.Alloc(ready->iMBufChain,KLinkMgrIncomingBufferSize,iStatus);
       
  1195 		SetActive();
       
  1196 		}
       
  1197 		
       
  1198 	return retChain;
       
  1199 	}
       
  1200 	
       
  1201 void CHostMBufPool::RunL()
       
  1202 	{
       
  1203 	LOG_FUNC
       
  1204 	if (iStatus.Int()!=KErrNone)
       
  1205 		{
       
  1206 		LOG1(_L("Error! CHostMBufPool:: RunL %d"),iStatus.Int());
       
  1207 		__DEBUGGER();
       
  1208 		}
       
  1209 	else
       
  1210 		{
       
  1211 		TPoolBuffer* justAllocd = iBufferPool.Last();
       
  1212 		
       
  1213 		
       
  1214 		if (iCurrAckHandle==KErrNotFound)
       
  1215 			{
       
  1216 			//This is the first completion we have ever seen
       
  1217 			iCurrAckHandle=justAllocd->iCurrentHandle;
       
  1218 			}
       
  1219 		
       
  1220 		TBool ackNow=((justAllocd->iCurrentHandle!=iCurrAckHandle));
       
  1221 		
       
  1222 		if (!ackNow)
       
  1223 			{
       
  1224 			iCurrCompletedPackets++;
       
  1225 			LOG2(_L("CHostMBufPool: CompletedPackets++ for conn: %d [->%d]"),justAllocd->iCurrentHandle,iCurrCompletedPackets);
       
  1226 			
       
  1227 			if (iCurrCompletedPackets>=KStackACLBuffersTideMarkNum)
       
  1228 				{
       
  1229 				ackNow=ETrue;
       
  1230 				}
       
  1231 			}
       
  1232 			
       
  1233 		if (ackNow)
       
  1234 			{
       
  1235 			TInt err=KErrNone;
       
  1236 			
       
  1237 			if (iCurrCompletedPackets>0)
       
  1238 				{
       
  1239 				LOG2(_L("CHostMBufPool: Sending HostNumberOfCompletedPackets for conn: %d [%d completed]"),iCurrAckHandle,iCurrCompletedPackets);
       
  1240 				//Acknowledge the completed packets
       
  1241 				TRAP(err, iHCIFacade.HostNumberOfCompletedPacketsL(iCurrAckHandle,iCurrCompletedPackets));
       
  1242 				//if this failed we probably couldn't alloc the memory for the command frame,
       
  1243 				//the HC is still flowed off.
       
  1244 				__ASSERT_DEBUG(err==KErrNone,Panic(ELinkMgrCouldNotSendHostNumberOfCompletedPackets));
       
  1245 				}
       
  1246 			
       
  1247 			iCurrCompletedPackets= (justAllocd->iCurrentHandle!=iCurrAckHandle) ? 1:0;
       
  1248 			iCurrAckHandle=justAllocd->iCurrentHandle;
       
  1249 			}
       
  1250 		
       
  1251 		justAllocd->iCurrentHandle=KErrNotFound;
       
  1252 		
       
  1253 		if (!iWaitingAllocPool.IsEmpty())
       
  1254 			{
       
  1255 			TPoolBuffer* needsAlloc = iWaitingAllocPool.First();
       
  1256 			iBufferPool.AddLast(*needsAlloc);
       
  1257 			iWaitingAllocPool.Remove(*needsAlloc);
       
  1258 			iMBufRequester.Alloc(needsAlloc->iMBufChain,KLinkMgrIncomingBufferSize,iStatus);
       
  1259 			SetActive();
       
  1260 			}
       
  1261 		}
       
  1262 	}
       
  1263 	
       
  1264 #endif