--- /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<const SAssociationResponseFixedFields*>
+ (reinterpret_cast<const TUint8*>(aFrame) +
+ sizeof( SHtManagementFrameHeader )) :
+ reinterpret_cast<const SAssociationResponseFixedFields*>
+ (reinterpret_cast<const TUint8*>(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<T802Dot11ManagementStatusCode>(
+ 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<const Sdot11MacHeader*>(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<SManagementFrameHeader*>
+ (const_cast<TAny*>(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<const TUint8*>( 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<const SWmmParamElemData*>(data))->ParameterSetCount() );
+
+ if ( (reinterpret_cast<const SWmmParamElemData*>
+ (data))->ParameterSetCount()
+ != aCtxImpl.WmmParameterSetCount() )
+ {
+ // AC parameters have changed => parse again
+ ParseAcParameters(
+ aCtxImpl,
+ reinterpret_cast<const SWmmParamElemData&>(*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 );
+ }