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