diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index b0e28d247c..388d1dc402 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -175,7 +175,7 @@ bool CellularConnectionFSM::open_sim() } if (_event_status_cb) { - _event_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularSIMStatusChanged); + _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state); } return state == CellularSIM::SimStateReady; @@ -302,6 +302,8 @@ bool CellularConnectionFSM::is_automatic_registering() nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state) { + tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state), + get_state_string((CellularConnectionFSM::CellularState)state)); _state = state; _next_state = state; _retry_count = 0; @@ -370,7 +372,7 @@ bool CellularConnectionFSM::device_ready() { tr_info("Cellular device ready"); if (_event_status_cb) { - _event_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularDeviceReady); + _event_status_cb((nsapi_event_t)CellularDeviceReady, 0); } _power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); @@ -505,6 +507,8 @@ void CellularConnectionFSM::event() if (_next_state != _state || _event_timeout >= 0) { if (_next_state != _state) { // state exit condition + tr_info("Cellular state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state), + get_state_string((CellularConnectionFSM::CellularState)_next_state)); if (_status_callback) { if (!_status_callback(_state, _next_state)) { return; @@ -529,7 +533,7 @@ nsapi_error_t CellularConnectionFSM::start_dispatch() { MBED_ASSERT(!_queue_thread); - _queue_thread = new rtos::Thread(osPriorityNormal, 1024); + _queue_thread = new rtos::Thread(osPriorityNormal, 2048); if (!_queue_thread) { stop(); return NSAPI_ERROR_NO_MEMORY; @@ -562,14 +566,9 @@ void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr) { tr_debug("FSM: network_callback called with event: %d, intptr: %d", ev, ptr); - if (ev == NSAPI_EVENT_CELLULAR_STATUS_CHANGE) { - if (ptr == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) { - // check for registration status - if (is_registered()) { - _queue.cancel(_eventID); - continue_from_state(STATE_ATTACHING_NETWORK); - } - } + if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && ptr == CellularNetwork::RegisteredHomeNetwork && _state == STATE_REGISTERING_NETWORK) { + _queue.cancel(_eventID); + continue_from_state(STATE_ATTACHING_NETWORK); } if (_event_status_cb) { @@ -579,7 +578,7 @@ void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr) void CellularConnectionFSM::ready_urc_cb() { - tr_info("Device ready URC func called"); + tr_debug("Device ready URC func called"); if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) { tr_info("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next"); _queue.cancel(_eventID); diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 60162eecfb..bbefd82ee1 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -358,6 +358,13 @@ public: virtual nsapi_error_t connect(const char *apn, const char *username = 0, const char *password = 0) = 0; + /** Finds the correct PDP context and activates it. If correct PDP context is not found, one is created. + * Given APN (or not given) and stack type (IPv4/IPv6/dual) are influencing when finding the PDP context. + * + * @return zero on success + */ + virtual nsapi_error_t activate_context() = 0; + /** * Set the pdn type to be used * diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index caa0402dd0..ec15f89039 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -42,7 +42,7 @@ AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(a _stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1), _connection_status_cb(NULL), _op_act(RAT_UNKNOWN), _authentication_type(CHAP), _cell_id(-1), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), - _reg_status(NotRegistered), _current_act(RAT_UNKNOWN) + _is_context_active(false), _reg_status(NotRegistered), _current_act(RAT_UNKNOWN) { } @@ -100,14 +100,17 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) { tr_debug("stat: %d, lac: %d, cellID: %d, act: %d", reg_status, lac, cell_id, act); + if (act != -1 && (RadioAccessTechnology)act != _current_act) { + _current_act = (RadioAccessTechnology)act; + _connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, _current_act); + } if (reg_status != _reg_status) { - _connection_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularRegistrationStatusChanged); + _reg_status = reg_status; + _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_status); } if (cell_id != -1 && cell_id != _cell_id) { - _connection_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularCellIDChanged); - } - if (act != -1 && (RadioAccessTechnology)act != _current_act) { - _connection_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularRadioAccessTechnologyChanged); + _cell_id = cell_id; + _connection_status_cb((nsapi_event_t)CellularCellIDChanged, _cell_id); } } } @@ -206,15 +209,10 @@ nsapi_error_t AT_CellularNetwork::delete_current_context() return _at.get_last_error(); } -nsapi_error_t AT_CellularNetwork::connect() +nsapi_error_t AT_CellularNetwork::activate_context() { _at.lock(); - _connect_status = NSAPI_STATUS_CONNECTING; - if (_connection_status_cb) { - _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING); - } - nsapi_error_t err = set_context_to_be_activated(); if (err != NSAPI_ERROR_OK) { _at.unlock(); @@ -228,18 +226,58 @@ nsapi_error_t AT_CellularNetwork::connect() return err; } - err = open_data_channel(); - if (err != NSAPI_ERROR_OK) { + // do check for stack to validate that we have support for stack + _stack = get_stack(); + if (!_stack) { + return err; + } - // If new PDP context was created and failed to activate, delete it - if (_new_context_set) { - delete_current_context(); + _is_context_active = 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(); - _at.unlock(); + if (!_is_context_active) { + tr_info("Activate PDP context"); + _at.cmd_start("AT+CGACT=1,"); + _at.write_int(_cid); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + } - tr_error("Failed to open data channel!"); + err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION; + // If new PDP context was created and failed to activate, delete it + if (err != NSAPI_ERROR_OK && _new_context_set) { + delete_current_context(); + } + + _at.unlock(); + + return err; +} + +nsapi_error_t AT_CellularNetwork::connect() +{ + _connect_status = NSAPI_STATUS_CONNECTING; + if (_connection_status_cb) { + _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING); + } + + nsapi_error_t err = NSAPI_ERROR_OK; + if (!_is_context_active) { + err = activate_context(); + } + if (err) { _connect_status = NSAPI_STATUS_DISCONNECTED; if (_connection_status_cb) { _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); @@ -248,9 +286,19 @@ nsapi_error_t AT_CellularNetwork::connect() return err; } +#if NSAPI_PPP_AVAILABLE + _at.lock(); + err = open_data_channel(); _at.unlock(); - -#if !NSAPI_PPP_AVAILABLE + if (err != NSAPI_ERROR_OK) { + tr_error("Failed to open data channel!"); + _connect_status = NSAPI_STATUS_DISCONNECTED; + if (_connection_status_cb) { + _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); + } + return err; + } +#else _connect_status = NSAPI_STATUS_GLOBAL_UP; if (_connection_status_cb) { _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_GLOBAL_UP); @@ -262,9 +310,6 @@ nsapi_error_t AT_CellularNetwork::connect() nsapi_error_t AT_CellularNetwork::open_data_channel() { - //old way: _at.send("ATD*99***%d#", _cid) && _at.recv("CONNECT"); - nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION; -#if NSAPI_PPP_AVAILABLE tr_info("Open data channel in PPP mode"); _at.cmd_start("AT+CGDATA=\"PPP\","); _at.write_int(_cid); @@ -277,41 +322,7 @@ nsapi_error_t AT_CellularNetwork::open_data_channel() /* Initialize PPP * If blocking: mbed_ppp_init() is a blocking call, it will block until connected, or timeout after 30 seconds*/ - err = nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularNetwork::ppp_status_cb), _uname, _pwd, _ip_stack_type); -#else - // do check for stack to validate that we have support for stack - _stack = get_stack(); - if (!_stack) { - return err; - } - - bool is_context_active = 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; - tr_debug("PDP context %d is active.", _cid); - break; - } - } - _at.resp_stop(); - - if (!is_context_active) { - tr_info("Activate PDP context %d", _cid); - _at.cmd_start("AT+CGACT=1,"); - _at.write_int(_cid); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - } - - err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION; -#endif - return err; + return nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularNetwork::ppp_status_cb), NULL, NULL, _ip_stack_type); } /** @@ -695,6 +706,7 @@ nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, int lac = -1, cell_id = -1, act = -1; read_reg_params(type, status, lac, cell_id, act); _at.resp_stop(); + _reg_status = status; if (cell_id != -1) { _cell_id = cell_id; diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 4cfa96ee00..3b6eef2b55 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -62,6 +62,8 @@ protected: public: // CellularNetwork virtual nsapi_error_t init(); + virtual nsapi_error_t activate_context(); + virtual nsapi_error_t set_registration(const char *plmn = 0); virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode& mode); @@ -176,6 +178,7 @@ protected: int _cell_id; nsapi_connection_status_t _connect_status; bool _new_context_set; + bool _is_context_active; RegistrationStatus _reg_status; RadioAccessTechnology _current_act; mbed::Callback _urc_funcs[C_MAX]; diff --git a/features/cellular/framework/common/CellularCommon.h b/features/cellular/framework/common/CellularCommon.h index 0f8bd117d8..5b98cdb862 100644 --- a/features/cellular/framework/common/CellularCommon.h +++ b/features/cellular/framework/common/CellularCommon.h @@ -19,18 +19,19 @@ #define CELLULAR_COMMON_ #include +#include "nsapi_types.h" /** * Cellular specific event changes. * Connect and disconnect are handled via NSAPI_EVENT_CONNECTION_STATUS_CHANGE */ typedef enum cellular_event_status { - CellularDeviceReady = 0, /*!< Modem is powered and ready to receive commands */ - CellularSIMStatusChanged = 1, /*!< SIM state changed, call SIM state */ - CellularRegistrationStatusChanged = 2, /*!< Registering status changed, e.g. roaming, registered, smsonly... */ - CellularRegistrationTypeChanged = 3, /*!< Registration type changed, e.g. C_EREG, C_GREG, C_REG */ - CellularCellIDChanged = 4, /*!< Network Cell ID have changed */ - CellularRadioAccessTechnologyChanged = 5, /*!< Network roaming status have changed */ + CellularDeviceReady = NSAPI_EVENT_CELLULAR_STATUS_BASE, /* Modem is powered and ready to receive commands. No additional info in callback intptr_t. */ + CellularSIMStatusChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 1, /* SIM state changed, call SIM state. enum SimState as additional info callback intptr_t. See enum SimState in ../API/CellularSIM.h */ + CellularRegistrationStatusChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 2, /* Registering status changed. enum RegistrationStatus as additional info callback intptr_t. See enum RegistrationStatus in ../API/CellularNetwork.h */ + CellularRegistrationTypeChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 3, /* Registration type changed. enum RegistrationType as additional info callback intptr_t. See enum RegistrationType in ../API/CellularNetwork.h */ + CellularCellIDChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 4, /* Network Cell ID have changed. int cellid as additional info callback intptr_t. */ + CellularRadioAccessTechnologyChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 5, /* Network roaming status have changed. enum RadioAccessTechnology as additional info callback intptr_t. See enum RadioAccessTechnology in ../API/CellularNetwork.h */ } cellular_connection_status_t; #endif // CELLULAR_COMMON_ diff --git a/features/netsocket/nsapi_types.h b/features/netsocket/nsapi_types.h index d1c4de773d..3d0dc467cd 100644 --- a/features/netsocket/nsapi_types.h +++ b/features/netsocket/nsapi_types.h @@ -80,7 +80,8 @@ enum nsapi_error { */ typedef enum nsapi_event { NSAPI_EVENT_CONNECTION_STATUS_CHANGE = 0, /*!< network connection status has changed, the parameter = new status (nsapi_connection_status_t) */ - NSAPI_EVENT_CELLULAR_STATUS_CHANGE = 1 /*!< cellular modem status has changed, the parameter = new status (cellular_connection_status_t) */ + NSAPI_EVENT_CELLULAR_STATUS_BASE = 0x1000, /*!< Cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */ + NSAPI_EVENT_CELLULAR_STATUS_END = 0x1FFF /*!< cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */ } nsapi_event_t;