cmmanager/cmmgr/Plugins/cmpluginwlan/src/cmwlancoveragecheck.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:23:51 +0100
branchRCL_3
changeset 58 83ca720e2b9a
parent 0 5a93021fdf25
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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 WLAN Coverage Check class
*
*/


#include <wlanmgmtclient.h>

#include "cmwlancoveragecheck.h"
#include "cmpluginwlan.h"
#include "cmpluginwlandata.h"
#include "cmpluginwlandataarray.h"
#include "cmlogger.h"


/**
* Management frame information element IDs.
* needed to determine coverage
*/
enum T802Dot11InformationElementID
    {
    E802Dot11SsidIE                 = 0,
    E802Dot11SupportedRatesIE       = 1,
    E802Dot11FhParameterSetIE       = 2,
    E802Dot11DsParameterSetIE       = 3,
    E802Dot11CfParameterSetIE       = 4,
    E802Dot11TimIE                  = 5,
    E802Dot11IbssParameterSetIE     = 6,
    E802Dot11CountryIE              = 7,
    E802Dot11HoppingPatternParamIE  = 8,
    E802Dot11HoppingPatternTableIE  = 9,
    E802Dot11RequestIE              = 10,

    E802Dot11ChallengeTextIE        = 16,
    // Reserved for challenge text extension 17 - 31
    E802Dot11ErpInformationIE       = 42,
    E802Dot11ExtendedRatesIE        = 50,
    E802Dot11AironetIE              = 133,
    E802Dot11ApIpAddressIE          = 149,
    E802Dot11RsnIE                  = 221
    };


/**
* Bit masks for Capability Information field.
*/
enum T802Dot11CapabilityBitMask
    {
    E802Dot11CapabilityEssMask          = 0x0001,
    E802Dot11CapabilityIbssMask         = 0x0002,
    E802Dot11CapabilityCfPollableMask   = 0x0004,
    E802Dot11CapabilityCfPollRequestMask= 0x0008,
    E802Dot11CapabilityPrivacyMask      = 0x0010,
    E802Dot11ShortPreambleMask          = 0x0020,
    E802Dot11PbccMask                   = 0x0040,      
    E802Dot11ChannelAgilityMask         = 0x0080
    };


// ======================= MEMBER FUNCTIONS =================================

// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::CCmWlanCoverageCheck()
// ----------------------------------------------------------------------------
//
CCmWlanCoverageCheck::CCmWlanCoverageCheck() : CActive( EPriorityStandard )
    {
    CActiveScheduler::Add( this );
    }
    
// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::~CCmWlanCoverageCheck()
// ----------------------------------------------------------------------------
//
CCmWlanCoverageCheck::~CCmWlanCoverageCheck()
    {
    Cancel();
    }
    
// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::DoCancel
// ----------------------------------------------------------------------------
//
void CCmWlanCoverageCheck::DoCancel()
    {
    iWait.AsyncStop();
    }
    
// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::RunL
// ----------------------------------------------------------------------------
//
void CCmWlanCoverageCheck::RunL()
    {
    CLOG_WRITE( "RunL entered" );
    switch( iProgState )
        {
        case EScanning:
            {
             if( !iStatus.Int() )
                // The list is ready 
                {
                iProgState = EDone;
                iWait.AsyncStop();
                }
            else
                // something went wrong -> no coverage.
                {
                iWait.AsyncStop();
                }
            }
            break;            
        case EDone:
            {
            iWait.AsyncStop();
            }
            break;
            
        default:
            {
            User::Leave( KErrCorrupt );
            }
        }
    }



// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::GetCoverageL
// ----------------------------------------------------------------------------
//
TInt CCmWlanCoverageCheck::GetCoverageL()
    {
    LOGGER_ENTERFN( "CCmWlanCoverageCheck::GetCoverageL" );

    iProgState = EServiceStatus;
    iCoverage = 0;
    
    CWlanMgmtClient* wlanMgmt = CWlanMgmtClient::NewL();
    CleanupStack::PushL( wlanMgmt );

    CWlanScanInfo* scanInfo = CWlanScanInfo::NewL();
    CleanupStack::PushL( scanInfo );

    iProgState = EScanning;
    
    wlanMgmt->GetScanResults( iStatus, *scanInfo );
    
    SetActive();
    iWait.Start();
    
    // now we have the results and might start to work on them...
    if ( iProgState == EDone )
        { //finished without error, work on the result...
        CCmPluginWlanDataArray* wlandataarray = new ( ELeave ) 
            CCmPluginWlanDataArray();
        CleanupStack::PushL( wlandataarray );

        for ( scanInfo->First(); !scanInfo->IsDone(); scanInfo->Next() )
            {
            // iWlanNetworks cannot be modified 'directly' in
            // a const method (like GetBoolAttributeL), so we have to
            // cast away the constness.
            
            // not simply count as before, but check if it is hidden,
            // and do not allow duplicates...
            TBool isHidden( EFalse );
            
            TUint8 ieLen( 0 );
            const TUint8* ieData;
            TBuf8<KWlanMaxSsidLength> ssid8;
            
            TInt ret = scanInfo->InformationElement( E802Dot11SsidIE, ieLen, 
                                                      &ieData );
            if ( ret == KErrNone ) 
                {               
                isHidden = IsHiddenSsid( ieLen, ieData );
                if ( !isHidden )
                    {
                    // get the ssid
                    ssid8.Copy( ieData, ieLen );
                    HBufC* tmp = HBufC::NewLC(KWlanMaxSsidLength);
                    TPtr tmpptr( tmp->Des() );
                    
                    tmpptr.Copy(ssid8);
                    // get the signal strength                        
                    TUint8 rxLevel8 = scanInfo->RXLevel();
                    TInt rxLevel = static_cast< TInt >( rxLevel8 );
                    
                    // now add it to an array of CCmPluginWlanData,
                    // as it is not hidden
                    // the adding function should handle uniqeness and 
                    // signal strength checking, it should contain only
                    // the strongest signal!                        
                    AddToArrayIfNeededL( *wlandataarray, rxLevel, tmpptr );
                    
                    CleanupStack::PopAndDestroy( tmp );
                    }                
                }
            else
                {
                User::Leave( ret );
                }
            }
        iCoverage = wlandataarray->Count();
        
        CleanupStack::PopAndDestroy( wlandataarray );

        CleanupStack::PopAndDestroy( 2, wlanMgmt );
        }
    else
        {
        User::LeaveIfError( iStatus.Int() );        
        }        
        
    return iCoverage;
    }

// ---------------------------------------------------------
// CCmWlanCoverageCheck::IsHiddenSsid
// ---------------------------------------------------------
//    
TBool CCmWlanCoverageCheck::IsHiddenSsid( TUint aSsidLength, 
                                   const TUint8* aSsid ) const
    {
    LOGGER_ENTERFN( "CCmWlanCoverageCheck::IsHiddenSsid" );
    
    const TUint8 CSPACE = 0x20; 
    TBool result( EFalse );
    TBool result2( ETrue );

    if ( !aSsidLength )
        {
        result = ETrue;
        }

    TInt count( 0 );
    TUint8 temp( 0x00 );
    
    for ( TUint i( 0 ); i < aSsidLength; ++i )
        {
        temp = aSsid[i];
        count += temp; // in hidden networks characters are: 0x00
        result2 &= temp == CSPACE ;
        }

    if( !count || result2 )
        {
        result = ETrue;
        }
        
    return result;    
    }


