diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_common/umac_common/src/umacelementlocator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/umacelementlocator.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,412 @@ +/* +* 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 WlanElementLocator class. +* +*/ + +/* +* %version: 9 % +*/ + +#include "config.h" +#include "umacelementlocator.h" + +// offset of the Length field from the beginning of element +const TUint KElemLengthOffset = 1; +// offset of the Type field from the beginning of element Information +const TUint KOuiTypeOffset = 3; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::WlanElementLocator( const TUint8* aStart, TUint16 aLength ) + : iStart ( aStart ), iLength ( aLength ), iIterator( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::InformationElement( + TUint8 aIeId, + TUint8& aIeLength, + const TUint8** aIeData, + TBool aValidateLength ) + { + // The general Information Element format is: + // Element id (1 byte) + // Length (1 byte) + // Information (Length bytes) + // + + TUint8 ie( 0 ); + TUint8 len( 0 ); + const TUint8* data( NULL ); + + if ( FirstIE( ie, len, &data ) != EWlanLocateOk ) + { + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + + TWlanLocateStatus ret( EWlanLocateOk ); + + while ( ie != aIeId && ret == EWlanLocateOk ) + { + ret = NextIE( ie, len, &data ); + } + + if ( ret == EWlanLocateElementNotFound ) + { + aIeLength = 0; + *aIeData = NULL; + return ret; + } + else + { + aIeLength = len; + *aIeData = data; + + if ( aValidateLength ) + { + return ValidIE( aIeId, aIeLength ); + } + else + { + return EWlanLocateOk; + } + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::InformationElement( + TUint8 aIeId, + const TIeOui& aIeOui, + TUint8 aIeOuiType, + TUint8& aIeLength, + const TUint8** aIeData ) + { + // Element format is: + // ID = Element ID (1 byte) + // Len = Length (1 byte) + // OUI = OUI (3 bytes) + // OUItyp = OUI Type (1 byte) + // ... + + TUint8 ie( aIeId ); + TUint8 len( 0 ); + const TUint8* data( NULL ); + + // Find the first element with matching IE id + if ( InformationElement( aIeId, len, &data, EFalse ) != + EWlanLocateOk ) + { // there isn't one + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + + // The ID is correct but also the OUI, OUI Type and OUI Subtype need to + // match + TWlanLocateStatus ret( EWlanLocateOk ); + + const TUint KMinAcceptableIeDataLen = + KIeOuiLength + + sizeof( KWmmElemOuiType ); + + while ( ret == EWlanLocateOk && + ( len < KMinAcceptableIeDataLen || + ie != aIeId || + !( data[0] == aIeOui[0] && data[1] == aIeOui[1] && + data[2] == aIeOui[2] + ) || + *( data + KOuiTypeOffset ) != aIeOuiType + ) + ) + { + ret = NextIE( ie, len, &data ); + } + + if ( ret == EWlanLocateElementNotFound ) + { + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + else + { + aIeLength = len; + *aIeData = data; + return ValidIE( aIeId, aIeLength, data, aIeOuiType ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::InformationElement( + TUint8 aIeId, + const TIeOui& aIeOui, + TUint8 aIeOuiType, + TUint8 aIeOuiSubtype, + TUint8& aIeLength, + const TUint8** aIeData ) + { + // Element format is: + // ID = Element ID (1 byte) + // Len = Length (1 byte) + // OUI = OUI (3 bytes) + // OUItyp = OUI Type (1 byte) + // OUIsub = OUI Subtype (1 byte) + // ... + + TUint8 ie( aIeId ); + TUint8 len( 0 ); + const TUint8* data( NULL ); + + // Find the first element with matching IE id + if ( InformationElement( aIeId, len, &data, EFalse ) != + EWlanLocateOk ) + { // there isn't one + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + + // The ID is correct but also the OUI, OUI Type and OUI Subtype need to + // match + TWlanLocateStatus ret( EWlanLocateOk ); + + const TUint KMinAcceptableIeDataLen = + KIeOuiLength + + sizeof( KWmmElemOuiType ) + + sizeof( KWmmInfoElemOuiSubType ); + + // offset of the Subtype field from the beginning of element Information + const TUint KOuiSubtypeOffset = 4; + + while ( ret == EWlanLocateOk && + ( len < KMinAcceptableIeDataLen || + ie != aIeId || + !( data[0] == aIeOui[0] && data[1] == aIeOui[1] && + data[2] == aIeOui[2] + ) || + *( data + KOuiTypeOffset ) != aIeOuiType || + *( data + KOuiSubtypeOffset ) != aIeOuiSubtype + ) + ) + { + ret = NextIE( ie, len, &data ); + } + + if ( ret == EWlanLocateElementNotFound ) + { + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + else + { + aIeLength = len; + *aIeData = data; + return ValidIE( aIeId, aIeLength, data, aIeOuiType, aIeOuiSubtype ); + } + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::FirstIE( + TUint8& aIeId, + TUint8& aIeLength, + const TUint8** aIeData) + { + iIterator = iStart; + return CurrentIE( aIeId, aIeLength, aIeData ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::NextIE( + TUint8& aIeId, + TUint8& aIeLength, + const TUint8** aIeData) + { + iIterator += *( iIterator + KElemLengthOffset ) + KInfoElementHeaderLength; + return CurrentIE( aIeId, aIeLength, aIeData ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::CurrentIE( + TUint8& aIeId, + TUint8& aIeLength, + const TUint8** aIeData) const + { + if ( iIterator >= iStart + iLength ) + { + aIeId = 0; + aIeLength = 0; + *aIeData = NULL; + return EWlanLocateElementNotFound; + } + aIeId = *iIterator; + aIeLength = *( iIterator + KElemLengthOffset ); + *aIeData = iIterator + KInfoElementHeaderLength; + return EWlanLocateOk; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +WlanElementLocator::TWlanLocateStatus WlanElementLocator::ValidIE( + TUint8 aIeId, + TUint8 aIeLength, + const TUint8* aIeData, + TUint8 aIeOuiType, + TUint8 aIeOuiSubtype ) const + { + OsTracePrint( KInfoLevel, (TUint8*) + ("UMAC: WlanElementLocator::ValidIE: element id: %d"), aIeId ); + + TWlanLocateStatus status ( EWlanLocateElementNotFound ); + + switch ( aIeId ) + { + case E802Dot11SupportedRatesIE: + if ( aIeLength >= K802Dot11SupportedRatesIeDataMinLen && + // Note! This is not according to 802.11 std, but some + // implementations do not follow the standard in this respect + aIeLength <= KMaxNumberOfDot11bAndgRates ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11DsParameterSetIE: + if ( aIeLength == K802Dot11DsParameterSetIeDataLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11TimIE: + if ( aIeLength >= K802Dot11TimIeDataMinLen && + aIeLength <= K802Dot11TimIeDataMaxLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11IbssParameterSetIE: + if ( aIeLength == K802Dot11IbssParameterSetIeDataLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11ErpInformationIE: + if ( aIeLength == K802Dot11ErpInformationIeDataLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11HtCapabilitiesIE: + if ( aIeLength == K802Dot11HtCapabilitiesIeDataLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11ExtendedRatesIE: + if ( aIeLength >= K802Dot11ExtendedRatesIeDataMinLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11HtOperationIE: + if ( aIeLength == K802Dot11HtOperationIeDataLen ) + { + status = EWlanLocateOk; + } + break; + case E802Dot11VendorSpecificIE: + if ( aIeData ) + { + if ( !os_memcmp( + aIeData, + &KWmmElemOui, + KIeOuiLength ) && + aIeOuiType == KWmmElemOuiType && + aIeOuiSubtype == KWmmInfoElemOuiSubType ) + { + // WMM information element + + if ( aIeLength == KWmmInfoElemLen ) + { + status = EWlanLocateOk; + } + } + else if ( !os_memcmp( + aIeData, + &KWmmElemOui, + KIeOuiLength ) && + aIeOuiType == KWmmElemOuiType && + aIeOuiSubtype == KWmmParamElemOuiSubtype ) + { + // WMM Parameter Element + + if ( aIeLength == sizeof( SWmmParamElemData ) ) + { + status = EWlanLocateOk; + } + } + else + { + // implementation error + OsTracePrint( KErrorLevel, + (TUint8*)("UMAC: aIeId: %d"), aIeId ); + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + } + else + { +#ifndef NDEBUG + OsTracePrint( KErrorLevel, (TUint8*) + ("UMAC: WlanElementLocator::ValidIE: ERROR: aIeData is NULL") ); + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); +#endif + status = EWlanLocateOk; + } + break; + default: + // implementation error + OsTracePrint( KErrorLevel, + (TUint8*)("UMAC: aIeId: %d"), aIeId ); + OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + OsTracePrint( KInfoLevel, (TUint8*) + ("UMAC: WlanElementLocator::ValidIE: status: %d"), status ); + + return status; + }