From d1f2e91e938ecf5d3dfdf836b77d54bcb47a30ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20J=C3=A4rvelin?= Date: Wed, 14 Mar 2018 15:24:29 +0200 Subject: [PATCH] Working version of async registration. --- .../easy_cellular/CellularConnectionFSM.cpp | 35 ++++--- .../easy_cellular/CellularConnectionFSM.h | 4 +- .../easy_cellular/EasyCellularConnection.cpp | 5 - .../easy_cellular/EasyCellularConnection.h | 1 - .../cellular/framework/API/CellularNetwork.h | 6 ++ features/cellular/framework/AT/ATHandler.cpp | 12 ++- features/cellular/framework/AT/ATHandler.h | 4 +- .../framework/AT/AT_CellularNetwork.cpp | 93 ++++++++----------- .../framework/AT/AT_CellularNetwork.h | 10 +- .../cellular/framework/AT/AT_CellularSMS.cpp | 8 +- .../framework/common/CellularCommon.h | 2 +- 11 files changed, 90 insertions(+), 90 deletions(-) diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index 0492820e27..4e070774ce 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -24,7 +24,7 @@ #endif #include "CellularLog.h" #include "CellularCommon.h" -#include "mbed_wait_api.h" + // timeout to wait for AT responses #define TIMEOUT_POWER_ON (1*1000) #define TIMEOUT_SIM_PIN (1*1000) @@ -110,16 +110,11 @@ nsapi_error_t CellularConnectionFSM::init() _at_queue.chain(&_queue); - _network->set_registration_urc(CellularNetwork::C_EREG, true); - _network->set_registration_urc(CellularNetwork::C_GREG, true); - _network->set_registration_urc(CellularNetwork::C_REG, true); - _retry_count = 0; _state = STATE_INIT; _next_state = STATE_INIT; - tr_info("init done..."); - return NSAPI_ERROR_OK; + return _network->init(); } bool CellularConnectionFSM::power_on() @@ -305,7 +300,7 @@ void CellularConnectionFSM::report_failure(const char* msg) const char* CellularConnectionFSM::get_state_string(CellularState state) { - static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Connect network", "Connected"}; + static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Connecting network", "Connected"}; return strings[state]; } @@ -393,6 +388,19 @@ void CellularConnectionFSM::state_device_ready() if (_event_status_cb) { _event_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularDeviceReady); } + + bool success = false; + for (int type = 0; type < CellularNetwork::C_MAX; type++) { + if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) { + success = true; + } + } + if (!success) { + tr_error("Failed to set any URC's for registration"); + report_failure(get_state_string(_state)); + return; + } + print_device_info(); enter_to_state(STATE_SIM_PIN); } else { @@ -433,7 +441,7 @@ void CellularConnectionFSM::state_attaching() CellularNetwork::AttachStatus attach_status; if (get_attach_network(attach_status)) { if (attach_status == CellularNetwork::Attached) { - enter_to_state(STATE_CONNECT_NETWORK); + enter_to_state(STATE_CONNECTING_NETWORK); } else { set_attach_network(); retry_state_or_fail(); @@ -487,7 +495,7 @@ void CellularConnectionFSM::event() case STATE_ATTACHING_NETWORK: state_attaching(); break; - case STATE_CONNECT_NETWORK: + case STATE_CONNECTING_NETWORK: state_connect_to_network(); break; case STATE_CONNECTED: @@ -500,20 +508,19 @@ void CellularConnectionFSM::event() if (_next_state != _state || _event_timeout >= 0) { if (_next_state != _state) { // state exit condition - //tr_info("Cellular state from %d to %d", _state, _next_state); if (_status_callback) { if (!_status_callback(_state, _next_state)) { return; } } } else { - tr_info("Cellular event in %d milliseconds", _event_timeout); + tr_info("Cellular event in %d seconds", _event_timeout); } _state = _next_state; if (_event_timeout == -1) { _event_timeout = 0; } - _eventID = _queue.call_in(_event_timeout, callback(this, &CellularConnectionFSM::event)); + _eventID = _queue.call_in(_event_timeout*1000, callback(this, &CellularConnectionFSM::event)); if (!_eventID) { report_failure("Cellular event failure!"); return; @@ -569,7 +576,7 @@ void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr) } /*else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) { if (ptr == NSAPI_STATUS_GLOBAL_UP) { // we are connected - if (_state == STATE_CONNECT_NETWORK) { + if (_state == STATE_CONNECTING_NETWORK) { _queue.cancel(_eventID); continue_from_state(STATE_CONNECTED); } diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.h b/features/cellular/easy_cellular/CellularConnectionFSM.h index d0a50efa66..6263e235f5 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.h +++ b/features/cellular/easy_cellular/CellularConnectionFSM.h @@ -60,8 +60,8 @@ public: STATE_SIM_PIN, STATE_REGISTERING_NETWORK, STATE_ATTACHING_NETWORK, - STATE_CONNECT_NETWORK, - STATE_CONNECTED, + STATE_CONNECTING_NETWORK, + STATE_CONNECTED }; public: diff --git a/features/cellular/easy_cellular/EasyCellularConnection.cpp b/features/cellular/easy_cellular/EasyCellularConnection.cpp index 1f7c7f9152..df61bb3e81 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.cpp +++ b/features/cellular/easy_cellular/EasyCellularConnection.cpp @@ -130,11 +130,6 @@ void EasyCellularConnection::set_sim_pin(const char *sim_pin) } } -void EasyCellularConnection::set_is_blocking(bool blocking) -{ - -} - nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) { if (_is_connected) { diff --git a/features/cellular/easy_cellular/EasyCellularConnection.h b/features/cellular/easy_cellular/EasyCellularConnection.h index c7e9f4c68b..95ab9f783e 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.h +++ b/features/cellular/easy_cellular/EasyCellularConnection.h @@ -132,7 +132,6 @@ public: */ void modem_debug_on(bool on); - void set_is_blocking(bool blocking); protected: /** Provide access to the NetworkStack object diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 1f9c19b440..89afd836f9 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -209,6 +209,12 @@ public: }; + /** Does all the needed initializations that can fail + * + * @return zero on success + */ + virtual nsapi_error_t init() = 0; + /** Request registering to network. * * @param plmn format is in numeric format or 0 for automatic network registration diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index 56586d1afb..e242009f48 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -153,17 +153,17 @@ void ATHandler::set_file_handle(FileHandle *fh) _fileHandle = fh; } -void ATHandler::set_urc_handler(const char *prefix, mbed::Callback callback) +nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback callback) { if (check_urc_existance(prefix, callback)) { tr_warn("URC already added with prefix: %s", prefix); - return; + return NSAPI_ERROR_OK; } - // TODO: what to do if this allocation fails? Should this return boolean false? Quite a few urc urc's are - // called from constructors which is another problem... struct oob_t *oob = new struct oob_t; - if (oob) { + if (!oob) { + return NSAPI_ERROR_NO_MEMORY; + } else { size_t prefix_len = strlen(prefix); if (prefix_len > _oob_string_max_length) { _oob_string_max_length = prefix_len; @@ -177,6 +177,8 @@ void ATHandler::set_urc_handler(const char *prefix, mbed::Callback callb oob->next = _oobs; _oobs = oob; } + + return NSAPI_ERROR_OK; } bool ATHandler::check_urc_existance(const char *prefix, mbed::Callback callback) diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index f040bc365c..de425f1c9e 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -106,11 +106,13 @@ public: nsapi_error_t unlock_return_error(); /** Set the urc callback for urc. If urc is found when parsing AT responses, then call if called. + * If urc is already set then it's not set twice. * * @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: " * @param callback Callback, which is called if urc is found in AT response + * @return NSAPI_ERROR_OK or NSAPI_ERROR_NO_MEMORY if no memory */ - void set_urc_handler(const char *prefix, mbed::Callback callback); + nsapi_error_t set_urc_handler(const char *prefix, mbed::Callback callback); ATHandler *_nextATHandler; // linked list diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 71d3f7a876..6c27d9cfc7 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -29,24 +29,23 @@ using namespace mbed; struct at_reg_t { const CellularNetwork::RegistrationType type; const char *const cmd; - const char *const urc; - void (*urc_handler)(); + const char *const urc_prefix; }; static const at_reg_t at_reg[] = { - { CellularNetwork::C_EREG, "AT+CEREG", "+CEREG:", AT_CellularNetwork::urc_creg}, - { CellularNetwork::C_GREG, "AT+CGREG", "+CGREG:", AT_CellularNetwork::urc_cgreg}, - { CellularNetwork::C_REG, "AT+CREG", "+CREG:", AT_CellularNetwork::urc_creg} + { CellularNetwork::C_EREG, "AT+CEREG", "+CEREG:"}, + { CellularNetwork::C_GREG, "AT+CGREG", "+CGREG:"}, + { CellularNetwork::C_REG, "AT+CREG", "+CREG:"} }; AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler), _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), _last_reg_type(C_REG), - _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), _reg_status(NotRegistered), _async(false) + _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), _reg_status(NotRegistered) { - - _at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier)); - _at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier)); + _urc_funcs[C_EREG] = callback(this, &AT_CellularNetwork::urc_cereg); + _urc_funcs[C_GREG] = callback(this, &AT_CellularNetwork::urc_cgreg); + _urc_funcs[C_REG] = callback(this, &AT_CellularNetwork::urc_creg); } AT_CellularNetwork::~AT_CellularNetwork() @@ -54,6 +53,19 @@ AT_CellularNetwork::~AT_CellularNetwork() free_credentials(); } +nsapi_error_t AT_CellularNetwork::init() +{ + for (int type = 0; type < CellularNetwork::C_MAX; type++) { + if (has_registration((RegistrationType)type)) { + if (_at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type])) { + return NSAPI_ERROR_NO_MEMORY; + } + } + } + + return _at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier)); +} + void AT_CellularNetwork::free_credentials() { if (_uname) { @@ -77,15 +89,15 @@ void AT_CellularNetwork::urc_no_carrier() } } -void AT_CellularNetwork::read_reg_params_and_compare(int index) +void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) { RegistrationStatus reg_status = NotRegistered; int lac = -1, cell_id = -1, act = -1; - read_reg_params(index, reg_status, lac, cell_id, act); + read_reg_params(type, reg_status, lac, cell_id, act); if (_at.get_last_error() == NSAPI_ERROR_OK) { - tr_info("stat: %d, lac: %d, cellID: %d, act: %d", reg_status, lac, cell_id, act); + tr_debug("stat: %d, lac: %d, cellID: %d, act: %d", reg_status, lac, cell_id, act); if (reg_status != _reg_status && _connection_status_cb) { _connection_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularRegistrationStatusChanged); } @@ -102,19 +114,19 @@ void AT_CellularNetwork::read_reg_params_and_compare(int index) void AT_CellularNetwork::urc_creg() { - tr_info("urc_creg"); + tr_debug("urc_creg"); read_reg_params_and_compare(C_REG); } void AT_CellularNetwork::urc_cereg() { - tr_info("urc_cereg"); + tr_debug("urc_cereg"); read_reg_params_and_compare(C_EREG); } void AT_CellularNetwork::urc_cgreg() { - tr_info("urc_cgreg"); + tr_debug("urc_cgreg"); read_reg_params_and_compare(C_GREG); } @@ -342,7 +354,6 @@ nsapi_connection_status_t AT_CellularNetwork::get_connection_status() const nsapi_error_t AT_CellularNetwork::set_blocking(bool blocking) { - _async = !blocking; #if NSAPI_PPP_AVAILABLE return nsapi_ppp_set_blocking(blocking); #else @@ -567,14 +578,13 @@ nsapi_ip_stack_t AT_CellularNetwork::string_to_stack_type(const char* pdp_type) nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on) { - _at.lock(); - - MBED_ASSERT(type >= 0 && type < C_MAX); + int index = (int)type; + MBED_ASSERT(index >= 0 && index < C_MAX); if (has_registration(type)) { + _at.lock(); _last_reg_type = type; if (urc_on) { - _at.set_urc_handler(at_reg[type].urc, at_reg[type].urc_handler); _at.cmd_start(at_reg[type].cmd); _at.write_string("=2", false); _at.cmd_stop(); @@ -586,9 +596,10 @@ nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bo _at.resp_start(); _at.resp_stop(); + return _at.unlock_return_error(); + } else { + return NSAPI_ERROR_UNSUPPORTED; } - - return _at.unlock_return_error(); } nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode& mode) @@ -634,7 +645,7 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) return _at.unlock_return_error(); } -void AT_CellularNetwork::read_reg_params(int type_index, RegistrationStatus ®_status, int &lac, int &cell_id, int &act) +void AT_CellularNetwork::read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act) { const int LAC_LENGTH = 5, CELL_ID_LENGTH = 9; char lac_string[LAC_LENGTH] = {0}, cell_id_string[CELL_ID_LENGTH] = {0}; @@ -663,6 +674,10 @@ void AT_CellularNetwork::read_reg_params(int type_index, RegistrationStatus ® cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH); tr_debug("cell_id %s %d", cell_id_string, cell_id ); } + + if (_at.get_last_error() == NSAPI_ERROR_OK) { + _last_reg_type = type; + } } nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status) @@ -675,13 +690,6 @@ nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, } _at.lock(); - if (!_async) { - _at.cmd_start(at_reg[i].cmd); - _at.write_string("=2", false); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - } const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"}; _at.cmd_start(at_reg[i].cmd); @@ -689,10 +697,9 @@ nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, _at.cmd_stop(); _at.resp_start(rsp[i]); - _at.read_int(); // ignore urc mode subparam int lac = -1, cell_id = -1, act = -1; - read_reg_params(i, status, lac, cell_id, act); + read_reg_params(type, status, lac, cell_id, act); _at.resp_stop(); if (cell_id != -1) { @@ -702,32 +709,12 @@ nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, _current_act = (RadioAccessTechnology)act; } - if (!_async) { - _at.cmd_start(at_reg[i].cmd); - _at.write_string("=0", false); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - } - - if (_at.get_last_error() == NSAPI_ERROR_OK) { - _last_reg_type = type; - } - return _at.unlock_return_error(); } nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id) { - if (_async) { - return _cell_id; - } - - RegistrationStatus tmp; - nsapi_error_t error = get_registration_status(_last_reg_type, tmp); - cell_id = _cell_id; - - return error; + return _cell_id; } bool AT_CellularNetwork::has_registration(RegistrationType reg_type) diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 1d35476b9b..f38c2e3dfb 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -60,6 +60,8 @@ protected: virtual NetworkStack *get_stack(); public: // CellularNetwork + virtual nsapi_error_t init(); + virtual nsapi_error_t set_registration(const char *plmn = 0); virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode& mode); @@ -135,7 +137,6 @@ protected: */ virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat); - private: // "NO CARRIER" urc void urc_no_carrier(); @@ -154,8 +155,8 @@ private: nsapi_error_t delete_current_context(); - void read_reg_params_and_compare(int index); - void read_reg_params(int type_index, RegistrationStatus ®_status, int &lac, int &cell_id, int &act); + void read_reg_params_and_compare(RegistrationType type); + void read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act); #if NSAPI_PPP_AVAILABLE void ppp_status_cb(nsapi_event_t, intptr_t); @@ -178,8 +179,7 @@ protected: bool _new_context_set; RegistrationStatus _reg_status; RadioAccessTechnology _current_act; - bool _async; - + mbed::Callback _urc_funcs[C_MAX]; }; } // namespace mbed diff --git a/features/cellular/framework/AT/AT_CellularSMS.cpp b/features/cellular/framework/AT/AT_CellularSMS.cpp index faa7a9eb6e..eff31f948e 100644 --- a/features/cellular/framework/AT/AT_CellularSMS.cpp +++ b/features/cellular/framework/AT/AT_CellularSMS.cpp @@ -176,9 +176,6 @@ const int GSM_TO_ASCII_TABLE_SIZE = sizeof(gsm_to_ascii)/sizeof(gsm_to_ascii[0]) AT_CellularSMS::AT_CellularSMS(ATHandler &at) : AT_CellularBase(at), _cb(0), _mode(CellularSMSMmodeText), _use_8bit_encoding(false), _sim_wait_time(0), _sms_message_ref_number(1), _sms_info(NULL) { - /* URCs, handled out of band */ - _at.set_urc_handler("+CMTI:", callback(this, &AT_CellularSMS::cmti_urc)); - _at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc)); } AT_CellularSMS::~AT_CellularSMS() @@ -258,6 +255,11 @@ nsapi_error_t AT_CellularSMS::set_csdh(int show_header) nsapi_error_t AT_CellularSMS::initialize(CellularSMSMmode mode) { + if (_at.set_urc_handler("+CMTI:", callback(this, &AT_CellularSMS::cmti_urc)) || + _at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc))) { + return NSAPI_ERROR_NO_MEMORY; + } + _at.lock(); set_cnmi(); //set new SMS indication set_cmgf(mode); //set message format/PDU diff --git a/features/cellular/framework/common/CellularCommon.h b/features/cellular/framework/common/CellularCommon.h index 76768b5f2d..0f8bd117d8 100644 --- a/features/cellular/framework/common/CellularCommon.h +++ b/features/cellular/framework/common/CellularCommon.h @@ -31,6 +31,6 @@ typedef enum cellular_event_status { 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 */ -} cellular_connection_status_t +} cellular_connection_status_t; #endif // CELLULAR_COMMON_