wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_check_rcpi.cpp
changeset 0 c40eb8fe8501
child 7 0abc8c98be24
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_check_rcpi.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,512 @@
+/*
+* Copyright (c) 2005-2010 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:  Statemachine for requesting RCPI values for roaming.
+*
+*/
+
+/*
+* %version: 21 %
+*/
+
+#include "core_operation_check_rcpi.h"
+#include "core_operation_roam.h"
+#include "core_operation_handle_bss_lost.h"
+#include "core_sub_operation_roam_scan.h"
+#include "core_server.h"
+#include "am_debug.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_operation_check_rcpi_c::core_operation_check_rcpi_c(
+    u32_t request_id,
+    core_server_c* server,
+    abs_core_driverif_c* drivers,
+    abs_core_server_callback_c* adaptation,
+    core_rcpi_check_reason_e reason ) :
+    core_operation_base_c( core_operation_check_rcpi, request_id, server, drivers, adaptation,
+        core_base_flag_drivers_needed | core_base_flag_connection_needed | core_base_flag_roam_operation ),
+    reason_m(  reason ),
+    current_rcpi_m( 0 ),
+    is_connected_m( true_t ) 
+    {
+    DEBUG( "core_operation_check_rcpi_c::core_operation_check_rcpi_c()" );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_operation_check_rcpi_c::~core_operation_check_rcpi_c()
+    {
+    DEBUG( "core_operation_check_rcpi_c::~core_operation_check_rcpi_c()" );
+    }
+    
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_operation_check_rcpi_c::next_state()
+    {
+    DEBUG( "core_operation_check_rcpi_c::next_state()" );
+    
+    switch ( operation_state_m )
+        {
+        case core_state_init:
+            {
+#ifdef _DEBUG
+            switch ( reason_m )
+                {
+                case core_rcpi_check_reason_timer:
+                    DEBUG( "core_operation_check_rcpi_c::next_state() - core_rcpi_check_reason_timer" );
+                    break;
+                case core_rcpi_check_reason_rcpi_trigger:
+                    DEBUG( "core_operation_check_rcpi_c::next_state() - core_rcpi_check_reason_rcpi_trigger" );
+                    break;
+                case core_rcpi_check_reason_signal_loss_prediction:
+                    DEBUG( "core_operation_check_rcpi_c::next_state() - core_rcpi_check_reason_signal_loss_prediction" );
+                    break;
+                default:
+                    ASSERT( false_t );
+                }
+#endif // _DEBUG
+
+            operation_state_m = core_state_rcpi_received;
+
+            /**
+             * Cancel the roaming timer just in case.
+             */
+            server_m->cancel_roam_timer();
+
+            DEBUG( "core_operation_check_rcpi_c::next_state() - requesting RCPI" );
+
+            drivers_m->get_current_rcpi(
+                request_id_m,
+                current_rcpi_m );
+
+            break;
+            }
+        case core_state_rcpi_received:
+            {
+            operation_state_m = core_state_rcpi_trigger;
+
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - current RCPI is %u",
+                current_rcpi_m );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - internal RCPI threshold level is %u",
+                server_m->get_device_settings().rcpi_trigger );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - external RCPI threshold level (down) is %u",
+                server_m->get_core_settings().rcp_decline_boundary() );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - external RCPI threshold level (up) is %u",
+                server_m->get_core_settings().rcp_improve_boundary() );
+
+            u8_t trigger_level_down = server_m->get_core_settings().rcp_decline_boundary();
+            if ( trigger_level_down < server_m->get_device_settings().rcpi_trigger )
+                {
+                trigger_level_down = server_m->get_device_settings().rcpi_trigger;
+                }
+            u8_t trigger_level_up = server_m->get_core_settings().rcp_improve_boundary();
+            if ( trigger_level_up < server_m->get_device_settings().rcpi_trigger )
+                {
+                trigger_level_up = server_m->get_device_settings().rcpi_trigger;
+                }
+
+            /**
+             * If signal level drops below roaming threshold, attempt roaming.
+             */
+            if ( current_rcpi_m < server_m->get_device_settings().rcpi_trigger &&
+                 server_m->get_connection_data()->iap_data().is_roaming_allowed() )
+                {
+                return goto_state( core_state_scan_start );
+                }
+
+            /**
+             * If moving from weak level to normal, notify client.
+             */
+            if ( current_rcpi_m > server_m->get_core_settings().rcp_improve_boundary() &&
+                 server_m->get_connection_data()->last_rcp_class() != core_rcp_normal )
+                {
+                DEBUG( "core_operation_check_rcpi_c::next_state() - sending a notification about the normal signal level" );
+
+                u8_t buf[5];
+                buf[0] = static_cast<u8_t>( core_rcp_normal );
+                buf[1] = static_cast<u8_t>( current_rcpi_m );
+
+                adaptation_m->notify(
+                    core_notification_rcp_changed,
+                    sizeof( buf ),
+                    buf );
+                server_m->get_connection_data()->set_last_rcp_class( core_rcp_normal );
+
+                DEBUG( "core_operation_check_rcpi_c::next_state() - reseting RCPI roam check interval" );
+                server_m->get_connection_data()->reset_rcpi_roam_interval();
+                }
+
+            /** 
+             * Send an indication to adaptation to indicate that this
+             * roam attempt has been completed.
+             */  
+            adaptation_m->notify(                
+                core_notification_rcpi_roam_attempt_completed,
+                0,
+                NULL );           
+
+            /**
+             * If the signal level is above the trigger level, we only have to check
+             * whether we should re-arm the trigger.
+             */
+            if ( current_rcpi_m > trigger_level_up )
+                {
+                DEBUG1( "core_operation_check_rcpi_c::next_state() - signal level is above trigger_level_up (%u)",
+                    trigger_level_up );
+
+                /**
+                 * If the operation was started because of a trigger event, schedule a timer.
+                 * This is done to prevent constant triggering when the signal level is
+                 * hovering right on the trigger level.
+                 */
+                if ( reason_m == core_rcpi_check_reason_rcpi_trigger ||
+                     reason_m == core_rcpi_check_reason_signal_loss_prediction )
+                    {
+                    DEBUG1( "core_operation_check_rcpi_c::next_state() - was triggered, scheduling the roaming timer to %u",
+                        server_m->get_device_settings().roam_timer );
+
+                    server_m->schedule_roam_timer(
+                        server_m->get_device_settings().roam_timer );
+
+                    return core_error_ok;
+                    }
+
+                /**
+                 * At least one timer-based poll has been done, trigger can be re-armed.
+                 */
+                DEBUG1( "core_operation_check_rcpi_c::next_state() - was not triggered, arming RCPI roam trigger (%u)",
+                    trigger_level_down );
+
+                drivers_m->set_rcpi_trigger_level(
+                    request_id_m,
+                    trigger_level_down );
+
+                DEBUG( "core_operation_check_rcpi_c::next_state() - reseting RCPI roam check interval" );
+                server_m->get_connection_data()->reset_rcpi_roam_interval();
+
+                return core_error_request_pending;
+                }
+
+            /**
+             * If we have come this far, it means the current signal level is between the
+             * external and the internal threshold level. Schedule a timer and if the operation
+             * was started because of a timer event, re-arm the trigger as well.
+             */
+            DEBUG2( "core_operation_check_rcpi_c::next_state() - between trigger_level_down (%u) and trigger_level_up (%u)",
+                trigger_level_down, trigger_level_up );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - scheduling the roaming timer to %u",
+                server_m->get_device_settings().roam_timer );
+
+            server_m->schedule_roam_timer(
+                server_m->get_device_settings().roam_timer );            
+
+            if ( reason_m == core_rcpi_check_reason_timer )
+                {
+                DEBUG1( "core_operation_check_rcpi_c::next_state() - was not triggered, arming RCPI roam trigger (%u)",
+                    trigger_level_down );                
+
+                drivers_m->set_rcpi_trigger_level(
+                    request_id_m,
+                    trigger_level_down );
+
+                return core_error_request_pending;
+                }
+
+            return core_error_ok;
+            }
+        case core_state_rcpi_trigger:
+            {
+            DEBUG( "core_operation_check_rcpi_c::next_state() - trigger re-armed" ); 
+
+            return core_error_ok;
+            }
+        case core_state_scan_start:
+            {
+            operation_state_m = core_state_scan_complete;
+
+            DEBUG( "core_operation_check_rcpi_c::next_state() - starting a direct scan on all channels" );           
+
+            server_m->get_scan_list().set_tag(
+                core_scan_list_tag_roam_scan );
+
+            core_operation_base_c* operation = new core_sub_operation_roam_scan_c(
+                request_id_m,
+                server_m,
+                drivers_m,
+                adaptation_m,
+                server_m->get_connection_data()->ssid(),
+                server_m->get_core_settings().all_valid_scan_channels(),
+                true_t,
+                false_t );
+
+            return run_sub_operation( operation );            
+            }
+        case core_state_scan_complete:
+            {
+            operation_state_m = core_state_connect_success;
+
+            DEBUG( "core_operation_check_rcpi_c::next_state() - attempting to roam" );
+
+            if ( reason_m == core_rcpi_check_reason_signal_loss_prediction )
+                {
+                server_m->get_connection_data()->set_last_roam_reason(
+                    core_roam_reason_signal_loss_prediction );
+                }
+            else
+                {
+                server_m->get_connection_data()->set_last_roam_reason(
+                    core_roam_reason_signal_strength );               
+                }
+            server_m->get_connection_data()->set_last_roam_failed_reason(
+                core_roam_failed_reason_none );
+
+            medium_time_s admitted_medium_time(
+                server_m->get_connection_data()->traffic_stream_list().admitted_medium_time() );            
+
+            core_operation_base_c* operation = new core_operation_roam_c(
+                request_id_m,
+                server_m,
+                drivers_m,
+                adaptation_m,
+                is_connected_m,
+                core_scan_list_tag_roam_scan,
+                current_rcpi_m + server_m->get_device_settings().rcpi_difference,
+                admitted_medium_time,
+                server_m->get_connection_data()->ssid(),
+                BROADCAST_MAC_ADDR );
+
+            return run_sub_operation( operation );
+            }                                   
+        case core_state_connect_success:
+            {
+            operation_state_m = core_state_rcpi_trigger;
+
+            DEBUG( "core_operation_check_rcpi_c::next_state() - roamed successfully" );
+                        
+            /**
+             * If moving from weak level to normal, notify client.
+             */
+            if ( server_m->get_connection_data()->last_rcp_class() != core_rcp_normal )
+                {
+                DEBUG( "core_operation_check_rcpi_c::next_state() - sending a notification about the normal signal level" );
+
+                u8_t buf[5];
+                buf[0] = static_cast<u8_t>( core_rcp_normal );
+                buf[1] = server_m->get_connection_data()->current_ap_data()->rcpi();
+                
+                adaptation_m->notify(
+                    core_notification_rcp_changed,
+                    sizeof( buf ),
+                    buf );
+                server_m->get_connection_data()->set_last_rcp_class( core_rcp_normal );
+                }
+
+            /** 
+             * Send an indication to adaptation to indicate that this
+             * roam attempt has been completed.
+             */  
+            adaptation_m->notify(                
+                core_notification_rcpi_roam_attempt_completed,
+                0,
+                NULL );           
+
+            DEBUG( "core_operation_check_rcpi_c::next_state() - reseting RCPI roam check interval" );
+            server_m->get_connection_data()->reset_rcpi_roam_interval();
+
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - internal RCPI threshold level is %u",
+                server_m->get_device_settings().rcpi_trigger );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - external RCPI threshold level is %u",
+                server_m->get_core_settings().rcp_decline_boundary() );
+
+            u8_t trigger_level = server_m->get_core_settings().rcp_decline_boundary();
+            if ( trigger_level < server_m->get_device_settings().rcpi_trigger )
+                {
+                trigger_level = server_m->get_device_settings().rcpi_trigger;
+                }
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - arming RCPI roam trigger (%u)",
+                trigger_level );
+
+            drivers_m->set_rcpi_trigger_level(
+                request_id_m,
+                trigger_level );
+
+            break;
+            }
+        case core_state_connect_failure:
+            {
+            operation_state_m = core_state_rcpi_trigger;
+                      
+            DEBUG( "core_operation_check_rcpi_c::next_state() - roaming failed" );
+            
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - internal RCPI threshold level is %u",
+                server_m->get_device_settings().rcpi_trigger );
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - external RCPI threshold level is %u",
+                server_m->get_core_settings().rcp_decline_boundary() );
+            
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - current RCPI is %u",
+                current_rcpi_m );
+
+            u8_t weak_trigger_level = server_m->get_core_settings().rcp_decline_boundary();
+            if ( weak_trigger_level > server_m->get_device_settings().rcpi_trigger )
+                {
+                weak_trigger_level = server_m->get_device_settings().rcpi_trigger;
+                }
+            weak_trigger_level = weak_trigger_level - 20;
+            
+            DEBUG1( "core_operation_check_rcpi_c::next_state() - weak_trigger_level (%u)",
+                               weak_trigger_level );
+            /**
+             * If we haven't notified the clients about a weak signal earlier,
+             * do it now.
+             */
+            if ( current_rcpi_m < weak_trigger_level &&
+                server_m->get_connection_data()->last_rcp_class() != core_rcp_weak )
+                {
+                DEBUG( "core_operation_check_rcpi_c::next_state() - sending a notification about the weak signal level" );
+
+                u8_t buf[5];
+                buf[0] = static_cast<u8_t>( core_rcp_weak );
+                buf[1] = static_cast<u8_t>( current_rcpi_m );
+                  
+                /**
+                 * Get current IAP Id value and add it to the weak list. 
+                 */
+                server_m->get_core_settings().add_iap_id_to_weak_iap_list(
+                     server_m->get_connection_data()->iap_data().iap_id());
+                 
+                adaptation_m->notify(
+                    core_notification_rcp_changed,
+                    sizeof( buf ),
+                    buf );
+                server_m->get_connection_data()->set_last_rcp_class( core_rcp_weak ); 
+                
+                }
+
+            if ( !is_connected_m )
+                {
+                DEBUG( "core_operation_check_rcpi_c::next_state() - no longer connected, scheduling bss_lost operation" );
+
+                core_operation_base_c* operation = new core_operation_handle_bss_lost_c(
+                    REQUEST_ID_CORE_INTERNAL,
+                    server_m,
+                    drivers_m,
+                    adaptation_m,
+                    core_operation_handle_bss_lost_c::core_bss_lost_reason_failed_rcpi_roam );
+
+                server_m->queue_int_operation( operation );
+                }
+            else
+                {
+                /** 
+                 * Send an indication to adaptation to indicate that this
+                 * roam attempt has been completed.
+                 */  
+                adaptation_m->notify(                
+                    core_notification_rcpi_roam_attempt_completed,
+                    0,
+                    NULL );
+                
+                core_rcpi_roam_interval_s interval(
+                    server_m->get_connection_data()->rcpi_roam_interval() );
+                ++interval.count;
+
+                if ( interval.count > server_m->get_device_settings().rcpi_roam_attempts_per_interval )
+                    {
+                    DEBUG1( "core_operation_check_rcpi_c::next_state() - maximum interval attempts (%u) exceeded, increasing interval",
+                        server_m->get_device_settings().rcpi_roam_attempts_per_interval );
+                    interval.count = 1;
+                    interval.interval *= server_m->get_device_settings().rcpi_roam_next_interval_factor;
+                    interval.interval += server_m->get_device_settings().rcpi_roam_next_interval_addition;
+
+                    if ( interval.interval > server_m->get_device_settings().rcpi_roam_max_interval )
+                        {
+                        interval.interval = server_m->get_device_settings().rcpi_roam_max_interval;
+                        
+                        DEBUG1( "core_operation_check_rcpi_c::next_state() - interval value set to maximum (%u)",
+                            interval.interval );
+                        }
+                    else
+                        {
+                        DEBUG1( "core_operation_check_rcpi_c::next_state() - interval value set to %u",
+                            interval.interval );
+                        }
+                    }
+
+                server_m->get_connection_data()->set_core_rcpi_roam_interval(
+                    interval );
+
+                DEBUG1( "core_operation_check_rcpi_c::next_state() - arming the roaming timer to %u",
+                    interval.interval );
+
+                server_m->schedule_roam_timer(
+                    interval.interval );
+                
+                if ( server_m->get_connection_data()->last_rcp_class() != core_rcp_weak )
+                    {
+                    DEBUG( "core_operation_check_rcpi_c::next_state() - set_rcpi_trigger_level( weak_trigger_level )" );
+            
+                    DEBUG1( "core_operation_check_rcpi_c::next_state() - arming new RCPI roam trigger (%u)",
+                        weak_trigger_level );
+               
+                    drivers_m->set_rcpi_trigger_level(   
+                         request_id_m,
+                         weak_trigger_level );
+               
+                    return core_error_request_pending;
+                    }
+                }
+            return core_error_ok;
+            }
+        default:
+            {
+            ASSERT( false_t );
+            }
+        }
+
+    return core_error_request_pending;
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_operation_check_rcpi_c::cancel()
+    {
+    DEBUG( "core_operation_check_rcpi_c::cancel() " );    
+    
+    switch ( operation_state_m )
+        {              
+        case core_state_connect_success:
+            {            
+            return goto_state( core_state_connect_failure );
+            }
+        default:
+            {
+            /** 
+             * Send an indication to adaptation to indicate that this
+             * roam attempt has been completed.
+             */  
+            adaptation_m->notify(                
+                core_notification_rcpi_roam_attempt_completed,
+                0,
+                NULL );
+
+            return failure_reason_m;
+            }
+        }    
+    }