wlan_bearer/wlanldd/wlan_common/umac_common/src/umacelementlocator.cpp
changeset 0 c40eb8fe8501
--- /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;
+    }