bluetooth/btstack/linkmgr/physicallinks.cpp
branchRCL_3
changeset 56 015fa7494bd2
parent 45 99439b07e980
equal deleted inserted replaced
49:10183c6d2913 56:015fa7494bd2
    23 #include "SCOSAP.h"
    23 #include "SCOSAP.h"
    24 #include "ProxySAP.h"
    24 #include "ProxySAP.h"
    25 #include "linkconsts.h"
    25 #include "linkconsts.h"
    26 #include "hcifacade.h"
    26 #include "hcifacade.h"
    27 #include "hostresolver.h"
    27 #include "hostresolver.h"
    28 #include "roleswitchhelper.h"
    28 #include "PhysicalLinkHelper.h"
    29 #include "pairingscache.h"
    29 #include "pairingscache.h"
    30 #include "oobdata.h"
    30 #include "oobdata.h"
    31 #include "pairingserver.h"
    31 #include "pairingserver.h"
    32 #include "encryptionkeyrefreshhelper.h"
       
    33 
    32 
    34 #include <bt_sock.h>
    33 #include <bt_sock.h>
    35 
    34 
    36 #include <bluetooth/hci/commandstatusevent.h>
    35 #include <bluetooth/hci/commandstatusevent.h>
    37 #include <bluetooth/hci/sniffmodecommand.h>
    36 #include <bluetooth/hci/sniffmodecommand.h>
    57 #endif
    56 #endif
    58 
    57 
    59 static const THCIErrorCode KDefaultRejectReason = EHostSecurityRejection; // see spec Error Codes
    58 static const THCIErrorCode KDefaultRejectReason = EHostSecurityRejection; // see spec Error Codes
    60 
    59 
    61 #ifdef _DEBUG
    60 #ifdef _DEBUG
    62 #define __CHECK_CONNECTION_HANDLE(aHandle) __ASSERT_DEBUG(HasHandle(aHandle), Panic(EBTLinkMgrConnectionEventInWrongSAP));
    61 #define __CHECK_CONNECTION_HANDLE(aHandle) __ASSERT_DEBUG(aHandle==iHandle, Panic(EBTLinkMgrConnectionEventInWrongSAP));
    63 #else
    62 #else
    64 #define __CHECK_CONNECTION_HANDLE(aHandle) aHandle=aHandle; // to suppress warnings
    63 #define __CHECK_CONNECTION_HANDLE(aHandle) aHandle=aHandle; // to suppress warnings
    65 #endif
    64 #endif
    66 
    65 
    67 CPhysicalLink* CPhysicalLink::NewLC(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice)
    66 CPhysicalLink* CPhysicalLink::NewLC(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice)
    90 	, iDeviceResult(KDeviceNotObtained)
    89 	, iDeviceResult(KDeviceNotObtained)
    91 	, iRegistryHelpers(_FOFF(CBTRegistryHelperBase,iLink))
    90 	, iRegistryHelpers(_FOFF(CBTRegistryHelperBase,iLink))
    92 	, iProxySAPs(_FOFF(CBTProxySAP, iQueueLink))
    91 	, iProxySAPs(_FOFF(CBTProxySAP, iQueueLink))
    93 	, iOverrideParkRequests(EFalse)
    92 	, iOverrideParkRequests(EFalse)
    94 	, iOverrideLPMRequests(EFalse)
    93 	, iOverrideLPMRequests(EFalse)
       
    94 	, iLPMOverrideTimerQueued(EFalse)
    95 	, iConnectionPacketTypeChanged(EFalse)
    95 	, iConnectionPacketTypeChanged(EFalse)
    96 	, iLowPowModeCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    96 	, iLowPowModeCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    97 	, iDisconnectCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    97 	, iDisconnectCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    98 	, iAuthenticationCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    98 	, iAuthenticationCtrl(*this, iLinksMan.HCIFacade().CommandQController())
    99 	, iLSTO(0)
    99 	, iLSTO(0)
   117 	// tell ConnectionsManager...
   117 	// tell ConnectionsManager...
   118 	iLinksMan.RemovePhysicalLink(*this);
   118 	iLinksMan.RemovePhysicalLink(*this);
   119 	iACLLogicalLinks.Close();
   119 	iACLLogicalLinks.Close();
   120 
   120 
   121 	RemoveIdleTimer();
   121 	RemoveIdleTimer();
       
   122 	if (iLPMOverrideTimerQueued)
       
   123 		{
       
   124 		BTSocketTimer::Remove(iOverrideLPMTimerEntry);
       
   125 		iLPMOverrideTimerQueued = EFalse;
       
   126 		}
   122 
   127 
   123 	LOG(_L("sec\tClosing subscribers..."))
   128 	LOG(_L("sec\tClosing subscribers..."))
   124 
   129 
   125 	LOG(_L("sec\tClosing helpers..."))
   130 	LOG(_L("sec\tClosing helpers..."))
   126 	TSglQueIter<CBTRegistryHelperBase> iter(iRegistryHelpers);
   131 	TSglQueIter<CBTRegistryHelperBase> iter(iRegistryHelpers);
   142 	delete iNumericComparator;
   147 	delete iNumericComparator;
   143 	delete iUserConfirmer;
   148 	delete iUserConfirmer;
   144 	delete iPasskeyEntry;
   149 	delete iPasskeyEntry;
   145 	delete iArbitrationDelay;
   150 	delete iArbitrationDelay;
   146 	delete iRoleSwitchCompleteCallBack;
   151 	delete iRoleSwitchCompleteCallBack;
   147 	delete iKeyRefreshCompleteCallBack;
       
   148 	delete iEncryptionEnforcer;
   152 	delete iEncryptionEnforcer;
   149 
   153 
   150 	DeleteRoleSwitcher();
   154 	DeleteRoleSwitcher();
   151 	DeleteKeyRefresher();
       
   152 	}
   155 	}
   153 
   156 
   154 void CPhysicalLink::ConstructL()
   157 void CPhysicalLink::ConstructL()
   155 	{
   158 	{
   156 	LOG_FUNC
   159 	LOG_FUNC
   159 	iArbitrationDelay = CArbitrationDelayTimer::NewL(this);
   162 	iArbitrationDelay = CArbitrationDelayTimer::NewL(this);
   160 
   163 
   161 	TCallBack cb1(RoleSwitchCompleteCallBack, this);
   164 	TCallBack cb1(RoleSwitchCompleteCallBack, this);
   162 	iRoleSwitchCompleteCallBack = new (ELeave)CAsyncCallBack(cb1, EActiveHighPriority);
   165 	iRoleSwitchCompleteCallBack = new (ELeave)CAsyncCallBack(cb1, EActiveHighPriority);
   163 
   166 
   164 	TCallBack cb2(KeyRefreshCompleteCallBack, this);
   167 	TCallBack cb2(OverrideLPMTimeoutCallback, this);
   165 	iKeyRefreshCompleteCallBack = new (ELeave)CAsyncCallBack(cb2, EActiveHighPriority);
   168 	iOverrideLPMTimerEntry.Set(cb2);
   166 	
   169 
   167 	iPhysicalLinkMetrics = CPhysicalLinkMetrics::NewL(*this, iLinksMan.HCIFacade().CommandQController());
   170 	iPhysicalLinkMetrics = CPhysicalLinkMetrics::NewL(*this, iLinksMan.HCIFacade().CommandQController());
   168 	}
   171 	}
   169 
   172 
   170 TBool CPhysicalLink::HasHandle(THCIConnHandle aHandle) const
   173 TBool CPhysicalLink::HasHandle(THCIConnHandle aHandle) const
   171 	{
   174 	{
   217 	}
   220 	}
   218 
   221 
   219 TInt CPhysicalLink::TryToAndThenPreventHostEncryptionKeyRefresh(TAny* aOutToken)
   222 TInt CPhysicalLink::TryToAndThenPreventHostEncryptionKeyRefresh(TAny* aOutToken)
   220 	{
   223 	{
   221 	LOG_FUNC
   224 	LOG_FUNC
   222 	TInt err = KErrNone;
   225 	// Currently the host encryption key refresh functionality is not supported
   223 	// The handling of the TAny* parameter seems a bit wacky - but it makes sense as follows
   226 	// as to work smoothly it relies on changes to disable low power modes that
   224 	// this call handles a call from the bluetooth control plane (which passes
   227 	// are not present in this codeline.
   225 	// only a TAny* as a parameter).  We need to return a value back through as well, so we need
   228 	*reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = NULL;
   226 	// a pointer to a pointer (so after using the input it can be modified to point to the
   229 	return KErrNotSupported;
   227 	// output).  We need a Bluetooth device address so a pointer to a pointer to a TBTDevAddr 
       
   228 	// is passed down. Then the pointer to a pointer is used to update the pointer to a control
       
   229 	// plane token (which represents a handle preventing host encryption key refreshes).
       
   230 	if (!IsEncryptionPauseResumeSupported())
       
   231 		{
       
   232 		err = KErrNotSupported;
       
   233 		*reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = NULL;
       
   234 		}
       
   235 	else
       
   236 		{
       
   237 		// Only refresh the key if no-one is preventing it and we aren't still 
       
   238 		// refreshing the key from a previous request.  Note that although
       
   239 		// the previous key refresh may actually have finished if the key
       
   240 		// refresher is waiting for async delete we have only just refreshed 
       
   241 		// the key and there's no point doing it again.
       
   242 		if (iAutoKeyRefreshQue.IsEmpty() && !iKeyRefresher)
       
   243 			{
       
   244 			TRAPD(err, iKeyRefresher = CEncryptionKeyRefresher::NewL(iLinksMan, *this));
       
   245 			if(!err)
       
   246 				{
       
   247 				// Kick off the helper state machine
       
   248 				iKeyRefresher->StartHelper();
       
   249 				}
       
   250 			// If we can't refresh the encryption key, there's not much we can do
       
   251 			}
       
   252 		XAutoKeyRefreshToken* token = new XAutoKeyRefreshToken();
       
   253 		if (token)
       
   254 			{
       
   255 			iAutoKeyRefreshQue.AddLast(*token);
       
   256 			}
       
   257 		else
       
   258 			{
       
   259 			err = KErrNoMemory;
       
   260 			}
       
   261 		*reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = token;
       
   262 		}
       
   263 	return err;
       
   264 	}
   230 	}
   265 
   231 
   266 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TInt /*aResult*/)
   232 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TInt /*aResult*/)
   267 /**
   233 /**
   268 	A task has completed where we don't expect a response - just cleanup helper
   234 	A task has completed where we don't expect a response - just cleanup helper
  1367 	{
  1333 	{
  1368 	LOG_FUNC
  1334 	LOG_FUNC
  1369 	CBTDeviceNameChanger* nameChanger = CBTDeviceNameChanger::NewL(iRegSess, *this);
  1335 	CBTDeviceNameChanger* nameChanger = CBTDeviceNameChanger::NewL(iRegSess, *this);
  1370 	iRegistryHelpers.AddLast(*nameChanger);
  1336 	iRegistryHelpers.AddLast(*nameChanger);
  1371 	nameChanger->Start(BDAddr(), aName);
  1337 	nameChanger->Start(BDAddr(), aName);
  1372 	}
       
  1373 
       
  1374 void CPhysicalLink::EncryptionKeyRefreshComplete(THCIErrorCode aErr, THCIConnHandle aConnH)
       
  1375 	{
       
  1376 	LOG_FUNC
       
  1377 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1378 
       
  1379 	if(iKeyRefresher)
       
  1380 		{
       
  1381 		iKeyRefresher->EncryptionKeyRefreshComplete(aErr);
       
  1382 		}
       
  1383 	}
  1338 	}
  1384 
  1339 
  1385 void CPhysicalLink::Disconnection(THCIErrorCode aErr, THCIConnHandle aConnH, THCIErrorCode aResult)
  1340 void CPhysicalLink::Disconnection(THCIErrorCode aErr, THCIConnHandle aConnH, THCIErrorCode aResult)
  1386 	{
  1341 	{
  1387 	LOG_FUNC
  1342 	LOG_FUNC
  1842 		LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask);
  1797 		LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask);
  1843 		// The current state is the same as the permitted required role(s).
  1798 		// The current state is the same as the permitted required role(s).
  1844 		return KErrNone;
  1799 		return KErrNone;
  1845 		}
  1800 		}
  1846 	
  1801 	
  1847 	TBTLinkMode targetMode = EActiveMode;
  1802 	TBTLinkMode nextMode = EActiveMode;
  1848 	// Determine which LPM we should be in (if any)
  1803 	// Determine which LPM we should be in (if any)
  1849 	if(modeChangeMask & KExplicitActiveMode)
  1804 	if(modeChangeMask & KExplicitActiveMode)
  1850 		{
  1805 		{
  1851 		targetMode = EActiveMode;
  1806 		nextMode = EActiveMode;
  1852 		}
  1807 		}
  1853 	else if(modeChangeMask & EHoldMode)
  1808 	else if(modeChangeMask & EHoldMode)
  1854 		{
  1809 		{
  1855 		targetMode = EHoldMode;
  1810 		nextMode = EHoldMode;
  1856 		}
  1811 		}
  1857 	else if(modeChangeMask & ESniffMode)
  1812 	else if(modeChangeMask & ESniffMode)
  1858 		{
  1813 		{
  1859 		targetMode = ESniffMode;
  1814 		nextMode = ESniffMode;
  1860 		}
  1815 		}
  1861 	else if(modeChangeMask & EParkMode)
  1816 	else if(modeChangeMask & EParkMode)
  1862 		{
  1817 		{
  1863 		targetMode = EParkMode;
  1818 		nextMode = EParkMode;
  1864 		}
  1819 		}
  1865 	LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, targetMode);
  1820 	LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, nextMode);
  1866 	
  1821 	
  1867 	if(IsConnected())
  1822 	if(nextMode != currentMode)
  1868 	    {
  1823 		{
  1869         TInt err = iLowPowModeCtrl.ExecuteModeChange(targetMode);
  1824 		if(currentMode != EActiveMode)
  1870         LOG1(_L8("Arbitration: iLowPowModeCtrl.ExecuteModeChange: err:%d"), err);
  1825 			{
  1871         return err;
  1826 			LOG(_L8("Arbitration: Exiting existing LPM mode..."));
  1872 	    }
  1827 			TInt err = RequestActive();
  1873 	else
  1828 			if(err != KErrNone)
  1874 	    {
  1829 				{
  1875         return KErrDisconnected;
  1830 				return err;
  1876 	    }
  1831 				}
       
  1832 			}
       
  1833 		if(nextMode == EHoldMode)
       
  1834 			{
       
  1835 			LOG(_L8("Arbitration: Entering Hold mode..."));
       
  1836 			return RequestHold();
       
  1837 			}
       
  1838 		else if(nextMode == ESniffMode)
       
  1839 			{
       
  1840 			LOG(_L8("Arbitration: Entering Sniff mode..."));
       
  1841 			return RequestSniff();
       
  1842 			}
       
  1843 		else if(nextMode == EParkMode)
       
  1844 			{
       
  1845 			LOG(_L8("Arbitration: Entering Park mode..."));
       
  1846 			return RequestPark();
       
  1847 			}
       
  1848 		else if(nextMode == EActiveMode)
       
  1849 			{
       
  1850 			LOG(_L8("Arbitration: Staying in Active mode..."));
       
  1851 			return KErrNone;
       
  1852 			}
       
  1853 		// Shouldn't reach here, we have a strange mode
       
  1854 		DEBUG_PANIC_LINENUM;
       
  1855 		}
       
  1856 
       
  1857 	LOG(_L8("Arbitration: Already in correct LPM, not doing anything"));
       
  1858 	return KErrNone;
  1877 	}
  1859 	}
  1878 
  1860 
  1879 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey)
  1861 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey)
  1880 	{
  1862 	{
  1881 	LOG_FUNC
  1863 	LOG_FUNC
  2243 		}
  2225 		}
  2244 	BTSocketTimer::Remove(iIdleTimerEntry);
  2226 	BTSocketTimer::Remove(iIdleTimerEntry);
  2245 	iIdleTimerQueued = EFalse;
  2227 	iIdleTimerQueued = EFalse;
  2246 	}
  2228 	}
  2247 
  2229 
       
  2230 void CPhysicalLink::QueueLPMOverrideTimer(TInt aTimeout)
       
  2231 /**
       
  2232 	Queue LPM Override timer entry.
       
  2233 	When this timer expires, it'll call UndoLPMOverride.
       
  2234 **/
       
  2235 	{
       
  2236 	LOG_FUNC
       
  2237 	__ASSERT_DEBUG(aTimeout!=0, Panic(EBTPhysicalLinksInvalidArgument));
       
  2238 	if (iLPMOverrideTimerQueued)
       
  2239 		{
       
  2240 		BTSocketTimer::Remove(iOverrideLPMTimerEntry);
       
  2241 		}
       
  2242 	BTSocketTimer::Queue(aTimeout, iOverrideLPMTimerEntry);
       
  2243 	iLPMOverrideTimerQueued = ETrue;
       
  2244 	}
       
  2245 
  2248 void CPhysicalLink::NotifyStateChange(TBTBasebandEventNotification& aEvent)
  2246 void CPhysicalLink::NotifyStateChange(TBTBasebandEventNotification& aEvent)
  2249 	{
  2247 	{
  2250 	LOG_FUNC
  2248 	LOG_FUNC
  2251 	// If this event is 'physical link down' / 'physical link error' then any ProxySAP
  2249 	// If this event is 'physical link down' / 'physical link error' then any ProxySAP
  2252 	// subscribers will unsubscribe as a result of PhysicalLinkChange being called.
  2250 	// subscribers will unsubscribe as a result of PhysicalLinkChange being called.
  2586 		}
  2584 		}
  2587 
  2585 
  2588 	return rerr;
  2586 	return rerr;
  2589 	}
  2587 	}
  2590 
  2588 
       
  2589 TInt CPhysicalLink::ExitMode(TBTLinkMode aMode)
       
  2590 	{
       
  2591 	LOG_FUNC
       
  2592 	return iLowPowModeCtrl.ExitMode(aMode, iHandle);
       
  2593 	}
       
  2594 
       
  2595 TInt CPhysicalLink::RequestMode(TBTLinkMode aMode)
       
  2596 	{
       
  2597 	LOG_FUNC
       
  2598 	if (!IsConnected())
       
  2599 		return KErrDisconnected;
       
  2600 
       
  2601 	// if active mode is required, try to exit whatever Low Power mode we are in -
       
  2602 	// if neither sniff nor park nothing will happen.
       
  2603 	if(aMode == EActiveMode)
       
  2604 		{
       
  2605 		return ExitMode(iLinkState.LinkMode());
       
  2606 		}
       
  2607 
       
  2608 	// now request this connection goes to requested mode
       
  2609 	return iLowPowModeCtrl.ChangeMode(aMode, iHandle);
       
  2610 	}
       
  2611 
  2591 TInt CPhysicalLink::RequestChangeRole(TBTBasebandRole aRole)
  2612 TInt CPhysicalLink::RequestChangeRole(TBTBasebandRole aRole)
  2592 	{
  2613 	{
  2593 	LOG_FUNC
  2614 	LOG_FUNC
  2594 	TInt err = KErrNone;
  2615 	TInt err = KErrNone;
  2595 
  2616 
  2664 	LOG_FUNC
  2685 	LOG_FUNC
  2665 	delete iRoleSwitcher;
  2686 	delete iRoleSwitcher;
  2666 	iRoleSwitcher = NULL;
  2687 	iRoleSwitcher = NULL;
  2667 	}
  2688 	}
  2668 
  2689 
  2669 void CPhysicalLink::AsyncDeleteKeyRefresher()
       
  2670 	{
       
  2671 	LOG_FUNC
       
  2672 	iKeyRefreshCompleteCallBack->CallBack();
       
  2673 	}
       
  2674 
       
  2675 /*static*/ TInt CPhysicalLink::KeyRefreshCompleteCallBack(TAny* aPhysicalLink)
       
  2676 	{
       
  2677 	LOG_STATIC_FUNC
       
  2678 	CPhysicalLink* physicalLink = static_cast<CPhysicalLink*>(aPhysicalLink);
       
  2679 	physicalLink->DeleteKeyRefresher();
       
  2680 	return EFalse;
       
  2681 	}
       
  2682 
       
  2683 void CPhysicalLink::DeleteKeyRefresher()
       
  2684 	{
       
  2685 	LOG_FUNC
       
  2686 	delete iKeyRefresher;
       
  2687 	iKeyRefresher = NULL;
       
  2688 	}
       
  2689 
       
  2690 TBool CPhysicalLink::IsEncryptionDisabledForRoleSwitch() const
  2690 TBool CPhysicalLink::IsEncryptionDisabledForRoleSwitch() const
  2691 /**
  2691 /**
  2692 	If link is encrypted, but role switcher temporarily disabled encryption, returns true.
  2692 	If link is encrypted, but role switcher temporarily disabled encryption, returns true.
  2693 **/
  2693 **/
  2694 	{
  2694 	{
  2732 	//Arbitrate even if there isn't an outstanding local park mode request beacuse
  2732 	//Arbitrate even if there isn't an outstanding local park mode request beacuse
  2733 	//the remote device may be requesting park mode.
  2733 	//the remote device may be requesting park mode.
  2734 	return Arbitrate();
  2734 	return Arbitrate();
  2735 	}
  2735 	}
  2736 
  2736 
       
  2737 TInt CPhysicalLink::OverrideLPMWithTimeout(TUint aTimeout)
       
  2738 	{
       
  2739 	LOG_FUNC
       
  2740 	if(aTimeout == 0)
       
  2741 		{
       
  2742 		return KErrNone; //facility not wanted
       
  2743 		}
       
  2744 
       
  2745 	TInt rerr = OverrideLPM();
       
  2746 	QueueLPMOverrideTimer(aTimeout);
       
  2747 
       
  2748 	return rerr;
       
  2749 	}
       
  2750 
  2737 TInt CPhysicalLink::OverrideLPM()
  2751 TInt CPhysicalLink::OverrideLPM()
  2738 /**
  2752 /**
  2739 	A request has come in that requires us to ensure we are not using
  2753 	A request has come in that requires us to ensure we are not using
  2740 	an LPM (low power mode).
  2754 	an LPM (low power mode).
  2741 
  2755 
  2744 	{
  2758 	{
  2745 	LOG_FUNC
  2759 	LOG_FUNC
  2746 	iOverrideLPMRequests = ETrue;
  2760 	iOverrideLPMRequests = ETrue;
  2747 
  2761 
  2748 	return Arbitrate();
  2762 	return Arbitrate();
       
  2763 	}
       
  2764 
       
  2765 /*static*/ TInt CPhysicalLink::OverrideLPMTimeoutCallback(TAny* aCPhysicalLink)
       
  2766 	{
       
  2767 	LOG_STATIC_FUNC	
       
  2768 	CPhysicalLink* c = reinterpret_cast<CPhysicalLink*>(aCPhysicalLink);
       
  2769 	TInt err = c->UndoOverrideLPM();
       
  2770 	//we deliberately ignore this return value because we can't do anything to correct the error situation
       
  2771 	if (KErrNone != err)
       
  2772 		{
       
  2773 		LOG2(_L("Physical link: UndoOverrideLPM returned an error %d on the connection 0x%08x"), err, c);
       
  2774 		}
       
  2775 	c->iLPMOverrideTimerQueued = EFalse;
       
  2776 	return KErrNone;
  2749 	}
  2777 	}
  2750 
  2778 
  2751 TInt CPhysicalLink::UndoOverrideLPM()
  2779 TInt CPhysicalLink::UndoOverrideLPM()
  2752 /**
  2780 /**
  2753 	A need to ensure we are not in LPM has gone.
  2781 	A need to ensure we are not in LPM has gone.
  3086 	iPinRequester = NULL;
  3114 	iPinRequester = NULL;
  3087 	iPinHandler = NULL;
  3115 	iPinHandler = NULL;
  3088 	AuthenticationComplete(EPinRequestPending);
  3116 	AuthenticationComplete(EPinRequestPending);
  3089 	}
  3117 	}
  3090 
  3118 
       
  3119 
  3091 TInt CPhysicalLink::RequestHold()
  3120 TInt CPhysicalLink::RequestHold()
  3092 	{
  3121 	{
  3093 	LOG_FUNC
  3122 	LOG_FUNC
  3094 	if (!IsConnected())
  3123 	return RequestMode(EHoldMode);
  3095         {
  3124 	}
  3096         return KErrDisconnected;
  3125 
  3097         }
  3126 TInt CPhysicalLink::RequestSniff()
  3098 	 return iLowPowModeCtrl.ChangeMode(EHoldMode, iHandle);
  3127 	{
       
  3128 	LOG_FUNC
       
  3129 	return RequestMode(ESniffMode);
       
  3130 	}
       
  3131 
       
  3132 TInt CPhysicalLink::RequestPark()
       
  3133 	{
       
  3134 	LOG_FUNC
       
  3135 	return RequestMode(EParkMode);
       
  3136 	}
       
  3137 
       
  3138 TInt CPhysicalLink::RequestActive()
       
  3139 	{
       
  3140 	LOG_FUNC
       
  3141 	return RequestMode(EActiveMode);
  3099 	}
  3142 	}
  3100 
  3143 
  3101 void CPhysicalLink::ReadNewPhysicalLinkMetricValue(TUint aIoctlName, CBTProxySAP& aSAP, TInt aCurrentValue)
  3144 void CPhysicalLink::ReadNewPhysicalLinkMetricValue(TUint aIoctlName, CBTProxySAP& aSAP, TInt aCurrentValue)
  3102 	{
  3145 	{
  3103 	LOG_FUNC
  3146 	LOG_FUNC
  3340 	LOG_FUNC
  3383 	LOG_FUNC
  3341 	ASSERT_DEBUG(iParent);
  3384 	ASSERT_DEBUG(iParent);
  3342 	CActiveScheduler::Add(this);
  3385 	CActiveScheduler::Add(this);
  3343 	}
  3386 	}
  3344 
  3387 
       
  3388 CArbitrationDelayTimer::~CArbitrationDelayTimer()
       
  3389 	{
       
  3390 	LOG_FUNC
       
  3391 	}
       
  3392 
  3345 void CArbitrationDelayTimer::ConstructL()
  3393 void CArbitrationDelayTimer::ConstructL()
  3346 	{
  3394 	{
  3347 	LOG_FUNC
  3395 	LOG_FUNC
  3348 	CTimer::ConstructL();
  3396 	CTimer::ConstructL();
  3349 	}
  3397 	}
  3361 TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority)
  3409 TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority)
  3362 	{
  3410 	{
  3363 	LOG_FUNC
  3411 	LOG_FUNC
  3364 	// Work out what the local priority will be now
  3412 	// Work out what the local priority will be now
  3365 	iLocalPriority = iLocalPriority || aLocalPriority;
  3413 	iLocalPriority = iLocalPriority || aLocalPriority;
  3366 	LOG1(_L8("Arbitration: Local Priority now %d"), iLocalPriority);
  3414 	LOG1(_L8("Arbitraion: Local Priority now %d"), iLocalPriority);
  3367 	if(aImmediate)
  3415 	if(aImmediate)
  3368 		{
  3416 		{
  3369 		LOG(_L8("Arbitration: Immediate Arbitration Requested..."));
  3417 		LOG(_L8("Arbitraion: Immediate Arbitration Requested..."));
  3370 		CancelButPreserveLocalPriority();
  3418 		CancelButPreserveLocalPriority();
  3371 		return DoArbitrate();
  3419 		return DoArbitrate();
  3372 		}
  3420 		}
  3373 	else if(!IsActive())
  3421 	else if(!IsActive())
  3374 		{
  3422 		{
  3375 		LOG(_L8("Arbitration: Arbitration requested, will execute after delay timer..."));
  3423 		LOG(_L8("Arbitraion: Arbitration requested, will execute after delay timer..."));
  3376 		After(KBTArbitrationDelay);
  3424 		After(KBTArbitrationDelay);
  3377 		}
  3425 		}
  3378 	else // timer is already on its way
  3426 	else // timer is already on its way
  3379 		{
  3427 		{
  3380 		LOG(_L8("Arbitration: Arbitration delay timer still pending..."));
  3428 		LOG(_L8("Arbitraion: Arbitration delay timer still pending..."));
  3381 		}
  3429 		}
  3382 	return KErrNone;
  3430 	return KErrNone;
  3383 	}
  3431 	}
  3384 
  3432 
  3385 void CArbitrationDelayTimer::Restart()
  3433 void CArbitrationDelayTimer::Restart()
  3386 	{
  3434 	{
  3387 	LOG_FUNC
  3435 	LOG_FUNC
  3388 	LOG(_L8("Arbitration: Arbitration timer restarted..."));
  3436 	LOG(_L8("Arbitraion: Arbitration timer restarted..."));
  3389 	CancelButPreserveLocalPriority();
  3437 	CancelButPreserveLocalPriority();
  3390 	After(KBTArbitrationDelay);
  3438 	After(KBTArbitrationDelay);
  3391 	}
  3439 	}
  3392 
  3440 
  3393 void CArbitrationDelayTimer::CancelButPreserveLocalPriority()
  3441 void CArbitrationDelayTimer::CancelButPreserveLocalPriority()
  3403 /**
  3451 /**
  3404 Allow arbitration of low power modes when the timer expires
  3452 Allow arbitration of low power modes when the timer expires
  3405 **/
  3453 **/
  3406 	{
  3454 	{
  3407 	LOG_FUNC
  3455 	LOG_FUNC
  3408 	LOG(_L8("Arbitration: Delayed Arbitration executing..."));
  3456 	LOG(_L8("Arbitraion: Delayed Arbitration executing..."));
  3409 	static_cast<void>(DoArbitrate()); // ignore the error (always has been...)
  3457 	static_cast<void>(DoArbitrate()); // ignore the error (always has been...)
  3410 	}
  3458 	}
  3411 
  3459 
  3412 TInt CArbitrationDelayTimer::DoArbitrate()
  3460 TInt CArbitrationDelayTimer::DoArbitrate()
  3413 	{
  3461 	{
  3941 	LOG_FUNC
  3989 	LOG_FUNC
  3942 	TRAPD(err, DoChangeModeL(aMode, aHandle));
  3990 	TRAPD(err, DoChangeModeL(aMode, aHandle));
  3943 	return err;
  3991 	return err;
  3944 	}
  3992 	}
  3945 
  3993 
  3946 TInt TLowPowModeCmdController::ExecuteModeChange(TBTLinkMode aTargetMode)
       
  3947 	{
       
  3948 	LOG_FUNC
       
  3949 	iTargetMode = aTargetMode;
       
  3950 	if(iTargetMode != iParent.LinkState().LinkMode())
       
  3951 		{
       
  3952 		if(iParent.LinkState().LinkMode() != EActiveMode)
       
  3953 			{
       
  3954 			//the current mode is not in Active Mode, therefore the mode need to change to active first before change to other mode.
       
  3955 			LOG(_L8("ExecuteModeChange: Exiting existing LPM mode..."));
       
  3956 			return ExitMode(iParent.LinkState().LinkMode(), iParent.Handle());
       
  3957 			}
       
  3958 		//the current mode is in Active mode, therefore the mode is ready to go other mode.
       
  3959 		if(iTargetMode == EHoldMode)
       
  3960 			{
       
  3961 			LOG(_L8("ExecuteModeChange: Entering Hold mode..."));
       
  3962 			return ChangeMode(EHoldMode, iParent.Handle());
       
  3963 			}
       
  3964 		else if(iTargetMode == ESniffMode)
       
  3965 			{
       
  3966 			LOG(_L8("ExecuteModeChange: Entering Sniff mode..."));
       
  3967 			return ChangeMode(ESniffMode, iParent.Handle());
       
  3968 			}
       
  3969 		else if(iTargetMode == EParkMode)
       
  3970 			{
       
  3971 			LOG(_L8("ExecuteModeChange: Entering Park mode..."));
       
  3972 			return ChangeMode(EParkMode, iParent.Handle());
       
  3973 			}
       
  3974 		else if(iTargetMode == EActiveMode)
       
  3975 			{
       
  3976 			LOG(_L8("ExecuteModeChange: Staying in Active mode..."));
       
  3977 			return KErrNone;
       
  3978 			}
       
  3979 		// Shouldn't reach here, we have a strange mode
       
  3980 		DEBUG_PANIC_LINENUM;
       
  3981 		}
       
  3982 	LOG(_L8("ExecuteModeChange: Already in correct LPM, not doing anything"));
       
  3983 	return KErrNone;
       
  3984 	}
       
  3985 
       
  3986 void TLowPowModeCmdController::SniffL(THCIConnHandle aHandleToRemote)
  3994 void TLowPowModeCmdController::SniffL(THCIConnHandle aHandleToRemote)
  3987 	{
  3995 	{
  3988 	LOG_FUNC
  3996 	LOG_FUNC
  3989 	CSniffModeCommand* cmd = CSniffModeCommand::NewL(aHandleToRemote, KBTSniffModeMaxInterval, KBTSniffModeMinInterval, KBTSniffModeAttempt, KBTSniffModeTimeout);
  3997 	CSniffModeCommand* cmd = CSniffModeCommand::NewL(aHandleToRemote, KBTSniffModeMaxInterval, KBTSniffModeMinInterval, KBTSniffModeAttempt, KBTSniffModeTimeout);
  3990 
  3998 
  4050 		iOutstandingCmd = EFalse;	// reset the outstanding flag
  4058 		iOutstandingCmd = EFalse;	// reset the outstanding flag
  4051 
  4059 
  4052 		LOG2(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode());
  4060 		LOG2(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode());
  4053 
  4061 
  4054 		const TModeChangeEvent& modeChangeEvent = TModeChangeEvent::Cast(aEvent);
  4062 		const TModeChangeEvent& modeChangeEvent = TModeChangeEvent::Cast(aEvent);
  4055 		TBTLinkMode currentmode = EActiveMode;
  4063 		TBTLinkMode mode = EActiveMode;
  4056 		switch(modeChangeEvent.CurrentMode())
  4064 		switch(modeChangeEvent.CurrentMode())
  4057 			{
  4065 			{
  4058 			// Mode 0, as defined for the Mode Change Event, is Active Mode
  4066 			// Mode 0, as defined for the Mode Change Event, is Active Mode
  4059 			case 0:
  4067 			case 0:
  4060 				break;
  4068 				break;
  4061 			case 1:
  4069 			case 1:
  4062 				currentmode = EHoldMode;
  4070 				mode = EHoldMode;
  4063 				break;
  4071 				break;
  4064 			case 2:
  4072 			case 2:
  4065 				currentmode = ESniffMode;
  4073 				mode = ESniffMode;
  4066 				break;
  4074 				break;
  4067 			case 3:
  4075 			case 3:
  4068 				currentmode = EParkMode;
  4076 				mode = EParkMode;
  4069 				break;
  4077 				break;
  4070 			default:
  4078 			default:
  4071 				__ASSERT_ALWAYS(EFalse, Panic(EHCICommandBadArgument));
  4079 				__ASSERT_ALWAYS(EFalse, Panic(EHCICommandBadArgument));
  4072 				break;
  4080 				break;
  4073 			}
  4081 			}
  4074 		// In the HCI_Facade, in this situation, CPhysicalLinksManager::ModeChanged() is called.
  4082 			// In the HCI_Facade, in this situation, CPhysicalLinksManager::ModeChanged() is called.
  4075 		// Since this methods find the CPhysicalLink object (that is iParent) and then call its
  4083 			// Since this methods find the CPhysicalLink object (that is iParent) and then call its
  4076 		// ModeChange method, we can call it directly.
  4084 			// ModeChange method, we can call it directly.
  4077 		iParent.ModeChange(aEvent.ErrorCode(), modeChangeEvent.ConnectionHandle(), currentmode, modeChangeEvent.Interval());
  4085 			iParent.ModeChange(aEvent.ErrorCode(), modeChangeEvent.ConnectionHandle(), mode, modeChangeEvent.Interval());
  4078 		//pass the current mode into Gear box. let gear box to decide if the mode is on the target mode. 
       
  4079 		//if it is, the gear box returns KErrNone, if it is not, the gear box will make another request for the target mode
       
  4080 		if (aEvent.ErrorCode() == EOK)
       
  4081 			{
       
  4082             TInt err = ExecuteModeChange(iTargetMode);
       
  4083 			LOG1(_L("TLowPowModeCmdController::ExecuteModeChange: err:%d"), err);
       
  4084 			}
       
  4085 		}
  4086 		}
  4086 	}
  4087 	}
  4087 
  4088 
  4088 void TLowPowModeCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
  4089 void TLowPowModeCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
  4089 	{
  4090 	{