wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_scan.cpp
changeset 0 c40eb8fe8501
child 5 51a71243e562
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 * ST-Ericsson
       
    14 *
       
    15 * Description:  Statemachine for scanning
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include "core_operation_scan.h"
       
    21 #include "core_server.h"
       
    22 #include "core_tools.h"
       
    23 #include "core_frame_beacon.h"
       
    24 #include "core_scan_list.h"
       
    25 #include "am_debug.h"
       
    26 
       
    27 // ======== MEMBER FUNCTIONS ========
       
    28 
       
    29 // ---------------------------------------------------------------------------
       
    30 // ---------------------------------------------------------------------------
       
    31 //
       
    32 core_operation_scan_c::core_operation_scan_c(
       
    33     u32_t request_id,
       
    34     core_server_c* server,
       
    35     abs_core_driverif_c* drivers,
       
    36     abs_core_server_callback_c* adaptation,
       
    37     core_scan_mode_e scan_mode,
       
    38     const core_ssid_s& scan_ssid,
       
    39     const core_scan_channels_s& scan_channels,
       
    40     u8_t scan_max_age,       
       
    41     ScanList& scan_data,
       
    42     bool_t passive_scan_all_channels,
       
    43     bool_t is_current_ap_added ) :
       
    44     core_operation_base_c( core_operation_scan, request_id, server, drivers, adaptation,
       
    45         core_base_flag_drivers_needed ),    
       
    46     scan_mode_m( scan_mode ),
       
    47     scan_ssid_m( scan_ssid ),
       
    48     scan_channels_m( scan_channels ),
       
    49     scan_max_age_m( scan_max_age ),
       
    50     scan_data_m( scan_data ),
       
    51     passive_scan_all_channels_m( passive_scan_all_channels ),
       
    52     region_from_ap_m( core_wlan_region_fcc ),
       
    53     is_current_ap_added_m( is_current_ap_added ),
       
    54     current_rcpi_m( 0 )
       
    55     {
       
    56     DEBUG( "core_operation_scan_c::core_operation_scan_c()" );
       
    57     }
       
    58 
       
    59 // ---------------------------------------------------------------------------
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 core_operation_scan_c::~core_operation_scan_c()
       
    63     {      
       
    64     DEBUG( "core_operation_scan_c::~core_operation_scan_c()" );
       
    65 
       
    66     server_m->unregister_event_handler( this );
       
    67     server_m->unregister_frame_handler( this );
       
    68     }
       
    69     
       
    70 // ---------------------------------------------------------------------------
       
    71 // ---------------------------------------------------------------------------
       
    72 //
       
    73 core_error_e core_operation_scan_c::next_state()
       
    74     {
       
    75     DEBUG( "core_operation_scan_c::next_state()" );
       
    76 
       
    77     switch ( operation_state_m )
       
    78         {
       
    79         case core_state_init:
       
    80             {                        
       
    81             operation_state_m = core_state_scan_start;
       
    82 
       
    83             u32_t min_ch_time( server_m->get_device_settings().active_scan_min_ch_time );
       
    84             u32_t max_ch_time( server_m->get_device_settings().active_scan_max_ch_time );
       
    85             if ( scan_mode_m == core_scan_mode_passive )
       
    86                 {
       
    87                 min_ch_time = server_m->get_device_settings().passive_scan_min_ch_time;
       
    88                 max_ch_time = server_m->get_device_settings().passive_scan_max_ch_time;
       
    89                 }
       
    90 
       
    91             if ( scan_ssid_m.length )
       
    92                 {
       
    93                 DEBUG1S( "core_operation_scan_c::next_state() - requesting a direct scan with SSID ",
       
    94                     scan_ssid_m.length, &scan_ssid_m.ssid[0] );
       
    95                 }
       
    96             else
       
    97                 {
       
    98                 DEBUG( "core_operation_scan_c::next_state() - requesting a broadcast scan" );
       
    99                 }
       
   100 
       
   101             bool_t is_split_scan( false_t );
       
   102             if ( server_m->get_core_settings().is_connected() )
       
   103                 {
       
   104                 is_split_scan = true_t;
       
   105                 DEBUG( "core_operation_scan_c::next_state() - requesting a split-scan" );
       
   106                 }
       
   107             else
       
   108                 {
       
   109                 DEBUG( "core_operation_scan_c::next_state() - requesting a regular scan" );
       
   110                 }
       
   111 
       
   112             server_m->get_scan_list().remove_entries_by_age(
       
   113                 server_m->get_device_settings().scan_list_expiration_time );
       
   114 
       
   115             server_m->get_scan_list().set_tag(
       
   116                 core_scan_list_tag_scan );
       
   117 
       
   118             server_m->register_event_handler( this );
       
   119             server_m->register_frame_handler( this );
       
   120             
       
   121             drivers_m->scan(
       
   122                 request_id_m,
       
   123                 scan_mode_m,
       
   124                 scan_ssid_m,
       
   125                 server_m->get_device_settings().scan_rate,
       
   126                 server_m->get_core_settings().valid_scan_channels( scan_channels_m ),
       
   127                 min_ch_time,
       
   128                 max_ch_time,
       
   129                 is_split_scan );
       
   130 
       
   131             break;
       
   132             }
       
   133         case core_state_scan_start:
       
   134             {
       
   135             DEBUG( "core_operation_scan_c::next_state() - scan request completed, waiting for scan completion" );
       
   136 
       
   137             break;
       
   138             }
       
   139         case core_state_scan_complete:
       
   140             {          
       
   141             /* If country information is not known then channels 12 and 13 can be scanned in passive mode */
       
   142             if ( server_m->get_core_settings().mcc_known() || scan_ssid_m.length || !passive_scan_all_channels_m )
       
   143             	{
       
   144             	/* All possible scans are done. 
       
   145             	 * When MCC information is known, the allowed scan channels are known and handled already.
       
   146             	 * If SSID is given then direct scan would be required so no need to do passive broadcast scan.
       
   147             	 * If operation does not require passive scanning on channels 12 and 13, this is not done. 
       
   148             	 */
       
   149             	return goto_state( core_state_scan_complete_handle_result );
       
   150             	}
       
   151             
       
   152             operation_state_m = core_state_scan_start_unknown_region;
       
   153             
       
   154             u32_t min_ch_time( server_m->get_device_settings().passive_scan_min_ch_time );
       
   155             u32_t max_ch_time( server_m->get_device_settings().passive_scan_max_ch_time );
       
   156 
       
   157             bool_t is_split_scan( false_t );
       
   158             if ( server_m->get_core_settings().is_connected() )
       
   159                 {
       
   160                 is_split_scan = true_t;
       
   161                 DEBUG( "core_operation_scan_c::next_state() - requesting a split-scan for channels 12 and 13" );
       
   162                 }
       
   163             else
       
   164                 {
       
   165                 DEBUG( "core_operation_scan_c::next_state() - requesting a regular scan for channels 12 and 13" );
       
   166                 }
       
   167 
       
   168             server_m->register_event_handler( this );
       
   169             server_m->register_frame_handler( this );
       
   170 
       
   171             drivers_m->scan(
       
   172                 request_id_m,
       
   173                 core_scan_mode_passive,
       
   174                 scan_ssid_m,
       
   175                 server_m->get_device_settings().scan_rate,
       
   176                 server_m->get_core_settings().invalid_scan_channels( scan_channels_m ),
       
   177                 min_ch_time,
       
   178                 max_ch_time,
       
   179                 is_split_scan );
       
   180 
       
   181             break;
       
   182             }
       
   183         case core_state_scan_start_unknown_region:
       
   184             {
       
   185             DEBUG( "core_operation_scan_c::next_state() - scan request for channels 12 and 13 completed, waiting for scan completion" );
       
   186 
       
   187             break;
       
   188             }
       
   189         case core_state_scan_complete_unknown_region:
       
   190         	{
       
   191             server_m->unregister_frame_handler( this );
       
   192             server_m->get_scan_list().print_contents(); // Additional print            
       
   193 
       
   194             operation_state_m = core_state_scan_complete_store_country_info;
       
   195 
       
   196             /* If WLAN region was not known before the scan, then check if country information is present
       
   197              * in the scan results. APs on channels 12 and 13 must be ignored if country information indicates this. 
       
   198              */
       
   199             core_scan_list_iterator_by_tag_c iter_country_beacon(
       
   200                 server_m->get_scan_list(),
       
   201                 core_scan_list_tag_scan );
       
   202 
       
   203             core_wlan_region_e found_region = core_wlan_region_undefined;
       
   204             bool_t inconsistent_info( false_t );
       
   205             for ( core_ap_data_c* ap_data = iter_country_beacon.first(); ap_data; ap_data = iter_country_beacon.next() )
       
   206                 {
       
   207                 core_country_string_s country_info = ap_data->country_info();
       
   208                 core_wlan_region_e ap_region = core_wlan_region_undefined;
       
   209                 if ( country_info.country[0] != 0 )                   
       
   210                     {
       
   211                     ap_region = core_tools_c::convert_country_to_region( country_info );
       
   212                     if ( found_region != core_wlan_region_undefined )
       
   213                       	{
       
   214                        	if ( ap_region != found_region )
       
   215                        		{
       
   216                       	    inconsistent_info = true_t; 
       
   217                        		}
       
   218                        	}
       
   219                     else
       
   220                        	{
       
   221                        	found_region = ap_region;
       
   222                        	}                        
       
   223                     }
       
   224                 }
       
   225             if ( found_region != core_wlan_region_undefined )
       
   226                	{
       
   227                	if ( !inconsistent_info )
       
   228                		{	
       
   229                	    region_from_ap_m = found_region;
       
   230                		}
       
   231                	else
       
   232                		{
       
   233                		region_from_ap_m = core_wlan_region_etsi;
       
   234                		}
       
   235                	adaptation_m->store_ap_country_info( request_id_m, region_from_ap_m, inconsistent_info );
       
   236                	}
       
   237             else
       
   238                	{
       
   239                	DEBUG( "core_operation_scan_c::next_state() - country info not found, continue with handling scan results" );
       
   240                	return goto_state( core_state_scan_complete_handle_result );
       
   241                	}
       
   242        	    break;
       
   243        	    }
       
   244         	
       
   245         case core_state_scan_complete_store_country_info:
       
   246           	{
       
   247             operation_state_m = core_state_scan_complete_handle_result;
       
   248             	
       
   249             /* Set the new region information also to core settings */
       
   250             DEBUG1( "core_operation_scan_c::next_state() - current region %u",
       
   251                 region_from_ap_m );
       
   252             server_m->get_core_settings().set_regional_domain(
       
   253                 region_from_ap_m );
       
   254             server_m->get_core_settings().set_mcc_known( true_t );
       
   255             	
       
   256             return goto_state( core_state_scan_complete_handle_result );
       
   257             }
       
   258 
       
   259         case core_state_scan_complete_handle_result:   
       
   260           	{
       
   261             /* If region is FCC, then ignore and remove the APs from channels 12 and 13 */
       
   262             if ( server_m->get_core_settings().regional_domain() == core_wlan_region_fcc )
       
   263             	{
       
   264             	DEBUG( "core_operation_scan_c::next_state() - remove APs that were found on channels 12 and 13" );
       
   265             	remove_disallowed_aps();
       
   266             	}
       
   267 
       
   268             DEBUG( "core_operation_scan_c::next_state() - final scan list" );
       
   269             server_m->get_scan_list().print_contents(); // Additional print            
       
   270 
       
   271             /**
       
   272              * If we have an ongoing connection, we'll have to see whether
       
   273              * the current AP was found in the scan.
       
   274              */
       
   275             core_ssid_s current_ssid( BROADCAST_SSID );
       
   276             core_mac_address_s current_bssid( ZERO_MAC_ADDR );
       
   277             bool_t is_current_ap_in_list( true_t );
       
   278             if ( is_current_ap_added_m &&
       
   279                  server_m->get_connection_data() &&
       
   280                  server_m->get_connection_data()->current_ap_data() )
       
   281                 {
       
   282                 current_ssid =
       
   283                     server_m->get_connection_data()->ssid();
       
   284                 current_bssid =
       
   285                     server_m->get_connection_data()->current_ap_data()->bssid();
       
   286 
       
   287                 /**
       
   288                  * Current AP only needs to be added in a broadcast scan or a direct
       
   289                  * scan done with the same SSID.
       
   290                  */
       
   291                 if ( !scan_ssid_m.length ||
       
   292                      scan_ssid_m == current_ssid )
       
   293                     {
       
   294                     is_current_ap_in_list = false_t;
       
   295                     }
       
   296                 }
       
   297 
       
   298             if ( scan_ssid_m.length )
       
   299                 {
       
   300                 core_scan_list_iterator_by_tag_and_ssid_c iter(
       
   301                     server_m->get_scan_list(),
       
   302                     core_scan_list_tag_scan,
       
   303                     scan_ssid_m );
       
   304                 for ( core_ap_data_c* ap_data = iter.first(); ap_data; ap_data = iter.next() )
       
   305                     {
       
   306                     const core_mac_address_s bssid = ap_data->bssid();
       
   307 
       
   308                     if ( !server_m->get_core_settings().is_mac_in_permanent_blacklist( bssid ) )
       
   309                         {
       
   310                         if ( !is_current_ap_in_list &&
       
   311                             current_bssid == bssid &&
       
   312                             current_ssid == ap_data->ssid() )
       
   313                             {
       
   314                             is_current_ap_in_list = true_t;
       
   315                             }
       
   316 
       
   317                         core_tools_c::add_beacon_to_scan_list(
       
   318                             scan_data_m,
       
   319                             *ap_data,
       
   320                             ap_data->rcpi() );
       
   321                         }
       
   322                     }
       
   323                 }
       
   324             else if ( !scan_max_age_m )
       
   325                 {
       
   326                 core_scan_list_iterator_by_tag_c iter(
       
   327                     server_m->get_scan_list(),
       
   328                     core_scan_list_tag_scan );
       
   329                 for ( core_ap_data_c* ap_data = iter.first(); ap_data; ap_data = iter.next() )
       
   330                     {
       
   331                     const core_mac_address_s bssid = ap_data->bssid();
       
   332 
       
   333                     if ( !server_m->get_core_settings().is_mac_in_permanent_blacklist( bssid ) )
       
   334                         {
       
   335                         if ( !is_current_ap_in_list &&
       
   336                              current_bssid == bssid &&
       
   337                              current_ssid == ap_data->ssid() )
       
   338                             {
       
   339                             is_current_ap_in_list = true_t;
       
   340                             }
       
   341 
       
   342                         core_tools_c::add_beacon_to_scan_list(
       
   343                             scan_data_m,
       
   344                             *ap_data,
       
   345                             ap_data->rcpi() );
       
   346                         }
       
   347                     }
       
   348                 }
       
   349             else
       
   350                 {
       
   351                 core_scan_list_iterator_by_age_c iter(
       
   352                     server_m->get_scan_list(),
       
   353                     scan_max_age_m );
       
   354                 for ( core_ap_data_c* ap_data = iter.first(); ap_data; ap_data = iter.next() )
       
   355                     {
       
   356                     const core_mac_address_s bssid = ap_data->bssid();
       
   357 
       
   358                     if ( !server_m->get_core_settings().is_mac_in_permanent_blacklist( bssid ) )
       
   359                         {
       
   360                         if ( !is_current_ap_in_list &&
       
   361                              current_bssid == bssid &&
       
   362                              current_ssid == ap_data->ssid() )
       
   363                             {
       
   364                             is_current_ap_in_list = true_t;
       
   365                             }
       
   366 
       
   367                         core_tools_c::add_beacon_to_scan_list(
       
   368                             scan_data_m,
       
   369                             *ap_data,
       
   370                             ap_data->rcpi() );
       
   371                         }
       
   372                     }
       
   373                 }
       
   374 
       
   375             if ( is_current_ap_in_list )
       
   376                 {
       
   377                 return goto_state( core_state_scanning_done );
       
   378                 }
       
   379 
       
   380             operation_state_m = core_state_rcpi_received;
       
   381 
       
   382             DEBUG( "core_operation_scan_c::next_state() - current AP was not found in scan" );
       
   383             DEBUG( "core_operation_scan_c::next_state() - requesting RCPI" );
       
   384 
       
   385             drivers_m->get_current_rcpi(
       
   386                 request_id_m,
       
   387                 current_rcpi_m );
       
   388 
       
   389             break;
       
   390             }
       
   391         case core_state_rcpi_received:
       
   392             {
       
   393             DEBUG1( "core_operation_scan_c::next_state() - current RCPI is %u",
       
   394                 current_rcpi_m );
       
   395             DEBUG( "core_operation_scan_c::next_state() - appending current AP to the scan list" );
       
   396 
       
   397             core_tools_c::add_beacon_to_scan_list(
       
   398                 scan_data_m,
       
   399                 *server_m->get_connection_data()->current_ap_data(),
       
   400                 current_rcpi_m );
       
   401 
       
   402             return goto_state( core_state_scanning_done );
       
   403             }
       
   404         case core_state_scanning_done:
       
   405             {
       
   406             DEBUG( "core_operation_scan_c::next_state() - scan complete" );
       
   407             DEBUG1( "core_operation_scan_c::next_state() - scan list contains %u AP(s)",
       
   408                 scan_data_m.Count() );            
       
   409             DEBUG1( "core_operation_scan_c::next_state() - scan list size is %u bytes",
       
   410                 scan_data_m.Size() );
       
   411 
       
   412             return core_error_ok;
       
   413             }
       
   414         default:
       
   415             {
       
   416             ASSERT( false_t );
       
   417             }
       
   418         }
       
   419 
       
   420     return core_error_request_pending;
       
   421     }
       
   422 
       
   423 // ---------------------------------------------------------------------------
       
   424 // ---------------------------------------------------------------------------
       
   425 //
       
   426 void core_operation_scan_c::user_cancel(
       
   427     bool_t do_graceful_cancel )
       
   428     {
       
   429     DEBUG1( "core_operation_scan_c::user_cancel(do_graceful_cancel=%d)", do_graceful_cancel );
       
   430 
       
   431 	/**
       
   432 	 * If region is FCC and region information is not known, then ignore 
       
   433 	 * and remove the APs from channels 12 and 13 
       
   434 	 */
       
   435     if ( !server_m->get_core_settings().mcc_known() && 
       
   436           server_m->get_core_settings().regional_domain() == core_wlan_region_fcc )
       
   437     	{
       
   438     	DEBUG( "core_operation_scan_c::next_state() - remove APs that were found on channels 12 and 13" );
       
   439     	remove_disallowed_aps();            	
       
   440     	}
       
   441     
       
   442     if ( !do_graceful_cancel )
       
   443         {
       
   444         /**
       
   445          * If we are in a middle of a scan, we have to schedule our own
       
   446          * event.
       
   447          */
       
   448         if ( ( operation_state_m == core_state_scan_start ||
       
   449                operation_state_m == core_state_scan_start_unknown_region ) &&
       
   450              server_m->event_handler() == this &&
       
   451              server_m->frame_handler() == this )
       
   452             {
       
   453             asynch_default_user_cancel();
       
   454     
       
   455             return;
       
   456             }
       
   457 
       
   458         /**
       
   459          * Everything else is handled by the default implementation.
       
   460          */
       
   461         core_operation_base_c::user_cancel( do_graceful_cancel );
       
   462         }
       
   463     }
       
   464 
       
   465 // ---------------------------------------------------------------------------
       
   466 // ---------------------------------------------------------------------------
       
   467 //    
       
   468 bool_t core_operation_scan_c::receive_frame(
       
   469     const core_frame_dot11_c* frame,
       
   470     u8_t rcpi )
       
   471     {
       
   472     DEBUG( "core_operation_scan_c::receive_frame()" );
       
   473     
       
   474     if ( frame->type() != core_frame_dot11_c::core_dot11_type_beacon &&
       
   475          frame->type() != core_frame_dot11_c::core_dot11_type_probe_resp )
       
   476         {
       
   477         DEBUG( "core_operation_scan_c::receive_frame() - not a beacon or a probe" );        
       
   478         return false_t;
       
   479         }
       
   480 
       
   481     core_ap_data_c* ap_data = core_ap_data_c::instance(
       
   482         server_m->get_wpx_adaptation_instance(),
       
   483         frame,
       
   484         rcpi,
       
   485         false_t );
       
   486     if ( ap_data )
       
   487         {        
       
   488         const core_ssid_s ssid = ap_data->ssid();
       
   489         DEBUG1S( "core_operation_scan_c::receive_frame() - SSID: ",
       
   490             ssid.length, &ssid.ssid[0] );
       
   491 
       
   492         core_mac_address_s bssid(
       
   493             ap_data->bssid() );
       
   494         DEBUG6( "core_operation_scan_c::receive_frame() - BSSID: %02X:%02X:%02X:%02X:%02X:%02X",
       
   495             bssid.addr[0], bssid.addr[1], bssid.addr[2], 
       
   496             bssid.addr[3], bssid.addr[4], bssid.addr[5] ); 
       
   497        
       
   498         server_m->get_scan_list().update_entry( *ap_data );
       
   499 
       
   500         delete ap_data;
       
   501         ap_data = NULL;            
       
   502         }
       
   503 
       
   504     return true_t;
       
   505     }
       
   506 
       
   507 // ---------------------------------------------------------------------------
       
   508 // ---------------------------------------------------------------------------
       
   509 //
       
   510 bool_t core_operation_scan_c::notify(
       
   511     core_am_indication_e indication )
       
   512     {
       
   513     if ( operation_state_m == core_state_scan_start &&
       
   514          indication == core_am_indication_wlan_scan_complete )
       
   515         {
       
   516         server_m->unregister_event_handler( this );
       
   517 
       
   518         DEBUG( "core_operation_scan_c::notify() - scan complete" );
       
   519 
       
   520         asynch_goto( core_state_scan_complete, CORE_TIMER_IMMEDIATELY );
       
   521 
       
   522         return true_t;
       
   523         }
       
   524     else if ( operation_state_m == core_state_scan_start_unknown_region && 
       
   525     		  indication == core_am_indication_wlan_scan_complete )
       
   526     	{
       
   527     	server_m->unregister_event_handler( this );
       
   528 
       
   529     	DEBUG( "core_operation_scan_c::notify() - scan complete for channels 12 and 13" );
       
   530 
       
   531         asynch_goto( core_state_scan_complete_unknown_region, CORE_TIMER_IMMEDIATELY );
       
   532 
       
   533         return true_t;
       
   534     	}
       
   535 
       
   536     return false_t;
       
   537     }
       
   538 
       
   539 // ---------------------------------------------------------------------------
       
   540 // ---------------------------------------------------------------------------
       
   541 //
       
   542 void core_operation_scan_c::remove_disallowed_aps()
       
   543     {
       
   544     core_type_list_c<core_mac_address_s> remove_ap_list;
       
   545                 
       
   546     core_scan_list_iterator_by_tag_c iter_removed_aps(
       
   547         server_m->get_scan_list(),
       
   548         core_scan_list_tag_scan );
       
   549 
       
   550     core_ap_data_c* ap_data = iter_removed_aps.first();
       
   551     while (ap_data)
       
   552         {
       
   553         if ( !server_m->get_core_settings().is_valid_channel(
       
   554                 SCAN_BAND_2DOT4GHZ,
       
   555                 ap_data->channel() ) )
       
   556             {
       
   557             core_mac_address_s* ignored_ap = new core_mac_address_s;
       
   558             if ( ignored_ap )
       
   559                 {
       
   560                 *ignored_ap = ap_data->bssid();
       
   561                 remove_ap_list.append( ignored_ap );
       
   562                 }
       
   563             }
       
   564         ap_data = iter_removed_aps.next(); 
       
   565         }
       
   566 
       
   567     core_mac_address_s* ignored_bssid = remove_ap_list.first(); 
       
   568     while (ignored_bssid )
       
   569         {
       
   570         server_m->get_scan_list().remove_entries_by_bssid( *ignored_bssid );
       
   571         ignored_bssid = remove_ap_list.next();
       
   572         }
       
   573     remove_ap_list.clear();
       
   574     
       
   575     }