diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacDot11AssociationPending.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacDot11AssociationPending.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,994 @@ +/* +* Copyright (c) 2005-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 WlanDot11AssociationPending class +* +*/ + +/* +* %version: 45 % +*/ + +#include "config.h" +#include "UmacDot11AssociationPending.h" +#include "UmacContextImpl.h" +#include "umacelementlocator.h" +#include "umacwhaconfigureac.h" +#include "802dot11DefaultValues.h" + +#ifndef NDEBUG +const TInt8 WlanDot11AssociationPending::iName[] = "dot11-associationpending"; + +const TUint8 WlanDot11AssociationPending::iStateName + [ESTATEMAX][KMaxStateStringLength] = + { + {"EINIT"}, + {"ETXASSOCREQFRAME"}, + {"EWAIT4ASSOCRESPONSE"}, + {"ECONFIGUREAC"}, + {"EWAIT4PUSHPACKET"}, + {"ECONTINUEDOT11TRAVERSE"} + }; + +const TUint8 WlanDot11AssociationPending::iEventName + [EEVENTMAX][KMaxEventStringLength] = + { + {"ESTATEENTRY"}, + {"ERXASSOCRESPONSE"}, + {"ETX_ASSOCFRAME_XFER"}, + {"ETXCOMPLETE"}, + {"ETIMEOUT"}, + {"ETX_SCHEDULER_FULL"}, + {"EPUSHPACKET"} + }; +#endif + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::Entry( + WlanContextImpl& aCtxImpl ) + { + OsTracePrint( KUmacProtocolState | KUmacAssoc, + (TUint8*)("UMAC: WlanDot11AssociationPending::Entry()")); + + if ( aCtxImpl.WsaCmdActive() ) + { + // sanity checking code + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + // no need to do event dispatching as this + // thing is triggered by the user and + // is executed synchronously as we only do OID completion + // at the end of authenticate + association process + + if ( iState == EINIT ) + { + // this is the start of the the FSM actions + Fsm( aCtxImpl, ESTATEENTRY ); + } + else + { + // 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 ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::Exit( + WlanContextImpl& /*aCtxImpl*/ ) + { + // reset our local FSM for the next time... + iState = EINIT; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::Fsm( + WlanContextImpl& aCtxImpl, + TEvent aEvent ) + { + OsTracePrint( KUmacAssoc, + (TUint8*)("UMAC: WlanDot11AssociationPending::Fsm(): FSM EVENT") ); +#ifndef NDEBUG + OsTracePrint( KUmacAssoc, (TUint8*)("UMAC: event:")); + OsTracePrint( KUmacAssoc, iEventName[aEvent] ); + OsTracePrint( KUmacAssoc, (TUint8*)("UMAC: state:")); + OsTracePrint( KUmacAssoc, iStateName[iState] ); +#endif + + switch ( aEvent ) + { + case ESTATEENTRY: + OnStateEntryEvent( aCtxImpl ); + break; + case ETX_ASSOCFRAME_XFER: + OnTxAssocFrameXferEvent( aCtxImpl ); + break; + case ERXASSOCRESPONSE: + OnRxAssociationResponseEvent( aCtxImpl ); + break; + case ETXCOMPLETE: + OnTxCompleteEvent( aCtxImpl ); + break; + case ETIMEOUT: + OnTimeoutEvent( aCtxImpl ); + break; + case ETX_SCHEDULER_FULL: + OnTxSchedulerFullEvent( aCtxImpl ); + break; + case EPUSHPACKET: + OnPushPacketEvent( aCtxImpl ); + break; + default: + // cath internal FSM programming error + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// Handler for state entry event. +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnStateEntryEvent( + WlanContextImpl& aCtxImpl ) + { + OsTracePrint( + KUmacAssoc, + (TUint8*)("UMAC: WlanDot11AssociationPending::OnStateEntryEvent()")); + + switch ( iState ) + { + case EINIT: + iFlags = 0; + ChangeInternalState( aCtxImpl, ETXASSOCREQFRAME ); + break; + case ETXASSOCREQFRAME: + // send the associate frame + if ( !SendAssociationRequest( aCtxImpl ) ) + { + // tx of dot11-associate frame failed + // because packet scheduler was full + // or because we didn't get a Tx buffer + // so we enter to a wait state + Fsm( aCtxImpl, ETX_SCHEDULER_FULL ); + } + break; + case EWAIT4ASSOCRESPONSE: + // start a timer to wait for the response frame + StartAssociationFrameResponseTimer( aCtxImpl ); + break; + case ECONFIGUREAC: + ConfigureAc( aCtxImpl ); + break; + case ECONTINUEDOT11TRAVERSE: + ContinueDot11StateTraversal( aCtxImpl ); + break; + case EWAIT4PUSHPACKET: + // nothing to do here than wait + 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 association response timeout event. +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnTimeoutEvent( + WlanContextImpl& aCtxImpl ) + { + // set completion code + // as dot11idle state does the OID completion + aCtxImpl.iStates.iIdleState.Set( KErrTimedOut ); + ChangeInternalState( aCtxImpl, ECONTINUEDOT11TRAVERSE ); + } + +// ----------------------------------------------------------------------------- +// Handler for associate request frame +// has been xferred to the WLAN device event +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnTxAssocFrameXferEvent( + WlanContextImpl& aCtxImpl ) + { + // change state + ChangeInternalState( aCtxImpl, EWAIT4ASSOCRESPONSE ); + } + +// ----------------------------------------------------------------------------- +// Handler for rx association response event. +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnRxAssociationResponseEvent( + WlanContextImpl& aCtxImpl ) + { + switch ( iState ) + { + case EWAIT4ASSOCRESPONSE: + if ( iFlags & KConfigureAc ) + { + ChangeInternalState( aCtxImpl, ECONFIGUREAC ); + } + else + { + ChangeInternalState( aCtxImpl, ECONTINUEDOT11TRAVERSE ); + } + break; + default: + // this means that we have recieved a valid dot11 + // associate response frame that we are waiting for + // but we are not internally in such a state + // only feasible situation for this is that + // someone has skipped a call to the packet xfer method + // that informs of associate request frame + // xfer to the WLAN device. + // other case is that our fsm is totally messed up + // so we catch this +#ifndef NDEBUG + OsTracePrint( KErrorLevel, (TUint8*)("state:")); + OsTracePrint( KErrorLevel, iStateName[iState] ); +#endif + OsAssert( (TUint8*)("* UMAC * panic"), + (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnTxCompleteEvent( + WlanContextImpl& aCtxImpl ) + { + switch ( iState ) + { + case ECONFIGUREAC: + // continue state traversal + ChangeInternalState( aCtxImpl, ECONTINUEDOT11TRAVERSE ); + break; + default: + // catch internal FSM programming error + OsTracePrint( KErrorLevel, (TUint8*)("UMAC: state: %d"), iState); + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + break; + } + } + +// ----------------------------------------------------------------------------- +// Handler for scheduler full event upon trying to tx dot11-associate frame +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnTxSchedulerFullEvent( + WlanContextImpl& aCtxImpl ) + { + // change state + OsTracePrint( KWarningLevel | KUmacAssoc, (TUint8*) + ("UMAC: packet scheduler full during association process") ); + + ChangeInternalState( aCtxImpl, EWAIT4PUSHPACKET ); + } + +// ----------------------------------------------------------------------------- +// Handler for push packet to packet scheduler possible event +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnPushPacketEvent( + WlanContextImpl& aCtxImpl ) + { + if ( iState == EWAIT4PUSHPACKET ) + { + ChangeInternalState( aCtxImpl, ETXASSOCREQFRAME ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::ContinueDot11StateTraversal( + WlanContextImpl& aCtxImpl ) + { + if ( iFlags & KAssocSuccess ) + { + // traverse to next dot11state + ChangeState( aCtxImpl, + *this, // prev state + aCtxImpl.iStates.iInfrastructureModeInit // next state + ); + } + else + { + // proceed back to idle + // + ChangeState( aCtxImpl, + *this, // prev state + aCtxImpl.iStates.iIdleState // next state + ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::ChangeInternalState( + WlanContextImpl& aCtxImpl, + TState aNewState ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::ChangeInternalState(): old state:")); +#ifndef NDEBUG + OsTracePrint( KUmacAssoc, iStateName[iState] ); + OsTracePrint( KUmacAssoc, (TUint8*)("new state:")); + OsTracePrint( KUmacAssoc, iStateName[aNewState] ); +#endif + iState = aNewState; + Fsm( aCtxImpl, ESTATEENTRY ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +#ifndef NDEBUG +const TInt8* WlanDot11AssociationPending::GetStateName( + TUint8& aLength ) const + { + aLength = sizeof( iName ); + return iName; + } +#endif + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool WlanDot11AssociationPending::SendAssociationRequest( + WlanContextImpl& aCtxImpl ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::SendAssociationRequest")); + + TBool status ( EFalse ); + TUint8* startOfFrame ( NULL ); + + const TUint32 length_of_frame + = ConstructAssociationRequestFrame( aCtxImpl, startOfFrame ); + + if ( length_of_frame ) + { + // frame is ready for delivery in the tx buffer + // send association request message to the AP + + const WHA::TQueueId queue_id + = QueueId( aCtxImpl, startOfFrame ); + + // push the frame to packet scheduler for transmission + status = aCtxImpl.PushPacketToPacketScheduler( + startOfFrame, + length_of_frame, + queue_id, + E802Dot11FrameTypeAssociationReq, + NULL, + EFalse, + EFalse, + ETrue ); + + if ( !status ) + { + // as we came here we did get an internal Tx buffer for the frame + // but packet push to scheduler failed. In this case we need cancel + // the internal Tx buffer reservation as we will request it again + // when the Packet Scheduler is again ready for packet push + aCtxImpl.MarkInternalTxBufFree(); + } + } + else + { + // frame not ready for delivery. EFalse will be returned + } + + return status; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TUint WlanDot11AssociationPending::ConstructAssociationRequestFrame( + WlanContextImpl& aCtxImpl, + TUint8*& aStartOfFrame ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::ConstructAssociationRequestFrame") ); + + TUint32 lengthOfFrame ( 0 ); + + // client doesn't have to take care of the tx buffer header space + // as the method below does that by itself + aStartOfFrame = aCtxImpl.TxBuffer( ETrue ); + + if ( aStartOfFrame ) + { + // construct association request frame + // note that we don't need to set SA because we have already set it + // in the initialization phase of the state machine + // Also capabilty information field is already set to frame template + // in AreNetworkRequirementsMet() method + + TUint8* buffer_ptr = aStartOfFrame; + + if ( aCtxImpl.HtSupportedByNw() && aCtxImpl.QosEnabled() ) + { + // set the BSSID field + (aCtxImpl.GetHtAssociationRequestFrame()).iHeader.iBSSID = + aCtxImpl.GetBssId(); + // set the DA field + (aCtxImpl.GetHtAssociationRequestFrame()).iHeader.iDA = + aCtxImpl.GetBssId(); + // set listen interval (in units of beacon interval) + (aCtxImpl.GetHtAssociationRequestFrame()).iFixedFields.iListenInterval + = KDot11ListenIntervalInMs / aCtxImpl.NetworkBeaconInterval(); + + // copy frame to tx-buffer to correct offset + os_memcpy( + buffer_ptr, + &(aCtxImpl.GetHtAssociationRequestFrame()), + sizeof( SHtAssociationRequestFrame ) ); + + buffer_ptr += sizeof( SHtAssociationRequestFrame ); + } + else + { + // set the BSSID field + (aCtxImpl.GetAssociationRequestFrame()).iHeader.iBSSID = + aCtxImpl.GetBssId(); + // set the DA field + (aCtxImpl.GetAssociationRequestFrame()).iHeader.iDA = + aCtxImpl.GetBssId(); + // set listen interval (in units of beacon interval) + (aCtxImpl.GetAssociationRequestFrame()).iFixedFields.iListenInterval + = KDot11ListenIntervalInMs / aCtxImpl.NetworkBeaconInterval(); + + // copy frame to tx-buffer to correct offset + os_memcpy( + buffer_ptr, + &(aCtxImpl.GetAssociationRequestFrame()), + sizeof( SAssociationRequestFrame ) ); + + buffer_ptr += sizeof( SAssociationRequestFrame ); + } + + // set SSID IE + + SSsIdIE ssid_ie( (aCtxImpl.GetSsId()).ssid, + (aCtxImpl.GetSsId()).ssidLength ); + + const TUint8 ssidIeLength( ssid_ie.GetIeLength() ); + + os_memcpy( + buffer_ptr, + &ssid_ie, + ssidIeLength ); + + buffer_ptr += ssidIeLength; + + // set supported rates IE + + const TUint8 supportedRatesIeLength( + aCtxImpl.GetOurSupportedRatesIE().GetIeLength() ); + + os_memcpy( + buffer_ptr, + &(aCtxImpl.GetOurSupportedRatesIE()), + supportedRatesIeLength ); + + buffer_ptr += supportedRatesIeLength; + + if ( aCtxImpl.HtSupportedByNw() ) + { + // set HT capabilities element + + const TUint8 htCapabilitiesIeLength( + aCtxImpl.GetOurHtCapabilitiesIe().GetIeLength() ); + + os_memcpy( + buffer_ptr, + &(aCtxImpl.GetOurHtCapabilitiesIe()), + htCapabilitiesIeLength ); + + buffer_ptr += htCapabilitiesIeLength; + + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: HT capabilities element added") ); + } + + // set extended supported rates IE if it's not empty + if ( aCtxImpl.GetOurExtendedSupportedRatesIE().GetElementLength() ) + { + const TUint8 extSupportedRatesIeLength( + aCtxImpl.GetOurExtendedSupportedRatesIE().GetIeLength() ); + + os_memcpy( + buffer_ptr, + &(aCtxImpl.GetOurExtendedSupportedRatesIE()), + extSupportedRatesIeLength ); + + buffer_ptr += extSupportedRatesIeLength; + } + + // set any IEs possibly provided by management client + const TUint8* ieData( aCtxImpl.IeData() ); + if ( ieData ) + { + const TUint16 ieDataLength( aCtxImpl.IeDataLength() ); + + os_memcpy( buffer_ptr, ieData, ieDataLength ); + buffer_ptr += ieDataLength; + + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: management client supplied IE(s) added") ); + } + + // set WMM IE if needed + if ( aCtxImpl.QosEnabled() ) + { + const TUint8 wmmIeLength( aCtxImpl.OurWmmIe().GetIeLength() ); + + os_memcpy( + buffer_ptr, + &(aCtxImpl.OurWmmIe()), + wmmIeLength); + + buffer_ptr += wmmIeLength; + + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WMM IE added") ); + } + + // length of frame + lengthOfFrame = buffer_ptr - aStartOfFrame; + } + else + { + // we didn't get a Tx buffer => frame not sent. Zero will be returned + // as the frame length to indicate that + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::ConstructAssociationRequestFrame: no internal Tx buffer available") ); + } + + return lengthOfFrame; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +T802Dot11ManagementStatusCode +WlanDot11AssociationPending::IsRxAssociationSuccess( + WlanContextImpl& aCtxImpl, + const void* aFrame, + TUint32 aFlags ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::IsRxAssociationSuccess")); + // get the fixed fields from association response + const SAssociationResponseFixedFields* fields = + HtcFieldPresent( aCtxImpl, aFrame, aFlags ) ? + reinterpret_cast + (reinterpret_cast(aFrame) + + sizeof( SHtManagementFrameHeader )) : + reinterpret_cast + (reinterpret_cast(aFrame) + + sizeof( SManagementFrameHeader ) ); + + // store AID + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::IsRxAssociationSuccess: AID extracted from association response: 0x%04x"), + fields->Aid() ); + aCtxImpl.Aid( fields->Aid() ); + + return static_cast( + fields->StatusCode() ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::StartAssociationFrameResponseTimer( + WlanContextImpl& aCtxImpl ) + { + // start association response timeout timer + const TUint32 timeout( dot11AssociateResponseTimeout * KTU ); + + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::StartAssociationFrameResponseTimer: timeout in microseconds: %d"), + timeout); + + aCtxImpl.iUmac.RegisterTimeout( timeout ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::ConfigureAc( + WlanContextImpl& aCtxImpl ) + { + ConfigureAcParams( aCtxImpl ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::ReceivePacket( + WlanContextImpl& aCtxImpl, + WHA::TStatus aStatus, + const void* aFrame, + TUint16 aLength, + WHA::TRate /*aRate*/, + WHA::TRcpi aRcpi, + WHA::TChannelNumber /*aChannel*/, + TUint8* aBuffer, + TUint32 aFlags ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: dot11-associatepending::ReceivePacket()") ); + + if ( aStatus == WHA::KSuccess ) + { + // receive success + const Sdot11MacHeader* dot11_hdr( + static_cast(aFrame) ); + + // we accept only frames with ToDS bit cleared + if ( dot11_hdr->IsToDsBitSet() ) + { + OsTracePrint( KWarningLevel | KUmacAssoc, + (TUint8*)("UMAC: associating to BSS:") ); + OsTracePrint( KWarningLevel | KUmacAssoc, + (TUint8*)("UMAC: rx-frame: ToDs bit set, discard frame") ); + + // release the Rx buffer & abort + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + return; + } + + const TBool class3_frame( IsClass3Frame( + dot11_hdr->iFrameControl.iType ) ); + const TBool unicast_addr( !IsGroupBitSet( dot11_hdr->iAddress1 ) ); + + if ( class3_frame && unicast_addr ) + { + OsTracePrint( KWarningLevel | KUmacAssoc, + (TUint8*)("UMAC: associating to BSS:") ); + OsTracePrint( KWarningLevel | KUmacAssoc, + (TUint8*)("rx class3 frame with unicast DA address") ); + + // class 3 frame rx and unicast address in address1 field + + // That's not the frame we are expecting so release the Rx buffer + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + + if ( !Associated() ) + { + // we do not have a valid association with the + // BSS where the frame came + OsTracePrint( KWarningLevel | KUmacAssoc, + (TUint8*)("UMAC: TxDisassociate") ); + + // set the BSSID of the existing network; and the DA + if ( aCtxImpl.HtSupportedByNw() ) + { + (aCtxImpl.GetHtDisassociationFrame()).iHeader.iBSSID + = aCtxImpl.GetBssId(); + (aCtxImpl.GetHtDisassociationFrame()).iHeader.iDA + = aCtxImpl.GetBssId(); + } + else + { + (aCtxImpl.GetDisassociationFrame()).iHeader.iBSSID + = aCtxImpl.GetBssId(); + (aCtxImpl.GetDisassociationFrame()).iHeader.iDA + = aCtxImpl.GetBssId(); + } + if ( !TxDisassociate( + aCtxImpl, + E802Dot11ReasonClass3FrameWhenNotAssoc ) ) + { + // frame was not sent because either packet scheduler was + // full or because we didn't get a Tx buffer. In any case + // we won't try to send it again. + } + } + else + { + // this section is left intentionally empty + } + } + else + { + // default handler + OnReceiveFrameSuccess( + aCtxImpl, + aFrame, + aLength, + aRcpi, + aFlags, + aBuffer ); + } + } + else // --- aStatus == WHA::KSuccess --- + { + // receive failed, so discard and release the Rx buffer + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnReceiveFrameSuccess( + WlanContextImpl& aCtxImpl, + const void* aFrame, + TUint16 aLength, + WHA::TRcpi aRcpi, + TUint32 aFlags, + TUint8* aBuffer ) + { + // receive success + // parse frame in order to determine if it is what we are expecting + SManagementFrameHeader* frame_hdr + = static_cast + (const_cast(aFrame)); + + TBool type_match( EFalse ); + + if ( // this an association response frame + IsRequestedFrameType( + frame_hdr->iFrameControl.iType, + E802Dot11FrameTypeAssociationResp, type_match ) + // AND our MAC address is DA + && ( frame_hdr->iDA == aCtxImpl.iWlanMib.dot11StationId ) + // AND we haven't received the assoc response yet + && ( !( iFlags & KAssocReceived ) ) ) + { + T802Dot11ManagementStatusCode status + = IsRxAssociationSuccess( aCtxImpl, aFrame, aFlags ); + + if ( status == E802Dot11StatusSuccess ) + { + // --- begin WMM + if ( aCtxImpl.QosEnabled() ) + { + WlanElementLocator elementLocator( + reinterpret_cast( aFrame ) + + sizeof( SManagementFrameHeader ) + + sizeof( SAssociationResponseFixedFields ), + aLength - + sizeof( SManagementFrameHeader ) + + sizeof( SAssociationResponseFixedFields ) ); + + TUint8 length( 0 ); + const TUint8* data( NULL ); + + // is WMM Parameter Element present + if ( elementLocator.InformationElement( + E802Dot11VendorSpecificIE, + KWmmElemOui, + KWmmElemOuiType, + KWmmParamElemOuiSubtype, + length, + &data ) == WlanElementLocator::EWlanLocateOk ) + { + // WMM Parameter Element found + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::ReceivePacket(): WMM param set cnt: %d"), + (reinterpret_cast(data))->ParameterSetCount() ); + + if ( (reinterpret_cast + (data))->ParameterSetCount() + != aCtxImpl.WmmParameterSetCount() ) + { + // AC parameters have changed => parse again + ParseAcParameters( + aCtxImpl, + reinterpret_cast(*data ) ); + // in this case we need to re-issue configure AC wha cmd + // so make a note of that + iFlags |= KConfigureAc; + } + } + else + { + // protocol error from AP; just try to continue with + // current WMM parameters + OsTracePrint( KWarningLevel | KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::ReceivePacket(): PROTOCOL ERROR from AP side") ); + } + } + // --- end WMM + } + else + { + // association failed + OsTracePrint( KWarningLevel | KUmacAssoc, (TUint8*) + ("UMAC: dot11-association denied; status code: %d"), + status); + + // in this case we will go back to idle state + // where the connect oid will be completed. + // So set the completion code value to be returned to user mode + aCtxImpl.iStates.iIdleState.Set( status ); + } + + // forward the association response frame to Wlan Mgmt client + if ( XferDot11FrameToMgmtClient( + aCtxImpl, + aFrame, + aLength, + aRcpi, + aBuffer ) ) + { + // forwarding succeeded. Now we can say that we have received + // the assoc response successfully + + iFlags |= KAssocReceived; + aCtxImpl.CancelTimer(); + + if ( status == E802Dot11StatusSuccess ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: association pending: association success") ); + + iFlags |= KAssocSuccess; + } + + Fsm( aCtxImpl, ERXASSOCRESPONSE ); + } + else + { + // forwarding the frame to WLAN Mgmt client failed, which + // won't happen in this situation under the normal circumstances. + // Anyhow, it has happened now, so we have no other choice than to + // discard the frame. The Rx buffer has already been + // released. So no action here + } + } + else + { + // not a valid frame in this situation; we just silently discard it + OsTracePrint( KUmacAssoc | KUmacDetails, (TUint8*) + ("UMAC: WlanDot11AssociationPending::OnReceiveFrameSuccess: " + "not relevant frame; ignore")); + + // release the Rx buffer + aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); + } + } + +// ----------------------------------------------------------------------------- +// completion method called when packet has been xferred to the WLAN device +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnPacketTransferComplete( + WlanContextImpl& aCtxImpl, + TUint32 aPacketId, + TDataBuffer* aMetaHeader ) + { + OsTracePrint( KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::OnPacketTransferComplete")); + + if ( aPacketId == E802Dot11FrameTypeData ) + { + OnTxProtocolStackDataComplete( aCtxImpl, aMetaHeader ); + } + else if ( aPacketId == E802Dot11FrameTypeDataEapol || + aPacketId == E802Dot11FrameTypeManagementAction || + aPacketId == E802Dot11FrameTypeTestFrame ) + { + OnMgmtPathWriteComplete( aCtxImpl ); + } + 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(); + } + + if ( aPacketId == E802Dot11FrameTypeAssociationReq ) + { + // associate tx message has been xferred to the WLAN device + + Fsm( aCtxImpl, ETX_ASSOCFRAME_XFER ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool WlanDot11AssociationPending::OnTimeout( + WlanContextImpl& aCtxImpl ) + { + TBool stateChange ( ETrue ); + + switch ( iState ) + { + case EWAIT4ASSOCRESPONSE: + // association timeout + + OsTracePrint( KWarningLevel | KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::OnTimeout: timeout => association failed!") ); + + Fsm( aCtxImpl, ETIMEOUT ); + + // in this case we return ETrue, i.e. signal the caller that a + // state change occurred + + break; + default: + // a timeout occurred when we weren't expecting it (yet). This + // means that a timeout callback had already been registered when + // we tried to cancel this timer the previous time (regarding + // authentication). So this callback is not relevant for + // association and can be ignored. + + OsTracePrint( KWarningLevel | KUmacAssoc, (TUint8*) + ("UMAC: WlanDot11AssociationPending::OnTimeout: irrelevant timeout; ignored") ); + + // Signal the caller that no state change occurred + stateChange = EFalse; + } + + return stateChange; + } + +// ----------------------------------------------------------------------------- +// packet sceduler notification that a packet push is guaranteed to succeed +// ----------------------------------------------------------------------------- +// +void WlanDot11AssociationPending::OnPacketPushPossible( + WlanContextImpl& aCtxImpl ) + { + // feed a critter to the fsm + Fsm( aCtxImpl, EPUSHPACKET ); + }