// ---------------------------------------------------------
// CCmWlanCoverageCheck::AddToArrayIfNeededL
// ---------------------------------------------------------
//    
void CCmWlanCoverageCheck::AddToArrayIfNeededL( 
                            CCmPluginWlanDataArray& aArray, 
                            TInt aRXLevel, 
                            TDesC& aNetworkName ) const
    {
    LOGGER_ENTERFN( "CCmWlanCoverageCheck::AddToArrayIfNeededL" );

    // first check if it is already in the array
    
    TBool found( EFalse );
    TInt index( 0 );
    TInt count = aArray.Count();
    
    while( ( index <  count ) && !found  )
        {
        if( ( aArray )[index]->iNetworkName->Compare( aNetworkName ) )
            {
            ++index;   
            }
        else
            {
            found = ETrue;
            }
        }

    TSignalStrength strength = ( TSignalStrength )aRXLevel;
    if ( found )
        {
        // if already exists, check signal strengths
        TSignalStrength signal = ( aArray )[index]->iSignalStrength;
        
        // set to higher value
        ( aArray )[index]->iSignalStrength = 
                              signal < strength ? signal : strength ;
        }
    else
        {
        // new element, add it to array with signal strength!!
        CCmPluginWlanData* data = CCmPluginWlanData::NewLC();
        data->iNetworkName = aNetworkName.AllocL();
        data->iSignalStrength = strength;
        aArray.AppendL( data );
        CleanupStack::Pop( data ); // item owned by list!
        }    
    }


// ----------------------------------------------------------------------------
// CCmWlanCoverageCheck::ScanForPromptedSsidL
// ----------------------------------------------------------------------------
//
TBool CCmWlanCoverageCheck::ScanForPromptedSsidL( TWlanSsid aEnteredSsid,
                                TBool aBroadcast,
                                TWlanNetMode& aNetworkMode, 
                                TWlanConnectionExtentedSecurityMode& aSecurityMode,
                                TBool& aProtectedSetupSupported )
    {
    LOGGER_ENTERFN( "CCmWlanCoverageCheck::ScanForPromptedSsidL" );
    
    TBool found = EFalse;

    iProgState = EServiceStatus;
       
    CWlanMgmtClient* wlanMgmt = CWlanMgmtClient::NewL();
    CleanupStack::PushL( wlanMgmt );

    CWlanScanInfo* scanInfo = CWlanScanInfo::NewL();
    CleanupStack::PushL( scanInfo );

    iProgState = EScanning;
    
    if ( aBroadcast )
        {
        wlanMgmt->GetScanResults( iStatus, *scanInfo );
        }
    else
        {
        wlanMgmt->GetScanResults( aEnteredSsid, iStatus, *scanInfo );
        }

    SetActive();
    iWait.Start();
    
    // now we have the results and might start to work on them...
    if ( iProgState == EDone )
        {       //finished without error, work on the result...
        TSignalStrength signalStrength = ESignalStrengthMin;

        for ( scanInfo->First(); !scanInfo->IsDone(); scanInfo->Next() )
            {
            TUint8 ieLen( 0 );
            const TUint8* ieData;
            TBuf8<KWlanMaxSsidLength> ssid8;
            
            TInt ret = scanInfo->InformationElement( E802Dot11SsidIE, ieLen, 
                                                     &ieData );
            if ( ret == KErrNone ) 
                {               
                // get the ssid
                ssid8.Copy( ieData, ieLen );
                
                if ( !aEnteredSsid.Compare( ssid8 ) )
                    {
                    // get the signal strength                        
                    TUint8 rxLevel8 = scanInfo->RXLevel();
                    TInt rxLevel = static_cast< TInt >( rxLevel8 );
            
                    TSignalStrength strength = ( TSignalStrength )rxLevel;
                    if ( !found || ( found && strength < signalStrength ) )
                        {
                        found = ETrue;
                        signalStrength = strength;

                        aNetworkMode = ( scanInfo->Capability() & 
                                         E802Dot11CapabilityEssMask ) ?
                                       EInfra : EAdhoc;
                        aSecurityMode = scanInfo->ExtendedSecurityMode();

                        aProtectedSetupSupported = 
                                        scanInfo->IsProtectedSetupSupported();
                        }
                    }
                }
            else
                {
                User::Leave( ret );
                }
        
            }
        
        CleanupStack::PopAndDestroy( scanInfo );
        CleanupStack::PopAndDestroy( wlanMgmt );
        }
    else
        {
        User::LeaveIfError( iStatus.Int() );        
        }
    
    return found;
    }