--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacDot11State.cpp Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,4758 @@
+/*
+* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of the WlanDot11State class.
+*
+*/
+
+/*
+* %version: 85 %
+*/
+
+#include "config.h"
+#include "UmacDot11State.h"
+#include "UmacWsaAddKey.h"
+#include "UmacWsaKeyIndexMapper.h"
+#include "umacaddbroadcastwepkey.h"
+#include "UmacWsaWriteMib.h"
+#include "UmacWsaReadMib.h"
+#include "umacwhaconfigurequeue.h"
+#include "umacwhaconfigureac.h"
+#include "umacconfiguretxautoratepolicy.h"
+#include "UmacContextImpl.h"
+#include "wha_mibDefaultvalues.h"
+#include "FrameXferBlock.h"
+#include "umacelementlocator.h"
+
+struct TRate2NwsaRate
+ {
+ TRate iTrate;
+ WHA::TRate iNwsaRate;
+ };
+
+const TRate2NwsaRate KTRate2NwsaRateTable[] =
+ {
+ { E1Mbps, WHA::KRate1Mbits },
+ { E2Mbps, WHA::KRate2Mbits },
+ { E5_5Mbps, WHA::KRate5_5Mbits },
+ { E11Mbps, WHA::KRate11Mbits },
+ { E22Mbps, WHA::KRate22Mbits },
+ };
+
+class TRate2NwsaRatePredicate
+ {
+public:
+
+ explicit TRate2NwsaRatePredicate( const TRate aRate )
+ : iKey( aRate ) {};
+
+ TBool operator() ( const TRate2NwsaRate& aEntry ) const
+ {
+ return aEntry.iTrate == iKey;
+ }
+
+private:
+
+ // Prohibit copy constructor.
+ TRate2NwsaRatePredicate ( const TRate2NwsaRatePredicate & );
+ // Prohibit assigment operator.
+ TRate2NwsaRatePredicate& operator= ( const TRate2NwsaRatePredicate & );
+
+ const TRate iKey;
+ };
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::Scan(
+ WlanContextImpl& aCtxImpl,
+ TScanMode aMode,
+ const TSSID& aSSID,
+ TRate aScanRate,
+ SChannels& aChannels,
+ TUint32 aMinChannelTime,
+ TUint32 aMaxChannelTime,
+ TBool aSplitScan )
+ {
+
+ WHA::TRate rate( 0 );
+ ResolveScanRate( aCtxImpl, aScanRate, rate );
+
+ // call the "real scan"
+ return RealScan( aCtxImpl, aMode, aSSID, rate, aChannels,
+ aMinChannelTime, aMaxChannelTime, aSplitScan );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::StopScan( WlanContextImpl& aCtxImpl )
+ {
+ // as we are here it means that we have received a stop scan request
+ // even though there is no scan ongoing. This should only happen if the
+ // mgmt client has been in the process of making a stop scan request and
+ // hasn't noticed that the scan has already completed. Anyhow in this
+ // case we just complete the request
+ OnOidComplete( aCtxImpl, KErrNone );
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetPowerMode(
+ WlanContextImpl& aCtxImpl,
+ TPowerMode aPowerMode,
+ TBool aDisableDynamicPowerModeManagement,
+ TWlanWakeUpInterval aWakeupModeInLightPs,
+ TUint8 aListenIntervalInLightPs,
+ TWlanWakeUpInterval aWakeupModeInDeepPs,
+ TUint8 aListenIntervalInDeepPs )
+ {
+ OsTracePrint( KPwrStateTransition, (TUint8*)
+ ("UMAC: WlanDot11State::SetPowerMode: aPowerMode: %d"), aPowerMode );
+
+ TBool ret( EFalse );
+
+ // store desired new dot11 power management mode by WLAN Mgmt Client
+ aCtxImpl.ClientDot11PwrMgmtMode( aPowerMode );
+
+ aCtxImpl.DynamicPwrModeMgtDisabled( aDisableDynamicPowerModeManagement );
+ if ( aDisableDynamicPowerModeManagement )
+ {
+ aCtxImpl.StopPowerModeManagement();
+ }
+
+ aCtxImpl.SetClientLightPsModeConfig(
+ aWakeupModeInLightPs,
+ aListenIntervalInLightPs );
+
+ aCtxImpl.SetClientDeepPsModeConfig(
+ aWakeupModeInDeepPs,
+ aListenIntervalInDeepPs );
+
+ // in case WLAN Mgmt Client wishes to use PS mode, Light PS is the initial
+ // desired PS mode configuration
+ aCtxImpl.SetDesiredPsModeConfig(
+ aCtxImpl.ClientLightPsModeConfig() );
+
+ if ( aCtxImpl.CurrentDot11PwrMgmtMode() !=
+ aCtxImpl.ClientDot11PwrMgmtMode() )
+ {
+ // there is a difference in current dot11 power management mode and
+ // WLAN Mgmt Client's desired dot11 power management mode
+
+ // So, WLAN Mgmt Client's desired dot11 power management mode becomes
+ // our new desired mode
+ aCtxImpl.DesiredDot11PwrMgmtMode( aCtxImpl.ClientDot11PwrMgmtMode() );
+
+ // callee will complete the mgmt command
+ ret = OnDot11PwrMgmtTransitRequired( aCtxImpl );
+ }
+ else
+ {
+ // no dot11 power management mode transition required.
+
+ // See if there is difference in desired vs. current wake-up setting,
+ // which we only need to worry about if the requested pwr mgmt
+ // mode is PS
+ if ( aPowerMode == EPowerModePs &&
+ DifferenceInPsModeWakeupSettings( aCtxImpl ) )
+ {
+ // callee shall complete the request
+ ret = OnWlanWakeUpIntervalChange( aCtxImpl );
+ }
+ else
+ {
+ // no action required regarding the wake-up setting, either
+
+ // one possibility is that the following has happened: WLAN Mgmt
+ // client has requested us to use PS mode when possible, but we
+ // have dynamically changed to CAM mode because of data traffic.
+ // If that is the case and now the WLAN Mgmt client wants us
+ // to stay in CAM mode, make sure that the dynamic power mode
+ // management is deactivated
+ if ( aPowerMode == EPowerModeCam )
+ {
+ OsTracePrint( KPwrStateTransition, (TUint8*)
+ ("UMAC: WlanDot11State::SetPowerMode: CAM requested when we already are in CAM. Make sure that dynamic pwr mode mgmt is not active") );
+
+ aCtxImpl.StopPowerModeManagement();
+ }
+ else
+ {
+ if ( !aDisableDynamicPowerModeManagement )
+ {
+ // in case the only change is that now dynamic pwr
+ // mode mgmt is again allowed, make sure it is active
+ aCtxImpl.StartPowerModeManagement();
+ }
+ }
+ }
+
+ // complete the mgmt command
+ OnOidComplete( aCtxImpl );
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::EnableUserData(
+ WlanContextImpl& aCtxImpl )
+ {
+ TBool stateChange( EFalse );
+ aCtxImpl.iEnableUserData = ETrue;
+ OnOidComplete( aCtxImpl, KErrNone );
+ aCtxImpl.iUmac.UserDataReEnabled();
+
+ // signal global state transition event
+ return stateChange;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::DisableUserData(
+ WlanContextImpl& aCtxImpl )
+ {
+ aCtxImpl.iEnableUserData = EFalse;
+ OnOidComplete( aCtxImpl, KErrNone );
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnConfigureUmacMib(
+ WlanContextImpl& aCtxImpl,
+ TUint16 aRTSThreshold,
+ TUint32 aMaxTxMSDULifetime )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnConfigureUmacMib") );
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnConfigureUmacMib: RTSThreshold: %d"),
+ aRTSThreshold );
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnConfigureUmacMib: maxTxMSDULifetime: %d"),
+ aMaxTxMSDULifetime );
+
+ aCtxImpl.iWlanMib.dot11RTSThreshold = aRTSThreshold;
+
+ for ( TUint i = 0; i < WHA::EQueueIdMax; ++i )
+ {
+ aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[i] = aMaxTxMSDULifetime;
+ }
+
+ aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetimeDefault = aMaxTxMSDULifetime;
+
+ for ( TUint i = 0; i < WHA::EQueueIdMax; ++i )
+ {
+ aCtxImpl.iWlanMib.iMediumTime[i] = KDot11MediumTimeDefault;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::AddDefaultBroadcastWepKeyComplete(
+ WlanContextImpl& aCtxImpl ) const
+ {
+ OnOidComplete( aCtxImpl );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ResolveScanRate(
+ WlanContextImpl& /*aCtxImpl*/,
+ const TRate aRate,
+ WHA::TRate& aScanRate )
+ {
+ const TRate2NwsaRatePredicate unary_predicate( aRate );
+
+ const TRate2NwsaRate* const end
+ = KTRate2NwsaRateTable
+ + (sizeof(KTRate2NwsaRateTable) / sizeof(TRate2NwsaRate));
+ const TRate2NwsaRate* pos
+ = find_if( KTRate2NwsaRateTable, end, unary_predicate );
+
+ if ( pos == end )
+ {
+ // not found; an implementation error
+ OsAssert( (TUint8*)("UMAC: panic"),(TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ aScanRate = pos->iNwsaRate;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::NetworkCapabilityInformationMet(
+ WlanContextImpl& aCtxImpl)
+ {
+ if ( // do this if channel agility bit is not set
+ ( !aCtxImpl.GetCapabilityInformation().IsChannelAgilityBitSet() ))
+ {
+ // mimic the preamble bit from AP
+ // as some APs might not let us in if not matched
+ if ( aCtxImpl.GetCapabilityInformation().IsShortPreambleBitSet() )
+ {
+ (aCtxImpl.GetAssociationRequestFrame())
+ .SetCapabilityShortPreamble();
+ (aCtxImpl.GetHtAssociationRequestFrame())
+ .SetCapabilityShortPreamble();
+ (aCtxImpl.GetReassociationRequestFrame())
+ .SetCapabilityShortPreamble();
+ (aCtxImpl.GetHtReassociationRequestFrame())
+ .SetCapabilityShortPreamble();
+
+ aCtxImpl.UseShortPreamble( ETrue );
+ }
+ else
+ {
+ (aCtxImpl.GetAssociationRequestFrame())
+ .ClearCapabilityShortPreamble();
+ (aCtxImpl.GetHtAssociationRequestFrame())
+ .ClearCapabilityShortPreamble();
+ (aCtxImpl.GetReassociationRequestFrame())
+ .ClearCapabilityShortPreamble();
+ (aCtxImpl.GetHtReassociationRequestFrame())
+ .ClearCapabilityShortPreamble();
+
+ aCtxImpl.UseShortPreamble( EFalse );
+ }
+
+ // clear both CF fields as we don't support PCF
+ aCtxImpl.GetAssociationRequestFrame().ClearCFfields();
+ aCtxImpl.GetHtAssociationRequestFrame().ClearCFfields();
+ aCtxImpl.GetReassociationRequestFrame().ClearCFfields();
+ aCtxImpl.GetHtReassociationRequestFrame().ClearCFfields();
+
+ // clear also all the fields we don't understand
+ aCtxImpl.GetAssociationRequestFrame().ClearReservedFields();
+ aCtxImpl.GetHtAssociationRequestFrame().ClearReservedFields();
+ aCtxImpl.GetReassociationRequestFrame().ClearReservedFields();
+ aCtxImpl.GetHtReassociationRequestFrame().ClearReservedFields();
+
+ // we don't do PBCC
+ aCtxImpl.GetAssociationRequestFrame().ClearCapabilityPbcc();
+ aCtxImpl.GetHtAssociationRequestFrame().ClearCapabilityPbcc();
+ aCtxImpl.GetReassociationRequestFrame().ClearCapabilityPbcc();
+ aCtxImpl.GetHtReassociationRequestFrame().ClearCapabilityPbcc();
+
+ if ( aCtxImpl.EncryptionStatus() != EEncryptionDisabled )
+ {
+ // privacy desired
+ aCtxImpl.GetAssociationRequestFrame().SetWepBit();
+ aCtxImpl.GetHtAssociationRequestFrame().SetWepBit();
+ aCtxImpl.GetReassociationRequestFrame().SetWepBit();
+ aCtxImpl.GetHtReassociationRequestFrame().SetWepBit();
+ }
+ else
+ {
+ aCtxImpl.GetAssociationRequestFrame().ClearWepBit();
+ aCtxImpl.GetHtAssociationRequestFrame().ClearWepBit();
+ aCtxImpl.GetReassociationRequestFrame().ClearWepBit();
+ aCtxImpl.GetHtReassociationRequestFrame().ClearWepBit();
+ }
+ if ( aCtxImpl.RadioMeasurement() != EFalse )
+ {
+ // Radio measurements desired
+ OsTracePrint (KInfoLevel, (TUint8 *)("UMAC: Radio measurements enabled"));
+ aCtxImpl.GetAssociationRequestFrame().SetRMBit();
+ aCtxImpl.GetHtAssociationRequestFrame().SetRMBit();
+ aCtxImpl.GetReassociationRequestFrame().SetRMBit();
+ aCtxImpl.GetHtReassociationRequestFrame().SetRMBit();
+ }
+ else
+ {
+ OsTracePrint (KInfoLevel, (TUint8 *)("UMAC: Radio measurements disabled"));
+ aCtxImpl.GetAssociationRequestFrame().ClearRMBit();
+ aCtxImpl.GetHtAssociationRequestFrame().ClearRMBit();
+ aCtxImpl.GetReassociationRequestFrame().ClearRMBit();
+ aCtxImpl.GetHtReassociationRequestFrame().ClearRMBit();
+ }
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AreSupportedRatesMet(
+ WlanContextImpl& aCtxImpl,
+ TBool aCheckAlsoExtendedRates )
+ {
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::AreSupportedRatesMet") );
+
+ // make sure these critters are zeroed at the beginning
+
+ aCtxImpl.GetMinBasicRate() = 0;
+ aCtxImpl.GetMaxBasicRate() = 0;
+ aCtxImpl.ClearBasicRateSet();
+
+ // clear our existing supported rates IE
+ aCtxImpl.GetOurSupportedRatesIE().Clear();
+ // ... and our existing extended supported rates IE
+ aCtxImpl.GetOurExtendedSupportedRatesIE().Clear();
+
+ TUint32 tx_rates( 0 );
+ TUint8 nwRate( 0 );
+
+ // go through all supported rate elements in the supported rates IE
+ // ( max 8 ).
+ // Remenber that basic rates are also always part of supported rates
+ // when building supported rates bitmask
+ for ( TUint32 outer_idx = 0
+ // loop until element count in the IE is reached
+ ; ( outer_idx != aCtxImpl.GetApSupportedRatesIE().GetElementLength() )
+ // OR maximum length allowed for the IE is reached
+ // NOTE! The 802.11 standard specifies that the max length of the
+ // information part of this IE is eight rates (eight bytes).
+ // However at least some APs seem to put all their supported rates
+ // into this element. In order to be able to associate with those
+ // APs we have allocated enough space for all 802.11b/g rates in this
+ // IE and hence the following constant in the loop end condition
+ && outer_idx < KMaxNumberOfDot11bAndgRates
+ ; ++outer_idx )
+ {
+ nwRate = (aCtxImpl.GetApSupportedRatesIE())[outer_idx];
+
+ if ( !ProcessSingleSupportedRateElement( aCtxImpl, nwRate, tx_rates ) )
+ {
+ // unknown supported rates element encountered
+ if ( nwRate & KBasicRateMask )
+ {
+ // it is part of BSS Basic Rate Set
+ if ( aCtxImpl.BssMembershipFeatureSupported( nwRate ) )
+ {
+ // it is a WLAN feature which we support,
+ // so we can continue. No action required here
+ }
+ else
+ {
+ // we can't cope with it and shall abort
+
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: network has unsupported mandatory rate/feature -> abort") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: rate: 0x%02x"),
+ nwRate);
+
+ return EFalse;
+ }
+ }
+ else
+ {
+ // unknown element is not part of BSS Basic Rate Set
+ // we can cope with that
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: init network connect") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: network has unsupported supported rate -> continue") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: rate: 0x%02x"),
+ nwRate);
+ }
+ }
+ } // end outer for
+
+ if ( aCheckAlsoExtendedRates )
+ {
+ // go through all supported rate elements in the extended supported
+ // rates IE ( max 255 ).
+ // Remember that basic rates are also always part of supported rates
+ // when building supported rates bitmask
+ for ( TUint32 outer_idx = 0;
+ // loop until max element count in the IE is reached
+ ( outer_idx != aCtxImpl.GetApExtendedSupportedRatesIE().GetElementLength() )
+ // OR maximum length allowed for the IE is reached
+ && outer_idx < KMaxNumberOfExtendedRates;
+ ++outer_idx )
+ {
+ nwRate = (aCtxImpl.GetApExtendedSupportedRatesIE())[outer_idx];
+
+ if ( !ProcessSingleSupportedRateElement(
+ aCtxImpl,
+ nwRate,
+ tx_rates ) )
+ {
+ // unknown supported rates element encountered
+
+ if ( nwRate & KBasicRateMask )
+ {
+ // it is part of BSS Basic Rate Set
+
+ if ( aCtxImpl.BssMembershipFeatureSupported( nwRate ) )
+ {
+ // it is a WLAN feature which we support,
+ // so we can continue. No action required here
+ }
+ else
+ {
+ // we can't cope with it and shall abort
+
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: network has unsupported mandatory rate/feature -> abort") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: rate: 0x%02x"),
+ nwRate);
+
+ return EFalse;
+ }
+ }
+ else
+ {
+ // unknown element is not part of BSS Basic Rate Set
+ // we can cope with that
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: init network connect") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: network has unsupported supported rate -> continue") );
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AreSupportedRatesMet: rate: 0x%02x"),
+ nwRate);
+ }
+ }
+ } // for
+ } // if
+
+ if ( tx_rates )
+ {
+ // store common rates (between us & the nw) in our connection context
+ aCtxImpl.RateBitMask( tx_rates );
+
+ return ETrue;
+ }
+ else
+ {
+ // we ended up with an empty rate mask, i.e. the intersection
+ // of network's supported rates and our supported rates is empty.
+ // We are not able to join the network under these circumstances
+ return EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ProcessSingleSupportedRateElement(
+ WlanContextImpl& aCtxImpl,
+ const TUint8 aApRate,
+ TUint32& aRateBitmask )
+ {
+ OsTracePrint( KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::ProcessSingleSupportedRateElement: processing AP rate: 0x%02x"), aApRate);
+
+ // match 4 elements in our rates lookup table
+ const TUint num_of_elems =
+ sizeof(aCtxImpl.iSupportedRatesLookUpTable)
+ / sizeof(WlanContextImpl::SupportedRateLookUp);
+
+ for ( TUint32 inner_idx = 0;
+ inner_idx != ( num_of_elems + 1 );
+ ++inner_idx )
+ {
+ if ( inner_idx == num_of_elems)
+ {
+ // if this block is reached it means that we have encountered
+ // a supported rates element that is not in our lookup table
+ OsTracePrint( KWarningLevel | KUmacDetails , (TUint8*)
+ ("UMAC: unknown AP rate element found: 0x%02x"), aApRate);
+
+ return EFalse;
+ }
+ if ( ( aApRate & (~KBasicRateMask) ) ==
+ ( aCtxImpl.iSupportedRatesLookUpTable[inner_idx].iSupportedRate &
+ ( ~KBasicRateMask ) ) )
+ {
+ // make a rate for the tx rate adaptation object
+ aRateBitmask |=
+ (aCtxImpl.iSupportedRatesLookUpTable[inner_idx].iWsaRate);
+
+ // check if this critter is part of a mandatory rate set
+ if ( aApRate & KBasicRateMask )
+ {
+ OsTracePrint( KUmacDetails,
+ (TUint8*)("UMAC: rate is part of Basic Rate Set") );
+
+ // yes it is
+ // construct basic rate set mask for Join NWSA command
+ aCtxImpl.BasicRateSetBitSet(
+ aCtxImpl.iSupportedRatesLookUpTable[inner_idx].iWsaRate );
+
+ // store min basic rate
+ if ( aCtxImpl.GetMinBasicRate() == 0 )
+ {
+ aCtxImpl.GetMinBasicRate() =
+ (aCtxImpl.iSupportedRatesLookUpTable[inner_idx]).iWsaRate;
+ }
+ // and store max basic rate
+ if ( aCtxImpl.GetMaxBasicRate() <
+ (aCtxImpl.iSupportedRatesLookUpTable[inner_idx]).iWsaRate )
+ {
+ aCtxImpl.GetMaxBasicRate()
+ = (aCtxImpl.iSupportedRatesLookUpTable[inner_idx])
+ .iWsaRate;
+ }
+ }
+
+ // set this rate to our supported rates IE
+ // which we will send in assoc-request frame. If there's no space any
+ // more in supported rates IE use the extended supported rates IE
+ //
+ if (aCtxImpl.GetOurSupportedRatesIE().GetElementLength() < KMaxNumberOfRates )
+ {
+ aCtxImpl.GetOurSupportedRatesIE().Append( aApRate );
+ }
+ else
+ {
+ aCtxImpl.GetOurExtendedSupportedRatesIE().Append( aApRate );
+ }
+
+ // break out of for loop,
+ // we got a match no need to traverse any longer
+ break;
+ }
+ } // end for
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetArpIpAddressTableMib(
+ WlanContextImpl& aCtxImpl,
+ TBool aEnableFiltering,
+ TIpv4Address aIpv4Address )
+ {
+ const TUint32 KMibLength( sizeof( WHA::SarpIpAddressTable ) );
+
+ OsTracePrint( KWlmCmdDetails, (TUint8*)
+ ("UMAC: WlanDot11State::SetArpIpAddressTableMib: mibLength: %d"),
+ KMibLength );
+
+ // allocate memory for the mib to write
+ WHA::SarpIpAddressTable* mib
+ = static_cast<WHA::SarpIpAddressTable*>
+ (os_alloc( KMibLength ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::SetArpIpAddressTableMib: memory allocating failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ if ( aEnableFiltering )
+ {
+ mib->iEnable = ETrue;
+ mib->iIpV4Addr = aIpv4Address;
+
+ OsTracePrint( KWlmCmdDetails, (TUint8*)
+ ("UMAC: WlanDot11State::SetArpIpAddressTableMib: enable filtering using address: 0x%08x"),
+ aIpv4Address );
+ }
+ else
+ {
+ mib->iEnable = EFalse;
+ mib->iIpV4Addr = aIpv4Address; // value not relevant in this case
+
+ OsTracePrint( KWlmCmdDetails, (TUint8*)
+ ("UMAC: WlanDot11State::SetArpIpAddressTableMib: disable filtering") );
+ }
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+
+ wha_cmd.Set(
+ aCtxImpl,
+ WHA::KMibArpIpAddressTable,
+ KMibLength,
+ mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( mib ); // release the allocated memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::OnDot11PwrMgmtTransitRequired(
+ WlanContextImpl& aCtxImpl )
+ {
+ // the specified power state will be taken into use later
+ // So nothing more to do at this point than completing the oid
+ OnOidComplete( aCtxImpl );
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::TQueueId WlanDot11State::QueueId(
+ const WlanContextImpl& aCtxImpl,
+ const TUint8* aDot11MacHeader ) const
+ {
+ // this initial value is always returned if we have a non-QoS connection
+ WHA::TQueueId queue_id( WHA::ELegacy );
+
+ if ( aCtxImpl.QosEnabled() )
+ {
+ // a QOS connection
+ SQosDataMpduHeader* dot11_hdr
+ = reinterpret_cast<SQosDataMpduHeader*>(
+ const_cast<TUint8*>(aDot11MacHeader));
+
+ // determine frame type
+ const TUint8 KFrameType( dot11_hdr->iHdr.iHdr.GetFrameControl().iType );
+
+ if ( KFrameType == E802Dot11FrameTypeQosData )
+ {
+ // this is a QoS data frame so assign it to
+ // the correct queue according to the priority
+
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::QueueId: 802.1d priority: %d"),
+ dot11_hdr->iHdr.UserPriority() );
+
+ queue_id = Queue( dot11_hdr->iHdr.UserPriority() );
+ }
+ else
+ {
+ // a non data type frame is put to voice queue
+ queue_id = WHA::EVoice;
+ }
+ }
+
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::QueueId: use queue: %d"),
+ queue_id );
+
+ return queue_id;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::TxDeauthenticate(
+ WlanContextImpl& aCtxImpl,
+ T802Dot11ManagementReasonCode aReason,
+ TBool aWaitIfIntTxBufNotFree ) const
+ {
+ OsTracePrint( KUmacProtocolState | KUmacAuth,
+ (TUint8*)("UMAC: WlanDot11State::TxDeauthenticate") );
+
+ TBool status ( EFalse );
+
+ // client doesn't have to take care of the tx buffer header space
+ // as the method below does that by itself
+ TUint8* start_of_frame = aCtxImpl.TxBuffer( aWaitIfIntTxBufNotFree );
+
+ if ( start_of_frame )
+ {
+ TUint32 frameLength ( 0 );
+
+ // construct deauthenticate frame
+ // note that we don't have to set SA because we have already set it
+ // in the initialize phase of the state machine
+
+ if ( aCtxImpl.HtSupportedByNw() )
+ {
+ // set the BSSID
+ (aCtxImpl.GetHtDeauthenticateFrame()).iHeader.iBSSID = aCtxImpl.GetBssId();
+ // set the DA
+ (aCtxImpl.GetHtDeauthenticateFrame()).iHeader.iDA = aCtxImpl.GetBssId();
+ // set the reason code
+ (aCtxImpl.GetHtDeauthenticateFrame()).iReasonCode.SetReasonCode(
+ aReason );
+
+ frameLength = sizeof( SHtDeauthenticateFrame );
+
+ // copy deauthentication frame to tx-buffer to correct offset
+ os_memcpy(
+ start_of_frame,
+ &(aCtxImpl.GetHtDeauthenticateFrame()),
+ frameLength );
+ }
+ else
+ {
+ // set the BSSID
+ (aCtxImpl.GetDeauthenticateFrame()).iHeader.iBSSID = aCtxImpl.GetBssId();
+ // set the DA
+ (aCtxImpl.GetDeauthenticateFrame()).iHeader.iDA = aCtxImpl.GetBssId();
+ // set the reason code
+ (aCtxImpl.GetDeauthenticateFrame()).iReasonCode.SetReasonCode(
+ aReason );
+
+ frameLength = sizeof( SDeauthenticateFrame );
+
+ // copy deauthentication frame to tx-buffer to correct offset
+ os_memcpy(
+ start_of_frame,
+ &(aCtxImpl.GetDeauthenticateFrame()),
+ frameLength );
+ }
+
+ const WHA::TQueueId queue_id( QueueId( aCtxImpl, start_of_frame ) );
+
+ // send deauthentication frame by pushing it to the packet scheduler
+ status = aCtxImpl.PushPacketToPacketScheduler(
+ start_of_frame,
+ frameLength,
+ queue_id,
+ E802Dot11FrameTypeDeauthentication,
+ NULL,
+ EFalse,
+ EFalse,
+ ETrue );
+ }
+ else
+ {
+ // we didn't get a Tx buffer => frame not sent. EFalse will be returned
+ // to indicate that
+
+ OsTracePrint( KUmacProtocolState | KUmacAuth, (TUint8*)
+ ("UMAC: no free internal tx buf => frame not sent") );
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::TxDisassociate(
+ WlanContextImpl& aCtxImpl,
+ T802Dot11ManagementReasonCode aReason,
+ TBool aWaitIfIntTxBufNotFree ) const
+ {
+ OsTracePrint( KUmacProtocolState | KUmacAssoc,
+ (TUint8*)("UMAC: WlanDot11State::TxDisassociate") );
+
+ TBool status ( EFalse );
+
+ // client doesn't have to take care of the tx buffer header space
+ // as the method below does that by itself
+ TUint8* start_of_frame = aCtxImpl.TxBuffer( aWaitIfIntTxBufNotFree );
+
+ if ( start_of_frame )
+ {
+ TUint32 frameLength ( 0 );
+
+ // NOTE: We don't set the address fields to frame here like
+ // in the case of dot11-deauthenticate frame, because in the case of
+ // roaming we would use that BSS's information where we are roaming
+ // to - instead of the existing one
+
+ if ( aCtxImpl.HtSupportedByNw() )
+ {
+ (aCtxImpl.GetHtDisassociationFrame()).iReasonCode.SetReasonCode(
+ aReason );
+
+ frameLength = sizeof( SHtDisassociateFrame );
+
+ // copy disassociation frame to tx-buffer to correct offset
+ os_memcpy(
+ start_of_frame,
+ &(aCtxImpl.GetHtDisassociationFrame()),
+ frameLength );
+ }
+ else
+ {
+ (aCtxImpl.GetDisassociationFrame()).iReasonCode.SetReasonCode(
+ aReason );
+
+ frameLength = sizeof( SDisassociateFrame );
+
+ // copy disassociation frame to tx-buffer to correct offset
+ os_memcpy(
+ start_of_frame,
+ &(aCtxImpl.GetDisassociationFrame()),
+ frameLength );
+ }
+
+ const WHA::TQueueId queue_id
+ = QueueId( aCtxImpl, start_of_frame );
+
+ // send disassociation frame to the current AP by pushing it to the packet
+ // scheduler
+ status = aCtxImpl.PushPacketToPacketScheduler(
+ start_of_frame,
+ frameLength,
+ queue_id,
+ E802Dot11FrameTypeDisassociation,
+ NULL,
+ EFalse,
+ EFalse,
+ ETrue );
+ }
+ else
+ {
+ // we didn't get a Tx buffer => frame not sent. EFalse will be returned
+ // to indicate that
+
+ OsTracePrint( KUmacProtocolState | KUmacAuth, (TUint8*)
+ ("UMAC: no free internal tx buf => frame not sent") );
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::SAesPairwiseKey* WlanDot11State::CreateAesPtkCtx(
+ WlanContextImpl& aCtxImpl,
+ WlanWsaAddKey& aWhaAddKey,
+ const TUint8* aData,
+ const TMacAddress& aMacAddr )
+ {
+ // store info of AES PTK insertion
+ aCtxImpl.PairWiseKeyType( WHA::EAesPairWiseKey );
+
+ // allocate memory for the key structure
+ WHA::SAesPairwiseKey* key = static_cast<WHA::SAesPairwiseKey*>
+ ( os_alloc( sizeof( WHA::SAesPairwiseKey ) ) );
+
+ if ( key )
+ {
+ os_memcpy(
+ key->iMacAddr.iMacAddress,
+ aMacAddr.iMacAddress,
+ WHA::TMacAddress::KMacAddressLength );
+ os_memcpy( key->iAesKey, aData, WHA::KAesKeyLength );
+
+ aWhaAddKey.Set(
+ aCtxImpl,
+ WHA::EAesPairWiseKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EAesPairWiseKey ) );
+ }
+ else
+ {
+ // left intentionally empty
+ }
+
+ return key;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::STkipPairwiseKey* WlanDot11State::CreateTkipPtkCtx(
+ WlanContextImpl& aCtxImpl,
+ WlanWsaAddKey& aWhaAddKey,
+ const TUint8* aData,
+ T802Dot11WepKeyId aKeyIndex,
+ const TMacAddress& aMacAddr )
+ {
+ // store info of TKIP PTK insertion
+ aCtxImpl.PairWiseKeyType( WHA::ETkipPairWiseKey );
+
+ // allocate memory for the key structure
+ // the caller of this method will deallocate the memory
+ WHA::STkipPairwiseKey* key = static_cast<WHA::STkipPairwiseKey*>
+ (os_alloc( sizeof( WHA::STkipPairwiseKey ) ));
+
+ if ( key )
+ {
+ os_memcpy(
+ key->iMacAddr.iMacAddress,
+ aMacAddr.iMacAddress,
+ WHA::TMacAddress::KMacAddressLength );
+ os_memcpy( key->iTkipKey, aData, WHA::KTKIPKeyLength );
+ os_memcpy(
+ key->iRxMicKey,
+ aData + WHA::KTKIPKeyLength,
+ WHA::KMicLength );
+ os_memcpy(
+ key->iTxMicKey,
+ aData + WHA::KTKIPKeyLength + WHA::KMicLength,
+ WHA::KMicLength);
+ key->iKeyId = static_cast<WHA::TPrivacyKeyId>(aKeyIndex);
+
+ aWhaAddKey.Set( aCtxImpl,
+ WHA::ETkipPairWiseKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::ETkipPairWiseKey ) );
+ }
+ else
+ {
+ // left intentionally empty
+ }
+
+ return key;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::SWepPairwiseKey* WlanDot11State::CreateUnicastWepKeyCtx(
+ WlanContextImpl& aCtxImpl,
+ WlanWsaAddKey& aWhaAddKey,
+ const TMacAddress& aMacAddr,
+ TUint32 aKeyLength,
+ const TUint8* aKey )
+ {
+ // store info of WEP PTK insertion
+ aCtxImpl.PairWiseKeyType( WHA::EWepPairWiseKey );
+
+ // allocate memory for the key structure
+ WHA::SWepPairwiseKey* key = static_cast<WHA::SWepPairwiseKey*>
+ (os_alloc( WHA::SWepPairwiseKey::KHeaderSize + aKeyLength ));
+
+ if ( key )
+ {
+ os_memcpy(
+ &(key->iMacAddr),
+ aMacAddr.iMacAddress,
+ sizeof(key->iMacAddr) );
+ key->iKeyLengthInBytes = static_cast<TUint8>(aKeyLength);
+ os_memcpy( key->iKey, aKey, key->iKeyLengthInBytes );
+
+ aWhaAddKey.Set( aCtxImpl,
+ WHA::EWepPairWiseKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EWepPairWiseKey ) );
+ }
+ else
+ {
+ // intentionally left empty
+ }
+
+ return key;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::SWapiPairwiseKey* WlanDot11State::CreateWapiPtkCtx(
+ WlanContextImpl& aCtxImpl,
+ WlanWsaAddKey& aWhaAddKey,
+ const TUint8* aData,
+ T802Dot11WepKeyId aKeyIndex,
+ const TMacAddress& aMacAddr )
+ {
+ // store info of WAPI pairwise key insertion
+ aCtxImpl.PairWiseKeyType( WHA::EWapiPairWiseKey );
+
+ // allocate memory for the key structure
+ // the caller of this method will deallocate the memory
+ WHA::SWapiPairwiseKey* key = static_cast<WHA::SWapiPairwiseKey*>
+ (os_alloc( sizeof( WHA::SWapiPairwiseKey ) ));
+
+ if ( key )
+ {
+ os_memcpy(
+ key->iMacAddr.iMacAddress,
+ aMacAddr.iMacAddress,
+ WHA::TMacAddress::KMacAddressLength );
+
+ key->iKeyId = static_cast<WHA::TPrivacyKeyId>(aKeyIndex);
+
+ os_memcpy( key->iWapiKey, aData, WHA::KWapiKeyLength );
+
+ os_memcpy(
+ key->iMicKey,
+ aData + WHA::KWapiKeyLength,
+ WHA::KWapiMicKeyLength );
+
+ aWhaAddKey.Set( aCtxImpl,
+ WHA::EWapiPairWiseKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EWapiPairWiseKey ) );
+ }
+ else
+ {
+ // left intentionally empty
+ }
+
+ return key;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::TRate WlanDot11State::InitialSpecialFrameTxRate(
+ const WlanContextImpl& aCtxImpl ) const
+ {
+ WHA::TRate rateToUse ( WHA::KRate1Mbits );
+
+ const TUint32 basicRateSet = aCtxImpl.BasicRateSet();
+
+ if ( basicRateSet )
+ {
+ // there is at least one supported basic rate (which is the way things
+ // are supposed to be if the network is correctly configured)
+
+ if ( basicRateSet & WHA::KRate1Mbits )
+ {
+ rateToUse = WHA::KRate1Mbits;
+ }
+ else if ( basicRateSet & WHA::KRate6Mbits )
+ {
+ rateToUse = WHA::KRate6Mbits;
+ }
+ else if ( basicRateSet & WHA::KRate2Mbits )
+ {
+ rateToUse = WHA::KRate2Mbits;
+ }
+ else if ( basicRateSet & WHA::KRate9Mbits )
+ {
+ rateToUse = WHA::KRate9Mbits;
+ }
+ else
+ {
+ // none of the rates above is a supported basic rate, which is
+ // rather odd.
+ // Anyhow, figure out the lowest supported basic rate and use that
+
+ WHA::TRate rateCandidate = WHA::KRate1Mbits;
+
+ do
+ {
+ if ( basicRateSet & rateCandidate )
+ {
+ rateToUse = rateCandidate;
+ // break the loop as we found what we are looking for
+ break;
+ }
+ else
+ {
+ rateCandidate <<= 1;
+ }
+
+ } while ( rateCandidate <= WHA::KRate54Mbits );
+ }
+ }
+ else
+ {
+ // there are no supported basic rates; which is actually a network
+ // configuration error.
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::InitialSpecialFrameTxRate: Warning: no basic rates configured in nw"));
+
+ // But as we don't absolutely have to find a
+ // basic rate here, just stay with 1Mbps (set above)
+ }
+
+ OsTracePrint( KWsaTxDetails,
+ (TUint8*)("UMAC: WlanDot11State::InitialSpecialFrameTxRate: use rate: 0x%08x"),
+ rateToUse );
+
+ return rateToUse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::DoErrorIndication(
+ WlanContextImpl& aCtxImpl,
+ WHA::TStatus /*aStatus*/ )
+ {
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC * handle an error indication!") );
+
+ // this is the one and only global error handler
+ ChangeState( aCtxImpl, *this, aCtxImpl.iStates.iMacError );
+
+ // signal with return value that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::DoConsecutiveBeaconsLostIndication(
+ WlanContextImpl& /*aCtxImpl*/ )
+ {
+ // not supported in default handler
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::DoRegainedBSSIndication(
+ WlanContextImpl& /*aCtxImpl*/ )
+ {
+ // not supported in default handler
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::DoRadarIndication(
+ WlanContextImpl& /*aCtxImpl*/ )
+ {
+ // not supported in default handler
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::DoRcpiIndication(
+ WlanContextImpl& /*aCtxImpl*/,
+ WHA::TRcpi /*aRcpi*/ )
+ {
+ // not supported in default handler
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanDot11State::DoPsModeErrorIndication(
+ WlanContextImpl& /*aCtxImpl*/ )
+ {
+ // not supported in default handler
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::TxData(
+ WlanContextImpl& aCtxImpl,
+ TDataBuffer& aDataBuffer,
+ TBool /*aMore*/ )
+ {
+ OsTracePrint( KErrorLevel, (TUint8*)
+ ("UMAC: Tx attempted when it's not allowed; frame ignored") );
+
+ aCtxImpl.iUmac.OnTxProtocolStackDataComplete(
+ KErrNone,
+ &aDataBuffer );
+
+ // no state change occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::TxMgmtData(
+ WlanContextImpl& aCtxImpl,
+ TDataBuffer& /*aDataBuffer*/ )
+ {
+ // as we are not connected to network, this frame cannot be sent.
+ // Just complete the frame send request without error status; as
+ // the WLAN Mgmt Client doesn't care about the status
+ OnMgmtPathWriteComplete( aCtxImpl );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TAny* WlanDot11State::RequestForBuffer(
+ WlanContextImpl& /*aCtxImpl*/,
+ TUint16 /*aLength*/ )
+ {
+ // no functionality in default handler
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ReceivePacket(
+ WlanContextImpl& aCtxImpl,
+ WHA::TStatus /*aStatus*/,
+ const void* /*aFrame*/,
+ TUint16 /*aLength*/,
+ WHA::TRate /*aRate*/,
+ WHA::TRcpi /*aRcpi*/,
+ WHA::TChannelNumber /*aChannel*/,
+ TUint8* aBuffer,
+ TUint32 /*aFlags*/ )
+ {
+ // release the Rx buffer
+ aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnWhaCommandResponse(
+ WlanContextImpl& aCtxImpl,
+ WHA::TCommandId aCommandId,
+ WHA::TStatus /*aStatus*/,
+ const WHA::UCommandResponseParams& aCommandResponseParams,
+ TUint32 aAct )
+ {
+ // this command response method is supposed to be called
+ // when a concrete dot11 state object does not care about
+ // the command response parameters
+
+ if ( aAct == KCompleteManagementRequest )
+ {
+ // this must be a response to a command that was generated
+ // by this this dot11 state object default layer
+ if ( aCommandId != WHA::EReadMIBResponse )
+ {
+ OnOidComplete( aCtxImpl );
+ }
+ else
+ {
+ // as this is a MIB read request, we must supply the
+ // response to the Mgmt Client
+ if ( aCommandResponseParams.iReadMibResponse.iMib
+ == WHA::KMibStatisticsTable )
+ {
+ // convert to a 32bit value before forwarding
+ TInt32 rcpi = reinterpret_cast
+ <const WHA::SstatisticsTable*>
+ (aCommandResponseParams.iReadMibResponse.iData)->iRcpi;
+
+ OsTracePrint(
+ KUmacDetails,
+ (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse(): last rcpi: %d"),
+ rcpi );
+
+ OnOidComplete( aCtxImpl,
+ KErrNone,
+ reinterpret_cast<const TAny*>(&rcpi),
+ sizeof(rcpi) );
+ }
+ else if ( aCommandResponseParams.iReadMibResponse.iMib
+ == WHA::KMibCountersTable )
+ {
+ const WHA::ScountersTable* countersTable = reinterpret_cast
+ <const WHA::ScountersTable*>
+ (aCommandResponseParams.iReadMibResponse.iData);
+
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: countersTableMib: nbr of FCS errors in received MPDUs: %d"),
+ countersTable->iFcsError );
+
+ aCtxImpl.StoreFcsErrorCount( countersTable->iFcsError );
+
+ // as we are about to report the frame statistics results,
+ // it's the time to perform also the necessary calculations
+
+ aCtxImpl.CalculateAverageTxMediaDelays();
+ aCtxImpl.CalculateAverageTotalTxDelays();
+
+ const TStatisticsResponse& frameStatistics ( aCtxImpl.FrameStatistics() );
+
+#ifndef NDEBUG
+ // trace frame statistics
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: *** reported frame statistics ***:") );
+
+ for ( TUint i = 0; i < EQueueIdMax; ++i )
+ {
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: * Access Category: %d *"),
+ i );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: successfully received unicast data frames: %d"),
+ frameStatistics.acSpecific[i].rxUnicastDataFrameCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: successfully transmitted unicast data frames: %d"),
+ frameStatistics.acSpecific[i].txUnicastDataFrameCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: successfully received multicast data frames: %d"),
+ frameStatistics.acSpecific[i].rxMulticastDataFrameCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: successfully transmitted multicast data frames: %d"),
+ frameStatistics.acSpecific[i].txMulticastDataFrameCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: nbr of data frame transmit retries: %d"),
+ frameStatistics.acSpecific[i].txRetryCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: nbr of data frame WLAN delivery failures: %d"),
+ frameStatistics.acSpecific[i].txErrorCount );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: average data frame Tx media delay in microsecs: %d"),
+ frameStatistics.acSpecific[i].txMediaDelay );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: average data frame total Tx delay in microsecs: %d"),
+ frameStatistics.acSpecific[i].totalTxDelay );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: data frame total Tx delay bin 0 count: %d"),
+ frameStatistics.acSpecific[i].totalTxDelayBin0 );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: data frame total Tx delay bin 1 count: %d"),
+ frameStatistics.acSpecific[i].totalTxDelayBin1 );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: data frame total Tx delay bin 2 count: %d"),
+ frameStatistics.acSpecific[i].totalTxDelayBin2 );
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: data frame total Tx delay bin 3 count: %d"),
+ frameStatistics.acSpecific[i].totalTxDelayBin3 );
+ }
+
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::OnWhaCommandResponse: all ACs: nbr of FCS errors in received MPDUs: %d"),
+ frameStatistics.fcsErrorCount );
+
+#endif
+
+ OnOidComplete( aCtxImpl,
+ KErrNone,
+ reinterpret_cast<const TAny*>(&frameStatistics),
+ sizeof( frameStatistics ) );
+
+ // the statistics are cleared after reporting them. It is safe
+ // to do it here as the information has already been copied
+ aCtxImpl.ResetFrameStatistics();
+ }
+ // -- == WHA::KMibStatisticsTable --
+ else
+ {
+ // this thing should never happen as we are not reading any
+ // other MIBs; an implementation error
+ OsAssert( (TUint8*)("UMAC: panic"),(TUint8*)(WLAN_FILE), __LINE__ );
+ // well exclusion to this is the dot11stationId MIB that
+ // is read by dot11initphase object, but it overrides this
+ // method so this code is not executed in that case.
+ }
+ }
+ }
+ // -- aAct == KCompleteManagementRequest --
+ else
+ {
+ // this is not a response to a command that was generated by this
+ // dot11 state object.
+ // which means that the originator of this command does not care
+ // about the response parameters.
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::OnWlanWakeUpIntervalChange(
+ WlanContextImpl& aCtxImpl )
+ {
+ OnOidComplete( aCtxImpl );
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+WHA::TQueueId WlanDot11State::Queue( TUint8 aPriority )
+ {
+ // Mapping of 802.1d priorities to WMM Access Categories, and hence to
+ // WHA queue (id)s, as specified in WiFi WMM Specification v1.1
+ const WHA::TQueueId K802Dot1dPriority2WhaQueueTable[] =
+ { WHA::ELegacy, // for priority 0
+ WHA::EBackGround, // for priority 1
+ WHA::EBackGround, // for priority 2
+ WHA::ELegacy, // for priority 3
+ WHA::EVideo, // for priority 4
+ WHA::EVideo, // for priority 5
+ WHA::EVoice, // for priority 6
+ WHA::EVoice }; // for priority 7
+
+ return ( aPriority > 7 ) ?
+ WHA::ELegacy :
+ K802Dot1dPriority2WhaQueueTable[aPriority];
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::UapsdEnabledInNetwork( const SRxWmmIeData& aRxWmmIE )
+ {
+ return ( aRxWmmIE.IsUapsdBitSet() );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::UapsdEnabledInNetwork( const SWmmParamElemData& aWmmParamElem )
+ {
+ return ( aWmmParamElem.IsUapsdBitSet() );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::EnableQos( WlanContextImpl& aCtxImpl,
+ TBool aUapsdEnabledInNw )
+ {
+ // enable QoS
+ aCtxImpl.QosEnabled( ETrue );
+
+ // first clear our WMM IE so that U-APSD flags will be set only when
+ // they are supposed to be set
+ aCtxImpl.OurWmmIe().Clear();
+
+ if ( aUapsdEnabledInNw )
+ {
+ OsTracePrint(
+ KQos, (TUint8*)
+ ("UMAC: WlanDot11State::EnableQos(): u-apsd is supported by nw"));
+
+ // make a note that U-APSD is supported/enabled in the nw
+ aCtxImpl.UapsdEnabled( ETrue );
+
+ // make a WMM AC both trigger & delivery enabled
+ // if U-APSD is supported by the nw (this we already know to be true)
+ // and
+ // if U-APSD usage has been requested by WLAN mgmt client for the AC
+ // in question
+ aCtxImpl.OurWmmIe().SetUapsdFlags( static_cast<TQosInfoUapsdFlag>(
+ ( aCtxImpl.UapsdRequestedForVoice() ? EAcVoUapsdFlag : 0 ) |
+ ( aCtxImpl.UapsdRequestedForVideo() ? EAcViUapsdFlag : 0 ) |
+ ( aCtxImpl.UapsdRequestedForBackground() ? EAcBkUapsdFlag : 0 ) |
+ ( aCtxImpl.UapsdRequestedForBestEffort() ? EAcBeUapsdFlag : 0 )) );
+
+ // set max service period length for the ACs as requested by WLAN
+ // mgmt client
+ aCtxImpl.OurWmmIe().SetMaxSpLen( aCtxImpl.UapsdMaxSpLen() );
+ }
+ else
+ {
+ OsTracePrint(
+ KQos, (TUint8*)
+ ("UMAC: WlanDot11State::EnableQos(): u-apsd not supported in nw"));
+
+ aCtxImpl.UapsdEnabled( EFalse );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::DetermineAcUapsdUsage( WlanContextImpl& aCtxImpl )
+ {
+ if ( aCtxImpl.UapsdEnabled() )
+ {
+ if ( aCtxImpl.UapsdRequestedForVoice() )
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd used for Voice"));
+ aCtxImpl.UapsdUsedForVoice( ETrue );
+ }
+ else
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd NOT used for Voice"));
+ aCtxImpl.UapsdUsedForVoice( EFalse );
+ }
+
+ if ( aCtxImpl.UapsdRequestedForVideo() )
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd used for Video"));
+ aCtxImpl.UapsdUsedForVideo( ETrue );
+ }
+ else
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd NOT used for Video"));
+ aCtxImpl.UapsdUsedForVideo( EFalse );
+ }
+
+ if ( aCtxImpl.UapsdRequestedForBestEffort() )
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd used for Best Effort"));
+ aCtxImpl.UapsdUsedForBestEffort( ETrue );
+ }
+ else
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd NOT used for Best Effort"));
+ aCtxImpl.UapsdUsedForBestEffort( EFalse );
+ }
+
+ if ( aCtxImpl.UapsdRequestedForBackground() )
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd used for Background"));
+ aCtxImpl.UapsdUsedForBackground( ETrue );
+ }
+ else
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd NOT used for Background"));
+ aCtxImpl.UapsdUsedForBackground( EFalse );
+ }
+ }
+ else
+ {
+ OsTracePrint( KQos, (TUint8*)
+ ("UMAC: WlanDot11State::DetermineAcUapsdUsage: u-apsd NOT used for any AC"));
+ aCtxImpl.UapsdUsedForVoice( EFalse );
+ aCtxImpl.UapsdUsedForVideo( EFalse );
+ aCtxImpl.UapsdUsedForBestEffort( EFalse );
+ aCtxImpl.UapsdUsedForBackground( EFalse );
+ }
+
+ // now when U-APSD usage per AC has been determined, freeze the dynamic
+ // power mode mgmt traffic override/ignoration settings
+ aCtxImpl.FreezePwrModeMgmtTrafficOverride();
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ResetAcParameters(
+ WlanContextImpl& aCtxImpl,
+ WHA::TQueueId aAccessCategory,
+ TBool aUseAandGvalues )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ResetAcParameters: Reset parameters of AC: %d"),
+ aAccessCategory );
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ResetAcParameters: aUseAandGvalues: %d"),
+ aUseAandGvalues );
+
+ switch ( aAccessCategory )
+ {
+ case WHA::ELegacy:
+ aCtxImpl.CwMinVector()[WHA::ELegacy] =
+ aUseAandGvalues ? KDot11BeCwMinAandG : KDot11BeCwMinB;
+ aCtxImpl.CwMaxVector()[WHA::ELegacy] = KDot11BeCwMax;
+ aCtxImpl.AifsVector()[WHA::ELegacy] = KDot11BeAifsn;
+ aCtxImpl.TxOplimitVector()[WHA::ELegacy] = KDot11BeTxopLimit;
+ break;
+ case WHA::EBackGround:
+ aCtxImpl.CwMinVector()[WHA::EBackGround] =
+ aUseAandGvalues ? KDot11BgCwMinAandG : KDot11BgCwMinB;
+ aCtxImpl.CwMaxVector()[WHA::EBackGround] = KDot11BgCwMax;
+ aCtxImpl.AifsVector()[WHA::EBackGround] = KDot11BgAifsn;
+ aCtxImpl.TxOplimitVector()[WHA::EBackGround] = KDot11BgTxopLimit;
+ break;
+ case WHA::EVideo:
+ aCtxImpl.CwMinVector()[WHA::EVideo] =
+ aUseAandGvalues ? KDot11ViCwMinAandG : KDot11ViCwMinB;
+ aCtxImpl.CwMaxVector()[WHA::EVideo] =
+ aUseAandGvalues ? KDot11ViCwMaxAandG : KDot11ViCwMaxB;
+ aCtxImpl.AifsVector()[WHA::EVideo] = KDot11ViAifsn;
+ aCtxImpl.TxOplimitVector()[WHA::EVideo] =
+ aUseAandGvalues ? KDot11ViTxopLimitAandG : KDot11ViTxopLimitB;
+ break;
+ case WHA::EVoice:
+ aCtxImpl.CwMinVector()[WHA::EVoice] =
+ aUseAandGvalues ? KDot11VoCwMinAandG : KDot11VoCwMinB;
+ aCtxImpl.CwMaxVector()[WHA::EVoice] =
+ aUseAandGvalues ? KDot11VoCwMaxAandG : KDot11VoCwMaxB;
+ aCtxImpl.AifsVector()[WHA::EVoice] = KDot11VoAifsn;
+ aCtxImpl.TxOplimitVector()[WHA::EVoice] =
+ aUseAandGvalues ? KDot11VoTxopLimitAandG : KDot11VoTxopLimitB;
+ break;
+ default:
+ {
+ // catch implementation error
+
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: WlanDot11State::ResetAcParameters: unsupported access category: %d"),
+ aAccessCategory );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ResetAcParameters(
+ WlanContextImpl& aCtxImpl,
+ TBool aUseAandGvalues )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ResetAcParameters: Reset parameters of all ACs. aUseAandGvalues: %d"),
+ aUseAandGvalues );
+
+ // Set the default values for a QoS connection for every AC
+
+ ResetAcParameters( aCtxImpl, WHA::ELegacy, aUseAandGvalues );
+ ResetAcParameters( aCtxImpl, WHA::EBackGround, aUseAandGvalues );
+ ResetAcParameters( aCtxImpl, WHA::EVideo, aUseAandGvalues );
+ ResetAcParameters( aCtxImpl, WHA::EVoice, aUseAandGvalues );
+
+ // reset also the WMM Parameter Set Count to initial (not defined) value
+ aCtxImpl.WmmParameterSetCount( KWmmParamSetNotDefined );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AcParametersValid(
+ WlanContextImpl& aCtxImpl,
+ WHA::TQueueId aAccessCategory )
+ {
+ TBool status ( ETrue );
+
+ if ( aAccessCategory < WHA::EHcca )
+ {
+ if ( // AIFSN validity per the WMM specification
+ (aCtxImpl.AifsVector())[aAccessCategory] < KDot11AifsnMin ||
+ // CwMin & CwMax sanity check
+ (aCtxImpl.CwMinVector())[aAccessCategory] >=
+ (aCtxImpl.CwMaxVector())[aAccessCategory] )
+ {
+ status = EFalse;
+ }
+ else
+ {
+ // parameters are reasonable. No action needed
+ }
+ }
+ else
+ {
+ // catch implementation error
+
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: WlanDot11State::AcParametersValid: unsupported aAccessCategory: %d"),
+ aAccessCategory );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ParseAcParameters(
+ WlanContextImpl& aCtxImpl,
+ const SWmmParamElemData& aWmmParamElem )
+ {
+ for( TUint8 i = 0; i < KNumOfWmmACs; i++ )
+ {
+ switch ( aWmmParamElem.iAcParams[i].AccessCategory() )
+ {
+ case EAcBestEffort:
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: parsing best effort AC parameters"));
+ (aCtxImpl.CwMinVector())[WHA::ELegacy] =
+ aWmmParamElem.iAcParams[i].CwMin();
+ (aCtxImpl.CwMaxVector())[WHA::ELegacy] =
+ aWmmParamElem.iAcParams[i].CwMax();
+ (aCtxImpl.AifsVector())[WHA::ELegacy] =
+ aWmmParamElem.iAcParams[i].Aifsn();
+ (aCtxImpl.TxOplimitVector())[WHA::ELegacy] =
+ aWmmParamElem.iAcParams[i].TxOpLimit();
+ (aCtxImpl.AcmVector())[WHA::ELegacy] =
+ ( aWmmParamElem.iAcParams[i].AdmissionControlMandatory() )?
+ ETrue : EFalse;
+
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aCntrl mandatory: %d"),
+ aWmmParamElem.iAcParams[i].AdmissionControlMandatory());
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmin: %d"), (aCtxImpl.CwMinVector())[WHA::ELegacy]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmax: %d"), (aCtxImpl.CwMaxVector())[WHA::ELegacy]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aifsn: %d"), (aCtxImpl.AifsVector())[WHA::ELegacy]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: txOpLimit: %d"), (aCtxImpl.TxOplimitVector())[WHA::ELegacy]);
+
+ if ( !AcParametersValid( aCtxImpl, WHA::ELegacy ) )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: BE parameters not reasonble. Resetting to defaults") );
+ ResetAcParameters(
+ aCtxImpl,
+ WHA::ELegacy,
+ aCtxImpl.ErpIePresent() );
+ }
+ break;
+ case EAcBackground:
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: parsing background AC parameters"));
+ (aCtxImpl.CwMinVector())[WHA::EBackGround] =
+ aWmmParamElem.iAcParams[i].CwMin();
+ (aCtxImpl.CwMaxVector())[WHA::EBackGround] =
+ aWmmParamElem.iAcParams[i].CwMax();
+ (aCtxImpl.AifsVector())[WHA::EBackGround] =
+ aWmmParamElem.iAcParams[i].Aifsn();
+ (aCtxImpl.TxOplimitVector())[WHA::EBackGround] =
+ aWmmParamElem.iAcParams[i].TxOpLimit();
+ (aCtxImpl.AcmVector())[WHA::EBackGround] =
+ ( aWmmParamElem.iAcParams[i].AdmissionControlMandatory() )?
+ ETrue : EFalse;
+
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aCntrl mandatory: %d"),
+ aWmmParamElem.iAcParams[i].AdmissionControlMandatory());
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmin: %d"), (aCtxImpl.CwMinVector())[WHA::EBackGround]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmax: %d"), (aCtxImpl.CwMaxVector())[WHA::EBackGround]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aifsn: %d"), (aCtxImpl.AifsVector())[WHA::EBackGround]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: txOpLimit: %d"), (aCtxImpl.TxOplimitVector())[WHA::EBackGround]);
+
+ if ( !AcParametersValid( aCtxImpl, WHA::EBackGround ) )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: BG parameters not reasonble. Resetting to defaults") );
+ ResetAcParameters(
+ aCtxImpl,
+ WHA::EBackGround,
+ aCtxImpl.ErpIePresent() );
+ }
+ break;
+ case EAcVideo:
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: parsing video AC parameters"));
+ (aCtxImpl.CwMinVector())[WHA::EVideo] =
+ aWmmParamElem.iAcParams[i].CwMin();
+ (aCtxImpl.CwMaxVector())[WHA::EVideo] =
+ aWmmParamElem.iAcParams[i].CwMax();
+ (aCtxImpl.AifsVector())[WHA::EVideo] =
+ aWmmParamElem.iAcParams[i].Aifsn();
+ (aCtxImpl.TxOplimitVector())[WHA::EVideo] =
+ aWmmParamElem.iAcParams[i].TxOpLimit();
+ (aCtxImpl.AcmVector())[WHA::EVideo] =
+ ( aWmmParamElem.iAcParams[i].AdmissionControlMandatory() )?
+ ETrue : EFalse;
+
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aCntrl mandatory: %d"),
+ aWmmParamElem.iAcParams[i].AdmissionControlMandatory());
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmin: %d"), (aCtxImpl.CwMinVector())[WHA::EVideo]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmax: %d"), (aCtxImpl.CwMaxVector())[WHA::EVideo]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aifsn: %d"), (aCtxImpl.AifsVector())[WHA::EVideo]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: txOpLimit: %d"), (aCtxImpl.TxOplimitVector())[WHA::EVideo]);
+
+ if ( !AcParametersValid( aCtxImpl, WHA::EVideo ) )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: VI parameters not reasonble. Resetting to defaults") );
+ ResetAcParameters(
+ aCtxImpl,
+ WHA::EVideo,
+ aCtxImpl.ErpIePresent() );
+ }
+ break;
+ case EAcVoice:
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: parsing voice AC parameters"));
+ (aCtxImpl.CwMinVector())[WHA::EVoice] =
+ aWmmParamElem.iAcParams[i].CwMin();
+ (aCtxImpl.CwMaxVector())[WHA::EVoice] =
+ aWmmParamElem.iAcParams[i].CwMax();
+ (aCtxImpl.AifsVector())[WHA::EVoice] =
+ aWmmParamElem.iAcParams[i].Aifsn();
+ (aCtxImpl.TxOplimitVector())[WHA::EVoice] =
+ aWmmParamElem.iAcParams[i].TxOpLimit();
+ (aCtxImpl.AcmVector())[WHA::EVoice] =
+ ( aWmmParamElem.iAcParams[i].AdmissionControlMandatory() )?
+ ETrue : EFalse;
+
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aCntrl mandatory: %d"),
+ aWmmParamElem.iAcParams[i].AdmissionControlMandatory());
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmin: %d"), (aCtxImpl.CwMinVector())[WHA::EVoice]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: cwmax: %d"), (aCtxImpl.CwMaxVector())[WHA::EVoice]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: aifsn: %d"), (aCtxImpl.AifsVector())[WHA::EVoice]);
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: txOpLimit: %d"), (aCtxImpl.TxOplimitVector())[WHA::EVoice]);
+
+ if ( !AcParametersValid( aCtxImpl, WHA::EVoice ) )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: VO parameters not reasonble. Resetting to defaults") );
+ ResetAcParameters(
+ aCtxImpl,
+ WHA::EVoice,
+ aCtxImpl.ErpIePresent() );
+ }
+ break;
+ default:
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WARNING: Unknown AC: %d => parameters ignored"),
+ aWmmParamElem.iAcParams[i].AccessCategory() );
+ }
+ }
+
+ // store the current Parameter Set Count.
+ aCtxImpl.WmmParameterSetCount( aWmmParamElem.ParameterSetCount() );
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ParseAcParameters: param set cnt: %d"),
+ aCtxImpl.WmmParameterSetCount() );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddTkIPKey(
+ WlanContextImpl& aCtxImpl,
+ const TUint8* aData,
+ TUint32 /*aLength*/,
+ T802Dot11WepKeyId aKeyIndex,
+ const TMacAddress& aMacAddr )
+ {
+ TBool ret( EFalse );
+ WlanWsaAddKey& wsa_cmd( aCtxImpl.WsaAddKey() );
+ WHA::STkipPairwiseKey* key( CreateTkipPtkCtx(
+ aCtxImpl,
+ wsa_cmd,
+ aData,
+ aKeyIndex,
+ aMacAddr )
+ );
+
+ if ( key )
+ {
+ ret = ETrue;
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // allways remember to release the memory
+ }
+ else
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddTkIPKey(): memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::StoreTxRatePolicyInfo(
+ WlanContextImpl& aCtxImpl,
+ const TTxRatePolicy& aRatePolicy,
+ const TQueue2RateClass& aQueue2RateClass,
+ const TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass,
+ const TTxAutoRatePolicy& aAutoRatePolicy,
+ const THtMcsPolicy& aHtMcsPolicy )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::StoreTxRatePolicyInfo: store provided Tx rate policy configuration data for later use"));
+
+ TTxRatePolicy& ratePolicy = aCtxImpl.RatePolicy();
+ os_memcpy( &ratePolicy, &aRatePolicy, sizeof( TTxRatePolicy ) );
+
+ TQueue2RateClass& queue2RateClass = aCtxImpl.Queue2RateClass();
+ os_memcpy( &queue2RateClass, &aQueue2RateClass, sizeof( TQueue2RateClass ) );
+
+ TInitialMaxTxRate4RateClass& initialMaxTxRate4RateClass =
+ aCtxImpl.InitialMaxTxRate4RateClass();
+ os_memcpy(
+ &initialMaxTxRate4RateClass,
+ &aInitialMaxTxRate4RateClass,
+ sizeof( TInitialMaxTxRate4RateClass ) );
+
+ TTxAutoRatePolicy& autoRatePolicy = aCtxImpl.AutoRatePolicy();
+ os_memcpy( &autoRatePolicy, &aAutoRatePolicy, sizeof( TTxAutoRatePolicy ) );
+
+ THtMcsPolicy& htMcsPolicy = aCtxImpl.HtMcsPolicy();
+ os_memcpy( &htMcsPolicy, &aHtMcsPolicy, sizeof( THtMcsPolicy ) );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureTxRatePolicies(
+ WlanContextImpl& aCtxImpl,
+ TBool aCompleteMgmtRequest )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureTxRatePolicies: rate bitmask (intersection of AP and our supported rates): 0x%08x"),
+ aCtxImpl.RateBitMask() );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureTxRatePolicies: aCompleteMgmtRequest: %d"),
+ aCompleteMgmtRequest );
+
+ TBool status ( ETrue );
+ // retrieve reference to the stored rate policy
+ TTxRatePolicy& ratePolicy ( aCtxImpl.RatePolicy() );
+ // retrieve reference to the stored Tx queue 2 Rate Class mapping
+ TQueue2RateClass& queue2RateClass ( aCtxImpl.Queue2RateClass() );
+ // retrieve reference to the stored initial max Tx rate per rate class -
+ // information
+ TInitialMaxTxRate4RateClass& initialMaxTxRate4RateClass(
+ aCtxImpl.InitialMaxTxRate4RateClass() );
+ // retrieve reference to the stored auto rate policy
+ TTxAutoRatePolicy& autoRatePolicy ( aCtxImpl.AutoRatePolicy() );
+ // retrieve reference to the stored HT MCS policy
+ THtMcsPolicy& htMcsPolicy ( aCtxImpl.HtMcsPolicy() );
+
+ if ( aCtxImpl.WHASettings().iNumOfTxRateClasses <
+ ratePolicy.numOfPolicyObjects )
+ {
+ // WHA layer doesn't support as many rate classes as has been
+ // provided to us.
+
+ ResortToSingleTxRatePolicy(
+ aCtxImpl,
+ ratePolicy,
+ queue2RateClass );
+ }
+
+ TWhaRateMasks rateMasks;
+ os_memset( rateMasks, 0, sizeof( rateMasks ) );
+
+ FinalizeTxRatePolicy(
+ aCtxImpl,
+ ratePolicy,
+ rateMasks,
+ initialMaxTxRate4RateClass );
+
+ if ( aCtxImpl.WHASettings().iCapability &
+ WHA::SSettings::KAutonomousRateAdapt )
+ {
+ //=====================================================================
+ // lower layer supports autonomous rate adaptation so we will let it
+ // handle the rate adaptation.
+ //=====================================================================
+
+ FinalizeTxAutoratePolicy(
+ aCtxImpl,
+ ratePolicy,
+ autoRatePolicy );
+
+ SpecialTxAutoratePolicy(
+ aCtxImpl,
+ ratePolicy,
+ autoRatePolicy,
+ htMcsPolicy );
+
+ ConfigureForTxAutoratePolicy(
+ aCtxImpl,
+ ratePolicy,
+ queue2RateClass,
+ htMcsPolicy,
+ aCompleteMgmtRequest );
+ }
+ else
+ {
+ //=====================================================================
+ // WHA layer doesn't support autonomous rate adaptation so we need to
+ // take care of rate adaption. Perform the relevant configuration
+ //=====================================================================
+
+ status = ConfigureForTxRatePolicy(
+ aCtxImpl,
+ ratePolicy,
+ rateMasks,
+ queue2RateClass,
+ initialMaxTxRate4RateClass,
+ aCompleteMgmtRequest );
+ } // else
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::DifferenceInPsModeWakeupSettings(
+ const WlanContextImpl& aCtxImpl ) const
+ {
+ TBool difference( EFalse );
+
+ // 1st determine the current PS mode wake-up setting
+
+ const WHA::TWlanWakeUpInterval currentWakeupMode (
+ aCtxImpl.iWlanMib.iWlanWakeupInterval );
+ const TUint8 currentListenInterval (
+ aCtxImpl.iWlanMib.iWlanListenInterval );
+
+ // and the desired wake-up setting
+ const TDot11PsModeWakeupSetting KDesiredPsModeConfig (
+ aCtxImpl.DesiredPsModeConfig() );
+
+ if ( currentWakeupMode !=
+ static_cast<WHA::TWlanWakeUpInterval>(
+ KDesiredPsModeConfig.iWakeupMode) )
+ {
+ // difference in wake-up mode
+ difference = ETrue;
+
+ OsTracePrint( KPwrStateTransition, (TUint8*)
+ ("UMAC: WlanDot11State::DifferenceInPsModeWakeupSettings: difference in wake-up mode") );
+ }
+ else
+ {
+ // wake-up mode is unchanged
+
+ if ( KDesiredPsModeConfig.iWakeupMode
+ == EWakeUpIntervalEveryNthBeacon ||
+ KDesiredPsModeConfig.iWakeupMode
+ == EWakeUpIntervalEveryNthDtim )
+ {
+ // for these wake-up modes there can be a
+ // difference in the listen interval. Check that
+ if ( currentListenInterval != KDesiredPsModeConfig.iListenInterval )
+ {
+ difference = ETrue;
+
+ OsTracePrint( KPwrStateTransition, (TUint8*)
+ ("UMAC: WlanDot11State::DifferenceInPsModeWakeupSettings: difference in listen interval") );
+ }
+ else
+ {
+ // no difference in listen interval either
+ // (return value is already correct)
+ }
+ }
+ else
+ {
+ // for these wake-up modes a possible difference in listen
+ // interval is not meaningful => no difference (return
+ // value is already correct)
+ }
+ }
+
+ OsTracePrint( KPwrStateTransition, (TUint8*)
+ ("UMAC: WlanDot11State::DifferenceInPsModeWakeupSettings: difference: %d"),
+ difference );
+
+ return difference;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureHtCapabilities(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureHtCapabilities") );
+
+ // allocate memory for the mib to write
+ WHA::ShtCapabilities* mib
+ = static_cast<WHA::ShtCapabilities*>
+ (os_alloc( sizeof( WHA::ShtCapabilities ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureHtCapabilities: abort") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ // reset MIB before starting to set the values
+ os_memset( mib, 0, sizeof( WHA::ShtCapabilities ) );
+
+ //=====================
+ // Set the MIB contents
+ //=====================
+
+ mib->iHtSupport = aCtxImpl.HtSupportedByNw();
+
+ // currently HT is supported only in infrastructure networks
+ mib->iPeerMac = WHA::KBroadcastMacAddr;
+
+ mib->iRxStbc = aCtxImpl.GetNwHtCapabilitiesIe().iData.StbcRx();
+
+ mib->iMaxAmpduLength =
+ aCtxImpl.GetNwHtCapabilitiesIe().iData.MaxAmpduLenExponent();
+
+ // if a feature is supported by the nw, set it in the capabilities bit
+ // mask. Otherwise it is left unset
+
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.LdpcRx() )
+ {
+ mib->iPeerFeatures |= WHA::KLdpcRx;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.FortyMhzOperation() )
+ {
+ mib->iPeerFeatures |= WHA::K40MhzChannel;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.GreenfieldFormat() )
+ {
+ mib->iPeerFeatures |= WHA::KGreenfieldFormat;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.ShortGiFor20Mhz() )
+ {
+ mib->iPeerFeatures |= WHA::KShortGiFor20Mhz;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.ShortGiFor40Mhz() )
+ {
+ mib->iPeerFeatures |= WHA::KShortGiFor40Mhz;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.StbcTx() )
+ {
+ mib->iPeerFeatures |= WHA::KStbcTx;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.DelayedBlockAck() )
+ {
+ mib->iPeerFeatures |= WHA::KDelayedBlockAck;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.DsssCckIn40Mhz() )
+ {
+ mib->iPeerFeatures |= WHA::KDsssCckIn40Mhz;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.Psmp() )
+ {
+ mib->iPeerFeatures |= WHA::KPsmp;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.LsigTxopProtection() )
+ {
+ mib->iPeerFeatures |= WHA::KLsigTxopProtection;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.Pco() )
+ {
+ mib->iPeerFeatures |= WHA::KPco;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.Htc() )
+ {
+ mib->iPeerFeatures |= WHA::KHtcField;
+ }
+ if ( aCtxImpl.GetNwHtCapabilitiesIe().iData.RdResponder() )
+ {
+ mib->iPeerFeatures |= WHA::KReverseDirectionResp;
+ }
+
+ os_memcpy(
+ mib->iMcsSet,
+ aCtxImpl.GetNwHtCapabilitiesIe().iData.iRxMcsBitmask,
+ sizeof( mib->iMcsSet ) );
+
+ mib->iAmpduSpacing =
+ aCtxImpl.GetNwHtCapabilitiesIe().iData.MinMpduStartSpacing();
+
+ mib->iMcsFeedback = aCtxImpl.GetNwHtCapabilitiesIe().iData.McsFeedback();
+
+ mib->iTxBeamFormingCapab =
+ aCtxImpl.GetNwHtCapabilitiesIe().iData.TransmitBeamformingCapabilities();
+
+ mib->iAntennaSelCapab =
+ aCtxImpl.GetNwHtCapabilitiesIe().iData.AselCapabilities();
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+
+ wha_cmd.Set(
+ aCtxImpl,
+ WHA::KMibHtCapabilities,
+ sizeof(*mib), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd // next state
+ );
+
+ os_free( mib ); // release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void WlanDot11State::ResetHtCapabilitiesMib(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ResetHtCapabilitiesMib") );
+
+ // allocate memory for the mib to write
+ WHA::ShtCapabilities* mib
+ = static_cast<WHA::ShtCapabilities*>
+ (os_alloc( sizeof( WHA::ShtCapabilities ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::ResetHtCapabilitiesMib: abort") );
+ DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ // reset the MIB to its default value
+ *mib = WHA::KHtCapabilitiesMibDefault;
+
+ WlanWsaWriteMib& wsa_cmd = aCtxImpl.WsaWriteMib();
+
+ wsa_cmd.Set(
+ aCtxImpl, WHA::KMibHtCapabilities, sizeof( *mib ), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd // next state
+ );
+
+ os_free( mib ); // release the memory
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void WlanDot11State::ResetHtBlockAckConfigureMib(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ResetHtBlockAckConfigureMib") );
+
+ // allocate memory for the mib to write
+ WHA::ShtBlockAckConfigure* mib
+ = static_cast<WHA::ShtBlockAckConfigure*>
+ (os_alloc( sizeof( WHA::ShtBlockAckConfigure ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::ResetHtBlockAckConfigureMib: abort") );
+ DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ // reset the MIB to its default value
+ *mib = WHA::KHtBlockAckConfigureMibDefault;
+
+ WlanWsaWriteMib& wsa_cmd = aCtxImpl.WsaWriteMib();
+
+ wsa_cmd.Set(
+ aCtxImpl, WHA::KMibHtBlockAckConfigure, sizeof( *mib ), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd // next state
+ );
+
+ os_free( mib ); // release the memory
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureHtBssOperation(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureHtBssOperation") );
+
+ // allocate memory for the mib to write
+ WHA::ShtBssOperation* mib
+ = static_cast<WHA::ShtBssOperation*>
+ (os_alloc( sizeof( WHA::ShtBssOperation ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureHtBssOperation: abort") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ // reset MIB before starting to set the values
+ os_memset( mib, 0, sizeof( WHA::ShtBssOperation ) );
+
+ //=====================
+ // Set the MIB contents
+ //=====================
+
+ if ( aCtxImpl.GetNwHtOperationIe().iData.NonGreenfieldPresent() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KNonGreenfieldPresent;
+ }
+ if ( aCtxImpl.GetNwHtOperationIe().iData.PcoActive() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KPcoActive;
+ }
+ if ( aCtxImpl.GetNwHtOperationIe().iData.RifsMode() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KRifsPermitted;
+ }
+ if ( aCtxImpl.GetNwHtOperationIe().iData.DualCtsProtection() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KDualCtsProtReq;
+ }
+ if ( aCtxImpl.GetNwHtOperationIe().iData.DualBeacon() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KSecondaryBeaconTx;
+ }
+ if ( aCtxImpl.GetNwHtOperationIe().iData.LsigTxopProtection() )
+ {
+ mib->iInfo |= WHA::ShtBssOperation::KLsigTxopProtection;
+ }
+
+ os_memcpy(
+ mib->iMcsSet,
+ aCtxImpl.GetNwHtOperationIe().iData.iBasicMcsSet,
+ sizeof( mib->iMcsSet ) );
+
+ mib->iOpMode =
+ aCtxImpl.GetNwHtOperationIe().iData.HtProtection();
+
+ mib->iSecChOffset =
+ aCtxImpl.GetNwHtOperationIe().iData.SecondaryChOffset();
+
+ mib->iApChWidth =
+ aCtxImpl.GetNwHtOperationIe().iData.ChWidth();
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+
+ wha_cmd.Set(
+ aCtxImpl,
+ WHA::KMibHtBssOperation,
+ sizeof(*mib), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd // next state
+ );
+
+ os_free( mib ); // release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::HtcFieldPresent(
+ WlanContextImpl& aCtxImpl,
+ const TAny* aFrame,
+ TUint32 aFlags )
+ {
+ TBool status ( EFalse );
+
+ if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KHtOperation )
+ {
+ // we can interpret the frame to have this header even if it would
+ // be a 802.11 mgmt frame as the header content that is relevant in
+ // this method is the same
+ const SDataFrameHeader* frameHdr
+ = reinterpret_cast<const SDataFrameHeader*>(aFrame);
+
+ if ( aFlags & WHA::KHtPacket && frameHdr->IsOrderBitSet() )
+ {
+ status = ETrue;
+ OsTracePrint( KRxFrame, (TUint8*)
+ ("UMAC: WlanDot11State::HtcFieldPresent: yes") );
+ }
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::OutgoingMulticastDataFrame(
+ const SDataFrameHeader* aDataFrameHdr )
+ {
+ if ( aDataFrameHdr->IsToDsBitSet() )
+ {
+ // frame to infrastructure nw. Address 3 == DA
+
+ return IsGroupBitSet( aDataFrameHdr->iAddress3 );
+ }
+ else
+ {
+ // frame to IBSS. Address 1 == DA
+
+ return IsGroupBitSet( aDataFrameHdr->iAddress1 );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::UpdateTxDataFrameStatistics(
+ WlanContextImpl& aCtxImpl,
+ WHA::TQueueId aAccessCategory,
+ WHA::TStatus aStatus,
+ TBool aMulticastData,
+ TUint aAckFailures,
+ TUint32 aMediaDelay,
+ TUint aTotalTxDelay )
+ {
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: aAccessCategory: %d"),
+ aAccessCategory );
+
+ if ( aStatus == WHA::KSuccess )
+ {
+ if ( aMulticastData )
+ {
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: inc tx mcast cnt") );
+
+ aCtxImpl.IncrementTxMulticastDataFrameCount( aAccessCategory );
+ }
+ else
+ {
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: inc tx unicast cnt") );
+
+ aCtxImpl.IncrementTxUnicastDataFrameCount( aAccessCategory );
+ }
+
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: ack failures: %d"),
+ aAckFailures );
+
+ aCtxImpl.IncrementTxRetryCount( aAccessCategory, aAckFailures );
+
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: aMediaDelay: %d"),
+ aMediaDelay );
+
+ aCtxImpl.IncrementTxMediaDelay( aAccessCategory, aMediaDelay );
+
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: aTotalTxDelay: %d"),
+ aTotalTxDelay );
+
+ aCtxImpl.IncrementTotalTxDelay( aAccessCategory, aTotalTxDelay );
+
+ aCtxImpl.UpdateTotalTxDelayHistogram( aAccessCategory, aTotalTxDelay );
+ }
+ else
+ {
+ OsTracePrint( KWsaTxDetails, (TUint8*)
+ ("UMAC: WlanDot11State::UpdateTxDataFrameStatistics: inc tx error cnt") );
+ aCtxImpl.IncrementTxErrorCount( aAccessCategory );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::XferDot11FrameToMgmtClient(
+ WlanContextImpl& aCtxImpl,
+ const void* aFrame,
+ TUint32 aLength,
+ const WHA::TRcpi aRcpi,
+ TUint8* aBuffer ) const
+ {
+ OsTracePrint( KRxFrame, (TUint8*)
+ ("UMAC: WlanDot11State::XferDot11FrameToMgmtClient: aRcpi: %d"),
+ aRcpi);
+
+ TBool status ( ETrue );
+
+ TDataBuffer* metaHdr ( aCtxImpl.GetRxFrameMetaHeader() );
+
+ if ( metaHdr )
+ {
+ // set frame length
+ metaHdr->KeSetLength( aLength );
+
+ // set frame type
+ metaHdr->FrameType( TDataBuffer::KDot11Frame );
+
+ // set RCPI for every frame transferred to the mgmt client
+ metaHdr->KeSetRcpi( aRcpi );
+
+ // set the offset to the beginning of the Rx buffer from the beginning
+ // of the meta header. Note that this may be also negative
+ metaHdr->KeSetBufferOffset(
+ aBuffer
+ - reinterpret_cast<TUint8*>(metaHdr) );
+
+ // set the offset to the beginning of the actual frame within the
+ // Rx buffer
+ metaHdr->KeSetOffsetToFrameBeginning(
+ reinterpret_cast<const TUint8*>(aFrame) // frame beginning
+ - aBuffer ); // buffer beginning
+
+ // complete
+ const TDataBuffer* KMetaHdr ( metaHdr );
+ aCtxImpl.iUmac.MgmtDataReceiveComplete( KMetaHdr, 1 );
+ }
+ else
+ {
+ // no memory available for the meta header. In this case we have no
+ // other choice than to discard the received frame.
+ aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+ // inform the caller about the situation
+ status = EFalse;
+ OsTracePrint( KWarningLevel | KRxFrame, (TUint8*)
+ ("UMAC: WlanDot11State::XferDot11FrameToMgmtClient: WARNING: no memory for meta hdr => abort rx") );
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddMulticastTKIPKey(
+ WlanContextImpl& aCtxImpl,
+ T802Dot11WepKeyId aKeyIndex,
+ TUint32 /*aLength*/,
+ const TUint8* aData )
+ {
+ // store info of TKIP GTK insertion
+ aCtxImpl.GroupKeyType( WHA::ETkipGroupKey );
+
+ // allocate memory for the key structure
+ WHA::STkipGroupKey* key = static_cast<WHA::STkipGroupKey*>
+ (os_alloc( sizeof(WHA::STkipGroupKey) ));
+
+ if ( !key )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::AddMulticastTKIPKey: memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ os_memcpy( key->iTkipKey, aData, WHA::KTKIPKeyLength );
+ os_memcpy( key->iRxMicKey, aData + WHA::KTKIPKeyLength, KMicLength );
+ key->iKeyId = static_cast<WHA::TPrivacyKeyId>(aKeyIndex);
+ // for now we fill this field with zeroes
+ os_memset( key->iRxSequenceCounter, 0, WHA::KRxSequenceCounterLength );
+
+ WlanWsaAddKey& wsa_cmd = aCtxImpl.WsaAddKey();
+
+ wsa_cmd.Set( aCtxImpl,
+ WHA::ETkipGroupKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::ETkipGroupKey ) );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // allways remember to release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddAesKey(
+ WlanContextImpl& aCtxImpl,
+ const TUint8* aData,
+ TUint32 /*aLength*/,
+ const TMacAddress& aMacAddr )
+ {
+ TBool ret( EFalse );
+ WlanWsaAddKey& wsa_cmd( aCtxImpl.WsaAddKey() );
+ WHA::SAesPairwiseKey* key( CreateAesPtkCtx(
+ aCtxImpl,
+ wsa_cmd,
+ aData,
+ aMacAddr )
+ );
+
+ if ( key )
+ {
+ ret = ETrue;
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // allways remember to release the memory
+ }
+ else
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddAesKey(): memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddMulticastAesKey(
+ WlanContextImpl& aCtxImpl,
+ T802Dot11WepKeyId aKeyIndex,
+ TUint32 /*aLength*/,
+ const TUint8* aData )
+ {
+ // store info of AES GTK insertion
+ aCtxImpl.GroupKeyType( WHA::EAesGroupKey );
+
+ // allocate memory for the key structure
+ WHA::SAesGroupKey* key = static_cast<WHA::SAesGroupKey*>
+ ( os_alloc( sizeof( WHA::SAesGroupKey ) ) );
+
+ if ( !key )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddMulticastAesKey(): memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ os_memcpy( key->iAesKey, aData, WHA::KAesKeyLength );
+ key->iKeyId = static_cast<WHA::TPrivacyKeyId>(aKeyIndex);
+ // for now we fill this field with zeroes
+ os_memset( key->iRxSequenceCounter, 0, WHA::KRxSequenceCounterLength );
+
+ WlanWsaAddKey& wsa_cmd = aCtxImpl.WsaAddKey();
+
+ wsa_cmd.Set( aCtxImpl,
+ WHA::EAesGroupKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EAesGroupKey ) );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // allways remember to release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddUnicastWepKey(
+ WlanContextImpl& aCtxImpl,
+ const TMacAddress& aMacAddr,
+ TUint32 aKeyLength,
+ const TUint8 aKey[KMaxWEPKeyLength])
+ {
+ // store info of WEP PTK insertion
+ aCtxImpl.PairWiseKeyType( WHA::EWepPairWiseKey );
+
+ // allocate memory for the key structure
+ WHA::SWepPairwiseKey* key = static_cast<WHA::SWepPairwiseKey*>
+ (os_alloc( WHA::SWepPairwiseKey::KHeaderSize + aKeyLength ));
+
+ if ( !key )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddUnicastWepKey(): memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ os_memcpy(
+ &(key->iMacAddr),
+ aMacAddr.iMacAddress,
+ sizeof(key->iMacAddr) );
+ key->iKeyLengthInBytes = static_cast<TUint8>(aKeyLength);
+ os_memcpy( key->iKey, aKey, key->iKeyLengthInBytes );
+
+ WlanWsaAddKey& wsa_cmd = aCtxImpl.WsaAddKey();
+ wsa_cmd.Set( aCtxImpl,
+ WHA::EWepPairWiseKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EWepPairWiseKey ) );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // allways remember to release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::OnAddBroadcastWepKey(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aKeyIndex,
+ TBool aUseAsDefaulKey,
+ TBool aUseAsPairwiseKey,
+ TUint32 aKeyLength,
+ const TUint8 aKey[KMaxWEPKeyLength],
+ const TMacAddress& aMac )
+ {
+ WlanAddBroadcastWepKey& complex_wha_cmd(
+ aCtxImpl.AddBroadcastWepKey() );
+
+ complex_wha_cmd.Set( aMac, aKeyIndex, aUseAsDefaulKey,
+ aUseAsPairwiseKey, aKeyLength, aKey );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ complex_wha_cmd // next state
+ );
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddMulticastWapiKey(
+ WlanContextImpl& aCtxImpl,
+ T802Dot11WepKeyId aKeyIndex,
+ TUint32 /*aLength*/,
+ const TUint8* aData )
+ {
+ if ( !(aCtxImpl.WHASettings().iCapability & WHA::SSettings::KWapi) )
+ {
+ // WAPI not supported by wlanpdd => abort key setting
+
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddMulticastWapiKey: WAPI not supported by wlanpdd -> abort") );
+
+ OnOidComplete( aCtxImpl, KErrNotSupported );
+ return EFalse;
+ }
+
+ // store info of WAPI group key insertion
+ aCtxImpl.GroupKeyType( WHA::EWapiGroupKey );
+
+ // allocate memory for the key structure
+ WHA::SWapiGroupKey* key = static_cast<WHA::SWapiGroupKey*>
+ (os_alloc( sizeof(WHA::SWapiGroupKey) ));
+
+ if ( !key )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::AddMulticastWapiKey: memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ os_memcpy( key->iWapiKey, aData, WHA::KWapiKeyLength );
+
+ os_memcpy(
+ key->iMicKey,
+ aData + WHA::KWapiKeyLength,
+ WHA::KWapiMicKeyLength );
+
+ key->iKeyId = static_cast<WHA::TPrivacyKeyId>(aKeyIndex);
+
+ WlanWsaAddKey& wsa_cmd = aCtxImpl.WsaAddKey();
+
+ wsa_cmd.Set( aCtxImpl,
+ WHA::EWapiGroupKey,
+ key,
+ WlanWsaKeyIndexMapper::Extract( WHA::EWapiGroupKey ) );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // release the memory
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::AddUnicastWapiKey(
+ WlanContextImpl& aCtxImpl,
+ const TUint8* aData,
+ TUint32 /*aLength*/,
+ T802Dot11WepKeyId aKeyIndex,
+ const TMacAddress& aMacAddr )
+ {
+ TBool ret( EFalse );
+
+ if ( !(aCtxImpl.WHASettings().iCapability & WHA::SSettings::KWapi) )
+ {
+ // WAPI not supported by wlanpdd => abort key setting
+
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddUnicastWapiKey: WAPI not supported by wlanpdd -> abort") );
+
+ OnOidComplete( aCtxImpl, KErrNotSupported );
+ return ret;
+ }
+
+ WlanWsaAddKey& wsa_cmd( aCtxImpl.WsaAddKey() );
+
+ WHA::SWapiPairwiseKey* key( CreateWapiPtkCtx(
+ aCtxImpl,
+ wsa_cmd,
+ aData,
+ aKeyIndex,
+ aMacAddr )
+ );
+
+ if ( key )
+ {
+ ret = ETrue;
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( key ); // release the memory
+ }
+ else
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::AddUnicastWapiKey: memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::InitNetworkConnect(
+ WlanContextImpl& aCtxImpl,
+ TUint16 aScanResponseFrameBodyLength,
+ const TUint8* aScanResponseFrameBody ) const
+ {
+ OsTracePrint( KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::InitNetworkConnect") );
+
+ const SScanResponseFixedFields* scanResponseFixedFields =
+ reinterpret_cast<const SScanResponseFixedFields*>(
+ aScanResponseFrameBody );
+
+ // store capability info from scan response frame body to our context
+ aCtxImpl.GetCapabilityInformation()
+ = scanResponseFixedFields->iCapability.CapabilityInformationField();
+
+ // and set it also as the initial value to our association request frame
+ // templates
+ aCtxImpl.GetAssociationRequestFrame().iFixedFields.iCapabilityInfo
+ = aCtxImpl.GetCapabilityInformation();
+ aCtxImpl.GetHtAssociationRequestFrame().iFixedFields.iCapabilityInfo
+ = aCtxImpl.GetCapabilityInformation();
+
+ // ... and to to our reassociation request frame templates
+ aCtxImpl.GetReassociationRequestFrame().iFixedFields.iCapabilityInfo
+ = aCtxImpl.GetCapabilityInformation();
+ aCtxImpl.GetHtReassociationRequestFrame().iFixedFields.iCapabilityInfo
+ = aCtxImpl.GetCapabilityInformation();
+
+ // use short slot time if supported by the network
+ aCtxImpl.UseShortSlotTime(
+ aCtxImpl.GetCapabilityInformation().IsShortSlotTimeBitSet() );
+
+ //=============================================
+ // check for WAPI
+ //=============================================
+ if ( aCtxImpl.EncryptionStatus() == EEncryptionWAPI &&
+ !(aCtxImpl.WHASettings().iCapability & WHA::SSettings::KWapi) )
+ {
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: WAPI requested but not supported by wlanpdd -> abort") );
+
+ return EFalse;
+ }
+
+ //=============================================
+ // do we meet network capability requirements
+ //=============================================
+
+ if ( !NetworkCapabilityInformationMet( aCtxImpl ) )
+ {
+ // requirements not met
+
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: network capabilities not met -> abort") );
+
+ return EFalse;
+ }
+
+ // network capabilities are met -> proceed
+
+
+ // initialize element locator for locating IEs from the scan response
+ // frame body
+ WlanElementLocator elementLocator(
+ reinterpret_cast<const TUint8*>( scanResponseFixedFields + 1 ),
+ aScanResponseFrameBodyLength -
+ sizeof( SScanResponseFixedFields ) );
+
+ TUint8 elementDatalength( 0 );
+ const TUint8* elementData( NULL );
+
+ //=============================================
+ // do we meet mandatory network rates
+ //=============================================
+
+ // locate supported rates IE
+ if ( elementLocator.InformationElement(
+ E802Dot11SupportedRatesIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // ...and store it to our context
+ aCtxImpl.GetApSupportedRatesIE().SetIeData(
+ elementData,
+ elementDatalength );
+ }
+ else
+ {
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: supported rates IE not found -> abort") );
+
+ return EFalse;
+ }
+
+ // locate extended supported rates information element
+ if ( elementLocator.InformationElement(
+ E802Dot11ExtendedRatesIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: E802Dot11ExtendedRatesIE present") );
+
+ // ...and store it to our context
+ aCtxImpl.GetApExtendedSupportedRatesIE().SetIeData( elementData, elementDatalength );
+
+ // check if we meet mandatory rates; in this case check also extended supported rates
+ if ( !AreSupportedRatesMet( aCtxImpl, ETrue ) )
+ {
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: rates not met -> abort") );
+
+ return EFalse;
+ }
+ }
+ else
+ {
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: E802Dot11ExtendedRatesIE not present") );
+
+ // check if we meet mandatory rates; in this case extended supported rates
+ // don't need to be checked
+ if ( !AreSupportedRatesMet( aCtxImpl, EFalse ) )
+ {
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::InitNetworkConnect: rates not met -> abort") );
+
+ return EFalse;
+ }
+ }
+
+ // mandatory network rates are met -> proceed
+
+ //=============================================
+ // determine the channel of the network
+ //=============================================
+
+ // locate DS parameter set information element
+ if ( elementLocator.InformationElement(
+ E802Dot11DsParameterSetIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // ...and store it to our context
+ aCtxImpl.NetworkChannelNumeber( *elementData );
+ }
+ else
+ {
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: 802Dot11DsParameterSetIE not found -> abort") );
+
+ return EFalse;
+ }
+
+ //=============================================
+ // determine the beacon interval of the network
+ //=============================================
+
+ const TUint32 beacon_interval = scanResponseFixedFields->BeaconInterval();
+
+ if ( beacon_interval )
+ {
+ // ...and store it to our context
+ aCtxImpl.NetworkBeaconInterval( beacon_interval );
+ }
+ else
+ {
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::InitNetworkConnect: zero beacon interval -> abort") );
+
+ return EFalse;
+ }
+
+ //=============================================
+ // determine the need to use protection
+ //=============================================
+
+ // locate ERP information element
+ if ( elementLocator.InformationElement(
+ E802Dot11ErpInformationIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // ERP IE present -> set the protection level according to the Use
+ // Protection bit
+ aCtxImpl.ProtectionBitSet( *elementData & KUseProtectionMask );
+ // make also a note of ERP IE presence, which means that the nw in
+ // question is a 802.11a/g nw (instead of a 802.11b nw)
+ aCtxImpl.ErpIePresent( ETrue );
+ }
+ else
+ {
+ // ERP IE not present
+ aCtxImpl.ProtectionBitSet( EFalse );
+ }
+
+ if ( aCtxImpl.NetworkOperationMode() == WHA::EBSS )
+ {
+ //=============================================
+ //
+ // only for infrastructure mode connections
+ //
+ //=============================================
+
+ //=============================================
+ // determine WMM / QoS information
+ //=============================================
+
+ // locate WMM information element
+ if ( elementLocator.InformationElement(
+ E802Dot11VendorSpecificIE,
+ KWmmElemOui,
+ KWmmElemOuiType,
+ KWmmInfoElemOuiSubType,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // WMM IE present
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: WMM IE present"));
+
+ EnableQos( aCtxImpl, UapsdEnabledInNetwork(
+ reinterpret_cast<const SRxWmmIeData&>( *elementData ) ) );
+
+ // as there are no WMM parameter values available in the WMM IE
+ // use the default AC parameter values until we get the values
+ // in (re)association response
+ ResetAcParameters( aCtxImpl, aCtxImpl.ErpIePresent() );
+ }
+ else
+ {
+ // WMM IE not present. Check if WMM Parameter Element exists instead
+ if ( elementLocator.InformationElement(
+ E802Dot11VendorSpecificIE,
+ KWmmElemOui,
+ KWmmElemOuiType,
+ KWmmParamElemOuiSubtype,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // WMM Parameter Element present
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: WMM param elem present"));
+
+ EnableQos( aCtxImpl, UapsdEnabledInNetwork(
+ reinterpret_cast<const SWmmParamElemData&>( *elementData ) ) );
+
+ // as the parameter element is present, use the opportunity to
+ // parse the AC (QoS) parameters.
+ // However, reset them 1st to their default values in case
+ // the nw would provide values for some AC multiple times and
+ // leave the parameters for some AC unspecified
+ //
+ ResetAcParameters( aCtxImpl, aCtxImpl.ErpIePresent() );
+ ParseAcParameters( aCtxImpl,
+ reinterpret_cast<const SWmmParamElemData&>( *elementData ) );
+ }
+ else
+ {
+ // WMM Parameter Element not present either => no QoS, no U-APSD
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: neither WMM IE nor WMM param elem present"));
+
+ aCtxImpl.QosEnabled( EFalse );
+ aCtxImpl.UapsdEnabled( EFalse );
+ }
+ }
+
+ //=================================================================
+ // perform 802.11n related actions & checks if lower layer supports
+ // HT operation
+ //=================================================================
+
+ if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KHtOperation )
+ {
+ if ( !HandleDot11n( aCtxImpl,elementLocator ) )
+ {
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: Nw's 802.11n requirements not met -> abort") );
+
+ return EFalse;
+ }
+ }
+ else
+ {
+ // lower layer doesn't support HT, so we must handle the network
+ // as a non-HT network
+ aCtxImpl.HtSupportedByNw( EFalse );
+ }
+ }
+ else
+ {
+ //=============================================
+ //
+ // only for IBSS mode connections
+ //
+ // ============================================
+
+ //=============================================
+ // determine ATIM window
+ //=============================================
+
+ // locate IBSS Parameter Set element
+ if ( elementLocator.InformationElement(
+ E802Dot11IbssParameterSetIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // store it to our context
+
+ // note that elementData points to the IE data and not the
+ // preceding IE header. That's why we need to back up the pointer
+ // by SInformationElementHeader length before doing the cast
+ aCtxImpl.AtimWindow(
+ ( reinterpret_cast<const SIbssParameterSetIE*>(
+ elementData - sizeof( SInformationElementHeader ) )
+ )->AtimWindow() );
+ }
+ else
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::InitNetworkConnect: atim not present, PS not used"));
+
+ // as IBSS Parameter Set element is not present, power saving
+ // is not used in the IBSS network we are going to join. So we
+ // will set the ATIM window to zero (to denote that PS is not used)
+ aCtxImpl.AtimWindow( 0 );
+ }
+ }
+
+ //=============================================
+ // determine U-APSD usage for the ACs/Tx queues
+ //=============================================
+ DetermineAcUapsdUsage( aCtxImpl );
+
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetTxPowerLevel(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aLevel)
+ {
+ OsTracePrint(
+ KUmacDetails,
+ (TUint8*)
+ ("UMAC: WlanDot11State::SetTxPowerLevel(): aLevel: %d"),
+ aLevel );
+
+ // allocate memory for the mib to write
+ WHA::Sdot11CurrentTxPowerLevel* mib
+ = static_cast<WHA::Sdot11CurrentTxPowerLevel*>
+ (os_alloc( sizeof(WHA::Sdot11CurrentTxPowerLevel) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC * SetRcpiTriggerLevel * abort") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ mib->iDot11CurrentTxPowerLevel = aLevel;
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+
+ wha_cmd.Set(
+ aCtxImpl,
+ WHA::KMibDot11CurrentTxPowerLevel,
+ sizeof(*mib), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( mib ); // always remember to release the memory
+
+ // store the new power level also to our soft mib
+ aCtxImpl.iWlanMib.dot11CurrentTxPowerLevel = aLevel;
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::GetLastRcpi(
+ WlanContextImpl& aCtxImpl )
+ {
+ TBool statechange ( EFalse );
+ WHA::TRcpi whaRcpi( 0 );
+
+ if ( aCtxImpl.GetLatestMedianRcpiFromPredictor( os_systemTime(), whaRcpi ) )
+ {
+ // we have a median filtered RCPI value available so we can return that
+ // directly to WLAN Mgmt Client
+
+ // convert to a 32bit value before returning
+ const TInt32 rcpi ( whaRcpi );
+
+ OnOidComplete( aCtxImpl,
+ KErrNone,
+ reinterpret_cast<const TAny*>(&rcpi),
+ sizeof( rcpi ) );
+ }
+ else
+ {
+ // we need to get the RCPI from lower layers
+
+ WlanWsaReadMib& wha_cmd = aCtxImpl.WsaReadMib();
+ wha_cmd.Set( aCtxImpl, WHA::KMibStatisticsTable );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // previous state
+ wha_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ // signal caller that a state transition occurred
+ statechange = ETrue;
+ }
+
+ return statechange;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnPacketTransferComplete(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aPacketId,
+ TDataBuffer* aMetaHeader )
+ {
+ // complete the transfer
+ if ( aPacketId == E802Dot11FrameTypeData )
+ {
+ OnTxProtocolStackDataComplete( aCtxImpl, aMetaHeader );
+ }
+ else if ( aPacketId == E802Dot11FrameTypeDataEapol ||
+ aPacketId == E802Dot11FrameTypeManagementAction ||
+ aPacketId == E802Dot11FrameTypeTestFrame )
+ {
+ OnMgmtPathWriteComplete( aCtxImpl );
+
+ aCtxImpl.iUmac.OnOtherTxDataComplete();
+ }
+ else
+ {
+ // this frame Tx request didn't come from above us (i.e. neither
+ // through the user data nor the management data API) but is
+ // related to a frame Tx we have done internally. So, we need to
+ // mark the internal Tx buffer free again
+ aCtxImpl.MarkInternalTxBufFree();
+
+ aCtxImpl.iUmac.OnOtherTxDataComplete();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnPacketSendComplete(
+ WlanContextImpl& aCtxImpl,
+ WHA::TStatus aStatus,
+ TUint32 /*aPacketId*/,
+ WHA::TRate aRate,
+ TUint32 /*aPacketQueueDelay*/,
+ TUint32 /*aMediaDelay*/,
+ TUint /*aTotalTxDelay*/,
+ TUint8 /*aAckFailures*/,
+ WHA::TQueueId aQueueId,
+ WHA::TRate aRequestedRate,
+ TBool /*aMulticastData*/ )
+ {
+ aCtxImpl.OnTxCompleted( aRate,
+ static_cast<TBool>(aStatus == WHA::KSuccess),
+ aQueueId,
+ aRequestedRate );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::CallPacketSchedule(
+ WlanContextImpl& aCtxImpl,
+ TBool aMore )
+ {
+ aCtxImpl.SchedulePackets( aMore );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnPacketFlushEvent(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aPacketId,
+ TDataBuffer* aMetaHeader )
+ {
+ if ( aPacketId == E802Dot11FrameTypeData )
+ {
+ OnTxProtocolStackDataComplete( aCtxImpl, aMetaHeader );
+ }
+ else if ( aPacketId == E802Dot11FrameTypeDataEapol ||
+ aPacketId == E802Dot11FrameTypeManagementAction ||
+ aPacketId == E802Dot11FrameTypeTestFrame )
+ {
+ // complete with an error code if WLAN Mgmt Client frame
+ // transmit fails
+ OnMgmtPathWriteComplete( aCtxImpl, KErrGeneral );
+ }
+ else
+ {
+ // this frame Tx request didn't come from above us (i.e. neither
+ // through the user data nor the management data API) but is
+ // related to a frame Tx we have done internally. So there's
+ // nothing to complete upwards. But we need to mark the internal
+ // Tx buffer free again
+ aCtxImpl.MarkInternalTxBufFree();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::OnPacketPushPossible(
+ WlanContextImpl& /*aCtxImpl*/ )
+ {
+ // intentionally left empty
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::Indication(
+ WlanContextImpl& aCtxImpl,
+ WHA::TIndicationId aIndicationId,
+ const WHA::UIndicationParams& aIndicationParams )
+ {
+ switch ( aIndicationId )
+ {
+ case WHA::EError:
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WHA error indication received!") );
+ DoErrorIndication( aCtxImpl, aIndicationParams.iError.iStatus );
+ break;
+ case WHA::EBssLost:
+ DoConsecutiveBeaconsLostIndication( aCtxImpl );
+ break;
+ case WHA::EBSSRegained:
+ DoRegainedBSSIndication( aCtxImpl );
+ break;
+ case WHA::ERadar:
+ DoRadarIndication( aCtxImpl );
+ break;
+ case WHA::ERcpi:
+ DoRcpiIndication( aCtxImpl, aIndicationParams.iRcpi.iRcpi );
+ break;
+ case WHA::EPsModeError:
+ DoPsModeErrorIndication( aCtxImpl );
+ break;
+ default:
+ // implementation error
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: aIndicationId: %d"), aIndicationId );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureTxQueue(
+ WlanContextImpl& aCtxImpl,
+ WHA::TQueueId aQueueId,
+ TBool aCompleteManagementRequest )
+ {
+ OsTracePrint( KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::ConfigureTxQueue: aQueueId: %d"),
+ aQueueId );
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureTxQueue: aCompleteManagementRequest: %d"),
+ aCompleteManagementRequest );
+
+ WHA::TPsScheme psScheme( WHA::ERegularPs );
+
+ // enable U-APSD for the AC/Queue in question when necessary.
+ // Otherwise stick to regular PS
+ switch ( aQueueId )
+ {
+ case WHA::ELegacy:
+ if ( aCtxImpl.UapsdUsedForBestEffort() )
+ {
+ psScheme = WHA::EUapsd;
+ }
+ break;
+ case WHA::EBackGround:
+ if ( aCtxImpl.UapsdUsedForBackground() )
+ {
+ psScheme = WHA::EUapsd;
+ }
+ break;
+ case WHA::EVideo:
+ if ( aCtxImpl.UapsdUsedForVideo() )
+ {
+ psScheme = WHA::EUapsd;
+ }
+ break;
+ case WHA::EVoice:
+ if ( aCtxImpl.UapsdUsedForVoice() )
+ {
+ psScheme = WHA::EUapsd;
+ }
+ break;
+ default:
+ // catch programming error
+ OsTracePrint( KErrorLevel, (TUint8*)
+ ("UMAC: ERROR: unsupported queue, aQueueId: %d"), aQueueId );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ WlanWhaConfigureQueue& wha_command = aCtxImpl.WhaConfigureQueue();
+
+ wha_command.Set(
+ aQueueId,
+ aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[aQueueId],
+ psScheme,
+ WHA::ENormal,
+ aCtxImpl.iWlanMib.iMediumTime[aQueueId] );
+
+ const TUint32 KNoNeedToCompleteManagementRequest = 0;
+
+ // change global state: entry procedure triggers action
+ ChangeState(
+ aCtxImpl,
+ *this, // prev state
+ wha_command, // next state
+ aCompleteManagementRequest ? KCompleteManagementRequest :
+ KNoNeedToCompleteManagementRequest );
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureAcParams(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint(
+ KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::ConfigureAcParams") );
+
+ WlanWhaConfigureAc& wha_command = aCtxImpl.WhaConfigureAc();
+
+ wha_command.Set(
+ aCtxImpl.CwMinVector(),
+ aCtxImpl.CwMaxVector(),
+ aCtxImpl.AifsVector(),
+ aCtxImpl.TxOplimitVector() );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_command // next state
+ );
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetCtsToSelfMib(
+ WlanContextImpl& aCtxImpl )
+ {
+ WHA::SctsToSelf* mib
+ = static_cast<WHA::SctsToSelf*>
+ (os_alloc( sizeof( WHA::SctsToSelf ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel, (TUint8*)
+ ("UMAC: WlanDot11State::SetCtsToSelfMib(): memory allocation failed") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ if ( aCtxImpl.ProtectionBitSet() )
+ {
+ OsTracePrint(
+ KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::SetCtsToSelfMib(): enable CTS to self") );
+
+ mib->iCtsToSelf = ETrue;
+ }
+ else
+ {
+ OsTracePrint(
+ KUmacDetails,
+ (TUint8*)("UMAC: WlanDot11State::SetCtsToSelfMib(): disable CTS to self") );
+
+ mib->iCtsToSelf = EFalse;
+ }
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+ wha_cmd.Set(
+ aCtxImpl, WHA::KMibCtsToSelf, sizeof(*mib), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd // next state
+ );
+
+ // as the parameters have been supplied we can now deallocate
+ os_free( mib );
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureBssLost(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aBeaconLostCount,
+ TUint8 aFailedTxPacketCount )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureBssLost") );
+
+ // store & take the new failed Tx packet count threshold into use
+ aCtxImpl.iWlanMib.iFailedTxPacketCountThreshold = aFailedTxPacketCount;
+ // set the beacon lost count mib
+ return SetBeaconLostCountMib( aCtxImpl, aBeaconLostCount );
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetTxRateAdaptParams(
+ WlanContextImpl& aCtxImpl,
+ TUint8 aMinStepUpCheckpoint,
+ TUint8 aMaxStepUpCheckpoint,
+ TUint8 aStepUpCheckpointFactor,
+ TUint8 aStepDownCheckpoint,
+ TUint8 aMinStepUpThreshold,
+ TUint8 aMaxStepUpThreshold,
+ TUint8 aStepUpThresholdIncrement,
+ TUint8 aStepDownThreshold,
+ TBool aDisableProbeHandling )
+ {
+ aCtxImpl.SetTxRateAdaptationAlgorithmParams(
+ aMinStepUpCheckpoint,
+ aMaxStepUpCheckpoint,
+ aStepUpCheckpointFactor,
+ aStepDownCheckpoint,
+ aMinStepUpThreshold,
+ aMaxStepUpThreshold,
+ aStepUpThresholdIncrement,
+ aStepDownThreshold,
+ aDisableProbeHandling );
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// At this point we only store the provided configuration data. It will be
+// taken into use when we know the nw we are going to join - i.e. just prior
+// actually joining that nw
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureTxRatePolicies(
+ WlanContextImpl& aCtxImpl,
+ const TTxRatePolicy& aRatePolicy,
+ const TQueue2RateClass& aQueue2RateClass,
+ const TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass,
+ const TTxAutoRatePolicy& aAutoRatePolicy,
+ const THtMcsPolicy& aHtMcsPolicy )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureTxRatePolicies"));
+
+ StoreTxRatePolicyInfo(
+ aCtxImpl,
+ aRatePolicy,
+ aQueue2RateClass,
+ aInitialMaxTxRate4RateClass,
+ aAutoRatePolicy,
+ aHtMcsPolicy );
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetPowerModeManagementParameters(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aToLightPsTimeout,
+ TUint16 aToLightPsFrameThreshold,
+ TUint32 aToActiveTimeout,
+ TUint16 aToActiveFrameThreshold,
+ TUint32 aToDeepPsTimeout,
+ TUint16 aToDeepPsFrameThreshold,
+ TUint16 aUapsdRxFrameLengthThreshold )
+ {
+ aCtxImpl.SetPowerModeManagementParameters(
+ aToLightPsTimeout,
+ aToLightPsFrameThreshold,
+ aToActiveTimeout,
+ aToActiveFrameThreshold,
+ aToDeepPsTimeout,
+ aToDeepPsFrameThreshold,
+ aUapsdRxFrameLengthThreshold );
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigurePwrModeMgmtTrafficOverride(
+ WlanContextImpl& aCtxImpl,
+ TBool aStayInPsDespiteUapsdVoiceTraffic,
+ TBool aStayInPsDespiteUapsdVideoTraffic,
+ TBool aStayInPsDespiteUapsdBestEffortTraffic,
+ TBool aStayInPsDespiteUapsdBackgroundTraffic,
+ TBool aStayInPsDespiteLegacyVoiceTraffic,
+ TBool aStayInPsDespiteLegacyVideoTraffic,
+ TBool aStayInPsDespiteLegacyBestEffortTraffic,
+ TBool aStayInPsDespiteLegacyBackgroundTraffic )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigurePwrModeMgmtTrafficOverride"));
+
+ aCtxImpl.ConfigurePwrModeMgmtTrafficOverride(
+ aStayInPsDespiteUapsdVoiceTraffic,
+ aStayInPsDespiteUapsdVideoTraffic,
+ aStayInPsDespiteUapsdBestEffortTraffic,
+ aStayInPsDespiteUapsdBackgroundTraffic,
+ aStayInPsDespiteLegacyVoiceTraffic,
+ aStayInPsDespiteLegacyVideoTraffic,
+ aStayInPsDespiteLegacyBestEffortTraffic,
+ aStayInPsDespiteLegacyBackgroundTraffic );
+
+ // Note, that in this case the dynamic power mode mgmt traffic
+ // override/ignoration settings will be frozen later (during connect
+ // operation, once we know the network capabilites) so that they become
+ // effective
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::GetFrameStatistics( WlanContextImpl& aCtxImpl )
+ {
+ WlanWsaReadMib& wha_cmd = aCtxImpl.WsaReadMib();
+ wha_cmd.Set( aCtxImpl, WHA::KMibCountersTable );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // previous state
+ wha_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ // signal caller that state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// At this point we only store the values provided by WLAN mgmt client. They
+// will be used later when we (re-)associate to an AP.
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureUapsd(
+ WlanContextImpl& aCtxImpl,
+ TMaxServicePeriodLength aMaxServicePeriodLength,
+ TBool aUapsdForVoice,
+ TBool aUapsdForVideo,
+ TBool aUapsdForBestEffort,
+ TBool aUapsdForBackground )
+ {
+ // this cast is safe as the types are effectively the same
+ aCtxImpl.UapsdMaxSpLen() =
+ static_cast<TQosInfoUapsdMaxSpLen>(aMaxServicePeriodLength);
+
+ aCtxImpl.UapsdRequestedForVoice( aUapsdForVoice );
+ aCtxImpl.UapsdRequestedForVideo( aUapsdForVideo );
+ aCtxImpl.UapsdRequestedForBestEffort( aUapsdForBestEffort );
+ aCtxImpl.UapsdRequestedForBackground( aUapsdForBackground );
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::GetMacAddress(
+ WlanContextImpl& aCtxImpl )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::GetMacAddress: mac address:"),
+ aCtxImpl.iWlanMib.dot11StationId );
+
+ OnOidComplete(
+ aCtxImpl,
+ KErrNone,
+ &(aCtxImpl.iWlanMib.dot11StationId),
+ sizeof(aCtxImpl.iWlanMib.dot11StationId) );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureArpIpAddressFiltering(
+ WlanContextImpl& aCtxImpl,
+ TBool aEnableFiltering,
+ TIpv4Address aIpv4Address )
+ {
+ return SetArpIpAddressTableMib(
+ aCtxImpl,
+ aEnableFiltering,
+ aIpv4Address );
+ }
+
+// -----------------------------------------------------------------------------
+// At this point we only store the provided configuration.
+// It will be passed to the lower layers when connecting to a HT network
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureHtBlockAck(
+ WlanContextImpl& aCtxImpl,
+ TUint8 aTxBlockAckUsage,
+ TUint8 aRxBlockAckUsage )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureHtBlockAck()") );
+
+ WHA::ShtBlockAckConfigure& blockAckConf (
+ aCtxImpl.GetHtBlockAckConfigure() );
+ blockAckConf.iTxBlockAckUsage = aTxBlockAckUsage;
+ blockAckConf.iRxBlockAckUsage = aRxBlockAckUsage;
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureProprietarySnapHdr(
+ WlanContextImpl& aCtxImpl,
+ const TSnapHeader& aSnapHeader )
+ {
+ OsTracePrint( KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureProprietarySnapHdr") );
+
+ // store the provided SNAP header for later use
+ os_memcpy(
+ reinterpret_cast<TUint8*>(&(aCtxImpl.GetProprietarySnapHeader())),
+ reinterpret_cast<const TUint8*>(&aSnapHeader),
+ sizeof( SSnapHeader ) );
+
+ OnOidComplete( aCtxImpl, KErrNone );
+
+ // signal caller that no state transition occurred
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::SetBeaconLostCountMib(
+ WlanContextImpl& aCtxImpl,
+ TUint32 aBeaconLostCount )
+ {
+ OsTracePrint(
+ KUmacDetails, (TUint8*)
+ ("UMAC: WlanDot11State::SetBeaconLostCountMib(): aBeaconLostCount: %d"),
+ aBeaconLostCount );
+
+ // allocate memory for the mib to write
+ WHA::SbeaconLostCount* mib
+ = static_cast<WHA::SbeaconLostCount*>
+ (os_alloc( sizeof( WHA::SbeaconLostCount ) ));
+
+ if ( !mib )
+ {
+ // allocation failed
+ // simulate macnotresponding error
+ OsTracePrint( KWarningLevel,
+ (TUint8*)("UMAC: WlanDot11State::SetBeaconLostCountMib: abort") );
+ return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+ }
+
+ mib->iLostCount = aBeaconLostCount;
+
+ WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+
+ wha_cmd.Set(
+ aCtxImpl,
+ WHA::KMibBeaconLostCount,
+ sizeof(*mib), mib );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wha_cmd, // next state
+ // the ACT
+ KCompleteManagementRequest
+ );
+
+ os_free( mib ); // always remember to release the memory
+
+ // store the new beacon lost count also to our soft mib
+ aCtxImpl.iWlanMib.iBeaconLostCount = aBeaconLostCount;
+
+ // signal caller that a state transition occurred
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ResortToSingleTxRatePolicy(
+ WlanContextImpl& aCtxImpl,
+ TTxRatePolicy& aRatePolicy,
+ TQueue2RateClass& aQueue2RateClass ) const
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ResortToSingleTxRatePolicy: WARNING: PDD "
+ "supports only %d policy objects ... "),
+ aCtxImpl.WHASettings().iNumOfTxRateClasses );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: ... and %d objects have been provided to us"),
+ aRatePolicy.numOfPolicyObjects );
+
+ // In this case - from the rate classes / autorate policies provided to
+ // us by WLAN Mgmt client - we will use only the rate class / autorate
+ // policy specified for legacy Tx Queue / AC, i.e. the 1st one at index 0
+
+ aRatePolicy.numOfPolicyObjects = 1;
+ for ( TUint queueId = ELegacy; queueId < EQueueIdMax; ++queueId )
+ {
+ aQueue2RateClass[queueId] = 0;
+ }
+
+#ifndef NDEBUG
+ if ( (aCtxImpl.Queue2RateClass())[ELegacy] != 0 )
+ {
+ OsTracePrint( KErrorLevel | KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ResortToSingleTxRatePolicy: ERROR: policy "
+ "for legacy not specified as the 1st in the policy array") );
+ OsAssert( (TUint8*)("UMAC: panic"),
+ (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::FinalizeTxRatePolicy(
+ WlanContextImpl& aCtxImpl,
+ TTxRatePolicy& aRatePolicy,
+ TWhaRateMasks& aRateMasks,
+ TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass ) const
+ {
+ for ( TUint rateClassInd = 0;
+ rateClassInd < aRatePolicy.numOfPolicyObjects;
+ ++rateClassInd )
+ {
+ // build a rate mask as an "intersection" of
+ // rates in the provided rate class AND
+ // rates supported by the nw and AND
+ // rates supported by WHA layer.
+ // Also keep the nbr of tx attempts in the rate class for a particular
+ // rate if that rate is supported by both the nw and WHA layer.
+ // Otherwise set the nbr of tx attemps to zero for that rate
+
+ HandleRates(
+ aCtxImpl,
+ aRatePolicy.txRateClass[rateClassInd],
+ aRateMasks[rateClassInd] );
+
+ if ( !( aRateMasks[rateClassInd] ) )
+ {
+ // the provided rate class was such that we ended up with an empty
+ // rate mask. To recover from this situation we will update the
+ // rate class definition on the fly to contain the rates which both
+ // the WHA layer and the nw support
+ RecoverRatePolicy(
+ aCtxImpl,
+ aRatePolicy,
+ rateClassInd,
+ aRateMasks[rateClassInd] );
+ // adjust also the Max Tx Rate for this rate class so that the
+ // highest possible rate will be used initially
+ aInitialMaxTxRate4RateClass[rateClassInd] = WHA::KRate54Mbits;
+ }
+ } // for
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::HandleRate(
+ WlanContextImpl& aCtxImpl,
+ WHA::TRate aRate,
+ TUint8& aTxAttempts,
+ WHA::TRate& aRateMask ) const
+ {
+ if ( aCtxImpl.RateBitMask() & aRate )
+ {
+ // rate is supported both by us and by the nw.
+
+ if ( aTxAttempts )
+ {
+ // non-zero Tx attempts defined => include the rate in dynamic Tx
+ // rate adaptation rates
+ aRateMask |= aRate;
+ }
+ }
+ else
+ {
+ // rate is not supported either by us or by the nw. Set zero Tx attempts
+ aTxAttempts = 0;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::HandleRates(
+ WlanContextImpl& aCtxImpl,
+ TTxRateClass& aRateClass,
+ WHA::TRate& aRateMask ) const
+ {
+ HandleRate( aCtxImpl, WHA::KRate54Mbits, aRateClass.txPolicy54,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate48Mbits, aRateClass.txPolicy48,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate36Mbits, aRateClass.txPolicy36,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate33Mbits, aRateClass.txPolicy33,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate24Mbits, aRateClass.txPolicy24,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate22Mbits, aRateClass.txPolicy22,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate18Mbits, aRateClass.txPolicy18,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate12Mbits, aRateClass.txPolicy12,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate11Mbits, aRateClass.txPolicy11,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate9Mbits, aRateClass.txPolicy9,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate6Mbits, aRateClass.txPolicy6,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate5_5Mbits, aRateClass.txPolicy5_5,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate2Mbits, aRateClass.txPolicy2,
+ aRateMask );
+
+ HandleRate( aCtxImpl, WHA::KRate1Mbits, aRateClass.txPolicy1,
+ aRateMask );
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::HandleRates: resulting rate mask: 0x%08x"),
+ aRateMask );
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::RecoverRatePolicy(
+ WlanContextImpl& aCtxImpl,
+ TTxRatePolicy& aRatePolicy,
+ TUint aRateClassInd,
+ WHA::TRate& aRateMask ) const
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::RecoverRatePolicy: aRateClassInd: %d"),
+ aRateClassInd );
+
+ const TUint8 KTxAttempts = 1;
+
+ // start with Tx attempts == 1 for all Tx rates
+ os_memset(
+ &aRatePolicy.txRateClass[aRateClassInd],
+ KTxAttempts,
+ sizeof( TUint8 ) * KMaxNumberOfDot11bAndgRates );
+
+ HandleRates( aCtxImpl, aRatePolicy.txRateClass[aRateClassInd], aRateMask );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::FinalizeTxAutoratePolicy(
+ WlanContextImpl& aCtxImpl,
+ const TTxRatePolicy& aRatePolicy,
+ TTxAutoRatePolicy& aAutoRatePolicy ) const
+ {
+ for ( TUint rateClassInd = 0;
+ rateClassInd < aRatePolicy.numOfPolicyObjects;
+ ++rateClassInd )
+ {
+ // build a rate mask as an "intersection" of
+ // rates in the provided auto rate class AND
+ // rates supported by the nw and AND
+ // rates supported by WHA layer.
+ aAutoRatePolicy[rateClassInd] =
+ aAutoRatePolicy[rateClassInd] & aCtxImpl.RateBitMask();
+
+ if ( !( aAutoRatePolicy[rateClassInd] ) )
+ {
+ // the provided rate class was such that we ended up with an
+ // empty rate mask. To recover from this situation we will
+ // update the rate class definition on the fly to contain
+ // the rates which both the WHA layer and the nw support
+ aAutoRatePolicy[rateClassInd] = aCtxImpl.RateBitMask();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::SpecialTxAutoratePolicy(
+ WlanContextImpl& aCtxImpl,
+ TTxRatePolicy& aRatePolicy,
+ TTxAutoRatePolicy& aAutoRatePolicy,
+ THtMcsPolicy& aHtMcsPolicy ) const
+ {
+ if ( aRatePolicy.numOfPolicyObjects >=
+ aCtxImpl.WHASettings().iNumOfTxRateClasses )
+ {
+ // there's no room in the lower layers for a special policy
+ // disable special policy use
+ aCtxImpl.SpecialTxAutoRatePolicy( 0 );
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::SpecialTxAutoratePolicy: no room") );
+
+ return;
+ }
+
+ const TUint KMaxNbrOfItemsToPick(1);
+
+ // start with an empty rate mask
+ aAutoRatePolicy[aRatePolicy.numOfPolicyObjects] = 0;
+
+ const WHA::TRate commonRates( aCtxImpl.RateBitMask() );
+
+ // pick the 802.11b/g rate(s) for the special policy
+
+ WHA::TRate rate( WHA::KRate1Mbits );
+ TUint cntPicked(0);
+ do
+ {
+ if ( rate & commonRates )
+ {
+ aAutoRatePolicy[aRatePolicy.numOfPolicyObjects] |= rate;
+ ++cntPicked;
+ }
+
+ rate <<= 1;
+ } while ( ( cntPicked < KMaxNbrOfItemsToPick ) &&
+ ( rate <= KRate54Mbits ) );
+
+ // start with an empty MCS set
+ for ( TUint mcsBucket = 0;
+ mcsBucket < WHA::KHtMcsSetLength;
+ ++mcsBucket )
+ {
+ aHtMcsPolicy[aRatePolicy.numOfPolicyObjects][mcsBucket] = 0;
+ }
+
+ // pick the 802.11n MCS(s) for the special policy
+
+ const SHtCapabilitiesIE& htCapabilitiesIe(
+ aCtxImpl.GetNwHtCapabilitiesIe() );
+ const TUint KLastMcsBucket = WHA::KHtMcsSetLength - 1;
+ const TUint8 KMcsCountInLastBucket( 5 );
+ TUint8 mcsCount( 8 );
+
+ cntPicked = 0;
+ TUint mcsBucket = 0;
+ do
+ {
+ if ( mcsBucket == KLastMcsBucket )
+ {
+ // there are only 5 MCSs in the last "bucket" per 802.11n std.
+ mcsCount = KMcsCountInLastBucket;
+ }
+
+ TUint8 mcs(1);
+ TUint mcsCounter( 0 );
+ do
+ {
+ if ( mcs &
+ ( aCtxImpl.WHASettings().iHtCapabilities.iTxMcs[mcsBucket] ) &
+ ( htCapabilitiesIe.iData.iRxMcsBitmask[mcsBucket] ) )
+ {
+ aHtMcsPolicy[aRatePolicy.numOfPolicyObjects][mcsBucket] |= mcs;
+ ++cntPicked;
+ }
+
+ mcs <<= 1;
+ ++mcsCounter;
+ } while ( ( cntPicked < KMaxNbrOfItemsToPick ) &&
+ ( mcsCounter < mcsCount ) );
+
+ ++mcsBucket;
+ } while ( ( cntPicked < KMaxNbrOfItemsToPick ) &&
+ ( mcsBucket < WHA::KHtMcsSetLength ) );
+
+ // set the retry counts
+ //
+ const TUint8 KSpecialShortRetryLimit = 10;
+ const TUint8 KSpecialLongRetryLimit = 4;
+ aRatePolicy.txRateClass[aRatePolicy.numOfPolicyObjects].shortRetryLimit =
+ KSpecialShortRetryLimit;
+ aRatePolicy.txRateClass[aRatePolicy.numOfPolicyObjects].longRetryLimit =
+ KSpecialLongRetryLimit;
+
+ // now we have an additional policy
+ ++(aRatePolicy.numOfPolicyObjects);
+ // enable special policy use
+ aCtxImpl.SpecialTxAutoRatePolicy( aRatePolicy.numOfPolicyObjects );
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::SpecialTxAutoratePolicy: policy id: %d"),
+ aRatePolicy.numOfPolicyObjects );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::ConfigureForTxAutoratePolicy(
+ WlanContextImpl& aCtxImpl,
+ const TTxRatePolicy& aRatePolicy,
+ const TQueue2RateClass& aQueue2RateClass,
+ THtMcsPolicy& aHtMcsPolicy,
+ TBool aCompleteMgmtRequest )
+ {
+ // store the Tx queue to rate class mapping
+ for ( TUint queueId = ELegacy; queueId < EQueueIdMax; ++queueId )
+ {
+ aCtxImpl.SetTxRatePolicy(
+ static_cast<WHA::TQueueId>(queueId),
+ // rate class ids start from 1, hence the + 1
+ aQueue2RateClass[queueId] + 1 );
+ }
+
+ // make sure that our MCS policy contains only MCSs that both the NW
+ // and the lower layers support
+ HandleHtMcsPolicy(
+ aCtxImpl,
+ aHtMcsPolicy,
+ aRatePolicy.numOfPolicyObjects );
+
+ // change to the state which performs the rest of the configuration
+
+ WlanConfigureTxAutoRatePolicy& complexWhaCmd(
+ aCtxImpl.ConfigureTxAutoRatePolicy() );
+
+ complexWhaCmd.Set( aCompleteMgmtRequest );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ complexWhaCmd // next state
+ );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void WlanDot11State::HandleHtMcsPolicy(
+ WlanContextImpl& aCtxImpl,
+ THtMcsPolicy& aHtMcsPolicy,
+ TUint aNbrOfMcsSets ) const
+ {
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleHtMcsPolicy") );
+
+ const SHtCapabilitiesIE& htCapabilitiesIe(
+ aCtxImpl.GetNwHtCapabilitiesIe() );
+
+ for ( TUint mcsSet = 0; mcsSet < aNbrOfMcsSets; ++mcsSet )
+ {
+ for ( TUint mcsBucket = 0;
+ mcsBucket < WHA::KHtMcsSetLength;
+ ++mcsBucket )
+ {
+ aHtMcsPolicy[mcsSet][mcsBucket] =
+ aCtxImpl.WHASettings().iHtCapabilities.iTxMcs[mcsBucket] &
+ htCapabilitiesIe.iData.iRxMcsBitmask[mcsBucket] &
+ aHtMcsPolicy[mcsSet][mcsBucket];
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11State::ConfigureForTxRatePolicy(
+ WlanContextImpl& aCtxImpl,
+ const TTxRatePolicy& aRatePolicy,
+ const TWhaRateMasks& aRateMasks,
+ const TQueue2RateClass& aQueue2RateClass,
+ const TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass,
+ TBool aCompleteMgmtRequest )
+ {
+ for ( TUint rateClassInd = 0;
+ rateClassInd < aRatePolicy.numOfPolicyObjects;
+ ++rateClassInd )
+ {
+ // provide the ratemask for this rate class to rate adaptation.
+ // Rate class ids start from 1, hence the + 1
+ if ( !aCtxImpl.SetTxRateAdaptationRates(
+ rateClassInd + 1,
+ aRateMasks[rateClassInd] ) )
+ {
+ // alloc failure; we cannot continue
+ OsTracePrint( KWarningLevel | KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanDot11State::ConfigureForTxRatePolicy: WARNING: "
+ "alloc failure in rate adaptation"));
+
+ return EFalse; // indicate fatal error
+ }
+
+ // set the initial max Tx rate for this rate class
+
+ aCtxImpl.SetCurrentMaxTxRate(
+ // rate class ids start from 1, hence the + 1
+ rateClassInd + 1,
+ aInitialMaxTxRate4RateClass[rateClassInd] );
+ }
+
+ // inform rate adaptation about the Tx queue to rate class mapping
+ for ( TUint queueId = ELegacy; queueId < EQueueIdMax; ++queueId )
+ {
+ aCtxImpl.SetTxRatePolicy(
+ static_cast<WHA::TQueueId>(queueId),
+ // rate class ids start from 1, hence the + 1
+ aQueue2RateClass[queueId] + 1 );
+ }
+
+ // update the Rate Policy MIB
+
+ WlanWsaWriteMib& wsa_cmd = aCtxImpl.WsaWriteMib();
+
+ const TUint16 mibLength = sizeof( WHA::StxRatePolicy )
+ // there is space for one policy object (rate class) in the
+ // StxRatePolicy struct, so space for any additional objects needs to
+ // be allocated in addition to that
+ + sizeof( WHA::StxRateClass ) *
+ ( aRatePolicy.numOfPolicyObjects - 1 );
+
+ wsa_cmd.Set(
+ aCtxImpl,
+ WHA::KMibTxRatePolicy,
+ mibLength,
+ // note that the types WHA::StxRatePolicy and TTxRatePolicy are
+ // effectively equivalent, so this is ok
+ &aRatePolicy );
+
+ const TUint32 KNotNecessary2Complete ( 0 );
+
+ // change global state: entry procedure triggers action
+ ChangeState( aCtxImpl,
+ *this, // prev state
+ wsa_cmd, // next state
+ aCompleteMgmtRequest ? KCompleteManagementRequest :
+ KNotNecessary2Complete
+ );
+
+ return ETrue; // indicate success & state change
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::HandleHtCapabilities(
+ WlanContextImpl& aCtxImpl,
+ WlanElementLocator& aElementLocator ) const
+ {
+ TBool status ( ETrue );
+ TUint8 elementDatalength( 0 );
+ const TUint8* elementData( NULL );
+
+ // try to locate HT capabilities element
+ if ( aElementLocator.InformationElement(
+ E802Dot11HtCapabilitiesIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // found, so store it to our context
+ aCtxImpl.GetNwHtCapabilitiesIe().SetIeData(
+ elementData,
+ elementDatalength );
+
+ // this also means that the target nw supports HT
+ aCtxImpl.HtSupportedByNw( ETrue );
+
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleHtCapabilities: HT capabilities element present => HT supported by nw") );
+ }
+ else
+ {
+ // not found => target nw doesn't support HT
+ aCtxImpl.HtSupportedByNw( EFalse );
+
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleHtCapabilities: HT capabilities element not found") );
+ }
+
+ return status;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::HandleHtOperation(
+ WlanContextImpl& aCtxImpl,
+ WlanElementLocator& aElementLocator ) const
+ {
+ TBool status ( ETrue );
+ TUint8 elementDatalength( 0 );
+ const TUint8* elementData( NULL );
+
+ // try to locate HT Operation element
+ if ( aElementLocator.InformationElement(
+ E802Dot11HtOperationIE,
+ elementDatalength,
+ &elementData ) == WlanElementLocator::EWlanLocateOk )
+ {
+ // found, so store it to our context
+ aCtxImpl.GetNwHtOperationIe().SetIeData(
+ elementData,
+ elementDatalength );
+
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleHtOperation: element present") );
+ }
+ else
+ {
+ // not found even though HT capabilities element is present =>
+ // protocol error
+ status = EFalse;
+
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleHtOperation: element not found => protocol error") );
+ }
+
+ return status;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11State::HandleDot11n(
+ WlanContextImpl& aCtxImpl,
+ WlanElementLocator& aElementLocator ) const
+ {
+ TBool status ( ETrue );
+
+ if ( ( aCtxImpl.PairwiseCipher() == EWlanCipherSuiteTkip ) ||
+ !( aCtxImpl.QosEnabled() ) )
+ {
+ // as the control is here it means that
+ // - the WLAN vendor implementation
+ // supports HT AND EITHER
+ // - TKIP will be used as the pairwise cipher OR
+ // - the target nw doesn't support WMM
+ // In these cases we must not use HT functionality, even if the target
+ // nw supported it. We achieve that by handling the target nw as
+ // a non-HT nw
+ aCtxImpl.HtSupportedByNw( EFalse );
+
+ OsTracePrint( KInfoLevel, (TUint8*)
+ ("UMAC: WlanDot11State::HandleDot11n: TKIP as pairwise cipher "
+ "or WMM not supported => HT disabled") );
+ }
+ else
+ {
+ status = HandleHtCapabilities( aCtxImpl, aElementLocator ) ;
+
+ // if HT capabilities element is present and ok
+ if ( aCtxImpl.HtSupportedByNw() && status )
+ {
+ // check also HT Operation element
+ status = HandleHtOperation( aCtxImpl, aElementLocator );
+ }
+ }
+
+ return status;
+ }