diff --git a/UNITTESTS/stubs/AT_CellularContext_stub.cpp b/UNITTESTS/stubs/AT_CellularContext_stub.cpp index f608fd98c8..39afef16b9 100644 --- a/UNITTESTS/stubs/AT_CellularContext_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularContext_stub.cpp @@ -191,6 +191,16 @@ nsapi_error_t AT_CellularContext::do_activate_context() return NSAPI_ERROR_OK; } +void AT_CellularContext::activate_context() +{ + +} + +void AT_CellularContext::deactivate_context() +{ + +} + void AT_CellularContext::do_connect() { } diff --git a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp index 899be2fb4c..680e40dbe1 100644 --- a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp @@ -158,7 +158,7 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam return NSAPI_ERROR_OK; } -bool AT_CellularNetwork::is_active_context() +bool AT_CellularNetwork::is_active_context(int *number_of_active_contexts, int cid) { return false; } @@ -167,3 +167,7 @@ nsapi_error_t AT_CellularNetwork::set_receive_period(int mode, EDRXAccessTechnol { return NSAPI_ERROR_OK; } + +void AT_CellularNetwork::get_context_state_command() +{ +} diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 0eb87366f4..f24d4809fd 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -338,11 +338,14 @@ public: */ virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0; - /** Check if there is any PDP context active + /** Check if there is any PDP context active. If cid is given, then check is done only for that cid. * - * @return true is any context is active, false otherwise or in case of error + * @param number_of_active_contexts If given then in return contains the number of active contexts + * @param cid If given then active contexts are checked only against this cid + * + * @return true if any (or the given cid) context is active, false otherwise or in case of error */ - virtual bool is_active_context() = 0; + virtual bool is_active_context(int *number_of_active_contexts = NULL, int cid = -1) = 0; /** Gets the latest received registration parameters from the network: * type, status, access technology, cell_id, lac, active_time, periodic_tau. diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index 1188979c1c..2230a7365f 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -467,15 +467,26 @@ nsapi_error_t AT_CellularContext::do_activate_context() nsapi_error_t AT_CellularContext::activate_ip_context() { - return activate_context(); + return find_and_activate_context(); } nsapi_error_t AT_CellularContext::activate_non_ip_context() { - return activate_context(); + return find_and_activate_context(); } -nsapi_error_t AT_CellularContext::activate_context() +void AT_CellularContext::activate_context() +{ + tr_info("Activate PDP context %d", _cid); + _at.cmd_start("AT+CGACT=1,"); + _at.write_int(_cid); + _at.cmd_stop_read_resp(); + if (_at.get_last_error() == NSAPI_ERROR_OK) { + _is_context_activated = true; + } +} + +nsapi_error_t AT_CellularContext::find_and_activate_context() { _at.lock(); @@ -511,26 +522,11 @@ nsapi_error_t AT_CellularContext::activate_context() _is_context_active = false; _is_context_activated = false; - _at.cmd_start("AT+CGACT?"); - _at.cmd_stop(); - _at.resp_start("+CGACT:"); - while (_at.info_resp()) { - int context_id = _at.read_int(); - int context_activation_state = _at.read_int(); - if (context_id == _cid && context_activation_state == 1) { - _is_context_active = true; - } - } - _at.resp_stop(); + + _is_context_active = _nw->is_active_context(NULL, _cid); if (!_is_context_active) { - tr_info("Activate PDP context %d", _cid); - _at.cmd_start("AT+CGACT=1,"); - _at.write_int(_cid); - _at.cmd_stop_read_resp(); - if (_at.get_last_error() == NSAPI_ERROR_OK) { - _is_context_activated = true; - } + activate_context(); } err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION; @@ -692,34 +688,27 @@ nsapi_error_t AT_CellularContext::disconnect() void AT_CellularContext::deactivate_ip_context() { - deactivate_context(); + check_and_deactivate_context(); } void AT_CellularContext::deactivate_non_ip_context() { - deactivate_context(); + check_and_deactivate_context(); } void AT_CellularContext::deactivate_context() +{ + _at.cmd_start("AT+CGACT=0,"); + _at.write_int(_cid); + _at.cmd_stop_read_resp(); +} + +void AT_CellularContext::check_and_deactivate_context() { // CGACT and CGATT commands might take up to 3 minutes to respond. _at.set_at_timeout(180 * 1000); - _is_context_active = false; - size_t active_contexts_count = 0; - _at.cmd_start("AT+CGACT?"); - _at.cmd_stop(); - _at.resp_start("+CGACT:"); - while (_at.info_resp()) { - int context_id = _at.read_int(); - int context_activation_state = _at.read_int(); - if (context_activation_state == 1) { - active_contexts_count++; - if (context_id == _cid) { - _is_context_active = true; - } - } - } - _at.resp_stop(); + int active_contexts_count = 0; + _is_context_active = _nw->is_active_context(&active_contexts_count, _cid); CellularNetwork::RadioAccessTechnology rat = CellularNetwork::RAT_GSM; // always return NSAPI_ERROR_OK @@ -730,9 +719,7 @@ void AT_CellularContext::deactivate_context() // For EPS, if an attempt is made to disconnect the last PDN connection, then the MT responds with ERROR if (_is_context_active && (rat < CellularNetwork::RAT_E_UTRAN || active_contexts_count > 1)) { _at.clear_error(); - _at.cmd_start("AT+CGACT=0,"); - _at.write_int(_cid); - _at.cmd_stop_read_resp(); + deactivate_context(); } if (_new_context_set) { diff --git a/features/cellular/framework/AT/AT_CellularContext.h b/features/cellular/framework/AT/AT_CellularContext.h index a5f6aee691..8c5624e956 100644 --- a/features/cellular/framework/AT/AT_CellularContext.h +++ b/features/cellular/framework/AT/AT_CellularContext.h @@ -97,8 +97,9 @@ protected: virtual nsapi_error_t activate_non_ip_context(); virtual nsapi_error_t setup_control_plane_opt(); virtual void deactivate_non_ip_context(); + virtual void deactivate_ip_context(); virtual void set_disconnect(); - + virtual void deactivate_context(); private: #if NSAPI_PPP_AVAILABLE nsapi_error_t open_data_channel(); @@ -106,10 +107,10 @@ private: void ppp_disconnected(); #endif // #if NSAPI_PPP_AVAILABLE nsapi_error_t do_activate_context(); - nsapi_error_t activate_context(); + virtual void activate_context(); + nsapi_error_t find_and_activate_context(); nsapi_error_t activate_ip_context(); - void deactivate_context(); - void deactivate_ip_context(); + void check_and_deactivate_context(); bool set_new_context(int cid); bool get_context(); nsapi_error_t delete_current_context(); diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 538fb27f81..6587c5c821 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -573,21 +573,40 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam return _at.unlock_return_error(); } -bool AT_CellularNetwork::is_active_context() +void AT_CellularNetwork::get_context_state_command() { - _at.lock(); - - bool active_found = false; - // read active contexts _at.cmd_start("AT+CGACT?"); _at.cmd_stop(); _at.resp_start("+CGACT:"); +} + +bool AT_CellularNetwork::is_active_context(int *number_of_active_contexts, int cid) +{ + _at.lock(); + + if (number_of_active_contexts) { + *number_of_active_contexts = 0; + } + bool active_found = false; + int context_id; + // read active contexts + get_context_state_command(); + while (_at.info_resp()) { - (void)_at.read_int(); // discard context id + context_id = _at.read_int(); // discard context id if (_at.read_int() == 1) { // check state tr_debug("Found active context"); - active_found = true; - break; + if (number_of_active_contexts) { + (*number_of_active_contexts)++; + } + if (cid == -1) { + active_found = true; + } else if (context_id == cid) { + active_found = true; + } + if (!number_of_active_contexts && active_found) { + break; + } } } _at.resp_stop(); diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 044bc50c0d..6f4a26c4e6 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -88,7 +88,7 @@ public: // CellularNetwork virtual nsapi_error_t get_operator_names(operator_names_list &op_names); - virtual bool is_active_context(); + virtual bool is_active_context(int *number_of_active_contexts = NULL, int cid = -1); virtual nsapi_error_t get_registration_params(registration_params_t ®_params); @@ -106,6 +106,10 @@ protected: */ virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat); + /** Sends a command to query the active state of the PDP contexts. + * Can be overridden by the target class. + */ + virtual void get_context_state_command(); private: // "NO CARRIER" urc void urc_no_carrier(); diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp index dd3ea30e29..96d4f477c8 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp @@ -112,6 +112,24 @@ nsapi_error_t QUECTEL_BG96_CellularContext::activate_non_ip_context() return (ret == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION; } +void QUECTEL_BG96_CellularContext::activate_context() +{ + tr_info("Activate PDP context %d", _cid); + _at.cmd_start("AT+QIACT="); + _at.write_int(_cid); + _at.cmd_stop_read_resp(); + if (_at.get_last_error() == NSAPI_ERROR_OK) { + _is_context_activated = true; + } +} + +void QUECTEL_BG96_CellularContext::deactivate_context() +{ + _at.cmd_start("AT+QIDEACT="); + _at.write_int(_cid); + _at.cmd_stop_read_resp(); +} + void QUECTEL_BG96_CellularContext::deactivate_non_ip_context() { // Close the NIDD connection @@ -119,7 +137,6 @@ void QUECTEL_BG96_CellularContext::deactivate_non_ip_context() _at.cmd_stop(); _at.resp_start(); _at.resp_stop(); - } void QUECTEL_BG96_CellularContext::urc_nidd() diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.h b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.h index 032ebf0771..c3f1a5ec20 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.h +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.h @@ -35,6 +35,8 @@ protected: virtual nsapi_error_t activate_non_ip_context(); virtual nsapi_error_t setup_control_plane_opt(); virtual void deactivate_non_ip_context(); + virtual void deactivate_context(); + virtual void activate_context(); rtos::Semaphore _semaphore; private: diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp index 5b425922e7..8bee825808 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp @@ -15,8 +15,9 @@ * limitations under the License. */ -#include "QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h" -#include "QUECTEL/BG96/QUECTEL_BG96_CellularStack.h" +#include "QUECTEL_BG96_CellularNetwork.h" +#include "QUECTEL_BG96_CellularStack.h" +#include "CellularLog.h" using namespace mbed; @@ -72,3 +73,12 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAcce return _at.unlock_return_error(); } + +void QUECTEL_BG96_CellularNetwork::get_context_state_command() +{ + // read active contexts + _at.cmd_start("AT+QIACT?"); + _at.cmd_stop(); + _at.resp_start("+QIACT:"); +} + diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h index 3d952de3d1..d9d20d19b5 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h @@ -29,6 +29,8 @@ public: protected: virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat); + virtual void get_context_state_command(); + }; } // namespace mbed