wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_sub_operation_adhoc.cpp
changeset 0 c40eb8fe8501
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Statemachine for establishing an adhoc network
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "core_sub_operation_adhoc.h"
       
    20 #include "core_tx_rate_policies.h"
       
    21 #include "core_frame_dot11.h"
       
    22 #include "core_server.h"
       
    23 #include "core_tools.h"
       
    24 #include "am_debug.h"
       
    25 
       
    26 /** The channel definition for automatic channel selection. */
       
    27 const u32_t AUTOMATIC_CHANNEL = 0;
       
    28 
       
    29 const u32_t CH_WEIGHT_1       = 4;
       
    30 const u32_t CH_WEIGHT_2       = 2;
       
    31 const u32_t CH_WEIGHT_3       = 1;
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // ---------------------------------------------------------------------------
       
    37 //
       
    38 core_sub_operation_adhoc_c::core_sub_operation_adhoc_c(
       
    39     u32_t request_id,
       
    40     core_server_c* server,
       
    41     abs_core_driverif_c* drivers,
       
    42     abs_core_server_callback_c* adaptation,
       
    43     core_ap_data_c** ap_data ) :
       
    44     core_operation_base_c( core_operation_unspecified, request_id, server, drivers, adaptation,
       
    45         core_base_flag_drivers_needed ),
       
    46     ptr_ap_data_m( ap_data ),
       
    47     channel_m( 0 )
       
    48     {
       
    49     DEBUG( "core_sub_operation_adhoc_c::core_sub_operation_adhoc_c()" );
       
    50     }
       
    51 
       
    52 // ---------------------------------------------------------------------------
       
    53 // ---------------------------------------------------------------------------
       
    54 //
       
    55 core_sub_operation_adhoc_c::~core_sub_operation_adhoc_c()
       
    56     {
       
    57     DEBUG( "core_sub_operation_adhoc_c::~core_sub_operation_adhoc_c()" );
       
    58 
       
    59     server_m->unregister_event_handler( this );
       
    60     server_m->unregister_frame_handler( this );
       
    61     ptr_ap_data_m = NULL;
       
    62     }
       
    63 
       
    64 // ---------------------------------------------------------------------------
       
    65 // ---------------------------------------------------------------------------
       
    66 //
       
    67 core_error_e core_sub_operation_adhoc_c::next_state()
       
    68     {
       
    69     DEBUG( "core_sub_operation_adhoc_c::next_state()" );
       
    70 
       
    71     switch ( operation_state_m )
       
    72         {
       
    73         case core_state_init:
       
    74             {
       
    75             core_tools_c::fillz(
       
    76                 &noise_per_channel_m[0],
       
    77                 SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_EURO * sizeof( u32_t ) );            
       
    78 
       
    79             core_iap_data_c* iap = &(server_m->get_connection_data()->iap_data());
       
    80             ASSERT( iap->adhoc_channel() <= SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_FCC ); // FCC limitations: no ch 12 or 13
       
    81             ASSERT( iap->ssid().length );
       
    82             ASSERT( iap->ssid().length <= MAX_SSID_LEN );
       
    83             ASSERT( iap->security_mode() == core_security_mode_allow_unsecure ||
       
    84                     iap->security_mode() == core_security_mode_wep );
       
    85 
       
    86             channel_m = iap->adhoc_channel();
       
    87             if ( channel_m != AUTOMATIC_CHANNEL )
       
    88                 {
       
    89                 return goto_state( core_state_req_set_tx_rate_policies );
       
    90                 }
       
    91 
       
    92             /**
       
    93              * Do a broadcast scan to detect the channel with least traffic.
       
    94              */
       
    95             operation_state_m = core_state_scan_start;
       
    96 
       
    97             server_m->get_scan_list().remove_entries_by_age(
       
    98                 server_m->get_device_settings().scan_list_expiration_time );
       
    99 
       
   100             server_m->register_event_handler( this );
       
   101             server_m->register_frame_handler( this );
       
   102 
       
   103             drivers_m->scan(
       
   104                 request_id_m,
       
   105                 core_scan_mode_passive,
       
   106                 BROADCAST_SSID,
       
   107                 server_m->get_device_settings().scan_rate,
       
   108                 server_m->get_core_settings().all_valid_scan_channels(),
       
   109                 server_m->get_device_settings().passive_scan_min_ch_time,
       
   110                 server_m->get_device_settings().passive_scan_max_ch_time,
       
   111                 false_t );
       
   112 
       
   113             break;    
       
   114             }
       
   115         case core_state_scan_start:
       
   116             {
       
   117             DEBUG( "core_sub_operation_adhoc_c::next_state() - scan request completed, waiting for scan completion" );
       
   118 
       
   119             break;
       
   120             }            
       
   121         case core_state_scan_complete:
       
   122             {
       
   123             server_m->unregister_frame_handler( this );
       
   124 
       
   125             DEBUG( "core_sub_operation_adhoc_c::next_state() - selecting channel with least noise" );
       
   126 
       
   127             /**
       
   128              * All channels are now checked and the noise marked.
       
   129              * Now, we have to found the smallest noise.
       
   130              */
       
   131             u32_t tmp_best_noise( 0xFFFFFFFF );
       
   132             u8_t tmp_best_channel( 0 );
       
   133             for ( u8_t idx = 0; idx < SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_FCC; ++idx ) // Only ch 1 - 11
       
   134                 {
       
   135                 DEBUG2( "core_sub_operation_adhoc_c::next_state() - NoiseTable[%u] = %u",
       
   136                     idx, noise_per_channel_m[idx] );
       
   137                 if ( noise_per_channel_m[idx] < tmp_best_noise )
       
   138                     {
       
   139                     tmp_best_noise = noise_per_channel_m[idx];
       
   140                     tmp_best_channel = idx;
       
   141                     }
       
   142                 }
       
   143             channel_m = tmp_best_channel + 1;
       
   144             DEBUG1( "core_sub_operation_adhoc_c::next_state() - channel %u selected",
       
   145                 channel_m );
       
   146 
       
   147             return goto_state( core_state_req_set_tx_rate_policies );
       
   148             }
       
   149         case core_state_req_set_tx_rate_policies:
       
   150             {
       
   151             operation_state_m = core_state_req_start_adhoc;
       
   152 
       
   153             core_tx_rate_policies_s policies;
       
   154             core_tx_rate_policy_mappings_s mappings;
       
   155 
       
   156             if ( server_m->get_core_settings().is_bt_connection_established() )
       
   157                 {
       
   158                 DEBUG( "core_sub_operation_adhoc_c::next_state() - using 802.11bg BT TX rate policy" );
       
   159 
       
   160                 policies.policy_count = 1;
       
   161                 policies.policy[0] = TX_RATE_POLICY_BLUETOOTH_BG;
       
   162                 mappings.policy_for_best_effort = 0;
       
   163                 mappings.policy_for_background = 0;
       
   164                 mappings.policy_for_video = 0;
       
   165                 mappings.policy_for_voice = 0;                
       
   166                 }
       
   167             else
       
   168                 {
       
   169                 DEBUG( "core_sub_operation_adhoc_c::next_state() - using 802.11bg default and voice TX rate policy" );
       
   170 
       
   171                 policies.policy_count = 2;
       
   172                 policies.policy[0] = TX_RATE_POLICY_BG;
       
   173                 policies.policy[1] = TX_RATE_POLICY_VOICE_BG;
       
   174                 mappings.policy_for_best_effort = 0;
       
   175                 mappings.policy_for_background = 0;
       
   176                 mappings.policy_for_video = 0;
       
   177                 mappings.policy_for_voice = 1;           
       
   178                 }
       
   179 
       
   180             /**
       
   181              * Fill in the default retry limits if not overridden by the policy.
       
   182              */
       
   183             for ( u8_t idx( 0 ); idx < policies.policy_count; ++idx )
       
   184                 {
       
   185                 if ( !policies.policy[idx].short_retry_limit )
       
   186                     {
       
   187                     policies.policy[idx].short_retry_limit =
       
   188                         server_m->get_device_settings().short_retry;
       
   189                     }
       
   190                 if ( ! policies.policy[idx].long_retry_limit )
       
   191                     {
       
   192                     policies.policy[idx].long_retry_limit =
       
   193                         server_m->get_device_settings().long_retry;
       
   194                     }
       
   195                 }
       
   196 
       
   197             DEBUG( "core_sub_operation_adhoc_c::next_state() - setting TX rate policies" );
       
   198 
       
   199             drivers_m->set_tx_rate_policies(
       
   200                 request_id_m,
       
   201                 policies,
       
   202                 mappings );
       
   203 
       
   204             break;
       
   205             }            
       
   206         case core_state_req_start_adhoc:
       
   207             {
       
   208             DEBUG( "core_sub_operation_adhoc_c::next_state() - TX rate policies set" );
       
   209 
       
   210             operation_state_m = core_state_adhoc_started;
       
   211 
       
   212             core_encryption_mode_e encryption_mode = core_encryption_mode_disabled;            
       
   213             if( server_m->get_connection_data()->iap_data().security_mode() ==
       
   214                 core_security_mode_wep )
       
   215                 {
       
   216                 encryption_mode = core_encryption_mode_wep;
       
   217                 }
       
   218 
       
   219             DEBUG1( "core_sub_operation_adhoc_c::next_state() - starting the adhoc on channel %u",
       
   220                 channel_m );
       
   221 
       
   222             server_m->register_frame_handler( this );
       
   223 
       
   224             drivers_m->start_ibss(
       
   225                 request_id_m,
       
   226                 server_m->get_connection_data()->iap_data().ssid(),
       
   227                 server_m->get_device_settings().beacon,
       
   228                 channel_m,
       
   229                 encryption_mode );
       
   230 
       
   231             break;    
       
   232             }
       
   233         case core_state_adhoc_started:
       
   234             {
       
   235             /**
       
   236              * If our own beacon has already been received, proceed to the
       
   237              * next state.
       
   238              */            
       
   239             if( *ptr_ap_data_m )
       
   240                 {
       
   241                 return goto_state( core_state_adhoc_complete );
       
   242                 }
       
   243             
       
   244             return goto_state( core_state_adhoc_frame );
       
   245             }
       
   246         case core_state_adhoc_frame:
       
   247             {
       
   248             DEBUG( "core_sub_operation_adhoc_c::next_state() - waiting for beacon frame" );
       
   249 
       
   250             break;
       
   251             }
       
   252         case core_state_adhoc_complete:
       
   253             {
       
   254             server_m->unregister_frame_handler( this );
       
   255 
       
   256             DEBUG( "core_sub_operation_adhoc_c::next_state() - all done" );           
       
   257 
       
   258             return core_error_ok;
       
   259             }
       
   260         default:
       
   261             {
       
   262             ASSERT( false_t );
       
   263             }          
       
   264         }
       
   265 
       
   266     return core_error_request_pending;
       
   267     }
       
   268 
       
   269 // ---------------------------------------------------------------------------
       
   270 // ---------------------------------------------------------------------------
       
   271 //
       
   272 core_error_e core_sub_operation_adhoc_c::cancel()
       
   273     {
       
   274     DEBUG( "core_sub_operation_adhoc_c::cancel() " );    
       
   275     
       
   276     switch ( operation_state_m )
       
   277         {              
       
   278         case core_state_adhoc_started:
       
   279             {
       
   280             /** The connection attempt failed, we are no longer connected. */
       
   281             return next_state();
       
   282             }
       
   283         default:
       
   284             {
       
   285             return failure_reason_m;
       
   286             }
       
   287         }    
       
   288     }
       
   289 
       
   290 // ---------------------------------------------------------------------------
       
   291 // ---------------------------------------------------------------------------
       
   292 //
       
   293 void core_sub_operation_adhoc_c::user_cancel(
       
   294     bool_t do_graceful_cancel )
       
   295     {
       
   296     DEBUG( "core_sub_operation_adhoc_c::user_cancel()" );
       
   297 
       
   298     if ( !do_graceful_cancel )
       
   299         {
       
   300         /**
       
   301          * If we are in a middle of a scan, we have to schedule our own
       
   302          * event.
       
   303          */
       
   304         if ( operation_state_m == core_state_scan_start &&
       
   305              server_m->event_handler() == this &&
       
   306              server_m->frame_handler() == this )         
       
   307             {
       
   308             asynch_default_user_cancel();
       
   309     
       
   310             return;
       
   311             }
       
   312 
       
   313         /**
       
   314          * If we are waiting for a beacon, we have to schedule our own
       
   315          * event.
       
   316          */
       
   317         if ( operation_state_m == core_state_adhoc_frame )
       
   318             {
       
   319             asynch_default_user_cancel();
       
   320     
       
   321             return;            
       
   322             }
       
   323 
       
   324         /**
       
   325          * Everything else is handled by the default implementation.
       
   326          */
       
   327         core_operation_base_c::user_cancel( do_graceful_cancel );
       
   328         }
       
   329     }
       
   330 
       
   331 // ---------------------------------------------------------------------------
       
   332 // ---------------------------------------------------------------------------
       
   333 //    
       
   334 bool_t core_sub_operation_adhoc_c::receive_frame(
       
   335     const core_frame_dot11_c* frame,
       
   336     u8_t rcpi )
       
   337     {
       
   338     DEBUG( "core_sub_operation_adhoc_c::receive_frame()" );
       
   339     
       
   340     if ( frame->type() != core_frame_dot11_c::core_dot11_type_beacon &&
       
   341          frame->type() != core_frame_dot11_c::core_dot11_type_probe_resp )
       
   342         {
       
   343         DEBUG( "core_sub_operation_adhoc_c::receive_frame() - not a beacon or a probe" );        
       
   344         return false_t;
       
   345         }
       
   346 
       
   347     core_ap_data_c* ap_data = core_ap_data_c::instance(
       
   348         server_m->get_wpx_adaptation_instance(),
       
   349         frame,
       
   350         rcpi,
       
   351         true_t );
       
   352     if ( ap_data )
       
   353         {
       
   354         server_m->get_scan_list().update_entry( *ap_data );
       
   355 
       
   356         if ( operation_state_m == core_state_scan_start )
       
   357             {
       
   358             u8_t channel = ap_data->channel();
       
   359             DEBUG1( "core_sub_operation_adhoc_c::next_state() - AP in channel %u",
       
   360                 channel );
       
   361         
       
   362             if ( channel && channel <= SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_EURO )
       
   363                 {
       
   364                 /**
       
   365                  * Add the ch table as follows:
       
   366                  * channel of the AP ==> increase by CH_WEIGHT_1
       
   367                  * channels +-1 ==> increase by CH_WEIGHT_2
       
   368                  * channels +-2 ==> increase by CH_WEIGHT_3
       
   369                  *
       
   370                  * Note that the legal channels are 1 - 13 BUT the
       
   371                  * array is 0 - 12! Beware edges!
       
   372                  */
       
   373                 noise_per_channel_m[channel - 1] += CH_WEIGHT_1;
       
   374                 if ( channel > 1 )
       
   375                     {
       
   376                     noise_per_channel_m[channel - 2] += CH_WEIGHT_2;
       
   377                     }
       
   378                 if ( channel > 2)
       
   379                     {
       
   380                     noise_per_channel_m[channel - 3] += CH_WEIGHT_3;
       
   381                     }
       
   382                 if ( channel < SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_EURO -2 )
       
   383                     {
       
   384                     noise_per_channel_m[channel] += CH_WEIGHT_2;
       
   385                     }
       
   386                 if ( channel < SCAN_BAND_2DOT4GHZ_MAX_CHANNEL_EURO -3 )
       
   387                     {
       
   388                     noise_per_channel_m[channel + 1] += CH_WEIGHT_3;
       
   389                     }
       
   390                 }           
       
   391             }
       
   392         else if ( operation_state_m == core_state_adhoc_started ||
       
   393             operation_state_m == core_state_adhoc_frame )
       
   394             {
       
   395             if ( frame->type() == core_frame_dot11_c::core_dot11_type_beacon )
       
   396                 {
       
   397                 DEBUG( "core_sub_operation_adhoc_c::next_state() - beacon received" );
       
   398 
       
   399                 ASSERT( !ap_data->is_infra() );
       
   400                 ASSERT( !*ptr_ap_data_m );
       
   401 
       
   402                 *ptr_ap_data_m = ap_data;
       
   403 
       
   404                 /**
       
   405                  * If we are just waiting for the beacon frame, we have to schedule
       
   406                  * our own timer to proceed.
       
   407                  */
       
   408                 if( operation_state_m == core_state_adhoc_frame )
       
   409                     {
       
   410                     asynch_goto( core_state_adhoc_complete, CORE_TIMER_IMMEDIATELY );
       
   411                     }
       
   412 
       
   413                 return true_t;
       
   414                 }
       
   415             }
       
   416 
       
   417         delete ap_data;
       
   418         ap_data = NULL;
       
   419         }    
       
   420 
       
   421     return true_t;
       
   422     }
       
   423 
       
   424 
       
   425 // ---------------------------------------------------------------------------
       
   426 // ---------------------------------------------------------------------------
       
   427 //
       
   428 bool_t core_sub_operation_adhoc_c::notify(
       
   429     core_am_indication_e indication )
       
   430     {
       
   431     if ( operation_state_m == core_state_scan_start &&
       
   432          indication == core_am_indication_wlan_scan_complete )
       
   433         {
       
   434         server_m->unregister_event_handler( this );
       
   435 
       
   436         DEBUG( "core_sub_operation_adhoc_c::notify() - scan complete" );
       
   437 
       
   438         asynch_goto( core_state_scan_complete, CORE_TIMER_IMMEDIATELY );
       
   439 
       
   440         return true_t;
       
   441         }
       
   442 
       
   443     return false_t;
       
   444     }