diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_base.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_base.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,431 @@ +/* +* Copyright (c) 2005-2006 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: Base class for wlan engine operations +* +*/ + + +#include "core_operation_base.h" +#include "core_server.h" +#include "core_sub_operation_load_drivers.h" +#include "am_debug.h" + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_operation_base_c::core_operation_base_c( + core_operation_type_e type, + u32_t request_id, + core_server_c* server, + abs_core_driverif_c* drivers, + abs_core_server_callback_c* adaptation, + u32_t feature_flags ) : + request_id_m( request_id ), + server_m( server ), + drivers_m( drivers ), + adaptation_m( adaptation ), + is_executing_m( false_t ), + is_canceling_m( false_t ), + operation_state_m( core_base_state_init ), + sub_operation_m( NULL ), + failure_reason_m( core_error_cancel ), + operation_type_m( type ), + feature_flags_m( feature_flags ) + { + DEBUG1( "core_operation_base_c::core_operation_base_c() (%08X)", + this ); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_operation_base_c::~core_operation_base_c() + { + DEBUG1( "core_operation_base_c::~core_operation_base_c() (%08X)", + this ); + + delete sub_operation_m; + sub_operation_m = NULL; + server_m = NULL; + drivers_m = NULL; + adaptation_m = NULL; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::start_operation() + { + DEBUG1( "core_operation_base_c::start_operation() (%08X)", + this ); + + is_executing_m = true_t; + return continue_operation( core_error_ok ); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::continue_operation( + core_error_e request_status ) + { + DEBUG1( "core_operation_base_c::continue_operation() (%08X)", + this ); + bool_t is_sub_operation_canceled( false_t ); + + /** + * If we have pending sub-operation, this continue must be for it. + */ + if ( sub_operation_m ) + { + core_error_e ret = sub_operation_m->continue_operation( request_status ); + if ( ret == core_error_request_pending ) + { + DEBUG( "core_operation_base_c::continue_operation() - sub-operation still pending" ); + return ret; + } + + delete sub_operation_m; + sub_operation_m = NULL; + + if ( ret == core_error_ok ) + { + DEBUG( "core_operation_base_c::continue_operation() - sub-operation completed successfully" ); + } + else if ( is_canceling_m ) + { + DEBUG( "core_operation_base_c::continue_operation() - sub-operation user cancel completed" ); + is_sub_operation_canceled = true_t; + } + else + { + DEBUG1( "core_operation_base_c::continue_operation() - sub-operation failed with %u", + ret ); + failure_reason_m = ret; + + return cancel_operation(); + } + } + + /** + * Handle user cancel for operations that haven't overridden the user cancel method. + */ + if ( operation_state_m == core_base_state_user_cancel ) + { + DEBUG( "core_operation_base_c::continue_operation() - user cancel complete" ); + ASSERT( is_canceling_m ); + + return core_error_cancel; + } + + /** + * This continue is for this operation. + * + * If a sub-operation has just completed its user cancel, ignore the return + * value. + */ + if ( !is_sub_operation_canceled && + request_status != core_error_ok ) + { + DEBUG1( "core_operation_base_c::continue_operation() - request failed with %u", + request_status ); + failure_reason_m = request_status; + + return cancel_operation(); + } + + switch ( operation_state_m ) + { + case core_base_state_init: + { + operation_state_m = core_base_state_next; + + if ( is_flags( core_base_flag_drivers_needed ) && + !server_m->get_core_settings().is_driver_loaded() ) + { + DEBUG( "core_operation_base_c::continue_operation() - drivers required" ); + + operation_state_m = core_base_state_load_drivers; + + core_operation_base_c* operation = new core_sub_operation_load_drivers_c( + request_id_m, server_m, drivers_m, adaptation_m ); + return run_sub_operation( operation ); + } + + return next_state(); + } + case core_base_state_load_drivers: + { + DEBUG( "core_operation_base_c::continue_operation() - drivers loaded successfully" ); + + operation_state_m = core_base_state_next; + + return next_state(); + } + default: + { + core_error_e ret = next_state(); + + /** + * Always return an error code when the operation completes + * after user cancel. + */ + if( is_canceling_m && + ret != core_error_request_pending ) + { + DEBUG( "core_operation_base_c::continue_operation() - completing user canceled operation with core_error_cancel" ); + + return core_error_cancel; + } + + return ret; + } + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::cancel_operation() + { + DEBUG1( "core_operation_base_c::cancel_operation() (%08X)", + this ); + + /** + * If we have pending sub-operation, it must be canceled first. + */ + if ( sub_operation_m ) + { + core_error_e ret = sub_operation_m->cancel_operation(); + if ( ret == core_error_request_pending ) + { + DEBUG( "core_operation_base_c::cancel_operation() - sub-operation cancel pending" ); + return ret; + } + + delete sub_operation_m; + sub_operation_m = NULL; + } + + /** + * If the cancel occurs during the base operation state machine, fail the operation + * immediately without making the main state machine handle the failure. + */ + if ( operation_state_m < core_base_state_next ) + { + DEBUG( "core_operation_base_c::cancel_operation() - canceling using base operation cancel()" ); + + return core_operation_base_c::cancel(); + } + + return cancel(); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void core_operation_base_c::user_cancel_operation( + bool_t do_graceful_cancel ) + { + DEBUG1( "core_operation_base_c::user_cancel_operation() (%08X)", + this ); + + /** + * Prevent double canceling. + */ + if ( is_canceling_m ) + { + DEBUG( "core_operation_base_c::user_cancel_operation() - canceling already in progress" ); + + return; + } + + /** + * If we have pending sub-operation, it must be canceled first. + */ + if ( sub_operation_m ) + { + sub_operation_m->user_cancel_operation( do_graceful_cancel ); + } + + is_canceling_m = true_t; + + /** + * If the user cancel occurs during the base operation state machine, fail the operation + * immediately without making the main state machine handle the user cancel. + */ + if ( operation_state_m < core_base_state_next ) + { + DEBUG( "core_operation_base_c::user_cancel_operation() - canceling using base operation user_cancel()" ); + + core_operation_base_c::user_cancel( do_graceful_cancel ); + return; + } + + user_cancel( do_graceful_cancel ); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +u32_t core_operation_base_c::request_id() const + { + return request_id_m; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_operation_type_e core_operation_base_c::operation_type() const + { + return operation_type_m; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +bool_t core_operation_base_c::is_executing() const + { + return is_executing_m; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +bool_t core_operation_base_c::is_flags( + u32_t feature_flags ) const + { + if ( feature_flags_m & feature_flags ) + { + return true_t; + } + + return false_t; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::cancel() + { + DEBUG( "core_operation_base_c::cancel() " ); + + return failure_reason_m; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void core_operation_base_c::user_cancel( + bool_t /* do_graceful_cancel */ ) + { + DEBUG( "core_operation_base_c::user_cancel()" ); + + operation_state_m = core_base_state_user_cancel; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::goto_state( + u32_t state ) + { + operation_state_m = state; + + return next_state(); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::run_sub_operation( + core_operation_base_c* sub_operation ) + { + DEBUG( "core_operation_base_c::run_sub_operation() " ); + + ASSERT( !sub_operation_m ); + sub_operation_m = sub_operation; + + if ( !sub_operation_m ) + { + DEBUG( "core_operation_base_c::run_sub_operation() - sub-operation creation failed" ); + failure_reason_m = core_error_no_memory; + + return cancel_operation(); + } + + core_error_e ret = sub_operation_m->start_operation(); + if ( ret == core_error_request_pending ) + { + DEBUG( "core_operation_base_c::run_sub_operation() - sub-operation still pending" ); + return ret; + } + + delete sub_operation_m; + sub_operation_m = NULL; + + if ( ret != core_error_ok ) + { + DEBUG1( "core_operation_base_c::run_sub_operation() - sub-operation failed with %u", + ret ); + failure_reason_m = ret; + + return cancel_operation(); + } + + DEBUG( "core_operation_base_c::run_sub_operation() - sub-operation completed successfully" ); + + return continue_operation( ret ); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::run_sub_operation( + core_operation_base_c* sub_operation, + u32_t state ) + { + operation_state_m = state; + + return run_sub_operation( sub_operation ); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +core_error_e core_operation_base_c::asynch_goto( + u32_t state, + u32_t delay ) + { + operation_state_m = state; + + server_m->schedule_operation_timer( + delay ); + + return core_error_request_pending; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void core_operation_base_c::asynch_default_user_cancel() + { + DEBUG( "core_operation_base_c::asynch_default_user_cancel()" ); + + server_m->cancel_operation_timer(); + + asynch_goto( core_base_state_user_cancel ); + }