diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_common/umac_common/src/umacdot11idlescanningmode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/umacdot11idlescanningmode.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,728 @@ +/* +* Copyright (c) 2005-2008 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 WlanDot11IdleScanningMode class. +* +*/ + +/* +* %version: 19 % +*/ + +#include "config.h" +#include "umacdot11idlescanningmode.h" +#include "umacscanfsmcntx.h" +#include "UmacContextImpl.h" +#include "UmacWsaWriteMib.h" +#include "UmacWsaScan.h" +#include "umacwhastopscan.h" +#include "umacwhatodot11typeconverter.h" + +#ifndef NDEBUG +const TInt8 WlanDot11IdleScanningMode::iName[] = "dot11-idlescanningmode"; + +const TUint8 WlanDot11IdleScanningMode::iStateName + [ESTATEMAX][KMaxStateStringLength] = + { + {"EINIT"}, + {"ESETSLEEPMODE"}, + {"EEXECUTESCANFSM"}, + {"ECONTINUEDOT11TRAVERSE"} + }; + +const TUint8 WlanDot11IdleScanningMode::iEventName + [EEVENTMAX][KMaxEventStringLength] = + { + {"ESTATEENTRY"}, + {"ETXCOMPLETE"}, + {"ESTARTSCANNINGMODE"}, + {"ESCANMODERUNNING"}, + {"ESTOPSCANNINGMODE"}, + {"ESCANNINGMODEEXIT"}, + {"EABORT"} + }; +#endif + +// ======== MEMBER FUNCTIONS ======== + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanDot11IdleScanningMode::~WlanDot11IdleScanningMode() + { + iCtxImpl = NULL; + iChannels = NULL; + iSSID = NULL; + iPimpl = NULL; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::Set( + WlanContextImpl& aCtxImpl ) + { + iCtxImpl = &aCtxImpl; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::Set( + TScanMode aMode, + const TSSID& aSSID, + TUint32 aScanRate, + SChannels& aChannels, + TUint32 aMinChannelTime, + TUint32 aMaxChannelTime, + TBool aSplitScan ) + { + // we can store pointers as oid parameters are guaranteed to be valid + // to the point the corresponding completion method is called + iMode = aMode; + iSSID = &aSSID; + iScanRate = aScanRate; + iChannels = &aChannels; + iMinChannelTime = aMinChannelTime; + iMaxChannelTime = aMaxChannelTime; + iSplitScan = aSplitScan; + } + +// ----------------------------------------------------------------------------- +// The internal state transition method. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::ChangeInternalState( + WlanContextImpl& aCtxImpl, + TState aNewState ) + { + iState = aNewState; + Fsm( aCtxImpl, ESTATEENTRY ); + } + +// ----------------------------------------------------------------------------- +// The event dispatcher method. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::Fsm( + WlanContextImpl& aCtxImpl, + TEvent aEvent ) + { + OsTracePrint( KScan, + (TUint8*)("UMAC * dot11-idlescanningmode * FSM EVENT") ); +#ifndef NDEBUG + OsTracePrint( KScan, (TUint8*)("event:")); + OsTracePrint( KScan, iEventName[aEvent] ); + OsTracePrint( KScan, (TUint8*)("state:")); + OsTracePrint( KScan, iStateName[iState] ); +#endif + + switch ( aEvent ) + { + case ESTATEENTRY: + OnStateEntryEvent( aCtxImpl ); + break; + case ETXCOMPLETE: + OnTxCompleteEvent( aCtxImpl ); + break; + case ESTARTSCANNINGMODE: + OnStartScanningModeEvent( aCtxImpl ); + break; + case ESCANMODERUNNING: + OnScanModeRunningEvent( aCtxImpl ); + break; + case ESTOPSCANNINGMODE: + OnStopScanningModeEvent( aCtxImpl ); + break; + case ESCANNINGMODEEXIT: + OnScanningModeExitEvent( aCtxImpl ); + break; + case EABORT: + OnAbortEvent( aCtxImpl ); + break; + default: + // catch internal FSM programming error +#ifndef NDEBUG + OsTracePrint( KErrorLevel, (TUint8*)("event:")); + OsTracePrint( KErrorLevel, iEventName[aEvent] ); +#endif + OsAssert( (TUint8*)("* UMAC * panic"), + (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnStateEntryEvent( + WlanContextImpl& aCtxImpl ) + { + switch ( iState ) + { + case EINIT: + iPimpl = static_cast + (os_alloc( sizeof(WlanScanFsmCntx) )); + if ( iPimpl ) + { + // allocation success + new (iPimpl) WlanScanFsmCntx( *this ); + // start fsm traversal + if ( aCtxImpl.Reassociate() ) + { + // a roaming case + ChangeInternalState( aCtxImpl, EEXECUTESCANFSM ); + } + else + { + // not a roaming case + ChangeInternalState( aCtxImpl, ESETSLEEPMODE ); + } + } + else + { + // allocation failure + Fsm( aCtxImpl, EABORT ); + } + + break; + case ESETSLEEPMODE: + SetSleepMode( aCtxImpl ); + break; + case EEXECUTESCANFSM: + ExecuteScanFsm( aCtxImpl ); + break; + case ECONTINUEDOT11TRAVERSE: + ContinueDot11StateTraversal( aCtxImpl ); + break; + default: + // catch internal FSM programming error +#ifndef NDEBUG + OsTracePrint( KErrorLevel, (TUint8*)("state:")); + OsTracePrint( KErrorLevel, iStateName[iState] ); +#endif + OsAssert( (TUint8*)("* UMAC * panic"), + (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnTxCompleteEvent( + WlanContextImpl& aCtxImpl ) + { + switch ( iState ) + { + case ESETSLEEPMODE: + ChangeInternalState( aCtxImpl, EEXECUTESCANFSM ); + break; + case EEXECUTESCANFSM: + // we are running the scan fsm + // and we have nothing to do here + break; + default: + // catch internal FSM programming error +#ifndef NDEBUG + OsTracePrint( KErrorLevel, (TUint8*)("state:")); + OsTracePrint( KErrorLevel, iStateName[iState] ); +#endif + OsAssert( (TUint8*)("* UMAC * panic"), + (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnStartScanningModeEvent( + WlanContextImpl& aCtxImpl ) + { + // start the scanning mode + + // convert scan parameters to WHA types + // Note that we need to deallocate the memory from whaChannels + // - which is allocated in ConvertToWhaTypes() - when we are done + + WHA::SSSID* wha_ssid = + static_cast(os_alloc( sizeof(WHA::SSSID) )); + if ( !wha_ssid ) + { + // memory allocation failue; that's fatal + Fsm( aCtxImpl, EABORT ); + return; + } + + WHA::SChannels* wha_channels( NULL ); + TUint8 wha_channelcount( 0 ); + + if ( !(WlanWhaToDot11TypeConverter::ConvertToWhaTypes( + aCtxImpl, + iSSID, + *wha_ssid, + iChannels, + iMinChannelTime, + iMaxChannelTime, + wha_channels, + wha_channelcount )) ) + { + // memory allocation failue; that's fatal + os_free( wha_ssid ); + Fsm( aCtxImpl, EABORT ); + } + else + { + // start the scanning process + + const TUint8 KNbrOfProbeReqsPerCh = 2; + const TUint8 KNoProbeReqs = 0; + const TUint8 KNbrOfSsids = 1; + const TUint8 KNoSsids = 0; + + // 1st set the context + aCtxImpl.WsaScan().Set( + aCtxImpl, + iScanRate, + iChannels->iBand, + wha_channelcount, + wha_channels, + WHA::EFgScan, + (iMode == EActiveScan) ? KNbrOfProbeReqsPerCh : KNoProbeReqs, + iSplitScan, + wha_ssid->iSSIDLength ? KNbrOfSsids : KNoSsids, + wha_ssid ); + + // change global state: entry procedure triggers action + ChangeState( aCtxImpl, + *this, // prev state + aCtxImpl.WsaScan() // next state + ); + + // as the parameters have been supplied we can now deallocate + os_free( wha_ssid ); + os_free( wha_channels ); + } + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnScanModeRunningEvent( + WlanContextImpl& aCtxImpl ) const + { + // complete the scan request + + OsTracePrint( KScan, (TUint8*) + ("UMAC: WlanDot11IdleScanningMode::OnScanModeRunningEvent: Complete scan request") ); + OnOidComplete( aCtxImpl ); + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnStopScanningModeEvent( + WlanContextImpl& aCtxImpl ) + { + // change global state: entry procedure triggers action + ChangeState( aCtxImpl, + *this, // prev state + aCtxImpl.WhaStopScan() // next state + ); + } + +// ----------------------------------------------------------------------------- +// Handler for the event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnScanningModeExitEvent( + WlanContextImpl& aCtxImpl ) + { + // scanning mode has stopped and so can we + + // request the next state (dot11IdleState) to inform the mgmt client about + // scan completion upon state entry + aCtxImpl.iStates.iIdleState.CompleteScanUponEntry(); + + ChangeInternalState( aCtxImpl, ECONTINUEDOT11TRAVERSE ); + } + +// --------------------------------------------------------- +// simulate macnotresponding error +// --------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnAbortEvent( + WlanContextImpl& aCtxImpl ) + { + OsTracePrint( KWarningLevel, + (TUint8*)("UMAC * dot11-idlescanningmode * abort") ); + + DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::SetSleepMode( + WlanContextImpl& aCtxImpl ) + { + WHA::SsleepMode* mib + = static_cast + (os_alloc( sizeof( WHA::SsleepMode ) )); + + if ( !mib ) + { + // this is fatal + Fsm( aCtxImpl, EABORT ); + return; + } + + mib->iMode = WHA::KPowerDownMode; + + WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib(); + wha_cmd.Set( + aCtxImpl, WHA::KMibSleepMode, 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 ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::ExecuteScanFsm( + WlanContextImpl& /*aCtxImpl*/ ) + { + // start scan fsm + iPimpl->Current().StartScanningMode( *iPimpl ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::ContinueDot11StateTraversal( + WlanContextImpl& aCtxImpl ) + { + // return back to dot11idle + ChangeState( aCtxImpl, + *this, // prev state + aCtxImpl.iStates.iIdleState // next state + ); + } + +// ----------------------------------------------------------------------------- +// Handler for WHA command response event. +// It is guaranteed by the global protocol fsm framework that no WHA command is +// pending when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnWhaCommandResponse( + WlanContextImpl& aCtxImpl, + WHA::TCommandId aCommandId, + WHA::TStatus /*aStatus*/, + const WHA::UCommandResponseParams& /*aCommandResponseParams*/, + TUint32 /*aAct*/ ) + { + if ( aCommandId == WHA::EScanCommandResponse ) + { + OsTracePrint( KScan, (TUint8*)("UMAC * OnScanningModeStarted")); + + // morph event to the scan fsm + iPimpl->Current().OnScanningModeStarted( *iPimpl ); + } + else if ( aCommandId == WHA::EStopScanResponse ) + { + // complete the stop scan request + + OsTracePrint( KScan, (TUint8*) + ("UMAC: WlanDot11IdleScanningMode::OnWhaCommandResponse: complete stop scan request")); + + OnOidComplete( aCtxImpl ); + } + else + { + // has to be the write mib command response. + // We have nothing to do here + } + } + +// ----------------------------------------------------------------------------- +// Handler for WHA command completion event. +// It is guaranteed by the global protocol fsm framework that no WHA command is +// pending when this method is entered +// ----------------------------------------------------------------------------- +// +TBool WlanDot11IdleScanningMode::CommandComplete( + WlanContextImpl& /*aCtxImpl*/, + WHA::TCompleteCommandId aCompleteCommandId, + WHA::TStatus /*aStatus*/, + const WHA::UCommandCompletionParams& /*aCommandCompletionParams*/ ) + { + if ( aCompleteCommandId != WHA::EScanComplete ) + { + // implementation error as this can be the only one + OsAssert( (TUint8*)("UMAC * panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + OsTracePrint( KScan, (TUint8*)("UMAC * OnScanningModeStopped")); + + // morph event to scan fsm + iPimpl->Current().OnScanningModeStopped( *iPimpl ); + + // as scanning mode has ended we will change dot11 state. + // Signal it to caller + return ETrue; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TAny* WlanDot11IdleScanningMode::RequestForBuffer( + WlanContextImpl& aCtxImpl, + TUint16 aLength ) + { + return aCtxImpl.GetRxBuffer( aLength ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::ReceivePacket( + WlanContextImpl& aCtxImpl, + WHA::TStatus aStatus, + const void* aFrame, + TUint16 aLength, + WHA::TRate /*aRate*/, + WHA::TRcpi aRcpi, + WHA::TChannelNumber /*aChannel*/, + TUint8* aBuffer, + TUint32 /*aFlags*/ ) + { + if ( aStatus == WHA::KSuccess ) + { + // frame reception success + + const Sdot11MacHeader* hdr + = reinterpret_cast(const_cast(aFrame)); + + OsTracePrint( KRxFrame, (TUint8*) + ("UMAC: dot11-idlescanningmode * frame rx * frame type: 0x%02x"), + hdr->iFrameControl.iType ); + + if ( (hdr->iFrameControl.iType + == E802Dot11FrameTypeBeacon) + || (hdr->iFrameControl.iType + == E802Dot11FrameTypeProbeResp) ) + { + // as we have a beacon or probe response frame we will pass it to + // the client of the mgmt interface + XferDot11FrameToMgmtClient( + aCtxImpl, + aFrame, + aLength, + aRcpi, + aBuffer ); + } + else + { + // other than scan frame received. This may be legal if the frame + // was received before receiving WHA::CommandResponse for WHA::Scan + // cmd. However, in other cases it may be an implementation error + // in the underlying adaptation layer. In any case the frame is not + // applicable for us as we are doing dot11idle mode scan (we are + // not connected) and we will ignore it + OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) + ("UMAC: WlanDot11IdleScanningMode::ReceivePacket: WARNING: Other than scan frame received. Frame type: 0x%02x"), + hdr->iFrameControl.iType ); + + // release the Rx buffer + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + } + } + else + { + // frame reception failure + OsTracePrint( KErrorLevel, (TUint8*) + ("UMAC * dot11-idlescanningmode * frame rx failure * status: %d"), + aStatus ); + + // release the Rx buffer + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::Entry( + WlanContextImpl& aCtxImpl ) + { + if ( aCtxImpl.WsaCmdActive() ) + { + // sanity checking code + OsAssert( (TUint8*)("UMAC * panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // we don't want to do full event dispatching here as we want + // to run this dot11 state in non pre-emptive mode. + // However, we do want to handle the scan complete event in case it has + // been registered + if ( aCtxImpl.CommandCompletionEventRegistered( WHA::EScanComplete ) ) + { + OsTracePrint( KScan, (TUint8*) + ("UMAC: WlanDot11IdleScanningMode::Entry: Scan complete event registered") ); + + aCtxImpl.DispatchCommandCompletionEvent(); + // in this case we have actually already changed to another state + // so there's nothing more for us to do here + } + else + { + // scan complete event not registered. Continue in the normal fashion + + if ( iState != EINIT ) + { + // this is NOT the start of the the FSM actions + // note that we send the ETXCOMPLETE event as the states + // that wait for it are the only ones that can be interrupted + // as they are asynchronous operations by nature + // and wait for corresponding WHA completion method + Fsm( aCtxImpl, ETXCOMPLETE ); + } + else + { + // this is the start of the FSM actions + Fsm( aCtxImpl, ESTATEENTRY ); + } + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::Exit( + WlanContextImpl& /*aCtxImpl*/ ) + { + // reset fsm + iState = EINIT; + + // get rid of scan fsm implementation + iPimpl->~WlanScanFsmCntx(); + os_free( iPimpl ); + iPimpl = NULL; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool WlanDot11IdleScanningMode::StopScan( WlanContextImpl& /*aCtxImpl*/ ) + { + // inform scan fsm that scanning mode stop is desired + iPimpl->Current().StopScanningMode( *iPimpl ); + // indicate that a state change has occurred + return ETrue; + } + +#ifndef NDEBUG +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +const TInt8* WlanDot11IdleScanningMode::GetStateName( + TUint8& aLength ) const + { + aLength = sizeof( iName ); + return iName; + } +#endif + +// ----------------------------------------------------------------------------- +// Handler for scan fsm event. +// It is guaranteed by the FSM framework that no WHA command is pending +// when this method is entered +// ----------------------------------------------------------------------------- +// +void WlanDot11IdleScanningMode::OnScanFsmEvent( + MWlanScanFsmCb::TEvent aEvent ) + { + OsTracePrint( KScan, (TUint8*) + ("UMAC: * dot11-idlescanningmode * SCAN FSM EVENT: %d"), aEvent ); + + // do what the scan fsm desires + switch( aEvent ) + { + case EFSMSTARTSCANNINGMODE: + // scanning mode start desired + Fsm( *iCtxImpl, ESTARTSCANNINGMODE ); + break; + case EFSMSCANMODERUNNING: + // scanning mode is running + Fsm( *iCtxImpl, ESCANMODERUNNING ); + break; + case EFSMSTOPSCANNINGMODE: + // scanning mode stop desired + Fsm( *iCtxImpl, ESTOPSCANNINGMODE ); + break; + + case EFSMSCANMODESTOPPED: + // scanning mode has stopped + Fsm( *iCtxImpl, ESCANNINGMODEEXIT ); + break; + default: + // catch scan FSM programming error + OsTracePrint( KErrorLevel, + (TUint8*)("UMAC: scan fsm event: :%d"), aEvent); + OsAssert( (TUint8*)("UMAC: panic"), + (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + }