925 } |
925 } |
926 |
926 |
927 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn) |
927 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn) |
928 { |
928 { |
929 LOG_FUNC |
929 LOG_FUNC |
930 if (aErr == KErrNone) |
930 ConnectionComplete(CHciUtil::SymbianErrorCode(aErr), aConn); |
|
931 } |
|
932 |
|
933 void CPhysicalLink::ConnectionComplete(TInt aResult, const TBTConnect& aConn) |
|
934 { |
|
935 if (aResult == KErrNone) |
931 { |
936 { |
932 if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink) |
937 if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink) |
933 { |
938 { |
934 LOG(_L("Got a ConnectionComplete for a non-existant SCO link")) |
939 LOG(_L("Got a ConnectionComplete for a non-existant SCO link")) |
935 //This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for |
940 //This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for |
936 //a remote device to respond to a connection request. |
941 //a remote device to respond to a connection request. |
937 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
942 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
938 |
943 |
939 if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that |
944 //The baseband might actually have established a SCO link, so send a Disconnect. |
940 { |
945 //If no SCO link exists the command will fail gracefully. |
941 //The baseband might actually have established a SCO link, so send a Disconnect. |
946 TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); |
942 //If no SCO link exists the command will fail gracefully. |
|
943 TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); |
|
944 } |
|
945 |
947 |
946 return; |
948 return; |
947 } |
949 } |
948 |
950 |
949 // update bb model |
951 // update bb model |
1698 |
1700 |
1699 TInt CPhysicalLink::Arbitrate(TBool aImmediately, TBool aLocalPriority) |
1701 TInt CPhysicalLink::Arbitrate(TBool aImmediately, TBool aLocalPriority) |
1700 { |
1702 { |
1701 LOG_FUNC |
1703 LOG_FUNC |
1702 if (!IsConnected()) |
1704 if (!IsConnected()) |
|
1705 { |
|
1706 LOG(_L8("Physical link not connected, no arbitration executed")); |
1703 return KErrDisconnected; |
1707 return KErrDisconnected; |
1704 |
1708 } |
1705 if ( aImmediately ) |
1709 // The arbitration delay object will decide how much delay |
1706 { |
1710 return iArbitrationDelay->Start(aImmediately, aLocalPriority); |
1707 iArbitrationDelay->Cancel(); |
|
1708 return DoArbitrate(aLocalPriority); |
|
1709 } |
|
1710 else if (iArbitrationDelay->IsActive()) |
|
1711 { |
|
1712 return KErrNone; |
|
1713 } |
|
1714 else |
|
1715 { |
|
1716 iArbitrationDelay->Start(aLocalPriority); |
|
1717 return KErrNone; |
|
1718 } |
|
1719 } |
1711 } |
1720 |
1712 |
1721 TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority) |
1713 TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority) |
1722 { |
1714 { |
|
1715 LOG_FUNC |
1723 if (!IsConnected()) |
1716 if (!IsConnected()) |
1724 { |
1717 { |
|
1718 LOG(_L8("Physical link not connected, no arbitration executed")); |
1725 return KErrDisconnected; |
1719 return KErrDisconnected; |
1726 } |
1720 } |
1727 |
1721 |
1728 //start arbitrate process with what our local controller supports |
1722 //start arbitrate process with what our local controller supports |
1729 TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later |
1723 TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later |
1730 TBool roleSwitchAllowed = EFalse; |
1724 TBool roleSwitchAllowed = iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed(); |
1731 |
1725 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - Prior to proxies"), allowedModesMask, roleSwitchAllowed); |
1732 if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed()) |
1726 |
1733 { |
|
1734 roleSwitchAllowed = ETrue; |
|
1735 } |
|
1736 |
|
1737 // ask proxies what they want from the PHY |
1727 // ask proxies what they want from the PHY |
1738 TUint8 requestedModeMask = 0; |
1728 TUint16 requestedModeMask = 0; // mask of current LPM requests from proxy's |
1739 TUint8 requestedMode = 0; |
1729 static const TUint16 KExplicitActiveMode = 0x0100; // special bit for explicit active mode requests |
1740 TBool activeModeIsRequested = EFalse; |
1730 |
1741 TSglQueIter<CBTProxySAP> iter(iProxySAPs); |
1731 TSglQueIter<CBTProxySAP> iter(iProxySAPs); |
1742 while (iter) |
1732 while (iter) |
1743 { |
1733 { |
1744 CBTProxySAP* proxy = iter++; |
1734 CBTProxySAP* proxy = iter++; |
1745 |
1735 |
1746 requestedMode = proxy->GetRequestedModes(); |
1736 TUint8 requestedMode = proxy->GetRequestedModes(); |
1747 requestedModeMask |= requestedMode; |
1737 requestedModeMask |= requestedMode; |
1748 |
1738 |
1749 if (requestedMode == EActiveMode && proxy->RequestedActiveMode()) |
1739 TBool explicitActiveModeRequest = proxy->RequestedActiveMode(); |
1750 { |
1740 if (requestedMode == EActiveMode && explicitActiveModeRequest) |
1751 // An Active Mode request will override all other local low power mode requests |
1741 { |
1752 // but continue to collect the requirement from the other proxies.. |
1742 requestedModeMask |= KExplicitActiveMode; |
1753 activeModeIsRequested = ETrue; |
1743 } |
1754 } |
1744 |
1755 |
1745 TUint8 allowedModes = proxy->GetAllowedModes(); |
1756 allowedModesMask &= proxy->GetAllowedModes(); |
1746 allowedModesMask &= allowedModes; |
1757 roleSwitchAllowed &= proxy->IsRoleSwitchAllowed(); |
1747 |
1758 } |
1748 TBool roleSwitchAllowedByProxy = proxy->IsRoleSwitchAllowed(); |
1759 |
1749 roleSwitchAllowed = roleSwitchAllowed && roleSwitchAllowedByProxy; |
1760 if (activeModeIsRequested) |
1750 |
1761 { |
1751 LOG4(_L8("Arbitration: Proxy(0x%08x) - requested mode = 0x%04x, link policy (LPM:0x%02x, Role:0x%x)"), proxy, requestedMode, allowedModes, roleSwitchAllowedByProxy); |
1762 // Any Active Mode request will override all other low power mode requests, |
1752 } |
1763 // so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed |
1753 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - after proxies"), allowedModesMask, roleSwitchAllowed); |
1764 // as specified by all the local proxies |
|
1765 requestedModeMask = EActiveMode; |
|
1766 } |
|
1767 |
1754 |
1768 // clear out modes not supported by local Controller |
1755 // clear out modes not supported by local Controller |
|
1756 // Future improvement - what about modes supported by the remote device? |
1769 allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally(); |
1757 allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally(); |
|
1758 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - only supported modes"), allowedModesMask, roleSwitchAllowed); |
1770 |
1759 |
1771 if(iOverrideParkRequests) |
1760 if(iOverrideParkRequests) |
1772 { |
1761 { |
1773 // We wish to ensure the physical link is not in PARK mode. |
1762 // We wish to ensure the physical link is not in PARK mode. |
1774 // The only way to guarantee this is to disallow PARK via the link policy settings. |
1763 // The only way to guarantee this is to disallow PARK via the link policy settings. |
1775 allowedModesMask &= ~EParkMode; |
1764 allowedModesMask &= ~EParkMode; |
1776 } |
1765 } |
1777 |
1766 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - overrides applied"), allowedModesMask, roleSwitchAllowed); |
1778 if(allowedModesMask != iLinkPolicy.LowPowerModePolicy() |
1767 |
1779 || roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed()) |
1768 // Controller policy for the connection may need updating |
1780 { |
1769 SetModesAllowed(allowedModesMask, roleSwitchAllowed); |
1781 // Controller policy for the connection needs updating |
1770 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - submitted"), allowedModesMask, roleSwitchAllowed); |
1782 SetModesAllowed(allowedModesMask, roleSwitchAllowed); |
|
1783 } |
|
1784 |
1771 |
1785 //If OverrideLPM flag is set, we do not disable LP modes via the link policy settings |
1772 //If OverrideLPM flag is set, we do not disable LP modes via the link policy settings |
1786 //This is done because OverrideLPM should not prevent remotes putting us into an LPM |
1773 //This is done because OverrideLPM should not prevent remotes putting us into an LPM |
1787 //Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM |
1774 //Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM |
1788 if(iOverrideLPMRequests) |
1775 if(iOverrideLPMRequests) |
1789 { |
1776 { |
1790 // We need to ensure the physical link is in active mode. |
1777 // We need to ensure the physical link is in active mode. |
1791 allowedModesMask = EActiveMode; |
1778 allowedModesMask = EActiveMode; |
1792 } |
1779 } |
1793 |
1780 LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - post setting overrides applied"), allowedModesMask, roleSwitchAllowed); |
1794 TUint8 modeChangeMask = static_cast<TUint8>(requestedModeMask & allowedModesMask); |
1781 |
1795 TUint8 modeCompareMask = 0; |
1782 TUint16 modeChangeMask = requestedModeMask & (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode); |
|
1783 TUint16 modeCompareMask = 0; |
|
1784 LOG2(_L8("Arbitration: mode change mask = 0x%04x, local priority = 0x%x"), modeChangeMask, aLocalPriority); |
1796 |
1785 |
1797 if(aLocalPriority) |
1786 if(aLocalPriority) |
1798 { |
1787 { |
1799 // If we want local priority, we go with what we want to do |
1788 // If we want local priority, we go with what we want to do |
1800 // irrespective of what the remote may have previously requested. |
1789 // irrespective of what the remote may have previously requested. |
1807 // because a remote device has changed it.. |
1796 // because a remote device has changed it.. |
1808 |
1797 |
1809 // modeCompareMask should start only having zero bits where |
1798 // modeCompareMask should start only having zero bits where |
1810 // requestedModeMask has a zero bit and iPreviousRequestedModeMask does not |
1799 // requestedModeMask has a zero bit and iPreviousRequestedModeMask does not |
1811 // i.e. a mode is newly no longer requested. |
1800 // i.e. a mode is newly no longer requested. |
1812 modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask; |
1801 modeCompareMask = ~((requestedModeMask ^ iPreviousRequestedModeMask) & iPreviousRequestedModeMask); |
1813 |
1802 |
1814 // Remove bits from modeCompareMask that are not in allowedModesMask |
1803 // Remove bits from modeCompareMask that are not in allowedModesMask |
1815 // We cannot stay in a power mode that we do not allow. |
1804 // We cannot stay in a power mode that we do not allow. |
1816 modeCompareMask &= allowedModesMask; |
1805 modeCompareMask &= (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode); |
1817 } |
1806 } |
|
1807 LOG1(_L8("Arbitration: Comparison mask = 0x%04x"), modeCompareMask); |
1818 |
1808 |
1819 iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value. |
1809 iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value. |
1820 |
1810 |
1821 TUint8 currentModeMask = static_cast<TUint8>(iLinkState.LinkMode()); |
1811 // get the current mode. |
|
1812 TBTLinkMode currentMode = iLinkState.LinkMode(); |
|
1813 TUint16 currentModeMask = static_cast<TUint16>(currentMode); |
|
1814 if(currentModeMask == EActiveMode) |
|
1815 { |
|
1816 // if in active mode then could have been because of an explicit active mode request |
|
1817 currentModeMask |= KExplicitActiveMode; |
|
1818 } |
|
1819 LOG1(_L8("Arbitration: Current mode mask = 0x%04x"), currentModeMask); |
|
1820 |
1822 if(modeCompareMask & currentModeMask) |
1821 if(modeCompareMask & currentModeMask) |
1823 { |
1822 { |
|
1823 LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask); |
1824 // The current state is the same as the permitted required role(s). |
1824 // The current state is the same as the permitted required role(s). |
1825 return KErrNone; |
1825 return KErrNone; |
1826 } |
1826 } |
1827 |
1827 |
1828 if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode) |
1828 TBTLinkMode nextMode = EActiveMode; |
1829 { |
1829 // Determine which LPM we should be in (if any) |
1830 // The current low power mode should be exited. |
1830 if(modeChangeMask & KExplicitActiveMode) |
1831 return RequestActive(); |
1831 { |
1832 } |
1832 nextMode = EActiveMode; |
1833 |
1833 } |
1834 if(modeChangeMask != EActiveMode) |
1834 else if(modeChangeMask & EHoldMode) |
1835 { |
1835 { |
1836 if(currentModeMask != EActiveMode) |
1836 nextMode = EHoldMode; |
1837 { |
1837 } |
1838 // The system is currently in a low power mode. Exit this before |
1838 else if(modeChangeMask & ESniffMode) |
1839 // entering the new mode. |
1839 { |
1840 TInt rerr = RequestActive(); |
1840 nextMode = ESniffMode; |
1841 if(rerr != KErrNone) |
1841 } |
|
1842 else if(modeChangeMask & EParkMode) |
|
1843 { |
|
1844 nextMode = EParkMode; |
|
1845 } |
|
1846 LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, nextMode); |
|
1847 |
|
1848 if(nextMode != currentMode) |
|
1849 { |
|
1850 if(currentMode != EActiveMode) |
|
1851 { |
|
1852 LOG(_L8("Arbitration: Exiting existing LPM mode...")); |
|
1853 TInt err = RequestActive(); |
|
1854 if(err != KErrNone) |
1842 { |
1855 { |
1843 return rerr; |
1856 return err; |
1844 } |
1857 } |
1845 } |
1858 } |
1846 |
1859 if(nextMode == EHoldMode) |
1847 if(modeChangeMask & EHoldMode) |
1860 { |
1848 { |
1861 LOG(_L8("Arbitration: Entering Hold mode...")); |
1849 return RequestHold(); |
1862 return RequestHold(); |
1850 } |
1863 } |
1851 if(modeChangeMask & ESniffMode) |
1864 else if(nextMode == ESniffMode) |
1852 { |
1865 { |
|
1866 LOG(_L8("Arbitration: Entering Sniff mode...")); |
1853 return RequestSniff(); |
1867 return RequestSniff(); |
1854 } |
1868 } |
1855 if(modeChangeMask & EParkMode) |
1869 else if(nextMode == EParkMode) |
1856 { |
1870 { |
|
1871 LOG(_L8("Arbitration: Entering Park mode...")); |
1857 return RequestPark(); |
1872 return RequestPark(); |
1858 } |
1873 } |
1859 } |
1874 else if(nextMode == EActiveMode) |
1860 |
1875 { |
1861 // This point in the code is reached if the Link Policy settings are |
1876 LOG(_L8("Arbitration: Staying in Active mode...")); |
1862 // changed but the mode is not. Return OK error code. |
1877 return KErrNone; |
|
1878 } |
|
1879 // Shouldn't reach here, we have a strange mode |
|
1880 DEBUG_PANIC_LINENUM; |
|
1881 } |
|
1882 |
|
1883 LOG(_L8("Arbitration: Already in correct LPM, not doing anything")); |
1863 return KErrNone; |
1884 return KErrNone; |
1864 } |
1885 } |
1865 |
1886 |
1866 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey) |
1887 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey) |
1867 { |
1888 { |
1900 TUint16 pkt = KHCIDefaultPacketType; |
1921 TUint16 pkt = KHCIDefaultPacketType; |
1901 |
1922 |
1902 // optimise paging (as a best-effort attempt). |
1923 // optimise paging (as a best-effort attempt). |
1903 TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit); |
1924 TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit); |
1904 iLinksMan.TryToChangePageTimeout(pagetimeout); |
1925 iLinksMan.TryToChangePageTimeout(pagetimeout); |
|
1926 |
|
1927 // Set state in anticipation of the connection |
|
1928 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); |
|
1929 iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink); |
|
1930 iLinkState.SetLinkRole(EMaster); |
1905 |
1931 |
1906 TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch)); |
1932 TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch)); |
1907 if(ret==KErrNone) |
1933 if(ret != KErrNone) // a physical link is in charge of it's own destiny. |
1908 { |
1934 { |
1909 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); |
1935 TBTConnect conn; |
1910 iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink); |
1936 conn.iBdaddr = BDAddr(); |
1911 iLinkState.SetLinkRole(EMaster); |
1937 conn.iLinkType = EACLLink; |
1912 } |
1938 ConnectionComplete(ret, conn); |
1913 |
1939 } |
1914 return ret; |
|
1915 } |
1940 } |
1916 |
1941 |
1917 TInt CPhysicalLink::SCOConnect() |
1942 TInt CPhysicalLink::SCOConnect() |
1918 /** |
1943 /** |
1919 A utility service provided to the SCO transport |
1944 A utility service provided to the SCO transport |
3399 self->ConstructL(); |
3425 self->ConstructL(); |
3400 CleanupStack::Pop(self); |
3426 CleanupStack::Pop(self); |
3401 return self; |
3427 return self; |
3402 } |
3428 } |
3403 |
3429 |
3404 void CArbitrationDelayTimer::Start(TBool aLocalPriority) |
3430 TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority) |
3405 { |
3431 { |
3406 LOG_FUNC |
3432 LOG_FUNC |
3407 // Work out what the local priority will be now |
3433 // Work out what the local priority will be now |
3408 TBool localPriority = iLocalPriority || aLocalPriority; |
3434 iLocalPriority = iLocalPriority || aLocalPriority; |
3409 Cancel(); // cancel current timer (will also reset priority so ... |
3435 LOG1(_L8("Arbitraion: Local Priority now %d"), iLocalPriority); |
3410 iLocalPriority = localPriority; // set the new priority) |
3436 if(aImmediate) |
|
3437 { |
|
3438 LOG(_L8("Arbitraion: Immediate Arbitration Requested...")); |
|
3439 CancelButPreserveLocalPriority(); |
|
3440 return DoArbitrate(); |
|
3441 } |
|
3442 else if(!IsActive()) |
|
3443 { |
|
3444 LOG(_L8("Arbitraion: Arbitration requested, will execute after delay timer...")); |
|
3445 After(KBTArbitrationDelay); |
|
3446 } |
|
3447 else // timer is already on its way |
|
3448 { |
|
3449 LOG(_L8("Arbitraion: Arbitration delay timer still pending...")); |
|
3450 } |
|
3451 return KErrNone; |
|
3452 } |
|
3453 |
|
3454 void CArbitrationDelayTimer::Restart() |
|
3455 { |
|
3456 LOG_FUNC |
|
3457 LOG(_L8("Arbitraion: Arbitration timer restarted...")); |
|
3458 CancelButPreserveLocalPriority(); |
3411 After(KBTArbitrationDelay); |
3459 After(KBTArbitrationDelay); |
|
3460 } |
|
3461 |
|
3462 void CArbitrationDelayTimer::CancelButPreserveLocalPriority() |
|
3463 { |
|
3464 LOG_FUNC |
|
3465 TBool localPriority = iLocalPriority; |
|
3466 Cancel(); |
|
3467 iLocalPriority = localPriority; |
3412 } |
3468 } |
3413 |
3469 |
3414 |
3470 |
3415 void CArbitrationDelayTimer::RunL() |
3471 void CArbitrationDelayTimer::RunL() |
3416 /** |
3472 /** |
3417 Allow arbitration of low power modes when the timer expires |
3473 Allow arbitration of low power modes when the timer expires |
3418 **/ |
3474 **/ |
3419 { |
3475 { |
3420 LOG_FUNC |
3476 LOG_FUNC |
3421 if (iParent) |
3477 LOG(_L8("Arbitraion: Delayed Arbitration executing...")); |
3422 { |
3478 static_cast<void>(DoArbitrate()); // ignore the error (always has been...) |
3423 iParent->DoArbitrate(iLocalPriority); |
3479 } |
3424 } |
3480 |
|
3481 TInt CArbitrationDelayTimer::DoArbitrate() |
|
3482 { |
|
3483 LOG_FUNC |
|
3484 TBool localPriority = iLocalPriority; |
|
3485 iLocalPriority = EFalse; |
|
3486 return iParent->DoArbitrate(localPriority); |
3425 } |
3487 } |
3426 |
3488 |
3427 void CArbitrationDelayTimer::DoCancel() |
3489 void CArbitrationDelayTimer::DoCancel() |
3428 { |
3490 { |
3429 LOG_FUNC |
3491 LOG_FUNC |