bluetooth/btstack/linkmgr/physicallinks.cpp
changeset 33 4e80e1b997a8
parent 19 4b81101308c6
child 34 9d84592f5036
equal deleted inserted replaced
19:4b81101308c6 33:4e80e1b997a8
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
   143 	iAuthenticationCtrl.Abort();
   143 	iAuthenticationCtrl.Abort();
   144 
   144 
   145 	delete iPhysicalLinkMetrics;
   145 	delete iPhysicalLinkMetrics;
   146 	delete iPinRequester;
   146 	delete iPinRequester;
   147 	delete iNumericComparator;
   147 	delete iNumericComparator;
       
   148 	delete iUserConfirmer;
   148 	delete iPasskeyEntry;
   149 	delete iPasskeyEntry;
   149 	delete iArbitrationDelay;
   150 	delete iArbitrationDelay;
   150 	delete iRoleSwitchCompleteCallBack;
   151 	delete iRoleSwitchCompleteCallBack;
   151 	delete iEncryptionEnforcer;
   152 	delete iEncryptionEnforcer;
   152 
   153 
   554 		}
   555 		}
   555 	if(juice->IsClockOffsetFromHCI())
   556 	if(juice->IsClockOffsetFromHCI())
   556 		{
   557 		{
   557 		iDevice.SetClockOffset(jle.iClockOffset);
   558 		iDevice.SetClockOffset(jle.iClockOffset);
   558 		}
   559 		}
       
   560 	if(juice->IsCoDFromHCI())
       
   561 		{
       
   562 		iDevice.SetDeviceClass(jle.iCoD);
       
   563 		}
   559 	}
   564 	}
   560 
   565 
   561 void CPhysicalLink::StoreDeviceL( TBool aPreventDeviceAddition )
   566 void CPhysicalLink::StoreDeviceL( TBool aPreventDeviceAddition )
   562 	{
   567 	{
   563 	LOG_FUNC
   568 	LOG_FUNC
   921 	}
   926 	}
   922 
   927 
   923 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn)
   928 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn)
   924 	{
   929 	{
   925 	LOG_FUNC
   930 	LOG_FUNC
   926 	if (aErr == KErrNone)
   931 	ConnectionComplete(CHciUtil::SymbianErrorCode(aErr), aConn);
       
   932 	}
       
   933 
       
   934 void CPhysicalLink::ConnectionComplete(TInt aResult, const TBTConnect& aConn)
       
   935 	{
       
   936 	if (aResult == KErrNone)
   927 		{
   937 		{
   928 		if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink)
   938 		if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink)
   929 			{
   939 			{
   930 			LOG(_L("Got a ConnectionComplete for a non-existant SCO link"))
   940 			LOG(_L("Got a ConnectionComplete for a non-existant SCO link"))
   931 			//This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for
   941 			//This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for
   932 			//a remote device to respond to a connection request.
   942 			//a remote device to respond to a connection request.
   933 			iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
   943 			iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
   934 
   944 
   935 			if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that
   945 			//The baseband might actually have established a SCO link, so send a Disconnect.
   936 				{
   946 			//If no SCO link exists the command will fail gracefully.
   937 				//The baseband might actually have established a SCO link, so send a Disconnect.
   947 			TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
   938 				//If no SCO link exists the command will fail gracefully.
       
   939 				TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
       
   940 				}
       
   941 
   948 
   942 			return;
   949 			return;
   943 			}
   950 			}
   944 
   951 
   945 		// update bb model
   952 		// update bb model
   983 			NotifyStateChange(event);
   990 			NotifyStateChange(event);
   984 
   991 
   985 			if (aConn.iEncryptMode)
   992 			if (aConn.iEncryptMode)
   986 				{
   993 				{
   987 				// pretend there's been an encryption event
   994 				// pretend there's been an encryption event
   988 				EncryptionChange(aErr, aConn.iConnH, aConn.iEncryptMode);
   995 				EncryptionChange(EOK, aConn.iConnH, aConn.iEncryptMode);
   989 				}
   996 				}
   990 			}
   997 			}
   991 
   998 
   992 		// This is assuming that our stack only allows one synchronous link per phy link.
   999 		// This is assuming that our stack only allows one synchronous link per phy link.
   993  		// SCO (not eSCO) Link getting notified here.
  1000  		// SCO (not eSCO) Link getting notified here.
  1055 			// The KInvalidConnectionHandle test ensures that we ignore errored outgoing SCO connects.
  1062 			// The KInvalidConnectionHandle test ensures that we ignore errored outgoing SCO connects.
  1056 			return;
  1063 			return;
  1057 			}
  1064 			}
  1058 
  1065 
  1059 		iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
  1066 		iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
  1060 		NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr));
  1067 		NotifyLogicalLinkError(aConn.iLinkType, aResult);
  1061 		if (aConn.iLinkType == EACLLink)
  1068 		if (aConn.iLinkType == EACLLink)
  1062 			{
  1069 			{
  1063 			// BT 1.2 says that as the ACL Link goes up and down, so does the physical link
  1070 			// BT 1.2 says that as the ACL Link goes up and down, so does the physical link
  1064 			// so if the ACL Link has gone, so has this
  1071 			// so if the ACL Link has gone, so has this
  1065 			// for SCO we remain in place.
  1072 			// for SCO we remain in place.
  1066 			TBTBasebandEventNotification event(ENotifyPhysicalLinkError, CHciUtil::SymbianErrorCode(aErr));
  1073 			TBTBasebandEventNotification event(ENotifyPhysicalLinkError, aResult);
  1067 			NotifyStateChange(event);
  1074 			NotifyStateChange(event);
  1068 			delete this;
  1075 			delete this;
  1069 			}
  1076 			}
  1070 		}
  1077 		}
  1071 	// ***Watchout*** delete this above: careful about code here
  1078 	// ***Watchout*** delete this above: careful about code here
  1694 
  1701 
  1695 TInt CPhysicalLink::Arbitrate(TBool aImmediately, TBool aLocalPriority)
  1702 TInt CPhysicalLink::Arbitrate(TBool aImmediately, TBool aLocalPriority)
  1696 	{
  1703 	{
  1697 	LOG_FUNC
  1704 	LOG_FUNC
  1698 	if (!IsConnected())
  1705 	if (!IsConnected())
       
  1706 		{
       
  1707 		LOG(_L8("Physical link not connected, no arbitration executed"));
  1699 		return KErrDisconnected;
  1708 		return KErrDisconnected;
  1700 
  1709 		}
  1701 	if ( aImmediately )
  1710 	// The arbitration delay object will decide how much delay
  1702 		{
  1711 	return iArbitrationDelay->Start(aImmediately, aLocalPriority);
  1703 		iArbitrationDelay->Cancel();
       
  1704 		return DoArbitrate(aLocalPriority);		
       
  1705 		}
       
  1706 	else if (iArbitrationDelay->IsActive())
       
  1707 		{
       
  1708 		return KErrNone;
       
  1709 		}
       
  1710 	else
       
  1711 		{
       
  1712 		iArbitrationDelay->Start(aLocalPriority);
       
  1713 		return KErrNone;
       
  1714 		}
       
  1715 	}
  1712 	}
  1716 
  1713 
  1717 TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority)
  1714 TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority)
  1718 	{
  1715 	{
       
  1716 	LOG_FUNC
  1719 	if (!IsConnected())
  1717 	if (!IsConnected())
  1720 		{
  1718 		{
       
  1719 		LOG(_L8("Physical link not connected, no arbitration executed"));
  1721 		return KErrDisconnected;
  1720 		return KErrDisconnected;
  1722 		}
  1721 		}
  1723 
  1722 
  1724 	//start arbitrate process with what our local controller supports
  1723 	//start arbitrate process with what our local controller supports
  1725 	TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later
  1724 	TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later
  1726 	TBool roleSwitchAllowed = EFalse;
  1725 	TBool roleSwitchAllowed = iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed();
  1727 
  1726 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - Prior to proxies"), allowedModesMask, roleSwitchAllowed);
  1728  	if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed())
  1727 	
  1729  		{
       
  1730  		roleSwitchAllowed = ETrue;
       
  1731  		}
       
  1732 
       
  1733 	// ask proxies what they want from the PHY
  1728 	// ask proxies what they want from the PHY
  1734  	TUint8 requestedModeMask = 0;
  1729 	TUint16 requestedModeMask = 0; // mask of current LPM requests from proxy's
  1735  	TUint8 requestedMode = 0;
  1730 	static const TUint16 KExplicitActiveMode = 0x0100; // special bit for explicit active mode requests
  1736  	TBool activeModeIsRequested = EFalse;
  1731 	
  1737 	TSglQueIter<CBTProxySAP> iter(iProxySAPs);
  1732 	TSglQueIter<CBTProxySAP> iter(iProxySAPs);
  1738 	while (iter)
  1733 	while (iter)
  1739 		{
  1734 		{
  1740 		CBTProxySAP* proxy = iter++;
  1735 		CBTProxySAP* proxy = iter++;
  1741 
  1736 
  1742  		requestedMode = proxy->GetRequestedModes();
  1737 		TUint8 requestedMode = proxy->GetRequestedModes();
  1743  		requestedModeMask |= requestedMode;
  1738 		requestedModeMask |= requestedMode;
  1744 
  1739 
  1745 		if (requestedMode == EActiveMode && proxy->RequestedActiveMode())
  1740 		TBool explicitActiveModeRequest = proxy->RequestedActiveMode();
  1746  			{
  1741 		if (requestedMode == EActiveMode && explicitActiveModeRequest)
  1747  			// An Active Mode request will override all other local low power mode requests
  1742 			{
  1748  			// but continue to collect the requirement from the other proxies..
  1743 			requestedModeMask |= KExplicitActiveMode;
  1749  			activeModeIsRequested = ETrue;
  1744 			}
  1750  			}
  1745 
  1751 
  1746 		TUint8 allowedModes = proxy->GetAllowedModes();
  1752 		allowedModesMask &= proxy->GetAllowedModes();
  1747 		allowedModesMask &= allowedModes;
  1753 		roleSwitchAllowed &= proxy->IsRoleSwitchAllowed();
  1748 		
  1754 		}
  1749 		TBool roleSwitchAllowedByProxy = proxy->IsRoleSwitchAllowed();
  1755 
  1750 		roleSwitchAllowed = roleSwitchAllowed && roleSwitchAllowedByProxy;
  1756  	if (activeModeIsRequested)
  1751 		
  1757  		{
  1752 		LOG4(_L8("Arbitration: Proxy(0x%08x) - requested mode = 0x%04x, link policy (LPM:0x%02x, Role:0x%x)"), proxy, requestedMode, allowedModes, roleSwitchAllowedByProxy);
  1758  		// Any Active Mode request will override all other low power mode requests,
  1753 		}
  1759  		// so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed
  1754 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - after proxies"), allowedModesMask, roleSwitchAllowed);
  1760  		// as specified by all the local proxies
       
  1761  		requestedModeMask = EActiveMode;
       
  1762  		}
       
  1763 
  1755 
  1764 	// clear out modes not supported by local Controller
  1756 	// clear out modes not supported by local Controller
       
  1757 	// Future improvement - what about modes supported by the remote device?
  1765 	allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally();
  1758 	allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally();
       
  1759 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - only supported modes"), allowedModesMask, roleSwitchAllowed);
  1766 
  1760 
  1767 	if(iOverrideParkRequests)
  1761 	if(iOverrideParkRequests)
  1768 		{
  1762 		{
  1769 		// We wish to ensure the physical link is not in PARK mode.
  1763 		// We wish to ensure the physical link is not in PARK mode.
  1770 		// The only way to guarantee this is to disallow PARK via the link policy settings.
  1764 		// The only way to guarantee this is to disallow PARK via the link policy settings.
  1771 		allowedModesMask &= ~EParkMode;
  1765 		allowedModesMask &= ~EParkMode;
  1772 		}
  1766 		}
  1773 
  1767 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - overrides applied"), allowedModesMask, roleSwitchAllowed);
  1774 	if(allowedModesMask != iLinkPolicy.LowPowerModePolicy()
  1768 
  1775 		|| roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed())
  1769 	// Controller policy for the connection may need updating
  1776 		{
  1770 	SetModesAllowed(allowedModesMask, roleSwitchAllowed);
  1777 		// Controller policy for the connection needs updating
  1771 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - submitted"), allowedModesMask, roleSwitchAllowed);
  1778 		SetModesAllowed(allowedModesMask, roleSwitchAllowed);
       
  1779 		}
       
  1780 
  1772 
  1781 	//If OverrideLPM flag is set, we do not disable LP modes via the link policy settings
  1773 	//If OverrideLPM flag is set, we do not disable LP modes via the link policy settings
  1782 	//This is done because OverrideLPM should not prevent remotes putting us into an LPM
  1774 	//This is done because OverrideLPM should not prevent remotes putting us into an LPM
  1783 	//Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM
  1775 	//Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM
  1784 	if(iOverrideLPMRequests)
  1776 	if(iOverrideLPMRequests)
  1785 		{
  1777 		{
  1786 		// We need to ensure the physical link is in active mode.
  1778 		// We need to ensure the physical link is in active mode.
  1787 		allowedModesMask = EActiveMode;
  1779 		allowedModesMask = EActiveMode;
  1788 		}
  1780 		}
  1789 
  1781 	LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - post setting overrides applied"), allowedModesMask, roleSwitchAllowed);
  1790 	TUint8 modeChangeMask = static_cast<TUint8>(requestedModeMask & allowedModesMask);
  1782 
  1791 	TUint8 modeCompareMask = 0;
  1783 	TUint16 modeChangeMask = requestedModeMask & (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode);
       
  1784 	TUint16 modeCompareMask = 0;
       
  1785 	LOG2(_L8("Arbitration: mode change mask = 0x%04x, local priority = 0x%x"), modeChangeMask, aLocalPriority);
  1792 
  1786 
  1793 	if(aLocalPriority)
  1787 	if(aLocalPriority)
  1794 		{
  1788 		{
  1795 		// If we want local priority, we go with what we want to do
  1789 		// If we want local priority, we go with what we want to do
  1796 		// irrespective of what the remote may have previously requested.
  1790 		// irrespective of what the remote may have previously requested.
  1803  		// because a remote device has changed it..
  1797  		// because a remote device has changed it..
  1804 
  1798 
  1805 		// modeCompareMask should start only having zero bits where
  1799 		// modeCompareMask should start only having zero bits where
  1806 		// requestedModeMask has a zero bit and iPreviousRequestedModeMask does not
  1800 		// requestedModeMask has a zero bit and iPreviousRequestedModeMask does not
  1807 		// i.e. a mode is newly no longer requested.
  1801 		// i.e. a mode is newly no longer requested.
  1808 		modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask;
  1802 		modeCompareMask = ~((requestedModeMask ^ iPreviousRequestedModeMask) & iPreviousRequestedModeMask);
  1809 
  1803 
  1810 		// Remove bits from modeCompareMask that are not in allowedModesMask
  1804 		// Remove bits from modeCompareMask that are not in allowedModesMask
  1811 		// We cannot stay in a power mode that we do not allow.
  1805 		// We cannot stay in a power mode that we do not allow.
  1812 		modeCompareMask &= allowedModesMask;
  1806 		modeCompareMask &= (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode);
  1813 		}
  1807 		}
       
  1808 	LOG1(_L8("Arbitration: Comparison mask = 0x%04x"), modeCompareMask);
  1814 
  1809 
  1815 	iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value.
  1810 	iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value.
  1816 
  1811 
  1817 	TUint8 currentModeMask = static_cast<TUint8>(iLinkState.LinkMode());
  1812 	// get the current mode.
       
  1813 	TBTLinkMode currentMode = iLinkState.LinkMode();
       
  1814 	TUint16 currentModeMask = static_cast<TUint16>(currentMode);
       
  1815 	if(currentModeMask == EActiveMode)
       
  1816 		{
       
  1817 		// if in active mode then could have been because of an explicit active mode request
       
  1818 		currentModeMask |= KExplicitActiveMode;
       
  1819 		}
       
  1820 	LOG1(_L8("Arbitration: Current mode mask = 0x%04x"), currentModeMask);
       
  1821 	
  1818 	if(modeCompareMask & currentModeMask)
  1822 	if(modeCompareMask & currentModeMask)
  1819 		{
  1823 		{
       
  1824 		LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask);
  1820 		// The current state is the same as the permitted required role(s).
  1825 		// The current state is the same as the permitted required role(s).
  1821 		return KErrNone;
  1826 		return KErrNone;
  1822 		}
  1827 		}
  1823 
  1828 	
  1824 	if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode)
  1829 	TBTLinkMode nextMode = EActiveMode;
  1825 		{
  1830 	// Determine which LPM we should be in (if any)
  1826 		// The current low power mode should be exited.
  1831 	if(modeChangeMask & KExplicitActiveMode)
  1827 		return RequestActive();
  1832 		{
  1828 		}
  1833 		nextMode = EActiveMode;
  1829 
  1834 		}
  1830 	if(modeChangeMask != EActiveMode)
  1835 	else if(modeChangeMask & EHoldMode)
  1831 		{
  1836 		{
  1832 		if(currentModeMask != EActiveMode)
  1837 		nextMode = EHoldMode;
  1833 			{
  1838 		}
  1834 			// The system is currently in a low power mode.  Exit this before
  1839 	else if(modeChangeMask & ESniffMode)
  1835 			// entering the new mode.
  1840 		{
  1836 			TInt rerr = RequestActive();
  1841 		nextMode = ESniffMode;
  1837 			if(rerr != KErrNone)
  1842 		}
       
  1843 	else if(modeChangeMask & EParkMode)
       
  1844 		{
       
  1845 		nextMode = EParkMode;
       
  1846 		}
       
  1847 	LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, nextMode);
       
  1848 	
       
  1849 	if(nextMode != currentMode)
       
  1850 		{
       
  1851 		if(currentMode != EActiveMode)
       
  1852 			{
       
  1853 			LOG(_L8("Arbitration: Exiting existing LPM mode..."));
       
  1854 			TInt err = RequestActive();
       
  1855 			if(err != KErrNone)
  1838 				{
  1856 				{
  1839 				return rerr;
  1857 				return err;
  1840 				}
  1858 				}
  1841 			}
  1859 			}
  1842 
  1860 		if(nextMode == EHoldMode)
  1843 		if(modeChangeMask & EHoldMode)
  1861 			{
  1844 			{
  1862 			LOG(_L8("Arbitration: Entering Hold mode..."));
  1845 			return RequestHold();
  1863 			return RequestHold();
  1846 			}
  1864 			}
  1847 		if(modeChangeMask & ESniffMode)
  1865 		else if(nextMode == ESniffMode)
  1848 			{
  1866 			{
       
  1867 			LOG(_L8("Arbitration: Entering Sniff mode..."));
  1849 			return RequestSniff();
  1868 			return RequestSniff();
  1850 			}
  1869 			}
  1851 		if(modeChangeMask & EParkMode)
  1870 		else if(nextMode == EParkMode)
  1852 			{
  1871 			{
       
  1872 			LOG(_L8("Arbitration: Entering Park mode..."));
  1853 			return RequestPark();
  1873 			return RequestPark();
  1854 			}
  1874 			}
  1855 		}
  1875 		else if(nextMode == EActiveMode)
  1856 
  1876 			{
  1857 	// This point in the code is reached if the Link Policy settings are
  1877 			LOG(_L8("Arbitration: Staying in Active mode..."));
  1858 	// changed but the mode is not.	 Return OK error code.
  1878 			return KErrNone;
       
  1879 			}
       
  1880 		// Shouldn't reach here, we have a strange mode
       
  1881 		DEBUG_PANIC_LINENUM;
       
  1882 		}
       
  1883 
       
  1884 	LOG(_L8("Arbitration: Already in correct LPM, not doing anything"));
  1859 	return KErrNone;
  1885 	return KErrNone;
  1860 	}
  1886 	}
  1861 
  1887 
  1862 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey)
  1888 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey)
  1863 	{
  1889 	{
  1874 	}
  1900 	}
  1875 
  1901 
  1876 void CPhysicalLink::StartArbitrationTimer() const
  1902 void CPhysicalLink::StartArbitrationTimer() const
  1877 	{
  1903 	{
  1878 	LOG_FUNC
  1904 	LOG_FUNC
  1879 	iArbitrationDelay->Start();
  1905 	iArbitrationDelay->Restart();
  1880 	}
  1906 	}
  1881 
  1907 
  1882 TInt CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy)
  1908 void CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy)
  1883 	{
  1909 	{
  1884 	LOG_FUNC
  1910 	LOG_FUNC
  1885 	// assume that we will be master until told otherwise
  1911 	// assume that we will be master until told otherwise
  1886 	ASSERT_DEBUG(!IsConnected());
  1912 	ASSERT_DEBUG(!IsConnected());
  1887 
  1913 
  1896 	TUint16 pkt = KHCIDefaultPacketType;
  1922 	TUint16 pkt = KHCIDefaultPacketType;
  1897 
  1923 
  1898 	// optimise paging (as a best-effort attempt).
  1924 	// optimise paging (as a best-effort attempt).
  1899 	TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit);
  1925 	TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit);
  1900 	iLinksMan.TryToChangePageTimeout(pagetimeout);
  1926 	iLinksMan.TryToChangePageTimeout(pagetimeout);
       
  1927 	
       
  1928 	// Set state in anticipation of the connection
       
  1929 	iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
       
  1930 	iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink);
       
  1931 	iLinkState.SetLinkRole(EMaster);
  1901 
  1932 
  1902 	TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch));
  1933 	TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch));
  1903 	if(ret==KErrNone)
  1934 	if(ret != KErrNone) // a physical link is in charge of it's own destiny.
  1904 		{
  1935 		{
  1905 		iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
  1936 		TBTConnect conn;
  1906 		iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink);
  1937 		conn.iBdaddr = BDAddr();
  1907 		iLinkState.SetLinkRole(EMaster);
  1938 		conn.iLinkType = EACLLink;
  1908 		}
  1939 		ConnectionComplete(ret, conn);
  1909 
  1940 		}
  1910 	return ret;
       
  1911 	}
  1941 	}
  1912 
  1942 
  1913 TInt CPhysicalLink::SCOConnect()
  1943 TInt CPhysicalLink::SCOConnect()
  1914 /**
  1944 /**
  1915 	A utility service provided to the SCO transport
  1945 	A utility service provided to the SCO transport
  2258 		(aEvent.EventType() & ENotifySniffMode)||
  2288 		(aEvent.EventType() & ENotifySniffMode)||
  2259 		(aEvent.EventType() & ENotifyParkMode)||
  2289 		(aEvent.EventType() & ENotifyParkMode)||
  2260 		(aEvent.EventType() & ENotifyHoldMode)) &&
  2290 		(aEvent.EventType() & ENotifyHoldMode)) &&
  2261 		(aEvent.ErrorCode() == KErrNone))
  2291 		(aEvent.ErrorCode() == KErrNone))
  2262 		{
  2292 		{
  2263 		iArbitrationDelay->Start();
  2293 		iArbitrationDelay->Restart();
  2264 		}
  2294 		}
  2265 	}
  2295 	}
  2266 
  2296 
  2267 /*static*/ TInt CPhysicalLink::TerminateCallback(TAny* aCPhysicalLink)
  2297 /*static*/ TInt CPhysicalLink::TerminateCallback(TAny* aCPhysicalLink)
  2268 	{
  2298 	{
  2300 TInt CPhysicalLink::Terminate(THCIErrorCode aReason)
  2330 TInt CPhysicalLink::Terminate(THCIErrorCode aReason)
  2301 	{
  2331 	{
  2302 	LOG_FUNC
  2332 	LOG_FUNC
  2303 	TInt err = KErrNone;
  2333 	TInt err = KErrNone;
  2304 
  2334 
       
  2335 	__ASSERT_DEBUG(aReason == EAuthenticationFailure
       
  2336 				|| aReason == ERemoteUserEndedConnection
       
  2337 				|| aReason == ERemoteLowResources
       
  2338 				|| aReason == ERemoteAboutToPowerOff
       
  2339 				|| aReason == EUnsupportedRemoteLMPFeature
       
  2340 				|| aReason == EPairingWithUnitKeyNotSupported,
       
  2341 				Panic (EInvalidDisconnectReason)); // Check the error code is valid with the spec
       
  2342 	
  2305 	if (iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending)
  2343 	if (iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending)
  2306 		{
  2344 		{
  2307 		// If the Link is not yet up then we cannot know the correct connection handle
  2345 		// If the Link is not yet up then we cannot know the correct connection handle
  2308 		// to disconnect so remember the request so we disconnect the link straight away
  2346 		// to disconnect so remember the request so we disconnect the link straight away
  2309 		// after it does come up.
  2347 		// after it does come up.
  2819 		aRequester.PINCodeRequestNegativeReply(aAddr);
  2857 		aRequester.PINCodeRequestNegativeReply(aAddr);
  2820 		return;
  2858 		return;
  2821 		}
  2859 		}
  2822 
  2860 
  2823 	TBTPinCode pinCode;
  2861 	TBTPinCode pinCode;
  2824 	if(iLinksMan.PrefetchMan().IsPrefetchAvailable(aAddr, pinCode))
  2862 	if(iLinksMan.PrefetchMan().GetPrefetch(aAddr, pinCode))
  2825 		{
  2863 	    {
  2826 		aRequester.PINCodeRequestReply(aAddr, pinCode);
  2864         iLinksMan.PrefetchMan().RemovePrefetch(aAddr);
  2827 		return;
  2865         aRequester.PINCodeRequestReply(aAddr, pinCode);
  2828 		}
  2866         return;
       
  2867 	    }
  2829 
  2868 
  2830 	iPinHandler = &aRequester;
  2869 	iPinHandler = &aRequester;
  2831 
  2870 
  2832 	TRAPD(err, DoPinRequestL(aAddr, *this)); // physical links will proxy a request.
  2871 	TRAPD(err, DoPinRequestL(aAddr, *this)); // physical links will proxy a request.
  2833 
  2872 
  2894 TBool CPhysicalLink::LinkKeyRequestPending()
  2933 TBool CPhysicalLink::LinkKeyRequestPending()
  2895 	{
  2934 	{
  2896 	LOG_FUNC
  2935 	LOG_FUNC
  2897 	return iAuthStateMask & ELinkKeyRequestPending;
  2936 	return iAuthStateMask & ELinkKeyRequestPending;
  2898 	}
  2937 	}
       
  2938 
       
  2939 TBool CPhysicalLink::IsAuthenticationRequestPending() const
       
  2940 	{
       
  2941 	LOG_FUNC
       
  2942 	return iAuthStateMask & EAuthenticationRequestPending;
       
  2943 	}
       
  2944 
  2899 
  2945 
  2900 void CPhysicalLink::SetAuthenticationPending(TUint8 aState)
  2946 void CPhysicalLink::SetAuthenticationPending(TUint8 aState)
  2901 	{
  2947 	{
  2902 	LOG_FUNC
  2948 	LOG_FUNC
  2903 	iAuthStateMask |= aState;
  2949 	iAuthStateMask |= aState;
  3356 	}
  3402 	}
  3357 
  3403 
  3358 // CArbitrationDelayTimer
  3404 // CArbitrationDelayTimer
  3359 
  3405 
  3360 CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent)
  3406 CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent)
  3361 	:CTimer(CActive::EPriorityStandard),
  3407 	: CTimer(CActive::EPriorityStandard)
  3362 	iParent(aParent)
  3408 	, iParent(aParent)
  3363 	{
  3409 	{
  3364 	LOG_FUNC
  3410 	LOG_FUNC
       
  3411 	ASSERT_DEBUG(iParent);
       
  3412 	CActiveScheduler::Add(this);
  3365 	}
  3413 	}
  3366 
  3414 
  3367 void CArbitrationDelayTimer::ConstructL()
  3415 void CArbitrationDelayTimer::ConstructL()
  3368 	{
  3416 	{
  3369 	LOG_FUNC
  3417 	LOG_FUNC
  3370 	CTimer::ConstructL();
  3418 	CTimer::ConstructL();
  3371 	CActiveScheduler::Add(this);
       
  3372 	}
  3419 	}
  3373 
  3420 
  3374 CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent)
  3421 CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent)
  3375 	{
  3422 	{
  3376 	LOG_STATIC_FUNC
  3423 	LOG_STATIC_FUNC
  3379 	self->ConstructL();
  3426 	self->ConstructL();
  3380 	CleanupStack::Pop(self);
  3427 	CleanupStack::Pop(self);
  3381 	return self;
  3428 	return self;
  3382 	}
  3429 	}
  3383 
  3430 
  3384 void CArbitrationDelayTimer::Start(TBool aLocalPriority)
  3431 TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority)
  3385 	{
  3432 	{
  3386 	LOG_FUNC
  3433 	LOG_FUNC
  3387 	// Work out what the local priority will be now
  3434 	// Work out what the local priority will be now
  3388 	TBool localPriority = iLocalPriority || aLocalPriority;
  3435 	iLocalPriority = iLocalPriority || aLocalPriority;
  3389 	Cancel(); // cancel current timer (will also reset priority so ...
  3436 	LOG1(_L8("Arbitraion: Local Priority now %d"), iLocalPriority);
  3390 	iLocalPriority = localPriority; // set the new priority)
  3437 	if(aImmediate)
       
  3438 		{
       
  3439 		LOG(_L8("Arbitraion: Immediate Arbitration Requested..."));
       
  3440 		CancelButPreserveLocalPriority();
       
  3441 		return DoArbitrate();
       
  3442 		}
       
  3443 	else if(!IsActive())
       
  3444 		{
       
  3445 		LOG(_L8("Arbitraion: Arbitration requested, will execute after delay timer..."));
       
  3446 		After(KBTArbitrationDelay);
       
  3447 		}
       
  3448 	else // timer is already on its way
       
  3449 		{
       
  3450 		LOG(_L8("Arbitraion: Arbitration delay timer still pending..."));
       
  3451 		}
       
  3452 	return KErrNone;
       
  3453 	}
       
  3454 
       
  3455 void CArbitrationDelayTimer::Restart()
       
  3456 	{
       
  3457 	LOG_FUNC
       
  3458 	LOG(_L8("Arbitraion: Arbitration timer restarted..."));
       
  3459 	CancelButPreserveLocalPriority();
  3391 	After(KBTArbitrationDelay);
  3460 	After(KBTArbitrationDelay);
       
  3461 	}
       
  3462 
       
  3463 void CArbitrationDelayTimer::CancelButPreserveLocalPriority()
       
  3464 	{
       
  3465 	LOG_FUNC
       
  3466 	TBool localPriority = iLocalPriority;
       
  3467 	Cancel();
       
  3468 	iLocalPriority = localPriority;
  3392 	}
  3469 	}
  3393 
  3470 
  3394 
  3471 
  3395 void CArbitrationDelayTimer::RunL()
  3472 void CArbitrationDelayTimer::RunL()
  3396 /**
  3473 /**
  3397 Allow arbitration of low power modes when the timer expires
  3474 Allow arbitration of low power modes when the timer expires
  3398 **/
  3475 **/
  3399 	{
  3476 	{
  3400 	LOG_FUNC
  3477 	LOG_FUNC
  3401 	if (iParent)
  3478 	LOG(_L8("Arbitraion: Delayed Arbitration executing..."));
  3402 		{
  3479 	static_cast<void>(DoArbitrate()); // ignore the error (always has been...)
  3403 		iParent->DoArbitrate(iLocalPriority);
  3480 	}
  3404 		}
  3481 
       
  3482 TInt CArbitrationDelayTimer::DoArbitrate()
       
  3483 	{
       
  3484 	LOG_FUNC
       
  3485 	TBool localPriority = iLocalPriority;
       
  3486 	iLocalPriority = EFalse;
       
  3487 	return iParent->DoArbitrate(localPriority);
  3405 	}
  3488 	}
  3406 
  3489 
  3407 void CArbitrationDelayTimer::DoCancel()
  3490 void CArbitrationDelayTimer::DoCancel()
  3408 	{
  3491 	{
  3409 	LOG_FUNC
  3492 	LOG_FUNC